diff --git a/contrib/netcat/nc.1 b/contrib/netcat/nc.1 index 9f8696135f35..2e34cdc586c3 100644 --- a/contrib/netcat/nc.1 +++ b/contrib/netcat/nc.1 @@ -42,6 +42,7 @@ .Op Fl i Ar interval .Op Fl -no-tcpopt .Op Fl -sctp +.Op Fl -crlf .Op Fl O Ar length .Op Fl P Ar proxy_username .Op Fl p Ar source_port @@ -104,6 +105,8 @@ to use IPv4 addresses only. Forces .Nm to use IPv6 addresses only. +.It Fl -crlf +Convert LF into CRLF when sending data over the network. .It Fl D Enable debugging on the socket. .It Fl d diff --git a/contrib/netcat/netcat.c b/contrib/netcat/netcat.c index 65266b99c28e..9a1e5ac084a6 100644 --- a/contrib/netcat/netcat.c +++ b/contrib/netcat/netcat.c @@ -94,6 +94,7 @@ int Nflag; /* shutdown() network socket */ int nflag; /* Don't do name look up */ int FreeBSD_Oflag; /* Do not use TCP options */ int FreeBSD_sctp; /* Use SCTP */ +int FreeBSD_crlf; /* Convert LF to CRLF */ char *Pflag; /* Proxy username */ char *pflag; /* Localport flag */ int rflag; /* Random ports flag */ @@ -136,7 +137,8 @@ void set_common_sockopts(int, int); int map_tos(char *, int *); void report_connect(const struct sockaddr *, socklen_t); void usage(int); -ssize_t drainbuf(int, unsigned char *, size_t *); +ssize_t write_wrapper(int, const void *, size_t); +ssize_t drainbuf(int, unsigned char *, size_t *, int); ssize_t fillbuf(int, unsigned char *, size_t *); #ifdef IPSEC @@ -168,6 +170,7 @@ main(int argc, char *argv[]) { "no-tcpopt", no_argument, &FreeBSD_Oflag, 1 }, { "sctp", no_argument, &FreeBSD_sctp, 1 }, { "tun", required_argument, NULL, FREEBSD_TUN }, + { "crlf", no_argument, &FreeBSD_crlf, 1 }, { NULL, 0, NULL, 0 } }; @@ -972,7 +975,7 @@ readwrite(int net_fd) /* try to write to network */ if (pfd[POLL_NETOUT].revents & POLLOUT && stdinbufpos > 0) { ret = drainbuf(pfd[POLL_NETOUT].fd, stdinbuf, - &stdinbufpos); + &stdinbufpos, FreeBSD_crlf); if (ret == -1) pfd[POLL_NETOUT].fd = -1; /* buffer empty - remove self from polling */ @@ -1007,7 +1010,7 @@ readwrite(int net_fd) /* try to write to stdout */ if (pfd[POLL_STDOUT].revents & POLLOUT && netinbufpos > 0) { ret = drainbuf(pfd[POLL_STDOUT].fd, netinbuf, - &netinbufpos); + &netinbufpos, 0); if (ret == -1) pfd[POLL_STDOUT].fd = -1; /* buffer empty - remove self from polling */ @@ -1037,17 +1040,41 @@ readwrite(int net_fd) } ssize_t -drainbuf(int fd, unsigned char *buf, size_t *bufpos) +write_wrapper(int fd, const void *buf, size_t buflen) { - ssize_t n; + ssize_t n = write(fd, buf, buflen); + /* don't treat EAGAIN, EINTR as error */ + return (n == -1 && (errno == EAGAIN || errno == EINTR)) ? -2 : n; +} + +ssize_t +drainbuf(int fd, unsigned char *buf, size_t *bufpos, int crlf) +{ + ssize_t n = *bufpos, n2 = 0; ssize_t adjust; + unsigned char *lf = NULL; + + if (crlf) { + lf = memchr(buf, '\n', *bufpos); + if (lf && (lf == buf || *(lf-1) != '\r')) + n = lf - buf; + else + lf = NULL; + } + + if (n != 0) { + n = write_wrapper(fd, buf, n); + if (n <= 0) + return n; + } + + if (lf) { + n2 = write_wrapper(fd, "\r\n", 2); + if (n2 <= 0) + return n2; + n += 1; + } - n = write(fd, buf, *bufpos); - /* don't treat EAGAIN, EINTR as error */ - if (n == -1 && (errno == EAGAIN || errno == EINTR)) - n = -2; - if (n <= 0) - return n; /* adjust buffer */ adjust = *bufpos - n; if (adjust > 0) @@ -1440,6 +1467,7 @@ help(void) fprintf(stderr, "\tCommand Summary:\n\ \t-4 Use IPv4\n\ \t-6 Use IPv6\n\ + \t--crlf Convert LF into CRLF when sending data over the network\n\ \t-D Enable the debug socket option\n\ \t-d Detach from stdin\n"); #ifdef IPSEC