xref: /csrg-svn/usr.bin/uucp/libuu/ulockf.c (revision 62386)
148652Sbostic /*-
2*62386Sbostic  * Copyright (c) 1985, 1993
3*62386Sbostic  *	The Regents of the University of California.  All rights reserved.
448652Sbostic  *
548652Sbostic  * %sccs.include.proprietary.c%
648652Sbostic  */
748652Sbostic 
813673Ssam #ifndef lint
9*62386Sbostic static char sccsid[] = "@(#)ulockf.c	8.1 (Berkeley) 06/06/93";
1048652Sbostic #endif /* not lint */
1113673Ssam 
1213673Ssam #include "uucp.h"
1313673Ssam #include <sys/stat.h>
1425138Sbloom #include <errno.h>
1513673Ssam 
1625138Sbloom #define	LCKMODE	0444	/* File mode for lock files */
1725138Sbloom #define MAXLOCKS 16	/* Maximum number of lock files */
1813673Ssam 
1925138Sbloom char *Lockfile[MAXLOCKS];
2025138Sbloom char *LockDirectory = LOCKDIR;
2125138Sbloom int Nlocks = 0;
2234095Sbostic extern int errno;
2325138Sbloom 
2423677Sbloom /*LINTLIBRARY*/
2523677Sbloom 
2617839Sralph /*
2725138Sbloom  *	This routine will attempt to create a lock file (file).
2825138Sbloom  *	It makes sure that the lock file is valid if it already exists.
2913673Ssam  *
3023677Sbloom  *	return codes:  SUCCESS  |  FAIL
3113673Ssam  */
ulockf(hfile,atime)3218623Sralph ulockf(hfile, atime)
3318623Sralph char *hfile;
3413673Ssam time_t atime;
3513673Ssam {
3625138Sbloom 	register char *p;
3725138Sbloom 	register int i;
3813673Ssam 	static char tempfile[NAMESIZE];
3918623Sralph 	char file[NAMESIZE];
4025138Sbloom 	static int pid = -1;
4113673Ssam 
4213673Ssam 	if (pid < 0) {
4313673Ssam 		pid = getpid();
4425138Sbloom 		sprintf(tempfile, "%s/LTMP.%d", LockDirectory, pid);
4513673Ssam 	}
4625138Sbloom 	sprintf(file, "%s/LCK..%s", LockDirectory, hfile);
4725138Sbloom 	i = 0;
4825138Sbloom 	while (onelock(pid, tempfile, file) == -1) { /* lock file exists */
4925138Sbloom #if !defined(BSD4_2) && !defined(USG)
5025138Sbloom 		struct stat stbuf;
5125138Sbloom 		time_t ptime;
5213673Ssam 		/* get status to check age of the lock file */
5325138Sbloom 		if (stat(file, &stbuf) == 0) {
5425138Sbloom 			(void) time(&ptime);
5525138Sbloom 			if ((ptime - stbuf.st_ctime) < atime)
5625138Sbloom 				return FAIL; /* file not old enough to delete */
5713673Ssam 		}
5825138Sbloom #else	BSD4_2 || USG
5925138Sbloom 		register int fd;
6025138Sbloom 		fd = open(file, 0);
6125138Sbloom 		if (fd >= 0) {
6225138Sbloom 			int upid, ret;
6325138Sbloom 			ret = read(fd, &upid, sizeof upid);
6425138Sbloom 			close(fd);
6525138Sbloom 			if (ret == sizeof upid && (kill(upid, 0) == 0
6625138Sbloom 				|| errno != ESRCH))
6725138Sbloom 				return FAIL; /* process is still running */
6825138Sbloom 		}
6925138Sbloom #endif BSD4_2 || USG
7033958Srick 		syslog(LOG_WARNING, "%s: dead lock %s", Rmtname, file);
7125138Sbloom 		logent(file, "DEAD LOCK");
7225138Sbloom 		(void) unlink(file);
7325138Sbloom 		sleep(5);	/* avoid a possible race */
7433958Srick 		if (i++ >= 5) {
7533958Srick 			syslog(LOG_ERR, "%s: can't get lockfile %s: %m",
7633958Srick 				Rmtname, tempfile);
7733958Srick 			cleanup(FAIL);
7833958Srick 		}
7913673Ssam 	}
8013673Ssam 
8113673Ssam 	for (i = 0; i < Nlocks; i++) {
8213673Ssam 		if (Lockfile[i] == NULL)
8313673Ssam 			break;
8413673Ssam 	}
8533958Srick 	if (i >= MAXLOCKS) {
8633958Srick 		syslog(LOG_ERR, "Too many locks");
8733958Srick 		cleanup(FAIL);
8833958Srick 	}
8913673Ssam 	if (i >= Nlocks)
9013673Ssam 		i = Nlocks++;
9125138Sbloom 	p = malloc((unsigned)(strlen(file)+1));
9233958Srick 	if (p == NULL) {
9333958Srick 		syslog(LOG_ERR, "malloc failed: %m");
9433958Srick 		cleanup(FAIL);
9533958Srick 	}
9625138Sbloom 	strcpy(p, file);
9713673Ssam 	Lockfile[i] = p;
9825138Sbloom 
9925138Sbloom 	return SUCCESS;
10013673Ssam }
10113673Ssam 
10217839Sralph /*
10325138Sbloom  *	remove all lock files in list or name
10413673Ssam  */
rmlock(name)10513673Ssam rmlock(name)
10613673Ssam register char *name;
10713673Ssam {
10813673Ssam 	register int i;
10925138Sbloom 	char file[MAXFULLNAME];
11013673Ssam 
11125138Sbloom 	if (name != NULL) {
11225138Sbloom 		sprintf(file, "%s/LCK..%s", LockDirectory, name);
11325138Sbloom 		name = file;
11425138Sbloom 	}
11513673Ssam 	for (i = 0; i < Nlocks; i++) {
11613673Ssam 		if (Lockfile[i] == NULL)
11713673Ssam 			continue;
11817839Sralph 		if (name == NULL || strcmp(name, Lockfile[i]) == SAME) {
11913673Ssam 			unlink(Lockfile[i]);
12013673Ssam 			free(Lockfile[i]);
12113673Ssam 			Lockfile[i] = NULL;
12213673Ssam 		}
12313673Ssam 	}
12413673Ssam }
12513673Ssam 
12613673Ssam /*
12725138Sbloom  *	makes lock a name on behalf of pid. Tempfile must be in the same
12813673Ssam  *	file system as name.
12913673Ssam  */
onelock(pid,tempfile,name)13023677Sbloom onelock(pid, tempfile, name)
13123677Sbloom int pid;
13225138Sbloom char *tempfile, *name;
13317839Sralph {
13425138Sbloom 	register int fd, ret;
13517839Sralph #ifdef VMS
13617839Sralph 	fd = creat(name, LCKMODE, "1version");
13717839Sralph #else !VMS
13817839Sralph 	fd = creat(tempfile, LCKMODE);
13917839Sralph #endif !VMS
14025138Sbloom 	if (fd < 0) {
14125138Sbloom 		DEBUG(1,"Can't creat temp file %s ", tempfile);
14225138Sbloom 		DEBUG(1,"-- errno %d", errno);
14317839Sralph 		return FAIL;
14425138Sbloom 	}
14525138Sbloom 	ret = write(fd, (char *)&pid, sizeof(int));
14625138Sbloom 	(void) close(fd);
14725138Sbloom 
14825138Sbloom 	if (ret != sizeof(int)) {
14925138Sbloom 		DEBUG(1,"Temp file write failed -- errno %d\n", errno);
15025138Sbloom #ifdef VMS
15125138Sbloom 		(void) unlink(name);
15225138Sbloom #else !VMS
15325138Sbloom 		(void) unlink(tempfile);
15425138Sbloom #endif !VMS
15525138Sbloom 		return FAIL;
15625138Sbloom 	}
15725138Sbloom #ifndef VMS
15817839Sralph 	if (link(tempfile, name) < 0) {
15925138Sbloom 		(void) unlink(tempfile);
16017839Sralph 		return FAIL;
16113673Ssam 	}
16213673Ssam 	unlink(tempfile);
16325138Sbloom #endif	!VMS
16417839Sralph 	return SUCCESS;
16513673Ssam }
16617839Sralph 
16725138Sbloom #if !defined(BSD4_2) && !defined(USG)
16817839Sralph /*
16917839Sralph  *	update 'change' time for lock files
17013673Ssam  *
17113673Ssam  *	Only update ctime, not mtime or atime.
17213673Ssam  *	The 'chmod' method permits cu(I)-like programs
17313673Ssam  *	to determine how long uucp has been on the line.
17413673Ssam  *	The old "change access, mod, and change time" method
17513673Ssam  *	can be had by defining OLDTOUCH
17613673Ssam  *
17713673Ssam  *	return code - none
17813673Ssam  */
17913673Ssam 
ultouch()18013673Ssam ultouch()
18113673Ssam {
18213673Ssam 	static time_t lasttouch = 0;
18313673Ssam 	register int i;
18413673Ssam 	struct ut {
18513673Ssam 		time_t actime;
18613673Ssam 		time_t modtime;
18713673Ssam 	} ut;
18813673Ssam 
18925138Sbloom #ifdef USG
19025138Sbloom 	time(&Now.time);
19125138Sbloom 	t1.millitm = 0;
19225138Sbloom #else !USG
19325138Sbloom 	ftime(&Now);
19425138Sbloom #endif !USG
19525138Sbloom 	ut.actime = ut.modtime = Now.time;
19613673Ssam 	/* Do not waste time touching locking files too often */
19713673Ssam 	/* (But, defend against backward time changes) */
19813673Ssam 	if (ut.actime >= lasttouch && ut.actime < lasttouch+60)
19913673Ssam 		return;
20013673Ssam 	lasttouch = ut.actime;
20113673Ssam 	DEBUG(4, "ultouch\n", 0);
20213673Ssam 
20313673Ssam 	for (i = 0; i < Nlocks; i++) {
20413673Ssam 		if (Lockfile[i] == NULL)
20513673Ssam 			continue;
20613673Ssam #ifdef	OLDTOUCH
20713673Ssam 		utime(Lockfile[i], &ut);
20817839Sralph #else 	!OLDTOUCH
20913673Ssam 		chmod(Lockfile[i], LCKMODE);
21017839Sralph #endif !OLDTOUCH
21113673Ssam 	}
21213673Ssam }
21325138Sbloom #endif !BSD4_2 && ! USG
214