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
];
109 ret
= snprintf(buf
, sizeof(buf
), "%ld\n", (long)pid
);
110 if (ret
>= (int)sizeof(buf
) || ret
== -1)
111 err(1, "snprintf() failed"); /* Must not happen. */
113 tmpbuf
= strdup(file
);
114 if ((dir
= dirname(tmpbuf
)) == NULL
)
115 err(1, "dirname() failed");
117 ret
= snprintf(tmpf
, sizeof(tmpf
), "%s/shlock%ld", dir
, (long)getpid());
118 if (ret
>= (int)sizeof(tmpf
) || ret
== -1)
119 err(1, "snprintf failed");
123 printf("%s: trying lock file %s for process %ld\n",
124 getprogname(), file
, (long)pid
);
127 while ((fd
= open(tmpf
, O_RDWR
| O_CREAT
| O_EXCL
, 0644)) == -1){
129 err(1, "could not create tempory lock file");
131 warnx("temporary lock file %s existed already", tmpf
);
132 if (unlink(tmpf
) && errno
!= ENOENT
) {
133 err(1, "could not remove old temporary lock file %s",
139 if ((uucpstyle
&& write(fd
, &pid
, sizeof(pid
)) != sizeof(pid
)) ||
140 (!uucpstyle
&& write(fd
, buf
, strlen(buf
)) != (int)strlen(buf
))) {
141 warn("could not write PID to temporary lock file");
145 err(1, "could not remove temporary lock file %s", tmpf
);
152 while (link(tmpf
, file
)) {
153 if (errno
!= EEXIST
) {
156 "could not remove temporary lock file %s",
159 err(1, "could not create lock file");
161 if (check_lock(file
, uucpstyle
, debug
) == 0) {
164 "could not remove temporary lock file %s",
167 return(1); /* Lock file is valid. */
169 if (unlink(file
) == 0) {
170 printf("%s: stale lock file removed\n", getprogname());
174 err(1, "could not remove temporary lock file %s",
177 err(1, "could not remove stale lock file");
181 printf("%s: lock successfully obtained\n", getprogname());
184 warn("could not remove temporary lock file %s", tmpf
);
190 check_lock(const char *file
, int uucpstyle
, int debug
)
197 if ((fd
= open(file
, O_RDONLY
)) == -1) {
200 return(1); /* File doesn't exist. */
203 * Something went wrong, bail out as
204 * if the lock existed.
206 err(1, "could not open lock file");
210 len
= read(fd
, buf
, uucpstyle
? sizeof(pid_t
) : sizeof(buf
));
215 warn("could not read lock file");
220 warnx("found empty lock file");
224 if (len
!= sizeof(pid_t
)) {
226 warnx("invalid lock file format");
229 memcpy(&pid
, buf
, sizeof(pid_t
));
234 if (len
== BUFSIZE
) {
236 warnx("invalid lock file format");
240 buf
[BUFSIZE
- 1] = '\0';
242 tmp_pid
= strtol(buf
, &endptr
, 10);
243 if ((*endptr
!= '\0' && *endptr
!= '\n') || errno
||
244 tmp_pid
< 1 || (pid
= tmp_pid
) != tmp_pid
) {
246 warnx("invalid lock file format");
251 if (kill(pid
, 0) == 0)
252 return(0); /* Process is alive. */
256 return(1); /* Process is dead. */
258 return(0); /* Process is alive. */
260 return(0); /* Something else, assume alive. */
267 fprintf(stderr
, "%s [-u] [-d] [-p pid] -f file\n", getprogname());