From 4b52d01b64a75dbf0a098a021a771cffb055b33a Mon Sep 17 00:00:00 2001 From: Bill Joy Date: Wed, 30 Jul 1980 02:57:02 -0800 Subject: [PATCH 1/1] BSD 4 development Work on file usr/src/cmd/tset/tset.c Synthesized-from: CSRG//cd1/4.0 --- usr/src/cmd/tset/tset.c | 1385 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 1385 insertions(+) create mode 100644 usr/src/cmd/tset/tset.c diff --git a/usr/src/cmd/tset/tset.c b/usr/src/cmd/tset/tset.c new file mode 100644 index 0000000000..bfca60ae20 --- /dev/null +++ b/usr/src/cmd/tset/tset.c @@ -0,0 +1,1385 @@ +/* +# define DEB +/* +** TSET -- set terminal modes +** +** This program does sophisticated terminal initialization. +** I recommend that you include it in your .start_up or .login +** file to initialize whatever terminal you are on. +** +** There are several features: +** +** A special file or sequence (as controlled by the ttycap file) +** is sent to the terminal. +** +** Mode bits are set on a per-terminal_type basis (much better +** than UNIX itself). This allows special delays, automatic +** tabs, etc. +** +** Erase and Kill characters can be set to whatever you want. +** Default is to change erase to control-H on a terminal which +** can overstrike, and leave it alone on anything else. Kill +** is always left alone unless specifically requested. These +** characters can be represented as "^X" meaning control-X; +** X is any character. +** +** Terminals which are dialups or plugboard types can be aliased +** to whatever type you may have in your home or office. Thus, +** if you know that when you dial up you will always be on a +** TI 733, you can specify that fact to tset. You can represent +** a type as "?type". This will ask you what type you want it +** to be -- if you reply with just a newline, it will default +** to the type given. +** +** The htmp file, used by ex, etc., can be updated. +** +** The current terminal type can be queried. +** +** Usage: +** tset [-] [-EC] [-eC] [-kC] [-s] [-h] [-u] [-r] +** [-m [ident] [test baudrate] :type] +** [-Q] [-I] [-S] [type] +** +** In systems with environments, use: +** `tset -s ...` +** Actually, this doesn't work because of a shell bug. +** Instead, use: +** tset -s ... > tset.tmp +** source tset.tmp +** rm tset.tmp +** or: +** set noglob +** set term=(`tset -S ....`) +** setenv TERM $term[1] +** setenv TERMCAP "$term[2]" +** unset term +** unset noglob +** +** Positional Parameters: +** type -- the terminal type to force. If this is +** specified, initialization is for this +** terminal type. +** +** Flags: +** - -- report terminal type. Whatever type is +** decided on is reported. If no other flags +** are stated, the only affect is to write +** the terminal type on the standard output. +** -r -- report to user in addition to other flags. +** -EC -- set the erase character to C on all terminals +** except those which cannot backspace (e.g., +** a TTY 33). C defaults to control-H. +** -eC -- set the erase character to C on all terminals. +** C defaults to control-H. If neither -E or -e +** are specified, the erase character is set to +** control-H if the terminal can both backspace +** and not overstrike (e.g., a CRT). If the erase +** character is NULL (zero byte), it will be reset +** to '#' if nothing else is specified. +** -kC -- set the kill character to C on all terminals. +** Default for C is control-X. If not specified, +** the kill character is untouched; however, if +** not specified and the kill character is NULL +** (zero byte), the kill character is set to '@'. +** -iC -- reserved for setable interrupt character. +** -qC -- reserved for setable quit character. +** -m -- map the system identified type to some user +** specified type. The mapping can be baud rate +** dependent. This replaces the old -d, -p flags. +** (-d type -> -m dialup:type) +** (-p type -> -m plug:type) +** Syntax: -m identifier [test baudrate] :type +** where: ``identifier'' is whatever is found in +** /etc/ttytype for this port, (abscence of an identifier +** matches any identifier); ``test'' may be any combination +** of > = < ! @; ``baudrate'' is as with stty(1); +** ``type'' is the actual terminal type to use if the +** mapping condition is met. Multiple maps are scanned +** in order and the first match prevails. +** -h -- don't read htmp file. Normally the terminal type +** is determined by reading the htmp file or the +** environment (unless some mapping is specified). +** This forces a read of the ttytype file -- useful +** when htmp is somehow wrong. +** -u -- don't update htmp. It seemed like this should +** be put in. Note that htmp is never actually +** written if there are no changes, so don't bother +** bother using this for efficiency reasons alone. +** -s -- output setenv commands for TERM. This can be +** used with +** `tset -s ...` +** and is to be prefered to: +** setenv TERM `tset - ...` +** because -s sets the TERMCAP variable also. +** -S -- Similar to -s but outputs 2 strings suitable for +** use in csh .login files as follows: +** set noglob +** set term=(`tset -S .....`) +** setenv TERM $term[1] +** setenv TERMCAP "$term[2]" +** unset term +** unset noglob +** -Q -- be quiet. don't output 'Erase set to' etc. +** -I -- don't do terminal initialization (is & if +** strings). +** +** Files: +** /etc/ttytype +** contains a terminal id -> terminal type +** mapping; used when any user mapping is specified, +** or the environment doesn't have TERM set. +** /etc/termcap +** a terminal_type -> terminal_capabilities +** mapping. +** +** Return Codes: +** -1 -- couldn't open ttycap. +** 1 -- bad terminal type, or standard output not tty. +** 0 -- ok. +** +** Defined Constants: +** DIALUP -- the type code for a dialup port +** PLUGBOARD -- the code for a plugboard port. +** ARPANET -- the code for an arpanet port. +** BACKSPACE -- control-H, the default for -e. +** CONTROLX -- control-X, the default for -k. +** OLDERASE -- the system default erase character. +** OLDKILL -- the system default kill character. +** FILEDES -- the file descriptor to do the operation +** on, nominally 1 or 2. +** STDOUT -- the standard output file descriptor. +** UIDMASK -- the bit pattern to mask with the getuid() +** call to get just the user id. +** GTTYN -- defines file containing generalized ttynames +** and compiles code to look there. +** +** Requires: +** Routines to handle htmp, ttytype, and ttycap. +** +** Compilation Flags: +** OLDDIALUP -- accept the -d flag. Map "sd" to "dialup". +** OLDPLUGBOARD -- accept the -p flag. Map "sp" to "plugboard". +** OLDARPANET -- accept the -a flag. Map "sa" to "arpanet". +** OLDFLAGS -- must be defined to compile code for any of +** the -d, -p, or -a flags. +** FULLLOGIN -- if defined, login sets the ttytype from +** /etc/ttytype file. +** V6 -- if clear, use environments, not htmp. +** also use TIOCSETN rather than stty to avoid flushing +** GTTYN -- if set, compiles code to look at /etc/ttytype. +** +** Trace Flags: +** none +** +** Diagnostics: +** Bad flag +** An incorrect option was specified. +** Too few args +** more command line arguments are required. +** Unexpected arg +** wrong type of argument was encountered. +** Cannot open ... +** The specified file could not be openned. +** Type ... unknown +** An unknown terminal type was specified. +** Cannot update htmp +** Cannot update htmp file when the standard +** output is not a terminal. +** Erase set to ... +** Telling that the erase character has been +** set to the specified character. +** Kill set to ... +** Ditto for kill +** Erase is ... Kill is ... +** Tells that the erase/kill characters were +** wierd before, but they are being left as-is. +** Not a terminal +** Set if FILEDES is not a terminal. +** +** Compilation Instructions: +** cc -n -O tset.c -ltermlib +** mv a.out tset +** chown bin tset +** chmod 4755 tset +** +** where 'bin' should be whoever owns the 'htmp' file. +** If 'htmp' is 666, then tset need not be setuid. +** +** Author: +** Eric Allman +** Electronics Research Labs +** U.C. Berkeley +** +** History: +** 7/80 -- '-S' added. -m mapping added. TERMCAP string +** cleaned up. +** 3/80 -- Changed to use tputs. Prc & flush added. +** 10/79 -- '-s' option extended to handle TERMCAP +** variable, set noglob, quote the entry, +** and know about the Bourne shell. Terminal +** initialization moved to before any information +** output so screen clears would not screw you. +** '-Q' option added. +** 8/79 -- '-' option alone changed to only output +** type. '-s' option added. 'VERSION7' +** changed to 'V6' for compatibility. +** 12/78 -- modified for eventual migration to VAX/UNIX, +** so the '-' option is changed to output only +** the terminal type to STDOUT instead of +** FILEDES. FULLLOGIN flag added. +** 9/78 -- '-' and '-p' options added (now fully +** compatible with ttytype!), and spaces are +** permitted between the -d and the type. +** 8/78 -- The sense of -h and -u were reversed, and the +** -f flag is dropped -- same effect is available +** by just stating the terminal type. +** 10/77 -- Written. +*/ + +/* +# define FULLLOGIN 1 +*/ +# ifndef V6 +# define GTTYN "/etc/ttytype" +# endif + +# include +# include +# include + +# define BACKSPACE ('H' & 037) +# define CONTROLX ('X' & 037) +# define OLDERASE '#' +# define OLDKILL '@' + +# define FILEDES 2 +# define STDOUT 1 + +# ifdef V6 +# define UIDMASK 0377 +# else +# define UIDMASK -1 +# endif + +# define DEFTYPE "unknown" +# define USAGE\ +"usage: tset [-] [-hrsuIQS] [-eC] [-kC] [-m [ident][test speed]:type] [type]\n" + +# define DIALUP "dialup" +# define OLDDIALUP "sd" +# define PLUGBOARD "plugboard" +# define OLDPLUGBOARD "sp" +/*** +# define ARPANET "arpanet" +# define OLDARPANET "sa" +***/ +# define OLDFLAGS + + + +# ifdef GTTYN +typedef char *ttyid_t; +# define NOTTY 0 +# else +typedef char ttyid_t; +# define NOTTY 'x' +# endif + +/* + * Baud Rate Conditionals + */ +# define ANY 0 +# define GT 1 +# define EQ 2 +# define LT 4 +# define GE (GT|EQ) +# define LE (LT|EQ) +# define NE (GT|LT) +# define ALL (GT|EQ|LT) + + + +# define NMAP 10 + +struct map { + char *Ident; + char Test; + char Speed; + char *Type; +} map[NMAP]; + +struct map *Map = map; + +struct +{ + char *string; + int speed; +} speeds[] = { + "0", B0, + "50", B50, + "75", B75, + "110", B110, + "134", B134, + "134.5",B134, + "150", B150, + "200", B200, + "300", B300, + "600", B600, + "1200", B1200, + "1800", B1800, + "2400", B2400, + "4800", B4800, + "9600", B9600, + "exta", EXTA, + "extb", EXTB, + 0, +}; + +char Erase_char; /* new erase character */ +char Kill_char; /* new kill character */ +char Specialerase; /* set => Erase_char only on terminals with backspace */ + +ttyid_t Ttyid = NOTTY; /* terminal identifier */ +char *TtyType; /* type of terminal */ +char *DefType; /* default type if none other computed */ +char *NewType; /* mapping identifier based on old flags */ +int Dash_u; /* don't update htmp */ +int Dash_h; /* don't read htmp */ +int DoSetenv; /* output setenv commands */ +int BeQuiet; /* be quiet */ +int NoInit; /* don't output initialization string */ +int Report; /* report current type */ +int Ureport; /* report to user */ +int RepOnly; /* report only */ +int CmndLine; /* output full command lines (-s option) */ +int Ask; /* ask user for termtype */ + +# define CAPBUFSIZ 1024 +char Capbuf[CAPBUFSIZ]; /* line from /etc/termcap for this TtyType */ +char *Ttycap; /* termcap line from termcap or environ */ + +struct delay +{ + int d_delay; + int d_bits; +}; + +# include "tset.delays.h" + + + +main(argc, argv) +int argc; +char *argv[]; +{ + struct sgttyb mode; + struct sgttyb oldmode; + char buf[256]; + auto char *bufp; + register char *p; + char *command; + register int i; + int Break; + int Not; + int Mapped; + extern char *nextarg(); + extern char *mapped(); +# ifdef V6 + extern char *hsgettype(); +# else + extern char *getenv(); +# endif +# ifdef GTTYN + extern char *stypeof(); + extern char *ttyname(); + extern char *tgetstr(); +# endif + char bs_char; + int csh; + extern prc(); + extern char PC; + extern short ospeed; + + if (gtty(FILEDES, &mode) < 0) + { + prs("Not a terminal\n"); + exit(1); + } + bmove(&mode, &oldmode, sizeof mode); + ospeed = mode.sg_ospeed; + + /* scan argument list and collect flags */ + command = argv[0]; + if (argc == 2 && argv[1][0] == '-' && argv[1][1] == '\0') + { + RepOnly++; + Dash_u++; + } + argc--; + while (--argc >= 0) + { + p = *++argv; + if (*p == '-') + { + if (*++p == NULL) + Report++; /* report current terminal type */ + else while (*p) switch (*p++) + { + + case 'r': /* report to user */ + Ureport++; + continue; + + case 'E': /* special erase: operate on all but TTY33 */ + Specialerase++; + /* explicit fall-through to -e case */ + + case 'e': /* erase character */ + if (*p == NULL) + Erase_char = -1; + else + { + if (*p == '^' && p[1] != NULL) + Erase_char = *++p & 037; + else + Erase_char = *p; + p++; + } + continue; + + case 'k': /* kill character */ + if (*p == NULL) + Kill_char = CONTROLX; + else + { + if (*p == '^' && p[1] != NULL) + Kill_char = *++p & 037; + else + Kill_char = *p; + p++; + } + continue; + +# ifdef OLDFLAGS +# ifdef OLDDIALUP + case 'd': /* dialup type */ + NewType = DIALUP; + goto mapold; +# endif + +# ifdef OLDPLUGBOARD + case 'p': /* plugboard type */ + NewType = PLUGBOARD; + goto mapold; +# endif + +# ifdef OLDARPANET + case 'a': /* arpanet type */ + Newtype = ARPANET; + goto mapold; +# endif + +mapold: Map->Ident = NewType; + Map->Test = ALL; + if (*p == NULL) + { + p = nextarg(argc--, argv++); + } + Map->Type = p; + Map++; + Mapped++; + p = ""; + continue; +# endif + + case 'm': /* map identifier to type */ + /* This code is very loose. Almost no + ** syntax checking is done!! However, + ** illegal syntax will only produce + ** weird results. + */ + if (*p == NULL) + { + p = nextarg(argc--, argv++); + } + if (isalnum(*p)) + { + Map->Ident = p; /* identifier */ + while (isalnum(*p)) p++; + } + else + Map->Ident = ""; + Break = 0; + Not = 0; + while (!Break) switch (*p) + { + case NULL: + p = nextarg(argc--, argv++); + continue; + + case ':': /* mapped type */ + *p++ = NULL; + Break++; + continue; + + case '>': /* conditional */ + Map->Test |= GT; + *p++ = NULL; + continue; + + case '<': /* conditional */ + Map->Test |= LT; + *p++ = NULL; + continue; + + case '=': /* conditional */ + case '@': + Map->Test |= EQ; + *p++ = NULL; + continue; + + case '!': /* invert conditions */ + Not = ~Not; + *p++ = NULL; + continue; + + case 'B': /* Baud rate */ + p++; + /* intentional fallthru */ + default: + if (isdigit(*p) || *p == 'e') + { + Map->Speed = baudrate(p); + while (isalnum(*p) || *p == '.') + p++; + } + else + Break++; + continue; + } + if (Not) /* invert sense of test */ + { + Map->Test = (~(Map->Test))&ALL; + } + if (*p == NULL) + { + p = nextarg(argc--, argv++); + } + Map->Type = p; + p = ""; + Map++; + Mapped++; + continue; + + case 'h': /* don't get type from htmp or env */ + Dash_h++; + continue; + + case 'u': /* don't update htmp */ + Dash_u++; + continue; + + case 's': /* output setenv commands */ + DoSetenv++; + CmndLine++; + continue; + + case 'S': /* output setenv strings */ + DoSetenv++; + CmndLine=0; + continue; + + case 'Q': /* be quiet */ + BeQuiet++; + continue; + + case 'I': /* no initialization */ + NoInit++; + continue; + + case 'A': /* Ask user */ + Ask++; + continue; + + default: + *p-- = NULL; + fatal("Bad flag -", p); + } + } + else + { + /* terminal type */ + DefType = p; + } + } + + if (DefType) + { + if (Mapped) + { + Map->Ident = ""; /* means "map any type" */ + Map->Test = ALL; /* at all baud rates */ + Map->Type = DefType; /* to the default type */ + } + else + TtyType = DefType; + } + +# ifndef V6 + /* get current idea of terminal type from environment */ + if (!Dash_h && !Mapped && TtyType == 0) + TtyType = getenv("TERM"); +# endif + + /* determine terminal id if needed */ +# ifdef V6 + if (Ttyid == NOTTY && (TtyType == 0 || !Dash_h || !Dash_u)) + Ttyid = ttyn(FILEDES); +# else + if (!RepOnly && Ttyid == NOTTY && (TtyType == 0 || !Dash_h)) + Ttyid = ttyname(FILEDES); +# endif + +# ifdef V6 + /* get htmp if ever used */ + if (!Dash_u || (TtyType == 0 && !Dash_h)) + { + /* get htmp entry -- if error or wrong user use ttytype */ + if (Ttyid == NOTTY || hget(Ttyid) < 0 || + hgettype() == 0 || hgetuid() != (getuid() & UIDMASK)) + Dash_h++; + } + + /* find terminal type (if not already known) */ + if (TtyType == 0 && !Dash_h) + { + /* get type from /etc/htmp */ + TtyType = hsgettype(); + } +# endif + +# ifdef GTTYN + /* If still undefined, look at /etc/ttytype */ + if (TtyType == 0) + { + TtyType = stypeof(Ttyid); + } +# endif + + /* If still undefined, use DEFTYPE */ + if (TtyType == 0) + { + TtyType = DEFTYPE; + } + + /* check for dialup or other mapping */ + if (Mapped) + TtyType = mapped(TtyType, ospeed); + + /* TtyType now contains a pointer to the type of the terminal */ + /* If the first character is '?', ask the user */ + if (TtyType[0] == '?') + { + Ask++; + TtyType++; + if (TtyType[0] == '\0') + TtyType = DEFTYPE; + } + if (Ask) + { + prs("TERM = ("); + prs(TtyType); + prs(") "); + flush(); + + /* read the terminal. If not empty, set type */ + i = read(2, buf, sizeof buf - 1); + if (i >= 0) + { + if (buf[i - 1] == '\n') + i--; + buf[i] = '\0'; + if (buf[0] != '\0') + TtyType = buf; + } + } + + if (Ttycap == 0) + { + /* get terminal capabilities */ + switch (tgetent(Capbuf, TtyType)) + { + case -1: + prs("Cannot open termcap file\n"); + flush(); + exit(-1); + + case 0: + prs("Type "); + prs(TtyType); + prs(" unknown\n"); + flush(); + exit(1); + } + Ttycap = Capbuf; + } + + if (!RepOnly) + { + /* determine erase and kill characters */ + if (Specialerase && !tgetflag("bs")) + Erase_char = 0; + bufp = buf; + p = tgetstr("kb", &bufp); + if (p == NULL || p[1] != '\0') + p = tgetstr("bc", &bufp); + if (p != NULL && p[1] == '\0') + bs_char = p[0]; + else if (tgetflag("bs")) + bs_char = BACKSPACE; + else + bs_char = 0; + if (Erase_char == 0 && !tgetflag("os") && mode.sg_erase == OLDERASE) + { + if (tgetflag("bs") || bs_char != 0) + Erase_char = -1; + } + if (Erase_char < 0) + Erase_char = (bs_char != 0) ? bs_char : BACKSPACE; + + if (mode.sg_erase == 0) + mode.sg_erase = OLDERASE; + if (Erase_char != 0) + mode.sg_erase = Erase_char; + + if (mode.sg_kill == 0) + mode.sg_kill = OLDKILL; + if (Kill_char != 0) + mode.sg_kill = Kill_char; + + /* set modes */ + setdelay("dC", CRdelay, CRbits, &mode.sg_flags); + setdelay("dN", NLdelay, NLbits, &mode.sg_flags); + setdelay("dB", BSdelay, BSbits, &mode.sg_flags); + setdelay("dF", FFdelay, FFbits, &mode.sg_flags); + setdelay("dT", TBdelay, TBbits, &mode.sg_flags); + if (tgetflag("UC") || command[0] == 'T') + mode.sg_flags |= LCASE; + else if (tgetflag("LC")) + mode.sg_flags &= ~LCASE; + mode.sg_flags &= ~(EVENP | ODDP | RAW); +# ifndef V6 + mode.sg_flags &= ~CBREAK; +# endif + if (tgetflag("EP")) + mode.sg_flags |= EVENP; + if (tgetflag("OP")) + mode.sg_flags |= ODDP; + if ((mode.sg_flags & (EVENP | ODDP)) == 0) + mode.sg_flags |= EVENP | ODDP; + mode.sg_flags |= CRMOD | ECHO | XTABS; + if (tgetflag("NL")) /* new line, not line feed */ + mode.sg_flags &= ~CRMOD; + if (tgetflag("HD")) /* half duplex */ + mode.sg_flags &= ~ECHO; + if (tgetflag("pt")) /* print tabs */ + mode.sg_flags &= ~XTABS; + if (!bequal(&mode, &oldmode, sizeof mode)) +# ifndef V6 + ioctl(FILEDES, TIOCSETN, &mode); +# else + stty(FILEDES, &mode); +# endif + + /* get pad character */ + bufp = buf; + if (tgetstr("pc", &bufp) != 0) + PC = buf[0]; + + /* output startup string */ + if (!NoInit) + { + bufp = buf; + if (tgetstr("is", &bufp) != 0) + tputs(buf, 0, prc); + flush(); + bufp = buf; + if (tgetstr("if", &bufp) != 0) + cat(buf); + sleep(1); /* let terminal settle down */ + } + + /* set up environment for the shell we are using */ + /* (this code is rather heuristic) */ + csh = 0; + if (DoSetenv) + { +# ifndef V6 + char *sh; + + if ((sh = getenv("SHELL")) && (i = strlen(sh)) >= 3) + { + p = &sh[i-3]; + if ((csh = sequal(p, "csh")) && CmndLine) + write(STDOUT, "set noglob;\n", 12); + } + if (!csh) +# endif + /* running system shell */ + write(STDOUT, "export TERMCAP TERM;\n", 21); + } + } + + /* report type if appropriate */ + if (DoSetenv || Report || Ureport) + { + /* find first alias (if any) */ + for (p = Ttycap; *p != 0 && *p != '|' && *p != ':'; p++) + continue; + if (*p == 0 || *p == ':') + p = Ttycap; + else + p++; + bufp = p; + while (*p != '|' && *p != ':' && *p != 0) + p++; + i = *p; + if (DoSetenv) + { + if (csh) + { + if (CmndLine) + write(STDOUT, "setenv TERM ", 12); + write(STDOUT, bufp, p - bufp); + write(STDOUT, " ", 1); + if (CmndLine) + write(STDOUT, ";\n", 2); + } + else + { + write(STDOUT, "TERM=", 5); + write(STDOUT, bufp, p - bufp); + write(STDOUT, ";\n", 2); + } + } + if (Report && !DoSetenv) + { + write(STDOUT, bufp, p - bufp); + write(STDOUT, "\n", 1); + } + if (Ureport) + { + *p = '\0'; + prs("Terminal type is "); + prs(bufp); + prs("\n"); + flush(); + } + *p = i; + if (DoSetenv) + { + if (csh) + { + if (CmndLine) + write(STDOUT, "setenv TERMCAP '", 16); + } + else + write(STDOUT, "TERMCAP='", 9); + wrtermcap(Ttycap); + if (csh) + { + if (CmndLine) + { + write(STDOUT, "';\n", 3); + write(STDOUT, "unset noglob;\n", 14); + } + } + else + write(STDOUT, "';\n", 3); + } + } + + if (RepOnly) + exit(0); + + /* tell about changing erase and kill characters */ + reportek("Erase", mode.sg_erase, oldmode.sg_erase, OLDERASE); + reportek("Kill", mode.sg_kill, oldmode.sg_kill, OLDKILL); + +# ifdef V6 + /* update htmp */ + if (!Dash_u) + { + if (Ttyid == 0) + Ttyid = ttyn(FILEDES); + if (Ttyid == 'x') + { + prs("Cannot update htmp\n"); + flush(); + } + else + { + /* update htmp file only if changed */ + if (!bequal(Capbuf, hsgettype(), 2)) + { + hsettype(Capbuf[0] | (Capbuf[1] << 8)); + hput(Ttyid); + } + } + } +# endif + + exit(0); +} + +reportek(name, new, old, def) +char *name; +char old; +char new; +char def; +{ + register char o; + register char n; + register char *p; + + if (BeQuiet) + return; + o = old; + n = new; + + if (o == n && n == def) + return; + prs(name); + if (o == n) + prs(" is "); + else + prs(" set to "); + if (n < 040) + { + prs("control-"); + n = (n & 037) | 0100; + } + p = "x\n"; + p[0] = n; + prs(p); + flush(); +} + + + + +setdelay(cap, dtab, bits, flags) +char *cap; +struct delay dtab[]; +int bits; +int *flags; +{ + register int i; + register struct delay *p; + + /* see if this capability exists at all */ + i = tgetnum(cap); + if (i < 0) + i = 0; + + /* clear out the bits, replace with new ones */ + *flags &= ~bits; + + /* scan dtab for first entry with adequate delay */ + for (p = dtab; p->d_delay >= 0; p++) + { + if (p->d_delay >= i) + { + p++; + break; + } + } + + /* use last entry if none will do */ + *flags |= (--p)->d_bits; +} + + +prs(s) +char *s; +{ + while (*s != '\0') + prc(*s++); +} + + +char OutBuf[256]; +int OutPtr; + +prc(c) + char c; +{ + OutBuf[OutPtr++] = c; + if (OutPtr >= sizeof OutBuf) + flush(); +} + +flush() +{ + if (OutPtr > 0) + write(2, OutBuf, OutPtr); + OutPtr = 0; +} + + +cat(file) +char *file; +{ + register int fd; + register int i; + char buf[BUFSIZ]; + + fd = open(file, 0); + if (fd < 0) + { + prs("Cannot open "); + prs(file); + prs("\n"); + flush(); + exit(-1); + } + + flush(); + while ((i = read(fd, buf, BUFSIZ)) > 0) + write(FILEDES, buf, i); + + close(fd); +} + + + +bmove(from, to, length) +char *from; +char *to; +int length; +{ + register char *p, *q; + register int i; + + i = length; + p = from; + q = to; + + while (i-- > 0) + *q++ = *p++; +} + + + +bequal(a, b, len) +char *a; +char *b; +int len; +{ + register char *p, *q; + register int i; + + i = len; + p = a; + q = b; + + while (*p && *q && (*p == *q) && --i > 0) + { + p++; q++; + } + return ((*p == *q) && i >= 0); +} + +sequal(a, b) +char *a; +char *b; +{ + register char *p = a, *q = b; + + while (*p && *q && (*p == *q)) + { + p++; q++; + } + return (*p == *q); +} + +# ifdef GTTYN +char * +stypeof(ttyid) +char *ttyid; +{ + static char typebuf[50]; + register char *PortType; + register char *PortName; + register char *TtyId; + register char *p; + register FILE *f; + + if (ttyid == NOTTY) + return (DEFTYPE); + f = fopen(GTTYN, "r"); + if (f == NULL) + return (DEFTYPE); + + /* split off end of name */ + TtyId = ttyid; + while (*ttyid) + if (*ttyid++ == '/') + TtyId = ttyid; + + /* scan the file */ + while (fgets(typebuf, sizeof typebuf, f) != NULL) + { + p = PortType = typebuf; + while (*p && isalnum(*p)) + p++; + *p++ = NULL; + + /* skip separator */ + while (*p && !isalnum(*p)) + p++; + + PortName = p; + /* put NULL at end of name */ + while (*p && isalnum(*p)) + p++; + *p = NULL; + + /* check match on port name */ + if (sequal(PortName, TtyId)) /* found it */ + { +# ifdef OLDDIALUP + if (sequal(PortType, OLDDIALUP)) + PortType = DIALUP; +# endif + +# ifdef OLDPLUGBOARD + if (sequal(PortType, OLDPLUGBOARD)) + PortType = PLUGBOARD; +# endif + +# ifdef OLDARPANET + if (sequal(PortType, OLDARPANET)) + PortType = ARPANET; +# endif + fclose (f); + return(PortType); + } + } + fclose (f); + return (DEFTYPE); +} +# endif + +#define YES 1 +#define NO 0 +/* + * routine to output the string for the environment TERMCAP variable + */ +#define WHITE(c) (c == ' ' || c == '\t') +char delcap[128][2]; +int ncap = 0; + +wrtermcap(bp) +char *bp; +{ + char buf[CAPBUFSIZ]; + char *p = buf; + char *tp; + char *putbuf(); + int space, empty; + + /* discard names with blanks */ +/** May not be desireable ? **/ + while (*bp && *bp != ':') { + if (*bp == '|') { + tp = bp+1; + space = NO; + while (*tp && *tp != '|' && *tp != ':') { + space = (space || WHITE(*tp) ); + tp++; + } + if (space) { + bp = tp; + continue; + } + } + *p++ = *bp++; + } +/**/ + + while (*bp) { + switch (*bp) { + case ':': /* discard empty, cancelled or dupl fields */ + tp = bp+1; + empty = YES; + while (*tp && *tp != ':') { + empty = (empty && WHITE(*tp) ); + tp++; + } + if (empty || cancelled(bp+1)) { + bp = tp; + continue; + } + break; + + case ' ': /* no spaces in output */ + p = putbuf(p, "\\040"); + bp++; + continue; + + case '"': /* no quotes in output */ + p = putbuf(p, "\\042"); + bp++; + continue; + + case '\'': /* no quotes in output */ + p = putbuf(p, "\\047"); + bp++; + continue; + + case '\\': + case '^': /* anything following is OK */ + *p++ = *bp++; + } + *p++ = *bp++; + } + write (STDOUT, buf, p-buf); +} + +cancelled(cap) +char *cap; +{ + register int i; + + for (i = 0; i < ncap; i++) + { + if (cap[0] == delcap[i][0] && cap[1] == delcap[i][1]) + return (YES); + } + /* delete a second occurrance of the same capability */ + delcap[ncap][0] = cap[0]; + delcap[ncap][1] = cap[1]; + ncap++; + return (cap[2] == '@'); +} + +char * +putbuf(ptr, str) +char *ptr; +char *str; +{ + while (*str) + *ptr++ = *str++; + return (ptr); +} + + +baudrate(p) +char *p; +{ + char buf[8]; + int i = 0; + + while (i < 7 && (isalnum(*p) || *p == '.')) + buf[i++] = *p++; + buf[i] = NULL; + for (i=0; speeds[i].string; i++) + if (sequal(speeds[i].string, buf)) + return (speeds[i].speed); + return (-1); +} + +char * +mapped(type, speed) +char *type; +short speed; +{ + int match; + +# ifdef DEB + printf ("spd:%d\n", speed); + prmap(); +# endif + Map = map; + while (Map->Ident) + { + if (*(Map->Ident) == NULL || bequal(Map->Ident, type, 4)) + { + match = NO; + switch (Map->Test) + { + case ANY: /* no test specified */ + case ALL: + match = YES; + break; + + case GT: + match = (speed > Map->Speed); + break; + + case GE: + match = (speed >= Map->Speed); + break; + + case EQ: + match = (speed == Map->Speed); + break; + + case LE: + match = (speed <= Map->Speed); + break; + + case LT: + match = (speed < Map->Speed); + break; + + case NE: + match = (speed != Map->Speed); + break; + } + if (match) + return (Map->Type); + } + Map++; + } + /* no match found; return given type */ + return (type); +} + +# ifdef DEB +prmap() +{ + Map = map; + while (Map->Ident) + { + printf ("%s t:%d s:%d %s\n", + Map->Ident, Map->Test, Map->Speed, Map->Type); + Map++; + } +} +# endif + +char * +nextarg(argc, argv) +int argc; +char *argv[]; +{ + if (argc <= 0) + fatal ("Too few args: ", *argv); + if (*(*++argv) == '-') + fatal ("Unexpected arg: ", *argv); + return (*argv); +} + +fatal (mesg, obj) +char *mesg; +char *obj; +{ + prs (mesg); + prs (obj); + prc ('\n'); + prs (USAGE); + flush(); + exit(1); +} -- 2.20.1