master xplshn/aruu / cmd / pseudo / flock.c
 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}