X-Git-Url: https://git.subgeniuskitty.com/unix-history/.git/blobdiff_plain/177ed6dd1e65d2fc8530a445552a9f4fa8de9354..9c50374f0792e9289728367cb68f8e6448721f05:/usr/src/usr.bin/tset/tset.c diff --git a/usr/src/usr.bin/tset/tset.c b/usr/src/usr.bin/tset/tset.c index f652019025..0e9372a0d8 100644 --- a/usr/src/usr.bin/tset/tset.c +++ b/usr/src/usr.bin/tset/tset.c @@ -1,15 +1,40 @@ /* -# define DEB + * Copyright (c) 1980 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the University of California, Berkeley. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#ifndef lint +char copyright[] = +"@(#) Copyright (c) 1980 Regents of the University of California.\n\ + All rights reserved.\n"; +#endif /* not lint */ + +#ifndef lint +static char sccsid[] = "@(#)tset.c 5.11 (Berkeley) %G%"; +#endif /* not lint */ + /* ** TSET -- set terminal modes ** ** This program does sophisticated terminal initialization. -** I recommend that you include it in your .start_up or .login +** I recommend that you include it in your .profile 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) +** A special file or sequence (as controlled by the termcap file) ** is sent to the terminal. ** ** Mode bits are set on a per-terminal_type basis (much better @@ -31,18 +56,16 @@ ** 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] +** tset [-] [-EC] [-eC] [-kC] [-iC] [-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. +** eval `tset -s ...` +** Actually, this doesn't work in old csh's. ** Instead, use: ** tset -s ... > tset.tmp ** source tset.tmp @@ -70,18 +93,21 @@ ** 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. +** C defaults to control-H. If not specified, +** the erase character is untouched; however, if +** not specified and the erase character is NULL +** (zero byte), the erase character is set to delete. ** -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. +** (zero byte), the kill character is set to control-U. +** -iC -- set the interrupt character to C on all terminals. +** Default for C is control-C. If not specified, the +** interrupt character is untouched; however, if +** not specified and the interrupt character is NULL +** (zero byte), the interrupt character is set to +** control-C. ** -qC -- reserved for setable quit character. ** -m -- map the system identified type to some user ** specified type. The mapping can be baud rate @@ -89,18 +115,23 @@ ** (-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 +** where: ``identifier'' is terminal type found in +** /etc/ttys 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. +** -n -- If the new tty driver from UCB is available, this flag +** will activate the new options for erase and kill +** processing. This will be different for printers +** and crt's. For crts, if the baud rate is < 1200 then +** erase and kill don't remove characters from the screen. ** -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. +** when htmp is somehow wrong. (V6 only) ** -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 @@ -122,9 +153,14 @@ ** -Q -- be quiet. don't output 'Erase set to' etc. ** -I -- don't do terminal initialization (is & if ** strings). +** -v -- On virtual terminal systems, don't set up a +** virtual terminal. Otherwise tset will tell +** the operating system what kind of terminal you +** are on (if it is a known terminal) and fix up +** the output of -s to use virtual terminal sequences. ** ** Files: -** /etc/ttytype +** /etc/ttys ** contains a terminal id -> terminal type ** mapping; used when any user mapping is specified, ** or the environment doesn't have TERM set. @@ -138,11 +174,11 @@ ** 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. +** DIALUP -- the type code for a dialup port. +** PLUGBOARD -- the type code for a plugboard port. +** ARPANET -- the type code for an arpanet port. ** BACKSPACE -- control-H, the default for -e. -** CONTROLX -- control-X, the default for -k. +** CNTL('X') -- 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 @@ -154,19 +190,18 @@ ** and compiles code to look there. ** ** Requires: -** Routines to handle htmp, ttytype, and ttycap. +** Routines to handle htmp, ttys, 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. +** OLDDIALUP -- accept the -d flag. +** OLDPLUGBOARD -- accept the -p flag. +** OLDARPANET -- accept the -a flag. ** 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. +** GTTYN -- if set, compiles code to look at /etc/ttys. +** UCB_NTTY -- set to handle new tty driver modes. ** ** Trace Flags: ** none @@ -205,13 +240,19 @@ ** where 'bin' should be whoever owns the 'htmp' file. ** If 'htmp' is 666, then tset need not be setuid. ** +** For version 6 the compile command should be: +** cc -n -O -I/usr/include/retrofit tset.c -ltermlib -lretro -lS +** ** Author: ** Eric Allman ** Electronics Research Labs ** U.C. Berkeley ** ** History: -** 7/80 -- '-S' added. -m mapping added. TERMCAP string +** 1/81 -- Added alias checking for mapping identifiers. +** 9/80 -- Added UCB_NTTY mods to setup the new tty driver. +** Added the 'reset ...' invocation. +** 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 @@ -226,7 +267,7 @@ ** 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. +** FILEDES. ** 9/78 -- '-' and '-p' options added (now fully ** compatible with ttytype!), and spaces are ** permitted between the -d and the type. @@ -236,35 +277,96 @@ ** 10/77 -- Written. */ -/* -# define FULLLOGIN 1 -*/ +#define UCB_NTTY + +# ifdef USG +# define index strchr +# define rindex strrchr +# define curerase mode.c_cc[VERASE] +# define curkill mode.c_cc[VKILL] +# define curintr mode.c_cc[VINTR] +# define olderase oldmode.c_cc[VERASE] +# define oldkill oldmode.c_cc[VKILL] +# define oldintr oldmode.c_cc[VINTR] +# else +# define curerase mode.sg_erase +# define curkill mode.sg_kill +# define curintr tchar.t_intrc +# define olderase oldmode.sg_erase +# define oldkill oldmode.sg_kill +# define oldintr oldtchar.t_intrc +# endif + # ifndef V6 -# define GTTYN "/etc/ttytype" +# define GTTYN +# include +# endif + +# ifndef USG +# include +# else +# include # endif -# include -# include # include +# include +# ifdef V6 +# include +# endif -# define BACKSPACE ('H' & 037) -# define CONTROLX ('X' & 037) +# define YES 1 +# define NO 0 +#undef CNTL +# define CNTL(c) ((c)&037) +# define BACKSPACE (CNTL('H')) +# define CHK(val, dft) (val<=0 ? dft : val) +# define isdigit(c) (c >= '0' && c <= '9') +# define isalnum(c) (c > ' ' && (index("<@=>!:|\177", c) == NULL)) # define OLDERASE '#' # define OLDKILL '@' - -# define FILEDES 2 -# define STDOUT 1 - -# ifdef V6 +# define OLDINTR '\177' /* del */ + +/* default special characters */ +#ifndef CERASE +#define CERASE '\177' +#endif +#ifndef CKILL +#define CKILL CNTL('U') +#endif +#ifndef CINTR +#define CINTR CNTL('C') +#endif +#ifndef CDSUSP +#define CQUIT 034 /* FS, ^\ */ +#define CSTART CNTL('Q') +#define CSTOP CNTL('S') +#define CEOF CNTL('D') +#define CEOT CEOF +#define CBRK 0377 +#define CSUSP CNTL('Z') +#define CDSUSP CNTL('Y') +#define CRPRNT CNTL('R') +#define CFLUSH CNTL('O') +#define CWERASE CNTL('W') +#define CLNEXT CNTL('V') +#endif + +# define FILEDES 2 /* do gtty/stty on this descriptor */ +# define STDOUT 1 /* output of -s/-S to this descriptor */ + +# 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" +# ifdef UCB_NTTY +# define USAGE "usage: tset [-] [-nrsIQS] [-eC] [-kC] [-iC] [-m [ident][test speed]:type] [type]\n" +# else +# define USAGE "usage: tset [-] [-rsIQS] [-eC] [-kC] [-iC] [-m [ident][test speed]:type] [type]\n" +# endif +# define OLDFLAGS # define DIALUP "dialup" # define OLDDIALUP "sd" # define PLUGBOARD "plugboard" @@ -272,16 +374,14 @@ /*** # define ARPANET "arpanet" # define OLDARPANET "sa" -***/ -# define OLDFLAGS +/***/ +# define DEFTYPE "unknown" # ifdef GTTYN -typedef char *ttyid_t; # define NOTTY 0 # else -typedef char ttyid_t; # define NOTTY 'x' # endif @@ -310,54 +410,106 @@ struct map { struct map *Map = map; +/* This should be available in an include file */ struct { char *string; int speed; + int baudrate; } 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", B0, 0, + "50", B50, 50, + "75", B75, 75, + "110", B110, 110, + "134", B134, 134, + "134.5",B134, 134, + "150", B150, 150, + "200", B200, 200, + "300", B300, 300, + "600", B600, 600, + "1200", B1200, 1200, + "1800", B1800, 1800, + "2400", B2400, 2400, + "4800", B4800, 4800, + "9600", B9600, 9600, + "19200",EXTA, 19200, + "exta", EXTA, 19200, + "extb", EXTB, 38400, 0, }; +#ifdef CBVIRTTERM +struct vterm { + char cap[2]; + char *value; +} vtab [] = { + "al", "\033\120", + "cd", "\033\114", + "ce", "\033\113", + "cm", "\033\107%r%.%.", + "cl", "\033\112", + "dc", "\033\115", + "dl", "\033\116", + "ic", "\033\117", + "kl", "\033\104", + "kr", "\033\103", + "ku", "\033\101", + "kd", "\033\102", + "kh", "\033\105", + "nd", "\033\103", + "se", "\033\142\004", + "so", "\033\141\004", + "ue", "\033\142\001", + "up", "\033\101", + "us", "\033\141\001", + "\0\0", NULL, +}; + +int VirTermNo = -2; +int HasAM; /* True if terminal has automatic margins */ +# endif CBVIRTTERM + char Erase_char; /* new erase character */ char Kill_char; /* new kill character */ +char Intr_char; /* new interrupt character */ char Specialerase; /* set => Erase_char only on terminals with backspace */ -ttyid_t Ttyid = NOTTY; /* terminal identifier */ +# ifdef GTTYN +char *Ttyid = NOTTY; /* terminal identifier */ +# else +char Ttyid = NOTTY; /* terminal identifier */ +# endif char *TtyType; /* type of terminal */ char *DefType; /* default type if none other computed */ char *NewType; /* mapping identifier based on old flags */ +int Mapped; /* mapping has been specified */ 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 IsReset; /* invoked as reset */ 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 */ +int DoVirtTerm = YES; /* Set up a virtual terminal */ +int PadBaud; /* Min rate of padding needed */ +int lines, columns; # define CAPBUFSIZ 1024 char Capbuf[CAPBUFSIZ]; /* line from /etc/termcap for this TtyType */ char *Ttycap; /* termcap line from termcap or environ */ +char Aliasbuf[128]; +char *Alias[16]; + +extern char *strcpy(); +extern char *index(); +extern char *tgetstr(); +extern int prc(); + struct delay { int d_delay; @@ -366,72 +518,191 @@ struct delay # include "tset.delays.h" +# ifndef USG +struct sgttyb mode; +struct sgttyb oldmode; +struct tchars tchar; +struct tchars oldtchar; +# else +struct termio mode; +struct termio oldmode; +# endif +# ifdef CBVIRTTERM +struct termcb block = {0, 2, 0, 0, 0, 20}; +# endif CBVIRTTERM main(argc, argv) int argc; char *argv[]; { - struct sgttyb mode; - struct sgttyb oldmode; - char buf[256]; + char buf[CAPBUFSIZ]; + char termbuf[32]; auto char *bufp; register char *p; char *command; register int i; +# ifdef CBVIRTTERM + int j; +# endif CBVIRTTERM int Break; int Not; - int Mapped; - extern char *nextarg(); - extern char *mapped(); + char *nextarg(); + char *mapped(); + extern char *rindex(); + struct winsize win; # ifdef V6 extern char *hsgettype(); # else extern char *getenv(); # endif # ifdef GTTYN - extern char *stypeof(); + char *stypeof(); extern char *ttyname(); - extern char *tgetstr(); # endif char bs_char; int csh; - extern prc(); + int settle; + int setmode(); extern char PC; +# ifdef V6 + extern int ospeed; +# else extern short ospeed; +# endif +# ifdef UCB_NTTY + int lmode; + int ldisc; + (void) ioctl(FILEDES, TIOCLGET, (char *)&lmode); + (void) ioctl(FILEDES, TIOCGETD, (char *)&ldisc); +# endif + +# ifndef USG if (gtty(FILEDES, &mode) < 0) +# else + if (ioctl(FILEDES, TCGETA, (char *)&mode) < 0) +# endif { prs("Not a terminal\n"); exit(1); } - bmove(&mode, &oldmode, sizeof mode); - ospeed = mode.sg_ospeed; + bmove((char *)&mode, (char *)&oldmode, sizeof mode); +# ifdef TIOCGETC + (void) ioctl(FILEDES, TIOCGETC, (char *)&tchar); + bmove((char *)&tchar, (char *)&oldtchar, sizeof tchar); +# endif +# ifndef USG + ospeed = mode.sg_ospeed & 017; +# else + ospeed = mode.c_cflag & CBAUD; +# endif + (void) signal(SIGINT, setmode); + (void) signal(SIGQUIT, setmode); + (void) signal(SIGTERM, setmode); - /* scan argument list and collect flags */ - command = argv[0]; - if (argc == 2 && argv[1][0] == '-' && argv[1][1] == '\0') + if (command = rindex(argv[0], '/')) + command++; + else + command = argv[0]; + if (sequal(command, "reset") ) { - RepOnly++; - Dash_u++; + /* + * reset the teletype mode bits to a sensible state. + * Copied from the program by Kurt Shoens & Mark Horton. + * Very useful after crapping out in raw. + */ +# ifndef V6 +# ifdef UCB_NTTY + struct ltchars ltc; + + if (ldisc == NTTYDISC) + { + (void) ioctl(FILEDES, TIOCGLTC, (char *)<c); + ltc.t_suspc = CHK(ltc.t_suspc, CSUSP); + ltc.t_dsuspc = CHK(ltc.t_dsuspc, CDSUSP); + ltc.t_rprntc = CHK(ltc.t_rprntc, CRPRNT); + ltc.t_flushc = CHK(ltc.t_flushc, CFLUSH); + ltc.t_werasc = CHK(ltc.t_werasc, CWERASE); + ltc.t_lnextc = CHK(ltc.t_lnextc, CLNEXT); + (void) ioctl(FILEDES, TIOCSLTC, (char *)<c); + } +# endif UCB_NTTY +# ifndef USG +# ifdef TIOCGETC + tchar.t_intrc = CHK(tchar.t_intrc, CINTR); + tchar.t_quitc = CHK(tchar.t_quitc, CQUIT); + tchar.t_startc = CHK(tchar.t_startc, CSTART); + tchar.t_stopc = CHK(tchar.t_stopc, CSTOP); + tchar.t_eofc = CHK(tchar.t_eofc, CEOF); + /* brkc is left alone */ + (void) ioctl(FILEDES, TIOCSETC, (char *)&tchar); +# endif TIOCGETC + mode.sg_flags &= ~(RAW +# ifdef CBREAK + |CBREAK +# endif CBREAK + |VTDELAY|ALLDELAY); + mode.sg_flags |= XTABS|ECHO|CRMOD|ANYP; + curerase = CHK(curerase, CERASE); + curkill = CHK(curkill, CKILL); + curintr = CHK(curintr, CINTR); +# else USG + (void) ioctl(FILEDES, TCGETA, (char *)&mode); + curerase = CHK(curerase, OLDERASE); + curkill = CHK(curkill, OLDKILL); + curintr = CHK(curintr, OLDINTR); + mode.c_cc[VQUIT] = CHK(mode.c_cc[VQUIT], CQUIT); + mode.c_cc[VEOF] = CHK(mode.c_cc[VEOF], CEOF); + + mode.c_iflag |= (BRKINT|ISTRIP|ICRNL|IXON); + mode.c_iflag &= ~(IGNBRK|PARMRK|INPCK|INLCR|IGNCR|IUCLC|IXOFF); + mode.c_oflag |= (OPOST|ONLCR); + mode.c_oflag &= ~(OLCUC|OCRNL|ONOCR|ONLRET|OFILL|OFDEL| + NLDLY|CRDLY|TABDLY|BSDLY|VTDLY|FFDLY); + mode.c_cflag |= (CS7|CREAD); + mode.c_cflag &= ~(CSIZE|PARODD|CLOCAL); + mode.c_lflag |= (ISIG|ICANON|ECHO|ECHOK); + mode.c_lflag &= ~(XCASE|ECHONL|NOFLSH); + (void) ioctl(FILEDES, TCSETAW, (char *)&mode); +# endif USG +# endif V6 + Dash_u = YES; + BeQuiet = YES; + IsReset = YES; + } + else if (argc == 2 && sequal(argv[1], "-")) + { + RepOnly = YES; + Dash_u = YES; } argc--; + + /* scan argument list and collect flags */ while (--argc >= 0) { p = *++argv; if (*p == '-') { if (*++p == NULL) - Report++; /* report current terminal type */ + Report = YES; /* report current terminal type */ else while (*p) switch (*p++) { +# ifdef UCB_NTTY + case 'n': + ldisc = NTTYDISC; + if (ioctl(FILEDES, TIOCSETD, (char *)&ldisc)<0) + fatal("ioctl ", "new"); + continue; +# endif + case 'r': /* report to user */ - Ureport++; + Ureport = YES; continue; case 'E': /* special erase: operate on all but TTY33 */ - Specialerase++; + Specialerase = YES; /* explicit fall-through to -e case */ case 'e': /* erase character */ @@ -440,20 +711,44 @@ char *argv[]; else { if (*p == '^' && p[1] != NULL) - Erase_char = *++p & 037; + if (*++p == '?') + Erase_char = '\177'; + else + Erase_char = CNTL(*p); else Erase_char = *p; p++; } continue; +# if defined(USG) || defined(TIOCGETC) + case 'i': /* interrupt character */ + if (*p == NULL) + Intr_char = CNTL('C'); + else + { + if (*p == '^' && p[1] != NULL) + if (*++p == '?') + Intr_char = '\177'; + else + Intr_char = CNTL(*p); + else + Intr_char = *p; + p++; + } + continue; +# endif + case 'k': /* kill character */ if (*p == NULL) - Kill_char = CONTROLX; + Kill_char = CNTL('X'); else { if (*p == '^' && p[1] != NULL) - Kill_char = *++p & 037; + if (*++p == '?') + Kill_char = '\177'; + else + Kill_char = CNTL(*p); else Kill_char = *p; p++; @@ -487,7 +782,7 @@ mapold: Map->Ident = NewType; } Map->Type = p; Map++; - Mapped++; + Mapped = YES; p = ""; continue; # endif @@ -509,8 +804,8 @@ mapold: Map->Ident = NewType; } else Map->Ident = ""; - Break = 0; - Not = 0; + Break = NO; + Not = NO; while (!Break) switch (*p) { case NULL: @@ -519,7 +814,7 @@ mapold: Map->Ident = NewType; case ':': /* mapped type */ *p++ = NULL; - Break++; + Break = YES; continue; case '>': /* conditional */ @@ -554,7 +849,7 @@ mapold: Map->Ident = NewType; p++; } else - Break++; + Break = YES; continue; } if (Not) /* invert sense of test */ @@ -568,37 +863,41 @@ mapold: Map->Ident = NewType; Map->Type = p; p = ""; Map++; - Mapped++; + Mapped = YES; continue; case 'h': /* don't get type from htmp or env */ - Dash_h++; + Dash_h = YES; continue; case 'u': /* don't update htmp */ - Dash_u++; + Dash_u = YES; continue; case 's': /* output setenv commands */ - DoSetenv++; - CmndLine++; + DoSetenv = YES; + CmndLine = YES; continue; case 'S': /* output setenv strings */ - DoSetenv++; - CmndLine=0; + DoSetenv = YES; + CmndLine = NO; continue; case 'Q': /* be quiet */ - BeQuiet++; + BeQuiet = YES; continue; case 'I': /* no initialization */ - NoInit++; + NoInit = YES; continue; case 'A': /* Ask user */ - Ask++; + Ask = YES; + continue; + + case 'v': /* no virtual terminal */ + DoVirtTerm = NO; continue; default: @@ -626,8 +925,17 @@ mapold: Map->Ident = NewType; } # ifndef V6 + /* + * Get rid of $TERMCAP, if it's there, so we get a real + * entry from /etc/termcap. This prevents us from being + * fooled by out of date stuff in the environment, and + * makes tabs work right on CB/Unix. + */ + bufp = getenv("TERMCAP"); + if (bufp && *bufp != '/') + (void) strcpy(bufp-8, "NOTHING"); /* overwrite only "TERMCAP" */ /* get current idea of terminal type from environment */ - if (!Dash_h && !Mapped && TtyType == 0) + if (!Dash_h && TtyType == 0) TtyType = getenv("TERM"); # endif @@ -674,43 +982,48 @@ mapold: Map->Ident = NewType; /* check for dialup or other mapping */ if (Mapped) - TtyType = mapped(TtyType, ospeed); + { + if (!(Alias[0] && isalias(TtyType))) + if (tgetent(Capbuf, TtyType) > 0) + makealias(Capbuf); + TtyType = mapped(TtyType); + } /* TtyType now contains a pointer to the type of the terminal */ /* If the first character is '?', ask the user */ if (TtyType[0] == '?') { - Ask++; + Ask = YES; TtyType++; if (TtyType[0] == '\0') TtyType = DEFTYPE; } if (Ask) { +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) + i = read(2, termbuf, sizeof termbuf - 1); + if (i > 0) { - if (buf[i - 1] == '\n') + if (termbuf[i - 1] == '\n') i--; - buf[i] = '\0'; - if (buf[0] != '\0') - TtyType = buf; + termbuf[i] = '\0'; + if (termbuf[0] != '\0') + TtyType = termbuf; } } - if (Ttycap == 0) - { - /* get terminal capabilities */ + /* get terminal capabilities */ + if (!(Alias[0] && isalias(TtyType))) { switch (tgetent(Capbuf, TtyType)) { case -1: - prs("Cannot open termcap file\n"); + prs("Cannot find termcap\n"); flush(); exit(-1); @@ -719,10 +1032,17 @@ mapold: Map->Ident = NewType; prs(TtyType); prs(" unknown\n"); flush(); - exit(1); + if (DoSetenv) + { + TtyType = DEFTYPE; + Alias[0] = '\0'; + goto ask; + } + else + exit(1); } - Ttycap = Capbuf; } + Ttycap = Capbuf; if (!RepOnly) { @@ -739,7 +1059,7 @@ mapold: Map->Ident = NewType; bs_char = BACKSPACE; else bs_char = 0; - if (Erase_char == 0 && !tgetflag("os") && mode.sg_erase == OLDERASE) + if (Erase_char == 0 && !tgetflag("os") && curerase == OLDERASE) { if (tgetflag("bs") || bs_char != 0) Erase_char = -1; @@ -747,28 +1067,40 @@ mapold: Map->Ident = NewType; if (Erase_char < 0) Erase_char = (bs_char != 0) ? bs_char : BACKSPACE; - if (mode.sg_erase == 0) - mode.sg_erase = OLDERASE; + if (curerase == 0) + curerase = CERASE; if (Erase_char != 0) - mode.sg_erase = Erase_char; + curerase = Erase_char; + + if (curintr == 0) + curintr = CINTR; + if (Intr_char != 0) + curintr = Intr_char; - if (mode.sg_kill == 0) - mode.sg_kill = OLDKILL; + if (curkill == 0) + curkill = CKILL; if (Kill_char != 0) - mode.sg_kill = Kill_char; + curkill = Kill_char; /* set modes */ + PadBaud = tgetnum("pb"); /* OK if fails */ + for (i=0; speeds[i].string; i++) + if (speeds[i].baudrate == PadBaud) { + PadBaud = speeds[i].speed; + break; + } +# ifndef USG 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') + if (tgetflag("UC") || (command[0] & 0140) == 0100) mode.sg_flags |= LCASE; else if (tgetflag("LC")) mode.sg_flags &= ~LCASE; mode.sg_flags &= ~(EVENP | ODDP | RAW); -# ifndef V6 +# ifdef CBREAK mode.sg_flags &= ~CBREAK; # endif if (tgetflag("EP")) @@ -784,11 +1116,74 @@ mapold: Map->Ident = NewType; 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); + setdelay("dC", CRdelay, CRbits, &mode.c_oflag); + setdelay("dN", NLdelay, NLbits, &mode.c_oflag); + setdelay("dB", BSdelay, BSbits, &mode.c_oflag); + setdelay("dF", FFdelay, FFbits, &mode.c_oflag); + setdelay("dT", TBdelay, TBbits, &mode.c_oflag); + setdelay("dV", VTdelay, VTbits, &mode.c_oflag); + + if (tgetflag("UC") || (command[0] & 0140) == 0100) { + mode.c_iflag |= IUCLC; + mode.c_oflag |= OLCUC; + } + else if (tgetflag("LC")) { + mode.c_iflag &= ~IUCLC; + mode.c_oflag &= ~OLCUC; + } + mode.c_iflag &= ~(PARMRK|INPCK); + mode.c_lflag |= ICANON; + if (tgetflag("EP")) { + mode.c_cflag |= PARENB; + mode.c_cflag &= ~PARODD; + } + if (tgetflag("OP")) { + mode.c_cflag |= PARENB; + mode.c_cflag |= PARODD; + } + + mode.c_oflag |= ONLCR; + mode.c_iflag |= ICRNL; + mode.c_lflag |= ECHO; + mode.c_oflag |= TAB3; + if (tgetflag("NL")) { /* new line, not line feed */ + mode.c_oflag &= ~ONLCR; + mode.c_iflag &= ~ICRNL; + } + if (tgetflag("HD")) /* half duplex */ + mode.c_lflag &= ~ECHO; + if (tgetflag("pt")) /* print tabs */ + mode.c_oflag &= ~TAB3; + + mode.c_lflag |= (ECHOE|ECHOK); +# endif +# ifdef CBVIRTTERM + HasAM = tgetflag("am"); +# endif CBVIRTTERM +# ifdef UCB_NTTY + if (ldisc == NTTYDISC) + { + lmode |= LCTLECH; /* display ctrl chars */ + if (tgetflag("hc")) + { /** set printer modes **/ + lmode &= ~(LCRTBS|LCRTERA|LCRTKIL); + lmode |= LPRTERA; + } + else + { /** set crt modes **/ + if (!tgetflag("os")) + { + lmode &= ~LPRTERA; + lmode |= LCRTBS; + if (mode.sg_ospeed >= B1200) + lmode |= LCRTERA|LCRTKIL; + } + } + } + if (IsReset) + lmode &= ~(LMDMBUF|LLITOUT|LPASS8); + (void) ioctl(FILEDES, TIOCLSET, (char *)&lmode); # endif /* get pad character */ @@ -796,22 +1191,81 @@ mapold: Map->Ident = NewType; if (tgetstr("pc", &bufp) != 0) PC = buf[0]; + columns = tgetnum("co"); + lines = tgetnum("li"); + + /* Set window size */ + (void) ioctl(FILEDES, TIOCGWINSZ, (char *)&win); + if (win.ws_row == 0 && win.ws_col == 0 && + lines > 0 && columns > 0) { + win.ws_row = lines; + win.ws_col = columns; + (void) ioctl(FILEDES, TIOCSWINSZ, (char *)&win); + } /* output startup string */ if (!NoInit) { +# ifndef USG + if (oldmode.sg_flags&(XTABS|CRMOD)) + { + oldmode.sg_flags &= ~(XTABS|CRMOD); + setmode(-1); + } +# else + if (oldmode.c_oflag&(TAB3|ONLCR|OCRNL|ONLRET)) + { + oldmode.c_oflag &= (TAB3|ONLCR|OCRNL|ONLRET); + setmode(-1); + } +# endif +# ifdef CBVIRTTERM + block.st_termt = 0; + (void) ioctl(FILEDES, LDSETT, (char *)&block); +# endif CBVIRTTERM + if (settabs()) { + settle = YES; + flush(); + } bufp = buf; - if (tgetstr("is", &bufp) != 0) + if (IsReset && tgetstr("rs", &bufp) != 0 || + tgetstr("is", &bufp) != 0) + { tputs(buf, 0, prc); - flush(); + settle = YES; + flush(); + } bufp = buf; - if (tgetstr("if", &bufp) != 0) + if (IsReset && tgetstr("rf", &bufp) != 0 || + tgetstr("if", &bufp) != 0) + { cat(buf); - sleep(1); /* let terminal settle down */ + settle = YES; + } + if (settle) + { + prc('\r'); + flush(); + sleep(1); /* let terminal settle down */ + } } +# ifdef CBVIRTTERM + if (DoVirtTerm) { + j = tgetnum("vt"); + VirTermNo = -1; + for (i=0; vt_map[i].stdnum; i++) + if (vt_map[i].stdnum == j) + VirTermNo = vt_map[i].localnum; + } else + VirTermNo = -1; +# endif CBVIRTTERM + + setmode(0); /* set new modes, if they've changed */ + /* set up environment for the shell we are using */ - /* (this code is rather heuristic) */ - csh = 0; + /* (this code is rather heuristic, checking for $SHELL */ + /* ending in the 3 characters "csh") */ + csh = NO; if (DoSetenv) { # ifndef V6 @@ -819,92 +1273,86 @@ mapold: Map->Ident = NewType; 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 = sequal(&sh[i-3], "csh")) && CmndLine) + (void) write(STDOUT, "set noglob;\n", 12); } if (!csh) # endif - /* running system shell */ - write(STDOUT, "export TERMCAP TERM;\n", 21); + /* running Bourne shell */ + (void) 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 type is the short name, find first alias (if any) */ + makealias(Ttycap); + if (sequal(TtyType, Alias[0]) && Alias[1]) { + TtyType = Alias[1]; + } + if (DoSetenv) { if (csh) { if (CmndLine) - write(STDOUT, "setenv TERM ", 12); - write(STDOUT, bufp, p - bufp); - write(STDOUT, " ", 1); + (void) write(STDOUT, "setenv TERM ", 12); + (void) write(STDOUT, TtyType, strlen(TtyType)); + (void) write(STDOUT, " ", 1); if (CmndLine) - write(STDOUT, ";\n", 2); + (void) write(STDOUT, ";\n", 2); } else { - write(STDOUT, "TERM=", 5); - write(STDOUT, bufp, p - bufp); - write(STDOUT, ";\n", 2); + (void) write(STDOUT, "TERM=", 5); + (void) write(STDOUT, TtyType, strlen(TtyType)); + (void) write(STDOUT, ";\n", 2); } } - if (Report && !DoSetenv) + else if (Report) { - write(STDOUT, bufp, p - bufp); - write(STDOUT, "\n", 1); + (void) write(STDOUT, TtyType, strlen(TtyType)); + (void) write(STDOUT, "\n", 1); } if (Ureport) { - *p = '\0'; prs("Terminal type is "); - prs(bufp); + prs(TtyType); prs("\n"); flush(); } - *p = i; + if (DoSetenv) { if (csh) { - if (CmndLine) - write(STDOUT, "setenv TERMCAP '", 16); + if (CmndLine) + (void) write(STDOUT, "setenv TERMCAP '", 16); } else - write(STDOUT, "TERMCAP='", 9); + (void) write(STDOUT, "TERMCAP='", 9); wrtermcap(Ttycap); if (csh) { if (CmndLine) { - write(STDOUT, "';\n", 3); - write(STDOUT, "unset noglob;\n", 14); + (void) write(STDOUT, "';\n", 3); + (void) write(STDOUT, "unset noglob;\n", 14); } } else - write(STDOUT, "';\n", 3); + (void) 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); + /* tell about changing erase, kill and interrupt characters */ + reportek("Erase", curerase, olderase, OLDERASE); + reportek("Kill", curkill, oldkill, OLDKILL); + reportek("Interrupt", curintr, oldintr, OLDINTR); # ifdef V6 /* update htmp */ @@ -932,6 +1380,130 @@ mapold: Map->Ident = NewType; exit(0); } +/* + * Set the hardware tabs on the terminal, using the ct (clear all tabs), + * st (set one tab) and ch (horizontal cursor addressing) capabilities. + * This is done before if and is, so they can patch in case we blow this. + */ +settabs() +{ + char caps[100]; + char *capsp = caps; + char *clear_tabs, *set_tab, *set_column, *set_pos; + char *tg_out, *tgoto(); + int c; + + clear_tabs = tgetstr("ct", &capsp); + set_tab = tgetstr("st", &capsp); + set_column = tgetstr("ch", &capsp); + if (set_column == 0) + set_pos = tgetstr("cm", &capsp); + + if (clear_tabs && set_tab) { + prc('\r'); /* force to be at left margin */ + tputs(clear_tabs, 0, prc); + } + if (set_tab) { + for (c=8; c 0. + * if called from terminal init, flag == -1 means reset "oldmode". + * called with flag == 0 at end of normal mode processing. + */ +{ +# ifndef USG + struct sgttyb *ttymode; +# else + struct termio *ttymode; +# endif +# ifdef TIOCGETC + struct tchars *ttytchars; +# endif + + if (flag < 0) { /* unconditionally reset oldmode (called from init) */ + ttymode = &oldmode; +# ifdef TIOCGETC + ttytchars = &oldtchar; +# endif + } else if (!bequal((char *)&mode, (char *)&oldmode, sizeof mode)) { + ttymode = &mode; +# ifdef TIOCGETC + ttytchars = &tchar; +# endif + } else { /* don't need it */ +# ifndef USG + ttymode = (struct sgttyb *)0; +# else + ttymode = (struct termio *)0; +# endif +# ifdef TIOCGETC + ttytchars = (struct tchars *)0; +# endif + } + + if (ttymode) + { +# ifdef USG + (void) ioctl(FILEDES, TCSETAW, (char *)ttymode); +# else +# ifndef V6 + /* don't flush */ + (void) ioctl(FILEDES, TIOCSETN, (char *)ttymode); +# else + stty(FILEDES, ttymode); +# endif +# endif + } +# ifdef TIOCGETC + if (ttytchars) { + (void) ioctl(FILEDES, TIOCSETC, (char *)ttytchars); + } +# endif +# ifdef CBVIRTTERM + if (VirTermNo != -2) { + int r1, r2; + extern int errno; + + r1 = ioctl(FILEDES, LDGETT, (char *)&block); + block.st_flgs |= TM_SET; + block.st_termt = VirTermNo; + if (block.st_termt < 0) + block.st_termt = 0; + if (!HasAM) + block.st_flgs |= TM_ANL; + else + block.st_flgs &= ~TM_ANL; + r2 = ioctl(FILEDES, LDSETT, (char *)&block); + } +# endif + + if (flag > 0) /* trapped signal */ + exit(1); +} + reportek(name, new, old, def) char *name; char old; @@ -941,6 +1513,8 @@ char def; register char o; register char n; register char *p; + char buf[32]; + char *bufp; if (BeQuiet) return; @@ -954,18 +1528,22 @@ char def; prs(" is "); else prs(" set to "); - if (n < 040) + bufp = buf; + if (tgetstr("kb", &bufp) > 0 && n == buf[0] && buf[1] == NULL) + prs("Backspace\n"); + else if (n == 0177) + prs("Delete\n"); + else { - prs("control-"); - n = (n & 037) | 0100; - } else if (n == 0177) { - prs("delete\n"); - flush(); - return; + if (n < 040) + { + prs("Ctrl-"); + n ^= 0100; + } + p = "x\n"; + p[0] = n; + prs(p); } - p = "x\n"; - p[0] = n; - prs(p); flush(); } @@ -976,15 +1554,23 @@ setdelay(cap, dtab, bits, flags) char *cap; struct delay dtab[]; int bits; -int *flags; +short *flags; { register int i; register struct delay *p; +# ifdef V6 + extern int ospeed; +# else + extern short ospeed; +# endif /* see if this capability exists at all */ i = tgetnum(cap); if (i < 0) i = 0; + /* No padding at speeds below PadBaud */ + if (PadBaud > ospeed) + i = 0; /* clear out the bits, replace with new ones */ *flags &= ~bits; @@ -1016,7 +1602,7 @@ char OutBuf[256]; int OutPtr; prc(c) - char c; +char c; { OutBuf[OutPtr++] = c; if (OutPtr >= sizeof OutBuf) @@ -1026,7 +1612,7 @@ prc(c) flush() { if (OutPtr > 0) - write(2, OutBuf, OutPtr); + (void) write(2, OutBuf, OutPtr); OutPtr = 0; } @@ -1045,14 +1631,13 @@ char *file; prs(file); prs("\n"); flush(); - exit(-1); + return; } - flush(); while ((i = read(fd, buf, BUFSIZ)) > 0) - write(FILEDES, buf, i); + (void) write(FILEDES, buf, i); - close(fd); + (void) close(fd); } @@ -1075,7 +1660,7 @@ int length; -bequal(a, b, len) +bequal(a, b, len) /* must be same thru len chars */ char *a; char *b; int len; @@ -1087,14 +1672,14 @@ int len; p = a; q = b; - while (*p && *q && (*p == *q) && --i > 0) + while ((*p == *q) && --i > 0) { p++; q++; } return ((*p == *q) && i >= 0); } -sequal(a, b) +sequal(a, b) /* must be same thru NULL */ char *a; char *b; { @@ -1107,23 +1692,57 @@ char *b; return (*p == *q); } +makealias(buf) +char *buf; +{ + register int i; + register char *a; + register char *b; + + Alias[0] = a = Aliasbuf; + b = buf; + i = 1; + while (*b && *b != ':') { + if (*b == '|') { + *a++ = NULL; + Alias[i++] = a; + b++; + } + else + *a++ = *b++; + } + *a = NULL; + Alias[i] = NULL; +# ifdef DEB + for(i = 0; Alias[i]; printf("A:%s\n", Alias[i++])); +# endif +} + +isalias(ident) /* is ident same as one of the aliases? */ +char *ident; +{ + char **a = Alias; + + if (*a) + while (*a) + if (sequal(ident, *a)) + return(YES); + else + a++; + return(NO); +} + # 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; + struct ttyent *t; if (ttyid == NOTTY) return (DEFTYPE); - f = fopen(GTTYN, "r"); - if (f == NULL) - return (DEFTYPE); /* split off end of name */ TtyId = ttyid; @@ -1132,51 +1751,21 @@ char *ttyid; TtyId = ttyid; /* scan the file */ - while (fgets(typebuf, sizeof typebuf, f) != NULL) + if ((t = getttynam(TtyId)) != 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); + PortType = t->ty_type; + /* get aliases from termcap entry */ + if (Mapped && tgetent(Capbuf, PortType) > 0) { + makealias(Capbuf); + if (sequal(Alias[0], PortType) && Alias[1]) + PortType = Alias[1]; } + return (PortType); } - fclose (f); return (DEFTYPE); } # endif -#define YES 1 -#define NO 0 /* * routine to output the string for the environment TERMCAP variable */ @@ -1192,6 +1781,9 @@ char *bp; char *tp; char *putbuf(); int space, empty; +# ifdef CBVIRTTERM + register int i; +# endif CBVIRTTERM /* discard names with blanks */ /** May not be desireable ? **/ @@ -1212,6 +1804,12 @@ char *bp; } /**/ +# ifdef CBVIRTTERM + if (VirTermNo > 0) { + p = putbuf(p, ":am"); /* All virt terms have auto margins */ + cancelled("am"); + } +# endif while (*bp) { switch (*bp) { case ':': /* discard empty, cancelled or dupl fields */ @@ -1221,10 +1819,47 @@ char *bp; empty = (empty && WHITE(*tp) ); tp++; } +# ifdef CBVIRTTERM + /* + * Virtual terminals use ic, not im or ei. Turn + * any of them into ic - duplicates will be cancelled + * below. I assume that terminals needing im+ic+ei + * are handled by the kernel. + */ + if (VirTermNo > 0 && !HasAM && + (bp[1]=='i' && bp[2]=='m' || + bp[1]=='e' && bp[2]=='i')) { + bp[1] = 'i'; + bp[2] = 'c'; + } + if (VirTermNo > 0 && !HasAM && + (bp[1]=='c' && bp[2]=='s')) { + bp[1] = 'd'; + bp[2] = 'l'; + /* Also need al, so kludge: */ + if (!cancelled("al")) + p = putbuf(p, ":al=\033\120"); + } +# endif CBVIRTTERM if (empty || cancelled(bp+1)) { bp = tp; continue; } +# ifdef CBVIRTTERM + if (VirTermNo > 0 && !HasAM) + for (i = 0; vtab[i].value; i++) { + if (vtab[i].cap[0] == bp[1] && + vtab[i].cap[1] == bp[2]) { + *p++ = *bp++; /* colon */ + *p++ = *bp++; /* first char */ + *p++ = *bp++; /* second " */ + *p++ = *bp++; /* = sign */ + p = putbuf(p, vtab[i].value); + bp = tp; + goto contin; + } + } +# endif CBVIRTTERM break; case ' ': /* no spaces in output */ @@ -1232,6 +1867,16 @@ char *bp; bp++; continue; + case '!': /* the shell thinks this is history */ + p = putbuf(p, "\\041"); + bp++; + continue; + + case ',': /* the shell thinks this is history */ + p = putbuf(p, "\\054"); + bp++; + continue; + case '"': /* no quotes in output */ p = putbuf(p, "\\042"); bp++; @@ -1242,13 +1887,28 @@ char *bp; bp++; continue; + case '`': /* no back quotes in output */ + p = putbuf(p, "\\140"); + bp++; + continue; + case '\\': case '^': /* anything following is OK */ *p++ = *bp++; +# ifdef CBVIRTTERM + if (*bp == 'E' && VirTermNo > 0 && + (bp[-3]!='\\'||bp[-2]!='E') && + (bp[1]!='\\'||bp[2]!='E')) + p = putbuf(p, "E\\"); +# endif CBVIRTTERM } *p++ = *bp++; +# ifdef CBVIRTTERM +contin: ; +# endif CBVIRTTERM } - write (STDOUT, buf, p-buf); + *p++ = ':'; /* we skipped the last : with the : lookahead hack */ + (void) write (STDOUT, buf, p-buf); } cancelled(cap) @@ -1273,8 +1933,23 @@ putbuf(ptr, str) char *ptr; char *str; { - while (*str) - *ptr++ = *str++; + char buf[20]; + + while (*str) { + switch (*str) { + case '\033': + ptr = putbuf(ptr, "\\E"); + str++; + break; + default: + if (*str <= ' ') { + (void) sprintf(buf, "\\%03o", *str); + ptr = putbuf(ptr, buf); + str++; + } else + *ptr++ = *str++; + } + } return (ptr); } @@ -1295,20 +1970,24 @@ char *p; } char * -mapped(type, speed) +mapped(type) char *type; -short speed; { +# ifdef V6 + extern int ospeed; +# else + extern short ospeed; +# endif int match; # ifdef DEB - printf ("spd:%d\n", speed); + printf ("spd:%d\n", ospeed); prmap(); # endif Map = map; while (Map->Ident) { - if (*(Map->Ident) == NULL || bequal(Map->Ident, type, 4)) + if (*(Map->Ident) == NULL || sequal(Map->Ident, type) || isalias(Map->Ident)) { match = NO; switch (Map->Test) @@ -1319,27 +1998,27 @@ short speed; break; case GT: - match = (speed > Map->Speed); + match = (ospeed > Map->Speed); break; case GE: - match = (speed >= Map->Speed); + match = (ospeed >= Map->Speed); break; case EQ: - match = (speed == Map->Speed); + match = (ospeed == Map->Speed); break; case LE: - match = (speed <= Map->Speed); + match = (ospeed <= Map->Speed); break; case LT: - match = (speed < Map->Speed); + match = (ospeed < Map->Speed); break; case NE: - match = (speed != Map->Speed); + match = (ospeed != Map->Speed); break; } if (match)