s6-setlock.c (2363B)
1 /* ISC license. */ 2 3 #include <unistd.h> 4 #include <errno.h> 5 #include <signal.h> 6 7 #include <skalibs/sgetopt.h> 8 #include <skalibs/strerr.h> 9 #include <skalibs/types.h> 10 #include <skalibs/tai.h> 11 #include <skalibs/sig.h> 12 #include <skalibs/alarm.h> 13 #include <skalibs/djbunix.h> 14 #include <skalibs/exec.h> 15 16 #include <s6/config.h> 17 18 #define USAGE "s6-setlock [ -r | -w ] [ -n | -N ] [ -t timeout ] [ -d fd ] lockfile prog..." 19 #define dieusage() strerr_dieusage(100, USAGE) 20 21 static char const *file ; 22 23 static void sigalrm_handler (int sig) 24 { 25 (void)sig ; 26 strerr_dief3x(1, "lock ", file, ": timed out") ; 27 } 28 29 int main (int argc, char const *const *argv) 30 { 31 unsigned int nb = 0, ex = 1 ; 32 unsigned int timeout = 0 ; 33 int dest = -1 ; 34 int fd ; 35 int r ; 36 PROG = "s6-setlock" ; 37 38 for (;;) 39 { 40 int opt = lgetopt(argc, argv, "nNrwt:d:") ; 41 if (opt == -1) break ; 42 switch (opt) 43 { 44 case 'n' : nb = 1 ; break ; 45 case 'N' : nb = 0 ; break ; 46 case 'r' : ex = 0 ; break ; 47 case 'w' : ex = 1 ; break ; 48 case 't' : if (!uint0_scan(subgetopt_here.arg, &timeout)) dieusage() ; break ; 49 case 'd' : { unsigned int u ; if (!uint0_scan(subgetopt_here.arg, &u)) dieusage() ; dest = u ; break ; } 50 default : dieusage() ; 51 } 52 } 53 argc -= subgetopt_here.ind ; argv += subgetopt_here.ind ; 54 if (argc < 2) dieusage() ; 55 file = argv[0] ; 56 57 if (ex) 58 { 59 fd = open_create(file) ; 60 if (fd == -1) strerr_diefu3sys(111, "open ", file, " for writing") ; 61 } 62 else 63 { 64 fd = open_read(file) ; 65 if (fd == -1) 66 { 67 if (errno != ENOENT) strerr_diefu3sys(111, "open ", file, " for reading") ; 68 fd = open_create(file) ; 69 if (fd == -1) strerr_diefu2sys(111, "create ", file) ; 70 fd_close(fd) ; 71 fd = open_read(file) ; 72 if (fd == -1) strerr_diefu3sys(111, "open ", file, " for reading") ; 73 } 74 } 75 76 if (timeout) 77 { 78 tain tto ; 79 tain_from_millisecs(&tto, timeout) ; 80 if (!sig_catch(SIGALRM, &sigalrm_handler)) 81 strerr_diefu1sys(111, "set SIGALRM handler") ; 82 if (!alarm_timeout(&tto)) 83 strerr_diefu1sys(111, "set timer") ; 84 } 85 r = fd_lock(fd, ex, nb) ; 86 if (timeout) alarm_disable() ; 87 88 if (!r) errno = EBUSY ; 89 if (r < 1) strerr_diefu2sys(1, "lock ", file) ; 90 91 if (dest >= 0 && fd_move(dest, fd) == -1) 92 strerr_diefu1sys(111, "move lock descriptor") ; 93 xexec(argv+1) ; 94 }