initctl signal command parsing: done

This commit is contained in:
Jörgen Sigvardsson committed 2022-02-15 12:29:40 +01:00
1 parent 3c9053b055
commit 62da379472
6 files changed
+135 -37

No files matched your search

+3
View File
@@ -45,3 +45,6 @@ GTAGS
/.autoconf /.autoconf
/.automake /.automake
/.built /.built
# VS Code user settings
.vscode
+4
View File
@@ -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]
+1
View File
@@ -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
View File
@@ -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;
+28
View File
@@ -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];
+1
View File
@@ -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);