X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=src%2Fsystemctl.c;h=b584e7032b9558672b5424d854096ffdaf974a6e;hp=10c6319b4e840a21c8786eaadb74bfa5f1d89f6c;hb=1a63987788624a8819b94b199aa6748665f5e957;hpb=e190aa0be1fa6cb1f56e036598ba90d58d16d9e8 diff --git a/src/systemctl.c b/src/systemctl.c index 10c6319b4..b584e7032 100644 --- a/src/systemctl.c +++ b/src/systemctl.c @@ -80,6 +80,7 @@ static bool arg_failed = false; static char **arg_wall = NULL; static const char *arg_kill_who = NULL; static const char *arg_kill_mode = NULL; +static const char *arg_root = NULL; static int arg_signal = SIGTERM; static usec_t arg_when = 0; static enum action { @@ -1565,6 +1566,7 @@ static int check_unit(DBusConnection *bus, char **args, unsigned n) { dbus_error_free(&error); dbus_message_unref(m); + m = NULL; continue; } @@ -3323,6 +3325,13 @@ static int daemon_reload(DBusConnection *bus, char **args, unsigned n) { goto finish; } + if (streq(method, "Reexecute") && dbus_error_has_name(&error, DBUS_ERROR_NO_REPLY)) { + /* On reexecution, we expect a disconnect, not + * a reply */ + r = 0; + goto finish; + } + log_error("Failed to issue method call: %s", bus_error_message(&error)); r = -EIO; goto finish; @@ -3840,8 +3849,14 @@ static int remove_marked_symlinks(const char *config_path) { return r; } -static int create_symlink(const char *verb, const char *old_path, const char *new_path) { +static int create_symlink(const char *verb, const char *orig_old_path, const char *new_path) { int r; + const char *old_path; + + if (arg_root) + old_path = orig_old_path+strlen(arg_root); + else + old_path = orig_old_path; assert(old_path); assert(new_path); @@ -3955,6 +3970,7 @@ static int create_symlink(const char *verb, const char *old_path, const char *ne return 1; } + free(dest); return 0; } @@ -4053,12 +4069,23 @@ static int install_info_apply(const char *verb, LookupPaths *paths, InstallInfo STRV_FOREACH(p, paths->unit_path) { int fd; + char *path, *should_free; + + if (arg_root) + should_free = path = strappend(arg_root, *p); + else { + should_free = NULL; + path = *p; + } - if (!(filename = path_make_absolute(i->name, *p))) { + if (!(filename = path_make_absolute(i->name, path))) { log_error("Out of memory"); return -ENOMEM; } + if (should_free) + free(should_free); + /* Ensure that we don't follow symlinks */ if ((fd = open(filename, O_RDONLY|O_CLOEXEC|O_NOFOLLOW|O_NOCTTY)) >= 0) if ((f = fdopen(fd, "re"))) @@ -4081,7 +4108,7 @@ static int install_info_apply(const char *verb, LookupPaths *paths, InstallInfo } if (!f) { -#if (defined(TARGET_FEDORA) || defined(TARGET_MANDRIVA)) || defined(TARGET_MEEGO) && defined (HAVE_SYSV_COMPAT) +#if (defined(TARGET_FEDORA) || defined(TARGET_MANDRIVA) || defined(TARGET_SUSE) || defined(TARGET_MEEGO) || defined(TARGET_ALTLINUX)) && defined (HAVE_SYSV_COMPAT) if (endswith(i->name, ".service")) { char *sysv; @@ -4093,7 +4120,14 @@ static int install_info_apply(const char *verb, LookupPaths *paths, InstallInfo } sysv[strlen(sysv) - sizeof(".service") + 1] = 0; - exists = access(sysv, F_OK) >= 0; + if (arg_root) { + char *tmp_path; + + tmp_path = strappend (arg_root, sysv); + exists = access (tmp_path, F_OK) >= 0; + free (tmp_path); + } else + exists = access(sysv, F_OK) >= 0; if (exists) { pid_t pid; @@ -4103,6 +4137,7 @@ static int install_info_apply(const char *verb, LookupPaths *paths, InstallInfo "/sbin/chkconfig", NULL, NULL, + NULL, NULL }; @@ -4112,8 +4147,10 @@ static int install_info_apply(const char *verb, LookupPaths *paths, InstallInfo argv[2] = streq(verb, "enable") ? "on" : streq(verb, "disable") ? "off" : "--level=5"; + if (arg_root) + argv[3] = strappend("--root=", arg_root); - log_info("Executing %s %s %s", argv[0], argv[1], strempty(argv[2])); + log_info("Executing %s %s %s %s", argv[0], argv[1], strempty(argv[2]), strempty(argv[3])); if ((pid = fork()) < 0) { log_error("Failed to fork: %m"); @@ -4152,19 +4189,21 @@ static int install_info_apply(const char *verb, LookupPaths *paths, InstallInfo return -ENOENT; } + i->path = filename; + + if ((r = config_parse(filename, f, NULL, items, true, i)) < 0) { + fclose(f); + return r; + } + /* Consider unit files stored in /lib and /usr always enabled * if they have no [Install] data. */ if (streq(verb, "is-enabled") && strv_isempty(i->aliases) && strv_isempty(i->wanted_by) && - !path_startswith(filename, "/etc")) - return 1; - - i->path = filename; - - if ((r = config_parse(filename, f, NULL, items, true, i)) < 0) { + !path_startswith(filename, "/etc")) { fclose(f); - return r; + return 1; } n_symlinks += strv_length(i->aliases); @@ -4188,20 +4227,24 @@ static int install_info_apply(const char *verb, LookupPaths *paths, InstallInfo } static char *get_config_path(void) { + char *ret; if (arg_user && arg_global) - return strdup(USER_CONFIG_UNIT_PATH); + ret = strdup(USER_CONFIG_UNIT_PATH); if (arg_user) { - char *p; - - if (user_config_home(&p) < 0) + if (user_config_home(&ret) < 0) return NULL; - - return p; } - return strdup(SYSTEM_CONFIG_UNIT_PATH); + ret = strdup(SYSTEM_CONFIG_UNIT_PATH); + if (arg_root) { + char *p; + p = strappend (arg_root, ret); + free (ret); + return p; + } else + return ret; } static int enable_unit(DBusConnection *bus, char **args, unsigned n) { @@ -4284,7 +4327,7 @@ static int enable_unit(DBusConnection *bus, char **args, unsigned n) { /* Don't try to reload anything if we are called for system changes but the system wasn't booted with systemd */ (arg_user || sd_booted() > 0) && /* Don't try to reload anything if we are running in a chroot environment */ - (arg_user || running_in_chroot() <= 0) ) { + (arg_user || running_in_chroot() <= 0 || arg_root) ) { int q; if ((q = daemon_reload(bus, args, n)) < 0) @@ -4336,6 +4379,7 @@ static int systemctl_help(void) { " Do not ask for system passwords\n" " --order When generating graph for dot, show only order\n" " --require When generating graph for dot, show only requirement\n" + " --root=path Use as the root file system\n" " --system Connect to system manager\n" " --user Connect to user service manager\n" " --global Enable/disable unit files globally\n" @@ -4470,6 +4514,7 @@ static int systemctl_parse_argv(int argc, char *argv[]) { ARG_NO_WALL, ARG_ORDER, ARG_REQUIRE, + ARG_ROOT, ARG_FULL, ARG_NO_RELOAD, ARG_DEFAULTS, @@ -4498,6 +4543,7 @@ static int systemctl_parse_argv(int argc, char *argv[]) { { "quiet", no_argument, NULL, 'q' }, { "order", no_argument, NULL, ARG_ORDER }, { "require", no_argument, NULL, ARG_REQUIRE }, + { "root", required_argument, NULL, ARG_ROOT }, { "force", no_argument, NULL, 'f' }, { "no-reload", no_argument, NULL, ARG_NO_RELOAD }, { "defaults", no_argument, NULL, ARG_DEFAULTS }, @@ -4592,6 +4638,10 @@ static int systemctl_parse_argv(int argc, char *argv[]) { arg_dot = DOT_REQUIRE; break; + case ARG_ROOT: + arg_root = optarg; + break; + case ARG_FULL: arg_full = true; break; @@ -4765,10 +4815,10 @@ static int parse_time_spec(const char *t, usec_t *_u) { if (streq(t, "now")) *_u = 0; - else if (t[0] == '+') { + else if (!strchr(t, ':')) { uint64_t u; - if (safe_atou64(t + 1, &u) < 0) + if (safe_atou64(t, &u) < 0) return -EINVAL; *_u = now(CLOCK_REALTIME) + USEC_PER_MINUTE * u; @@ -5561,7 +5611,7 @@ static void pager_open(void) { if (!on_tty() || arg_no_pager) return; - if ((pager = getenv("PAGER"))) + if ((pager = getenv("SYSTEMD_PAGER")) || (pager = getenv("PAGER"))) if (!*pager || streq(pager, "cat")) return;