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