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