1/* See LICENSE file for copyright and license details. */
2
3#include <sys/file.h>
4#include <sys/wait.h>
5
6#include <errno.h>
7#include <fcntl.h>
8#include <stdio.h>
9#include <unistd.h>
10
11#include "util.h"
12#include "wexec.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 {
31 // ?man -n: print line numbers or counts
32 case 'n':
33 nonblk = LOCK_NB;
34 break;
35 // ?man -o: specify output file
36 case 'o':
37 oflag = 1;
38 break;
39 // ?man -s: silent mode or print summary
40 case 's':
41 flags = LOCK_SH;
42 break;
43 // ?man -u: unbuffered output
44 case 'u':
45 flags = LOCK_UN;
46 break;
47 // ?man -x: hex format or match whole lines
48 case 'x':
49 flags = LOCK_EX;
50 break;
51 default:
52 usage();
53 }
54 ARGEND
55
56 if (argc < 2)
57 usage();
58
59 if ((fd = open(*argv, O_RDONLY | O_CREAT, 0644)) < 0)
60 eprintf("open %s:", *argv);
61
62 if (flock(fd, flags | nonblk)) {
63 if (nonblk && errno == EWOULDBLOCK)
64 return 1;
65 eprintf("flock:");
66 }
67
68 switch ((pid = fork())) {
69 case -1:
70 eprintf("fork:");
71 /* fallthrough */
72 case 0:
73 if (oflag && close(fd) < 0)
74 eprintf("close:");
75 argv++;
76 wexecvp_self(*argv, argv);
77 savederrno = errno;
78 weprintf("wexecvp %s:", *argv);
79 _exit(126 + (savederrno == ENOENT));
80 default:
81 break;
82 }
83 if (waitpid(pid, &status, 0) < 0)
84 eprintf("waitpid:");
85
86 if (close(fd) < 0)
87 eprintf("close:");
88
89 if (WIFSIGNALED(status))
90 return 128 + WTERMSIG(status);
91 if (WIFEXITED(status))
92 return WEXITSTATUS(status);
93
94 return 0;
95}