summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--initd/init.h5
-rw-r--r--initd/main.c8
-rw-r--r--initd/supervisor.c42
-rw-r--r--lib/include/initsock.h6
-rw-r--r--lib/include/service.h1
-rw-r--r--lib/init/init_socket_send_request.c5
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;
}