xref: /titanic_51/usr/src/cmd/tip/uucplock.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
3*7c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
4*7c478bd9Sstevel@tonic-gate  */
5*7c478bd9Sstevel@tonic-gate /*
6*7c478bd9Sstevel@tonic-gate  * Copyright (c) 1983 Regents of the University of California.
7*7c478bd9Sstevel@tonic-gate  * All rights reserved. The Berkeley software License Agreement
8*7c478bd9Sstevel@tonic-gate  * specifies the terms and conditions for redistribution.
9*7c478bd9Sstevel@tonic-gate  */
10*7c478bd9Sstevel@tonic-gate #ident	"%Z%%M%	%I%	%E% SMI"	/* from UCB 4.6 6/25/83 */
11*7c478bd9Sstevel@tonic-gate /*
12*7c478bd9Sstevel@tonic-gate  * defs that come from uucp.h
13*7c478bd9Sstevel@tonic-gate  */
14*7c478bd9Sstevel@tonic-gate #define	NAMESIZE 40
15*7c478bd9Sstevel@tonic-gate #define	FAIL -1
16*7c478bd9Sstevel@tonic-gate #define	SAME 0
17*7c478bd9Sstevel@tonic-gate #define	SLCKTIME (8*60*60)	/* device timeout (LCK.. files) in seconds */
18*7c478bd9Sstevel@tonic-gate #ifdef __STDC__
19*7c478bd9Sstevel@tonic-gate #define	ASSERT(e, f, v) if (!(e)) {\
20*7c478bd9Sstevel@tonic-gate 	fprintf(stderr, "AERROR - (%s) ", #e); \
21*7c478bd9Sstevel@tonic-gate 	fprintf(stderr, f, v); \
22*7c478bd9Sstevel@tonic-gate 	finish(FAIL); \
23*7c478bd9Sstevel@tonic-gate }
24*7c478bd9Sstevel@tonic-gate #else
25*7c478bd9Sstevel@tonic-gate #define	ASSERT(e, f, v) if (!(e)) {\
26*7c478bd9Sstevel@tonic-gate 	fprintf(stderr, "AERROR - (%s) ", "e"); \
27*7c478bd9Sstevel@tonic-gate 	fprintf(stderr, f, v); \
28*7c478bd9Sstevel@tonic-gate 	finish(FAIL); \
29*7c478bd9Sstevel@tonic-gate }
30*7c478bd9Sstevel@tonic-gate #endif
31*7c478bd9Sstevel@tonic-gate #define	SIZEOFPID	10		/* maximum number of digits in a pid */
32*7c478bd9Sstevel@tonic-gate 
33*7c478bd9Sstevel@tonic-gate #define	LOCKDIR "/var/spool/locks"
34*7c478bd9Sstevel@tonic-gate #define	LOCKPRE "LK"
35*7c478bd9Sstevel@tonic-gate 
36*7c478bd9Sstevel@tonic-gate /*
37*7c478bd9Sstevel@tonic-gate  * This code is taken almost directly from uucp and follows the same
38*7c478bd9Sstevel@tonic-gate  * conventions.  This is important since uucp and tip should
39*7c478bd9Sstevel@tonic-gate  * respect each others locks.
40*7c478bd9Sstevel@tonic-gate  */
41*7c478bd9Sstevel@tonic-gate 
42*7c478bd9Sstevel@tonic-gate #include <sys/types.h>
43*7c478bd9Sstevel@tonic-gate #include <sys/stat.h>
44*7c478bd9Sstevel@tonic-gate #include <sys/mkdev.h>
45*7c478bd9Sstevel@tonic-gate #include <stdio.h>
46*7c478bd9Sstevel@tonic-gate #include <errno.h>
47*7c478bd9Sstevel@tonic-gate #include <string.h>
48*7c478bd9Sstevel@tonic-gate 
49*7c478bd9Sstevel@tonic-gate static void	stlock();
50*7c478bd9Sstevel@tonic-gate static int	onelock();
51*7c478bd9Sstevel@tonic-gate static int	checkLock();
52*7c478bd9Sstevel@tonic-gate 
53*7c478bd9Sstevel@tonic-gate 
54*7c478bd9Sstevel@tonic-gate /*
55*7c478bd9Sstevel@tonic-gate  *	ulockf(file, atime)
56*7c478bd9Sstevel@tonic-gate  *	char *file;
57*7c478bd9Sstevel@tonic-gate  *	time_t atime;
58*7c478bd9Sstevel@tonic-gate  *
59*7c478bd9Sstevel@tonic-gate  *	ulockf  -  this routine will create a lock file (file).
60*7c478bd9Sstevel@tonic-gate  *	If one already exists, send a signal 0 to the process--if
61*7c478bd9Sstevel@tonic-gate  *	it fails, then unlink it and make a new one.
62*7c478bd9Sstevel@tonic-gate  *
63*7c478bd9Sstevel@tonic-gate  *	input:
64*7c478bd9Sstevel@tonic-gate  *		file - name of the lock file
65*7c478bd9Sstevel@tonic-gate  *		atime - is unused, but we keep it for lint compatibility
66*7c478bd9Sstevel@tonic-gate  *			with non-ATTSVKILL
67*7c478bd9Sstevel@tonic-gate  *
68*7c478bd9Sstevel@tonic-gate  *	return codes:  0  |  FAIL
69*7c478bd9Sstevel@tonic-gate  */
70*7c478bd9Sstevel@tonic-gate 
71*7c478bd9Sstevel@tonic-gate static
72*7c478bd9Sstevel@tonic-gate ulockf(file, atime)
73*7c478bd9Sstevel@tonic-gate 	char *file;
74*7c478bd9Sstevel@tonic-gate 	time_t atime;
75*7c478bd9Sstevel@tonic-gate {
76*7c478bd9Sstevel@tonic-gate 	static char pid[SIZEOFPID+2] = { '\0' }; /* +2 for '\n' and NULL */
77*7c478bd9Sstevel@tonic-gate 	static char tempfile[NAMESIZE];
78*7c478bd9Sstevel@tonic-gate 
79*7c478bd9Sstevel@tonic-gate 	if (pid[0] == '\0') {
80*7c478bd9Sstevel@tonic-gate 		(void) sprintf(pid, "%*d\n", SIZEOFPID, getpid());
81*7c478bd9Sstevel@tonic-gate 		(void) sprintf(tempfile, "%s/LTMP.%d", LOCKDIR, getpid());
82*7c478bd9Sstevel@tonic-gate 	}
83*7c478bd9Sstevel@tonic-gate 	if (onelock(pid, tempfile, file) == -1) {
84*7c478bd9Sstevel@tonic-gate 		/* lock file exists */
85*7c478bd9Sstevel@tonic-gate 		(void) unlink(tempfile);
86*7c478bd9Sstevel@tonic-gate 		if (checkLock(file))
87*7c478bd9Sstevel@tonic-gate 			return (FAIL);
88*7c478bd9Sstevel@tonic-gate 		else {
89*7c478bd9Sstevel@tonic-gate 			if (onelock(pid, tempfile, file)) {
90*7c478bd9Sstevel@tonic-gate 				(void) unlink(tempfile);
91*7c478bd9Sstevel@tonic-gate 				return (FAIL);
92*7c478bd9Sstevel@tonic-gate 			}
93*7c478bd9Sstevel@tonic-gate 		}
94*7c478bd9Sstevel@tonic-gate 	}
95*7c478bd9Sstevel@tonic-gate 	stlock(file);
96*7c478bd9Sstevel@tonic-gate 	return (0);
97*7c478bd9Sstevel@tonic-gate }
98*7c478bd9Sstevel@tonic-gate 
99*7c478bd9Sstevel@tonic-gate /*
100*7c478bd9Sstevel@tonic-gate  * check to see if the lock file exists and is still active
101*7c478bd9Sstevel@tonic-gate  * - use kill(pid, 0) - (this only works on ATTSV and some hacked
102*7c478bd9Sstevel@tonic-gate  * BSD systems at this time)
103*7c478bd9Sstevel@tonic-gate  * return:
104*7c478bd9Sstevel@tonic-gate  *	0	-> success (lock file removed - no longer active)
105*7c478bd9Sstevel@tonic-gate  *	FAIL	-> lock file still active
106*7c478bd9Sstevel@tonic-gate  */
107*7c478bd9Sstevel@tonic-gate static int
108*7c478bd9Sstevel@tonic-gate checkLock(file)
109*7c478bd9Sstevel@tonic-gate register char *file;
110*7c478bd9Sstevel@tonic-gate {
111*7c478bd9Sstevel@tonic-gate 	register int ret;
112*7c478bd9Sstevel@tonic-gate 	int lpid = -1;
113*7c478bd9Sstevel@tonic-gate 	char alpid[SIZEOFPID+2];	/* +2 for '\n' and NULL */
114*7c478bd9Sstevel@tonic-gate 	int fd;
115*7c478bd9Sstevel@tonic-gate 	extern int errno;
116*7c478bd9Sstevel@tonic-gate 
117*7c478bd9Sstevel@tonic-gate 	fd = open(file, 0);
118*7c478bd9Sstevel@tonic-gate 	if (fd == -1) {
119*7c478bd9Sstevel@tonic-gate 		if (errno == ENOENT)  /* file does not exist -- OK */
120*7c478bd9Sstevel@tonic-gate 			return (0);
121*7c478bd9Sstevel@tonic-gate 		goto unlk;
122*7c478bd9Sstevel@tonic-gate 	}
123*7c478bd9Sstevel@tonic-gate 	ret = read(fd, (char *)alpid, SIZEOFPID+1); /* +1 for '\n' */
124*7c478bd9Sstevel@tonic-gate 	(void) close(fd);
125*7c478bd9Sstevel@tonic-gate 	if (ret != (SIZEOFPID+1))
126*7c478bd9Sstevel@tonic-gate 		goto unlk;
127*7c478bd9Sstevel@tonic-gate 	lpid = atoi(alpid);
128*7c478bd9Sstevel@tonic-gate 	if ((ret = kill(lpid, 0)) == 0 || errno == EPERM)
129*7c478bd9Sstevel@tonic-gate 		return (FAIL);
130*7c478bd9Sstevel@tonic-gate 
131*7c478bd9Sstevel@tonic-gate unlk:
132*7c478bd9Sstevel@tonic-gate 	if (unlink(file) != 0)
133*7c478bd9Sstevel@tonic-gate 		return (FAIL);
134*7c478bd9Sstevel@tonic-gate 	return (0);
135*7c478bd9Sstevel@tonic-gate }
136*7c478bd9Sstevel@tonic-gate 
137*7c478bd9Sstevel@tonic-gate #define	MAXLOCKS 10	/* maximum number of lock files */
138*7c478bd9Sstevel@tonic-gate char *Lockfile[MAXLOCKS];
139*7c478bd9Sstevel@tonic-gate int Nlocks = 0;
140*7c478bd9Sstevel@tonic-gate 
141*7c478bd9Sstevel@tonic-gate /*
142*7c478bd9Sstevel@tonic-gate  *	stlock(name)	put name in list of lock files
143*7c478bd9Sstevel@tonic-gate  *	char *name;
144*7c478bd9Sstevel@tonic-gate  *
145*7c478bd9Sstevel@tonic-gate  *	return codes:  none
146*7c478bd9Sstevel@tonic-gate  */
147*7c478bd9Sstevel@tonic-gate 
148*7c478bd9Sstevel@tonic-gate static void
149*7c478bd9Sstevel@tonic-gate stlock(name)
150*7c478bd9Sstevel@tonic-gate 	char *name;
151*7c478bd9Sstevel@tonic-gate {
152*7c478bd9Sstevel@tonic-gate 	char *p;
153*7c478bd9Sstevel@tonic-gate 	extern char *calloc();
154*7c478bd9Sstevel@tonic-gate 	int i;
155*7c478bd9Sstevel@tonic-gate 
156*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < Nlocks; i++) {
157*7c478bd9Sstevel@tonic-gate 		if (Lockfile[i] == NULL)
158*7c478bd9Sstevel@tonic-gate 			break;
159*7c478bd9Sstevel@tonic-gate 	}
160*7c478bd9Sstevel@tonic-gate 	ASSERT(i < MAXLOCKS, "TOO MANY LOCKS %d", i);
161*7c478bd9Sstevel@tonic-gate 	if (i >= Nlocks)
162*7c478bd9Sstevel@tonic-gate 		i = Nlocks++;
163*7c478bd9Sstevel@tonic-gate 	p = calloc(strlen(name) + 1, sizeof (char));
164*7c478bd9Sstevel@tonic-gate 	ASSERT(p != NULL, "CAN NOT ALLOCATE FOR %s", name);
165*7c478bd9Sstevel@tonic-gate 	strcpy(p, name);
166*7c478bd9Sstevel@tonic-gate 	Lockfile[i] = p;
167*7c478bd9Sstevel@tonic-gate }
168*7c478bd9Sstevel@tonic-gate 
169*7c478bd9Sstevel@tonic-gate /*
170*7c478bd9Sstevel@tonic-gate  *	rmlock(name)	remove all lock files in list
171*7c478bd9Sstevel@tonic-gate  *	char *name;	or name
172*7c478bd9Sstevel@tonic-gate  *
173*7c478bd9Sstevel@tonic-gate  *	return codes: none
174*7c478bd9Sstevel@tonic-gate  */
175*7c478bd9Sstevel@tonic-gate 
176*7c478bd9Sstevel@tonic-gate static
177*7c478bd9Sstevel@tonic-gate rmlock(name)
178*7c478bd9Sstevel@tonic-gate 	char *name;
179*7c478bd9Sstevel@tonic-gate {
180*7c478bd9Sstevel@tonic-gate 	int i;
181*7c478bd9Sstevel@tonic-gate 
182*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < Nlocks; i++) {
183*7c478bd9Sstevel@tonic-gate 		if (Lockfile[i] == NULL)
184*7c478bd9Sstevel@tonic-gate 			continue;
185*7c478bd9Sstevel@tonic-gate 		if (name == NULL || strcmp(name, Lockfile[i]) == SAME) {
186*7c478bd9Sstevel@tonic-gate 			unlink(Lockfile[i]);
187*7c478bd9Sstevel@tonic-gate 			free(Lockfile[i]);
188*7c478bd9Sstevel@tonic-gate 			Lockfile[i] = NULL;
189*7c478bd9Sstevel@tonic-gate 		}
190*7c478bd9Sstevel@tonic-gate 	}
191*7c478bd9Sstevel@tonic-gate }
192*7c478bd9Sstevel@tonic-gate 
193*7c478bd9Sstevel@tonic-gate static
194*7c478bd9Sstevel@tonic-gate onelock(pid, tempfile, name)
195*7c478bd9Sstevel@tonic-gate 	char *pid, *tempfile, *name;
196*7c478bd9Sstevel@tonic-gate {
197*7c478bd9Sstevel@tonic-gate 	int fd;
198*7c478bd9Sstevel@tonic-gate 	static int first = 1;
199*7c478bd9Sstevel@tonic-gate 	extern int errno;
200*7c478bd9Sstevel@tonic-gate 
201*7c478bd9Sstevel@tonic-gate 	fd = creat(tempfile, 0444);
202*7c478bd9Sstevel@tonic-gate 	if (fd < 0) {
203*7c478bd9Sstevel@tonic-gate 		if (first) {
204*7c478bd9Sstevel@tonic-gate 			if (errno == EACCES) {
205*7c478bd9Sstevel@tonic-gate 				fprintf(stderr,
206*7c478bd9Sstevel@tonic-gate 			"tip: can't create files in lock file directory %s\n",
207*7c478bd9Sstevel@tonic-gate 				    LOCKDIR);
208*7c478bd9Sstevel@tonic-gate 			} else if (access(LOCKDIR, 0) < 0) {
209*7c478bd9Sstevel@tonic-gate 				fprintf(stderr, "tip: lock file directory %s: ",
210*7c478bd9Sstevel@tonic-gate 				    LOCKDIR);
211*7c478bd9Sstevel@tonic-gate 				perror("");
212*7c478bd9Sstevel@tonic-gate 			}
213*7c478bd9Sstevel@tonic-gate 			first = 0;
214*7c478bd9Sstevel@tonic-gate 		}
215*7c478bd9Sstevel@tonic-gate 		if (errno == EMFILE || errno == ENFILE)
216*7c478bd9Sstevel@tonic-gate 			(void) unlink(tempfile);
217*7c478bd9Sstevel@tonic-gate 		return (-1);
218*7c478bd9Sstevel@tonic-gate 	}
219*7c478bd9Sstevel@tonic-gate 	/* +1 for '\n' */
220*7c478bd9Sstevel@tonic-gate 	if (write(fd, pid, SIZEOFPID+1) != (SIZEOFPID+1)) {
221*7c478bd9Sstevel@tonic-gate 		fprintf(stderr,
222*7c478bd9Sstevel@tonic-gate 		    "tip: can't write to files in lock file directory %s: %s\n",
223*7c478bd9Sstevel@tonic-gate 		    LOCKDIR, strerror(errno));
224*7c478bd9Sstevel@tonic-gate 		(void) unlink(tempfile);
225*7c478bd9Sstevel@tonic-gate 		return (-1);
226*7c478bd9Sstevel@tonic-gate 	}
227*7c478bd9Sstevel@tonic-gate 	fchmod(fd, 0444);
228*7c478bd9Sstevel@tonic-gate 	close(fd);
229*7c478bd9Sstevel@tonic-gate 	if (link(tempfile, name) < 0) {
230*7c478bd9Sstevel@tonic-gate 		unlink(tempfile);
231*7c478bd9Sstevel@tonic-gate 		return (-1);
232*7c478bd9Sstevel@tonic-gate 	}
233*7c478bd9Sstevel@tonic-gate 	unlink(tempfile);
234*7c478bd9Sstevel@tonic-gate 	return (0);
235*7c478bd9Sstevel@tonic-gate }
236*7c478bd9Sstevel@tonic-gate 
237*7c478bd9Sstevel@tonic-gate /*
238*7c478bd9Sstevel@tonic-gate  *	delock(sys)	remove a lock file
239*7c478bd9Sstevel@tonic-gate  *	char *sys;
240*7c478bd9Sstevel@tonic-gate  *
241*7c478bd9Sstevel@tonic-gate  *	return codes:  0  |  FAIL
242*7c478bd9Sstevel@tonic-gate  */
243*7c478bd9Sstevel@tonic-gate 
244*7c478bd9Sstevel@tonic-gate delock(sys)
245*7c478bd9Sstevel@tonic-gate 	char *sys;
246*7c478bd9Sstevel@tonic-gate {
247*7c478bd9Sstevel@tonic-gate 	struct stat sb;
248*7c478bd9Sstevel@tonic-gate 	char lname[NAMESIZE];
249*7c478bd9Sstevel@tonic-gate 
250*7c478bd9Sstevel@tonic-gate 	if (stat(sys, &sb) < 0)
251*7c478bd9Sstevel@tonic-gate 		return (FAIL);
252*7c478bd9Sstevel@tonic-gate 	sprintf(lname, "%s/%s.%3.3lu.%3.3lu.%3.3lu", LOCKDIR, LOCKPRE,
253*7c478bd9Sstevel@tonic-gate 		(unsigned long)major(sb.st_dev),
254*7c478bd9Sstevel@tonic-gate 		(unsigned long)major(sb.st_rdev),
255*7c478bd9Sstevel@tonic-gate 		(unsigned long)minor(sb.st_rdev));
256*7c478bd9Sstevel@tonic-gate 	rmlock(lname);
257*7c478bd9Sstevel@tonic-gate }
258*7c478bd9Sstevel@tonic-gate 
259*7c478bd9Sstevel@tonic-gate /*
260*7c478bd9Sstevel@tonic-gate  *	mlock(sys)	create system lock
261*7c478bd9Sstevel@tonic-gate  *	char *sys;
262*7c478bd9Sstevel@tonic-gate  *
263*7c478bd9Sstevel@tonic-gate  *	return codes:  0  |  FAIL
264*7c478bd9Sstevel@tonic-gate  */
265*7c478bd9Sstevel@tonic-gate 
266*7c478bd9Sstevel@tonic-gate mlock(sys)
267*7c478bd9Sstevel@tonic-gate 	char *sys;
268*7c478bd9Sstevel@tonic-gate {
269*7c478bd9Sstevel@tonic-gate 	struct stat sb;
270*7c478bd9Sstevel@tonic-gate 	char lname[NAMESIZE];
271*7c478bd9Sstevel@tonic-gate 
272*7c478bd9Sstevel@tonic-gate 	if (stat(sys, &sb) < 0)
273*7c478bd9Sstevel@tonic-gate 		return (FAIL);
274*7c478bd9Sstevel@tonic-gate 	sprintf(lname, "%s/%s.%3.3lu.%3.3lu.%3.3lu", LOCKDIR, LOCKPRE,
275*7c478bd9Sstevel@tonic-gate 		(unsigned long)major(sb.st_dev),
276*7c478bd9Sstevel@tonic-gate 		(unsigned long)major(sb.st_rdev),
277*7c478bd9Sstevel@tonic-gate 		(unsigned long)minor(sb.st_rdev));
278*7c478bd9Sstevel@tonic-gate 	return (ulockf(lname, (time_t)SLCKTIME) < 0 ? FAIL : 0);
279*7c478bd9Sstevel@tonic-gate }
280*7c478bd9Sstevel@tonic-gate 
281*7c478bd9Sstevel@tonic-gate /*
282*7c478bd9Sstevel@tonic-gate  * update access and modify times for lock files
283*7c478bd9Sstevel@tonic-gate  * return:
284*7c478bd9Sstevel@tonic-gate  *	none
285*7c478bd9Sstevel@tonic-gate  */
286*7c478bd9Sstevel@tonic-gate void
287*7c478bd9Sstevel@tonic-gate ultouch()
288*7c478bd9Sstevel@tonic-gate {
289*7c478bd9Sstevel@tonic-gate 	register int i;
290*7c478bd9Sstevel@tonic-gate 	time_t time();
291*7c478bd9Sstevel@tonic-gate 
292*7c478bd9Sstevel@tonic-gate 	struct ut {
293*7c478bd9Sstevel@tonic-gate 		time_t actime;
294*7c478bd9Sstevel@tonic-gate 		time_t modtime;
295*7c478bd9Sstevel@tonic-gate 	} ut;
296*7c478bd9Sstevel@tonic-gate 
297*7c478bd9Sstevel@tonic-gate 	ut.actime = time(&ut.modtime);
298*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < Nlocks; i++) {
299*7c478bd9Sstevel@tonic-gate 		if (Lockfile[i] == NULL)
300*7c478bd9Sstevel@tonic-gate 			continue;
301*7c478bd9Sstevel@tonic-gate 		utime(Lockfile[i], &ut);
302*7c478bd9Sstevel@tonic-gate 	}
303*7c478bd9Sstevel@tonic-gate }
304