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

Defined functions

chwrsig defined in line 550; used 1 times
cleanup defined in line 729; used 8 times
conn defined in line 232; used 1 times
delock defined in line 909; used 2 times
dodiver defined in line 573; used 2 times
dopercen defined in line 449; used 1 times
echo defined in line 703; used 4 times
equal defined in line 531; used 2 times
exists defined in line 720; used 2 times
  • in line 167(2)
isalock defined in line 865; used 1 times
lock defined in line 890; never used
main defined in line 114; never used
mlock defined in line 926; used 2 times
mode defined in line 681; used 10 times
onelock defined in line 877; used 3 times
prf defined in line 712; used 28 times
rd defined in line 612; used 1 times
rdc defined in line 65; used 3 times
readmsg defined in line 557; used 3 times
rmlock defined in line 837; used 2 times
sig14 defined in line 96; used 2 times
sig2 defined in line 75; used 2 times
stlock defined in line 808; used 1 times
ulockf defined in line 762; used 1 times
ultouch defined in line 942; never used
unlock defined in line 872; never used
wr defined in line 325; used 1 times
wrln defined in line 540; used 11 times
xalarm defined in line 90; used 10 times
xsleep defined in line 83; used 5 times

Defined variables

Lockfile defined in line 798; used 9 times
Nlocks defined in line 799; used 5 times
c defined in line 49; used 38 times
connmsg defined in line 52; used 2 times
dbflag defined in line 104; used 5 times
devcua defined in line 43; used 5 times
devcul defined in line 42; used 5 times
dout defined in line 102; used 8 times
ds defined in line 555; used 23 times
efk defined in line 48; used 5 times
intr defined in line 73; used 7 times
justrung defined in line 556; used 3 times
ln defined in line 46; used 24 times
lspeed defined in line 44; used 2 times
nhup defined in line 103; used 4 times
nullbrk defined in line 106; used 2 times
oc defined in line 50; used 3 times
pflag defined in line 105; used 2 times
pipes defined in line 107; used 5 times
sccsid defined in line 1; never used
set14 defined in line 81; used 2 times
slnt defined in line 555; used 7 times
taking defined in line 555; never used
terase defined in line 47; used 3 times
tkill defined in line 47; used 4 times
whoami defined in line 549; used 1 times

Defined struct's

ut defined in line 946; never used

Defined macros

ASSERT defined in line 14; used 2 times
CRLF defined in line 38; used 6 times
CTRLZ defined in line 432; never used
DIVER defined in line 610; used 1 times
EOL defined in line 608; used 1 times
FAIL defined in line 11; used 6 times
LOCKPRE defined in line 900; used 2 times
MAXLOCKS defined in line 797; used 2 times
NAMESIZE defined in line 10; used 1 times
ORDIN defined in line 606; used 4 times
SAME defined in line 12; used 1 times
SAWCR defined in line 607; used 3 times
SAWTL defined in line 609; used 1 times
SLCKTIME defined in line 13; used 1 times
wrc defined in line 39; used 5 times
Last modified: 1982-10-22
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 7193
Valid CSS Valid XHTML 1.0 Strict