set term since login expects it now
[unix-history] / usr / src / libexec / telnetd / telnetd.c
index a86f912..1698d4c 100644 (file)
@@ -1,5 +1,5 @@
 #ifndef lint
 #ifndef lint
-static char sccsid[] = "@(#)telnetd.c  4.11 82/11/15";
+static char sccsid[] = "@(#)telnetd.c  4.25 (Berkeley) 83/07/06";
 #endif
 
 /*
 #endif
 
 /*
@@ -7,19 +7,20 @@ static char sccsid[] = "@(#)telnetd.c 4.11 82/11/15";
  */
 #include <sys/types.h>
 #include <sys/socket.h>
  */
 #include <sys/types.h>
 #include <sys/socket.h>
+#include <sys/wait.h>
 
 #include <netinet/in.h>
 
 
 #include <netinet/in.h>
 
+#include <arpa/telnet.h>
+
 #include <stdio.h>
 #include <signal.h>
 #include <errno.h>
 #include <sgtty.h>
 #include <stdio.h>
 #include <signal.h>
 #include <errno.h>
 #include <sgtty.h>
-#include <wait.h>
 #include <netdb.h>
 
 #include <netdb.h>
 
-#include "telnet.h"
-
-#define        BELL            '\07'
+#define        BELL    '\07'
+#define BANNER "\r\n\r\n4.2 BSD UNIX (%s)\r\n\r\r\n\r%s"
 
 char   hisopts[256];
 char   myopts[256];
 
 char   hisopts[256];
 char   myopts[256];
@@ -40,6 +41,8 @@ int   pcc, ncc;
 
 int    pty, net;
 int    inter;
 
 int    pty, net;
 int    inter;
+int    reapchild();
+extern char **environ;
 extern int errno;
 char   line[] = "/dev/ptyp0";
 
 extern int errno;
 char   line[] = "/dev/ptyp0";
 
@@ -48,8 +51,7 @@ struct        sockaddr_in sin = { AF_INET };
 main(argc, argv)
        char *argv[];
 {
 main(argc, argv)
        char *argv[];
 {
-       int s, pid;
-       union wait status;
+       int s, pid, options;
        struct servent *sp;
 
        sp = getservbyname("telnet", "tcp");
        struct servent *sp;
 
        sp = getservbyname("telnet", "tcp");
@@ -59,14 +61,18 @@ main(argc, argv)
        }
        sin.sin_port = sp->s_port;
        argc--, argv++;
        }
        sin.sin_port = sp->s_port;
        argc--, argv++;
+       if (argc > 0 && !strcmp(*argv, "-d")) {
+               options |= SO_DEBUG;
+               argc--, argv++;
+       }
        if (argc > 0) {
                sin.sin_port = atoi(*argv);
                if (sin.sin_port <= 0) {
                        fprintf(stderr, "telnetd: %s: bad port #\n", *argv);
                        exit(1);
                }
        if (argc > 0) {
                sin.sin_port = atoi(*argv);
                if (sin.sin_port <= 0) {
                        fprintf(stderr, "telnetd: %s: bad port #\n", *argv);
                        exit(1);
                }
+               sin.sin_port = htons((u_short)sin.sin_port);
        }
        }
-       sin.sin_port = htons((u_short)sin.sin_port);
 #ifndef DEBUG
        if (fork())
                exit(0);
 #ifndef DEBUG
        if (fork())
                exit(0);
@@ -83,47 +89,68 @@ main(argc, argv)
        }
 #endif
 again:
        }
 #endif
 again:
-       s = socket(0, SOCK_STREAM, 0, 0);
+       s = socket(AF_INET, SOCK_STREAM, 0, 0);
        if (s < 0) {
                perror("telnetd: socket");;
                sleep(5);
                goto again;
        }
        if (s < 0) {
                perror("telnetd: socket");;
                sleep(5);
                goto again;
        }
+       if (options & SO_DEBUG)
+               if (setsockopt(s, SOL_SOCKET, SO_DEBUG, 0, 0) < 0)
+                       perror("telnetd: setsockopt (SO_DEBUG)");
+       if (setsockopt(s, SOL_SOCKET, SO_KEEPALIVE, 0, 0) < 0)
+               perror("telnetd: setsockopt (SO_KEEPALIVE)");
        while (bind(s, (caddr_t)&sin, sizeof (sin), 0) < 0) {
                perror("telnetd: bind");
                sleep(5);
        }
        while (bind(s, (caddr_t)&sin, sizeof (sin), 0) < 0) {
                perror("telnetd: bind");
                sleep(5);
        }
+       signal(SIGCHLD, reapchild);
        listen(s, 10);
        for (;;) {
        listen(s, 10);
        for (;;) {
-               int s2;
+               struct sockaddr_in from;
+               int s2, fromlen = sizeof (from);
 
 
-               s2 = accept(s, (caddr_t)0, 0, 0);
+               s2 = accept(s, (caddr_t)&from, &fromlen);
                if (s2 < 0) {
                if (s2 < 0) {
+                       if (errno == EINTR)
+                               continue;
                        perror("telnetd: accept");
                        sleep(1);
                        continue;
                }
                if ((pid = fork()) < 0)
                        printf("Out of processes\n");
                        perror("telnetd: accept");
                        sleep(1);
                        continue;
                }
                if ((pid = fork()) < 0)
                        printf("Out of processes\n");
-               else if (pid == 0)
-                       doit(s2);
+               else if (pid == 0) {
+                       signal(SIGCHLD, SIG_IGN);
+                       doit(s2, &from);
+               }
                close(s2);
                close(s2);
-               while (wait3(status, WNOHANG, 0) > 0)
-                       continue;
        }
        /*NOTREACHED*/
 }
 
        }
        /*NOTREACHED*/
 }
 
+reapchild()
+{
+       union wait status;
+
+       while (wait3(&status, WNOHANG, 0) > 0)
+               ;
+}
+
+char   *envinit[] = { "TERM=network", 0 };
 int    cleanup();
 
 /*
  * Get a pty, scan input lines.
  */
 int    cleanup();
 
 /*
  * Get a pty, scan input lines.
  */
-doit(f)
+doit(f, who)
+       int f;
+       struct sockaddr_in *who;
 {
 {
-       char *cp = line;
+       char *cp = line, *host, *ntoa();
        int i, p, cc, t;
        struct sgttyb b;
        int i, p, cc, t;
        struct sgttyb b;
+       struct hostent *hp;
 
        for (i = 0; i < 16; i++) {
                cp[strlen("/dev/ptyp")] = "0123456789abcdef"[i];
 
        for (i = 0; i < 16; i++) {
                cp[strlen("/dev/ptyp")] = "0123456789abcdef"[i];
@@ -150,6 +177,12 @@ gotpty:
        ioctl(p, TIOCGETP, &b);
        b.sg_flags &= ~ECHO;
        ioctl(p, TIOCSETP, &b);
        ioctl(p, TIOCGETP, &b);
        b.sg_flags &= ~ECHO;
        ioctl(p, TIOCSETP, &b);
+       hp = gethostbyaddr(&who->sin_addr, sizeof (struct in_addr),
+               who->sin_family);
+       if (hp)
+               host = hp->h_name;
+       else
+               host = ntoa(who->sin_addr);
        if ((i = fork()) < 0)
                fatalperror(f, "fork", errno);
        if (i)
        if ((i = fork()) < 0)
                fatalperror(f, "fork", errno);
        if (i)
@@ -160,7 +193,8 @@ gotpty:
        dup2(t, 1);
        dup2(t, 2);
        close(t);
        dup2(t, 1);
        dup2(t, 2);
        close(t);
-       execl("/bin/login", "telnet-login", 0);
+       environ = envinit;
+       execl("/bin/login", "login", "-h", host, 0);
        fatalperror(f, "/bin/login", errno);
        /*NOTREACHED*/
 }
        fatalperror(f, "/bin/login", errno);
        /*NOTREACHED*/
 }
@@ -195,18 +229,25 @@ fatalperror(f, msg, errno)
 telnet(f, p)
 {
        int on = 1;
 telnet(f, p)
 {
        int on = 1;
+       char hostname[32];
 
        net = f, pty = p;
        ioctl(f, FIONBIO, &on);
        ioctl(p, FIONBIO, &on);
        signal(SIGTSTP, SIG_IGN);
 
        net = f, pty = p;
        ioctl(f, FIONBIO, &on);
        ioctl(p, FIONBIO, &on);
        signal(SIGTSTP, SIG_IGN);
-       sigset(SIGCHLD, cleanup);
+       signal(SIGCHLD, cleanup);
 
        /*
         * Request to do remote echo.
         */
        dooption(TELOPT_ECHO);
        myopts[TELOPT_ECHO] = 1;
 
        /*
         * Request to do remote echo.
         */
        dooption(TELOPT_ECHO);
        myopts[TELOPT_ECHO] = 1;
+       /*
+        * Show banner that getty never gave.
+        */
+       gethostname(hostname, sizeof (hostname));
+       sprintf(nfrontp, BANNER, hostname, "");
+       nfrontp += strlen(nfrontp);
        for (;;) {
                int ibits = 0, obits = 0;
                register int c;
        for (;;) {
                int ibits = 0, obits = 0;
                register int c;
@@ -579,13 +620,10 @@ netflush()
 
 cleanup()
 {
 
 cleanup()
 {
-       int how = 2;
 
        rmut();
 
        rmut();
-#ifdef notdef
-       vhangup();
-#endif
-       ioctl(net, SIOCDONE, &how);
+       vhangup();      /* XXX */
+       shutdown(net, 2);
        kill(0, SIGKILL);
        exit(1);
 }
        kill(0, SIGKILL);
        exit(1);
 }
@@ -610,6 +648,7 @@ rmut()
                                continue;
                        lseek(f, -(long)sizeof (wtmp), 1);
                        SCPYN(wtmp.ut_name, "");
                                continue;
                        lseek(f, -(long)sizeof (wtmp), 1);
                        SCPYN(wtmp.ut_name, "");
+                       SCPYN(wtmp.ut_host, "");
                        time(&wtmp.ut_time);
                        write(f, (char *)&wtmp, sizeof (wtmp));
                        found++;
                        time(&wtmp.ut_time);
                        write(f, (char *)&wtmp, sizeof (wtmp));
                        found++;
@@ -621,6 +660,7 @@ rmut()
                if (f >= 0) {
                        SCPYN(wtmp.ut_line, line+5);
                        SCPYN(wtmp.ut_name, "");
                if (f >= 0) {
                        SCPYN(wtmp.ut_line, line+5);
                        SCPYN(wtmp.ut_name, "");
+                       SCPYN(wtmp.ut_host, "");
                        time(&wtmp.ut_time);
                        lseek(f, (long)0, 2);
                        write(f, (char *)&wtmp, sizeof (wtmp));
                        time(&wtmp.ut_time);
                        lseek(f, (long)0, 2);
                        write(f, (char *)&wtmp, sizeof (wtmp));
@@ -633,3 +673,20 @@ rmut()
        chmod(line, 0666);
        chown(line, 0, 0);
 }
        chmod(line, 0666);
        chown(line, 0, 0);
 }
+
+/*
+ * Convert network-format internet address
+ * to base 256 d.d.d.d representation.
+ */
+char *
+ntoa(in)
+       struct in_addr in;
+{
+       static char b[18];
+       register char *p;
+
+       p = (char *)&in;
+#define        UC(b)   (((int)b)&0xff)
+       sprintf(b, "%d.%d.%d.%d", UC(p[0]), UC(p[1]), UC(p[2]), UC(p[3]));
+       return (b);
+}