Commit | Line | Data |
---|---|---|
7c1e1a13 BJ |
1 | # include <sgtty.h> |
2 | # include <stdio.h> | |
3 | ||
4 | /* | |
5 | ** TSET -- set terminal modes | |
6 | ** | |
7 | ** This program does sophisticated terminal initialization. | |
8 | ** I recommend that you include it in your .start_up or .login | |
9 | ** file to initialize whatever terminal you are on. | |
10 | ** | |
11 | ** There are several features: | |
12 | ** | |
13 | ** A special file or sequence (as controlled by the ttycap file) | |
14 | ** is sent to the terminal. | |
15 | ** | |
16 | ** Mode bits are set on a per-terminal_type basis (much better | |
17 | ** than UNIX itself). This allows special delays, automatic | |
18 | ** tabs, etc. | |
19 | ** | |
20 | ** Erase and Kill characters can be set to whatever you want. | |
21 | ** Default is to change erase to control-H on a terminal which | |
22 | ** can overstrike, and leave it alone on anything else. Kill | |
23 | ** is always left alone unless specifically requested. | |
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. | |
29 | ** | |
30 | ** The htmp file, used by ex, etc., can be updated. | |
31 | ** | |
32 | ** The current terminal type can be queried. | |
33 | ** | |
34 | ** Usage: | |
35 | ** tset [-] [-r] [-EC] [-eC] [-d type] [-p type] | |
36 | ** [-b type] [-h] [-u] [type] | |
37 | ** | |
38 | ** In systems with environments, use: | |
39 | ** setenv TERM `tset - ...` | |
40 | ** | |
41 | ** Positional Parameters: | |
42 | ** type -- the terminal type to force. If this is | |
43 | ** specified, initialization is for this | |
44 | ** terminal type. | |
45 | ** | |
46 | ** Flags: | |
47 | ** - -- report terminal type. Whatever type is | |
48 | ** decided on is reported. | |
49 | ** -r -- report to user, on diagnostic output instead | |
50 | ** of standard output. | |
51 | ** -EC -- set the erase character to C on all terminals | |
52 | ** except those which cannot backspace (e.g., | |
53 | ** a TTY 33). C defaults to control-H. | |
54 | ** -eC -- set the erase character to C on all terminals. | |
55 | ** C defaults to control-H. If neither -E or -e | |
56 | ** are specified, the erase character is set to | |
57 | ** control-H if the terminal can both backspace | |
58 | ** and not overstrike (e.g., a CRT). If the erase | |
59 | ** character is NULL (zero byte), it will be reset | |
60 | ** to '#' if nothing else is specified. | |
61 | ** -kC -- set the kill character to C on all terminals. | |
62 | ** Default for C is control-X. If not specified, | |
63 | ** the kill character is untouched; however, if | |
64 | ** not specified and the kill character is NULL | |
65 | ** (zero byte), the kill character is set to '@'. | |
66 | ** -d type -- set the dialup type to be type. If the | |
67 | ** terminal type seems to be dialup, make it | |
68 | ** 'type' instead. There need not be a space | |
69 | ** between 'd' and 'type'. | |
70 | ** -p type -- ditto for a plugboard. | |
71 | ** -b type -- ditto for a bussiplexer. | |
72 | ** -h -- don't read htmp file. Normally the terminal type | |
73 | ** is determined by reading the htmp file (unless | |
74 | ** -d or -p are specified). This forces a read | |
75 | ** of the ttytype file -- useful when htmp is | |
76 | ** somehow wrong. On a version seven system, this | |
77 | ** flag means don't look at the TERM entry in | |
78 | ** the environment. | |
79 | ** -u -- don't update htmp. It seemed like this should | |
80 | ** be put in. Note that htmp is never actually | |
81 | ** written if there are no changes, so don't bother | |
82 | ** bother using this for efficiency reasons alone. | |
83 | ** On version seven systems this flag is ignored. | |
84 | ** | |
85 | ** Files: | |
86 | ** /etc/ttytype | |
87 | ** contains a terminal id -> terminal type | |
88 | ** mapping; used when -h, -d, or -p is used. | |
89 | ** /etc/termcap | |
90 | ** a terminal_type -> terminal_capabilities | |
91 | ** mapping. | |
92 | ** | |
93 | ** Return Codes: | |
94 | ** -1 -- couldn't open ttycap. | |
95 | ** 1 -- bad terminal type, or standard output not tty. | |
96 | ** 0 -- ok. | |
97 | ** | |
98 | ** Defined Constants: | |
99 | ** DIALUP -- the type code for a dialup port | |
100 | ** PLUGBOARD -- the code for a plugboard port. | |
101 | ** BUSSIPLEXER -- the code for a bussiplexer port. | |
102 | ** BACKSPACE -- control-H, the default for -e. | |
103 | ** CONTROLX -- control-X, the default for -k. | |
104 | ** OLDERASE -- the system default erase character. | |
105 | ** OLDKILL -- the system default kill character. | |
106 | ** FILEDES -- the file descriptor to do the operation | |
107 | ** on, nominally 1 or 2. | |
108 | ** STDOUT -- the standard output file descriptor. | |
109 | ** UIDMASK -- the bit pattern to mask with the getuid() | |
110 | ** call to get just the user id. | |
111 | ** | |
112 | ** Requires: | |
113 | ** Routines to handle htmp, ttytype, and ttycap. | |
114 | ** | |
115 | ** Compilation Flags: | |
116 | ** PLUGBOARD -- if defined, accept the -p flag. | |
117 | ** BUSSIPLEXER -- if defined, accept the -b flag. | |
118 | ** FULLLOGIN -- if defined, login sets the ttytype from | |
119 | ** /etc/ttytype file. | |
120 | ** VERSION7 -- if set, use environments, not htmp. | |
121 | ** Also, use 'ioctl' not 'stty' -- to get type- | |
122 | ** ahead. | |
123 | ** GTTYN -- if set, uses generalized tty names. | |
124 | ** | |
125 | ** Compilation Instructions: | |
126 | ** cc -n -O tset.c -lX | |
127 | ** mv a.out tset | |
128 | ** chown bin tset | |
129 | ** chmod 4755 tset | |
130 | ** | |
131 | ** where 'bin' should be whoever owns the 'htmp' file. | |
132 | ** If 'htmp' is 666, then tset need not be setuid. | |
133 | ** | |
134 | ** Author: | |
135 | ** Eric Allman | |
136 | ** Electronics Research Labs | |
137 | ** U.C. Berkeley | |
138 | ** | |
139 | ** History: | |
140 | ** 3/79 -- Use ioctl in version7. | |
141 | ** 12/78 -- modified for eventual migration to VAX/UNIX, | |
142 | ** so the '-' option is changed to output only | |
143 | ** the terminal type to STDOUT instead of | |
144 | ** FILEDES. FULLLOGIN flag added. BUSSIPLEXER | |
145 | ** and -r added. | |
146 | ** 9/78 -- '-' and '-p' options added (now fully | |
147 | ** compatible with ttytype!), and spaces are | |
148 | ** permitted between the -d and the type. | |
149 | ** 8/78 -- The sense of -h and -u were reversed, and the | |
150 | ** -f flag is dropped -- same effect is available | |
151 | ** by just stating the terminal type. | |
152 | ** 10/77 -- This version, in much it's previous state, | |
153 | ** written by Eric Allman. | |
154 | */ | |
155 | ||
156 | # define BACKSPACE ('H' & 037) | |
157 | # define CONTROLX ('X' & 037) | |
158 | # define OLDERASE '#' | |
159 | # define OLDKILL '@' | |
160 | ||
161 | # define FILEDES 2 | |
162 | # define STDOUT 1 | |
163 | ||
164 | # define DIALUP "du" | |
165 | # define PLUGBOARD "pb" | |
166 | # define BUSSIPLEXER "bx" | |
167 | /* # define FULLLOGIN FULLLOGIN login does everything */ | |
168 | /* # define VERSION7 VERSION7 version seven flag */ | |
169 | /* # define GTTYN GTTYN general tty names */ | |
170 | ||
171 | # ifdef VERSION7 | |
172 | # define UIDMASK 0177777 | |
173 | # else | |
174 | # define UIDMASK 0377 | |
175 | # endif | |
176 | ||
177 | # ifdef GTTYN | |
178 | typedef char *ttyid_t; | |
179 | # else | |
180 | typedef char ttyid_t; | |
181 | # endif | |
182 | ||
183 | # define NOTTY 0 | |
184 | ||
185 | ||
186 | ||
187 | ||
188 | ||
189 | char Erase_char; /* new erase character */ | |
190 | char Kill_char; /* new kill character */ | |
191 | char Specialerase; /* set => Erase_char only on terminals with backspace */ | |
192 | ||
193 | ttyid_t Ttyid = NOTTY; /* terminal identifier */ | |
194 | char *Ttytype; /* type of terminal */ | |
195 | char *Dialtype; /* override type if dialup terminal */ | |
196 | char *Plugtype; /* override type if plugboard port */ | |
197 | char *Bxtype; /* override type if bussiplexer port */ | |
198 | int Dash_u; /* don't-update-htmp flag */ | |
199 | int Dash_h; /* don't-read-htmp flag */ | |
200 | int Report; /* report current type */ | |
201 | int Ureport; /* report to user */ | |
202 | ||
203 | char Usage[] = "usage: tset [-] [-r] [-eC] [-kC] [-d T] [-p T] [-b T] [-h] [-u] [type]\n"; | |
204 | ||
205 | char Capbuf[256]; /* line from /etc/ttycap for this Ttytype */ | |
206 | ||
207 | struct delay | |
208 | { | |
209 | int d_delay; | |
210 | int d_bits; | |
211 | }; | |
212 | ||
213 | # include "tset.del.h" | |
214 | ||
215 | ||
216 | ||
217 | main(argc, argv) | |
218 | int argc; | |
219 | char *argv[]; | |
220 | { | |
221 | struct sgttyb mode; | |
222 | struct sgttyb oldmode; | |
223 | char buf[256]; | |
224 | auto char *bufp; | |
225 | register char *p; | |
226 | char *command; | |
227 | register int i; | |
228 | register int error; | |
229 | int mdvect[2]; | |
230 | extern char *stypeof(); | |
231 | # ifndef VERSION7 | |
232 | extern char *hsgettype(); | |
233 | # else | |
234 | extern char *getenv(); | |
235 | # endif | |
236 | # ifdef GTTYN | |
237 | extern char *ttyname(); | |
238 | # endif | |
239 | ||
240 | /* scan argument list and collect flags */ | |
241 | error = 0; | |
242 | command = argv[0]; | |
243 | argc--; | |
244 | while (--argc >= 0) | |
245 | { | |
246 | p = *++argv; | |
247 | if (p[0] == '-') | |
248 | { | |
249 | switch (p[1]) | |
250 | { | |
251 | ||
252 | case 0: /* report current terminal type */ | |
253 | Report++; | |
254 | continue; | |
255 | ||
256 | case 'r': /* report to user */ | |
257 | Ureport++; | |
258 | continue; | |
259 | ||
260 | case 'E': /* special erase: operate on all but TTY33 */ | |
261 | Specialerase++; | |
262 | /* exlicit fall-through to -e case */ | |
263 | ||
264 | case 'e': /* erase character */ | |
265 | if (p[2] == 0) | |
266 | Erase_char = BACKSPACE; | |
267 | else | |
268 | Erase_char = p[2]; | |
269 | continue; | |
270 | ||
271 | case 'k': /* kill character */ | |
272 | if (p[2] == 0) | |
273 | Kill_char = CONTROLX; | |
274 | else | |
275 | Kill_char = p[2]; | |
276 | continue; | |
277 | ||
278 | case 'd': /* dialup type */ | |
279 | if (p[2] != 0) | |
280 | Dialtype = &p[2]; | |
281 | else if (--argc < 0 || argv[1][0] == '-') | |
282 | error++; | |
283 | else | |
284 | Dialtype = *++argv; | |
285 | continue; | |
286 | ||
287 | # ifdef PLUGBOARD | |
288 | case 'p': /* plugboard type */ | |
289 | if (p[2] != 0) | |
290 | Plugtype = &p[2]; | |
291 | else if (--argc < 0 || argv[1][0] == '-') | |
292 | error++; | |
293 | else | |
294 | Plugtype = *++argv; | |
295 | continue; | |
296 | # endif | |
297 | ||
298 | # ifdef BUSSIPLEXER | |
299 | case 'b': /* bussiplexer type */ | |
300 | if (p[2] != 0) | |
301 | Bxtype = &p[2]; | |
302 | else if (--argc < 0 || argv[1][0] == '-') | |
303 | error++; | |
304 | else | |
305 | Bxtype = *++argv; | |
306 | # endif | |
307 | ||
308 | case 'h': /* don't get type from htmp */ | |
309 | Dash_h++; | |
310 | continue; | |
311 | ||
312 | # ifndef VERSION7 | |
313 | case 'u': /* don't update htmp */ | |
314 | Dash_u++; | |
315 | continue; | |
316 | # endif | |
317 | ||
318 | default: | |
319 | prs("Bad flag "); | |
320 | prs(p); | |
321 | prs("\n"); | |
322 | error++; | |
323 | ||
324 | } | |
325 | } | |
326 | else | |
327 | { | |
328 | /* terminal type */ | |
329 | Ttytype = p; | |
330 | } | |
331 | } | |
332 | ||
333 | if (error) | |
334 | { | |
335 | prs(Usage); | |
336 | exit(1); | |
337 | } | |
338 | ||
339 | # ifndef FULLLOGIN | |
340 | /* if dialup is specified, check ttytype not htmp */ | |
341 | if (Dialtype != 0 || Plugtype != 0 || Bxtype != 0) | |
342 | Dash_h++; | |
343 | # endif | |
344 | ||
345 | /* determine terminal id if needed */ | |
346 | if (Ttyid == NOTTY && (Ttytype == 0 || !Dash_h || !Dash_u)) | |
347 | # ifndef VERSION7 | |
348 | Ttyid = ttyn(FILEDES); | |
349 | # else | |
350 | Ttyid = ttyname(FILEDES); | |
351 | # endif | |
352 | ||
353 | # ifndef VERSION7 | |
354 | /* get htmp if ever used */ | |
355 | if (!Dash_u || (Ttytype == 0 && !Dash_h)) | |
356 | { | |
357 | /* get htmp entry */ | |
358 | hget(Ttyid); | |
359 | ||
360 | /* if not for this user, look at ttytype file */ | |
361 | if (hgettype() == 0 || hgetuid() != (getuid() & UIDMASK)) | |
362 | Dash_h++; | |
363 | } | |
364 | # endif | |
365 | ||
366 | /* find terminal type (if not already known) */ | |
367 | if (Ttytype == 0) | |
368 | { | |
369 | /* get type from /etc/ttytype or /etc/htmp */ | |
370 | if (!Dash_h) | |
371 | { | |
372 | # ifndef VERSION7 | |
373 | Ttytype = hsgettype(); | |
374 | # else | |
375 | Ttytype = getenv("TERM"); | |
376 | # endif | |
377 | } | |
378 | if (Ttytype == 0) | |
379 | { | |
380 | Ttytype = stypeof(Ttyid); | |
381 | } | |
382 | ||
383 | /* check for dialup or plugboard override */ | |
384 | if (Dialtype != 0 && bequal(Ttytype, DIALUP, 2)) | |
385 | Ttytype = Dialtype; | |
386 | # ifdef PLUGBOARD | |
387 | else if (Plugtype != 0 && bequal(Ttytype, PLUGBOARD, 2)) | |
388 | Ttytype = Plugtype; | |
389 | # endif | |
390 | # ifdef BUSSIPLEXER | |
391 | else if (Bxtype != 0 && bequal(Ttytype, BUSSIPLEXER, 2)) | |
392 | Ttytype = Bxtype; | |
393 | # endif | |
394 | } | |
395 | ||
396 | /* Ttytype now contains a pointer to the type of the terminal */ | |
397 | ||
398 | if (gtty(FILEDES, &mode) < 0) | |
399 | { | |
400 | prs("Not a terminal\n"); | |
401 | exit(1); | |
402 | } | |
403 | bmove(&mode, &oldmode, sizeof mode); | |
404 | ||
405 | /* get terminal capabilities */ | |
406 | switch (tgetent(Capbuf, Ttytype)) | |
407 | { | |
408 | ||
409 | case -1: | |
410 | prs("Cannot open ttycap file\n"); | |
411 | exit(-1); | |
412 | ||
413 | case 0: | |
414 | prs("Type "); | |
415 | prs(Ttytype); | |
416 | prs(" unknown\n"); | |
417 | exit(1); | |
418 | } | |
419 | ||
420 | /* report type if appropriate */ | |
421 | if (Report || Ureport) | |
422 | { | |
423 | /* find first alias (if any) */ | |
424 | for (p = Capbuf; *p != 0 && *p != '|' && *p != ':'; p++) | |
425 | continue; | |
426 | if (*p == 0 || *p == ':') | |
427 | p = Capbuf; | |
428 | else | |
429 | p++; | |
430 | bufp = p; | |
431 | while (*p != '|' && *p != ':' && *p != 0) | |
432 | p++; | |
433 | i = *p; | |
434 | if (Report) | |
435 | { | |
436 | *p = '\n'; | |
437 | write(STDOUT, bufp, p + 1 - bufp); | |
438 | } | |
439 | if (Ureport) | |
440 | { | |
441 | *p = '\0'; | |
442 | prs("Terminal type is "); | |
443 | prs(bufp); | |
444 | prs("\n"); | |
445 | } | |
446 | *p = i; | |
447 | } | |
448 | ||
449 | /* determine erase and kill characters */ | |
450 | if (Specialerase && !tgetflag("bs")) | |
451 | Erase_char = 0; | |
452 | if (Erase_char == 0) | |
453 | { | |
454 | if (mode.sg_erase == 0) | |
455 | mode.sg_erase = OLDERASE; | |
456 | if (tgetflag("bs") && !tgetflag("os")) | |
457 | mode.sg_erase = BACKSPACE; | |
458 | } | |
459 | else | |
460 | mode.sg_erase = Erase_char; | |
461 | ||
462 | if (mode.sg_kill == 0) | |
463 | mode.sg_kill = OLDKILL; | |
464 | if (Kill_char != 0) | |
465 | mode.sg_kill = Kill_char; | |
466 | ||
467 | /* set modes */ | |
468 | setdelay("dC", CRdelay, CRbits, &mode.sg_flags); | |
469 | setdelay("dN", NLdelay, NLbits, &mode.sg_flags); | |
470 | setdelay("dB", BSdelay, BSbits, &mode.sg_flags); | |
471 | setdelay("dF", FFdelay, FFbits, &mode.sg_flags); | |
472 | setdelay("dT", TBdelay, TBbits, &mode.sg_flags); | |
473 | if (tgetflag("UC") || command[0] == 'T') | |
474 | mode.sg_flags |= LCASE; | |
475 | else if (tgetflag("LC")) | |
476 | mode.sg_flags &= ~LCASE; | |
477 | mode.sg_flags &= ~(EVENP | ODDP | RAW); | |
478 | if (tgetflag("EP")) | |
479 | mode.sg_flags |= EVENP; | |
480 | if (tgetflag("OP")) | |
481 | mode.sg_flags |= ODDP; | |
482 | if ((mode.sg_flags & (EVENP | ODDP)) == 0) | |
483 | mode.sg_flags |= EVENP | ODDP; | |
484 | mode.sg_flags |= CRMOD | ECHO | XTABS; | |
485 | if (tgetflag("NL")) /* new line, not line feed */ | |
486 | mode.sg_flags &= ~CRMOD; | |
487 | if (tgetflag("HD")) /* half duplex */ | |
488 | mode.sg_flags &= ~ECHO; | |
489 | if (tgetflag("pt")) /* print tabs */ | |
490 | mode.sg_flags &= ~XTABS; | |
491 | # ifdef VERSION7 | |
492 | if (!bequal(&mode, &oldmode, sizeof mode)) | |
493 | ioctl(FILEDES, TIOCSETN, &mode); | |
494 | # else | |
495 | if (!bequal(&mode, &oldmode, sizeof mode)) | |
496 | stty(FILEDES, &mode); | |
497 | # endif | |
498 | ||
499 | /* output startup string */ | |
500 | bufp = buf; | |
501 | if (tgetstr("is", &bufp) != 0) | |
502 | prs(buf); | |
503 | bufp = buf; | |
504 | if (tgetstr("if", &bufp) != 0) | |
505 | cat(buf); | |
506 | ||
507 | /* tell about changing erase and kill characters */ | |
508 | reportek("Erase", mode.sg_erase, oldmode.sg_erase, OLDERASE); | |
509 | reportek("Kill", mode.sg_kill, oldmode.sg_kill, OLDKILL); | |
510 | ||
511 | # ifndef VERSION7 | |
512 | /* update htmp */ | |
513 | if (!Dash_u) | |
514 | { | |
515 | if (Ttyid == 0) | |
516 | Ttyid = ttyn(FILEDES); | |
517 | if (Ttyid == 'x') | |
518 | prs("Cannot update htmp\n"); | |
519 | else | |
520 | { | |
521 | /* update htmp file only if changed */ | |
522 | if (!bequal(Capbuf, hsgettype(), 2)) | |
523 | { | |
524 | hsettype(Capbuf[0] | (Capbuf[1] << 8)); | |
525 | hput(Ttyid); | |
526 | } | |
527 | } | |
528 | } | |
529 | # endif | |
530 | ||
531 | exit(0); | |
532 | } | |
533 | ||
534 | ||
535 | reportek(name, new, old, def) | |
536 | char *name; | |
537 | char old; | |
538 | char new; | |
539 | char def; | |
540 | { | |
541 | register char o; | |
542 | register char n; | |
543 | register char *p; | |
544 | ||
545 | o = old; | |
546 | n = new; | |
547 | ||
548 | if (o == n && n == def) | |
549 | return; | |
550 | prs(name); | |
551 | if (o == n) | |
552 | prs(" is "); | |
553 | else | |
554 | prs(" set to "); | |
555 | if (n < 040) | |
556 | { | |
557 | prs("control-"); | |
558 | n = (n & 037) | 0100; | |
559 | } | |
560 | p = "x\n"; | |
561 | p[0] = n; | |
562 | prs(p); | |
563 | } | |
564 | ||
565 | ||
566 | ||
567 | ||
568 | setdelay(cap, dtab, bits, flags) | |
569 | char *cap; | |
570 | struct delay dtab[]; | |
571 | int bits; | |
572 | int *flags; | |
573 | { | |
574 | register int i; | |
575 | register struct delay *p; | |
576 | ||
577 | /* see if this capability exists at all */ | |
578 | i = tgetnum(cap); | |
579 | if (i < 0) | |
580 | i = 0; | |
581 | ||
582 | /* clear out the bits, replace with new ones */ | |
583 | *flags &= ~bits; | |
584 | ||
585 | /* scan dtab for first entry with adequate delay */ | |
586 | for (p = dtab; p->d_delay >= 0; p++) | |
587 | { | |
588 | if (p->d_delay >= i) | |
589 | { | |
590 | p++; | |
591 | break; | |
592 | } | |
593 | } | |
594 | ||
595 | /* use last entry if none will do */ | |
596 | *flags |= (--p)->d_bits; | |
597 | } | |
598 | ||
599 | ||
600 | prs(s) | |
601 | char *s; | |
602 | { | |
603 | register char *p; | |
604 | register char *q; | |
605 | register int i; | |
606 | ||
607 | p = q = s; | |
608 | i = 0; | |
609 | while (*q++ != 0) | |
610 | i++; | |
611 | ||
612 | if (i > 0) | |
613 | write(FILEDES, p, i); | |
614 | } | |
615 | ||
616 | ||
617 | cat(file) | |
618 | char *file; | |
619 | { | |
620 | register int fd; | |
621 | register int i; | |
622 | char buf[512]; | |
623 | ||
624 | fd = open(file, 0); | |
625 | if (fd < 0) | |
626 | { | |
627 | prs("Cannot open "); | |
628 | prs(file); | |
629 | prs("\n"); | |
630 | exit(-1); | |
631 | } | |
632 | ||
633 | while ((i = read(fd, buf, 512)) > 0) | |
634 | write(FILEDES, buf, i); | |
635 | ||
636 | close(fd); | |
637 | } | |
638 | ||
639 | ||
640 | ||
641 | bmove(from, to, length) | |
642 | char *from; | |
643 | char *to; | |
644 | int length; | |
645 | { | |
646 | register char *p, *q; | |
647 | register int i; | |
648 | ||
649 | i = length; | |
650 | p = from; | |
651 | q = to; | |
652 | ||
653 | while (i-- > 0) | |
654 | *q++ = *p++; | |
655 | } | |
656 | ||
657 | ||
658 | ||
659 | bequal(a, b, len) | |
660 | char *a; | |
661 | char *b; | |
662 | int len; | |
663 | { | |
664 | register char *p, *q; | |
665 | register int i; | |
666 | ||
667 | i = len; | |
668 | p = a; | |
669 | q = b; | |
670 | ||
671 | while (i-- > 0) | |
672 | if (*p++ != *q++) | |
673 | return (0); | |
674 | return (1); | |
675 | } |