Added support for credentials forwarding
authorTheodore Tso <tytso@mit.edu>
Thu, 3 Jun 1993 12:14:18 +0000 (12:14 +0000)
committerTheodore Tso <tytso@mit.edu>
Thu, 3 Jun 1993 12:14:18 +0000 (12:14 +0000)
git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@2598 dc483132-0cff-0310-8789-dd5450dbe970

src/appl/bsd/kcmd.c
src/appl/bsd/krlogin.c
src/appl/bsd/krsh.c
src/appl/bsd/login.c

index a7b9f962e8137fcaa818c5b007f367d4338133df..4dab0f2592ead45ace33143fe878eb27ef1332ae 100644 (file)
@@ -57,6 +57,8 @@ static char sccsid[] = "derived from @(#)rcmd.c       5.17 (Berkeley) 6/27/88";
 #include <errno.h>
 #include <krb5/krb5.h>
 #include <krb5/asn1.h>
+
+#include "defines.h"
      
 #ifndef MAXHOSTNAMELEN 
 #define MAXHOSTNAMELEN 64
@@ -67,7 +69,7 @@ extern        errno;
 #define        START_PORT      5120     /* arbitrary */
 char *default_service = "host";
 
-
+extern krb5_cksumtype krb5_kdc_req_sumtype;
 
 kcmd(sock, ahost, rport, locuser, remuser, cmd, fd2p, service, realm,
      cred, seqno, server_seqno, laddr, faddr, authopts)
@@ -84,7 +86,7 @@ kcmd(sock, ahost, rport, locuser, remuser, cmd, fd2p, service, realm,
      struct sockaddr_in *laddr, *faddr;
      krb5_flags authopts;
 {
-    int s, timo = 1, pid;
+    int i, s, timo = 1, pid;
     long oldmask;
     struct sockaddr_in sin, from, local_laddr;
     krb5_creds *ret_cred = 0;
@@ -97,12 +99,13 @@ kcmd(sock, ahost, rport, locuser, remuser, cmd, fd2p, service, realm,
     krb5_error *err_ret;
     krb5_ap_rep_enc_part *rep_ret;
     krb5_checksum send_cksum;
-    krb5_principal server, client;
     char *tmpstr = 0;
+    krb5_error *error;
     int sin_len;
     krb5_ccache cc;
     krb5_data outbuf;
-    
+    krb5_flags options = authopts;
+
     pid = getpid();
     hp = gethostbyname(*ahost);
     if (hp == 0) {
@@ -137,7 +140,8 @@ kcmd(sock, ahost, rport, locuser, remuser, cmd, fd2p, service, realm,
         return(-1);
     }
     if ((realm == NULL) || (realm[0] == '\0')) {
-       krb5_sname_to_principal(host_save,service,1,&ret_cred->server);
+       krb5_sname_to_principal(host_save,service,KRB5_NT_SRV_HST,
+                               &ret_cred->server);
     }
     else {
         sprintf(tmpstr,"%s/%s@%s",service,host_save,realm);
@@ -290,41 +294,63 @@ kcmd(sock, ahost, rport, locuser, remuser, cmd, fd2p, service, realm,
     status = krb5_get_credentials(0, cc, ret_cred);
     if (status) goto bad3;
 
-    krb5_cc_close(cc);
+    /* Reset internal flags; these should not be sent. */
+    authopts &= (~OPTS_FORWARD_CREDS);
+    authopts &= (~OPTS_FORWARDABLE_CREDS);
 
    /* call Kerberos library routine to obtain an authenticator,
        pass it over the socket to the server, and obtain mutual
        authentication. */
     status = krb5_sendauth((krb5_pointer) &s,
                            "KCMDV0.1", ret_cred->client, ret_cred->server,
-                           AP_OPTS_MUTUAL_REQUIRED,
+                          authopts,
                            &send_cksum,
                            ret_cred,
                            0,          /* We have the credentials */
                            seqno,
                            0,           /* don't need a subsession key */
-                           0,          /* No error return */
+                           &error,             /* No error return */
                            &rep_ret);
-    
+    if (status) {
+       printf("We have a sendauth error %d\n", error->error);
+       if (error->text.length) {
+           fprintf(stderr, "Text: %s\n", error->text.data);
+       }
+       krb5_free_error(error);
+    }  
     if (status) goto bad3;
     if (rep_ret && server_seqno) {
        *server_seqno = rep_ret->seq_number;
        krb5_free_ap_rep_enc_part(rep_ret);
     }
     
-    outbuf.length = 0;
-
-    /* Send two empty messages. These will be used in a later release
-       to send a forwarded TGT and related info. */
-    if (status = krb5_write_message((krb5_pointer)&s, &outbuf))
-       goto bad3;
-    if (status = krb5_write_message((krb5_pointer)&s, &outbuf))
-       goto bad3;
-
     (void) write(s, remuser, strlen(remuser)+1);
     (void) write(s, cmd, strlen(cmd)+1);
     (void) write(s, locuser, strlen(locuser)+1);
     
+    if (options & OPTS_FORWARD_CREDS) {   /* Forward credentials */
+       if (status = get_for_creds(ETYPE_DES_CBC_CRC,
+                                  krb5_kdc_req_sumtype,
+                                  hp->h_name,
+                                  ret_cred->client,
+                                  &ret_cred->keyblock,
+                                  /* Forwardable TGT? */
+                                  options & OPTS_FORWARDABLE_CREDS,
+                                  &outbuf)) {
+           fprintf(stderr, "kcmd: Error getting forwarded creds\n");
+           goto bad2;
+       }
+       
+       /* Send forwarded credentials */
+       if (status = krb5_write_message((krb5_pointer)&s, &outbuf))
+         goto bad3;
+    }
+    else { /* Dummy write to signal no forwarding */
+       outbuf.length = 0;
+       if (status = krb5_write_message((krb5_pointer)&s, &outbuf))
+         goto bad3;
+    }
+
     if ((rc=read(s, &c, 1)) != 1) {
        if (rc==-1) {
            perror(*ahost);
@@ -350,7 +376,7 @@ kcmd(sock, ahost, rport, locuser, remuser, cmd, fd2p, service, realm,
     if (tmpstr) xfree(tmpstr);
     if (host_save) xfree(host_save);
     
-    /* Pass back credentials if wanted */
+    /* pass back credentials if wanted */
     if (cred) krb5_copy_creds(ret_cred,cred);
     krb5_free_creds(ret_cred);
     
index 8191f5798e7eb010ea775eae6299f086af71b72f..fd4cb71140d22b525ccce5926543aef8c6b89ef2 100644 (file)
@@ -33,7 +33,6 @@ char copyright[] =
 static char sccsid[] = "@(#)rlogin.c   5.12 (Berkeley) 9/19/88";
 #endif /* not lint */
 
-#define KERBEROS
      
      /*
       * rlogin - remote login
@@ -94,8 +93,8 @@ static char sccsid[] = "@(#)rlogin.c  5.12 (Berkeley) 9/19/88";
 #include <krb5/crc-32.h>
 #include <krb5/mit-des.h>
 #include <krb5/los-proto.h>
-
 #include <com_err.h>
+#include "defines.h"
      
 #ifdef BUFSIZ
 #undef BUFSIZ
@@ -110,6 +109,7 @@ krb5_encrypt_block eblock;      /* eblock for encrypt/decrypt */
 void try_normal();
 char *krb_realm = (char *)0;
 int encrypt = 0;
+int fflag = 0, Fflag = 0;
 krb5_creds *cred;
 struct sockaddr_in local, foreign;
 
@@ -180,7 +180,7 @@ struct winsize {
 #endif /* NO_WINSIZE */
 struct winsize winsize;
 krb5_sigtype   sigwinch(), oob();
-char   *host;                          /* external, so it can be
+char   *host=0;                        /* external, so it can be
                                           reached from confirm_death() */
 
 
@@ -263,13 +263,30 @@ main(argc, argv)
     int sock;
     krb5_flags authopts;
     krb5_error_code status;
+    int debug_port = 0;
 #endif /* KERBEROS */
-    
+   
+    if (rindex(argv[0], '/'))
+      argv[0] = rindex(argv[0], '/')+1;
+
     if ( argc < 2 ) goto usage;
-    host = argv[1];
-    argc -= 2;
-    argv +=2;
+    argc--;
+    argv++;
+
   another:
+    if (argc > 0 && host == 0 && strncmp(*argv, "-", 1)) {
+       host = *argv;
+       argv++, argc--;
+       goto another;
+    }
+
+    if (argc > 0 && !strcmp(*argv, "-D")) {
+       argv++; argc--;
+       debug_port = atoi(*argv);
+       argv++; argc--;
+       goto another;
+    }
+
     if (argc > 0 && !strcmp(*argv, "-d")) {
        argv++, argc--;
        options |= SO_DEBUG;
@@ -350,6 +367,24 @@ main(argc, argv)
        argv++, argc--;
        goto another;
     }
+    if (argc > 0 && !strcmp(*argv, "-f")) {
+       if (Fflag) {
+           fprintf(stderr, "rlogin: Only one of -f and -F allowed\n");
+           goto usage;
+       }
+       fflag++;
+       argv++, argc--;
+       goto another;
+    }
+    if (argc > 0 && !strcmp(*argv, "-F")) {
+       if (fflag) {
+           fprintf(stderr, "rlogin: Only one of -f and -F allowed\n");
+           goto usage;
+       }
+       Fflag++;
+       argv++, argc--;
+       goto another;
+    }
 #endif /* KERBEROS */
     if (host == 0)
       goto usage;
@@ -410,8 +445,19 @@ main(argc, argv)
     oldmask = sigblock(sigmask(SIGURG) | sigmask(SIGUSR1));
 #endif
     
+    if (debug_port)
+      sp->s_port = htons(debug_port);
+
 #ifdef KERBEROS
     authopts = AP_OPTS_MUTUAL_REQUIRED;
+
+    /* Piggy-back forwarding flags on top of authopts; */
+    /* they will be reset in kcmd */
+    if (fflag || Fflag)
+      authopts |= OPTS_FORWARD_CREDS;
+    if (Fflag)
+      authopts |= OPTS_FORWARDABLE_CREDS;
+
     status = kcmd(&sock, &host, sp->s_port,
                  null_local_username ? NULL : pwd->pw_name,
                  name ? name : pwd->pw_name, term,
@@ -474,7 +520,7 @@ main(argc, argv)
 #ifdef KERBEROS
     fprintf (stderr,
             "usage: rlogin host [-option] [-option...] [-k realm ] [-t ttytype] [-l username]\n");
-    fprintf (stderr, "     where option is e, 7, 8, noflow, n, a, x, or c\n");
+    fprintf (stderr, "     where option is e, 7, 8, noflow, n, a, x, f, F, or c\n");
 #else /* !KERBEROS */
     fprintf (stderr,
             "usage: rlogin host [-option] [-option...] [-t ttytype] [-l username]\n");
index 57df62ad570e325221542e8fad19f0137d931ddb..194ef97008aae018f6fb3b22cb3b37c1aba91ae6 100644 (file)
@@ -35,8 +35,6 @@ char copyright[] =
 static char sccsid[] = "@(#)rsh.c      5.7 (Berkeley) 9/20/88";
 #endif /* not lint */
 
-#define KERBEROS
-     
 #include <sys/types.h>
 #include <sys/socket.h>
 #include <sys/ioctl.h>
@@ -55,6 +53,8 @@ static char sccsid[] = "@(#)rsh.c     5.7 (Berkeley) 9/20/88";
 #include <krb5/asn1.h>
 #include <krb5/crc-32.h>
 #include <krb5/mit-des.h>
+#include <krb5/osconf.h>
+#include "defines.h"
 #endif /* KERBEROS */
      
      /*
@@ -75,9 +75,9 @@ krb5_sigtype  sendsig();
 
 #ifdef KERBEROS
 char   *krb_realm = (char *)0;
-     void      try_normal();
+void   try_normal();
 #define UCB_RSH "/usr/ucb/rsh"
-#define RLOGIN_PROGRAM "/nfs/kerberos/bin/sun3/rlogin"
+#define RLOGIN_PROGRAM KRB5_PATH_RLOGIN
 #else /* KERBEROS */
 #define RLOGIN_PROGRAM "/usr/ucb/rlogin"
 #endif  /* KERBEROS */
@@ -89,7 +89,7 @@ char  *krb_realm = (char *)0;
      char **argv0;
 {
     int rem, pid;
-    char *host, *cp, **ap, buf[BUFSIZ], *args, **argv = argv0, *user = 0;
+    char *host=0, *cp, **ap, buf[BUFSIZ], *args, **argv = argv0, *user = 0;
     register int cc;
     int asrsh = 0;
     struct passwd *pwd;
@@ -100,17 +100,31 @@ char      *krb_realm = (char *)0;
 #ifdef KERBEROS
     krb5_flags authopts;
     krb5_error_code status;
+    int fflag = 0, Fflag = 0;
+    int debug_port = 0;
 #endif  /* KERBEROS */
-    
+   
+    if (rindex(argv[0], '/'))
+      argv[0] = rindex(argv[0], '/')+1; 
+
     if ( argc < 2 ) goto usage;
-    host = argv[1];
-    argc -= 2;
-    argv +=2;  
-    if (!strcmp(host, "rsh")) {
-       host = *argv++, --argc;
-       asrsh = 1;
-    }
+    argc--;
+    argv++;
+
   another:
+    if (argc > 0 && host == 0 && strncmp(*argv, "-", 1)) {
+       host = *argv;
+       argv++, argc--;
+       goto another;
+    }
+
+    if (argc > 0 && !strcmp(*argv, "-D")) {
+       argv++; argc--;
+       debug_port = atoi(*argv);
+       argv++; argc--;
+       goto another;
+    }
+
     if (argc > 0 && !strcmp(*argv, "-l")) {
        argv++, argc--;
        if (argc > 0)
@@ -149,7 +163,24 @@ char       *krb_realm = (char *)0;
        argv++, argc--;
        goto another;
     }
-    
+    if (argc > 0 && !strncmp(*argv, "-f", 2)) {
+       if (Fflag) {
+           fprintf(stderr, "rsh: Only one of -f and -F allowed\n");
+           goto usage;
+       }
+       fflag++;
+       argv++, argc--;
+       goto another;
+    }
+    if (argc > 0 && !strncmp(*argv, "-F", 2)) {
+       if (fflag) {
+           fprintf(stderr, "rsh: Only one of -f and -F allowed\n");
+           goto usage;
+       }
+       Fflag++;
+       argv++, argc--;
+       goto another;
+    }
 #endif  /* KERBEROS */
     /*
      * Ignore the -L, -w, -e and -8 flags to allow aliases with rlogin
@@ -206,8 +237,6 @@ char        *krb_realm = (char *)0;
     if (host == 0)
       goto usage;
     if (argv[0] == 0) {
-       if (asrsh)
-         *argv0 = "rlogin";
        execv(RLOGIN_PROGRAM, argv0);
        perror(RLOGIN_PROGRAM);
        exit(1);
@@ -242,9 +271,21 @@ char       *krb_realm = (char *)0;
 #endif /* KERBEROS */
        exit(1);
     }
+
+    if (debug_port)
+      sp->s_port = debug_port;
+    
 #ifdef KERBEROS
     krb5_init_ets();
     authopts = AP_OPTS_MUTUAL_REQUIRED;
+
+    /* Piggy-back forwarding flags on top of authopts; */
+    /* they will be reset in kcmd */
+    if (fflag || Fflag)
+      authopts |= OPTS_FORWARD_CREDS;
+    if (Fflag)
+      authopts |= OPTS_FORWARDABLE_CREDS;    
+
     status = kcmd(&rem, &host, sp->s_port,
                  pwd->pw_name,
                  user ? user : pwd->pw_name,
@@ -257,7 +298,7 @@ char        *krb_realm = (char *)0;
                  authopts);
     if (status) {
        fprintf(stderr,
-               "%s: kcmd to host %s failed - %s\n",argv[0], host,
+               "%s: kcmd to host %s failed - %s\n",argv0[0], host,
                error_message(status));
        try_normal(argv0);
     }
@@ -369,7 +410,9 @@ char        *krb_realm = (char *)0;
     exit(0);
   usage:
     fprintf(stderr,
-           "usage: rsh host [ -l login ] [ -n ] command\n");
+           "usage: \trsh host [ -l login ] [ -n ] [ -f / -F] command\n");
+    fprintf(stderr,
+           "OR \trsh [ -l login ] [-n ] [ -f / -F ] host command\n");
     exit(1);
 }
 
index 36fc46fb919abc1ec7a6147a8cb6783cee9d4ca8..55118414a3e1b9c3af4c5a88b8ece840f3b450ea 100644 (file)
@@ -27,7 +27,7 @@ static char rcsid_login_c[] = "$Id$";
 
 #ifndef lint
 char copyright[] =
-  "@(#) Copyright (c) 1980, 1987, 1988 The Regents of the University of California.\n\
+"@(#) Copyright (c) 1980, 1987, 1988 The Regents of the University of California.\n\
  All rights reserved.\n";
 #endif /* not lint */
 
@@ -35,16 +35,16 @@ char copyright[] =
 static char sccsid[] = "@(#)login.c    5.25 (Berkeley) 1/6/89";
 #endif /* not lint */
 
-#define KERBEROS
-     
-     /*
     * login -f name  (for pre-authenticated login)
     * login name           (for non-authenticated/non-authorized login)
     */
-     
+/*
+ * login [ name ]
+ * login -r hostname   (for rlogind)
* login -h hostname   (for telnetd, etc.)
* login -f name       (for pre-authenticated login: datakit, xterm, etc.)
+ */
+
 #define VFS
 #define BYPASS_ROOT_CHK
-     
+
 #include <sys/param.h>
 #ifndef VFS
 #include <sys/quota.h>
@@ -54,7 +54,7 @@ static char sccsid[] = "@(#)login.c   5.25 (Berkeley) 1/6/89";
 #include <sys/resource.h>
 #include <sys/file.h>
 #include <sys/ioctl.h>
-     
+
 #include <utmp.h>
 #include <signal.h>
 #include <lastlog.h>
@@ -68,617 +68,597 @@ static char sccsid[] = "@(#)login.c       5.25 (Berkeley) 1/6/89";
 #include <setjmp.h>
 #include <stdio.h>
 #include <strings.h>
-     
+
+#include <netdb.h>
+#include <string.h>
+
 #ifdef UIDGID_T
-     uid_t getuid();
+uid_t getuid();
 #define uid_type uid_t
 #define gid_type gid_t
 #else
-     int getuid();
+int getuid();
 #define uid_type int
 #define gid_type int
 #endif /* UIDGID_T */
-     
+
 #define        TTYGRPNAME      "tty"           /* name of group to own ttys */
-     
+
 #define        MOTDFILE        "/etc/motd"
 #define        MAILDIR         "/usr/spool/mail"
 #define        NOLOGIN         "/etc/nologin"
 #define        HUSHLOGIN       ".hushlogin"
 #define        LASTLOG         "/usr/adm/lastlog"
 #define        BSHELL          "/bin/sh"
-     
+
 #ifdef VFS
 #define QUOTAWARN      "/usr/ucb/quota" /* warn user about quotas */
 #endif VFS
-     
+
 #define        UT_HOSTSIZE     sizeof(((struct utmp *)0)->ut_host)
 #define        UT_NAMESIZE     sizeof(((struct utmp *)0)->ut_name)
-     
+
 /*
  * This bounds the time given to login.  Not a define so it can
  * be patched on machines where it's too small.
  */
-int timeout = 300;
+int    timeout = 300;
 
 struct passwd *pwd;
-char term[64], *hostname, *username = NULL;
+char term[64], *hostname, *username;
 
 struct sgttyb sgttyb;
 struct tchars tc = {
-    CINTR, CQUIT, CSTART, CSTOP, CEOT, CBRK
-  };
+       CINTR, CQUIT, CSTART, CSTOP, CEOT, CBRK
+};
 struct ltchars ltc = {
-    CSUSP, CDSUSP, CRPRNT, CFLUSH, CWERASE, CLNEXT
-  };
+       CSUSP, CDSUSP, CRPRNT, CFLUSH, CWERASE, CLNEXT
+};
 
 extern int errno;
 
-char *getenv();
-int putenv();
-void setenv();
-void dofork();
-
 #ifdef POSIX
 typedef void sigtype;
 #else
 typedef int sigtype;
 #endif /* POSIX */
 
-#ifdef CRAY
-char    user[32] = "LOGNAME=";
-#include <tmpdir.h>
-char tmpdir[64] = "TMPDIR=";
-#else
-char   user[20] = "USER=";
-#endif
-
-char   homedir[64] = "HOME=";
-char   shell[64] = "SHELL=";
-
-
-#ifdef KERBEROS
-char    *envinit[] =
-#ifdef CRAY
-    {homedir, shell, PATH, user, "TZ=GMT0", tmpdir, 0};
-#define TZENV   4
-#define TMPDIRENV 5
-char    *getenv();
-extern
-#else
-    {homedir, shell, "PATH=:/usr/ucb:/bin:/usr/bin:/usr/bin/kerberos",
-   user, 0};
-#endif /* CRAY */
-#else /* !KERBEROS */
-char   *envinit[] =
-#ifdef CRAY
-    {homedir, shell, PATH, user, "TZ=GMT0", tmpdir, 0};
-#define TZENV   4
-#define TMPDIRENV 5
-char    *getenv();
-extern
-#else
-    {homedir, shell, "PATH=:/usr/ucb:/bin:/usr/bin:/usr/bin/kerberos",
-   user, 0};
-#endif /* CRAY */
-#endif /* KERBEROS */
-char **environ;
-
+#define EXCL_TEST if (rflag || hflag) { \
+                      fprintf(stderr, \
+                              "login: only one of -r and -h allowed.\n"); \
+                      exit(1);\
+                    }
 main(argc, argv)
-     int argc;
-     char **argv;
+       int argc;
+       char **argv;
 {
-    extern int optind;
-    extern char *optarg;
-    struct group *gr;
-    register int ch;
-    register char *p;
-    int fflag, pflag, cnt;
-    int quietlog, ioctlval;
-    sigtype timedout();
-    char *domain, *salt, *ttyn, *tty;
-    char tbuf[MAXPATHLEN + 2];
-    char *ttyname(), *stypeof(), *crypt(), *getpass();
-    time_t time();
-    off_t lseek();
-    int passwd_req = 1, preserve_env = 0;
-    
-    (void)signal(SIGALRM, timedout);
-    (void)alarm((u_int)timeout);
-    (void)signal(SIGQUIT, SIG_IGN);
-    (void)signal(SIGINT, SIG_IGN);
-    (void)setpriority(PRIO_PROCESS, 0, 0);
+       extern int optind;
+       extern char *optarg, **environ;
+       struct group *gr;
+       register int ch;
+       register char *p;
+       int fflag, hflag, pflag, rflag, cnt;
+       int quietlog, passwd_req, ioctlval;
+       sigtype timedout();
+       char *domain, *salt, *envinit[1], *ttyn, *tty;
+       char tbuf[MAXPATHLEN + 2];
+       char *ttyname(), *stypeof(), *crypt(), *getpass();
+       time_t time();
+       off_t lseek();
+       struct hostent *hp;
+
+       (void)signal(SIGALRM, timedout);
+       (void)alarm((u_int)timeout);
+       (void)signal(SIGQUIT, SIG_IGN);
+       (void)signal(SIGINT, SIG_IGN);
+       (void)setpriority(PRIO_PROCESS, 0, 0);
 #ifndef VFS
-    (void)quota(Q_SETUID, 0, 0, 0);
+       (void)quota(Q_SETUID, 0, 0, 0);
 #endif VFS
-    
-    (void)gethostname(tbuf, sizeof(tbuf));
-    domain = index(tbuf, '.');
-    
-    passwd_req = 1;
-    while ((ch = getopt(argc, argv, "fp")) != EOF)
-      switch (ch) {
-       case 'f':
-         passwd_req = 0;
-         break;
-       case 'p':
-         preserve_env = 1;
-         break;
-       case '?':
-       default:
-         fprintf(stderr, "usage: login [-fp] [username]\n");
-         exit(1);
-         break;
-      }
-    argc -= optind;
-    argv += optind;
-    if (*argv)
-      hostname = *argv;
-    
-    ioctlval = 0;
-    (void)ioctl(0, TIOCLSET, (char *)&ioctlval);
-    (void)ioctl(0, TIOCNXCL, (char *)0);
-    (void)fcntl(0, F_SETFL, ioctlval);
-    (void)ioctl(0, TIOCGETP, (char *)&sgttyb);
-    
-    doremotelogin();
-    
-    /*
-     * If talking to an rlogin process, propagate the terminal type and
-     * baud rate across the network.
-     */
-    doremoteterm(&sgttyb);     
-    sgttyb.sg_erase = CERASE;
-    sgttyb.sg_kill = CKILL;
-    (void)ioctl(0, TIOCSLTC, (char *)&ltc);
-    (void)ioctl(0, TIOCSETC, (char *)&tc);
-    (void)ioctl(0, TIOCSETP, (char *)&sgttyb);
-    
-    for (cnt = getdtablesize(); cnt > 2; cnt--)
-      (void) close(cnt);
-    
-    ttyn = ttyname(0);
-    if (ttyn == NULL || *ttyn == '\0')
-      ttyn = "/dev/tty??";
-    if (tty = rindex(ttyn, '/'))
-      ++tty;
-    else
-      tty = ttyn;
-    
-#ifndef LOG_ODELAY /* 4.2 syslog ... */                      
-    openlog("login", 0);
-#else
-    openlog("login", LOG_ODELAY, LOG_AUTH);
-#endif /* 4.2 syslog */
-    
-    for (cnt = 0;; username = NULL) {
+
+       /*
+        * -p is used by getty to tell login not to destroy the environment
+        * -r is used by rlogind to cause the autologin protocol;
+        * -f is used to skip a second login authentication 
+        * -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
+        */
+       (void)gethostname(tbuf, sizeof(tbuf));
+       domain = index(tbuf, '.');
+
+       fflag = hflag = pflag = rflag = 0;
+       passwd_req = 1;
+       while ((ch = getopt(argc, argv, "fh:pr:")) != EOF)
+               switch (ch) {
+               case 'f':
+                       fflag = 1;
+                       break;
+               case 'h':
+                       EXCL_TEST;
+                       if (getuid()) {
+                               fprintf(stderr,
+                                   "login: -h for super-user only.\n");
+                               exit(1);
+                       }
+                       hflag = 1;
+                       if (domain && (p = index(optarg, '.')) &&
+                           strcmp(p, domain) == 0)
+                               *p = 0;
+                       hostname = optarg;
+                       break;
+               case 'p':
+                       pflag = 1;
+                       break;
+               case 'r':
+                       EXCL_TEST;
+                       if (getuid()) {
+                               fprintf(stderr,
+                                   "login: -r for super-user only.\n");
+                               exit(1);
+                       }
+                       /* "-r hostname" must be last args */
+                       if (optind != argc) {
+                               fprintf(stderr, "Syntax error.\n");
+                               exit(1);
+                       }
+                       rflag = 1;
+                       passwd_req = (doremotelogin(optarg) == -1);
+                       if (domain && (p = index(optarg, '.')) &&
+                           !strcmp(p, domain))
+                               *p = '\0';
+                       hostname = optarg;
+                       break;
+               case '?':
+               default:
+                       fprintf(stderr, "usage: login [-fp] [-h hostname] [-r hostname] [username] \n");
+                       exit(1);
+               }
+       argc -= optind;
+       argv += optind;
+       if (*argv)
+               username = *argv;
+
+       if (!(hp = gethostbyname(hostname))) {
+           fprintf(stderr, "Unknown host: %s\n", hostname);
+           exit(1);
+       }
+       hostname = malloc(strlen(hp->h_name)+1);
+       if (!hostname) {
+               fprintf(stderr, "Couldn't malloc space for hostname.\n");
+               exit(1);
+       }
+       strcpy(hostname, hp->h_name);
+
        ioctlval = 0;
-       (void)ioctl(0, TIOCSETD, (char *)&ioctlval);
-       
-       if (username == NULL) 
-         getloginname();
-       
-       if (pwd = getpwnam(username))
-         salt = pwd->pw_passwd;
-       else
-         salt = "xx";
-       
-       /* if user not super-user, check for disabled logins */
-       if (pwd == NULL || pwd->pw_uid)
-         checknologin();
-       
+       (void)ioctl(0, TIOCLSET, (char *)&ioctlval);
+       (void)ioctl(0, TIOCNXCL, (char *)0);
+       (void)fcntl(0, F_SETFL, ioctlval);
+       (void)ioctl(0, TIOCGETP, (char *)&sgttyb);
+
        /*
-        * Disallow automatic login to root; if not invoked by
-        * root, disallow if the uid's differ.
+        * If talking to an rlogin process, propagate the terminal type and
+        * baud rate across the network.
         */
-       if (!passwd_req && pwd) {
-           int uid = (int) getuid();
-           
-           passwd_req = (uid && uid != pwd->pw_uid)
+       if (rflag)
+               doremoteterm(&sgttyb);
+       sgttyb.sg_erase = CERASE;
+       sgttyb.sg_kill = CKILL;
+       (void)ioctl(0, TIOCSLTC, (char *)&ltc);
+       (void)ioctl(0, TIOCSETC, (char *)&tc);
+       (void)ioctl(0, TIOCSETP, (char *)&sgttyb);
+
+       for (cnt = getdtablesize(); cnt > 2; cnt--)
+               (void) close(cnt);
+
+       ttyn = ttyname(0);
+       if (ttyn == NULL || *ttyn == '\0')
+               ttyn = "/dev/tty??";
+       if (tty = rindex(ttyn, '/'))
+               ++tty;
+       else
+               tty = ttyn;
+
+#ifndef LOG_ODELAY /* 4.2 syslog ... */                      
+       openlog("login", 0);
+#else
+       openlog("login", LOG_ODELAY, LOG_AUTH);
+#endif /* 4.2 syslog */
+
+       for (cnt = 0;; username = NULL) {
+               ioctlval = 0;
+               (void)ioctl(0, TIOCSETD, (char *)&ioctlval);
+
+               if (username == NULL) {
+                       fflag = 0;
+                       getloginname();
+               }
+               if (pwd = getpwnam(username))
+                       salt = pwd->pw_passwd;
+               else
+                       salt = "xx";
+
+               /* if user not super-user, check for disabled logins */
+               if (pwd == NULL || pwd->pw_uid)
+                       checknologin();
+
+               /*
+                * Disallow automatic login to root; if not invoked by
+                * root, disallow if the uid's differ.
+                */
+               if (fflag && pwd) {
+                       int uid = (int) getuid();
+
+                       passwd_req = (uid && uid != pwd->pw_uid)
 #ifndef BYPASS_ROOT_CHK
-             || (pwd->pw_uid == 0);
+                         || (pwd->pw_uid == 0);
 #else
-           ;
+                       ;
 #endif
+               }
+
+               /*
+                * If no remote login authentication and a password exists
+                * for this user, prompt for one and verify it.
+                */
+               if (!passwd_req || pwd && !*pwd->pw_passwd)
+                       break;
+
+               (void) setpriority(PRIO_PROCESS, 0, -4);
+               p = crypt(getpass("Password:"), salt);
+               (void) setpriority(PRIO_PROCESS, 0, 0);
+               if (pwd && !strcmp(p, pwd->pw_passwd))
+                       break;
+
+               printf("Login incorrect\n");
+               if (++cnt >= 5) {
+                       if (hostname)
+                           syslog(LOG_ERR,
+                               "REPEATED LOGIN FAILURES ON %s FROM %.*s, %.*s",
+                               tty, UT_HOSTSIZE, hostname, UT_NAMESIZE,
+                               username);
+                       else
+                           syslog(LOG_ERR,
+                               "REPEATED LOGIN FAILURES ON %s, %.*s",
+                               tty, UT_NAMESIZE, username);
+                       (void)ioctl(0, TIOCHPCL, (char *)0);
+                       sleepexit(1);
+               }
        }
-       
+
+       /* committed to login -- turn off timeout */
+       (void)alarm((u_int)0);
+
        /*
-        * If no remote login authentication and a password exists
-        * for this user, prompt for one and verify it.
+        * If valid so far and root is logging in, see if root logins on
+        * this terminal are permitted.
         */
-       if (!passwd_req || pwd && !*pwd->pw_passwd)
-         break;
-       
-       (void) setpriority(PRIO_PROCESS, 0, -4);
-       p = crypt(getpass("Password:"), salt);
-       (void) setpriority(PRIO_PROCESS, 0, 0);
-       if (pwd && !strcmp(p, pwd->pw_passwd))
-         break;
-       
-       printf("Login incorrect\n");
-       if (++cnt >= 5) {
-           if (hostname)
-             syslog(LOG_ERR,
-                    "REPEATED LOGIN FAILURES ON %s FROM %.*s, %.*s",
-                    tty, UT_HOSTSIZE, hostname, UT_NAMESIZE,
-                    username);
-           else
-             syslog(LOG_ERR,
-                    "REPEATED LOGIN FAILURES ON %s, %.*s",
-                    tty, UT_NAMESIZE, username);
-           (void)ioctl(0, TIOCHPCL, (char *)0);
-           sleepexit(1);
-       }
-    }
-    
-    /* committed to login -- turn off timeout */
-    (void)alarm((u_int)0);
-    
-    /*
-     * If valid so far and root is logging in, see if root logins on
-     * this terminal are permitted.
-     */
 #ifndef BYPASS_ROOT_CHK
-    if (pwd->pw_uid == 0 && !rootterm(tty)) {
-       if (hostname)
-         syslog(LOG_ERR, "ROOT LOGIN REFUSED ON %s FROM %.*s",
-                tty, UT_HOSTSIZE, hostname);
-       else
-         syslog(LOG_ERR, "ROOT LOGIN REFUSED ON %s", tty);
-       printf("Login incorrect\n");
-       sleepexit(1);
-    }
+       if (pwd->pw_uid == 0 && !rootterm(tty)) {
+               if (hostname)
+                       syslog(LOG_ERR, "ROOT LOGIN REFUSED ON %s FROM %.*s",
+                           tty, UT_HOSTSIZE, hostname);
+               else
+                       syslog(LOG_ERR, "ROOT LOGIN REFUSED ON %s", tty);
+               printf("Login incorrect\n");
+               sleepexit(1);
+       }
 #endif
-    
+
 #ifndef VFS
-    if (quota(Q_SETUID, pwd->pw_uid, 0, 0) < 0 && errno != EINVAL) {
-       switch(errno) {
-         case EUSERS:
-           fprintf(stderr,
-                   "Too many users logged on already.\nTry again later.\n");
-           break;
-         case EPROCLIM:
-           fprintf(stderr,
-                   "You have too many processes running.\n");
-           break;
-         default:
-           perror("quota (Q_SETUID)");
+       if (quota(Q_SETUID, pwd->pw_uid, 0, 0) < 0 && errno != EINVAL) {
+               switch(errno) {
+               case EUSERS:
+                       fprintf(stderr,
+               "Too many users logged on already.\nTry again later.\n");
+                       break;
+               case EPROCLIM:
+                       fprintf(stderr,
+                           "You have too many processes running.\n");
+                       break;
+               default:
+                       perror("quota (Q_SETUID)");
+               }
+               sleepexit(0);
        }
-       sleepexit(0);
-    }
 #endif /* !VFS */
-    
-    if (chdir(pwd->pw_dir) < 0) {
-       printf("No directory %s!\n", pwd->pw_dir);
-       if (chdir("/"))
-         exit(0);
-       pwd->pw_dir = "/";
-       printf("Logging in with home = \"/\".\n");
-    }
-    
-    /* nothing else left to fail -- really log in */
-    {
-       struct utmp utmp;
-       
-       (void)time(&utmp.ut_time);
-       (void) strncpy(utmp.ut_name, username, sizeof(utmp.ut_name));
-       if (hostname)
-         (void) strncpy(utmp.ut_host, hostname,
-                        sizeof(utmp.ut_host));
-       else
-         bzero(utmp.ut_host, sizeof(utmp.ut_host));
-       (void) strncpy(utmp.ut_line, tty, sizeof(utmp.ut_line));
-       login(&utmp);
-    }
-    
-    quietlog = access(HUSHLOGIN, F_OK) == 0;
-    dolastlog(quietlog, tty);
-    
-    {
-       static struct winsize win = { 0, 0, 0, 0 };
+
+       if (chdir(pwd->pw_dir) < 0) {
+               printf("No directory %s!\n", pwd->pw_dir);
+               if (chdir("/"))
+                       exit(0);
+               pwd->pw_dir = "/";
+               printf("Logging in with home = \"/\".\n");
+       }
+
+       /* nothing else left to fail -- really log in */
+       {
+               struct utmp utmp;
+
+               (void)time(&utmp.ut_time);
+               (void) strncpy(utmp.ut_name, username, sizeof(utmp.ut_name));
+               if (hostname)
+                   (void) strncpy(utmp.ut_host, hostname,
+                                  sizeof(utmp.ut_host));
+               else
+                   bzero(utmp.ut_host, sizeof(utmp.ut_host));
+               (void) strncpy(utmp.ut_line, tty, sizeof(utmp.ut_line));
+               login(&utmp);
+       }
+
+       quietlog = access(HUSHLOGIN, F_OK) == 0;
+       dolastlog(quietlog, tty);
+
+       if (!hflag && !rflag) { /* XXX */
+               static struct winsize win = { 0, 0, 0, 0 };
+
+               (void)ioctl(0, TIOCSWINSZ, (char *)&win);
+       }
+
+       (void)chown(ttyn, pwd->pw_uid,
+           (gr = getgrnam(TTYGRPNAME)) ? gr->gr_gid : pwd->pw_gid);
+       (void)chmod(ttyn, 0620);
        
-       (void)ioctl(0, TIOCSWINSZ, (char *)&win);
-    }
-    
-    (void)chown(ttyn, pwd->pw_uid,
-               (gr = getgrnam(TTYGRPNAME)) ? gr->gr_gid : pwd->pw_gid);
-    
-    (void)chmod(ttyn, 0620);
-    
-    (void)setgid((gid_type) pwd->pw_gid);
-    
-    (void) initgroups(username, pwd->pw_gid);
-    
+       (void)setgid((gid_type) pwd->pw_gid);
+
+       (void) initgroups(username, pwd->pw_gid);
+
 #ifndef VFS
-    quota(Q_DOWARN, pwd->pw_uid, (dev_t)-1, 0);
+       quota(Q_DOWARN, pwd->pw_uid, (dev_t)-1, 0);
 #endif
-    (void)setuid((uid_type) pwd->pw_uid);
-    
-    if (*pwd->pw_shell == '\0')
-      pwd->pw_shell = BSHELL;
-    /* turn on new line discipline for the csh */
-    else if (!strcmp(pwd->pw_shell, "/bin/csh")) {
-       ioctlval = NTTYDISC;
-       (void)ioctl(0, TIOCSETD, (char *)&ioctlval);
-    }
-    /* Destroy old environment unless requested. */ 
-    if (!preserve_env)
-      environ = envinit;
-    
-    setenv("HOME", pwd->pw_dir);
-    setenv("SHELL", pwd->pw_shell);
-    if (term[0] == '\0')
-      (void) strncpy(term, stypeof(tty), sizeof(term));
-    setenv("TERM", term);
-    setenv("USER", pwd->pw_name);
-    setenv("PATH", "/usr/ucb:/bin:/usr/bin:");
-    
-    if (tty[sizeof("tty")-1] == 'd')
-      syslog(LOG_INFO, "DIALUP %s, %s", tty, pwd->pw_name);
-    
-    if (!quietlog) {
-       struct stat st;
-       motd();
-       (void)sprintf(tbuf, "%s/%s", MAILDIR, pwd->pw_name);
-       if (stat(tbuf, &st) == 0 && st.st_size != 0)
-         printf("You have %smail.\n",
-                (st.st_mtime > st.st_atime) ? "new " : "");
-    }
-    
+       (void)setuid((uid_type) pwd->pw_uid);
+
+       if (*pwd->pw_shell == '\0')
+               pwd->pw_shell = BSHELL;
+       /* turn on new line discipline for the csh */
+       else if (!strcmp(pwd->pw_shell, "/bin/csh")) {
+               ioctlval = NTTYDISC;
+               (void)ioctl(0, TIOCSETD, (char *)&ioctlval);
+       }
+
+       /* destroy environment unless user has requested preservation */
+       if (!pflag)
+               environ = envinit;
+       (void)setenv("HOME", pwd->pw_dir, 1);
+       (void)setenv("SHELL", pwd->pw_shell, 1);
+       if (term[0] == '\0')
+               (void) strncpy(term, stypeof(tty), sizeof(term));
+       (void)setenv("TERM", term, 0);
+       (void)setenv("USER", pwd->pw_name, 1);
+       (void)setenv("PATH", ":/usr/ucb:/bin:/usr/bin", 0);
+
+       if (tty[sizeof("tty")-1] == 'd')
+               syslog(LOG_INFO, "DIALUP %s, %s", tty, pwd->pw_name);
+       if (pwd->pw_uid == 0)
+               if (hostname)
+                       syslog(LOG_NOTICE, "ROOT LOGIN %s FROM %.*s",
+                           tty, UT_HOSTSIZE, hostname);
+               else
+                       syslog(LOG_NOTICE, "ROOT LOGIN %s", tty);
+
+       if (!quietlog) {
+               struct stat st;
+
+               motd();
+               (void)sprintf(tbuf, "%s/%s", MAILDIR, pwd->pw_name);
+               if (stat(tbuf, &st) == 0 && st.st_size != 0)
+                       printf("You have %smail.\n",
+                           (st.st_mtime > st.st_atime) ? "new " : "");
+       }
+
 #ifdef VFS
-    if (! access( QUOTAWARN, X_OK)) (void) system(QUOTAWARN);
+       if (! access( QUOTAWARN, X_OK)) (void) system(QUOTAWARN);
 #endif VFS
-    (void)signal(SIGALRM, SIG_DFL);
-    (void)signal(SIGQUIT, SIG_DFL);
-    (void)signal(SIGINT, SIG_DFL);
-    (void)signal(SIGTSTP, SIG_IGN);
-    
-    tbuf[0] = '-';
-    (void) strcpy(tbuf + 1, (p = rindex(pwd->pw_shell, '/')) ?
-                 p + 1 : pwd->pw_shell);
-    execlp(pwd->pw_shell, tbuf, 0);
-    fprintf(stderr, "login: no shell: ");
-    perror(pwd->pw_shell);
-    exit(0);
+       (void)signal(SIGALRM, SIG_DFL);
+       (void)signal(SIGQUIT, SIG_DFL);
+       (void)signal(SIGINT, SIG_DFL);
+       (void)signal(SIGTSTP, SIG_IGN);
+
+       tbuf[0] = '-';
+       (void) strcpy(tbuf + 1, (p = rindex(pwd->pw_shell, '/')) ?
+           p + 1 : pwd->pw_shell);
+       execlp(pwd->pw_shell, tbuf, 0);
+       fprintf(stderr, "login: no shell: ");
+       perror(pwd->pw_shell);
+       exit(0);
 }
 
-
-
 getloginname()
 {
-    register int ch;
-    register char *p;
-    static char nbuf[UT_NAMESIZE + 1];
-    
-    for (;;) {
-       printf("login: ");
-       for (p = nbuf; (ch = getchar()) != '\n'; ) {
-           if (ch == EOF)
-             exit(0);
-           if (p < nbuf + UT_NAMESIZE)
-             *p++ = ch;
+       register int ch;
+       register char *p;
+       static char nbuf[UT_NAMESIZE + 1];
+
+       for (;;) {
+               printf("login: ");
+               for (p = nbuf; (ch = getchar()) != '\n'; ) {
+                       if (ch == EOF)
+                               exit(0);
+                       if (p < nbuf + UT_NAMESIZE)
+                               *p++ = ch;
+               }
+               if (p > nbuf)
+                       if (nbuf[0] == '-')
+                               fprintf(stderr,
+                                   "login names may not start with '-'.\n");
+                       else {
+                               *p = '\0';
+                               username = nbuf;
+                               break;
+                       }
        }
-       if (p > nbuf)
-         if (nbuf[0] == '-')
-           fprintf(stderr,
-                   "login names may not start with '-'.\n");
-         else {
-             *p = '\0';
-             username = nbuf;
-             break;
-         }
-    }
 }
 
-
-
 sigtype
-  timedout()
+timedout()
 {
-    fprintf(stderr, "Login timed out after %d seconds\n", timeout);
-    exit(0);
+       fprintf(stderr, "Login timed out after %d seconds\n", timeout);
+       exit(0);
 }
 
-
-
 #ifdef NOTTYENT
 int root_tty_security = 0;
 #endif
 rootterm(tty)
-     char *tty;
+       char *tty;
 {
 #ifdef NOTTYENT
-    return(root_tty_security);
+       return(root_tty_security);
 #else
-    struct ttyent *t;
-    
-    return((t = getttynam(tty)) && t->ty_status&TTY_SECURE);
+       struct ttyent *t;
+
+       return((t = getttynam(tty)) && t->ty_status&TTY_SECURE);
 #endif NOTTYENT
 }
 
-
-
 jmp_buf motdinterrupt;
 
 motd()
 {
-    register int fd, nchars;
-    sigtype (*oldint)(), sigint();
-    char tbuf[8192];
-    
-    if ((fd = open(MOTDFILE, O_RDONLY, 0)) < 0)
-      return;
-    oldint = (sigtype (*)()) signal(SIGINT, sigint);
-    if (setjmp(motdinterrupt) == 0)
-      while ((nchars = read(fd, tbuf, sizeof(tbuf))) > 0)
-       (void)write(fileno(stdout), tbuf, nchars);
-    (void)signal(SIGINT, oldint);
-    (void)close(fd);
+       register int fd, nchars;
+       sigtype (*oldint)(), sigint();
+       char tbuf[8192];
+
+       if ((fd = open(MOTDFILE, O_RDONLY, 0)) < 0)
+               return;
+       oldint = (sigtype (*)())signal(SIGINT, sigint);
+       if (setjmp(motdinterrupt) == 0)
+               while ((nchars = read(fd, tbuf, sizeof(tbuf))) > 0)
+                       (void)write(fileno(stdout), tbuf, nchars);
+       (void)signal(SIGINT, oldint);
+       (void)close(fd);
 }
 
-
-
 sigtype
-  sigint()
+sigint()
 {
-    longjmp(motdinterrupt, 1);
+       longjmp(motdinterrupt, 1);
 }
 
-
-
 checknologin()
 {
-    register int fd, nchars;
-    char tbuf[8192];
-    
-    if ((fd = open(NOLOGIN, O_RDONLY, 0)) >= 0) {
-       while ((nchars = read(fd, tbuf, sizeof(tbuf))) > 0)
-         (void)write(fileno(stdout), tbuf, nchars);
-       sleepexit(0);
-    }
-}
-
+       register int fd, nchars;
+       char tbuf[8192];
 
+       if ((fd = open(NOLOGIN, O_RDONLY, 0)) >= 0) {
+               while ((nchars = read(fd, tbuf, sizeof(tbuf))) > 0)
+                       (void)write(fileno(stdout), tbuf, nchars);
+               sleepexit(0);
+       }
+}
 
 dolastlog(quiet, tty)
-     int quiet;
-     char *tty;
+       int quiet;
+       char *tty;
 {
-    struct lastlog ll;
-    int fd;
-    
-    if ((fd = open(LASTLOG, O_RDWR, 0)) >= 0) {
-       (void)lseek(fd, (off_t)pwd->pw_uid * sizeof(ll), L_SET);
-       if (!quiet) {
-           if (read(fd, (char *)&ll, sizeof(ll)) == sizeof(ll) &&
-               ll.ll_time != 0) {
-               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);
+       struct lastlog ll;
+       int fd;
+
+       if ((fd = open(LASTLOG, O_RDWR, 0)) >= 0) {
+               (void)lseek(fd, (off_t)pwd->pw_uid * sizeof(ll), L_SET);
+               if (!quiet) {
+                       if (read(fd, (char *)&ll, sizeof(ll)) == sizeof(ll) &&
+                           ll.ll_time != 0) {
+                               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);
+                       }
+                       (void)lseek(fd, (off_t)pwd->pw_uid * sizeof(ll), L_SET);
+               }
+               (void)time(&ll.ll_time);
+               (void) strncpy(ll.ll_line, tty, sizeof(ll.ll_line));
+               if (hostname)
+                   (void) strncpy(ll.ll_host, hostname, sizeof(ll.ll_host));
                else
-                 printf("on %.*s\n",
-                        sizeof(ll.ll_line), ll.ll_line);
-           }
-           (void)lseek(fd, (off_t)pwd->pw_uid * sizeof(ll), L_SET);
+                   (void) bzero(ll.ll_host, sizeof(ll.ll_host));
+               (void)write(fd, (char *)&ll, sizeof(ll));
+               (void)close(fd);
        }
-       (void)time(&ll.ll_time);
-       (void) strncpy(ll.ll_line, tty, sizeof(ll.ll_line));
-       if (hostname)
-         (void) strncpy(ll.ll_host, hostname, sizeof(ll.ll_host));
-       else
-         (void) bzero(ll.ll_host, sizeof(ll.ll_host));
-       (void)write(fd, (char *)&ll, sizeof(ll));
-       (void)close(fd);
-    }
 }
 
-
-
 #undef UNKNOWN
 #define        UNKNOWN "su"
 
-char *stypeof(ttyid)
-     char *ttyid;
+char *
+stypeof(ttyid)
+       char *ttyid;
 {
 #ifdef NOTTYENT
-    return(UNKNOWN);
+       return(UNKNOWN);
 #else
-    struct ttyent *t;
-    
-    return(ttyid && (t = getttynam(ttyid)) ? t->ty_type : UNKNOWN);
+       struct ttyent *t;
+
+       return(ttyid && (t = getttynam(ttyid)) ? t->ty_type : UNKNOWN);
 #endif
 }
 
-
-
-getstr(buf, cnt, err)
-     char *buf, *err;
-     int cnt;
+doremotelogin(host)
+       char *host;
 {
-    char ch;
-    
-    do {
-       if (read(0, &ch, sizeof(ch)) != sizeof(ch))
-         exit(1);
-       if (--cnt < 0) {
-           fprintf(stderr, "%s too long\r\n", err);
-           sleepexit(1);
-       }
-       *buf++ = ch;
-    } while (ch);
+       static char lusername[UT_NAMESIZE+1];
+       char rusername[UT_NAMESIZE+1];
+
+       getstr(rusername, sizeof(rusername), "remuser");
+       getstr(lusername, sizeof(lusername), "locuser");
+       getstr(term, sizeof(term), "Terminal type");
+       username = lusername;
+       pwd = getpwnam(username);
+       if (pwd == NULL)
+               return(-1);
+       return(ruserok(host, (pwd->pw_uid == 0), rusername, username));
 }
 
-
-
-doremotelogin()
+getstr(buf, cnt, err)
+       char *buf, *err;
+       int cnt;
 {
-    static char lusername[UT_NAMESIZE+1];
-    char rusername[UT_NAMESIZE+1];
-    
-    getstr(rusername, sizeof(rusername), "remuser");
-    getstr(lusername, sizeof(lusername), "locuser");
-    if (username == NULL)
-      username = lusername;
-    getstr(term, sizeof(term), "Terminal type");
+       char ch;
+
+       do {
+               if (read(0, &ch, sizeof(ch)) != sizeof(ch))
+                       exit(1);
+               if (--cnt < 0) {
+                       fprintf(stderr, "%s too long\r\n", err);
+                       sleepexit(1);
+               }
+               *buf++ = ch;
+       } while (ch);
 }
 
-
-
 char *speeds[] = {
-    "0", "50", "75", "110", "134", "150", "200", "300", "600",
-    "1200", "1800", "2400", "4800", "9600", "19200", "38400",
+       "0", "50", "75", "110", "134", "150", "200", "300", "600",
+       "1200", "1800", "2400", "4800", "9600", "19200", "38400",
 };
 #define        NSPEEDS (sizeof(speeds) / sizeof(speeds[0]))
 
 doremoteterm(tp)
-     struct sgttyb *tp;
+       struct sgttyb *tp;
 {
-    register char *cp = index(term, '/'), **cpp;
-    char *speed;
-    
-    if (cp) {
-       *cp++ = '\0';
-       speed = cp;
-       cp = index(speed, '/');
-       if (cp)
-         *cp++ = '\0';
-       for (cpp = speeds; cpp < &speeds[NSPEEDS]; cpp++)
-         if (strcmp(*cpp, speed) == 0) {
-             tp->sg_ispeed = tp->sg_ospeed = cpp-speeds;
-             break;
-         }
-    }
-    tp->sg_flags = ECHO|CRMOD|ANYP|XTABS;
+       register char *cp = index(term, '/'), **cpp;
+       char *speed;
+
+       if (cp) {
+               *cp++ = '\0';
+               speed = cp;
+               cp = index(speed, '/');
+               if (cp)
+                       *cp++ = '\0';
+               for (cpp = speeds; cpp < &speeds[NSPEEDS]; cpp++)
+                       if (strcmp(*cpp, speed) == 0) {
+                               tp->sg_ispeed = tp->sg_ospeed = cpp-speeds;
+                               break;
+                       }
+       }
+       tp->sg_flags = ECHO|CRMOD|ANYP|XTABS;
 }
 
-
-
 sleepexit(eval)
-     int eval;
-{
-    sleep((u_int)5);
-    exit(eval);
-}
-
-
-
-void setenv(var, value)
-     char *var, *value;
+       int eval;
 {
-    char *env_str;
-    int retval, str_size = strlen(var) + strlen(value) + strlen("=") + 1;
-    
-    env_str = (char *) malloc(str_size);
-    
-    strcpy(env_str, var);
-    strcat(env_str, "=");
-    strcat(env_str, value);
-    env_str[str_size-1] = '\0';
-    
-    if (retval = putenv(env_str)) {
-       syslog(LOG_ERR, "Not enough memory\n");
-       exit(1);
-    }
+       sleep((u_int)5);
+       exit(eval);
 }