BSD 4_2 release
[unix-history] / usr / src / bin / login.c
index 7bb1c6e..22066ab 100644 (file)
@@ -1,22 +1,30 @@
-static char *sccsid = "@(#)login.c     4.20 82/12/21";
+#ifndef lint
+static char *sccsid = "@(#)login.c     4.33 (Berkeley) 83/09/02";
+#endif
+
 /*
  * login [ name ]
 /*
  * login [ name ]
- * login -r
+ * login -r hostname (for rlogind)
+ * login -h hostname (for telnetd, etc.)
  */
 
  */
 
-#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/quota.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+
 #include <sgtty.h>
 #include <utmp.h>
 #include <signal.h>
 #include <pwd.h>
 #include <stdio.h>
 #include <sgtty.h>
 #include <utmp.h>
 #include <signal.h>
 #include <pwd.h>
 #include <stdio.h>
-#include <sys/stat.h>
 #include <lastlog.h>
 #include <lastlog.h>
+#include <errno.h>
 
 #define        SCPYN(a, b)     strncpy(a, b, sizeof(a))
 
 #define NMAX   sizeof(utmp.ut_name)
 
 #define        SCPYN(a, b)     strncpy(a, b, sizeof(a))
 
 #define NMAX   sizeof(utmp.ut_name)
-#define LMAX   sizeof(utmp.ut_line)
 
 #define        FALSE   0
 #define        TRUE    -1
 
 #define        FALSE   0
 #define        TRUE    -1
@@ -30,34 +38,37 @@ struct      passwd nouser = {"", "nope", -1, -1, -1, "", "", "", "" };
 struct sgttyb ttyb;
 struct utmp utmp;
 char   minusnam[16] = "-";
 struct sgttyb ttyb;
 struct utmp utmp;
 char   minusnam[16] = "-";
+/*
+ * This bounds the time given to login.  We initialize it here
+ * so it can be patched on machines where it's too small.
+ */
+int    timeout = 60;
 
 char   homedir[64] = "HOME=";
 char   shell[64] = "SHELL=";
 char   term[64] = "TERM=";
 char   user[20] = "USER=";
 
 char   homedir[64] = "HOME=";
 char   shell[64] = "SHELL=";
 char   term[64] = "TERM=";
 char   user[20] = "USER=";
-char   *speeds[] =
-    { "0", "50", "75", "110", "134", "150", "200", "300",
-      "600", "1200", "1800", "2400", "4800", "9600", "19200", "38400" };
-#define        NSPEEDS (sizeof (speeds) / sizeof (speeds[0]))
 
 char   *envinit[] =
 
 char   *envinit[] =
-    {homedir, shell, "PATH=:/usr/ucb:/bin:/usr/bin", term, user, 0};
+    { homedir, shell, "PATH=:/usr/ucb:/bin:/usr/bin", term, user, 0 };
 
 struct passwd *pwd;
 struct passwd *getpwnam();
 char   *strcat(), *rindex(), *index();
 int    setpwent();
 
 struct passwd *pwd;
 struct passwd *getpwnam();
 char   *strcat(), *rindex(), *index();
 int    setpwent();
+int    timedout();
 char   *ttyname();
 char   *crypt();
 char   *getpass();
 char   *ttyname();
 char   *crypt();
 char   *getpass();
-char   *rindex();
 char   *stypeof();
 extern char **environ;
 char   *stypeof();
 extern char **environ;
+extern int errno;
 
 
-struct ttychars tc = {
-       CERASE, CKILL,  CINTR,  CQUIT,  CSTART,
-       CSTOP,  CEOF,   CBRK,   CSUSP,  CDSUSP,
-       CRPRNT, CFLUSH, CWERASE,CLNEXT
+struct tchars tc = {
+       CINTR, CQUIT, CSTART, CSTOP, CEOT, CBRK
+};
+struct ltchars ltc = {
+       CSUSP, CDSUSP, CRPRNT, CFLUSH, CWERASE, CLNEXT
 };
 
 int    rflag;
 };
 
 int    rflag;
@@ -67,93 +78,53 @@ char        name[NMAX+1];
 char   *rhost;
 
 main(argc, argv)
 char   *rhost;
 
 main(argc, argv)
-char **argv;
+       char *argv[];
 {
        register char *namep;
 {
        register char *namep;
-       int t, f, c;
-       int invalid;
-       int quietlog;
-       int i;
+       int t, f, c, i;
+       int invalid, quietlog;
        FILE *nlfd;
        char *ttyn;
        int ldisc = 0, zero = 0;
        FILE *nlfd;
        char *ttyn;
        int ldisc = 0, zero = 0;
-       FILE *hostf; int first = 1;
 
 
-       alarm(60);
+       signal(SIGALRM, timedout);
+       alarm(timeout);
        signal(SIGQUIT, SIG_IGN);
        signal(SIGINT, SIG_IGN);
        signal(SIGQUIT, SIG_IGN);
        signal(SIGINT, SIG_IGN);
-       nice(-100);
-       nice(20);
-       nice(0);
-       if (argc > 1 && !strcmp(argv[1], "-r")) {
-               rflag++;
-               rhost = argv[2];
-               argc = 1;
-               getstr(rusername, sizeof (rusername), "remuser");
-               getstr(lusername, sizeof (lusername), "locuser");
-               getstr(term+5, sizeof(term)-5, "Terminal type");
-               if (getuid())
-                       goto abnormal;
-               setpwent();
-               pwd = getpwnam(lusername);
-               endpwent();
-               if (pwd == NULL) {
-                       if (strcmp(rusername, lusername))
-                               printf("%s: No such user\r\n", lusername);
-                       goto abnormal;
-               }
-               hostf = pwd->pw_uid ? fopen("/etc/hosts.equiv", "r") : 0;
-       again:
-               if (hostf) {
-                 char ahost[32];
-                 while (fgets(ahost, sizeof (ahost), hostf)) {
-                       char *user;
-                       if (index(ahost, '\n'))
-                               *index(ahost, '\n') = 0;
-                       user = index(ahost, ' ');
-                       if (user)
-                               *user++ = 0;
-                       if (!strcmp(rhost, ahost) &&
-                           !strcmp(rusername, user ? user : lusername)) {
-                               fclose(hostf);
-                               goto normal;
-                       }
-                 }
-                 fclose(hostf);
+       setpriority(PRIO_PROCESS, 0, 0);
+       quota(Q_SETUID, 0, 0, 0);
+       /*
+        * -r is used by rlogind to cause the autologin protocol;
+        * -h is used by other servers to pass the name of the
+        * remote host to login so that it may be placed in utmp and wtmp
+        */
+       if (argc > 1) {
+               if (strcmp(argv[1], "-r") == 0) {
+                       rflag = doremotelogin(argv[2]);
+                       SCPYN(utmp.ut_host, argv[2]);
+                       argc = 0;
                }
                }
-               if (first == 1) {
-                       first = 0;
-                       if (chdir(pwd->pw_dir) < 0)
-                               goto again;
-                       hostf = fopen(".rhosts", "r");
-                       goto again;
+               if (strcmp(argv[1], "-h") == 0 && getuid() == 0) {
+                       SCPYN(utmp.ut_host, argv[2]);
+                       argc = 0;
                }
                }
-abnormal:
-               rhost = 0;
-               rflag = -1;
        }
        }
-normal:
-       ioctl(0, TIOCLSET, &zero);      /* XXX */
+       ioctl(0, TIOCLSET, &zero);
        ioctl(0, TIOCNXCL, 0);
        ioctl(0, FIONBIO, &zero);
        ioctl(0, FIOASYNC, &zero);
        ioctl(0, TIOCNXCL, 0);
        ioctl(0, FIONBIO, &zero);
        ioctl(0, FIOASYNC, &zero);
-       ioctl(0, TIOCGETP, &ttyb);      /* XXX */
-       if (rflag) {
-               char *cp = index(term, '/');
-               if (cp) {
-                       int i;
-                       *cp++ = 0;
-                       for (i = 0; i < NSPEEDS; i++)
-                               if (!strcmp(speeds[i], cp)) {
-                                       ttyb.sg_ispeed = ttyb.sg_ospeed = i;
-                                       break;
-                               }
-               }
-               ttyb.sg_flags = ECHO|CRMOD|ANYP|XTABS;
-       }
-       ioctl(0, TIOCSETP, &ttyb);      /* XXX */
-       ioctl(0, TIOCCSET, &tc);
-       for (t=3; t<20; t++)
+       ioctl(0, TIOCGETP, &ttyb);
+       /*
+        * If talking to an rlogin process,
+        * propagate the terminal type and
+        * baud rate across the network.
+        */
+       if (rflag)
+               doremoteterm(term, &ttyb);
+       ioctl(0, TIOCSLTC, &ltc);
+       ioctl(0, TIOCSETC, &tc);
+       ioctl(0, TIOCSETP, &ttyb);
+       for (t = getdtablesize(); t > 3; t--)
                close(t);
        ttyn = ttyname(0);
        if (ttyn==(char *)0)
                close(t);
        ttyn = ttyname(0);
        if (ttyn==(char *)0)
@@ -163,61 +134,57 @@ normal:
                ioctl(0, TIOCSETD, &ldisc);
                invalid = FALSE;
                SCPYN(utmp.ut_name, "");
                ioctl(0, TIOCSETD, &ldisc);
                invalid = FALSE;
                SCPYN(utmp.ut_name, "");
-               if (argc>1) {
+               /*
+                * Name specified, take it.
+                */
+               if (argc > 1) {
                        SCPYN(utmp.ut_name, argv[1]);
                        argc = 0;
                }
                        SCPYN(utmp.ut_name, argv[1]);
                        argc = 0;
                }
+               /*
+                * If remote login take given name,
+                * otherwise prompt user for something.
+                */
                if (rflag) {
                        SCPYN(utmp.ut_name, lusername);
                if (rflag) {
                        SCPYN(utmp.ut_name, lusername);
+                       /* autologin failed, prompt for passwd */
                        if (rflag == -1)
                                rflag = 0;
                } else
                        if (rflag == -1)
                                rflag = 0;
                } else
-                       while (utmp.ut_name[0] == '\0') {
-                               namep = utmp.ut_name;
-                               { char hostname[32];
-                                 gethostname(hostname, sizeof (hostname));
-                                 printf("%s login: ", hostname); }
-                               while ((c = getchar()) != '\n') {
-                                       if (c == ' ')
-                                               c = '_';
-                                       if (c == EOF)
-                                               exit(0);
-                                       if (namep < utmp.ut_name+NMAX)
-                                               *namep++ = c;
-                               }
-                       }
-               if (rhost == 0) {
-                       setpwent();
-                       if ((pwd = getpwnam(utmp.ut_name)) == NULL)
-                               pwd = &nouser;
-                       endpwent();
-               }
+                       getloginname(&utmp);
                if (!strcmp(pwd->pw_shell, "/bin/csh")) {
                        ldisc = NTTYDISC;
                        ioctl(0, TIOCSETD, &ldisc);
                }
                if (!strcmp(pwd->pw_shell, "/bin/csh")) {
                        ldisc = NTTYDISC;
                        ioctl(0, TIOCSETD, &ldisc);
                }
-               if (rhost == 0) {
-                       if (*pwd->pw_passwd != '\0') {
-                               char *pp;
-                               nice(-4);
-                               if (rflag == 0)
-                                       pp = getpass("Password:");
-                               else
-                                       pp = rpassword;
-                               namep = crypt(pp,pwd->pw_passwd);
-                               nice(4);
-                               if (strcmp(namep, pwd->pw_passwd))
-                                       invalid = TRUE;
-                       }
+               /*
+                * If no remote login authentication and
+                * a password exists for this user, prompt
+                * for one and verify it.
+                */
+               if (!rflag && *pwd->pw_passwd != '\0') {
+                       char *pp;
+
+                       setpriority(PRIO_PROCESS, 0, -4);
+                       pp = getpass("Password:");
+                       namep = crypt(pp, pwd->pw_passwd);
+                       setpriority(PRIO_PROCESS, 0, 0);
+                       if (strcmp(namep, pwd->pw_passwd))
+                               invalid = TRUE;
                }
                }
+               /*
+                * If user not super-user, check for logins disabled.
+                */
                if (pwd->pw_uid != 0 && (nlfd = fopen(nolog, "r")) > 0) {
                if (pwd->pw_uid != 0 && (nlfd = fopen(nolog, "r")) > 0) {
-                       /* logins are disabled except for root */
                        while ((c = getc(nlfd)) != EOF)
                                putchar(c);
                        fflush(stdout);
                        sleep(5);
                        exit(0);
                }
                        while ((c = getc(nlfd)) != EOF)
                                putchar(c);
                        fflush(stdout);
                        sleep(5);
                        exit(0);
                }
+               /*
+                * If valid so far and root is logging in,
+                * see if root logins on this terminal are permitted.
+                */
                if (!invalid && pwd->pw_uid == 0 &&
                    !rootterm(ttyn+sizeof("/dev/")-1)) {
                        logerr("ROOT LOGIN REFUSED %s",
                if (!invalid && pwd->pw_uid == 0 &&
                    !rootterm(ttyn+sizeof("/dev/")-1)) {
                        logerr("ROOT LOGIN REFUSED %s",
@@ -227,7 +194,7 @@ normal:
                if (invalid) {
                        printf("Login incorrect\n");
                        if (ttyn[sizeof("/dev/tty")-1] == 'd')
                if (invalid) {
                        printf("Login incorrect\n");
                        if (ttyn[sizeof("/dev/tty")-1] == 'd')
-                               logerr("BADDIALUP %s %s\n",
+                               logerr("BADDIALUP %s %s",
                                    ttyn+sizeof("/dev/")-1, utmp.ut_name);
                }
                if (*pwd->pw_shell == '\0')
                                    ttyn+sizeof("/dev/")-1, utmp.ut_name);
                }
                if (*pwd->pw_shell == '\0')
@@ -238,48 +205,66 @@ normal:
                                printf("No directory!\n");
                                invalid = TRUE;
                        } else {
                                printf("No directory!\n");
                                invalid = TRUE;
                        } else {
-                               printf("No directory!  Logging in with home=/\n");
+                               printf("No directory! %s\n",
+                                  "Logging in with home=/");
                                pwd->pw_dir = "/";
                        }
                }
                                pwd->pw_dir = "/";
                        }
                }
+               /*
+                * Remote login invalid must have been because
+                * of a restriction of some sort, no extra chances.
+                */
                if (rflag && invalid)
                        exit(1);
        } while (invalid);
                if (rflag && invalid)
                        exit(1);
        } while (invalid);
+/* committed to login turn off timeout */
+       alarm(0);
 
 
-
+       if (quota(Q_SETUID, pwd->pw_uid, 0, 0) < 0) {
+               if (errno == EUSERS)
+                       printf("%s.\n%s.\n",
+                          "Too many users logged on already",
+                          "Try again later");
+               else if (errno == EPROCLIM)
+                       printf("You have too many processes running.\n");
+               else
+                       perror("setuid");
+               sleep(5);
+               exit(0);
+       }
        time(&utmp.ut_time);
        t = ttyslot();
        time(&utmp.ut_time);
        t = ttyslot();
-       if (t>0 && (f = open("/etc/utmp", 1)) >= 0) {
+       if (t > 0 && (f = open("/etc/utmp", 1)) >= 0) {
                lseek(f, (long)(t*sizeof(utmp)), 0);
                SCPYN(utmp.ut_line, rindex(ttyn, '/')+1);
                write(f, (char *)&utmp, sizeof(utmp));
                close(f);
        }
                lseek(f, (long)(t*sizeof(utmp)), 0);
                SCPYN(utmp.ut_line, rindex(ttyn, '/')+1);
                write(f, (char *)&utmp, sizeof(utmp));
                close(f);
        }
-       if (t>0 && (f = open("/usr/adm/wtmp", 1)) >= 0) {
+       if (t > 0 && (f = open("/usr/adm/wtmp", 1)) >= 0) {
                lseek(f, 0L, 2);
                write(f, (char *)&utmp, sizeof(utmp));
                close(f);
        }
                lseek(f, 0L, 2);
                write(f, (char *)&utmp, sizeof(utmp));
                close(f);
        }
-       quietlog = 0;
-       if (access(qlog, 0) == 0)
-               quietlog = 1;
+       quietlog = access(qlog, 0) == 0;
        if ((f = open(lastlog, 2)) >= 0) {
                struct lastlog ll;
 
                lseek(f, (long)pwd->pw_uid * sizeof (struct lastlog), 0);
                if (read(f, (char *) &ll, sizeof ll) == sizeof ll &&
        if ((f = open(lastlog, 2)) >= 0) {
                struct lastlog ll;
 
                lseek(f, (long)pwd->pw_uid * sizeof (struct lastlog), 0);
                if (read(f, (char *) &ll, sizeof ll) == sizeof ll &&
-                   ll.ll_time != 0) {
-                       if (quietlog == 0)
-                       printf("Last login: %.*s on %.*s\n"
-                           , 24-5
-                           , (char *) ctime(&ll.ll_time)
-                           , sizeof(ll.ll_line)
-                           , ll.ll_line
-                       );
+                   ll.ll_time != 0 && !quietlog) {
+                       printf("Last login: %.*s ",
+                           24-5, (char *)ctime(&ll.ll_time));
+                       if (*ll.ll_host != '\0')
+                               printf("from %.*s\n",
+                                   sizeof (ll.ll_host), ll.ll_host);
+                       else
+                               printf("on %.*s\n",
+                                   sizeof (ll.ll_line), ll.ll_line);
                }
                lseek(f, (long)pwd->pw_uid * sizeof (struct lastlog), 0);
                time(&ll.ll_time);
                SCPYN(ll.ll_line, rindex(ttyn, '/')+1);
                }
                lseek(f, (long)pwd->pw_uid * sizeof (struct lastlog), 0);
                time(&ll.ll_time);
                SCPYN(ll.ll_line, rindex(ttyn, '/')+1);
+               SCPYN(ll.ll_host, utmp.ut_host);
                write(f, (char *) &ll, sizeof ll);
                close(f);
        }
                write(f, (char *) &ll, sizeof ll);
                close(f);
        }
@@ -289,6 +274,7 @@ normal:
        strncpy(name, utmp.ut_name, NMAX);
        name[NMAX] = '\0';
        initgroups(name, pwd->pw_gid);
        strncpy(name, utmp.ut_name, NMAX);
        name[NMAX] = '\0';
        initgroups(name, pwd->pw_gid);
+       quota(Q_DOWARN, pwd->pw_uid, (dev_t)-1, 0);
        setuid(pwd->pw_uid);
        environ = envinit;
        strncat(homedir, pwd->pw_dir, sizeof(homedir)-6);
        setuid(pwd->pw_uid);
        environ = envinit;
        strncat(homedir, pwd->pw_dir, sizeof(homedir)-6);
@@ -301,10 +287,10 @@ normal:
        else
                namep++;
        strcat(minusnam, namep);
        else
                namep++;
        strcat(minusnam, namep);
-       alarm(0);
        umask(022);
        if (ttyn[sizeof("/dev/tty")-1] == 'd')
        umask(022);
        if (ttyn[sizeof("/dev/tty")-1] == 'd')
-               logerr("DIALUP %s %s\n", ttyn+sizeof("/dev/")-1, pwd->pw_name);
+               logerr("DIALUP %s %s",
+                   ttyn+sizeof("/dev/")-1, pwd->pw_name);
        if (!quietlog) {
                showmotd();
                strcat(maildir, pwd->pw_name);
        if (!quietlog) {
                showmotd();
                strcat(maildir, pwd->pw_name);
@@ -315,7 +301,7 @@ normal:
                                printf("You have mail.\n");
                }
        }
                                printf("You have mail.\n");
                }
        }
-       
+       signal(SIGALRM, SIG_DFL);
        signal(SIGQUIT, SIG_DFL);
        signal(SIGINT, SIG_DFL);
        signal(SIGTSTP, SIG_IGN);
        signal(SIGQUIT, SIG_DFL);
        signal(SIGINT, SIG_DFL);
        signal(SIGTSTP, SIG_IGN);
@@ -325,6 +311,39 @@ normal:
        exit(0);
 }
 
        exit(0);
 }
 
+getloginname(up)
+       register struct utmp *up;
+{
+       register char *namep;
+       char c;
+
+       while (up->ut_name[0] == '\0') {
+               namep = up->ut_name;
+               printf("login: ");
+               while ((c = getchar()) != '\n') {
+                       if (c == ' ')
+                               c = '_';
+                       if (c == EOF)
+                               exit(0);
+                       if (namep < up->ut_name+NMAX)
+                               *namep++ = c;
+               }
+       }
+       strncpy(lusername, up->ut_name, NMAX);
+       lusername[NMAX] = 0;
+       setpwent();
+       if ((pwd = getpwnam(lusername)) == NULL)
+               pwd = &nouser;
+       endpwent();
+}
+
+timedout()
+{
+
+       printf("Login timed out after %d seconds\n", timeout);
+       exit(0);
+}
+
 int    stopmotd;
 catch()
 {
 int    stopmotd;
 catch()
 {
@@ -339,8 +358,6 @@ rootterm(tty)
        register FILE *fd;
        char buf[100];
 
        register FILE *fd;
        char buf[100];
 
-       if (rflag)
-               return(1);
        if ((fd = fopen(securetty, "r")) == NULL)
                return(1);
        while (fgets(buf, sizeof buf, fd) != NULL) {
        if ((fd = fopen(securetty, "r")) == NULL)
                return(1);
        while (fgets(buf, sizeof buf, fd) != NULL) {
@@ -373,12 +390,12 @@ showmotd()
 
 char *
 stypeof(ttyid)
 
 char *
 stypeof(ttyid)
-char   *ttyid;
+       char *ttyid;
 {
 {
-       static char     typebuf[16];
-       char            buf[50];
-       register FILE   *f;
-       register char   *p, *t, *q;
+       static char typebuf[16];
+       char buf[50];
+       register FILE *f;
+       register char *p, *t, *q;
 
        if (ttyid == NULL)
                return (UNKNOWN);
 
        if (ttyid == NULL)
                return (UNKNOWN);
@@ -391,17 +408,16 @@ char      *ttyid;
                        q = p + 1;
 
        /* scan the file */
                        q = p + 1;
 
        /* scan the file */
-       while (fgets(buf, sizeof buf, f) != NULL)
-       {
-               for (t=buf; *t!=' ' && *t != '\t'; t++)
+       while (fgets(buf, sizeof buf, f) != NULL) {
+               for (t = buf; *t != ' ' && *t != '\t'; t++)
                        ;
                *t++ = 0;
                while (*t == ' ' || *t == '\t')
                        t++;
                        ;
                *t++ = 0;
                while (*t == ' ' || *t == '\t')
                        t++;
-               for (p=t; *p>' '; p++)
+               for (p = t; *p > ' '; p++)
                        ;
                *p = 0;
                        ;
                *p = 0;
-               if (strcmp(q,t)==0) {
+               if (strcmp(q,t) == 0) {
                        strcpy(typebuf, buf);
                        fclose(f);
                        return (typebuf);
                        strcpy(typebuf, buf);
                        fclose(f);
                        return (typebuf);
@@ -411,6 +427,72 @@ char       *ttyid;
        return (UNKNOWN);
 }
 
        return (UNKNOWN);
 }
 
+doremotelogin(host)
+       char *host;
+{
+       FILE *hostf;
+       int first = 1;
+
+       getstr(rusername, sizeof (rusername), "remuser");
+       getstr(lusername, sizeof (lusername), "locuser");
+       getstr(term+5, sizeof(term)-5, "Terminal type");
+       if (getuid()) {
+               pwd = &nouser;
+               goto bad;
+       }
+       setpwent();
+       pwd = getpwnam(lusername);
+       endpwent();
+       if (pwd == NULL) {
+               pwd = &nouser;
+               goto bad;
+       }
+       hostf = pwd->pw_uid ? fopen("/etc/hosts.equiv", "r") : 0;
+again:
+       if (hostf) {
+               char ahost[32];
+
+               while (fgets(ahost, sizeof (ahost), hostf)) {
+                       char *user;
+
+                       if ((user = index(ahost, '\n')) != 0)
+                               *user++ = '\0';
+                       if ((user = index(ahost, ' ')) != 0)
+                               *user++ = '\0';
+                       if (!strcmp(host, ahost) &&
+                           !strcmp(rusername, user ? user : lusername)) {
+                               fclose(hostf);
+                               return (1);
+                       }
+               }
+               fclose(hostf);
+       }
+       if (first == 1) {
+               char *rhosts = ".rhosts";
+               struct stat sbuf;
+
+               first = 0;
+               if (chdir(pwd->pw_dir) < 0)
+                       goto again;
+               if (lstat(rhosts, &sbuf) < 0)
+                       goto again;
+               if ((sbuf.st_mode & S_IFMT) == S_IFLNK) {
+                       printf("login: .rhosts is a soft link.\r\n");
+                       goto bad;
+               }
+               hostf = fopen(rhosts, "r");
+               fstat(fileno(hostf), &sbuf);
+               if (sbuf.st_uid && sbuf.st_uid != pwd->pw_uid) {
+                       printf("login: Bad .rhosts ownership.\r\n");
+                       fclose(hostf);
+                       goto bad;
+               }
+               goto again;
+       }
+bad:
+       return (-1);
+}
+
 getstr(buf, cnt, err)
        char *buf;
        int cnt;
 getstr(buf, cnt, err)
        char *buf;
        int cnt;
@@ -429,8 +511,39 @@ getstr(buf, cnt, err)
        } while (c != 0);
 }
 
        } while (c != 0);
 }
 
+char   *speeds[] =
+    { "0", "50", "75", "110", "134", "150", "200", "300",
+      "600", "1200", "1800", "2400", "4800", "9600", "19200", "38400" };
+#define        NSPEEDS (sizeof (speeds) / sizeof (speeds[0]))
+
+doremoteterm(term, tp)
+       char *term;
+       struct sgttyb *tp;
+{
+       char *cp = index(term, '/');
+       register int i;
+
+       if (cp) {
+               *cp++ = 0;
+               for (i = 0; i < NSPEEDS; i++)
+                       if (!strcmp(speeds[i], cp)) {
+                               tp->sg_ispeed = tp->sg_ospeed = i;
+                               break;
+                       }
+       }
+       tp->sg_flags = ECHO|CRMOD|ANYP|XTABS;
+}
+
 logerr(fmt, a1, a2, a3)
        char *fmt, *a1, *a2, *a3;
 {
 logerr(fmt, a1, a2, a3)
        char *fmt, *a1, *a2, *a3;
 {
+#ifdef LOGERR
+       FILE *cons = fopen("/dev/console", "w");
 
 
+       if (cons != NULL) {
+               fprintf(cons, fmt, a1, a2, a3);
+               fprintf(cons, "\n\r");
+               fclose(cons);
+       }
+#endif
 }
 }