xref: /csrg-svn/usr.bin/uucp/libuu/ulockf.c (revision 13673)
1*13673Ssam #ifndef lint
2*13673Ssam static char sccsid[] = "@(#)ulockf.c	5.1 (Berkeley) 07/02/83";
3*13673Ssam #endif
4*13673Ssam 
5*13673Ssam #include "uucp.h"
6*13673Ssam #include <sys/types.h>
7*13673Ssam #include <sys/stat.h>
8*13673Ssam 
9*13673Ssam 
10*13673Ssam extern time_t	time();
11*13673Ssam 
12*13673Ssam /* File mode for lock files */
13*13673Ssam #define	LCKMODE	0444
14*13673Ssam 
15*13673Ssam /*******
16*13673Ssam  *	ulockf(file, atime)
17*13673Ssam  *	char *file;
18*13673Ssam  *	time_t atime;
19*13673Ssam  *
20*13673Ssam  *	ulockf  -  this routine will create a lock file (file).
21*13673Ssam  *	If one already exists, the create time is checked for
22*13673Ssam  *	older than the age time (atime).
23*13673Ssam  *	If it is older, an attempt will be made to unlink it
24*13673Ssam  *	and create a new one.
25*13673Ssam  *
26*13673Ssam  *	return codes:  0  |  FAIL
27*13673Ssam  */
28*13673Ssam 
29*13673Ssam ulockf(file, atime)
30*13673Ssam register char *file;
31*13673Ssam time_t atime;
32*13673Ssam {
33*13673Ssam 	struct stat stbuf;
34*13673Ssam 	time_t ptime;
35*13673Ssam 	register int ret;
36*13673Ssam 	static int pid = -1;
37*13673Ssam 	static char tempfile[NAMESIZE];
38*13673Ssam 
39*13673Ssam 	if (pid < 0) {
40*13673Ssam 		pid = getpid();
41*13673Ssam 		sprintf(tempfile, "LTMP.%d", pid);
42*13673Ssam 	}
43*13673Ssam 	if (onelock(pid, tempfile, file) == -1) {
44*13673Ssam 		/* lock file exists */
45*13673Ssam 		/* get status to check age of the lock file */
46*13673Ssam 		ret = stat(file, &stbuf);
47*13673Ssam 		if (ret != -1) {
48*13673Ssam 			time(&ptime);
49*13673Ssam 			if ((ptime - stbuf.st_ctime) < atime) {
50*13673Ssam 				/* file not old enough to delete */
51*13673Ssam 				return(FAIL);
52*13673Ssam 			}
53*13673Ssam 		}
54*13673Ssam 		ret = unlink(file);
55*13673Ssam 		ret = onelock(pid, tempfile, file);
56*13673Ssam 		if (ret != 0)
57*13673Ssam 			return(FAIL);
58*13673Ssam 	}
59*13673Ssam 	stlock(file);
60*13673Ssam 	return(0);
61*13673Ssam }
62*13673Ssam 
63*13673Ssam 
64*13673Ssam #define MAXLOCKS 10	/* maximum number of lock files */
65*13673Ssam char *Lockfile[MAXLOCKS];
66*13673Ssam int Nlocks = 0;
67*13673Ssam 
68*13673Ssam /***
69*13673Ssam  *	stlock(name)	put name in list of lock files
70*13673Ssam  *	char *name;
71*13673Ssam  *
72*13673Ssam  *	return codes:  none
73*13673Ssam  */
74*13673Ssam 
75*13673Ssam stlock(name)
76*13673Ssam register char *name;
77*13673Ssam {
78*13673Ssam 	register char *p;
79*13673Ssam 	register int i;
80*13673Ssam 
81*13673Ssam 	for (i = 0; i < Nlocks; i++) {
82*13673Ssam 		if (Lockfile[i] == NULL)
83*13673Ssam 			break;
84*13673Ssam 	}
85*13673Ssam 	ASSERT(i < MAXLOCKS, "TOO MANY LOCKS", "", i);
86*13673Ssam 	if (i >= Nlocks)
87*13673Ssam 		i = Nlocks++;
88*13673Ssam 	p = calloc((unsigned)(strlen(name)+1), sizeof (char));
89*13673Ssam 	ASSERT(p != NULL, "CAN NOT ALLOCATE FOR", name, 0);
90*13673Ssam 	strcpy(p, name);
91*13673Ssam 	Lockfile[i] = p;
92*13673Ssam 	return;
93*13673Ssam }
94*13673Ssam 
95*13673Ssam 
96*13673Ssam /***
97*13673Ssam  *	rmlock(name)	remove all lock files in list
98*13673Ssam  *	char *name;	or name
99*13673Ssam  *
100*13673Ssam  *	return codes: none
101*13673Ssam  */
102*13673Ssam 
103*13673Ssam rmlock(name)
104*13673Ssam register char *name;
105*13673Ssam {
106*13673Ssam 	register int i;
107*13673Ssam 
108*13673Ssam 	for (i = 0; i < Nlocks; i++) {
109*13673Ssam 		if (Lockfile[i] == NULL)
110*13673Ssam 			continue;
111*13673Ssam 		if (name == NULL
112*13673Ssam 		|| strcmp(name, Lockfile[i]) == SAME) {
113*13673Ssam 			unlink(Lockfile[i]);
114*13673Ssam 			free(Lockfile[i]);
115*13673Ssam 			Lockfile[i] = NULL;
116*13673Ssam 		}
117*13673Ssam 	}
118*13673Ssam 	return;
119*13673Ssam }
120*13673Ssam 
121*13673Ssam 
122*13673Ssam /*
123*13673Ssam  *  this stuff from pjw
124*13673Ssam  *  /usr/pjw/bin/recover - Check pids to remove unnecessary locks.
125*13673Ssam  *	isalock(name) returns 0 if the name is a lock.
126*13673Ssam  *	unlock(name)  unlocks name if it is a lock.
127*13673Ssam  *	onelock(pid,tempfile,name) makes lock a name
128*13673Ssam  *	on behalf of pid.  Tempfile must be in the same
129*13673Ssam  *	file system as name.
130*13673Ssam  *	lock(pid,tempfile,names) either locks all the
131*13673Ssam  *	names or none of them.
132*13673Ssam  */
133*13673Ssam isalock(name) char *name;
134*13673Ssam {
135*13673Ssam 	struct stat xstat;
136*13673Ssam 	if(stat(name,&xstat)<0) return(0);
137*13673Ssam 	if(xstat.st_size!=sizeof(int)) return(0);
138*13673Ssam 	return(1);
139*13673Ssam }
140*13673Ssam unlock(name) char *name;
141*13673Ssam {
142*13673Ssam 	if(isalock(name)) return(unlink(name));
143*13673Ssam 	else return(-1);
144*13673Ssam }
145*13673Ssam onelock(pid,tempfile,name) char *tempfile,*name;
146*13673Ssam {	register int fd;
147*13673Ssam 	fd=creat(tempfile,LCKMODE);
148*13673Ssam 	if(fd<0) return(-1);
149*13673Ssam 	write(fd,(char *) &pid,sizeof(int));
150*13673Ssam 	close(fd);
151*13673Ssam 	if(link(tempfile,name)<0)
152*13673Ssam 	{	unlink(tempfile);
153*13673Ssam 		return(-1);
154*13673Ssam 	}
155*13673Ssam 	unlink(tempfile);
156*13673Ssam 	return(0);
157*13673Ssam }
158*13673Ssam lock(pid,tempfile,names) char *tempfile;
159*13673Ssam register char **names;
160*13673Ssam {	register int i,j;
161*13673Ssam 	for(i=0;names[i]!=0;i++)
162*13673Ssam 	{	if(onelock(pid,tempfile,names[i])==0) continue;
163*13673Ssam 		for(j=0;j<i;j++) unlink(names[j]);
164*13673Ssam 		return(-1);
165*13673Ssam 	}
166*13673Ssam 	return(0);
167*13673Ssam }
168*13673Ssam 
169*13673Ssam #define LOCKPRE "LCK."
170*13673Ssam 
171*13673Ssam /***
172*13673Ssam  *	delock(s)	remove a lock file
173*13673Ssam  *	char *s;
174*13673Ssam  *
175*13673Ssam  *	return codes:  0  |  FAIL
176*13673Ssam  */
177*13673Ssam 
178*13673Ssam delock(s)
179*13673Ssam char *s;
180*13673Ssam {
181*13673Ssam 	char ln[30];
182*13673Ssam 
183*13673Ssam 	sprintf(ln, "%s.%s", LOCKPRE, s);
184*13673Ssam 	rmlock(ln);
185*13673Ssam }
186*13673Ssam 
187*13673Ssam 
188*13673Ssam /***
189*13673Ssam  *	mlock(sys)	create system lock
190*13673Ssam  *	char *sys;
191*13673Ssam  *
192*13673Ssam  *	return codes:  0  |  FAIL
193*13673Ssam  */
194*13673Ssam 
195*13673Ssam mlock(sys)
196*13673Ssam char *sys;
197*13673Ssam {
198*13673Ssam 	char lname[30];
199*13673Ssam 	sprintf(lname, "%s.%s", LOCKPRE, sys);
200*13673Ssam 	return(ulockf(lname, (time_t) SLCKTIME ) < 0 ? FAIL : 0);
201*13673Ssam }
202*13673Ssam 
203*13673Ssam 
204*13673Ssam /***
205*13673Ssam  *	ultouch()	update 'change' time for lock files
206*13673Ssam  *
207*13673Ssam  *	-- mod by rti!trt --
208*13673Ssam  *	Only update ctime, not mtime or atime.
209*13673Ssam  *	The 'chmod' method permits cu(I)-like programs
210*13673Ssam  *	to determine how long uucp has been on the line.
211*13673Ssam  *	The old "change access, mod, and change time" method
212*13673Ssam  *	can be had by defining OLDTOUCH
213*13673Ssam  *
214*13673Ssam  *	return code - none
215*13673Ssam  */
216*13673Ssam 
217*13673Ssam ultouch()
218*13673Ssam {
219*13673Ssam 	time_t time();
220*13673Ssam 	static time_t lasttouch = 0;
221*13673Ssam 	register int i;
222*13673Ssam 	struct ut {
223*13673Ssam 		time_t actime;
224*13673Ssam 		time_t modtime;
225*13673Ssam 	} ut;
226*13673Ssam 
227*13673Ssam 	ut.actime = time(&ut.modtime);
228*13673Ssam 	/* Do not waste time touching locking files too often */
229*13673Ssam 	/* (But, defend against backward time changes) */
230*13673Ssam 	if (ut.actime >= lasttouch && ut.actime < lasttouch+60)
231*13673Ssam 		return;
232*13673Ssam 	lasttouch = ut.actime;
233*13673Ssam 	DEBUG(4, "ultouch\n", 0);
234*13673Ssam 
235*13673Ssam 	for (i = 0; i < Nlocks; i++) {
236*13673Ssam 		if (Lockfile[i] == NULL)
237*13673Ssam 			continue;
238*13673Ssam #ifdef	OLDTOUCH
239*13673Ssam 		utime(Lockfile[i], &ut);
240*13673Ssam #else
241*13673Ssam 		chmod(Lockfile[i], LCKMODE);
242*13673Ssam #endif
243*13673Ssam 	}
244*13673Ssam }
245