xref: /csrg-svn/usr.bin/uucp/libuu/ulockf.c (revision 23677)
113673Ssam #ifndef lint
2*23677Sbloom static char sccsid[] = "@(#)ulockf.c	5.4 (Berkeley) 06/23/85";
313673Ssam #endif
413673Ssam 
513673Ssam #include "uucp.h"
613673Ssam #include <sys/stat.h>
713673Ssam 
813673Ssam /* File mode for lock files */
913673Ssam #define	LCKMODE	0444
1013673Ssam 
11*23677Sbloom /*LINTLIBRARY*/
12*23677Sbloom 
1317839Sralph /*
14*23677Sbloom  *	this routine will create a lock file (file).
1513673Ssam  *	If one already exists, the create time is checked for
1613673Ssam  *	older than the age time (atime).
1713673Ssam  *	If it is older, an attempt will be made to unlink it
1813673Ssam  *	and create a new one.
1913673Ssam  *
20*23677Sbloom  *	return codes:  SUCCESS  |  FAIL
2113673Ssam  */
2213673Ssam 
2318623Sralph ulockf(hfile, atime)
2418623Sralph char *hfile;
2513673Ssam time_t atime;
2613673Ssam {
2713673Ssam 	struct stat stbuf;
2813673Ssam 	time_t ptime;
2913673Ssam 	register int ret;
3013673Ssam 	static int pid = -1;
3113673Ssam 	static char tempfile[NAMESIZE];
3218623Sralph 	char file[NAMESIZE];
3313673Ssam 
3413673Ssam 	if (pid < 0) {
3513673Ssam 		pid = getpid();
3617839Sralph 		sprintf(tempfile, "%s/LTMP.%d", LOCKDIR, pid);
3713673Ssam 	}
3818623Sralph 	sprintf(file, "%s/%s", LOCKDIR, hfile);
3913673Ssam 	if (onelock(pid, tempfile, file) == -1) {
4013673Ssam 		/* lock file exists */
4113673Ssam 		/* get status to check age of the lock file */
4213673Ssam 		ret = stat(file, &stbuf);
4313673Ssam 		if (ret != -1) {
4413673Ssam 			time(&ptime);
4513673Ssam 			if ((ptime - stbuf.st_ctime) < atime) {
4613673Ssam 				/* file not old enough to delete */
4717839Sralph 				return FAIL;
4813673Ssam 			}
4917839Sralph 			ret = unlink(file);
5017839Sralph 			logent(file, "DEAD LOCK");
5117839Sralph 			sleep(5);	/* rti!trt: avoid a race */
5217839Sralph 			ret = onelock(pid, tempfile, file);
5313673Ssam 		}
5413673Ssam 		if (ret != 0)
5517839Sralph 			return FAIL;
5613673Ssam 	}
5713673Ssam 	stlock(file);
5817839Sralph 	return SUCCESS;
5913673Ssam }
6013673Ssam 
6113673Ssam 
6213673Ssam #define MAXLOCKS 10	/* maximum number of lock files */
6313673Ssam char *Lockfile[MAXLOCKS];
6413673Ssam int Nlocks = 0;
6513673Ssam 
6613673Ssam /***
6713673Ssam  *	stlock(name)	put name in list of lock files
6813673Ssam  *	char *name;
6913673Ssam  *
7013673Ssam  *	return codes:  none
7113673Ssam  */
7213673Ssam 
7313673Ssam stlock(name)
7413673Ssam register char *name;
7513673Ssam {
7613673Ssam 	register char *p;
7713673Ssam 	register int i;
7813673Ssam 
7913673Ssam 	for (i = 0; i < Nlocks; i++) {
8013673Ssam 		if (Lockfile[i] == NULL)
8113673Ssam 			break;
8213673Ssam 	}
8317839Sralph 	ASSERT(i < MAXLOCKS, "TOO MANY LOCKS", CNULL, i);
8413673Ssam 	if (i >= Nlocks)
8513673Ssam 		i = Nlocks++;
8613673Ssam 	p = calloc((unsigned)(strlen(name)+1), sizeof (char));
8713673Ssam 	ASSERT(p != NULL, "CAN NOT ALLOCATE FOR", name, 0);
8813673Ssam 	strcpy(p, name);
8913673Ssam 	Lockfile[i] = p;
9013673Ssam }
9113673Ssam 
9213673Ssam 
9317839Sralph /*
9417839Sralph  *	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;
10717839Sralph 		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  */
12417839Sralph isalock(name)
12517839Sralph char *name;
12613673Ssam {
12713673Ssam 	struct stat xstat;
12817839Sralph 	if (stat(name,&xstat) < 0)
12917839Sralph 		return 0;
13017839Sralph 	if (xstat.st_size != sizeof(int))
13117839Sralph 		return 0;
13217839Sralph 	return 1;
13313673Ssam }
13417839Sralph unlock(name)
13517839Sralph char *name;
13613673Ssam {
13717839Sralph 	if (isalock(name))
13817839Sralph 		return unlink(name);
13917839Sralph 	else
14017839Sralph 		return -1;
14113673Ssam }
142*23677Sbloom onelock(pid, tempfile, name)
143*23677Sbloom int pid;
14417839Sralph char *tempfile,*name;
14517839Sralph {
14617839Sralph 	register int fd;
14717839Sralph #ifdef VMS
14817839Sralph 	fd = creat(name, LCKMODE, "1version");
14917839Sralph #else !VMS
15017839Sralph 	fd = creat(tempfile, LCKMODE);
15117839Sralph #endif !VMS
152*23677Sbloom 	if (fd < 0)
15317839Sralph 		return FAIL;
154*23677Sbloom 	write(fd, (char *)&pid, sizeof(int));
15513673Ssam 	close(fd);
15617839Sralph #ifndef	VMS
15717839Sralph 	if (link(tempfile, name) < 0) {
15817839Sralph 		unlink(tempfile);
15917839Sralph 		return FAIL;
16013673Ssam 	}
16113673Ssam 	unlink(tempfile);
16217839Sralph #endif
16317839Sralph 	return SUCCESS;
16413673Ssam }
16517839Sralph 
16617839Sralph 
16717839Sralph lock(pid, tempfile, names)
16817839Sralph char *tempfile;
16913673Ssam register char **names;
17017839Sralph {
17117839Sralph 	register int i, j;
17217839Sralph 
17317839Sralph 	for(i=0; names[i] != 0; i++) {
17417839Sralph 		if (onelock(pid, tempfile, names[i]) == 0)
17517839Sralph 			continue;
17617839Sralph 		for(j=0; j < i ;j++)
17717839Sralph 			unlink(names[j]);
17817839Sralph 		return FAIL;
17913673Ssam 	}
18017839Sralph 	return SUCCESS;
18113673Ssam }
18213673Ssam 
18313673Ssam #define LOCKPRE "LCK."
18413673Ssam 
18517839Sralph /*
18617839Sralph  *	remove a lock file
18713673Ssam  */
18813673Ssam delock(s)
18913673Ssam char *s;
19013673Ssam {
19117839Sralph 	char ln[NAMESIZE];
19213673Ssam 
19317839Sralph 	sprintf(ln, "%s/%s.%s", LOCKDIR, LOCKPRE, s);
19413673Ssam 	rmlock(ln);
19513673Ssam }
19613673Ssam 
19717839Sralph /*
19817839Sralph  *	create system lock
19913673Ssam  *
20017839Sralph  *	return codes:  SUCCESS  |  FAIL
20113673Ssam  */
20213673Ssam mlock(sys)
20313673Ssam char *sys;
20413673Ssam {
20517839Sralph 	char lname[NAMESIZE];
20617839Sralph 
20718623Sralph 	sprintf(lname, "%s.%s", LOCKPRE, sys);
20817839Sralph 	return ulockf(lname, (time_t) SLCKTIME ) < 0 ? FAIL : SUCCESS;
20913673Ssam }
21013673Ssam 
21113673Ssam /***
21217839Sralph  *	update 'change' time for lock files
21313673Ssam  *
21413673Ssam  *	Only update ctime, not mtime or atime.
21513673Ssam  *	The 'chmod' method permits cu(I)-like programs
21613673Ssam  *	to determine how long uucp has been on the line.
21713673Ssam  *	The old "change access, mod, and change time" method
21813673Ssam  *	can be had by defining OLDTOUCH
21913673Ssam  *
22013673Ssam  *	return code - none
22113673Ssam  */
22213673Ssam 
22313673Ssam ultouch()
22413673Ssam {
22513673Ssam 	time_t time();
22613673Ssam 	static time_t lasttouch = 0;
22713673Ssam 	register int i;
22813673Ssam 	struct ut {
22913673Ssam 		time_t actime;
23013673Ssam 		time_t modtime;
23113673Ssam 	} ut;
23213673Ssam 
23313673Ssam 	ut.actime = time(&ut.modtime);
23413673Ssam 	/* Do not waste time touching locking files too often */
23513673Ssam 	/* (But, defend against backward time changes) */
23613673Ssam 	if (ut.actime >= lasttouch && ut.actime < lasttouch+60)
23713673Ssam 		return;
23813673Ssam 	lasttouch = ut.actime;
23913673Ssam 	DEBUG(4, "ultouch\n", 0);
24013673Ssam 
24113673Ssam 	for (i = 0; i < Nlocks; i++) {
24213673Ssam 		if (Lockfile[i] == NULL)
24313673Ssam 			continue;
24413673Ssam #ifdef	OLDTOUCH
24513673Ssam 		utime(Lockfile[i], &ut);
24617839Sralph #else 	!OLDTOUCH
24713673Ssam 		chmod(Lockfile[i], LCKMODE);
24817839Sralph #endif !OLDTOUCH
24917839Sralph 	/*
25017839Sralph 	 * set 'nologinflag' if the file /etc/nologin exists.
25117839Sralph 	 * This permits graceful shutdown of uucp.
25217839Sralph 	 */
25317839Sralph 	if (nologinflag == 0 && access(NOLOGIN, 0) == 0)
25417839Sralph 		nologinflag = 1;
25513673Ssam 	}
25613673Ssam }
257