1BSD/s8/login.c

Compare this file to the similar file:
Show the results in this format:

#
/*
 * login [ name ]
 */

struct {
	char	name[8];
	char	tty;
	char	ifill;
	int	time[2];
	int	uuid;
} utmp, xtmp;

struct {
	int	speeds;
	char	erase, kill;
	int	tflags;
} ttyb;

struct {
	int	junk[5];
	int	size;
	int	more[12];
} statb;

extern	htmp;
struct {
	int	l_tty;
	int	l_time[2];
} last;

char mailfile[] "/usr/mail/xxxxxxxx";
char kickoff[]	"/etc/kickoff";
char lastlog[]	"/usr/adm/lastlog/XXXX";

char	*ttyx;

#define	ECHO	010

main(argc, argv)
char **argv;
{
	char pbuf[128];
	register char *namep, *np, *mp;
	int quiet;
	char pwbuf[9], *cp, *ll;
	int t, sflags, f, c, uid, gid, badname;

	alarm(300); /* 5 minutes to log in */
	signal(3, 1);
	signal(2, 1);
	nice(-2);
	ttyx = "/dev/ttyx";
	if ((utmp.tty=ttyn(0)) == 'x') {
		write(1, "Sorry.\n", 7);
		exit();
	}
	ttyx[8] = utmp.tty;
    loop:
	badname = 0;
	namep = utmp.name;
	mp = &mailfile[10];
	if (argc>1) {
		np = argv[1];
		while (namep<utmp.name+8 && *np) {
			*mp++ = *np;
			*namep++ = *np++;
		}
		argc = 0;
	} else {
		write(1, "Name: ", 7);
		while ((c = getchar()) != '\n') {
			if (c <= 0)
				exit();
			if (namep < utmp.name+8) {
				*mp++ = c;
				*namep++ = c;
			}
		}
		if(namep == utmp.name)
			goto loop;
	}
	while (namep < utmp.name+8)
		*namep++ = ' ';
	*mp = '\0';
	if (getpwentry(utmp.name, pbuf, "/etc/passwdf")) {
		badname++;
		goto askpw;
	}
	mp = np = colon(pbuf);
	if (*np!=':') {
	   askpw:
		gtty(0, &ttyb);
		sflags = ttyb.tflags;
		ttyb.tflags =& ~ ECHO;
		stty(0, &ttyb);
		write(1, "Password: ", 10);
		namep = pwbuf;
		while ((c=getchar()) != '\n') {
			if (c <= 0)
				exit();
			if (namep<pwbuf+8)
				*namep++ = c;
		}
		*namep++ = '\0';
		ttyb.tflags = sflags;
		stty(0, &ttyb);
		write(1, "\n", 1);
		namep = crypt(pwbuf);
		while (*namep++ == *np++);
		if (*--namep== '\0' && *--np ==':')
			goto good;
		namep = crypt(pwbuf);
		np = mp;
		while (*namep++ == *np++);
		if (*--namep!= '\0' || *--np !=':' || badname)
			goto bad;
good:	;
	}
	if (getpwentry(utmp.name, pbuf, "/etc/passwd"))
		goto bad;
	np = colon(pbuf);
	np = colon(np);
	uid = 0;
	while (*np != ':')
		uid = uid*10 + *np++ - '0';
	np++;
	ll = &lastlog[17];
	gid = 0;
	while (*np != ':') {
		*ll++ = *np;
		gid = gid*10 + *np++ - '0';
	}
	*ll = 0;
	np++;
	np = colon(np);
	namep = np;
	np = colon(np);
	time(utmp.time);
	utmp.uuid = (gid<<8)|uid;
	if ((f = open("/etc/utmp", 1)) >= 0) {
		t = utmp.tty;
		seek(f, (t&0177)*16, 0);
		write(f, &utmp, 16);
		close(f);
	}
	if ((f = open("/usr/adm/wtmp", 1)) >= 0) {
		seek(f, 0, 2);
		write(f, &utmp, 16);
		close(f);
	}
	f = gid<<8 | uid;
	if (f == 0)
		if (utmp.tty!='5' && utmp.tty!='8' && utmp.tty!='t')
			goto bad;
	if ((f=open(lastlog, 2)) < 0) {
		if ((f=creat(lastlog, 0600)) < 0)
			goto cont;
		close(f);
		if ((f=open(lastlog, 2)) < 0)
			goto cont;
	}
	seek(f, uid*6, 0);
	if (read(f, &last.l_tty, 6) == 6) {
		if (last.l_time[0]) {
			ll = ctime(last.l_time);
			c = ' ';
			if (last.l_tty < 033) {
				c = last.l_tty - 1 + 'a';
				last.l_tty = '^';
			}
		printf("Last login: %.16s on tty%c%c\n", ll, last.l_tty, c);
		}
	}
	seek(f, uid*6, 0);
	write(f, &utmp.tty, 6);
	close(f);
    cont:
	quiet = 0;
	if(utmp.name[0] >= 'A' && utmp.name[0] <= 'Z')
		quiet++;
	if(!quiet)
	if ((f = open("/etc/motd", 0)) >= 0) {
		while ((t=read(f, &xtmp, sizeof xtmp)) > 0)
			write(1, &xtmp, t);
		close(f);
	}
	if(!quiet)
	if(stat(mailfile, &statb) >= 0 && statb.size)
		write(1, "You have mail.\n", 15);
	chown(ttyx, gid<<8|uid);
	hsetuid(gid << 8 | uid);
	hsethome(namep);
	hsettype(typeof(utmp.tty));
	hput(utmp.tty);
	setuid(gid<<8 | uid);
	f = 0;
	if (fork() == 0) {
		execl(kickoff, "kickoff", 0);
		exit();
	} else {
		if (gid || uid) {
			wait(&f);
			if (f>>8 != 0) {
				printf("priority too low to log in\n");
				exit();
			}
		}
	}
	for (;;) {
		if (*namep == '\0')
			break;
		cp = namep++;
		for (; *namep != '/' && *namep != '\0'; namep++);
		if (*namep == '/')
			*namep++ = '\0';
		if (chdir(cp)<0) {
			write(1, "No directory\n", 13);
			exit();
		}
		alarm(0);
		if(!quiet)
		if ((f = open(".reminder", 0)) >= 0) {
			while ((t=read(f, &utmp, sizeof utmp)) > 0)
				write(1, &utmp, t);
			close(f);
		}
	}
	nice(0);
	if (*np == '\0')
		np = "/bin/sh";
	if (stat(".start_up", &statb) >= 0 && statb.size)
		if (fork() == 0) {
			execl("/bin/sh", "-", ".start_up", 0);
			exit();
		} else
			wait(&f);
	execl(np, "-", 0);
	write(1, "No shell.\n", 9);
	exit();
bad:
	write(1, "Login incorrect.\n", 17);
	goto loop;
}

getpwentry(name, buf, fname)
char *name, *buf;
{
	extern fin;
	int fi, r, c;
	register char *gnp, *rnp;

	fi = fin;
	r = 1;
	if((fin = open(fname, 0)) < 0)
		goto ret;
loop:
	gnp = name;
	rnp = buf;
	while((c=getchar()) != '\n') {
		if(c <= 0)
			goto ret;
		*rnp++ = c;
	}
	*rnp++ = '\0';
	rnp = buf;
	while (*gnp++ == *rnp++);
	if ((*--gnp!=' ' && gnp<name+8) || *--rnp!=':')
		goto loop;
	r = 0;
ret:
	close(fin);
	fin = 0;
	(&fin)[1] = 0;
	(&fin)[2] = 0;
	return(r);
}

colon(p)
char *p;
{
	register char *rp;

	rp = p;
	while (*rp != ':') {
		if (*rp++ == '\0') {
			write(1, "Bad /etc/passwd\n", 16);
			exit();
		}
	}
	*rp++ = '\0';
	return(rp);
}