5 * with-lock-ex -<mode> <lockfile> <command> <args>...
6 * with-lock-ex -l <lockfile>
10 * f fail if the lock cannot be acquired
11 * q silently do nothing if the lock cannot be acquired
12 * l show who is waiting (print "none" or "read <pid>"
13 * or "write <pid>"; lockfile opened for reading;
14 * no command may be specified)
16 * with-lock-ex will open and lock the lockfile for writing and
17 * then feed the remainder of its arguments to exec(2); when
18 * that process terminates the fd will be closed and the file
19 * unlocked automatically by the kernel.
21 * If invoked as with-lock, behaves like with-lock-ex -f (for backward
22 * compatibility with an earlier version).
24 * This file written by me, Ian Jackson, in 1993, 1994, 1995, 1996,
25 * 1998, 1999, 2016. I hereby place it in the public domain.
36 static const char *cmd;
38 static void fail(const char *why) __attribute__((noreturn));
40 static void fail(const char *why) {
41 fprintf(stderr,"with-lock-ex %s: %s: %s\n",cmd,why,strerror(errno));
45 int main(int argc, char **argv) {
47 struct stat stab, fstab;
52 if (argc >= 3 && !strcmp((p= strrchr(argv[0],'/')) ? ++p : argv[0], "with-lock")) {
54 } else if (argc < 3 || argv[1][0] != '-' || argv[1][2] ||
55 ((mode= argv[1][1]) != 'w' && mode != 'q' && mode != 'f'
57 (mode != 'l' && argc < 4) ||
58 (mode == 'l' && argc != 3)) {
59 fputs("usage: with-lock-ex -w|-q|-f <lockfile> <command> <args>...\n"
60 " with-lock-ex -l <lockfile>\n"
61 " with-lock <lockfile> <command> <args>...\n",
68 um= umask(0777); if (um==-1) fail("find umask");
69 if (umask(um)==-1) fail("reset umask");
73 int openmode = mode=='l' ? O_RDONLY : O_RDWR|O_CREAT;
75 fd= open(argv[1],openmode,0666&~(um|((um&0222)<<1)));
76 if (fd<0) fail(argv[1]);
80 fl.l_whence= SEEK_SET;
82 fl.l_len= mode=='l' ? 0 : 1;
85 mode=='w' ? F_SETLKW :
89 (errno == EAGAIN || errno == EWOULDBLOCK || errno == EBUSY))
91 if (errno != EINTR) fail("could not acquire lock");
96 fl.l_type == F_WRLCK ? "write" :
97 fl.l_type == F_RDLCK ? "read" : "unknown",
98 (unsigned long)fl.l_pid);
102 if (ferror(stdout)) fail("print to stdout\n");
106 if (fstat(fd, &fstab)) fail("could not fstat lock fd");
107 if (stat(argv[1], &stab)) {
108 if (errno != ENOENT) fail("could not stat lockfile");
110 if (stab.st_dev == fstab.st_dev &&
111 stab.st_ino == fstab.st_ino) break;
116 cloexec= fcntl(fd, F_GETFD); if (cloexec==-1) fail("fcntl F_GETFD");
118 if (fcntl(fd, F_SETFD, cloexec)==-1) fail("fcntl F_SETFD");
121 fail("unable to execute command");