summaryrefslogtreecommitdiff
path: root/src/core
diff options
context:
space:
mode:
Diffstat (limited to 'src/core')
-rw-r--r--src/core/automount.c24
-rw-r--r--src/core/automount.h12
-rw-r--r--src/core/busname.c26
-rw-r--r--src/core/busname.h17
-rw-r--r--src/core/dbus-execute.c87
-rw-r--r--src/core/dbus-manager.c23
-rw-r--r--src/core/dbus-service.c32
-rw-r--r--src/core/dbus-socket.c21
-rw-r--r--src/core/device.c8
-rw-r--r--src/core/device.h13
-rw-r--r--src/core/execute.c271
-rw-r--r--src/core/execute.h29
-rw-r--r--src/core/load-fragment-gperf.gperf.m44
-rw-r--r--src/core/load-fragment.c588
-rw-r--r--src/core/load-fragment.h2
-rw-r--r--src/core/machine-id-setup.c19
-rw-r--r--src/core/main.c458
-rw-r--r--src/core/manager.c67
-rw-r--r--src/core/manager.h6
-rw-r--r--src/core/mount.c21
-rw-r--r--src/core/mount.h21
-rw-r--r--src/core/namespace.c44
-rw-r--r--src/core/path.c9
-rw-r--r--src/core/path.h12
-rw-r--r--src/core/scope.c11
-rw-r--r--src/core/scope.h14
-rw-r--r--src/core/selinux-setup.c6
-rw-r--r--src/core/service.c310
-rw-r--r--src/core/service.h29
-rw-r--r--src/core/shutdown.c1
-rw-r--r--src/core/slice.c7
-rw-r--r--src/core/slice.h11
-rw-r--r--src/core/smack-setup.c9
-rw-r--r--src/core/snapshot.c7
-rw-r--r--src/core/snapshot.h11
-rw-r--r--src/core/socket.c322
-rw-r--r--src/core/socket.h32
-rw-r--r--src/core/swap.c18
-rw-r--r--src/core/swap.h19
-rw-r--r--src/core/system.conf6
-rw-r--r--src/core/target.c7
-rw-r--r--src/core/target.h11
-rw-r--r--src/core/timer.c10
-rw-r--r--src/core/timer.h13
-rw-r--r--src/core/unit.c82
-rw-r--r--src/core/unit.h23
46 files changed, 1389 insertions, 1384 deletions
diff --git a/src/core/automount.c b/src/core/automount.c
index c88e3311bc..e0535ec201 100644
--- a/src/core/automount.c
+++ b/src/core/automount.c
@@ -774,8 +774,9 @@ static int automount_stop(Unit *u) {
static int automount_serialize(Unit *u, FILE *f, FDSet *fds) {
Automount *a = AUTOMOUNT(u);
- void *p;
Iterator i;
+ void *p;
+ int r;
assert(a);
assert(f);
@@ -790,15 +791,9 @@ static int automount_serialize(Unit *u, FILE *f, FDSet *fds) {
SET_FOREACH(p, a->expire_tokens, i)
unit_serialize_item_format(u, f, "expire-token", "%u", PTR_TO_UINT(p));
- if (a->pipe_fd >= 0) {
- int copy;
-
- copy = fdset_put_dup(fds, a->pipe_fd);
- if (copy < 0)
- return copy;
-
- unit_serialize_item_format(u, f, "pipe-fd", "%i", copy);
- }
+ r = unit_serialize_item_fd(u, f, fds, "pipe-fd", a->pipe_fd);
+ if (r < 0)
+ return r;
return 0;
}
@@ -1024,15 +1019,6 @@ static bool automount_supported(void) {
return supported;
}
-static const char* const automount_state_table[_AUTOMOUNT_STATE_MAX] = {
- [AUTOMOUNT_DEAD] = "dead",
- [AUTOMOUNT_WAITING] = "waiting",
- [AUTOMOUNT_RUNNING] = "running",
- [AUTOMOUNT_FAILED] = "failed"
-};
-
-DEFINE_STRING_TABLE_LOOKUP(automount_state, AutomountState);
-
static const char* const automount_result_table[_AUTOMOUNT_RESULT_MAX] = {
[AUTOMOUNT_SUCCESS] = "success",
[AUTOMOUNT_FAILURE_RESOURCES] = "resources"
diff --git a/src/core/automount.h b/src/core/automount.h
index 2a50fef68d..43ea9f772d 100644
--- a/src/core/automount.h
+++ b/src/core/automount.h
@@ -25,15 +25,6 @@ typedef struct Automount Automount;
#include "unit.h"
-typedef enum AutomountState {
- AUTOMOUNT_DEAD,
- AUTOMOUNT_WAITING,
- AUTOMOUNT_RUNNING,
- AUTOMOUNT_FAILED,
- _AUTOMOUNT_STATE_MAX,
- _AUTOMOUNT_STATE_INVALID = -1
-} AutomountState;
-
typedef enum AutomountResult {
AUTOMOUNT_SUCCESS,
AUTOMOUNT_FAILURE_RESOURCES,
@@ -66,8 +57,5 @@ extern const UnitVTable automount_vtable;
int automount_update_mount(Automount *a, MountState old_state, MountState state);
-const char* automount_state_to_string(AutomountState i) _const_;
-AutomountState automount_state_from_string(const char *s) _pure_;
-
const char* automount_result_to_string(AutomountResult i) _const_;
AutomountResult automount_result_from_string(const char *s) _pure_;
diff --git a/src/core/busname.c b/src/core/busname.c
index 4020e9dd3c..38becfc119 100644
--- a/src/core/busname.c
+++ b/src/core/busname.c
@@ -656,6 +656,7 @@ static int busname_stop(Unit *u) {
static int busname_serialize(Unit *u, FILE *f, FDSet *fds) {
BusName *n = BUSNAME(u);
+ int r;
assert(n);
assert(f);
@@ -667,15 +668,9 @@ static int busname_serialize(Unit *u, FILE *f, FDSet *fds) {
if (n->control_pid > 0)
unit_serialize_item_format(u, f, "control-pid", PID_FMT, n->control_pid);
- if (n->starter_fd >= 0) {
- int copy;
-
- copy = fdset_put_dup(fds, n->starter_fd);
- if (copy < 0)
- return copy;
-
- unit_serialize_item_format(u, f, "starter-fd", "%i", copy);
- }
+ r = unit_serialize_item_fd(u, f, fds, "starter-fd", n->starter_fd);
+ if (r < 0)
+ return r;
return 0;
}
@@ -991,19 +986,6 @@ static bool busname_supported(void) {
return supported;
}
-static const char* const busname_state_table[_BUSNAME_STATE_MAX] = {
- [BUSNAME_DEAD] = "dead",
- [BUSNAME_MAKING] = "making",
- [BUSNAME_REGISTERED] = "registered",
- [BUSNAME_LISTENING] = "listening",
- [BUSNAME_RUNNING] = "running",
- [BUSNAME_SIGTERM] = "sigterm",
- [BUSNAME_SIGKILL] = "sigkill",
- [BUSNAME_FAILED] = "failed",
-};
-
-DEFINE_STRING_TABLE_LOOKUP(busname_state, BusNameState);
-
static const char* const busname_result_table[_BUSNAME_RESULT_MAX] = {
[BUSNAME_SUCCESS] = "success",
[BUSNAME_FAILURE_RESOURCES] = "resources",
diff --git a/src/core/busname.h b/src/core/busname.h
index 69528a2aef..1bc3290596 100644
--- a/src/core/busname.h
+++ b/src/core/busname.h
@@ -24,20 +24,6 @@
typedef struct BusName BusName;
typedef struct BusNamePolicy BusNamePolicy;
-
-typedef enum BusNameState {
- BUSNAME_DEAD,
- BUSNAME_MAKING,
- BUSNAME_REGISTERED,
- BUSNAME_LISTENING,
- BUSNAME_RUNNING,
- BUSNAME_SIGTERM,
- BUSNAME_SIGKILL,
- BUSNAME_FAILED,
- _BUSNAME_STATE_MAX,
- _BUSNAME_STATE_INVALID = -1
-} BusNameState;
-
typedef enum BusNameResult {
BUSNAME_SUCCESS,
BUSNAME_FAILURE_RESOURCES,
@@ -77,8 +63,5 @@ struct BusName {
extern const UnitVTable busname_vtable;
-const char* busname_state_to_string(BusNameState i) _const_;
-BusNameState busname_state_from_string(const char *s) _pure_;
-
const char* busname_result_to_string(BusNameResult i) _const_;
BusNameResult busname_result_from_string(const char *s) _pure_;
diff --git a/src/core/dbus-execute.c b/src/core/dbus-execute.c
index 868c8cc05a..adf613d328 100644
--- a/src/core/dbus-execute.c
+++ b/src/core/dbus-execute.c
@@ -595,6 +595,33 @@ static int property_get_address_families(
return sd_bus_message_close_container(reply);
}
+static int property_get_working_directory(
+ sd_bus *bus,
+ const char *path,
+ const char *interface,
+ const char *property,
+ sd_bus_message *reply,
+ void *userdata,
+ sd_bus_error *error) {
+
+ ExecContext *c = userdata;
+ const char *wd;
+
+ assert(bus);
+ assert(reply);
+ assert(c);
+
+ if (c->working_directory_home)
+ wd = "~";
+ else
+ wd = c->working_directory;
+
+ if (c->working_directory_missing_ok)
+ wd = strjoina("!", wd);
+
+ return sd_bus_message_append(reply, "s", wd);
+}
+
const sd_bus_vtable bus_exec_vtable[] = {
SD_BUS_VTABLE_START(0),
SD_BUS_PROPERTY("Environment", "as", NULL, offsetof(ExecContext, environment), SD_BUS_VTABLE_PROPERTY_CONST),
@@ -616,7 +643,7 @@ const sd_bus_vtable bus_exec_vtable[] = {
SD_BUS_PROPERTY("LimitNICE", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_NICE]), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("LimitRTPRIO", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_RTPRIO]), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("LimitRTTIME", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_RTTIME]), SD_BUS_VTABLE_PROPERTY_CONST),
- SD_BUS_PROPERTY("WorkingDirectory", "s", NULL, offsetof(ExecContext, working_directory), SD_BUS_VTABLE_PROPERTY_CONST),
+ SD_BUS_PROPERTY("WorkingDirectory", "s", property_get_working_directory, 0, SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("RootDirectory", "s", NULL, offsetof(ExecContext, root_directory), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("OOMScoreAdjust", "i", property_get_oom_score_adjust, 0, SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("Nice", "i", property_get_nice, 0, SD_BUS_VTABLE_PROPERTY_CONST),
@@ -847,8 +874,7 @@ int bus_exec_context_set_transient_property(
return 1;
- } else if (STR_IN_SET(name,
- "TTYPath", "WorkingDirectory", "RootDirectory")) {
+ } else if (STR_IN_SET(name, "TTYPath", "RootDirectory")) {
const char *s;
r = sd_bus_message_read(message, "s", &s);
@@ -859,24 +885,51 @@ int bus_exec_context_set_transient_property(
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "%s takes an absolute path", name);
if (mode != UNIT_CHECK) {
- char *t;
+ if (streq(name, "TTYPath"))
+ r = free_and_strdup(&c->tty_path, s);
+ else {
+ assert(streq(name, "RootDirectory"));
+ r = free_and_strdup(&c->root_directory, s);
+ }
+ if (r < 0)
+ return r;
- t = strdup(s);
- if (!t)
- return -ENOMEM;
+ unit_write_drop_in_private_format(u, mode, name, "%s=%s\n", name, s);
+ }
- if (streq(name, "TTYPath")) {
- free(c->tty_path);
- c->tty_path = t;
- } else if (streq(name, "WorkingDirectory")) {
- free(c->working_directory);
- c->working_directory = t;
- } else if (streq(name, "RootDirectory")) {
- free(c->root_directory);
- c->root_directory = t;
+ return 1;
+
+ } else if (streq(name, "WorkingDirectory")) {
+ const char *s;
+ bool missing_ok;
+
+ r = sd_bus_message_read(message, "s", &s);
+ if (r < 0)
+ return r;
+
+ if (s[0] == '-') {
+ missing_ok = true;
+ s++;
+ } else
+ missing_ok = false;
+
+ if (!streq(s, "~") && !path_is_absolute(s))
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "WorkingDirectory= expects an absolute path or '~'");
+
+ if (mode != UNIT_CHECK) {
+ if (streq(s, "~")) {
+ c->working_directory = mfree(c->working_directory);
+ c->working_directory_home = true;
+ } else {
+ r = free_and_strdup(&c->working_directory, s);
+ if (r < 0)
+ return r;
+
+ c->working_directory_home = false;
}
- unit_write_drop_in_private_format(u, mode, name, "%s=%s\n", name, s);
+ c->working_directory_missing_ok = missing_ok;
+ unit_write_drop_in_private_format(u, mode, name, "WorkingDirectory=%s%s", missing_ok ? "-" : "", s);
}
return 1;
diff --git a/src/core/dbus-manager.c b/src/core/dbus-manager.c
index 561b6f8bfa..9e21b0787d 100644
--- a/src/core/dbus-manager.c
+++ b/src/core/dbus-manager.c
@@ -81,10 +81,21 @@ static int property_get_virtualization(
void *userdata,
sd_bus_error *error) {
+ int v;
+
assert(bus);
assert(reply);
- return sd_bus_message_append(reply, "s", virtualization_to_string(detect_virtualization()));
+ v = detect_virtualization();
+
+ /* Make sure to return the empty string when we detect no virtualization, as that is the API.
+ *
+ * https://github.com/systemd/systemd/issues/1423
+ */
+
+ return sd_bus_message_append(
+ reply, "s",
+ v == VIRTUALIZATION_NONE ? "" : virtualization_to_string(v));
}
static int property_get_architecture(
@@ -1960,6 +1971,16 @@ const sd_bus_vtable bus_manager_vtable[] = {
SD_BUS_PROPERTY("ControlGroup", "s", NULL, offsetof(Manager, cgroup_root), 0),
SD_BUS_PROPERTY("SystemState", "s", property_get_system_state, 0, 0),
SD_BUS_PROPERTY("ExitCode", "y", bus_property_get_unsigned, offsetof(Manager, return_value), 0),
+ SD_BUS_PROPERTY("DefaultTimerAccuracyUSec", "t", bus_property_get_usec, offsetof(Manager, default_timer_accuracy_usec), SD_BUS_VTABLE_PROPERTY_CONST),
+ SD_BUS_PROPERTY("DefaultTimeoutStartUSec", "t", bus_property_get_usec, offsetof(Manager, default_timeout_start_usec), SD_BUS_VTABLE_PROPERTY_CONST),
+ SD_BUS_PROPERTY("DefaultTimeoutStopUSec", "t", bus_property_get_usec, offsetof(Manager, default_timeout_stop_usec), SD_BUS_VTABLE_PROPERTY_CONST),
+ SD_BUS_PROPERTY("DefaultRestartUSec", "t", bus_property_get_usec, offsetof(Manager, default_restart_usec), SD_BUS_VTABLE_PROPERTY_CONST),
+ SD_BUS_PROPERTY("DefaultStartLimitInterval", "t", bus_property_get_usec, offsetof(Manager, default_start_limit_interval), SD_BUS_VTABLE_PROPERTY_CONST),
+ SD_BUS_PROPERTY("DefaultStartLimitBurst", "u", bus_property_get_unsigned, offsetof(Manager, default_start_limit_burst), SD_BUS_VTABLE_PROPERTY_CONST),
+ SD_BUS_PROPERTY("DefaultCPUAccounting", "b", bus_property_get_bool, offsetof(Manager, default_cpu_accounting), SD_BUS_VTABLE_PROPERTY_CONST),
+ SD_BUS_PROPERTY("DefaultBlockIOAccounting", "b", bus_property_get_bool, offsetof(Manager, default_blockio_accounting), SD_BUS_VTABLE_PROPERTY_CONST),
+ SD_BUS_PROPERTY("DefaultMemoryAccounting", "b", bus_property_get_bool, offsetof(Manager, default_memory_accounting), SD_BUS_VTABLE_PROPERTY_CONST),
+ SD_BUS_PROPERTY("DefaultTasksAccounting", "b", bus_property_get_bool, offsetof(Manager, default_tasks_accounting), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_METHOD("GetUnit", "s", "o", method_get_unit, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("GetUnitByPID", "u", "o", method_get_unit_by_pid, SD_BUS_VTABLE_UNPRIVILEGED),
diff --git a/src/core/dbus-service.c b/src/core/dbus-service.c
index 3436342bef..b636f8ba6a 100644
--- a/src/core/dbus-service.c
+++ b/src/core/dbus-service.c
@@ -19,6 +19,7 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include "async.h"
#include "strv.h"
#include "path-util.h"
#include "unit.h"
@@ -120,6 +121,37 @@ static int bus_service_set_transient_property(
return 1;
+ } else if (STR_IN_SET(name,
+ "StandardInputFileDescriptor",
+ "StandardOutputFileDescriptor",
+ "StandardErrorFileDescriptor")) {
+ int fd;
+
+ r = sd_bus_message_read(message, "h", &fd);
+ if (r < 0)
+ return r;
+
+ if (mode != UNIT_CHECK) {
+ int copy;
+
+ copy = fcntl(fd, F_DUPFD_CLOEXEC, 3);
+ if (copy < 0)
+ return -errno;
+
+ if (streq(name, "StandardInputFileDescriptor")) {
+ asynchronous_close(s->stdin_fd);
+ s->stdin_fd = copy;
+ } else if (streq(name, "StandardOutputFileDescriptor")) {
+ asynchronous_close(s->stdout_fd);
+ s->stdout_fd = copy;
+ } else {
+ asynchronous_close(s->stderr_fd);
+ s->stderr_fd = copy;
+ }
+ }
+
+ return 1;
+
} else if (streq(name, "ExecStart")) {
unsigned n = 0;
diff --git a/src/core/dbus-socket.c b/src/core/dbus-socket.c
index 86732e2a45..7444649f8b 100644
--- a/src/core/dbus-socket.c
+++ b/src/core/dbus-socket.c
@@ -84,6 +84,25 @@ static int property_get_listen(
return sd_bus_message_close_container(reply);
}
+
+static int property_get_fdname(
+ sd_bus *bus,
+ const char *path,
+ const char *interface,
+ const char *property,
+ sd_bus_message *reply,
+ void *userdata,
+ sd_bus_error *error) {
+
+ Socket *s = SOCKET(userdata);
+
+ assert(bus);
+ assert(reply);
+ assert(s);
+
+ return sd_bus_message_append(reply, "s", socket_fdname(s));
+}
+
const sd_bus_vtable bus_socket_vtable[] = {
SD_BUS_VTABLE_START(0),
SD_BUS_PROPERTY("BindIPv6Only", "s", property_get_bind_ipv6_only, offsetof(Socket, bind_ipv6_only), SD_BUS_VTABLE_PROPERTY_CONST),
@@ -95,6 +114,7 @@ const sd_bus_vtable bus_socket_vtable[] = {
SD_BUS_PROPERTY("SocketMode", "u", bus_property_get_mode, offsetof(Socket, socket_mode), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("DirectoryMode", "u", bus_property_get_mode, offsetof(Socket, directory_mode), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("Accept", "b", bus_property_get_bool, offsetof(Socket, accept), SD_BUS_VTABLE_PROPERTY_CONST),
+ SD_BUS_PROPERTY("Writable", "b", bus_property_get_bool, offsetof(Socket, writable), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("KeepAlive", "b", bus_property_get_bool, offsetof(Socket, keep_alive), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("KeepAliveTimeUSec", "t", bus_property_get_usec, offsetof(Socket, keep_alive_time), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("KeepAliveIntervalUSec", "t", bus_property_get_usec, offsetof(Socket, keep_alive_interval), SD_BUS_VTABLE_PROPERTY_CONST),
@@ -127,6 +147,7 @@ const sd_bus_vtable bus_socket_vtable[] = {
SD_BUS_PROPERTY("Result", "s", property_get_result, offsetof(Socket, result), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
SD_BUS_PROPERTY("NConnections", "u", bus_property_get_unsigned, offsetof(Socket, n_connections), 0),
SD_BUS_PROPERTY("NAccepted", "u", bus_property_get_unsigned, offsetof(Socket, n_accepted), 0),
+ SD_BUS_PROPERTY("FileDescriptorName", "s", property_get_fdname, 0, 0),
BUS_EXEC_COMMAND_LIST_VTABLE("ExecStartPre", offsetof(Socket, exec_command[SOCKET_EXEC_START_PRE]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION),
BUS_EXEC_COMMAND_LIST_VTABLE("ExecStartPost", offsetof(Socket, exec_command[SOCKET_EXEC_START_POST]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION),
BUS_EXEC_COMMAND_LIST_VTABLE("ExecStopPre", offsetof(Socket, exec_command[SOCKET_EXEC_STOP_PRE]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION),
diff --git a/src/core/device.c b/src/core/device.c
index 0b54518691..a819ab8d4e 100644
--- a/src/core/device.c
+++ b/src/core/device.c
@@ -816,14 +816,6 @@ int device_found_node(Manager *m, const char *node, bool add, DeviceFound found,
return device_update_found_by_name(m, node, add, found, now);
}
-static const char* const device_state_table[_DEVICE_STATE_MAX] = {
- [DEVICE_DEAD] = "dead",
- [DEVICE_TENTATIVE] = "tentative",
- [DEVICE_PLUGGED] = "plugged",
-};
-
-DEFINE_STRING_TABLE_LOOKUP(device_state, DeviceState);
-
const UnitVTable device_vtable = {
.object_size = sizeof(Device),
.sections =
diff --git a/src/core/device.h b/src/core/device.h
index 10ab113176..da8737870b 100644
--- a/src/core/device.h
+++ b/src/core/device.h
@@ -23,16 +23,6 @@
typedef struct Device Device;
-/* We simply watch devices, we cannot plug/unplug them. That
- * simplifies the state engine greatly */
-typedef enum DeviceState {
- DEVICE_DEAD,
- DEVICE_TENTATIVE, /* mounted or swapped, but not (yet) announced by udev */
- DEVICE_PLUGGED, /* announced by udev */
- _DEVICE_STATE_MAX,
- _DEVICE_STATE_INVALID = -1
-} DeviceState;
-
typedef enum DeviceFound {
DEVICE_NOT_FOUND = 0,
DEVICE_FOUND_UDEV = 1,
@@ -56,7 +46,4 @@ struct Device {
extern const UnitVTable device_vtable;
-const char* device_state_to_string(DeviceState i) _const_;
-DeviceState device_state_from_string(const char *s) _pure_;
-
int device_found_node(Manager *m, const char *node, bool add, DeviceFound found, bool now);
diff --git a/src/core/execute.c b/src/core/execute.c
index 7796c07fcf..d6217840c0 100644
--- a/src/core/execute.c
+++ b/src/core/execute.c
@@ -21,18 +21,18 @@
#include <errno.h>
#include <fcntl.h>
-#include <unistd.h>
-#include <string.h>
+#include <glob.h>
+#include <grp.h>
+#include <poll.h>
#include <signal.h>
-#include <sys/socket.h>
-#include <sys/un.h>
+#include <string.h>
+#include <sys/personality.h>
#include <sys/prctl.h>
+#include <sys/socket.h>
#include <sys/stat.h>
-#include <grp.h>
-#include <poll.h>
-#include <glob.h>
+#include <sys/un.h>
+#include <unistd.h>
#include <utmpx.h>
-#include <sys/personality.h>
#ifdef HAVE_PAM
#include <security/pam_appl.h>
@@ -50,37 +50,38 @@
#include <sys/apparmor.h>
#endif
-#include "barrier.h"
#include "sd-messages.h"
-#include "rm-rf.h"
-#include "strv.h"
-#include "macro.h"
+
+#include "af-list.h"
+#include "async.h"
+#include "barrier.h"
+#include "bus-endpoint.h"
+#include "cap-list.h"
#include "capability.h"
-#include "util.h"
-#include "log.h"
-#include "ioprio.h"
-#include "securebits.h"
-#include "namespace.h"
-#include "exit-status.h"
-#include "missing.h"
-#include "utmp-wtmp.h"
#include "def.h"
-#include "path-util.h"
#include "env-util.h"
-#include "fileio.h"
-#include "unit.h"
-#include "async.h"
-#include "selinux-util.h"
#include "errno-list.h"
-#include "af-list.h"
-#include "mkdir.h"
-#include "smack-util.h"
-#include "bus-endpoint.h"
-#include "cap-list.h"
+#include "exit-status.h"
+#include "fileio.h"
#include "formats-util.h"
+#include "ioprio.h"
+#include "log.h"
+#include "macro.h"
+#include "missing.h"
+#include "mkdir.h"
+#include "namespace.h"
+#include "path-util.h"
#include "process-util.h"
-#include "terminal-util.h"
+#include "rm-rf.h"
+#include "securebits.h"
+#include "selinux-util.h"
#include "signal-util.h"
+#include "smack-util.h"
+#include "strv.h"
+#include "terminal-util.h"
+#include "unit.h"
+#include "util.h"
+#include "utmp-wtmp.h"
#ifdef HAVE_APPARMOR
#include "apparmor-util.h"
@@ -358,12 +359,28 @@ static int fixup_output(ExecOutput std_output, int socket_fd) {
return std_output;
}
-static int setup_input(const ExecContext *context, int socket_fd, bool apply_tty_stdin) {
+static int setup_input(
+ const ExecContext *context,
+ const ExecParameters *params,
+ int socket_fd) {
+
ExecInput i;
assert(context);
+ assert(params);
- i = fixup_input(context->std_input, socket_fd, apply_tty_stdin);
+ if (params->stdin_fd >= 0) {
+ if (dup2(params->stdin_fd, STDIN_FILENO) < 0)
+ return -errno;
+
+ /* Try to make this the controlling tty, if it is a tty, and reset it */
+ (void) ioctl(STDIN_FILENO, TIOCSCTTY, context->std_input == EXEC_INPUT_TTY_FORCE);
+ (void) reset_terminal_fd(STDIN_FILENO, true);
+
+ return STDIN_FILENO;
+ }
+
+ i = fixup_input(context->std_input, socket_fd, params->apply_tty_stdin);
switch (i) {
@@ -400,16 +417,40 @@ static int setup_input(const ExecContext *context, int socket_fd, bool apply_tty
}
}
-static int setup_output(Unit *unit, const ExecContext *context, int fileno, int socket_fd, const char *ident, bool apply_tty_stdin, uid_t uid, gid_t gid) {
+static int setup_output(
+ Unit *unit,
+ const ExecContext *context,
+ const ExecParameters *params,
+ int fileno,
+ int socket_fd,
+ const char *ident,
+ uid_t uid, gid_t gid) {
+
ExecOutput o;
ExecInput i;
int r;
assert(unit);
assert(context);
+ assert(params);
assert(ident);
- i = fixup_input(context->std_input, socket_fd, apply_tty_stdin);
+ if (fileno == STDOUT_FILENO && params->stdout_fd >= 0) {
+
+ if (dup2(params->stdout_fd, STDOUT_FILENO) < 0)
+ return -errno;
+
+ return STDOUT_FILENO;
+ }
+
+ if (fileno == STDERR_FILENO && params->stderr_fd >= 0) {
+ if (dup2(params->stderr_fd, STDERR_FILENO) < 0)
+ return -errno;
+
+ return STDERR_FILENO;
+ }
+
+ i = fixup_input(context->std_input, socket_fd, params->apply_tty_stdin);
o = fixup_output(context->std_output, socket_fd);
if (fileno == STDERR_FILENO) {
@@ -502,9 +543,9 @@ static int chown_terminal(int fd, uid_t uid) {
return 0;
}
-static int setup_confirm_stdio(int *_saved_stdin,
- int *_saved_stdout) {
- int fd = -1, saved_stdin, saved_stdout = -1, r;
+static int setup_confirm_stdio(int *_saved_stdin, int *_saved_stdout) {
+ _cleanup_close_ int fd = -1, saved_stdin = -1, saved_stdout = -1;
+ int r;
assert(_saved_stdin);
assert(_saved_stdout);
@@ -514,10 +555,8 @@ static int setup_confirm_stdio(int *_saved_stdin,
return -errno;
saved_stdout = fcntl(STDOUT_FILENO, F_DUPFD, 3);
- if (saved_stdout < 0) {
- r = errno;
- goto fail;
- }
+ if (saved_stdout < 0)
+ return -errno;
fd = acquire_terminal(
"/dev/console",
@@ -525,39 +564,33 @@ static int setup_confirm_stdio(int *_saved_stdin,
false,
false,
DEFAULT_CONFIRM_USEC);
- if (fd < 0) {
- r = fd;
- goto fail;
- }
+ if (fd < 0)
+ return fd;
r = chown_terminal(fd, getuid());
if (r < 0)
- goto fail;
+ return r;
- if (dup2(fd, STDIN_FILENO) < 0) {
- r = -errno;
- goto fail;
- }
+ r = reset_terminal_fd(fd, true);
+ if (r < 0)
+ return r;
- if (dup2(fd, STDOUT_FILENO) < 0) {
- r = -errno;
- goto fail;
- }
+ if (dup2(fd, STDIN_FILENO) < 0)
+ return -errno;
+
+ if (dup2(fd, STDOUT_FILENO) < 0)
+ return -errno;
if (fd >= 2)
safe_close(fd);
+ fd = -1;
*_saved_stdin = saved_stdin;
*_saved_stdout = saved_stdout;
- return 0;
-
-fail:
- safe_close(saved_stdout);
- safe_close(saved_stdin);
- safe_close(fd);
+ saved_stdin = saved_stdout = -1;
- return r;
+ return 0;
}
_printf_(1, 2) static int write_confirm_message(const char *format, ...) {
@@ -577,9 +610,7 @@ _printf_(1, 2) static int write_confirm_message(const char *format, ...) {
return 0;
}
-static int restore_confirm_stdio(int *saved_stdin,
- int *saved_stdout) {
-
+static int restore_confirm_stdio(int *saved_stdin, int *saved_stdout) {
int r = 0;
assert(saved_stdin);
@@ -595,8 +626,8 @@ static int restore_confirm_stdio(int *saved_stdin,
if (dup2(*saved_stdout, STDOUT_FILENO) < 0)
r = -errno;
- safe_close(*saved_stdin);
- safe_close(*saved_stdout);
+ *saved_stdin = safe_close(*saved_stdin);
+ *saved_stdout = safe_close(*saved_stdout);
return r;
}
@@ -1198,6 +1229,7 @@ static void do_idle_pipe_dance(int idle_pipe[4]) {
static int build_environment(
const ExecContext *c,
unsigned n_fds,
+ char ** fd_names,
usec_t watchdog_usec,
const char *home,
const char *username,
@@ -1211,11 +1243,13 @@ static int build_environment(
assert(c);
assert(ret);
- our_env = new0(char*, 10);
+ our_env = new0(char*, 11);
if (!our_env)
return -ENOMEM;
if (n_fds > 0) {
+ _cleanup_free_ char *joined = NULL;
+
if (asprintf(&x, "LISTEN_PID="PID_FMT, getpid()) < 0)
return -ENOMEM;
our_env[n_env++] = x;
@@ -1223,6 +1257,15 @@ static int build_environment(
if (asprintf(&x, "LISTEN_FDS=%u", n_fds) < 0)
return -ENOMEM;
our_env[n_env++] = x;
+
+ joined = strv_join(fd_names, ":");
+ if (!joined)
+ return -ENOMEM;
+
+ x = strjoin("LISTEN_FDNAMES=", joined, NULL);
+ if (!x)
+ return -ENOMEM;
+ our_env[n_env++] = x;
}
if (watchdog_usec > 0) {
@@ -1273,7 +1316,7 @@ static int build_environment(
}
our_env[n_env++] = NULL;
- assert(n_env <= 10);
+ assert(n_env <= 11);
*ret = our_env;
our_env = NULL;
@@ -1311,6 +1354,44 @@ static bool exec_needs_mount_namespace(
return false;
}
+static int close_remaining_fds(
+ const ExecParameters *params,
+ ExecRuntime *runtime,
+ int socket_fd,
+ int *fds, unsigned n_fds) {
+
+ unsigned n_dont_close = 0;
+ int dont_close[n_fds + 7];
+
+ assert(params);
+
+ if (params->stdin_fd >= 0)
+ dont_close[n_dont_close++] = params->stdin_fd;
+ if (params->stdout_fd >= 0)
+ dont_close[n_dont_close++] = params->stdout_fd;
+ if (params->stderr_fd >= 0)
+ dont_close[n_dont_close++] = params->stderr_fd;
+
+ if (socket_fd >= 0)
+ dont_close[n_dont_close++] = socket_fd;
+ if (n_fds > 0) {
+ memcpy(dont_close + n_dont_close, fds, sizeof(int) * n_fds);
+ n_dont_close += n_fds;
+ }
+
+ if (params->bus_endpoint_fd >= 0)
+ dont_close[n_dont_close++] = params->bus_endpoint_fd;
+
+ if (runtime) {
+ if (runtime->netns_storage_socket[0] >= 0)
+ dont_close[n_dont_close++] = runtime->netns_storage_socket[0];
+ if (runtime->netns_storage_socket[1] >= 0)
+ dont_close[n_dont_close++] = runtime->netns_storage_socket[1];
+ }
+
+ return close_all_fds(dont_close, n_dont_close);
+}
+
static int exec_child(
Unit *unit,
ExecCommand *command,
@@ -1325,9 +1406,7 @@ static int exec_child(
_cleanup_strv_free_ char **our_env = NULL, **pam_env = NULL, **final_env = NULL, **final_argv = NULL;
_cleanup_free_ char *mac_selinux_context_net = NULL;
- const char *username = NULL, *home = NULL, *shell = NULL;
- unsigned n_dont_close = 0;
- int dont_close[n_fds + 4];
+ const char *username = NULL, *home = NULL, *shell = NULL, *wd;
uid_t uid = UID_INVALID;
gid_t gid = GID_INVALID;
int i, r;
@@ -1367,22 +1446,7 @@ static int exec_child(
log_forget_fds();
- if (socket_fd >= 0)
- dont_close[n_dont_close++] = socket_fd;
- if (n_fds > 0) {
- memcpy(dont_close + n_dont_close, fds, sizeof(int) * n_fds);
- n_dont_close += n_fds;
- }
- if (params->bus_endpoint_fd >= 0)
- dont_close[n_dont_close++] = params->bus_endpoint_fd;
- if (runtime) {
- if (runtime->netns_storage_socket[0] >= 0)
- dont_close[n_dont_close++] = runtime->netns_storage_socket[0];
- if (runtime->netns_storage_socket[1] >= 0)
- dont_close[n_dont_close++] = runtime->netns_storage_socket[1];
- }
-
- r = close_all_fds(dont_close, n_dont_close);
+ r = close_remaining_fds(params, runtime, socket_fd, fds, n_fds);
if (r < 0) {
*exit_status = EXIT_FDS;
return r;
@@ -1438,21 +1502,21 @@ static int exec_child(
/* If a socket is connected to STDIN/STDOUT/STDERR, we
* must sure to drop O_NONBLOCK */
if (socket_fd >= 0)
- fd_nonblock(socket_fd, false);
+ (void) fd_nonblock(socket_fd, false);
- r = setup_input(context, socket_fd, params->apply_tty_stdin);
+ r = setup_input(context, params, socket_fd);
if (r < 0) {
*exit_status = EXIT_STDIN;
return r;
}
- r = setup_output(unit, context, STDOUT_FILENO, socket_fd, basename(command->path), params->apply_tty_stdin, uid, gid);
+ r = setup_output(unit, context, params, STDOUT_FILENO, socket_fd, basename(command->path), uid, gid);
if (r < 0) {
*exit_status = EXIT_STDOUT;
return r;
}
- r = setup_output(unit, context, STDERR_FILENO, socket_fd, basename(command->path), params->apply_tty_stdin, uid, gid);
+ r = setup_output(unit, context, params, STDERR_FILENO, socket_fd, basename(command->path), uid, gid);
if (r < 0) {
*exit_status = EXIT_STDERR;
return r;
@@ -1698,6 +1762,13 @@ static int exec_child(
}
}
+ if (context->working_directory_home)
+ wd = home;
+ else if (context->working_directory)
+ wd = context->working_directory;
+ else
+ wd = "/";
+
if (params->apply_chroot) {
if (!needs_mount_namespace && context->root_directory)
if (chroot(context->root_directory) < 0) {
@@ -1705,21 +1776,15 @@ static int exec_child(
return -errno;
}
- if (chdir(context->working_directory ?: "/") < 0 &&
+ if (chdir(wd) < 0 &&
!context->working_directory_missing_ok) {
*exit_status = EXIT_CHDIR;
return -errno;
}
} else {
- _cleanup_free_ char *d = NULL;
-
- if (asprintf(&d, "%s/%s",
- context->root_directory ?: "",
- context->working_directory ?: "") < 0) {
- *exit_status = EXIT_MEMORY;
- return -ENOMEM;
- }
+ const char *d;
+ d = strjoina(strempty(context->root_directory), "/", strempty(wd));
if (chdir(d) < 0 &&
!context->working_directory_missing_ok) {
*exit_status = EXIT_CHDIR;
@@ -1849,7 +1914,7 @@ static int exec_child(
#endif
}
- r = build_environment(context, n_fds, params->watchdog_usec, home, username, shell, &our_env);
+ r = build_environment(context, n_fds, params->fd_names, params->watchdog_usec, home, username, shell, &our_env);
if (r < 0) {
*exit_status = EXIT_MEMORY;
return r;
@@ -2711,7 +2776,7 @@ int exec_command_append(ExecCommand *c, const char *path, ...) {
if (!l)
return -ENOMEM;
- r = strv_extend_strv(&c->argv, l);
+ r = strv_extend_strv(&c->argv, l, false);
if (r < 0)
return r;
diff --git a/src/core/execute.h b/src/core/execute.h
index a750246a89..f8995a4203 100644
--- a/src/core/execute.h
+++ b/src/core/execute.h
@@ -103,6 +103,7 @@ struct ExecContext {
struct rlimit *rlimit[_RLIMIT_MAX];
char *working_directory, *root_directory;
bool working_directory_missing_ok;
+ bool working_directory_home;
mode_t umask;
int oom_score_adjust;
@@ -207,21 +208,35 @@ struct ExecContext {
struct ExecParameters {
char **argv;
- int *fds; unsigned n_fds;
char **environment;
- bool apply_permissions;
- bool apply_chroot;
- bool apply_tty_stdin;
- bool confirm_spawn;
- bool selinux_context_net;
+
+ int *fds;
+ char **fd_names;
+ unsigned n_fds;
+
+ bool apply_permissions:1;
+ bool apply_chroot:1;
+ bool apply_tty_stdin:1;
+
+ bool confirm_spawn:1;
+ bool selinux_context_net:1;
+
+ bool cgroup_delegate:1;
CGroupMask cgroup_supported;
const char *cgroup_path;
- bool cgroup_delegate;
+
const char *runtime_prefix;
+
usec_t watchdog_usec;
+
int *idle_pipe;
+
char *bus_endpoint_path;
int bus_endpoint_fd;
+
+ int stdin_fd;
+ int stdout_fd;
+ int stderr_fd;
};
int exec_spawn(Unit *unit,
diff --git a/src/core/load-fragment-gperf.gperf.m4 b/src/core/load-fragment-gperf.gperf.m4
index fd293d8287..89e624b557 100644
--- a/src/core/load-fragment-gperf.gperf.m4
+++ b/src/core/load-fragment-gperf.gperf.m4
@@ -17,7 +17,7 @@ struct ConfigPerfItem;
%%
m4_dnl Define the context options only once
m4_define(`EXEC_CONTEXT_CONFIG_ITEMS',
-`$1.WorkingDirectory, config_parse_unit_path_printf, 0, offsetof($1, exec_context.working_directory)
+`$1.WorkingDirectory, config_parse_working_directory, 0, offsetof($1, exec_context)
$1.RootDirectory, config_parse_unit_path_printf, 0, offsetof($1, exec_context.root_directory)
$1.User, config_parse_unit_string_printf, 0, offsetof($1, exec_context.user)
$1.Group, config_parse_unit_string_printf, 0, offsetof($1, exec_context.group)
@@ -261,6 +261,7 @@ Socket.SocketGroup, config_parse_unit_string_printf, 0,
Socket.SocketMode, config_parse_mode, 0, offsetof(Socket, socket_mode)
Socket.DirectoryMode, config_parse_mode, 0, offsetof(Socket, directory_mode)
Socket.Accept, config_parse_bool, 0, offsetof(Socket, accept)
+Socket.Writable, config_parse_bool, 0, offsetof(Socket, writable)
Socket.MaxConnections, config_parse_unsigned, 0, offsetof(Socket, max_connections)
Socket.KeepAlive, config_parse_bool, 0, offsetof(Socket, keep_alive)
Socket.KeepAliveTimeSec, config_parse_sec, 0, offsetof(Socket, keep_alive_time)
@@ -286,6 +287,7 @@ Socket.MessageQueueMaxMessages, config_parse_long, 0,
Socket.MessageQueueMessageSize, config_parse_long, 0, offsetof(Socket, mq_msgsize)
Socket.RemoveOnStop, config_parse_bool, 0, offsetof(Socket, remove_on_stop)
Socket.Symlinks, config_parse_unit_path_strv_printf, 0, offsetof(Socket, symlinks)
+Socket.FileDescriptorName, config_parse_fdname, 0, 0
Socket.Service, config_parse_socket_service, 0, 0
m4_ifdef(`HAVE_SMACK',
`Socket.SmackLabel, config_parse_string, 0, offsetof(Socket, smack)
diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c
index a13f42b5e0..b1d4c6b57d 100644
--- a/src/core/load-fragment.c
+++ b/src/core/load-fragment.c
@@ -20,44 +20,43 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <linux/oom.h>
#include <errno.h>
-#include <string.h>
#include <fcntl.h>
-#include <sched.h>
#include <linux/fs.h>
-#include <sys/stat.h>
-#include <sys/resource.h>
-
+#include <linux/oom.h>
#ifdef HAVE_SECCOMP
#include <seccomp.h>
#endif
+#include <sched.h>
+#include <string.h>
+#include <sys/resource.h>
+#include <sys/stat.h>
-#include "unit.h"
-#include "strv.h"
+#include "af-list.h"
+#include "bus-error.h"
+#include "bus-internal.h"
+#include "bus-util.h"
+#include "cap-list.h"
+#include "cgroup.h"
#include "conf-parser.h"
-#include "load-fragment.h"
-#include "log.h"
+#include "cpu-set-util.h"
+#include "env-util.h"
+#include "errno-list.h"
#include "ioprio.h"
-#include "securebits.h"
+#include "log.h"
#include "missing.h"
-#include "unit-name.h"
-#include "unit-printf.h"
-#include "utf8.h"
#include "path-util.h"
-#include "env-util.h"
-#include "cgroup.h"
-#include "bus-util.h"
-#include "bus-error.h"
-#include "errno-list.h"
-#include "af-list.h"
-#include "cap-list.h"
-#include "signal-util.h"
-#include "bus-internal.h"
-
#ifdef HAVE_SECCOMP
#include "seccomp-util.h"
#endif
+#include "securebits.h"
+#include "signal-util.h"
+#include "strv.h"
+#include "unit-name.h"
+#include "unit-printf.h"
+#include "unit.h"
+#include "utf8.h"
+#include "load-fragment.h"
int config_parse_warn_compat(
const char *unit,
@@ -74,15 +73,15 @@ int config_parse_warn_compat(
switch(reason) {
case DISABLED_CONFIGURATION:
- log_syntax(unit, LOG_DEBUG, filename, line, EINVAL,
+ log_syntax(unit, LOG_DEBUG, filename, line, 0,
"Support for option %s= has been disabled at compile time and it is ignored", lvalue);
break;
case DISABLED_LEGACY:
- log_syntax(unit, LOG_INFO, filename, line, EINVAL,
+ log_syntax(unit, LOG_INFO, filename, line, 0,
"Support for option %s= has been removed and it is ignored", lvalue);
break;
case DISABLED_EXPERIMENTAL:
- log_syntax(unit, LOG_INFO, filename, line, EINVAL,
+ log_syntax(unit, LOG_INFO, filename, line, 0,
"Support for option %s= has not yet been enabled and it is ignored", lvalue);
break;
};
@@ -120,18 +119,16 @@ int config_parse_unit_deps(const char *unit,
r = unit_name_printf(u, t, &k);
if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, -r,
- "Failed to resolve specifiers, ignoring: %s", strerror(-r));
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve specifiers, ignoring: %m");
continue;
}
r = unit_add_dependency_by_name(u, d, k, NULL, true);
if (r < 0)
- log_syntax(unit, LOG_ERR, filename, line, -r,
- "Failed to add dependency on %s, ignoring: %s", k, strerror(-r));
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to add dependency on %s, ignoring: %m", k);
}
if (!isempty(state))
- log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Invalid syntax, ignoring.");
+ log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid syntax, ignoring.");
return 0;
}
@@ -166,16 +163,17 @@ int config_parse_unit_string_printf(
return config_parse_string(unit, filename, line, section, section_line, lvalue, ltype, k, data, userdata);
}
-int config_parse_unit_strv_printf(const char *unit,
- const char *filename,
- unsigned line,
- const char *section,
- unsigned section_line,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
+int config_parse_unit_strv_printf(
+ const char *unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
Unit *u = userdata;
_cleanup_free_ char *k = NULL;
@@ -187,24 +185,25 @@ int config_parse_unit_strv_printf(const char *unit,
assert(u);
r = unit_full_printf(u, rvalue, &k);
- if (r < 0)
- log_syntax(unit, LOG_ERR, filename, line, -r,
- "Failed to resolve unit specifiers on %s, ignoring: %s", rvalue, strerror(-r));
+ if (r < 0) {
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers on %s, ignoring: %m", rvalue);
+ return 0;
+ }
- return config_parse_strv(unit, filename, line, section, section_line, lvalue, ltype,
- k ? k : rvalue, data, userdata);
+ return config_parse_strv(unit, filename, line, section, section_line, lvalue, ltype, k, data, userdata);
}
-int config_parse_unit_path_printf(const char *unit,
- const char *filename,
- unsigned line,
- const char *section,
- unsigned section_line,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
+int config_parse_unit_path_printf(
+ const char *unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
_cleanup_free_ char *k = NULL;
Unit *u = userdata;
@@ -217,7 +216,7 @@ int config_parse_unit_path_printf(const char *unit,
r = unit_full_printf(u, rvalue, &k);
if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, -r, "Failed to resolve unit specifiers on %s, ignoring: %s", rvalue, strerror(-r));
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers on %s, ignoring: %m", rvalue);
return 0;
}
@@ -256,17 +255,17 @@ int config_parse_unit_path_strv_printf(
r = unit_full_printf(u, t, &k);
if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, -r, "Failed to resolve unit specifiers on %s, ignoring: %s", t, strerror(-r));
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers on %s, ignoring: %m", t);
return 0;
}
if (!utf8_is_valid(k)) {
- log_invalid_utf8(unit, LOG_ERR, filename, line, EINVAL, rvalue);
+ log_syntax_invalid_utf8(unit, LOG_ERR, filename, line, rvalue);
return 0;
}
if (!path_is_absolute(k)) {
- log_syntax(unit, LOG_ERR, filename, line, -r, "Symlink path %s is not absolute, ignoring: %s", k, strerror(-r));
+ log_syntax(unit, LOG_ERR, filename, line, 0, "Symlink path %s is not absolute, ignoring: %m", k);
return 0;
}
@@ -279,7 +278,7 @@ int config_parse_unit_path_strv_printf(
k = NULL;
}
if (!isempty(state))
- log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Invalid syntax, ignoring.");
+ log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid syntax, ignoring.");
return 0;
}
@@ -322,12 +321,8 @@ int config_parse_socket_listen(const char *unit,
p->type = ltype;
r = unit_full_printf(UNIT(s), rvalue, &p->path);
if (r < 0) {
- p->path = strdup(rvalue);
- if (!p->path)
- return log_oom();
- else
- log_syntax(unit, LOG_ERR, filename, line, -r,
- "Failed to resolve unit specifiers on %s, ignoring: %s", rvalue, strerror(-r));
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers on %s, ignoring: %m", rvalue);
+ return 0;
}
path_kill_slashes(p->path);
@@ -337,14 +332,14 @@ int config_parse_socket_listen(const char *unit,
p->type = SOCKET_SOCKET;
r = unit_full_printf(UNIT(s), rvalue, &k);
- if (r < 0)
- log_syntax(unit, LOG_ERR, filename, line, -r,
- "Failed to resolve unit specifiers on %s, ignoring: %s", rvalue, strerror(-r));
+ if (r < 0) {
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers on %s, ignoring: %m", rvalue);
+ return 0;
+ }
- r = socket_address_parse_netlink(&p->address, k ?: rvalue);
+ r = socket_address_parse_netlink(&p->address, k);
if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, -r,
- "Failed to parse address value, ignoring: %s", rvalue);
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse address value, ignoring: %s", rvalue);
return 0;
}
@@ -353,14 +348,14 @@ int config_parse_socket_listen(const char *unit,
p->type = SOCKET_SOCKET;
r = unit_full_printf(UNIT(s), rvalue, &k);
- if (r < 0)
- log_syntax(unit, LOG_ERR, filename, line, -r,
- "Failed to resolve unit specifiers on %s, ignoring: %s", rvalue, strerror(-r));
+ if (r < 0) {
+ log_syntax(unit, LOG_ERR, filename, line, r,"Failed to resolve unit specifiers on %s, ignoring: %m", rvalue);
+ return 0;
+ }
- r = socket_address_parse_and_warn(&p->address, k ? k : rvalue);
+ r = socket_address_parse_and_warn(&p->address, k);
if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, -r,
- "Failed to parse address value, ignoring: %s", rvalue);
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse address value, ignoring: %s", rvalue);
return 0;
}
@@ -374,8 +369,7 @@ int config_parse_socket_listen(const char *unit,
}
if (socket_address_family(&p->address) != AF_LOCAL && p->address.type == SOCK_SEQPACKET) {
- log_syntax(unit, LOG_ERR, filename, line, EOPNOTSUPP,
- "Address family not supported, ignoring: %s", rvalue);
+ log_syntax(unit, LOG_ERR, filename, line, 0, "Address family not supported, ignoring: %s", rvalue);
return 0;
}
}
@@ -422,8 +416,7 @@ int config_parse_socket_bind(const char *unit,
r = parse_boolean(rvalue);
if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, EINVAL,
- "Failed to parse bind IPv6 only value, ignoring: %s", rvalue);
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse bind IPv6 only value, ignoring: %s", rvalue);
return 0;
}
@@ -455,14 +448,12 @@ int config_parse_exec_nice(const char *unit,
r = safe_atoi(rvalue, &priority);
if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, -r,
- "Failed to parse nice priority, ignoring: %s. ", rvalue);
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse nice priority, ignoring: %s", rvalue);
return 0;
}
if (priority < PRIO_MIN || priority >= PRIO_MAX) {
- log_syntax(unit, LOG_ERR, filename, line, ERANGE,
- "Nice priority out of range, ignoring: %s", rvalue);
+ log_syntax(unit, LOG_ERR, filename, line, 0, "Nice priority out of range, ignoring: %s", rvalue);
return 0;
}
@@ -493,14 +484,12 @@ int config_parse_exec_oom_score_adjust(const char* unit,
r = safe_atoi(rvalue, &oa);
if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, -r,
- "Failed to parse the OOM score adjust value, ignoring: %s", rvalue);
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse the OOM score adjust value, ignoring: %s", rvalue);
return 0;
}
if (oa < OOM_SCORE_ADJ_MIN || oa > OOM_SCORE_ADJ_MAX) {
- log_syntax(unit, LOG_ERR, filename, line, ERANGE,
- "OOM score adjust value out of range, ignoring: %s", rvalue);
+ log_syntax(unit, LOG_ERR, filename, line, 0, "OOM score adjust value out of range, ignoring: %s", rvalue);
return 0;
}
@@ -574,24 +563,19 @@ int config_parse_exec(
if (isempty(f)) {
/* First word is either "-" or "@" with no command. */
- log_syntax(unit, LOG_ERR, filename, line, EINVAL,
- "Empty path in command line, ignoring: \"%s\"", rvalue);
+ log_syntax(unit, LOG_ERR, filename, line, 0, "Empty path in command line, ignoring: \"%s\"", rvalue);
return 0;
}
-
if (!string_is_safe(f)) {
- log_syntax(unit, LOG_ERR, filename, line, EINVAL,
- "Executable path contains special characters, ignoring: %s", rvalue);
+ log_syntax(unit, LOG_ERR, filename, line, 0, "Executable path contains special characters, ignoring: %s", rvalue);
return 0;
}
if (!path_is_absolute(f)) {
- log_syntax(unit, LOG_ERR, filename, line, EINVAL,
- "Executable path is not absolute, ignoring: %s", rvalue);
+ log_syntax(unit, LOG_ERR, filename, line, 0, "Executable path is not absolute, ignoring: %s", rvalue);
return 0;
}
if (endswith(f, "/")) {
- log_syntax(unit, LOG_ERR, filename, line, EINVAL,
- "Executable path specifies a directory, ignoring: %s", rvalue);
+ log_syntax(unit, LOG_ERR, filename, line, 0, "Executable path specifies a directory, ignoring: %s", rvalue);
return 0;
}
@@ -658,8 +642,7 @@ int config_parse_exec(
}
if (!n || !n[0]) {
- log_syntax(unit, LOG_ERR, filename, line, EINVAL,
- "Empty executable name or zeroeth argument, ignoring: %s", rvalue);
+ log_syntax(unit, LOG_ERR, filename, line, 0, "Empty executable name or zeroeth argument, ignoring: %s", rvalue);
return 0;
}
@@ -743,8 +726,7 @@ int config_parse_exec_io_class(const char *unit,
x = ioprio_class_from_string(rvalue);
if (x < 0) {
- log_syntax(unit, LOG_ERR, filename, line, EINVAL,
- "Failed to parse IO scheduling class, ignoring: %s", rvalue);
+ log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse IO scheduling class, ignoring: %s", rvalue);
return 0;
}
@@ -775,8 +757,7 @@ int config_parse_exec_io_priority(const char *unit,
r = safe_atoi(rvalue, &i);
if (r < 0 || i < 0 || i >= IOPRIO_BE_NR) {
- log_syntax(unit, LOG_ERR, filename, line, -r,
- "Failed to parse IO priority, ignoring: %s", rvalue);
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse IO priority, ignoring: %s", rvalue);
return 0;
}
@@ -808,8 +789,7 @@ int config_parse_exec_cpu_sched_policy(const char *unit,
x = sched_policy_from_string(rvalue);
if (x < 0) {
- log_syntax(unit, LOG_ERR, filename, line, -x,
- "Failed to parse CPU scheduling policy, ignoring: %s", rvalue);
+ log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse CPU scheduling policy, ignoring: %s", rvalue);
return 0;
}
@@ -842,8 +822,7 @@ int config_parse_exec_cpu_sched_prio(const char *unit,
r = safe_atoi(rvalue, &i);
if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, -r,
- "Failed to parse CPU scheduling policy, ignoring: %s", rvalue);
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse CPU scheduling policy, ignoring: %s", rvalue);
return 0;
}
@@ -852,8 +831,7 @@ int config_parse_exec_cpu_sched_prio(const char *unit,
max = sched_get_priority_max(c->cpu_sched_policy);
if (i < min || i > max) {
- log_syntax(unit, LOG_ERR, filename, line, ERANGE,
- "CPU scheduling priority is out of range, ignoring: %s", rvalue);
+ log_syntax(unit, LOG_ERR, filename, line, 0, "CPU scheduling priority is out of range, ignoring: %s", rvalue);
return 0;
}
@@ -883,8 +861,7 @@ int config_parse_exec_cpu_affinity(const char *unit,
assert(rvalue);
assert(data);
- ncpus = parse_cpu_set(rvalue, &cpuset, unit, filename, line, lvalue);
-
+ ncpus = parse_cpu_set_and_warn(rvalue, &cpuset, unit, filename, line, lvalue);
if (ncpus < 0)
return ncpus;
@@ -924,8 +901,7 @@ int config_parse_exec_capabilities(const char *unit,
cap = cap_from_text(rvalue);
if (!cap) {
- log_syntax(unit, LOG_ERR, filename, line, errno,
- "Failed to parse capabilities, ignoring: %s", rvalue);
+ log_syntax(unit, LOG_ERR, filename, line, errno, "Failed to parse capabilities, ignoring: %s", rvalue);
return 0;
}
@@ -976,14 +952,12 @@ int config_parse_exec_secure_bits(const char *unit,
else if (first_word(word, "noroot-locked"))
c->secure_bits |= 1<<SECURE_NOROOT_LOCKED;
else {
- log_syntax(unit, LOG_ERR, filename, line, EINVAL,
- "Failed to parse secure bits, ignoring: %s", rvalue);
+ log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse secure bits, ignoring: %s", rvalue);
return 0;
}
}
if (!isempty(state))
- log_syntax(unit, LOG_ERR, filename, line, EINVAL,
- "Invalid syntax, garbage at the end, ignoring.");
+ log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid syntax, garbage at the end, ignoring.");
return 0;
}
@@ -1030,15 +1004,14 @@ int config_parse_bounding_set(const char *unit,
cap = capability_from_name(t);
if (cap < 0) {
- log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Failed to parse capability in bounding set, ignoring: %s", t);
+ log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse capability in bounding set, ignoring: %s", t);
continue;
}
sum |= ((uint64_t) 1ULL) << (uint64_t) cap;
}
if (!isempty(state))
- log_syntax(unit, LOG_ERR, filename, line, EINVAL,
- "Trailing garbage, ignoring.");
+ log_syntax(unit, LOG_ERR, filename, line, 0, "Trailing garbage, ignoring.");
if (invert)
*capability_bounding_set_drop |= sum;
@@ -1076,8 +1049,7 @@ int config_parse_limit(const char *unit,
r = safe_atollu(rvalue, &u);
if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, -r,
- "Failed to parse resource value, ignoring: %s", rvalue);
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse resource value, ignoring: %s", rvalue);
return 0;
}
}
@@ -1114,8 +1086,7 @@ int config_parse_sysv_priority(const char *unit,
r = safe_atoi(rvalue, &i);
if (r < 0 || i < 0) {
- log_syntax(unit, LOG_ERR, filename, line, -r,
- "Failed to parse SysV start priority, ignoring: %s", rvalue);
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse SysV start priority, ignoring: %s", rvalue);
return 0;
}
@@ -1162,12 +1133,12 @@ int config_parse_exec_mount_flags(const char *unit,
else if (streq(t, "private"))
flags = MS_PRIVATE;
else {
- log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Failed to parse mount flag %s, ignoring: %s", t, rvalue);
+ log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse mount flag %s, ignoring: %s", t, rvalue);
return 0;
}
}
if (!isempty(state))
- log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Trailing garbage, ignoring.");
+ log_syntax(unit, LOG_ERR, filename, line, 0, "Trailing garbage, ignoring.");
c->mount_flags = flags;
return 0;
@@ -1210,8 +1181,7 @@ int config_parse_exec_selinux_context(
r = unit_name_printf(u, rvalue, &k);
if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, -r,
- "Failed to resolve specifiers, ignoring: %s", strerror(-r));
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve specifiers, ignoring: %m");
return 0;
}
@@ -1259,8 +1229,7 @@ int config_parse_exec_apparmor_profile(
r = unit_name_printf(u, rvalue, &k);
if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, -r,
- "Failed to resolve specifiers, ignoring: %s", strerror(-r));
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve specifiers, ignoring: %m");
return 0;
}
@@ -1308,8 +1277,7 @@ int config_parse_exec_smack_process_label(
r = unit_name_printf(u, rvalue, &k);
if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, -r,
- "Failed to resolve specifiers, ignoring: %s", strerror(-r));
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve specifiers, ignoring: %m");
return 0;
}
@@ -1350,23 +1318,18 @@ int config_parse_timer(const char *unit,
b = timer_base_from_string(lvalue);
if (b < 0) {
- log_syntax(unit, LOG_ERR, filename, line, -b,
- "Failed to parse timer base, ignoring: %s", lvalue);
+ log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse timer base, ignoring: %s", lvalue);
return 0;
}
if (b == TIMER_CALENDAR) {
if (calendar_spec_from_string(rvalue, &c) < 0) {
- log_syntax(unit, LOG_ERR, filename, line, EINVAL,
- "Failed to parse calendar specification, ignoring: %s",
- rvalue);
+ log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse calendar specification, ignoring: %s", rvalue);
return 0;
}
} else {
if (parse_sec(rvalue, &u) < 0) {
- log_syntax(unit, LOG_ERR, filename, line, EINVAL,
- "Failed to parse timer value, ignoring: %s",
- rvalue);
+ log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse timer value, ignoring: %s", rvalue);
return 0;
}
}
@@ -1409,33 +1372,30 @@ int config_parse_trigger_unit(
assert(data);
if (!set_isempty(u->dependencies[UNIT_TRIGGERS])) {
- log_syntax(unit, LOG_ERR, filename, line, EINVAL,
- "Multiple units to trigger specified, ignoring: %s", rvalue);
+ log_syntax(unit, LOG_ERR, filename, line, 0, "Multiple units to trigger specified, ignoring: %s", rvalue);
return 0;
}
r = unit_name_printf(u, rvalue, &p);
- if (r < 0)
- log_syntax(unit, LOG_ERR, filename, line, -r,
- "Failed to resolve specifiers, ignoring: %s", strerror(-r));
+ if (r < 0) {
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve specifiers, ignoring: %m");
+ return 0;
+ }
- type = unit_name_to_type(p ?: rvalue);
+ type = unit_name_to_type(p);
if (type < 0) {
- log_syntax(unit, LOG_ERR, filename, line, EINVAL,
- "Unit type not valid, ignoring: %s", rvalue);
+ log_syntax(unit, LOG_ERR, filename, line, 0, "Unit type not valid, ignoring: %s", rvalue);
return 0;
}
if (type == u->type) {
- log_syntax(unit, LOG_ERR, filename, line, EINVAL,
- "Trigger cannot be of same type, ignoring: %s", rvalue);
+ log_syntax(unit, LOG_ERR, filename, line, 0, "Trigger cannot be of same type, ignoring: %s", rvalue);
return 0;
}
- r = unit_add_two_dependencies_by_name(u, UNIT_BEFORE, UNIT_TRIGGERS, p ?: rvalue, NULL, true);
+ r = unit_add_two_dependencies_by_name(u, UNIT_BEFORE, UNIT_TRIGGERS, p, NULL, true);
if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, -r,
- "Failed to add trigger on %s, ignoring: %s", p ?: rvalue, strerror(-r));
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to add trigger on %s, ignoring: %m", p);
return 0;
}
@@ -1472,25 +1432,18 @@ int config_parse_path_spec(const char *unit,
b = path_type_from_string(lvalue);
if (b < 0) {
- log_syntax(unit, LOG_ERR, filename, line, EINVAL,
- "Failed to parse path type, ignoring: %s", lvalue);
+ log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse path type, ignoring: %s", lvalue);
return 0;
}
r = unit_full_printf(UNIT(p), rvalue, &k);
if (r < 0) {
- k = strdup(rvalue);
- if (!k)
- return log_oom();
- else
- log_syntax(unit, LOG_ERR, filename, line, -r,
- "Failed to resolve unit specifiers on %s. Ignoring.",
- rvalue);
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers on %s. Ignoring.", rvalue);
+ return 0;
}
if (!path_is_absolute(k)) {
- log_syntax(unit, LOG_ERR, filename, line, EINVAL,
- "Path is not absolute, ignoring: %s", k);
+ log_syntax(unit, LOG_ERR, filename, line, 0, "Path is not absolute, ignoring: %s", k);
return 0;
}
@@ -1522,10 +1475,10 @@ int config_parse_socket_service(
void *userdata) {
_cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_free_ char *p = NULL;
Socket *s = data;
- int r;
Unit *x;
- _cleanup_free_ char *p = NULL;
+ int r;
assert(filename);
assert(lvalue);
@@ -1539,13 +1492,13 @@ int config_parse_socket_service(
}
if (!endswith(p, ".service")) {
- log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Unit must be of type service, ignoring: %s", rvalue);
+ log_syntax(unit, LOG_ERR, filename, line, 0, "Unit must be of type service, ignoring: %s", rvalue);
return 0;
}
r = manager_load_unit(UNIT(s)->manager, p, NULL, &error, &x);
if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, -r, "Failed to load unit %s, ignoring: %s", rvalue, bus_error_message(&error, r));
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to load unit %s, ignoring: %s", rvalue, bus_error_message(&error, r));
return 0;
}
@@ -1554,6 +1507,50 @@ int config_parse_socket_service(
return 0;
}
+int config_parse_fdname(
+ const char *unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
+
+ _cleanup_free_ char *p = NULL;
+ Socket *s = data;
+ int r;
+
+ assert(filename);
+ assert(lvalue);
+ assert(rvalue);
+ assert(data);
+
+ if (isempty(rvalue)) {
+ s->fdname = mfree(s->fdname);
+ return 0;
+ }
+
+ r = unit_name_printf(UNIT(s), rvalue, &p);
+ if (r < 0) {
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve specifiers, ignoring: %s", rvalue);
+ return 0;
+ }
+
+ if (!fdname_is_valid(p)) {
+ log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid file descriptor name, ignoring: %s", p);
+ return 0;
+ }
+
+ free(s->fdname);
+ s->fdname = p;
+ p = NULL;
+
+ return 0;
+}
+
int config_parse_service_sockets(
const char *unit,
const char *filename,
@@ -1590,7 +1587,7 @@ int config_parse_service_sockets(
}
if (!endswith(k, ".socket")) {
- log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Unit must be of type socket, ignoring: %s", k);
+ log_syntax(unit, LOG_ERR, filename, line, 0, "Unit must be of type socket, ignoring: %s", k);
continue;
}
@@ -1603,7 +1600,7 @@ int config_parse_service_sockets(
log_syntax(unit, LOG_ERR, filename, line, r, "Failed to add dependency on %s, ignoring: %m", k);
}
if (!isempty(state))
- log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Trailing garbage, ignoring.");
+ log_syntax(unit, LOG_ERR, filename, line, 0, "Trailing garbage, ignoring.");
return 0;
}
@@ -1636,7 +1633,7 @@ int config_parse_bus_name(
}
if (!service_name_is_valid(k)) {
- log_syntax(unit, LOG_ERR, filename, line, r, "Invalid bus name %s, ignoring.", k);
+ log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid bus name %s, ignoring.", k);
return 0;
}
@@ -1701,21 +1698,18 @@ int config_parse_busname_service(
r = unit_name_printf(UNIT(n), rvalue, &p);
if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, -r,
- "Failed to resolve specifiers, ignoring: %s", rvalue);
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve specifiers, ignoring: %s", rvalue);
return 0;
}
if (!endswith(p, ".service")) {
- log_syntax(unit, LOG_ERR, filename, line, EINVAL,
- "Unit must be of type service, ignoring: %s", rvalue);
+ log_syntax(unit, LOG_ERR, filename, line, 0, "Unit must be of type service, ignoring: %s", rvalue);
return 0;
}
r = manager_load_unit(UNIT(n)->manager, p, NULL, &error, &x);
if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, -r,
- "Failed to load unit %s, ignoring: %s", rvalue, bus_error_message(&error, r));
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to load unit %s, ignoring: %s", rvalue, bus_error_message(&error, r));
return 0;
}
@@ -1765,8 +1759,7 @@ int config_parse_bus_policy(
access_str = strpbrk(id_str, WHITESPACE);
if (!access_str) {
- log_syntax(unit, LOG_ERR, filename, line, EINVAL,
- "Invalid busname policy value '%s'", rvalue);
+ log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid busname policy value '%s'", rvalue);
return 0;
}
@@ -1776,8 +1769,7 @@ int config_parse_bus_policy(
p->access = bus_policy_access_from_string(access_str);
if (p->access < 0) {
- log_syntax(unit, LOG_ERR, filename, line, EINVAL,
- "Invalid busname policy access type '%s'", access_str);
+ log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid busname policy access type '%s'", access_str);
return 0;
}
@@ -1819,8 +1811,7 @@ int config_parse_bus_endpoint_policy(
access_str = strpbrk(name, WHITESPACE);
if (!access_str) {
- log_syntax(unit, LOG_ERR, filename, line, EINVAL,
- "Invalid endpoint policy value '%s'", rvalue);
+ log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid endpoint policy value '%s'", rvalue);
return 0;
}
@@ -1831,21 +1822,83 @@ int config_parse_bus_endpoint_policy(
access = bus_policy_access_from_string(access_str);
if (access <= _BUS_POLICY_ACCESS_INVALID ||
access >= _BUS_POLICY_ACCESS_MAX) {
- log_syntax(unit, LOG_ERR, filename, line, EINVAL,
- "Invalid endpoint policy access type '%s'", access_str);
+ log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid endpoint policy access type '%s'", access_str);
return 0;
}
if (!c->bus_endpoint) {
r = bus_endpoint_new(&c->bus_endpoint);
-
if (r < 0)
- return r;
+ return log_error_errno(r, "Failed to create bus endpoint object: %m");
}
return bus_endpoint_add_policy(c->bus_endpoint, name, access);
}
+int config_parse_working_directory(
+ const char *unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
+
+ ExecContext *c = data;
+ Unit *u = userdata;
+ bool missing_ok;
+ int r;
+
+ assert(filename);
+ assert(lvalue);
+ assert(rvalue);
+ assert(c);
+ assert(u);
+
+ if (rvalue[0] == '-') {
+ missing_ok = true;
+ rvalue++;
+ } else
+ missing_ok = false;
+
+ if (streq(rvalue, "~")) {
+ c->working_directory_home = true;
+ c->working_directory = mfree(c->working_directory);
+ } else {
+ _cleanup_free_ char *k = NULL;
+
+ r = unit_full_printf(u, rvalue, &k);
+ if (r < 0) {
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in working directory path '%s', ignoring: %m", rvalue);
+ return 0;
+ }
+
+ path_kill_slashes(k);
+
+ if (!utf8_is_valid(k)) {
+ log_syntax_invalid_utf8(unit, LOG_ERR, filename, line, rvalue);
+ return 0;
+ }
+
+ if (!path_is_absolute(k)) {
+ log_syntax(unit, LOG_ERR, filename, line, 0, "Working directory path '%s' is not absolute, ignoring.", rvalue);
+ return 0;
+ }
+
+ free(c->working_directory);
+ c->working_directory = k;
+ k = NULL;
+
+ c->working_directory_home = false;
+ }
+
+ c->working_directory_missing_ok = missing_ok;
+ return 0;
+}
+
int config_parse_unit_env_file(const char *unit,
const char *filename,
unsigned line,
@@ -1860,7 +1913,6 @@ int config_parse_unit_env_file(const char *unit,
char ***env = data;
Unit *u = userdata;
_cleanup_free_ char *n = NULL;
- const char *s;
int r;
assert(filename);
@@ -1875,18 +1927,17 @@ int config_parse_unit_env_file(const char *unit,
}
r = unit_full_printf(u, rvalue, &n);
- if (r < 0)
- log_syntax(unit, LOG_ERR, filename, line, -r,
- "Failed to resolve specifiers, ignoring: %s", rvalue);
+ if (r < 0) {
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve specifiers, ignoring: %s", rvalue);
+ return 0;
+ }
- s = n ?: rvalue;
- if (!path_is_absolute(s[0] == '-' ? s + 1 : s)) {
- log_syntax(unit, LOG_ERR, filename, line, EINVAL,
- "Path '%s' is not absolute, ignoring.", s);
+ if (!path_is_absolute(n[0] == '-' ? n + 1 : n)) {
+ log_syntax(unit, LOG_ERR, filename, line, 0, "Path '%s' is not absolute, ignoring.", n);
return 0;
}
- r = strv_extend(env, s);
+ r = strv_extend(env, n);
if (r < 0)
return log_oom();
@@ -1924,14 +1975,17 @@ int config_parse_environ(const char *unit,
if (u) {
r = unit_full_printf(u, rvalue, &k);
- if (r < 0)
- log_syntax(unit, LOG_ERR, filename, line, -r, "Failed to resolve specifiers, ignoring: %s", rvalue);
+ if (r < 0) {
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve specifiers, ignoring: %s", rvalue);
+ return 0;
+ }
}
- if (!k)
+ if (!k) {
k = strdup(rvalue);
- if (!k)
- return log_oom();
+ if (!k)
+ return log_oom();
+ }
FOREACH_WORD_QUOTED(word, l, k, state) {
_cleanup_free_ char *n = NULL;
@@ -1944,7 +1998,7 @@ int config_parse_environ(const char *unit,
}
if (!env_assignment_is_valid(n)) {
- log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Invalid environment assignment, ignoring: %s", rvalue);
+ log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid environment assignment, ignoring: %s", rvalue);
continue;
}
@@ -1956,8 +2010,7 @@ int config_parse_environ(const char *unit,
*env = x;
}
if (!isempty(state))
- log_syntax(unit, LOG_ERR, filename, line, EINVAL,
- "Trailing garbage, ignoring.");
+ log_syntax(unit, LOG_ERR, filename, line, 0, "Trailing garbage, ignoring.");
return 0;
}
@@ -1982,8 +2035,7 @@ int config_parse_ip_tos(const char *unit,
x = ip_tos_from_string(rvalue);
if (x < 0) {
- log_syntax(unit, LOG_ERR, filename, line, EINVAL,
- "Failed to parse IP TOS value, ignoring: %s", rvalue);
+ log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse IP TOS value, ignoring: %s", rvalue);
return 0;
}
@@ -2031,12 +2083,12 @@ int config_parse_unit_condition_path(
r = unit_full_printf(u, rvalue, &p);
if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, -r, "Failed to resolve specifiers, ignoring: %s", rvalue);
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve specifiers, ignoring: %s", rvalue);
return 0;
}
if (!path_is_absolute(p)) {
- log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Path in condition not absolute, ignoring: %s", p);
+ log_syntax(unit, LOG_ERR, filename, line, 0, "Path in condition not absolute, ignoring: %s", p);
return 0;
}
@@ -2088,7 +2140,7 @@ int config_parse_unit_condition_string(
r = unit_full_printf(u, rvalue, &s);
if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, -r, "Failed to resolve specifiers, ignoring: %s", rvalue);
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve specifiers, ignoring: %s", rvalue);
return 0;
}
@@ -2137,7 +2189,7 @@ int config_parse_unit_condition_null(
b = parse_boolean(rvalue);
if (b < 0) {
- log_syntax(unit, LOG_ERR, filename, line, -b, "Failed to parse boolean value in condition, ignoring: %s", rvalue);
+ log_syntax(unit, LOG_ERR, filename, line, b, "Failed to parse boolean value in condition, ignoring: %s", rvalue);
return 0;
}
@@ -2185,20 +2237,18 @@ int config_parse_unit_requires_mounts_for(
return log_oom();
if (!utf8_is_valid(n)) {
- log_invalid_utf8(unit, LOG_ERR, filename, line, EINVAL, rvalue);
+ log_syntax_invalid_utf8(unit, LOG_ERR, filename, line, rvalue);
continue;
}
r = unit_require_mounts_for(u, n);
if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, -r,
- "Failed to add required mount for, ignoring: %s", rvalue);
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to add required mount for, ignoring: %s", rvalue);
continue;
}
}
if (!isempty(state))
- log_syntax(unit, LOG_ERR, filename, line, EINVAL,
- "Trailing garbage, ignoring.");
+ log_syntax(unit, LOG_ERR, filename, line, 0, "Trailing garbage, ignoring.");
return 0;
}
@@ -2239,8 +2289,7 @@ int config_parse_documentation(const char *unit,
if (documentation_url_is_valid(*a))
*(b++) = *a;
else {
- log_syntax(unit, LOG_ERR, filename, line, EINVAL,
- "Invalid URL, ignoring: %s", *a);
+ log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid URL, ignoring: %s", *a);
free(*a);
}
}
@@ -2335,8 +2384,7 @@ int config_parse_syscall_filter(
id = seccomp_syscall_resolve_name(t);
if (id < 0) {
- log_syntax(unit, LOG_ERR, filename, line, EINVAL,
- "Failed to parse system call, ignoring: %s", t);
+ log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse system call, ignoring: %s", t);
continue;
}
@@ -2353,8 +2401,7 @@ int config_parse_syscall_filter(
set_remove(c->syscall_filter, INT_TO_PTR(id + 1));
}
if (!isempty(state))
- log_syntax(unit, LOG_ERR, filename, line, EINVAL,
- "Trailing garbage, ignoring.");
+ log_syntax(unit, LOG_ERR, filename, line, 0, "Trailing garbage, ignoring.");
/* Turn on NNP, but only if it wasn't configured explicitly
* before, and only if we are in user mode. */
@@ -2400,8 +2447,7 @@ int config_parse_syscall_archs(
r = seccomp_arch_from_string(t, &a);
if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, EINVAL,
- "Failed to parse system call architecture, ignoring: %s", t);
+ log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse system call architecture, ignoring: %s", t);
continue;
}
@@ -2412,8 +2458,7 @@ int config_parse_syscall_archs(
return log_oom();
}
if (!isempty(state))
- log_syntax(unit, LOG_ERR, filename, line, EINVAL,
- "Trailing garbage, ignoring.");
+ log_syntax(unit, LOG_ERR, filename, line, 0, "Trailing garbage, ignoring.");
return 0;
}
@@ -2445,8 +2490,7 @@ int config_parse_syscall_errno(
e = errno_from_name(rvalue);
if (e < 0) {
- log_syntax(unit, LOG_ERR, filename, line, EINVAL,
- "Failed to parse error number, ignoring: %s", rvalue);
+ log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse error number, ignoring: %s", rvalue);
return 0;
}
@@ -2506,8 +2550,7 @@ int config_parse_address_families(
af = af_from_name(t);
if (af <= 0) {
- log_syntax(unit, LOG_ERR, filename, line, EINVAL,
- "Failed to parse address family, ignoring: %s", t);
+ log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse address family, ignoring: %s", t);
continue;
}
@@ -2524,8 +2567,7 @@ int config_parse_address_families(
set_remove(c->address_families, INT_TO_PTR(af));
}
if (!isempty(state))
- log_syntax(unit, LOG_ERR, filename, line, EINVAL,
- "Trailing garbage, ignoring.");
+ log_syntax(unit, LOG_ERR, filename, line, 0, "Trailing garbage, ignoring.");
return 0;
}
@@ -2628,15 +2670,12 @@ int config_parse_cpu_quota(
}
if (!endswith(rvalue, "%")) {
-
- log_syntax(unit, LOG_ERR, filename, line, EINVAL,
- "CPU quota '%s' not ending in '%%'. Ignoring.", rvalue);
+ log_syntax(unit, LOG_ERR, filename, line, 0, "CPU quota '%s' not ending in '%%'. Ignoring.", rvalue);
return 0;
}
if (sscanf(rvalue, "%lf%%", &percent) != 1 || percent <= 0) {
- log_syntax(unit, LOG_ERR, filename, line, EINVAL,
- "CPU quota '%s' invalid. Ignoring.", rvalue);
+ log_syntax(unit, LOG_ERR, filename, line, 0, "CPU quota '%s' invalid. Ignoring.", rvalue);
return 0;
}
@@ -2668,7 +2707,7 @@ int config_parse_memory_limit(
r = parse_size(rvalue, 1024, &bytes);
if (r < 0 || bytes < 1) {
- log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Memory limit '%s' invalid. Ignoring.", rvalue);
+ log_syntax(unit, LOG_ERR, filename, line, r, "Memory limit '%s' invalid. Ignoring.", rvalue);
return 0;
}
@@ -2699,7 +2738,7 @@ int config_parse_tasks_max(
r = safe_atou64(rvalue, &u);
if (r < 0 || u < 1) {
- log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Maximum tasks value '%s' invalid. Ignoring.", rvalue);
+ log_syntax(unit, LOG_ERR, filename, line, r, "Maximum tasks value '%s' invalid. Ignoring.", rvalue);
return 0;
}
@@ -2739,8 +2778,7 @@ int config_parse_device_allow(
if (!startswith(path, "/dev/") &&
!startswith(path, "block-") &&
!startswith(path, "char-")) {
- log_syntax(unit, LOG_ERR, filename, line, EINVAL,
- "Invalid device node path '%s'. Ignoring.", path);
+ log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid device node path '%s'. Ignoring.", path);
return 0;
}
@@ -2749,8 +2787,7 @@ int config_parse_device_allow(
m = "rwm";
if (!in_charset(m, "rwm")) {
- log_syntax(unit, LOG_ERR, filename, line, EINVAL,
- "Invalid device rights '%s'. Ignoring.", m);
+ log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid device rights '%s'. Ignoring.", m);
return 0;
}
@@ -2832,7 +2869,7 @@ int config_parse_blockio_device_weight(
weight += strspn(weight, WHITESPACE);
if (isempty(weight)) {
- log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Expected block device and device weight. Ignoring.");
+ log_syntax(unit, LOG_ERR, filename, line, 0, "Expected block device and device weight. Ignoring.");
return 0;
}
@@ -2841,7 +2878,7 @@ int config_parse_blockio_device_weight(
return log_oom();
if (!path_startswith(path, "/dev")) {
- log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Invalid device node path '%s'. Ignoring.", path);
+ log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid device node path '%s'. Ignoring.", path);
return 0;
}
@@ -2908,8 +2945,7 @@ int config_parse_blockio_bandwidth(
bandwidth += strspn(bandwidth, WHITESPACE);
if (!*bandwidth) {
- log_syntax(unit, LOG_ERR, filename, line, EINVAL,
- "Expected space separated pair of device node and bandwidth. Ignoring.");
+ log_syntax(unit, LOG_ERR, filename, line, 0, "Expected space separated pair of device node and bandwidth. Ignoring.");
return 0;
}
@@ -2918,15 +2954,13 @@ int config_parse_blockio_bandwidth(
return log_oom();
if (!path_startswith(path, "/dev")) {
- log_syntax(unit, LOG_ERR, filename, line, EINVAL,
- "Invalid device node path '%s'. Ignoring.", path);
+ log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid device node path '%s'. Ignoring.", path);
return 0;
}
r = parse_size(bandwidth, 1000, &bytes);
if (r < 0 || bytes <= 0) {
- log_syntax(unit, LOG_ERR, filename, line, EINVAL,
- "Block IO Bandwidth '%s' invalid. Ignoring.", rvalue);
+ log_syntax(unit, LOG_ERR, filename, line, r, "Block IO Bandwidth '%s' invalid. Ignoring.", rvalue);
return 0;
}
@@ -2971,13 +3005,12 @@ int config_parse_netclass(
r = safe_atou32(rvalue, &v);
if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, EINVAL,
- "Netclass '%s' invalid. Ignoring.", rvalue);
+ log_syntax(unit, LOG_ERR, filename, line, r, "Netclass '%s' invalid. Ignoring.", rvalue);
return 0;
}
if (v > CGROUP_NETCLASS_FIXED_MAX)
- log_syntax(unit, LOG_ERR, filename, line, EINVAL,
+ log_syntax(unit, LOG_ERR, filename, line, 0,
"Fixed netclass %" PRIu32 " out of allowed range (0-%d). Applying anyway.", v, (uint32_t) CGROUP_NETCLASS_FIXED_MAX);
c->netclass_id = v;
@@ -3009,8 +3042,7 @@ int config_parse_job_mode_isolate(
r = parse_boolean(rvalue);
if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, EINVAL,
- "Failed to parse boolean, ignoring: %s", rvalue);
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse boolean, ignoring: %s", rvalue);
return 0;
}
@@ -3056,14 +3088,12 @@ int config_parse_runtime_directory(
r = unit_name_printf(u, t, &n);
if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, -r,
- "Failed to resolve specifiers, ignoring: %s", strerror(-r));
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve specifiers, ignoring: %m");
continue;
}
if (!filename_is_valid(n)) {
- log_syntax(unit, LOG_ERR, filename, line, EINVAL,
- "Runtime directory is not valid, ignoring assignment: %s", rvalue);
+ log_syntax(unit, LOG_ERR, filename, line, 0, "Runtime directory is not valid, ignoring assignment: %s", rvalue);
continue;
}
@@ -3074,8 +3104,7 @@ int config_parse_runtime_directory(
n = NULL;
}
if (!isempty(state))
- log_syntax(unit, LOG_ERR, filename, line, EINVAL,
- "Trailing garbage, ignoring.");
+ log_syntax(unit, LOG_ERR, filename, line, 0, "Trailing garbage, ignoring.");
return 0;
}
@@ -3122,15 +3151,13 @@ int config_parse_set_status(
val = signal_from_string_try_harder(temp);
if (val <= 0) {
- log_syntax(unit, LOG_ERR, filename, line, -val,
- "Failed to parse value, ignoring: %s", word);
+ log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse value, ignoring: %s", word);
continue;
}
set = &status_set->signal;
} else {
if (val < 0 || val > 255) {
- log_syntax(unit, LOG_ERR, filename, line, ERANGE,
- "Value %d is outside range 0-255, ignoring", val);
+ log_syntax(unit, LOG_ERR, filename, line, 0, "Value %d is outside range 0-255, ignoring", val);
continue;
}
set = &status_set->status;
@@ -3142,14 +3169,12 @@ int config_parse_set_status(
r = set_put(*set, INT_TO_PTR(val));
if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, -r,
- "Unable to store: %s", word);
+ log_syntax(unit, LOG_ERR, filename, line, r, "Unable to store: %s", word);
return r;
}
}
if (!isempty(state))
- log_syntax(unit, LOG_ERR, filename, line, EINVAL,
- "Trailing garbage, ignoring.");
+ log_syntax(unit, LOG_ERR, filename, line, 0, "Trailing garbage, ignoring.");
return 0;
}
@@ -3191,14 +3216,13 @@ int config_parse_namespace_path_strv(
return log_oom();
if (!utf8_is_valid(n)) {
- log_invalid_utf8(unit, LOG_ERR, filename, line, EINVAL, rvalue);
+ log_syntax_invalid_utf8(unit, LOG_ERR, filename, line, rvalue);
continue;
}
offset = n[0] == '-';
if (!path_is_absolute(n + offset)) {
- log_syntax(unit, LOG_ERR, filename, line, EINVAL,
- "Not an absolute path, ignoring: %s", rvalue);
+ log_syntax(unit, LOG_ERR, filename, line, 0, "Not an absolute path, ignoring: %s", rvalue);
continue;
}
@@ -3211,8 +3235,7 @@ int config_parse_namespace_path_strv(
n = NULL;
}
if (!isempty(state))
- log_syntax(unit, LOG_ERR, filename, line, EINVAL,
- "Trailing garbage, ignoring.");
+ log_syntax(unit, LOG_ERR, filename, line, 0, "Trailing garbage, ignoring.");
return 0;
}
@@ -3239,8 +3262,7 @@ int config_parse_no_new_privileges(
k = parse_boolean(rvalue);
if (k < 0) {
- log_syntax(unit, LOG_ERR, filename, line, -k,
- "Failed to parse boolean value, ignoring: %s", rvalue);
+ log_syntax(unit, LOG_ERR, filename, line, k, "Failed to parse boolean value, ignoring: %s", rvalue);
return 0;
}
@@ -3283,8 +3305,7 @@ int config_parse_protect_home(
h = protect_home_from_string(rvalue);
if (h < 0){
- log_syntax(unit, LOG_ERR, filename, line, -h,
- "Failed to parse protect home value, ignoring: %s", rvalue);
+ log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse protect home value, ignoring: %s", rvalue);
return 0;
}
@@ -3327,8 +3348,7 @@ int config_parse_protect_system(
s = protect_system_from_string(rvalue);
if (s < 0){
- log_syntax(unit, LOG_ERR, filename, line, -s,
- "Failed to parse protect system value, ignoring: %s", rvalue);
+ log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse protect system value, ignoring: %s", rvalue);
return 0;
}
diff --git a/src/core/load-fragment.h b/src/core/load-fragment.h
index 5d0a09249f..8661cbfedc 100644
--- a/src/core/load-fragment.h
+++ b/src/core/load-fragment.h
@@ -106,6 +106,8 @@ int config_parse_protect_home(const char* unit, const char *filename, unsigned l
int config_parse_protect_system(const char* unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
int config_parse_bus_name(const char* unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
int config_parse_exec_utmp_mode(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
+int config_parse_working_directory(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
+int config_parse_fdname(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
/* gperf prototypes */
const struct ConfigPerfItem* load_fragment_gperf_lookup(const char *key, unsigned length);
diff --git a/src/core/machine-id-setup.c b/src/core/machine-id-setup.c
index 8f682c6d10..363ffaaf05 100644
--- a/src/core/machine-id-setup.c
+++ b/src/core/machine-id-setup.c
@@ -19,24 +19,25 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <unistd.h>
-#include <stdio.h>
#include <errno.h>
-#include <string.h>
#include <fcntl.h>
+#include <sched.h>
+#include <stdio.h>
+#include <string.h>
#include <sys/mount.h>
+#include <unistd.h>
-#include "systemd/sd-id128.h"
+#include "sd-id128.h"
-#include "machine-id-setup.h"
+#include "fileio.h"
+#include "log.h"
#include "macro.h"
-#include "util.h"
#include "mkdir.h"
-#include "log.h"
-#include "virt.h"
-#include "fileio.h"
#include "path-util.h"
#include "process-util.h"
+#include "util.h"
+#include "virt.h"
+#include "machine-id-setup.h"
static int shorten_uuid(char destination[34], const char source[36]) {
unsigned i, j;
diff --git a/src/core/main.c b/src/core/main.c
index bc72a2b00b..87b3af92bc 100644
--- a/src/core/main.c
+++ b/src/core/main.c
@@ -19,63 +19,64 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <stdio.h>
#include <errno.h>
-#include <string.h>
-#include <unistd.h>
-#include <sys/stat.h>
+#include <fcntl.h>
#include <getopt.h>
#include <signal.h>
-#include <fcntl.h>
-#include <sys/prctl.h>
+#include <stdio.h>
+#include <string.h>
#include <sys/mount.h>
-
-#ifdef HAVE_VALGRIND_VALGRIND_H
-#include <valgrind/valgrind.h>
-#endif
+#include <sys/prctl.h>
+#include <sys/reboot.h>
+#include <sys/stat.h>
+#include <unistd.h>
#ifdef HAVE_SECCOMP
#include <seccomp.h>
#endif
+#ifdef HAVE_VALGRIND_VALGRIND_H
+#include <valgrind/valgrind.h>
+#endif
#include "sd-daemon.h"
#include "sd-bus.h"
-#include "log.h"
-#include "fdset.h"
-#include "special.h"
-#include "conf-parser.h"
-#include "missing.h"
-#include "pager.h"
-#include "build.h"
-#include "strv.h"
-#include "def.h"
-#include "virt.h"
+
#include "architecture.h"
-#include "watchdog.h"
-#include "switch-root.h"
+#include "build.h"
+#include "bus-error.h"
+#include "bus-util.h"
#include "capability.h"
-#include "killall.h"
-#include "env-util.h"
#include "clock-util.h"
+#include "conf-parser.h"
+#include "cpu-set-util.h"
+#include "dbus-manager.h"
+#include "def.h"
+#include "env-util.h"
+#include "fdset.h"
#include "fileio.h"
-#include "bus-error.h"
-#include "bus-util.h"
-#include "selinux-util.h"
#include "formats-util.h"
-#include "process-util.h"
-#include "terminal-util.h"
-#include "signal-util.h"
-#include "manager.h"
-#include "dbus-manager.h"
+#include "hostname-setup.h"
+#include "ima-setup.h"
+#include "killall.h"
+#include "kmod-setup.h"
#include "load-fragment.h"
-
-#include "mount-setup.h"
+#include "log.h"
#include "loopback-setup.h"
-#include "hostname-setup.h"
#include "machine-id-setup.h"
+#include "manager.h"
+#include "missing.h"
+#include "mount-setup.h"
+#include "pager.h"
+#include "process-util.h"
#include "selinux-setup.h"
-#include "ima-setup.h"
+#include "selinux-util.h"
+#include "signal-util.h"
#include "smack-setup.h"
-#include "kmod-setup.h"
+#include "special.h"
+#include "strv.h"
+#include "switch-root.h"
+#include "terminal-util.h"
+#include "virt.h"
+#include "watchdog.h"
static enum {
ACTION_RUN,
@@ -88,8 +89,9 @@ static enum {
static char *arg_default_unit = NULL;
static ManagerRunningAs arg_running_as = _MANAGER_RUNNING_AS_INVALID;
static bool arg_dump_core = true;
-static bool arg_crash_shell = false;
static int arg_crash_chvt = -1;
+static bool arg_crash_shell = false;
+static bool arg_crash_reboot = false;
static bool arg_confirm_spawn = false;
static ShowStatus arg_show_status = _SHOW_STATUS_UNSET;
static bool arg_switched_root = false;
@@ -116,8 +118,6 @@ static bool arg_default_blockio_accounting = false;
static bool arg_default_memory_accounting = false;
static bool arg_default_tasks_accounting = false;
-static void nop_handler(int sig) {}
-
static void pager_open_if_enabled(void) {
if (arg_no_pager <= 0)
@@ -126,49 +126,66 @@ static void pager_open_if_enabled(void) {
pager_open(false);
}
+noreturn static void freeze_or_reboot(void) {
+
+ if (arg_crash_reboot) {
+ log_notice("Rebooting in 10s...");
+ (void) sleep(10);
+
+ log_notice("Rebooting now...");
+ (void) reboot(RB_AUTOBOOT);
+ log_emergency_errno(errno, "Failed to reboot: %m");
+ }
+
+ log_emergency("Freezing execution.");
+ freeze();
+}
+
noreturn static void crash(int sig) {
+ struct sigaction sa;
+ pid_t pid;
if (getpid() != 1)
/* Pass this on immediately, if this is not PID 1 */
- raise(sig);
+ (void) raise(sig);
else if (!arg_dump_core)
log_emergency("Caught <%s>, not dumping core.", signal_to_string(sig));
else {
- struct sigaction sa = {
- .sa_handler = nop_handler,
+ sa = (struct sigaction) {
+ .sa_handler = nop_signal_handler,
.sa_flags = SA_NOCLDSTOP|SA_RESTART,
};
- pid_t pid;
/* We want to wait for the core process, hence let's enable SIGCHLD */
- sigaction(SIGCHLD, &sa, NULL);
+ (void) sigaction(SIGCHLD, &sa, NULL);
pid = raw_clone(SIGCHLD, NULL);
if (pid < 0)
log_emergency_errno(errno, "Caught <%s>, cannot fork for core dump: %m", signal_to_string(sig));
-
else if (pid == 0) {
- struct rlimit rl = {};
+ struct rlimit rl = {
+ .rlim_cur = RLIM_INFINITY,
+ .rlim_max = RLIM_INFINITY,
+ };
/* Enable default signal handler for core dump */
- zero(sa);
- sa.sa_handler = SIG_DFL;
- sigaction(sig, &sa, NULL);
+ sa = (struct sigaction) {
+ .sa_handler = SIG_DFL,
+ };
+ (void) sigaction(sig, &sa, NULL);
/* Don't limit the core dump size */
- rl.rlim_cur = RLIM_INFINITY;
- rl.rlim_max = RLIM_INFINITY;
- setrlimit(RLIMIT_CORE, &rl);
+ (void) setrlimit(RLIMIT_CORE, &rl);
/* Just to be sure... */
(void) chdir("/");
/* Raise the signal again */
pid = raw_getpid();
- kill(pid, sig); /* raise() would kill the parent */
+ (void) kill(pid, sig); /* raise() would kill the parent */
assert_not_reached("We shouldn't be here...");
- _exit(1);
+ _exit(EXIT_FAILURE);
} else {
siginfo_t status;
int r;
@@ -190,37 +207,38 @@ noreturn static void crash(int sig) {
}
}
- if (arg_crash_chvt)
- chvt(arg_crash_chvt);
+ if (arg_crash_chvt >= 0)
+ (void) chvt(arg_crash_chvt);
- if (arg_crash_shell) {
- struct sigaction sa = {
- .sa_handler = SIG_IGN,
- .sa_flags = SA_NOCLDSTOP|SA_NOCLDWAIT|SA_RESTART,
- };
- pid_t pid;
+ sa = (struct sigaction) {
+ .sa_handler = SIG_IGN,
+ .sa_flags = SA_NOCLDSTOP|SA_NOCLDWAIT|SA_RESTART,
+ };
- log_info("Executing crash shell in 10s...");
- sleep(10);
+ /* Let the kernel reap children for us */
+ (void) sigaction(SIGCHLD, &sa, NULL);
- /* Let the kernel reap children for us */
- assert_se(sigaction(SIGCHLD, &sa, NULL) == 0);
+ if (arg_crash_shell) {
+ log_notice("Executing crash shell in 10s...");
+ (void) sleep(10);
pid = raw_clone(SIGCHLD, NULL);
if (pid < 0)
log_emergency_errno(errno, "Failed to fork off crash shell: %m");
else if (pid == 0) {
- make_console_stdio();
- execle("/bin/sh", "/bin/sh", NULL, environ);
+ (void) setsid();
+ (void) make_console_stdio();
+ (void) execle("/bin/sh", "/bin/sh", NULL, environ);
log_emergency_errno(errno, "execle() failed: %m");
- _exit(1);
- } else
- log_info("Successfully spawned crash shell as PID "PID_FMT".", pid);
+ _exit(EXIT_FAILURE);
+ } else {
+ log_info("Spawned crash shell as PID "PID_FMT".", pid);
+ (void) wait_for_terminate(pid, NULL);
+ }
}
- log_emergency("Freezing execution.");
- freeze();
+ freeze_or_reboot();
}
static void install_crash_handler(void) {
@@ -254,17 +272,20 @@ static int console_setup(void) {
return 0;
}
-static int set_default_unit(const char *u) {
- char *c;
+static int parse_crash_chvt(const char *value) {
+ int b;
- assert(u);
+ if (safe_atoi(value, &arg_crash_chvt) >= 0)
+ return 0;
- c = strdup(u);
- if (!c)
- return -ENOMEM;
+ b = parse_boolean(value);
+ if (b < 0)
+ return b;
- free(arg_default_unit);
- arg_default_unit = c;
+ if (b > 0)
+ arg_crash_chvt = 0; /* switch to where kmsg goes */
+ else
+ arg_crash_chvt = -1; /* turn off switching */
return 0;
}
@@ -292,12 +313,12 @@ static int parse_proc_cmdline_item(const char *key, const char *value) {
if (streq(key, "systemd.unit") && value) {
if (!in_initrd())
- return set_default_unit(value);
+ return free_and_strdup(&arg_default_unit, value);
} else if (streq(key, "rd.systemd.unit") && value) {
if (in_initrd())
- return set_default_unit(value);
+ return free_and_strdup(&arg_default_unit, value);
} else if (streq(key, "systemd.dump_core") && value) {
@@ -307,6 +328,11 @@ static int parse_proc_cmdline_item(const char *key, const char *value) {
else
arg_dump_core = r;
+ } else if (streq(key, "systemd.crash_chvt") && value) {
+
+ if (parse_crash_chvt(value) < 0)
+ log_warning("Failed to parse crash chvt switch %s. Ignoring.", value);
+
} else if (streq(key, "systemd.crash_shell") && value) {
r = parse_boolean(value);
@@ -315,12 +341,13 @@ static int parse_proc_cmdline_item(const char *key, const char *value) {
else
arg_crash_shell = r;
- } else if (streq(key, "systemd.crash_chvt") && value) {
+ } else if (streq(key, "systemd.crash_reboot") && value) {
- if (safe_atoi(value, &r) < 0)
- log_warning("Failed to parse crash chvt switch %s. Ignoring.", value);
+ r = parse_boolean(value);
+ if (r < 0)
+ log_warning("Failed to parse crash reboot switch %s. Ignoring.", value);
else
- arg_crash_chvt = r;
+ arg_crash_reboot = r;
} else if (streq(key, "systemd.confirm_spawn") && value) {
@@ -384,7 +411,7 @@ static int parse_proc_cmdline_item(const char *key, const char *value) {
/* SysV compatibility */
for (i = 0; i < ELEMENTSOF(rlmap); i += 2)
if (streq(key, rlmap[i]))
- return set_default_unit(rlmap[i+1]);
+ return free_and_strdup(&arg_default_unit, rlmap[i+1]);
}
return 0;
@@ -410,9 +437,9 @@ static int parse_proc_cmdline_item(const char *key, const char *value) {
\
r = func(rvalue); \
if (r < 0) \
- log_syntax(unit, LOG_ERR, filename, line, -r, \
- "Invalid " descr "'%s': %s", \
- rvalue, strerror(-r)); \
+ log_syntax(unit, LOG_ERR, filename, line, r, \
+ "Invalid " descr "'%s': %m", \
+ rvalue); \
\
return 0; \
}
@@ -437,8 +464,7 @@ static int config_parse_cpu_affinity2(
_cleanup_cpu_free_ cpu_set_t *c = NULL;
int ncpus;
- ncpus = parse_cpu_set(rvalue, &c, unit, filename, line, lvalue);
-
+ ncpus = parse_cpu_set_and_warn(rvalue, &c, unit, filename, line, lvalue);
if (ncpus < 0)
return ncpus;
@@ -470,29 +496,38 @@ static int config_parse_show_status(
k = parse_show_status(rvalue, b);
if (k < 0) {
- log_syntax(unit, LOG_ERR, filename, line, -k,
- "Failed to parse show status setting, ignoring: %s", rvalue);
+ log_syntax(unit, LOG_ERR, filename, line, k, "Failed to parse show status setting, ignoring: %s", rvalue);
return 0;
}
return 0;
}
-static void strv_free_free(char ***l) {
- char ***i;
+static int config_parse_crash_chvt(
+ const char* unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
- if (!l)
- return;
+ int r;
- for (i = l; *i; i++)
- strv_free(*i);
+ assert(filename);
+ assert(lvalue);
+ assert(rvalue);
- free(l);
-}
+ r = parse_crash_chvt(rvalue);
+ if (r < 0) {
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse CrashChangeVT= setting, ignoring: %s", rvalue);
+ return 0;
+ }
-static void free_join_controllers(void) {
- strv_free_free(arg_join_controllers);
- arg_join_controllers = NULL;
+ return 0;
}
static int config_parse_join_controllers(const char *unit,
@@ -513,7 +548,7 @@ static int config_parse_join_controllers(const char *unit,
assert(lvalue);
assert(rvalue);
- free_join_controllers();
+ arg_join_controllers = strv_free_free(arg_join_controllers);
for (;;) {
_cleanup_free_ char *word = NULL;
@@ -530,7 +565,7 @@ static int config_parse_join_controllers(const char *unit,
l = strv_split(word, ",");
if (!l)
- log_oom();
+ return log_oom();
strv_uniq(l);
if (strv_length(l) <= 1) {
@@ -564,7 +599,7 @@ static int config_parse_join_controllers(const char *unit,
for (a = arg_join_controllers; *a; a++) {
if (strv_overlap(*a, l)) {
- if (strv_extend_strv(&l, *a) < 0) {
+ if (strv_extend_strv(&l, *a, false) < 0) {
strv_free(l);
strv_free_free(t);
return log_oom();
@@ -591,8 +626,7 @@ static int config_parse_join_controllers(const char *unit,
}
}
if (!isempty(rvalue))
- log_syntax(unit, LOG_ERR, filename, line, EINVAL,
- "Trailing garbage, ignoring.");
+ log_syntax(unit, LOG_ERR, filename, line, 0, "Trailing garbage, ignoring.");
return 0;
}
@@ -605,9 +639,11 @@ static int parse_config_file(void) {
{ "Manager", "LogColor", config_parse_color, 0, NULL },
{ "Manager", "LogLocation", config_parse_location, 0, NULL },
{ "Manager", "DumpCore", config_parse_bool, 0, &arg_dump_core },
+ { "Manager", "CrashChVT", /* legacy */ config_parse_crash_chvt, 0, NULL },
+ { "Manager", "CrashChangeVT", config_parse_crash_chvt, 0, NULL },
{ "Manager", "CrashShell", config_parse_bool, 0, &arg_crash_shell },
+ { "Manager", "CrashReboot", config_parse_bool, 0, &arg_crash_reboot },
{ "Manager", "ShowStatus", config_parse_show_status, 0, &arg_show_status },
- { "Manager", "CrashChVT", config_parse_int, 0, &arg_crash_chvt },
{ "Manager", "CPUAffinity", config_parse_cpu_affinity2, 0, NULL },
{ "Manager", "JoinControllers", config_parse_join_controllers, 0, &arg_join_controllers },
{ "Manager", "RuntimeWatchdogSec", config_parse_sec, 0, &arg_runtime_watchdog },
@@ -695,7 +731,9 @@ static int parse_argv(int argc, char *argv[]) {
ARG_VERSION,
ARG_DUMP_CONFIGURATION_ITEMS,
ARG_DUMP_CORE,
+ ARG_CRASH_CHVT,
ARG_CRASH_SHELL,
+ ARG_CRASH_REBOOT,
ARG_CONFIRM_SPAWN,
ARG_SHOW_STATUS,
ARG_DESERIALIZE,
@@ -718,7 +756,9 @@ static int parse_argv(int argc, char *argv[]) {
{ "version", no_argument, NULL, ARG_VERSION },
{ "dump-configuration-items", no_argument, NULL, ARG_DUMP_CONFIGURATION_ITEMS },
{ "dump-core", optional_argument, NULL, ARG_DUMP_CORE },
+ { "crash-chvt", required_argument, NULL, ARG_CRASH_CHVT },
{ "crash-shell", optional_argument, NULL, ARG_CRASH_SHELL },
+ { "crash-reboot", optional_argument, NULL, ARG_CRASH_REBOOT },
{ "confirm-spawn", optional_argument, NULL, ARG_CONFIRM_SPAWN },
{ "show-status", optional_argument, NULL, ARG_SHOW_STATUS },
{ "deserialize", required_argument, NULL, ARG_DESERIALIZE },
@@ -803,7 +843,7 @@ static int parse_argv(int argc, char *argv[]) {
case ARG_UNIT:
- r = set_default_unit(optarg);
+ r = free_and_strdup(&arg_default_unit, optarg);
if (r < 0)
return log_error_errno(r, "Failed to set default unit %s: %m", optarg);
@@ -836,21 +876,42 @@ static int parse_argv(int argc, char *argv[]) {
break;
case ARG_DUMP_CORE:
- r = optarg ? parse_boolean(optarg) : 1;
- if (r < 0) {
- log_error("Failed to parse dump core boolean %s.", optarg);
- return r;
+ if (!optarg)
+ arg_dump_core = true;
+ else {
+ r = parse_boolean(optarg);
+ if (r < 0)
+ return log_error_errno(r, "Failed to parse dump core boolean: %s", optarg);
+ arg_dump_core = r;
}
- arg_dump_core = r;
+ break;
+
+ case ARG_CRASH_CHVT:
+ r = parse_crash_chvt(optarg);
+ if (r < 0)
+ return log_error_errno(r, "Failed to parse crash virtual terminal index: %s", optarg);
break;
case ARG_CRASH_SHELL:
- r = optarg ? parse_boolean(optarg) : 1;
- if (r < 0) {
- log_error("Failed to parse crash shell boolean %s.", optarg);
- return r;
+ if (!optarg)
+ arg_crash_shell = true;
+ else {
+ r = parse_boolean(optarg);
+ if (r < 0)
+ return log_error_errno(r, "Failed to parse crash shell boolean: %s", optarg);
+ arg_crash_shell = r;
+ }
+ break;
+
+ case ARG_CRASH_REBOOT:
+ if (!optarg)
+ arg_crash_reboot = true;
+ else {
+ r = parse_boolean(optarg);
+ if (r < 0)
+ return log_error_errno(r, "Failed to parse crash shell boolean: %s", optarg);
+ arg_crash_reboot = r;
}
- arg_crash_shell = r;
break;
case ARG_CONFIRM_SPAWN:
@@ -880,17 +941,16 @@ static int parse_argv(int argc, char *argv[]) {
r = safe_atoi(optarg, &fd);
if (r < 0 || fd < 0) {
log_error("Failed to parse deserialize option %s.", optarg);
- return r < 0 ? r : -EINVAL;
+ return -EINVAL;
}
- fd_cloexec(fd, true);
+ (void) fd_cloexec(fd, true);
f = fdopen(fd, "r");
if (!f)
return log_error_errno(errno, "Failed to open serialization fd: %m");
safe_fclose(arg_serialization);
-
arg_serialization = f;
break;
@@ -950,14 +1010,16 @@ static int help(void) {
" --unit=UNIT Set default unit\n"
" --system Run a system instance, even if PID != 1\n"
" --user Run a user instance\n"
- " --dump-core[=0|1] Dump core on crash\n"
- " --crash-shell[=0|1] Run shell on crash\n"
- " --confirm-spawn[=0|1] Ask for confirmation when spawning processes\n"
- " --show-status[=0|1] Show status updates on the console during bootup\n"
+ " --dump-core[=BOOL] Dump core on crash\n"
+ " --crash-vt=NR Change to specified VT on crash\n"
+ " --crash-reboot[=BOOL] Reboot on crash\n"
+ " --crash-shell[=BOOL] Run shell on crash\n"
+ " --confirm-spawn[=BOOL] Ask for confirmation when spawning processes\n"
+ " --show-status[=BOOL] Show status updates on the console during bootup\n"
" --log-target=TARGET Set log target (console, journal, kmsg, journal-or-kmsg, null)\n"
" --log-level=LEVEL Set log level (debug, info, notice, warning, err, crit, alert, emerg)\n"
- " --log-color[=0|1] Highlight important log messages\n"
- " --log-location[=0|1] Include code location in log messages\n"
+ " --log-color[=BOOL] Highlight important log messages\n"
+ " --log-location[=BOOL] Include code location in log messages\n"
" --default-standard-output= Set default standard output for services\n"
" --default-standard-error= Set default standard error output for services\n",
program_invocation_short_name);
@@ -965,16 +1027,9 @@ static int help(void) {
return 0;
}
-static int version(void) {
- puts(PACKAGE_STRING);
- puts(SYSTEMD_FEATURES);
-
- return 0;
-}
-
static int prepare_reexecute(Manager *m, FILE **_f, FDSet **_fds, bool switching_root) {
- FILE *f = NULL;
- FDSet *fds = NULL;
+ _cleanup_fdset_free_ FDSet *fds = NULL;
+ _cleanup_fclose_ FILE *f = NULL;
int r;
assert(m);
@@ -982,56 +1037,39 @@ static int prepare_reexecute(Manager *m, FILE **_f, FDSet **_fds, bool switching
assert(_fds);
r = manager_open_serialization(m, &f);
- if (r < 0) {
- log_error_errno(r, "Failed to create serialization file: %m");
- goto fail;
- }
+ if (r < 0)
+ return log_error_errno(r, "Failed to create serialization file: %m");
/* Make sure nothing is really destructed when we shut down */
m->n_reloading ++;
bus_manager_send_reloading(m, true);
fds = fdset_new();
- if (!fds) {
- r = -ENOMEM;
- log_error_errno(r, "Failed to allocate fd set: %m");
- goto fail;
- }
+ if (!fds)
+ return log_oom();
r = manager_serialize(m, f, fds, switching_root);
- if (r < 0) {
- log_error_errno(r, "Failed to serialize state: %m");
- goto fail;
- }
+ if (r < 0)
+ return log_error_errno(r, "Failed to serialize state: %m");
- if (fseeko(f, 0, SEEK_SET) < 0) {
- log_error_errno(errno, "Failed to rewind serialization fd: %m");
- goto fail;
- }
+ if (fseeko(f, 0, SEEK_SET) == (off_t) -1)
+ return log_error_errno(errno, "Failed to rewind serialization fd: %m");
r = fd_cloexec(fileno(f), false);
- if (r < 0) {
- log_error_errno(r, "Failed to disable O_CLOEXEC for serialization: %m");
- goto fail;
- }
+ if (r < 0)
+ return log_error_errno(r, "Failed to disable O_CLOEXEC for serialization: %m");
r = fdset_cloexec(fds, false);
- if (r < 0) {
- log_error_errno(r, "Failed to disable O_CLOEXEC for serialization fds: %m");
- goto fail;
- }
+ if (r < 0)
+ return log_error_errno(r, "Failed to disable O_CLOEXEC for serialization fds: %m");
*_f = f;
*_fds = fds;
- return 0;
-
-fail:
- fdset_free(fds);
-
- safe_fclose(f);
+ f = NULL;
+ fds = NULL;
- return r;
+ return 0;
}
static int bump_rlimit_nofile(struct rlimit *saved_rlimit) {
@@ -1089,8 +1127,8 @@ static void test_mtab(void) {
log_error("/etc/mtab is not a symlink or not pointing to /proc/self/mounts. "
"This is not supported anymore. "
- "Please make sure to replace this file by a symlink to avoid incorrect or misleading mount(8) output.");
- freeze();
+ "Please replace /etc/mtab with a symlink to /proc/self/mounts.");
+ freeze_or_reboot();
}
static void test_usr(void) {
@@ -1116,15 +1154,19 @@ static int initialize_join_controllers(void) {
return -ENOMEM;
arg_join_controllers[0] = strv_new("cpu", "cpuacct", NULL);
- arg_join_controllers[1] = strv_new("net_cls", "net_prio", NULL);
- arg_join_controllers[2] = NULL;
+ if (!arg_join_controllers[0])
+ goto oom;
- if (!arg_join_controllers[0] || !arg_join_controllers[1]) {
- free_join_controllers();
- return -ENOMEM;
- }
+ arg_join_controllers[1] = strv_new("net_cls", "net_prio", NULL);
+ if (!arg_join_controllers[1])
+ goto oom;
+ arg_join_controllers[2] = NULL;
return 0;
+
+oom:
+ arg_join_controllers = strv_free_free(arg_join_controllers);
+ return -ENOMEM;
}
static int enforce_syscall_archs(Set *archs) {
@@ -1222,7 +1264,6 @@ int main(int argc, char *argv[]) {
char *switch_root_dir = NULL, *switch_root_init = NULL;
struct rlimit saved_rlimit_nofile = RLIMIT_MAKE_CONST(0);
const char *error_message = NULL;
- uint8_t shutdown_exit_code = 0;
#ifdef HAVE_SYSV_COMPAT
if (getpid() != 1 && strstr(program_invocation_short_name, "init")) {
@@ -1369,7 +1410,7 @@ int main(int argc, char *argv[]) {
}
/* Initialize default unit */
- r = set_default_unit(SPECIAL_DEFAULT_TARGET);
+ r = free_and_strdup(&arg_default_unit, SPECIAL_DEFAULT_TARGET);
if (r < 0) {
log_emergency_errno(r, "Failed to set default unit %s: %m", SPECIAL_DEFAULT_TARGET);
error_message = "Failed to set default unit";
@@ -1646,8 +1687,7 @@ int main(int argc, char *argv[]) {
/* This will close all file descriptors that were opened, but
* not claimed by any unit. */
- fdset_free(fds);
- fds = NULL;
+ fds = fdset_free(fds);
arg_serialization = safe_fclose(arg_serialization);
@@ -1775,8 +1815,9 @@ int main(int argc, char *argv[]) {
goto finish;
case MANAGER_EXIT:
+ retval = m->return_value;
+
if (m->running_as == MANAGER_USER) {
- retval = EXIT_SUCCESS;
log_debug("Exit.");
goto finish;
}
@@ -1809,21 +1850,17 @@ int main(int argc, char *argv[]) {
finish:
pager_close();
- if (m) {
+ if (m)
arg_shutdown_watchdog = m->shutdown_watchdog;
- shutdown_exit_code = m->return_value;
- }
+
m = manager_free(m);
for (j = 0; j < ELEMENTSOF(arg_default_rlimit); j++)
arg_default_rlimit[j] = mfree(arg_default_rlimit[j]);
arg_default_unit = mfree(arg_default_unit);
-
- free_join_controllers();
-
+ arg_join_controllers = strv_free_free(arg_join_controllers);
arg_default_environment = strv_free(arg_default_environment);
-
arg_syscall_archs = set_free(arg_syscall_archs);
mac_selinux_finish();
@@ -1841,7 +1878,7 @@ finish:
* that the new systemd can pass the kernel default to
* its child processes */
if (saved_rlimit_nofile.rlim_cur > 0)
- setrlimit(RLIMIT_NOFILE, &saved_rlimit_nofile);
+ (void) setrlimit(RLIMIT_NOFILE, &saved_rlimit_nofile);
if (switch_root_dir) {
/* Kill all remaining processes from the
@@ -1883,10 +1920,10 @@ finish:
/* do not pass along the environment we inherit from the kernel or initrd */
if (switch_root_dir)
- clearenv();
+ (void) clearenv();
assert(i <= args_size);
- execv(args[0], (char* const*) args);
+ (void) execv(args[0], (char* const*) args);
}
/* Try the fallback, if there is any, without any
@@ -1896,14 +1933,10 @@ finish:
* but let's hope that doesn't matter.) */
arg_serialization = safe_fclose(arg_serialization);
-
- if (fds) {
- fdset_free(fds);
- fds = NULL;
- }
+ fds = fdset_free(fds);
/* Reopen the console */
- make_console_stdio();
+ (void) make_console_stdio();
for (j = 1, i = 1; j < (unsigned) argc; j++)
args[i++] = argv[j];
@@ -1917,30 +1950,26 @@ finish:
if (switch_root_init) {
args[0] = switch_root_init;
- execv(args[0], (char* const*) args);
+ (void) execv(args[0], (char* const*) args);
log_warning_errno(errno, "Failed to execute configured init, trying fallback: %m");
}
args[0] = "/sbin/init";
- execv(args[0], (char* const*) args);
+ (void) execv(args[0], (char* const*) args);
if (errno == ENOENT) {
log_warning("No /sbin/init, trying fallback");
args[0] = "/bin/sh";
args[1] = NULL;
- execv(args[0], (char* const*) args);
+ (void) execv(args[0], (char* const*) args);
log_error_errno(errno, "Failed to execute /bin/sh, giving up: %m");
} else
log_warning_errno(errno, "Failed to execute /sbin/init, giving up: %m");
}
arg_serialization = safe_fclose(arg_serialization);
-
- if (fds) {
- fdset_free(fds);
- fds = NULL;
- }
+ fds = fdset_free(fds);
#ifdef HAVE_VALGRIND_VALGRIND_H
/* If we are PID 1 and running under valgrind, then let's exit
@@ -1969,6 +1998,7 @@ finish:
xsprintf(log_level, "%d", log_get_max_level());
switch (log_get_target()) {
+
case LOG_TARGET_KMSG:
case LOG_TARGET_JOURNAL_OR_KMSG:
case LOG_TARGET_SYSLOG_OR_KMSG:
@@ -1994,7 +2024,7 @@ finish:
if (streq(shutdown_verb, "exit")) {
command_line[pos++] = "--exit-code";
command_line[pos++] = exit_code;
- xsprintf(exit_code, "%d", shutdown_exit_code);
+ xsprintf(exit_code, "%d", retval);
}
assert(pos < ELEMENTSOF(command_line));
@@ -2010,7 +2040,7 @@ finish:
/* Tell the binary how often to ping, ignore failure */
if (asprintf(&e, "WATCHDOG_USEC="USEC_FMT, arg_shutdown_watchdog) > 0)
- strv_push(&env_block, e);
+ (void) strv_push(&env_block, e);
} else
watchdog_close(true);
@@ -2030,7 +2060,7 @@ finish:
manager_status_printf(NULL, STATUS_TYPE_EMERGENCY,
ANSI_HIGHLIGHT_RED "!!!!!!" ANSI_NORMAL,
"%s, freezing.", error_message);
- freeze();
+ freeze_or_reboot();
}
return retval;
diff --git a/src/core/manager.c b/src/core/manager.c
index 9bfe867ea0..526d4d1cef 100644
--- a/src/core/manager.c
+++ b/src/core/manager.c
@@ -19,19 +19,19 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include <dirent.h>
#include <errno.h>
-#include <string.h>
+#include <fcntl.h>
+#include <linux/kd.h>
#include <signal.h>
-#include <sys/wait.h>
-#include <unistd.h>
-#include <sys/inotify.h>
+#include <string.h>
#include <sys/epoll.h>
-#include <sys/reboot.h>
+#include <sys/inotify.h>
#include <sys/ioctl.h>
-#include <linux/kd.h>
-#include <fcntl.h>
-#include <dirent.h>
+#include <sys/reboot.h>
#include <sys/timerfd.h>
+#include <sys/wait.h>
+#include <unistd.h>
#ifdef HAVE_AUDIT
#include <libaudit.h>
@@ -40,40 +40,40 @@
#include "sd-daemon.h"
#include "sd-messages.h"
+#include "audit-fd.h"
+#include "boot-timestamps.h"
+#include "bus-common-errors.h"
+#include "bus-error.h"
+#include "bus-kernel.h"
+#include "bus-util.h"
+#include "dbus-job.h"
+#include "dbus-manager.h"
+#include "dbus-unit.h"
+#include "dbus.h"
+#include "env-util.h"
+#include "exit-status.h"
#include "hashmap.h"
-#include "macro.h"
-#include "strv.h"
+#include "locale-setup.h"
#include "log.h"
-#include "util.h"
+#include "macro.h"
+#include "missing.h"
#include "mkdir.h"
+#include "path-lookup.h"
+#include "path-util.h"
+#include "process-util.h"
#include "ratelimit.h"
-#include "locale-setup.h"
-#include "unit-name.h"
-#include "missing.h"
#include "rm-rf.h"
-#include "path-lookup.h"
+#include "signal-util.h"
#include "special.h"
-#include "exit-status.h"
+#include "strv.h"
+#include "terminal-util.h"
+#include "time-util.h"
+#include "transaction.h"
+#include "unit-name.h"
+#include "util.h"
#include "virt.h"
#include "watchdog.h"
-#include "path-util.h"
-#include "audit-fd.h"
-#include "boot-timestamps.h"
-#include "env-util.h"
-#include "bus-common-errors.h"
-#include "bus-error.h"
-#include "bus-util.h"
-#include "bus-kernel.h"
-#include "time-util.h"
-#include "process-util.h"
-#include "terminal-util.h"
-#include "signal-util.h"
-#include "dbus.h"
-#include "dbus-unit.h"
-#include "dbus-job.h"
-#include "dbus-manager.h"
#include "manager.h"
-#include "transaction.h"
/* Initial delay and the interval for printing status messages about running jobs */
#define JOBS_IN_PROGRESS_WAIT_USEC (5*USEC_PER_SEC)
@@ -495,6 +495,7 @@ static void manager_clean_environment(Manager *m) {
"MANAGERPID",
"LISTEN_PID",
"LISTEN_FDS",
+ "LISTEN_FDNAMES",
"WATCHDOG_PID",
"WATCHDOG_USEC",
NULL);
diff --git a/src/core/manager.h b/src/core/manager.h
index cc0e5e3361..fad10aaacf 100644
--- a/src/core/manager.h
+++ b/src/core/manager.h
@@ -27,8 +27,8 @@
#include "sd-bus.h"
#include "sd-event.h"
-#include "fdset.h"
#include "cgroup-util.h"
+#include "fdset.h"
#include "hashmap.h"
#include "list.h"
#include "ratelimit.h"
@@ -69,11 +69,11 @@ typedef enum StatusType {
STATUS_TYPE_EMERGENCY,
} StatusType;
+#include "execute.h"
#include "job.h"
#include "path-lookup.h"
-#include "execute.h"
-#include "unit-name.h"
#include "show-status.h"
+#include "unit-name.h"
struct Manager {
/* Note that the set of units we know of is allowed to be
diff --git a/src/core/mount.c b/src/core/mount.c
index e7aae6e19a..8611129453 100644
--- a/src/core/mount.c
+++ b/src/core/mount.c
@@ -694,6 +694,9 @@ static int mount_spawn(Mount *m, ExecCommand *c, pid_t *_pid) {
.apply_chroot = true,
.apply_tty_stdin = true,
.bus_endpoint_fd = -1,
+ .stdin_fd = -1,
+ .stdout_fd = -1,
+ .stderr_fd = -1,
};
assert(m);
@@ -1756,24 +1759,6 @@ static int mount_kill(Unit *u, KillWho who, int signo, sd_bus_error *error) {
return unit_kill_common(u, who, signo, -1, MOUNT(u)->control_pid, error);
}
-static const char* const mount_state_table[_MOUNT_STATE_MAX] = {
- [MOUNT_DEAD] = "dead",
- [MOUNT_MOUNTING] = "mounting",
- [MOUNT_MOUNTING_DONE] = "mounting-done",
- [MOUNT_MOUNTED] = "mounted",
- [MOUNT_REMOUNTING] = "remounting",
- [MOUNT_UNMOUNTING] = "unmounting",
- [MOUNT_MOUNTING_SIGTERM] = "mounting-sigterm",
- [MOUNT_MOUNTING_SIGKILL] = "mounting-sigkill",
- [MOUNT_REMOUNTING_SIGTERM] = "remounting-sigterm",
- [MOUNT_REMOUNTING_SIGKILL] = "remounting-sigkill",
- [MOUNT_UNMOUNTING_SIGTERM] = "unmounting-sigterm",
- [MOUNT_UNMOUNTING_SIGKILL] = "unmounting-sigkill",
- [MOUNT_FAILED] = "failed"
-};
-
-DEFINE_STRING_TABLE_LOOKUP(mount_state, MountState);
-
static const char* const mount_exec_command_table[_MOUNT_EXEC_COMMAND_MAX] = {
[MOUNT_EXEC_MOUNT] = "ExecMount",
[MOUNT_EXEC_UNMOUNT] = "ExecUnmount",
diff --git a/src/core/mount.h b/src/core/mount.h
index 280ea0d638..83d14ae713 100644
--- a/src/core/mount.h
+++ b/src/core/mount.h
@@ -26,24 +26,6 @@ typedef struct Mount Mount;
#include "kill.h"
#include "execute.h"
-typedef enum MountState {
- MOUNT_DEAD,
- MOUNT_MOUNTING, /* /usr/bin/mount is running, but the mount is not done yet. */
- MOUNT_MOUNTING_DONE, /* /usr/bin/mount is running, and the mount is done. */
- MOUNT_MOUNTED,
- MOUNT_REMOUNTING,
- MOUNT_UNMOUNTING,
- MOUNT_MOUNTING_SIGTERM,
- MOUNT_MOUNTING_SIGKILL,
- MOUNT_REMOUNTING_SIGTERM,
- MOUNT_REMOUNTING_SIGKILL,
- MOUNT_UNMOUNTING_SIGTERM,
- MOUNT_UNMOUNTING_SIGKILL,
- MOUNT_FAILED,
- _MOUNT_STATE_MAX,
- _MOUNT_STATE_INVALID = -1
-} MountState;
-
typedef enum MountExecCommand {
MOUNT_EXEC_MOUNT,
MOUNT_EXEC_UNMOUNT,
@@ -120,9 +102,6 @@ extern const UnitVTable mount_vtable;
void mount_fd_event(Manager *m, int events);
-const char* mount_state_to_string(MountState i) _const_;
-MountState mount_state_from_string(const char *s) _pure_;
-
const char* mount_exec_command_to_string(MountExecCommand i) _const_;
MountExecCommand mount_exec_command_from_string(const char *s) _pure_;
diff --git a/src/core/namespace.c b/src/core/namespace.c
index eb88574f8f..2b8b707df5 100644
--- a/src/core/namespace.c
+++ b/src/core/namespace.c
@@ -643,16 +643,7 @@ int setup_tmp_dirs(const char *id, char **tmp_dir, char **var_tmp_dir) {
int setup_netns(int netns_storage_socket[2]) {
_cleanup_close_ int netns = -1;
- union {
- struct cmsghdr cmsghdr;
- uint8_t buf[CMSG_SPACE(sizeof(int))];
- } control = {};
- struct msghdr mh = {
- .msg_control = &control,
- .msg_controllen = sizeof(control),
- };
- struct cmsghdr *cmsg;
- int r;
+ int r, q;
assert(netns_storage_socket);
assert(netns_storage_socket[0] >= 0);
@@ -669,12 +660,8 @@ int setup_netns(int netns_storage_socket[2]) {
if (lockf(netns_storage_socket[0], F_LOCK, 0) < 0)
return -errno;
- if (recvmsg(netns_storage_socket[0], &mh, MSG_DONTWAIT|MSG_CMSG_CLOEXEC) < 0) {
- if (errno != EAGAIN) {
- r = -errno;
- goto fail;
- }
-
+ netns = receive_one_fd(netns_storage_socket[0], MSG_DONTWAIT);
+ if (netns == -EAGAIN) {
/* Nothing stored yet, so let's create a new namespace */
if (unshare(CLONE_NEWNET) < 0) {
@@ -691,15 +678,13 @@ int setup_netns(int netns_storage_socket[2]) {
}
r = 1;
- } else {
- /* Yay, found something, so let's join the namespace */
- CMSG_FOREACH(cmsg, &mh)
- if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) {
- assert(cmsg->cmsg_len == CMSG_LEN(sizeof(int)));
- netns = *(int*) CMSG_DATA(cmsg);
- }
+ } else if (netns < 0) {
+ r = netns;
+ goto fail;
+ } else {
+ /* Yay, found something, so let's join the namespace */
if (setns(netns, CLONE_NEWNET) < 0) {
r = -errno;
goto fail;
@@ -708,21 +693,14 @@ int setup_netns(int netns_storage_socket[2]) {
r = 0;
}
- cmsg = CMSG_FIRSTHDR(&mh);
- cmsg->cmsg_level = SOL_SOCKET;
- cmsg->cmsg_type = SCM_RIGHTS;
- cmsg->cmsg_len = CMSG_LEN(sizeof(int));
- memcpy(CMSG_DATA(cmsg), &netns, sizeof(int));
- mh.msg_controllen = cmsg->cmsg_len;
-
- if (sendmsg(netns_storage_socket[1], &mh, MSG_DONTWAIT|MSG_NOSIGNAL) < 0) {
- r = -errno;
+ q = send_one_fd(netns_storage_socket[1], netns, MSG_DONTWAIT);
+ if (q < 0) {
+ r = q;
goto fail;
}
fail:
lockf(netns_storage_socket[0], F_ULOCK, 0);
-
return r;
}
diff --git a/src/core/path.c b/src/core/path.c
index e9111d0612..081ac2040d 100644
--- a/src/core/path.c
+++ b/src/core/path.c
@@ -715,15 +715,6 @@ static void path_reset_failed(Unit *u) {
p->result = PATH_SUCCESS;
}
-static const char* const path_state_table[_PATH_STATE_MAX] = {
- [PATH_DEAD] = "dead",
- [PATH_WAITING] = "waiting",
- [PATH_RUNNING] = "running",
- [PATH_FAILED] = "failed"
-};
-
-DEFINE_STRING_TABLE_LOOKUP(path_state, PathState);
-
static const char* const path_type_table[_PATH_TYPE_MAX] = {
[PATH_EXISTS] = "PathExists",
[PATH_EXISTS_GLOB] = "PathExistsGlob",
diff --git a/src/core/path.h b/src/core/path.h
index dec39333e4..deb9bab1e5 100644
--- a/src/core/path.h
+++ b/src/core/path.h
@@ -26,15 +26,6 @@ typedef struct PathSpec PathSpec;
#include "unit.h"
-typedef enum PathState {
- PATH_DEAD,
- PATH_WAITING,
- PATH_RUNNING,
- PATH_FAILED,
- _PATH_STATE_MAX,
- _PATH_STATE_INVALID = -1
-} PathState;
-
typedef enum PathType {
PATH_EXISTS,
PATH_EXISTS_GLOB,
@@ -96,9 +87,6 @@ void path_free_specs(Path *p);
extern const UnitVTable path_vtable;
-const char* path_state_to_string(PathState i) _const_;
-PathState path_state_from_string(const char *s) _pure_;
-
const char* path_type_to_string(PathType i) _const_;
PathType path_type_from_string(const char *s) _pure_;
diff --git a/src/core/scope.c b/src/core/scope.c
index 98395becfd..7325e3601b 100644
--- a/src/core/scope.c
+++ b/src/core/scope.c
@@ -549,17 +549,6 @@ static int scope_enumerate(Manager *m) {
return 0;
}
-static const char* const scope_state_table[_SCOPE_STATE_MAX] = {
- [SCOPE_DEAD] = "dead",
- [SCOPE_RUNNING] = "running",
- [SCOPE_ABANDONED] = "abandoned",
- [SCOPE_STOP_SIGTERM] = "stop-sigterm",
- [SCOPE_STOP_SIGKILL] = "stop-sigkill",
- [SCOPE_FAILED] = "failed",
-};
-
-DEFINE_STRING_TABLE_LOOKUP(scope_state, ScopeState);
-
static const char* const scope_result_table[_SCOPE_RESULT_MAX] = {
[SCOPE_SUCCESS] = "success",
[SCOPE_FAILURE_RESOURCES] = "resources",
diff --git a/src/core/scope.h b/src/core/scope.h
index 4452fe2c94..f838ee5357 100644
--- a/src/core/scope.h
+++ b/src/core/scope.h
@@ -25,17 +25,6 @@ typedef struct Scope Scope;
#include "kill.h"
-typedef enum ScopeState {
- SCOPE_DEAD,
- SCOPE_RUNNING,
- SCOPE_ABANDONED,
- SCOPE_STOP_SIGTERM,
- SCOPE_STOP_SIGKILL,
- SCOPE_FAILED,
- _SCOPE_STATE_MAX,
- _SCOPE_STATE_INVALID = -1
-} ScopeState;
-
typedef enum ScopeResult {
SCOPE_SUCCESS,
SCOPE_FAILURE_RESOURCES,
@@ -64,8 +53,5 @@ extern const UnitVTable scope_vtable;
int scope_abandon(Scope *s);
-const char* scope_state_to_string(ScopeState i) _const_;
-ScopeState scope_state_from_string(const char *s) _pure_;
-
const char* scope_result_to_string(ScopeResult i) _const_;
ScopeResult scope_result_from_string(const char *s) _pure_;
diff --git a/src/core/selinux-setup.c b/src/core/selinux-setup.c
index e5b457643b..ff1ea23528 100644
--- a/src/core/selinux-setup.c
+++ b/src/core/selinux-setup.c
@@ -78,14 +78,14 @@ int mac_selinux_setup(bool *loaded_policy) {
before_load = now(CLOCK_MONOTONIC);
r = selinux_init_load_policy(&enforce);
if (r == 0) {
+ _cleanup_(mac_selinux_freep) char *label = NULL;
char timespan[FORMAT_TIMESPAN_MAX];
- char *label;
mac_selinux_retest();
/* Transition to the new context */
r = mac_selinux_get_create_label_from_exe(SYSTEMD_BINARY_PATH, &label);
- if (r < 0 || label == NULL) {
+ if (r < 0 || !label) {
log_open();
log_error("Failed to compute init label, ignoring.");
} else {
@@ -94,8 +94,6 @@ int mac_selinux_setup(bool *loaded_policy) {
log_open();
if (r < 0)
log_error("Failed to transition into init label '%s', ignoring.", label);
-
- mac_selinux_free(label);
}
after_load = now(CLOCK_MONOTONIC);
diff --git a/src/core/service.c b/src/core/service.c
index f7de5e89ff..1e4f707bf4 100644
--- a/src/core/service.c
+++ b/src/core/service.c
@@ -108,6 +108,7 @@ static void service_init(Unit *u) {
s->type = _SERVICE_TYPE_INVALID;
s->socket_fd = -1;
s->bus_endpoint_fd = -1;
+ s->stdin_fd = s->stdout_fd = s->stderr_fd = -1;
s->guess_main_pid = true;
RATELIMIT_INIT(s->start_limit, u->manager->default_start_limit_interval, u->manager->default_start_limit_burst);
@@ -261,6 +262,7 @@ static void service_fd_store_unlink(ServiceFDStore *fs) {
sd_event_source_unref(fs->event_source);
}
+ free(fs->fdname);
safe_close(fs->fd);
free(fs);
}
@@ -270,11 +272,15 @@ static void service_release_resources(Unit *u) {
assert(s);
- if (!s->fd_store)
+ if (!s->fd_store && s->stdin_fd < 0 && s->stdout_fd < 0 && s->stderr_fd < 0)
return;
log_unit_debug(u, "Releasing all resources.");
+ s->stdin_fd = safe_close(s->stdin_fd);
+ s->stdout_fd = safe_close(s->stdout_fd);
+ s->stderr_fd = safe_close(s->stderr_fd);
+
while (s->fd_store)
service_fd_store_unlink(s->fd_store);
@@ -334,7 +340,7 @@ static int on_fd_store_io(sd_event_source *e, int fd, uint32_t revents, void *us
return 0;
}
-static int service_add_fd_store(Service *s, int fd) {
+static int service_add_fd_store(Service *s, int fd, const char *name) {
ServiceFDStore *fs;
int r;
@@ -361,9 +367,15 @@ static int service_add_fd_store(Service *s, int fd) {
fs->fd = fd;
fs->service = s;
+ fs->fdname = strdup(name ?: "stored");
+ if (!fs->fdname) {
+ free(fs);
+ return -ENOMEM;
+ }
r = sd_event_add_io(UNIT(s)->manager->event, &fs->event_source, fd, 0, on_fd_store_io, fs);
if (r < 0) {
+ free(fs->fdname);
free(fs);
return r;
}
@@ -376,7 +388,7 @@ static int service_add_fd_store(Service *s, int fd) {
return 1;
}
-static int service_add_fd_store_set(Service *s, FDSet *fds) {
+static int service_add_fd_store_set(Service *s, FDSet *fds, const char *name) {
int r;
assert(s);
@@ -391,7 +403,7 @@ static int service_add_fd_store_set(Service *s, FDSet *fds) {
if (fd < 0)
break;
- r = service_add_fd_store(s, fd);
+ r = service_add_fd_store(s, fd, name);
if (r < 0)
return log_unit_error_errno(UNIT(s), r, "Couldn't add fd to fd store: %m");
if (r > 0) {
@@ -884,7 +896,6 @@ static void service_set_state(Service *s, ServiceState state) {
log_unit_debug(UNIT(s), "Changed %s -> %s", service_state_to_string(old_state), service_state_to_string(state));
unit_notify(UNIT(s), table[old_state], table[state], s->reload_result == SERVICE_SUCCESS);
- s->reload_result = SERVICE_SUCCESS;
}
static int service_coldplug(Unit *u) {
@@ -957,62 +968,79 @@ static int service_coldplug(Unit *u) {
return 0;
}
-static int service_collect_fds(Service *s, int **fds, unsigned *n_fds) {
+static int service_collect_fds(Service *s, int **fds, char ***fd_names) {
+ _cleanup_strv_free_ char **rfd_names = NULL;
_cleanup_free_ int *rfds = NULL;
- unsigned rn_fds = 0;
- Iterator i;
- int r;
- Unit *u;
+ int rn_fds = 0, r;
assert(s);
assert(fds);
- assert(n_fds);
+ assert(fd_names);
- if (s->socket_fd >= 0)
- return 0;
+ if (s->socket_fd >= 0) {
- SET_FOREACH(u, UNIT(s)->dependencies[UNIT_TRIGGERED_BY], i) {
- int *cfds;
- unsigned cn_fds;
- Socket *sock;
+ /* Pass the per-connection socket */
- if (u->type != UNIT_SOCKET)
- continue;
+ rfds = new(int, 1);
+ if (!rfds)
+ return -ENOMEM;
+ rfds[0] = s->socket_fd;
- sock = SOCKET(u);
+ rfd_names = strv_new("connection", NULL);
+ if (!rfd_names)
+ return -ENOMEM;
- r = socket_collect_fds(sock, &cfds, &cn_fds);
- if (r < 0)
- return r;
+ rn_fds = 1;
+ } else {
+ Iterator i;
+ Unit *u;
- if (cn_fds <= 0) {
- free(cfds);
- continue;
- }
+ /* Pass all our configured sockets for singleton services */
- if (!rfds) {
- rfds = cfds;
- rn_fds = cn_fds;
- } else {
- int *t;
+ SET_FOREACH(u, UNIT(s)->dependencies[UNIT_TRIGGERED_BY], i) {
+ _cleanup_free_ int *cfds = NULL;
+ Socket *sock;
+ int cn_fds;
- t = realloc(rfds, (rn_fds + cn_fds) * sizeof(int));
- if (!t) {
- free(cfds);
- return -ENOMEM;
- }
+ if (u->type != UNIT_SOCKET)
+ continue;
+
+ sock = SOCKET(u);
- memcpy(t + rn_fds, cfds, cn_fds * sizeof(int));
- rfds = t;
- rn_fds += cn_fds;
+ cn_fds = socket_collect_fds(sock, &cfds);
+ if (cn_fds < 0)
+ return cn_fds;
- free(cfds);
+ if (cn_fds <= 0)
+ continue;
+
+ if (!rfds) {
+ rfds = cfds;
+ rn_fds = cn_fds;
+
+ cfds = NULL;
+ } else {
+ int *t;
+
+ t = realloc(rfds, (rn_fds + cn_fds) * sizeof(int));
+ if (!t)
+ return -ENOMEM;
+
+ memcpy(t + rn_fds, cfds, cn_fds * sizeof(int));
+
+ rfds = t;
+ rn_fds += cn_fds;
+ }
+ r = strv_extend_n(&rfd_names, socket_fdname(sock), cn_fds);
+ if (r < 0)
+ return r;
}
}
if (s->n_fd_store > 0) {
ServiceFDStore *fs;
+ char **nl;
int *t;
t = realloc(rfds, (rn_fds + s->n_fd_store) * sizeof(int));
@@ -1020,15 +1048,32 @@ static int service_collect_fds(Service *s, int **fds, unsigned *n_fds) {
return -ENOMEM;
rfds = t;
- LIST_FOREACH(fd_store, fs, s->fd_store)
- rfds[rn_fds++] = fs->fd;
+
+ nl = realloc(rfd_names, (rn_fds + s->n_fd_store + 1) * sizeof(char*));
+ if (!nl)
+ return -ENOMEM;
+
+ rfd_names = nl;
+
+ LIST_FOREACH(fd_store, fs, s->fd_store) {
+ rfds[rn_fds] = fs->fd;
+ rfd_names[rn_fds] = strdup(strempty(fs->fdname));
+ if (!rfd_names[rn_fds])
+ return -ENOMEM;
+
+ rn_fds++;
+ }
+
+ rfd_names[rn_fds] = NULL;
}
*fds = rfds;
- *n_fds = rn_fds;
+ *fd_names = rfd_names;
rfds = NULL;
- return 0;
+ rfd_names = NULL;
+
+ return rn_fds;
}
static int service_spawn(
@@ -1042,23 +1087,25 @@ static int service_spawn(
bool is_control,
pid_t *_pid) {
- pid_t pid;
- int r;
- int *fds = NULL;
- _cleanup_free_ int *fdsbuf = NULL;
- unsigned n_fds = 0, n_env = 0;
+ _cleanup_strv_free_ char **argv = NULL, **final_env = NULL, **our_env = NULL, **fd_names = NULL;
_cleanup_free_ char *bus_endpoint_path = NULL;
- _cleanup_strv_free_ char
- **argv = NULL, **final_env = NULL, **our_env = NULL;
+ _cleanup_free_ int *fds = NULL;
+ unsigned n_fds = 0, n_env = 0;
const char *path;
+ pid_t pid;
+
ExecParameters exec_params = {
- .apply_permissions = apply_permissions,
- .apply_chroot = apply_chroot,
- .apply_tty_stdin = apply_tty_stdin,
- .bus_endpoint_fd = -1,
- .selinux_context_net = s->socket_fd_selinux_context_net
+ .apply_permissions = apply_permissions,
+ .apply_chroot = apply_chroot,
+ .apply_tty_stdin = apply_tty_stdin,
+ .bus_endpoint_fd = -1,
+ .stdin_fd = -1,
+ .stdout_fd = -1,
+ .stderr_fd = -1,
};
+ int r;
+
assert(s);
assert(c);
assert(_pid);
@@ -1078,16 +1125,11 @@ static int service_spawn(
s->exec_context.std_output == EXEC_OUTPUT_SOCKET ||
s->exec_context.std_error == EXEC_OUTPUT_SOCKET) {
- if (s->socket_fd >= 0) {
- fds = &s->socket_fd;
- n_fds = 1;
- } else {
- r = service_collect_fds(s, &fdsbuf, &n_fds);
- if (r < 0)
- goto fail;
+ r = service_collect_fds(s, &fds, &fd_names);
+ if (r < 0)
+ goto fail;
- fds = fdsbuf;
- }
+ n_fds = r;
}
if (timeout > 0) {
@@ -1125,7 +1167,7 @@ static int service_spawn(
goto fail;
}
- if (UNIT_DEREF(s->accept_socket)) {
+ if (s->socket_fd >= 0) {
union sockaddr_union sa;
socklen_t salen = sizeof(sa);
@@ -1191,6 +1233,7 @@ static int service_spawn(
exec_params.argv = argv;
exec_params.fds = fds;
+ exec_params.fd_names = fd_names;
exec_params.n_fds = n_fds;
exec_params.environment = final_env;
exec_params.confirm_spawn = UNIT(s)->manager->confirm_spawn;
@@ -1200,8 +1243,12 @@ static int service_spawn(
exec_params.runtime_prefix = manager_get_runtime_prefix(UNIT(s)->manager);
exec_params.watchdog_usec = s->watchdog_usec;
exec_params.bus_endpoint_path = bus_endpoint_path;
+ exec_params.selinux_context_net = s->socket_fd_selinux_context_net;
if (s->type == SERVICE_IDLE)
exec_params.idle_pipe = UNIT(s)->manager->idle_pipe;
+ exec_params.stdin_fd = s->stdin_fd;
+ exec_params.stdout_fd = s->stdout_fd;
+ exec_params.stderr_fd = s->stderr_fd;
r = exec_spawn(UNIT(s),
c,
@@ -1778,6 +1825,7 @@ static void service_enter_reload(Service *s) {
assert(s);
service_unwatch_control_pid(s);
+ s->reload_result = SERVICE_SUCCESS;
s->control_command = s->exec_command[SERVICE_EXEC_RELOAD];
if (s->control_command) {
@@ -2001,6 +2049,7 @@ _pure_ static bool service_can_reload(Unit *u) {
static int service_serialize(Unit *u, FILE *f, FDSet *fds) {
Service *s = SERVICE(u);
ServiceFDStore *fs;
+ int r;
assert(u);
assert(f);
@@ -2019,12 +2068,9 @@ static int service_serialize(Unit *u, FILE *f, FDSet *fds) {
unit_serialize_item(u, f, "main-pid-known", yes_no(s->main_pid_known));
unit_serialize_item(u, f, "bus-name-good", yes_no(s->bus_name_good));
- if (s->status_text) {
- _cleanup_free_ char *c = NULL;
-
- c = cescape(s->status_text);
- unit_serialize_item(u, f, "status-text", strempty(c));
- }
+ r = unit_serialize_item_escaped(u, f, "status-text", s->status_text);
+ if (r < 0)
+ return r;
/* FIXME: There's a minor uncleanliness here: if there are
* multiple commands attached here, we will start from the
@@ -2032,34 +2078,34 @@ static int service_serialize(Unit *u, FILE *f, FDSet *fds) {
if (s->control_command_id >= 0)
unit_serialize_item(u, f, "control-command", service_exec_command_to_string(s->control_command_id));
- if (s->socket_fd >= 0) {
- int copy;
-
- copy = fdset_put_dup(fds, s->socket_fd);
- if (copy < 0)
- return copy;
-
- unit_serialize_item_format(u, f, "socket-fd", "%i", copy);
- }
-
- if (s->bus_endpoint_fd >= 0) {
- int copy;
-
- copy = fdset_put_dup(fds, s->bus_endpoint_fd);
- if (copy < 0)
- return copy;
+ r = unit_serialize_item_fd(u, f, fds, "stdin-fd", s->stdin_fd);
+ if (r < 0)
+ return r;
+ r = unit_serialize_item_fd(u, f, fds, "stdout-fd", s->stdout_fd);
+ if (r < 0)
+ return r;
+ r = unit_serialize_item_fd(u, f, fds, "stderr-fd", s->stderr_fd);
+ if (r < 0)
+ return r;
- unit_serialize_item_format(u, f, "endpoint-fd", "%i", copy);
- }
+ r = unit_serialize_item_fd(u, f, fds, "socket-fd", s->socket_fd);
+ if (r < 0)
+ return r;
+ r = unit_serialize_item_fd(u, f, fds, "endpoint-fd", s->bus_endpoint_fd);
+ if (r < 0)
+ return r;
LIST_FOREACH(fd_store, fs, s->fd_store) {
+ _cleanup_free_ char *c = NULL;
int copy;
copy = fdset_put_dup(fds, fs->fd);
if (copy < 0)
return copy;
- unit_serialize_item_format(u, f, "fd-store-fd", "%i", copy);
+ c = cescape(fs->fdname);
+
+ unit_serialize_item_format(u, f, "fd-store-fd", "%i %s", copy, strempty(c));
}
if (s->main_exec_status.pid > 0) {
@@ -2076,8 +2122,7 @@ static int service_serialize(Unit *u, FILE *f, FDSet *fds) {
if (dual_timestamp_is_set(&s->watchdog_timestamp))
dual_timestamp_serialize(f, "watchdog-timestamp", &s->watchdog_timestamp);
- if (s->forbid_restart)
- unit_serialize_item(u, f, "forbid-restart", yes_no(s->forbid_restart));
+ unit_serialize_item(u, f, "forbid-restart", yes_no(s->forbid_restart));
return 0;
}
@@ -2189,12 +2234,24 @@ static int service_deserialize_item(Unit *u, const char *key, const char *value,
s->bus_endpoint_fd = fdset_remove(fds, fd);
}
} else if (streq(key, "fd-store-fd")) {
+ const char *fdv;
+ size_t pf;
int fd;
- if (safe_atoi(value, &fd) < 0 || fd < 0 || !fdset_contains(fds, fd))
+ pf = strcspn(value, WHITESPACE);
+ fdv = strndupa(value, pf);
+
+ if (safe_atoi(fdv, &fd) < 0 || fd < 0 || !fdset_contains(fds, fd))
log_unit_debug(u, "Failed to parse fd-store-fd value: %s", value);
else {
- r = service_add_fd_store(s, fd);
+ _cleanup_free_ char *t = NULL;
+ const char *fdn;
+
+ fdn = value + pf;
+ fdn += strspn(fdn, WHITESPACE);
+ (void) cunescape(fdn, 0, &t);
+
+ r = service_add_fd_store(s, fd, t);
if (r < 0)
log_unit_error_errno(u, r, "Failed to add fd to store: %m");
else if (r > 0)
@@ -2236,6 +2293,33 @@ static int service_deserialize_item(Unit *u, const char *key, const char *value,
log_unit_debug(u, "Failed to parse forbid-restart value: %s", value);
else
s->forbid_restart = b;
+ } else if (streq(key, "stdin-fd")) {
+ int fd;
+
+ if (safe_atoi(value, &fd) < 0 || fd < 0 || !fdset_contains(fds, fd))
+ log_unit_debug(u, "Failed to parse stdin-fd value: %s", value);
+ else {
+ asynchronous_close(s->stdin_fd);
+ s->stdin_fd = fdset_remove(fds, fd);
+ }
+ } else if (streq(key, "stdout-fd")) {
+ int fd;
+
+ if (safe_atoi(value, &fd) < 0 || fd < 0 || !fdset_contains(fds, fd))
+ log_unit_debug(u, "Failed to parse stdout-fd value: %s", value);
+ else {
+ asynchronous_close(s->stdout_fd);
+ s->stdout_fd = fdset_remove(fds, fd);
+ }
+ } else if (streq(key, "stderr-fd")) {
+ int fd;
+
+ if (safe_atoi(value, &fd) < 0 || fd < 0 || !fdset_contains(fds, fd))
+ log_unit_debug(u, "Failed to parse stderr-fd value: %s", value);
+ else {
+ asynchronous_close(s->stderr_fd);
+ s->stderr_fd = fdset_remove(fds, fd);
+ }
} else
log_unit_debug(u, "Unknown serialization key: %s", key);
@@ -2948,8 +3032,17 @@ static void service_notify_message(Unit *u, pid_t pid, char **tags, FDSet *fds)
if (strv_find(tags, "WATCHDOG=1"))
service_reset_watchdog(s);
- if (strv_find(tags, "FDSTORE=1"))
- service_add_fd_store_set(s, fds);
+ if (strv_find(tags, "FDSTORE=1")) {
+ const char *name;
+
+ name = strv_find_startswith(tags, "FDNAME=");
+ if (name && !fdname_is_valid(name)) {
+ log_unit_warning(u, "Passed FDNAME= name is invalid, ignoring.");
+ name = NULL;
+ }
+
+ service_add_fd_store_set(s, fds, name);
+ }
/* Notify clients about changed status or main pid */
if (notify_dbus)
@@ -3092,27 +3185,6 @@ static int service_kill(Unit *u, KillWho who, int signo, sd_bus_error *error) {
return unit_kill_common(u, who, signo, s->main_pid, s->control_pid, error);
}
-static const char* const service_state_table[_SERVICE_STATE_MAX] = {
- [SERVICE_DEAD] = "dead",
- [SERVICE_START_PRE] = "start-pre",
- [SERVICE_START] = "start",
- [SERVICE_START_POST] = "start-post",
- [SERVICE_RUNNING] = "running",
- [SERVICE_EXITED] = "exited",
- [SERVICE_RELOAD] = "reload",
- [SERVICE_STOP] = "stop",
- [SERVICE_STOP_SIGABRT] = "stop-sigabrt",
- [SERVICE_STOP_SIGTERM] = "stop-sigterm",
- [SERVICE_STOP_SIGKILL] = "stop-sigkill",
- [SERVICE_STOP_POST] = "stop-post",
- [SERVICE_FINAL_SIGTERM] = "final-sigterm",
- [SERVICE_FINAL_SIGKILL] = "final-sigkill",
- [SERVICE_FAILED] = "failed",
- [SERVICE_AUTO_RESTART] = "auto-restart",
-};
-
-DEFINE_STRING_TABLE_LOOKUP(service_state, ServiceState);
-
static const char* const service_restart_table[_SERVICE_RESTART_MAX] = {
[SERVICE_RESTART_NO] = "no",
[SERVICE_RESTART_ON_SUCCESS] = "on-success",
diff --git a/src/core/service.h b/src/core/service.h
index 789dff23a9..e765668247 100644
--- a/src/core/service.h
+++ b/src/core/service.h
@@ -29,27 +29,6 @@ typedef struct ServiceFDStore ServiceFDStore;
#include "kill.h"
#include "exit-status.h"
-typedef enum ServiceState {
- SERVICE_DEAD,
- SERVICE_START_PRE,
- SERVICE_START,
- SERVICE_START_POST,
- SERVICE_RUNNING,
- SERVICE_EXITED, /* Nothing is running anymore, but RemainAfterExit is true hence this is OK */
- SERVICE_RELOAD,
- SERVICE_STOP, /* No STOP_PRE state, instead just register multiple STOP executables */
- SERVICE_STOP_SIGABRT, /* Watchdog timeout */
- SERVICE_STOP_SIGTERM,
- SERVICE_STOP_SIGKILL,
- SERVICE_STOP_POST,
- SERVICE_FINAL_SIGTERM, /* In case the STOP_POST executable hangs, we shoot that down, too */
- SERVICE_FINAL_SIGKILL,
- SERVICE_FAILED,
- SERVICE_AUTO_RESTART,
- _SERVICE_STATE_MAX,
- _SERVICE_STATE_INVALID = -1
-} ServiceState;
-
typedef enum ServiceRestart {
SERVICE_RESTART_NO,
SERVICE_RESTART_ON_SUCCESS,
@@ -118,6 +97,7 @@ struct ServiceFDStore {
Service *service;
int fd;
+ char *fdname;
sd_event_source *event_source;
LIST_FIELDS(ServiceFDStore, fd_store);
@@ -215,15 +195,16 @@ struct Service {
char *usb_function_descriptors;
char *usb_function_strings;
+
+ int stdin_fd;
+ int stdout_fd;
+ int stderr_fd;
};
extern const UnitVTable service_vtable;
int service_set_socket_fd(Service *s, int fd, struct Socket *socket, bool selinux_context_net);
-const char* service_state_to_string(ServiceState i) _const_;
-ServiceState service_state_from_string(const char *s) _pure_;
-
const char* service_restart_to_string(ServiceRestart i) _const_;
ServiceRestart service_restart_from_string(const char *s) _pure_;
diff --git a/src/core/shutdown.c b/src/core/shutdown.c
index 5296efce1d..27c581d9c1 100644
--- a/src/core/shutdown.c
+++ b/src/core/shutdown.c
@@ -430,6 +430,5 @@ int main(int argc, char *argv[]) {
error:
log_emergency_errno(r, "Critical error while doing system shutdown: %m");
-
freeze();
}
diff --git a/src/core/slice.c b/src/core/slice.c
index b414462066..063024134a 100644
--- a/src/core/slice.c
+++ b/src/core/slice.c
@@ -287,13 +287,6 @@ static int slice_enumerate(Manager *m) {
return 0;
}
-static const char* const slice_state_table[_SLICE_STATE_MAX] = {
- [SLICE_DEAD] = "dead",
- [SLICE_ACTIVE] = "active"
-};
-
-DEFINE_STRING_TABLE_LOOKUP(slice_state, SliceState);
-
const UnitVTable slice_vtable = {
.object_size = sizeof(Slice),
.cgroup_context_offset = offsetof(Slice, cgroup_context),
diff --git a/src/core/slice.h b/src/core/slice.h
index ac648e56f8..0c356651e3 100644
--- a/src/core/slice.h
+++ b/src/core/slice.h
@@ -23,14 +23,6 @@
typedef struct Slice Slice;
-
-typedef enum SliceState {
- SLICE_DEAD,
- SLICE_ACTIVE,
- _SLICE_STATE_MAX,
- _SLICE_STATE_INVALID = -1
-} SliceState;
-
struct Slice {
Unit meta;
@@ -40,6 +32,3 @@ struct Slice {
};
extern const UnitVTable slice_vtable;
-
-const char* slice_state_to_string(SliceState i) _const_;
-SliceState slice_state_from_string(const char *s) _pure_;
diff --git a/src/core/smack-setup.c b/src/core/smack-setup.c
index cbe7d0b4a9..761582c7a2 100644
--- a/src/core/smack-setup.c
+++ b/src/core/smack-setup.c
@@ -215,16 +215,14 @@ int mac_smack_setup(bool *loaded_policy) {
log_info("Successfully loaded Smack policies.");
break;
default:
- log_warning("Failed to load Smack access rules: %s, ignoring.",
- strerror(abs(r)));
+ log_warning_errno(r, "Failed to load Smack access rules, ignoring: %m");
return 0;
}
#ifdef SMACK_RUN_LABEL
r = write_string_file("/proc/self/attr/current", SMACK_RUN_LABEL, 0);
if (r)
- log_warning("Failed to set SMACK label \"%s\" on self: %s",
- SMACK_RUN_LABEL, strerror(-r));
+ log_warning_errno(r, "Failed to set SMACK label \"%s\" on self: %m", SMACK_RUN_LABEL);
#endif
r = write_cipso2_rules("/etc/smack/cipso.d/");
@@ -239,8 +237,7 @@ int mac_smack_setup(bool *loaded_policy) {
log_info("Successfully loaded Smack/CIPSO policies.");
break;
default:
- log_warning("Failed to load Smack/CIPSO access rules: %s, ignoring.",
- strerror(abs(r)));
+ log_warning_errno(r, "Failed to load Smack/CIPSO access rules, ignoring: %m");
return 0;
}
diff --git a/src/core/snapshot.c b/src/core/snapshot.c
index 336ff20f84..867f3765e7 100644
--- a/src/core/snapshot.c
+++ b/src/core/snapshot.c
@@ -272,13 +272,6 @@ void snapshot_remove(Snapshot *s) {
unit_add_to_cleanup_queue(UNIT(s));
}
-static const char* const snapshot_state_table[_SNAPSHOT_STATE_MAX] = {
- [SNAPSHOT_DEAD] = "dead",
- [SNAPSHOT_ACTIVE] = "active"
-};
-
-DEFINE_STRING_TABLE_LOOKUP(snapshot_state, SnapshotState);
-
const UnitVTable snapshot_vtable = {
.object_size = sizeof(Snapshot),
diff --git a/src/core/snapshot.h b/src/core/snapshot.h
index f2451b1193..97747e18bd 100644
--- a/src/core/snapshot.h
+++ b/src/core/snapshot.h
@@ -23,14 +23,6 @@
typedef struct Snapshot Snapshot;
-
-typedef enum SnapshotState {
- SNAPSHOT_DEAD,
- SNAPSHOT_ACTIVE,
- _SNAPSHOT_STATE_MAX,
- _SNAPSHOT_STATE_INVALID = -1
-} SnapshotState;
-
struct Snapshot {
Unit meta;
@@ -43,6 +35,3 @@ extern const UnitVTable snapshot_vtable;
int snapshot_create(Manager *m, const char *name, bool cleanup, sd_bus_error *e, Snapshot **s);
void snapshot_remove(Snapshot *s);
-
-const char* snapshot_state_to_string(SnapshotState i) _const_;
-SnapshotState snapshot_state_from_string(const char *s) _pure_;
diff --git a/src/core/socket.c b/src/core/socket.c
index 54e94c4f74..e42ed62ef1 100644
--- a/src/core/socket.c
+++ b/src/core/socket.c
@@ -19,38 +19,39 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <sys/stat.h>
-#include <unistd.h>
+#include <arpa/inet.h>
#include <errno.h>
#include <fcntl.h>
-#include <sys/epoll.h>
-#include <signal.h>
-#include <arpa/inet.h>
-#include <netinet/tcp.h>
#include <mqueue.h>
+#include <netinet/tcp.h>
+#include <signal.h>
+#include <sys/epoll.h>
+#include <sys/stat.h>
+#include <unistd.h>
#include "sd-event.h"
+
+#include "bus-error.h"
+#include "bus-util.h"
+#include "copy.h"
+#include "dbus-socket.h"
+#include "def.h"
+#include "exit-status.h"
+#include "formats-util.h"
+#include "label.h"
#include "log.h"
-#include "strv.h"
+#include "missing.h"
#include "mkdir.h"
#include "path-util.h"
-#include "unit-name.h"
-#include "unit-printf.h"
-#include "missing.h"
-#include "special.h"
-#include "label.h"
-#include "exit-status.h"
-#include "def.h"
-#include "smack-util.h"
-#include "bus-util.h"
-#include "bus-error.h"
#include "selinux-util.h"
-#include "dbus-socket.h"
-#include "unit.h"
-#include "formats-util.h"
#include "signal-util.h"
+#include "smack-util.h"
#include "socket.h"
-#include "copy.h"
+#include "special.h"
+#include "strv.h"
+#include "unit-name.h"
+#include "unit-printf.h"
+#include "unit.h"
static const UnitActiveState state_translation_table[_SOCKET_STATE_MAX] = {
[SOCKET_DEAD] = UNIT_INACTIVE,
@@ -506,6 +507,8 @@ static void socket_dump(Unit *u, FILE *f, const char *prefix) {
"%sPassSecurity: %s\n"
"%sTCPCongestion: %s\n"
"%sRemoveOnStop: %s\n"
+ "%sWritable: %s\n"
+ "%sFDName: %s\n"
"%sSELinuxContextFromNet: %s\n",
prefix, socket_state_to_string(s->state),
prefix, socket_result_to_string(s->result),
@@ -522,6 +525,8 @@ static void socket_dump(Unit *u, FILE *f, const char *prefix) {
prefix, yes_no(s->pass_sec),
prefix, strna(s->tcp_congestion),
prefix, yes_no(s->remove_on_stop),
+ prefix, yes_no(s->writable),
+ prefix, socket_fdname(s),
prefix, yes_no(s->selinux_context_from_net));
if (s->control_pid > 0)
@@ -642,7 +647,8 @@ static void socket_dump(Unit *u, FILE *f, const char *prefix) {
int r;
char *k = NULL;
- if ((r = socket_address_print(&p->address, &k)) < 0)
+ r = socket_address_print(&p->address, &k);
+ if (r < 0)
t = strerror(-r);
else
t = k;
@@ -955,50 +961,48 @@ static void socket_apply_fifo_options(Socket *s, int fd) {
if (s->pipe_size > 0)
if (fcntl(fd, F_SETPIPE_SZ, s->pipe_size) < 0)
- log_unit_warning_errno(UNIT(s), errno, "F_SETPIPE_SZ: %m");
+ log_unit_warning_errno(UNIT(s), errno, "Setting pipe size failed, ignoring: %m");
if (s->smack) {
r = mac_smack_apply_fd(fd, SMACK_ATTR_ACCESS, s->smack);
if (r < 0)
- log_unit_error_errno(UNIT(s), r, "mac_smack_apply_fd: %m");
+ log_unit_error_errno(UNIT(s), r, "SMACK relabelling failed, ignoring: %m");
}
}
static int fifo_address_create(
const char *path,
mode_t directory_mode,
- mode_t socket_mode,
- int *_fd) {
+ mode_t socket_mode) {
- int fd = -1, r = 0;
- struct stat st;
+ _cleanup_close_ int fd = -1;
mode_t old_mask;
+ struct stat st;
+ int r;
assert(path);
- assert(_fd);
mkdir_parents_label(path, directory_mode);
r = mac_selinux_create_file_prepare(path, S_IFIFO);
if (r < 0)
- goto fail;
+ return r;
/* Enforce the right access mode for the fifo */
old_mask = umask(~ socket_mode);
/* Include the original umask in our mask */
- umask(~socket_mode | old_mask);
+ (void) umask(~socket_mode | old_mask);
r = mkfifo(path, socket_mode);
- umask(old_mask);
+ (void) umask(old_mask);
if (r < 0 && errno != EEXIST) {
r = -errno;
goto fail;
}
- fd = open(path,
- O_RDWR | O_CLOEXEC | O_NOCTTY | O_NONBLOCK | O_NOFOLLOW);
+ fd = open(path, O_RDWR | O_CLOEXEC | O_NOCTTY | O_NONBLOCK | O_NOFOLLOW);
if (fd < 0) {
r = -errno;
goto fail;
@@ -1015,66 +1019,50 @@ static int fifo_address_create(
(st.st_mode & 0777) != (socket_mode & ~old_mask) ||
st.st_uid != getuid() ||
st.st_gid != getgid()) {
-
r = -EEXIST;
goto fail;
}
- *_fd = fd;
- return 0;
+ r = fd;
+ fd = -1;
+
+ return r;
fail:
mac_selinux_create_file_clear();
- safe_close(fd);
-
return r;
}
-static int special_address_create(
- const char *path,
- int *_fd) {
-
- int fd = -1, r = 0;
+static int special_address_create(const char *path, bool writable) {
+ _cleanup_close_ int fd = -1;
struct stat st;
+ int r;
assert(path);
- assert(_fd);
- fd = open(path, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_NONBLOCK|O_NOFOLLOW);
- if (fd < 0) {
- r = -errno;
- goto fail;
- }
+ fd = open(path, (writable ? O_RDWR : O_RDONLY)|O_CLOEXEC|O_NOCTTY|O_NONBLOCK|O_NOFOLLOW);
+ if (fd < 0)
+ return -errno;
- if (fstat(fd, &st) < 0) {
- r = -errno;
- goto fail;
- }
+ if (fstat(fd, &st) < 0)
+ return -errno;
/* Check whether this is a /proc, /sys or /dev file or char device */
- if (!S_ISREG(st.st_mode) && !S_ISCHR(st.st_mode)) {
- r = -EEXIST;
- goto fail;
- }
-
- *_fd = fd;
- return 0;
+ if (!S_ISREG(st.st_mode) && !S_ISCHR(st.st_mode))
+ return -EEXIST;
-fail:
- safe_close(fd);
+ r = fd;
+ fd = -1;
return r;
}
-static int ffs_address_create(
- const char *path,
- int *_fd) {
-
+static int usbffs_address_create(const char *path) {
_cleanup_close_ int fd = -1;
struct stat st;
+ int r;
assert(path);
- assert(_fd);
fd = open(path, O_RDWR|O_CLOEXEC|O_NOCTTY|O_NONBLOCK|O_NOFOLLOW);
if (fd < 0)
@@ -1087,32 +1075,32 @@ static int ffs_address_create(
if (!S_ISREG(st.st_mode))
return -EEXIST;
- *_fd = fd;
+ r = fd;
fd = -1;
- return 0;
+ return r;
}
static int mq_address_create(
const char *path,
mode_t mq_mode,
long maxmsg,
- long msgsize,
- int *_fd) {
+ long msgsize) {
- int fd = -1, r = 0;
+ _cleanup_close_ int fd = -1;
struct stat st;
mode_t old_mask;
struct mq_attr _attr, *attr = NULL;
+ int r;
assert(path);
- assert(_fd);
if (maxmsg > 0 && msgsize > 0) {
- zero(_attr);
- _attr.mq_flags = O_NONBLOCK;
- _attr.mq_maxmsg = maxmsg;
- _attr.mq_msgsize = msgsize;
+ _attr = (struct mq_attr) {
+ .mq_flags = O_NONBLOCK,
+ .mq_maxmsg = maxmsg,
+ .mq_msgsize = msgsize,
+ };
attr = &_attr;
}
@@ -1120,33 +1108,24 @@ static int mq_address_create(
old_mask = umask(~ mq_mode);
/* Include the original umask in our mask */
- umask(~mq_mode | old_mask);
+ (void) umask(~mq_mode | old_mask);
fd = mq_open(path, O_RDONLY|O_CLOEXEC|O_NONBLOCK|O_CREAT, mq_mode, attr);
- umask(old_mask);
+ (void) umask(old_mask);
- if (fd < 0) {
- r = -errno;
- goto fail;
- }
+ if (fd < 0)
+ return -errno;
- if (fstat(fd, &st) < 0) {
- r = -errno;
- goto fail;
- }
+ if (fstat(fd, &st) < 0)
+ return -errno;
if ((st.st_mode & 0777) != (mq_mode & ~old_mask) ||
st.st_uid != getuid() ||
- st.st_gid != getgid()) {
-
- r = -EEXIST;
- goto fail;
- }
+ st.st_gid != getgid())
+ return -EEXIST;
- *_fd = fd;
- return 0;
+ r = fd;
+ fd = -1;
-fail:
- safe_close(fd);
return r;
}
@@ -1166,8 +1145,7 @@ static int socket_symlink(Socket *s) {
return 0;
}
-static int ffs_write_descs(int fd, Unit *u) {
- Service *s = SERVICE(u);
+static int usbffs_write_descs(int fd, Service *s) {
int r;
if (!s->usb_function_descriptors || !s->usb_function_strings)
@@ -1175,27 +1153,25 @@ static int ffs_write_descs(int fd, Unit *u) {
r = copy_file_fd(s->usb_function_descriptors, fd, false);
if (r < 0)
- return 0;
-
- r = copy_file_fd(s->usb_function_strings, fd, false);
+ return r;
- return r;
+ return copy_file_fd(s->usb_function_strings, fd, false);
}
-static int select_ep(const struct dirent *d) {
+static int usbffs_select_ep(const struct dirent *d) {
return d->d_name[0] != '.' && !streq(d->d_name, "ep0");
}
-static int ffs_dispatch_eps(SocketPort *p) {
+static int usbffs_dispatch_eps(SocketPort *p) {
_cleanup_free_ struct dirent **ent = NULL;
- int r, i, n, k;
_cleanup_free_ char *path = NULL;
+ int r, i, n, k;
r = path_get_parent(p->path, &path);
if (r < 0)
return r;
- r = scandir(path, &ent, select_ep, alphasort);
+ r = scandir(path, &ent, usbffs_select_ep, alphasort);
if (r < 0)
return -errno;
@@ -1216,10 +1192,12 @@ static int ffs_dispatch_eps(SocketPort *p) {
path_kill_slashes(ep);
- r = ffs_address_create(ep, &p->auxiliary_fds[k]);
+ r = usbffs_address_create(ep);
if (r < 0)
goto fail;
+ p->auxiliary_fds[k] = r;
+
++k;
free(ent[i]);
}
@@ -1227,9 +1205,7 @@ static int ffs_dispatch_eps(SocketPort *p) {
return r;
fail:
- while (k)
- safe_close(p->auxiliary_fds[--k]);
-
+ close_many(p->auxiliary_fds, k);
p->auxiliary_fds = mfree(p->auxiliary_fds);
p->n_auxiliary_fds = 0;
@@ -1237,10 +1213,10 @@ fail:
}
static int socket_open_fds(Socket *s) {
+ _cleanup_(mac_selinux_freep) char *label = NULL;
+ bool know_label = false;
SocketPort *p;
int r;
- char *label = NULL;
- bool know_label = false;
assert(s);
@@ -1249,7 +1225,9 @@ static int socket_open_fds(Socket *s) {
if (p->fd >= 0)
continue;
- if (p->type == SOCKET_SOCKET) {
+ switch (p->type) {
+
+ case SOCKET_SOCKET:
if (!know_label) {
/* Figure out label, if we don't it know
@@ -1300,64 +1278,72 @@ static int socket_open_fds(Socket *s) {
p->fd = r;
socket_apply_socket_options(s, p->fd);
socket_symlink(s);
+ break;
- } else if (p->type == SOCKET_SPECIAL) {
+ case SOCKET_SPECIAL:
- r = special_address_create(
- p->path,
- &p->fd);
- if (r < 0)
+ p->fd = special_address_create(p->path, s->writable);
+ if (p->fd < 0) {
+ r = p->fd;
goto rollback;
+ }
+ break;
- } else if (p->type == SOCKET_FIFO) {
+ case SOCKET_FIFO:
- r = fifo_address_create(
+ p->fd = fifo_address_create(
p->path,
s->directory_mode,
- s->socket_mode,
- &p->fd);
- if (r < 0)
+ s->socket_mode);
+ if (p->fd < 0) {
+ r = p->fd;
goto rollback;
+ }
socket_apply_fifo_options(s, p->fd);
socket_symlink(s);
+ break;
- } else if (p->type == SOCKET_MQUEUE) {
+ case SOCKET_MQUEUE:
- r = mq_address_create(
+ p->fd = mq_address_create(
p->path,
s->socket_mode,
s->mq_maxmsg,
- s->mq_msgsize,
- &p->fd);
- if (r < 0)
+ s->mq_msgsize);
+ if (p->fd < 0) {
+ r = p->fd;
goto rollback;
- } else if (p->type == SOCKET_USB_FUNCTION) {
+ }
+ break;
- r = ffs_address_create(
- p->path,
- &p->fd);
- if (r < 0)
+ case SOCKET_USB_FUNCTION:
+
+ p->fd = usbffs_address_create(p->path);
+ if (p->fd < 0) {
+ r = p->fd;
goto rollback;
+ }
- r = ffs_write_descs(p->fd, s->service.unit);
+ r = usbffs_write_descs(p->fd, SERVICE(UNIT_DEREF(s->service)));
if (r < 0)
goto rollback;
- r = ffs_dispatch_eps(p);
+ r = usbffs_dispatch_eps(p);
if (r < 0)
goto rollback;
- } else
+
+ break;
+
+ default:
assert_not_reached("Unknown port type");
+ }
}
- mac_selinux_free(label);
return 0;
rollback:
socket_close_fds(s);
- mac_selinux_free(label);
-
return r;
}
@@ -1519,6 +1505,9 @@ static int socket_spawn(Socket *s, ExecCommand *c, pid_t *_pid) {
.apply_chroot = true,
.apply_tty_stdin = true,
.bus_endpoint_fd = -1,
+ .stdin_fd = -1,
+ .stdout_fd = -1,
+ .stderr_fd = -1,
};
assert(s);
@@ -2644,49 +2633,43 @@ static int socket_dispatch_timer(sd_event_source *source, usec_t usec, void *use
return 0;
}
-int socket_collect_fds(Socket *s, int **fds, unsigned *n_fds) {
- int *rfds;
- unsigned rn_fds, k;
- int i;
+int socket_collect_fds(Socket *s, int **fds) {
+ int *rfds, k = 0, n = 0;
SocketPort *p;
assert(s);
assert(fds);
- assert(n_fds);
/* Called from the service code for requesting our fds */
- rn_fds = 0;
LIST_FOREACH(port, p, s->ports) {
if (p->fd >= 0)
- rn_fds++;
- rn_fds += p->n_auxiliary_fds;
+ n++;
+ n += p->n_auxiliary_fds;
}
- if (rn_fds <= 0) {
+ if (n <= 0) {
*fds = NULL;
- *n_fds = 0;
return 0;
}
- rfds = new(int, rn_fds);
+ rfds = new(int, n);
if (!rfds)
return -ENOMEM;
- k = 0;
LIST_FOREACH(port, p, s->ports) {
+ int i;
+
if (p->fd >= 0)
rfds[k++] = p->fd;
for (i = 0; i < p->n_auxiliary_fds; ++i)
rfds[k++] = p->auxiliary_fds[i];
}
- assert(k == rn_fds);
+ assert(k == n);
*fds = rfds;
- *n_fds = rn_fds;
-
- return 0;
+ return n;
}
static void socket_reset_failed(Unit *u) {
@@ -2782,23 +2765,18 @@ static int socket_get_timeout(Unit *u, uint64_t *timeout) {
return 1;
}
-static const char* const socket_state_table[_SOCKET_STATE_MAX] = {
- [SOCKET_DEAD] = "dead",
- [SOCKET_START_PRE] = "start-pre",
- [SOCKET_START_CHOWN] = "start-chown",
- [SOCKET_START_POST] = "start-post",
- [SOCKET_LISTENING] = "listening",
- [SOCKET_RUNNING] = "running",
- [SOCKET_STOP_PRE] = "stop-pre",
- [SOCKET_STOP_PRE_SIGTERM] = "stop-pre-sigterm",
- [SOCKET_STOP_PRE_SIGKILL] = "stop-pre-sigkill",
- [SOCKET_STOP_POST] = "stop-post",
- [SOCKET_FINAL_SIGTERM] = "final-sigterm",
- [SOCKET_FINAL_SIGKILL] = "final-sigkill",
- [SOCKET_FAILED] = "failed"
-};
+char *socket_fdname(Socket *s) {
+ assert(s);
+
+ /* Returns the name to use for $LISTEN_NAMES. If the user
+ * didn't specify anything specifically, use the socket unit's
+ * name as fallback. */
-DEFINE_STRING_TABLE_LOOKUP(socket_state, SocketState);
+ if (s->fdname)
+ return s->fdname;
+
+ return UNIT(s)->id;
+}
static const char* const socket_exec_command_table[_SOCKET_EXEC_COMMAND_MAX] = {
[SOCKET_EXEC_START_PRE] = "StartPre",
diff --git a/src/core/socket.h b/src/core/socket.h
index 286397b41c..94cda8a90d 100644
--- a/src/core/socket.h
+++ b/src/core/socket.h
@@ -27,24 +27,6 @@ typedef struct Socket Socket;
#include "mount.h"
#include "service.h"
-typedef enum SocketState {
- SOCKET_DEAD,
- SOCKET_START_PRE,
- SOCKET_START_CHOWN,
- SOCKET_START_POST,
- SOCKET_LISTENING,
- SOCKET_RUNNING,
- SOCKET_STOP_PRE,
- SOCKET_STOP_PRE_SIGTERM,
- SOCKET_STOP_PRE_SIGKILL,
- SOCKET_STOP_POST,
- SOCKET_FINAL_SIGTERM,
- SOCKET_FINAL_SIGKILL,
- SOCKET_FAILED,
- _SOCKET_STATE_MAX,
- _SOCKET_STATE_INVALID = -1
-} SocketState;
-
typedef enum SocketExecCommand {
SOCKET_EXEC_START_PRE,
SOCKET_EXEC_START_CHOWN,
@@ -136,6 +118,7 @@ struct Socket {
bool accept;
bool remove_on_stop;
+ bool writable;
/* Socket options */
bool keep_alive;
@@ -171,20 +154,23 @@ struct Socket {
char *user, *group;
bool reset_cpu_usage:1;
+
+ char *fdname;
};
/* Called from the service code when collecting fds */
-int socket_collect_fds(Socket *s, int **fds, unsigned *n_fds);
+int socket_collect_fds(Socket *s, int **fds);
/* Called from the service code when a per-connection service ended */
void socket_connection_unref(Socket *s);
void socket_free_ports(Socket *s);
-extern const UnitVTable socket_vtable;
+int socket_instantiate_service(Socket *s);
-const char* socket_state_to_string(SocketState i) _const_;
-SocketState socket_state_from_string(const char *s) _pure_;
+char *socket_fdname(Socket *s);
+
+extern const UnitVTable socket_vtable;
const char* socket_exec_command_to_string(SocketExecCommand i) _const_;
SocketExecCommand socket_exec_command_from_string(const char *s) _pure_;
@@ -193,5 +179,3 @@ const char* socket_result_to_string(SocketResult i) _const_;
SocketResult socket_result_from_string(const char *s) _pure_;
const char* socket_port_type_to_string(SocketPort *p) _pure_;
-
-int socket_instantiate_service(Socket *s);
diff --git a/src/core/swap.c b/src/core/swap.c
index bef457069f..f42d151075 100644
--- a/src/core/swap.c
+++ b/src/core/swap.c
@@ -597,6 +597,9 @@ static int swap_spawn(Swap *s, ExecCommand *c, pid_t *_pid) {
.apply_chroot = true,
.apply_tty_stdin = true,
.bus_endpoint_fd = -1,
+ .stdin_fd = -1,
+ .stdout_fd = -1,
+ .stderr_fd = -1,
};
assert(s);
@@ -1398,21 +1401,6 @@ static bool swap_supported(void) {
return supported;
}
-static const char* const swap_state_table[_SWAP_STATE_MAX] = {
- [SWAP_DEAD] = "dead",
- [SWAP_ACTIVATING] = "activating",
- [SWAP_ACTIVATING_DONE] = "activating-done",
- [SWAP_ACTIVE] = "active",
- [SWAP_DEACTIVATING] = "deactivating",
- [SWAP_ACTIVATING_SIGTERM] = "activating-sigterm",
- [SWAP_ACTIVATING_SIGKILL] = "activating-sigkill",
- [SWAP_DEACTIVATING_SIGTERM] = "deactivating-sigterm",
- [SWAP_DEACTIVATING_SIGKILL] = "deactivating-sigkill",
- [SWAP_FAILED] = "failed"
-};
-
-DEFINE_STRING_TABLE_LOOKUP(swap_state, SwapState);
-
static const char* const swap_exec_command_table[_SWAP_EXEC_COMMAND_MAX] = {
[SWAP_EXEC_ACTIVATE] = "ExecActivate",
[SWAP_EXEC_DEACTIVATE] = "ExecDeactivate",
diff --git a/src/core/swap.h b/src/core/swap.h
index 9136b9abab..7f29603c32 100644
--- a/src/core/swap.h
+++ b/src/core/swap.h
@@ -26,22 +26,6 @@
typedef struct Swap Swap;
-
-typedef enum SwapState {
- SWAP_DEAD,
- SWAP_ACTIVATING, /* /sbin/swapon is running, but the swap not yet enabled. */
- SWAP_ACTIVATING_DONE, /* /sbin/swapon is running, and the swap is done. */
- SWAP_ACTIVE,
- SWAP_DEACTIVATING,
- SWAP_ACTIVATING_SIGTERM,
- SWAP_ACTIVATING_SIGKILL,
- SWAP_DEACTIVATING_SIGTERM,
- SWAP_DEACTIVATING_SIGKILL,
- SWAP_FAILED,
- _SWAP_STATE_MAX,
- _SWAP_STATE_INVALID = -1
-} SwapState;
-
typedef enum SwapExecCommand {
SWAP_EXEC_ACTIVATE,
SWAP_EXEC_DEACTIVATE,
@@ -120,9 +104,6 @@ extern const UnitVTable swap_vtable;
int swap_process_device_new(Manager *m, struct udev_device *dev);
int swap_process_device_remove(Manager *m, struct udev_device *dev);
-const char* swap_state_to_string(SwapState i) _const_;
-SwapState swap_state_from_string(const char *s) _pure_;
-
const char* swap_exec_command_to_string(SwapExecCommand i) _const_;
SwapExecCommand swap_exec_command_from_string(const char *s) _pure_;
diff --git a/src/core/system.conf b/src/core/system.conf
index 231609033b..50668e12c4 100644
--- a/src/core/system.conf
+++ b/src/core/system.conf
@@ -17,9 +17,10 @@
#LogColor=yes
#LogLocation=no
#DumpCore=yes
-#CrashShell=no
#ShowStatus=yes
-#CrashChVT=1
+#CrashChangeVT=no
+#CrashShell=no
+#CrashReboot=no
#CPUAffinity=1 2
#JoinControllers=cpu,cpuacct net_cls,net_prio
#RuntimeWatchdogSec=0
@@ -39,6 +40,7 @@
#DefaultCPUAccounting=no
#DefaultBlockIOAccounting=no
#DefaultMemoryAccounting=no
+#DefaultTasksAccounting=no
#DefaultLimitCPU=
#DefaultLimitFSIZE=
#DefaultLimitDATA=
diff --git a/src/core/target.c b/src/core/target.c
index f714cb31c2..a905a1adf6 100644
--- a/src/core/target.c
+++ b/src/core/target.c
@@ -192,13 +192,6 @@ _pure_ static const char *target_sub_state_to_string(Unit *u) {
return target_state_to_string(TARGET(u)->state);
}
-static const char* const target_state_table[_TARGET_STATE_MAX] = {
- [TARGET_DEAD] = "dead",
- [TARGET_ACTIVE] = "active"
-};
-
-DEFINE_STRING_TABLE_LOOKUP(target_state, TargetState);
-
const UnitVTable target_vtable = {
.object_size = sizeof(Target),
diff --git a/src/core/target.h b/src/core/target.h
index 0a25ef469a..3cc6c07bfa 100644
--- a/src/core/target.h
+++ b/src/core/target.h
@@ -23,14 +23,6 @@
typedef struct Target Target;
-
-typedef enum TargetState {
- TARGET_DEAD,
- TARGET_ACTIVE,
- _TARGET_STATE_MAX,
- _TARGET_STATE_INVALID = -1
-} TargetState;
-
struct Target {
Unit meta;
@@ -38,6 +30,3 @@ struct Target {
};
extern const UnitVTable target_vtable;
-
-const char* target_state_to_string(TargetState i) _const_;
-TargetState target_state_from_string(const char *s) _pure_;
diff --git a/src/core/timer.c b/src/core/timer.c
index eb6567bbfa..800e58261c 100644
--- a/src/core/timer.c
+++ b/src/core/timer.c
@@ -713,16 +713,6 @@ static void timer_time_change(Unit *u) {
timer_enter_waiting(t, false);
}
-static const char* const timer_state_table[_TIMER_STATE_MAX] = {
- [TIMER_DEAD] = "dead",
- [TIMER_WAITING] = "waiting",
- [TIMER_RUNNING] = "running",
- [TIMER_ELAPSED] = "elapsed",
- [TIMER_FAILED] = "failed"
-};
-
-DEFINE_STRING_TABLE_LOOKUP(timer_state, TimerState);
-
static const char* const timer_base_table[_TIMER_BASE_MAX] = {
[TIMER_ACTIVE] = "OnActiveSec",
[TIMER_BOOT] = "OnBootSec",
diff --git a/src/core/timer.h b/src/core/timer.h
index 9d919e4d3e..ac5af6a93c 100644
--- a/src/core/timer.h
+++ b/src/core/timer.h
@@ -25,16 +25,6 @@ typedef struct Timer Timer;
#include "calendarspec.h"
-typedef enum TimerState {
- TIMER_DEAD,
- TIMER_WAITING,
- TIMER_RUNNING,
- TIMER_ELAPSED,
- TIMER_FAILED,
- _TIMER_STATE_MAX,
- _TIMER_STATE_INVALID = -1
-} TimerState;
-
typedef enum TimerBase {
TIMER_ACTIVE,
TIMER_BOOT,
@@ -91,9 +81,6 @@ void timer_free_values(Timer *t);
extern const UnitVTable timer_vtable;
-const char *timer_state_to_string(TimerState i) _const_;
-TimerState timer_state_from_string(const char *s) _pure_;
-
const char *timer_base_to_string(TimerBase i) _const_;
TimerBase timer_base_from_string(const char *s) _pure_;
diff --git a/src/core/unit.c b/src/core/unit.c
index 1227399e16..39cd89f1e3 100644
--- a/src/core/unit.c
+++ b/src/core/unit.c
@@ -1129,12 +1129,12 @@ static int unit_add_slice_dependencies(Unit *u) {
return 0;
if (UNIT_ISSET(u->slice))
- return unit_add_two_dependencies(u, UNIT_AFTER, UNIT_WANTS, UNIT_DEREF(u->slice), true);
+ return unit_add_two_dependencies(u, UNIT_AFTER, UNIT_REQUIRES, UNIT_DEREF(u->slice), true);
- if (streq(u->id, SPECIAL_ROOT_SLICE))
+ if (unit_has_name(u, SPECIAL_ROOT_SLICE))
return 0;
- return unit_add_two_dependencies_by_name(u, UNIT_AFTER, UNIT_WANTS, SPECIAL_ROOT_SLICE, NULL, true);
+ return unit_add_two_dependencies_by_name(u, UNIT_AFTER, UNIT_REQUIRES, SPECIAL_ROOT_SLICE, NULL, true);
}
static int unit_add_mount_dependencies(Unit *u) {
@@ -2634,6 +2634,62 @@ int unit_serialize(Unit *u, FILE *f, FDSet *fds, bool serialize_jobs) {
return 0;
}
+int unit_serialize_item(Unit *u, FILE *f, const char *key, const char *value) {
+ assert(u);
+ assert(f);
+ assert(key);
+
+ if (!value)
+ return 0;
+
+ fputs(key, f);
+ fputc('=', f);
+ fputs(value, f);
+ fputc('\n', f);
+
+ return 1;
+}
+
+int unit_serialize_item_escaped(Unit *u, FILE *f, const char *key, const char *value) {
+ _cleanup_free_ char *c = NULL;
+
+ assert(u);
+ assert(f);
+ assert(key);
+
+ if (!value)
+ return 0;
+
+ c = cescape(value);
+ if (!c)
+ return -ENOMEM;
+
+ fputs(key, f);
+ fputc('=', f);
+ fputs(c, f);
+ fputc('\n', f);
+
+ return 1;
+}
+
+int unit_serialize_item_fd(Unit *u, FILE *f, FDSet *fds, const char *key, int fd) {
+ int copy;
+
+ assert(u);
+ assert(f);
+ assert(key);
+
+ if (fd < 0)
+ return 0;
+
+ copy = fdset_put_dup(fds, fd);
+ if (copy < 0)
+ return copy;
+
+ fprintf(f, "%s=%i\n", key, copy);
+ return 1;
+}
+
void unit_serialize_item_format(Unit *u, FILE *f, const char *key, const char *format, ...) {
va_list ap;
@@ -2652,15 +2708,6 @@ void unit_serialize_item_format(Unit *u, FILE *f, const char *key, const char *f
fputc('\n', f);
}
-void unit_serialize_item(Unit *u, FILE *f, const char *key, const char *value) {
- assert(u);
- assert(f);
- assert(key);
- assert(value);
-
- fprintf(f, "%s=%s\n", key, value);
-}
-
int unit_deserialize(Unit *u, FILE *f, FDSet *fds) {
ExecRuntime **rt = NULL;
size_t offset;
@@ -3739,14 +3786,3 @@ int unit_fail_if_symlink(Unit *u, const char* where) {
return -ELOOP;
}
-
-static const char* const unit_active_state_table[_UNIT_ACTIVE_STATE_MAX] = {
- [UNIT_ACTIVE] = "active",
- [UNIT_RELOADING] = "reloading",
- [UNIT_INACTIVE] = "inactive",
- [UNIT_FAILED] = "failed",
- [UNIT_ACTIVATING] = "activating",
- [UNIT_DEACTIVATING] = "deactivating"
-};
-
-DEFINE_STRING_TABLE_LOOKUP(unit_active_state, UnitActiveState);
diff --git a/src/core/unit.h b/src/core/unit.h
index c868d75c79..a4a1b011fc 100644
--- a/src/core/unit.h
+++ b/src/core/unit.h
@@ -27,7 +27,6 @@
typedef struct Unit Unit;
typedef struct UnitVTable UnitVTable;
-typedef enum UnitActiveState UnitActiveState;
typedef struct UnitRef UnitRef;
typedef struct UnitStatusMessageFormats UnitStatusMessageFormats;
@@ -37,17 +36,6 @@ typedef struct UnitStatusMessageFormats UnitStatusMessageFormats;
#include "unit-name.h"
#include "failure-action.h"
-enum UnitActiveState {
- UNIT_ACTIVE,
- UNIT_RELOADING,
- UNIT_INACTIVE,
- UNIT_FAILED,
- UNIT_ACTIVATING,
- UNIT_DEACTIVATING,
- _UNIT_ACTIVE_STATE_MAX,
- _UNIT_ACTIVE_STATE_INVALID = -1
-};
-
typedef enum KillOperation {
KILL_TERMINATE,
KILL_KILL,
@@ -545,11 +533,15 @@ char *unit_dbus_path(Unit *u);
int unit_load_related_unit(Unit *u, const char *type, Unit **_found);
bool unit_can_serialize(Unit *u) _pure_;
+
int unit_serialize(Unit *u, FILE *f, FDSet *fds, bool serialize_jobs);
-void unit_serialize_item_format(Unit *u, FILE *f, const char *key, const char *value, ...) _printf_(4,5);
-void unit_serialize_item(Unit *u, FILE *f, const char *key, const char *value);
int unit_deserialize(Unit *u, FILE *f, FDSet *fds);
+int unit_serialize_item(Unit *u, FILE *f, const char *key, const char *value);
+int unit_serialize_item_escaped(Unit *u, FILE *f, const char *key, const char *value);
+int unit_serialize_item_fd(Unit *u, FILE *f, FDSet *fds, const char *key, int fd);
+void unit_serialize_item_format(Unit *u, FILE *f, const char *key, const char *value, ...) _printf_(4,5);
+
int unit_add_node_link(Unit *u, const char *what, bool wants);
int unit_coldplug(Unit *u);
@@ -617,9 +609,6 @@ static inline bool unit_supported(Unit *u) {
void unit_warn_if_dir_nonempty(Unit *u, const char* where);
int unit_fail_if_symlink(Unit *u, const char* where);
-const char *unit_active_state_to_string(UnitActiveState i) _const_;
-UnitActiveState unit_active_state_from_string(const char *s) _pure_;
-
/* Macros which append UNIT= or USER_UNIT= to the message */
#define log_unit_full(unit, level, error, ...) \