xref: /csrg-svn/usr.bin/uucp/libuu/ulockf.c (revision 17839)
113673Ssam #ifndef lint
2*17839Sralph static char sccsid[] = "@(#)ulockf.c	5.2 (Berkeley) 01/22/85";
313673Ssam #endif
413673Ssam 
513673Ssam #include "uucp.h"
613673Ssam #include <sys/types.h>
713673Ssam #include <sys/stat.h>
813673Ssam 
913673Ssam extern time_t	time();
1013673Ssam 
1113673Ssam /* File mode for lock files */
1213673Ssam #define	LCKMODE	0444
1313673Ssam 
14*17839Sralph /*
1513673Ssam  *	ulockf  -  this routine will create a lock file (file).
1613673Ssam  *	If one already exists, the create time is checked for
1713673Ssam  *	older than the age time (atime).
1813673Ssam  *	If it is older, an attempt will be made to unlink it
1913673Ssam  *	and create a new one.
2013673Ssam  *
2113673Ssam  *	return codes:  0  |  FAIL
2213673Ssam  */
2313673Ssam 
2413673Ssam ulockf(file, atime)
2513673Ssam register char *file;
2613673Ssam time_t atime;
2713673Ssam {
2813673Ssam 	struct stat stbuf;
2913673Ssam 	time_t ptime;
3013673Ssam 	register int ret;
3113673Ssam 	static int pid = -1;
3213673Ssam 	static char tempfile[NAMESIZE];
3313673Ssam 
3413673Ssam 	if (pid < 0) {
3513673Ssam 		pid = getpid();
36*17839Sralph 		sprintf(tempfile, "%s/LTMP.%d", LOCKDIR, pid);
3713673Ssam 	}
3813673Ssam 	if (onelock(pid, tempfile, file) == -1) {
3913673Ssam 		/* lock file exists */
4013673Ssam 		/* get status to check age of the lock file */
4113673Ssam 		ret = stat(file, &stbuf);
4213673Ssam 		if (ret != -1) {
4313673Ssam 			time(&ptime);
4413673Ssam 			if ((ptime - stbuf.st_ctime) < atime) {
4513673Ssam 				/* file not old enough to delete */
46*17839Sralph 				return FAIL;
4713673Ssam 			}
48*17839Sralph 			ret = unlink(file);
49*17839Sralph 			logent(file, "DEAD LOCK");
50*17839Sralph 			sleep(5);	/* rti!trt: avoid a race */
51*17839Sralph 			ret = onelock(pid, tempfile, file);
5213673Ssam 		}
5313673Ssam 		if (ret != 0)
54*17839Sralph 			return FAIL;
5513673Ssam 	}
5613673Ssam 	stlock(file);
57*17839Sralph 	return SUCCESS;
5813673Ssam }
5913673Ssam 
6013673Ssam 
6113673Ssam #define MAXLOCKS 10	/* maximum number of lock files */
6213673Ssam char *Lockfile[MAXLOCKS];
6313673Ssam int Nlocks = 0;
6413673Ssam 
6513673Ssam /***
6613673Ssam  *	stlock(name)	put name in list of lock files
6713673Ssam  *	char *name;
6813673Ssam  *
6913673Ssam  *	return codes:  none
7013673Ssam  */
7113673Ssam 
7213673Ssam stlock(name)
7313673Ssam register char *name;
7413673Ssam {
7513673Ssam 	register char *p;
7613673Ssam 	register int i;
7713673Ssam 
7813673Ssam 	for (i = 0; i < Nlocks; i++) {
7913673Ssam 		if (Lockfile[i] == NULL)
8013673Ssam 			break;
8113673Ssam 	}
82*17839Sralph 	ASSERT(i < MAXLOCKS, "TOO MANY LOCKS", CNULL, i);
8313673Ssam 	if (i >= Nlocks)
8413673Ssam 		i = Nlocks++;
8513673Ssam 	p = calloc((unsigned)(strlen(name)+1), sizeof (char));
8613673Ssam 	ASSERT(p != NULL, "CAN NOT ALLOCATE FOR", name, 0);
8713673Ssam 	strcpy(p, name);
8813673Ssam 	Lockfile[i] = p;
8913673Ssam 	return;
9013673Ssam }
9113673Ssam 
9213673Ssam 
93*17839Sralph /*
94*17839Sralph  *	remove all lock files in list *	or name
9513673Ssam  *
9613673Ssam  *	return codes: none
9713673Ssam  */
9813673Ssam 
9913673Ssam rmlock(name)
10013673Ssam register char *name;
10113673Ssam {
10213673Ssam 	register int i;
10313673Ssam 
10413673Ssam 	for (i = 0; i < Nlocks; i++) {
10513673Ssam 		if (Lockfile[i] == NULL)
10613673Ssam 			continue;
107*17839Sralph 		if (name == NULL || strcmp(name, Lockfile[i]) == SAME) {
10813673Ssam 			unlink(Lockfile[i]);
10913673Ssam 			free(Lockfile[i]);
11013673Ssam 			Lockfile[i] = NULL;
11113673Ssam 		}
11213673Ssam 	}
11313673Ssam }
11413673Ssam 
11513673Ssam /*
11613673Ssam  *	isalock(name) returns 0 if the name is a lock.
11713673Ssam  *	unlock(name)  unlocks name if it is a lock.
11813673Ssam  *	onelock(pid,tempfile,name) makes lock a name
11913673Ssam  *	on behalf of pid.  Tempfile must be in the same
12013673Ssam  *	file system as name.
12113673Ssam  *	lock(pid,tempfile,names) either locks all the
12213673Ssam  *	names or none of them.
12313673Ssam  */
124*17839Sralph isalock(name)
125*17839Sralph char *name;
12613673Ssam {
12713673Ssam 	struct stat xstat;
128*17839Sralph 	if (stat(name,&xstat) < 0)
129*17839Sralph 		return 0;
130*17839Sralph 	if (xstat.st_size != sizeof(int))
131*17839Sralph 		return 0;
132*17839Sralph 	return 1;
13313673Ssam }
134*17839Sralph unlock(name)
135*17839Sralph char *name;
13613673Ssam {
137*17839Sralph 	if (isalock(name))
138*17839Sralph 		return unlink(name);
139*17839Sralph 	else
140*17839Sralph 		return -1;
14113673Ssam }
142*17839Sralph onelock(pid,tempfile,name)
143*17839Sralph char *tempfile,*name;
144*17839Sralph {
145*17839Sralph 	register int fd;
146*17839Sralph #ifdef VMS
147*17839Sralph 	fd = creat(name, LCKMODE, "1version");
148*17839Sralph #else !VMS
149*17839Sralph 	fd = creat(tempfile, LCKMODE);
150*17839Sralph #endif !VMS
151*17839Sralph 	if (fd<0)
152*17839Sralph 		return FAIL;
153*17839Sralph 	write(fd, (char *) &pid, sizeof(int));
15413673Ssam 	close(fd);
155*17839Sralph #ifndef	VMS
156*17839Sralph 	if (link(tempfile, name) < 0) {
157*17839Sralph 		unlink(tempfile);
158*17839Sralph 		return FAIL;
15913673Ssam 	}
16013673Ssam 	unlink(tempfile);
161*17839Sralph #endif
162*17839Sralph 	return SUCCESS;
16313673Ssam }
164*17839Sralph 
165*17839Sralph 
166*17839Sralph lock(pid, tempfile, names)
167*17839Sralph char *tempfile;
16813673Ssam register char **names;
169*17839Sralph {
170*17839Sralph 	register int i, j;
171*17839Sralph 
172*17839Sralph 	for(i=0; names[i] != 0; i++) {
173*17839Sralph 		if (onelock(pid, tempfile, names[i]) == 0)
174*17839Sralph 			continue;
175*17839Sralph 		for(j=0; j < i ;j++)
176*17839Sralph 			unlink(names[j]);
177*17839Sralph 		return FAIL;
17813673Ssam 	}
179*17839Sralph 	return SUCCESS;
18013673Ssam }
18113673Ssam 
18213673Ssam #define LOCKPRE "LCK."
18313673Ssam 
184*17839Sralph /*
185*17839Sralph  *	remove a lock file
18613673Ssam  */
18713673Ssam delock(s)
18813673Ssam char *s;
18913673Ssam {
190*17839Sralph 	char ln[NAMESIZE];
19113673Ssam 
192*17839Sralph 	sprintf(ln, "%s/%s.%s", LOCKDIR, LOCKPRE, s);
19313673Ssam 	rmlock(ln);
19413673Ssam }
19513673Ssam 
196*17839Sralph /*
197*17839Sralph  *	create system lock
19813673Ssam  *
199*17839Sralph  *	return codes:  SUCCESS  |  FAIL
20013673Ssam  */
20113673Ssam mlock(sys)
20213673Ssam char *sys;
20313673Ssam {
204*17839Sralph 	char lname[NAMESIZE];
205*17839Sralph 
206*17839Sralph 	sprintf(lname, "%s/%s.%s", LOCKDIR, LOCKPRE, sys);
207*17839Sralph 	return ulockf(lname, (time_t) SLCKTIME ) < 0 ? FAIL : SUCCESS;
20813673Ssam }
20913673Ssam 
21013673Ssam /***
211*17839Sralph  *	update 'change' time for lock files
21213673Ssam  *
21313673Ssam  *	Only update ctime, not mtime or atime.
21413673Ssam  *	The 'chmod' method permits cu(I)-like programs
21513673Ssam  *	to determine how long uucp has been on the line.
21613673Ssam  *	The old "change access, mod, and change time" method
21713673Ssam  *	can be had by defining OLDTOUCH
21813673Ssam  *
21913673Ssam  *	return code - none
22013673Ssam  */
22113673Ssam 
22213673Ssam ultouch()
22313673Ssam {
22413673Ssam 	time_t time();
22513673Ssam 	static time_t lasttouch = 0;
22613673Ssam 	register int i;
22713673Ssam 	struct ut {
22813673Ssam 		time_t actime;
22913673Ssam 		time_t modtime;
23013673Ssam 	} ut;
23113673Ssam 
23213673Ssam 	ut.actime = time(&ut.modtime);
23313673Ssam 	/* Do not waste time touching locking files too often */
23413673Ssam 	/* (But, defend against backward time changes) */
23513673Ssam 	if (ut.actime >= lasttouch && ut.actime < lasttouch+60)
23613673Ssam 		return;
23713673Ssam 	lasttouch = ut.actime;
23813673Ssam 	DEBUG(4, "ultouch\n", 0);
23913673Ssam 
24013673Ssam 	for (i = 0; i < Nlocks; i++) {
24113673Ssam 		if (Lockfile[i] == NULL)
24213673Ssam 			continue;
24313673Ssam #ifdef	OLDTOUCH
24413673Ssam 		utime(Lockfile[i], &ut);
245*17839Sralph #else 	!OLDTOUCH
24613673Ssam 		chmod(Lockfile[i], LCKMODE);
247*17839Sralph #endif !OLDTOUCH
248*17839Sralph 	/*
249*17839Sralph 	 * set 'nologinflag' if the file /etc/nologin exists.
250*17839Sralph 	 * This permits graceful shutdown of uucp.
251*17839Sralph 	 */
252*17839Sralph 	if (nologinflag == 0 && access(NOLOGIN, 0) == 0)
253*17839Sralph 		nologinflag = 1;
25413673Ssam 	}
25513673Ssam }
256