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