mirror of
https://github.com/troglobit/finit.git
synced 2026-11-02 13:20:32 +00:00
Merge pull request #229 from jorgensigvardsson/issue/255/initctl-signal
Fix #225: add support for initctl signal Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
This commit is contained in:
12 files changed
+226
-56
No files matched your search
@@ -45,3 +45,6 @@ GTAGS
|
|||||||
/.autoconf
|
/.autoconf
|
||||||
/.automake
|
/.automake
|
||||||
/.built
|
/.built
|
||||||
|
|
||||||
|
# VS Code user settings
|
||||||
|
.vscode
|
||||||
@@ -140,6 +140,10 @@ Start service by name, with optional ID, e.g.,
|
|||||||
Stop/Pause a running service by name
|
Stop/Pause a running service by name
|
||||||
.It Nm Ar reload Cm NAME[:ID]
|
.It Nm Ar reload Cm NAME[:ID]
|
||||||
Reload service by name (SIGHUP or restart)
|
Reload service by name (SIGHUP or restart)
|
||||||
|
.It Nm Ar signal Cm NAME:[ID] S
|
||||||
|
Send signal S to service, by name.
|
||||||
|
.Cm S
|
||||||
|
may be a complete signal name such as SIGHUP, or short name such as HUP, or the signal number such as 1 (SIGHUP).
|
||||||
.It Nm Ar restart Cm NAME[:ID]
|
.It Nm Ar restart Cm NAME[:ID]
|
||||||
Restart (stop/start) service by name
|
Restart (stop/start) service by name
|
||||||
.It Nm Ar status Cm NAME[:ID]
|
.It Nm Ar status Cm NAME[:ID]
|
||||||
|
|||||||
@@ -51,12 +51,12 @@
|
|||||||
extern svc_t *wdog;
|
extern svc_t *wdog;
|
||||||
static uev_t api_watcher;
|
static uev_t api_watcher;
|
||||||
|
|
||||||
static int call(int (*action)(svc_t *), char *buf, size_t len)
|
static int call(int (*action)(svc_t *, void *), char *buf, size_t len)
|
||||||
{
|
{
|
||||||
return svc_parse_jobstr(buf, len, action, NULL);
|
return svc_parse_jobstr(buf, len, NULL, action, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int stop(svc_t *svc)
|
static int stop(svc_t *svc, void *user_data)
|
||||||
{
|
{
|
||||||
if (!svc)
|
if (!svc)
|
||||||
return 1;
|
return 1;
|
||||||
@@ -67,7 +67,7 @@ static int stop(svc_t *svc)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int start(svc_t *svc)
|
static int start(svc_t *svc, void *user_data)
|
||||||
{
|
{
|
||||||
if (!svc)
|
if (!svc)
|
||||||
return 1;
|
return 1;
|
||||||
@@ -83,7 +83,7 @@ static int start(svc_t *svc)
|
|||||||
* responsibility of initctl to do. Otherwise we'd block PID 1,
|
* responsibility of initctl to do. Otherwise we'd block PID 1,
|
||||||
* or introduce some nasty race conditions.
|
* or introduce some nasty race conditions.
|
||||||
*/
|
*/
|
||||||
static int restart(svc_t *svc)
|
static int restart(svc_t *svc, void *user_data)
|
||||||
{
|
{
|
||||||
if (!svc)
|
if (!svc)
|
||||||
return 1;
|
return 1;
|
||||||
@@ -95,7 +95,7 @@ static int restart(svc_t *svc)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int reload(svc_t *svc)
|
static int reload(svc_t *svc, void *user_data)
|
||||||
{
|
{
|
||||||
if (!svc)
|
if (!svc)
|
||||||
return 1;
|
return 1;
|
||||||
@@ -114,8 +114,32 @@ static int do_start (char *buf, size_t len) { return call(start, buf, len); }
|
|||||||
static int do_restart(char *buf, size_t len) { return call(restart, buf, len); }
|
static int do_restart(char *buf, size_t len) { return call(restart, buf, len); }
|
||||||
static int do_reload (char *buf, size_t len) { return call(reload, buf, len); }
|
static int do_reload (char *buf, size_t len) { return call(reload, buf, len); }
|
||||||
|
|
||||||
|
static int do_signal_svc(svc_t *svc, void *user_data)
|
||||||
|
{
|
||||||
|
if (!svc)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
if (!svc_is_running(svc))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
int sig = *(int *)user_data;
|
||||||
|
if (kill(svc->pid, sig))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int do_signal(char *buf, size_t len, int sig)
|
||||||
|
{
|
||||||
|
/* Sanity check: Do we know this signal!? */
|
||||||
|
if (!*sig2str(sig))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
return svc_parse_jobstr(buf, len, &sig, do_signal_svc, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
static char query_buf[368];
|
static char query_buf[368];
|
||||||
static int missing(char *job, char *id)
|
static int missing(char *job, char *id, void *user_data)
|
||||||
{
|
{
|
||||||
char buf[20];
|
char buf[20];
|
||||||
|
|
||||||
@@ -133,7 +157,7 @@ static int missing(char *job, char *id)
|
|||||||
static int do_query(char *buf, size_t len)
|
static int do_query(char *buf, size_t len)
|
||||||
{
|
{
|
||||||
query_buf[0] = 0;
|
query_buf[0] = 0;
|
||||||
if (svc_parse_jobstr(buf, len, NULL, missing)) {
|
if (svc_parse_jobstr(buf, len, NULL, NULL, missing)) {
|
||||||
memcpy(buf, query_buf, len);
|
memcpy(buf, query_buf, len);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@@ -407,7 +431,7 @@ static void api_cb(uev_t *w, void *arg, int events)
|
|||||||
|
|
||||||
if (wdog->protect) {
|
if (wdog->protect) {
|
||||||
logit(LOG_NOTICE, "Stopping and deleting built-in watchdog.");
|
logit(LOG_NOTICE, "Stopping and deleting built-in watchdog.");
|
||||||
stop(wdog);
|
stop(wdog, NULL);
|
||||||
svc_del(wdog);
|
svc_del(wdog);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -443,6 +467,12 @@ static void api_cb(uev_t *w, void *arg, int events)
|
|||||||
send_svc(sd, do_find_byc(rq.data, sizeof(rq.data)));
|
send_svc(sd, do_find_byc(rq.data, sizeof(rq.data)));
|
||||||
goto leave;
|
goto leave;
|
||||||
|
|
||||||
|
case INIT_CMD_SIGNAL:
|
||||||
|
_d("svc signal %d: %s", rq.runlevel, rq.data);
|
||||||
|
strterm(rq.data, sizeof(rq.data));
|
||||||
|
result = do_signal(rq.data, sizeof(rq.data), rq.runlevel /* runlevel is reused for signal! */);
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
_d("Unsupported cmd: %d", rq.cmd);
|
_d("Unsupported cmd: %d", rq.cmd);
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -95,6 +95,7 @@
|
|||||||
#define INIT_CMD_SVC_QUERY 130
|
#define INIT_CMD_SVC_QUERY 130
|
||||||
#define INIT_CMD_SVC_FIND 131
|
#define INIT_CMD_SVC_FIND 131
|
||||||
#define INIT_CMD_SVC_FIND_BYC 132
|
#define INIT_CMD_SVC_FIND_BYC 132
|
||||||
|
#define INIT_CMD_SIGNAL 133
|
||||||
#define INIT_CMD_NACK 254
|
#define INIT_CMD_NACK 254
|
||||||
#define INIT_CMD_ACK 255
|
#define INIT_CMD_ACK 255
|
||||||
|
|
||||||
|
|||||||
+98
-37
@@ -52,6 +52,7 @@ struct cmd {
|
|||||||
struct cmd *ctx;
|
struct cmd *ctx;
|
||||||
int (*cb)(char *arg);
|
int (*cb)(char *arg);
|
||||||
int *cond;
|
int *cond;
|
||||||
|
int (*cb_multiarg)(int argc, char **argv);
|
||||||
};
|
};
|
||||||
|
|
||||||
int icreate = 0;
|
int icreate = 0;
|
||||||
@@ -275,6 +276,60 @@ static int do_restart(char *arg)
|
|||||||
return do_startstop(INIT_CMD_RESTART_SVC, arg);
|
return do_startstop(INIT_CMD_RESTART_SVC, arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* do_signal - Ask finit to send a signal to a service.
|
||||||
|
* @argv: must point to an array of strings, containing a service
|
||||||
|
* and signal name, in that order.
|
||||||
|
* @argc: must be 2.
|
||||||
|
*
|
||||||
|
* A signal can be a complete signal name such as "SIGHUP", or
|
||||||
|
* it can be the shortest unique name, such as "HUP" (no SIG prefix).
|
||||||
|
* It can also be a raw signal number, such as "9" (SIGKILL).
|
||||||
|
*/
|
||||||
|
int do_signal(int argc, char **argv)
|
||||||
|
{
|
||||||
|
int signum;
|
||||||
|
|
||||||
|
struct init_request rq = {
|
||||||
|
.magic = INIT_MAGIC,
|
||||||
|
.cmd = INIT_CMD_SVC_QUERY
|
||||||
|
};
|
||||||
|
|
||||||
|
if (argc != 2)
|
||||||
|
errx(1, "invalid number of arguments to signal");
|
||||||
|
|
||||||
|
/* Validate service name */
|
||||||
|
strlcpy(rq.data, argv[0], sizeof(rq.data));
|
||||||
|
if (client_send(&rq, sizeof(rq))) {
|
||||||
|
fprintf(stderr, "No such task or service(s): %s\n\n", argv[0]);
|
||||||
|
goto show_usage;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Validate signal name (or number) */
|
||||||
|
if ((signum = str2sig(argv[1])) < 0) {
|
||||||
|
/* It wasn't a signal name, so let's see if argv[1]
|
||||||
|
is an actual signal number. */
|
||||||
|
errno = 0; /* Make sure errno is reset */
|
||||||
|
signum = (int) strtol(argv[1], NULL, 10);
|
||||||
|
|
||||||
|
/* Was it a number? Was it a signum that finit recognizes? */
|
||||||
|
if (errno || !*(sig2str(signum))) {
|
||||||
|
fprintf(stderr, "Not a valid signal (or signum): %s\n", argv[1]);
|
||||||
|
goto show_usage;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
rq.magic = INIT_MAGIC;
|
||||||
|
rq.cmd = INIT_CMD_SIGNAL;
|
||||||
|
strlcpy(rq.data, argv[0], sizeof(rq.data));
|
||||||
|
rq.runlevel = signum; /* Reuse runlevel for signal number. */
|
||||||
|
return client_send(&rq, sizeof(rq));
|
||||||
|
|
||||||
|
show_usage:
|
||||||
|
fprintf(stderr, "Usage: initctl signal <NAME>[:ID] <S>\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
static int dump_one_cond(const char *fpath, const struct stat *sb, int tflag, struct FTW *ftwbuf)
|
static int dump_one_cond(const char *fpath, const struct stat *sb, int tflag, struct FTW *ftwbuf)
|
||||||
{
|
{
|
||||||
const char *cond, *asserted;
|
const char *cond, *asserted;
|
||||||
@@ -939,6 +994,7 @@ static int usage(int rc)
|
|||||||
" stop <NAME>[:ID] Stop/Pause a running service by name\n"
|
" stop <NAME>[:ID] Stop/Pause a running service by name\n"
|
||||||
" reload <NAME>[:ID] Reload service by name (SIGHUP or restart)\n"
|
" reload <NAME>[:ID] Reload service by name (SIGHUP or restart)\n"
|
||||||
" restart <NAME>[:ID] Restart (stop/start) service by name\n"
|
" restart <NAME>[:ID] Restart (stop/start) service by name\n"
|
||||||
|
" signal <NAME>[:ID] <S> Send signal S to service by name, with optional ID\n"
|
||||||
" ident [NAME] Show matching identities for NAME, or all\n"
|
" ident [NAME] Show matching identities for NAME, or all\n"
|
||||||
" status <NAME>[:ID] Show service status, by name\n"
|
" status <NAME>[:ID] Show service status, by name\n"
|
||||||
" status Show status of services, default command\n");
|
" status Show status of services, default command\n");
|
||||||
@@ -1001,6 +1057,9 @@ static int cmd_parse(int argc, char *argv[], struct cmd *command)
|
|||||||
if (command[i].ctx)
|
if (command[i].ctx)
|
||||||
return cmd_parse(argc - 1, &argv[1], command[i].ctx);
|
return cmd_parse(argc - 1, &argv[1], command[i].ctx);
|
||||||
|
|
||||||
|
if (command[i].cb_multiarg)
|
||||||
|
return command[i].cb_multiarg(argc - 1, argv + 1);
|
||||||
|
|
||||||
if (command[i].cb) {
|
if (command[i].cb) {
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
|
|
||||||
@@ -1019,6 +1078,7 @@ static int cmd_parse(int argc, char *argv[], struct cmd *command)
|
|||||||
|
|
||||||
return command[0].cb(NULL); /* default cmd */
|
return command[0].cb(NULL); /* default cmd */
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
struct option long_options[] = {
|
struct option long_options[] = {
|
||||||
@@ -1036,52 +1096,53 @@ int main(int argc, char *argv[])
|
|||||||
{ NULL, 0, NULL, 0 }
|
{ NULL, 0, NULL, 0 }
|
||||||
};
|
};
|
||||||
struct cmd cond[] = {
|
struct cmd cond[] = {
|
||||||
{ "status", NULL, do_cond_show, NULL }, /* default cmd */
|
{ "status", NULL, do_cond_show, NULL, NULL }, /* default cmd */
|
||||||
{ "dump", NULL, do_cond_dump, NULL },
|
{ "dump", NULL, do_cond_dump, NULL, NULL },
|
||||||
{ "set", NULL, do_cond_set, NULL },
|
{ "set", NULL, do_cond_set, NULL, NULL },
|
||||||
{ "clr", NULL, do_cond_clr, NULL },
|
{ "clr", NULL, do_cond_clr, NULL, NULL },
|
||||||
{ "clear", NULL, do_cond_clr, NULL },
|
{ "clear", NULL, do_cond_clr, NULL, NULL },
|
||||||
{ NULL, NULL, NULL, NULL }
|
{ NULL, NULL, NULL, NULL, NULL }
|
||||||
};
|
};
|
||||||
struct cmd command[] = {
|
struct cmd command[] = {
|
||||||
{ "status", NULL, show_status, NULL }, /* default cmd */
|
{ "status", NULL, show_status, NULL, NULL }, /* default cmd */
|
||||||
{ "ident", NULL, show_ident, NULL },
|
{ "ident", NULL, show_ident, NULL, NULL },
|
||||||
|
|
||||||
{ "debug", NULL, toggle_debug, NULL },
|
{ "debug", NULL, toggle_debug, NULL, NULL },
|
||||||
{ "devel", NULL, do_devel, NULL },
|
{ "devel", NULL, do_devel, NULL, NULL },
|
||||||
{ "help", NULL, do_help, NULL },
|
{ "help", NULL, do_help, NULL, NULL },
|
||||||
{ "version", NULL, show_version, NULL },
|
{ "version", NULL, show_version, NULL, NULL },
|
||||||
|
|
||||||
{ "list", NULL, serv_list, NULL },
|
{ "list", NULL, serv_list, NULL, NULL },
|
||||||
{ "ls", NULL, serv_list, NULL },
|
{ "ls", NULL, serv_list, NULL, NULL },
|
||||||
{ "enable", NULL, serv_enable, NULL },
|
{ "enable", NULL, serv_enable, NULL, NULL },
|
||||||
{ "disable", NULL, serv_disable, NULL },
|
{ "disable", NULL, serv_disable, NULL, NULL },
|
||||||
{ "touch", NULL, serv_touch, NULL },
|
{ "touch", NULL, serv_touch, NULL, NULL },
|
||||||
{ "show", NULL, serv_show, NULL },
|
{ "show", NULL, serv_show, NULL, NULL },
|
||||||
{ "edit", NULL, serv_edit, NULL },
|
{ "edit", NULL, serv_edit, NULL, NULL },
|
||||||
{ "create", NULL, serv_creat, NULL },
|
{ "create", NULL, serv_creat, NULL, NULL },
|
||||||
{ "delete", NULL, serv_delete, NULL },
|
{ "delete", NULL, serv_delete, NULL, NULL },
|
||||||
{ "reload", NULL, do_reload, NULL },
|
{ "reload", NULL, do_reload, NULL, NULL },
|
||||||
|
|
||||||
{ "cond", cond, NULL, NULL },
|
{ "cond", cond, NULL, NULL, NULL },
|
||||||
|
|
||||||
{ "log", NULL, do_log, NULL },
|
{ "log", NULL, do_log, NULL, NULL },
|
||||||
{ "start", NULL, do_start, NULL },
|
{ "start", NULL, do_start, NULL, NULL },
|
||||||
{ "stop", NULL, do_stop, NULL },
|
{ "stop", NULL, do_stop, NULL, NULL },
|
||||||
{ "restart", NULL, do_restart, NULL },
|
{ "restart", NULL, do_restart, NULL, NULL },
|
||||||
|
{ "signal", NULL, NULL, NULL, do_signal },
|
||||||
|
|
||||||
{ "cgroup", NULL, show_cgroup, &cgrp },
|
{ "cgroup", NULL, show_cgroup, &cgrp, NULL },
|
||||||
{ "ps", NULL, show_cgps, &cgrp },
|
{ "ps", NULL, show_cgps, &cgrp, NULL },
|
||||||
{ "top", NULL, show_cgtop, &cgrp },
|
{ "top", NULL, show_cgtop, &cgrp, NULL },
|
||||||
|
|
||||||
{ "runlevel", NULL, do_runlevel, NULL },
|
{ "runlevel", NULL, do_runlevel, NULL, NULL },
|
||||||
{ "reboot", NULL, do_reboot, NULL },
|
{ "reboot", NULL, do_reboot, NULL, NULL },
|
||||||
{ "halt", NULL, do_halt, NULL },
|
{ "halt", NULL, do_halt, NULL, NULL },
|
||||||
{ "poweroff", NULL, do_poweroff, NULL },
|
{ "poweroff", NULL, do_poweroff, NULL, NULL },
|
||||||
{ "suspend", NULL, do_suspend, NULL },
|
{ "suspend", NULL, do_suspend, NULL, NULL },
|
||||||
|
|
||||||
{ "utmp", NULL, do_utmp, &utmp },
|
{ "utmp", NULL, do_utmp, &utmp, NULL },
|
||||||
{ NULL, NULL, NULL, NULL }
|
{ NULL, NULL, NULL, NULL, NULL }
|
||||||
};
|
};
|
||||||
int interactive = 1, c;
|
int interactive = 1, c;
|
||||||
|
|
||||||
|
|||||||
@@ -650,7 +650,7 @@ static char *tokstr(char *str, size_t len)
|
|||||||
/*
|
/*
|
||||||
* Used by api.c (to start/stop/restart) and initctl.c (for input validation)
|
* Used by api.c (to start/stop/restart) and initctl.c (for input validation)
|
||||||
*/
|
*/
|
||||||
int svc_parse_jobstr(char *str, size_t len, int (*found)(svc_t *), int (not_found)(char *, char *))
|
int svc_parse_jobstr(char *str, size_t len, void *user_data, int (*found)(svc_t *, void *), int (not_found)(char *, char *, void *))
|
||||||
{
|
{
|
||||||
char *input, *token;
|
char *input, *token;
|
||||||
int result = 0;
|
int result = 0;
|
||||||
@@ -686,11 +686,11 @@ int svc_parse_jobstr(char *str, size_t len, int (*found)(svc_t *), int (not_foun
|
|||||||
if (!ptr) {
|
if (!ptr) {
|
||||||
svc = svc_job_iterator(&iter, 1, job);
|
svc = svc_job_iterator(&iter, 1, job);
|
||||||
if (!svc && not_found)
|
if (!svc && not_found)
|
||||||
result += not_found(NULL, token);
|
result += not_found(NULL, token, user_data);
|
||||||
|
|
||||||
while (svc) {
|
while (svc) {
|
||||||
if (found)
|
if (found)
|
||||||
result += found(svc);
|
result += found(svc, user_data);
|
||||||
svc = svc_job_iterator(&iter, 0, job);
|
svc = svc_job_iterator(&iter, 0, job);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -699,19 +699,19 @@ int svc_parse_jobstr(char *str, size_t len, int (*found)(svc_t *), int (not_foun
|
|||||||
|
|
||||||
svc = svc_find_by_jobid(job, id);
|
svc = svc_find_by_jobid(job, id);
|
||||||
if (!svc && not_found)
|
if (!svc && not_found)
|
||||||
result += not_found(token, id);
|
result += not_found(token, id, user_data);
|
||||||
else if (found)
|
else if (found)
|
||||||
result += found(svc);
|
result += found(svc, user_data);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (!ptr) {
|
if (!ptr) {
|
||||||
svc = svc_named_iterator(&iter, 1, token);
|
svc = svc_named_iterator(&iter, 1, token);
|
||||||
if (!svc && not_found)
|
if (!svc && not_found)
|
||||||
result += not_found(token, id);
|
result += not_found(token, id, user_data);
|
||||||
|
|
||||||
while (svc) {
|
while (svc) {
|
||||||
if (found)
|
if (found)
|
||||||
result += found(svc);
|
result += found(svc, user_data);
|
||||||
svc = svc_named_iterator(&iter, 0, token);
|
svc = svc_named_iterator(&iter, 0, token);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -720,9 +720,9 @@ int svc_parse_jobstr(char *str, size_t len, int (*found)(svc_t *), int (not_foun
|
|||||||
|
|
||||||
svc = svc_find_by_nameid(token, id);
|
svc = svc_find_by_nameid(token, id);
|
||||||
if (!svc && not_found)
|
if (!svc && not_found)
|
||||||
result += not_found(token, id);
|
result += not_found(token, id, user_data);
|
||||||
else if (found)
|
else if (found)
|
||||||
result += found(svc);
|
result += found(svc, user_data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -222,7 +222,7 @@ void svc_prune_bootstrap (void);
|
|||||||
void svc_enable (svc_t *svc);
|
void svc_enable (svc_t *svc);
|
||||||
int svc_enabled (svc_t *svc);
|
int svc_enabled (svc_t *svc);
|
||||||
|
|
||||||
int svc_parse_jobstr (char *str, size_t len, int (*found)(svc_t *), int (not_found)(char *, char *));
|
int svc_parse_jobstr (char *str, size_t len, void *user_data, int (*found)(svc_t *, void *), int (not_found)(char *, char *, void *));
|
||||||
|
|
||||||
static inline int svc_is_daemon (svc_t *svc) { return svc && SVC_TYPE_SERVICE == svc->type; }
|
static inline int svc_is_daemon (svc_t *svc) { return svc && SVC_TYPE_SERVICE == svc->type; }
|
||||||
static inline int svc_is_sysv (svc_t *svc) { return svc && SVC_TYPE_SYSV == svc->type; }
|
static inline int svc_is_sysv (svc_t *svc) { return svc && SVC_TYPE_SYSV == svc->type; }
|
||||||
|
|||||||
+28
@@ -275,6 +275,34 @@ char *sig2str(int sig)
|
|||||||
return signame;
|
return signame;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* str2sig - Translate signal name to the corresponding signal number.
|
||||||
|
* @sig: The name of the signal
|
||||||
|
*
|
||||||
|
* A signal can be a complete signal name such as "SIGHUP", or
|
||||||
|
* it can be the shortest unique name, such as "HUP" (no SIG prefix).
|
||||||
|
*/
|
||||||
|
int str2sig(char *sig)
|
||||||
|
{
|
||||||
|
int name_offset = 0;
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
/* if sig name starts with "SIG", then skip the first
|
||||||
|
* three characters. signames holds the names without
|
||||||
|
* the "SIG" prefix.
|
||||||
|
*/
|
||||||
|
if (strncasecmp(sig, "SIG", 3) == 0) {
|
||||||
|
name_offset = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 1; i < NELEMS(signames); ++i) {
|
||||||
|
if (strcasecmp(&sig[name_offset], signames[i]) == 0)
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
char *code2str(int code)
|
char *code2str(int code)
|
||||||
{
|
{
|
||||||
static char codename[20];
|
static char codename[20];
|
||||||
|
|||||||
@@ -61,6 +61,7 @@ int fngetint (char *path, int *val);
|
|||||||
|
|
||||||
int strtobytes (char *arg);
|
int strtobytes (char *arg);
|
||||||
char *sig2str (int sig);
|
char *sig2str (int sig);
|
||||||
|
int str2sig (char *sig);
|
||||||
char *code2str (int code);
|
char *code2str (int code);
|
||||||
|
|
||||||
void do_sleep (unsigned int sec);
|
void do_sleep (unsigned int sec);
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ EXTRA_DIST += add-remove-dynamic-service-sub-config.sh
|
|||||||
EXTRA_DIST += start-stop-service.sh
|
EXTRA_DIST += start-stop-service.sh
|
||||||
EXTRA_DIST += start-stop-service-sub-config.sh
|
EXTRA_DIST += start-stop-service-sub-config.sh
|
||||||
EXTRA_DIST += start-kill-service.sh
|
EXTRA_DIST += start-kill-service.sh
|
||||||
|
EXTRA_DIST += signal-service.sh
|
||||||
|
|
||||||
AM_TESTS_ENVIRONMENT = TENV_ROOT='$(abs_builddir)/tenv-root/';
|
AM_TESTS_ENVIRONMENT = TENV_ROOT='$(abs_builddir)/tenv-root/';
|
||||||
AM_TESTS_ENVIRONMENT += export TENV_ROOT;
|
AM_TESTS_ENVIRONMENT += export TENV_ROOT;
|
||||||
@@ -28,6 +29,7 @@ TESTS += add-remove-dynamic-service-sub-config.sh
|
|||||||
TESTS += start-stop-service.sh
|
TESTS += start-stop-service.sh
|
||||||
TESTS += start-stop-service-sub-config.sh
|
TESTS += start-stop-service-sub-config.sh
|
||||||
TESTS += start-kill-service.sh
|
TESTS += start-kill-service.sh
|
||||||
|
TESTS += signal-service.sh
|
||||||
|
|
||||||
clean-local:
|
clean-local:
|
||||||
-rm -rf $(builddir)/tenv-root/
|
-rm -rf $(builddir)/tenv-root/
|
||||||
|
|||||||
@@ -2,6 +2,10 @@
|
|||||||
|
|
||||||
set -eu
|
set -eu
|
||||||
|
|
||||||
|
# Hook SIGUSR1 and dump trace to file system
|
||||||
|
# shellcheck disable=SC2172
|
||||||
|
trap 'echo USR1 > /tmp/usr1.log' 10
|
||||||
|
|
||||||
echo $$ > /run/service.pid
|
echo $$ > /run/service.pid
|
||||||
|
|
||||||
while true; do
|
while true; do
|
||||||
|
|||||||
Executable
+36
@@ -0,0 +1,36 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
# Verifies initctl can send arbitrary signals (USR1 in this case) to finit managed services
|
||||||
|
|
||||||
|
set -eu
|
||||||
|
|
||||||
|
TEST_DIR=$(dirname "$0")
|
||||||
|
|
||||||
|
# shellcheck source=/dev/null
|
||||||
|
. "$TEST_DIR/tenv/lib.sh"
|
||||||
|
|
||||||
|
test_teardown() {
|
||||||
|
say "Test done $(date)"
|
||||||
|
say "Running test teardown."
|
||||||
|
|
||||||
|
texec rm -f "$FINIT_CONF"
|
||||||
|
texec rm -f /test_assets/service.sh
|
||||||
|
}
|
||||||
|
|
||||||
|
say "Test start $(date)"
|
||||||
|
|
||||||
|
cp "$TEST_DIR"/common/service.sh "$TENV_ROOT"/test_assets/
|
||||||
|
|
||||||
|
say 'Ensure file system is cleared'
|
||||||
|
texec rm -f /tmp/usr1.log
|
||||||
|
|
||||||
|
say "Add service stanza in $FINIT_CONF"
|
||||||
|
texec sh -c "echo 'service [2345] kill:20 log /test_assets/service.sh -- Test service' > $FINIT_CONF"
|
||||||
|
|
||||||
|
say 'Reload Finit'
|
||||||
|
texec sh -c "initctl reload"
|
||||||
|
|
||||||
|
say 'Send SIGUSR1 to service...'
|
||||||
|
texec sh -c "initctl signal service.sh SIGUSR1"
|
||||||
|
|
||||||
|
# shellcheck disable=SC2016
|
||||||
|
retry 'assert "service.sh received SIGUSR" "$(texec cat /tmp/usr1.log)" = "USR1"' 10 1
|
||||||
Reference in new issue
Block a user