Skip to content

Commit

Permalink
Implement environment unset and listening on environment changes
Browse files Browse the repository at this point in the history
  • Loading branch information
q66 authored and davmac314 committed Oct 9, 2024
1 parent 301e750 commit 92cb58e
Show file tree
Hide file tree
Showing 11 changed files with 480 additions and 43 deletions.
35 changes: 26 additions & 9 deletions doc/manpages/dinit-monitor.8.m4
Original file line number Diff line number Diff line change
@@ -1,23 +1,25 @@
changequote(`@@@',`$$$')dnl
@@@.TH DINIT\-MONITOR "8" "$$$MONTH YEAR@@@" "Dinit $$$VERSION@@@" "Dinit \- service management system"
.SH NAME
dinit\-monitor \- monitor services supervised by Dinit
dinit\-monitor \- monitor services or environment supervised by Dinit
.\"
.SH SYNOPSIS
.\"
.PD 0
.nh
.HP
.B dinit-monitor
[\fIoptions\fR] {\fB\-c\fR \fIcommand\fR, \fB\-\-command\fR \fIcommand\fR} \fIservice-name\fR [\fIservice-name\fR...]
[\fIoptions\fR] {\fB\-c\fR \fIcommand\fR, \fB\-\-command\fR \fIcommand\fR} \fIservice-or-env\fR [\fIservice-or-env\fR...]
.\"
.PD
.hy
.\"
.SH DESCRIPTION
.\"
\fBdinit\-monitor\fR is a utility to monitor the state of one or more services managed by the \fBdinit\fR daemon.
Changes in service state are reported by the execution of the specified command.
\fBdinit\-monitor\fR is a utility to monitor the state of one or more services or environment managed by the \fBdinit\fR daemon.
Changes in service or environment state are reported by the execution of the specified command.
When monitoring environment, positional arguments are not required (all environment will be monitored).
By default, service events are monitored.
.\"
.SH GENERAL OPTIONS
.TP
Expand All @@ -27,6 +29,11 @@ Display brief help text and then exit.
\fB\-\-version\fR
Display version and then exit.
.TP
\fB\-e\fR, \fB\-\-exit\fR
Exit after the first command is executed, instead of waiting for more events.
\fB\-E\fR, \fB\-\-env\fR
Instead of monitoring the services, monitor changes in the global environment.
If no environment variables are passed, all environment is monitored.
\fB\-s\fR, \fB\-\-system\fR
Control the system init process (this is the default when run as root).
This option determines the default path to the control socket used to communicate with the \fBdinit\fR daemon
Expand All @@ -38,8 +45,8 @@ This option determines the default path to the control socket used to communicat
(it does not override the \fB\-p\fR option).
.TP
\fB\-i\fR, \fB\-\-initial\fR
Issue the specified command additionally for the initial status of the services (when \fBdinit\-monitor\fR is started).
Without this option, the command is only executed whenever service status changes.
Issue the specified command additionally for the initial status of the services or environment (when \fBdinit\-monitor\fR is started).
Without this option, the command is only executed whenever status changes.
.TP
\fB\-\-str\-started\fR \fIstarted-text\fR
Specify the text used for the substitution of the status in the command (as specified
Expand All @@ -53,6 +60,14 @@ by the \fB\-\-command\fR option) when a service stops.
Specify the text used for the substitution of the status in the command (as specified
by the \fB\-\-command\fR option) when a service fails to start.
.TP
\fB\-\-str\-set\fR \fIset-text\fR
Specify the text used for the substitution of the status in the command (as specified
by the \fB\-\-command\fR option) when an environment variable is set.
.TP
\fB\-\-str\-unset\fR \fIunset-text\fR
Specify the text used for the substitution of the status in the command (as specified
by the \fB\-\-command\fR option) when an environment variable is unset.
.TP
\fB\-\-socket\-path\fR \fIsocket-path\fR, \fB\-p\fR \fIsocket-path\fR
Specify the path to the socket used for communicating with the service manager daemon.
When not specified, the \fIDINIT_SOCKET_PATH\fR environment variable is read, otherwise
Expand All @@ -61,9 +76,11 @@ Dinit's default values are used.
.SH STATUS REPORT OPTIONS
.TP
\fB\-\-command\fR \fIcommand\fR, \fB\-c\fR \fIcommand\fR
Execute the specified \fIcommand\fR when the service status changes. In \fIcommand\fR, \fB%n\fR
will be substituted with the service name and \fB%s\fR will be substituted with a textual
description of the new status (\fBstarted\fR, \fBstopped\fR or \fBfailed\fR). A double percent sign
Execute the specified \fIcommand\fR when the service status changes.
In \fIcommand\fR, \fB%n\fR will be substituted with the service or environment variable name,
\fB%v\fR will be substituted with the environment variable value, and \fB%s\fR will be substituted
with a textual description of the new status (\fBstarted\fR, \fBstopped\fR or \fBfailed\fR for
services, \fBset\fR or \fBunset\fR for environment variables). A double percent sign
(\fB%%\fR) is substituted with a single percent sign character.
.\"
.SH OPERATION
Expand Down
7 changes: 7 additions & 0 deletions doc/manpages/dinitctl.8.m4
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,9 @@ dinitctl \- control services supervised by Dinit
[\fIoptions\fR] \fBsetenv\fR [\fIname\fR[=\fIvalue\fR] \fI...\fR]
.HP
.B dinitctl
[\fIoptions\fR] \fBunsetenv\fR [\fIname\fR \fI...\fR]
.HP
.B dinitctl
[\fIoptions\fR] \fBcatlog\fR [\fB--clear\fR] \fIservice-name\fR
.HP
.B dinitctl
Expand Down Expand Up @@ -322,6 +325,10 @@ called in.
Any subsequently started or restarted service will have these environment variables available.
This is particularly useful for user services that need access to session information.
.TP
\fBunsetenv\fR
Unset one or more variables in the activation environment.
Any subsequently started or restarted service will have these environment variables unset.
.TP
\fBcatlog\fR
Show the contents of the log buffer for the named service.
This is possible only if the log type of the service is set to \fBbuffer\fR.
Expand Down
50 changes: 46 additions & 4 deletions src/control.cc
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,8 @@ bool control_conn_t::process_packet()
return process_setenv();
case cp_cmd::GETALLENV:
return process_getallenv();
case cp_cmd::LISTENENV:
return process_listenenv();
case cp_cmd::SETTRIGGER:
return process_set_trigger();
case cp_cmd::CATLOG:
Expand Down Expand Up @@ -1076,13 +1078,19 @@ bool control_conn_t::process_setenv()
envVar = rbuf.extract_string(3, envvar_len);

eq = envVar.find('=');
if (!eq || eq == envVar.npos) {
// Not found or at the beginning of the string
if (eq == envVar.npos) {
// Unset the env var
main_env.undefine_var(std::move(envVar), true);
}
else if (eq) {
// Regular set
main_env.set_var(std::move(envVar), true);
}
else {
// At the beginning of the string
goto badreq;
}

main_env.set_var(std::move(envVar));

// Success response
if (!queue_packet(okRep, 1)) return false;

Expand Down Expand Up @@ -1141,6 +1149,17 @@ bool control_conn_t::process_getallenv()
return true;
}

bool control_conn_t::process_listenenv()
{
// 1 byte packet type, nothing else
rbuf.consume(1);

main_env.add_listener(this);

char ack_rep[] = { (char)cp_rply::ACK };
return queue_packet(ack_rep, 1);
}

bool control_conn_t::process_set_trigger()
{
// 1 byte packet type
Expand Down Expand Up @@ -1468,6 +1487,28 @@ void control_conn_t::service_event(service_record *service, service_event_t even
}
}

void control_conn_t::environ_event(environment *env, std::string const &var_and_val, bool overridden) noexcept
{
// packet type (byte) + packet length (byte) + flags byte + data size + data
// flags byte can be 1 or 0 for now, 1 if the var was overridden and 0 if fresh
constexpr int pktsize = 3 + sizeof(envvar_len_t);
envvar_len_t ln = var_and_val.size() + 1;
auto *ptr = var_and_val.data();

try {
std::vector<char> pkt;
pkt.reserve(pktsize + ln);
pkt.push_back((char)cp_info::ENVEVENT);
pkt.push_back(pktsize);
pkt.push_back(overridden ? 1 : 0);
pkt.insert(pkt.end(), (char *)&ln, ((char *)&ln) + sizeof(envvar_len_t));
pkt.insert(pkt.end(), ptr, ptr + ln);
queue_packet(std::move(pkt));
} catch (std::bad_alloc &exc) {
do_oom_close();
}
}

bool control_conn_t::queue_packet(const char *pkt, unsigned size) noexcept
{
bool was_empty = outbuf.empty();
Expand Down Expand Up @@ -1671,6 +1712,7 @@ control_conn_t::~control_conn_t() noexcept
for (auto p : service_key_map) {
p.first->remove_listener(this);
}
main_env.remove_listener(this);

active_control_conns--;
}
Loading

0 comments on commit 92cb58e

Please sign in to comment.