119843Sdist/* 236515Sbostic * Copyright (c) 1980, 1987, 1988 The Regents of the University of California. 336515Sbostic * All rights reserved. 436515Sbostic * 536515Sbostic * Redistribution and use in source and binary forms are permitted 636515Sbostic * provided that the above copyright notice and this paragraph are 736515Sbostic * duplicated in all such forms and that any documentation, 836515Sbostic * advertising materials, and other materials related to such 936515Sbostic * distribution and use acknowledge that the software was developed 1036515Sbostic * by the University of California, Berkeley. The name of the 1136515Sbostic * University may not be used to endorse or promote products derived 1236515Sbostic * from this software without specific prior written permission. 1336515Sbostic * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 1436515Sbostic * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 1536515Sbostic * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 1619843Sdist */ 1719843Sdist 1812678Ssam#ifndef lint 1919843Sdistchar copyright[] = 2036515Sbostic"@(#) Copyright (c) 1980, 1987, 1988 The Regents of the University of California.\n\ 2119843Sdist All rights reserved.\n"; 2236515Sbostic#endif /* not lint */ 2312678Ssam 2419843Sdist#ifndef lint 25*36880Sbosticstatic char sccsid[] = "@(#)login.c.1 5.34 (Berkeley) 02/23/89"; 2636515Sbostic#endif /* not lint */ 2719843Sdist 281043Sbill/* 291043Sbill * login [ name ] 3031695Skarels * login -h hostname (for telnetd, etc.) 3131695Skarels * login -f name (for pre-authenticated login: datakit, xterm, etc.) 321043Sbill */ 331043Sbill 3412984Ssam#include <sys/param.h> 3512687Ssam#include <sys/quota.h> 3612687Ssam#include <sys/stat.h> 3712687Ssam#include <sys/time.h> 3812687Ssam#include <sys/resource.h> 3916453Sroot#include <sys/file.h> 4036460Sbostic#include <sys/ioctl.h> 4112687Ssam 421043Sbill#include <utmp.h> 431043Sbill#include <signal.h> 441043Sbill#include <lastlog.h> 4512678Ssam#include <errno.h> 4616453Sroot#include <ttyent.h> 4716453Sroot#include <syslog.h> 4826862Smckusick#include <grp.h> 4936460Sbostic#include <pwd.h> 5036515Sbostic#include <setjmp.h> 5136460Sbostic#include <stdio.h> 5236460Sbostic#include <strings.h> 531043Sbill 5436709Skfall#ifdef KERBEROS 5536709Skfall#include <kerberos/krb.h> 5636709Skfall#include <sys/termios.h> 5736709Skfallchar realm[REALM_SZ]; 5836709Skfallint kerror = KSUCCESS, notickets = 1; 5936709Skfall#endif 6036709Skfall 6136460Sbostic#define TTYGRPNAME "tty" /* name of group to own ttys */ 6226862Smckusick 6336460Sbostic#define MOTDFILE "/etc/motd" 6436460Sbostic#define MAILDIR "/usr/spool/mail" 6536460Sbostic#define NOLOGIN "/etc/nologin" 6636460Sbostic#define HUSHLOGIN ".hushlogin" 6736460Sbostic#define LASTLOG "/usr/adm/lastlog" 6836460Sbostic#define BSHELL "/bin/sh" 692822Swnj 7012687Ssam/* 7136460Sbostic * This bounds the time given to login. Not a define so it can 7236460Sbostic * be patched on machines where it's too small. 7312687Ssam */ 7431509Sbosticint timeout = 300; 756005Swnj 7636647Skarelsstruct passwd *pwd; 7736647Skarelsint failures; 7836647Skarelschar term[64], *hostname, *username, *tty; 796005Swnj 8036647Skarelsstruct sgttyb sgttyb; 8136647Skarelsstruct tchars tc = { 8213074Ssam CINTR, CQUIT, CSTART, CSTOP, CEOT, CBRK 831365Sbill}; 8436647Skarelsstruct ltchars ltc = { 8513074Ssam CSUSP, CDSUSP, CRPRNT, CFLUSH, CWERASE, CLNEXT 8613074Ssam}; 871365Sbill 88*36880Sbosticchar *months[] = 89*36880Sbostic { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", 90*36880Sbostic "Sep", "Oct", "Nov", "Dec" }; 91*36880Sbostic 921043Sbillmain(argc, argv) 9336460Sbostic int argc; 9436460Sbostic char **argv; 951043Sbill{ 9636460Sbostic extern int errno, optind; 9736460Sbostic extern char *optarg, **environ; 98*36880Sbostic struct timeval tp; 99*36880Sbostic struct tm *ttp; 10036460Sbostic struct group *gr; 10136460Sbostic register int ch; 10236647Skarels register char *p; 10336549Sbostic int ask, fflag, hflag, pflag, cnt; 10436460Sbostic int quietlog, passwd_req, ioctlval, timedout(); 10536647Skarels char *domain, *salt, *envinit[1], *ttyn, *pp; 10636460Sbostic char tbuf[MAXPATHLEN + 2]; 107*36880Sbostic char *ctime(), *ttyname(), *stypeof(), *crypt(), *getpass(); 10836460Sbostic time_t time(); 10936460Sbostic off_t lseek(); 1101043Sbill 11136460Sbostic (void)signal(SIGALRM, timedout); 11236460Sbostic (void)alarm((u_int)timeout); 11336460Sbostic (void)signal(SIGQUIT, SIG_IGN); 11436460Sbostic (void)signal(SIGINT, SIG_IGN); 11536460Sbostic (void)setpriority(PRIO_PROCESS, 0, 0); 11636460Sbostic (void)quota(Q_SETUID, 0, 0, 0); 11736460Sbostic 11812687Ssam /* 11918549Ssam * -p is used by getty to tell login not to destroy the environment 12031695Skarels * -f is used to skip a second login authentication 12136523Skarels * -h is used by other servers to pass the name of the remote 12236523Skarels * host to login so that it may be placed in utmp and wtmp 12312687Ssam */ 12436460Sbostic (void)gethostname(tbuf, sizeof(tbuf)); 12536460Sbostic domain = index(tbuf, '.'); 12636460Sbostic 12736523Skarels fflag = hflag = pflag = 0; 12836460Sbostic passwd_req = 1; 12936523Skarels while ((ch = getopt(argc, argv, "fh:p")) != EOF) 13036515Sbostic switch (ch) { 13136460Sbostic case 'f': 13236460Sbostic fflag = 1; 13336460Sbostic break; 13436460Sbostic case 'h': 13536460Sbostic if (getuid()) { 13636460Sbostic fprintf(stderr, 13736460Sbostic "login: -h for super-user only.\n"); 13832313Sbostic exit(1); 13931695Skarels } 14036460Sbostic hflag = 1; 14136460Sbostic if (domain && (p = index(optarg, '.')) && 14236553Sbostic strcasecmp(p, domain) == 0) 14336460Sbostic *p = 0; 14436460Sbostic hostname = optarg; 14536460Sbostic break; 14636460Sbostic case 'p': 14718549Ssam pflag = 1; 14836460Sbostic break; 14936460Sbostic case '?': 15036460Sbostic default: 15136515Sbostic fprintf(stderr, "usage: login [-fp] [username]\n"); 15236460Sbostic exit(1); 15318549Ssam } 15436460Sbostic argc -= optind; 15536460Sbostic argv += optind; 15636549Sbostic if (*argv) { 15736647Skarels username = *argv; 15836549Sbostic ask = 0; 15936647Skarels } else 16036549Sbostic ask = 1; 16136460Sbostic 16236460Sbostic ioctlval = 0; 16336460Sbostic (void)ioctl(0, TIOCLSET, &ioctlval); 16436460Sbostic (void)ioctl(0, TIOCNXCL, 0); 16536515Sbostic (void)fcntl(0, F_SETFL, ioctlval); 16636515Sbostic (void)ioctl(0, TIOCGETP, &sgttyb); 16736515Sbostic sgttyb.sg_erase = CERASE; 16836515Sbostic sgttyb.sg_kill = CKILL; 16936460Sbostic (void)ioctl(0, TIOCSLTC, <c); 17036460Sbostic (void)ioctl(0, TIOCSETC, &tc); 17136515Sbostic (void)ioctl(0, TIOCSETP, &sgttyb); 17236460Sbostic 17336460Sbostic for (cnt = getdtablesize(); cnt > 2; cnt--) 17436460Sbostic close(cnt); 17536460Sbostic 1761043Sbill ttyn = ttyname(0); 17736460Sbostic if (ttyn == NULL || *ttyn == '\0') 1781043Sbill ttyn = "/dev/tty??"; 17936460Sbostic if (tty = rindex(ttyn, '/')) 18036460Sbostic ++tty; 18136460Sbostic else 18216453Sroot tty = ttyn; 18336460Sbostic 18424852Seric openlog("login", LOG_ODELAY, LOG_AUTH); 18536460Sbostic 18636549Sbostic for (cnt = 0;; ask = 1) { 18736460Sbostic ioctlval = 0; 18836460Sbostic (void)ioctl(0, TIOCSETD, &ioctlval); 18936460Sbostic 19036549Sbostic if (ask) { 19136515Sbostic fflag = 0; 19236460Sbostic getloginname(); 19336515Sbostic } 19436647Skarels /* 19536647Skarels * Note if trying multiple user names; 19636647Skarels * log failures for previous user name, 19736647Skarels * but don't bother logging one failure 19836647Skarels * for nonexistent name (mistyped username). 19936647Skarels */ 20036647Skarels if (failures && strcmp(tbuf, username)) { 20136647Skarels if (failures > (pwd ? 0 : 1)) 20236549Sbostic badlogin(tbuf); 20336647Skarels failures = 0; 20436549Sbostic } 20536647Skarels (void)strcpy(tbuf, username); 20636515Sbostic if (pwd = getpwnam(username)) 20736515Sbostic salt = pwd->pw_passwd; 20836515Sbostic else 20936515Sbostic salt = "xx"; 21036460Sbostic 21136460Sbostic /* if user not super-user, check for disabled logins */ 21236515Sbostic if (pwd == NULL || pwd->pw_uid) 21336460Sbostic checknologin(); 21436460Sbostic 21512687Ssam /* 21636515Sbostic * Disallow automatic login to root; if not invoked by 21736515Sbostic * root, disallow if the uid's differ. 21812687Ssam */ 21936515Sbostic if (fflag && pwd) { 22031695Skarels int uid = getuid(); 22131695Skarels 22236515Sbostic passwd_req = pwd->pw_uid == 0 || 22336515Sbostic (uid && uid != pwd->pw_uid); 22431695Skarels } 22536460Sbostic 22612687Ssam /* 22736523Skarels * If no pre-authentication and a password exists 22836460Sbostic * for this user, prompt for one and verify it. 22912687Ssam */ 23036608Skfall if (!passwd_req || (pwd && !*pwd->pw_passwd)) 23136460Sbostic break; 23212687Ssam 23336460Sbostic setpriority(PRIO_PROCESS, 0, -4); 23436608Skfall pp = getpass("Password:"); 23536608Skfall p = crypt(pp, salt); 23636460Sbostic setpriority(PRIO_PROCESS, 0, 0); 23736608Skfall 23836709Skfall#ifdef KERBEROS 23936709Skfall 24036709Skfall /* 24136709Skfall * If not present in pw file, act as we normally would. 24236709Skfall * If we aren't Kerberos-authenticated, try the normal 24336709Skfall * pw file for a password. If that's ok, log the user 24436709Skfall * in without issueing any tickets. 24536709Skfall */ 24636709Skfall 24736709Skfall if (pwd && !krb_get_lrealm(realm,1)) { 24836709Skfall /* get TGT for local realm 24936709Skfall * be careful about uid's here for ticket 25036709Skfall * file ownership 25136709Skfall */ 25236709Skfall (void) setreuid(geteuid(),pwd->pw_uid); 25336709Skfall kerror = krb_get_pw_in_tkt( 25436709Skfall pwd->pw_name, "", realm, 25536709Skfall "krbtgt", realm, DEFAULT_TKT_LIFE, pp); 25636709Skfall (void) setuid(0); 25736709Skfall if (kerror == INTK_OK) { 25836709Skfall bzero(pp, strlen(pp)); 25936709Skfall notickets = 0; /* user got ticket */ 26036709Skfall break; 26136709Skfall } 26236709Skfall } 26336709Skfall#endif 26436608Skfall (void) bzero(pp, strlen(pp)); 26536515Sbostic if (pwd && !strcmp(p, pwd->pw_passwd)) 26636460Sbostic break; 26736460Sbostic 26836460Sbostic printf("Login incorrect\n"); 26936647Skarels failures++; 27036549Sbostic /* we allow 10 tries, but after 3 we start backing off */ 27136549Sbostic if (++cnt > 3) { 27236549Sbostic if (cnt >= 10) { 27336549Sbostic badlogin(username); 27436549Sbostic (void)ioctl(0, TIOCHPCL, (struct sgttyb *)NULL); 27536549Sbostic sleepexit(1); 27636549Sbostic } 27736549Sbostic sleep((u_int)((cnt - 3) * 5)); 2782822Swnj } 27936460Sbostic } 2801043Sbill 28136460Sbostic /* committed to login -- turn off timeout */ 28236460Sbostic (void)alarm((u_int)0); 28336460Sbostic 28436460Sbostic /* 28536460Sbostic * If valid so far and root is logging in, see if root logins on 28636460Sbostic * this terminal are permitted. 28736460Sbostic */ 28836647Skarels if (pwd->pw_uid == 0 && !rootterm(tty)) { 28936460Sbostic if (hostname) 29036647Skarels syslog(LOG_NOTICE, "ROOT LOGIN REFUSED FROM %s", 29136647Skarels hostname); 29212678Ssam else 29336647Skarels syslog(LOG_NOTICE, "ROOT LOGIN REFUSED ON %s", tty); 29436460Sbostic printf("Login incorrect\n"); 29536460Sbostic sleepexit(1); 29612678Ssam } 2972822Swnj 29836460Sbostic if (quota(Q_SETUID, pwd->pw_uid, 0, 0) < 0 && errno != EINVAL) { 29936460Sbostic switch(errno) { 30036460Sbostic case EUSERS: 30136460Sbostic fprintf(stderr, 30236460Sbostic "Too many users logged on already.\nTry again later.\n"); 30336460Sbostic break; 30436460Sbostic case EPROCLIM: 30536460Sbostic fprintf(stderr, 30636460Sbostic "You have too many processes running.\n"); 30736460Sbostic break; 30836460Sbostic default: 30936460Sbostic perror("quota (Q_SETUID)"); 3102822Swnj } 31136460Sbostic sleepexit(0); 3122822Swnj } 31336460Sbostic 31436515Sbostic if (chdir(pwd->pw_dir) < 0) { 31536515Sbostic printf("No directory %s!\n", pwd->pw_dir); 31636515Sbostic if (chdir("/")) 31736515Sbostic exit(0); 31836515Sbostic pwd->pw_dir = "/"; 31936515Sbostic printf("Logging in with home = \"/\".\n"); 32036515Sbostic } 32136515Sbostic 322*36880Sbostic#ifdef KERBEROS 32336709Skfall if (notickets) 32436709Skfall printf("Warning: no Kerberos tickets issued\n"); 32536709Skfall#endif 32636709Skfall 327*36880Sbostic#define TWOWEEKS (14*24*60*60) 328*36880Sbostic if (pwd->pw_change || pwd->pw_expire) 329*36880Sbostic (void)gettimeofday(&tp, (struct timezone *)NULL); 330*36880Sbostic if (pwd->pw_change) 331*36880Sbostic if (tp.tv_sec >= pwd->pw_change) { 332*36880Sbostic printf("Sorry -- your password has expired.\n"); 333*36880Sbostic sleepexit(1); 334*36880Sbostic } 335*36880Sbostic else if (tp.tv_sec - pwd->pw_change < TWOWEEKS) { 336*36880Sbostic ttp = localtime(&pwd->pw_change); 337*36880Sbostic printf("Warning: your password expires on %s %d, 19%d\n", 338*36880Sbostic months[ttp->tm_mon], ttp->tm_mday, ttp->tm_year); 339*36880Sbostic } 340*36880Sbostic if (pwd->pw_expire) 341*36880Sbostic if (tp.tv_sec >= pwd->pw_expire) { 342*36880Sbostic printf("Sorry -- your account has expired.\n"); 343*36880Sbostic sleepexit(1); 344*36880Sbostic } 345*36880Sbostic else if (tp.tv_sec - pwd->pw_expire < TWOWEEKS) { 346*36880Sbostic ttp = localtime(&pwd->pw_expire); 347*36880Sbostic printf("Warning: your account expires on %s %d, 19%d\n", 348*36880Sbostic months[ttp->tm_mon], ttp->tm_mday, ttp->tm_year); 349*36880Sbostic } 350*36880Sbostic 35136515Sbostic /* nothing else left to fail -- really log in */ 35236460Sbostic { 35336460Sbostic struct utmp utmp; 35436460Sbostic 35536647Skarels bzero((char *)&utmp, sizeof(utmp)); 35636460Sbostic (void)time(&utmp.ut_time); 35736460Sbostic strncpy(utmp.ut_name, username, sizeof(utmp.ut_name)); 35836591Sbostic if (hostname) 35936591Sbostic strncpy(utmp.ut_host, hostname, sizeof(utmp.ut_host)); 36036460Sbostic strncpy(utmp.ut_line, tty, sizeof(utmp.ut_line)); 36136460Sbostic login(&utmp); 36236460Sbostic } 36336460Sbostic 36436460Sbostic quietlog = access(HUSHLOGIN, F_OK) == 0; 36536549Sbostic dolastlog(quietlog); 36636460Sbostic 36736523Skarels if (!hflag) { /* XXX */ 36836460Sbostic static struct winsize win = { 0, 0, 0, 0 }; 36936460Sbostic 37036460Sbostic (void)ioctl(0, TIOCSWINSZ, &win); 37136460Sbostic } 37236460Sbostic 37336460Sbostic (void)chown(ttyn, pwd->pw_uid, 37436460Sbostic (gr = getgrnam(TTYGRPNAME)) ? gr->gr_gid : pwd->pw_gid); 37536460Sbostic (void)chmod(ttyn, 0620); 37636460Sbostic (void)setgid(pwd->pw_gid); 37736460Sbostic 37836460Sbostic initgroups(username, pwd->pw_gid); 37936460Sbostic 38012678Ssam quota(Q_DOWARN, pwd->pw_uid, (dev_t)-1, 0); 38136460Sbostic (void)setuid(pwd->pw_uid); 38230606Sbostic 38336515Sbostic if (*pwd->pw_shell == '\0') 38436515Sbostic pwd->pw_shell = BSHELL; 38536515Sbostic /* turn on new line discipline for the csh */ 38636515Sbostic else if (!strcmp(pwd->pw_shell, "/bin/csh")) { 38736515Sbostic ioctlval = NTTYDISC; 38836515Sbostic (void)ioctl(0, TIOCSETD, &ioctlval); 38936515Sbostic } 39036515Sbostic 39136460Sbostic /* destroy environment unless user has requested preservation */ 39218549Ssam if (!pflag) 39318549Ssam environ = envinit; 39436515Sbostic (void)setenv("HOME", pwd->pw_dir, 1); 39536515Sbostic (void)setenv("SHELL", pwd->pw_shell, 1); 39618549Ssam if (term[0] == '\0') 39736647Skarels strncpy(term, stypeof(tty), sizeof(term)); 39836515Sbostic (void)setenv("TERM", term, 0); 39936515Sbostic (void)setenv("USER", pwd->pw_name, 1); 40036515Sbostic (void)setenv("PATH", "/usr/ucb:/bin:/usr/bin:", 0); 40118549Ssam 40216453Sroot if (tty[sizeof("tty")-1] == 'd') 40318549Ssam syslog(LOG_INFO, "DIALUP %s, %s", tty, pwd->pw_name); 40418549Ssam if (pwd->pw_uid == 0) 40536460Sbostic if (hostname) 40636647Skarels syslog(LOG_NOTICE, "ROOT LOGIN ON %s FROM %s", 40736549Sbostic tty, hostname); 40825230Smckusick else 40936647Skarels syslog(LOG_NOTICE, "ROOT LOGIN ON %s", tty); 41036460Sbostic 4116329Swnj if (!quietlog) { 41217664Sserge struct stat st; 41318549Ssam 41436460Sbostic motd(); 41536460Sbostic (void)sprintf(tbuf, "%s/%s", MAILDIR, pwd->pw_name); 41636460Sbostic if (stat(tbuf, &st) == 0 && st.st_size != 0) 41717664Sserge printf("You have %smail.\n", 41836460Sbostic (st.st_mtime > st.st_atime) ? "new " : ""); 4192822Swnj } 42036460Sbostic 42136460Sbostic (void)signal(SIGALRM, SIG_DFL); 42236460Sbostic (void)signal(SIGQUIT, SIG_DFL); 42336460Sbostic (void)signal(SIGINT, SIG_DFL); 42436460Sbostic (void)signal(SIGTSTP, SIG_IGN); 42536460Sbostic 42636460Sbostic tbuf[0] = '-'; 42736460Sbostic strcpy(tbuf + 1, (p = rindex(pwd->pw_shell, '/')) ? 42836460Sbostic p + 1 : pwd->pw_shell); 42936460Sbostic execlp(pwd->pw_shell, tbuf, 0); 43036515Sbostic fprintf(stderr, "login: no shell: "); 4312822Swnj perror(pwd->pw_shell); 4321043Sbill exit(0); 4331043Sbill} 4341043Sbill 43536460Sbosticgetloginname() 43612687Ssam{ 43736460Sbostic register int ch; 43836460Sbostic register char *p; 43936460Sbostic static char nbuf[UT_NAMESIZE + 1]; 44012687Ssam 44136460Sbostic for (;;) { 44212712Ssam printf("login: "); 44336515Sbostic for (p = nbuf; (ch = getchar()) != '\n'; ) { 44436549Sbostic if (ch == EOF) { 44536549Sbostic badlogin(username); 44612687Ssam exit(0); 44736549Sbostic } 44836515Sbostic if (p < nbuf + UT_NAMESIZE) 44936460Sbostic *p++ = ch; 45012687Ssam } 45136460Sbostic if (p > nbuf) 45236460Sbostic if (nbuf[0] == '-') 45336460Sbostic fprintf(stderr, 45436460Sbostic "login names may not start with '-'.\n"); 45536460Sbostic else { 45636460Sbostic *p = '\0'; 45736460Sbostic username = nbuf; 45836515Sbostic break; 45936460Sbostic } 46012687Ssam } 46112687Ssam} 46212687Ssam 46312687Ssamtimedout() 46412687Ssam{ 46536460Sbostic fprintf(stderr, "Login timed out after %d seconds\n", timeout); 46612687Ssam exit(0); 46712687Ssam} 46812687Ssam 46936647Skarelsrootterm(ttyn) 47036647Skarels char *ttyn; 4711043Sbill{ 47236460Sbostic struct ttyent *t; 4736466Swnj 47436647Skarels return((t = getttynam(ttyn)) && t->ty_status&TTY_SECURE); 4751043Sbill} 4761043Sbill 47736515Sbosticjmp_buf motdinterrupt; 47836515Sbostic 47936460Sbosticmotd() 4802822Swnj{ 48136515Sbostic register int fd, nchars; 48236460Sbostic int (*oldint)(), sigint(); 48336515Sbostic char tbuf[8192]; 4842822Swnj 48536515Sbostic if ((fd = open(MOTDFILE, O_RDONLY, 0)) < 0) 48636460Sbostic return; 48736460Sbostic oldint = signal(SIGINT, sigint); 48836515Sbostic if (setjmp(motdinterrupt) == 0) 48936515Sbostic while ((nchars = read(fd, tbuf, sizeof(tbuf))) > 0) 49036515Sbostic (void)write(fileno(stdout), tbuf, nchars); 49136460Sbostic (void)signal(SIGINT, oldint); 49236515Sbostic (void)close(fd); 49336460Sbostic} 49436460Sbostic 49536460Sbosticsigint() 49636460Sbostic{ 49736515Sbostic longjmp(motdinterrupt, 1); 49836460Sbostic} 49936460Sbostic 50036460Sbosticchecknologin() 50136460Sbostic{ 50236460Sbostic register int fd, nchars; 50336515Sbostic char tbuf[8192]; 50436460Sbostic 50536460Sbostic if ((fd = open(NOLOGIN, O_RDONLY, 0)) >= 0) { 50636460Sbostic while ((nchars = read(fd, tbuf, sizeof(tbuf))) > 0) 50736460Sbostic (void)write(fileno(stdout), tbuf, nchars); 50836460Sbostic sleepexit(0); 5092822Swnj } 5102822Swnj} 5112822Swnj 51236549Sbosticdolastlog(quiet) 51336460Sbostic int quiet; 5141043Sbill{ 51536460Sbostic struct lastlog ll; 51636460Sbostic int fd; 517*36880Sbostic char *ctime(); 5181043Sbill 51936460Sbostic if ((fd = open(LASTLOG, O_RDWR, 0)) >= 0) { 52036515Sbostic (void)lseek(fd, (off_t)pwd->pw_uid * sizeof(ll), L_SET); 52136460Sbostic if (!quiet) { 52236460Sbostic if (read(fd, (char *)&ll, sizeof(ll)) == sizeof(ll) && 52336460Sbostic ll.ll_time != 0) { 52436460Sbostic printf("Last login: %.*s ", 52536460Sbostic 24-5, (char *)ctime(&ll.ll_time)); 52636460Sbostic if (*ll.ll_host != '\0') 52736460Sbostic printf("from %.*s\n", 52836460Sbostic sizeof(ll.ll_host), ll.ll_host); 52936460Sbostic else 53036460Sbostic printf("on %.*s\n", 53136460Sbostic sizeof(ll.ll_line), ll.ll_line); 53236460Sbostic } 53336515Sbostic (void)lseek(fd, (off_t)pwd->pw_uid * sizeof(ll), L_SET); 53436460Sbostic } 53536647Skarels bzero((char *)&ll, sizeof(ll)); 53636460Sbostic (void)time(&ll.ll_time); 53736460Sbostic strncpy(ll.ll_line, tty, sizeof(ll.ll_line)); 53836591Sbostic if (hostname) 53936591Sbostic strncpy(ll.ll_host, hostname, sizeof(ll.ll_host)); 54036460Sbostic (void)write(fd, (char *)&ll, sizeof(ll)); 54136460Sbostic (void)close(fd); 5421043Sbill } 5431043Sbill} 5441043Sbill 54536549Sbosticbadlogin(name) 54636549Sbostic char *name; 54736549Sbostic{ 54836647Skarels if (failures == 0) 54936549Sbostic return; 55036549Sbostic if (hostname) 55136647Skarels syslog(LOG_NOTICE, "%d LOGIN FAILURE%s FROM %s, %s", 55236647Skarels failures, failures > 1 ? "S" : "", hostname, name); 55336549Sbostic else 55436647Skarels syslog(LOG_NOTICE, "%d LOGIN FAILURE%s ON %s, %s", 55536647Skarels failures, failures > 1 ? "S" : "", tty, name); 55636549Sbostic} 55736549Sbostic 5582822Swnj#undef UNKNOWN 55936460Sbostic#define UNKNOWN "su" 5601043Sbill 5611043Sbillchar * 56236647Skarelsstypeof(ttyid) 56336647Skarels char *ttyid; 5641043Sbill{ 56536460Sbostic struct ttyent *t; 5661043Sbill 56736647Skarels return(ttyid && (t = getttynam(ttyid)) ? t->ty_type : UNKNOWN); 5681043Sbill} 5696005Swnj 5706005Swnjgetstr(buf, cnt, err) 57136460Sbostic char *buf, *err; 5726005Swnj int cnt; 5736005Swnj{ 57436460Sbostic char ch; 5756005Swnj 5766005Swnj do { 57736460Sbostic if (read(0, &ch, sizeof(ch)) != sizeof(ch)) 5786005Swnj exit(1); 5796005Swnj if (--cnt < 0) { 58036460Sbostic fprintf(stderr, "%s too long\r\n", err); 58136460Sbostic sleepexit(1); 5826005Swnj } 58336460Sbostic *buf++ = ch; 58436460Sbostic } while (ch); 5856005Swnj} 5866329Swnj 58736460Sbosticsleepexit(eval) 58836460Sbostic int eval; 58926862Smckusick{ 59036460Sbostic sleep((u_int)5); 59136460Sbostic exit(eval); 59226862Smckusick} 593