1: #include <whoami.h> 2: #include <stdio.h> 3: #include <signal.h> 4: #include <sgtty.h> 5: /* 6: * defs that come from uucp.h 7: */ 8: #define NAMESIZE 35 9: #define FAIL -1 10: #define SAME 0 11: #define SLCKTIME 5400 /* system/device timeout (LCK.. files) in seconds */ 12: #define ASSERT(e, f, v) if (!(e)) {\ 13: fprintf(stderr, "AERROR - (%s) ", "e");\ 14: fprintf(stderr, f, v);\ 15: cleanup(FAIL);\ 16: } 17: 18: /* 19: * cu telno [-t] [-s speed] [-l line] [-a acu] [-p] 20: * 21: * -t is for dial-out to terminal. 22: * speeds are: 110, 134, 150, 300, 1200, 2400. 300 is default. 23: * 24: * -p says strip parity of characters transmitted. (to compensate 25: * for c100's) 26: * 27: * Escape with `~' at beginning of line. 28: * Ordinary diversions are ~<, ~> and ~>>. 29: * Silent output diversions are ~>: and ~>>:. 30: * Terminate output diversion with ~> alone. 31: * Quit is ~. and ~! gives local command or shell. 32: * Also ~$ for canned procedure pumping remote. 33: * ~%put from [to] and ~%take from [to] invoke builtins 34: */ 35: 36: #define CRLF "\r\n" 37: #define wrc(ds) write(ds,&c,1) 38: 39: 40: char *devcul = "/dev/cul0"; 41: char *devcua = "/dev/cua0"; 42: char *lspeed = "300"; 43: 44: int ln; /* fd for comm line */ 45: char tkill, terase; /* current input kill & erase */ 46: int notabs; /* terminal doesn't expand tabs */ 47: int efk; /* process of id of listener */ 48: char c; 49: char oc; 50: 51: char *connmsg[] = { 52: "", 53: "line busy", 54: "call dropped", 55: "no carrier", 56: "can't fork", 57: "acu access", 58: "tty access", 59: "tty hung", 60: "usage: cu telno [-t] [-p] [-h] [-b] [-acu#] [-s speed] [-l line] [-a acu]", 61: "lock failed: line busy" 62: }; 63: 64: rdc(ds) { 65: 66: ds=read(ds,&oc,1); 67: c = oc & 0177; 68: return (ds); 69: } 70: 71: int intr; 72: 73: sig2() 74: { 75: signal(SIGINT, SIG_IGN); 76: intr = 1; 77: } 78: 79: int set14; 80: 81: xsleep(n) 82: { 83: xalarm(n); 84: pause(); 85: xalarm(0); 86: } 87: 88: xalarm(n) 89: { 90: set14=n; 91: alarm(n); 92: } 93: 94: sig14() 95: { 96: signal(SIGALRM, sig14); 97: if (set14) alarm(1); 98: } 99: 100: int dout; 101: int nhup; 102: int dbflag; 103: int pflag; /* strip parity on chars sent to remote */ 104: int hdplx; /* set to emulate half-duplex terminal */ 105: int nullbrk; /* turn breaks (nulls) into dels */ 106: int pipes[2] = { -1, -1 }; 107: int speed; 108: 109: /* 110: * main: get connection, set speed for line. 111: * spawn child to invoke rd to read from line, output to fd 1 112: * main line invokes wr to read tty, write to line 113: */ 114: main(ac,av) 115: char *av[]; 116: { 117: int fk; 118: char *telno = NULL; 119: struct sgttyb stbuf; 120: int cleanup(); 121: 122: signal(SIGALRM, sig14); 123: nhup = (int)signal(SIGINT, cleanup); 124: signal(SIGHUP, cleanup); 125: signal(SIGQUIT, cleanup); 126: if (ac < 2) { 127: prf(connmsg[8]); 128: exit(8); 129: } 130: for (; ac > 1; av++,ac--) { 131: if (av[1][0] != '-') 132: telno = av[1]; 133: else switch(av[1][1]) { 134: case 't': 135: dout = 1; 136: continue; 137: case 'b': 138: nullbrk++; 139: continue; 140: case 'd': 141: dbflag++; 142: continue; 143: case 'h': 144: hdplx++; 145: continue; 146: case 'p': 147: pflag++; 148: continue; 149: case 's': 150: lspeed = av[2]; ++av; --ac; 151: break; 152: case 'l': 153: devcul = av[2]; ++av; --ac; 154: break; 155: case 'a': 156: devcua = av[2]; ++av; --ac; 157: break; 158: case '0': case '1': case '2': case '3': case '4': 159: case '5': case '6': case '7': case '8': case '9': 160: devcua[strlen(devcua)-1] = av[1][1]; 161: devcul[strlen(devcul)-1] = av[1][1]; 162: break; 163: default: 164: prf("Bad flag %s", av[1]); 165: break; 166: } 167: } 168: if (telno == NULL) { 169: prf(connmsg[8]); 170: exit(8); 171: } 172: if (!exists(devcua) || !exists(devcul)) 173: exit(9); 174: switch(atoi(lspeed)) { 175: case 110: 176: speed = B110;break; 177: case 150: 178: speed = B150;break; 179: default: 180: case 300: 181: speed = B300;break; 182: case 1200: 183: speed = B1200;break; 184: case 2400: 185: speed = B2400;break; 186: } 187: ln = conn(devcul, devcua, telno); 188: if (ln < 0) { 189: prf("Connect failed: %s",connmsg[-ln]); 190: cleanup(-ln); 191: } 192: ioctl(0, TIOCGETP, &stbuf); 193: notabs = stbuf.sg_flags & XTABS; 194: stbuf.sg_ispeed = speed; 195: stbuf.sg_ospeed = speed; 196: stbuf.sg_flags = EVENP|ODDP; 197: if (!dout) 198: stbuf.sg_flags |= RAW | TANDEM; 199: ioctl(ln, TIOCSETP, &stbuf); 200: ioctl(ln, TIOCEXCL, (struct sgttyb *)NULL); 201: ioctl(ln, TIOCHPCL, (struct sgttyb *)NULL); 202: prf("Connected"); 203: pipe(pipes); 204: if (dout) 205: fk = -1; 206: else 207: fk = fork(); 208: signal(SIGINT, SIG_IGN); 209: if (fk == 0) { 210: chwrsig(); 211: rd(); 212: prf("\007Lost carrier"); 213: cleanup(3); 214: } 215: mode(1); 216: efk = fk; 217: wr(); 218: mode(0); 219: if (fk != -1) kill(fk, SIGKILL); 220: wait((int *)NULL); 221: stbuf.sg_ispeed = 0; 222: stbuf.sg_ospeed = 0; 223: ioctl(ln, TIOCSETP, &stbuf); 224: prf("Disconnected"); 225: cleanup(0); 226: } 227: 228: /* 229: * conn: establish dial-out connection. 230: * Example: fd = conn("/dev/ttyh","/dev/dn1","4500"); 231: * Returns descriptor open to tty for reading and writing. 232: * Negative values (-1...-7) denote errors in connmsg. 233: * Uses alarm and fork/wait; requires sig14 handler. 234: * Be sure to disconnect tty when done, via HUPCL or stty 0. 235: */ 236: conn(dev,acu,telno) 237: char *dev, *acu, *telno; 238: { 239: struct sgttyb stbuf; 240: extern errno; 241: char *p, *q, b[30]; 242: char *ltail, *atail; 243: char *rindex(); 244: int er, fk, dn, dh, t; 245: er=0; 246: fk=(-1); 247: atail = rindex(acu, '/')+1; 248: if (mlock(atail) == FAIL) { 249: er = 9; 250: goto X; 251: } 252: ltail = rindex(dev, '/')+1; 253: if (mlock(ltail) == FAIL) { 254: er = 9; 255: delock(atail); 256: goto X; 257: } 258: if ((dn=open(acu,1))<0) { 259: er=(errno == 6? 1:5); 260: goto X; 261: } 262: if ((fk=fork()) == (-1)) { 263: er=4; 264: goto X; 265: } 266: if (fk == 0) { 267: open(dev,2); 268: for (;;) pause(); 269: } 270: xsleep(2); 271: /* 272: * copy phone #, assure EON 273: */ 274: p=b; 275: q=telno; 276: while (*p++=(*q++)) 277: ; 278: p--; 279: if (*(p-1)!='<') { 280: /*if (*(p-1)!='-') *p++='-';*/ 281: *p++='<'; 282: } 283: t=p-b; 284: xalarm(5*t); 285: t=write(dn,b,t); 286: xalarm(0); 287: if (t<0) { 288: er=2; 289: goto X; 290: } 291: /* close(dn) */ 292: xalarm(40); /* was 5; sometimes missed carrier */ 293: dh = open(dev,2); 294: xalarm(0); 295: if (dh<0) { 296: er=(errno == 4? 3:6); 297: goto X; 298: } 299: ioctl(dh, TIOCGETP, &stbuf); 300: stbuf.sg_flags &= ~ECHO; 301: xalarm(10); 302: ioctl(dh, TIOCSETP, &stbuf); 303: ioctl(dh, TIOCHPCL, (struct sgttyb *)NULL); 304: xalarm(0); 305: X: 306: if (er) close(dn); 307: delock(atail); 308: if (fk!=(-1)) { 309: kill(fk, SIGKILL); 310: xalarm(10); 311: while ((t=wait((int *)NULL))!=(-1) && t!=fk); 312: xalarm(0); 313: } 314: return (er? -er:dh); 315: } 316: 317: /* 318: * wr: write to remote: 0 -> line. 319: * ~. terminate 320: * ~<file send file 321: * ~! local login-style shell 322: * ~!cmd execute cmd locally 323: * ~$proc execute proc locally, send output to line 324: * ~%cmd execute builtin cmd (put and take) 325: * ~# send 1-sec break 326: * ~^Z suspend cu process. 327: */ 328: 329: wr() 330: { 331: int ds,fk,lcl,x; 332: char *p,b[600]; 333: for (;;) { 334: p=b; 335: while (rdc(0) == 1) { 336: if (p == b) lcl=(c == '~'); 337: if (p == b+1 && b[0] == '~') lcl=(c!='~'); 338: if (nullbrk && c == 0) oc=c=0177; /* fake break kludge */ 339: if (!lcl) { 340: if(!pflag)c = oc; 341: if (wrc(ln) == 0) { 342: prf("line gone"); return; 343: } 344: if (hdplx) wrc(0); 345: c &= 0177; 346: } 347: if (lcl) { 348: if (c == 0177) c=tkill; 349: if (c == '\r' || c == '\n') goto A; 350: if (!dout) wrc(0); 351: } 352: *p++=c; 353: if (c == terase) { 354: p=p-2; 355: if (p<b) p=b; 356: } 357: if (c == tkill || c == 0177 || c == '\4' || c == '\r' || c == '\n') p=b; 358: } 359: return; 360: A: 361: if (!dout) echo(""); 362: *p=0; 363: switch (b[1]) { 364: case '.': 365: case '\004': 366: return; 367: #ifdef TIOCSBRK 368: case '#': 369: if (ioctl(ln, TIOCSBRK, 0) < 0) 370: prf("can't send break"); 371: else { 372: sleep(1); 373: ioctl(ln, TIOCCBRK, 0); 374: continue; 375: } 376: #endif 377: case '!': 378: case '$': 379: fk = fork(); 380: if (fk == 0) { 381: char *getenv(); 382: char *shell = getenv("SHELL"); 383: if (shell == 0) shell = "/bin/sh"; 384: close(1); 385: dup(b[1] == '$'? ln:2); 386: close(ln); 387: mode(0); 388: if (!nhup) signal(SIGINT, SIG_DFL); 389: if (b[2] == 0) execl(shell,shell,0); 390: /* if (b[2] == 0) execl(shell,"-",0); */ 391: else execl(shell,"sh","-c",b+2,0); 392: prf("Can't execute shell"); 393: exit(~0); 394: } 395: if (fk!=(-1)) { 396: while (wait(&x)!=fk); 397: } 398: mode(1); 399: if (b[1] == '!') echo("!"); 400: else { 401: if (dout) echo("$"); 402: } 403: break; 404: case '<': 405: if (b[2] == 0) break; 406: if ((ds=open(b+2,0))<0) { 407: prf("Can't divert %s",b+1); 408: break; 409: } 410: intr=x=0; 411: mode(2); 412: if (!nhup) signal(SIGINT, sig2); 413: while (!intr && rdc(ds) == 1) { 414: if (wrc(ln) == 0) { 415: x=1; 416: break; 417: } 418: } 419: signal(SIGINT, SIG_IGN); 420: close(ds); 421: mode(1); 422: if (x) return; 423: if (dout) echo("<"); 424: break; 425: case '>': 426: case ':': 427: { 428: register char *q; 429: 430: if(pipes[1]==-1) { 431: prf("Can't tell other demon to divert"); 432: break; 433: } 434: q = b+1; 435: if(*q=='>') q++; 436: write(pipes[1],q,strlen(q)+1); 437: if(dbflag) prf("msg to be delivered:"),prf(q); 438: if (efk != -1) kill(efk,SIGEMT); 439: } 440: break; 441: #ifdef SIGTSTP 442: #define CTRLZ 26 443: case CTRLZ: 444: mode(0); 445: kill(getpid(), SIGTSTP); 446: mode(1); 447: break; 448: #endif 449: case '%': 450: dopercen(&b[2]); 451: break; 452: default: 453: prf("Use `~~' to start line with `~'"); 454: } 455: continue; 456: } 457: } 458: 459: dopercen(line) 460: register char *line; 461: { 462: char *args[10]; 463: register narg, f; 464: int rcount; 465: for (narg = 0; narg < 10;) { 466: while(*line == ' ' || *line == '\t') 467: line++; 468: if (*line == '\0') 469: break; 470: args[narg++] = line; 471: while(*line != '\0' && *line != ' ' && *line != '\t') 472: line++; 473: if (*line == '\0') 474: break; 475: *line++ = '\0'; 476: } 477: if (equal(args[0], "take")) { 478: if (narg < 2) { 479: prf("usage: ~%%take from [to]"); 480: return; 481: } 482: if (narg < 3) 483: args[2] = args[1]; 484: write(pipes[1], ">/dev/null",sizeof(">/dev/null")); 485: if(dbflag) prf("sending take message"); 486: if (efk != -1) kill(efk,SIGEMT); 487: xsleep(5); 488: if (notabs) 489: wrln("stty tabs;"); 490: wrln("echo '~>:"); 491: wrln(args[2]); 492: wrln("'; tee /dev/null <"); 493: wrln(args[1]); 494: wrln(";echo '~>'"); 495: if (notabs) 496: wrln(";stty -tabs"); 497: wrln("\n"); 498: return; 499: } else if (equal(args[0], "put")) { 500: if (narg < 2) { 501: prf("usage: ~%%put from [to]"); 502: return; 503: } 504: if (narg < 3) 505: args[2] = args[1]; 506: if ((f = open(args[1], 0)) < 0) { 507: prf("cannot open: %s", args[1]); 508: return; 509: } 510: wrln("stty -echo;cat >"); 511: wrln(args[2]); 512: wrln(";stty echo\n"); 513: xsleep(5); 514: intr = 0; 515: if (!nhup) 516: signal(SIGINT, sig2); 517: mode(2); 518: rcount = 0; 519: while(!intr && rdc(f) == 1) { 520: rcount++; 521: if (c == tkill || c == terase) 522: wrln("\\"); 523: if (wrc(ln) != 1) { 524: xsleep(2); 525: if (wrc(ln) != 1) { 526: prf("character missed"); 527: intr = 1; 528: break; 529: } 530: } 531: } 532: signal(SIGINT, SIG_IGN); 533: close(f); 534: if (intr) { 535: wrln("\n"); 536: prf("stopped after %d bytes", rcount); 537: } 538: wrln("\004"); 539: xsleep(5); 540: mode(1); 541: return; 542: } 543: prf("~%%%s unknown\n", args[0]); 544: } 545: 546: equal(s1, s2) 547: register char *s1, *s2; 548: { 549: while (*s1++ == *s2) 550: if (*s2++ == '\0') 551: return(1); 552: return(0); 553: } 554: 555: wrln(s) 556: register char *s; 557: { 558: while (*s) 559: write(ln, s++, 1); 560: } 561: /* chwrsig: Catch orders from wr process 562: * to instigate diversion 563: */ 564: int whoami; 565: chwrsig(){ 566: int readmsg(); 567: whoami = getpid(); 568: signal(SIGEMT,readmsg); 569: } 570: int ds,slnt,taking; 571: int justrung; 572: readmsg(){ 573: static char dobuff[128], morejunk[256]; 574: int n; 575: justrung = 1; 576: signal(SIGEMT,readmsg); 577: if(dbflag) { 578: prf("About to read from pipe"); 579: } 580: n = read(pipes[0],morejunk,256); 581: if(dbflag) { 582: prf("diversion mesg recieved is"); 583: prf(morejunk); 584: prf(CRLF); 585: } 586: dodiver(morejunk); 587: } 588: dodiver(msg) 589: char *msg; 590: { 591: register char *cp = msg; 592: 593: if (*cp=='>') cp++; 594: if (*cp==':') { 595: cp++; 596: if(*cp==0) { 597: slnt ^= 1; 598: return; 599: } else { 600: slnt = 1; 601: } 602: } 603: if (ds >= 0) close(ds); 604: if (*cp==0) { 605: slnt = 0; 606: ds = -1; 607: return; 608: } 609: if (*msg!='>' || (ds=open(cp,1))<0) ds=creat(cp,0644); 610: lseek(ds, (long)0, 2); 611: if(ds < 0) prf("Creat failed:"), prf(cp); 612: if (ds<0) prf("Can't divert %s",cp+1); 613: } 614: 615: 616: /* 617: * rd: read from remote: line -> 1 618: * catch: diversion caught by interrupt routine 619: */ 620: 621: #define ORDIN 0 622: #define SAWCR 1 623: #define EOL 2 624: #define SAWTL 3 625: #define DIVER 4 626: 627: rd() 628: { 629: extern int ds,slnt; 630: char rb[600], lb[600], *rlim, *llim, c; 631: register char *p,*q; 632: int cnt, state = ORDIN, mustecho, oldslnt; 633: 634: ds=(-1); 635: p = lb; llim = lb+600; 636: agin: 637: while((cnt = read(ln,rb,600)) > 0) { 638: if(!slnt) { 639: if (pflag) 640: for (q=rb, rlim = rb + cnt - 1; q <= rlim; ) 641: *q++ &= 0177; 642: write(1,rb,cnt); 643: } 644: if(ds < 0) continue; 645: oldslnt = slnt; 646: for( q=rb, rlim = rb + cnt - 1; q <= rlim; ) { 647: c = *q++ & 0177; 648: if(p < llim) *p++ = c; 649: switch(state) { 650: case ORDIN: 651: if(c=='\r') state = SAWCR; 652: break; 653: case SAWCR: 654: if(c=='\n') { 655: state = EOL; 656: p--; 657: p[-1] = '\n'; 658: } else state = ORDIN; 659: break; 660: case EOL: 661: state = (c=='~' ? SAWTL : 662: (c=='\r' ? SAWCR : ORDIN)); 663: break; 664: case SAWTL: 665: state = (c=='>' ? DIVER : 666: (c=='\r' ? SAWCR : ORDIN)); 667: break; 668: case DIVER: 669: if(c=='\r') { 670: p--; 671: } else if (c=='\n') { 672: state = ORDIN; 673: p[-1] = 0; 674: dodiver(lb+2); 675: c = 0; p = lb; 676: } 677: } 678: if(slnt==0 && oldslnt) { 679: if(c=='\n') { 680: write(1,lb,p-lb-1); 681: write(1,CRLF,sizeof(CRLF)); 682: } else if(q==rlim) { 683: write(1,lb,p-lb); 684: c = '\n'; /*force flush to file*/ 685: } 686: } 687: if(c=='\n') { 688: if(ds >= 0) 689: write(ds,lb,p-lb); 690: p = lb; 691: } 692: } 693: } 694: if(justrung) { 695: justrung = 0; 696: goto agin; 697: } 698: } 699: 700: struct {char lobyte; char hibyte;}; 701: mode(f) 702: { 703: struct sgttyb stbuf; 704: if (dout) return; 705: ioctl(0, TIOCGETP, &stbuf); 706: tkill = stbuf.sg_kill; 707: terase = stbuf.sg_erase; 708: if (f == 0) { 709: stbuf.sg_flags &= ~RAW; 710: stbuf.sg_flags |= ECHO|CRMOD; 711: } 712: if (f == 1) { 713: stbuf.sg_flags |= RAW; 714: stbuf.sg_flags &= ~(ECHO|CRMOD); 715: } 716: if (f == 2) { 717: stbuf.sg_flags &= ~RAW; 718: stbuf.sg_flags &= ~(ECHO|CRMOD); 719: } 720: ioctl(0, TIOCSETP, &stbuf); 721: } 722: 723: echo(s) 724: char *s; 725: { 726: char *p; 727: for (p=s;*p;p++); 728: if (p>s) write(0,s,p-s); 729: write(0,CRLF, sizeof(CRLF)); 730: } 731: 732: prf(f, s) 733: char *f; 734: char *s; 735: { 736: fprintf(stderr, f, s); 737: fprintf(stderr, CRLF); 738: } 739: 740: exists(devname) 741: char *devname; 742: { 743: if (access(devname, 0)==0) 744: return(1); 745: prf("%s does not exist", devname); 746: return(0); 747: } 748: 749: cleanup(code) 750: { 751: rmlock(NULL); 752: ioctl(ln, TIOCNXCL, (struct sgttyb *)NULL); 753: exit(code); 754: } 755: 756: /* 757: * This code is taken directly from uucp and follows the same 758: * conventions. This is important since uucp and cu should 759: * respect each others locks. 760: */ 761: 762: /* ulockf 3.2 10/26/79 11:40:29 */ 763: /* #include "uucp.h" */ 764: #include <sys/types.h> 765: #include <sys/stat.h> 766: 767: 768: 769: /******* 770: * ulockf(file, atime) 771: * char *file; 772: * time_t atime; 773: * 774: * ulockf - this routine will create a lock file (file). 775: * If one already exists, the create time is checked for 776: * older than the age time (atime). 777: * If it is older, an attempt will be made to unlink it 778: * and create a new one. 779: * 780: * return codes: 0 | FAIL 781: */ 782: 783: ulockf(file, atime) 784: char *file; 785: time_t atime; 786: { 787: struct stat stbuf; 788: time_t ptime; 789: int ret; 790: static int pid = -1; 791: static char tempfile[NAMESIZE]; 792: 793: if (pid < 0) { 794: pid = getpid(); 795: sprintf(tempfile, "/usr/spool/uucp/LTMP.%d", pid); 796: } 797: if (onelock(pid, tempfile, file) == -1) { 798: /* lock file exists */ 799: /* get status to check age of the lock file */ 800: ret = stat(file, &stbuf); 801: if (ret != -1) { 802: time(&ptime); 803: if ((ptime - stbuf.st_ctime) < atime) { 804: /* file not old enough to delete */ 805: return(FAIL); 806: } 807: } 808: ret = unlink(file); 809: ret = onelock(pid, tempfile, file); 810: if (ret != 0) 811: return(FAIL); 812: } 813: stlock(file); 814: return(0); 815: } 816: 817: 818: #define MAXLOCKS 10 /* maximum number of lock files */ 819: char *Lockfile[MAXLOCKS]; 820: int Nlocks = 0; 821: 822: /*** 823: * stlock(name) put name in list of lock files 824: * char *name; 825: * 826: * return codes: none 827: */ 828: 829: stlock(name) 830: char *name; 831: { 832: char *p; 833: extern char *calloc(); 834: int i; 835: 836: for (i = 0; i < Nlocks; i++) { 837: if (Lockfile[i] == NULL) 838: break; 839: } 840: ASSERT(i < MAXLOCKS, "TOO MANY LOCKS %d", i); 841: if (i >= Nlocks) 842: i = Nlocks++; 843: p = calloc(strlen(name) + 1, sizeof (char)); 844: ASSERT(p != NULL, "CAN NOT ALLOCATE FOR %s", name); 845: strcpy(p, name); 846: Lockfile[i] = p; 847: return; 848: } 849: 850: 851: /*** 852: * rmlock(name) remove all lock files in list 853: * char *name; or name 854: * 855: * return codes: none 856: */ 857: 858: rmlock(name) 859: char *name; 860: { 861: int i; 862: 863: for (i = 0; i < Nlocks; i++) { 864: if (Lockfile[i] == NULL) 865: continue; 866: if (name == NULL 867: || strcmp(name, Lockfile[i]) == SAME) { 868: unlink(Lockfile[i]); 869: free(Lockfile[i]); 870: Lockfile[i] = NULL; 871: } 872: } 873: return; 874: } 875: 876: 877: /* this stuff from pjw */ 878: /* /usr/pjw/bin/recover - check pids to remove unnecessary locks */ 879: /* isalock(name) returns 0 if the name is a lock */ 880: /* unlock(name) unlocks name if it is a lock*/ 881: /* onelock(pid,tempfile,name) makes lock a name 882: on behalf of pid. Tempfile must be in the same 883: file system as name. */ 884: /* lock(pid,tempfile,names) either locks all the 885: names or none of them */ 886: isalock(name) char *name; 887: { 888: struct stat xstat; 889: if(stat(name,&xstat)<0) return(0); 890: if(xstat.st_size!=sizeof(int)) return(0); 891: return(1); 892: } 893: unlock(name) char *name; 894: { 895: if(isalock(name)) return(unlink(name)); 896: else return(-1); 897: } 898: onelock(pid,tempfile,name) char *tempfile,*name; 899: { int fd; 900: fd=creat(tempfile,0444); 901: if(fd<0) return(-1); 902: write(fd,(char *) &pid,sizeof(int)); 903: close(fd); 904: if(link(tempfile,name)<0) 905: { unlink(tempfile); 906: return(-1); 907: } 908: unlink(tempfile); 909: return(0); 910: } 911: lock(pid,tempfile,names) char *tempfile,**names; 912: { int i,j; 913: for(i=0;names[i]!=0;i++) 914: { if(onelock(pid,tempfile,names[i])==0) continue; 915: for(j=0;j<i;j++) unlink(names[j]); 916: return(-1); 917: } 918: return(0); 919: } 920: 921: #define LOCKPRE "/usr/spool/uucp/LCK." 922: 923: /*** 924: * delock(s) remove a lock file 925: * char *s; 926: * 927: * return codes: 0 | FAIL 928: */ 929: 930: delock(s) 931: char *s; 932: { 933: char ln[30]; 934: 935: sprintf(ln, "%s.%s", LOCKPRE, s); 936: rmlock(ln); 937: } 938: 939: 940: /*** 941: * mlock(sys) create system lock 942: * char *sys; 943: * 944: * return codes: 0 | FAIL 945: */ 946: 947: mlock(sys) 948: char *sys; 949: { 950: char lname[30]; 951: sprintf(lname, "%s.%s", LOCKPRE, sys); 952: return(ulockf(lname, (time_t) SLCKTIME ) < 0 ? FAIL : 0); 953: } 954: 955: 956: 957: /*** 958: * ultouch() update access and modify times for lock files 959: * 960: * return code - none 961: */ 962: 963: ultouch() 964: { 965: time_t time(); 966: int i; 967: struct ut { 968: time_t actime; 969: time_t modtime; 970: } ut; 971: 972: ut.actime = time(&ut.modtime); 973: for (i = 0; i < Nlocks; i++) { 974: if (Lockfile[i] == NULL) 975: continue; 976: utime(Lockfile[i], &ut); 977: } 978: return; 979: }