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

Defined functions

chwrsig defined in line 565; used 1 times
cleanup defined in line 749; used 8 times
conn defined in line 236; used 1 times
delock defined in line 930; used 2 times
dodiver defined in line 588; used 2 times
dopercen defined in line 459; used 1 times
echo defined in line 723; used 4 times
equal defined in line 546; used 2 times
exists defined in line 740; used 2 times
  • in line 172(2)
isalock defined in line 886; used 1 times
lock defined in line 911; never used
main defined in line 114; never used
mlock defined in line 947; used 2 times
mode defined in line 701; used 10 times
onelock defined in line 898; used 3 times
prf defined in line 732; used 30 times
rd defined in line 627; used 1 times
rdc defined in line 64; used 3 times
readmsg defined in line 572; used 3 times
rmlock defined in line 858; used 2 times
sig14 defined in line 94; used 2 times
sig2 defined in line 73; used 2 times
stlock defined in line 829; used 1 times
ulockf defined in line 783; used 1 times
ultouch defined in line 963; never used
unlock defined in line 893; never used
wr defined in line 329; used 1 times
wrln defined in line 555; used 14 times
xalarm defined in line 88; used 10 times
xsleep defined in line 81; used 5 times

Defined variables

Lockfile defined in line 819; used 9 times
Nlocks defined in line 820; used 5 times
c defined in line 48; used 36 times
connmsg defined in line 51; used 3 times
dbflag defined in line 102; used 5 times
devcua defined in line 41; used 5 times
devcul defined in line 40; used 5 times
dout defined in line 100; used 8 times
ds defined in line 570; used 23 times
efk defined in line 47; used 5 times
hdplx defined in line 104; used 2 times
intr defined in line 71; used 7 times
justrung defined in line 571; used 3 times
ln defined in line 44; used 22 times
lspeed defined in line 42; used 2 times
nhup defined in line 101; used 4 times
notabs defined in line 46; used 3 times
nullbrk defined in line 105; used 2 times
oc defined in line 49; used 4 times
pflag defined in line 103; used 3 times
pipes defined in line 106; used 5 times
set14 defined in line 79; used 2 times
slnt defined in line 570; used 7 times
speed defined in line 107; used 7 times
taking defined in line 570; never used
terase defined in line 45; used 3 times
tkill defined in line 45; used 4 times
whoami defined in line 564; used 1 times

Defined struct's

ut defined in line 967; never used

Defined macros

ASSERT defined in line 12; used 2 times
CRLF defined in line 36; used 6 times
CTRLZ defined in line 442; never used
DIVER defined in line 625; used 1 times
EOL defined in line 623; used 1 times
FAIL defined in line 9; used 6 times
LOCKPRE defined in line 921; used 2 times
MAXLOCKS defined in line 818; used 2 times
NAMESIZE defined in line 8; used 1 times
ORDIN defined in line 621; used 5 times
SAME defined in line 10; used 1 times
SAWCR defined in line 622; used 3 times
SAWTL defined in line 624; used 1 times
SLCKTIME defined in line 11; used 1 times
wrc defined in line 37; used 6 times
Last modified: 1983-04-29
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 2300
Valid CSS Valid XHTML 1.0 Strict