From 05a8ace030f39f492fdf9ee64366359c9b33139a Mon Sep 17 00:00:00 2001 From: Joachim Nilsson Date: Mon, 29 Jun 2015 00:58:12 +0200 Subject: [PATCH] Add support for 'initctl emit EVENT' for more granular control. Signed-off-by: Joachim Nilsson --- api.c | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++++ conf.c | 6 ++---- conf.h | 2 +- finit.h | 1 + initctl.c | 10 ++++++++-- 5 files changed, 65 insertions(+), 7 deletions(-) diff --git a/api.c b/api.c index 911eafd5..0327ae5d 100644 --- a/api.c +++ b/api.c @@ -136,6 +136,55 @@ static int do_query_inetd(char *buf, size_t len) return inetd_filter_str(&svc->inetd, buf, len); } +typedef struct { + char *event; + void (*cb)(void); +} ev_t; + +ev_t ev_list[] = { + { "RELOAD", conf_reload_dynamic }, + { "STOP", service_stop_dynamic }, + { "START", service_start_dynamic }, + { NULL, NULL } +}; + +static int do_handle_event(char *event) +{ + int i; + + for (i = 0; ev_list[i].event; i++) { + ev_t *e = &ev_list[i]; + size_t len = MAX(strlen(e->event), strlen(event)); + + if (!strncasecmp(e->event, event, len)) { + e->cb(); + return 0; + } + } + + /* XXX: iterate over all services' events before failing. */ + + return -1; +} + +static int do_handle_emit(char *buf, size_t len) +{ + int result = 0; + char *input, *event, *pos; + + input = sanitize(buf, len); + if (!input) + return -1; + + event = strtok_r(input, " ", &pos); + while (event) { + result += do_handle_event(event); + event = strtok_r(NULL, " ", &pos); + } + + return result; +} + static void cb(uev_t *w, void *UNUSED(arg), int UNUSED(events)) { int sd; @@ -230,6 +279,10 @@ static void cb(uev_t *w, void *UNUSED(arg), int UNUSED(events)) result = do_query_inetd(rq.data, sizeof(rq.data)); break; + case INIT_CMD_EMIT: + result = do_handle_emit(rq.data, sizeof(rq.data)); + break; + case INIT_CMD_ACK: _d("Client failed reading ACK."); goto leave; diff --git a/conf.c b/conf.c index edb9aa21..3468dc70 100644 --- a/conf.c +++ b/conf.c @@ -341,7 +341,7 @@ static int parse_conf(char *file) } /* Reload all *.conf in /etc/finit.d/ */ -int conf_reload_dynamic(void) +void conf_reload_dynamic(void) { int i, num; char *dir = rcsd; @@ -353,7 +353,7 @@ int conf_reload_dynamic(void) num = scandir(dir, &e, NULL, alphasort); if (num < 0) { _d("No files found in %s, skipping ...", dir); - return -1; + return; } for (i = 0; i < num; i++) { @@ -383,8 +383,6 @@ int conf_reload_dynamic(void) while (num--) free(e[num]); free(e); - - return 0; } int conf_parse_config(void) diff --git a/conf.h b/conf.h index e0d8c1ee..d958a68d 100644 --- a/conf.h +++ b/conf.h @@ -27,7 +27,7 @@ void conf_parse_cmdline (void); int conf_parse_runlevels (char *runlevels); int conf_parse_config (void); -int conf_reload_dynamic (void); +void conf_reload_dynamic (void); #endif /* FINIT_CONF_H_ */ diff --git a/finit.h b/finit.h index ec2916a0..b0c8cae6 100644 --- a/finit.h +++ b/finit.h @@ -50,6 +50,7 @@ #define INIT_CMD_RELOAD_SVC 6 /* SIGHUP service */ #define INIT_CMD_RESTART_SVC 7 /* STOP + START service */ #define INIT_CMD_QUERY_INETD 8 +#define INIT_CMD_EMIT 9 #define INIT_CMD_NACK 254 #define INIT_CMD_ACK 255 diff --git a/initctl.c b/initctl.c index bc68e2ef..19dc137b 100644 --- a/initctl.c +++ b/initctl.c @@ -107,7 +107,7 @@ static int do_svc(int cmd, char *arg) .cmd = cmd, }; - if (!arg) { + if (!arg || !arg[0]) { if (cmd == INIT_CMD_RELOAD_SVC) { rq.cmd = INIT_CMD_RELOAD; goto exit; @@ -121,6 +121,7 @@ exit: return do_send(&rq, sizeof(rq)); } +static int do_emit (char *arg) { return do_svc(INIT_CMD_EMIT, arg); } static int do_start (char *arg) { return do_svc(INIT_CMD_START_SVC, arg); } static int do_stop (char *arg) { return do_svc(INIT_CMD_STOP_SVC, arg); } static int do_reload (char *arg) { return do_svc(INIT_CMD_RELOAD_SVC, arg); } @@ -206,7 +207,11 @@ static int usage(int rc) " -h, --help This help text\n\n" "Commands:\n" " debug Toggle Finit debug\n" - " reload Reload *.conf in /etc/finit.d/\n" + " emit Emit an event. Can be a predefined event: RELOAD, STOP,\n" + " START, or a custom string to match the event list in a\n" + " service stanza, e.g: GW, IFUP:IFNAME, IFDN:IFNAME, where\n" + " IFNAME is the interface name, e.g. eth0\n" + " reload Reload *.conf in /etc/finit.d/ and activate changes\n" " runlevel [0-9] Show or set runlevel: 0 halt, 6 reboot\n" " status Show status of services\n" " start Start stopped job or service\n" @@ -223,6 +228,7 @@ int main(int argc, char *argv[]) int c; command_t command[] = { { "debug", toggle_debug }, + { "emit", do_emit }, { "reload", do_reload }, { "runlevel", do_runlevel }, { "status", show_status },