uucplock.c (e1a10354cb2bb904da90e90b88ba6ab4a2c1ea9f) uucplock.c (84dc22996da39f0d729487f9223011ec189d020f)
1/*
2 * Copyright (c) 1988, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

--- 16 unchanged lines hidden (view full) ---

25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 *
1/*
2 * Copyright (c) 1988, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

--- 16 unchanged lines hidden (view full) ---

25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 *
33 * $Id: uucplock.c,v 1.6 1997/05/12 10:36:14 brian Exp $
33 * $Id: uucplock.c,v 1.7 1997/08/05 12:58:02 ache Exp $
34 *
35 */
36
37#ifndef lint
38static const char sccsid[] = "@(#)uucplock.c 8.1 (Berkeley) 6/6/93";
39#endif /* not lint */
40
41#include <sys/types.h>
42#include <sys/file.h>
43#include <dirent.h>
44#include <errno.h>
45#include <unistd.h>
46#include <signal.h>
47#include <stdio.h>
48#include <stdlib.h>
49#include <paths.h>
50#include <string.h>
51#include "libutil.h"
52
34 *
35 */
36
37#ifndef lint
38static const char sccsid[] = "@(#)uucplock.c 8.1 (Berkeley) 6/6/93";
39#endif /* not lint */
40
41#include <sys/types.h>
42#include <sys/file.h>
43#include <dirent.h>
44#include <errno.h>
45#include <unistd.h>
46#include <signal.h>
47#include <stdio.h>
48#include <stdlib.h>
49#include <paths.h>
50#include <string.h>
51#include "libutil.h"
52
53#define MAXTRIES 5
54
55#define LOCKTMP "LCKTMP..%d"
53#define LOCKFMT "LCK..%s"
54
56#define LOCKFMT "LCK..%s"
57
58#define GORET(level, val) { err = errno; uuerr = (val); \
59 goto __CONCAT(ret, level); }
60
55/* Forward declarations */
56static int put_pid (int fd, pid_t pid);
57static pid_t get_pid (int fd,int *err);
58
59/*
60 * uucp style locking routines
61/* Forward declarations */
62static int put_pid (int fd, pid_t pid);
63static pid_t get_pid (int fd,int *err);
64
65/*
66 * uucp style locking routines
61 * return: 0 - success
62 * -1 - failure
63 */
64
65int uu_lock (const char *ttyname)
66{
67 */
68
69int uu_lock (const char *ttyname)
70{
67 int fd;
71 int fd, tmpfd, i;
68 pid_t pid;
72 pid_t pid;
69 char tbuf[sizeof(_PATH_UUCPLOCK) + MAXNAMLEN];
70 int err;
73 char lckname[sizeof(_PATH_UUCPLOCK) + MAXNAMLEN],
74 lcktmpname[sizeof(_PATH_UUCPLOCK) + MAXNAMLEN];
75 int err, uuerr;
71
76
72 (void)snprintf(tbuf, sizeof(tbuf), _PATH_UUCPLOCK LOCKFMT, ttyname);
73 fd = open(tbuf, O_RDWR|O_CREAT|O_EXCL|O_EXLOCK, 0660);
74 if (fd < 0) {
75 /*
76 * file is already locked
77 * check to see if the process holding the lock still exists
78 */
79 fd = open(tbuf, O_RDWR|O_SHLOCK);
80 if (fd < 0)
81 return UU_LOCK_OPEN_ERR;
77 pid = getpid();
78 (void)snprintf(lcktmpname, sizeof(lcktmpname), _PATH_UUCPLOCK LOCKTMP,
79 pid);
80 (void)snprintf(lckname, sizeof(lckname), _PATH_UUCPLOCK LOCKFMT,
81 ttyname);
82 if ((tmpfd = creat(lcktmpname, 0664)) < 0)
83 GORET(0, UU_LOCK_CREAT_ERR);
82
84
83 if ((pid = get_pid (fd, &err)) == -1) {
84 (void)close(fd);
85 errno = err;
86 return UU_LOCK_READ_ERR;
87 }
85 for (i = 0; i < MAXTRIES; i++) {
86 if (link (lcktmpname, lckname) < 0) {
87 if (errno != EEXIST)
88 GORET(1, UU_LOCK_LINK_ERR);
89 /*
90 * file is already locked
91 * check to see if the process holding the lock
92 * still exists
93 */
94 if ((fd = open(lckname, O_RDONLY)) < 0)
95 GORET(1, UU_LOCK_OPEN_ERR);
88
96
89 if (kill(pid, 0) == 0 || errno != ESRCH) {
90 (void)close(fd); /* process is still running */
91 return UU_LOCK_INUSE;
97 if ((pid = get_pid (fd, &err)) == -1)
98 GORET(2, UU_LOCK_READ_ERR);
99
100 close(fd);
101
102 if (kill(pid, 0) == 0 || errno != ESRCH)
103 GORET(1, UU_LOCK_INUSE);
104 /*
105 * The process that locked the file isn't running, so
106 * we'll lock it ourselves
107 */
108 (void)unlink(lckname);
109 } else {
110 if (!put_pid (tmpfd, pid))
111 GORET(3, UU_LOCK_WRITE_ERR);
112 break;
92 }
113 }
93 /*
94 * The process that locked the file isn't running, so
95 * we'll lock it ourselves
96 */
97 if (lseek(fd, (off_t) 0, L_SET) < 0) {
98 err = errno;
99 (void)close(fd);
100 errno = err;
101 return UU_LOCK_SEEK_ERR;
102 }
103 if (flock(fd, LOCK_EX|LOCK_NB) < 0) {
104 (void)close(fd);
105 return UU_LOCK_INUSE;
106 }
107 /* fall out and finish the locking process */
108 }
114 }
109 pid = getpid();
110 if (!put_pid (fd, pid)) {
111 err = errno;
112 (void)unlink(tbuf);
113 (void)close(fd);
114 errno = err;
115 return UU_LOCK_WRITE_ERR;
116 }
115 GORET(1, (i >= MAXTRIES) ? UU_LOCK_TRY_ERR : UU_LOCK_OK);
116
117ret3:
118 (void)unlink(lckname);
119 goto ret1;
120ret2:
117 (void)close(fd);
121 (void)close(fd);
118 return UU_LOCK_OK;
122ret1:
123 (void)close(tmpfd);
124 (void)unlink(lcktmpname);
125ret0:
126 errno = err;
127 return uuerr;
119}
120
121int uu_unlock (const char *ttyname)
122{
123 char tbuf[sizeof(_PATH_UUCPLOCK) + MAXNAMLEN];
124
125 (void)snprintf(tbuf, sizeof(tbuf), _PATH_UUCPLOCK LOCKFMT, ttyname);
126 return unlink(tbuf);

--- 10 unchanged lines hidden (view full) ---

137 case UU_LOCK_OK:
138 return "";
139 case UU_LOCK_OPEN_ERR:
140 fmt = "open error: %s";
141 break;
142 case UU_LOCK_READ_ERR:
143 fmt = "read error: %s";
144 break;
128}
129
130int uu_unlock (const char *ttyname)
131{
132 char tbuf[sizeof(_PATH_UUCPLOCK) + MAXNAMLEN];
133
134 (void)snprintf(tbuf, sizeof(tbuf), _PATH_UUCPLOCK LOCKFMT, ttyname);
135 return unlink(tbuf);

--- 10 unchanged lines hidden (view full) ---

146 case UU_LOCK_OK:
147 return "";
148 case UU_LOCK_OPEN_ERR:
149 fmt = "open error: %s";
150 break;
151 case UU_LOCK_READ_ERR:
152 fmt = "read error: %s";
153 break;
145 case UU_LOCK_SEEK_ERR:
146 fmt = "seek error: %s";
154 case UU_LOCK_CREAT_ERR:
155 fmt = "creat error: %s";
147 break;
148 case UU_LOCK_WRITE_ERR:
149 fmt = "write error: %s";
150 break;
156 break;
157 case UU_LOCK_WRITE_ERR:
158 fmt = "write error: %s";
159 break;
160 case UU_LOCK_LINK_ERR:
161 fmt = "link error: %s";
162 break;
163 case UU_LOCK_TRY_ERR:
164 fmt = "too many tries: %s";
165 break;
151 default:
152 fmt = "undefined error: %s";
153 break;
154 }
155
156 (void)snprintf(errbuf, sizeof(errbuf), fmt, strerror(errno));
157 return errbuf;
158}
159
160static int put_pid (int fd, pid_t pid)
161{
162 char buf[32];
163 int len;
164
165 len = sprintf (buf, "%10d\n", pid);
166 return write (fd, buf, len) == len;
167}
168
166 default:
167 fmt = "undefined error: %s";
168 break;
169 }
170
171 (void)snprintf(errbuf, sizeof(errbuf), fmt, strerror(errno));
172 return errbuf;
173}
174
175static int put_pid (int fd, pid_t pid)
176{
177 char buf[32];
178 int len;
179
180 len = sprintf (buf, "%10d\n", pid);
181 return write (fd, buf, len) == len;
182}
183
169static pid_t get_pid (int fd,int *err)
184static pid_t get_pid (int fd, int *err)
170{
171 int bytes_read;
172 char buf[32];
173 pid_t pid;
174
175 bytes_read = read (fd, buf, sizeof (buf) - 1);
176 if (bytes_read > 0) {
177 buf[bytes_read] = '\0';
178 pid = strtol (buf, (char **) NULL, 10);
179 } else {
180 pid = -1;
181 *err = bytes_read ? errno : EINVAL;
182 }
183 return pid;
184}
185
186/* end of uucplock.c */
185{
186 int bytes_read;
187 char buf[32];
188 pid_t pid;
189
190 bytes_read = read (fd, buf, sizeof (buf) - 1);
191 if (bytes_read > 0) {
192 buf[bytes_read] = '\0';
193 pid = strtol (buf, (char **) NULL, 10);
194 } else {
195 pid = -1;
196 *err = bytes_read ? errno : EINVAL;
197 }
198 return pid;
199}
200
201/* end of uucplock.c */