flock.c - sbase - suckless unix tools
(HTM) git clone git://git.suckless.org/sbase
(DIR) Log
(DIR) Files
(DIR) Refs
(DIR) README
(DIR) LICENSE
---
flock.c (1358B)
---
1 /* See LICENSE file for copyright and license details. */
2 #include <sys/file.h>
3 #include <sys/wait.h>
4
5 #include <errno.h>
6 #include <fcntl.h>
7 #include <stdio.h>
8 #include <unistd.h>
9
10 #include "util.h"
11
12 static void
13 usage(void)
14 {
15 eprintf("usage: %s [-nosux] file cmd [arg ...]\n", argv0);
16 }
17
18 int
19 main(int argc, char *argv[])
20 {
21 int fd, status, savederrno, flags = LOCK_EX, nonblk = 0, oflag = 0;
22 pid_t pid;
23
24 ARGBEGIN {
25 case 'n':
26 nonblk = LOCK_NB;
27 break;
28 case 'o':
29 oflag = 1;
30 break;
31 case 's':
32 flags = LOCK_SH;
33 break;
34 case 'u':
35 flags = LOCK_UN;
36 break;
37 case 'x':
38 flags = LOCK_EX;
39 break;
40 default:
41 usage();
42 } ARGEND
43
44 if (argc < 2)
45 usage();
46
47 if ((fd = open(*argv, O_RDONLY | O_CREAT, 0644)) < 0)
48 eprintf("open %s:", *argv);
49
50 if (flock(fd, flags | nonblk)) {
51 if (nonblk && errno == EWOULDBLOCK)
52 return 1;
53 eprintf("flock:");
54 }
55
56 switch ((pid = fork())) {
57 case -1:
58 eprintf("fork:");
59 case 0:
60 if (oflag && close(fd) < 0)
61 eprintf("close:");
62 argv++;
63 execvp(*argv, argv);
64 savederrno = errno;
65 weprintf("execvp %s:", *argv);
66 _exit(126 + (savederrno == ENOENT));
67 default:
68 break;
69 }
70 if (waitpid(pid, &status, 0) < 0)
71 eprintf("waitpid:");
72
73 if (close(fd) < 0)
74 eprintf("close:");
75
76 if (WIFSIGNALED(status))
77 return 128 + WTERMSIG(status);
78 if (WIFEXITED(status))
79 return WEXITSTATUS(status);
80
81 return 0;
82 }