|
|
1.1 ! root 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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.