#include "efivars.h"
#include "env-util.h"
#include "exit-status.h"
+#include "fd-util.h"
#include "fileio.h"
#include "formats-util.h"
+#include "fs-util.h"
#include "hostname-util.h"
#include "initreq.h"
#include "install.h"
+#include "io-util.h"
#include "list.h"
#include "log.h"
#include "logs-show.h"
#include "macro.h"
#include "mkdir.h"
#include "pager.h"
+#include "parse-util.h"
#include "path-lookup.h"
#include "path-util.h"
#include "process-util.h"
+#include "rlimit-util.h"
#include "set.h"
#include "signal-util.h"
#include "socket-util.h"
#include "strv.h"
#include "terminal-util.h"
#include "unit-name.h"
+#include "user-util.h"
#include "util.h"
#include "utmp-wtmp.h"
#include "verbs.h"
static char **arg_wall = NULL;
static const char *arg_kill_who = NULL;
static int arg_signal = SIGTERM;
-static const char *arg_root = NULL;
+static char *arg_root = NULL;
static usec_t arg_when = 0;
static enum action {
_ACTION_INVALID,
return r;
} else if (a == ACTION_EXIT && argc > 1) {
- uint8_t code = 0;
+ uint8_t code;
/* If the exit code is not given on the command line,
* don't reset it to zero: just keep it as it might
dir = mfree(dir);
- if (path_get_parent(*dropin, &dir) < 0) {
+ dir = dirname_malloc(*dropin);
+ if (!dir) {
log_oom();
return;
}
}
static int create_edit_temp_file(const char *new_path, const char *original_path, char **ret_tmp_fn) {
- char *t;
+ _cleanup_free_ char *t = NULL;
int r;
assert(new_path);
return log_error_errno(r, "Failed to determine temporary filename for \"%s\": %m", new_path);
r = mkdir_parents(new_path, 0755);
- if (r < 0) {
- free(t);
+ if (r < 0)
return log_error_errno(r, "Failed to create directories for \"%s\": %m", new_path);
- }
r = copy_file(original_path, t, 0, 0644, 0);
if (r == -ENOENT) {
+
r = touch(t);
- if (r < 0) {
- log_error_errno(r, "Failed to create temporary file \"%s\": %m", t);
- free(t);
- return r;
- }
- } else if (r < 0) {
- log_error_errno(r, "Failed to copy \"%s\" to \"%s\": %m", original_path, t);
- free(t);
- return r;
- }
+ if (r < 0)
+ return log_error_errno(r, "Failed to create temporary file \"%s\": %m", t);
+
+ } else if (r < 0)
+ return log_error_errno(r, "Failed to copy \"%s\" to \"%s\": %m", original_path, t);
*ret_tmp_fn = t;
+ t = NULL;
return 0;
}
static int get_file_to_edit(const char *name, const char *user_home, const char *user_runtime, char **ret_path) {
_cleanup_free_ char *path = NULL, *path2 = NULL, *run = NULL;
+ assert(name);
+ assert(ret_path);
+
switch (arg_scope) {
case UNIT_FILE_SYSTEM:
path = path_join(arg_root, SYSTEM_CONFIG_UNIT_PATH, name);
}
static int unit_file_create_dropin(const char *unit_name, const char *user_home, const char *user_runtime, char **ret_new_path, char **ret_tmp_path) {
- char *tmp_new_path, *ending;
- char *tmp_tmp_path;
+ char *tmp_new_path, *tmp_tmp_path, *ending;
int r;
assert(unit_name);
char **ret_new_path,
char **ret_tmp_path) {
- char *tmp_new_path;
- char *tmp_tmp_path;
+ char *tmp_new_path, *tmp_tmp_path;
int r;
assert(fragment_path);
if (r < 0)
return log_error_errno(r, "Failed to wait for child: %m");
- return r;
+ return 0;
}
static int find_paths_to_edit(sd_bus *bus, char **names, char ***paths) {
goto end;
STRV_FOREACH_PAIR(original, tmp, paths) {
- /* If the temporary file is empty we ignore it.
- * It's useful if the user wants to cancel its modification
+ /* If the temporary file is empty we ignore it. It's
+ * useful if the user wants to cancel its modification
*/
if (null_or_empty_path(*tmp)) {
- log_warning("Editing \"%s\" canceled: temporary file is empty", *original);
+ log_warning("Editing \"%s\" canceled: temporary file is empty.", *original);
continue;
}
+
r = rename(*tmp, *original);
if (r < 0) {
r = log_error_errno(errno, "Failed to rename \"%s\" to \"%s\": %m", *tmp, *original);
}
}
- if (!arg_no_reload && bus && !install_client_side())
+ r = 0;
+
+ if (!arg_no_reload && !install_client_side())
r = daemon_reload(argc, argv, userdata);
end:
STRV_FOREACH_PAIR(original, tmp, paths)
- unlink_noerrno(*tmp);
+ (void) unlink(*tmp);
return r;
}
static void help_types(void) {
int i;
- const char *t;
if (!arg_no_legend)
puts("Available unit types:");
- for (i = 0; i < _UNIT_TYPE_MAX; i++) {
- t = unit_type_to_string(i);
- if (t)
- puts(t);
- }
+ for (i = 0; i < _UNIT_TYPE_MAX; i++)
+ puts(unit_type_to_string(i));
+}
+
+static void help_states(void) {
+ int i;
+
+ if (!arg_no_legend)
+ puts("Available unit load states:");
+ for (i = 0; i < _UNIT_LOAD_STATE_MAX; i++)
+ puts(unit_load_state_to_string(i));
+
+ if (!arg_no_legend)
+ puts("\nAvailable unit active states:");
+ for (i = 0; i < _UNIT_ACTIVE_STATE_MAX; i++)
+ puts(unit_active_state_to_string(i));
+
+ if (!arg_no_legend)
+ puts("\nAvailable automount unit substates:");
+ for (i = 0; i < _AUTOMOUNT_STATE_MAX; i++)
+ puts(automount_state_to_string(i));
+
+ if (!arg_no_legend)
+ puts("\nAvailable busname unit substates:");
+ for (i = 0; i < _BUSNAME_STATE_MAX; i++)
+ puts(busname_state_to_string(i));
+
+ if (!arg_no_legend)
+ puts("\nAvailable device unit substates:");
+ for (i = 0; i < _DEVICE_STATE_MAX; i++)
+ puts(device_state_to_string(i));
+
+ if (!arg_no_legend)
+ puts("\nAvailable mount unit substates:");
+ for (i = 0; i < _MOUNT_STATE_MAX; i++)
+ puts(mount_state_to_string(i));
+
+ if (!arg_no_legend)
+ puts("\nAvailable path unit substates:");
+ for (i = 0; i < _PATH_STATE_MAX; i++)
+ puts(path_state_to_string(i));
+
+ if (!arg_no_legend)
+ puts("\nAvailable scope unit substates:");
+ for (i = 0; i < _SCOPE_STATE_MAX; i++)
+ puts(scope_state_to_string(i));
+
+ if (!arg_no_legend)
+ puts("\nAvailable service unit substates:");
+ for (i = 0; i < _SERVICE_STATE_MAX; i++)
+ puts(service_state_to_string(i));
+
+ if (!arg_no_legend)
+ puts("\nAvailable slice unit substates:");
+ for (i = 0; i < _SLICE_STATE_MAX; i++)
+ puts(slice_state_to_string(i));
+
+ if (!arg_no_legend)
+ puts("\nAvailable snapshot unit substates:");
+ for (i = 0; i < _SNAPSHOT_STATE_MAX; i++)
+ puts(snapshot_state_to_string(i));
+
+ if (!arg_no_legend)
+ puts("\nAvailable socket unit substates:");
+ for (i = 0; i < _SOCKET_STATE_MAX; i++)
+ puts(socket_state_to_string(i));
+
+ if (!arg_no_legend)
+ puts("\nAvailable swap unit substates:");
+ for (i = 0; i < _SWAP_STATE_MAX; i++)
+ puts(swap_state_to_string(i));
+
+ if (!arg_no_legend)
+ puts("\nAvailable target unit substates:");
+ for (i = 0; i < _TARGET_STATE_MAX; i++)
+ puts(target_state_to_string(i));
+
+ if (!arg_no_legend)
+ puts("\nAvailable timer unit substates:");
+ for (i = 0; i < _TIMER_STATE_MAX; i++)
+ puts(timer_state_to_string(i));
}
static int systemctl_parse_argv(int argc, char *argv[]) {
{}
};
- int c;
+ int c, r;
assert(argc >= 0);
assert(argv);
}
if (unit_type_from_string(type) >= 0) {
- if (strv_push(&arg_types, type))
+ if (strv_push(&arg_types, type) < 0)
return log_oom();
type = NULL;
continue;
* load states, but let's support this
* in --types= too for compatibility
* with old versions */
- if (unit_load_state_from_string(optarg) >= 0) {
+ if (unit_load_state_from_string(type) >= 0) {
if (strv_push(&arg_states, type) < 0)
return log_oom();
type = NULL;
break;
case ARG_ROOT:
- arg_root = optarg;
+ r = parse_path_argument_and_warn(optarg, true, &arg_root);
+ if (r < 0)
+ return r;
break;
case 'l':
size_t size;
FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
- char *s;
+ _cleanup_free_ char *s = NULL;
s = strndup(word, size);
if (!s)
return log_oom();
- if (strv_consume(&arg_states, s) < 0)
+ if (streq(s, "help")) {
+ help_states();
+ return 0;
+ }
+
+ if (strv_push(&arg_states, s) < 0)
return log_oom();
+
+ s = NULL;
}
break;
}
assert(argc >= 0);
assert(argv);
- while ((c = getopt_long(argc, argv, "HPrhkKt:afFc", options, NULL)) >= 0)
+ while ((c = getopt_long(argc, argv, "HPrhkKtafFc", options, NULL)) >= 0)
switch (c) {
case ARG_HELP:
static int systemctl_main(int argc, char *argv[]) {
static const Verb verbs[] = {
- { "list-units", VERB_ANY, 1, VERB_DEFAULT, list_units },
- { "list-unit-files", VERB_ANY, 1, 0, list_unit_files },
- { "list-sockets", VERB_ANY, 1, 0, list_sockets },
- { "list-timers", VERB_ANY, 1, 0, list_timers },
- { "list-jobs", VERB_ANY, 1, 0, list_jobs },
- { "list-machines", VERB_ANY, 1, 0, list_machines },
+ { "list-units", VERB_ANY, VERB_ANY, VERB_DEFAULT, list_units },
+ { "list-unit-files", VERB_ANY, VERB_ANY, 0, list_unit_files },
+ { "list-sockets", VERB_ANY, VERB_ANY, 0, list_sockets },
+ { "list-timers", VERB_ANY, VERB_ANY, 0, list_timers },
+ { "list-jobs", VERB_ANY, VERB_ANY, 0, list_jobs },
+ { "list-machines", VERB_ANY, VERB_ANY, 0, list_machines },
{ "clear-jobs", VERB_ANY, 1, 0, daemon_reload },
{ "cancel", 2, VERB_ANY, 0, cancel_job },
{ "start", 2, VERB_ANY, 0, start_unit },
case ACTION_KEXEC:
action = "kexec";
break;
+ case ACTION_EXIT:
+ action = "exit";
+ break;
+ case ACTION_REBOOT:
default:
action = "reboot";
break;
strv_free(arg_properties);
strv_free(arg_wall);
+ free(arg_root);
release_busses();