[systemd-commits] 12 commits - Makefile.am man/pam_systemd.xml man/systemd.service.xml man/systemd-tmpfiles.xml man/tmpfiles.d.xml src/cgroup.c src/dbus-service.c src/load-fragment.c src/pam-module.c src/readahead-collect.c src/readahead-replay.c src/service.c src/service.h src/systemctl.c src/tmpfiles.c src/util.c src/util.h tmpfiles.d/x11.conf TODO units/systemd-tmpfiles-clean.service.in units/systemd-tmpfiles-setup.service.in
Lennart Poettering
lennart at kemper.freedesktop.org
Sun Feb 13 12:46:39 PST 2011
Makefile.am | 5 -
TODO | 16 ---
man/pam_systemd.xml | 50 ++++++++--
man/systemd-tmpfiles.xml | 150 ++++++++++++++++++++++++++++++++
man/systemd.service.xml | 24 +++++
man/tmpfiles.d.xml | 19 ++--
src/cgroup.c | 15 ++-
src/dbus-service.c | 5 -
src/load-fragment.c | 1
src/pam-module.c | 125 +++++++++++++++++++++++---
src/readahead-collect.c | 5 +
src/readahead-replay.c | 5 +
src/service.c | 22 +++-
src/service.h | 1
src/systemctl.c | 43 +++++----
src/tmpfiles.c | 147 ++++++++++++++++++-------------
src/util.c | 96 +++++++++++++++++++-
src/util.h | 2
tmpfiles.d/x11.conf | 11 --
units/systemd-tmpfiles-clean.service.in | 2
units/systemd-tmpfiles-setup.service.in | 2
21 files changed, 584 insertions(+), 162 deletions(-)
New commits:
commit cfdc0c8941f25ab08140d56f773105228e459ac5
Author: Lennart Poettering <lennart at poettering.net>
Date: Sun Feb 13 19:02:18 2011 +0100
update TODO
diff --git a/TODO b/TODO
index 9827b07..f7269f1 100644
--- a/TODO
+++ b/TODO
@@ -124,10 +124,6 @@ Features:
* allow runtime changing of log level and target
-* automatically determine TERM= based on tty name even for /dev/console
- http://git.kernel.org/?p=linux/kernel/git/gregkh/tty-2.6.git;a=commitdiff;h=fbc92a3455577ab17615cbcb91826399061bd789
- http://git.kernel.org/?p=linux/kernel/git/gregkh/tty-2.6.git;a=commitdiff;h=b7b8de087384cc1954a8cd075af3f9e5977caa2e
-
* global defaults for StandardOuput=xxx
Fedora:
commit 3030ccd79f71854551d06cda904fd56b85b1aeb7
Author: Lennart Poettering <lennart at poettering.net>
Date: Sun Feb 13 19:01:47 2011 +0100
util: when determining the right TERM for /dev/console consult /sys/class/tty/console/active
diff --git a/src/util.c b/src/util.c
index 09c1314..e78063c 100644
--- a/src/util.c
+++ b/src/util.c
@@ -3550,18 +3550,28 @@ void filter_environ(const char *prefix) {
}
const char *default_term_for_tty(const char *tty) {
+ char *active = NULL;
+ const char *term;
+
assert(tty);
if (startswith(tty, "/dev/"))
tty += 5;
- if (startswith(tty, "tty") &&
- tty[3] >= '0' && tty[3] <= '9')
- return "TERM=linux";
+ /* Resolve where /dev/console is pointing when determining
+ * TERM */
+ if (streq(tty, "console"))
+ if (read_one_line_file("/sys/class/tty/console/active", &active) >= 0) {
+ truncate_nl(active);
+ tty = active;
+ }
+
+ term = (startswith(tty, "tty") &&
+ tty[3] >= '0' && tty[3] <= '9') ? "TERM=linux" : "TERM=vt100";
- /* FIXME: Proper handling of /dev/console would be cool */
+ free(active);
- return "TERM=vt100";
+ return term;
}
bool running_in_vm(void) {
commit 2633eb8317623138f585957fcf8337a99fb1528f
Author: Lennart Poettering <lennart at poettering.net>
Date: Sun Feb 13 18:52:02 2011 +0100
service: when guessing the main PID don't consider processes that aren't our children
diff --git a/src/cgroup.c b/src/cgroup.c
index 392736f..729cc75 100644
--- a/src/cgroup.c
+++ b/src/cgroup.c
@@ -403,7 +403,7 @@ char *cgroup_bonding_to_string(CGroupBonding *b) {
pid_t cgroup_bonding_search_main_pid(CGroupBonding *b) {
FILE *f;
- pid_t pid = 0, npid;
+ pid_t pid = 0, npid, mypid;
assert(b);
@@ -413,15 +413,22 @@ pid_t cgroup_bonding_search_main_pid(CGroupBonding *b) {
if (cg_enumerate_processes(b->controller, b->path, &f) < 0)
return 0;
+ mypid = getpid();
+
while (cg_read_pid(f, &npid) > 0) {
+ pid_t ppid;
if (npid == pid)
continue;
+ /* Ignore processes that aren't our kids */
+ if (get_parent_of_pid(npid, &ppid) >= 0 && ppid != mypid)
+ continue;
+
if (pid != 0) {
- /* Dang, there's more than one PID in this
- * group, so we don't know what process is the
- * main process. */
+ /* Dang, there's more than one daemonized PID
+ in this group, so we don't know what process
+ is the main process. */
pid = 0;
break;
}
commit 3185a36b05d53757a412f847d8c510978b9b00f0
Author: Lennart Poettering <lennart at poettering.net>
Date: Sun Feb 13 18:51:30 2011 +0100
service: make main pid guessing optional, and reread pid file after reloads
diff --git a/TODO b/TODO
index 4d5a144..9827b07 100644
--- a/TODO
+++ b/TODO
@@ -9,6 +9,8 @@ Bugs:
Features:
+* Maybe store in unit files whether a service should be enabled by default on package installation
+
* perhaps add "systemctl reenable" as combination of "systemctl disable" and "systemctl enable"
* need a way to apply mount options of api vfs from systemd unit files instead of fstab
@@ -23,12 +25,8 @@ Features:
* gnome-shell python script/glxinfo/is-accelerated wech
-* PID heuristik bei Type=forking ausmachbar machen
-
* maybe introduce ExecRestartPre=
-* reload PID file after reload, allow dynamically changing main PIDs
-
* figure out what happened to bluez patch
* introduce StandardOutput=syslog+console and StandardOutput=kmsg+console to support fsck output at boot
diff --git a/man/systemd.service.xml b/man/systemd.service.xml
index 3bd058f..7200525 100644
--- a/man/systemd.service.xml
+++ b/man/systemd.service.xml
@@ -216,6 +216,30 @@
</varlistentry>
<varlistentry>
+ <term><varname>GuessMainPID=</varname></term>
+
+ <listitem><para>Takes a boolean value
+ that specifies whether systemd should
+ try to guess the main PID of a service
+ should if it cannot be determined
+ reliably. This option is ignored
+ unless <option>Type=forking</option>
+ is set and <option>PIDFile=</option>
+ is unset because for the other types
+ or with an explicitly configured PID
+ file the main PID is always known. The
+ guessing algorithm might come to
+ incorrect conclusions if a daemon
+ consists of more than one process. If
+ the main PID cannot be determined
+ failure detection and automatic
+ restarting of a service will not work
+ reliably. Defaults to
+ <option>yes</option>.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
<term><varname>PIDFile=</varname></term>
<listitem><para>Takes an absolute file
diff --git a/src/dbus-service.c b/src/dbus-service.c
index f929627..93fc2a3 100644
--- a/src/dbus-service.c
+++ b/src/dbus-service.c
@@ -127,8 +127,9 @@ DBusHandlerResult bus_service_message_handler(Unit *u, DBusConnection *connectio
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 },
- { "org.freedesktop.systemd1.Service", "RemainAfterExit", bus_property_append_bool, "b", &u->service.remain_after_exit },
- BUS_EXEC_STATUS_PROPERTIES("org.freedesktop.systemd1.Service", u->service.main_exec_status, "ExecMain"),
+ { "org.freedesktop.systemd1.Service", "RemainAfterExit", bus_property_append_bool, "b", &u->service.remain_after_exit },
+ { "org.freedesktop.systemd1.Service", "GuessMainPID", bus_property_append_bool, "b", &u->service.guess_main_pid },
+ BUS_EXEC_STATUS_PROPERTIES("org.freedesktop.systemd1.Service", u->service.main_exec_status, "ExecMain"),
{ "org.freedesktop.systemd1.Service", "MainPID", bus_property_append_pid, "u", &u->service.main_pid },
{ "org.freedesktop.systemd1.Service", "ControlPID", bus_property_append_pid, "u", &u->service.control_pid },
#ifdef HAVE_SYSV_COMPAT
diff --git a/src/load-fragment.c b/src/load-fragment.c
index ab2bcd2..eaeaada 100644
--- a/src/load-fragment.c
+++ b/src/load-fragment.c
@@ -1854,6 +1854,7 @@ static int load_from_path(Unit *u, const char *path) {
{ "PermissionsStartOnly", config_parse_bool, &u->service.permissions_start_only, "Service" },
{ "RootDirectoryStartOnly", config_parse_bool, &u->service.root_directory_start_only, "Service" },
{ "RemainAfterExit", config_parse_bool, &u->service.remain_after_exit, "Service" },
+ { "GuessMainPID", config_parse_bool, &u->service.guess_main_pid, "Service" },
#ifdef HAVE_SYSV_COMPAT
{ "SysVStartPriority", config_parse_sysv_priority, &u->service.sysv_start_priority, "Service" },
#else
diff --git a/src/service.c b/src/service.c
index 60576df..243e553 100644
--- a/src/service.c
+++ b/src/service.c
@@ -118,6 +118,7 @@ static void service_init(Unit *u) {
s->sysv_start_priority = -1;
#endif
s->socket_fd = -1;
+ s->guess_main_pid = true;
exec_context_init(&s->exec_context);
@@ -1151,6 +1152,7 @@ static void service_dump(Unit *u, FILE *f, const char *prefix) {
"%sPermissionsStartOnly: %s\n"
"%sRootDirectoryStartOnly: %s\n"
"%sRemainAfterExit: %s\n"
+ "%sGuessMainPID: %s\n"
"%sType: %s\n"
"%sRestart: %s\n"
"%sNotifyAccess: %s\n",
@@ -1158,6 +1160,7 @@ static void service_dump(Unit *u, FILE *f, const char *prefix) {
prefix, yes_no(s->permissions_start_only),
prefix, yes_no(s->root_directory_start_only),
prefix, yes_no(s->remain_after_exit),
+ prefix, yes_no(s->guess_main_pid),
prefix, service_type_to_string(s->type),
prefix, service_restart_to_string(s->restart),
prefix, notify_access_to_string(s->notify_access));
@@ -1236,11 +1239,6 @@ static int service_load_pid_file(Service *s) {
assert(s);
- if (s->main_pid_known)
- return 0;
-
- assert(s->main_pid <= 0);
-
if (!s->pid_file)
return -ENOENT;
@@ -1275,9 +1273,14 @@ static int service_search_main_pid(Service *s) {
assert(s);
+ /* If we know it anyway, don't ever fallback to unreliable
+ * heuristics */
if (s->main_pid_known)
return 0;
+ if (!s->guess_main_pid)
+ return 0;
+
assert(s->main_pid <= 0);
if ((pid = cgroup_bonding_search_main_pid_list(s->meta.cgroup_bondings)) <= 0)
@@ -2674,9 +2677,16 @@ static void service_sigchld_event(Unit *u, pid_t pid, int code, int status) {
log_warning("%s: failed to load PID file %s: %s", s->meta.id, s->pid_file, strerror(-r));
}
- /* Fall through */
+ s->reload_failure = !success;
+ service_enter_running(s, true);
+ break;
case SERVICE_RELOAD:
+ if (success) {
+ service_load_pid_file(s);
+ service_search_main_pid(s);
+ }
+
s->reload_failure = !success;
service_enter_running(s, true);
break;
diff --git a/src/service.h b/src/service.h
index e06ff3d..627b356 100644
--- a/src/service.h
+++ b/src/service.h
@@ -125,6 +125,7 @@ struct Service {
bool permissions_start_only;
bool root_directory_start_only;
bool remain_after_exit;
+ bool guess_main_pid;
/* If we shut down, remember why */
bool failure:1;
commit e9fbc77c8f6a396ce9432e3791710e30de6e570b
Author: Lennart Poettering <lennart at poettering.net>
Date: Sun Feb 13 18:21:11 2011 +0100
pam: introduce whitelist and blacklist user list feature
This is useful to exclude root from the session logout killings or to
limit killing to the selinux guest users.
diff --git a/TODO b/TODO
index 8660f16..4d5a144 100644
--- a/TODO
+++ b/TODO
@@ -147,8 +147,6 @@ External:
* patch kernel for cpu feature modalias for autoloading aes/kvm/...
http://git.kernel.org/?p=linux/kernel/git/ak/linux-misc-2.6.git;a=shortlog;h=refs/heads/cpuid-match
-* place /etc/inittab with explaining blurb.
-
* procps, psmisc, sysvinit-tools, hostname â util-linux-ng
https://bugzilla.redhat.com/show_bug.cgi?id=614245 -- plymouth
diff --git a/man/pam_systemd.xml b/man/pam_systemd.xml
index 6fe6981..915e0b6 100644
--- a/man/pam_systemd.xml
+++ b/man/pam_systemd.xml
@@ -202,17 +202,43 @@
</varlistentry>
<varlistentry>
- <term><option>keep-root=</option></term>
+ <term><option>kill-only-users=</option></term>
- <listitem><para>Takes a boolean
- argument. If true, all processes
- created by the root user (UID 0) during his
- session and from his session will be
- kept around after he logged out. This
- option allows cancelling the effect of
- <option>kill-session=1</option> and
- <option>kill-user=1</option> for the
- root user.</para></listitem>
+ <listitem><para>Takes a comma
+ separated list of user names or
+ numeric user ids as argument. If this
+ option is used the effect of the
+ <option>kill-session=</option> and
+ <option>kill-user=</option> options
+ will apply only to the listed
+ users. If this option is not used the
+ option applies to all local
+ users. Note that
+ <option>kill-exclude-users=</option>
+ takes precedence over this list and is
+ hence subtracted from the list
+ specified here.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>kill-exclude-users=</option></term>
+
+ <listitem><para>Takes a comma
+ separated list of user names or
+ numeric user ids as argument. Users
+ listed in this argument will not be
+ subject to the effect of
+ <option>kill-session=</option> or
+ <option>kill-user=</option>. Note
+ that that this option takes precedence
+ over
+ <option>kill-only-users=</option>, and
+ hence whatever is listed for
+ <option>kill-exclude-users=</option>
+ is guaranteed to never be killed by
+ this PAM module, independent of any
+ other configuration
+ setting.</para></listitem>
</varlistentry>
<varlistentry>
@@ -259,7 +285,9 @@
<option>kill-session=0</option>,
<option>kill-user=0</option>,
<option>keep-root=1</option>,
- <option>reset-controllers=cpu</option>.</para>
+ <option>reset-controllers=cpu</option>,
+ <option>kill-only-users=</option>,
+ <option>kill-exclude-users=root</option>.</para>
</refsect1>
<refsect1>
diff --git a/src/pam-module.c b/src/pam-module.c
index 117df05..7f91584 100644
--- a/src/pam-module.c
+++ b/src/pam-module.c
@@ -42,12 +42,14 @@ static int parse_argv(pam_handle_t *handle,
bool *create_session,
bool *kill_session,
bool *kill_user,
- bool *keep_root,
char ***controllers,
- char ***reset_controllers) {
+ char ***reset_controllers,
+ char ***kill_only_users,
+ char ***kill_exclude_users) {
unsigned i;
bool reset_controller_set = false;
+ bool kill_exclude_users_set = false;
assert(argc >= 0);
assert(argc == 0 || argv);
@@ -82,15 +84,6 @@ static int parse_argv(pam_handle_t *handle,
if (kill_user)
*kill_user = k;
- } else if (startswith(argv[i], "keep-root=")) {
- if ((k = parse_boolean(argv[i] + 10)) < 0) {
- pam_syslog(handle, LOG_ERR, "Failed to parse keep-root= argument.");
- return k;
- }
-
- if (keep_root)
- *keep_root = k;
-
} else if (startswith(argv[i], "controllers=")) {
if (controllers) {
@@ -121,6 +114,36 @@ static int parse_argv(pam_handle_t *handle,
reset_controller_set = true;
+ } else if (startswith(argv[i], "kill-only-users=")) {
+
+ if (kill_only_users) {
+ char **l;
+
+ if (!(l = strv_split(argv[i] + 16, ","))) {
+ pam_syslog(handle, LOG_ERR, "Out of memory.");
+ return -ENOMEM;
+ }
+
+ strv_free(*kill_only_users);
+ *kill_only_users = l;
+ }
+
+ } else if (startswith(argv[i], "kill-exclude-users=")) {
+
+ if (kill_exclude_users) {
+ char **l;
+
+ if (!(l = strv_split(argv[i] + 19, ","))) {
+ pam_syslog(handle, LOG_ERR, "Out of memory.");
+ return -ENOMEM;
+ }
+
+ strv_free(*kill_exclude_users);
+ *kill_exclude_users = l;
+ }
+
+ kill_exclude_users_set = true;
+
} else {
pam_syslog(handle, LOG_ERR, "Unknown parameter '%s'.", argv[i]);
return -EINVAL;
@@ -147,6 +170,17 @@ static int parse_argv(pam_handle_t *handle,
if (kill_session && *kill_session && kill_user)
*kill_user = true;
+ if (!kill_exclude_users_set && kill_exclude_users) {
+ char **l;
+
+ if (!(l = strv_new("root", NULL))) {
+ pam_syslog(handle, LOG_ERR, "Out of memory");
+ return -ENOMEM;
+ }
+
+ *kill_exclude_users = l;
+ }
+
return 0;
}
@@ -369,7 +403,11 @@ _public_ PAM_EXTERN int pam_sm_open_session(
if (sd_booted() <= 0)
return PAM_SUCCESS;
- if (parse_argv(handle, argc, argv, &create_session, NULL, NULL, NULL, &controllers, &reset_controllers) < 0)
+ if (parse_argv(handle,
+ argc, argv,
+ &create_session, NULL, NULL,
+ &controllers, &reset_controllers,
+ NULL, NULL) < 0)
return PAM_SESSION_ERR;
if ((r = get_user_data(handle, &username, &pw)) != PAM_SUCCESS)
@@ -500,6 +538,54 @@ static int session_remains(pam_handle_t *handle, const char *user_path) {
return !!remains;
}
+static bool check_user_lists(
+ pam_handle_t *handle,
+ uid_t uid,
+ char **kill_only_users,
+ char **kill_exclude_users) {
+
+ const char *name = NULL;
+ char **l;
+
+ assert(handle);
+
+ if (uid == 0)
+ name = "root"; /* Avoid obvious NSS requests, to suppress network traffic */
+ else {
+ struct passwd *pw;
+
+ if ((pw = pam_modutil_getpwuid(handle, uid)))
+ name = pw->pw_name;
+ }
+
+ STRV_FOREACH(l, kill_exclude_users) {
+ uint32_t id;
+
+ if (safe_atou32(*l, &id) >= 0)
+ if ((uid_t) id == uid)
+ return false;
+
+ if (name && streq(name, *l))
+ return false;
+ }
+
+ if (strv_isempty(kill_only_users))
+ return true;
+
+ STRV_FOREACH(l, kill_only_users) {
+ uint32_t id;
+
+ if (safe_atou32(*l, &id) >= 0)
+ if ((uid_t) id == uid)
+ return true;
+
+ if (name && streq(name, *l))
+ return true;
+ }
+
+ return false;
+}
+
_public_ PAM_EXTERN int pam_sm_close_session(
pam_handle_t *handle,
int flags,
@@ -508,13 +594,12 @@ _public_ PAM_EXTERN int pam_sm_close_session(
const char *username = NULL;
bool kill_session = false;
bool kill_user = false;
- bool keep_root = true;
int lock_fd = -1, r;
char *session_path = NULL, *nosession_path = NULL, *user_path = NULL;
const char *id;
struct passwd *pw;
const void *created = NULL;
- char **controllers = NULL, **c;
+ char **controllers = NULL, **c, **kill_only_users = NULL, **kill_exclude_users = NULL;
assert(handle);
@@ -522,7 +607,11 @@ _public_ PAM_EXTERN int pam_sm_close_session(
if (sd_booted() <= 0)
return PAM_SUCCESS;
- if (parse_argv(handle, argc, argv, NULL, &kill_session, &kill_user, &keep_root, &controllers, NULL) < 0)
+ if (parse_argv(handle,
+ argc, argv,
+ NULL, &kill_session, &kill_user,
+ &controllers, NULL,
+ &kill_only_users, &kill_exclude_users) < 0)
return PAM_SESSION_ERR;
if ((r = get_user_data(handle, &username, &pw)) != PAM_SUCCESS)
@@ -557,7 +646,7 @@ _public_ PAM_EXTERN int pam_sm_close_session(
goto finish;
}
- if (kill_session && (pw->pw_uid != 0 || !keep_root)) {
+ if (kill_session && check_user_lists(handle, pw->pw_uid, kill_only_users, kill_exclude_users)) {
pam_syslog(handle, LOG_INFO, "Killing remaining processes of user session %s of %s.", id, username);
/* Kill processes in session cgroup, and delete it */
@@ -591,7 +680,7 @@ _public_ PAM_EXTERN int pam_sm_close_session(
pam_syslog(handle, LOG_ERR, "Failed to determine whether a session remains: %s", strerror(-r));
/* Kill user processes not attached to any session */
- if (kill_user && r == 0 && (pw->pw_uid != 0 || !keep_root)) {
+ if (kill_user && r == 0 && check_user_lists(handle, pw->pw_uid, kill_only_users, kill_exclude_users)) {
/* Kill user cgroup */
if ((r = cg_kill_recursive_and_wait(SYSTEMD_CGROUP_CONTROLLER, user_path, true)) < 0)
@@ -635,6 +724,8 @@ finish:
free(user_path);
strv_free(controllers);
+ strv_free(kill_exclude_users);
+ strv_free(kill_only_users);
return r;
}
commit 7fc01d33196f329c24766795b7af66e598c3e65b
Author: Lennart Poettering <lennart at poettering.net>
Date: Sun Feb 13 17:18:45 2011 +0100
systemctl: minor optimizations
diff --git a/src/systemctl.c b/src/systemctl.c
index 94a12dd..dfa952e 100644
--- a/src/systemctl.c
+++ b/src/systemctl.c
@@ -161,6 +161,7 @@ static void spawn_ask_password_agent(void) {
};
int fd;
+ bool stdout_is_tty, stderr_is_tty;
/* Make sure the agent goes away when the parent dies */
if (prctl(PR_SET_PDEATHSIG, SIGTERM) < 0)
@@ -174,7 +175,10 @@ static void spawn_ask_password_agent(void) {
/* Don't leak fds to the agent */
close_all_fds(NULL, 0);
- if (!isatty(STDOUT_FILENO) || !isatty(STDERR_FILENO)) {
+ stdout_is_tty = isatty(STDOUT_FILENO);
+ stderr_is_tty = isatty(STDERR_FILENO);
+
+ if (!stdout_is_tty || !stderr_is_tty) {
/* Detach from stdout/stderr. and reopen
* /dev/tty for them. This is important to
* ensure that when systemctl is started via
@@ -187,15 +191,11 @@ static void spawn_ask_password_agent(void) {
_exit(EXIT_FAILURE);
}
- if (!isatty(STDOUT_FILENO)) {
- close(STDOUT_FILENO);
+ if (!stdout_is_tty)
dup2(fd, STDOUT_FILENO);
- }
- if (!isatty(STDERR_FILENO)) {
- close(STDERR_FILENO);
+ if (!stderr_is_tty)
dup2(fd, STDERR_FILENO);
- }
if (fd > 2)
close(fd);
commit 060ed82ec24d942c5f519e3dae45e9e2bfb227d8
Author: Lennart Poettering <lennart at poettering.net>
Date: Sun Feb 13 17:09:29 2011 +0100
systemctl: don't unnecessarily close stdin/stdout/stderr for tty agent so that locking by tty works
diff --git a/TODO b/TODO
index 747a669..8660f16 100644
--- a/TODO
+++ b/TODO
@@ -11,8 +11,6 @@ Features:
* perhaps add "systemctl reenable" as combination of "systemctl disable" and "systemctl enable"
-* tty name lock for password agent is broken, since it will always lock "/dev/tty" since we now reattach the agent process when forking it off systemctl
-
* need a way to apply mount options of api vfs from systemd unit files instead of fstab
* udisks should not use udisks-part-id, instead use blkid. also not probe /dev/loopxxx
diff --git a/src/systemctl.c b/src/systemctl.c
index c09b31d..94a12dd 100644
--- a/src/systemctl.c
+++ b/src/systemctl.c
@@ -121,7 +121,7 @@ static bool on_tty(void) {
/* Note that this is invoked relatively early, before we start
* the pager. That means the value we return reflects whether
* we originally were started on a tty, not if we currently
- * are. But this is intended, since we want color, and so on
+ * are. But this is intended, since we want colour and so on
* when run in our own pager. */
if (_unlikely_(t < 0))
@@ -174,27 +174,32 @@ static void spawn_ask_password_agent(void) {
/* Don't leak fds to the agent */
close_all_fds(NULL, 0);
- /* Detach from stdin/stdout/stderr. and reopen
- * /dev/tty for them. This is important to ensure that
- * when systemctl is started via popen() or a similar
- * call that expects to read EOF we actually do
- * generate EOF and not delay this indefinitely by
- * because we keep an unused copy of stdin around. */
- if ((fd = open("/dev/tty", O_RDWR)) < 0) {
- log_error("Failed to open /dev/tty: %m");
- _exit(EXIT_FAILURE);
- }
+ if (!isatty(STDOUT_FILENO) || !isatty(STDERR_FILENO)) {
+ /* Detach from stdout/stderr. and reopen
+ * /dev/tty for them. This is important to
+ * ensure that when systemctl is started via
+ * popen() or a similar call that expects to
+ * read EOF we actually do generate EOF and
+ * not delay this indefinitely by because we
+ * keep an unused copy of stdin around. */
+ if ((fd = open("/dev/tty", O_WRONLY)) < 0) {
+ log_error("Failed to open /dev/tty: %m");
+ _exit(EXIT_FAILURE);
+ }
- close(STDIN_FILENO);
- close(STDOUT_FILENO);
- close(STDERR_FILENO);
+ if (!isatty(STDOUT_FILENO)) {
+ close(STDOUT_FILENO);
+ dup2(fd, STDOUT_FILENO);
+ }
- dup2(fd, STDIN_FILENO);
- dup2(fd, STDOUT_FILENO);
- dup2(fd, STDERR_FILENO);
+ if (!isatty(STDERR_FILENO)) {
+ close(STDERR_FILENO);
+ dup2(fd, STDERR_FILENO);
+ }
- if (fd > 2)
- close(fd);
+ if (fd > 2)
+ close(fd);
+ }
execv(args[0], (char **) args);
_exit(EXIT_FAILURE);
commit 46a08e381589c50394d71e428c09857dfeaa3761
Author: Lennart Poettering <lennart at poettering.net>
Date: Sun Feb 13 15:46:05 2011 +0100
readahead: disable readahead in virtual machines
diff --git a/src/readahead-collect.c b/src/readahead-collect.c
index ac46c7b..4ca6d74 100644
--- a/src/readahead-collect.c
+++ b/src/readahead-collect.c
@@ -649,6 +649,11 @@ int main(int argc, char *argv[]) {
return 0;
}
+ if (running_in_vm()) {
+ log_info("Disabling readahead collector due to execution in virtual machine.");
+ return 0;
+ }
+
if (!(shared = shared_get()))
return 1;
diff --git a/src/readahead-replay.c b/src/readahead-replay.c
index 87f2e59..e9c573a 100644
--- a/src/readahead-replay.c
+++ b/src/readahead-replay.c
@@ -346,6 +346,11 @@ int main(int argc, char*argv[]) {
return 0;
}
+ if (running_in_vm()) {
+ log_info("Disabling readahead replay due to execution in virtual machine.");
+ return 0;
+ }
+
if (!(shared = shared_get()))
return 1;
diff --git a/src/util.c b/src/util.c
index 7692a2d..09c1314 100644
--- a/src/util.c
+++ b/src/util.c
@@ -3564,6 +3564,82 @@ const char *default_term_for_tty(const char *tty) {
return "TERM=vt100";
}
+bool running_in_vm(void) {
+
+#if defined(__i386__) || defined(__x86_64__)
+
+ /* Both CPUID and DMI are x86 specific interfaces... */
+
+ const char *const dmi_vendors[] = {
+ "/sys/class/dmi/id/sys_vendor",
+ "/sys/class/dmi/id/board_vendor",
+ "/sys/class/dmi/id/bios_vendor"
+ };
+
+ uint32_t eax = 0x40000000;
+ union {
+ uint32_t sig32[3];
+ char text[13];
+ } sig;
+
+ unsigned i;
+
+ for (i = 0; i < ELEMENTSOF(dmi_vendors); i++) {
+ char *s;
+ bool b;
+
+ if (read_one_line_file(dmi_vendors[i], &s) < 0)
+ continue;
+
+ b = startswith(s, "QEMU") ||
+ /* http://kb.vmware.com/selfservice/microsites/search.do?language=en_US&cmd=displayKC&externalId=1009458 */
+ startswith(s, "VMware") ||
+ startswith(s, "VMW") ||
+ startswith(s, "Microsoft Corporation") ||
+ startswith(s, "innotek GmbH") ||
+ startswith(s, "Xen");
+
+ free(s);
+
+ if (b)
+ return true;
+ }
+
+ /* http://lwn.net/Articles/301888/ */
+ zero(sig);
+
+
+#if defined (__i386__)
+#define REG_a "eax"
+#define REG_b "ebx"
+#elif defined (__amd64__)
+#define REG_a "rax"
+#define REG_b "rbx"
+#endif
+
+ __asm__ __volatile__ (
+ /* ebx/rbx is being used for PIC! */
+ " push %%"REG_b" \n\t"
+ " cpuid \n\t"
+ " mov %%ebx, %1 \n\t"
+ " pop %%"REG_b" \n\t"
+
+ : "=a" (eax), "=r" (sig.sig32[0]), "=c" (sig.sig32[1]), "=d" (sig.sig32[2])
+ : "0" (eax)
+ );
+
+ if (streq(sig.text, "XenVMMXenVMM") ||
+ streq(sig.text, "KVMKVMKVM") ||
+ /* http://kb.vmware.com/selfservice/microsites/search.do?language=en_US&cmd=displayKC&externalId=1009458 */
+ streq(sig.text, "VMwareVMware") ||
+ /* http://msdn.microsoft.com/en-us/library/bb969719.aspx */
+ streq(sig.text, "Microsoft Hv"))
+ return true;
+#endif
+
+ return false;
+}
+
static const char *const ioprio_class_table[] = {
[IOPRIO_CLASS_NONE] = "none",
[IOPRIO_CLASS_RT] = "realtime",
diff --git a/src/util.h b/src/util.h
index c8cae70..3f0f48f 100644
--- a/src/util.h
+++ b/src/util.h
@@ -372,6 +372,8 @@ void filter_environ(const char *prefix);
const char *default_term_for_tty(const char *tty);
+bool running_in_vm(void);
+
#define NULSTR_FOREACH(i, l) \
for ((i) = (l); (i) && *(i); (i) = strchr((i), 0)+1)
commit a49728dc8c64fe5a2a0e3327274a01adcf18c330
Author: Lennart Poettering <lennart at poettering.net>
Date: Sun Feb 13 15:11:28 2011 +0100
tmpfiles: simplify default tmpfiles configuration by using globs
diff --git a/tmpfiles.d/x11.conf b/tmpfiles.d/x11.conf
index 09f7dfe..5072b58 100644
--- a/tmpfiles.d/x11.conf
+++ b/tmpfiles.d/x11.conf
@@ -15,13 +15,4 @@ d /tmp/.font-unix 1777 root root 10d
d /tmp/.Test-unix 1777 root root 10d
# Unlink the X11 lock files
-r /tmp/.X0-lock
-r /tmp/.X1-lock
-r /tmp/.X2-lock
-r /tmp/.X3-lock
-r /tmp/.X4-lock
-r /tmp/.X5-lock
-r /tmp/.X6-lock
-r /tmp/.X7-lock
-r /tmp/.X8-lock
-r /tmp/.X9-lock
+r /tmp/.X[0-9]-lock
commit 522d4a495af3a615526fccdf038d2d68f41a73c8
Author: Lennart Poettering <lennart at poettering.net>
Date: Sun Feb 13 15:08:15 2011 +0100
systemd: document systemd-tmpfiles
diff --git a/Makefile.am b/Makefile.am
index 56fdfce..dd872f8 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -485,6 +485,7 @@ MANPAGES = \
man/systemctl.1 \
man/systemadm.1 \
man/systemd-cgls.1 \
+ man/systemd-tmpfiles.8 \
man/systemd-notify.1 \
man/sd_notify.3 \
man/sd_readahead.3 \
diff --git a/man/systemd-tmpfiles.xml b/man/systemd-tmpfiles.xml
new file mode 100644
index 0000000..986a442
--- /dev/null
+++ b/man/systemd-tmpfiles.xml
@@ -0,0 +1,150 @@
+<?xml version='1.0'?> <!--*-nxml-*-->
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
+ "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+
+<!--
+ This file is part of systemd.
+
+ Copyright 2010 Lennart Poettering
+
+ systemd is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ systemd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with systemd; If not, see <http://www.gnu.org/licenses/>.
+-->
+
+<refentry id="systemd-tmpfiles">
+
+ <refentryinfo>
+ <title>systemd-tmpfiles</title>
+ <productname>systemd</productname>
+
+ <authorgroup>
+ <author>
+ <contrib>Developer</contrib>
+ <firstname>Lennart</firstname>
+ <surname>Poettering</surname>
+ <email>lennart at poettering.net</email>
+ </author>
+ </authorgroup>
+ </refentryinfo>
+
+ <refmeta>
+ <refentrytitle>systemd-tmpfiles</refentrytitle>
+ <manvolnum>8</manvolnum>
+ </refmeta>
+
+ <refnamediv>
+ <refname>systemd-tmpfiles</refname>
+ <refpurpose>Creates, deletes and cleans up volatile
+ and temporary files and directories.</refpurpose>
+ </refnamediv>
+
+ <refsynopsisdiv>
+ <cmdsynopsis>
+ <command>systemd-tmpfiles <arg choice="opt" rep="repeat">OPTIONS</arg> <arg choice="opt" rep="repeat">CONFIGURATION FILE</arg></command>
+ </cmdsynopsis>
+ </refsynopsisdiv>
+
+ <refsect1>
+ <title>Description</title>
+
+ <para><command>systemd-tmpfiles</command> creates,
+ deletes and cleans up volatile ad temporary files and
+ directories, based on the configuration from
+ <filename>/etc/tmpfiles.d/</filename>. See
+ <citerefentry><refentrytitle>tmpfiles.d</refentrytitle><manvolnum>5</manvolnum></citerefentry>
+ for more details on these files.</para>
+
+ <para>If invoked with no arguments applies all
+ directives from all configuration files in
+ <filename>/etc/tmpfiles.d/*.conf</filename>. If one or
+ more absolute file names are passed on the command
+ line only the directives in these files are
+ applied.</para>
+ </refsect1>
+
+ <refsect1>
+ <title>Options</title>
+
+ <para>The following options are understood:</para>
+
+ <variablelist>
+
+ <varlistentry>
+ <term><option>--create</option></term>
+ <listitem><para>If this option is passed all
+ files and directories marked with f,
+ F, d, D in the configuration files are
+ created.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>--clean</option></term>
+ <listitem><para>If this option is
+ passed all files and directories with
+ an age parameter configured will be
+ cleaned up.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>--remove</option></term>
+ <listitem><para>If this option is
+ passed all files and directories marked
+ with r, R in the configuration files
+ are removed.</para></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>--prefix=PATH</option></term>
+ <listitem><para>Only apply rules that
+ apply to paths with the specified
+ prefix.</para></listitem>
+ </varlistentry>
+
+
+ <varlistentry>
+ <term><option>--help</option></term>
+
+ <listitem><para>Prints a short help
+ text and exits.</para></listitem>
+ </varlistentry>
+
+ </variablelist>
+
+ <para>It is possible to combine
+ <option>--create</option>, <option>--clean</option>,
+ and <option>--remove</option> in one invocation. For
+ example, during boot the following command line is
+ executed to ensure that all temporary and volatile
+ directores are removed and created according to the
+ configuration file:</para>
+
+ <programlisting>systemctl-tmpfiles --remove --create</programlisting>
+
+ </refsect1>
+
+ <refsect1>
+ <title>Exit status</title>
+
+ <para>On success 0 is returned, a non-zero failure
+ code otherwise.</para>
+ </refsect1>
+
+ <refsect1>
+ <title>See Also</title>
+ <para>
+ <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>tmpfiles.d</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>tmpwatch</refentrytitle><manvolnum>8</manvolnum></citerefentry>
+ </para>
+ </refsect1>
+
+</refentry>
diff --git a/man/tmpfiles.d.xml b/man/tmpfiles.d.xml
index e211d6d..868b57e 100644
--- a/man/tmpfiles.d.xml
+++ b/man/tmpfiles.d.xml
@@ -42,7 +42,8 @@
<refnamediv>
<refname>tmpfiles.d</refname>
- <refpurpose>Configuration for creation, deletion and cleaning of temporary and volatile files</refpurpose>
+ <refpurpose>Configuration for creation, deletion and
+ cleaning of volatile and temporary files</refpurpose>
</refnamediv>
<refsynopsisdiv>
@@ -52,13 +53,14 @@
<refsect1>
<title>Description</title>
- <para><command>systemd</command> uses
+ <para><command>systemd-tmpfiles</command> uses the
+ configuration files in
<filename>/etc/tmpfiles.d/</filename> to describe the
- creation, cleaning and removal of volatile files and
- directories which usually reside in directories such
- as <filename>/var/run</filename> or
- <filename>/tmp</filename>. Each configuration file is
- named in the style of
+ creation, cleaning and removal of volatile and
+ temporary files and directories which usually reside
+ in directories such as <filename>/var/run</filename>
+ or <filename>/tmp</filename>. Each configuration file
+ is named in the style of
<filename>/etc/tmpfiles.d/<program>.conf</filename>.</para>
</refsect1>
@@ -201,7 +203,8 @@ d /var/run/uscreens 0755 root root 10d12h</programlisting>
<refsect1>
<title>See Also</title>
<para>
- <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>
+ <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>systemd-tmpfiles</refentrytitle><manvolnum>8</manvolnum></citerefentry>
</para>
</refsect1>
diff --git a/src/tmpfiles.c b/src/tmpfiles.c
index 36fc916..9b697e4 100644
--- a/src/tmpfiles.c
+++ b/src/tmpfiles.c
@@ -700,13 +700,13 @@ static int scandir_filter(const struct dirent *d) {
static int help(void) {
- printf("%s [OPTIONS...] [CONFIGURATION FILE]\n\n"
- "Create and clean up temporary files and directories.\n\n"
+ printf("%s [OPTIONS...] [CONFIGURATION FILE...]\n\n"
+ "Creates, deletes and cleans up volatile and temporary files and directories.\n\n"
" -h --help Show this help\n"
" --create Create marked files/directories\n"
" --clean Clean up marked directories\n"
" --remove Remove marked files/directories\n"
- " --prefix=PATH Only apply rules that apply to paths\n",
+ " --prefix=PATH Only apply rules that apply to paths with the specified prefix\n",
program_invocation_short_name);
return 0;
commit 74ce487dafff196f657835672aae5ad1eb3a6daf
Author: Lennart Poettering <lennart at poettering.net>
Date: Sun Feb 13 14:04:57 2011 +0100
tmpfiles: move binary to /bin to make it publicly available
diff --git a/Makefile.am b/Makefile.am
index 5370504..56fdfce 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -95,7 +95,8 @@ rootbin_PROGRAMS = \
systemctl \
systemd-notify \
systemd-ask-password \
- systemd-tty-ask-password-agent
+ systemd-tty-ask-password-agent \
+ systemd-tmpfiles
bin_PROGRAMS = \
systemd-cgls
@@ -121,7 +122,6 @@ rootlibexec_PROGRAMS = \
systemd-reply-password \
systemd-readahead-collect \
systemd-readahead-replay \
- systemd-tmpfiles \
systemd-user-sessions \
systemd-fsck \
systemd-quotacheck \
diff --git a/units/systemd-tmpfiles-clean.service.in b/units/systemd-tmpfiles-clean.service.in
index 9d05135..002daf6 100644
--- a/units/systemd-tmpfiles-clean.service.in
+++ b/units/systemd-tmpfiles-clean.service.in
@@ -15,5 +15,5 @@ ConditionPathExists=/etc/tmpfiles.d
[Service]
Type=oneshot
-ExecStart=@rootlibexecdir@/systemd-tmpfiles --clean
+ExecStart=@rootbindir@/systemd-tmpfiles --clean
IOSchedulingClass=idle
diff --git a/units/systemd-tmpfiles-setup.service.in b/units/systemd-tmpfiles-setup.service.in
index d9274ed..b43f6f5 100644
--- a/units/systemd-tmpfiles-setup.service.in
+++ b/units/systemd-tmpfiles-setup.service.in
@@ -16,4 +16,4 @@ ConditionPathExists=/etc/tmpfiles.d
[Service]
Type=oneshot
RemainAfterExit=yes
-ExecStart=@rootlibexecdir@/systemd-tmpfiles --create --remove
+ExecStart=@rootbindir@/systemd-tmpfiles --create --remove
commit fba6e687234660739e5ea1f2fc9c010db893c253
Author: Lennart Poettering <lennart at poettering.net>
Date: Sun Feb 13 14:00:54 2011 +0100
tmpfiles: take names of tmpfiles configuration files on the command line
diff --git a/TODO b/TODO
index 8aac19b..747a669 100644
--- a/TODO
+++ b/TODO
@@ -126,8 +126,6 @@ Features:
* systemctl condrestart should return 0 if service isn't running
-* tmpfiles: allow specification of .conf files on cmdline
-
* allow runtime changing of log level and target
* automatically determine TERM= based on tty name even for /dev/console
diff --git a/src/tmpfiles.c b/src/tmpfiles.c
index d7ca062..36fc916 100644
--- a/src/tmpfiles.c
+++ b/src/tmpfiles.c
@@ -85,6 +85,8 @@ static bool arg_create = false;
static bool arg_clean = false;
static bool arg_remove = false;
+static const char *arg_prefix = NULL;
+
#define MAX_DEPTH 256
static bool needs_glob(int t) {
@@ -538,7 +540,7 @@ static void item_free(Item *i) {
free(i);
}
-static int parse_line(const char *fname, unsigned line, const char *buffer, const char *prefix) {
+static int parse_line(const char *fname, unsigned line, const char *buffer) {
Item *i;
char *mode = NULL, *user = NULL, *group = NULL, *age = NULL;
int r;
@@ -590,7 +592,7 @@ static int parse_line(const char *fname, unsigned line, const char *buffer, cons
path_kill_slashes(i->path);
- if (prefix && !path_startswith(i->path, prefix)) {
+ if (arg_prefix && !path_startswith(i->path, arg_prefix)) {
r = 0;
goto finish;
}
@@ -698,12 +700,13 @@ static int scandir_filter(const struct dirent *d) {
static int help(void) {
- printf("%s [OPTIONS...]\n\n"
- "Create and clean up temporary directories.\n\n"
+ printf("%s [OPTIONS...] [CONFIGURATION FILE]\n\n"
+ "Create and clean up temporary files and directories.\n\n"
" -h --help Show this help\n"
" --create Create marked files/directories\n"
" --clean Clean up marked directories\n"
- " --remove Remove marked files/directories\n",
+ " --remove Remove marked files/directories\n"
+ " --prefix=PATH Only apply rules that apply to paths\n",
program_invocation_short_name);
return 0;
@@ -714,7 +717,8 @@ static int parse_argv(int argc, char *argv[]) {
enum {
ARG_CREATE,
ARG_CLEAN,
- ARG_REMOVE
+ ARG_REMOVE,
+ ARG_PREFIX
};
static const struct option options[] = {
@@ -722,6 +726,7 @@ static int parse_argv(int argc, char *argv[]) {
{ "create", no_argument, NULL, ARG_CREATE },
{ "clean", no_argument, NULL, ARG_CLEAN },
{ "remove", no_argument, NULL, ARG_REMOVE },
+ { "prefix", required_argument, NULL, ARG_PREFIX },
{ NULL, 0, NULL, 0 }
};
@@ -750,6 +755,10 @@ static int parse_argv(int argc, char *argv[]) {
arg_remove = true;
break;
+ case ARG_PREFIX:
+ arg_prefix = optarg;
+ break;
+
case '?':
return -EINVAL;
@@ -760,28 +769,66 @@ static int parse_argv(int argc, char *argv[]) {
}
if (!arg_clean && !arg_create && !arg_remove) {
- help();
+ log_error("You need to specify at leat one of --clean, --create or --remove.");
return -EINVAL;
}
return 1;
}
+static int read_config_file(const char *fn, bool ignore_enoent) {
+ FILE *f;
+ unsigned v = 0;
+ int r = 0;
+
+ assert(fn);
+
+ if (!(f = fopen(fn, "re"))) {
+
+ if (ignore_enoent && errno == ENOENT)
+ return 0;
+
+ log_error("Failed to open %s: %m", fn);
+ return -errno;
+ }
+
+ for (;;) {
+ char line[LINE_MAX], *l;
+ int k;
+
+ if (!(fgets(line, sizeof(line), f)))
+ break;
+
+ v++;
+
+ l = strstrip(line);
+ if (*l == '#' || *l == 0)
+ continue;
+
+ if ((k = parse_line(fn, v, l)) < 0)
+ if (r == 0)
+ r = k;
+ }
+
+ if (ferror(f)) {
+ log_error("Failed to read from file %s: %m", fn);
+ if (r == 0)
+ r = -EIO;
+ }
+
+ fclose(f);
+
+ return r;
+}
+
int main(int argc, char *argv[]) {
- struct dirent **de = NULL;
- int r, n, j;
- const char *prefix = NULL;
+ int r;
Item *i;
Iterator iterator;
if ((r = parse_argv(argc, argv)) <= 0)
return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
- if (optind < argc)
- prefix = argv[optind];
- else
- prefix = "/";
-
log_set_target(LOG_TARGET_AUTO);
log_parse_environment();
log_open();
@@ -797,75 +844,51 @@ int main(int argc, char *argv[]) {
goto finish;
}
- if ((n = scandir("/etc/tmpfiles.d/", &de, scandir_filter, alphasort)) < 0) {
-
- if (errno == ENOENT)
- r = EXIT_SUCCESS;
- else {
- log_error("Failed to enumerate /etc/tmpfiles.d/ files: %m");
- r = EXIT_FAILURE;
- }
-
- goto finish;
- }
-
r = EXIT_SUCCESS;
- for (j = 0; j < n; j++) {
- int k;
- char *fn;
- FILE *f;
- unsigned v;
+ if (optind < argc) {
+ int j;
- k = asprintf(&fn, "/etc/tmpfiles.d/%s", de[j]->d_name);
- free(de[j]);
+ for (j = optind; j < argc; j++)
+ if (read_config_file(argv[j], false) < 0)
+ r = EXIT_FAILURE;
- if (k < 0) {
- log_error("Failed to allocate file name.");
- r = EXIT_FAILURE;
- continue;
- }
+ } else {
+ int n, j;
+ struct dirent **de = NULL;
- if (!(f = fopen(fn, "re"))) {
+ if ((n = scandir("/etc/tmpfiles.d/", &de, scandir_filter, alphasort)) < 0) {
if (errno != ENOENT) {
- log_error("Failed to open %s: %m", fn);
+ log_error("Failed to enumerate /etc/tmpfiles.d/ files: %m");
r = EXIT_FAILURE;
}
- free(fn);
- continue;
+ goto finish;
}
- v = 0;
- for (;;) {
- char line[LINE_MAX], *l;
-
- if (!(fgets(line, sizeof(line), f)))
- break;
+ for (j = 0; j < n; j++) {
+ int k;
+ char *fn;
- v++;
+ k = asprintf(&fn, "/etc/tmpfiles.d/%s", de[j]->d_name);
+ free(de[j]);
- l = strstrip(line);
- if (*l == '#' || *l == 0)
+ if (k < 0) {
+ log_error("Failed to allocate file name.");
+ r = EXIT_FAILURE;
continue;
+ }
- if (parse_line(fn, v, l, prefix) < 0)
+ if (read_config_file(fn, true) < 0)
r = EXIT_FAILURE;
- }
- if (ferror(f)) {
- r = EXIT_FAILURE;
- log_error("Failed to read from file %s: %m", fn);
+ free(fn);
}
- free(fn);
-
- fclose(f);
+ free(de);
}
- free(de);
-
HASHMAP_FOREACH(i, globs, iterator)
if (process_item(i) < 0)
r = EXIT_FAILURE;
More information about the systemd-commits
mailing list