text: #if	!defined(lint) && defined(DOSCCS)
  static char sccsid[] = "@(#)ulockf.c	5.5.1 (2.11BSD) 1997/10/2";
  #endif
  
  #include "uucp.h"
  #include <sys/stat.h>
  #include <errno.h>
  
  #define	LCKMODE	0444	/* File mode for lock files */
  #define MAXLOCKS 16	/* Maximum number of lock files */
  
  char *Lockfile[MAXLOCKS];
  char *LockDirectory = LOCKDIR;
  int Nlocks = 0;
  
  /*LINTLIBRARY*/
  
  /*
   *	This routine will attempt to create a lock file (file).
   *	It makes sure that the lock file is valid if it already exists.
   *
   *	return codes:  SUCCESS  |  FAIL
   */
  ulockf(hfile, atime)
  char *hfile;
  time_t atime;
  {
  	register char *p;
  	register int i;
  	static char tempfile[NAMESIZE];
  	char file[NAMESIZE];
  	static int pid = -1;
  	extern int errno;
  
  	if (pid < 0) {
  		pid = getpid();
  		sprintf(tempfile, "%s/LTMP.%d", LockDirectory, pid);
  	}
  	sprintf(file, "%s/LCK..%s", LockDirectory, hfile);
  	i = 0;
  	while (onelock(pid, tempfile, file) == -1) { /* lock file exists */
  #if !defined(BSD4_2) && !defined(USG)
  		struct stat stbuf;
  		time_t ptime;
  		/* get status to check age of the lock file */
  		if (stat(file, &stbuf) == 0) {
  			(void) time(&ptime);
  			if ((ptime - stbuf.st_ctime) < atime)
  				return FAIL; /* file not old enough to delete */
  		}
  #else
  		register int fd;
  		fd = open(file, 0);
  		if (fd >= 0) {
  			int upid, ret;
  			ret = read(fd, &upid, sizeof upid);
  			close(fd);
  			if (ret == sizeof upid && (kill(upid, 0) == 0
  				|| errno != ESRCH))
  				return FAIL; /* process is still running */
  		}
  #endif
  		assert("DEAD LOCK", file, errno);
  		logent(file, "DEAD LOCK");
  		(void) unlink(file);
  		sleep(5);	/* avoid a possible race */
  		ASSERT(i++ < 5, "CAN'T GET LOCKFILE", tempfile, errno);
  	}
  
  	for (i = 0; i < Nlocks; i++) {
  		if (Lockfile[i] == NULL)
  			break;
  	}
  	ASSERT(i < MAXLOCKS, "TOO MANY LOCKS", CNULL, i);
  	if (i >= Nlocks)
  		i = Nlocks++;
  	p = (char *)malloc((unsigned)(strlen(file)+1));
  	ASSERT(p != NULL, "CAN NOT ALLOCATE FOR", file, 0);
  	strcpy(p, file);
  	Lockfile[i] = p;
  
  	return SUCCESS;
  }
  
  /*
   *	remove all lock files in list or name
   */
  rmlock(name)
  register char *name;
  {
  	register int i;
  	char file[MAXFULLNAME];
  
  	if (name != NULL) {
  		sprintf(file, "%s/LCK..%s", LockDirectory, name);
  		name = file;
  	}
  	for (i = 0; i < Nlocks; i++) {
  		if (Lockfile[i] == NULL)
  			continue;
  		if (name == NULL || strcmp(name, Lockfile[i]) == SAME) {
  			unlink(Lockfile[i]);
  			free(Lockfile[i]);
  			Lockfile[i] = NULL;
  		}
  	}
  }
  
  /*
   *	makes lock a name on behalf of pid. Tempfile must be in the same
   *	file system as name.
   */
  onelock(pid, tempfile, name)
  int pid;
  char *tempfile, *name;
  {
  	register int fd, ret;
  	extern int errno;
  #ifdef VMS
  	fd = creat(name, LCKMODE, "1version");
  #else
  	fd = creat(tempfile, LCKMODE);
  #endif
  	if (fd < 0) {
  		DEBUG(1,"Can't creat temp file %s ", tempfile);
  		DEBUG(1,"-- errno %d", errno);
  		return FAIL;
  	}
  	ret = write(fd, (char *)&pid, sizeof(int));
  	(void) close(fd);
  
  	if (ret != sizeof(int)) {
  		DEBUG(1,"Temp file write failed -- errno %d\n", errno);
  #ifdef VMS
  		(void) unlink(name);
  #else
  		(void) unlink(tempfile);
  #endif
  		return FAIL;
  	}
  #ifndef VMS
  	if (link(tempfile, name) < 0) {
  		(void) unlink(tempfile);
  		return FAIL;
  	}
  	unlink(tempfile);
  #endif
  	return SUCCESS;
  }
  
  #if !defined(BSD4_2) && !defined(USG)
  /*
   *	update 'change' time for lock files
   *
   *	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()
  {
  	static time_t lasttouch = 0;
  	register int i;
  	struct ut {
  		time_t actime;
  		time_t modtime;
  	} ut;
  
  #ifdef USG
  	time(&Now.time);
  	t1.millitm = 0;
  #else
  	ftime(&Now);
  #endif
  	ut.actime = ut.modtime = Now.time;
  	/* 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;
  	DEBUG(4, "ultouch\n", 0);
  
  	for (i = 0; i < Nlocks; i++) {
  		if (Lockfile[i] == NULL)
  			continue;
  #ifdef	OLDTOUCH
  		utime(Lockfile[i], &ut);
  #else
  		chmod(Lockfile[i], LCKMODE);
  #endif
  	}
  }
  #endif
  