diff options
author | Leah Neukirchen <leah@vuxu.org> | 2022-02-12 23:44:54 +0100 |
---|---|---|
committer | Leah Neukirchen <leah@vuxu.org> | 2022-02-12 23:44:54 +0100 |
commit | 06769a66a616d4d984eb91614bb3e88d289de79c (patch) | |
tree | d954c3f46e07cdc393d9c02d2f27dcd371b265c0 | |
parent | ee94145132953271fb3fd606d00154442689e7ec (diff) | |
download | rvnit-06769a66a616d4d984eb91614bb3e88d289de79c.tar.gz rvnit-06769a66a616d4d984eb91614bb3e88d289de79c.tar.xz rvnit-06769a66a616d4d984eb91614bb3e88d289de79c.zip |
rvnitctl: hack some start/stop commands ala sv
This is quite ugly still but shows a polling approach works. Services need to be up/down for 250ms for the start/stop to succeed.
-rw-r--r-- | rvnitctl.c | 92 |
1 files changed, 91 insertions, 1 deletions
diff --git a/rvnitctl.c b/rvnitctl.c index 9920f30..5fca706 100644 --- a/rvnitctl.c +++ b/rvnitctl.c @@ -1,12 +1,59 @@ #include <sys/socket.h> #include <sys/un.h> +#include <ctype.h> #include <stdio.h> #include <stdlib.h> #include <string.h> +#include <time.h> #include <unistd.h> int +check(const char *path, const char *service) +{ + struct sockaddr_un addr = { 0 }; + addr.sun_family = AF_UNIX; + strncpy(addr.sun_path, path, sizeof addr.sun_path - 1); + int connfd = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0); + if (connfd < 0) { + perror("socket"); + exit(111); + } + + if (connect(connfd, (struct sockaddr *)&addr, sizeof addr) < 0) { + perror("connect"); + exit(111); + } + + write(connfd, "s", 1); + + // XXX what if too low? + char buf[4096]; + ssize_t rd = read(connfd, buf, sizeof buf); + if (rd < 0) { + perror("read"); + exit(111); + } + + char *p; + char *f = strstr(buf, service); + if (f && (f == buf || f[-1] == '\n') && + f[strlen(service)+1] == ' ' && + (p = strstr(f, "pid="))) { + p += 4; + printf("found pid %c\n", p[0]); + if (isdigit(p[0])) { + close(connfd); + return 1; // has pid >= 0 + } + } + // XXX fix multiple strstr matches + + close(connfd); + return 0; +} + +int main(int argc, char *argv[]) { if (argc < 2 || ( @@ -24,6 +71,8 @@ main(int argc, char *argv[]) strcmp(argv[1], "k") != 0 && strcmp(argv[1], "kill") != 0 && strcmp(argv[1], "1") != 0 && strcmp(argv[1], "2") != 0 && + strcmp(argv[1], "start") != 0 && + strcmp(argv[1], "stop") != 0 && strcmp(argv[1], "Restart") != 0 && strcmp(argv[1], "Shutdown") != 0)) { dprintf(2, "usage: rvnitctl COMMAND [SERVICE]\n"); @@ -49,7 +98,14 @@ main(int argc, char *argv[]) exit(111); } - dprintf(connfd, "%c%s", *argv[1], argv[2] ? argv[2] : ""); + char cmd = argv[1][0]; + + if (strcmp(argv[1], "start") == 0 && argv[2]) + cmd = 'u'; + else if (strcmp(argv[1], "stop") == 0 && argv[2]) + cmd = 'd'; + + dprintf(connfd, "%c%s", cmd, argv[2] ? argv[2] : ""); int status = 1; @@ -66,5 +122,39 @@ main(int argc, char *argv[]) write(1, buf, rd); } while (rd > 0); + if (strcmp(argv[1], "start") == 0 && argv[2]) { + int i; + int up = 0; + for (i = 7*4; i > 0; i--) { + if (check(path, argv[2])) { + if (++up >= 2) + break; + } else { + up = 0; + } + nanosleep(&(struct timespec){0, 250000000}, 0); + } + if (up < 2) { + fprintf(stderr, "start failed\n"); + return 1; + } + } else if (strcmp(argv[1], "stop") == 0 && argv[2]) { + int i; + int down = 0; + for (i = 7*4; i > 0; i--) { + if (!check(path, argv[2])) { + if (++down >= 2) + break; + } else { + down = 0; + } + nanosleep(&(struct timespec){0, 250000000}, 0); + } + if (down < 2) { + fprintf(stderr, "stop failed\n"); + return 1; + } + } + return status; } |