|
|
1.1 root 1: #
2: /*
3: ** TSET -- set terminal modes
4: **
5: ** This program does sophisticated terminal initialization.
6: ** I recommend that you include it in your .start_up or .login
7: ** file to initialize whatever terminal you are on.
8: **
9: ** There are several features:
10: **
11: ** A special file or sequence (as controlled by the ttycap file)
12: ** is sent to the terminal.
13: **
14: ** Mode bits are set on a per-terminal_type basis (much better
15: ** than UNIX itself). This allows special delays, automatic
16: ** tabs, etc.
17: **
18: ** Erase and Kill characters can be set to whatever you want.
19: ** Default is to change erase to control-H on a terminal which
20: ** can overstrike, and leave it alone on anything else. Kill
21: ** is always left alone unless specifically requested. These
22: ** characters can be represented as "^X" meaning control-X;
23: ** X is any character.
24: **
25: ** Terminals which are dialups or plugboard types can be aliased
26: ** to whatever type you may have in your home or office. Thus,
27: ** if you know that when you dial up you will always be on a
28: ** TI 733, you can specify that fact to tset. You can represent
29: ** a type as "?type". This will ask you what type you want it
30: ** to be -- if you reply with just a newline, it will default
31: ** to the type given.
32: **
33: ** The htmp file, used by ex, etc., can be updated.
34: **
35: ** The current terminal type can be queried.
36: **
37: ** Usage:
38: ** tset [-] [-EC] [-eC] [-kC] [-s] [-h] [-u]
39: ** [-d type] [-p type] [-b type] [-a type]
40: ** [-Q] [-I] [type]
41: **
42: ** In systems with environments, use:
43: ** `tset -s ...`
44: ** Actually, this doesn't work because of a shell bug.
45: ** Instead, use:
46: ** tset -s ... > tset.tmp
47: ** source tset.tmp
48: ** rm tset.tmp
49: **
50: ** Positional Parameters:
51: ** type -- the terminal type to force. If this is
52: ** specified, initialization is for this
53: ** terminal type.
54: **
55: ** Flags:
56: ** - -- report terminal type. Whatever type is
57: ** decided on is reported. If no other flags
58: ** are stated, the only affect is to write
59: ** the terminal type on the standard output.
60: ** -EC -- set the erase character to C on all terminals
61: ** except those which cannot backspace (e.g.,
62: ** a TTY 33). C defaults to control-H.
63: ** -eC -- set the erase character to C on all terminals.
64: ** C defaults to control-H. If neither -E or -e
65: ** are specified, the erase character is set to
66: ** control-H if the terminal can both backspace
67: ** and not overstrike (e.g., a CRT). If the erase
68: ** character is NULL (zero byte), it will be reset
69: ** to '#' if nothing else is specified.
70: ** -kC -- set the kill character to C on all terminals.
71: ** Default for C is control-X. If not specified,
72: ** the kill character is untouched; however, if
73: ** not specified and the kill character is NULL
74: ** (zero byte), the kill character is set to '@'.
75: ** -iC -- reserved for setable interrupt character.
76: ** -qC -- reserved for setable quit character.
77: ** -d type -- set the dialup type to be type. If the
78: ** terminal type seems to be dialup, make it
79: ** 'type' instead. There need not be a space
80: ** between 'd' and 'type'.
81: ** -p type -- ditto for a plugboard.
82: ** -b type -- ditto for a bussiplexor.
83: ** -a type -- ditto for an arpanet link.
84: ** -h -- don't read htmp file. Normally the terminal type
85: ** is determined by reading the htmp file (unless
86: ** -d or -p are specified). This forces a read
87: ** of the ttytype file -- useful when htmp is
88: ** somehow wrong.
89: ** -u -- don't update htmp. It seemed like this should
90: ** be put in. Note that htmp is never actually
91: ** written if there are no changes, so don't bother
92: ** bother using this for efficiency reasons alone.
93: ** -s -- output setenv commands for TERM. This can be
94: ** used with
95: ** `tset -s ...`
96: ** and is to be prefered to:
97: ** setenv TERM `tset - ...`
98: ** because -s sets the TERMCAP variable also.
99: ** -Q -- be quiet. don't output 'Erase set to' etc.
100: ** -I -- don't do terminal initialization (is & if
101: ** strings).
102: **
103: ** Files:
104: ** /etc/ttytype
105: ** contains a terminal id -> terminal type
106: ** mapping; used when -h, -d, or -p is used.
107: ** /etc/termcap
108: ** a terminal_type -> terminal_capabilities
109: ** mapping.
110: **
111: ** Return Codes:
112: ** -1 -- couldn't open ttycap.
113: ** 1 -- bad terminal type, or standard output not tty.
114: ** 0 -- ok.
115: **
116: ** Defined Constants:
117: ** DIALUP -- the type code for a dialup port
118: ** PLUGBOARD -- the code for a plugboard port.
119: ** BUSSIPLEXER -- the code for a bussiplexer port.
120: ** ARPANET -- the code for an arpanet port.
121: ** BACKSPACE -- control-H, the default for -e.
122: ** CONTROLX -- control-X, the default for -k.
123: ** OLDERASE -- the system default erase character.
124: ** OLDKILL -- the system default kill character.
125: ** FILEDES -- the file descriptor to do the operation
126: ** on, nominally 1 or 2.
127: ** STDOUT -- the standard output file descriptor.
128: ** UIDMASK -- the bit pattern to mask with the getuid()
129: ** call to get just the user id.
130: **
131: ** Requires:
132: ** Routines to handle htmp, ttytype, and ttycap.
133: **
134: ** Compilation Flags:
135: ** PLUGBOARD -- if defined, accept the -p flag.
136: ** BUSSIPLEXER -- if defined, accept the -b flag.
137: ** FULLLOGIN -- if defined, login sets the ttytype from
138: ** /etc/ttytype file.
139: ** V6 -- if clear, use environments, not htmp.
140: ** also use TIOCSETN rather than stty to avoid flushing
141: ** GTTYN -- if set, uses generalized tty names.
142: **
143: ** Trace Flags:
144: ** none
145: **
146: ** Diagnostics:
147: ** Bad flag
148: ** An incorrect option was specified.
149: ** Cannot open ...
150: ** The specified file could not be openned.
151: ** Type ... unknown
152: ** An unknown terminal type was specified.
153: ** Cannot update htmp
154: ** Cannot update htmp file when the standard
155: ** output is not a terminal.
156: ** Erase set to ...
157: ** Telling that the erase character has been
158: ** set to the specified character.
159: ** Kill set to ...
160: ** Ditto for kill
161: ** Erase is ... Kill is ...
162: ** Tells that the erase/kill characters were
163: ** wierd before, but they are being left as-is.
164: ** Not a terminal
165: ** Set if FILEDES is not a terminal.
166: **
167: ** Compilation Instructions:
168: ** cc -n -O tset.c -lX
169: ** mv a.out tset
170: ** chown bin tset
171: ** chmod 4755 tset
172: **
173: ** where 'bin' should be whoever owns the 'htmp' file.
174: ** If 'htmp' is 666, then tset need not be setuid.
175: **
176: ** Author:
177: ** Eric Allman
178: ** Electronics Research Labs
179: ** U.C. Berkeley
180: **
181: ** History:
182: ** 10/79 -- '-s' option extended to handle TERMCAP
183: ** variable, set noglob, quote the entry,
184: ** and know about the Bourne shell. Terminal
185: ** initialization moved to before any information
186: ** output so screen clears would not screw you.
187: ** '-Q' option added.
188: ** 8/79 -- '-' option alone changed to only output
189: ** type. '-s' option added. 'VERSION7'
190: ** changed to 'V6' for compatibility.
191: ** 12/78 -- modified for eventual migration to VAX/UNIX,
192: ** so the '-' option is changed to output only
193: ** the terminal type to STDOUT instead of
194: ** FILEDES. FULLLOGIN flag added.
195: ** 9/78 -- '-' and '-p' options added (now fully
196: ** compatible with ttytype!), and spaces are
197: ** permitted between the -d and the type.
198: ** 8/78 -- The sense of -h and -u were reversed, and the
199: ** -f flag is dropped -- same effect is available
200: ** by just stating the terminal type.
201: ** 10/77 -- Written.
202: */
203:
204: /*
205: # define FULLLOGIN 1
206: */
207: # ifndef V6
208: # define GTTYN 1
209: # endif
210:
211: # include <sgtty.h>
212: # include <stdio.h>
213:
214: # define BACKSPACE ('H' & 037)
215: # define CONTROLX ('X' & 037)
216: # define OLDERASE '#'
217: # define OLDKILL '@'
218:
219: # define FILEDES 2
220: # define STDOUT 1
221:
222: # ifdef V6
223: # define UIDMASK 0377
224: # else
225: # define UIDMASK -1
226: # endif
227:
228: # define DIALUP "sd"
229: # define PLUGBOARD "sp"
230: # define BUSSIPLEXER "sb"
231: # define ARPANET "sa"
232:
233: # ifdef GTTYN
234: typedef char *ttyid_t;
235: # define NOTTY 0
236: # else
237: typedef char ttyid_t;
238: # define NOTTY 'x'
239: # endif
240:
241:
242:
243:
244:
245:
246: char Erase_char; /* new erase character */
247: char Kill_char; /* new kill character */
248: char Specialerase; /* set => Erase_char only on terminals with backspace */
249:
250: ttyid_t Ttyid = NOTTY; /* terminal identifier */
251: char *TtyType; /* type of terminal */
252: char *DefType; /* default type if none other computed */
253: char *DialType; /* override type if dialup port */
254: char *PlugType; /* override type if plugboard port */
255: char *BxType; /* override type if bussiplexer port */
256: char *AnType; /* override type if arpanet port */
257: int Dash_u; /* don't update htmp */
258: int Dash_h; /* don't read htmp */
259: int DoSetenv; /* output setenv commands */
260: int BeQuiet; /* be quiet */
261: int NoInit; /* don't output initialization string */
262: int Report; /* report current type */
263: int Ureport; /* report to user */
264: int RepOnly; /* report only */
265:
266: char Usage[] = "usage: tset [-] [-r] [-s] [-eC] [-kC] [-d T] [-p T] [-b T] [-a T]\n\t[-Q] [-I] [-h] [-u] [type]\n";
267:
268: char Capbuf[1024]; /* line from /etc/termcap for this TtyType */
269: char *Ttycap; /* termcap line from termcap or environ */
270:
271: struct delay
272: {
273: int d_delay;
274: int d_bits;
275: };
276:
277: # include "tset.delays.h"
278:
279:
280:
281: main(argc, argv)
282: int argc;
283: char *argv[];
284: {
285: struct sgttyb mode;
286: struct sgttyb oldmode;
287: char buf[256];
288: auto char *bufp;
289: register char *p;
290: char *command;
291: register int i;
292: register int error;
293: extern char *stypeof();
294: # ifdef V6
295: extern char *hsgettype();
296: # else
297: extern char *getenv();
298: # endif
299: # ifdef GTTYN
300: extern char *ttyname();
301: extern char *tgetstr();
302: # endif
303: char bs_char;
304: int csh;
305:
306: /* scan argument list and collect flags */
307: error = 0;
308: command = argv[0];
309: if (argc == 2 && argv[1][0] == '-' && argv[1][1] == '\0')
310: RepOnly++;
311: argc--;
312: while (--argc >= 0)
313: {
314: p = *++argv;
315: if (p[0] == '-')
316: {
317: switch (p[1])
318: {
319:
320: case 0: /* report current terminal type */
321: Report++;
322: continue;
323:
324: case 'r': /* report to user */
325: Ureport++;
326: continue;
327:
328: case 'E': /* special erase: operate on all but TTY33 */
329: Specialerase++;
330: /* explicit fall-through to -e case */
331:
332: case 'e': /* erase character */
333: if (p[2] == 0)
334: Erase_char = -1;
335: else if (p[2] == '^' && p[3] != '\0')
336: Erase_char = p[3] & 037;
337: else
338: Erase_char = p[2];
339: continue;
340:
341: case 'k': /* kill character */
342: if (p[2] == 0)
343: Kill_char = CONTROLX;
344: else if (p[2] == '^' && p[3] != '\0')
345: Kill_char = p[3] & 037;
346: else
347: Kill_char = p[2];
348: continue;
349:
350: case 'd': /* dialup type */
351: if (p[2] != 0)
352: DialType = &p[2];
353: else if (--argc < 0 || argv[1][0] == '-')
354: error++;
355: else
356: DialType = *++argv;
357: continue;
358:
359: # ifdef PLUGBOARD
360: case 'p': /* plugboard type */
361: if (p[2] != 0)
362: PlugType = &p[2];
363: else if (--argc < 0 || argv[1][0] == '-')
364: error++;
365: else
366: PlugType = *++argv;
367: continue;
368: # endif
369:
370: # ifdef BUSSIPLEXER
371: case 'b': /* bussiplexer type */
372: if (p[2] != 0)
373: BxType = &p[2];
374: else if (--argc < 0 || argv[1][0] == '-')
375: error++;
376: else
377: BxType = *++argv;
378: # endif
379:
380: # ifdef ARPANET
381: case 'a': /* arpanet type */
382: if (p[2] != 0)
383: AnType = &p[2];
384: else if (--argc < 0 || argv[1][0] == '-')
385: error++;
386: else
387: AnType = *++argv;
388: # endif
389:
390: case 'h': /* don't get type from htmp or env */
391: Dash_h++;
392: continue;
393:
394: case 'u': /* don't update htmp */
395: Dash_u++;
396: continue;
397:
398: case 's': /* output setenv commands */
399: DoSetenv++;
400: continue;
401:
402: case 'Q': /* be quiet */
403: BeQuiet++;
404: continue;
405:
406: case 'I': /* no initialization */
407: NoInit++;
408: continue;
409:
410: default:
411: prs("Bad flag ");
412: prs(p);
413: prs("\n");
414: error++;
415:
416: }
417: }
418: else
419: {
420: /* terminal type */
421: DefType = p;
422: }
423: }
424:
425: if (error)
426: {
427: prs(Usage);
428: exit(1);
429: }
430:
431: /* if dialup is specified, check ttytype not htmp */
432: if (DialType == 0 && PlugType == 0 && BxType == 0 && AnType == 0)
433: TtyType = DefType;
434: # ifndef FULLLOGIN
435: else
436: Dash_h++;
437: # endif
438:
439: /* if report only, say that we won't update htmp */
440: if (RepOnly)
441: Dash_u++;
442:
443: # ifndef V6
444: /* get current idea of terminal type from environment */
445: if (!Dash_h && TtyType == 0)
446: TtyType = getenv("TERM");
447: # endif
448:
449: /* determine terminal id if needed */
450: # ifdef V6
451: if (Ttyid == NOTTY && (TtyType == 0 || !Dash_h || !Dash_u))
452: Ttyid = ttyn(FILEDES);
453: # else
454: if (!RepOnly && Ttyid == NOTTY && (TtyType == 0 || !Dash_h))
455: Ttyid = ttyname(FILEDES);
456: # endif
457:
458: # ifdef V6
459: /* get htmp if ever used */
460: if (!Dash_u || (TtyType == 0 && !Dash_h))
461: {
462: /* get htmp entry -- if error or wrong user use ttytype */
463: if (Ttyid == NOTTY || hget(Ttyid) < 0 ||
464: hgettype() == 0 || hgetuid() != (getuid() & UIDMASK))
465: Dash_h++;
466: }
467: # endif
468:
469: /* find terminal type (if not already known) */
470: if (TtyType == 0)
471: {
472: /* get type from /etc/ttytype or /etc/htmp */
473: if (!Dash_h)
474: {
475: # ifdef V6
476: TtyType = hsgettype();
477: # else
478: TtyType = getenv("TERM");
479: # endif
480: }
481: if (TtyType == 0)
482: {
483: TtyType = stypeof(Ttyid);
484: }
485:
486: /* check for dialup or plugboard override */
487: if (DialType != 0 && bequal(TtyType, DIALUP, 2))
488: TtyType = DialType;
489: # ifdef PLUGBOARD
490: else if (PlugType != 0 && bequal(TtyType, PLUGBOARD, 2))
491: TtyType = PlugType;
492: # endif
493: # ifdef BUSSIPLEXER
494: else if (BxType != 0 && bequal(TtyType, BUSSIPLEXER, 2))
495: TtyType = BxType;
496: # endif
497: # ifdef ARPANET
498: else if (AnType != 0 && bequal(TtyType, ARPANET, 2))
499: TtyType = AnType;
500: # endif
501: else if (DefType != 0)
502: TtyType = DefType;
503: }
504:
505: /* TtyType now contains a pointer to the type of the terminal */
506: /* If the first character is '?', ask the user */
507: if (TtyType[0] == '?')
508: {
509: if (*++TtyType == '\0')
510: TtyType = "dumb";
511: prs("TERM = (");
512: prs(TtyType);
513: prs(") ");
514:
515: /* read the terminal. If not empty, set type */
516: i = read(2, buf, sizeof buf - 1);
517: if (i >= 0)
518: {
519: if (buf[i - 1] == '\n')
520: i--;
521: buf[i] = '\0';
522: if (buf[0] != '\0')
523: TtyType = buf;
524: }
525: }
526:
527: if (Ttycap == 0)
528: {
529: /* get terminal capabilities */
530: switch (tgetent(Capbuf, TtyType))
531: {
532: case -1:
533: prs("Cannot open termcap file\n");
534: exit(-1);
535:
536: case 0:
537: prs("Type ");
538: prs(TtyType);
539: prs(" unknown\n");
540: exit(1);
541: }
542: Ttycap = Capbuf;
543: }
544:
545: /* output startup string */
546: if (!RepOnly && !NoInit)
547: {
548: bufp = buf;
549: if (tgetstr("is", &bufp) != 0)
550: prs(buf);
551: bufp = buf;
552: if (tgetstr("if", &bufp) != 0)
553: cat(buf);
554: sleep(1); /* let terminal settle down */
555: }
556:
557: /* set up environment for the shell we are using */
558: /* (this code is rather heuristic) */
559: csh = 0;
560: if (DoSetenv)
561: {
562: # ifndef V6
563: if (bequal(getenv("SHELL"), "/bin/csh", 9))
564: {
565: # endif
566: /* running csh */
567: csh++;
568: write(STDOUT, "set noglob;\n", 12);
569: # ifndef V6
570: }
571: else
572: {
573: /* running system shell */
574: write(STDOUT, "export TERMCAP TERM;\n", 21);
575: }
576: # endif
577: }
578:
579: /* report type if appropriate */
580: if (DoSetenv || Report || Ureport)
581: {
582: /* find first alias (if any) */
583: for (p = Ttycap; *p != 0 && *p != '|' && *p != ':'; p++)
584: continue;
585: if (*p == 0 || *p == ':')
586: p = Ttycap;
587: else
588: p++;
589: bufp = p;
590: while (*p != '|' && *p != ':' && *p != 0)
591: p++;
592: i = *p;
593: if (DoSetenv)
594: {
595: if (csh)
596: write(STDOUT, "setenv TERM ", 12);
597: else
598: write(STDOUT, "TERM=", 5);
599: }
600: if (Report || DoSetenv)
601: {
602: write(STDOUT, bufp, p - bufp);
603: if (DoSetenv)
604: write(STDOUT, ";", 1);
605: write(STDOUT, "\n", 1);
606: }
607: if (Ureport)
608: {
609: *p = '\0';
610: prs("Terminal type is ");
611: prs(bufp);
612: prs("\n");
613: }
614: *p = i;
615: if (DoSetenv)
616: {
617: for (p = Ttycap; *p != '\0'; p++)
618: continue;
619: if (csh)
620: write(STDOUT, "setenv TERMCAP '", 16);
621: else
622: write(STDOUT, "TERMCAP='", 9);
623: write(STDOUT, Ttycap, p - Ttycap);
624: write(STDOUT, "';\n", 3);
625:
626: /* reset noglob */
627: if (csh)
628: write(STDOUT, "unset noglob;\n", 14);
629: }
630: }
631:
632: /* exit if report only mode */
633: if (RepOnly)
634: exit(0);
635:
636: if (gtty(FILEDES, &mode) < 0)
637: {
638: prs("Not a terminal\n");
639: exit(1);
640: }
641: bmove(&mode, &oldmode, sizeof mode);
642:
643: /* determine erase and kill characters */
644: if (Specialerase && !tgetflag("bs"))
645: Erase_char = 0;
646: bufp = buf;
647: p = tgetstr("bc", &bufp);
648: if (p != NULL)
649: bs_char = p[0];
650: else if (tgetflag("bs"))
651: bs_char = BACKSPACE;
652: else
653: bs_char = 0;
654: if (Erase_char == 0 && !tgetflag("os"))
655: {
656: if (tgetflag("bs") || bs_char != 0)
657: Erase_char = -1;
658: }
659: if (Erase_char < 0)
660: Erase_char = (bs_char != 0) ? bs_char : BACKSPACE;
661:
662: if (mode.sg_erase == 0)
663: mode.sg_erase = OLDERASE;
664: if (Erase_char != 0)
665: mode.sg_erase = Erase_char;
666:
667: if (mode.sg_kill == 0)
668: mode.sg_kill = OLDKILL;
669: if (Kill_char != 0)
670: mode.sg_kill = Kill_char;
671:
672: /* set modes */
673: setdelay("dC", CRdelay, CRbits, &mode.sg_flags);
674: setdelay("dN", NLdelay, NLbits, &mode.sg_flags);
675: setdelay("dB", BSdelay, BSbits, &mode.sg_flags);
676: setdelay("dF", FFdelay, FFbits, &mode.sg_flags);
677: setdelay("dT", TBdelay, TBbits, &mode.sg_flags);
678: if (tgetflag("UC") || command[0] == 'T')
679: mode.sg_flags |= LCASE;
680: else if (tgetflag("LC"))
681: mode.sg_flags &= ~LCASE;
682: mode.sg_flags &= ~(EVENP | ODDP | RAW);
683: # ifndef V6
684: mode.sg_flags &= ~CBREAK;
685: # endif
686: if (tgetflag("EP"))
687: mode.sg_flags |= EVENP;
688: if (tgetflag("OP"))
689: mode.sg_flags |= ODDP;
690: if ((mode.sg_flags & (EVENP | ODDP)) == 0)
691: mode.sg_flags |= EVENP | ODDP;
692: mode.sg_flags |= CRMOD | ECHO | XTABS;
693: if (tgetflag("NL")) /* new line, not line feed */
694: mode.sg_flags &= ~CRMOD;
695: if (tgetflag("HD")) /* half duplex */
696: mode.sg_flags &= ~ECHO;
697: if (tgetflag("pt")) /* print tabs */
698: mode.sg_flags &= ~XTABS;
699: if (!bequal(&mode, &oldmode, sizeof mode))
700: # ifndef V6
701: ioctl(FILEDES, TIOCSETN, &mode);
702: # else
703: stty(FILEDES, &mode);
704: # endif
705:
706: /* tell about changing erase and kill characters */
707: reportek("Erase", mode.sg_erase, oldmode.sg_erase, OLDERASE);
708: reportek("Kill", mode.sg_kill, oldmode.sg_kill, OLDKILL);
709:
710: # ifdef V6
711: /* update htmp */
712: if (!Dash_u)
713: {
714: if (Ttyid == 0)
715: Ttyid = ttyn(FILEDES);
716: if (Ttyid == 'x')
717: prs("Cannot update htmp\n");
718: else
719: {
720: /* update htmp file only if changed */
721: if (!bequal(Capbuf, hsgettype(), 2))
722: {
723: hsettype(Capbuf[0] | (Capbuf[1] << 8));
724: hput(Ttyid);
725: }
726: }
727: }
728: # endif
729:
730: exit(0);
731: }
732:
733:
734: reportek(name, new, old, def)
735: char *name;
736: char old;
737: char new;
738: char def;
739: {
740: register char o;
741: register char n;
742: register char *p;
743:
744: if (BeQuiet)
745: return;
746: o = old;
747: n = new;
748:
749: if (o == n && n == def)
750: return;
751: prs(name);
752: if (o == n)
753: prs(" is ");
754: else
755: prs(" set to ");
756: if (n < 040)
757: {
758: prs("control-");
759: n = (n & 037) | 0100;
760: }
761: p = "x\n";
762: p[0] = n;
763: prs(p);
764: }
765:
766:
767:
768:
769: setdelay(cap, dtab, bits, flags)
770: char *cap;
771: struct delay dtab[];
772: int bits;
773: int *flags;
774: {
775: register int i;
776: register struct delay *p;
777:
778: /* see if this capability exists at all */
779: i = tgetnum(cap);
780: if (i < 0)
781: i = 0;
782:
783: /* clear out the bits, replace with new ones */
784: *flags &= ~bits;
785:
786: /* scan dtab for first entry with adequate delay */
787: for (p = dtab; p->d_delay >= 0; p++)
788: {
789: if (p->d_delay >= i)
790: {
791: p++;
792: break;
793: }
794: }
795:
796: /* use last entry if none will do */
797: *flags |= (--p)->d_bits;
798: }
799:
800:
801: prs(s)
802: char *s;
803: {
804: register char *p;
805: register char *q;
806: register int i;
807:
808: p = q = s;
809: i = 0;
810: while (*q++ != 0)
811: i++;
812:
813: if (i > 0)
814: write(FILEDES, p, i);
815: }
816:
817:
818: cat(file)
819: char *file;
820: {
821: register int fd;
822: register int i;
823: char buf[BUFSIZ];
824:
825: fd = open(file, 0);
826: if (fd < 0)
827: {
828: prs("Cannot open ");
829: prs(file);
830: prs("\n");
831: exit(-1);
832: }
833:
834: while ((i = read(fd, buf, BUFSIZ)) > 0)
835: write(FILEDES, buf, i);
836:
837: close(fd);
838: }
839:
840:
841:
842: bmove(from, to, length)
843: char *from;
844: char *to;
845: int length;
846: {
847: register char *p, *q;
848: register int i;
849:
850: i = length;
851: p = from;
852: q = to;
853:
854: while (i-- > 0)
855: *q++ = *p++;
856: }
857:
858:
859:
860: bequal(a, b, len)
861: char *a;
862: char *b;
863: int len;
864: {
865: register char *p, *q;
866: register int i;
867:
868: i = len;
869: p = a;
870: q = b;
871:
872: while (i-- > 0)
873: if (*p++ != *q++)
874: return (0);
875: return (1);
876: }
877:
878: # ifdef GTTYN
879: char *
880: stypeof(ttyid)
881: char *ttyid;
882: {
883: static char typebuf[3];
884: char buf[50];
885: register char *p;
886: register FILE *f;
887: register char *t;
888: register char *q;
889:
890: if (ttyid == NOTTY)
891: return ("un");
892: f = fopen("/etc/ttytype", "r");
893: if (f == NULL)
894: return ("un");
895:
896: /* split off end of name */
897: for (p = q = ttyid; *p != 0; p++)
898: if (*p == '/')
899: q = p + 1;
900:
901: /* scan the file */
902: while (fgets(buf, sizeof buf, f) != NULL)
903: {
904: for (p = q, t = &buf[3]; *p != '\0'; p++, t++)
905: if (*p != *t)
906: break;
907: if (*p == '\0' && (*t == '\n' || *t == '\t'))
908: {
909: typebuf[0] = buf[0];
910: typebuf[1] = buf[1];
911: typebuf[2] = '\0';
912: fclose(f);
913: return (typebuf);
914: }
915: }
916: fclose (f);
917: return ("un");
918: }
919: # endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.