/* ISC license. */ #include #include #include #include #include #include #include #include #include #include #define USAGE "s6-svc [ -wu | -wU | -wd | -wD | -wr | -wR ] [ -T timeout ] [ -abqhkti12pcyroduDUxOX ] servicedir" #define dieusage() strerr_dieusage(100, USAGE) #define DATASIZE 63 int main (int argc, char const *const *argv) { size_t len ; int downfile = -1 ; unsigned int datalen = 1 ; unsigned int timeout = 0 ; char data[DATASIZE+1] = "-" ; char updown[3] = "-\0" ; PROG = "s6-svc" ; { subgetopt l = SUBGETOPT_ZERO ; for (;;) { int opt = subgetopt_r(argc, argv, "abqhkti12pcyroduDUxOT:w:", &l) ; if (opt == -1) break ; switch (opt) { case 'a' : case 'b' : case 'q' : case 'h' : case 'k' : case 't' : case 'i' : case '1' : case '2' : case 'p' : case 'c' : case 'y' : case 'r' : case 'o' : case 'd' : case 'u' : case 'x' : case 'O' : { if (datalen >= DATASIZE) strerr_dief1x(100, "too many commands") ; data[datalen++] = opt ; break ; } case 'D' : { if (datalen >= DATASIZE) strerr_dief1x(100, "too many commands") ; data[datalen++] = 'd' ; downfile = 1 ; break ; } case 'U' : { if (datalen >= DATASIZE) strerr_dief1x(100, "too many commands") ; data[datalen++] = 'u' ; downfile = 0 ; break ; } case 'T' : if (!uint0_scan(l.arg, &timeout)) dieusage() ; break ; case 'w' : { if (!memchr("dDuUrR", l.arg[0], 6)) dieusage() ; updown[1] = l.arg[0] ; break ; } default : dieusage() ; } } argc -= l.ind ; argv += l.ind ; } if (!argc) dieusage() ; if (argc > 1) strerr_warnw1x("ignoring extra arguments") ; len = strlen(argv[0]) ; if (!len) strerr_dief1x(100, "invalid service path") ; if (updown[1] == 'U' || updown[1] == 'R') { char fn[len + 17] ; memcpy(fn, argv[0], len) ; memcpy(fn + len, "/notification-fd", 17) ; if (access(fn, F_OK) < 0) { if (errno != ENOENT) strerr_diefu2sys(111, "access ", fn) ; updown[1] = updown[1] == 'U' ? 'u' : 'r' ; strerr_warnw2x(fn, " not present - ignoring request for readiness notification") ; } } if (downfile >= 0) { char fn[len + 6] ; memcpy(fn, argv[0], len) ; memcpy(fn + len, "/down", 6) ; if (downfile) { if (!openwritenclose_unsafe(fn, "", 0)) strerr_diefu2sys(111, "touch ", fn) ; } else unlink_void(fn) ; } if (updown[1]) { char const *newargv[11] ; unsigned int m = 0 ; char fmt[UINT_FMT] ; newargv[m++] = datalen > 1 ? S6_BINPREFIX "s6-svlisten1" : S6_BINPREFIX "s6-svwait" ; newargv[m++] = updown ; if (timeout) { fmt[uint_fmt(fmt, timeout)] = 0 ; newargv[m++] = "-t" ; newargv[m++] = fmt ; } newargv[m++] = "--" ; newargv[m++] = argv[0] ; if (datalen > 1) { newargv[m++] = S6_BINPREFIX "s6-svc" ; newargv[m++] = data ; newargv[m++] = "--" ; newargv[m++] = argv[0] ; } newargv[m++] = 0 ; xexec(newargv) ; } else switch (s6_svc_writectl(argv[0], S6_SUPERVISE_CTLDIR, data + 1, datalen - 1)) { case -1 : strerr_diefu2sys(111, "control ", argv[0]) ; case -2 : strerr_dief3sys(100, "something is wrong with the ", argv[0], "/" S6_SUPERVISE_CTLDIR " directory") ; case 0 : strerr_diefu3x(100, "control ", argv[0], ": supervisor not listening") ; } return 0 ; }