* selinux
-* Show exit status auf auxiliary programs in systemctl status
+* systemctl status $PID, systemctl stop $PID!
-* rtkit status
+* make shutdown go on even if conflicting units fail to shut down.
-* systemctl status $PID, systemctl stop $PID!
+* sulogin in den single user mode, mit plymouth --hide davor
External:
token will be passed as
<literal>argv[0]</literal> to the
executed process, followed by the
- further arguments specified. Unless
+ further arguments specified. If the
+ first token is prefixed with
+ <literal>-</literal> an error code of
+ the command normally considered a
+ failure is ignored and considered
+ success. If both <literal>-</literal>
+ and <literal>@</literal> are used for
+ the same command the latter must
+ preceed the latter. Unless
<varname>Type=forking</varname> is
set, the process started via this
command line will be considered the
assert(i);
assert(property);
- if (!dbus_message_iter_open_container(i, DBUS_TYPE_ARRAY, "(sasttuii)", &sub))
+ if (!dbus_message_iter_open_container(i, DBUS_TYPE_ARRAY, "(sasbttuii)", &sub))
return -ENOMEM;
LIST_FOREACH(command, c, c) {
status = (int32_t) c->exec_status.status;
if (!dbus_message_iter_close_container(&sub2, &sub3) ||
+ !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_BOOLEAN, &c->ignore) ||
!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) ||
" <property name=\"KillSignal\" type=\"i\" access=\"read\"/>\n"
#define BUS_EXEC_COMMAND_INTERFACE(name) \
- " <property name=\"" name "\" type=\"a(sasttuii)\" access=\"read\"/>\n"
+ " <property name=\"" name "\" type=\"a(sasbttuii)\" access=\"read\"/>\n"
#define BUS_EXEC_CONTEXT_PROPERTIES(interface, context) \
{ interface, "Environment", bus_property_append_strv, "as", (context).environment }, \
{ 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) }
+ { interface, name, bus_execute_append_command, "a(sasbttuii)", (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);
char *path;
char **argv;
ExecStatus exec_status;
+ bool ignore;
LIST_FIELDS(ExecCommand, command); /* useful for chaining commands */
};
char *w;
size_t l;
char *state;
- bool honour_argv0, write_to_path;
+ bool honour_argv0 = false, ignore = false;
path = NULL;
nce = NULL;
if (rvalue[0] == 0)
break;
- honour_argv0 = rvalue[0] == '@';
+ if (rvalue[0] == '-') {
+ ignore = true;
+ rvalue ++;
+ }
+
+ if (rvalue[0] == '@') {
+ honour_argv0 = true;
+ rvalue ++;
+ }
- if (rvalue[honour_argv0 ? 1 : 0] != '/') {
+ if (*rvalue != '/') {
log_error("[%s:%u] Invalid executable path in command line: %s", filename, line, rvalue);
return -EINVAL;
}
k++;
}
- if (!(n = new(char*, k + (honour_argv0 ? 0 : 1))))
+ if (!(n = new(char*, k + !honour_argv0)))
return -ENOMEM;
k = 0;
- write_to_path = honour_argv0;
FOREACH_WORD_QUOTED(w, l, rvalue, state) {
if (strncmp(w, ";", l) == 0)
break;
- if (write_to_path) {
- if (!(path = cunescape_length(w+1, l-1)))
+ if (honour_argv0 && w == rvalue) {
+ assert(!path);
+ if (!(path = cunescape_length(w, l)))
goto fail;
- write_to_path = false;
} else {
if (!(n[k++] = cunescape_length(w, l)))
goto fail;
nce->argv = n;
nce->path = path;
+ nce->ignore = ignore;
path_kill_slashes(nce->path);
assert(pid >= 0);
success = is_clean_exit(code, status);
- s->failure = s->failure || !success;
if (s->main_pid == pid) {
if (s->type != SERVICE_FORKING) {
assert(s->exec_command[SERVICE_EXEC_START]);
s->exec_command[SERVICE_EXEC_START]->exec_status = s->main_exec_status;
+
+ if (s->exec_command[SERVICE_EXEC_START]->ignore)
+ success = true;
}
log_debug("%s: main process exited, code=%s, status=%i", u->meta.id, sigchld_code_to_string(code), status);
+ s->failure = s->failure || !success;
/* The service exited, so the service is officially
* gone. */
} else if (s->control_pid == pid) {
- if (s->control_command)
+ if (s->control_command) {
exec_status_exit(&s->control_command->exec_status, pid, code, status);
+ if (s->control_command->ignore)
+ success = true;
+ }
+
s->control_pid = 0;
log_debug("%s: control process exited, code=%s status=%i", u->meta.id, sigchld_code_to_string(code), status);
+ s->failure = s->failure || !success;
/* If we are shutting things down anyway we
* don't care about failing commands. */
s->control_pid = 0;
success = is_clean_exit(code, status);
- s->failure = s->failure || !success;
- if (s->control_command)
+ if (s->control_command) {
exec_status_exit(&s->control_command->exec_status, pid, code, status);
+ if (s->control_command->ignore)
+ success = true;
+ }
+
log_debug("%s control process exited, code=%s status=%i", u->meta.id, sigchld_code_to_string(code), status);
+ s->failure = s->failure || !success;
if (s->control_command && s->control_command->command_next && success) {
log_debug("%s running next command for state %s", u->meta.id, socket_state_to_string(s->state));
char *path;
char **argv;
+ bool ignore;
+
usec_t start_timestamp;
usec_t exit_timestamp;
pid_t pid;
unsigned n;
uint32_t pid;
int32_t code, status;
+ dbus_bool_t ignore;
assert(i);
assert(i);
}
if (!dbus_message_iter_next(&sub2) ||
+ bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &ignore, true) < 0 ||
bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &start_timestamp, true) < 0 ||
bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &exit_timestamp, 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, &status, false) < 0)
return -EIO;
+ i->ignore = ignore;
i->start_timestamp = (usec_t) start_timestamp;
i->exit_timestamp = (usec_t) exit_timestamp;
i->pid = (pid_t) pid;
t = strv_join(info.argv, " ");
- printf("%s={ path=%s ; argv[]=%s; start_time=[%s] ; stop_time=[%s] ; pid=%u ; code=%s ; status=%i%s%s }\n",
+ printf("%s={ path=%s ; argv[]=%s ; ignore=%s ; start_time=[%s] ; stop_time=[%s] ; pid=%u ; code=%s ; status=%i%s%s }\n",
name,
strna(info.path),
strna(t),
+ yes_no(info.ignore),
strna(format_timestamp(timestamp1, sizeof(timestamp1), info.start_timestamp)),
strna(format_timestamp(timestamp2, sizeof(timestamp2), info.exit_timestamp)),
(unsigned) info. pid,