Add copyright
[unix-history] / usr / src / libexec / telnetd / telnetd.c
index 144e873..e8928a7 100644 (file)
@@ -1,25 +1,41 @@
+/*
+ * Copyright (c) 1983 Regents of the University of California.
+ * All rights reserved.  The Berkeley software License Agreement
+ * specifies the terms and conditions for redistribution.
+ */
+
 #ifndef lint
 #ifndef lint
-static char sccsid[] = "@(#)telnetd.c  4.15 83/01/07";
-#endif
+char copyright[] =
+"@(#) Copyright (c) 1983 Regents of the University of California.\n\
+ All rights reserved.\n";
+#endif not lint
+
+#ifndef lint
+static char sccsid[] = "@(#)telnetd.c  5.1 (Berkeley) %G%";
+#endif not lint
 
 /*
  * Stripped-down telnet server.
  */
 #include <sys/types.h>
 #include <sys/socket.h>
 
 /*
  * Stripped-down telnet server.
  */
 #include <sys/types.h>
 #include <sys/socket.h>
+#include <sys/wait.h>
+#include <sys/file.h>
+#include <sys/stat.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 <syslog.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,116 +56,85 @@ int        pcc, ncc;
 
 int    pty, net;
 int    inter;
 
 int    pty, net;
 int    inter;
+extern char **environ;
 extern int errno;
 extern int errno;
-char   line[] = "/dev/ptyp0";
-
-struct sockaddr_in sin = { AF_INET };
+char   *line;
 
 main(argc, argv)
        char *argv[];
 {
 
 main(argc, argv)
        char *argv[];
 {
-       int s, pid;
-       union wait status;
-       struct servent *sp;
-
-       sp = getservbyname("telnet", "tcp");
-       if (sp == 0) {
-               fprintf(stderr, "telnetd: tcp/telnet: unknown service\n");
-               exit(1);
-       }
-       sin.sin_port = sp->s_port;
-       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);
-               }
-               sin.sin_port = htons((u_short)sin.sin_port);
-       }
-#ifndef DEBUG
-       if (fork())
-               exit(0);
-       for (s = 0; s < 10; s++)
-               (void) close(s);
-       (void) open("/", 0);
-       (void) dup2(0, 1);
-       (void) dup2(0, 2);
-       { int tt = open("/dev/tty", 2);
-         if (tt > 0) {
-               ioctl(tt, TIOCNOTTY, 0);
-               close(tt);
-         }
-       }
-#endif
-again:
-       s = socket(AF_INET, SOCK_STREAM, 0, 0);
-       if (s < 0) {
-               perror("telnetd: socket");;
-               sleep(5);
-               goto again;
+       struct sockaddr_in from;
+       int on = 1, fromlen;
+
+       fromlen = sizeof (from);
+       if (getpeername(0, &from, &fromlen) < 0) {
+               fprintf(stderr, "%s: ", argv[0]);
+               perror("getpeername");
+               _exit(1);
        }
        }
-       while (bind(s, (caddr_t)&sin, sizeof (sin), 0) < 0) {
-               perror("telnetd: bind");
-               sleep(5);
+       if (setsockopt(0, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof (on)) < 0) {
+               openlog(argv[0], LOG_PID, 0);
+               syslog(LOG_WARNING, "setsockopt (SO_KEEPALIVE): %m");
        }
        }
-       listen(s, 10);
-       for (;;) {
-               int s2;
-
-               s2 = accept(s, (caddr_t)0, 0, 0);
-               if (s2 < 0) {
-                       perror("telnetd: accept");
-                       sleep(1);
-                       continue;
-               }
-               if ((pid = fork()) < 0)
-                       printf("Out of processes\n");
-               else if (pid == 0)
-                       doit(s2);
-               close(s2);
-               while (wait3(status, WNOHANG, 0) > 0)
-                       continue;
-       }
-       /*NOTREACHED*/
+       doit(0, &from);
 }
 
 }
 
+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;
-       int i, p, cc, t;
+       char *host, *inet_ntoa();
+       int i, p, t;
        struct sgttyb b;
        struct sgttyb b;
+       struct hostent *hp;
+       char c;
+
+       for (c = 'p'; c <= 's'; c++) {
+               struct stat stb;
 
 
-       for (i = 0; i < 16; i++) {
-               cp[strlen("/dev/ptyp")] = "0123456789abcdef"[i];
-               p = open(cp, 2);
-               if (p > 0)
-                       goto gotpty;
+               line = "/dev/ptyXX";
+               line[strlen("/dev/pty")] = c;
+               line[strlen("/dev/ptyp")] = '0';
+               if (stat(line, &stb) < 0)
+                       break;
+               for (i = 0; i < 16; i++) {
+                       line[strlen("/dev/ptyp")] = "0123456789abcdef"[i];
+                       p = open(line, 2);
+                       if (p > 0)
+                               goto gotpty;
+               }
        }
        fatal(f, "All network ports in use");
        /*NOTREACHED*/
 gotpty:
        dup2(f, 0);
        }
        fatal(f, "All network ports in use");
        /*NOTREACHED*/
 gotpty:
        dup2(f, 0);
-       cp[strlen("/dev/")] = 't';
-       t = open("/dev/tty", 2);
+       line[strlen("/dev/")] = 't';
+       t = open("/dev/tty", O_RDWR);
        if (t >= 0) {
                ioctl(t, TIOCNOTTY, 0);
                close(t);
        }
        if (t >= 0) {
                ioctl(t, TIOCNOTTY, 0);
                close(t);
        }
-       t = open(cp, 2);
+       t = open(line, O_RDWR);
        if (t < 0)
        if (t < 0)
-               fatalperror(f, cp, errno);
+               fatalperror(f, line, errno);
        ioctl(t, TIOCGETP, &b);
        b.sg_flags = CRMOD|XTABS|ANYP;
        ioctl(t, TIOCSETP, &b);
        ioctl(p, TIOCGETP, &b);
        b.sg_flags &= ~ECHO;
        ioctl(p, TIOCSETP, &b);
        ioctl(t, TIOCGETP, &b);
        b.sg_flags = CRMOD|XTABS|ANYP;
        ioctl(t, 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 = inet_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 +145,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*/
 }
@@ -171,7 +157,7 @@ fatal(f, msg)
 {
        char buf[BUFSIZ];
 
 {
        char buf[BUFSIZ];
 
-       (void) sprintf(buf, "telnetd: %s.\n", msg);
+       (void) sprintf(buf, "telnetd: %s.\r\n", msg);
        (void) write(f, buf, strlen(buf));
        exit(1);
 }
        (void) write(f, buf, strlen(buf));
        exit(1);
 }
@@ -184,7 +170,7 @@ fatalperror(f, msg, errno)
        char buf[BUFSIZ];
        extern char *sys_errlist[];
 
        char buf[BUFSIZ];
        extern char *sys_errlist[];
 
-       (void) sprintf(buf, "%s: %s", msg, sys_errlist[errno]);
+       (void) sprintf(buf, "%s: %s\r\n", msg, sys_errlist[errno]);
        fatal(f, buf);
 }
 
        fatal(f, buf);
 }
 
@@ -195,18 +181,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;
@@ -215,11 +208,11 @@ telnet(f, p)
                 * Never look for input if there's still
                 * stuff in the corresponding output buffer
                 */
                 * Never look for input if there's still
                 * stuff in the corresponding output buffer
                 */
-               if (nfrontp - nbackp)
+               if (nfrontp - nbackp || pcc > 0)
                        obits |= (1 << f);
                else
                        ibits |= (1 << p);
                        obits |= (1 << f);
                else
                        ibits |= (1 << p);
-               if (pfrontp - pbackp)
+               if (pfrontp - pbackp || ncc > 0)
                        obits |= (1 << p);
                else
                        ibits |= (1 << f);
                        obits |= (1 << p);
                else
                        ibits |= (1 << f);
@@ -337,7 +330,8 @@ telrcv()
                         * Are You There?
                         */
                        case AYT:
                         * Are You There?
                         */
                        case AYT:
-                               *pfrontp++ = BELL;
+                               strcpy(nfrontp, "\r\n[Yes]\r\n");
+                               nfrontp += 9;
                                break;
 
                        /*
                                break;
 
                        /*
@@ -600,13 +594,14 @@ rmut()
        register f;
        int found = 0;
 
        register f;
        int found = 0;
 
-       f = open(utmp, 2);
+       f = open(utmp, O_RDWR);
        if (f >= 0) {
                while(read(f, (char *)&wtmp, sizeof (wtmp)) == sizeof (wtmp)) {
                        if (SCMPN(wtmp.ut_line, line+5) || wtmp.ut_name[0]==0)
                                continue;
        if (f >= 0) {
                while(read(f, (char *)&wtmp, sizeof (wtmp)) == sizeof (wtmp)) {
                        if (SCMPN(wtmp.ut_line, line+5) || wtmp.ut_name[0]==0)
                                continue;
-                       lseek(f, -(long)sizeof (wtmp), 1);
+                       lseek(f, -(long)sizeof (wtmp), L_INCR);
                        SCPYN(wtmp.ut_name, "");
                        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++;
@@ -614,12 +609,12 @@ rmut()
                close(f);
        }
        if (found) {
                close(f);
        }
        if (found) {
-               f = open(wtmpf, 1);
+               f = open(wtmpf, O_WRONLY|O_APPEND);
                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);
                        time(&wtmp.ut_time);
-                       lseek(f, (long)0, 2);
                        write(f, (char *)&wtmp, sizeof (wtmp));
                        close(f);
                }
                        write(f, (char *)&wtmp, sizeof (wtmp));
                        close(f);
                }