xref: /freebsd/lib/libutil/uucplock.c (revision 687d0cdeb381b9003bb907fac08f035be93d1d7f)
1568b59b9SBrian Somers /*
2568b59b9SBrian Somers  * Copyright (c) 1988, 1993
3568b59b9SBrian Somers  *	The Regents of the University of California.  All rights reserved.
4568b59b9SBrian Somers  *
5568b59b9SBrian Somers  * Redistribution and use in source and binary forms, with or without
6568b59b9SBrian Somers  * modification, are permitted provided that the following conditions
7568b59b9SBrian Somers  * are met:
8568b59b9SBrian Somers  * 1. Redistributions of source code must retain the above copyright
9568b59b9SBrian Somers  *    notice, this list of conditions and the following disclaimer.
10568b59b9SBrian Somers  * 2. Redistributions in binary form must reproduce the above copyright
11568b59b9SBrian Somers  *    notice, this list of conditions and the following disclaimer in the
12568b59b9SBrian Somers  *    documentation and/or other materials provided with the distribution.
13568b59b9SBrian Somers  * 3. All advertising materials mentioning features or use of this software
14568b59b9SBrian Somers  *    must display the following acknowledgement:
15568b59b9SBrian Somers  *	This product includes software developed by the University of
16568b59b9SBrian Somers  *	California, Berkeley and its contributors.
17568b59b9SBrian Somers  * 4. Neither the name of the University nor the names of its contributors
18568b59b9SBrian Somers  *    may be used to endorse or promote products derived from this software
19568b59b9SBrian Somers  *    without specific prior written permission.
20568b59b9SBrian Somers  *
21568b59b9SBrian Somers  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22568b59b9SBrian Somers  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23568b59b9SBrian Somers  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24568b59b9SBrian Somers  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25568b59b9SBrian Somers  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26568b59b9SBrian Somers  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27568b59b9SBrian Somers  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28568b59b9SBrian Somers  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29568b59b9SBrian Somers  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30568b59b9SBrian Somers  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31568b59b9SBrian Somers  * SUCH DAMAGE.
32568b59b9SBrian Somers  */
33568b59b9SBrian Somers 
34568b59b9SBrian Somers #ifndef lint
35568b59b9SBrian Somers static const char sccsid[] = "@(#)uucplock.c	8.1 (Berkeley) 6/6/93";
36568b59b9SBrian Somers #endif /* not lint */
37568b59b9SBrian Somers 
38568b59b9SBrian Somers #include <sys/types.h>
39568b59b9SBrian Somers #include <sys/file.h>
40568b59b9SBrian Somers #include <dirent.h>
41568b59b9SBrian Somers #include <errno.h>
42568b59b9SBrian Somers #ifndef USE_PERROR
43568b59b9SBrian Somers #include <syslog.h>
44568b59b9SBrian Somers #endif
45568b59b9SBrian Somers #include <unistd.h>
46568b59b9SBrian Somers #include <signal.h>
47568b59b9SBrian Somers #include <stdio.h>
48568b59b9SBrian Somers #include <stdlib.h>
49568b59b9SBrian Somers #include <paths.h>
50687d0cdeSBrian Somers #include <string.h>
51687d0cdeSBrian Somers #include "libutil.h"
52568b59b9SBrian Somers 
53568b59b9SBrian Somers #define LOCKFMT "LCK..%s"
54568b59b9SBrian Somers 
55568b59b9SBrian Somers /* Forward declarations */
56568b59b9SBrian Somers static int put_pid (int fd, pid_t pid);
57687d0cdeSBrian Somers static pid_t get_pid (int fd,int *err);
58568b59b9SBrian Somers 
59568b59b9SBrian Somers /*
60568b59b9SBrian Somers  * uucp style locking routines
61568b59b9SBrian Somers  * return: 0 - success
62568b59b9SBrian Somers  * 	  -1 - failure
63568b59b9SBrian Somers  */
64568b59b9SBrian Somers 
65568b59b9SBrian Somers int uu_lock (char *ttyname)
66568b59b9SBrian Somers {
67568b59b9SBrian Somers 	int fd;
68568b59b9SBrian Somers 	pid_t pid;
69568b59b9SBrian Somers 	char tbuf[sizeof(_PATH_UUCPLOCK) + MAXNAMLEN];
70687d0cdeSBrian Somers 	int err;
71568b59b9SBrian Somers 
72568b59b9SBrian Somers 	(void)sprintf(tbuf, _PATH_UUCPLOCK LOCKFMT, ttyname);
73568b59b9SBrian Somers 	fd = open(tbuf, O_RDWR|O_CREAT|O_EXCL, 0660);
74568b59b9SBrian Somers 	if (fd < 0) {
75568b59b9SBrian Somers 		/*
76568b59b9SBrian Somers 		 * file is already locked
77568b59b9SBrian Somers 		 * check to see if the process holding the lock still exists
78568b59b9SBrian Somers 		 */
79568b59b9SBrian Somers 		fd = open(tbuf, O_RDWR, 0);
80687d0cdeSBrian Somers 		if (fd < 0)
81687d0cdeSBrian Somers 			return UU_LOCK_OPEN_ERR;
82687d0cdeSBrian Somers 
83687d0cdeSBrian Somers 		if ((pid = get_pid (fd, &err)) == -1) {
84568b59b9SBrian Somers 			(void)close(fd);
85687d0cdeSBrian Somers 			errno = err;
86687d0cdeSBrian Somers 			return UU_LOCK_READ_ERR;
87568b59b9SBrian Somers 		}
88568b59b9SBrian Somers 
89568b59b9SBrian Somers 		if (kill(pid, 0) == 0 || errno != ESRCH) {
90568b59b9SBrian Somers 			(void)close(fd);	/* process is still running */
91687d0cdeSBrian Somers 			return UU_LOCK_INUSE;
92568b59b9SBrian Somers 		}
93568b59b9SBrian Somers 		/*
94568b59b9SBrian Somers 		 * The process that locked the file isn't running, so
95568b59b9SBrian Somers 		 * we'll lock it ourselves
96568b59b9SBrian Somers 		 */
97568b59b9SBrian Somers 		if (lseek(fd, (off_t) 0, L_SET) < 0) {
98687d0cdeSBrian Somers 			err = errno;
99568b59b9SBrian Somers 			(void)close(fd);
100687d0cdeSBrian Somers 			errno = err;
101687d0cdeSBrian Somers 			return UU_LOCK_SEEK_ERR;
102568b59b9SBrian Somers 		}
103568b59b9SBrian Somers 		/* fall out and finish the locking process */
104568b59b9SBrian Somers 	}
105568b59b9SBrian Somers 	pid = getpid();
106568b59b9SBrian Somers 	if (!put_pid (fd, pid)) {
107687d0cdeSBrian Somers 		err = errno;
108568b59b9SBrian Somers 		(void)close(fd);
109568b59b9SBrian Somers 		(void)unlink(tbuf);
110687d0cdeSBrian Somers 		errno = err;
111687d0cdeSBrian Somers 		return UU_LOCK_WRITE_ERR;
112568b59b9SBrian Somers 	}
113568b59b9SBrian Somers 	(void)close(fd);
114687d0cdeSBrian Somers 	return UU_LOCK_OK;
115568b59b9SBrian Somers }
116568b59b9SBrian Somers 
117568b59b9SBrian Somers int uu_unlock (char *ttyname)
118568b59b9SBrian Somers {
119568b59b9SBrian Somers 	char tbuf[sizeof(_PATH_UUCPLOCK) + MAXNAMLEN];
120568b59b9SBrian Somers 
121568b59b9SBrian Somers 	(void)sprintf(tbuf, _PATH_UUCPLOCK LOCKFMT, ttyname);
122687d0cdeSBrian Somers 	return unlink(tbuf);
123687d0cdeSBrian Somers }
124687d0cdeSBrian Somers 
125687d0cdeSBrian Somers char *uu_lockerr (int uu_lockresult)
126687d0cdeSBrian Somers {
127687d0cdeSBrian Somers 	static char errbuf[512];
128687d0cdeSBrian Somers 	int len;
129687d0cdeSBrian Somers 
130687d0cdeSBrian Somers 	switch (uu_lockresult) {
131687d0cdeSBrian Somers 		case UU_LOCK_INUSE:
132687d0cdeSBrian Somers 			return "";
133687d0cdeSBrian Somers 		case UU_LOCK_OK:
134687d0cdeSBrian Somers 			return 0;
135687d0cdeSBrian Somers 		case UU_LOCK_OPEN_ERR:
136687d0cdeSBrian Somers 			strcpy(errbuf,"open error: ");
137687d0cdeSBrian Somers 			len = 12;
138687d0cdeSBrian Somers 			break;
139687d0cdeSBrian Somers 		case UU_LOCK_READ_ERR:
140687d0cdeSBrian Somers 			strcpy(errbuf,"read error: ");
141687d0cdeSBrian Somers 			len = 12;
142687d0cdeSBrian Somers 			break;
143687d0cdeSBrian Somers 		case UU_LOCK_SEEK_ERR:
144687d0cdeSBrian Somers 			strcpy(errbuf,"seek error: ");
145687d0cdeSBrian Somers 			len = 12;
146687d0cdeSBrian Somers 			break;
147687d0cdeSBrian Somers 		case UU_LOCK_WRITE_ERR:
148687d0cdeSBrian Somers 			strcpy(errbuf,"write error: ");
149687d0cdeSBrian Somers 			len = 13;
150687d0cdeSBrian Somers 			break;
151687d0cdeSBrian Somers 		default:
152687d0cdeSBrian Somers 			strcpy(errbuf,"Undefined error: ");
153687d0cdeSBrian Somers 			len = 17;
154687d0cdeSBrian Somers 			break;
155687d0cdeSBrian Somers 	}
156687d0cdeSBrian Somers 
157687d0cdeSBrian Somers 	strncpy(errbuf+len,strerror(errno),sizeof(errbuf)-len-1);
158687d0cdeSBrian Somers 	return errbuf;
159568b59b9SBrian Somers }
160568b59b9SBrian Somers 
161568b59b9SBrian Somers static int put_pid (int fd, pid_t pid)
162568b59b9SBrian Somers {
163568b59b9SBrian Somers 	char buf[32];
164568b59b9SBrian Somers 	int len;
165568b59b9SBrian Somers 
166568b59b9SBrian Somers 	len = sprintf (buf, "%10d\n", pid);
167568b59b9SBrian Somers 	return write (fd, buf, len) == len;
168568b59b9SBrian Somers }
169568b59b9SBrian Somers 
170687d0cdeSBrian Somers static pid_t get_pid (int fd,int *err)
171568b59b9SBrian Somers {
172568b59b9SBrian Somers 	int bytes_read;
173568b59b9SBrian Somers 	char buf[32];
174568b59b9SBrian Somers 	pid_t pid;
175568b59b9SBrian Somers 
176568b59b9SBrian Somers 	bytes_read = read (fd, buf, sizeof (buf) - 1);
177568b59b9SBrian Somers 	if (bytes_read > 0) {
178568b59b9SBrian Somers 		buf[bytes_read] = '\0';
179568b59b9SBrian Somers 		pid = strtol (buf, (char **) NULL, 10);
180687d0cdeSBrian Somers 	} else {
181568b59b9SBrian Somers 		pid = -1;
182687d0cdeSBrian Somers 		*err = bytes_read ? errno : EINVAL;
183687d0cdeSBrian Somers 	}
184568b59b9SBrian Somers 	return pid;
185568b59b9SBrian Somers }
186568b59b9SBrian Somers 
187568b59b9SBrian Somers /* end of uucplock.c */
188