#include "dbus-execute.h"
#include "missing.h"
#include "ioprio.h"
+#include "strv.h"
DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_execute_append_input, exec_input, ExecInput);
DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_execute_append_output, exec_output, ExecOutput);
assert(property);
assert(c);
- if (!(dbus_message_iter_open_container(i, DBUS_TYPE_ARRAY, "y", &sub)))
+ if (!dbus_message_iter_open_container(i, DBUS_TYPE_ARRAY, "y", &sub))
return -ENOMEM;
if (c->cpuset)
return 0;
}
+
+int bus_execute_append_command(Manager *m, DBusMessageIter *i, const char *property, void *data) {
+ ExecCommand *c = data;
+ DBusMessageIter sub, sub2, sub3;
+
+ assert(m);
+ assert(i);
+ assert(property);
+
+ if (!dbus_message_iter_open_container(i, DBUS_TYPE_ARRAY, "(sasttuii)", &sub))
+ return -ENOMEM;
+
+ LIST_FOREACH(command, c, c) {
+ char **l;
+ uint32_t pid;
+ int32_t code, status;
+
+ if (!c->path)
+ continue;
+
+ if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2) ||
+ !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &c->path) ||
+ !dbus_message_iter_open_container(&sub2, DBUS_TYPE_ARRAY, "s", &sub3))
+ return -ENOMEM;
+
+ STRV_FOREACH(l, c->argv)
+ if (!dbus_message_iter_append_basic(&sub3, DBUS_TYPE_STRING, l))
+ return -ENOMEM;
+
+ pid = (uint32_t) c->exec_status.pid;
+ code = (int32_t) c->exec_status.code;
+ status = (int32_t) c->exec_status.status;
+
+ if (!dbus_message_iter_close_container(&sub2, &sub3) ||
+ !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT64, &c->exec_status.start_timestamp.realtime) ||
+ !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT64, &c->exec_status.exit_timestamp.realtime) ||
+ !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT32, &c->exec_status.pid) ||
+ !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_INT32, &c->exec_status.code) ||
+ !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_INT32, &c->exec_status.status))
+ return -ENOMEM;
+
+ if (!dbus_message_iter_close_container(&sub, &sub2))
+ return -ENOMEM;
+ }
+
+ if (!dbus_message_iter_close_container(i, &sub))
+ return -ENOMEM;
+
+ return 0;
+}
" <property name=\"InaccessibleDirectories\" type=\"as\" access=\"read\"/>\n" \
" <property name=\"MountFlags\" type=\"t\" access=\"read\"/>\n" \
" <property name=\"PrivateTmp\" type=\"b\" access=\"read\"/>\n" \
- " <property name=\"NoSetSID\" type=\"b\" access=\"read\"/>\n" \
+ " <property name=\"NoSetSID\" type=\"b\" access=\"read\"/>\n"
+
+#define BUS_EXEC_COMMAND_INTERFACE(name) \
+ " <property name=\"" name "\" type=\"a(sasttuii)\" access=\"read\"/>\n"
#define BUS_EXEC_CONTEXT_PROPERTIES(interface, context) \
{ interface, "Environment", bus_property_append_strv, "as", (context).environment }, \
{ interface, prefix "Code", bus_property_append_int, "i", &(estatus).code }, \
{ interface, prefix "Status", bus_property_append_int, "i", &(estatus).status }
+#define BUS_EXEC_COMMAND_PROPERTY(interface, command, name) \
+ { interface, name, bus_execute_append_command, "a(sasttuii)", (command) }
+
int bus_execute_append_output(Manager *m, DBusMessageIter *i, const char *property, void *data);
int bus_execute_append_input(Manager *m, DBusMessageIter *i, const char *property, void *data);
int bus_execute_append_oom_adjust(Manager *m, DBusMessageIter *i, const char *property, void *data);
int bus_execute_append_timer_slack_ns(Manager *m, DBusMessageIter *i, const char *property, void *data);
int bus_execute_append_capabilities(Manager *m, DBusMessageIter *i, const char *property, void *data);
int bus_execute_append_rlimits(Manager *m, DBusMessageIter *i, const char *property, void *data);
+int bus_execute_append_command(Manager *m, DBusMessageIter *u, const char *property, void *data);
#endif
" <property name=\"Options\" type=\"s\" access=\"read\"/>\n" \
" <property name=\"Type\" type=\"s\" access=\"read\"/>\n" \
" <property name=\"TimeoutUSec\" type=\"t\" access=\"read\"/>\n" \
+ BUS_EXEC_COMMAND_INTERFACE("ExecMount") \
+ BUS_EXEC_COMMAND_INTERFACE("ExecUnmount") \
+ BUS_EXEC_COMMAND_INTERFACE("ExecRemount") \
BUS_EXEC_CONTEXT_INTERFACE \
" <property name=\"KillMode\" type=\"s\" access=\"read\"/>\n" \
" <property name=\"ControlPID\" type=\"u\" access=\"read\"/>\n" \
{ "org.freedesktop.systemd1.Mount", "Options", bus_mount_append_options, "s", u },
{ "org.freedesktop.systemd1.Mount", "Type", bus_mount_append_type, "s", u },
{ "org.freedesktop.systemd1.Mount", "TimeoutUSec", bus_property_append_usec, "t", &u->mount.timeout_usec },
- /* ExecCommand */
+ BUS_EXEC_COMMAND_PROPERTY("org.freedesktop.systemd1.Mount", u->mount.exec_command+MOUNT_EXEC_MOUNT, "ExecMount"),
+ BUS_EXEC_COMMAND_PROPERTY("org.freedesktop.systemd1.Mount", u->mount.exec_command+MOUNT_EXEC_UNMOUNT, "ExecUnmount"),
+ BUS_EXEC_COMMAND_PROPERTY("org.freedesktop.systemd1.Mount", u->mount.exec_command+MOUNT_EXEC_REMOUNT, "ExecRemount"),
BUS_EXEC_CONTEXT_PROPERTIES("org.freedesktop.systemd1.Mount", u->mount.exec_context),
{ "org.freedesktop.systemd1.Mount", "KillMode", bus_unit_append_kill_mode, "s", &u->mount.kill_mode },
{ "org.freedesktop.systemd1.Mount", "ControlPID", bus_property_append_pid, "u", &u->mount.control_pid },
" <property name=\"NotifyAccess\" type=\"s\" access=\"read\"/>\n" \
" <property name=\"RestartUSec\" type=\"t\" access=\"read\"/>\n" \
" <property name=\"TimeoutUSec\" type=\"t\" access=\"read\"/>\n" \
+ BUS_EXEC_COMMAND_INTERFACE("ExecStartPre") \
+ BUS_EXEC_COMMAND_INTERFACE("ExecStart") \
+ BUS_EXEC_COMMAND_INTERFACE("ExecStartPost") \
+ BUS_EXEC_COMMAND_INTERFACE("ExecReload") \
+ BUS_EXEC_COMMAND_INTERFACE("ExecStop") \
+ BUS_EXEC_COMMAND_INTERFACE("ExecStopPost") \
BUS_EXEC_CONTEXT_INTERFACE \
" <property name=\"PermissionsStartOnly\" type=\"b\" access=\"read\"/>\n" \
" <property name=\"RootDirectoryStartOnly\" type=\"b\" access=\"read\"/>\n" \
{ "org.freedesktop.systemd1.Service", "NotifyAccess", bus_service_append_notify_access, "s", &u->service.notify_access },
{ "org.freedesktop.systemd1.Service", "RestartUSec", bus_property_append_usec, "t", &u->service.restart_usec },
{ "org.freedesktop.systemd1.Service", "TimeoutUSec", bus_property_append_usec, "t", &u->service.timeout_usec },
- /* ExecCommand */
+ BUS_EXEC_COMMAND_PROPERTY("org.freedesktop.systemd1.Service", u->service.exec_command[SERVICE_EXEC_START_PRE], "ExecStartPre"),
+ BUS_EXEC_COMMAND_PROPERTY("org.freedesktop.systemd1.Service", u->service.exec_command[SERVICE_EXEC_START], "ExecStart"),
+ BUS_EXEC_COMMAND_PROPERTY("org.freedesktop.systemd1.Service", u->service.exec_command[SERVICE_EXEC_START_POST], "ExecStartPost"),
+ BUS_EXEC_COMMAND_PROPERTY("org.freedesktop.systemd1.Service", u->service.exec_command[SERVICE_EXEC_RELOAD], "ExecReload"),
+ BUS_EXEC_COMMAND_PROPERTY("org.freedesktop.systemd1.Service", u->service.exec_command[SERVICE_EXEC_STOP], "ExecStop"),
+ BUS_EXEC_COMMAND_PROPERTY("org.freedesktop.systemd1.Service", u->service.exec_command[SERVICE_EXEC_STOP_POST], "ExecStopPost"),
BUS_EXEC_CONTEXT_PROPERTIES("org.freedesktop.systemd1.Service", u->service.exec_context),
{ "org.freedesktop.systemd1.Service", "PermissionsStartOnly", bus_property_append_bool, "b", &u->service.permissions_start_only },
{ "org.freedesktop.systemd1.Service", "RootDirectoryStartOnly", bus_property_append_bool, "b", &u->service.root_directory_start_only },
" <property name=\"BindIPv6Only\" type=\"b\" access=\"read\"/>\n" \
" <property name=\"Backlog\" type=\"u\" access=\"read\"/>\n" \
" <property name=\"TimeoutUSec\" type=\"t\" access=\"read\"/>\n" \
+ BUS_EXEC_COMMAND_INTERFACE("ExecStartPre") \
+ BUS_EXEC_COMMAND_INTERFACE("ExecStartPost") \
+ BUS_EXEC_COMMAND_INTERFACE("ExecStopPre") \
+ BUS_EXEC_COMMAND_INTERFACE("ExecStopPost") \
BUS_EXEC_CONTEXT_INTERFACE \
" <property name=\"KillMode\" type=\"s\" access=\"read\"/>\n" \
" <property name=\"ControlPID\" type=\"u\" access=\"read\"/>\n" \
{ "org.freedesktop.systemd1.Socket", "BindIPv6Only", bus_socket_append_bind_ipv6_only, "s", &u->socket.bind_ipv6_only },
{ "org.freedesktop.systemd1.Socket", "Backlog", bus_property_append_unsigned, "u", &u->socket.backlog },
{ "org.freedesktop.systemd1.Socket", "TimeoutUSec", bus_property_append_usec, "t", &u->socket.timeout_usec },
- /* ExecCommand */
+ BUS_EXEC_COMMAND_PROPERTY("org.freedesktop.systemd1.Socket", u->service.exec_command[SOCKET_EXEC_START_PRE], "ExecStartPre"),
+ BUS_EXEC_COMMAND_PROPERTY("org.freedesktop.systemd1.Socket", u->service.exec_command[SOCKET_EXEC_START_POST], "ExecStartPost"),
+ BUS_EXEC_COMMAND_PROPERTY("org.freedesktop.systemd1.Socket", u->service.exec_command[SOCKET_EXEC_STOP_PRE], "ExecStopPre"),
+ BUS_EXEC_COMMAND_PROPERTY("org.freedesktop.systemd1.Socket", u->service.exec_command[SOCKET_EXEC_STOP_POST], "ExecStopPost"),
BUS_EXEC_CONTEXT_PROPERTIES("org.freedesktop.systemd1.Socket", u->socket.exec_context),
{ "org.freedesktop.systemd1.Socket", "KillMode", bus_unit_append_kill_mode, "s", &u->socket.kill_mode },
{ "org.freedesktop.systemd1.Socket", "ControlPID", bus_property_append_pid, "u", &u->socket.control_pid },
if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &base, true) >= 0 &&
bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &value, true) >= 0 &&
bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &next_elapse, false) >= 0)
- printf("%s=%llu\n", base, (unsigned long long) value);
+ printf("%s={ value=%llu ; next_elapse=%llu }\n",
+ base,
+ (unsigned long long) value,
+ (unsigned long long) next_elapse);
+
+ dbus_message_iter_next(&sub);
+ }
+
+ return 0;
+ } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && startswith(name, "Exec")) {
+
+ DBusMessageIter sub, sub2, sub3;
+
+ dbus_message_iter_recurse(iter, &sub);
+
+ while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
+ const char *path;
+ uint64_t start_time, exit_time;
+ uint32_t pid;
+ int32_t code, status;
+
+ dbus_message_iter_recurse(&sub, &sub2);
+
+ if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0)
+ continue;
+
+ if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_ARRAY ||
+ dbus_message_iter_get_element_type(&sub2) != DBUS_TYPE_STRING)
+ continue;
+
+ printf("%s={ path=%s ; argv[]=", name, path);
+
+ dbus_message_iter_recurse(&sub2, &sub3);
+
+ while (dbus_message_iter_get_arg_type(&sub3) != DBUS_TYPE_INVALID) {
+ const char *s;
+
+ assert(dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_STRING);
+ dbus_message_iter_get_basic(&sub3, &s);
+ printf("%s ", s);
+ dbus_message_iter_next(&sub3);
+ }
+
+ if (dbus_message_iter_next(&sub2) &&
+ bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &start_time, true) >= 0 &&
+ bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &exit_time, true) >= 0 &&
+ bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &pid, true) >= 0 &&
+ bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &code, true) >= 0 &&
+ bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &status, false) >= 0) {
+
+ char timestamp1[FORMAT_TIMESTAMP_MAX], timestamp2[FORMAT_TIMESTAMP_MAX];
+
+ printf("; start=%s ; stop=%s ; pid=%u ; code=%s ; status=%i/%s",
+ strna(format_timestamp(timestamp1, sizeof(timestamp1), start_time)),
+ strna(format_timestamp(timestamp2, sizeof(timestamp2), exit_time)),
+ (unsigned) pid,
+ sigchld_code_to_string(code),
+ status,
+ strna(code == CLD_EXITED ? NULL : strsignal(status)));
+ }
+
+ printf(" }\n");
dbus_message_iter_next(&sub);
}