|
|
1.1 root 1: #ifndef lint
2: static char sccsid[] = "@(#)acucntrl.c 5.8 (Berkeley) 2/12/86";
3: #endif
4:
5: /* acucntrl - turn around tty line between dialin and dialout
6: *
7: * Usage: acucntrl {enable,disable} /dev/ttydX
8: *
9: * History:
10: * First written by Allan Wilkes (fisher!allan)
11: *
12: * Modified June 8,1983 by W.Sebok (astrovax!wls) to poke kernel rather
13: * than use kernel hack to turn on/off modem control, using subroutine
14: * stolen from program written by Tsutomu Shimomura
15: * {astrovax,escher}!tsutomu
16: *
17: * Worked over many times by W.Sebok (i.e. hacked to death)
18: *
19: * Operation:
20: * disable (i.e. setup for dialing out)
21: * (1) check input arguments
22: * (2) look in /etc/utmp to check that the line is not in use by another
23: * (3) disable modem control on terminal
24: * (4) check for carrier on device
25: * (5) change owner of device to real id
26: * (6) edit /etc/ttys, changing the first character of the appropriate
27: * line to 0
28: * (7) send a hangup to process 1 to poke init to disable getty
29: * (8) post uid name in capitals in /etc/utmp to let world know device has
30: * been grabbed
31: * (9) make sure that DTR is on
32: *
33: * enable (i.e.) restore for dialin
34: * (1) check input arguments
35: * (2) look in /etc/utmp to check that the line is not in use by another
36: * (3) make sure modem control on terminal is disabled
37: * (4) turn off DTR to make sure line is hung up
38: * (5) condition line: clear exclusive use and set hangup on close modes
39: * (6) turn on modem control
40: * (7) edit /etc/ttys, changing the first character of the appropriate
41: * line to 1
42: * (8) send a hangup to process 1 to poke init to enable getty
43: * (9) clear uid name for /etc/utmp
44: */
45:
46: /* #define SENSECARRIER */
47:
48: #include "uucp.h"
49: #include <sys/buf.h>
50: #include <signal.h>
51: #include <sys/conf.h>
52: #ifdef BSD4_2
53: #include <vaxuba/ubavar.h>
54: #else
55: #include <sys/ubavar.h>
56: #endif
57: #include <sys/stat.h>
58: #include <nlist.h>
59: #include <sgtty.h>
60: #include <utmp.h>
61: #include <pwd.h>
62: #include <stdio.h>
63: #include <sys/file.h>
64:
65: #define NDZLINE 8 /* lines/dz */
66: #define NDHLINE 16 /* lines/dh */
67: #define NDMFLINE 8 /* lines/dmf */
68:
69: #define DZ11 1
70: #define DH11 2
71: #define DMF 3
72:
73: #define NLVALUE(val) (nl[val].n_value)
74:
75: struct nlist nl[] = {
76: #define CDEVSW 0
77: { "_cdevsw" },
78:
79: #define DZOPEN 1
80: { "_dzopen" },
81: #define DZINFO 2
82: { "_dzinfo" },
83: #define NDZ11 3
84: { "_dz_cnt" },
85: #define DZSCAR 4
86: { "_dzsoftCAR" },
87:
88: #define DHOPEN 5
89: { "_dhopen" },
90: #define DHINFO 6
91: { "_dhinfo" },
92: #define NDH11 7
93: { "_ndh11" },
94: #define DHSCAR 8
95: { "_dhsoftCAR" },
96:
97: #define DMFOPEN 9
98: { "_dmfopen" },
99: #define DMFINFO 10
100: { "_dmfinfo" },
101: #define NDMF 11
102: { "_ndmf" },
103: #define DMFSCAR 12
104: { "_dmfsoftCAR" },
105:
106: { "\0" }
107: };
108:
109: #define ENABLE 1
110: #define DISABLE 0
111:
112: char Etcutmp[] = "/etc/utmp";
113: char Etcttys[] = "/etc/ttys";
114: #ifdef BSD4_3
115: FILE *ttysfile, *nttysfile;
116: char NEtcttys[] = "/etc/ttys.new";
117: extern long ftell();
118: #endif BSD4_3
119: char Devhome[] = "/dev";
120:
121: char usage[] = "Usage: acucntrl {dis|en}able ttydX\n";
122:
123: struct utmp utmp;
124: char resettty, resetmodem;
125: int etcutmp;
126: off_t utmploc;
127: off_t ttyslnbeg;
128:
129: #define NAMSIZ sizeof(utmp.ut_name)
130: #define LINSIZ sizeof(utmp.ut_line)
131:
132: main(argc, argv)
133: int argc; char *argv[];
134: {
135: register char *p;
136: register int i;
137: char uname[NAMSIZ], Uname[NAMSIZ];
138: int enable ;
139: char *device;
140: int devfile;
141: int uid, gid;
142: off_t lseek();
143: struct passwd *getpwuid();
144: char *rindex();
145: extern int errno;
146: extern char *sys_errlist[];
147:
148: /* check input arguments */
149: if (argc!=3) {
150: fprintf(stderr, usage);
151: exit(1);
152: }
153:
154: /* interpret command type */
155: if (prefix(argv[1], "disable") || strcmp(argv[1], "dialout")==0)
156: enable = 0;
157: else if (prefix(argv[1], "enable") || strcmp(argv[1], "dialin")==0)
158: enable = 1;
159: else {
160: fprintf(stderr, usage);
161: exit(1);
162: }
163:
164: device = rindex(argv[2], '/');
165: device = (device == NULL) ? argv[2]: device+1;
166:
167: /* only recognize devices of the form ttydX */
168: if (strncmp(device, "ttyd", 4)!=0) {
169: fprintf(stderr, "Bad Device Name %s", device);
170: exit(1);
171: }
172:
173: opnttys(device);
174:
175: /* Get nlist info */
176: nlist("/vmunix", nl);
177:
178: /* Chdir to /dev */
179: if(chdir(Devhome) < 0) {
180: fprintf(stderr, "Cannot chdir to %s: %s\r\n",
181: Devhome, sys_errlist[errno]);
182: exit(1);
183: }
184:
185: /* Get uid information */
186: uid = getuid();
187: gid = getgid();
188:
189: p = getpwuid(uid)->pw_name;
190: if (p==NULL) {
191: fprintf(stderr, "cannot get uid name\n");
192: exit(1);
193: }
194:
195: /* to upper case */
196: i = 0;
197: do {
198: uname[i] = *p;
199: Uname[i] = (*p>='a' && *p<='z') ? (*p - ('a'-'A')) : *p;
200: i++; p++;
201: } while (*p && i<NAMSIZ);
202:
203:
204: /* check to see if line is being used */
205: if( (etcutmp = open(Etcutmp, 2)) < 0) {
206: fprintf(stderr, "On open %s open: %s\n",
207: Etcutmp, sys_errlist[errno]);
208: exit(1);
209: }
210:
211: (void)lseek(etcutmp, utmploc, 0);
212:
213: i = read(etcutmp, (char *)&utmp, sizeof(struct utmp));
214:
215: if(
216: i == sizeof(struct utmp) &&
217: utmp.ut_line[0] != '\0' &&
218: utmp.ut_name[0] != '\0' &&
219: (
220: !upcase(utmp.ut_name, NAMSIZ) ||
221: (
222: uid != 0 &&
223: strncmp(utmp.ut_name, Uname, NAMSIZ) != 0
224: )
225: )
226: ) {
227: fprintf(stderr, "%s in use by %s\n", device, utmp.ut_name);
228: exit(2);
229: }
230:
231: /* Disable modem control */
232: if (setmodem(device, DISABLE) < 0) {
233: fprintf(stderr, "Unable to disable modem control\n");
234: exit(1);
235: }
236:
237: if (enable) {
238: if((devfile = open(device, 1)) < 0) {
239: fprintf(stderr, "On open of %s: %s\n",
240: device, sys_errlist[errno]);
241: (void)setmodem(device, resetmodem);
242: exit(1);
243: }
244: /* Try one last time to hang up */
245: if (ioctl(devfile, (int)TIOCCDTR, (char *)0) < 0)
246: fprintf(stderr, "On TIOCCDTR ioctl: %s\n",
247: sys_errlist[errno]);
248:
249: if (ioctl(devfile, (int)TIOCNXCL, (char *)0) < 0)
250: fprintf(stderr,
251: "Cannot clear Exclusive Use on %s: %s\n",
252: device, sys_errlist[errno]);
253:
254: if (ioctl(devfile, (int)TIOCHPCL, (char *)0) < 0)
255: fprintf(stderr,
256: "Cannot set hangup on close on %s: %s\n",
257: device, sys_errlist[errno]);
258:
259: i = resetmodem;
260:
261: if (setmodem(device, ENABLE) < 0) {
262: fprintf(stderr, "Cannot Enable modem control\n");
263: (void)setmodem(device, i);
264: exit(1);
265: }
266: resetmodem=i;
267:
268: if (settys(ENABLE)) {
269: fprintf(stderr, "%s already enabled\n", device);
270: } else {
271: pokeinit(device, Uname, enable);
272: }
273: post(device, "");
274:
275: } else {
276: #if defined(TIOCMGET) && defined(SENSECARRIER)
277: if (uid!=0) {
278: int linestat = 0;
279:
280: /* check for presence of carrier */
281: sleep(2); /* need time after modem control turnoff */
282:
283: if((devfile = open(device, 1)) < 0) {
284: fprintf(stderr, "On open of %s: %s\n",
285: device, sys_errlist[errno]);
286: (void)setmodem(device, resetmodem);
287: exit(1);
288: }
289:
290: (void)ioctl(devfile, TIOCMGET, &linestat);
291:
292: if (linestat&TIOCM_CAR) {
293: fprintf(stderr, "%s is in use (Carrier On)\n",
294: device);
295: (void)setmodem(device, resetmodem);
296: exit(2);
297: }
298: (void)close(devfile);
299: }
300: #endif TIOCMGET
301: /* chown device */
302: if(chown(device, uid, gid) < 0)
303: fprintf(stderr, "Cannot chown %s: %s\n",
304: device, sys_errlist[errno]);
305:
306:
307: /* poke init */
308: if(settys(DISABLE)) {
309: fprintf(stderr, "%s already disabled\n", device);
310: } else {
311: pokeinit(device, Uname, enable);
312: }
313: post(device, Uname);
314: if((devfile = open(device, O_RDWR|O_NDELAY)) < 0) {
315: fprintf(stderr, "On %s open: %s\n",
316: device, sys_errlist[errno]);
317: } else {
318: if(ioctl(devfile, (int)TIOCSDTR, (char *)0) < 0)
319: fprintf(stderr,
320: "Cannot set DTR on %s: %s\n",
321: device, sys_errlist[errno]);
322: }
323: }
324:
325: exit(0);
326: }
327:
328: /* return true if no lower case */
329: upcase(str, len)
330: register char *str;
331: register int len;
332: {
333: for (; *str, --len >= 0 ; str++)
334: if (*str>='a' && *str<='z')
335: return(0);
336: return(1);
337: }
338:
339: /* Post name to public */
340: post(device, name)
341: char *device, *name;
342: {
343: (void)time((time_t *)&utmp.ut_time);
344: strncpy(utmp.ut_line, device, LINSIZ);
345: strncpy(utmp.ut_name, name, NAMSIZ);
346: if (lseek(etcutmp, utmploc, 0) < 0)
347: fprintf(stderr, "on lseek in /etc/utmp: %s",
348: sys_errlist[errno]);
349: if (write(etcutmp, (char *)&utmp, sizeof(utmp)) < 0)
350: fprintf(stderr, "on write in /etc/utmp: %s",
351: sys_errlist[errno]);
352: }
353:
354: /* poke process 1 and wait for it to do its thing */
355: pokeinit(device, uname, enable)
356: char *uname, *device; int enable;
357: {
358: struct utmp utmp;
359: register int i;
360:
361: post(device, uname);
362:
363: /* poke init */
364: if (kill(1, SIGHUP)) {
365: fprintf(stderr,
366: "Cannot send hangup to init process: %s\n",
367: sys_errlist[errno]);
368: (void)settys(resettty);
369: (void)setmodem(device, resetmodem);
370: exit(1);
371: }
372:
373: if (enable)
374: return;
375:
376: /* wait till init has responded, clearing the utmp entry */
377: i = 100;
378: do {
379: sleep(1);
380: if (lseek(etcutmp, utmploc, 0) < 0)
381: fprintf(stderr, "On lseek in /etc/utmp: %s",
382: sys_errlist[errno]);
383: if (read(etcutmp, (char *)&utmp, sizeof utmp) < 0)
384: fprintf(stderr, "On read from /etc/utmp: %s",
385: sys_errlist[errno]);
386: } while (utmp.ut_name[0] != '\0' && --i > 0);
387: }
388:
389: #ifdef BSD4_3
390: /* identify terminal line in ttys */
391: opnttys(device)
392: char *device;
393: {
394: register int ndevice;
395: register char *p;
396: char *index();
397: char linebuf[BUFSIZ];
398:
399: ttysfile = NULL;
400: do {
401: if (ttysfile != NULL) {
402: fclose(ttysfile);
403: sleep(5);
404: }
405: ttysfile = fopen(Etcttys, "r");
406: if(ttysfile == NULL) {
407: fprintf(stderr, "Cannot open %s: %s\n", Etcttys,
408: sys_errlist[errno]);
409: exit(1);
410: }
411: } while (flock(fileno(ttysfile), LOCK_NB|LOCK_EX) < 0);
412: nttysfile = fopen(NEtcttys, "w");
413: if(nttysfile == NULL) {
414: fprintf(stderr, "Cannot open %s: %s\n", Etcttys,
415: sys_errlist[errno]);
416: exit(1);
417: }
418:
419: ndevice = strlen(device);
420: #ifndef BRL4_2
421: utmploc = sizeof(utmp);
422: #else BRL4_2
423: utmploc = 0;
424: #endif BRL4_2
425:
426: while(fgets(linebuf, sizeof(linebuf) - 1, ttysfile) != NULL) {
427: if(strncmp(device, linebuf, ndevice) == 0)
428: return;
429: ttyslnbeg += strlen(linebuf);
430: if (linebuf[0] != '#' && linebuf[0] != '\0')
431: utmploc += sizeof(utmp);
432: if (fputs(linebuf, nttysfile) == NULL) {
433: fprintf(stderr, "On %s write: %s\n",
434: Etcttys, sys_errlist[errno]);
435: exit(1);
436: }
437:
438: }
439: fprintf(stderr, "%s not found in %s\n", device, Etcttys);
440: exit(1);
441: }
442:
443: /* modify appropriate line in /etc/ttys to turn on/off the device */
444: settys(enable)
445: int enable;
446: {
447: register char *cp, *cp2;
448: char lbuf[BUFSIZ];
449: int i;
450: char c1, c2;
451:
452: (void) fseek(ttysfile, ttyslnbeg, 0);
453: if(fgets(lbuf, BUFSIZ, ttysfile) == NULL) {
454: fprintf(stderr, "On %s read: %s\n",
455: Etcttys, sys_errlist[errno]);
456: exit(1);
457: }
458: /* format is now */
459: /* ttyd0 std.100 dialup on secure # comment */
460: /* except, 2nd item may have embedded spaces inside quotes, Hubert */
461: cp = lbuf;
462: for (i=0;*cp && i<3;i++) {
463: if (*cp == '"') {
464: cp++;
465: while (*cp && *cp != '"')
466: cp++;
467: if (*cp != '\0')
468: cp++;
469: }else {
470: while (*cp && *cp != ' ' && *cp != '\t')
471: cp++;
472: }
473: while (*cp && (*cp == ' ' || *cp == '\t'))
474: cp++;
475: }
476: if (*cp == '\0') {
477: fprintf(stderr,"Badly formatted line in /etc/ttys:\n%s", lbuf);
478: exit(1);
479: }
480: c1 = *--cp;
481: *cp++ = '\0';
482: cp2 = cp;
483: while (*cp && *cp != ' ' && *cp != '\t' && *cp != '\n')
484: cp++;
485: if (*cp == '\0') {
486: fprintf(stderr,"Badly formatted line in /etc/ttys:\n%s", lbuf);
487: exit(1);
488: }
489: c2 = *cp;
490: *cp++ = '\0';
491: while (*cp && (*cp == ' ' || *cp == '\t'))
492: cp++;
493: resettty = strcmp("on", cp2) != 0;
494: fprintf(nttysfile,"%s%c%s%c%s", lbuf, c1, enable ? "on" : "off", c2, cp);
495: if (ferror(nttysfile)) {
496: fprintf(stderr, "On %s fprintf: %s\n",
497: NEtcttys, sys_errlist[errno]);
498: exit(1);
499: }
500: while(fgets(lbuf, sizeof(lbuf) - 1, ttysfile) != NULL) {
501: if (fputs(lbuf, nttysfile) == NULL) {
502: fprintf(stderr, "On %s write: %s\n",
503: NEtcttys, sys_errlist[errno]);
504: exit(1);
505: }
506: }
507:
508: if (enable^resettty)
509: (void) unlink(NEtcttys);
510: else {
511: struct stat statb;
512: if (stat(Etcttys, &statb) == 0) {
513: fchmod(fileno(nttysfile) ,statb.st_mode);
514: fchown(fileno(nttysfile), statb.st_uid, statb.st_gid);
515: }
516: (void) rename(NEtcttys, Etcttys);
517: }
518: (void) fclose(nttysfile);
519: (void) fclose(ttysfile);
520: return enable^resettty;
521: }
522:
523: #else !BSD4_3
524:
525: /* identify terminal line in ttys */
526: opnttys(device)
527: char *device;
528: {
529: register FILE *ttysfile;
530: register int ndevice, lnsiz;
531: register char *p;
532: char *index();
533: char linebuf[BUFSIZ];
534:
535: ttysfile = fopen(Etcttys, "r");
536: if(ttysfile == NULL) {
537: fprintf(stderr, "Cannot open %s: %s\n", Etcttys,
538: sys_errlist[errno]);
539: exit(1);
540: }
541:
542: ndevice = strlen(device);
543: ttyslnbeg = 0;
544: utmploc = 0;
545:
546: while(fgets(linebuf, sizeof(linebuf) - 1, ttysfile) != NULL) {
547: lnsiz = strlen(linebuf);
548: if ((p = index(linebuf, '\n')) != NULL)
549: *p = '\0';
550: if(strncmp(device, &linebuf[2], ndevice) == 0) {
551: (void)fclose(ttysfile);
552: return;
553: }
554: ttyslnbeg += lnsiz;
555: utmploc += sizeof(utmp);
556: }
557: fprintf(stderr, "%s not found in %s\n", device, Etcttys);
558: exit(1);
559: }
560:
561: /* modify appropriate line in /etc/ttys to turn on/off the device */
562: settys(enable)
563: int enable;
564: {
565: int ittysfil;
566: char out, in;
567:
568: ittysfil = open(Etcttys, 2);
569: if(ittysfil < 0) {
570: fprintf(stderr, "Cannot open %s for output: %s\n",
571: Etcttys, sys_errlist[errno]);
572: exit(1);
573: }
574: (void)lseek(ittysfil, ttyslnbeg, 0);
575: if(read(ittysfil, &in, 1)<0) {
576: fprintf(stderr, "On %s write: %s\n",
577: Etcttys, sys_errlist[errno]);
578: exit(1);
579: }
580: resettty = (in == '1');
581: out = enable ? '1' : '0';
582: (void)lseek(ittysfil, ttyslnbeg, 0);
583: if(write(ittysfil, &out, 1)<0) {
584: fprintf(stderr, "On %s write: %s\n",
585: Etcttys, sys_errlist[errno]);
586: exit(1);
587: }
588: (void)close(ittysfil);
589: return(in==out);
590: }
591: #endif !BSD4_3
592:
593: /*
594: * Excerpted from (June 8, 1983 W.Sebok)
595: * > ttymodem.c - enable/disable modem control for tty lines.
596: * >
597: * > Knows about DZ11s and DH11/DM11s.
598: * > 23.3.83 - TS
599: * > modified to know about DMF's (hasn't been tested) Nov 8, 1984 - WLS
600: */
601:
602:
603: setmodem(ttyline, enable)
604: char *ttyline; int enable;
605: {
606: dev_t dev;
607: int kmem;
608: int unit, line, nlines, addr, tflags;
609: int devtype=0;
610: char cflags; short sflags;
611: #ifdef BSD4_2
612: int flags;
613: #else
614: short flags;
615: #endif
616: struct uba_device *ubinfo;
617: struct stat statb;
618: struct cdevsw cdevsw;
619:
620: if(nl[CDEVSW].n_type == 0) {
621: fprintf(stderr, "No namelist.\n");
622: return(-1);
623: }
624:
625: if((kmem = open("/dev/kmem", 2)) < 0) {
626: fprintf(stderr, "/dev/kmem open: %s\n", sys_errlist[errno]);
627: return(-1);
628: }
629:
630: if(stat(ttyline, &statb) < 0) {
631: fprintf(stderr, "%s stat: %s\n", ttyline, sys_errlist[errno]);
632: return(-1);
633: }
634:
635: if((statb.st_mode&S_IFMT) != S_IFCHR) {
636: fprintf(stderr, "%s is not a character device.\n",ttyline);
637: return(-1);
638: }
639:
640: dev = statb.st_rdev;
641: (void)lseek(kmem,
642: (off_t) &(((struct cdevsw *)NLVALUE(CDEVSW))[major(dev)]),0);
643: (void)read(kmem, (char *) &cdevsw, sizeof cdevsw);
644:
645: if((int)(cdevsw.d_open) == NLVALUE(DZOPEN)) {
646: devtype = DZ11;
647: unit = minor(dev) / NDZLINE;
648: line = minor(dev) % NDZLINE;
649: addr = (int) &(((int *)NLVALUE(DZINFO))[unit]);
650: (void)lseek(kmem, (off_t) NLVALUE(NDZ11), 0);
651: } else if((int)(cdevsw.d_open) == NLVALUE(DHOPEN)) {
652: devtype = DH11;
653: unit = minor(dev) / NDHLINE;
654: line = minor(dev) % NDHLINE;
655: addr = (int) &(((int *)NLVALUE(DHINFO))[unit]);
656: (void)lseek(kmem, (off_t) NLVALUE(NDH11), 0);
657: } else if((int)(cdevsw.d_open) == NLVALUE(DMFOPEN)) {
658: devtype = DMF;
659: unit = minor(dev) / NDMFLINE;
660: line = minor(dev) % NDMFLINE;
661: addr = (int) &(((int *)NLVALUE(DMFINFO))[unit]);
662: (void)lseek(kmem, (off_t) NLVALUE(NDMF), 0);
663: } else {
664: fprintf(stderr, "Device %s (%d/%d) unknown.\n", ttyline,
665: major(dev), minor(dev));
666: return(-1);
667: }
668:
669: (void)read(kmem, (char *) &nlines, sizeof nlines);
670: if(minor(dev) >= nlines) {
671: fprintf(stderr, "Sub-device %d does not exist (only %d).\n",
672: minor(dev), nlines);
673: return(-1);
674: }
675:
676: (void)lseek(kmem, (off_t)addr, 0);
677: (void)read(kmem, (char *) &ubinfo, sizeof ubinfo);
678: (void)lseek(kmem, (off_t) &(ubinfo->ui_flags), 0);
679: (void)read(kmem, (char *) &flags, sizeof flags);
680:
681: tflags = 1<<line;
682: resetmodem = ((flags&tflags) == 0);
683: flags = enable ? (flags & ~tflags) : (flags | tflags);
684: (void)lseek(kmem, (off_t) &(ubinfo->ui_flags), 0);
685: (void)write(kmem, (char *) &flags, sizeof flags);
686: switch(devtype) {
687: case DZ11:
688: if((addr = NLVALUE(DZSCAR)) == 0) {
689: fprintf(stderr, "No dzsoftCAR.\n");
690: return(-1);
691: }
692: cflags = flags;
693: (void)lseek(kmem, (off_t) &(((char *)addr)[unit]), 0);
694: (void)write(kmem, (char *) &cflags, sizeof cflags);
695: break;
696: case DH11:
697: if((addr = NLVALUE(DHSCAR)) == 0) {
698: fprintf(stderr, "No dhsoftCAR.\n");
699: return(-1);
700: }
701: sflags = flags;
702: (void)lseek(kmem, (off_t) &(((short *)addr)[unit]), 0);
703: (void)write(kmem, (char *) &sflags, sizeof sflags);
704: break;
705: case DMF:
706: if((addr = NLVALUE(DMFSCAR)) == 0) {
707: fprintf(stderr, "No dmfsoftCAR.\n");
708: return(-1);
709: }
710: cflags = flags;
711: (void)lseek(kmem, (off_t) &(((char *)addr)[unit]), 0);
712: (void)write(kmem, (char *) &flags, sizeof cflags);
713: break;
714: default:
715: fprintf(stderr, "Unknown device type\n");
716: return(-1);
717: }
718: return(0);
719: }
720:
721: prefix(s1, s2)
722: register char *s1, *s2;
723: {
724: register char c;
725:
726: while ((c = *s1++) == *s2++)
727: if (c == '\0')
728: return (1);
729: return (c == '\0');
730: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.