Author: jdp@ll.mit.edu --- nc/netcat.c.orig Wed May 2 15:45:17 2001 +++ nc/netcat.c Mon May 14 14:27:25 2001 @@ -59,6 +59,14 @@ #define RAND rand #endif /* HAVE_RANDOM */ +/* #define POSIX_SETJMP /* If you want timeouts to work under the */ + /* posixly correct, yet non-standard glibc-2.x*/ + /* then define this- you may also need it for */ + /* IRIX, and maybe some others */ +#ifdef LINUX +#define POSIX_SETJMP +#endif + /* includes: */ #include /* timeval, time_t */ #include /* jmp_buf et al */ @@ -106,7 +117,11 @@ #define PINF struct port_poop /* globals: */ +#ifdef POSIX_SETJMP +sigjmp_buf jbuf; /* timer crud */ +#else jmp_buf jbuf; /* timer crud */ +#endif int jval = 0; /* timer crud */ int netfd = -1; int ofd = 0; /* hexdump output fd */ @@ -232,7 +247,11 @@ alarm (0); if (jval == 0) bail ("spurious timer interrupt!"); +#ifdef POSIX_SETJMP + siglongjmp (jbuf, jval); +#else longjmp (jbuf, jval); +#endif } /* arm : @@ -744,12 +763,21 @@ /* wrap connect inside a timer, and hit it */ arm (1, o_wait); +#ifdef POSIX_SETJMP + if (sigsetjmp (jbuf,1) == 0) { + rr = connect (nnetfd, (SA *)remend, sizeof (SA)); + } else { /* setjmp: connect failed... */ + rr = -1; + errno = ETIMEDOUT; /* fake it */ + } +#else if (setjmp (jbuf) == 0) { rr = connect (nnetfd, (SA *)remend, sizeof (SA)); } else { /* setjmp: connect failed... */ rr = -1; errno = ETIMEDOUT; /* fake it */ } +#endif arm (0, 0); if (rr == 0) return (nnetfd); @@ -821,7 +849,8 @@ if (o_udpmode) { x = sizeof (SA); /* retval for recvfrom */ arm (2, o_wait); /* might as well timeout this, too */ - if (setjmp (jbuf) == 0) { /* do timeout for initial connect */ +#ifdef POSIX_SETJMP + if (sigsetjmp (jbuf,1) == 0) { /* do timeout for initial connect */ rr = recvfrom /* and here we block... */ (nnetfd, bigbuf_net, BIGSIZ, MSG_PEEK, (SA *) remend, &x); Debug (("dolisten/recvfrom ding, rr = %d, netbuf %s ", rr, bigbuf_net)) @@ -842,14 +871,44 @@ rr = connect (nnetfd, (SA *)remend, sizeof (SA)); goto whoisit; } /* o_udpmode */ +#else + if (setjmp (jbuf) == 0) { /* do timeout for initial connect */ + rr = recvfrom /* and here we block... */ + (nnetfd, bigbuf_net, BIGSIZ, MSG_PEEK, (SA *) remend, &x); +Debug (("dolisten/recvfrom ding, rr = %d, netbuf %s ", rr, bigbuf_net)) + } else + goto dol_tmo; /* timeout */ + arm (0, 0); +/* I'm not completely clear on how this works -- BSD seems to make UDP + just magically work in a connect()ed context, but we'll undoubtedly run + into systems this deal doesn't work on. For now, we apparently have to + issue a connect() on our just-tickled socket so we can write() back. + Again, why the fuck doesn't it just get filled in and taken care of?! + This hack is anything but optimal. Basically, if you want your listener + to also be able to send data back, you need this connect() line, which + also has the side effect that now anything from a different source or even a + different port on the other end won't show up and will cause ICMP errors. + I guess that's what they meant by "connect". + Let's try to remember what the "U" is *really* for, eh? */ + rr = connect (nnetfd, (SA *)remend, sizeof (SA)); + goto whoisit; + } /* o_udpmode */ +#endif /* fall here for TCP */ x = sizeof (SA); /* retval for accept */ arm (2, o_wait); /* wrap this in a timer, too; 0 = forever */ +#ifdef POSIX_SETJMP + if (sigsetjmp (jbuf,1) == 0) { + rr = accept (nnetfd, (SA *)remend, &x); + } else + goto dol_tmo; /* timeout */ +#else if (setjmp (jbuf) == 0) { rr = accept (nnetfd, (SA *)remend, &x); } else goto dol_tmo; /* timeout */ +#endif arm (0, 0); close (nnetfd); /* dump the old socket */ nnetfd = rr; /* here's our new one */