--- /tmp/td1.c  2008-11-10 09:28:49.000000000 -0800
+++ /tmp/td2.c  2008-11-11 15:14:06.000000000 -0800
@@ -74,9 +74,6 @@
    past (bf + len) then that IAC will be left unprocessed and *processed
    will be less than len.
 
-   FIXME - if we mean to send 0xFF to the terminal then it will be escaped,
-   what is the escape character?  We aren't handling that situation here.
-
    CR-LF ->'s CR mapping is also done here, for convenience.
 
    NB: may fail to remove iacs which wrap around buffer!
@@ -103,6 +100,14 @@
                        if (c == '\r' && ptr < end && (*ptr == '\n' || *ptr == '\0'))
                                ptr++;
                } else {
+                       if ((ptr+1) >= end)     // Need at least 2 bytes.
+                               break;
+                       if (ptr[1] == NOP)      // Ignore?  (Keepalive, etc.)
+                               ptr += 2;
+                       else if (ptr[1] == IAC){// Literal IAC?
+                               *totty++ = ptr[1];
+                               ptr += 2;
+                       } else
                        /*
                         * TELOPT_NAWS support!
                         */
@@ -148,17 +153,58 @@
        return memmove(ptr - num_totty, ptr0, num_totty);
 }
 
+/*
+   Add an IAC escape for any literal IAC's found in buf2.
+
+   NB: will fail to quote IAC's which wrap around buffer!
+ */
+static void
+add_iacs(struct tsession *ts, int *pnum_fromtty)
+{
+       unsigned char *ptr = TS_BUF2 + ts->rdidx2;
+       unsigned char *end = ptr + MIN(BUFSIZE - ts->rdidx2, *pnum_fromtty);
+
+       while (ptr < end) {
+               if (*ptr == IAC) {
+                       memmove(ptr+1, ptr, end - ptr); // Results in dupe IAC!
+                       if (end < TS_BUF2 + BUFSIZE)
+                               end++;
+                       (*pnum_fromtty)++;
+                       ptr++; // Don't process the dupe next time either.
+               }
+               ptr++;
+       }
+}
+
 
 static struct tsession *
 make_new_session(
                USE_FEATURE_TELNETD_STANDALONE(int sock)
                SKIP_FEATURE_TELNETD_STANDALONE(void)
 ) {
-       const char *login_argv[2];
+       const char *login_argv[3];
        struct termios termbuf;
        int fd, pid;
        char tty_name[GETPTY_BUFSIZE];
        struct tsession *ts = xzalloc(sizeof(struct tsession) + BUFSIZE * 2);
+       struct sockaddr_in ir_sin;
+       socklen_t size;
+       char envBuf[32];
+
+       size = sizeof(ir_sin);
+
+       memset(envBuf,0, sizeof envBuf);
+
+       // grab the peer IP address before it's gone
+       if (getpeername(sock, (struct sockaddr *) &ir_sin, &size) < 0) {
+          fprintf(stdout, "%s %d getsockname error\n\r",__FUNCTION__,__LINE__);
+          bb_perror_msg("getsockname");
+       }
+       else
+       {
+          //fprintf(stdout, "%s %d 0x%s\n\r",__FUNCTION__,__LINE__,inet_ntoa(ir_sin.sin_addr));
+          snprintf(envBuf, sizeof envBuf - 1, "-h%s",inet_ntoa(ir_sin.sin_addr));
+       }
 
        /*ts->buf1 = (char *)(ts + 1);*/
        /*ts->buf2 = ts->buf1 + BUFSIZE;*/
@@ -256,7 +302,8 @@
 
        /* Exec shell / login / whatever */
        login_argv[0] = loginpath;
-       login_argv[1] = NULL;
+       login_argv[1] = envBuf;
+       login_argv[2] = NULL;
        /* exec busybox applet (if PREFER_APPLETS=y), if that fails,
         * exec external program */
        BB_EXECVP(loginpath, (char **)login_argv);
@@ -269,8 +316,9 @@
 enum {
        OPT_WATCHCHILD = (1 << 2), /* -K */
        OPT_INETD      = (1 << 3) * ENABLE_FEATURE_TELNETD_STANDALONE, /* -i */
-       OPT_PORT       = (1 << 4) * ENABLE_FEATURE_TELNETD_STANDALONE, /* -p */
-       OPT_FOREGROUND = (1 << 6) * ENABLE_FEATURE_TELNETD_STANDALONE, /* -F */
+       OPT_NKEEPALIVE = (1 << 4) * ENABLE_FEATURE_TELNETD_STANDALONE, /* -n */
+       OPT_PORT       = (1 << 5) * ENABLE_FEATURE_TELNETD_STANDALONE, /* -p */
+       OPT_FOREGROUND = (1 << 7) * ENABLE_FEATURE_TELNETD_STANDALONE, /* -F */
 };
 
 #if ENABLE_FEATURE_TELNETD_STANDALONE
@@ -373,7 +421,7 @@
 #endif
        /* Even if !STANDALONE, we accept (and ignore) -i, thus people
         * don't need to guess whether it's ok to pass -i to us */
-       opt = getopt32(argv, "f:l:Ki" USE_FEATURE_TELNETD_STANDALONE("p:b:F"),
+       opt = getopt32(argv, "f:l:Kin" USE_FEATURE_TELNETD_STANDALONE("p:b:F"),
                        &issuefile, &loginpath
                        USE_FEATURE_TELNETD_STANDALONE(, &opt_portnbr, &opt_bindaddr));
        if (!IS_INETD /*&& !re_execed*/) {
@@ -401,6 +449,9 @@
 
 #if ENABLE_FEATURE_TELNETD_STANDALONE
        if (IS_INETD) {
+               if (!(opt & OPT_NKEEPALIVE))
+                       setsockopt(0, SOL_SOCKET, SO_KEEPALIVE,
+                       &const_int_1, sizeof(const_int_1));
                sessions = make_new_session(0);
                if (!sessions) /* pty opening or vfork problem, exit */
                        return 1; /* make_new_session prints error message */
@@ -409,6 +460,9 @@
                xlisten(master_fd, 1);
        }
 #else
+       if (!(opt & OPT_NKEEPALIVE))
+               setsockopt(0, SOL_SOCKET, SO_KEEPALIVE,
+               &const_int_1, sizeof(const_int_1));
        sessions = make_new_session();
        if (!sessions) /* pty opening or vfork problem, exit */
                return 1; /* make_new_session prints error message */
@@ -489,6 +543,9 @@
                if (fd < 0)
                        goto again;
                /* Create a new session and link it into our active list */
+               if (!(opt & OPT_NKEEPALIVE))
+                       setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE,
+                       &const_int_1, sizeof(const_int_1));
                new_ts = make_new_session(fd);
                if (new_ts) {
                        new_ts->next = sessions;
@@ -579,6 +636,7 @@
                                        goto skip4;
                                goto kill_session;
                        }
+                       add_iacs(ts, &count);
                        ts->size2 += count;
                        ts->rdidx2 += count;
                        if (ts->rdidx2 >= BUFSIZE) /* actually == BUFSIZE */
[jimc@localhost rel_6_4_0]$ 
