2

Note, I have looked at Using netcat/cat in a background shell script (How to avoid Stopped (tty input)? ), but it doesn't seem to apply to my case. I'm using the netcat (nc) that comes with busybox, and none of the workarounds I've found seem to work for me. Also, there is no -d option, nor are there any -q options.

I'm trying to use netcat to receive a file in a shell script, and this script is in a background process that apparently doesn't have a stdin. I have tried several different approaches, but none seem to work. Here's what I've tried:

  • nc -l -p 8888 > file returns the instant the remote sender connects, dropping the connection early.
  • nc -l -p 8888 < /dev/null > file does the same.
  • echo -n | nc -l -p 8888 > file does the same.
  • tail -f /dev/null | nc -l -p 8888 > file will receive the file, but it doesn't quit when the file transfer is finished.

I'm running out of ideas. Is this version of netcat fundamentally broken?

Community
  • 1
  • 1
Timothy Miller
  • 1,527
  • 4
  • 28
  • 48

2 Answers2

2

Well, it's been days, and nobody had an answer, so I had to roll my own. Below is the code, in case it's useful to anyone.

#include <signal.h>
#include <sys/types.h> 
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h> 
#include <ctype.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/uio.h>
#include <unistd.h>

void bail(const char *s)
{
    perror(s);
    exit(-1);
}

int listen_socket;
struct sockaddr_in my_addr;

void setup_socket(int port)
{
    int er;
    listen_socket = socket(AF_INET, SOCK_STREAM, 0);
    if (listen_socket < 0) bail("socket");

    int on=1;
    er = setsockopt(listen_socket, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
    if (er < 0) bail("setsockopt");

    memset(&my_addr, 0, sizeof(my_addr));
    my_addr.sin_family = AF_INET;
    my_addr.sin_port = htons(port);
    my_addr.sin_addr.s_addr = htonl(INADDR_ANY);

    er = bind(listen_socket, (struct  sockaddr  *)&my_addr,
        (socklen_t)sizeof(struct sockaddr_in));
    if (er < 0) bail("bind");

    er = listen(listen_socket, 1);
    if (er < 0) bail("listen");
}

int listen_wait()
{
    socklen_t len = sizeof(struct sockaddr_in);
    int s = accept(listen_socket, (struct  sockaddr  *)&my_addr, &len);
    if (s < 0) bail("accept");
    return s;
}

char buf[1024];

int main(int argc, char *argv[])
{
    int port = 8888;
    int sock;
    int tryagain;
    if (argc>1) {
        port = atoi(argv[1]);
    }

    setup_socket(port);
    sock = listen_wait();

    do {
        int i = read(sock, buf, 1024);
        tryagain = (errno==EAGAIN);
        if ((i<1) && (!tryagain)) {
            shutdown(sock, 2);
            close(sock);
            return 0;
        }
        if (i>0) {
            fwrite(buf, 1, i, stdout);
        }
    } while (1);
    return 0;
}
Timothy Miller
  • 1,527
  • 4
  • 28
  • 48
0

This will do the trick

sleep 99999 | nc -l -p 8888 > file 
mohit
  • 124
  • 7