|
@@ -51,6 +51,7 @@ static int add_remove_dependency(int socknum, cpbuffer_t &rbuffer, bool add, con
|
|
|
static int enable_disable_service(int socknum, cpbuffer_t &rbuffer, const char *from, const char *to,
|
|
|
bool enable, bool verbose);
|
|
|
static int do_setenv(int socknum, cpbuffer_t &rbuffer, std::vector<const char *> &env_names);
|
|
|
+static int trigger_service(int socknum, cpbuffer_t &rbuffer, const char *service_name, bool trigger_value);
|
|
|
|
|
|
static const char * describeState(bool stopped)
|
|
|
{
|
|
@@ -80,6 +81,8 @@ enum class command_t {
|
|
|
ENABLE_SERVICE,
|
|
|
DISABLE_SERVICE,
|
|
|
SETENV,
|
|
|
+ SET_TRIGGER,
|
|
|
+ UNSET_TRIGGER,
|
|
|
};
|
|
|
|
|
|
class dinit_protocol_error
|
|
@@ -215,6 +218,12 @@ int dinitctl_main(int argc, char **argv)
|
|
|
else if (strcmp(argv[i], "setenv") == 0) {
|
|
|
command = command_t::SETENV;
|
|
|
}
|
|
|
+ else if (strcmp(argv[i], "trigger") == 0) {
|
|
|
+ command = command_t::SET_TRIGGER;
|
|
|
+ }
|
|
|
+ else if (strcmp(argv[i], "untrigger") == 0) {
|
|
|
+ command = command_t::UNSET_TRIGGER;
|
|
|
+ }
|
|
|
else {
|
|
|
cerr << "dinitctl: unrecognized command: " << argv[i] << " (use --help for help)\n";
|
|
|
return 1;
|
|
@@ -322,6 +331,8 @@ int dinitctl_main(int argc, char **argv)
|
|
|
" dinitctl [options] rm-dep <type> <from-service> <to-service>\n"
|
|
|
" dinitctl [options] enable [--from <from-service>] <to-service>\n"
|
|
|
" dinitctl [options] disable [--from <from-service>] <to-service>\n"
|
|
|
+ " dinitctl [options] trigger <service-name>\n"
|
|
|
+ " dinitctl [options] untrigger <service-name>\n"
|
|
|
" dinitctl [options] setenv [name[=value] ...]\n"
|
|
|
"\n"
|
|
|
"Note: An activated service continues running when its dependents stop.\n"
|
|
@@ -363,7 +374,7 @@ int dinitctl_main(int argc, char **argv)
|
|
|
|
|
|
// Start by querying protocol version:
|
|
|
cpbuffer_t rbuffer;
|
|
|
- check_protocol_version(min_cp_version, max_cp_version, rbuffer, socknum);
|
|
|
+ uint16_t daemon_protocol_ver = check_protocol_version(min_cp_version, max_cp_version, rbuffer, socknum);
|
|
|
|
|
|
if (command == command_t::UNPIN_SERVICE) {
|
|
|
return unpin_service(socknum, rbuffer, service_name, verbose);
|
|
@@ -398,6 +409,12 @@ int dinitctl_main(int argc, char **argv)
|
|
|
else if (command == command_t::SETENV) {
|
|
|
return do_setenv(socknum, rbuffer, cmd_args);
|
|
|
}
|
|
|
+ else if (command == command_t::SET_TRIGGER || command == command_t::UNSET_TRIGGER) {
|
|
|
+ if (daemon_protocol_ver < 2) {
|
|
|
+ throw cp_old_server_exception();
|
|
|
+ }
|
|
|
+ return trigger_service(socknum, rbuffer, service_name, (command == command_t::SET_TRIGGER));
|
|
|
+ }
|
|
|
else {
|
|
|
return start_stop_service(socknum, rbuffer, service_name, command, do_pin, do_force,
|
|
|
wait_for_service, ignore_unstarted, verbose);
|
|
@@ -1635,3 +1652,35 @@ static int do_setenv(int socknum, cpbuffer_t &rbuffer, std::vector<const char *>
|
|
|
|
|
|
return 0;
|
|
|
}
|
|
|
+
|
|
|
+static int trigger_service(int socknum, cpbuffer_t &rbuffer, const char *service_name, bool trigger_value)
|
|
|
+{
|
|
|
+ using namespace std;
|
|
|
+
|
|
|
+ handle_t handle;
|
|
|
+ if (!load_service(socknum, rbuffer, service_name, &handle, nullptr, true)) {
|
|
|
+ return 1;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Issue SET_TRIGGER command.
|
|
|
+ {
|
|
|
+ auto m = membuf()
|
|
|
+ .append<char>(DINIT_CP_SETTRIGGER)
|
|
|
+ .append(handle)
|
|
|
+ .append<char>(trigger_value);
|
|
|
+ write_all_x(socknum, m);
|
|
|
+
|
|
|
+ wait_for_reply(rbuffer, socknum);
|
|
|
+ if (rbuffer[0] == DINIT_RP_NAK) {
|
|
|
+ cerr << "dinitctl: cannot trigger a service that is not of 'triggered' type.\n";
|
|
|
+ return 1;
|
|
|
+ }
|
|
|
+ if (rbuffer[0] != DINIT_RP_ACK) {
|
|
|
+ cerr << "dinitctl: protocol error.\n";
|
|
|
+ return 1;
|
|
|
+ }
|
|
|
+ rbuffer.consume(1);
|
|
|
+ }
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|