fiss

Friedel's Initialization and Service Supervision
Log | Files | Refs | LICENSE

commit fdade2facf5fd2164bca13d324c68468c8abbfdc
parent 7193253d7ce1d7e63dfcf032801f1dcd59471181
Author: Friedel Schön <[email protected]>
Date:   Fri, 26 May 2023 12:47:41 +0200

adding 'enable' to fsvc

Diffstat:
Msrc/exec/fsvc.c | 122++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------------------
Msrc/register.c | 34++++++++++++++++++++--------------
2 files changed, 110 insertions(+), 46 deletions(-)

diff --git a/src/exec/fsvc.c b/src/exec/fsvc.c @@ -6,6 +6,7 @@ #include <fcntl.h> #include <getopt.h> +#include <limits.h> #include <stdbool.h> #include <string.h> #include <sys/stat.h> @@ -15,33 +16,39 @@ struct ident { const char* name; const char* command; + bool runit; }; static struct ident command_names[] = { - { "up", "u" }, // starts the services, pin as started - { "down", "d" }, // stops the service, pin as stopped - { "xup", "U" }, // stops the service, don't pin as stopped - { "xdown", "D" }, // stops the service, don't pin as stopped - { "once", "o" }, // same as xup - { "term", "t" }, // same as down - { "kill", "k" }, // sends kill, pin as stopped - { "pause", "p" }, // pauses the service - { "cont", "c" }, // resumes the service - { "reset", "r" }, // resets the service - { "alarm", "a" }, // sends alarm - { "hup", "h" }, // sends hup - { "int", "i" }, // sends interrupt - { "quit", "q" }, // sends quit - { "1", "1" }, // sends usr1 - { "2", "2" }, // sends usr2 - { "exit", "x" }, // does nothing - { "+up", "U0" }, // starts the service, don't modify pin - { "+down", "D0" }, // stops the service, don't modify pin - { "restart", "!D0U0" }, // restarts the service, don't modify pin - { "start", "!u" }, // start the service, pin as started, print status - { "stop", "!d" }, // stop the service, pin as stopped, print status - { "status", "!" }, // print status - { 0, 0 } + { "up", "u", true }, // starts the services, pin as started + { "down", "d", true }, // stops the service, pin as stopped + { "xup", "U", true }, // stops the service, don't pin as stopped + { "xdown", "D", true }, // stops the service, don't pin as stopped + { "once", "o", true }, // same as xup + { "term", "t", true }, // same as down + { "kill", "k", true }, // sends kill, pin as stopped + { "pause", "p", true }, // pauses the service + { "cont", "c", true }, // resumes the service + { "reset", "r", true }, // resets the service + { "alarm", "a", true }, // sends alarm + { "hup", "h", true }, // sends hup + { "int", "i", true }, // sends interrupt + { "quit", "q", true }, // sends quit + { "1", "1", true }, // sends usr1 + { "2", "2", true }, // sends usr2 + { "exit", "x", true }, // does nothing + { "+up", "U0", false }, // starts the service, don't modify pin + { "+down", "D0", false }, // stops the service, don't modify pin + { "restart", "!D0U0", false }, // restarts the service, don't modify pin + { "start", "!u", true }, // start the service, pin as started, print status + { "stop", "!d", true }, // stop the service, pin as stopped, print status + { "status", "!", true }, // print status + { "check", "!", true }, // print status + { "enable", "!.e", false }, // enable service + { "disable", "!.d", false }, // disable service + { "enable-once", "!.e", false }, // enable service once + { "disable-once", "!.d", false }, // disable service once + { 0, 0, 0 } }; static const struct option long_options[] = { @@ -50,12 +57,24 @@ static const struct option long_options[] = { { 0 } }; -static int check_service(int dir) { - int fd; +static int check_service(int dir, char* runlevel) { + int fd; + ssize_t size; if ((fd = openat(dir, "supervise/ok", O_WRONLY | O_NONBLOCK)) == -1) return -1; close(fd); + + if ((fd = openat(dir, "supervise/runlevel", O_RDONLY)) == -1) + return -1; + + if ((size = read(fd, runlevel, NAME_MAX)) == -1) { + close(fd); + return -1; + } + runlevel[size] = '\0'; + close(fd); + return 0; } @@ -66,14 +85,51 @@ static time_t get_mtime(int dir) { return st.st_mtim.tv_sec; } -static int send_command(int dir, const char* command) { +static int handle_command(int dir, char command, const char* runlevel) { int fd; - if ((fd = openat(dir, "supervise/control", O_WRONLY | O_NONBLOCK)) == -1) - return -1; - if (write(fd, command, strlen(command)) == -1) + char up_file[SV_NAME_MAX] = "up-"; + char once_file[SV_NAME_MAX] = "once-"; + + strcat(up_file, runlevel); + strcat(once_file, runlevel); + + switch (command) { + case 'e': // enable + if ((fd = openat(dir, up_file, O_WRONLY | O_TRUNC | O_CREAT, 0644)) != -1) + close(fd); + break; + case 'd': + unlinkat(dir, up_file, 0); + break; + case 'E': // enable + if ((fd = openat(dir, once_file, O_WRONLY | O_TRUNC | O_CREAT, 0644)) != -1) + close(fd); + break; + case 'D': + unlinkat(dir, once_file, 0); + break; + default: + return -1; + } + return 0; +} + +static int send_command(int dir, const char* command, const char* runlevel) { + int fd; + if ((fd = openat(dir, "supervise/control", O_WRONLY | O_NONBLOCK)) == -1) return -1; + for (const char* c = command; *c != '\0'; c++) { + if (*c == '.') { + c++; + if (handle_command(dir, *c, runlevel) == -1) + return -1; + } else { + if (write(fd, c, 1) == -1) + break; + } + } close(fd); return 0; @@ -170,6 +226,7 @@ int main(int argc, char** argv) { time_t mod, start; const char* command = NULL; + char runlevel[SV_NAME_MAX]; while ((opt = getopt_long(argc, argv, ":Vw:", long_options, NULL)) != -1) { switch (opt) { @@ -226,7 +283,8 @@ int main(int argc, char** argv) { continue; } - if (check_service(dir) == -1) { + + if (check_service(dir, runlevel) == -1) { fprintf(stderr, "warning: '%s' is not a valid service\n", argv[i]); continue; } @@ -237,7 +295,7 @@ int main(int argc, char** argv) { } if (command[0] != '\0') { - if (send_command(dir, command) == -1) { + if (send_command(dir, command, runlevel) == -1) { fprintf(stderr, "warning: unable to send command to '%s'\n", argv[i]); continue; } diff --git a/src/register.c b/src/register.c @@ -24,7 +24,7 @@ static int fd_set_flag(int fd, int flags) { } static void init_supervise(service_t* s) { - int lockfd; + int fd; struct stat st; if (fstatat(s->dir, "supervise", &st, 0) == -1) @@ -48,17 +48,29 @@ static void init_supervise(service_t* s) { fd_set_flag(s->control, O_NONBLOCK); - if ((lockfd = openat(s->dir, "supervise/lock", O_CREAT | O_WRONLY, 0644)) == -1) { + if ((fd = openat(s->dir, "supervise/lock", O_CREAT | O_WRONLY, 0644)) == -1) { print_error("cannot create supervise/lock: %s\n"); return; } - close(lockfd); + close(fd); + + + if ((fd = openat(s->dir, "supervise/runlevel", O_CREAT | O_TRUNC | O_WRONLY, 0644)) == -1) { + print_error("cannot create supervise/runlevel: %s\n"); + return; + } + + if (write(fd, runlevel, strlen(runlevel)) == -1) { + print_error("cannot write to supervise/runlevel: %s\n"); + close(fd); + return; + } + close(fd); } service_t* service_register(int dir, const char* name, bool is_log_service) { service_t* s; struct stat st; - bool autostart, autostart_once; char up_path[SV_NAME_MAX] = "up-", once_path[SV_NAME_MAX] = "once-"; @@ -104,19 +116,13 @@ service_t* service_register(int dir, const char* name, bool is_log_service) { strcat(up_path, runlevel); strcat(once_path, runlevel); - autostart = fstatat(s->dir, up_path, &st, 0) != -1 && S_ISREG(st.st_mode); - autostart_once = fstatat(s->dir, once_path, &st, 0) != -1 && S_ISREG(st.st_mode); - s->restart_file = S_DOWN; - if (autostart && autostart_once) { - fprintf(stderr, "error: %s is marked for up AND once!\n", s->name); - } else if (autostart) { + if (fstatat(s->dir, up_path, &st, 0) != -1 && st.st_mode & S_IREAD) s->restart_file = S_RESTART; - } else if (autostart_once) { - if (s->restart_file == S_DOWN) - s->restart_file = S_ONCE; - } + else if (fstatat(s->dir, once_path, &st, 0) != -1 && st.st_mode & S_IREAD) + s->restart_file = S_ONCE; + return s; }