diff --git a/cmd/Makemodule.am b/cmd/Makemodule.am index 203a840..d6ed4fc 100644 --- a/cmd/Makemodule.am +++ b/cmd/Makemodule.am @@ -25,6 +25,7 @@ service_SOURCES = cmd/service/servicecmd.c cmd/service/help.c service_SOURCES += cmd/service/enable.c cmd/service/disable.c service_SOURCES += cmd/service/dumpscript.c cmd/service/list.c service_SOURCES += cmd/service/status.c cmd/service/loadsvc.c +service_SOURCES += cmd/service/startstop.c service_SOURCES += $(SRVHEADERS) service_CPPFLAGS = $(AM_CPPFLAGS) service_CFLAGS = $(AM_CFLAGS) diff --git a/cmd/service/service.8 b/cmd/service/service.8 index 1f021db..8bcb651 100644 --- a/cmd/service/service.8 +++ b/cmd/service/service.8 @@ -43,6 +43,12 @@ exact commands executed when starting the service. Print a status report of all supervised services, i.e. if they are currently running, have exited or waiting to be scheduled. A specific list of services can be specified. Shell globbing patterns can be used. +.TP +.BR start " " \fIservices...\fP +Start one or more currently not running services. Shell globbing patterns can be used. +.TP +.BR stop " " \fIservices...\fP +Stop one or more currently running services. Shell globbing patterns can be used. .SH AVAILABILITY This program is part of the Pygos init system. .SH COPYRIGHT diff --git a/cmd/service/startstop.c b/cmd/service/startstop.c new file mode 100644 index 0000000..ffc33de --- /dev/null +++ b/cmd/service/startstop.c @@ -0,0 +1,110 @@ +/* SPDX-License-Identifier: ISC */ +#include "servicecmd.h" +#include "initsock.h" +#include "service.h" +#include "config.h" + +#include +#include +#include + +static void free_resp(init_status_response_t *resp) +{ + free(resp->filename); + free(resp->service_name); +} + +static int cmd_startstop(int argc, char **argv, + E_SERVICE_STATE filter, E_INIT_REQUEST action) +{ + int i, fd, ret = EXIT_FAILURE; + init_status_response_t resp; + char tmppath[256]; + bool found; + + if (check_arguments(argv[0], argc, 2, 2)) + return EXIT_FAILURE; + + sprintf(tmppath, "/tmp/svcstatus.%d.sock", (int)getpid()); + fd = init_socket_open(tmppath); + + if (fd < 0) { + unlink(tmppath); + return EXIT_FAILURE; + } + + if (init_socket_send_request(fd, EIR_STATUS, filter)) + goto out; + + for (;;) { + memset(&resp, 0, sizeof(resp)); + + if (init_socket_recv_status(fd, &resp)) { + perror("reading from initd socket"); + free_resp(&resp); + goto out; + } + + if (resp.state == ESS_NONE) { + free_resp(&resp); + break; + } + + found = false; + + for (i = optind; i < argc; ++i) { + if (fnmatch(argv[i], resp.service_name, 0) == 0) { + found = true; + break; + } + if (fnmatch(argv[i], resp.filename, 0) == 0) { + found = true; + break; + } + } + + if (found) { + if (init_socket_send_request(fd, action, resp.id)) + goto out; + } + + free_resp(&resp); + } + + ret = EXIT_SUCCESS; +out: + close(fd); + unlink(tmppath); + return ret; +} + +static int cmd_start(int argc, char **argv) +{ + return cmd_startstop(argc, argv, ESS_NONE, EIR_START); +} + +static int cmd_stop(int argc, char **argv) +{ + return cmd_startstop(argc, argv, ESS_NONE, EIR_STOP); +} + +static command_t start = { + .cmd = "start", + .usage = "services...", + .s_desc = "start a currently not running service", + .l_desc = "Start one or more service that are currently not running. " + "Shell style globbing patterns can used for service names.", + .run_cmd = cmd_start, +}; + +static command_t stop = { + .cmd = "stop", + .usage = "services...", + .s_desc = "stop a currently running service", + .l_desc = "Stop one or more service that are currently running. " + "Shell style globbing patterns can used for service names.", + .run_cmd = cmd_stop, +}; + +REGISTER_COMMAND(start) +REGISTER_COMMAND(stop)