1/* See LICENSE file for copyright and license details. */
2
3
4#include <sys/file.h>
5#include <sys/wait.h>
6
7#include <errno.h>
8#include <fcntl.h>
9#include <stdio.h>
10#include <unistd.h>
11
12#include "util.h"
13
14static void
15usage(void)
16{
17 eprintf("usage: %s [-nosux] file cmd [arg ...]\n", argv0);
18}
19
20// ?man flock: manage locks
21// ?man arguments: file cmd [arg ...
22// ?man acquire or release locks from shell scripts
23int
24main(int argc, char *argv[])
25{
26 int fd, status, savederrno, flags = LOCK_EX, nonblk = 0, oflag = 0;
27 pid_t pid;
28
29 ARGBEGIN {
30 // ?man -n: print line numbers or counts
31 case 'n':
32 nonblk = LOCK_NB;
33 break;
34 // ?man -o: specify output file
35 case 'o':
36 oflag = 1;
37 break;
38 // ?man -s: silent mode or print summary
39 case 's':
40 flags = LOCK_SH;
41 break;
42 // ?man -u: unbuffered output
43 case 'u':
44 flags = LOCK_UN;
45 break;
46 // ?man -x: hex format or match whole lines
47 case 'x':
48 flags = LOCK_EX;
49 break;
50 default:
51 usage();
52 } ARGEND
53
54 if (argc < 2)
55 usage();
56
57 if ((fd = open(*argv, O_RDONLY | O_CREAT, 0644)) < 0)
58 eprintf("open %s:", *argv);
59
60 if (flock(fd, flags | nonblk)) {
61 if (nonblk && errno == EWOULDBLOCK)
62 return 1;
63 eprintf("flock:");
64 }
65
66 switch ((pid = fork())) {
67 case -1:
68 eprintf("fork:");
69 /* fallthrough */
70 case 0:
71 if (oflag && close(fd) < 0)
72 eprintf("close:");
73 argv++;
74 execvp(*argv, argv);
75 savederrno = errno;
76 weprintf("execvp %s:", *argv);
77 _exit(126 + (savederrno == ENOENT));
78 default:
79 break;
80 }
81 if (waitpid(pid, &status, 0) < 0)
82 eprintf("waitpid:");
83
84 if (close(fd) < 0)
85 eprintf("close:");
86
87 if (WIFSIGNALED(status))
88 return 128 + WTERMSIG(status);
89 if (WIFEXITED(status))
90 return WEXITSTATUS(status);
91
92 return 0;
93}