diff options
| author | stevel@tonic-gate <none@none> | 2005-06-14 00:00:00 -0700 |
|---|---|---|
| committer | stevel@tonic-gate <none@none> | 2005-06-14 00:00:00 -0700 |
| commit | 7c478bd95313f5f23a4c958a745db2134aa03244 (patch) | |
| tree | c871e58545497667cbb4b0a4f2daf204743e1fe7 /usr/src/ucbcmd/tset | |
| download | illumos-joyent-7c478bd95313f5f23a4c958a745db2134aa03244.tar.gz | |
OpenSolaris Launch
Diffstat (limited to 'usr/src/ucbcmd/tset')
| -rw-r--r-- | usr/src/ucbcmd/tset/Makefile | 59 | ||||
| -rw-r--r-- | usr/src/ucbcmd/tset/tset.c | 1691 | ||||
| -rw-r--r-- | usr/src/ucbcmd/tset/tset.delays.h | 110 |
3 files changed, 1860 insertions, 0 deletions
diff --git a/usr/src/ucbcmd/tset/Makefile b/usr/src/ucbcmd/tset/Makefile new file mode 100644 index 0000000000..c185245555 --- /dev/null +++ b/usr/src/ucbcmd/tset/Makefile @@ -0,0 +1,59 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (the "License"). You may not use this file except in compliance +# with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# +#ident "%Z%%M% %I% %E% SMI" +# +# Copyright (c) 1989 by Sun Microsystems, Inc. +# + +PROG= tset + +include ../Makefile.ucbcmd + +FILEMODE= 755 + +#LDLIBS += -lcurses +LDLIBS = -L$(ROOT)/usr/ucblib $(LDLIBS.cmd) -lucb -ltermcap + +CPPFLAGS = -I$(ROOT)/usr/ucbinclude $(CPPFLAGS.master) + +ROOTSYMLINK= $(ROOTBIN)/reset + +.KEEP_STATE: + +all: $(PROG) + +$(PROG): $(PROG).c + $(SETRUNPATH) $(LINK.c) -o $@ $(PROG).c $(LDLIBS) + $(POST_PROCESS) + +install: all $(ROOTBIN) $(ROOTPROG) $(ROOTSYMLINK) + +$(ROOTSYMLINK): + $(RM) $@ + $(SYMLINK) $(PROG) $@ + +clean: + +lint: lint_PROG + +include ../Makefile.ucbtarg diff --git a/usr/src/ucbcmd/tset/tset.c b/usr/src/ucbcmd/tset/tset.c new file mode 100644 index 0000000000..4dc67a1975 --- /dev/null +++ b/usr/src/ucbcmd/tset/tset.c @@ -0,0 +1,1691 @@ +/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ +/* All Rights Reserved */ + + +/* + * Copyright (c) 1980 Regents of the University of California. + * All rights reserved. The Berkeley software License Agreement + * specifies the terms and conditions for redistribution. + */ + +/* + * Copyright (c) 1983 - 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#ident "%Z%%M% %I% %E% SMI" /* SVr4.0 1.1 */ + +/* +** TSET -- set terminal modes +** +** This program does sophisticated terminal initialization. +** 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 termcap 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 current terminal type can be queried. +** +** Usage: +** tset [-] [-EC] [-eC] [-kC] [-iC] [-s] [-h] [-u] [-r] +** [-m [ident] [test baudrate] :type] +** [-Q] [-I] [-S] [type] +** +** In systems with environments, use: +** eval `tset -s ...` +** Actually, this doesn't work in old csh's. +** 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 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 CERASE. +** -kC -- set the kill character to C on all terminals. +** Default for C is control-U. 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 CKILL. +** -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 +** 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 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. (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 +** 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). +** -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/ttys +** 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 termcap. +** 1 -- bad terminal type, or standard output not tty. +** 0 -- ok. +** +** Defined Constants: +** 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. +** CNTL('U') -- control-U, the default for -k. +** OLDERASE -- the ancient default erase 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, ttys, and termcap. +** +** Compilation Flags: +** OLDFLAGS -- must be defined to compile code for any of +** the -d, -p, or -a flags. +** 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/ttys. +** +** 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. +** +** For version 6 the compile command should be: +** cc -n -O -I/usr/include/retrofit tset.c -ltermlib -lretro -lS +** +** +** History: +** 1/81 -- Added alias checking for mapping identifiers. +** 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. +** 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 index strchr +#define rindex strrchr +#define curerase modes.c_cc[VERASE] +#define curkill modes.c_cc[VKILL] +#define curintr modes.c_cc[VINTR] +#define olderase oldmodes.c_cc[VERASE] +#define oldkill oldmodes.c_cc[VKILL] +#define oldintr oldmodes.c_cc[VINTR] + +#include <stdio.h> +#include <termio.h> +#include <signal.h> + + +#define YES 1 +#define NO 0 +#undef CNTL +#define CNTL(c) ((c)&037) +#define BACKSPACE (CNTL('H')) +#define isdigit(c) (c >= '0' && c <= '9') +#define isalnum(c) (c > ' ' && (index("<@=>!:|\177", c) == NULL)) +#define OLDERASE '#' + +/* 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 */ + +#define UIDMASK -1 + +#define USAGE "usage: tset [-] [-rsIQS] [-eC] [-kC] [-iC] [-m [ident][test speed]:type] [type]\n" + +#define OLDFLAGS +#define DIALUP "dialup" +#define OLDDIALUP "sd" +#define PLUGBOARD "plugboard" +#define OLDPLUGBOARD "sp" +/*** +#define ARPANET "arpanet" +#define OLDARPANET "sa" +/***/ + +#define DEFTYPE "unknown" + +#define NOTTY 'x' + +/* + * 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; + +/* This should be available in an include file */ +struct +{ + char *string; + int speed; + int baudrate; +} speeds[] = { + "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, + "57600",B57600, 57600, + "76800",B76800, 76800, + "115200",B115200,115200, + "153600",B153600,153600, + "230400",B230400,230400, + "307200",B307200,307200, + "460800",B460800,460800, + 0, +}; + +signed 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 */ + +char 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 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 */ + +#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(); + +struct delay +{ + int d_delay; + int d_bits; +}; + +#include "tset.delays.h" + +struct termio mode; +struct termio oldmode; +struct termios modes; +struct termios oldmodes; +int istermios; + +char reset(); /* Routine for checking&resetting chars */ +int prc(); + +main(argc, argv) +int argc; +char *argv[]; +{ + char buf[CAPBUFSIZ]; + char termbuf[32]; + auto char *bufp; + register char *p; + char *command; + register int i; + int Break; + int Not; + char *nextarg(); + char *mapped(); + extern char *rindex(); + struct winsize win; + extern char *getenv(); + extern char *tgetstr(); + char bs_char; + int csh; + int settle = NO; + void setmode(); + extern char PC; + extern short ospeed; + + if ((istermios = ioctl(FILEDES, TCGETS, (char *)&modes)) < 0) { + if (ioctl(FILEDES, TCGETA, (char *)&mode) < 0) + { + prs("Not a terminal\n"); + exit(1); + } + bmove((char *)&mode, (char *)&oldmode, sizeof mode); + modes.c_lflag = oldmodes.c_lflag = mode.c_lflag; + modes.c_oflag = oldmodes.c_oflag = mode.c_oflag; + modes.c_iflag = oldmodes.c_iflag = mode.c_iflag; + modes.c_cflag = oldmodes.c_cflag = mode.c_cflag; + for(i = 0; i < NCC; i++) + modes.c_cc[i] = oldmodes.c_cc[i] = mode.c_cc[i]; + } else + bmove((char *)&modes, (char *)&oldmodes, sizeof modes); + ospeed = cfgetospeed(&modes); + (void) signal(SIGINT, setmode); + (void) signal(SIGQUIT, setmode); + (void) signal(SIGTERM, setmode); + + if (command = rindex(argv[0], '/')) + command++; + else + command = argv[0]; + if (sequal(command, "reset") ) + { + /* + * 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. + */ + if ((istermios = ioctl(FILEDES, TCGETS, (char *)&modes)) < 0) { + (void) ioctl(FILEDES, TCGETA, (char *)&mode); + modes.c_lflag = mode.c_lflag; + modes.c_oflag = mode.c_oflag; + modes.c_iflag = mode.c_iflag; + modes.c_cflag = mode.c_cflag; + for(i = 0; i < NCC; i++) + modes.c_cc[i] = mode.c_cc[i]; + } + curerase = reset(curerase, CERASE); + curkill = reset(curkill, CKILL); + curintr = reset(curintr, CINTR); + modes.c_cc[VQUIT] = reset(modes.c_cc[VQUIT], CQUIT); + modes.c_cc[VEOF] = reset(modes.c_cc[VEOF], CEOF); + + modes.c_iflag |= (BRKINT|ISTRIP|ICRNL|IXON); + modes.c_iflag &= ~(IGNBRK|PARMRK|INPCK|INLCR|IGNCR|IUCLC|IXOFF); + modes.c_oflag |= (OPOST|ONLCR); + modes.c_oflag &= ~(OLCUC|OCRNL|ONOCR|ONLRET|OFILL|OFDEL| + NLDLY|CRDLY|TABDLY|BSDLY|VTDLY|FFDLY); + modes.c_cflag |= (CS7|CREAD); + modes.c_cflag &= ~(PARODD|CLOCAL); + modes.c_lflag |= (ISIG|ICANON|ECHO|ECHOK); + modes.c_lflag &= ~(XCASE|ECHONL|NOFLSH); + if (istermios < 0) { + mode.c_lflag = modes.c_lflag; + mode.c_oflag = modes.c_oflag; + mode.c_iflag = modes.c_iflag; + mode.c_cflag = modes.c_cflag; + for(i = 0; i < NCC; i++) + mode.c_cc[i] = modes.c_cc[i]; + (void) ioctl(FILEDES, TCSETAW, (char *)&mode); + } else + (void) ioctl(FILEDES, TCSETSW, (char *)&modes); + 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 = YES; /* report current terminal type */ + else while (*p) switch (*p++) + { + + case 'r': /* report to user */ + Ureport = YES; + continue; + + case 'E': /* special erase: operate on all but TTY33 */ + Specialerase = YES; + /* explicit fall-through to -e case */ + + case 'e': /* erase character */ + if (*p == NULL) + Erase_char = -1; + else + { + if (*p == '^' && p[1] != NULL) + if (*++p == '?') + Erase_char = '\177'; + else + Erase_char = CNTL(*p); + else + Erase_char = *p; + p++; + } + continue; + + 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; + + case 'k': /* kill character */ + if (*p == NULL) + Kill_char = CNTL('U'); + else + { + if (*p == '^' && p[1] != NULL) + if (*++p == '?') + Kill_char = '\177'; + else + Kill_char = CNTL(*p); + 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 = YES; + 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 = NO; + Not = NO; + while (!Break) switch (*p) + { + case NULL: + p = nextarg(argc--, argv++); + continue; + + case ':': /* mapped type */ + *p++ = NULL; + Break = YES; + 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 = YES; + 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 = YES; + continue; + + case 'h': /* don't get type from htmp or env */ + Dash_h = YES; + continue; + + case 'u': /* don't update htmp */ + Dash_u = YES; + continue; + + case 's': /* output setenv commands */ + DoSetenv = YES; + CmndLine = YES; + continue; + + case 'S': /* output setenv strings */ + DoSetenv = YES; + CmndLine = NO; + continue; + + case 'Q': /* be quiet */ + BeQuiet = YES; + continue; + + case 'I': /* no initialization */ + NoInit = YES; + continue; + + case 'A': /* Ask user */ + Ask = YES; + continue; + + case 'v': /* no virtual terminal */ + DoVirtTerm = NO; + 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; + } + + /* + * 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 && TtyType == 0) + TtyType = getenv("TERM"); + + if (!RepOnly && Ttyid == NOTTY && (TtyType == 0 || !Dash_h)) + Ttyid = ttyname(FILEDES); + + /* If still undefined, use DEFTYPE */ + if (TtyType == 0) + { + TtyType = DEFTYPE; + } + + /* check for dialup or other mapping */ + if (Mapped) + { + 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 = 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, termbuf, sizeof termbuf - 1); + if (i > 0) + { + if (termbuf[i - 1] == '\n') + i--; + termbuf[i] = '\0'; + if (termbuf[0] != '\0') + TtyType = termbuf; + } + } + + /* get terminal capabilities */ + if (!(Alias[0] && isalias(TtyType))) { + switch (tgetent(Capbuf, TtyType)) + { + case -1: + prs("Cannot find termcap\n"); + flush(); + exit(-1); + + case 0: + prs("Type "); + prs(TtyType); + prs(" unknown\n"); + flush(); + if (DoSetenv) + { + TtyType = DEFTYPE; + Alias[0] = '\0'; + goto ask; + } + else + 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; + /* + * The next statement can't be fixed, because now users + * depend on keeping their erase character as DEL if the + * system set it there. People who want backspace have + * to say tset -e. + */ + if (Erase_char == 0 && !tgetflag("os") && curerase == OLDERASE) + { + if (tgetflag("bs") || bs_char != 0) + Erase_char = -1; + } + if (Erase_char < 0) + Erase_char = (bs_char != 0) ? bs_char : BACKSPACE; + + if (curerase == 0) + curerase = CERASE; + if (Erase_char != 0) + curerase = Erase_char; + + if (curintr == 0) + curintr = CINTR; + if (Intr_char != 0) + curintr = Intr_char; + + if (curkill == 0) + curkill = CKILL; + if (Kill_char != 0) + 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; + } + setdelay("dC", CRdelay, CRbits, &modes.c_oflag); + setdelay("dN", NLdelay, NLbits, &modes.c_oflag); + setdelay("dB", BSdelay, BSbits, &modes.c_oflag); + setdelay("dF", FFdelay, FFbits, &modes.c_oflag); + setdelay("dT", TBdelay, TBbits, &modes.c_oflag); + setdelay("dV", VTdelay, VTbits, &modes.c_oflag); + + if (tgetflag("UC") || (command[0] & 0140) == 0100) { + modes.c_iflag |= IUCLC; + modes.c_oflag |= OLCUC; + modes.c_cflag |= XCASE; + } + else if (tgetflag("LC")) { + modes.c_iflag &= ~IUCLC; + modes.c_oflag &= ~OLCUC; + modes.c_cflag &= ~XCASE; + } + modes.c_iflag &= ~(PARMRK|INPCK); + modes.c_lflag |= ICANON; + if (tgetflag("EP")) { + modes.c_iflag |= INPCK; + modes.c_cflag |= PARENB; + modes.c_cflag &= ~PARODD; + } + if (tgetflag("OP")) { + modes.c_iflag |= INPCK; + modes.c_cflag |= PARENB; + modes.c_cflag |= PARODD; + } + + modes.c_oflag |= ONLCR; + modes.c_iflag |= ICRNL; + modes.c_lflag |= ECHO; + modes.c_oflag |= TAB3; + if (tgetflag("NL")) { /* new line, not line feed */ + modes.c_oflag &= ~ONLCR; + modes.c_iflag &= ~ICRNL; + } + if (tgetflag("HD")) /* half duplex */ + modes.c_lflag &= ~ECHO; + if (tgetflag("pt")) /* print tabs */ + modes.c_oflag &= ~TAB3; + + modes.c_lflag |= (ECHOE|ECHOK); + if (tgetflag("hc")) + { /** set printer modes **/ + modes.c_lflag &= ~ECHOE; + } + + /* get pad character */ + bufp = buf; + if (tgetstr("pc", &bufp) != 0) + PC = buf[0]; + + /* output startup string */ + if (!NoInit) + { + if (oldmodes.c_oflag&(TAB3|ONLCR|OCRNL|ONLRET)) + { + oldmodes.c_oflag &= (TAB3|ONLCR|OCRNL|ONLRET); + setmode(-1); + } + if (settabs()) { + settle = YES; + flush(); + } + bufp = buf; + if (IsReset && tgetstr("rs", &bufp) != 0 || + tgetstr("is", &bufp) != 0) + { + tputs(buf, 0, prc); + settle = YES; + flush(); + } + bufp = buf; + if (IsReset && tgetstr("rf", &bufp) != 0 || + tgetstr("if", &bufp) != 0) + { + cat(buf); + settle = YES; + } + if (settle) + { + prc('\r'); + if (IsReset) + prc('\n'); /* newline too */ + flush(); + sleep(1); /* let terminal settle down */ + } + } + + setmode(0); /* set new modes, if they've changed */ + + /* set up environment for the shell we are using */ + /* (this code is rather heuristic, checking for $SHELL */ + /* ending in the 3 characters "csh") */ + csh = NO; + if (DoSetenv) + { + char *sh; + + if ((sh = getenv("SHELL")) && (i = strlen(sh)) >= 3) + { + if ((csh = sequal(&sh[i-3], "csh")) && CmndLine) + (void) write(STDOUT, "set noglob;\n", 12); + } + if (!csh) + /* running Bourne shell */ + (void) write(STDOUT, "export TERMCAP TERM;\n", 21); + } + } + + /* report type if appropriate */ + if (DoSetenv || Report || Ureport) + { + /* 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) + (void) write(STDOUT, "setenv TERM ", 12); + (void) write(STDOUT, TtyType, strlen(TtyType)); + (void) write(STDOUT, " ", 1); + if (CmndLine) + (void) write(STDOUT, ";\n", 2); + } + else + { + (void) write(STDOUT, "TERM=", 5); + (void) write(STDOUT, TtyType, strlen(TtyType)); + (void) write(STDOUT, ";\n", 2); + } + } + else if (Report) + { + (void) write(STDOUT, TtyType, strlen(TtyType)); + (void) write(STDOUT, "\n", 1); + } + if (Ureport) + { + prs("Terminal type is "); + prs(TtyType); + prs("\n"); + flush(); + } + + if (DoSetenv) + { + if (csh) + { + if (CmndLine) + (void) write(STDOUT, "setenv TERMCAP '", 16); + } + else + (void) write(STDOUT, "TERMCAP='", 9); + wrtermcap(Ttycap); + if (csh) + { + if (CmndLine) + { + (void) write(STDOUT, "';\n", 3); + (void) write(STDOUT, "unset noglob;\n", 14); + } + } + else + (void) write(STDOUT, "';\n", 3); + } + } + + if (RepOnly) + exit(0); + + /* tell about changing erase, kill and interrupt characters */ + reportek("Erase", curerase, olderase, CERASE); + reportek("Kill", curkill, oldkill, CKILL); + reportek("Interrupt", curintr, oldintr, CINTR); + + 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; + extern char *tgetstr(); + int lines, columns; + + 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) { + columns = tgetnum("co"); + lines = tgetnum("li"); + for (c=0; c<columns; c += 8) { + /* get to that column. */ + tg_out = "OOPS"; /* also returned by tgoto */ + if (set_column) + tg_out = tgoto(set_column, 0, c); + if (*tg_out == 'O' && set_pos) + tg_out = tgoto(set_pos, c, lines-1); + if (*tg_out != 'O') + tputs(tg_out, 1, prc); + else if (c != 0) { + prc(' '); prc(' '); prc(' '); prc(' '); + prc(' '); prc(' '); prc(' '); prc(' '); + } + /* set the tab */ + tputs(set_tab, 0, prc); + } + prc('\r'); + return 1; + } + return 0; +} + +void setmode(flag) +int flag; +/* flag serves several purposes: + * if called as the result of a signal, flag will be > 0. + * if called from terminal init, flag == -1 means reset "oldmode". + * called with flag == 0 at end of normal mode processing. + */ +{ + struct termio *ttymode; + struct termios *ttymodes; + register int i; + + ttymode = (struct termio *)0; + ttymodes = (struct termios *)0; + + if (flag < 0) { /* unconditionally reset oldmode (called from init) */ + if (istermios < 0) { + oldmode.c_lflag = oldmodes.c_lflag; + oldmode.c_oflag = oldmodes.c_oflag; + oldmode.c_iflag = oldmodes.c_iflag; + oldmode.c_cflag = oldmodes.c_cflag; + for(i = 0; i < NCC; i++) + oldmode.c_cc[i] = oldmodes.c_cc[i]; + ttymode = &oldmode; + } else + ttymodes = &oldmodes; + } else { + if (istermios < 0) { + oldmode.c_lflag = oldmodes.c_lflag; + oldmode.c_oflag = oldmodes.c_oflag; + oldmode.c_iflag = oldmodes.c_iflag; + oldmode.c_cflag = oldmodes.c_cflag; + for(i = 0; i < NCC; i++) + oldmode.c_cc[i] = oldmodes.c_cc[i]; + mode.c_lflag = modes.c_lflag; + mode.c_oflag = modes.c_oflag; + mode.c_iflag = modes.c_iflag; + mode.c_cflag = modes.c_cflag; + for(i = 0; i < NCC; i++) + mode.c_cc[i] = modes.c_cc[i]; + if (!bequal((char *)&mode, (char *)&oldmode, sizeof mode)) + ttymode = &mode; + } else if (!bequal((char *)&modes, (char *)&oldmodes, + sizeof modes)) + ttymodes = &modes; + } + + if (ttymode) + { + (void) ioctl(FILEDES, TCSETAW, (char *)ttymode); + } else if (ttymodes) { + (void) ioctl(FILEDES, TCSETSW, (char *)ttymodes); + } + if (flag > 0) /* trapped signal */ + exit(1); +} + +reportek(name, new, old, def) +char *name; +char old; +char new; +char def; +{ + register char o; + register char n; + register char *p; + char buf[32]; + char *bufp; + extern char *tgetstr(); + + if (BeQuiet) + return; + o = old; + n = new; + + if (o == n && n == def) + return; + prs(name); + if (o == n) + prs(" is "); + else + prs(" set to "); + bufp = buf; + if (tgetstr("kb", &bufp) > (char *)0 && n == buf[0] && buf[1] == NULL) + prs("Backspace\n"); + else if (n == 0177) + prs("Delete\n"); + else + { + if (n < 040) + { + prs("Ctrl-"); + n ^= 0100; + } + p = "x\n"; + p[0] = n; + prs(p); + } + flush(); +} + + + + +setdelay(cap, dtab, bits, flags) +char *cap; +struct delay dtab[]; +int bits; +short *flags; +{ + register int i; + register struct delay *p; + extern short ospeed; + + /* 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; + + /* 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) + (void) 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(); + return; + } + + while ((i = read(fd, buf, BUFSIZ)) > 0) + (void) write(FILEDES, buf, i); + + (void) 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) /* must be same thru len chars */ +char *a; +char *b; +int len; +{ + register char *p, *q; + register int i; + + i = len; + p = a; + q = b; + + while ((*p == *q) && --i > 0) + { + p++; q++; + } + return ((*p == *q) && i >= 0); +} + +sequal(a, b) /* must be same thru NULL */ +char *a; +char *b; +{ + register char *p = a, *q = b; + + while (*p && *q && (*p == *q)) + { + p++; q++; + } + 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); +} + + +/* + * 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 '!': /* 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++; + continue; + + case '\'': /* no quotes in output */ + p = putbuf(p, "\\047"); + bp++; + continue; + + case '`': /* no back quotes in output */ + p = putbuf(p, "\\140"); + bp++; + continue; + + case '\\': + case '^': /* anything following is OK */ + *p++ = *bp++; + } + *p++ = *bp++; + } + *p++ = ':'; /* we skipped the last : with the : lookahead hack */ + (void) 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; +{ + 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); +} + + +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) +char *type; +{ + extern short ospeed; + int match; + +# ifdef DEB + printf ("spd:%d\n", ospeed); + prmap(); +# endif + Map = map; + while (Map->Ident) + { + if (*(Map->Ident) == NULL || sequal(Map->Ident, type) || isalias(Map->Ident)) + { + match = NO; + switch (Map->Test) + { + case ANY: /* no test specified */ + case ALL: + match = YES; + break; + + case GT: + match = (ospeed > Map->Speed); + break; + + case GE: + match = (ospeed >= Map->Speed); + break; + + case EQ: + match = (ospeed == Map->Speed); + break; + + case LE: + match = (ospeed <= Map->Speed); + break; + + case LT: + match = (ospeed < Map->Speed); + break; + + case NE: + match = (ospeed != 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); +} + + +/* + * Stolen from /usr/src/ucb/reset.c, which this mod obsoletes. + */ +char +reset(ch, def) + char ch; + int def; +{ + + if (ch == 0 || (ch&0377) == 0377) + return def; + return ch; +} diff --git a/usr/src/ucbcmd/tset/tset.delays.h b/usr/src/ucbcmd/tset/tset.delays.h new file mode 100644 index 0000000000..46044007a5 --- /dev/null +++ b/usr/src/ucbcmd/tset/tset.delays.h @@ -0,0 +1,110 @@ +/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ +/* All Rights Reserved */ + + +/* + * Copyright (c) 1980 Regents of the University of California. + * All rights reserved. The Berkeley software License Agreement + * specifies the terms and conditions for redistribution. + */ + +/* + * Copyright (c) 1983, 1984 1985, 1986, 1987, 1988, Sun Microsystems, Inc. + * All Rights Reserved. + */ + +#ident "%Z%%M% %I% %E% SMI" /* SVr4.0 1.1 */ + +/* +** SYSTEM DEPENDENT TERMINAL DELAY TABLES +** +** +** This file maintains the correspondence between the delays +** defined in /etc/termcap and the delay algorithms on a +** particular system. For each type of delay, the bits used +** for that delay must be specified (in XXbits) and a table +** must be defined giving correspondences between delays and +** algorithms. Algorithms which are not fixed delays (such +** as dependent on current column or line number) must be +** cludged in some way at this time. +*/ + + + +/* +** Carriage Return delays +*/ + +int CRbits = CRDLY; +struct delay CRdelay[] = +{ + 0, CR0, + 9, CR3, + 80, CR1, + 160, CR2, + -1 +}; + +/* +** New Line delays +*/ + +int NLbits = NLDLY; +struct delay NLdelay[] = +{ + 0, NL0, + 66, NL1, /* special M37 delay */ + -1 +}; + + +/* +** Back Space delays +*/ + +int BSbits = BSDLY; +struct delay BSdelay[] = +{ + 0, BS0, + -1 +}; + + +/* +** TaB delays +*/ + +int TBbits = TABDLY; +struct delay TBdelay[] = +{ + 0, TAB0, + 11, TAB1, /* special M37 delay */ + -1 +}; + + +/* +** Form Feed delays +*/ + +int FFbits = FFDLY; +struct delay FFdelay[] = +{ + 0, FF0, + 2000, FF1, + -1 +}; + + +/* +** Vertical Tab delays +*/ + +int VTbits = VTDLY; +struct delay VTdelay[] = +{ + 0, VT0, + 2000, VT1, + -1 +}; + |
