home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / unix / volume13 / 4.3autobaud next >
Text File  |  1988-01-31  |  8KB  |  255 lines

  1. Subject:  v13i058:  Baud rate detection for 4.3BSD
  2. Newsgroups: comp.sources.unix
  3. Sender: sources
  4. Approved: rsalz@uunet.UU.NET
  5.  
  6. Submitted-by: Gregg Townsend <gmt@MEGARON.ARIZONA.EDU>
  7. Posting-number: Volume 13, Issue 58
  8. Archive-name: 4.3autobaud
  9.  
  10. This program does automatic baud rate detection under 4.3 BSD Unix.  That is,
  11. you send it a carriage return and it figures out your baud rate.  It depends
  12. on the hardware response to a speed mismatch, but the technique dates back at
  13. least to TOPS-10 and probably much earlier.  I've seen it work on several
  14. systems; we're running this code on Vaxes.
  15.  
  16. Note that only certain speeds work; generalizing it to handle all possible
  17. speeds is decidedly nontrivial.  The set here (300, 1200, 2400, 9600) is
  18. sufficient for us.
  19.  
  20. Autobaud was originally written to handle terminals coming in through a port
  21. switch that intercepts BREAKs.  Now we run it on nearly all incoming lines as
  22. a replacement for getty(8).
  23.  
  24. (We tried, not too hard, to get getty's baud detection code to work; the
  25.  tangled code, comments referencing Micom, and omission of the feature from
  26.  the published documentation were all discouraging.)
  27.  
  28.      Gregg Townsend / Computer Science Dept / Univ of Arizona / Tucson, AZ 85721
  29.      +1 602 621 4325      gmt@Arizona.EDU       {allegra|noao|ihnp4}!arizona!gmt
  30.  
  31. ---------------------------- cut here -----------------------------------
  32. # To unbundle, sh this file
  33. echo unbundling Makefile 1>&2
  34. cat >Makefile <<'AlBeRtEiNsTeIn'
  35. autobaud:    autobaud.c    ; cc -O -s -o autobaud autobaud.c
  36. AlBeRtEiNsTeIn
  37. echo unbundling autobaud.8 1>&2
  38. cat >autobaud.8 <<'AlBeRtEiNsTeIn'
  39. .TH AUTOBAUD 8 "15 April 1987" "University of Arizona"
  40. .SH NAME
  41. autobaud \- terminal speed detection
  42. .SH SYNOPSIS
  43. \fB/etc/local/autobaud [ \-l ] [ \fIttyname\fB ]
  44. .SH DESCRIPTION
  45. .I Autobaud
  46. is a simpler replacement for
  47. .IR getty (8),
  48. the crucial difference being that
  49. .I autobaud
  50. performs line speed detection as distinguished from cycling.
  51. The speeds recognized are 300, 1200, 2400, and 9600 baud.
  52. Autobaud expects the user to type a carriage return and will loop
  53. until one is received.
  54. .PP
  55. If
  56. .I ttyname
  57. is given,
  58. .I autobaud
  59. samples
  60. .RI /dev/ ttyname
  61. instead of standard input.
  62. The
  63. .B \-l
  64. option is normally set in /etc/ttys
  65. and causes
  66. .I autobaud
  67. to exec
  68. .IR login (1)
  69. after determining the speed.
  70. .PP
  71. Autobaud sets these terminal parameters:  any parity, no tabs, echo,
  72. erase ^H, kill ^U.
  73. .SH FILES
  74. .PP
  75. /etc/ttys
  76. .br
  77. /dev/\fIttyname\fP
  78. .SH "SEE ALSO"
  79. init(8), getty(8), login(1)
  80. .SH BUGS
  81. .PP
  82. BREAK and NUL have no effect, but typing any other character is
  83. likely to cause
  84. .I autobaud
  85. to set the speed incorrectly.
  86. .PP
  87. Theory says that 600 baud should also work, but it doesn't.
  88. AlBeRtEiNsTeIn
  89. echo unbundling autobaud.c 1>&2
  90. cat >autobaud.c <<'AlBeRtEiNsTeIn'
  91. /*  autobaud.c - determine tty speed of standard input  (for 4.3 BSD Unix)
  92.  *
  93.  *  Autobaud reads standard input at 2400 baud.  Assuming a carriage return
  94.  *  is typed, the bit pattern received is used to select and set the "true"
  95.  *  speed.  This works for speeds of 300, 1200, 2400, and 9600 baud.  In theory
  96.  *  600 should also work, but empirically a 00 character is read and it doesn't.
  97.  *  Any other speed, or any character other than a carriage return, is likely
  98.  *  to give a wrong result.
  99.  *
  100.  *  Autobaud is primarily intended as a replacement for getty(8), and as such
  101.  *  it also sets a few terminal parameters such as the kill character to
  102.  *  default values.  However, it can also be run from a shell for testing.
  103.  *
  104.  *  usage:  autobaud [-l] [ttyname]
  105.  *
  106.  *  -l        sets "login" mode and execs login after the speed is set
  107.  *  ttyname    specifies a device to autobaud (/dev/ttyname) instead of stdin
  108.  *
  109.  *  Gregg Townsend
  110.  *  University of Arizona
  111.  *  April, 1987
  112.  */
  113.  
  114. #define PGMNAME "autobaud"        /* program name (for diagnostics) */
  115. #define LOGIN "/bin/login"        /* location of login program */
  116. #define STRSIZ 100            /* string size for host and tty names */
  117.  
  118. #include <sgtty.h>
  119. #include <signal.h>
  120. #include <stdio.h>
  121. #include <sys/file.h>
  122. #include <sys/time.h>
  123.  
  124.  
  125.  
  126. char *sp[] = {   "0",   "50",   "75",  "110",  "134",  "150",  "200",  "300",
  127.            "600", "1200", "1800", "2400", "4800", "9600", "EXTA", "EXTB"};
  128.  
  129. int login = 0;                /* set nonzero if to exec login */
  130. char ttyname[STRSIZ] = "/dev/";        /* buffer for explicit tty name */
  131. char hostname[STRSIZ];            /* buffer for hostname */
  132.  
  133.  
  134.  
  135. /*  main program  */
  136.  
  137. main(argc,argv)
  138. int argc;
  139. char **argv;
  140. {
  141.     struct sgttyb ttyb;
  142.     unsigned char c;
  143.     char s;
  144.     int zero = 0;
  145.  
  146.     argv++;                    /* skip program name */
  147.     if (*argv && !strcmp(*argv,"-l"))
  148.     login++, argv++;            /* if "-l", set login flag */
  149.     if (*argv)  {                
  150.     strcpy(ttyname+5,*argv++);        /* if tty given, build name */
  151.     close(0);                /* close previous stdin */
  152.     close(1);                /* close previous stdout */
  153.     close(2);                /* close previous stderr */
  154.     if (login)  {
  155.         nap(2000);                /* hold DTR down for 2 sec */
  156.         chown(ttyname,0,0);            /* make root the owner */
  157.         chmod(ttyname,0622);        /* and set the protections */
  158.     }
  159.     if (open(ttyname,O_RDWR) != 0)        /* open once for stdin */
  160.         abort(ttyname);
  161.     dup(0);                    /* dup for stdout */
  162.     dup(0);                    /* dup for stderr */
  163.     }
  164.  
  165.     ttyb.sg_ispeed = ttyb.sg_ospeed = B2400;    /* sample line at 2400 baud */
  166.     ttyb.sg_erase = ttyb.sg_kill = -1;        /* no editing characters */
  167.     ttyb.sg_flags = EVENP + ODDP + RAW;        /* raw mode, no echo */
  168.     if (ioctl(0,TIOCSETN,&ttyb) <0)        /* set tty parameters */
  169.     abort("ioctl");
  170.     s = 0;
  171.     while (!s)  {
  172.     nap(100);                /* wait .1 sec for line quiet */
  173.     ioctl(0,TIOCFLUSH,&zero);        /* flush input & output */
  174.     if (read(0,&c,1) != 1)            /* read a character */
  175.         exit(1);
  176.     /* select baud rate based on pattern received */
  177.     if (c >= 0xF0)
  178.         s = B9600;
  179.     else switch (c)  {
  180.         case 0x80: s = B300;  break;
  181.         case 0x78: s = B600;  break;
  182.         case 0xE6: s = B1200; break;
  183.         case 0x0D: s = B2400; break;
  184.         case 0x8D: s = B2400; break;
  185.         default:   s = 0;     break;
  186.     }
  187.     }
  188.     nap(100);                    /* let slow input finish */
  189.     ttyb.sg_ispeed = ttyb.sg_ospeed = s;    /* set speeds */
  190.     ttyb.sg_erase =  '\b';            /* \b for char correction */
  191.     ttyb.sg_kill = 'U' & 037;            /* ^U for line kill */
  192.     ttyb.sg_flags = XTABS+EVENP+ODDP+CRMOD+ECHO;/* any parity, -TABS, CR, ECHO*/
  193.     ioctl(0,TIOCSETN,&ttyb);            /* set parameters */
  194.     ioctl(0,TIOCFLUSH,&zero);            /* flush I/O */
  195.     ioctl(0,TIOCHPCL,0);            /* set hangup on last close */
  196.     if (login)  {
  197.     gethostname(hostname,STRSIZ);
  198.     printf("\n%s %s\n",hostname,ttyname+5);    /* display banner */
  199.     fflush(stdout);                /* flush it */
  200.     execl(LOGIN,"login",NULL);        /* exec login */
  201.     abort("can't exec login");
  202.     } else {
  203.     printf("%s baud\n",sp[s]);        /* from shell,just print speed*/
  204.     exit(0);
  205.     }
  206. }
  207.  
  208.  
  209.  
  210. /*  abort(s) - abort, for reason given in string s, calling perror first
  211.  *
  212.  *  (It's not totally clear what we should do, but we'll do it here for
  213.  *   uniformity.)
  214.  */
  215.  
  216. abort(s)
  217. char *s;
  218. {
  219.     fprintf(stderr,"%s: ",PGMNAME);    /* display program name */
  220.     perror(s);                /* display detail, and error message */
  221.     if (login)
  222.     nap(5000);            /* prevent fast looping in login mode */
  223.     exit(1);
  224. }
  225.  
  226.  
  227.  
  228.  
  229. /*  nap(n) - delay for n milliseconds.
  230.  *  Assumes nobody else is using SIGALRM or ITIMER_REAL.
  231.  */
  232.  
  233. static int nap_flag = -1;
  234. static nap_done() { nap_flag = 0; }
  235.  
  236. nap(n)
  237. int n;
  238. {
  239.     struct itimerval t;
  240.  
  241.     if (nap_flag < 0)
  242.     signal(SIGALRM,nap_done);
  243.     if (!(nap_flag = n))
  244.     return;
  245.     t.it_value.tv_sec = n / 1000;
  246.     t.it_value.tv_usec = (n % 1000) * 1000;
  247.     t.it_interval.tv_sec = t.it_interval.tv_usec = 0;
  248.     setitimer(ITIMER_REAL,&t,(struct itimerval *)0);
  249.     while (nap_flag)
  250.     pause();
  251. }
  252. AlBeRtEiNsTeIn
  253. exit 0
  254.  
  255.