s6-instance-status.c (2582B)
1 /* ISC license. */ 2 3 #include <string.h> 4 5 #include <skalibs/bytestr.h> 6 #include <skalibs/strerr.h> 7 #include <skalibs/sgetopt.h> 8 #include <skalibs/exec.h> 9 10 #include <s6/config.h> 11 12 #define USAGE "s6-instance-status [ -uwNrpest | -o up,wantedup,normallyup,ready,paused,pid,exitcode,signal,signum,updownsince,readysince,updownfor,readyfor ] [ -n ] service name" 13 #define dieusage() strerr_dieusage(100, USAGE) 14 15 #define MAXFIELDS 16 16 #define checkfields() if (n++ >= MAXFIELDS) strerr_dief1x(100, "too many option fields") 17 18 static unsigned int check_options (char const *arg, unsigned int n) 19 { 20 static char const *table[] = 21 { 22 "up", 23 "wantedup", 24 "normallyup", 25 "ready", 26 "paused", 27 "pid", 28 "exitcode", 29 "signal", 30 "signum", 31 "updownsince", 32 "readysince", 33 "updownfor", 34 "readyfor", 35 0 36 } ; 37 while (*arg) 38 { 39 size_t pos = str_chr(arg, ',') ; 40 char const *const *p = table ; 41 if (!pos) strerr_dief1x(100, "invalid null option field") ; 42 for (; *p ; p++) if (!strncmp(arg, *p, pos)) break ; 43 if (!p) 44 { 45 char blah[pos+1] ; 46 memcpy(blah, arg, pos) ; 47 blah[pos] = 0 ; 48 strerr_dief2x(100, "invalid option field: ", blah) ; 49 } 50 checkfields() ; 51 arg += pos ; if (*arg) arg++ ; 52 } 53 return n ; 54 } 55 56 int main (int argc, char const **argv) 57 { 58 char const **fullargv = argv ; 59 size_t namelen ; 60 unsigned int n = 0 ; 61 PROG = "s6-instance-status" ; 62 { 63 subgetopt l = SUBGETOPT_ZERO ; 64 for (;;) 65 { 66 int opt = subgetopt_r(argc, argv, "no:uwNrpest", &l) ; 67 if (opt == -1) break ; 68 switch (opt) 69 { 70 case 'n' : break ; 71 case 'o' : n = check_options(l.arg, n) ; break ; 72 case 'u' : 73 case 'w' : 74 case 'N' : 75 case 'r' : 76 case 'p' : 77 case 'e' : 78 case 's' : 79 case 't' : if (n++ >= MAXFIELDS) strerr_dief1x(100, "too many option fields") ; break ; 80 default : dieusage() ; 81 } 82 } 83 argc -= l.ind ; argv += l.ind ; 84 } 85 if (argc < 2) dieusage() ; 86 namelen = strlen(argv[1]) ; 87 if (!argv[0][0]) strerr_dief1x(100, "invalid service name") ; 88 if (!argv[1][0] || argv[1][0] == '.' || byte_in(argv[1], namelen, " \t\f\r\n", 5) < namelen) 89 strerr_dief1x(100, "invalid instance name") ; 90 91 { 92 size_t svlen = strlen(argv[0]) ; 93 char fn[svlen + 11 + namelen] ; 94 memcpy(fn, argv[0], svlen) ; 95 memcpy(fn + svlen, "/instance/", 10) ; 96 memcpy(fn + svlen + 10, argv[1], namelen + 1) ; 97 argv[0] = fn ; 98 argv[1] = 0 ; 99 fullargv[0] = S6_BINPREFIX "s6-svstat" ; 100 xexec(fullargv) ; 101 } 102 }