Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Posting-Version: version B 2.10.3 alpha 4/3/85; site ukma.UUCP Path: utzoo!watmath!clyde!burl!ulysses!mhuxr!mhuxn!ihnp4!cbosgd!ukma!david From: david@ukma.UUCP (David Herron, NPR Lover) Newsgroups: net.bugs.4bsd Subject: The definitive fix for tips' lock file problem Message-ID: <1942@ukma.UUCP> Date: Sun, 7-Jul-85 20:49:05 EDT Article-I.D.: ukma.1942 Posted: Sun Jul 7 20:49:05 1985 Date-Received: Mon, 8-Jul-85 05:39:56 EDT Organization: U of Kentucky, Mathematical Sciences, Lexington KY Lines: 626 Index: /usr/src/usr.bin/tip/{cu.c,tip.c,tip.h,uucplock.c} Unix-Version: BRL-Unix Release 3 (but not very different from 4.2BSD tip) Date: 7-July-1985 Summary: The definitive fix for the tip lock file problem. Problem: As distributed, tip doesn't work. There are two specific problems. One is that it doesn't remove lock files. Examining the comments in the RCS logs shows that y'all were heading that direction but had never made it. The other problem is that it doesn't do wls@astrovax's dialin and out stuff. I'm sending the revisions I made which finished the stuff y'all were doing for the lock files. I am assuming you have wls's code and will put it in yourselves. (If not, I *can* forward it). Explanation: This is being posted to net.bugs.4bsd because the fix is needed, and should easily slide into place. The only problem is that in 4.2BSD tip, finish() calls delock(). The BRL people had deleted this call in preparation for code like this but had never installed the rest of it. Description: I put a trap in tip (by calling a routine called "Parent()") at the point just before it setuid()'s. Parent() fork()'s and the child returns immediately to continue on with setuid()'s and all the rest. In the meantime, the parent is setting up two things. One is a SIGALRM every 10 minutes which will touch the lock file (I'm using ultouch() from uucp). (I'm doing this for people who sit in tip for days at a time :-)). The other is a loop which is doing wait3()'s looking for stopped/dead/dying children. For dead children the parent deletes the lock file and exits. For stopped children it stops itself then when it wakes up sends a SIGCONT to the children. Something-I-Am-Thinking-About: There was a suggestion the Will Sebok posted about a month ago. It was for tip to have a set of variables which identified the commands to run for file transfers. For instance. One variable is "sendfile_here" (more thought will come up with a better name) which would be defined as "kermit -l /dev/ttyxx -b 1200 -s %s". The %s is substituted to be the name of the file to send. There's a corresponding variable to use as the command string for the other side. Ckermit will have to be modified to have an "override the lock file" switch is the biggest problem. But, I think you get the idea. David Herron cbosgd!ukma!david RCS file: RCS/cu.c,v retrieving revision 1.2 retrieving revision 1.3 diff -c -r1.2 -r1.3 *** /tmp/,RCSt1002886 Sun Jul 7 20:04:30 1985 --- /tmp/,RCSt2002886 Sun Jul 7 20:04:32 1985 *************** *** 1,7 /* * C U . C * ! * $Revision: 1.2 $ * * $Log: cu.c,v $ * Revision 1.2 83/12/13 23:51:47 dpk --- 1,7 ----- /* * C U . C * ! * $Revision: 1.3 $ * * $Log: cu.c,v $ * Revision 1.3 85/07/07 14:06:21 root *************** *** 4,9 * $Revision: 1.2 $ * * $Log: cu.c,v $ * Revision 1.2 83/12/13 23:51:47 dpk * Added distinctive RCS header * --- 4,20 ----- * $Revision: 1.3 $ * * $Log: cu.c,v $ + * Revision 1.3 85/07/07 14:06:21 root + * New method to solve the lock file problem. We keep a process around who + * is still setuid. This is done by fork()ing before the setuid. The + * parent goes into a loop waiting for children to die. (Also watches + * for children SIGSTOP so it can STOP itself, also touches the lock + * file (using ultouch() from uucp) every TOUCHTIME seconds.) + * + * Look at Parent(). + * + * ukma!david + * * Revision 1.2 83/12/13 23:51:47 dpk * Added distinctive RCS header * *************** *** 9,15 * */ #ifndef lint ! static char RCSid[] = "@(#)$Header: cu.c,v 1.2 83/12/13 23:51:47 dpk BRL $"; #endif #ifndef lint --- 20,26 ----- * */ #ifndef lint ! static char RCSid[] = "@(#)$Header: cu.c,v 1.3 85/07/07 14:06:21 root Exp $"; #endif #ifndef lint *************** *** 20,25 int cleanup(); int timeout(); /* * Botch the interface to look like cu's --- 31,37 ----- int cleanup(); int timeout(); + int touchlock(); /* * Botch the interface to look like cu's *************** *** 29,34 { register int i; static char sbuf[12]; if (argc < 2) { printf("usage: cu telno [-t] [-s speed] [-a acu] [-l line] [-#]\n"); --- 41,47 ----- { register int i; static char sbuf[12]; + extern int Parent(); if (argc < 2) { printf("usage: cu telno [-t] [-s speed] [-a acu] [-l line] [-#]\n"); *************** *** 95,100 } setbuf(stdout, NULL); loginit(); setuid(getuid()); setgid(getgid()); vinit(); --- 108,114 ----- } setbuf(stdout, NULL); loginit(); + Parent(); /* child returns, parent never returns */ setuid(getuid()); setgid(getgid()); vinit(); RCS file: RCS/tip.c,v retrieving revision 1.2 retrieving revision 1.3 diff -c -r1.2 -r1.3 *** /tmp/,RCSt1002932 Sun Jul 7 20:06:11 1985 --- /tmp/,RCSt2002932 Sun Jul 7 20:06:17 1985 *************** *** 1,7 /* * T I P . C * ! * $Revision: 1.2 $ * * $Log: tip.c,v $ * Revision 1.2 83/12/13 23:52:37 dpk --- 1,7 ----- /* * T I P . C * ! * $Revision: 1.3 $ * * $Log: tip.c,v $ * Revision 1.3 85/07/07 13:57:25 root *************** *** 4,9 * $Revision: 1.2 $ * * $Log: tip.c,v $ * Revision 1.2 83/12/13 23:52:37 dpk * Added distinctive RCS header * --- 4,20 ----- * $Revision: 1.3 $ * * $Log: tip.c,v $ + * Revision 1.3 85/07/07 13:57:25 root + * New method to solve the lock file problem. We keep a process around who + * is still setuid. This is done by fork()ing before the setuid. The + * parent goes into a loop waiting for children to die. (Also watches + * for children SIGSTOP so it can STOP itself, also touches the lock + * file (using ultouch() from uucp) every TOUCHTIME seconds.) + * + * Look at Parent(). + * + * ukma!david + * * Revision 1.2 83/12/13 23:52:37 dpk * Added distinctive RCS header * *************** *** 9,15 * */ #ifndef lint ! static char RCSid[] = "@(#)$Header: tip.c,v 1.2 83/12/13 23:52:37 dpk BRL $"; #endif #ifndef lint --- 20,26 ----- * */ #ifndef lint ! static char RCSid[] = "@(#)$Header: tip.c,v 1.3 85/07/07 13:57:25 root Exp $"; #endif #ifndef lint *************** *** 22,27 * or * cu phone-number [-s speed] [-l line] [-a acu] */ #include "tip.h" /* --- 33,41 ----- * or * cu phone-number [-s speed] [-l line] [-a acu] */ + #include+ #include + #include #include "tip.h" /* *************** *** 33,38 }; int disc = OTTYDISC; /* tip normally runs this way */ int intprompt(); int timeout(); int cleanup(); --- 47,53 ----- }; int disc = OTTYDISC; /* tip normally runs this way */ + int touchlock(); int intprompt(); int timeout(); int cleanup(); *************** *** 47,52 register char *p; char sbuf[12]; if (equal(sname(argv[0]), "cu")) { cumain(argc, argv); cumode = 1; --- 62,71 ----- register char *p; char sbuf[12]; + ioctl(0, TIOCGETP, (char *)&defarg); + ioctl(0, TIOCGETC, (char *)&defchars); + ioctl(0, TIOCGLTC, (char *)&deflchars); + ioctl(0, TIOCGETD, (char *)&odisc); if (equal(sname(argv[0]), "cu")) { cumain(argc, argv); cumode = 1; *************** *** 107,112 } setbuf(stdout, NULL); loginit(); /* * Now that we have the logfile and the ACU open * return to the real uid and gid. These things will --- 126,132 ----- } setbuf(stdout, NULL); loginit(); + Parent(); /* It is the CHILD that returns from this ... */ /* * Now that we have the logfile and the ACU open * return to the real uid and gid. These things will *************** *** 150,159 * From here down the code is shared with * the "cu" version of tip. */ - ioctl(0, TIOCGETP, (char *)&defarg); - ioctl(0, TIOCGETC, (char *)&defchars); - ioctl(0, TIOCGLTC, (char *)&deflchars); - ioctl(0, TIOCGETD, (char *)&odisc); arg = defarg; arg.sg_flags = ANYP | CBREAK; tchars = defchars; --- 170,175 ----- * From here down the code is shared with * the "cu" version of tip. */ arg = defarg; arg.sg_flags = ANYP | CBREAK; tchars = defchars; *************** *** 508,511 } fprintf(stderr, "%s: unknown parity value\n", PA); fflush(stderr); } --- 524,579 ----- } fprintf(stderr, "%s: unknown parity value\n", PA); fflush(stderr); + } + + /* + * code for the parent to touch the lock file. + */ + touchlock() + { + ultouch(); + printf("touchlock()\r\n"); /* DEBUG */ + signal(SIGALRM, touchlock); + alarm(TOUCHTIME); + } + + /* + * Parent() -- Be a big daddy and watch for the children to die off. + * + * fork() off so the child can change user id's. The parent + * will be up here watching for the child to exit, and when + * it does it will remove the lock file and reenable the modem + * (if necessary). It will also touch the lock file from + * time to time. + */ + Parent() + { + union wait chstatus; + struct rusage rusage; + int child; + + if ((child = fork()) != 0) { + /* parent */ + touchlock(); + /* STRUCTURE ALERT!!! */ + loop: + while (wait3(&chstatus, WUNTRACED, &rusage) != child) + printf("waiting ...\r\n"); + if (chstatus.w_stopval == WSTOPPED) { + /* + * Child has stopped because of ~^Z command + */ + kill(0, SIGTSTP); + goto loop; + } + /* else */ + kill(child, SIGTERM); + delock(uucplock); + printf("done\r\n"); + /* make sure ... */ + unraw(); + exit(chstatus); + } + else + return; } RCS file: RCS/tip.h,v retrieving revision 1.2 retrieving revision 1.3 diff -c -r1.2 -r1.3 *** /tmp/,RCSt1002940 Sun Jul 7 20:06:53 1985 --- /tmp/,RCSt2002940 Sun Jul 7 20:06:54 1985 *************** *** 1,7 /* * T I P . H * ! * $Revision: 1.2 $ * * $Log: tip.h,v $ * Revision 1.2 83/12/13 23:53:25 dpk --- 1,7 ----- /* * T I P . H * ! * $Revision: 1.3 $ * * $Log: tip.h,v $ * Revision 1.3 85/07/07 14:06:25 root *************** *** 4,9 * $Revision: 1.2 $ * * $Log: tip.h,v $ * Revision 1.2 83/12/13 23:53:25 dpk * Added distinctive RCS header * --- 4,20 ----- * $Revision: 1.3 $ * * $Log: tip.h,v $ + * Revision 1.3 85/07/07 14:06:25 root + * New method to solve the lock file problem. We keep a process around who + * is still setuid. This is done by fork()ing before the setuid. The + * parent goes into a loop waiting for children to die. (Also watches + * for children SIGSTOP so it can STOP itself, also touches the lock + * file (using ultouch() from uucp) every TOUCHTIME seconds.) + * + * Look at Parent(). + * + * ukma!david + * * Revision 1.2 83/12/13 23:53:25 dpk * Added distinctive RCS header * *************** *** 245,247 extern char *index(); extern char *malloc(); extern char *connect(); --- 256,260 ----- extern char *index(); extern char *malloc(); extern char *connect(); + #define TOUCHTIME 600 + extern int ultouch(); RCS file: RCS/uucplock.c,v retrieving revision 1.3 retrieving revision 1.4 diff -c -r1.3 -r1.4 *** /tmp/,RCSt1002955 Sun Jul 7 20:07:29 1985 --- /tmp/,RCSt2002955 Sun Jul 7 20:07:35 1985 *************** *** 1,7 /* * U U C P L O C K . C * ! * $Revision: 1.3 $ * * $Log: uucplock.c,v $ * Revision 1.3 84/10/12 17:05:18 dpk --- 1,7 ----- /* * U U C P L O C K . C * ! * $Revision: 1.4 $ * * $Log: uucplock.c,v $ * Revision 1.4 85/07/07 14:06:32 root *************** *** 4,9 * $Revision: 1.3 $ * * $Log: uucplock.c,v $ * Revision 1.3 84/10/12 17:05:18 dpk * Increased sizeof lockfile name array. * Size is now 64. --- 4,20 ----- * $Revision: 1.4 $ * * $Log: uucplock.c,v $ + * Revision 1.4 85/07/07 14:06:32 root + * New method to solve the lock file problem. We keep a process around who + * is still setuid. This is done by fork()ing before the setuid. The + * parent goes into a loop waiting for children to die. (Also watches + * for children SIGSTOP so it can STOP itself, also touches the lock + * file (using ultouch() from uucp) every TOUCHTIME seconds.) + * + * Look at Parent(). + * + * ukma!david + * * Revision 1.3 84/10/12 17:05:18 dpk * Increased sizeof lockfile name array. * Size is now 64. *************** *** 13,19 * */ #ifndef lint ! static char RCSid[] = "@(#)$Header: uucplock.c,v 1.3 84/10/12 17:05:18 dpk Exp $"; #endif #ifndef lint --- 24,30 ----- * */ #ifndef lint ! static char RCSid[] = "@(#)$Header: uucplock.c,v 1.4 85/07/07 14:06:32 root Exp $"; #endif #ifndef lint *************** *** 33,38 } #define LOCKPRE "/usr/spool/uucp/LCK." /* * This code is taken almost directly from uucp and follows the same --- 44,50 ----- } #define LOCKPRE "/usr/spool/uucp/LCK." + #define LCKMODE 0664 /* * This code is taken almost directly from uucp and follows the same *************** *** 184,190 { int fd; ! fd = creat(tempfile, 0444); if (fd < 0) return (-1); write(fd,(char *)&pid, sizeof(int)); --- 196,202 ----- { int fd; ! fd = creat(tempfile, LCKMODE); if (fd < 0) return (-1); write(fd,(char *)&pid, sizeof(int)); *************** *** 226,229 char lname[30]; sprintf(lname, "%s.%s", LOCKPRE, sys); return (ulockf(lname, (time_t) SLCKTIME ) < 0 ? FAIL : 0); } --- 238,281 ----- char lname[30]; sprintf(lname, "%s.%s", LOCKPRE, sys); return (ulockf(lname, (time_t) SLCKTIME ) < 0 ? FAIL : 0); + } + + /*** + * ultouch() update 'change' time for lock files + * + * -- mod by rti!trt -- + * Only update ctime, not mtime or atime. + * The 'chmod' method permits cu(I)-like programs + * to determine how long uucp has been on the line. + * The old "change access, mod, and change time" method + * can be had by defining OLDTOUCH + * + * return code - none + */ + ultouch() + { + time_t time(); + static time_t lasttouch = 0; + register int i; + struct ut { + time_t actime; + time_t modtime; + } ut; + + ut.actime = time(&ut.modtime); + /* Do not waste time touching locking files too often */ + /* (But, defend against backward time changes) */ + if (ut.actime >= lasttouch && ut.actime < lasttouch+60) + return; + lasttouch = ut.actime; + + for (i = 0; i < Nlocks; i++) { + if (Lockfile[i] == NULL) + continue; + #ifdef OLDTOUCH + utime(Lockfile[i], &ut); + #else + chmod(Lockfile[i], LCKMODE); + #endif + } }