xref: /titanic_54/usr/src/cmd/tip/uucplock.c (revision 8d489c7a815fcac696803219572e95aa01532b0f)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
37c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
47c478bd9Sstevel@tonic-gate  */
5*8d489c7aSmuffin 
67c478bd9Sstevel@tonic-gate /*
77c478bd9Sstevel@tonic-gate  * Copyright (c) 1983 Regents of the University of California.
87c478bd9Sstevel@tonic-gate  * All rights reserved. The Berkeley software License Agreement
97c478bd9Sstevel@tonic-gate  * specifies the terms and conditions for redistribution.
107c478bd9Sstevel@tonic-gate  */
11*8d489c7aSmuffin 
12*8d489c7aSmuffin #pragma ident	"%Z%%M%	%I%	%E% SMI"
13*8d489c7aSmuffin 
147c478bd9Sstevel@tonic-gate /*
157c478bd9Sstevel@tonic-gate  * defs that come from uucp.h
167c478bd9Sstevel@tonic-gate  */
177c478bd9Sstevel@tonic-gate #define	NAMESIZE 40
187c478bd9Sstevel@tonic-gate #define	FAIL -1
197c478bd9Sstevel@tonic-gate #define	SAME 0
207c478bd9Sstevel@tonic-gate #define	SLCKTIME (8*60*60)	/* device timeout (LCK.. files) in seconds */
217c478bd9Sstevel@tonic-gate #ifdef __STDC__
227c478bd9Sstevel@tonic-gate #define	ASSERT(e, f, v) if (!(e)) {\
23*8d489c7aSmuffin 	(void) fprintf(stderr, "AERROR - (%s) ", #e); \
24*8d489c7aSmuffin 	(void) fprintf(stderr, f, v); \
257c478bd9Sstevel@tonic-gate 	finish(FAIL); \
267c478bd9Sstevel@tonic-gate }
277c478bd9Sstevel@tonic-gate #else
287c478bd9Sstevel@tonic-gate #define	ASSERT(e, f, v) if (!(e)) {\
29*8d489c7aSmuffin 	(void) fprintf(stderr, "AERROR - (%s) ", "e"); \
30*8d489c7aSmuffin 	(void) fprintf(stderr, f, v); \
317c478bd9Sstevel@tonic-gate 	finish(FAIL); \
327c478bd9Sstevel@tonic-gate }
337c478bd9Sstevel@tonic-gate #endif
347c478bd9Sstevel@tonic-gate #define	SIZEOFPID	10		/* maximum number of digits in a pid */
357c478bd9Sstevel@tonic-gate 
367c478bd9Sstevel@tonic-gate #define	LOCKDIR "/var/spool/locks"
377c478bd9Sstevel@tonic-gate #define	LOCKPRE "LK"
387c478bd9Sstevel@tonic-gate 
397c478bd9Sstevel@tonic-gate /*
407c478bd9Sstevel@tonic-gate  * This code is taken almost directly from uucp and follows the same
417c478bd9Sstevel@tonic-gate  * conventions.  This is important since uucp and tip should
427c478bd9Sstevel@tonic-gate  * respect each others locks.
437c478bd9Sstevel@tonic-gate  */
447c478bd9Sstevel@tonic-gate 
457c478bd9Sstevel@tonic-gate #include <sys/types.h>
467c478bd9Sstevel@tonic-gate #include <sys/stat.h>
477c478bd9Sstevel@tonic-gate #include <sys/mkdev.h>
487c478bd9Sstevel@tonic-gate #include <stdio.h>
497c478bd9Sstevel@tonic-gate #include <errno.h>
507c478bd9Sstevel@tonic-gate #include <string.h>
51*8d489c7aSmuffin #include <stdlib.h>
52*8d489c7aSmuffin #include <time.h>
53*8d489c7aSmuffin #include <unistd.h>
54*8d489c7aSmuffin #include <fcntl.h>
55*8d489c7aSmuffin #include <signal.h>
56*8d489c7aSmuffin #include <utime.h>
577c478bd9Sstevel@tonic-gate 
58*8d489c7aSmuffin static void	stlock(char *);
59*8d489c7aSmuffin static int	onelock(char *, char *, char *);
60*8d489c7aSmuffin static int	checkLock(char *);
617c478bd9Sstevel@tonic-gate 
62*8d489c7aSmuffin extern void	finish(int);
637c478bd9Sstevel@tonic-gate 
647c478bd9Sstevel@tonic-gate /*
657c478bd9Sstevel@tonic-gate  *	ulockf(file, atime)
667c478bd9Sstevel@tonic-gate  *	char *file;
677c478bd9Sstevel@tonic-gate  *	time_t atime;
687c478bd9Sstevel@tonic-gate  *
697c478bd9Sstevel@tonic-gate  *	ulockf  -  this routine will create a lock file (file).
707c478bd9Sstevel@tonic-gate  *	If one already exists, send a signal 0 to the process--if
717c478bd9Sstevel@tonic-gate  *	it fails, then unlink it and make a new one.
727c478bd9Sstevel@tonic-gate  *
737c478bd9Sstevel@tonic-gate  *	input:
747c478bd9Sstevel@tonic-gate  *		file - name of the lock file
757c478bd9Sstevel@tonic-gate  *		atime - is unused, but we keep it for lint compatibility
767c478bd9Sstevel@tonic-gate  *			with non-ATTSVKILL
777c478bd9Sstevel@tonic-gate  *
787c478bd9Sstevel@tonic-gate  *	return codes:  0  |  FAIL
797c478bd9Sstevel@tonic-gate  */
80*8d489c7aSmuffin /* ARGSUSED */
81*8d489c7aSmuffin static int
82*8d489c7aSmuffin ulockf(char *file, time_t atime)
837c478bd9Sstevel@tonic-gate {
847c478bd9Sstevel@tonic-gate 	static char pid[SIZEOFPID+2] = { '\0' }; /* +2 for '\n' and NULL */
857c478bd9Sstevel@tonic-gate 	static char tempfile[NAMESIZE];
867c478bd9Sstevel@tonic-gate 
877c478bd9Sstevel@tonic-gate 	if (pid[0] == '\0') {
88*8d489c7aSmuffin 		(void) sprintf(pid, "%*d\n", SIZEOFPID, (int)getpid());
89*8d489c7aSmuffin 		(void) snprintf(tempfile, sizeof (tempfile),
90*8d489c7aSmuffin 		    "%s/LTMP.%d", LOCKDIR, getpid());
917c478bd9Sstevel@tonic-gate 	}
927c478bd9Sstevel@tonic-gate 	if (onelock(pid, tempfile, file) == -1) {
937c478bd9Sstevel@tonic-gate 		/* lock file exists */
947c478bd9Sstevel@tonic-gate 		(void) unlink(tempfile);
957c478bd9Sstevel@tonic-gate 		if (checkLock(file))
967c478bd9Sstevel@tonic-gate 			return (FAIL);
977c478bd9Sstevel@tonic-gate 		else {
987c478bd9Sstevel@tonic-gate 			if (onelock(pid, tempfile, file)) {
997c478bd9Sstevel@tonic-gate 				(void) unlink(tempfile);
1007c478bd9Sstevel@tonic-gate 				return (FAIL);
1017c478bd9Sstevel@tonic-gate 			}
1027c478bd9Sstevel@tonic-gate 		}
1037c478bd9Sstevel@tonic-gate 	}
1047c478bd9Sstevel@tonic-gate 	stlock(file);
1057c478bd9Sstevel@tonic-gate 	return (0);
1067c478bd9Sstevel@tonic-gate }
1077c478bd9Sstevel@tonic-gate 
1087c478bd9Sstevel@tonic-gate /*
1097c478bd9Sstevel@tonic-gate  * check to see if the lock file exists and is still active
1107c478bd9Sstevel@tonic-gate  * - use kill(pid, 0) - (this only works on ATTSV and some hacked
1117c478bd9Sstevel@tonic-gate  * BSD systems at this time)
1127c478bd9Sstevel@tonic-gate  * return:
1137c478bd9Sstevel@tonic-gate  *	0	-> success (lock file removed - no longer active)
1147c478bd9Sstevel@tonic-gate  *	FAIL	-> lock file still active
1157c478bd9Sstevel@tonic-gate  */
1167c478bd9Sstevel@tonic-gate static int
117*8d489c7aSmuffin checkLock(char *file)
1187c478bd9Sstevel@tonic-gate {
119*8d489c7aSmuffin 	int ret;
1207c478bd9Sstevel@tonic-gate 	int lpid = -1;
1217c478bd9Sstevel@tonic-gate 	char alpid[SIZEOFPID+2];	/* +2 for '\n' and NULL */
1227c478bd9Sstevel@tonic-gate 	int fd;
1237c478bd9Sstevel@tonic-gate 
1247c478bd9Sstevel@tonic-gate 	fd = open(file, 0);
1257c478bd9Sstevel@tonic-gate 	if (fd == -1) {
1267c478bd9Sstevel@tonic-gate 		if (errno == ENOENT)  /* file does not exist -- OK */
1277c478bd9Sstevel@tonic-gate 			return (0);
1287c478bd9Sstevel@tonic-gate 		goto unlk;
1297c478bd9Sstevel@tonic-gate 	}
1307c478bd9Sstevel@tonic-gate 	ret = read(fd, (char *)alpid, SIZEOFPID+1); /* +1 for '\n' */
1317c478bd9Sstevel@tonic-gate 	(void) close(fd);
1327c478bd9Sstevel@tonic-gate 	if (ret != (SIZEOFPID+1))
1337c478bd9Sstevel@tonic-gate 		goto unlk;
1347c478bd9Sstevel@tonic-gate 	lpid = atoi(alpid);
1357c478bd9Sstevel@tonic-gate 	if ((ret = kill(lpid, 0)) == 0 || errno == EPERM)
1367c478bd9Sstevel@tonic-gate 		return (FAIL);
1377c478bd9Sstevel@tonic-gate 
1387c478bd9Sstevel@tonic-gate unlk:
1397c478bd9Sstevel@tonic-gate 	if (unlink(file) != 0)
1407c478bd9Sstevel@tonic-gate 		return (FAIL);
1417c478bd9Sstevel@tonic-gate 	return (0);
1427c478bd9Sstevel@tonic-gate }
1437c478bd9Sstevel@tonic-gate 
1447c478bd9Sstevel@tonic-gate #define	MAXLOCKS 10	/* maximum number of lock files */
1457c478bd9Sstevel@tonic-gate char *Lockfile[MAXLOCKS];
1467c478bd9Sstevel@tonic-gate int Nlocks = 0;
1477c478bd9Sstevel@tonic-gate 
1487c478bd9Sstevel@tonic-gate /*
1497c478bd9Sstevel@tonic-gate  *	stlock(name)	put name in list of lock files
1507c478bd9Sstevel@tonic-gate  *	char *name;
1517c478bd9Sstevel@tonic-gate  *
1527c478bd9Sstevel@tonic-gate  *	return codes:  none
1537c478bd9Sstevel@tonic-gate  */
1547c478bd9Sstevel@tonic-gate 
1557c478bd9Sstevel@tonic-gate static void
156*8d489c7aSmuffin stlock(char *name)
1577c478bd9Sstevel@tonic-gate {
1587c478bd9Sstevel@tonic-gate 	char *p;
1597c478bd9Sstevel@tonic-gate 	int i;
1607c478bd9Sstevel@tonic-gate 
1617c478bd9Sstevel@tonic-gate 	for (i = 0; i < Nlocks; i++) {
1627c478bd9Sstevel@tonic-gate 		if (Lockfile[i] == NULL)
1637c478bd9Sstevel@tonic-gate 			break;
1647c478bd9Sstevel@tonic-gate 	}
1657c478bd9Sstevel@tonic-gate 	ASSERT(i < MAXLOCKS, "TOO MANY LOCKS %d", i);
1667c478bd9Sstevel@tonic-gate 	if (i >= Nlocks)
1677c478bd9Sstevel@tonic-gate 		i = Nlocks++;
1687c478bd9Sstevel@tonic-gate 	p = calloc(strlen(name) + 1, sizeof (char));
1697c478bd9Sstevel@tonic-gate 	ASSERT(p != NULL, "CAN NOT ALLOCATE FOR %s", name);
170*8d489c7aSmuffin 	(void) strcpy(p, name);
1717c478bd9Sstevel@tonic-gate 	Lockfile[i] = p;
1727c478bd9Sstevel@tonic-gate }
1737c478bd9Sstevel@tonic-gate 
1747c478bd9Sstevel@tonic-gate /*
1757c478bd9Sstevel@tonic-gate  *	rmlock(name)	remove all lock files in list
1767c478bd9Sstevel@tonic-gate  *	char *name;	or name
1777c478bd9Sstevel@tonic-gate  *
1787c478bd9Sstevel@tonic-gate  *	return codes: none
1797c478bd9Sstevel@tonic-gate  */
1807c478bd9Sstevel@tonic-gate 
181*8d489c7aSmuffin static void
182*8d489c7aSmuffin rmlock(char *name)
1837c478bd9Sstevel@tonic-gate {
1847c478bd9Sstevel@tonic-gate 	int i;
1857c478bd9Sstevel@tonic-gate 
1867c478bd9Sstevel@tonic-gate 	for (i = 0; i < Nlocks; i++) {
1877c478bd9Sstevel@tonic-gate 		if (Lockfile[i] == NULL)
1887c478bd9Sstevel@tonic-gate 			continue;
1897c478bd9Sstevel@tonic-gate 		if (name == NULL || strcmp(name, Lockfile[i]) == SAME) {
190*8d489c7aSmuffin 			(void) unlink(Lockfile[i]);
1917c478bd9Sstevel@tonic-gate 			free(Lockfile[i]);
1927c478bd9Sstevel@tonic-gate 			Lockfile[i] = NULL;
1937c478bd9Sstevel@tonic-gate 		}
1947c478bd9Sstevel@tonic-gate 	}
1957c478bd9Sstevel@tonic-gate }
1967c478bd9Sstevel@tonic-gate 
197*8d489c7aSmuffin static int
198*8d489c7aSmuffin onelock(char *pid, char *tempfile, char *name)
1997c478bd9Sstevel@tonic-gate {
2007c478bd9Sstevel@tonic-gate 	int fd;
2017c478bd9Sstevel@tonic-gate 	static int first = 1;
2027c478bd9Sstevel@tonic-gate 
2037c478bd9Sstevel@tonic-gate 	fd = creat(tempfile, 0444);
2047c478bd9Sstevel@tonic-gate 	if (fd < 0) {
2057c478bd9Sstevel@tonic-gate 		if (first) {
2067c478bd9Sstevel@tonic-gate 			if (errno == EACCES) {
207*8d489c7aSmuffin 				(void) fprintf(stderr,
2087c478bd9Sstevel@tonic-gate 			"tip: can't create files in lock file directory %s\n",
2097c478bd9Sstevel@tonic-gate 				    LOCKDIR);
2107c478bd9Sstevel@tonic-gate 			} else if (access(LOCKDIR, 0) < 0) {
211*8d489c7aSmuffin 				(void) fprintf(stderr,
212*8d489c7aSmuffin 				    "tip: lock file directory %s: ",
2137c478bd9Sstevel@tonic-gate 				    LOCKDIR);
2147c478bd9Sstevel@tonic-gate 				perror("");
2157c478bd9Sstevel@tonic-gate 			}
2167c478bd9Sstevel@tonic-gate 			first = 0;
2177c478bd9Sstevel@tonic-gate 		}
2187c478bd9Sstevel@tonic-gate 		if (errno == EMFILE || errno == ENFILE)
2197c478bd9Sstevel@tonic-gate 			(void) unlink(tempfile);
2207c478bd9Sstevel@tonic-gate 		return (-1);
2217c478bd9Sstevel@tonic-gate 	}
2227c478bd9Sstevel@tonic-gate 	/* +1 for '\n' */
2237c478bd9Sstevel@tonic-gate 	if (write(fd, pid, SIZEOFPID+1) != (SIZEOFPID+1)) {
224*8d489c7aSmuffin 		(void) fprintf(stderr,
2257c478bd9Sstevel@tonic-gate 		    "tip: can't write to files in lock file directory %s: %s\n",
2267c478bd9Sstevel@tonic-gate 		    LOCKDIR, strerror(errno));
2277c478bd9Sstevel@tonic-gate 		(void) unlink(tempfile);
2287c478bd9Sstevel@tonic-gate 		return (-1);
2297c478bd9Sstevel@tonic-gate 	}
230*8d489c7aSmuffin 	(void) fchmod(fd, 0444);
231*8d489c7aSmuffin 	(void) close(fd);
2327c478bd9Sstevel@tonic-gate 	if (link(tempfile, name) < 0) {
233*8d489c7aSmuffin 		(void) unlink(tempfile);
2347c478bd9Sstevel@tonic-gate 		return (-1);
2357c478bd9Sstevel@tonic-gate 	}
236*8d489c7aSmuffin 	(void) unlink(tempfile);
2377c478bd9Sstevel@tonic-gate 	return (0);
2387c478bd9Sstevel@tonic-gate }
2397c478bd9Sstevel@tonic-gate 
2407c478bd9Sstevel@tonic-gate /*
2417c478bd9Sstevel@tonic-gate  *	delock(sys)	remove a lock file
2427c478bd9Sstevel@tonic-gate  *	char *sys;
2437c478bd9Sstevel@tonic-gate  */
2447c478bd9Sstevel@tonic-gate 
245*8d489c7aSmuffin void
246*8d489c7aSmuffin delock(char *sys)
2477c478bd9Sstevel@tonic-gate {
2487c478bd9Sstevel@tonic-gate 	struct stat sb;
2497c478bd9Sstevel@tonic-gate 	char lname[NAMESIZE];
2507c478bd9Sstevel@tonic-gate 
2517c478bd9Sstevel@tonic-gate 	if (stat(sys, &sb) < 0)
252*8d489c7aSmuffin 		return;
253*8d489c7aSmuffin 	(void) snprintf(lname, sizeof (lname), "%s/%s.%3.3lu.%3.3lu.%3.3lu",
254*8d489c7aSmuffin 	    LOCKDIR, LOCKPRE,
2557c478bd9Sstevel@tonic-gate 	    (unsigned long)major(sb.st_dev),
2567c478bd9Sstevel@tonic-gate 	    (unsigned long)major(sb.st_rdev),
2577c478bd9Sstevel@tonic-gate 	    (unsigned long)minor(sb.st_rdev));
2587c478bd9Sstevel@tonic-gate 	rmlock(lname);
2597c478bd9Sstevel@tonic-gate }
2607c478bd9Sstevel@tonic-gate 
2617c478bd9Sstevel@tonic-gate /*
262*8d489c7aSmuffin  *	tip_mlock(sys)	create system lock
2637c478bd9Sstevel@tonic-gate  *	char *sys;
2647c478bd9Sstevel@tonic-gate  *
2657c478bd9Sstevel@tonic-gate  *	return codes:  0  |  FAIL
2667c478bd9Sstevel@tonic-gate  */
2677c478bd9Sstevel@tonic-gate 
268*8d489c7aSmuffin int
269*8d489c7aSmuffin tip_mlock(char *sys)
2707c478bd9Sstevel@tonic-gate {
2717c478bd9Sstevel@tonic-gate 	struct stat sb;
2727c478bd9Sstevel@tonic-gate 	char lname[NAMESIZE];
2737c478bd9Sstevel@tonic-gate 
2747c478bd9Sstevel@tonic-gate 	if (stat(sys, &sb) < 0)
2757c478bd9Sstevel@tonic-gate 		return (FAIL);
276*8d489c7aSmuffin 	(void) snprintf(lname, sizeof (lname), "%s/%s.%3.3lu.%3.3lu.%3.3lu",
277*8d489c7aSmuffin 	    LOCKDIR, LOCKPRE,
2787c478bd9Sstevel@tonic-gate 	    (unsigned long)major(sb.st_dev),
2797c478bd9Sstevel@tonic-gate 	    (unsigned long)major(sb.st_rdev),
2807c478bd9Sstevel@tonic-gate 	    (unsigned long)minor(sb.st_rdev));
2817c478bd9Sstevel@tonic-gate 	return (ulockf(lname, (time_t)SLCKTIME) < 0 ? FAIL : 0);
2827c478bd9Sstevel@tonic-gate }
283