#
/*
 * getty -- adapt to terminal speed on dialup, and call login
 * getty lnid [tname]
 */

/*
 * tty flags
 */
#define	HUPCL 01
#define	XTABS	02
#define	LCASE	04
#define	ECHO	010
#define	CRMOD	020
#define	RAW	040
#define	ODDP	0100
#define	EVENP	0200
#define	ANYP	0300

/*
 * Delay algorithms
 */
#define	CR1	010000
#define	CR2	020000
#define	CR3	030000
#define	NL1	000400
#define	NL2	001000
#define	NL3	001400
#define	TAB1	002000
#define	TAB2	004000
#define	TAB3	006000
#define	FF1	040000

#define	ERASE	'#'
#define	KILL	'@'

/*
 * speeds
 */
#define	B110	3
#define	B150	5
#define	B300	7
#define	B1200	9

#define	SIGINT	2
#define	SIGQIT	3

#define	CHNGD	('t'<<8)|01	/* change discipline ioctl command */

struct	sgtty {
	char	sgispd, sgospd;
	char	sgerase, sgkill;
	int	sgflag;
} tmode;

struct	tab {
	int	tname;		/* this table name */
	int	nname;		/* successor table name */
	int	iflags;		/* initial flags */
	int	fflags;		/* final flags */
	int	ispeed;		/* input speed */
	int	ospeed;		/* output speed */
	char	*message;	/* login message */
} itab[] {

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

	'0', 1,
	ANYP+RAW+NL1+CR1, ANYP+ECHO+XTABS+CR1,
	B300, B300,
	"\n\r\033;\007login: ",

	1, 2,
	ANYP+RAW+NL1+CR1, EVENP+ECHO+FF1+CR2+TAB1+NL1,
	B150, B150,
	"\n\r\033:\006\006\017login: ",

	2, '0',
	ANYP+RAW+NL1+CR1, ANYP+ECHO+CRMOD+XTABS+LCASE+CR1,
	B110, B110,
	"\n\rlogin: ",

/* table '-' -- Console TTY 110 */
	'-', '-',
	ANYP+RAW+NL1+CR1, ANYP+ECHO+CRMOD+XTABS+LCASE+CR1,
	B110, B110,
	"\n\rlogin: ",

/* table '1' -- 150 */
	'1', '1',
	ANYP+RAW+NL1+CR1, EVENP+ECHO+FF1+CR2+TAB1+NL1,
	B150, B150,
	"\n\r\033:\006\006\017login: ",

/* table '2' -- 1200 */
	'2', '2',
	ANYP+RAW+NL1+CR1, ANYP+XTABS+ECHO+CRMOD+FF1,
	B1200, B1200,
	"\n\r\033;login: ",
/* table '4' -- 1200 */
	'4', '4',
	RAW+NL1+CR1, EVENP+NL1,
	B1200, B1200,
	"\n\r;login: ",
};

#define	NITAB	sizeof itab/sizeof itab[0]

char	name[16];
int	crmod;
int	upper;
int	lower;
int	stin;
int	stout;
char	*line;
char	*CTTY	"/dev/ln00";

main(argc, argv)
char **argv;
{
	register struct tab *tabp;
	register tname;
	register i;
	int discp;

/*
	signal(SIGINT, 1);
	signal(SIGQIT, 0);
*/
	stout = -1;
	if (argc == 1) {	/* error */
		puts(" lid [tname]\n");
		sleep(20);
		exit(1);
	}
	line = "/dev/\0\0\0\0";
	for(i=0;(line[i+5] = argv[1][i]); i++);
	chown(line,0);
	chmod(line,0622);
	discp = 0;
	switch(argc){
		case 2:	/*getty default*/
			tname = '0';
			break;
		case 4: /* line discipline argument */
			discp = (*argv[3] - '0')<<8;
		default:	/*tname argument*/
			tname = *argv[2];
	}

	switch(stin = open(line, -1)) {
		case -1:
			break;
		default:
			if (ioctl(stin, CHNGD, &discp) >= 0) {
				close(stin);
				break;
			}
			close(stin);
			puts(": illegal discipline change ");
			puts(line);
			puts("\n");
			sleep(20);
			exit(1);
	}

	switch(stin=open(line,2)){
		case -1:
			puts(": could not open ");
			puts(line);
			puts("\n");
			sleep(20);
			exit(1);
		default:	/*input file already there*/
			close(stin);
		case 0:	/*no file descriptors before this*/
			stout = dup(0);
			if(stout != 1) close(stout); /*is output file opened?*/
			break;	/*output file created*/
	}
	for (;;) {
		for(tabp = itab; tabp < &itab[NITAB]; tabp++)
			if(tabp->tname == tname)
				break;
		if(tabp >= &itab[NITAB])
			tabp = itab;
		tmode.sgispd = tabp->ispeed;
		tmode.sgospd = tabp->ospeed;
		tmode.sgflag = tabp->iflags;
		tmode.sgispd = tabp->ispeed;
		tmode.sgospd = tabp->ospeed;
		stty(0, &tmode);
		puts(tabp->message);
		stty(0, &tmode);
		if(getname()) {
			tmode.sgerase = ERASE;
			tmode.sgkill = KILL;
			tmode.sgflag = tabp->fflags;
			if(crmod)
				tmode.sgflag =| CRMOD;
			if(upper)
				tmode.sgflag =| LCASE;
			if(lower)
				tmode.sgflag =& ~LCASE;
			stty(0, &tmode);
			execl("/bin/login", "login", name, 0);
			exit(1);
		}
		tname = tabp->nname;
	}
}

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

	crmod = 0;
	upper = 0;
	lower = 0;
	np = name;
	do {
		if (read(0, &cs, 1) <= 0)
			exit(0);
		if ((c = cs&0177) == 0)
			return(0);
		write(1, &cs, 1);
		if (c>='a' && c <='z')
			lower++;
		else if (c>='A' && c<='Z') {
			upper++;
			c =+ 'a'-'A';
		} else if (c==ERASE) {
			if (np > name)
				np--;
			continue;
		} else if (c==KILL) {
			np = name;
			continue;
		}
		*np++ = c;
	} while (c!='\n' && c!='\r' && np <= &name[16]);
	*--np = 0;
	if (c == '\r') {
		write(1, "\n", 1);
		crmod++;
	} else
		write(1, "\r", 1);
	return(1);
}

puts(as)
char *as;
{
	register i;
	if(stout == -1){	/*error condition case only*/
		stout = open(CTTY,1);
		write(stout,"GETTY",5);
	}
	for(i=0;as[i];i++);
	write(stout,as,i);
}
