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: }