The definitive fix for tips' lock file problem

David Herron, NPR Lover david at ukma.UUCP
Mon Jul 8 10:49:05 AEST 1985


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 at 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 <sys/time.h>
+ #include <sys/resource.h>
+ #include <sys/wait.h>
  #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
+ 	}
  }



More information about the Comp.bugs.4bsd.ucb-fixes mailing list