xref: /csrg-svn/usr.bin/uucp/libuu/ulockf.c (revision 25138)
113673Ssam #ifndef lint
2*25138Sbloom static char sccsid[] = "@(#)ulockf.c	5.5 (Berkeley) 10/09/85";
313673Ssam #endif
413673Ssam 
513673Ssam #include "uucp.h"
613673Ssam #include <sys/stat.h>
7*25138Sbloom #include <errno.h>
813673Ssam 
9*25138Sbloom #define	LCKMODE	0444	/* File mode for lock files */
10*25138Sbloom #define MAXLOCKS 16	/* Maximum number of lock files */
1113673Ssam 
12*25138Sbloom char *Lockfile[MAXLOCKS];
13*25138Sbloom char *LockDirectory = LOCKDIR;
14*25138Sbloom int Nlocks = 0;
15*25138Sbloom 
1623677Sbloom /*LINTLIBRARY*/
1723677Sbloom 
1817839Sralph /*
19*25138Sbloom  *	This routine will attempt to create a lock file (file).
20*25138Sbloom  *	It makes sure that the lock file is valid if it already exists.
2113673Ssam  *
2223677Sbloom  *	return codes:  SUCCESS  |  FAIL
2313673Ssam  */
2418623Sralph ulockf(hfile, atime)
2518623Sralph char *hfile;
2613673Ssam time_t atime;
2713673Ssam {
28*25138Sbloom 	register char *p;
29*25138Sbloom 	register int i;
3013673Ssam 	static char tempfile[NAMESIZE];
3118623Sralph 	char file[NAMESIZE];
32*25138Sbloom 	static int pid = -1;
33*25138Sbloom 	extern int errno;
3413673Ssam 
3513673Ssam 	if (pid < 0) {
3613673Ssam 		pid = getpid();
37*25138Sbloom 		sprintf(tempfile, "%s/LTMP.%d", LockDirectory, pid);
3813673Ssam 	}
39*25138Sbloom 	sprintf(file, "%s/LCK..%s", LockDirectory, hfile);
40*25138Sbloom 	i = 0;
41*25138Sbloom 	while (onelock(pid, tempfile, file) == -1) { /* lock file exists */
42*25138Sbloom #if !defined(BSD4_2) && !defined(USG)
43*25138Sbloom 		struct stat stbuf;
44*25138Sbloom 		time_t ptime;
4513673Ssam 		/* get status to check age of the lock file */
46*25138Sbloom 		if (stat(file, &stbuf) == 0) {
47*25138Sbloom 			(void) time(&ptime);
48*25138Sbloom 			if ((ptime - stbuf.st_ctime) < atime)
49*25138Sbloom 				return FAIL; /* file not old enough to delete */
5013673Ssam 		}
51*25138Sbloom #else	BSD4_2 || USG
52*25138Sbloom 		register int fd;
53*25138Sbloom 		fd = open(file, 0);
54*25138Sbloom 		if (fd >= 0) {
55*25138Sbloom 			int upid, ret;
56*25138Sbloom 			ret = read(fd, &upid, sizeof upid);
57*25138Sbloom 			close(fd);
58*25138Sbloom 			if (ret == sizeof upid && (kill(upid, 0) == 0
59*25138Sbloom 				|| errno != ESRCH))
60*25138Sbloom 				return FAIL; /* process is still running */
61*25138Sbloom 		}
62*25138Sbloom #endif BSD4_2 || USG
63*25138Sbloom 		assert("DEAD LOCK", file, errno);
64*25138Sbloom 		logent(file, "DEAD LOCK");
65*25138Sbloom 		(void) unlink(file);
66*25138Sbloom 		sleep(5);	/* avoid a possible race */
67*25138Sbloom 		ASSERT(i++ < 5, "CAN'T GET LOCKFILE", tempfile, errno);
6813673Ssam 	}
6913673Ssam 
7013673Ssam 	for (i = 0; i < Nlocks; i++) {
7113673Ssam 		if (Lockfile[i] == NULL)
7213673Ssam 			break;
7313673Ssam 	}
7417839Sralph 	ASSERT(i < MAXLOCKS, "TOO MANY LOCKS", CNULL, i);
7513673Ssam 	if (i >= Nlocks)
7613673Ssam 		i = Nlocks++;
77*25138Sbloom 	p = malloc((unsigned)(strlen(file)+1));
78*25138Sbloom 	ASSERT(p != NULL, "CAN NOT ALLOCATE FOR", file, 0);
79*25138Sbloom 	strcpy(p, file);
8013673Ssam 	Lockfile[i] = p;
81*25138Sbloom 
82*25138Sbloom 	return SUCCESS;
8313673Ssam }
8413673Ssam 
8517839Sralph /*
86*25138Sbloom  *	remove all lock files in list or name
8713673Ssam  */
8813673Ssam rmlock(name)
8913673Ssam register char *name;
9013673Ssam {
9113673Ssam 	register int i;
92*25138Sbloom 	char file[MAXFULLNAME];
9313673Ssam 
94*25138Sbloom 	if (name != NULL) {
95*25138Sbloom 		sprintf(file, "%s/LCK..%s", LockDirectory, name);
96*25138Sbloom 		name = file;
97*25138Sbloom 	}
9813673Ssam 	for (i = 0; i < Nlocks; i++) {
9913673Ssam 		if (Lockfile[i] == NULL)
10013673Ssam 			continue;
10117839Sralph 		if (name == NULL || strcmp(name, Lockfile[i]) == SAME) {
10213673Ssam 			unlink(Lockfile[i]);
10313673Ssam 			free(Lockfile[i]);
10413673Ssam 			Lockfile[i] = NULL;
10513673Ssam 		}
10613673Ssam 	}
10713673Ssam }
10813673Ssam 
10913673Ssam /*
110*25138Sbloom  *	makes lock a name on behalf of pid. Tempfile must be in the same
11113673Ssam  *	file system as name.
11213673Ssam  */
11323677Sbloom onelock(pid, tempfile, name)
11423677Sbloom int pid;
115*25138Sbloom char *tempfile, *name;
11617839Sralph {
117*25138Sbloom 	register int fd, ret;
11817839Sralph #ifdef VMS
11917839Sralph 	fd = creat(name, LCKMODE, "1version");
12017839Sralph #else !VMS
12117839Sralph 	fd = creat(tempfile, LCKMODE);
12217839Sralph #endif !VMS
123*25138Sbloom 	if (fd < 0) {
124*25138Sbloom 		DEBUG(1,"Can't creat temp file %s ", tempfile);
125*25138Sbloom 		DEBUG(1,"-- errno %d", errno);
12617839Sralph 		return FAIL;
127*25138Sbloom 	}
128*25138Sbloom 	ret = write(fd, (char *)&pid, sizeof(int));
129*25138Sbloom 	(void) close(fd);
130*25138Sbloom 
131*25138Sbloom 	if (ret != sizeof(int)) {
132*25138Sbloom 		DEBUG(1,"Temp file write failed -- errno %d\n", errno);
133*25138Sbloom #ifdef VMS
134*25138Sbloom 		(void) unlink(name);
135*25138Sbloom #else !VMS
136*25138Sbloom 		(void) unlink(tempfile);
137*25138Sbloom #endif !VMS
138*25138Sbloom 		return FAIL;
139*25138Sbloom 	}
140*25138Sbloom #ifndef VMS
14117839Sralph 	if (link(tempfile, name) < 0) {
142*25138Sbloom 		(void) unlink(tempfile);
14317839Sralph 		return FAIL;
14413673Ssam 	}
14513673Ssam 	unlink(tempfile);
146*25138Sbloom #endif	!VMS
14717839Sralph 	return SUCCESS;
14813673Ssam }
14917839Sralph 
150*25138Sbloom #if !defined(BSD4_2) && !defined(USG)
15117839Sralph /*
15217839Sralph  *	update 'change' time for lock files
15313673Ssam  *
15413673Ssam  *	Only update ctime, not mtime or atime.
15513673Ssam  *	The 'chmod' method permits cu(I)-like programs
15613673Ssam  *	to determine how long uucp has been on the line.
15713673Ssam  *	The old "change access, mod, and change time" method
15813673Ssam  *	can be had by defining OLDTOUCH
15913673Ssam  *
16013673Ssam  *	return code - none
16113673Ssam  */
16213673Ssam 
16313673Ssam ultouch()
16413673Ssam {
16513673Ssam 	static time_t lasttouch = 0;
16613673Ssam 	register int i;
16713673Ssam 	struct ut {
16813673Ssam 		time_t actime;
16913673Ssam 		time_t modtime;
17013673Ssam 	} ut;
17113673Ssam 
172*25138Sbloom #ifdef USG
173*25138Sbloom 	time(&Now.time);
174*25138Sbloom 	t1.millitm = 0;
175*25138Sbloom #else !USG
176*25138Sbloom 	ftime(&Now);
177*25138Sbloom #endif !USG
178*25138Sbloom 	ut.actime = ut.modtime = Now.time;
17913673Ssam 	/* Do not waste time touching locking files too often */
18013673Ssam 	/* (But, defend against backward time changes) */
18113673Ssam 	if (ut.actime >= lasttouch && ut.actime < lasttouch+60)
18213673Ssam 		return;
18313673Ssam 	lasttouch = ut.actime;
18413673Ssam 	DEBUG(4, "ultouch\n", 0);
18513673Ssam 
18613673Ssam 	for (i = 0; i < Nlocks; i++) {
18713673Ssam 		if (Lockfile[i] == NULL)
18813673Ssam 			continue;
18913673Ssam #ifdef	OLDTOUCH
19013673Ssam 		utime(Lockfile[i], &ut);
19117839Sralph #else 	!OLDTOUCH
19213673Ssam 		chmod(Lockfile[i], LCKMODE);
19317839Sralph #endif !OLDTOUCH
19413673Ssam 	}
19513673Ssam }
196*25138Sbloom #endif !BSD4_2 && ! USG
197