home *** CD-ROM | disk | FTP | other *** search
- From decwrl!labrea!rutgers!ukma!cwjcc!hal!ncoast!allbery Sun Oct 30 15:07:27 PST 1988
- Article 697 of comp.sources.misc:
- Path: granite!decwrl!labrea!rutgers!ukma!cwjcc!hal!ncoast!allbery
- From: davev@spked.UUCP
- Newsgroups: comp.sources.misc
- Subject: v05i020: autobauding getty for System V (ported from 4BSD)
- Message-ID: <8810201858.AA06671@ucdavis.ucdavis.edu>
- Date: 28 Oct 88 03:15:05 GMT
- Sender: allbery@ncoast.UUCP
- Reply-To: davev@spked.UUCP
- Lines: 455
- Approved: allbery@ncoast.UUCP
-
- Posting-number: Volume 5, Issue 20
- Submitted-by: "A. Nonymous" <davev@spked.UUCP>
- Archive-name: autobaud
-
- [I consider these things black magic: it's too easy for the modem to pick
- up at the wrong spot or something and get the wrong bit pattern. Or so I
- believe....
-
- Various spots in the code are BSD-ish, others are System-V-ish. It probably
- won't work unmodified on anyone else's system. And some of the things in
- this code can only be called kluges. ++bsa]
-
- # This is a shell archive. Remove anything before this line, then
- # unpack it by saving it in a file and typing "sh file". (Files
- # unpacked will be owned by you and have default permissions.)
- #
- # This archive contains:
- # auto.c autolocal.h autobaud.8 README
-
- echo x - auto.c
- cat > "auto.c" << '//E*O*F auto.c//'
- /* autobaud.c - determine tty speed of standard input (for 4.3 BSD Unix)
- *
- * Autobaud reads standard input at 2400 baud. Assuming a carriage return
- * is typed, the bit pattern received is used to select and set the "true"
- * speed. This works for speeds of 300, 1200, 2400, and 9600 baud. In theory
- * 600 should also work, but empirically a 00 character is read and it doesn't.
- * Any other speed, or any character other than a carriage return, is likely
- * to give a wrong result.
- *
- * Autobaud is primarily intended as a replacement for getty(8), and as such
- * it also sets a few terminal parameters such as the kill character to
- * default values. However, it can also be run from a shell for testing.
- *
- * usage: autobaud [-l] [tty_name]
- *
- * -l sets "login" mode and execs login after the speed is set
- * tty_name specifies a device to autobaud (/dev/tty_name) instead of stdin
- *
- * Gregg Townsend
- * University of Arizona
- * April, 1987
- *
- * -------------------------------------------------------------
- *
- * David P. van De Kerk, U.S. Army Corps of Engineers,
- * Sacramento District. CESPK-ED-T-AMU.
- * ucdavis.ucdavis.edu!spked!davev
- *
- * Modified 10/09/88 to work on a Unisys 5000/80 computer,
- * running System 5 R 2. In a sense, this is a System 5 port,
- * although the program does NOT run on an NCR Tower running
- * System 5 release 1.
- *
- * Modified the recognition sequences for what was read on Sys V
- * Changed from sgtty to termio's tty ioctl structure.
- *
- * Added a bunk, but working, delay sequence, and used sockets on
- * those systems capable of using them. Note, while this should work
- * in theory on our system, which has NET-5000, it doesn't.
- *
- * Put the terminal type read from the getty defs in the environment
- *
- * Clear the screen before giving login banner, using the
- * environment's terminal type, as gotten from inittab.
- *
- * Note: Instead of reading inittab for the right stty parameters,
- * there is one fixed setting for everyone.
- *
- */
-
- #define PGMNAME "autobaud" /* program name (for diagnostics) */
- #define LOGIN "/bin/login" /* location of login program */
- #define ISSUE "/etc/issue" /* location of pre-login message */
- #define STRSIZ 100 /* string size for host and tty names */
-
- #include <signal.h>
- #include <curses.h>
- #include <stdio.h>
- #include <sys/types.h>
- #include <sys/file.h>
- /*
- #include <sys/termio.h>
- */
- #include <time.h>
- #include <malloc.h>
- #ifdef SOCKETS
- #include <NET-5000/sys/socket.h>
- #endif
-
- #include "autolocal.h"
-
- /* beware these definitions */
- #define TIOCHPCL (('t'<<8)|2)
- #define TIOCSETN TCSETA
- #define TIOCFLUSH TCFLSH
-
- char *sp[] = { "0", "50", "75", "110", "134", "150", "200", "300",
- "600", "1200", "1800", "2400", "4800", "9600", "EXTA", "EXTB"};
-
- int login = 0; /* set nonzero if to exec login */
- char tty_name[STRSIZ] = "/dev/"; /* buffer for explicit tty name */
- char hostname[STRSIZ]; /* buffer for hostname */
-
-
-
- /* main program */
- extern char **environ;
-
- main(argc,argv)
- int argc;
- char **argv;
- {
- struct termio ttyb;
- unsigned char c;
- char s;
- int zero = 0;
- char *dev_name; /* the name of the user's device */
- char alloc_dev [30]; /* space to put the above into */
-
- argv++; /* skip program name */
-
- if (*argv && !strcmp(*argv,"-l"))
- login++, argv++; /* if "-l", set login flag */
- dev_name = (char *) alloc_dev;
- dev_name = ttyname (0);
- if (*argv) {
- strcpy(tty_name+5,*argv++); /* if tty given, build name */
- close(0); /* close previous stdin */
- close(1); /* close previous stdout */
- close(2); /* close previous stderr */
- argv++; /* go past next entry, which is the getty def */
- /* if there's another entry, assume it's a desired term type */
- if (*argv) {
- char term_cmd [30];
- sprintf (term_cmd,"TERM=%s",*argv);
- putenv (term_cmd);
- }
-
- if (login) {
- nap(2000); /* hold DTR down for 2 sec */
- chown(tty_name,0,0); /* make root the owner */
- chmod(tty_name,0622); /* and set the protections */
- }
- if (open(tty_name,2) != 0) /* open once for stdin */
- abort(tty_name);
- dup(0); /* dup for stdout */
- dup(0); /* dup for stderr */
- }
-
- ioctl(0,TCGETA,&ttyb);
- ttyb.c_cflag = B2400 | CS8; /* sample line at 2400 baud, 8 bit */
- ttyb.c_cc[2] = ttyb.c_cc[3] = -1; /* no editing characters */
- ttyb.c_iflag = ttyb.c_iflag | ICRNL;
- ttyb.c_oflag = ttyb.c_oflag | ONLCR;
- ttyb.c_lflag = ttyb.c_lflag & (~ICANON);
- if (ioctl(0,TIOCSETN,&ttyb) <0) /* set tty parameters */
- abort("ioctl");
- s = 0;
- /* yes, it's gross, but it works. */
- system ("stty nl -lcase");
- while (!s) {
- nap(100); /* wait .1 sec for line quiet */
- ioctl(0,TIOCFLUSH,&zero); /* flush input & output */
- if (read(0,&c,1) != 1) /* read a character */
- {
- exit(1);
- }
- #ifdef DEBUG
- /* select baud rate based on pattern received */
- display (c);
- #endif
- /* select baud rate based on pattern received */
- if (c >= 0xF0)
- s = B9600;
- else switch (c) {
- case 0x80: s = B300; break;
- case 0x78: s = B600; break;
- case 0xE6: s = B1200; break;
- case 0x0D: s = B2400; break;
- case 0x8D: s = B2400; break;
- default: s = 0; break;
- }
- }
- nap(100); /* let slow input finish */
- ttyb.c_iflag = ttyb.c_iflag | ICRNL |IXON|IXANY;
- ttyb.c_oflag = ttyb.c_oflag | ONLCR;
- ttyb.c_cflag = (s & ~PARENB )| CS8; /* set speeds */
- ttyb.c_cc[0] = 'C' & 037; /* ^C = interrupt */
- ttyb.c_cc[2] = '\b'; /* \b for char correction */
- ttyb.c_cc[3] = 'U' & 037; /* ^U for line kill */
- ttyb.c_cc[4] = 'D' & 037; /* eof = ^D*/
- ttyb.c_lflag = ICANON | ECHO;/* any parity, -TABS, CR, ECHO*/
- ioctl(0,TIOCSETN,&ttyb); /* set parameters */
- ioctl(0,TIOCFLUSH,&zero); /* flush I/O */
- ioctl(0,TIOCHPCL,0); /* set hangup on last close */
- if (login) {
- sprintf (hostname,SITE_NAME); /* no gethostname call, so ... */
- initscr(); /* get the environment's idea of what kind of
- * terminal we're on */
- clear(); /* clear and home */
- echo(); /* add echo to user input */
- move (0,0);
- refresh(); /* update the window. Note, no endwin. That
- * would drop the cursor to the last line. */
- /* well, this kind of brute forse sets us to what the getty would
- expect upon login. Sleazy, isn't it ? */
- system ("stty echo cs8 hupcl ixon erase ixon ixany icrnl istrip ignpar erase '^H' brkint opost onlcr cread isig icanon echok echo tab3");
- /* and while we're at it, display our system */
- printf("%s on %s\n",sp[s], hostname);
- cat (ISSUE); /* display /etc/issue banner */
- fflush(stdout); /* flush it */
- execl(LOGIN,"login",NULL); /* exec login */
- abort("can't exec login");
- } else {
- /* well, this kind of brute forse sets us to what the getty would
- expect upon login. Sleazy, isn't it ? */
- system ("stty echo cs8 hupcl ixon erase ixon ixany icrnl istrip ignpar erase '^H' brkint opost onlcr cread isig icanon echok echo tab3");
- printf("%s baud\n",sp[s]); /* from shell,just print speed*/
- exit(0);
- }
- }
-
-
-
- /* abort(s) - abort, for reason given in string s, calling perror first
- *
- * (It's not totally clear what we should do, but we'll do it here for
- * uniformity.)
- */
-
- abort(s)
- char *s;
- {
- fprintf(stderr,"%s: ",PGMNAME); /* display program name */
- perror(s); /* display detail, and error message */
- if (login)
- nap(5000); /* prevent fast looping in login mode */
- exit(1);
- }
-
-
-
-
- /* nap(n) - delay for n milliseconds.
- *
- * if #ifdef SOCKETS, try to use the select function of sockets to
- * delay that many milliseconds, but it doesn't work right.
- *
- * What does work is weird, but ... it works.
- * Put a terminal on a tty port. Set it to 9600 baud. Then lock it
- * away and ignore it, because delays will be obtained by writing 100
- * characters to this terminal.
- */
-
- static int nap_flag = -1;
- static nap_done() { nap_flag = 0; }
-
- nap(n)
- int n;
- {
- #ifdef SOCKETS
- int nfound,nfds;
- long timeout;
- timeout = n; /* sleep n milliseconds */
- nfound = select (nfds,(int *) 0,(int *) 0,timeout);
- #endif
- #ifndef SOCKETS
- FILE *fp,*fopen();
- int i;
- if (n > 1000)
- /* sleep the correct # of seconds */
- sleep (n/1000);
- else
- {
- /* bloody hack time here ... open up a tty that's 9600 baud that
- there's an unused device on */
- if ((fp = fopen(DELAY_TTY,"w"))== NULL)
- {
- /* if we can't open the line, sleep one second, a safe amount */
- sleep (1);
- }
- else
- {
- /* fudge factor delay, figuring 960 chars a second */
- for (i=0;i<n;i++)
- fprintf (fp,"%c",'\n');
- /* and close our tty */
- fclose (fp);
- }
- }
- #endif
- }
-
-
- #ifdef DEBUG
- display(n)
- /* put out to a file the proper settings for the line, for debug
- * purposes. This way, we know what the getty thought the baud rate was.
- */
- int n;
- {
- FILE *fp,*fopen();
- if ((fp = fopen("parity.err","a"))== NULL)
- {
- printf ("fail 18\n");
- /* if we can't, sleep one second, a safe amount */
- }
- else
- {
- fprintf (fp,"char = %x\n",n);
- /* and close our tty */
- fclose (fp);
- }
- }
-
- #endif
- /*
- * list the file on the screen. Note, this is taken from BSA's BBS, ua.
- * although, BBS specific stuff has been stripped out. This routine
- * is used to display the /etc/issue file.
- */
- cat(file)
- char *file;
- {
- FILE *f;
- char ch;
-
- if ((f = fopen(file, "r")) == NULL)
- {
- fprintf (stderr,"Cannot open file %s\n.",file);
- return;
- }
- while ((ch = getc(f)) != EOF)
- putchar(ch);
- fclose(f);
- return (1);
- }
- //E*O*F auto.c//
-
- echo x - autolocal.h
- cat > "autolocal.h" << '//E*O*F autolocal.h//'
- /*
- *
- * CESPK-ED-T-AMU, David P. van De Kerk, U.S. Army COE,
- * Sacramento District. 20 Oct 88
- *
- */
-
- #define SITE_NAME "spked" /* our host name */
- #define DELAY_TTY "/dev/hty10" /* the tty we're sending, at 9600 baud,
- * junk to so we can delay .1 seconds */
- //E*O*F autolocal.h//
-
- echo x - autobaud.8
- cat > "autobaud.8" << '//E*O*F autobaud.8//'
- .TH AUTOBAUD 8 "20 October 1988" "U.S. Army COE"
- .SH NAME
- autobaud \- terminal speed detection
- .SH SYNOPSIS
- \fB/etc/autobaud [ \-l ] [ \fIttyname\fB ]
- .SH DESCRIPTION
- .I Autobaud
- is a simpler replacement for
- .IR getty (8),
- the crucial difference being that
- .I autobaud
- performs line speed detection as distinguished from cycling.
- The speeds recognized are 300, 1200, 2400, and 9600 baud.
- Autobaud expects the user to type a carriage return and will loop
- until one is received.
- .PP
- If
- .I ttyname
- is given,
- .I autobaud
- samples
- .RI /dev/ ttyname
- instead of standard input.
- The
- .B \-l
- option is normally set in /etc/inittab
- and causes
- .I autobaud
- to exec
- .IR login (1)
- after determining the speed.
- Here is an example inittab entry:
- .br
- h0a0:1:respawn:/etc/autobaud -l hty00 ignored svt100
- .br
- and clears the screen, according to curses.
- .PP
- Autobaud sets these terminal parameters: no parity, no tabs, echo,
- erase ^H, kill ^U, interrupt ^C.
- .SH FILES
- .PP
- /etc/inittab
- .br
- /dev/\fIttyname\fP
- .br
- /etc/issue
- .br
- /dev/\fIdelay_tty\fP
- .br
- /usr/lib/terminfo
- .SH "SEE ALSO"
- init(8), getty(8), inittab (4), issue (4), login(1)
- .SH BUGS
- .PP
- BREAK and NUL have no effect, but typing any other character is
- likely to cause
- .I autobaud
- to set the speed incorrectly. If this happens, wait two minutes,
- WITHOUT touching the keyboard. The login process will die, and autobaud
- will fire up again, allowing another attempt.
- .PP
- Theory says that 600 baud should also work, but it doesn't.
- .SH HISTORY
- .PP
- Originally written for 4.3 BSD at the University of Arizona. Hacked
- for Sys V.
- //E*O*F autobaud.8//
-
- echo x - README
- cat > "README" << '//E*O*F README//'
- David P. van De Kerk, U.S. Army Corps of Engineers,
- Sacramento District. CESPK-ED-T-AMU.
- ucdavis.ucdavis.edu!spked!davev
- 20-OCT-88
-
- This is an autobauding getty. It was originally written for 4.3 BSD,
- by Gregg Townsend, University of Arizona, April, 1987
-
- but has been modified for a Unisys 5000/80 computer running Unisys's
- Sys V r2. Note: While it runs on the Unisys 5000/80, I make NO
- claims about it running on any other machine.
-
- PLEASE carefully read nap() in auto.c.
-
- Manifest -----------------------------------------------------
-
- README -- This is it.
- auto.c -- Main sources.
- autolocal.h -- Put your site name in there
- autobaud.8 -- Manual page
- Makefile -- Make file for the program, tags, and shar file.
- //E*O*F README//
-
- exit 0
- ---
- The contents of this message are totally unauthorized, and represent no person
- or entity within any agency, nor any statement of policy.
- Standard Form 1 Disclaimer (Rev. 4-87)
- {{seismo|ihnp4!}lll-crg|sdcsvax|{decvax!}ucbvax}!ucdavis!spked!davev
-
-
-