143653Sbostic /*- 236515Sbostic * Copyright (c) 1980, 1987, 1988 The Regents of the University of California. 336515Sbostic * All rights reserved. 436515Sbostic * 543653Sbostic * %sccs.include.redist.c% 619843Sdist */ 719843Sdist 812678Ssam #ifndef lint 919843Sdist char copyright[] = 1036515Sbostic "@(#) Copyright (c) 1980, 1987, 1988 The Regents of the University of California.\n\ 1119843Sdist All rights reserved.\n"; 1236515Sbostic #endif /* not lint */ 1312678Ssam 1419843Sdist #ifndef lint 15*43663Sbostic static char sccsid[] = "@(#)login.c 5.59 (Berkeley) 06/24/90"; 1636515Sbostic #endif /* not lint */ 1719843Sdist 181043Sbill /* 191043Sbill * login [ name ] 2031695Skarels * login -h hostname (for telnetd, etc.) 2131695Skarels * login -f name (for pre-authenticated login: datakit, xterm, etc.) 221043Sbill */ 231043Sbill 2412984Ssam #include <sys/param.h> 2512687Ssam #include <sys/stat.h> 2612687Ssam #include <sys/time.h> 2712687Ssam #include <sys/resource.h> 2816453Sroot #include <sys/file.h> 2939271Skfall #include <sgtty.h> 3012687Ssam 311043Sbill #include <utmp.h> 321043Sbill #include <signal.h> 3312678Ssam #include <errno.h> 3416453Sroot #include <ttyent.h> 3516453Sroot #include <syslog.h> 3626862Smckusick #include <grp.h> 3736460Sbostic #include <pwd.h> 3836515Sbostic #include <setjmp.h> 3936460Sbostic #include <stdio.h> 4042063Sbostic #include <string.h> 4137203Sbostic #include <tzfile.h> 4237203Sbostic #include "pathnames.h" 431043Sbill 4436460Sbostic #define TTYGRPNAME "tty" /* name of group to own ttys */ 4526862Smckusick 4612687Ssam /* 4736460Sbostic * This bounds the time given to login. Not a define so it can 4836460Sbostic * be patched on machines where it's too small. 4912687Ssam */ 5031509Sbostic int timeout = 300; 5143653Sbostic #ifdef KERBEROS 5243653Sbostic int notickets = 1; 5343653Sbostic #endif 546005Swnj 5536647Skarels struct passwd *pwd; 5636647Skarels int failures; 5740490Sbostic char term[64], *envinit[1], *hostname, *username, *tty; 586005Swnj 5936647Skarels struct sgttyb sgttyb; 6036647Skarels struct tchars tc = { 6113074Ssam CINTR, CQUIT, CSTART, CSTOP, CEOT, CBRK 621365Sbill }; 6336647Skarels struct ltchars ltc = { 6443653Sbostic CSUSP, CDSUSP, CRPRNT, CDISCARD, CWERASE, CLNEXT 6513074Ssam }; 661365Sbill 671043Sbill main(argc, argv) 6836460Sbostic int argc; 6936460Sbostic char **argv; 701043Sbill { 7143653Sbostic extern int optind; 7236460Sbostic extern char *optarg, **environ; 7336880Sbostic struct timeval tp; 7436460Sbostic struct group *gr; 7536460Sbostic register int ch; 7636647Skarels register char *p; 7739271Skfall int ask, fflag, hflag, pflag, cnt, uid; 7843653Sbostic int quietlog, passwd_req, ioctlval, rval; 7943653Sbostic char *domain, *salt, *ttyn; 8037692Sbostic char tbuf[MAXPATHLEN + 2], tname[sizeof(_PATH_TTY) + 10]; 8138034Skfall char localhost[MAXHOSTNAMELEN]; 8236880Sbostic char *ctime(), *ttyname(), *stypeof(), *crypt(), *getpass(); 8336460Sbostic time_t time(); 8436460Sbostic off_t lseek(); 8543653Sbostic void timedout(); 861043Sbill 8736460Sbostic (void)signal(SIGALRM, timedout); 8836460Sbostic (void)alarm((u_int)timeout); 8936460Sbostic (void)signal(SIGQUIT, SIG_IGN); 9036460Sbostic (void)signal(SIGINT, SIG_IGN); 9136460Sbostic (void)setpriority(PRIO_PROCESS, 0, 0); 9236460Sbostic 9342502Sbostic openlog("login", LOG_ODELAY, LOG_AUTH); 9442502Sbostic 9512687Ssam /* 9618549Ssam * -p is used by getty to tell login not to destroy the environment 9731695Skarels * -f is used to skip a second login authentication 9836523Skarels * -h is used by other servers to pass the name of the remote 9936523Skarels * host to login so that it may be placed in utmp and wtmp 10012687Ssam */ 10138034Skfall domain = NULL; 10238034Skfall if (gethostname(localhost, sizeof(localhost)) < 0) 10338034Skfall syslog(LOG_ERR, "couldn't get local hostname: %m"); 10438034Skfall else 10538034Skfall domain = index(localhost, '.'); 10636460Sbostic 10737203Sbostic fflag = hflag = pflag = 0; 10836460Sbostic passwd_req = 1; 10939271Skfall uid = getuid(); 11037203Sbostic while ((ch = getopt(argc, argv, "fh:p")) != EOF) 11136515Sbostic switch (ch) { 11236460Sbostic case 'f': 11336460Sbostic fflag = 1; 11436460Sbostic break; 11536460Sbostic case 'h': 11639271Skfall if (uid) { 11737203Sbostic (void)fprintf(stderr, 11836460Sbostic "login: -h for super-user only.\n"); 11932313Sbostic exit(1); 12031695Skarels } 12136460Sbostic hflag = 1; 12236460Sbostic if (domain && (p = index(optarg, '.')) && 12336553Sbostic strcasecmp(p, domain) == 0) 12436460Sbostic *p = 0; 12536460Sbostic hostname = optarg; 12636460Sbostic break; 12736460Sbostic case 'p': 12818549Ssam pflag = 1; 12936460Sbostic break; 13036460Sbostic case '?': 13136460Sbostic default: 13239271Skfall if (!uid) 13339271Skfall syslog(LOG_ERR, "invalid flag %c", ch); 13437203Sbostic (void)fprintf(stderr, 13537203Sbostic "usage: login [-fp] [username]\n"); 13636460Sbostic exit(1); 13718549Ssam } 13836460Sbostic argc -= optind; 13936460Sbostic argv += optind; 14036549Sbostic if (*argv) { 14136647Skarels username = *argv; 14243653Sbostic if (strlen(username) > UT_NAMESIZE) 14343653Sbostic username[UT_NAMESIZE] = '\0'; 14436549Sbostic ask = 0; 14536647Skarels } else 14636549Sbostic ask = 1; 14736460Sbostic 14836460Sbostic ioctlval = 0; 14936460Sbostic (void)ioctl(0, TIOCLSET, &ioctlval); 15036460Sbostic (void)ioctl(0, TIOCNXCL, 0); 15136515Sbostic (void)fcntl(0, F_SETFL, ioctlval); 15236515Sbostic (void)ioctl(0, TIOCGETP, &sgttyb); 15336515Sbostic sgttyb.sg_erase = CERASE; 15436515Sbostic sgttyb.sg_kill = CKILL; 15536460Sbostic (void)ioctl(0, TIOCSLTC, <c); 15636460Sbostic (void)ioctl(0, TIOCSETC, &tc); 15736515Sbostic (void)ioctl(0, TIOCSETP, &sgttyb); 15836460Sbostic 15936460Sbostic for (cnt = getdtablesize(); cnt > 2; cnt--) 16036460Sbostic close(cnt); 16136460Sbostic 1621043Sbill ttyn = ttyname(0); 16337692Sbostic if (ttyn == NULL || *ttyn == '\0') { 16437692Sbostic (void)sprintf(tname, "%s??", _PATH_TTY); 16537692Sbostic ttyn = tname; 16637692Sbostic } 16736460Sbostic if (tty = rindex(ttyn, '/')) 16836460Sbostic ++tty; 16936460Sbostic else 17016453Sroot tty = ttyn; 17136460Sbostic 17236549Sbostic for (cnt = 0;; ask = 1) { 17338602Sbostic ioctlval = TTYDISC; 17436460Sbostic (void)ioctl(0, TIOCSETD, &ioctlval); 17536460Sbostic 17636549Sbostic if (ask) { 17736515Sbostic fflag = 0; 17836460Sbostic getloginname(); 17936515Sbostic } 18036647Skarels /* 18139271Skfall * Note if trying multiple user names; log failures for 18239271Skfall * previous user name, but don't bother logging one failure 18336647Skarels * for nonexistent name (mistyped username). 18436647Skarels */ 18536647Skarels if (failures && strcmp(tbuf, username)) { 18636647Skarels if (failures > (pwd ? 0 : 1)) 18736549Sbostic badlogin(tbuf); 18836647Skarels failures = 0; 18936549Sbostic } 19036647Skarels (void)strcpy(tbuf, username); 19143659Sbostic 19236515Sbostic if (pwd = getpwnam(username)) 19336515Sbostic salt = pwd->pw_passwd; 19443659Sbostic else 19543659Sbostic salt = "xx"; 19636460Sbostic 19712687Ssam /* 19836515Sbostic * Disallow automatic login to root; if not invoked by 19936515Sbostic * root, disallow if the uid's differ. 20012687Ssam */ 20143659Sbostic if (pwd && fflag) { 20238726Skfall passwd_req = 20338726Skfall #ifndef KERBEROS 20438726Skfall pwd->pw_uid == 0 || 20538726Skfall #endif 20636515Sbostic (uid && uid != pwd->pw_uid); 20731695Skarels } 20836460Sbostic 20912687Ssam /* 21036523Skarels * If no pre-authentication and a password exists 21136460Sbostic * for this user, prompt for one and verify it. 21212687Ssam */ 21343659Sbostic if (pwd && (!passwd_req || !*pwd->pw_passwd)) 21436460Sbostic break; 21512687Ssam 21639271Skfall /* 21739271Skfall * If trying to log in as root, but with insecure terminal, 21839271Skfall * refuse the login attempt. 21939271Skfall */ 22043659Sbostic if (pwd && pwd->pw_uid == 0 && !rootterm(tty)) { 22139271Skfall (void)fprintf(stderr, 22239271Skfall "%s login refused on this terminal.\n", 22339271Skfall pwd->pw_name); 22439271Skfall if (hostname) 22539271Skfall syslog(LOG_NOTICE, 22639271Skfall "LOGIN %s REFUSED FROM %s ON TTY %s", 22739271Skfall pwd->pw_name, hostname, tty); 22839271Skfall else 22939271Skfall syslog(LOG_NOTICE, 23039271Skfall "LOGIN %s REFUSED ON TTY %s", 23139271Skfall pwd->pw_name, tty); 23239271Skfall continue; 23339271Skfall } 23439271Skfall 23543653Sbostic (void)setpriority(PRIO_PROCESS, 0, -4); 23643659Sbostic 23743653Sbostic p = getpass("Password:"); 23836608Skfall 23943659Sbostic if (pwd) { 24043653Sbostic #ifdef KERBEROS 24143659Sbostic rval = klogin(pwd, localhost, p); 24243659Sbostic if (rval == 1) 24343659Sbostic rval = strcmp(crypt(p, salt), pwd->pw_passwd); 24443659Sbostic #else 24543653Sbostic rval = strcmp(crypt(p, salt), pwd->pw_passwd); 24637203Sbostic #endif 24743659Sbostic } 24843653Sbostic bzero(p, strlen(p)); 24943659Sbostic 25043659Sbostic (void)setpriority(PRIO_PROCESS, 0, 0); 25143659Sbostic 25243659Sbostic if (pwd && !rval) 25336460Sbostic break; 25436460Sbostic 25543659Sbostic (void)printf("Login incorrect\n"); 25636647Skarels failures++; 25736549Sbostic /* we allow 10 tries, but after 3 we start backing off */ 25836549Sbostic if (++cnt > 3) { 25936549Sbostic if (cnt >= 10) { 26036549Sbostic badlogin(username); 26136549Sbostic (void)ioctl(0, TIOCHPCL, (struct sgttyb *)NULL); 26236549Sbostic sleepexit(1); 26336549Sbostic } 26436549Sbostic sleep((u_int)((cnt - 3) * 5)); 2652822Swnj } 26636460Sbostic } 2671043Sbill 26836460Sbostic /* committed to login -- turn off timeout */ 26936460Sbostic (void)alarm((u_int)0); 27036460Sbostic 27137692Sbostic /* paranoia... */ 27237692Sbostic endpwent(); 27337692Sbostic 274*43663Sbostic /* if user not super-user, check for disabled logins */ 275*43663Sbostic if (pwd->pw_uid) 276*43663Sbostic checknologin(); 277*43663Sbostic 27836515Sbostic if (chdir(pwd->pw_dir) < 0) { 27937203Sbostic (void)printf("No directory %s!\n", pwd->pw_dir); 28036515Sbostic if (chdir("/")) 28136515Sbostic exit(0); 28236515Sbostic pwd->pw_dir = "/"; 28337203Sbostic (void)printf("Logging in with home = \"/\".\n"); 28436515Sbostic } 28536515Sbostic 28637203Sbostic quietlog = access(_PATH_HUSHLOGIN, F_OK) == 0; 28737203Sbostic 28836880Sbostic if (pwd->pw_change || pwd->pw_expire) 28936880Sbostic (void)gettimeofday(&tp, (struct timezone *)NULL); 29036880Sbostic if (pwd->pw_change) 29136880Sbostic if (tp.tv_sec >= pwd->pw_change) { 29237203Sbostic (void)printf("Sorry -- your password has expired.\n"); 29336880Sbostic sleepexit(1); 29436880Sbostic } 29538216Sbostic else if (pwd->pw_change - tp.tv_sec < 29643660Sbostic 2 * DAYSPERWEEK * SECSPERDAY && !quietlog) 29743660Sbostic (void)printf("Warning: your password expires on %s", 29843660Sbostic ctime(&pwd->pw_expire)); 29936880Sbostic if (pwd->pw_expire) 30036880Sbostic if (tp.tv_sec >= pwd->pw_expire) { 30137203Sbostic (void)printf("Sorry -- your account has expired.\n"); 30236880Sbostic sleepexit(1); 30336880Sbostic } 30438216Sbostic else if (pwd->pw_expire - tp.tv_sec < 30543660Sbostic 2 * DAYSPERWEEK * SECSPERDAY && !quietlog) 30643660Sbostic (void)printf("Warning: your account expires on %s", 30743660Sbostic ctime(&pwd->pw_expire)); 30836880Sbostic 30936515Sbostic /* nothing else left to fail -- really log in */ 31036460Sbostic { 31136460Sbostic struct utmp utmp; 31236460Sbostic 31343653Sbostic bzero((void *)&utmp, sizeof(utmp)); 31436460Sbostic (void)time(&utmp.ut_time); 31536460Sbostic strncpy(utmp.ut_name, username, sizeof(utmp.ut_name)); 31636591Sbostic if (hostname) 31736591Sbostic strncpy(utmp.ut_host, hostname, sizeof(utmp.ut_host)); 31836460Sbostic strncpy(utmp.ut_line, tty, sizeof(utmp.ut_line)); 31936460Sbostic login(&utmp); 32036460Sbostic } 32136460Sbostic 32236549Sbostic dolastlog(quietlog); 32336460Sbostic 32437203Sbostic if (!hflag) { /* XXX */ 32536460Sbostic static struct winsize win = { 0, 0, 0, 0 }; 32636460Sbostic 32736460Sbostic (void)ioctl(0, TIOCSWINSZ, &win); 32836460Sbostic } 32936460Sbostic 33036460Sbostic (void)chown(ttyn, pwd->pw_uid, 33136460Sbostic (gr = getgrnam(TTYGRPNAME)) ? gr->gr_gid : pwd->pw_gid); 33236460Sbostic (void)chmod(ttyn, 0620); 33336460Sbostic (void)setgid(pwd->pw_gid); 33436460Sbostic 33536460Sbostic initgroups(username, pwd->pw_gid); 33636460Sbostic 33736515Sbostic if (*pwd->pw_shell == '\0') 33837203Sbostic pwd->pw_shell = _PATH_BSHELL; 33936515Sbostic 34036460Sbostic /* destroy environment unless user has requested preservation */ 34118549Ssam if (!pflag) 34218549Ssam environ = envinit; 34336515Sbostic (void)setenv("HOME", pwd->pw_dir, 1); 34436515Sbostic (void)setenv("SHELL", pwd->pw_shell, 1); 34518549Ssam if (term[0] == '\0') 34636647Skarels strncpy(term, stypeof(tty), sizeof(term)); 34736515Sbostic (void)setenv("TERM", term, 0); 34836515Sbostic (void)setenv("USER", pwd->pw_name, 1); 34937252Sbostic (void)setenv("PATH", _PATH_DEFPATH, 0); 35018549Ssam 35116453Sroot if (tty[sizeof("tty")-1] == 'd') 35218549Ssam syslog(LOG_INFO, "DIALUP %s, %s", tty, pwd->pw_name); 35318549Ssam if (pwd->pw_uid == 0) 35436460Sbostic if (hostname) 35536647Skarels syslog(LOG_NOTICE, "ROOT LOGIN ON %s FROM %s", 35636549Sbostic tty, hostname); 35725230Smckusick else 35836647Skarels syslog(LOG_NOTICE, "ROOT LOGIN ON %s", tty); 35936460Sbostic 36043653Sbostic #ifdef KERBEROS 36143653Sbostic if (!quietlog && notickets == 1) 36243653Sbostic (void)printf("Warning: no Kerberos tickets issued.\n"); 36343653Sbostic #endif 36443653Sbostic 3656329Swnj if (!quietlog) { 36617664Sserge struct stat st; 36718549Ssam 36836460Sbostic motd(); 36937203Sbostic (void)sprintf(tbuf, "%s/%s", _PATH_MAILDIR, pwd->pw_name); 37036460Sbostic if (stat(tbuf, &st) == 0 && st.st_size != 0) 37137203Sbostic (void)printf("You have %smail.\n", 37236460Sbostic (st.st_mtime > st.st_atime) ? "new " : ""); 3732822Swnj } 37436460Sbostic 37536460Sbostic (void)signal(SIGALRM, SIG_DFL); 37636460Sbostic (void)signal(SIGQUIT, SIG_DFL); 37736460Sbostic (void)signal(SIGINT, SIG_DFL); 37836460Sbostic (void)signal(SIGTSTP, SIG_IGN); 37936460Sbostic 38036460Sbostic tbuf[0] = '-'; 38136460Sbostic strcpy(tbuf + 1, (p = rindex(pwd->pw_shell, '/')) ? 38236460Sbostic p + 1 : pwd->pw_shell); 38337203Sbostic 38440009Ssklower if (setlogin(pwd->pw_name) < 0) 38540009Ssklower syslog(LOG_ERR, "setlogin() failure: %m"); 38637692Sbostic 38737203Sbostic /* discard permissions last so can't get killed and drop core */ 38837203Sbostic (void)setuid(pwd->pw_uid); 38937203Sbostic 39036460Sbostic execlp(pwd->pw_shell, tbuf, 0); 39137203Sbostic (void)fprintf(stderr, "login: no shell: %s.\n", strerror(errno)); 3921043Sbill exit(0); 3931043Sbill } 3941043Sbill 39536460Sbostic getloginname() 39612687Ssam { 39736460Sbostic register int ch; 39836460Sbostic register char *p; 39936460Sbostic static char nbuf[UT_NAMESIZE + 1]; 40012687Ssam 40136460Sbostic for (;;) { 40237203Sbostic (void)printf("login: "); 40336515Sbostic for (p = nbuf; (ch = getchar()) != '\n'; ) { 40436549Sbostic if (ch == EOF) { 40536549Sbostic badlogin(username); 40612687Ssam exit(0); 40736549Sbostic } 40836515Sbostic if (p < nbuf + UT_NAMESIZE) 40936460Sbostic *p++ = ch; 41012687Ssam } 41136460Sbostic if (p > nbuf) 41236460Sbostic if (nbuf[0] == '-') 41337203Sbostic (void)fprintf(stderr, 41436460Sbostic "login names may not start with '-'.\n"); 41536460Sbostic else { 41636460Sbostic *p = '\0'; 41736460Sbostic username = nbuf; 41836515Sbostic break; 41936460Sbostic } 42012687Ssam } 42112687Ssam } 42212687Ssam 42343653Sbostic void 42412687Ssam timedout() 42512687Ssam { 42637203Sbostic (void)fprintf(stderr, "Login timed out after %d seconds\n", timeout); 42712687Ssam exit(0); 42812687Ssam } 42912687Ssam 43036647Skarels rootterm(ttyn) 43136647Skarels char *ttyn; 4321043Sbill { 43336460Sbostic struct ttyent *t; 4346466Swnj 43536647Skarels return((t = getttynam(ttyn)) && t->ty_status&TTY_SECURE); 4361043Sbill } 4371043Sbill 43836515Sbostic jmp_buf motdinterrupt; 43936515Sbostic 44036460Sbostic motd() 4412822Swnj { 44236515Sbostic register int fd, nchars; 44338726Skfall sig_t oldint; 44438726Skfall int sigint(); 44536515Sbostic char tbuf[8192]; 4462822Swnj 44737203Sbostic if ((fd = open(_PATH_MOTDFILE, O_RDONLY, 0)) < 0) 44836460Sbostic return; 44936460Sbostic oldint = signal(SIGINT, sigint); 45036515Sbostic if (setjmp(motdinterrupt) == 0) 45136515Sbostic while ((nchars = read(fd, tbuf, sizeof(tbuf))) > 0) 45236515Sbostic (void)write(fileno(stdout), tbuf, nchars); 45336460Sbostic (void)signal(SIGINT, oldint); 45436515Sbostic (void)close(fd); 45536460Sbostic } 45636460Sbostic 45736460Sbostic sigint() 45836460Sbostic { 45936515Sbostic longjmp(motdinterrupt, 1); 46036460Sbostic } 46136460Sbostic 46236460Sbostic checknologin() 46336460Sbostic { 46436460Sbostic register int fd, nchars; 46536515Sbostic char tbuf[8192]; 46636460Sbostic 46737203Sbostic if ((fd = open(_PATH_NOLOGIN, O_RDONLY, 0)) >= 0) { 46836460Sbostic while ((nchars = read(fd, tbuf, sizeof(tbuf))) > 0) 46936460Sbostic (void)write(fileno(stdout), tbuf, nchars); 47036460Sbostic sleepexit(0); 4712822Swnj } 4722822Swnj } 4732822Swnj 47436549Sbostic dolastlog(quiet) 47536460Sbostic int quiet; 4761043Sbill { 47736460Sbostic struct lastlog ll; 47836460Sbostic int fd; 47936880Sbostic char *ctime(); 4801043Sbill 48137203Sbostic if ((fd = open(_PATH_LASTLOG, O_RDWR, 0)) >= 0) { 48236515Sbostic (void)lseek(fd, (off_t)pwd->pw_uid * sizeof(ll), L_SET); 48336460Sbostic if (!quiet) { 48436460Sbostic if (read(fd, (char *)&ll, sizeof(ll)) == sizeof(ll) && 48536460Sbostic ll.ll_time != 0) { 48637203Sbostic (void)printf("Last login: %.*s ", 48736460Sbostic 24-5, (char *)ctime(&ll.ll_time)); 48836460Sbostic if (*ll.ll_host != '\0') 48937203Sbostic (void)printf("from %.*s\n", 49036460Sbostic sizeof(ll.ll_host), ll.ll_host); 49136460Sbostic else 49237203Sbostic (void)printf("on %.*s\n", 49336460Sbostic sizeof(ll.ll_line), ll.ll_line); 49436460Sbostic } 49536515Sbostic (void)lseek(fd, (off_t)pwd->pw_uid * sizeof(ll), L_SET); 49636460Sbostic } 49743653Sbostic bzero((void *)&ll, sizeof(ll)); 49836460Sbostic (void)time(&ll.ll_time); 49936460Sbostic strncpy(ll.ll_line, tty, sizeof(ll.ll_line)); 50036591Sbostic if (hostname) 50136591Sbostic strncpy(ll.ll_host, hostname, sizeof(ll.ll_host)); 50236460Sbostic (void)write(fd, (char *)&ll, sizeof(ll)); 50336460Sbostic (void)close(fd); 5041043Sbill } 5051043Sbill } 5061043Sbill 50736549Sbostic badlogin(name) 50836549Sbostic char *name; 50936549Sbostic { 51036647Skarels if (failures == 0) 51136549Sbostic return; 51236549Sbostic if (hostname) 51336647Skarels syslog(LOG_NOTICE, "%d LOGIN FAILURE%s FROM %s, %s", 51436647Skarels failures, failures > 1 ? "S" : "", hostname, name); 51536549Sbostic else 51636647Skarels syslog(LOG_NOTICE, "%d LOGIN FAILURE%s ON %s, %s", 51736647Skarels failures, failures > 1 ? "S" : "", tty, name); 51836549Sbostic } 51936549Sbostic 5202822Swnj #undef UNKNOWN 52136460Sbostic #define UNKNOWN "su" 5221043Sbill 5231043Sbill char * 52436647Skarels stypeof(ttyid) 52536647Skarels char *ttyid; 5261043Sbill { 52736460Sbostic struct ttyent *t; 5281043Sbill 52936647Skarels return(ttyid && (t = getttynam(ttyid)) ? t->ty_type : UNKNOWN); 5301043Sbill } 5316005Swnj 53236460Sbostic sleepexit(eval) 53336460Sbostic int eval; 53426862Smckusick { 53536460Sbostic sleep((u_int)5); 53636460Sbostic exit(eval); 53726862Smckusick } 538