diff options
-rw-r--r-- | initd/init.h | 5 | ||||
-rw-r--r-- | initd/main.c | 8 | ||||
-rw-r--r-- | initd/supervisor.c | 42 | ||||
-rw-r--r-- | lib/include/initsock.h | 6 | ||||
-rw-r--r-- | lib/include/service.h | 1 | ||||
-rw-r--r-- | lib/init/init_socket_send_request.c | 5 |
6 files changed, 67 insertions, 0 deletions
diff --git a/initd/init.h b/initd/init.h index 1d292d3..b98da98 100644 --- a/initd/init.h +++ b/initd/init.h @@ -9,6 +9,7 @@ #include <string.h> #include <stdlib.h> #include <unistd.h> +#include <endian.h> #include <stdio.h> #include <errno.h> #include <poll.h> @@ -70,6 +71,10 @@ bool supervisor_process_queues(void); void supervisor_answer_status_request(int fd, const void *dest_addr, size_t addrlen, E_SERVICE_STATE filter); +void supervisor_start(int id); + +void supervisor_stop(int id); + /********** signal_<platform>.c **********/ /* diff --git a/initd/main.c b/initd/main.c index 4eb4832..2b1a1cc 100644 --- a/initd/main.c +++ b/initd/main.c @@ -64,6 +64,14 @@ retry: supervisor_answer_status_request(sockfd, &addr, addrlen, rq.arg.status.filter); break; + case EIR_START: + rq.arg.startstop.id = be32toh(rq.arg.startstop.id); + supervisor_start(rq.arg.startstop.id); + break; + case EIR_STOP: + rq.arg.startstop.id = be32toh(rq.arg.startstop.id); + supervisor_stop(rq.arg.startstop.id); + break; } } diff --git a/initd/supervisor.c b/initd/supervisor.c index 871618a..53a2aec 100644 --- a/initd/supervisor.c +++ b/initd/supervisor.c @@ -38,6 +38,9 @@ static void handle_terminated_service(service_t *svc) if (target == TGT_REBOOT || target == TGT_SHUTDOWN) break; + if (svc->flags & SVC_FLAG_ADMIN_STOPPED) + break; + if (svc->rspwn_limit > 0) { svc->rspwn_limit -= 1; @@ -221,3 +224,42 @@ void supervisor_answer_status_request(int fd, const void *dst, size_t addrlen, return; init_socket_send_status(fd, dst, addrlen, ESS_NONE, NULL); } + +void supervisor_start(int id) +{ + service_t *svc; + + for (svc = completed; svc != NULL; svc = svc->next) { + if (svc->id == id) + goto found; + } + + for (svc = failed; svc != NULL; svc = svc->next) { + if (svc->id == id) + goto found; + } + return; +found: + if (svc->type == SVC_RESPAWN) + svc->rspwn_limit = 0; + + svc->flags &= ~SVC_FLAG_ADMIN_STOPPED; + svc->next = queue; + queue = svc; +} + +void supervisor_stop(int id) +{ + service_t *svc; + + for (svc = running; svc != NULL; svc = svc->next) { + if (svc->id == id) + break; + } + + if (svc != NULL) { + /* TODO: something more sophisticated? */ + svc->flags |= SVC_FLAG_ADMIN_STOPPED; + kill(svc->pid, SIGTERM); + } +} diff --git a/lib/include/initsock.h b/lib/include/initsock.h index 10abe08..a687481 100644 --- a/lib/include/initsock.h +++ b/lib/include/initsock.h @@ -11,6 +11,8 @@ typedef enum { EIR_STATUS = 0x00, + EIR_START = 0x01, + EIR_STOP = 0x02, } E_INIT_REQUEST; typedef enum { @@ -30,6 +32,10 @@ typedef struct { uint8_t filter; uint8_t padd[3]; } status; + + struct { + uint32_t id; + } startstop; } arg; } init_request_t; diff --git a/lib/include/service.h b/lib/include/service.h index 1ff5204..4e8f0b3 100644 --- a/lib/include/service.h +++ b/lib/include/service.h @@ -43,6 +43,7 @@ enum { SVC_FLAG_TRUNCATE_OUT = 0x01, SVC_FLAG_HAS_EXEC = 0x10, + SVC_FLAG_ADMIN_STOPPED = 0x20, }; typedef struct service_t { diff --git a/lib/init/init_socket_send_request.c b/lib/init/init_socket_send_request.c index e9c7cb9..53b31f6 100644 --- a/lib/init/init_socket_send_request.c +++ b/lib/init/init_socket_send_request.c @@ -2,6 +2,7 @@ #include <unistd.h> #include <string.h> #include <stdarg.h> +#include <endian.h> #include <stdio.h> #include <errno.h> @@ -21,6 +22,10 @@ int init_socket_send_request(int fd, E_INIT_REQUEST rq, ...) case EIR_STATUS: request.arg.status.filter = va_arg(ap, E_SERVICE_STATE); break; + case EIR_START: + case EIR_STOP: + request.arg.startstop.id = htobe32(va_arg(ap, int)); + break; default: break; } |