|
|
1.1 root 1: /*
2: # define DEB
3: /*
4: ** TSET -- set terminal modes
5: **
6: ** This program does sophisticated terminal initialization.
7: ** I recommend that you include it in your .start_up or .login
8: ** file to initialize whatever terminal you are on.
9: **
10: ** There are several features:
11: **
12: ** A special file or sequence (as controlled by the ttycap file)
13: ** is sent to the terminal.
14: **
15: ** Mode bits are set on a per-terminal_type basis (much better
16: ** than UNIX itself). This allows special delays, automatic
17: ** tabs, etc.
18: **
19: ** Erase and Kill characters can be set to whatever you want.
20: ** Default is to change erase to control-H on a terminal which
21: ** can overstrike, and leave it alone on anything else. Kill
22: ** is always left alone unless specifically requested. These
23: ** characters can be represented as "^X" meaning control-X;
24: ** X is any character.
25: **
26: ** Terminals which are dialups or plugboard types can be aliased
27: ** to whatever type you may have in your home or office. Thus,
28: ** if you know that when you dial up you will always be on a
29: ** TI 733, you can specify that fact to tset. You can represent
30: ** a type as "?type". This will ask you what type you want it
31: ** to be -- if you reply with just a newline, it will default
32: ** to the type given.
33: **
34: ** The htmp file, used by ex, etc., can be updated.
35: **
36: ** The current terminal type can be queried.
37: **
38: ** Usage:
39: ** tset [-] [-EC] [-eC] [-kC] [-s] [-h] [-u] [-r]
40: ** [-m [ident] [test baudrate] :type]
41: ** [-Q] [-I] [-S] [type]
42: **
43: ** In systems with environments, use:
44: ** `tset -s ...`
45: ** Actually, this doesn't work because of a shell bug.
46: ** Instead, use:
47: ** tset -s ... > tset.tmp
48: ** source tset.tmp
49: ** rm tset.tmp
50: ** or:
51: ** set noglob
52: ** set term=(`tset -S ....`)
53: ** setenv TERM $term[1]
54: ** setenv TERMCAP "$term[2]"
55: ** unset term
56: ** unset noglob
57: **
58: ** Positional Parameters:
59: ** type -- the terminal type to force. If this is
60: ** specified, initialization is for this
61: ** terminal type.
62: **
63: ** Flags:
64: ** - -- report terminal type. Whatever type is
65: ** decided on is reported. If no other flags
66: ** are stated, the only affect is to write
67: ** the terminal type on the standard output.
68: ** -r -- report to user in addition to other flags.
69: ** -EC -- set the erase character to C on all terminals
70: ** except those which cannot backspace (e.g.,
71: ** a TTY 33). C defaults to control-H.
72: ** -eC -- set the erase character to C on all terminals.
73: ** C defaults to control-H. If neither -E or -e
74: ** are specified, the erase character is set to
75: ** control-H if the terminal can both backspace
76: ** and not overstrike (e.g., a CRT). If the erase
77: ** character is NULL (zero byte), it will be reset
78: ** to '#' if nothing else is specified.
79: ** -kC -- set the kill character to C on all terminals.
80: ** Default for C is control-X. If not specified,
81: ** the kill character is untouched; however, if
82: ** not specified and the kill character is NULL
83: ** (zero byte), the kill character is set to '@'.
84: ** -iC -- reserved for setable interrupt character.
85: ** -qC -- reserved for setable quit character.
86: ** -m -- map the system identified type to some user
87: ** specified type. The mapping can be baud rate
88: ** dependent. This replaces the old -d, -p flags.
89: ** (-d type -> -m dialup:type)
90: ** (-p type -> -m plug:type)
91: ** Syntax: -m identifier [test baudrate] :type
92: ** where: ``identifier'' is whatever is found in
93: ** /etc/ttytype for this port, (abscence of an identifier
94: ** matches any identifier); ``test'' may be any combination
95: ** of > = < ! @; ``baudrate'' is as with stty(1);
96: ** ``type'' is the actual terminal type to use if the
97: ** mapping condition is met. Multiple maps are scanned
98: ** in order and the first match prevails.
99: ** -h -- don't read htmp file. Normally the terminal type
100: ** is determined by reading the htmp file or the
101: ** environment (unless some mapping is specified).
102: ** This forces a read of the ttytype file -- useful
103: ** when htmp is somehow wrong.
104: ** -u -- don't update htmp. It seemed like this should
105: ** be put in. Note that htmp is never actually
106: ** written if there are no changes, so don't bother
107: ** bother using this for efficiency reasons alone.
108: ** -s -- output setenv commands for TERM. This can be
109: ** used with
110: ** `tset -s ...`
111: ** and is to be prefered to:
112: ** setenv TERM `tset - ...`
113: ** because -s sets the TERMCAP variable also.
114: ** -S -- Similar to -s but outputs 2 strings suitable for
115: ** use in csh .login files as follows:
116: ** set noglob
117: ** set term=(`tset -S .....`)
118: ** setenv TERM $term[1]
119: ** setenv TERMCAP "$term[2]"
120: ** unset term
121: ** unset noglob
122: ** -Q -- be quiet. don't output 'Erase set to' etc.
123: ** -I -- don't do terminal initialization (is & if
124: ** strings).
125: **
126: ** Files:
127: ** /etc/ttytype
128: ** contains a terminal id -> terminal type
129: ** mapping; used when any user mapping is specified,
130: ** or the environment doesn't have TERM set.
131: ** /etc/termcap
132: ** a terminal_type -> terminal_capabilities
133: ** mapping.
134: **
135: ** Return Codes:
136: ** -1 -- couldn't open ttycap.
137: ** 1 -- bad terminal type, or standard output not tty.
138: ** 0 -- ok.
139: **
140: ** Defined Constants:
141: ** DIALUP -- the type code for a dialup port
142: ** PLUGBOARD -- the code for a plugboard port.
143: ** ARPANET -- the code for an arpanet port.
144: ** BACKSPACE -- control-H, the default for -e.
145: ** CONTROLX -- control-X, the default for -k.
146: ** OLDERASE -- the system default erase character.
147: ** OLDKILL -- the system default kill character.
148: ** FILEDES -- the file descriptor to do the operation
149: ** on, nominally 1 or 2.
150: ** STDOUT -- the standard output file descriptor.
151: ** UIDMASK -- the bit pattern to mask with the getuid()
152: ** call to get just the user id.
153: ** GTTYN -- defines file containing generalized ttynames
154: ** and compiles code to look there.
155: **
156: ** Requires:
157: ** Routines to handle htmp, ttytype, and ttycap.
158: **
159: ** Compilation Flags:
160: ** OLDDIALUP -- accept the -d flag. Map "sd" to "dialup".
161: ** OLDPLUGBOARD -- accept the -p flag. Map "sp" to "plugboard".
162: ** OLDARPANET -- accept the -a flag. Map "sa" to "arpanet".
163: ** OLDFLAGS -- must be defined to compile code for any of
164: ** the -d, -p, or -a flags.
165: ** FULLLOGIN -- if defined, login sets the ttytype from
166: ** /etc/ttytype file.
167: ** V6 -- if clear, use environments, not htmp.
168: ** also use TIOCSETN rather than stty to avoid flushing
169: ** GTTYN -- if set, compiles code to look at /etc/ttytype.
170: **
171: ** Trace Flags:
172: ** none
173: **
174: ** Diagnostics:
175: ** Bad flag
176: ** An incorrect option was specified.
177: ** Too few args
178: ** more command line arguments are required.
179: ** Unexpected arg
180: ** wrong type of argument was encountered.
181: ** Cannot open ...
182: ** The specified file could not be openned.
183: ** Type ... unknown
184: ** An unknown terminal type was specified.
185: ** Cannot update htmp
186: ** Cannot update htmp file when the standard
187: ** output is not a terminal.
188: ** Erase set to ...
189: ** Telling that the erase character has been
190: ** set to the specified character.
191: ** Kill set to ...
192: ** Ditto for kill
193: ** Erase is ... Kill is ...
194: ** Tells that the erase/kill characters were
195: ** wierd before, but they are being left as-is.
196: ** Not a terminal
197: ** Set if FILEDES is not a terminal.
198: **
199: ** Compilation Instructions:
200: ** cc -n -O tset.c -ltermlib
201: ** mv a.out tset
202: ** chown bin tset
203: ** chmod 4755 tset
204: **
205: ** where 'bin' should be whoever owns the 'htmp' file.
206: ** If 'htmp' is 666, then tset need not be setuid.
207: **
208: ** Author:
209: ** Eric Allman
210: ** Electronics Research Labs
211: ** U.C. Berkeley
212: **
213: ** History:
214: ** 7/80 -- '-S' added. -m mapping added. TERMCAP string
215: ** cleaned up.
216: ** 3/80 -- Changed to use tputs. Prc & flush added.
217: ** 10/79 -- '-s' option extended to handle TERMCAP
218: ** variable, set noglob, quote the entry,
219: ** and know about the Bourne shell. Terminal
220: ** initialization moved to before any information
221: ** output so screen clears would not screw you.
222: ** '-Q' option added.
223: ** 8/79 -- '-' option alone changed to only output
224: ** type. '-s' option added. 'VERSION7'
225: ** changed to 'V6' for compatibility.
226: ** 12/78 -- modified for eventual migration to VAX/UNIX,
227: ** so the '-' option is changed to output only
228: ** the terminal type to STDOUT instead of
229: ** FILEDES. FULLLOGIN flag added.
230: ** 9/78 -- '-' and '-p' options added (now fully
231: ** compatible with ttytype!), and spaces are
232: ** permitted between the -d and the type.
233: ** 8/78 -- The sense of -h and -u were reversed, and the
234: ** -f flag is dropped -- same effect is available
235: ** by just stating the terminal type.
236: ** 10/77 -- Written.
237: */
238:
239: /*
240: # define FULLLOGIN 1
241: */
242: # ifndef V6
243: # define GTTYN "/etc/ttytype"
244: # endif
245:
246: # include <ctype.h>
247: # include <sgtty.h>
248: # include <stdio.h>
249:
250: # define BACKSPACE ('H' & 037)
251: # define CONTROLX ('X' & 037)
252: # define OLDERASE '#'
253: # define OLDKILL '@'
254:
255: # define FILEDES 2
256: # define STDOUT 1
257:
258: # ifdef V6
259: # define UIDMASK 0377
260: # else
261: # define UIDMASK -1
262: # endif
263:
264: # define DEFTYPE "unknown"
265: # define USAGE\
266: "usage: tset [-] [-hrsuIQS] [-eC] [-kC] [-m [ident][test speed]:type] [type]\n"
267:
268: # define DIALUP "dialup"
269: # define OLDDIALUP "sd"
270: # define PLUGBOARD "plugboard"
271: # define OLDPLUGBOARD "sp"
272: /***
273: # define ARPANET "arpanet"
274: # define OLDARPANET "sa"
275: ***/
276: # define OLDFLAGS
277:
278:
279:
280: # ifdef GTTYN
281: typedef char *ttyid_t;
282: # define NOTTY 0
283: # else
284: typedef char ttyid_t;
285: # define NOTTY 'x'
286: # endif
287:
288: /*
289: * Baud Rate Conditionals
290: */
291: # define ANY 0
292: # define GT 1
293: # define EQ 2
294: # define LT 4
295: # define GE (GT|EQ)
296: # define LE (LT|EQ)
297: # define NE (GT|LT)
298: # define ALL (GT|EQ|LT)
299:
300:
301:
302: # define NMAP 10
303:
304: struct map {
305: char *Ident;
306: char Test;
307: char Speed;
308: char *Type;
309: } map[NMAP];
310:
311: struct map *Map = map;
312:
313: struct
314: {
315: char *string;
316: int speed;
317: } speeds[] = {
318: "0", B0,
319: "50", B50,
320: "75", B75,
321: "110", B110,
322: "134", B134,
323: "134.5",B134,
324: "150", B150,
325: "200", B200,
326: "300", B300,
327: "600", B600,
328: "1200", B1200,
329: "1800", B1800,
330: "2400", B2400,
331: "4800", B4800,
332: "9600", B9600,
333: "exta", EXTA,
334: "extb", EXTB,
335: 0,
336: };
337:
338: char Erase_char; /* new erase character */
339: char Kill_char; /* new kill character */
340: char Specialerase; /* set => Erase_char only on terminals with backspace */
341:
342: ttyid_t Ttyid = NOTTY; /* terminal identifier */
343: char *TtyType; /* type of terminal */
344: char *DefType; /* default type if none other computed */
345: char *NewType; /* mapping identifier based on old flags */
346: int Dash_u; /* don't update htmp */
347: int Dash_h; /* don't read htmp */
348: int DoSetenv; /* output setenv commands */
349: int BeQuiet; /* be quiet */
350: int NoInit; /* don't output initialization string */
351: int Report; /* report current type */
352: int Ureport; /* report to user */
353: int RepOnly; /* report only */
354: int CmndLine; /* output full command lines (-s option) */
355: int Ask; /* ask user for termtype */
356:
357: # define CAPBUFSIZ 1024
358: char Capbuf[CAPBUFSIZ]; /* line from /etc/termcap for this TtyType */
359: char *Ttycap; /* termcap line from termcap or environ */
360:
361: struct delay
362: {
363: int d_delay;
364: int d_bits;
365: };
366:
367: # include "tset.delays.h"
368:
369:
370:
371: main(argc, argv)
372: int argc;
373: char *argv[];
374: {
375: struct sgttyb mode;
376: struct sgttyb oldmode;
377: char buf[256];
378: auto char *bufp;
379: register char *p;
380: char *command;
381: register int i;
382: int Break;
383: int Not;
384: int Mapped;
385: extern char *nextarg();
386: extern char *mapped();
387: # ifdef V6
388: extern char *hsgettype();
389: # else
390: extern char *getenv();
391: # endif
392: # ifdef GTTYN
393: extern char *stypeof();
394: extern char *ttyname();
395: extern char *tgetstr();
396: # endif
397: char bs_char;
398: int csh;
399: extern prc();
400: extern char PC;
401: extern short ospeed;
402:
403: if (gtty(FILEDES, &mode) < 0)
404: {
405: prs("Not a terminal\n");
406: exit(1);
407: }
408: bmove(&mode, &oldmode, sizeof mode);
409: ospeed = mode.sg_ospeed;
410:
411: /* scan argument list and collect flags */
412: command = argv[0];
413: if (argc == 2 && argv[1][0] == '-' && argv[1][1] == '\0')
414: {
415: RepOnly++;
416: Dash_u++;
417: }
418: argc--;
419: while (--argc >= 0)
420: {
421: p = *++argv;
422: if (*p == '-')
423: {
424: if (*++p == NULL)
425: Report++; /* report current terminal type */
426: else while (*p) switch (*p++)
427: {
428:
429: case 'r': /* report to user */
430: Ureport++;
431: continue;
432:
433: case 'E': /* special erase: operate on all but TTY33 */
434: Specialerase++;
435: /* explicit fall-through to -e case */
436:
437: case 'e': /* erase character */
438: if (*p == NULL)
439: Erase_char = -1;
440: else
441: {
442: if (*p == '^' && p[1] != NULL)
443: Erase_char = *++p & 037;
444: else
445: Erase_char = *p;
446: p++;
447: }
448: continue;
449:
450: case 'k': /* kill character */
451: if (*p == NULL)
452: Kill_char = CONTROLX;
453: else
454: {
455: if (*p == '^' && p[1] != NULL)
456: Kill_char = *++p & 037;
457: else
458: Kill_char = *p;
459: p++;
460: }
461: continue;
462:
463: # ifdef OLDFLAGS
464: # ifdef OLDDIALUP
465: case 'd': /* dialup type */
466: NewType = DIALUP;
467: goto mapold;
468: # endif
469:
470: # ifdef OLDPLUGBOARD
471: case 'p': /* plugboard type */
472: NewType = PLUGBOARD;
473: goto mapold;
474: # endif
475:
476: # ifdef OLDARPANET
477: case 'a': /* arpanet type */
478: Newtype = ARPANET;
479: goto mapold;
480: # endif
481:
482: mapold: Map->Ident = NewType;
483: Map->Test = ALL;
484: if (*p == NULL)
485: {
486: p = nextarg(argc--, argv++);
487: }
488: Map->Type = p;
489: Map++;
490: Mapped++;
491: p = "";
492: continue;
493: # endif
494:
495: case 'm': /* map identifier to type */
496: /* This code is very loose. Almost no
497: ** syntax checking is done!! However,
498: ** illegal syntax will only produce
499: ** weird results.
500: */
501: if (*p == NULL)
502: {
503: p = nextarg(argc--, argv++);
504: }
505: if (isalnum(*p))
506: {
507: Map->Ident = p; /* identifier */
508: while (isalnum(*p)) p++;
509: }
510: else
511: Map->Ident = "";
512: Break = 0;
513: Not = 0;
514: while (!Break) switch (*p)
515: {
516: case NULL:
517: p = nextarg(argc--, argv++);
518: continue;
519:
520: case ':': /* mapped type */
521: *p++ = NULL;
522: Break++;
523: continue;
524:
525: case '>': /* conditional */
526: Map->Test |= GT;
527: *p++ = NULL;
528: continue;
529:
530: case '<': /* conditional */
531: Map->Test |= LT;
532: *p++ = NULL;
533: continue;
534:
535: case '=': /* conditional */
536: case '@':
537: Map->Test |= EQ;
538: *p++ = NULL;
539: continue;
540:
541: case '!': /* invert conditions */
542: Not = ~Not;
543: *p++ = NULL;
544: continue;
545:
546: case 'B': /* Baud rate */
547: p++;
548: /* intentional fallthru */
549: default:
550: if (isdigit(*p) || *p == 'e')
551: {
552: Map->Speed = baudrate(p);
553: while (isalnum(*p) || *p == '.')
554: p++;
555: }
556: else
557: Break++;
558: continue;
559: }
560: if (Not) /* invert sense of test */
561: {
562: Map->Test = (~(Map->Test))&ALL;
563: }
564: if (*p == NULL)
565: {
566: p = nextarg(argc--, argv++);
567: }
568: Map->Type = p;
569: p = "";
570: Map++;
571: Mapped++;
572: continue;
573:
574: case 'h': /* don't get type from htmp or env */
575: Dash_h++;
576: continue;
577:
578: case 'u': /* don't update htmp */
579: Dash_u++;
580: continue;
581:
582: case 's': /* output setenv commands */
583: DoSetenv++;
584: CmndLine++;
585: continue;
586:
587: case 'S': /* output setenv strings */
588: DoSetenv++;
589: CmndLine=0;
590: continue;
591:
592: case 'Q': /* be quiet */
593: BeQuiet++;
594: continue;
595:
596: case 'I': /* no initialization */
597: NoInit++;
598: continue;
599:
600: case 'A': /* Ask user */
601: Ask++;
602: continue;
603:
604: default:
605: *p-- = NULL;
606: fatal("Bad flag -", p);
607: }
608: }
609: else
610: {
611: /* terminal type */
612: DefType = p;
613: }
614: }
615:
616: if (DefType)
617: {
618: if (Mapped)
619: {
620: Map->Ident = ""; /* means "map any type" */
621: Map->Test = ALL; /* at all baud rates */
622: Map->Type = DefType; /* to the default type */
623: }
624: else
625: TtyType = DefType;
626: }
627:
628: # ifndef V6
629: /* get current idea of terminal type from environment */
630: if (!Dash_h && !Mapped && TtyType == 0)
631: TtyType = getenv("TERM");
632: # endif
633:
634: /* determine terminal id if needed */
635: # ifdef V6
636: if (Ttyid == NOTTY && (TtyType == 0 || !Dash_h || !Dash_u))
637: Ttyid = ttyn(FILEDES);
638: # else
639: if (!RepOnly && Ttyid == NOTTY && (TtyType == 0 || !Dash_h))
640: Ttyid = ttyname(FILEDES);
641: # endif
642:
643: # ifdef V6
644: /* get htmp if ever used */
645: if (!Dash_u || (TtyType == 0 && !Dash_h))
646: {
647: /* get htmp entry -- if error or wrong user use ttytype */
648: if (Ttyid == NOTTY || hget(Ttyid) < 0 ||
649: hgettype() == 0 || hgetuid() != (getuid() & UIDMASK))
650: Dash_h++;
651: }
652:
653: /* find terminal type (if not already known) */
654: if (TtyType == 0 && !Dash_h)
655: {
656: /* get type from /etc/htmp */
657: TtyType = hsgettype();
658: }
659: # endif
660:
661: # ifdef GTTYN
662: /* If still undefined, look at /etc/ttytype */
663: if (TtyType == 0)
664: {
665: TtyType = stypeof(Ttyid);
666: }
667: # endif
668:
669: /* If still undefined, use DEFTYPE */
670: if (TtyType == 0)
671: {
672: TtyType = DEFTYPE;
673: }
674:
675: /* check for dialup or other mapping */
676: if (Mapped)
677: TtyType = mapped(TtyType, ospeed);
678:
679: /* TtyType now contains a pointer to the type of the terminal */
680: /* If the first character is '?', ask the user */
681: if (TtyType[0] == '?')
682: {
683: Ask++;
684: TtyType++;
685: if (TtyType[0] == '\0')
686: TtyType = DEFTYPE;
687: }
688: if (Ask)
689: {
690: prs("TERM = (");
691: prs(TtyType);
692: prs(") ");
693: flush();
694:
695: /* read the terminal. If not empty, set type */
696: i = read(2, buf, sizeof buf - 1);
697: if (i >= 0)
698: {
699: if (buf[i - 1] == '\n')
700: i--;
701: buf[i] = '\0';
702: if (buf[0] != '\0')
703: TtyType = buf;
704: }
705: }
706:
707: if (Ttycap == 0)
708: {
709: /* get terminal capabilities */
710: switch (tgetent(Capbuf, TtyType))
711: {
712: case -1:
713: prs("Cannot open termcap file\n");
714: flush();
715: exit(-1);
716:
717: case 0:
718: prs("Type ");
719: prs(TtyType);
720: prs(" unknown\n");
721: flush();
722: exit(1);
723: }
724: Ttycap = Capbuf;
725: }
726:
727: if (!RepOnly)
728: {
729: /* determine erase and kill characters */
730: if (Specialerase && !tgetflag("bs"))
731: Erase_char = 0;
732: bufp = buf;
733: p = tgetstr("kb", &bufp);
734: if (p == NULL || p[1] != '\0')
735: p = tgetstr("bc", &bufp);
736: if (p != NULL && p[1] == '\0')
737: bs_char = p[0];
738: else if (tgetflag("bs"))
739: bs_char = BACKSPACE;
740: else
741: bs_char = 0;
742: if (Erase_char == 0 && !tgetflag("os") && mode.sg_erase == OLDERASE)
743: {
744: if (tgetflag("bs") || bs_char != 0)
745: Erase_char = -1;
746: }
747: if (Erase_char < 0)
748: Erase_char = (bs_char != 0) ? bs_char : BACKSPACE;
749:
750: if (mode.sg_erase == 0)
751: mode.sg_erase = OLDERASE;
752: if (Erase_char != 0)
753: mode.sg_erase = Erase_char;
754:
755: if (mode.sg_kill == 0)
756: mode.sg_kill = OLDKILL;
757: if (Kill_char != 0)
758: mode.sg_kill = Kill_char;
759:
760: /* set modes */
761: setdelay("dC", CRdelay, CRbits, &mode.sg_flags);
762: setdelay("dN", NLdelay, NLbits, &mode.sg_flags);
763: setdelay("dB", BSdelay, BSbits, &mode.sg_flags);
764: setdelay("dF", FFdelay, FFbits, &mode.sg_flags);
765: setdelay("dT", TBdelay, TBbits, &mode.sg_flags);
766: if (tgetflag("UC") || command[0] == 'T')
767: mode.sg_flags |= LCASE;
768: else if (tgetflag("LC"))
769: mode.sg_flags &= ~LCASE;
770: mode.sg_flags &= ~(EVENP | ODDP | RAW);
771: # ifndef V6
772: mode.sg_flags &= ~CBREAK;
773: # endif
774: if (tgetflag("EP"))
775: mode.sg_flags |= EVENP;
776: if (tgetflag("OP"))
777: mode.sg_flags |= ODDP;
778: if ((mode.sg_flags & (EVENP | ODDP)) == 0)
779: mode.sg_flags |= EVENP | ODDP;
780: mode.sg_flags |= CRMOD | ECHO | XTABS;
781: if (tgetflag("NL")) /* new line, not line feed */
782: mode.sg_flags &= ~CRMOD;
783: if (tgetflag("HD")) /* half duplex */
784: mode.sg_flags &= ~ECHO;
785: if (tgetflag("pt")) /* print tabs */
786: mode.sg_flags &= ~XTABS;
787: if (!bequal(&mode, &oldmode, sizeof mode))
788: # ifndef V6
789: ioctl(FILEDES, TIOCSETN, &mode);
790: # else
791: stty(FILEDES, &mode);
792: # endif
793:
794: /* get pad character */
795: bufp = buf;
796: if (tgetstr("pc", &bufp) != 0)
797: PC = buf[0];
798:
799: /* output startup string */
800: if (!NoInit)
801: {
802: bufp = buf;
803: if (tgetstr("is", &bufp) != 0)
804: tputs(buf, 0, prc);
805: flush();
806: bufp = buf;
807: if (tgetstr("if", &bufp) != 0)
808: cat(buf);
809: sleep(1); /* let terminal settle down */
810: }
811:
812: /* set up environment for the shell we are using */
813: /* (this code is rather heuristic) */
814: csh = 0;
815: if (DoSetenv)
816: {
817: # ifndef V6
818: char *sh;
819:
820: if ((sh = getenv("SHELL")) && (i = strlen(sh)) >= 3)
821: {
822: p = &sh[i-3];
823: if ((csh = sequal(p, "csh")) && CmndLine)
824: write(STDOUT, "set noglob;\n", 12);
825: }
826: if (!csh)
827: # endif
828: /* running system shell */
829: write(STDOUT, "export TERMCAP TERM;\n", 21);
830: }
831: }
832:
833: /* report type if appropriate */
834: if (DoSetenv || Report || Ureport)
835: {
836: /* find first alias (if any) */
837: for (p = Ttycap; *p != 0 && *p != '|' && *p != ':'; p++)
838: continue;
839: if (*p == 0 || *p == ':')
840: p = Ttycap;
841: else
842: p++;
843: bufp = p;
844: while (*p != '|' && *p != ':' && *p != 0)
845: p++;
846: i = *p;
847: if (DoSetenv)
848: {
849: if (csh)
850: {
851: if (CmndLine)
852: write(STDOUT, "setenv TERM ", 12);
853: write(STDOUT, bufp, p - bufp);
854: write(STDOUT, " ", 1);
855: if (CmndLine)
856: write(STDOUT, ";\n", 2);
857: }
858: else
859: {
860: write(STDOUT, "TERM=", 5);
861: write(STDOUT, bufp, p - bufp);
862: write(STDOUT, ";\n", 2);
863: }
864: }
865: if (Report && !DoSetenv)
866: {
867: write(STDOUT, bufp, p - bufp);
868: write(STDOUT, "\n", 1);
869: }
870: if (Ureport)
871: {
872: *p = '\0';
873: prs("Terminal type is ");
874: prs(bufp);
875: prs("\n");
876: flush();
877: }
878: *p = i;
879: if (DoSetenv)
880: {
881: if (csh)
882: {
883: if (CmndLine)
884: write(STDOUT, "setenv TERMCAP '", 16);
885: }
886: else
887: write(STDOUT, "TERMCAP='", 9);
888: wrtermcap(Ttycap);
889: if (csh)
890: {
891: if (CmndLine)
892: {
893: write(STDOUT, "';\n", 3);
894: write(STDOUT, "unset noglob;\n", 14);
895: }
896: }
897: else
898: write(STDOUT, "';\n", 3);
899: }
900: }
901:
902: if (RepOnly)
903: exit(0);
904:
905: /* tell about changing erase and kill characters */
906: reportek("Erase", mode.sg_erase, oldmode.sg_erase, OLDERASE);
907: reportek("Kill", mode.sg_kill, oldmode.sg_kill, OLDKILL);
908:
909: # ifdef V6
910: /* update htmp */
911: if (!Dash_u)
912: {
913: if (Ttyid == 0)
914: Ttyid = ttyn(FILEDES);
915: if (Ttyid == 'x')
916: {
917: prs("Cannot update htmp\n");
918: flush();
919: }
920: else
921: {
922: /* update htmp file only if changed */
923: if (!bequal(Capbuf, hsgettype(), 2))
924: {
925: hsettype(Capbuf[0] | (Capbuf[1] << 8));
926: hput(Ttyid);
927: }
928: }
929: }
930: # endif
931:
932: exit(0);
933: }
934:
935: reportek(name, new, old, def)
936: char *name;
937: char old;
938: char new;
939: char def;
940: {
941: register char o;
942: register char n;
943: register char *p;
944:
945: if (BeQuiet)
946: return;
947: o = old;
948: n = new;
949:
950: if (o == n && n == def)
951: return;
952: prs(name);
953: if (o == n)
954: prs(" is ");
955: else
956: prs(" set to ");
957: if (n < 040)
958: {
959: prs("control-");
960: n = (n & 037) | 0100;
961: }
962: p = "x\n";
963: p[0] = n;
964: prs(p);
965: flush();
966: }
967:
968:
969:
970:
971: setdelay(cap, dtab, bits, flags)
972: char *cap;
973: struct delay dtab[];
974: int bits;
975: int *flags;
976: {
977: register int i;
978: register struct delay *p;
979:
980: /* see if this capability exists at all */
981: i = tgetnum(cap);
982: if (i < 0)
983: i = 0;
984:
985: /* clear out the bits, replace with new ones */
986: *flags &= ~bits;
987:
988: /* scan dtab for first entry with adequate delay */
989: for (p = dtab; p->d_delay >= 0; p++)
990: {
991: if (p->d_delay >= i)
992: {
993: p++;
994: break;
995: }
996: }
997:
998: /* use last entry if none will do */
999: *flags |= (--p)->d_bits;
1000: }
1001:
1002:
1003: prs(s)
1004: char *s;
1005: {
1006: while (*s != '\0')
1007: prc(*s++);
1008: }
1009:
1010:
1011: char OutBuf[256];
1012: int OutPtr;
1013:
1014: prc(c)
1015: char c;
1016: {
1017: OutBuf[OutPtr++] = c;
1018: if (OutPtr >= sizeof OutBuf)
1019: flush();
1020: }
1021:
1022: flush()
1023: {
1024: if (OutPtr > 0)
1025: write(2, OutBuf, OutPtr);
1026: OutPtr = 0;
1027: }
1028:
1029:
1030: cat(file)
1031: char *file;
1032: {
1033: register int fd;
1034: register int i;
1035: char buf[BUFSIZ];
1036:
1037: fd = open(file, 0);
1038: if (fd < 0)
1039: {
1040: prs("Cannot open ");
1041: prs(file);
1042: prs("\n");
1043: flush();
1044: exit(-1);
1045: }
1046:
1047: flush();
1048: while ((i = read(fd, buf, BUFSIZ)) > 0)
1049: write(FILEDES, buf, i);
1050:
1051: close(fd);
1052: }
1053:
1054:
1055:
1056: bmove(from, to, length)
1057: char *from;
1058: char *to;
1059: int length;
1060: {
1061: register char *p, *q;
1062: register int i;
1063:
1064: i = length;
1065: p = from;
1066: q = to;
1067:
1068: while (i-- > 0)
1069: *q++ = *p++;
1070: }
1071:
1072:
1073:
1074: bequal(a, b, len)
1075: char *a;
1076: char *b;
1077: int len;
1078: {
1079: register char *p, *q;
1080: register int i;
1081:
1082: i = len;
1083: p = a;
1084: q = b;
1085:
1086: while (*p && *q && (*p == *q) && --i > 0)
1087: {
1088: p++; q++;
1089: }
1090: return ((*p == *q) && i >= 0);
1091: }
1092:
1093: sequal(a, b)
1094: char *a;
1095: char *b;
1096: {
1097: register char *p = a, *q = b;
1098:
1099: while (*p && *q && (*p == *q))
1100: {
1101: p++; q++;
1102: }
1103: return (*p == *q);
1104: }
1105:
1106: # ifdef GTTYN
1107: char *
1108: stypeof(ttyid)
1109: char *ttyid;
1110: {
1111: static char typebuf[50];
1112: register char *PortType;
1113: register char *PortName;
1114: register char *TtyId;
1115: register char *p;
1116: register FILE *f;
1117:
1118: if (ttyid == NOTTY)
1119: return (DEFTYPE);
1120: f = fopen(GTTYN, "r");
1121: if (f == NULL)
1122: return (DEFTYPE);
1123:
1124: /* split off end of name */
1125: TtyId = ttyid;
1126: while (*ttyid)
1127: if (*ttyid++ == '/')
1128: TtyId = ttyid;
1129:
1130: /* scan the file */
1131: while (fgets(typebuf, sizeof typebuf, f) != NULL)
1132: {
1133: p = PortType = typebuf;
1134: while (*p && isalnum(*p))
1135: p++;
1136: *p++ = NULL;
1137:
1138: /* skip separator */
1139: while (*p && !isalnum(*p))
1140: p++;
1141:
1142: PortName = p;
1143: /* put NULL at end of name */
1144: while (*p && isalnum(*p))
1145: p++;
1146: *p = NULL;
1147:
1148: /* check match on port name */
1149: if (sequal(PortName, TtyId)) /* found it */
1150: {
1151: # ifdef OLDDIALUP
1152: if (sequal(PortType, OLDDIALUP))
1153: PortType = DIALUP;
1154: # endif
1155:
1156: # ifdef OLDPLUGBOARD
1157: if (sequal(PortType, OLDPLUGBOARD))
1158: PortType = PLUGBOARD;
1159: # endif
1160:
1161: # ifdef OLDARPANET
1162: if (sequal(PortType, OLDARPANET))
1163: PortType = ARPANET;
1164: # endif
1165: fclose (f);
1166: return(PortType);
1167: }
1168: }
1169: fclose (f);
1170: return (DEFTYPE);
1171: }
1172: # endif
1173:
1174: #define YES 1
1175: #define NO 0
1176: /*
1177: * routine to output the string for the environment TERMCAP variable
1178: */
1179: #define WHITE(c) (c == ' ' || c == '\t')
1180: char delcap[128][2];
1181: int ncap = 0;
1182:
1183: wrtermcap(bp)
1184: char *bp;
1185: {
1186: char buf[CAPBUFSIZ];
1187: char *p = buf;
1188: char *tp;
1189: char *putbuf();
1190: int space, empty;
1191:
1192: /* discard names with blanks */
1193: /** May not be desireable ? **/
1194: while (*bp && *bp != ':') {
1195: if (*bp == '|') {
1196: tp = bp+1;
1197: space = NO;
1198: while (*tp && *tp != '|' && *tp != ':') {
1199: space = (space || WHITE(*tp) );
1200: tp++;
1201: }
1202: if (space) {
1203: bp = tp;
1204: continue;
1205: }
1206: }
1207: *p++ = *bp++;
1208: }
1209: /**/
1210:
1211: while (*bp) {
1212: switch (*bp) {
1213: case ':': /* discard empty, cancelled or dupl fields */
1214: tp = bp+1;
1215: empty = YES;
1216: while (*tp && *tp != ':') {
1217: empty = (empty && WHITE(*tp) );
1218: tp++;
1219: }
1220: if (empty || cancelled(bp+1)) {
1221: bp = tp;
1222: continue;
1223: }
1224: break;
1225:
1226: case ' ': /* no spaces in output */
1227: p = putbuf(p, "\\040");
1228: bp++;
1229: continue;
1230:
1231: case '"': /* no quotes in output */
1232: p = putbuf(p, "\\042");
1233: bp++;
1234: continue;
1235:
1236: case '\'': /* no quotes in output */
1237: p = putbuf(p, "\\047");
1238: bp++;
1239: continue;
1240:
1241: case '\\':
1242: case '^': /* anything following is OK */
1243: *p++ = *bp++;
1244: }
1245: *p++ = *bp++;
1246: }
1247: write (STDOUT, buf, p-buf);
1248: }
1249:
1250: cancelled(cap)
1251: char *cap;
1252: {
1253: register int i;
1254:
1255: for (i = 0; i < ncap; i++)
1256: {
1257: if (cap[0] == delcap[i][0] && cap[1] == delcap[i][1])
1258: return (YES);
1259: }
1260: /* delete a second occurrance of the same capability */
1261: delcap[ncap][0] = cap[0];
1262: delcap[ncap][1] = cap[1];
1263: ncap++;
1264: return (cap[2] == '@');
1265: }
1266:
1267: char *
1268: putbuf(ptr, str)
1269: char *ptr;
1270: char *str;
1271: {
1272: while (*str)
1273: *ptr++ = *str++;
1274: return (ptr);
1275: }
1276:
1277:
1278: baudrate(p)
1279: char *p;
1280: {
1281: char buf[8];
1282: int i = 0;
1283:
1284: while (i < 7 && (isalnum(*p) || *p == '.'))
1285: buf[i++] = *p++;
1286: buf[i] = NULL;
1287: for (i=0; speeds[i].string; i++)
1288: if (sequal(speeds[i].string, buf))
1289: return (speeds[i].speed);
1290: return (-1);
1291: }
1292:
1293: char *
1294: mapped(type, speed)
1295: char *type;
1296: short speed;
1297: {
1298: int match;
1299:
1300: # ifdef DEB
1301: printf ("spd:%d\n", speed);
1302: prmap();
1303: # endif
1304: Map = map;
1305: while (Map->Ident)
1306: {
1307: if (*(Map->Ident) == NULL || bequal(Map->Ident, type, 4))
1308: {
1309: match = NO;
1310: switch (Map->Test)
1311: {
1312: case ANY: /* no test specified */
1313: case ALL:
1314: match = YES;
1315: break;
1316:
1317: case GT:
1318: match = (speed > Map->Speed);
1319: break;
1320:
1321: case GE:
1322: match = (speed >= Map->Speed);
1323: break;
1324:
1325: case EQ:
1326: match = (speed == Map->Speed);
1327: break;
1328:
1329: case LE:
1330: match = (speed <= Map->Speed);
1331: break;
1332:
1333: case LT:
1334: match = (speed < Map->Speed);
1335: break;
1336:
1337: case NE:
1338: match = (speed != Map->Speed);
1339: break;
1340: }
1341: if (match)
1342: return (Map->Type);
1343: }
1344: Map++;
1345: }
1346: /* no match found; return given type */
1347: return (type);
1348: }
1349:
1350: # ifdef DEB
1351: prmap()
1352: {
1353: Map = map;
1354: while (Map->Ident)
1355: {
1356: printf ("%s t:%d s:%d %s\n",
1357: Map->Ident, Map->Test, Map->Speed, Map->Type);
1358: Map++;
1359: }
1360: }
1361: # endif
1362:
1363: char *
1364: nextarg(argc, argv)
1365: int argc;
1366: char *argv[];
1367: {
1368: if (argc <= 0)
1369: fatal ("Too few args: ", *argv);
1370: if (*(*++argv) == '-')
1371: fatal ("Unexpected arg: ", *argv);
1372: return (*argv);
1373: }
1374:
1375: fatal (mesg, obj)
1376: char *mesg;
1377: char *obj;
1378: {
1379: prs (mesg);
1380: prs (obj);
1381: prc ('\n');
1382: prs (USAGE);
1383: flush();
1384: exit(1);
1385: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.