mirror of
https://github.com/systemd/systemd-stable.git
synced 2024-12-24 21:34:08 +03:00
systemctl: hook up new install logic
This adds a number of new options to systemctl, for presets, reenabling, masking/unmask, and runtime operations.
This commit is contained in:
parent
4b7a6af440
commit
729e3769c3
@ -1203,7 +1203,9 @@ systemctl_SOURCES = \
|
|||||||
src/cgroup-util.c \
|
src/cgroup-util.c \
|
||||||
src/exit-status.c \
|
src/exit-status.c \
|
||||||
src/unit-name.c \
|
src/unit-name.c \
|
||||||
src/pager.c
|
src/pager.c \
|
||||||
|
src/install.c \
|
||||||
|
src/spawn-agent.c
|
||||||
|
|
||||||
systemctl_CFLAGS = \
|
systemctl_CFLAGS = \
|
||||||
$(AM_CFLAGS) \
|
$(AM_CFLAGS) \
|
||||||
|
13
TODO
13
TODO
@ -47,8 +47,6 @@ Features:
|
|||||||
|
|
||||||
* make sure systemd-ask-password-wall does not shutdown systemd-ask-password-console too early
|
* make sure systemd-ask-password-wall does not shutdown systemd-ask-password-console too early
|
||||||
|
|
||||||
* support presets
|
|
||||||
|
|
||||||
* kernel: add /proc/sys file exposing CAP_LAST_CAP?
|
* kernel: add /proc/sys file exposing CAP_LAST_CAP?
|
||||||
|
|
||||||
* kernel: add device_type = "fb", "fbcon" to class "graphics"
|
* kernel: add device_type = "fb", "fbcon" to class "graphics"
|
||||||
@ -86,17 +84,6 @@ Features:
|
|||||||
|
|
||||||
* show enablement status in systemctl status
|
* show enablement status in systemctl status
|
||||||
|
|
||||||
* teach systemctl to enable unit files in arbitrary directories
|
|
||||||
|
|
||||||
* In systemctl make sure both is-enabled and is-active print a string, or neither.
|
|
||||||
|
|
||||||
* Implement:
|
|
||||||
systemctl mask <unit>
|
|
||||||
systemctl unmask <unit>
|
|
||||||
Also support --temp to make this temporary by placing mask links in /run.
|
|
||||||
|
|
||||||
* perhaps add "systemctl reenable" as combination of "systemctl disable" and "systemctl enable"
|
|
||||||
|
|
||||||
* add support for /bin/mount -s
|
* add support for /bin/mount -s
|
||||||
|
|
||||||
* GC unreferenced jobs (such as .device jobs)
|
* GC unreferenced jobs (such as .device jobs)
|
||||||
|
@ -351,27 +351,31 @@
|
|||||||
immediate reboot.</para></listitem>
|
immediate reboot.</para></listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
<varlistentry>
|
|
||||||
<term><option>--defaults</option></term>
|
|
||||||
|
|
||||||
<listitem><para>When used with
|
|
||||||
<command>disable</command>, ensures
|
|
||||||
that only the symlinks created by
|
|
||||||
<command>enable</command> are removed,
|
|
||||||
not all symlinks pointing to the unit
|
|
||||||
file that shall be
|
|
||||||
disabled.</para></listitem>
|
|
||||||
</varlistentry>
|
|
||||||
|
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term><option>--root=</option></term>
|
<term><option>--root=</option></term>
|
||||||
|
|
||||||
<listitem><para>When used with
|
<listitem><para>When used with
|
||||||
<command>enable</command>/
|
<command>enable</command>/<command>disable</command>/<command>is-enabled</command> (and
|
||||||
<command>disable</command>/
|
related commands), use alternative
|
||||||
<command>is-enabled</command>,
|
root path when looking for unit
|
||||||
use alternative root path for systemd
|
files.</para></listitem>
|
||||||
install.</para></listitem>
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>--runtime</option></term>
|
||||||
|
|
||||||
|
<listitem><para>When used with
|
||||||
|
<command>enable</command>/<command>disable</command>/<command>is-enabled</command> (and related commands), make
|
||||||
|
changes only temporarily, so that they
|
||||||
|
are dropped on the next reboot. This
|
||||||
|
will have the effect that changes are
|
||||||
|
not made in subdirectories of
|
||||||
|
<filename>/etc</filename> but in
|
||||||
|
<filename>/run</filename>, with
|
||||||
|
identical immediate effects, however,
|
||||||
|
since the latter is lost on reboot,
|
||||||
|
the changes are lost
|
||||||
|
too.</para></listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
@ -674,14 +678,11 @@
|
|||||||
configuration directory, and hence
|
configuration directory, and hence
|
||||||
undoes the changes made by
|
undoes the changes made by
|
||||||
<command>enable</command>. Note
|
<command>enable</command>. Note
|
||||||
however that this by default removes
|
however that this removes
|
||||||
all symlinks to the unit files
|
all symlinks to the unit files
|
||||||
(i.e. including manual additions), not
|
(i.e. including manual additions), not
|
||||||
just those actually created by
|
just those actually created by
|
||||||
<command>enable</command>. If only the
|
<command>enable</command>. This call
|
||||||
symlinks that are suggested by default
|
|
||||||
shall be removed, pass
|
|
||||||
<option>--defaults</option>. This
|
|
||||||
implicitly reloads the systemd daemon
|
implicitly reloads the systemd daemon
|
||||||
configuration after completing the
|
configuration after completing the
|
||||||
disabling of the units. Note that this
|
disabling of the units. Note that this
|
||||||
@ -713,8 +714,85 @@
|
|||||||
(as with
|
(as with
|
||||||
<command>enable</command>). Returns an
|
<command>enable</command>). Returns an
|
||||||
exit code of 0 if at least one is
|
exit code of 0 if at least one is
|
||||||
enabled, non-zero
|
enabled, non-zero otherwise. Prints
|
||||||
otherwise.</para></listitem>
|
the current enable status. To suppress
|
||||||
|
this output use
|
||||||
|
<option>--quiet</option>.</para></listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><command>reenable [NAME...]</command></term>
|
||||||
|
|
||||||
|
<listitem><para>Reenable one or more
|
||||||
|
unit files, as specified on the
|
||||||
|
command line. This is a combination of
|
||||||
|
<command>disable</command> and
|
||||||
|
<command>enable</command> and is
|
||||||
|
useful to reset the symlinks a unit is
|
||||||
|
enabled with to the defaults
|
||||||
|
configured in the
|
||||||
|
<literal>[Install]</literal> section
|
||||||
|
of the unit file.</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><command>preset [NAME...]</command></term>
|
||||||
|
|
||||||
|
<listitem><para>Reset one or more unit
|
||||||
|
files, as specified on the command
|
||||||
|
line, to the defaults configured in a
|
||||||
|
preset file. This has the same effect
|
||||||
|
as <command>disable</command> or
|
||||||
|
<command>enable</command>, depending
|
||||||
|
how the unit is listed in the preset
|
||||||
|
files.</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><command>mask [NAME...]</command></term>
|
||||||
|
|
||||||
|
<listitem><para>Mask one or more unit
|
||||||
|
files, as specified on the command
|
||||||
|
line. This will link these units to
|
||||||
|
<filename>/dev/null</filename>, making
|
||||||
|
it impossible to start them. This is a stronger version
|
||||||
|
of <command>disable</command>, since
|
||||||
|
it prohibits all kinds of activation
|
||||||
|
of the unit, including manual
|
||||||
|
activation. Use this option with
|
||||||
|
care.</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><command>unmask [NAME...]</command></term>
|
||||||
|
|
||||||
|
<listitem><para>Unmask one or more
|
||||||
|
unit files, as specified on the
|
||||||
|
command line. This will undo the
|
||||||
|
effect of
|
||||||
|
<command>mask</command>.</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><command>link [NAME...]</command></term>
|
||||||
|
|
||||||
|
<listitem><para>Link a unit file that
|
||||||
|
is not in the unit file search paths
|
||||||
|
into the unit file search path. This
|
||||||
|
requires an absolute path to a unit
|
||||||
|
file. The effect of this can be undone
|
||||||
|
with <command>disable</command>. The
|
||||||
|
effect of this command is that a unit
|
||||||
|
file is available for
|
||||||
|
<command>start</command> and other
|
||||||
|
commands although it isn't installed
|
||||||
|
directly in the unit search
|
||||||
|
path.</para>
|
||||||
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
|
@ -145,6 +145,7 @@
|
|||||||
" <arg name=\"files\" type=\"as\" direction=\"in\"/>\n" \
|
" <arg name=\"files\" type=\"as\" direction=\"in\"/>\n" \
|
||||||
" <arg name=\"runtime\" type=\"b\" direction=\"in\"/>\n" \
|
" <arg name=\"runtime\" type=\"b\" direction=\"in\"/>\n" \
|
||||||
" <arg name=\"force\" type=\"b\" direction=\"in\"/>\n" \
|
" <arg name=\"force\" type=\"b\" direction=\"in\"/>\n" \
|
||||||
|
" <arg name=\"carries_install_info\" type=\"b\" directrion=\"out\"/>\n" \
|
||||||
" <arg name=\"changes\" type=\"a(sss)\" direction=\"out\"/>\n" \
|
" <arg name=\"changes\" type=\"a(sss)\" direction=\"out\"/>\n" \
|
||||||
" </method>\n" \
|
" </method>\n" \
|
||||||
" <method name=\"DisableUnitFiles\">\n" \
|
" <method name=\"DisableUnitFiles\">\n" \
|
||||||
@ -156,6 +157,7 @@
|
|||||||
" <arg name=\"files\" type=\"as\" direction=\"in\"/>\n" \
|
" <arg name=\"files\" type=\"as\" direction=\"in\"/>\n" \
|
||||||
" <arg name=\"runtime\" type=\"b\" direction=\"in\"/>\n" \
|
" <arg name=\"runtime\" type=\"b\" direction=\"in\"/>\n" \
|
||||||
" <arg name=\"force\" type=\"b\" direction=\"in\"/>\n" \
|
" <arg name=\"force\" type=\"b\" direction=\"in\"/>\n" \
|
||||||
|
" <arg name=\"carries_install_info\" type=\"b\" directrion=\"out\"/>\n" \
|
||||||
" <arg name=\"changes\" type=\"a(sss)\" direction=\"out\"/>\n" \
|
" <arg name=\"changes\" type=\"a(sss)\" direction=\"out\"/>\n" \
|
||||||
" </method>\n" \
|
" </method>\n" \
|
||||||
" <method name=\"LinkUnitFiles\">\n" \
|
" <method name=\"LinkUnitFiles\">\n" \
|
||||||
@ -168,6 +170,7 @@
|
|||||||
" <arg name=\"files\" type=\"as\" direction=\"in\"/>\n" \
|
" <arg name=\"files\" type=\"as\" direction=\"in\"/>\n" \
|
||||||
" <arg name=\"runtime\" type=\"b\" direction=\"in\"/>\n" \
|
" <arg name=\"runtime\" type=\"b\" direction=\"in\"/>\n" \
|
||||||
" <arg name=\"force\" type=\"b\" direction=\"in\"/>\n" \
|
" <arg name=\"force\" type=\"b\" direction=\"in\"/>\n" \
|
||||||
|
" <arg name=\"carries_install_info\" type=\"b\" directrion=\"out\"/>\n" \
|
||||||
" <arg name=\"changes\" type=\"a(sss)\" direction=\"out\"/>\n" \
|
" <arg name=\"changes\" type=\"a(sss)\" direction=\"out\"/>\n" \
|
||||||
" </method>\n" \
|
" </method>\n" \
|
||||||
" <method name=\"MaskUnitFiles\">\n" \
|
" <method name=\"MaskUnitFiles\">\n" \
|
||||||
@ -422,7 +425,12 @@ static const char *message_get_sender_with_fallback(DBusMessage *m) {
|
|||||||
return ":no-sender";
|
return ":no-sender";
|
||||||
}
|
}
|
||||||
|
|
||||||
static DBusMessage *message_from_file_changes(DBusMessage *m, UnitFileChange *changes, unsigned n_changes) {
|
static DBusMessage *message_from_file_changes(
|
||||||
|
DBusMessage *m,
|
||||||
|
UnitFileChange *changes,
|
||||||
|
unsigned n_changes,
|
||||||
|
int carries_install_info) {
|
||||||
|
|
||||||
DBusMessageIter iter, sub, sub2;
|
DBusMessageIter iter, sub, sub2;
|
||||||
DBusMessage *reply;
|
DBusMessage *reply;
|
||||||
unsigned i;
|
unsigned i;
|
||||||
@ -435,6 +443,14 @@ static DBusMessage *message_from_file_changes(DBusMessage *m, UnitFileChange *ch
|
|||||||
|
|
||||||
dbus_message_iter_init_append(reply, &iter);
|
dbus_message_iter_init_append(reply, &iter);
|
||||||
|
|
||||||
|
if (carries_install_info >= 0) {
|
||||||
|
dbus_bool_t b;
|
||||||
|
|
||||||
|
b = carries_install_info;
|
||||||
|
if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b))
|
||||||
|
goto oom;
|
||||||
|
}
|
||||||
|
|
||||||
if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(sss)", &sub))
|
if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(sss)", &sub))
|
||||||
goto oom;
|
goto oom;
|
||||||
|
|
||||||
@ -446,9 +462,9 @@ static DBusMessage *message_from_file_changes(DBusMessage *m, UnitFileChange *ch
|
|||||||
source = strempty(changes[i].source);
|
source = strempty(changes[i].source);
|
||||||
|
|
||||||
if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2) ||
|
if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2) ||
|
||||||
!dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &type) ||
|
!dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &type) ||
|
||||||
!dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &path) ||
|
!dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &path) ||
|
||||||
!dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &source) ||
|
!dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &source) ||
|
||||||
!dbus_message_iter_close_container(&sub, &sub2))
|
!dbus_message_iter_close_container(&sub, &sub2))
|
||||||
goto oom;
|
goto oom;
|
||||||
}
|
}
|
||||||
@ -1304,6 +1320,7 @@ static DBusHandlerResult bus_manager_message_handler(DBusConnection *connection,
|
|||||||
UnitFileChange *changes = NULL;
|
UnitFileChange *changes = NULL;
|
||||||
unsigned n_changes = 0;
|
unsigned n_changes = 0;
|
||||||
dbus_bool_t runtime, force;
|
dbus_bool_t runtime, force;
|
||||||
|
bool carries_install_info = -1;
|
||||||
|
|
||||||
if (!dbus_message_iter_init(message, &iter))
|
if (!dbus_message_iter_init(message, &iter))
|
||||||
goto oom;
|
goto oom;
|
||||||
@ -1323,15 +1340,18 @@ static DBusHandlerResult bus_manager_message_handler(DBusConnection *connection,
|
|||||||
return bus_send_error_reply(connection, message, NULL, -EIO);
|
return bus_send_error_reply(connection, message, NULL, -EIO);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (streq(member, "EnableUnitFiles"))
|
if (streq(member, "EnableUnitFiles")) {
|
||||||
r = unit_file_enable(scope, runtime, NULL, l, force, &changes, &n_changes);
|
r = unit_file_enable(scope, runtime, NULL, l, force, &changes, &n_changes);
|
||||||
else if (streq(member, "ReenableUnitFiles"))
|
carries_install_info = r;
|
||||||
|
} else if (streq(member, "ReenableUnitFiles")) {
|
||||||
r = unit_file_reenable(scope, runtime, NULL, l, force, &changes, &n_changes);
|
r = unit_file_reenable(scope, runtime, NULL, l, force, &changes, &n_changes);
|
||||||
else if (streq(member, "LinkUnitFiles"))
|
carries_install_info = r;
|
||||||
|
} else if (streq(member, "LinkUnitFiles"))
|
||||||
r = unit_file_link(scope, runtime, NULL, l, force, &changes, &n_changes);
|
r = unit_file_link(scope, runtime, NULL, l, force, &changes, &n_changes);
|
||||||
else if (streq(member, "PresetUnitFiles"))
|
else if (streq(member, "PresetUnitFiles")) {
|
||||||
r = unit_file_preset(scope, runtime, NULL, l, force, &changes, &n_changes);
|
r = unit_file_preset(scope, runtime, NULL, l, force, &changes, &n_changes);
|
||||||
else if (streq(member, "MaskUnitFiles"))
|
carries_install_info = r;
|
||||||
|
} else if (streq(member, "MaskUnitFiles"))
|
||||||
r = unit_file_mask(scope, runtime, NULL, l, force, &changes, &n_changes);
|
r = unit_file_mask(scope, runtime, NULL, l, force, &changes, &n_changes);
|
||||||
else
|
else
|
||||||
assert_not_reached("Uh? Wrong method");
|
assert_not_reached("Uh? Wrong method");
|
||||||
@ -1344,7 +1364,7 @@ static DBusHandlerResult bus_manager_message_handler(DBusConnection *connection,
|
|||||||
return bus_send_error_reply(connection, message, NULL, r);
|
return bus_send_error_reply(connection, message, NULL, r);
|
||||||
}
|
}
|
||||||
|
|
||||||
reply = message_from_file_changes(message, changes, n_changes);
|
reply = message_from_file_changes(message, changes, n_changes, carries_install_info);
|
||||||
unit_file_changes_free(changes, n_changes);
|
unit_file_changes_free(changes, n_changes);
|
||||||
|
|
||||||
if (!reply)
|
if (!reply)
|
||||||
@ -1392,7 +1412,7 @@ static DBusHandlerResult bus_manager_message_handler(DBusConnection *connection,
|
|||||||
return bus_send_error_reply(connection, message, NULL, r);
|
return bus_send_error_reply(connection, message, NULL, r);
|
||||||
}
|
}
|
||||||
|
|
||||||
reply = message_from_file_changes(message, changes, n_changes);
|
reply = message_from_file_changes(message, changes, n_changes, -1);
|
||||||
unit_file_changes_free(changes, n_changes);
|
unit_file_changes_free(changes, n_changes);
|
||||||
|
|
||||||
if (!reply)
|
if (!reply)
|
||||||
|
@ -596,16 +596,16 @@ Hashmap *hashmap_copy(Hashmap *h) {
|
|||||||
char **hashmap_get_strv(Hashmap *h) {
|
char **hashmap_get_strv(Hashmap *h) {
|
||||||
char **sv;
|
char **sv;
|
||||||
Iterator it;
|
Iterator it;
|
||||||
char *path;
|
char *item;
|
||||||
int n;
|
int n;
|
||||||
|
|
||||||
sv = malloc((h->n_entries+1) * sizeof(char *));
|
sv = new(char*, h->n_entries+1);
|
||||||
if (sv == NULL)
|
if (!sv)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
n = 0;
|
n = 0;
|
||||||
HASHMAP_FOREACH(path, h, it)
|
HASHMAP_FOREACH(item, h, it)
|
||||||
sv[n++] = path;
|
sv[n++] = item;
|
||||||
sv[n] = NULL;
|
sv[n] = NULL;
|
||||||
|
|
||||||
return sv;
|
return sv;
|
||||||
|
@ -126,8 +126,6 @@ static int add_file_change(
|
|||||||
UnitFileChange *c;
|
UnitFileChange *c;
|
||||||
unsigned i;
|
unsigned i;
|
||||||
|
|
||||||
assert(type >= 0);
|
|
||||||
assert(type < _UNIT_FILE_CHANGE_TYPE_MAX);
|
|
||||||
assert(path);
|
assert(path);
|
||||||
assert(!changes == !n_changes);
|
assert(!changes == !n_changes);
|
||||||
|
|
||||||
@ -1414,6 +1412,10 @@ int unit_file_enable(
|
|||||||
goto finish;
|
goto finish;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* This will return the number of symlink rules that were
|
||||||
|
supposed to be created, not the ones actually created. This is
|
||||||
|
useful to determine whether the passed files hat any
|
||||||
|
installation data at all. */
|
||||||
r = install_context_apply(&c, &paths, config_path, root_dir, force, changes, n_changes);
|
r = install_context_apply(&c, &paths, config_path, root_dir, force, changes, n_changes);
|
||||||
|
|
||||||
finish:
|
finish:
|
||||||
@ -1514,6 +1516,7 @@ int unit_file_reenable(
|
|||||||
|
|
||||||
r = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes);
|
r = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes);
|
||||||
|
|
||||||
|
/* Returns number of symlinks that where supposed to be installed. */
|
||||||
q = install_context_apply(&c, &paths, config_path, root_dir, force, changes, n_changes);
|
q = install_context_apply(&c, &paths, config_path, root_dir, force, changes, n_changes);
|
||||||
if (r == 0)
|
if (r == 0)
|
||||||
r = q;
|
r = q;
|
||||||
@ -1763,6 +1766,7 @@ int unit_file_preset(
|
|||||||
if (r == 0)
|
if (r == 0)
|
||||||
r = q;
|
r = q;
|
||||||
|
|
||||||
|
/* Returns number of symlinks that where supposed to be installed. */
|
||||||
q = install_context_apply(&plus, &paths, config_path, root_dir, force, changes, n_changes);
|
q = install_context_apply(&plus, &paths, config_path, root_dir, force, changes, n_changes);
|
||||||
if (r == 0)
|
if (r == 0)
|
||||||
r = q;
|
r = q;
|
||||||
|
@ -62,6 +62,14 @@
|
|||||||
send_interface="org.freedesktop.systemd1.Manager"
|
send_interface="org.freedesktop.systemd1.Manager"
|
||||||
send_member="ListUnits"/>
|
send_member="ListUnits"/>
|
||||||
|
|
||||||
|
<allow send_destination="org.freedesktop.systemd1"
|
||||||
|
send_interface="org.freedesktop.systemd1.Manager"
|
||||||
|
send_member="ListUnitFiles"/>
|
||||||
|
|
||||||
|
<allow send_destination="org.freedesktop.systemd1"
|
||||||
|
send_interface="org.freedesktop.systemd1.Manager"
|
||||||
|
send_member="GetUnitFileState"/>
|
||||||
|
|
||||||
<allow send_destination="org.freedesktop.systemd1"
|
<allow send_destination="org.freedesktop.systemd1"
|
||||||
send_interface="org.freedesktop.systemd1.Manager"
|
send_interface="org.freedesktop.systemd1.Manager"
|
||||||
send_member="ListJobs"/>
|
send_member="ListJobs"/>
|
||||||
|
@ -39,13 +39,13 @@ void pager_open(void) {
|
|||||||
if (pager_pid > 0)
|
if (pager_pid > 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (isatty(STDOUT_FILENO) <= 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if ((pager = getenv("SYSTEMD_PAGER")) || (pager = getenv("PAGER")))
|
if ((pager = getenv("SYSTEMD_PAGER")) || (pager = getenv("PAGER")))
|
||||||
if (!*pager || streq(pager, "cat"))
|
if (!*pager || streq(pager, "cat"))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (isatty(STDOUT_FILENO) <= 0)
|
||||||
|
return;
|
||||||
|
|
||||||
/* Determine and cache number of columns before we spawn the
|
/* Determine and cache number of columns before we spawn the
|
||||||
* pager so that we get the value from the actual tty */
|
* pager so that we get the value from the actual tty */
|
||||||
columns();
|
columns();
|
||||||
|
120
src/spawn-agent.c
Normal file
120
src/spawn-agent.c
Normal file
@ -0,0 +1,120 @@
|
|||||||
|
/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
|
||||||
|
|
||||||
|
/***
|
||||||
|
This file is part of systemd.
|
||||||
|
|
||||||
|
Copyright 2011 Lennart Poettering
|
||||||
|
|
||||||
|
systemd is free software; you can redistribute it and/or modify it
|
||||||
|
under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
systemd is distributed in the hope that it will be useful, but
|
||||||
|
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with systemd; If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
***/
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/prctl.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
|
||||||
|
#include "log.h"
|
||||||
|
#include "util.h"
|
||||||
|
#include "spawn-agent.h"
|
||||||
|
|
||||||
|
static pid_t agent_pid = 0;
|
||||||
|
|
||||||
|
void agent_open(void) {
|
||||||
|
pid_t parent_pid;
|
||||||
|
|
||||||
|
if (agent_pid > 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* We check STDIN here, not STDOUT, since this is about input,
|
||||||
|
* not output */
|
||||||
|
if (!isatty(STDIN_FILENO))
|
||||||
|
return;
|
||||||
|
|
||||||
|
parent_pid = getpid();
|
||||||
|
|
||||||
|
/* Spawns a temporary TTY agent, making sure it goes away when
|
||||||
|
* we go away */
|
||||||
|
|
||||||
|
agent_pid = fork();
|
||||||
|
if (agent_pid < 0) {
|
||||||
|
log_error("Failed to fork agent: %m");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (agent_pid == 0) {
|
||||||
|
/* In the child */
|
||||||
|
|
||||||
|
int fd;
|
||||||
|
bool stdout_is_tty, stderr_is_tty;
|
||||||
|
|
||||||
|
/* Make sure the agent goes away when the parent dies */
|
||||||
|
if (prctl(PR_SET_PDEATHSIG, SIGTERM) < 0)
|
||||||
|
_exit(EXIT_FAILURE);
|
||||||
|
|
||||||
|
/* Check whether our parent died before we were able
|
||||||
|
* to set the death signal */
|
||||||
|
if (getppid() != parent_pid)
|
||||||
|
_exit(EXIT_SUCCESS);
|
||||||
|
|
||||||
|
/* Don't leak fds to the agent */
|
||||||
|
close_all_fds(NULL, 0);
|
||||||
|
|
||||||
|
stdout_is_tty = isatty(STDOUT_FILENO);
|
||||||
|
stderr_is_tty = isatty(STDERR_FILENO);
|
||||||
|
|
||||||
|
if (!stdout_is_tty || !stderr_is_tty) {
|
||||||
|
/* Detach from stdout/stderr. and reopen
|
||||||
|
* /dev/tty for them. This is important to
|
||||||
|
* ensure that when systemctl is started via
|
||||||
|
* popen() or a similar call that expects to
|
||||||
|
* read EOF we actually do generate EOF and
|
||||||
|
* not delay this indefinitely by because we
|
||||||
|
* keep an unused copy of stdin around. */
|
||||||
|
fd = open("/dev/tty", O_WRONLY);
|
||||||
|
if (fd < 0) {
|
||||||
|
log_error("Failed to open /dev/tty: %m");
|
||||||
|
_exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!stdout_is_tty)
|
||||||
|
dup2(fd, STDOUT_FILENO);
|
||||||
|
|
||||||
|
if (!stderr_is_tty)
|
||||||
|
dup2(fd, STDERR_FILENO);
|
||||||
|
|
||||||
|
if (fd > 2)
|
||||||
|
close(fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
execl(SYSTEMD_TTY_ASK_PASSWORD_AGENT_BINARY_PATH, SYSTEMD_TTY_ASK_PASSWORD_AGENT_BINARY_PATH, "--watch", NULL);
|
||||||
|
|
||||||
|
log_error("Unable to execute agent: %m");
|
||||||
|
_exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void agent_close(void) {
|
||||||
|
|
||||||
|
if (agent_pid <= 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* Inform agent that we are done */
|
||||||
|
kill(agent_pid, SIGTERM);
|
||||||
|
kill(agent_pid, SIGCONT);
|
||||||
|
wait_for_terminate(agent_pid, NULL);
|
||||||
|
agent_pid = 0;
|
||||||
|
}
|
28
src/spawn-agent.h
Normal file
28
src/spawn-agent.h
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
|
||||||
|
|
||||||
|
#ifndef foospawnagenthfoo
|
||||||
|
#define foospawnagenthfoo
|
||||||
|
|
||||||
|
/***
|
||||||
|
This file is part of systemd.
|
||||||
|
|
||||||
|
Copyright 2011 Lennart Poettering
|
||||||
|
|
||||||
|
systemd is free software; you can redistribute it and/or modify it
|
||||||
|
under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
systemd is distributed in the hope that it will be useful, but
|
||||||
|
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with systemd; If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
***/
|
||||||
|
|
||||||
|
void agent_open(void);
|
||||||
|
void agent_close(void);
|
||||||
|
|
||||||
|
#endif
|
1740
src/systemctl.c
1740
src/systemctl.c
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user