2 * Copyright (c) 2005 The DragonFly Project. All rights reserved.
4 * This code is derived from software contributed to The DragonFly Project
5 * by Joerg Sonnenberger <joerg@bec.de>.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
17 * 3. Neither the name of The DragonFly Project nor the names of its
18 * contributors may be used to endorse or promote products derived
19 * from this software without specific, prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
29 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
31 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * $DragonFly: src/usr.bin/shlock/shlock.c,v 1.1 2005/07/23 19:47:15 joerg Exp $
37 #include <sys/types.h>
51 static int create_lock(const char *, pid_t
, int, int);
52 static int check_lock(const char *, int, int);
53 static void usage(void);
56 main(int argc
, char **argv
)
58 int ch
, debug
= 0, uucpstyle
= 0;
59 const char *file
= NULL
;
64 while ((ch
= getopt(argc
, argv
, "df:p:u")) != -1) {
74 tmp_pid
= strtol(optarg
, &endptr
, 10);
75 if (*endptr
!= '\0' || errno
||
76 tmp_pid
< 1 || (pid
= tmp_pid
) != tmp_pid
)
77 errx(1, "invalid pid specified");
96 return(create_lock(file
, pid
, uucpstyle
, debug
));
98 return(check_lock(file
, uucpstyle
, debug
));
102 create_lock(const char *file
, pid_t pid
, int uucpstyle
, int debug
)
104 char buf
[BUFSIZE
], tmpf
[PATH_MAX
];
108 ret
= snprintf(buf
, sizeof(buf
), "%ld\n", (long)pid
);
109 if (ret
>= (int)sizeof(buf
) || ret
== -1)
110 err(1, "snprintf() failed"); /* Must not happen. */
112 if ((dir
= dirname(file
)) == NULL
)
113 err(1, "dirname() failed");
115 ret
= snprintf(tmpf
, sizeof(tmpf
), "%s/shlock%ld", dir
, (long)getpid());
116 if (ret
>= (int)sizeof(tmpf
) || ret
== -1)
117 err(1, "snprintf failed");
120 printf("%s: trying lock file %s for process %ld\n",
121 getprogname(), file
, (long)pid
);
124 while ((fd
= open(tmpf
, O_RDWR
| O_CREAT
| O_EXCL
, 0644)) == -1){
126 err(1, "could not create tempory lock file");
128 warnx("temporary lock file %s existed already", tmpf
);
129 if (unlink(tmpf
) && errno
!= ENOENT
) {
130 err(1, "could not remove old temporary lock file %s",
136 if ((uucpstyle
&& write(fd
, &pid
, sizeof(pid
)) != sizeof(pid
)) ||
137 (!uucpstyle
&& write(fd
, buf
, strlen(buf
)) != (int)strlen(buf
))) {
138 warn("could not write PID to temporary lock file");
142 err(1, "could not remove temporary lock file %s", tmpf
);
149 while (link(tmpf
, file
)) {
150 if (errno
!= EEXIST
) {
153 "could not remove temporary lock file %s",
156 err(1, "could not create lock file");
158 if (check_lock(file
, uucpstyle
, debug
) == 0) {
161 "could not remove temporary lock file %s",
164 return(1); /* Lock file is valid. */
166 if (unlink(file
) == 0) {
167 printf("%s: stale lock file removed\n", getprogname());
171 err(1, "could not remove temporary lock file %s",
174 err(1, "could not remove stale lock file");
178 printf("%s: lock successfully obtained\n", getprogname());
181 warn("could not remove temporary lock file %s", tmpf
);
187 check_lock(const char *file
, int uucpstyle
, int debug
)
194 if ((fd
= open(file
, O_RDONLY
)) == -1) {
197 return(1); /* File doesn't exist. */
200 * Something went wrong, bail out as
201 * if the lock existed.
203 err(1, "could not open lock file");
207 len
= read(fd
, buf
, uucpstyle
? sizeof(pid_t
) : sizeof(buf
));
212 warn("could not read lock file");
217 warnx("found empty lock file");
221 if (len
!= sizeof(pid_t
)) {
223 warnx("invalid lock file format");
226 memcpy(&pid
, buf
, sizeof(pid_t
));
231 if (len
== BUFSIZE
) {
233 warnx("invalid lock file format");
237 buf
[BUFSIZE
- 1] = '\0';
239 tmp_pid
= strtol(buf
, &endptr
, 10);
240 if ((*endptr
!= '\0' && *endptr
!= '\n') || errno
||
241 tmp_pid
< 1 || (pid
= tmp_pid
) != tmp_pid
) {
243 warnx("invalid lock file format");
248 if (kill(pid
, 0) == 0)
249 return(0); /* Process is alive. */
253 return(1); /* Process is dead. */
255 return(0); /* Process is alive. */
257 return(0); /* Something else, assume alive. */
264 fprintf(stderr
, "%s [-u] [-d] [-p pid] -f file\n", getprogname());