turn on keep alives
[unix-history] / usr / src / libexec / rshd / rshd.c
index 15d80c3..f88ad8e 100644 (file)
@@ -1,5 +1,5 @@
 #ifndef lint
 #ifndef lint
-static char sccsid[] = "@(#)rshd.c     4.7 83/01/07";
+static char sccsid[] = "@(#)rshd.c     4.15 83/05/03";
 #endif
 
 #include <sys/ioctl.h>
 #endif
 
 #include <sys/ioctl.h>
@@ -16,10 +16,11 @@ static char sccsid[] = "@(#)rshd.c  4.7 83/01/07";
 #include <netdb.h>
 
 int    errno;
 #include <netdb.h>
 
 int    errno;
+int    reapchild();
 struct sockaddr_in sin = { AF_INET };
 struct passwd *getpwnam();
 char   *index(), *rindex(), *sprintf();
 struct sockaddr_in sin = { AF_INET };
 struct passwd *getpwnam();
 char   *index(), *rindex(), *sprintf();
-int    options = SO_ACCEPTCONN|SO_KEEPALIVE;
+int    options;
 /* VARARGS 1 */
 int    error();
 /*
 /* VARARGS 1 */
 int    error();
 /*
@@ -33,7 +34,6 @@ main(argc, argv)
        int argc;
        char **argv;
 {
        int argc;
        char **argv;
 {
-       union wait status;
        int f;
        struct sockaddr_in from;
        struct servent *sp;
        int f;
        struct sockaddr_in from;
        struct servent *sp;
@@ -61,6 +61,10 @@ main(argc, argv)
        sin.sin_port = sp->s_port;
        argc--, argv++;
        if (argc > 0 && !strcmp(argv[0], "-d")) {
        sin.sin_port = sp->s_port;
        argc--, argv++;
        if (argc > 0 && !strcmp(argv[0], "-d")) {
+               options |= SO_DEBUG;
+               argc--, argv++;
+       }
+       if (argc > 0) {
                int port = atoi(argv[0]);
 
                if (port < 0) {
                int port = atoi(argv[0]);
 
                if (port < 0) {
@@ -75,30 +79,43 @@ main(argc, argv)
                perror("rshd: socket");
                exit(1);
        }
                perror("rshd: socket");
                exit(1);
        }
+       if (options & SO_DEBUG && setsockopt(f, SOL_SOCKET, SO_DEBUG, 0, 0) < 0)
+               perror("rshd: setsockopt (SO_DEBUG)");
+       if (setsockopt(f, SOL_SOCKET, SO_KEEPALIVE, 0, 0) < 0)
+               perror("rshd: setsockopt (SO_KEEPALIVE)");
        if (bind(f, (caddr_t)&sin, sizeof (sin), 0) < 0) {
                perror("rshd: bind");
                exit(1);
        }
        if (bind(f, (caddr_t)&sin, sizeof (sin), 0) < 0) {
                perror("rshd: bind");
                exit(1);
        }
+       sigset(SIGCHLD, reapchild);
        listen(f, 10);
        for (;;) {
                int g, len = sizeof (from);
 
                g = accept(f, &from, &len, 0);
                if (g < 0) {
        listen(f, 10);
        for (;;) {
                int g, len = sizeof (from);
 
                g = accept(f, &from, &len, 0);
                if (g < 0) {
-                       perror("accept");
-                       sleep(1);
+                       if (errno == EINTR)
+                               continue;
+                       perror("rshd: accept");
                        continue;
                }
                if (fork() == 0) {
                        continue;
                }
                if (fork() == 0) {
+                       signal(SIGCHLD, SIG_IGN);
                        close(f);
                        doit(g, &from);
                }
                close(g);
                        close(f);
                        doit(g, &from);
                }
                close(g);
-               while (wait3(status, WNOHANG, 0) > 0)
-                       continue;
        }
 }
 
        }
 }
 
+reapchild()
+{
+       union wait status;
+
+       while (wait3(&status, WNOHANG, 0) > 0)
+               ;
+}
+
 char   username[20] = "USER=";
 char   homedir[64] = "HOME=";
 char   shell[64] = "SHELL=";
 char   username[20] = "USER=";
 char   homedir[64] = "HOME=";
 char   shell[64] = "SHELL=";
@@ -113,7 +130,7 @@ doit(f, fromp)
        char cmdbuf[NCARGS+1], *cp;
        char locuser[16], remuser[16];
        struct passwd *pwd;
        char cmdbuf[NCARGS+1], *cp;
        char locuser[16], remuser[16];
        struct passwd *pwd;
-       int s;
+       int s, backoff;
        struct hostent *hp;
        short port;
        int pv[2], pid, ready, readfrom, cc;
        struct hostent *hp;
        short port;
        int pv[2], pid, ready, readfrom, cc;
@@ -131,37 +148,46 @@ doit(f, fromp)
          }
        }
 #endif
          }
        }
 #endif
-       dup2(f, 0);
-       dup2(f, 1);
-       dup2(f, 2);
        fromp->sin_port = ntohs((u_short)fromp->sin_port);
        if (fromp->sin_family != AF_INET ||
        fromp->sin_port = ntohs((u_short)fromp->sin_port);
        if (fromp->sin_family != AF_INET ||
-           fromp->sin_port >= IPPORT_RESERVED)
+           fromp->sin_port >= IPPORT_RESERVED) {
+               fprintf(stderr, "rshd: malformed from address\n");
                exit(1);
                exit(1);
+       }
        (void) alarm(60);
        port = 0;
        for (;;) {
                char c;
        (void) alarm(60);
        port = 0;
        for (;;) {
                char c;
-               if (read(f, &c, 1) != 1)
+               if (read(f, &c, 1) != 1) {
+                       perror("rshd: read");
+                       shutdown(f, 1+1);
                        exit(1);
                        exit(1);
+               }
                if (c == 0)
                        break;
                port = port * 10 + c - '0';
        }
        (void) alarm(0);
        if (port != 0) {
                if (c == 0)
                        break;
                port = port * 10 + c - '0';
        }
        (void) alarm(0);
        if (port != 0) {
-               int lport = IPPORT_RESERVED - 1;
-               s = rresvport(0, &lport);
-               if (s < 0)
+               int lport = IPPORT_RESERVED - 1, retryshift;
+               s = rresvport(&lport);
+               if (s < 0) {
+                       perror("rshd: can't get stderr port");
+                       exit(1);
+               }
+               if (port >= IPPORT_RESERVED) {
+                       fprintf(stderr, "rshd: 2nd port not reserved\n");
                        exit(1);
                        exit(1);
-               if (port >= IPPORT_RESERVED)
-                       goto protofail;
-               (void) alarm(60);
+               }
                fromp->sin_port = htons((u_short)port);
                fromp->sin_port = htons((u_short)port);
-               if (connect(s, fromp, sizeof (*fromp), 0) < 0)
+               if (connect(s, fromp, sizeof (*fromp), 0) < 0) {
+                       perror("rshd: connect");
                        exit(1);
                        exit(1);
-               (void) alarm(0);
+               }
        }
        }
+       dup2(f, 0);
+       dup2(f, 1);
+       dup2(f, 2);
        hp = gethostbyaddr(&fromp->sin_addr, sizeof (struct in_addr),
                fromp->sin_family);
        if (hp == 0) {
        hp = gethostbyaddr(&fromp->sin_addr, sizeof (struct in_addr),
                fromp->sin_family);
        if (hp == 0) {
@@ -182,7 +208,7 @@ doit(f, fromp)
                error("No remote directory.\n");
                exit(1);
        }
                error("No remote directory.\n");
                exit(1);
        }
-       if (ruserok(hp->h_name, remuser, locuser) < 0) {
+       if (ruserok(hp->h_name, pwd->pw_uid == 0, remuser, locuser) < 0) {
                error("Permission denied.\n");
                exit(1);
        }
                error("Permission denied.\n");
                exit(1);
        }
@@ -214,6 +240,7 @@ doit(f, fromp)
                                                killpg(pid, sig);
                                }
                                if (ready & (1<<pv[0])) {
                                                killpg(pid, sig);
                                }
                                if (ready & (1<<pv[0])) {
+                                       errno = 0;
                                        cc = read(pv[0], buf, sizeof (buf));
                                        if (cc <= 0) {
                                                shutdown(s, 1+1);
                                        cc = read(pv[0], buf, sizeof (buf));
                                        if (cc <= 0) {
                                                shutdown(s, 1+1);
@@ -232,8 +259,8 @@ doit(f, fromp)
                pwd->pw_shell = "/bin/sh";
        (void) close(f);
        initgroups(pwd->pw_name, pwd->pw_gid);
                pwd->pw_shell = "/bin/sh";
        (void) close(f);
        initgroups(pwd->pw_name, pwd->pw_gid);
-       (void) setuid(pwd->pw_uid);
        (void) setgid(pwd->pw_gid);
        (void) setgid(pwd->pw_gid);
+       (void) setuid(pwd->pw_uid);
        environ = envinit;
        strncat(homedir, pwd->pw_dir, sizeof(homedir)-6);
        strncat(shell, pwd->pw_shell, sizeof(shell)-7);
        environ = envinit;
        strncat(homedir, pwd->pw_dir, sizeof(homedir)-6);
        strncat(shell, pwd->pw_shell, sizeof(shell)-7);