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