1 /* $Id: shlock.c 6124 2003-01-14 06:03:29Z rra $
3 ** Produce reliable locks for shell scripts, by Peter Honeyman as told
14 #include "inn/messages.h"
17 static bool BinaryLock;
21 ** See if the process named in an existing lock still exists by
22 ** sending it a null signal.
25 ValidLock(char *name, bool JustChecking)
33 if ((fd = open(name, O_RDONLY)) < 0) {
36 syswarn("cannot open %s", name);
40 /* Read the PID that is written there. */
42 if (read(fd, (char *)&pid, sizeof pid) != sizeof pid) {
48 if ((i = read(fd, buff, sizeof buff - 1)) <= 0) {
53 pid = (pid_t) atol(buff);
59 /* Send the signal. */
60 if (kill(pid, 0) < 0 && errno == ESRCH)
63 /* Either the kill worked, or we're optimistic about the error code. */
69 ** Unlink a file, print a message on error, and exit.
72 UnlinkAndExit(char *name, int x)
75 syswarn("cannot unlink %s", name);
81 ** Print a usage message and exit.
86 fprintf(stderr, "Usage: shlock [-u|-b] -f file -p pid\n");
92 main(int ac, char *av[])
104 /* Establish our identity. */
105 message_program_name = "shlock";
110 JustChecking = false;
114 while ((i = getopt(ac, av, "bcup:f:")) != EOF)
127 pid = (pid_t) atol(optarg);
135 if (ac || pid == 0 || name == NULL)
138 /* Create the temp file in the same directory as the destination. */
139 if ((p = strrchr(name, '/')) != NULL) {
141 snprintf(tmp, sizeof(tmp), "%s/shlock%ld", name, (long)getpid());
145 snprintf(tmp, sizeof(tmp), "shlock%ld", (long)getpid());
147 /* Loop until we can open the file. */
148 while ((fd = open(tmp, O_RDWR | O_CREAT | O_EXCL, 0644)) < 0)
151 /* Unknown error -- give up. */
152 sysdie("cannot open %s", tmp);
154 /* If we can remove the old temporary, retry the open. */
156 sysdie("cannot unlink %s", tmp);
160 /* Write the process ID. */
162 ok = write(fd, &pid, sizeof pid) == sizeof pid;
164 snprintf(buff, sizeof(buff), "%ld\n", (long) pid);
166 ok = write(fd, buff, i) == i;
169 syswarn("cannot write PID to %s", tmp);
171 UnlinkAndExit(tmp, 1);
176 /* Handle the "-c" flag. */
178 if (ValidLock(name, true))
179 UnlinkAndExit(tmp, 1);
180 UnlinkAndExit(tmp, 0);
183 /* Try to link the temporary to the lockfile. */
184 while (link(tmp, name) < 0)
187 /* Unknown error -- give up. */
188 syswarn("cannot link %s to %s", tmp, name);
189 UnlinkAndExit(tmp, 1);
192 /* File exists; if lock is valid, give up. */
193 if (ValidLock(name, false))
194 UnlinkAndExit(tmp, 1);
195 if (unlink(name) < 0) {
196 syswarn("cannot unlink %s", name);
197 UnlinkAndExit(tmp, 1);
201 UnlinkAndExit(tmp, 0);