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