home *** CD-ROM | disk | FTP | other *** search
- Subject: v13i058: Baud rate detection for 4.3BSD
- Newsgroups: comp.sources.unix
- Sender: sources
- Approved: rsalz@uunet.UU.NET
-
- Submitted-by: Gregg Townsend <gmt@MEGARON.ARIZONA.EDU>
- Posting-number: Volume 13, Issue 58
- Archive-name: 4.3autobaud
-
- This program does automatic baud rate detection under 4.3 BSD Unix. That is,
- you send it a carriage return and it figures out your baud rate. It depends
- on the hardware response to a speed mismatch, but the technique dates back at
- least to TOPS-10 and probably much earlier. I've seen it work on several
- systems; we're running this code on Vaxes.
-
- Note that only certain speeds work; generalizing it to handle all possible
- speeds is decidedly nontrivial. The set here (300, 1200, 2400, 9600) is
- sufficient for us.
-
- Autobaud was originally written to handle terminals coming in through a port
- switch that intercepts BREAKs. Now we run it on nearly all incoming lines as
- a replacement for getty(8).
-
- (We tried, not too hard, to get getty's baud detection code to work; the
- tangled code, comments referencing Micom, and omission of the feature from
- the published documentation were all discouraging.)
-
- Gregg Townsend / Computer Science Dept / Univ of Arizona / Tucson, AZ 85721
- +1 602 621 4325 gmt@Arizona.EDU {allegra|noao|ihnp4}!arizona!gmt
-
- ---------------------------- cut here -----------------------------------
- # To unbundle, sh this file
- echo unbundling Makefile 1>&2
- cat >Makefile <<'AlBeRtEiNsTeIn'
- autobaud: autobaud.c ; cc -O -s -o autobaud autobaud.c
- AlBeRtEiNsTeIn
- echo unbundling autobaud.8 1>&2
- cat >autobaud.8 <<'AlBeRtEiNsTeIn'
- .TH AUTOBAUD 8 "15 April 1987" "University of Arizona"
- .SH NAME
- autobaud \- terminal speed detection
- .SH SYNOPSIS
- \fB/etc/local/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/ttys
- and causes
- .I autobaud
- to exec
- .IR login (1)
- after determining the speed.
- .PP
- Autobaud sets these terminal parameters: any parity, no tabs, echo,
- erase ^H, kill ^U.
- .SH FILES
- .PP
- /etc/ttys
- .br
- /dev/\fIttyname\fP
- .SH "SEE ALSO"
- init(8), getty(8), 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.
- .PP
- Theory says that 600 baud should also work, but it doesn't.
- AlBeRtEiNsTeIn
- echo unbundling autobaud.c 1>&2
- cat >autobaud.c <<'AlBeRtEiNsTeIn'
- /* 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] [ttyname]
- *
- * -l sets "login" mode and execs login after the speed is set
- * ttyname specifies a device to autobaud (/dev/ttyname) instead of stdin
- *
- * Gregg Townsend
- * University of Arizona
- * April, 1987
- */
-
- #define PGMNAME "autobaud" /* program name (for diagnostics) */
- #define LOGIN "/bin/login" /* location of login program */
- #define STRSIZ 100 /* string size for host and tty names */
-
- #include <sgtty.h>
- #include <signal.h>
- #include <stdio.h>
- #include <sys/file.h>
- #include <sys/time.h>
-
-
-
- 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 ttyname[STRSIZ] = "/dev/"; /* buffer for explicit tty name */
- char hostname[STRSIZ]; /* buffer for hostname */
-
-
-
- /* main program */
-
- main(argc,argv)
- int argc;
- char **argv;
- {
- struct sgttyb ttyb;
- unsigned char c;
- char s;
- int zero = 0;
-
- argv++; /* skip program name */
- if (*argv && !strcmp(*argv,"-l"))
- login++, argv++; /* if "-l", set login flag */
- if (*argv) {
- strcpy(ttyname+5,*argv++); /* if tty given, build name */
- close(0); /* close previous stdin */
- close(1); /* close previous stdout */
- close(2); /* close previous stderr */
- if (login) {
- nap(2000); /* hold DTR down for 2 sec */
- chown(ttyname,0,0); /* make root the owner */
- chmod(ttyname,0622); /* and set the protections */
- }
- if (open(ttyname,O_RDWR) != 0) /* open once for stdin */
- abort(ttyname);
- dup(0); /* dup for stdout */
- dup(0); /* dup for stderr */
- }
-
- ttyb.sg_ispeed = ttyb.sg_ospeed = B2400; /* sample line at 2400 baud */
- ttyb.sg_erase = ttyb.sg_kill = -1; /* no editing characters */
- ttyb.sg_flags = EVENP + ODDP + RAW; /* raw mode, no echo */
- if (ioctl(0,TIOCSETN,&ttyb) <0) /* set tty parameters */
- abort("ioctl");
- s = 0;
- 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);
- /* 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.sg_ispeed = ttyb.sg_ospeed = s; /* set speeds */
- ttyb.sg_erase = '\b'; /* \b for char correction */
- ttyb.sg_kill = 'U' & 037; /* ^U for line kill */
- ttyb.sg_flags = XTABS+EVENP+ODDP+CRMOD+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) {
- gethostname(hostname,STRSIZ);
- printf("\n%s %s\n",hostname,ttyname+5); /* display banner */
- fflush(stdout); /* flush it */
- execl(LOGIN,"login",NULL); /* exec login */
- abort("can't exec login");
- } else {
- 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.
- * Assumes nobody else is using SIGALRM or ITIMER_REAL.
- */
-
- static int nap_flag = -1;
- static nap_done() { nap_flag = 0; }
-
- nap(n)
- int n;
- {
- struct itimerval t;
-
- if (nap_flag < 0)
- signal(SIGALRM,nap_done);
- if (!(nap_flag = n))
- return;
- t.it_value.tv_sec = n / 1000;
- t.it_value.tv_usec = (n % 1000) * 1000;
- t.it_interval.tv_sec = t.it_interval.tv_usec = 0;
- setitimer(ITIMER_REAL,&t,(struct itimerval *)0);
- while (nap_flag)
- pause();
- }
- AlBeRtEiNsTeIn
- exit 0
-
-