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*44348Skarels static char sccsid[] = "@(#)login.c 5.61 (Berkeley) 06/27/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; 7843674Sbostic int quietlog, 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; 10839271Skfall uid = getuid(); 10937203Sbostic while ((ch = getopt(argc, argv, "fh:p")) != EOF) 11036515Sbostic switch (ch) { 11136460Sbostic case 'f': 11236460Sbostic fflag = 1; 11336460Sbostic break; 11436460Sbostic case 'h': 11539271Skfall if (uid) { 11637203Sbostic (void)fprintf(stderr, 11736460Sbostic "login: -h for super-user only.\n"); 11832313Sbostic exit(1); 11931695Skarels } 12036460Sbostic hflag = 1; 12136460Sbostic if (domain && (p = index(optarg, '.')) && 12236553Sbostic strcasecmp(p, domain) == 0) 12336460Sbostic *p = 0; 12436460Sbostic hostname = optarg; 12536460Sbostic break; 12636460Sbostic case 'p': 12718549Ssam pflag = 1; 12836460Sbostic break; 12936460Sbostic case '?': 13036460Sbostic default: 13139271Skfall if (!uid) 13239271Skfall syslog(LOG_ERR, "invalid flag %c", ch); 13337203Sbostic (void)fprintf(stderr, 13437203Sbostic "usage: login [-fp] [username]\n"); 13536460Sbostic exit(1); 13618549Ssam } 13736460Sbostic argc -= optind; 13836460Sbostic argv += optind; 13936549Sbostic if (*argv) { 14036647Skarels username = *argv; 14143653Sbostic if (strlen(username) > UT_NAMESIZE) 14243653Sbostic username[UT_NAMESIZE] = '\0'; 14336549Sbostic ask = 0; 14436647Skarels } else 14536549Sbostic ask = 1; 14636460Sbostic 14736460Sbostic ioctlval = 0; 14836460Sbostic (void)ioctl(0, TIOCLSET, &ioctlval); 14936460Sbostic (void)ioctl(0, TIOCNXCL, 0); 15036515Sbostic (void)fcntl(0, F_SETFL, ioctlval); 15136515Sbostic (void)ioctl(0, TIOCGETP, &sgttyb); 15236515Sbostic sgttyb.sg_erase = CERASE; 15336515Sbostic sgttyb.sg_kill = CKILL; 15436460Sbostic (void)ioctl(0, TIOCSLTC, <c); 15536460Sbostic (void)ioctl(0, TIOCSETC, &tc); 15636515Sbostic (void)ioctl(0, TIOCSETP, &sgttyb); 15736460Sbostic 15836460Sbostic for (cnt = getdtablesize(); cnt > 2; cnt--) 15936460Sbostic close(cnt); 16036460Sbostic 1611043Sbill ttyn = ttyname(0); 16237692Sbostic if (ttyn == NULL || *ttyn == '\0') { 16337692Sbostic (void)sprintf(tname, "%s??", _PATH_TTY); 16437692Sbostic ttyn = tname; 16537692Sbostic } 16636460Sbostic if (tty = rindex(ttyn, '/')) 16736460Sbostic ++tty; 16836460Sbostic else 16916453Sroot tty = ttyn; 17036460Sbostic 17136549Sbostic for (cnt = 0;; ask = 1) { 17238602Sbostic ioctlval = TTYDISC; 17336460Sbostic (void)ioctl(0, TIOCSETD, &ioctlval); 17436460Sbostic 17536549Sbostic if (ask) { 17636515Sbostic fflag = 0; 17736460Sbostic getloginname(); 17836515Sbostic } 17936647Skarels /* 18039271Skfall * Note if trying multiple user names; log failures for 18139271Skfall * previous user name, but don't bother logging one failure 18236647Skarels * for nonexistent name (mistyped username). 18336647Skarels */ 18436647Skarels if (failures && strcmp(tbuf, username)) { 18536647Skarels if (failures > (pwd ? 0 : 1)) 18636549Sbostic badlogin(tbuf); 18736647Skarels failures = 0; 18836549Sbostic } 18936647Skarels (void)strcpy(tbuf, username); 19043659Sbostic 19136515Sbostic if (pwd = getpwnam(username)) 19236515Sbostic salt = pwd->pw_passwd; 19343659Sbostic else 19443659Sbostic salt = "xx"; 19536460Sbostic 19612687Ssam /* 19743674Sbostic * if we have a valid account name, and it doesn't have a 19843674Sbostic * password, or the -f option was specified and the caller 19943674Sbostic * is root or the caller isn't changing their uid, don't 20043674Sbostic * authenticate. 20112687Ssam */ 20243674Sbostic if (pwd && (*pwd->pw_passwd == '\0' || 20343674Sbostic fflag && (uid == 0 || uid == pwd->pw_uid))) 20436460Sbostic break; 205*44348Skarels fflag = 0; 20612687Ssam 20739271Skfall /* 20839271Skfall * If trying to log in as root, but with insecure terminal, 20939271Skfall * refuse the login attempt. 21039271Skfall */ 21143659Sbostic if (pwd && pwd->pw_uid == 0 && !rootterm(tty)) { 21239271Skfall (void)fprintf(stderr, 21339271Skfall "%s login refused on this terminal.\n", 21439271Skfall pwd->pw_name); 21539271Skfall if (hostname) 21639271Skfall syslog(LOG_NOTICE, 21739271Skfall "LOGIN %s REFUSED FROM %s ON TTY %s", 21839271Skfall pwd->pw_name, hostname, tty); 21939271Skfall else 22039271Skfall syslog(LOG_NOTICE, 22139271Skfall "LOGIN %s REFUSED ON TTY %s", 22239271Skfall pwd->pw_name, tty); 22339271Skfall continue; 22439271Skfall } 22539271Skfall 22643653Sbostic (void)setpriority(PRIO_PROCESS, 0, -4); 22743659Sbostic 22843653Sbostic p = getpass("Password:"); 22936608Skfall 23043659Sbostic if (pwd) { 23143653Sbostic #ifdef KERBEROS 23243659Sbostic rval = klogin(pwd, localhost, p); 23343659Sbostic if (rval == 1) 23443659Sbostic rval = strcmp(crypt(p, salt), pwd->pw_passwd); 23543659Sbostic #else 23643653Sbostic rval = strcmp(crypt(p, salt), pwd->pw_passwd); 23737203Sbostic #endif 23843659Sbostic } 23943653Sbostic bzero(p, strlen(p)); 24043659Sbostic 24143659Sbostic (void)setpriority(PRIO_PROCESS, 0, 0); 24243659Sbostic 24343659Sbostic if (pwd && !rval) 24436460Sbostic break; 24536460Sbostic 24643659Sbostic (void)printf("Login incorrect\n"); 24736647Skarels failures++; 24836549Sbostic /* we allow 10 tries, but after 3 we start backing off */ 24936549Sbostic if (++cnt > 3) { 25036549Sbostic if (cnt >= 10) { 25136549Sbostic badlogin(username); 25236549Sbostic (void)ioctl(0, TIOCHPCL, (struct sgttyb *)NULL); 25336549Sbostic sleepexit(1); 25436549Sbostic } 25536549Sbostic sleep((u_int)((cnt - 3) * 5)); 2562822Swnj } 25736460Sbostic } 2581043Sbill 25936460Sbostic /* committed to login -- turn off timeout */ 26036460Sbostic (void)alarm((u_int)0); 26136460Sbostic 26237692Sbostic /* paranoia... */ 26337692Sbostic endpwent(); 26437692Sbostic 26543663Sbostic /* if user not super-user, check for disabled logins */ 26643663Sbostic if (pwd->pw_uid) 26743663Sbostic checknologin(); 26843663Sbostic 26936515Sbostic if (chdir(pwd->pw_dir) < 0) { 27037203Sbostic (void)printf("No directory %s!\n", pwd->pw_dir); 27136515Sbostic if (chdir("/")) 27236515Sbostic exit(0); 27336515Sbostic pwd->pw_dir = "/"; 27437203Sbostic (void)printf("Logging in with home = \"/\".\n"); 27536515Sbostic } 27636515Sbostic 27737203Sbostic quietlog = access(_PATH_HUSHLOGIN, F_OK) == 0; 27837203Sbostic 27936880Sbostic if (pwd->pw_change || pwd->pw_expire) 28036880Sbostic (void)gettimeofday(&tp, (struct timezone *)NULL); 28136880Sbostic if (pwd->pw_change) 28236880Sbostic if (tp.tv_sec >= pwd->pw_change) { 28337203Sbostic (void)printf("Sorry -- your password has expired.\n"); 28436880Sbostic sleepexit(1); 28536880Sbostic } 28638216Sbostic else if (pwd->pw_change - tp.tv_sec < 28743660Sbostic 2 * DAYSPERWEEK * SECSPERDAY && !quietlog) 28843660Sbostic (void)printf("Warning: your password expires on %s", 28943660Sbostic ctime(&pwd->pw_expire)); 29036880Sbostic if (pwd->pw_expire) 29136880Sbostic if (tp.tv_sec >= pwd->pw_expire) { 29237203Sbostic (void)printf("Sorry -- your account has expired.\n"); 29336880Sbostic sleepexit(1); 29436880Sbostic } 29538216Sbostic else if (pwd->pw_expire - tp.tv_sec < 29643660Sbostic 2 * DAYSPERWEEK * SECSPERDAY && !quietlog) 29743660Sbostic (void)printf("Warning: your account expires on %s", 29843660Sbostic ctime(&pwd->pw_expire)); 29936880Sbostic 30036515Sbostic /* nothing else left to fail -- really log in */ 30136460Sbostic { 30236460Sbostic struct utmp utmp; 30336460Sbostic 30443653Sbostic bzero((void *)&utmp, sizeof(utmp)); 30536460Sbostic (void)time(&utmp.ut_time); 30636460Sbostic strncpy(utmp.ut_name, username, sizeof(utmp.ut_name)); 30736591Sbostic if (hostname) 30836591Sbostic strncpy(utmp.ut_host, hostname, sizeof(utmp.ut_host)); 30936460Sbostic strncpy(utmp.ut_line, tty, sizeof(utmp.ut_line)); 31036460Sbostic login(&utmp); 31136460Sbostic } 31236460Sbostic 31336549Sbostic dolastlog(quietlog); 31436460Sbostic 31537203Sbostic if (!hflag) { /* XXX */ 31636460Sbostic static struct winsize win = { 0, 0, 0, 0 }; 31736460Sbostic 31836460Sbostic (void)ioctl(0, TIOCSWINSZ, &win); 31936460Sbostic } 32036460Sbostic 32136460Sbostic (void)chown(ttyn, pwd->pw_uid, 32236460Sbostic (gr = getgrnam(TTYGRPNAME)) ? gr->gr_gid : pwd->pw_gid); 32336460Sbostic (void)chmod(ttyn, 0620); 32436460Sbostic (void)setgid(pwd->pw_gid); 32536460Sbostic 32636460Sbostic initgroups(username, pwd->pw_gid); 32736460Sbostic 32836515Sbostic if (*pwd->pw_shell == '\0') 32937203Sbostic pwd->pw_shell = _PATH_BSHELL; 33036515Sbostic 33136460Sbostic /* destroy environment unless user has requested preservation */ 33218549Ssam if (!pflag) 33318549Ssam environ = envinit; 33436515Sbostic (void)setenv("HOME", pwd->pw_dir, 1); 33536515Sbostic (void)setenv("SHELL", pwd->pw_shell, 1); 33618549Ssam if (term[0] == '\0') 33736647Skarels strncpy(term, stypeof(tty), sizeof(term)); 33836515Sbostic (void)setenv("TERM", term, 0); 33936515Sbostic (void)setenv("USER", pwd->pw_name, 1); 34037252Sbostic (void)setenv("PATH", _PATH_DEFPATH, 0); 34118549Ssam 34216453Sroot if (tty[sizeof("tty")-1] == 'd') 34318549Ssam syslog(LOG_INFO, "DIALUP %s, %s", tty, pwd->pw_name); 344*44348Skarels /* if fflag is on, assume caller/authenticator has logged root login */ 345*44348Skarels if (pwd->pw_uid == 0 && fflag == 0) 34636460Sbostic if (hostname) 34736647Skarels syslog(LOG_NOTICE, "ROOT LOGIN ON %s FROM %s", 34836549Sbostic tty, hostname); 34925230Smckusick else 35036647Skarels syslog(LOG_NOTICE, "ROOT LOGIN ON %s", tty); 35136460Sbostic 35243653Sbostic #ifdef KERBEROS 35343653Sbostic if (!quietlog && notickets == 1) 35443653Sbostic (void)printf("Warning: no Kerberos tickets issued.\n"); 35543653Sbostic #endif 35643653Sbostic 3576329Swnj if (!quietlog) { 35817664Sserge struct stat st; 35918549Ssam 36036460Sbostic motd(); 36137203Sbostic (void)sprintf(tbuf, "%s/%s", _PATH_MAILDIR, pwd->pw_name); 36236460Sbostic if (stat(tbuf, &st) == 0 && st.st_size != 0) 36337203Sbostic (void)printf("You have %smail.\n", 36436460Sbostic (st.st_mtime > st.st_atime) ? "new " : ""); 3652822Swnj } 36636460Sbostic 36736460Sbostic (void)signal(SIGALRM, SIG_DFL); 36836460Sbostic (void)signal(SIGQUIT, SIG_DFL); 36936460Sbostic (void)signal(SIGINT, SIG_DFL); 37036460Sbostic (void)signal(SIGTSTP, SIG_IGN); 37136460Sbostic 37236460Sbostic tbuf[0] = '-'; 37336460Sbostic strcpy(tbuf + 1, (p = rindex(pwd->pw_shell, '/')) ? 37436460Sbostic p + 1 : pwd->pw_shell); 37537203Sbostic 37640009Ssklower if (setlogin(pwd->pw_name) < 0) 37740009Ssklower syslog(LOG_ERR, "setlogin() failure: %m"); 37837692Sbostic 37937203Sbostic /* discard permissions last so can't get killed and drop core */ 38037203Sbostic (void)setuid(pwd->pw_uid); 38137203Sbostic 38236460Sbostic execlp(pwd->pw_shell, tbuf, 0); 38337203Sbostic (void)fprintf(stderr, "login: no shell: %s.\n", strerror(errno)); 3841043Sbill exit(0); 3851043Sbill } 3861043Sbill 38736460Sbostic getloginname() 38812687Ssam { 38936460Sbostic register int ch; 39036460Sbostic register char *p; 39136460Sbostic static char nbuf[UT_NAMESIZE + 1]; 39212687Ssam 39336460Sbostic for (;;) { 39437203Sbostic (void)printf("login: "); 39536515Sbostic for (p = nbuf; (ch = getchar()) != '\n'; ) { 39636549Sbostic if (ch == EOF) { 39736549Sbostic badlogin(username); 39812687Ssam exit(0); 39936549Sbostic } 40036515Sbostic if (p < nbuf + UT_NAMESIZE) 40136460Sbostic *p++ = ch; 40212687Ssam } 40336460Sbostic if (p > nbuf) 40436460Sbostic if (nbuf[0] == '-') 40537203Sbostic (void)fprintf(stderr, 40636460Sbostic "login names may not start with '-'.\n"); 40736460Sbostic else { 40836460Sbostic *p = '\0'; 40936460Sbostic username = nbuf; 41036515Sbostic break; 41136460Sbostic } 41212687Ssam } 41312687Ssam } 41412687Ssam 41543653Sbostic void 41612687Ssam timedout() 41712687Ssam { 41837203Sbostic (void)fprintf(stderr, "Login timed out after %d seconds\n", timeout); 41912687Ssam exit(0); 42012687Ssam } 42112687Ssam 42236647Skarels rootterm(ttyn) 42336647Skarels char *ttyn; 4241043Sbill { 42536460Sbostic struct ttyent *t; 4266466Swnj 42736647Skarels return((t = getttynam(ttyn)) && t->ty_status&TTY_SECURE); 4281043Sbill } 4291043Sbill 43036515Sbostic jmp_buf motdinterrupt; 43136515Sbostic 43236460Sbostic motd() 4332822Swnj { 43436515Sbostic register int fd, nchars; 43538726Skfall sig_t oldint; 43638726Skfall int sigint(); 43736515Sbostic char tbuf[8192]; 4382822Swnj 43937203Sbostic if ((fd = open(_PATH_MOTDFILE, O_RDONLY, 0)) < 0) 44036460Sbostic return; 44136460Sbostic oldint = signal(SIGINT, sigint); 44236515Sbostic if (setjmp(motdinterrupt) == 0) 44336515Sbostic while ((nchars = read(fd, tbuf, sizeof(tbuf))) > 0) 44436515Sbostic (void)write(fileno(stdout), tbuf, nchars); 44536460Sbostic (void)signal(SIGINT, oldint); 44636515Sbostic (void)close(fd); 44736460Sbostic } 44836460Sbostic 44936460Sbostic sigint() 45036460Sbostic { 45136515Sbostic longjmp(motdinterrupt, 1); 45236460Sbostic } 45336460Sbostic 45436460Sbostic checknologin() 45536460Sbostic { 45636460Sbostic register int fd, nchars; 45736515Sbostic char tbuf[8192]; 45836460Sbostic 45937203Sbostic if ((fd = open(_PATH_NOLOGIN, O_RDONLY, 0)) >= 0) { 46036460Sbostic while ((nchars = read(fd, tbuf, sizeof(tbuf))) > 0) 46136460Sbostic (void)write(fileno(stdout), tbuf, nchars); 46236460Sbostic sleepexit(0); 4632822Swnj } 4642822Swnj } 4652822Swnj 46636549Sbostic dolastlog(quiet) 46736460Sbostic int quiet; 4681043Sbill { 46936460Sbostic struct lastlog ll; 47036460Sbostic int fd; 47136880Sbostic char *ctime(); 4721043Sbill 47337203Sbostic if ((fd = open(_PATH_LASTLOG, O_RDWR, 0)) >= 0) { 47436515Sbostic (void)lseek(fd, (off_t)pwd->pw_uid * sizeof(ll), L_SET); 47536460Sbostic if (!quiet) { 47636460Sbostic if (read(fd, (char *)&ll, sizeof(ll)) == sizeof(ll) && 47736460Sbostic ll.ll_time != 0) { 47837203Sbostic (void)printf("Last login: %.*s ", 47936460Sbostic 24-5, (char *)ctime(&ll.ll_time)); 48036460Sbostic if (*ll.ll_host != '\0') 48137203Sbostic (void)printf("from %.*s\n", 48236460Sbostic sizeof(ll.ll_host), ll.ll_host); 48336460Sbostic else 48437203Sbostic (void)printf("on %.*s\n", 48536460Sbostic sizeof(ll.ll_line), ll.ll_line); 48636460Sbostic } 48736515Sbostic (void)lseek(fd, (off_t)pwd->pw_uid * sizeof(ll), L_SET); 48836460Sbostic } 48943653Sbostic bzero((void *)&ll, sizeof(ll)); 49036460Sbostic (void)time(&ll.ll_time); 49136460Sbostic strncpy(ll.ll_line, tty, sizeof(ll.ll_line)); 49236591Sbostic if (hostname) 49336591Sbostic strncpy(ll.ll_host, hostname, sizeof(ll.ll_host)); 49436460Sbostic (void)write(fd, (char *)&ll, sizeof(ll)); 49536460Sbostic (void)close(fd); 4961043Sbill } 4971043Sbill } 4981043Sbill 49936549Sbostic badlogin(name) 50036549Sbostic char *name; 50136549Sbostic { 50236647Skarels if (failures == 0) 50336549Sbostic return; 50436549Sbostic if (hostname) 50536647Skarels syslog(LOG_NOTICE, "%d LOGIN FAILURE%s FROM %s, %s", 50636647Skarels failures, failures > 1 ? "S" : "", hostname, name); 50736549Sbostic else 50836647Skarels syslog(LOG_NOTICE, "%d LOGIN FAILURE%s ON %s, %s", 50936647Skarels failures, failures > 1 ? "S" : "", tty, name); 51036549Sbostic } 51136549Sbostic 5122822Swnj #undef UNKNOWN 51336460Sbostic #define UNKNOWN "su" 5141043Sbill 5151043Sbill char * 51636647Skarels stypeof(ttyid) 51736647Skarels char *ttyid; 5181043Sbill { 51936460Sbostic struct ttyent *t; 5201043Sbill 52136647Skarels return(ttyid && (t = getttynam(ttyid)) ? t->ty_type : UNKNOWN); 5221043Sbill } 5236005Swnj 52436460Sbostic sleepexit(eval) 52536460Sbostic int eval; 52626862Smckusick { 52736460Sbostic sleep((u_int)5); 52836460Sbostic exit(eval); 52926862Smckusick } 530