[comp.sources.misc] v06i034: gettyfe - XENIX 286/386 getty front end

allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc) (02/04/89)

Posting-number: Volume 6, Issue 34
Submitted-by: wht@tridom.UUCP (Warren Tucker)
Archive-name: gettyfe

Here is yet-another-getty-front-end-for-autobauding, this
one for SCO XENIX 286/386.  It is likely to be portable
to future releases.  The source has the README built in.

---- Cut Here and unpack ----
#!/bin/sh
# shar:	Shell Archiver  (v1.22)
#
#	Run the following text with /bin/sh to create:
#	  gettyfe.c
#
if test -f gettyfe.c; then echo "File gettyfe.c exists"; else
echo "x - extracting gettyfe.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > gettyfe.c &&
X/* CHK=0x71AC */
X/* vi: set tabstop=4 shiftwidth=4: */
X/*+-------------------------------------------------------------------------
X	gettyfe.c - front end to SCO XENIX getty
X	by Warren Tucker ...!gatech!{emory,kd4nc}!wht
X
XAs exec'd by init, getty gets:
Xargv[0] = "-"
Xargv[1] = "ttyxx"
Xargv[2] = "?" where ? is gettydefs character from /etc/ttys
X
XThis program becomes /etc/getty, the supplied getty being renamed
X/etc/real-getty.  My sole dial-in line is tty2D (your mileage may vary).
XThus, if gettyfe sees that it is invoked for a tty other than tty2D,
Xit immediately chains to "real-getty".
X
Xgettyfe counts on the following two gettydefs entries:
X
X2 # B1200 HUPCL OPOST CR0 ECHOE NL1 #
X	B1200 CS8 SANE HUPCL TAB3 ECHOE IXANY #@\r\nlogin: # 3
X
X3 # B2400  HUPCL OPOST CR0 ECHOE NL1 #
X	B2400 CS8 SANE HUPCL TAB3 ECHOE IXANY #@\r\nlogin: # 2
X
XThe port is opened and the file descriptor is dup(2)'d three times.
XThis means that fd 0 (stdin), 1 (stdout) and 2 (stderr) is established
Xas well as fd 3, the use of which is described below.
X
XThe port is set up for 2400 baud, NL mapping to CR and otherwise very
Xraw.  The caller is prompted to set to 8-N-1 and to press ENTER.  If the
Xcaller is calling at 2400 baud, if he/she/it presses either CR or NL
X(via INLCR), then gettyfe executes "real-getty" such that it will prompt
Xfor a login at 2400 baud.  Otherwise, gettyfe changes the baud rate to
X1200, repeats the prompt and so on until CR or NL is found at the proper
Xbaud rate.
X
XWhen a chain to "real-getty" happens after the tty has been opened, fds
X0-2 are closed since getty expects to be able to open them.  fd 3 is
Xleft open so that the tty will not be closed.  I'm not sure if this
Xis necessary or not, or whether or not the problem can be fixed by
Xomitting HUPCL, but I didn't find out.
X
XFinally, an alarm(30) call gives the caller 30 seconds to start a getty.
X
XNotes for variations:
Xwith port set at 2400 baud, a 1200 baud 8-N CR appears as 0xE6
Xwith port set at 1200 baud, a 2400 baud 8-N CR appears as 0xFE
X
XTo compile for XENIX 286 or 386:
X% cc -O -i -s gettyfe.c -o gettyfe
X
XIt probably will work under BSD4 if you hacked the code to replace
Xnap calls with select() calls of equivalent (I have put my copy in here)
X
X--------------------------------------------------------------------------*/
X/*+:EDITS:*/
X/*:01-30-1989-20:08-wht-creation */
X
X#include <fcntl.h>
X#include <signal.h>
X#include <termio.h>
X
Xint fdtty;
Xstruct termio tty_termio;
X
X#if defined(DEBUG)
X#include <stdio.h>
X/*+-------------------------------------------------------------------------
X	debugit(cbaud,user_char)
X--------------------------------------------------------------------------*/
Xdebugit(cbaud,user_char)
Xint cbaud;
Xunsigned char user_char;
X{
XFILE *fp = fopen("/gettyfe.log","a");
X	fprintf(fp,"baud %d user_char %02x\n",(cbaud == B2400) ? 2400 : 1200,
X		user_char);
X	fclose(fp);
X}	/* end of debugit */
X#endif
X
X#if defined(BSD4)
X/*+-------------------------------------------------------------------------
X	nap(msec) - BSD4 nap(); needs <time.h>
X--------------------------------------------------------------------------*/
Xlong
Xnap(msec)
Xlong	msec;
X{
Xstruct timeval tp;
Xstruct timezone tzp;
Xu_long	start_sec;
Xlong	start_usec;
Xlong	target_usec;
Xlong	now_usec;
X
X	gettimeofday(&tp,&tzp);
X	start_sec = tp.tv_sec;
X	start_usec = tp.tv_usec;
X	target_usec = start_usec + (msec * 1000L);
X	now_usec = start_usec;
X	while(now_usec < target_usec)
X	{
X		gettimeofday(&tp,&tzp);
X		now_usec = ((tp.tv_sec - start_sec) * 1000000L) + tp.tv_usec;
X	}
X	return((now_usec - start_usec) / 1000L);
X}	/* end of nap */
X#endif
X
X/*+-------------------------------------------------------------------------
X	bye(code)
X--------------------------------------------------------------------------*/
Xvoid
Xbye(code)
Xint code;
X{
X#if defined(DEBUG)
XFILE *fp = fopen("/gettyfe.log","a");
X	fprintf(fp,"exit(%d)\n",code);
X	fclose(fp);
X#endif
X	exit(code);
X}	/* end of bye */
X
X/*+-------------------------------------------------------------------------
X	login_timeout()
X--------------------------------------------------------------------------*/
Xvoid
Xlogin_timeout()
X{
X	bye(13);
X}	/* end of login_timeout */
X
X/*+-------------------------------------------------------------------------
X	setline(cbaud)
X--------------------------------------------------------------------------*/
Xsetline(cbaud)
Xint cbaud;
X{
X	tty_termio.c_cflag &= ~CBAUD;
X	tty_termio.c_cflag |= cbaud;
X	ioctl(fdtty,TCSETA,(char *)&tty_termio);
X	nap(100L);
X	ioctl(fdtty,TCFLSH,0);
X}	/* end of setline */
X
X/*+-------------------------------------------------------------------------
X	main(argc,argv,envp)
X--------------------------------------------------------------------------*/
Xmain(argc,argv,envp)
Xint		argc;
Xchar	**argv;
Xchar	**envp;
X{
Xint cbaud;
Xunsigned char user_char;
Xchar ttyname[64];
Xchar *prompt = "\r\nUse 8-N-1 and press ENTER: ";
Xint promptlen = strlen(prompt);
X
X	if(strcmp(argv[1],"tty2D"))
X	{
X		execv("/etc/real-getty",argv);
X		bye(1);
X	}
X
X	strcpy(ttyname,"/dev/");
X	strcat(ttyname,argv[1]);
X
X	if((fdtty = open(ttyname,O_RDWR)) < 0)		/* open stdin */
X		bye(2);
X
X	dup(0);			/* create stdout */
X	dup(0);			/* create stderr */
X	dup(0);			/* create an extra we will not close on exec */
X
X	tty_termio.c_iflag = IGNPAR | IGNBRK | INLCR;
X	tty_termio.c_oflag = 0;
X	tty_termio.c_cflag = CREAD | HUPCL | CS8 | CSTOPB | B2400;
X	tty_termio.c_lflag = 0;
X	tty_termio.c_cc[VMIN]  = 1;
X	tty_termio.c_cc[VTIME] = 0;
X	ioctl(fdtty,TCSETA,(char *)&tty_termio);
X
X	nap(1750L);		/* allow for other end carrier detect */
X
X	signal(SIGALRM,login_timeout);
X	alarm(30);		/* 30 secs to finish this */
X
X	cbaud = B2400;
X
X	while(1)
X	{
X		write(1,prompt,promptlen);
X		read(0,&user_char,1);
X#if defined(DEBUG)
X		debugit(cbaud,user_char);
X#endif
X		switch(user_char)
X		{
X			case 0x0D:
X				close(0);	/* getty will re-open */
X				close(1);
X				close(2);	/* keep fd 3 open */
X				alarm(0);
X				execl("/etc/real-getty","-",argv[1],
X					(cbaud == B2400) ? "3" : "2",(char *)0);
X				bye(3);
X
X			default:
X				cbaud = (cbaud == B2400) ? B1200 : B2400;
X				setline(cbaud);
X		}
X	}
X	/*NOTREACHED*/
X
X}	/* end of main */
X
SHAR_EOF
chmod 0644 gettyfe.c || echo "restore of gettyfe.c fails"
fi
exit 0