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