Path: ficc!sugar!texbell!swbatl!wuarchive!cs.utexas.edu!uunet!allbery From: allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc) Newsgroups: comp.sources.misc Subject: v09i065: agetty, alternative getty for System-V Message-ID: <73729@uunet.UU.NET> Date: 15 Dec 89 00:38:34 GMT Sender: allbery@uunet.UU.NET Reply-To: wietse@wzv.win.tue.nl (Wietse Z. Venema) Organization: Eindhoven University of Technology, The Netherlands Lines: 964 Approved: allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc) Posting-number: Volume 9, Issue 65 Submitted-by: wietse@wzv.win.tue.nl (Wietse Z. Venema) Archive-name: agetty This is a SYSV getty replacement that adapts itself to parity bits and to erase, kill and end-of-line characters when a user enters her login name. It has an optional facility do detect the baud rate of incoming calls from the status messages produced by some multi-speed Hayes(tm) modem clones. #! /bin/sh # This is a shell archive. Remove anything before this line, then unpack # it by saving it into a file and typing "sh file". To overwrite existing # files, type "sh file -c". You can also feed this as standard input via # unshar, or by typing "sh 'README' <<'END_OF_FILE' X@(#) README 1.1 11/26/89 22:04:59 X XThis is a SYSV getty replacement that adapts itself to parity bits, and Xto erase, kill and end-of-line characters found in its input. It also Xhas an optional facility do detect the baud rate of incoming calls from Xthe status messages produced by some multi-speed Hayes modem clones. XThis program is an adapted version of a getty I once wrote for a V7 UNIX Ximplementation; it does not use the /etc/gettydefs file. X X Wietse Venema (wietse@wzv.win.tue.nl) END_OF_FILE if test 490 -ne `wc -c <'README'`; then echo shar: \"'README'\" unpacked with wrong size! fi # end of 'README' fi if test -f 'agetty.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'agetty.c'\" else echo shar: Extracting \"'agetty.c'\" \(20261 characters\) sed "s/^X//" >'agetty.c' <<'END_OF_FILE' X/*++ X/* NAME X/* agetty 8 X/* SUMMARY X/* alternative System-V getty X/* SYNOPSIS X/* agetty [-a alternate_rates] [-h] [-m] [-t timeout] port baud_rate X/* DESCRIPTION X/* \fIagetty\fR opens a tty port, prompts for a login name and invokes the X/* /bin/login command. It is normally invoked by \fIinit(8)\fR. X/* X/* \fIagetty\fR has some useful features not present in the System X/* V Release 2 getty command: X/* .IP o X/* Adapts the tty settings to parity bits and to X/* erase, kill and end-of-line characters found in its input. The X/* program understands 7-bit characters with even, odd, none or space X/* parity, and 8-bit characters with no parity. The following special X/* characters are recognized: @ and Control-U (kill); #, DEL and X/* backspace (erase); carriage-return and linefeed (end of line). X/* .IP o X/* Optionally recognizes the baud rate of incoming X/* calls from the status messages produced by some multi-speed Hayes (tm) X/* modem clones. X/* .PP X/* This program does not use the \fI/etc/gettydefs\fR file. Except for X/* differences described here the program appears to operate similar X/* to the System-V Release 2 \fIgetty\fR program. X/* X/* Options: X/* .TP X/* -a alternate_rates X/* Initially the program will use the \fIbaud_rate\fR as specified. X/* Upon receipt of successive BREAK characters the program will step X/* through the \fIalternate_rates\fR, which should be specified as a X/* comma-separated list (preferably in decreasing order). After all X/* \fIalternate_rates\fR have been tried, \fIagetty\fR will try the X/* speed specified with the \fIbaud_rate\fR argument and so on. X/* .TP X/* -h X/* Do not hang up the line. Normally, \fIagetty\fR will lower X/* DTR for two seconds to force a modem to hang up (if the hangup X/* feature has been compiled into the program). X/* .TP X/* -m X/* Try to extract the baud rate of incoming calls from the status message X/* produced by some Hayes (tm) multi-speed modem clones. These usually X/* produce a status message of the form: "". X/* If no \fIspeed\fR is found within one second, the \fIbaud_rate\fR as X/* specified on the command line will be used. Since this feature will X/* work only on lightly-loaded systems, you will probably want to use this X/* feature in combination with the \fI-a\fR option. X/* .TP X/* -t timeout X/* Causes the program to terminate if no user name could be read X/* within \fItimeout\fR seconds. This is useful only for dial-in lines. X/* EXAMPLES X/* For hard-wired lines: X/* .ti +5 X/* /etc/agetty ttyM0 9600 X/* X/* For dial-in lines with a 300/1200/2400 baud Hayes clone: X/* .ti +5 X/* /etc/agetty -t60 -m -a1200,300 ttyM1 2400 X/* FILES X/* /etc/utmp, the system log file. X/* BUGS X/* The baud-rate detection code (the \fI-m\fR option) only works if X/* \fIagetty\fR is scheduled soon enough after completion of a dial-in X/* call (within 30 ms with modems that talk at 2400 baud). For robustness, X/* always use the \fI-m\fR option in combination with the \fI-a\fR option. X/* X/* The login prompt is always output with space parity. X/* DIAGNOSTICS X/* All diagnostics are written to the console. X/* X/* In particular, \fIagetty\fR will detect if it is asked to open X/* someting that is not a terminal. X/* AUTHOR(S) X/* W.Z. Venema X/* wietse@wzv.win.tue.nl X/* Eindhoven University of Technology X/* Department of Mathematics and Computer Science X/* Den Dolech 2, P.O. Box 513, 5600 MB Eindhoven, The Netherlands X/* CREATION DATE X/* Sat Nov 25 22:51:05 MET 1989 X/* LAST MODIFICATION X/* 89/12/11 23:02:55 X/* VERSION/RELEASE X/* 1.20 X/*--*/ X X#ifndef lint Xstatic char sccsid[] = "@(#) agetty.c 1.20 12/11/89 23:02:55"; X#endif X X#include X#include X#include X#include X#include X#include X#include X#include X X /* X * Things you may want to modify. HANGUP should be defined only if your tty X * driver is not capable of hanging up the modem (by briefly dropping DTR). X * If HANGUP is defined you probably cannot use the auto-baud and time-out X * features. X */ X X#define LOGIN "\r\nlogin: " /* login prompt */ X X/* #define HANGUP /* enable hangup code */ X X/* Some shorthands for control characters */ X X#define CTL(x) (x ^ 0100) /* controllify */ X#define CR CTL('M') /* carriage return */ X#define NL CTL('J') /* linefeed */ X#define BS CTL('H') /* backspace */ X#define DEL CTL('?') /* delete */ X X/* Default values of special characters; you may want to change this */ X X#define DEF_INTR CTL('C') /* default interrupt character */ X#define DEF_QUIT CTL('\\') /* default quit character */ X#define DEF_KILL CTL('U') /* default kill character */ X#define DEF_EOF CTL('D') /* default EOF character */ X#define DEF_SWITCH CTL('^') /* default switch character */ X#define DEF_ERASE BS /* default erase character */ X#define DEF_EOL 0 X X/* Storage for command-line options */ X X#define MAXSPEED 10 X Xstruct options { X int autobaud; /* process modem status messages */ X int timeout; /* timeout period */ X int hangup; /* hang up tty */ X int numspeed; /* number of baud rates to try */ X int curspeed; /* current speed */ X int speeds[MAXSPEED]; /* baud rates to be tried */ X char *tty; /* name of tty */ X}; X X/* Storage for things detected while the login name was read */ X Xstruct chardata { X int erase; /* erase character */ X int kill; /* kill character */ X int eol; /* end-of-line character */ X int parity; /* what parity did we see */ X int capslock; /* upper case without lower case */ X}; X X/* The following is used for understandable diagnostics */ X Xextern int errno; Xextern char *sys_errlist[]; Xstatic char *progname; Xextern char *strcpy(); Xextern char *strcat(); X X/* ... */ X Xmain(argc, argv) Xint argc; Xchar **argv; X{ X char *logname; /* login name, given to /bin/login */ X char *get_logname(); X struct chardata chardata; /* set by get_logname() */ X struct termio termio; /* terminal mode bits */ X static struct options options = { X 0, /* no modem status message processing */ X 0, /* no timeout */ X 1, /* do hangup */ X 1, /* no baud-rate cycling */ X 0, /* use baud-rate argument as speed */ X }; X X progname = argv[0]; X X /* Parse command-line arguments */ X X parse_args(argc, argv, &options); X X /* Update the utmp file */ X X update_utmp(options.tty); X X /* Open the tty as standard { input, output, error } */ X X open_tty(options.tty, &termio); X X /* Optionally hang up the tty */ X X if (options.hangup) X hangup_tty(&termio); X X /* Initialize the termio settings (raw mode, eight-bit, blocking i/o) */ X X termio_init(&termio, options.speeds[0]); X X /* Optionally detect the baud rate from the modem status message */ X X if (options.autobaud) X auto_baud(&termio); X X /* With dial-in lines, briefly pause to allow modems etc. to settle */ X X if (options.timeout) X (void) sleep(1); X X /* Optional time-out feature */ X X if (options.timeout) X (void) alarm((unsigned) options.timeout); X X /* Read the login name */ X X while ((logname = get_logname(&options, &chardata)) == 0) X next_speed(&termio, &options); X X /* Disable time-out feature */ X X if (options.timeout) X (void) alarm(0); X X /* Finalize the termio settings */ X X termio_final(&termio, &chardata); X X /* Now the newline should be properly output */ X X (void) write(1, "\n", 1); X X /* Let /bin/login take care of password validation */ X X execl("/bin/login", "login", logname, (char *) 0); X error("%s: can't exec /bin/login", options.tty); X /* NOTREACHED */ X} X X/* parse-args - parse command-line arguments */ X Xparse_args(argc, argv, op) Xint argc; Xchar **argv; Xstruct options *op; X{ X extern char *optarg; /* getopt */ X extern int optind; /* getopt */ X int c; X X while ((c = getopt(argc, argv, "a:hmt:")) != EOF) { X switch (c) { X case 'a': /* enable auto-baud feature */ X parse_speeds(op, optarg); X break; X case 'h': /* do not hangup the tty */ X op->hangup = 0; X break; X case 'm': /* parse modem status message */ X op->autobaud = 1; X break; X case 't': /* time out */ X if ((op->timeout = atoi(optarg)) <= 0) X error("bad timeout value: %s", optarg); X break; X case '?': X usage(); X } X } X if (argc != optind + 2) /* check parameter count */ X usage(); X op->tty = argv[optind++]; /* tty name */ X if ((op->speeds[0] = bcode(argv[optind])) <= 0) /* baud rate */ X error("bad speed: %s", argv[optind]); X} X X/* parse_speeds - parse alternate baud rates */ X Xparse_speeds(op, arg) Xstruct options *op; Xchar *arg; X{ X char *strtok(); X char *cp; X X for (cp = strtok(arg, ","); cp != 0; cp = strtok((char *) 0, ",")) { X if ((op->speeds[op->numspeed++] = bcode(cp)) <= 0) X error("bad speed: %s", cp); X if (op->numspeed > MAXSPEED) X error("too many alternate speeds"); X } X} X X/* update_utmp - update our utmp entry */ X Xupdate_utmp(line) Xchar *line; X{ X struct utmp ut; X long ut_size = sizeof(ut); /* avoid nonsense */ X int ut_fd; X int mypid = getpid(); X long time(); X long lseek(); X X /* X * The utmp file holds miscellaneous information about things started by X * /etc/init and other system-related events. Our purpose is to update X * the utmp entry for the current process, in particular the process type X * and the tty line we are listening to. Return successfully only if the X * utmp file can be opened for update, and if we are able to find our X * entry in the utmp file. X */ X X if ((ut_fd = open(UTMP_FILE, 2)) < 0) { X error("%s: open for update", UTMP_FILE); X } else { X while (read(ut_fd, (char *) &ut, sizeof(ut)) == sizeof(ut)) { X if (ut.ut_type == INIT_PROCESS && ut.ut_pid == mypid) { X ut.ut_type = LOGIN_PROCESS; X ut.ut_time = time((long *) 0); X (void) strncpy(ut.ut_name, "LOGIN", sizeof(ut.ut_name)); X (void) strncpy(ut.ut_line, line, sizeof(ut.ut_line)); X (void) lseek(ut_fd, -ut_size, 1); X (void) write(ut_fd, (char *) &ut, sizeof(ut)); X (void) close(ut_fd); X return; X } X } X error("no utmp entry found for process id %u", mypid); X } X} X X/* open_tty - open tty as standard { input, output, error } */ X Xopen_tty(tty, tp) Xchar *tty; Xstruct termio *tp; X{ X struct stat st; X X /* Close standard { input, output, error } files, just in case */ X X (void) close(0); X (void) close(1); X (void) close(2); X errno = 0; /* ignore above errors */ X X /* Make sure we are given a character device */ X X if (chdir("/dev")) X error("/dev: chdir() failed"); X if (stat(tty, &st) < 0) X error("/dev/%s: stat() failed", tty); X if ((st.st_mode & S_IFMT) != S_IFCHR) X error("not a character device: /dev/%s", tty); X X /* Set up new standard input, output and error files */ X X if (open(tty, 2) != 0) /* set up std input */ X error("/dev/%s: cannot open as standard input", tty); X if (dup(0) != 1 || dup(0) != 2) /* set up std out and std err */ X error("%s: dup problem", tty); /* we have a problem */ X if (ioctl(0, TCGETA, tp) < 0) /* read tty status bits */ X error("%s: ioctl failed", tty); /* this is not a terminal */ X X /* It seems to be a terminal; set proper protections and ownership */ X X (void) chown(tty, 0, 0); /* root, sys */ X (void) chmod(tty, 0622); /* crw--w--w- */ X errno = 0; /* ignore above errors */ X} X X/* hangup_tty - hang up by forcing DTR down for at least 2 seconds */ X Xhangup_tty(tp) Xstruct termio *tp; X{ X#ifdef HANGUP X (void) signal(SIGHUP, SIG_IGN); X tp->c_cflag &= ~CBAUD; X tp->c_cflag |= B0; X (void) ioctl(0, TCSETA, tp); X (void) signal(SIGHUP, SIG_DFL); X (void) sleep(2); X#endif X} X X/* termio_init - initialize termio settings */ X Xtermio_init(tp, speed) Xstruct termio *tp; Xint speed; X{ X X /* X * Initial termio settings: 8-bit characters, raw-mode, blocking i/o. X * Special characters are set after we have read the login name; all X * reads will be done in raw mode anyway. X */ X X tp->c_cflag = CS8 | HUPCL | CREAD | speed; X tp->c_iflag = tp->c_lflag = tp->c_oflag = tp->c_line = 0; X tp->c_cc[VMIN] = 1; X tp->c_cc[VTIME] = 0; X (void) ioctl(0, TCSETA, tp); X} X X/* auto_baud - extract baud rate from modem status message */ X Xauto_baud(tp) Xstruct termio *tp; X{ X int speed; X int vmin; X int iflag; X char buf[BUFSIZ]; X char *bp; X int nread; X X /* X * This works only if the modem produces its status code AFTER raising X * the DCD line, and if the computer is fast enough to set the proper X * baud rate before the message has gone by. We expect a message of the X * following format: X * X * X * X * The number is interpreted as the baud rate of the incoming call. If the X * modem does not tell us the baud rate within one second we will keep X * using the current baud rate. It is advisable to enable baud-rate X * cycling (-a option) if the processing of modem status messages is X * enabled. X */ X X /* Use 7-bit characters, don't block if input queue is empty */ X X iflag = tp->c_iflag; X tp->c_iflag |= ISTRIP; /* enable 8th-bit stripping */ X vmin = tp->c_cc[VMIN]; X tp->c_cc[VMIN] = 0; /* don't block if queue empty */ X (void) ioctl(0, TCSETA, tp); X X /* X * Wait for a while, then read everything the modem has said so far and X * try to extract the speed of the dial-in call. X */ X X (void) sleep(1); X if ((nread = read(0, buf, sizeof(buf) - 1)) > 0) { X buf[nread] = '\0'; X for (bp = buf; bp < buf + nread; bp++) { X if (isascii(*bp) && isdigit(*bp)) { X if (speed = bcode(bp)) { X tp->c_cflag &= ~CBAUD; X tp->c_cflag |= speed; X } X break; X } X } X } X /* Restore settings */ X X tp->c_iflag = iflag; X tp->c_cc[VMIN] = vmin; X (void) ioctl(0, TCSETA, tp); X} X X/* next_speed - select next baud rate */ X Xnext_speed(tp, op) Xstruct termio *tp; Xstruct options *op; X{ X op->curspeed = (op->curspeed + 1) % op->numspeed; X tp->c_cflag &= ~CBAUD; X tp->c_cflag |= op->speeds[op->curspeed]; X (void) ioctl(0, TCSETA, tp); X} X X/* get_logname - get user name, establish parity, speed, erase, kill, eol */ X Xchar *get_logname(op, cp) Xstruct options *op; Xstruct chardata *cp; X{ X char logname[BUFSIZ]; X char *bp; X char c; /* input character, full eight bits */ X char ascval; /* low 7 bits of input character */ X int bits; /* # of "1" bits per character */ X int mask; /* mask with 1 bit up */ X static char *erase[] = { /* backspace-space-backspace */ X "\010\040\010", /* space parity */ X "\010\040\010", /* odd parity */ X "\210\240\210", /* even parity */ X "\210\240\210", /* no parity */ X }; X X /* Initialize kill, erase, parity etcetera (also after switching speeds) */ X X cp->kill = DEF_KILL; X cp->erase = DEF_ERASE; X cp->parity = 0; X X /* Flush any pending input */ X X ioctl(0, TCFLSH, (struct termio *) 0); X X /* Read a login name */ X X for (*logname = 0; *logname == 0; /* void */ ) { X X /* Write the prompt, with "parity" bit == 0 */ X X (void) write(1, LOGIN, sizeof(LOGIN) - 1); X X /* Read name, watch for break, parity, erase, kill, end-of-line */ X X for (bp = logname, cp->eol = 0; cp->eol == 0; /* void */ ) { X if (read(0, &c, 1) < 1) X error("%s: read error", op->tty); X X /* Do BREAK handling elsewhere */ X X if ((c == 0) && op->numspeed > 1) X return (0); X X /* Do parity bit handling */ X X if (c != (ascval = (c & 0177))) { /* "parity" bit on ? */ X for (bits = 1, mask = 1; mask & 0177; mask <<= 1) X if (mask & ascval) X bits++; /* count "1" bits */ X cp->parity |= ((bits & 1) ? 1 : 2); X } X /* Do erase, kill and end-of-line processing */ X X switch (ascval) { X case CR: X case NL: X *bp = 0; /* terminate logname */ X cp->eol = ascval; /* send end-of-line char */ X break; X case BS: X case DEL: X case '#': X cp->erase = ascval; /* set erase character */ X if (bp > logname) { X (void) write(1, erase[cp->parity], 3); X bp--; X } X break; X case CTL('U'): X case '@': X cp->kill = ascval; /* set kill character */ X while (bp > logname) { X (void) write(1, erase[cp->parity], 3); X bp--; X } X break; X case CTL('D'): X exit(0); X default: X if (!isascii(ascval) || !isprint(ascval)) { X /* ignore garbage characters */ ; X } else if (bp - logname >= sizeof(logname) - 1) { X error("%s: input overrun", op->tty); X } else { X (void) write(1, &c, 1); /* echo the character */ X *bp++ = ascval; /* and store it */ X } X break; X } X } X } X cp->capslock = caps_lock(logname); /* upper case w/o lower case? */ X return (logname); X} X X/* termio_final - set the final tty mode bits */ X Xtermio_final(tp, cp) Xstruct termio *tp; Xstruct chardata *cp; X{ X /* General terminal-independent stuff */ X X tp->c_iflag |= IXON | IXOFF; /* 2-way flow control */ X tp->c_lflag |= ICANON | ISIG | ECHO | ECHOE | ECHOK; X tp->c_oflag |= OPOST; X tp->c_cc[VEOF] = DEF_EOF; X tp->c_cc[VEOL] = DEF_EOL; X tp->c_cc[VINTR] = DEF_INTR; X tp->c_cc[VQUIT] = DEF_QUIT; X tp->c_cc[VKILL] = DEF_KILL; X tp->c_cc[VERASE] = DEF_ERASE; X tp->c_cc[VSWTCH] = DEF_SWITCH; X X /* Account for special characters seen in input */ X X if (cp->eol == CR) { X tp->c_iflag |= ICRNL; /* map CR in input to NL */ X tp->c_oflag |= ONLCR; /* map NL in output to CR-NL */ X } X tp->c_cc[VERASE] = cp->erase; /* set erase character */ X tp->c_cc[VKILL] = cp->kill; /* set kill character */ X X /* Account for the presence or absence of parity bits in input */ X X switch (cp->parity) { X case 0: /* space (always 0) parity */ X break; X case 1: /* odd parity */ X tp->c_cflag |= PARODD; X /* FALLTHROUGH */ X case 2: /* even parity */ X tp->c_cflag |= PARENB; X tp->c_iflag |= INPCK | ISTRIP; X /* FALLTHROUGH */ X case (1 | 2): /* no parity bit */ X tp->c_cflag &= ~CSIZE; X tp->c_cflag |= CS7; X break; X } X /* Account for upper case without lower case */ X X if (cp->capslock) { X tp->c_iflag |= IUCLC; X tp->c_lflag |= XCASE; X tp->c_oflag |= OLCUC; X } X X /* Finally, make the new settings effective */ X X (void) ioctl(0, TCSETA, tp); X} X X/* caps_lock - string contains upper case without lower case */ X Xcaps_lock(s) Xchar *s; X{ X int hascaps; X X for (hascaps = 0; *s; s++) { X if (islower(*s)) X return (0); X if (hascaps == 0) X hascaps = isupper(*s); X } X return (hascaps); X} X X/* bcode - convert speed string to speed code; return 0 on failure */ X Xbcode(s) Xchar *s; X{ X struct Speedtab { X int speed; X int code; X }; X static struct Speedtab speedtab[] = { X 50, B50, X 75, B75, X 110, B110, X 134, B134, X 150, B150, X 200, B200, X 300, B300, X 600, B600, X 1200, B1200, X 1800, B1800, X 2400, B2400, X 4800, B4800, X 9600, B9600, X 19200, EXTA, X 0, 0, X }; X struct Speedtab *sp; X int speed = atoi(s); X X for (sp = speedtab; sp->speed; sp++) X if (sp->speed == speed) X return (sp->code); X return (0); X} X X/* usage - explain */ X Xusage() X{ X error("usage: %s [-a alternate_rates] [-h] [-m] [-t timeout] line baud_rate", X progname); X} X X/* error - report errors to the console; only understands %s */ X X#define str2cpy(b,s1,s2) strcat(strcpy(b,s1),s2) X X/* VARARGS */ X Xerror(va_alist) Xva_dcl X{ X va_list ap; X char *fmt; X int fd; X int err = errno; X char buf[BUFSIZ]; X char *bp; X X if ((fd = open("/dev/console", 1)) >= 0) { X (void) str2cpy(buf, progname, ": "); X bp = buf + strlen(buf); X X /* X * %s expansion is done by hand. The program would become three times X * as big if we would use the stdio library... X */ X X va_start(ap); X fmt = va_arg(ap, char *); X while (*fmt) { X if (strncmp(fmt, "%s", 2) == 0) { X (void) strcat(bp, va_arg(ap, char *)); X bp += strlen(bp); X fmt += 2; X } else { X *bp++ = *fmt++; X } X } X *bp = 0; X va_end(ap); X X /* Add system error message if errno was set */ X X if (err) X (void) str2cpy(bp, ": ", sys_errlist[errno]); X X /* Terminate with CR-LF since the console mode is unknown */ X X (void) strcat(bp, "\r\n"); X (void) write(fd, buf, strlen(buf)); X (void) close(fd); X } X (void) sleep(5); /* be kind to init */ X exit(1); X} X END_OF_FILE if test 20261 -ne `wc -c <'agetty.c'`; then echo shar: \"'agetty.c'\" unpacked with wrong size! fi # end of 'agetty.c' fi if test -f 'agetty.8' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'agetty.8'\" else echo shar: Extracting \"'agetty.8'\" \(3388 characters\) sed "s/^X//" >'agetty.8' <<'END_OF_FILE' X.TH AGETTY 8 X.ad X.fi X.SH NAME Xagetty X\- Xalternative System-V getty X.SH SYNOPSIS X.na X.nf Xagetty [-a alternate_rates] [-h] [-m] [-t timeout] port baud_rate X.SH DESCRIPTION X.ad X.fi X\fIagetty\fR opens a tty port, prompts for a login name and invokes the X/bin/login command. It is normally invoked by \fIinit(8)\fR. X X\fIagetty\fR has some useful features not present in the System XV Release 2 getty command: X.IP o XAdapts the tty settings to parity bits and to Xerase, kill and end-of-line characters found in its input. The Xprogram understands 7-bit characters with even, odd, none or space Xparity, and 8-bit characters with no parity. The following special Xcharacters are recognized: @ and Control-U (kill); #, DEL and Xbackspace (erase); carriage-return and linefeed (end of line). X.IP o XOptionally recognizes the baud rate of incoming Xcalls from the status messages produced by some multi-speed Hayes (tm) Xmodem clones. X.PP XThis program does not use the \fI/etc/gettydefs\fR file. Except for Xdifferences described here the program appears to operate similar Xto the System-V Release 2 \fIgetty\fR program. X XOptions: X.TP X-a alternate_rates XInitially the program will use the \fIbaud_rate\fR as specified. XUpon receipt of successive BREAK characters the program will step Xthrough the \fIalternate_rates\fR, which should be specified as a Xcomma-separated list (preferably in decreasing order). After all X\fIalternate_rates\fR have been tried, \fIagetty\fR will try the Xspeed specified with the \fIbaud_rate\fR argument and so on. X.TP X-h XDo not hang up the line. Normally, \fIagetty\fR will lower XDTR for two seconds to force a modem to hang up (if the hangup Xfeature has been compiled into the program). X.TP X-m XTry to extract the baud rate of incoming calls from the status message Xproduced by some Hayes (tm) multi-speed modem clones. These usually Xproduce a status message of the form: "". XIf no \fIspeed\fR is found within one second, the \fIbaud_rate\fR as Xspecified on the command line will be used. Since this feature will Xwork only on lightly-loaded systems, you will probably want to use this Xfeature in combination with the \fI-a\fR option. X.TP X-t timeout XCauses the program to terminate if no user name could be read Xwithin \fItimeout\fR seconds. This is useful only for dial-in lines. X.SH EXAMPLES X.na X.nf XFor hard-wired lines: X.ti +5 X/etc/agetty ttyM0 9600 X XFor dial-in lines with a 300/1200/2400 baud Hayes clone: X.ti +5 X/etc/agetty -t60 -m -a1200,300 ttyM1 2400 X.SH FILES X.na X.nf X/etc/utmp, the system log file. X.SH BUGS X.ad X.fi XThe baud-rate detection code (the \fI-m\fR option) only works if X\fIagetty\fR is scheduled soon enough after completion of a dial-in Xcall (within 30 ms with modems that talk at 2400 baud). For robustness, Xalways use the \fI-m\fR option in combination with the \fI-a\fR option. X XThe login prompt is always output with space parity. X.SH DIAGNOSTICS X.ad X.fi XAll diagnostics are written to the console. X XIn particular, \fIagetty\fR will detect if it is asked to open Xsometing that is not a terminal. X.SH AUTHOR(S) X.na X.nf XW.Z. Venema Xwietse@wzv.win.tue.nl XEindhoven University of Technology XDepartment of Mathematics and Computer Science XDen Dolech 2, P.O. Box 513, 5600 MB Eindhoven, The Netherlands X.SH CREATION DATE X.na X.nf XSat Nov 25 22:51:05 MET 1989 X.SH LAST MODIFICATION X.na X.nf X89/12/11 23:02:55 X.SH VERSION/RELEASE X.na X.nf X1.20 END_OF_FILE if test 3388 -ne `wc -c <'agetty.8'`; then echo shar: \"'agetty.8'\" unpacked with wrong size! fi # end of 'agetty.8' fi if test -f 'Makefile' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'Makefile'\" else echo shar: Extracting \"'Makefile'\" \(257 characters\) sed "s/^X//" >'Makefile' <<'END_OF_FILE' X# @(#) Makefile 1.3 11/26/89 22:20:28 X XSHELL = /bin/sh XCFLAGS = -s -O XFILES = README agetty.c agetty.8 Makefile X Xagetty: agetty.c X cc $(CFLAGS) -o $@ $? X Xclean: X rm -f agetty.o agetty X Xshar: $(FILES) X @shar $(FILES) X Xagetty.8: X srctoman agetty.c >agetty.8 END_OF_FILE if test 257 -ne `wc -c <'Makefile'`; then echo shar: \"'Makefile'\" unpacked with wrong size! fi # end of 'Makefile' fi echo shar: End of shell archive. exit 0