SysIII/usr/src/cmd/getty.c

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

/*
 * getty -- adapt to terminal speed on dialup, and call login
 *	
 *	invoked as "/etc/getty name type delay" where
 *		name :  character  string (length <= 14) e.g. tty3
 *		type :  single character
 *		delay : number of seconds to complete getty before
 *			sudden death and hang-up. A non-zero value
 *			implies a dial-up line
 */

#include <termio.h>
#include <signal.h>
#include <fcntl.h>
#include <utmp.h>

#define XONLY '!'
#define TTYPE *argv[2-argp]
#define TDELAY argv[3-argp]
#define NARGS argc+argp

#define UTMP "/etc/utmp"
#define WTMP "/usr/adm/wtmp"

struct termio tmode;

struct	tab {
	char	tname;		/* this table name */
	char	nname;		/* successor table name */
	unsigned short	iiflag;		/* initial input mode */
	unsigned short	ioflag;		/* initial output mode */
	unsigned short	icflag;		/* initial control mode */
	unsigned short	ilflag;		/* initial local mode */
	unsigned short	fiflag;		/* final input mode */
	unsigned short	foflag;		/* final output mode */
	unsigned short	fcflag;		/* final control mode */
	unsigned short	flflag;		/* final local mode */
	char	line;			/* line discipline */
	char	*message;	/* login message */
} itab[] = {

/* table '0'-1-2-'3' 300,150,110,1200 */

	'0', 1,
	0, ONLRET|CR1|OPOST,
	B300|CREAD|CS8, ECHOK,
	BRKINT|IGNPAR|ISTRIP|IXON|IXANY, ONLRET|CR1|OPOST,
	B300|CREAD|CS7|PARENB, ECHO|ECHOK|ICANON|ISIG,
	0,
	"\n\r\033;\007login: ",

	1, 2,
	0, ONLRET|CR1|OPOST,
	B150|CREAD|CS8, ECHOK,
	BRKINT|IGNPAR|ISTRIP|IXON|IXANY|INPCK, ONLRET|CR1|OPOST|TAB1|FFDLY,
	B150|CREAD|CS7|PARENB, ECHO|ECHOK|ICANON|ISIG,
	0,
	"\n\r\033:\006\006\017login: ",

	2, '3',
	0, ONLRET|CR1|OPOST,
	B110|CREAD|CS8|CSTOPB, ECHOK,
	BRKINT|IGNPAR|ISTRIP|IXON|IXANY|ICRNL|IUCLC, ONLCR|CR1|OPOST|OLCUC|TAB3,
	B110|CREAD|CS7|PARENB|CSTOPB, ECHO|ECHOK|ICANON|ISIG|XCASE,
	0,
	"\n\rlogin: ",

/* table '-' -- Console TTY 110 */
	'-', '-',
	0, ONLRET|CR1|OPOST,
	B110|CREAD|CS8|CSTOPB, ECHOK,
	BRKINT|IGNPAR|ISTRIP|IXON|IXANY|ICRNL|IUCLC, ONLCR|CR1|OPOST|OLCUC|TAB3,
	B110|CREAD|CS7|PARENB|CSTOPB, ECHO|ECHOK|ICANON|ISIG|XCASE,
	0,
	"\n\rlogin: ",

/* table '1' -- 150 */
	'1', '1',
	0, ONLRET|CR1|OPOST,
	B150|CREAD|CS8, ECHOK,
	BRKINT|IGNPAR|ISTRIP|IXON|IXANY|INPCK, ONLRET|CR1|OPOST|TAB1|FFDLY,
	B150|CREAD|CS7|PARENB, ECHO|ECHOK|ICANON|ISIG,
	0,
	"\n\r\033:\006\006\017login: ",

/* table '2' -- 2400 */
	'2', '2',
	0, ONLRET|CR1|OPOST,
	B2400|CREAD|CS8, ECHOK,
	BRKINT|IGNPAR|ISTRIP|IXON|IXANY|ICRNL, ONLCR|OPOST|TAB3,
	B2400|CREAD|CS7|PARENB, ECHO|ECHOK|ICANON|ISIG,
	0,
	"\n\rlogin: ",

/* table '3'-'0' -- 1200,300 */
	'3', '0',
	0, ONLRET|CR1|OPOST,
	B1200|CREAD|CS8, ECHOK,
	BRKINT|IGNPAR|ISTRIP|IXON|IXANY|ICRNL, ONLCR|OPOST|TAB3,
	B1200|CREAD|CS7|PARENB, ECHO|ECHOK|ICANON|ISIG,
	0,
	"\n\rlogin: ",

/* table '4' -- Console Decwriter */
	'4', '4',
	BRKINT|IGNPAR|ISTRIP|IXON|IXANY|ICRNL, ONLCR|OPOST|TAB3,
	B300|CREAD|CS7|PARENB, ECHO|ECHOK|ICANON|ISIG,
	BRKINT|IGNPAR|ISTRIP|IXON|IXANY|ICRNL, ONLCR|OPOST|TAB3,
	B300|CREAD|CS7|PARENB, ECHO|ECHOK|ICANON|ISIG,
	0,
	"\n\rlogin: ",

/* table '5' -- 9600 */
	'5', '5',
	0, ONLRET|CR1|OPOST,
	B9600|CREAD|CS8, ECHOK,
	BRKINT|IGNPAR|ISTRIP|IXON|IXANY|ICRNL, ONLCR|OPOST|TAB3,
	B9600|CREAD|CS7|PARENB, ECHO|ECHOK|ICANON|ISIG,
	0,
	"\n\rlogin: ",

/* table '6' -- 4800/9600 -- tektronix 4014 */
	'6', 7,
	0, ONLRET|FFDLY|OPOST,
	B4800|CREAD|CS8, ECHOK,
	BRKINT|IGNPAR|ISTRIP|IXON|IXANY|ICRNL, ONLCR|OPOST|FFDLY,
	B4800|CREAD|CS7|PARENB, ECHO|ECHOK|ICANON|ISIG,
	0,
	"\033\014login: ",

	7, '6',
	0, ONLRET|FFDLY|OPOST,
	B9600|CREAD|CS8, ECHOK,
	BRKINT|IGNPAR|ISTRIP|IXON|IXANY|ICRNL, ONLCR|OPOST|FFDLY,
	B9600|CREAD|CS7|PARENB, ECHO|ECHOK|ICANON|ISIG,
	0,
	"\033\014login: ",

/* table '7' -- 4800 */
	'7', '7',
	0, ONLRET|CR1|OPOST,
	B4800|CREAD|CS8, ECHOK,
	BRKINT|IGNPAR|ISTRIP|IXON|IXANY|ICRNL, ONLCR|OPOST|TAB3,
	B4800|CREAD|CS7|PARENB, ECHO|ECHOK|ICANON|ISIG,
	0,
	"\n\rlogin: ",

};

#define	NITAB	sizeof itab/sizeof itab[0]

char	name[16];
int	crmod;
int	upper;
int	lower;
int	bailout();
int	hupclr();
int	stin;	/* standard input file */
int	stout;	/* standard output file */
int	sterr;	/* diagnostic output file */
char	*ttyname();
char	*strrchr();
char	rline[20]="/dev/";
char	*line;

char partab[] = {
	0001,0201,0201,0001,0201,0001,0001,0201,
	0202,0004,0003,0205,0005,0206,0201,0001,
	0201,0001,0001,0201,0001,0201,0201,0001,
	0001,0201,0201,0001,0201,0001,0001,0201,
	0200,0000,0000,0200,0000,0200,0200,0000,
	0000,0200,0200,0000,0200,0000,0000,0200,
	0000,0200,0200,0000,0200,0000,0000,0200,
	0200,0000,0000,0200,0000,0200,0200,0000,
	0200,0000,0000,0200,0000,0200,0200,0000,
	0000,0200,0200,0000,0200,0000,0000,0200,
	0000,0200,0200,0000,0200,0000,0000,0200,
	0200,0000,0000,0200,0000,0200,0200,0000,
	0000,0200,0200,0000,0200,0000,0000,0200,
	0200,0000,0000,0200,0000,0200,0200,0000,
	0200,0000,0000,0200,0000,0200,0200,0000,
	0000,0200,0200,0000,0200,0000,0000,0201
};

struct tab *tabp;

main(argc, argv)
char **argv;
{
	int argp=0;
	char tname;

	signal (SIGALRM, bailout);
	signal (SIGHUP, hupclr);
	stout = -1;

	if(isatty(0))
	{
		line=ttyname(0);
		argp++;
	}
	else
	{
		close(0);
		if(argc==1)
			err(300);
		line=rline;
		strcat (line, argv[1]);
	}

/* updates to wtmp etc. */
	rmut();

/* If the term type arg is special, exit only,
   this is so you can update utmp without spawning 
   an open line
*/
	if(TTYPE == XONLY) hangup(line, (NARGS>3 ? atoi (TDELAY) : 2));

/* check for existence of line */

	if(access(line,0) != 0)	err(300);
	chown(line,0);
	chmod(line,0622);


	switch(stin=open(line,O_RDWR)){
		case -1:
			err(300);
		case 0:	/*no file descriptors before this*/
			break;
		default:
			close(stin);
	}

	close(1);
	close(2);
	stout=dup(0);
	sterr=dup(0);

	/* get terminal class from second argument */
	tname = (NARGS > 2 ? TTYPE : '0');

	/* set alarm from third argument; zero implies no hangup;
		non-zero: seconds to complete before hangup (typically 60) */
	alarm (NARGS>3 ? atoi (TDELAY) : 0);

	for (;;) {
		for(tabp = itab; tabp < &itab[NITAB]; tabp++)
			if(tabp->tname == tname)
				break;
		if(tabp >= &itab[NITAB])
			tabp = itab;
		tmode.c_iflag=tabp->iiflag;
		tmode.c_oflag=tabp->ioflag;
		tmode.c_cflag=tabp->icflag;
		tmode.c_lflag=tabp->ilflag;
		tmode.c_line = tabp->line;
		tmode.c_cc[VINTR] = CINTR;
		tmode.c_cc[VQUIT] = CQUIT;
		tmode.c_cc[VERASE] = CERASE;
		tmode.c_cc[VKILL] = CKILL;
		tmode.c_cc[VMIN] = 1;
		tmode.c_cc[VTIME] = 1;
		ioctl(0, TCSETAF, &tmode);
		puts(tabp->message);
		if(getname()) {
			tmode.c_iflag=tabp->fiflag;
			tmode.c_oflag=tabp->foflag;
			tmode.c_cflag=tabp->fcflag;
			tmode.c_lflag=tabp->flflag;
			tmode.c_cc[VINTR] = CINTR;
			tmode.c_cc[VQUIT] = CQUIT;
			tmode.c_cc[VERASE] = CERASE;
			tmode.c_cc[VKILL] = CKILL;
			tmode.c_cc[VEOF] = CEOF;
			tmode.c_cc[VEOL] = CNUL;
			if(crmod) {
				tmode.c_iflag |= ICRNL;
				tmode.c_oflag |= ONLCR;
				tmode.c_oflag &= ~ONLRET;
				if (tmode.c_oflag&CR2)
					tmode.c_oflag |= ONOCR;
			}
			if(upper) {
				tmode.c_iflag |= IUCLC;
				tmode.c_oflag |= OLCUC;
				tmode.c_lflag |= XCASE;
			}
			if(lower) {
				tmode.c_iflag &= ~IUCLC;
				tmode.c_oflag &= ~OLCUC;
				tmode.c_lflag &= ~XCASE;
			}
			ioctl(0, TCSETAF, &tmode);
			if ((tabp->ilflag&ECHO) == 0)
				putchr('\n');
			execl("/etc/login","login",name,(NARGS>3?TDELAY:"60"),0);
			err(300);
		}
		tname = tabp->nname;
	}
}

getname()
{
	register char *np;
	register c;
	char cs;

	crmod = 0;
	upper = 0;
	lower = 0;
	np = name;
	for (;;) {
		if (read(0, &cs, 1) <= 0)
			err(10);
		if ((c = cs&0177) == 0)
			return(0);
		if (c==CEOF)
			err(6);
		if (c=='\r' || c=='\n' || np >= &name[16])
			break;
		if ((tabp->ilflag&ECHO) == 0)
			putchr(c);
		if (c>='a' && c <='z')
			lower++;
		else if (c>='A' && c<='Z') {
			upper++;
			c += 'a'-'A';
		} else if (c==CERASE) {
			if (np > name)
				np--;
			continue;
		} else if (c==CKILL) {
			putchr('\r');
			putchr('\n');
			np = name;
			continue;
		} else if(c == ' ')
			c = '_';
		*np++ = c;
	}
	*np = 0;
	if (c == '\r')
		crmod++;
	return(1);
}

puts(as)
char *as;
{
	register char *s;
	if (stout == -1)  /* error case only */
		err(300);

	s = as;
	while (*s)
		putchr(*s++);
}

putchr(cc)
{
	char c;
	c = cc;
	c |= partab[c&0177] & 0200;
	write(stout, &c, 1);
}
hangup(line, delay)
char *line;
int delay;
{
	if(delay == 0) exit(0);
	signal(SIGHUP, SIG_DFL);
	alarm(delay);
	open(line, O_RDWR);
	bailout();
}
bailout ()
{
		tmode.c_cflag = B0|HUPCL;
		ioctl(0, TCSETA, &tmode);
		exit(1);
}
utscan(utf,lnam)
register utf;
char *lnam;
{
	register i;
	struct utmp wtmp;

	lseek(utf, (long)0, 0);
	while(read(utf, (char *)&wtmp, sizeof(wtmp)) == sizeof(wtmp))
	{
		for(i=0; i<8; i++)
			if(wtmp.ut_line[i] != lnam[i])
				goto contin;
		lseek(utf, -(long)sizeof(wtmp), 1);
		return(1);
		contin:;
	}
	return(0);
}

rmut()
{
	int utf, i;
	struct utmp wtmp;
	char *lnam;

	lnam = strrchr(line,'/') + 1;

	for(i=0; i<8; i++)
	{
		wtmp.ut_name[i] = '\0';
		wtmp.ut_line[i] = lnam[i];
	}
	time(&wtmp.ut_time);

	utf = open(UTMP, O_RDWR|O_CREAT, 0644);
	if(utscan(utf,lnam) != 0)
		write(utf, &wtmp, sizeof(wtmp));
	else
	{
		fcntl(utf, F_SETFL, fcntl(utf, F_GETFL, 0) | O_APPEND);
		write(utf, &wtmp, sizeof(wtmp));
	}

	close(utf);
	utf = open(WTMP, O_WRONLY|O_CREAT|O_APPEND);
	write(utf, &wtmp, sizeof(wtmp));
	close(utf);
}
err(secs)
int secs;
{
	sleep(secs);
	exit(9);
}
hupclr(){
	err(0);
}