[systemd-commits] 3 commits - man/systemd.exec.xml man/systemd.unit.xml src/core src/login src/nspawn src/shared src/tmpfiles

Lennart Poettering lennart at kemper.freedesktop.org
Mon Jul 16 03:45:31 PDT 2012


 man/systemd.exec.xml    |    8 +++-
 man/systemd.unit.xml    |   15 ++++++++
 src/core/execute.c      |    2 -
 src/core/mount.c        |    4 ++
 src/core/service.c      |    4 ++
 src/core/socket.c       |    4 ++
 src/core/swap.c         |    4 ++
 src/core/unit.c         |   84 ++++++++++++++++++++++++++++++++++++++++++++++++
 src/core/unit.h         |    2 +
 src/login/loginctl.c    |    8 ++--
 src/login/logind.c      |    2 -
 src/nspawn/nspawn.c     |    2 -
 src/shared/util.c       |   14 +++++++-
 src/shared/util.h       |    2 -
 src/tmpfiles/tmpfiles.c |    2 -
 15 files changed, 145 insertions(+), 12 deletions(-)

New commits:
commit e06c73cc91e02a1a3dffdb0976fef754f1109e74
Author: Lennart Poettering <lennart at poettering.net>
Date:   Mon Jul 16 12:44:42 2012 +0200

    unit: set default working directory to the user's home directory when running in user mode

diff --git a/man/systemd.exec.xml b/man/systemd.exec.xml
index eff75d0..2911786 100644
--- a/man/systemd.exec.xml
+++ b/man/systemd.exec.xml
@@ -89,8 +89,12 @@
 
                                 <listitem><para>Takes an absolute
                                 directory path. Sets the working
-                                directory for executed
-                                processes.</para></listitem>
+                                directory for executed processes. If
+                                not set defaults to the root directory
+                                when systemd is running as a system
+                                instance and the respective user's
+                                home directory if run as
+                                user.</para></listitem>
                         </varlistentry>
 
                         <varlistentry>
diff --git a/src/core/mount.c b/src/core/mount.c
index 15d5f21..a88b255 100644
--- a/src/core/mount.c
+++ b/src/core/mount.c
@@ -631,6 +631,10 @@ static int mount_load(Unit *u) {
                 r = mount_add_extras(m);
                 if (r < 0)
                         return r;
+
+                r = unit_patch_working_directory(UNIT(m), &m->exec_context);
+                if (r < 0)
+                        return r;
         }
 
         return mount_verify(m);
diff --git a/src/core/service.c b/src/core/service.c
index 0a66588..7a7e25f 100644
--- a/src/core/service.c
+++ b/src/core/service.c
@@ -1282,6 +1282,10 @@ static int service_load(Unit *u) {
                 if (UNIT(s)->default_dependencies)
                         if ((r = service_add_default_dependencies(s)) < 0)
                                 return r;
+
+                r = unit_patch_working_directory(UNIT(s), &s->exec_context);
+                if (r < 0)
+                        return r;
         }
 
         return service_verify(s);
diff --git a/src/core/socket.c b/src/core/socket.c
index 3613e84..8153a8e 100644
--- a/src/core/socket.c
+++ b/src/core/socket.c
@@ -372,6 +372,10 @@ static int socket_load(Unit *u) {
                 if (UNIT(s)->default_dependencies)
                         if ((r = socket_add_default_dependencies(s)) < 0)
                                 return r;
+
+                r = unit_patch_working_directory(UNIT(s), &s->exec_context);
+                if (r < 0)
+                        return r;
         }
 
         return socket_verify(s);
diff --git a/src/core/swap.c b/src/core/swap.c
index aeb8bda..ed61ba3 100644
--- a/src/core/swap.c
+++ b/src/core/swap.c
@@ -294,6 +294,10 @@ static int swap_load(Unit *u) {
                 if (UNIT(s)->default_dependencies)
                         if ((r = swap_add_default_dependencies(s)) < 0)
                                 return r;
+
+                r = unit_patch_working_directory(UNIT(s), &s->exec_context);
+                if (r < 0)
+                        return r;
         }
 
         return swap_verify(s);
diff --git a/src/core/unit.c b/src/core/unit.c
index 673af13..7994f70 100644
--- a/src/core/unit.c
+++ b/src/core/unit.c
@@ -2817,6 +2817,19 @@ int unit_add_mount_links(Unit *u) {
         return 0;
 }
 
+int unit_patch_working_directory(Unit *u, ExecContext *c) {
+        assert(u);
+        assert(c);
+
+        if (u->manager->running_as != MANAGER_USER)
+                return 0;
+
+        if (c->working_directory)
+                return 0;
+
+        return get_home_dir(&c->working_directory);
+}
+
 static const char* const unit_active_state_table[_UNIT_ACTIVE_STATE_MAX] = {
         [UNIT_ACTIVE] = "active",
         [UNIT_RELOADING] = "reloading",
diff --git a/src/core/unit.h b/src/core/unit.h
index 45849a4..2483e4e 100644
--- a/src/core/unit.h
+++ b/src/core/unit.h
@@ -537,6 +537,8 @@ void unit_ref_unset(UnitRef *ref);
 int unit_add_one_mount_link(Unit *u, Mount *m);
 int unit_add_mount_links(Unit *u);
 
+int unit_patch_working_directory(Unit *u, ExecContext *c);
+
 const char *unit_active_state_to_string(UnitActiveState i);
 UnitActiveState unit_active_state_from_string(const char *s);
 

commit d05c5031ad4c528fe6bbfed289519edb9f13180a
Author: Lennart Poettering <lennart at poettering.net>
Date:   Mon Jul 16 12:34:54 2012 +0200

    unit: introduce %s specifier for the user shell

diff --git a/man/systemd.unit.xml b/man/systemd.unit.xml
index 3236bfa..4a2e9c3 100644
--- a/man/systemd.unit.xml
+++ b/man/systemd.unit.xml
@@ -268,6 +268,11 @@
                         <entry>User home directory</entry>
                         <entry>This is the home directory of the configured user of the unit, or (if none is set) the user running the systemd instance.</entry>
                       </row>
+                      <row>
+                        <entry><literal>%s</literal></entry>
+                        <entry>User shell</entry>
+                        <entry>This is the shell of the configured user of the unit, or (if none is set) the user running the systemd instance.</entry>
+                      </row>
                     </tbody>
                   </tgroup>
                 </table>
diff --git a/src/core/execute.c b/src/core/execute.c
index c0e8f9e..daba1a3 100644
--- a/src/core/execute.c
+++ b/src/core/execute.c
@@ -1182,7 +1182,7 @@ int exec_spawn(ExecCommand *command,
 
                 if (context->user) {
                         username = context->user;
-                        err = get_user_creds(&username, &uid, &gid, &home);
+                        err = get_user_creds(&username, &uid, &gid, &home, NULL);
                         if (err < 0) {
                                 r = EXIT_USER;
                                 goto fail_child;
diff --git a/src/core/unit.c b/src/core/unit.c
index ed519b3..673af13 100644
--- a/src/core/unit.c
+++ b/src/core/unit.c
@@ -2232,7 +2232,7 @@ static char *specifier_user_name(char specifier, void *data, void *userdata) {
 
         /* fish username from passwd */
         username = s->exec_context.user;
-        r = get_user_creds(&username, NULL, NULL, NULL);
+        r = get_user_creds(&username, NULL, NULL, NULL, NULL);
         if (r < 0)
                 return NULL;
 
@@ -2256,13 +2256,37 @@ static char *specifier_user_home(char specifier, void *data, void *userdata) {
         }
 
         username = s->exec_context.user;
-        r = get_user_creds(&username, NULL, NULL, &home);
+        r = get_user_creds(&username, NULL, NULL, &home, NULL);
         if (r < 0)
                return NULL;
 
         return strdup(home);
 }
 
+static char *specifier_user_shell(char specifier, void *data, void *userdata) {
+        Service *s = userdata;
+        int r;
+        const char *username, *shell;
+
+        /* return HOME if set, otherwise from passwd */
+        if (!s->exec_context.user) {
+                char *sh;
+
+                r = get_shell(&sh);
+                if (r < 0)
+                        return strdup("/bin/sh");
+
+                return sh;
+        }
+
+        username = s->exec_context.user;
+        r = get_user_creds(&username, NULL, NULL, NULL, &shell);
+        if (r < 0)
+                return strdup("/bin/sh");
+
+        return strdup(shell);
+}
+
 char *unit_name_printf(Unit *u, const char* format) {
 
         /*
@@ -2316,6 +2340,7 @@ char *unit_full_printf(Unit *u, const char *format) {
                 { 't', specifier_runtime,             NULL },
                 { 'u', specifier_user_name,           NULL },
                 { 'h', specifier_user_home,           NULL },
+                { 's', specifier_user_shell,          NULL },
                 { 0, NULL, NULL }
         };
 
diff --git a/src/login/loginctl.c b/src/login/loginctl.c
index a838a54..7b751e7 100644
--- a/src/login/loginctl.c
+++ b/src/login/loginctl.c
@@ -1089,7 +1089,7 @@ static int show(DBusConnection *bus, char **args, unsigned n) {
                         uid_t uid;
                         uint32_t u;
 
-                        ret = get_user_creds((const char**) (args+i), &uid, NULL, NULL);
+                        ret = get_user_creds((const char**) (args+i), &uid, NULL, NULL, NULL);
                         if (ret < 0) {
                                 log_error("User %s unknown.", args[i]);
                                 goto finish;
@@ -1320,7 +1320,7 @@ static int enable_linger(DBusConnection *bus, char **args, unsigned n) {
                         goto finish;
                 }
 
-                ret = get_user_creds((const char**) (args+i), &uid, NULL, NULL);
+                ret = get_user_creds((const char**) (args+i), &uid, NULL, NULL, NULL);
                 if (ret < 0) {
                         log_error("Failed to resolve user %s: %s", args[i], strerror(-ret));
                         goto finish;
@@ -1387,7 +1387,7 @@ static int terminate_user(DBusConnection *bus, char **args, unsigned n) {
                         goto finish;
                 }
 
-                ret = get_user_creds((const char**) (args+i), &uid, NULL, NULL);
+                ret = get_user_creds((const char**) (args+i), &uid, NULL, NULL, NULL);
                 if (ret < 0) {
                         log_error("Failed to look up user %s: %s", args[i], strerror(-ret));
                         goto finish;
@@ -1455,7 +1455,7 @@ static int kill_user(DBusConnection *bus, char **args, unsigned n) {
                         goto finish;
                 }
 
-                ret = get_user_creds((const char**) (args+i), &uid, NULL, NULL);
+                ret = get_user_creds((const char**) (args+i), &uid, NULL, NULL, NULL);
                 if (ret < 0) {
                         log_error("Failed to look up user %s: %s", args[i], strerror(-ret));
                         goto finish;
diff --git a/src/login/logind.c b/src/login/logind.c
index 1eb745a..0775583 100644
--- a/src/login/logind.c
+++ b/src/login/logind.c
@@ -279,7 +279,7 @@ int manager_add_user_by_name(Manager *m, const char *name, User **_user) {
         assert(m);
         assert(name);
 
-        r = get_user_creds(&name, &uid, &gid, NULL);
+        r = get_user_creds(&name, &uid, &gid, NULL, NULL);
         if (r < 0)
                 return r;
 
diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c
index ffd8fd4..2879db1 100644
--- a/src/nspawn/nspawn.c
+++ b/src/nspawn/nspawn.c
@@ -1059,7 +1059,7 @@ int main(int argc, char *argv[]) {
 
                 if (arg_user) {
 
-                        if (get_user_creds((const char**)&arg_user, &uid, &gid, &home) < 0) {
+                        if (get_user_creds((const char**)&arg_user, &uid, &gid, &home, NULL) < 0) {
                                 log_error("get_user_creds() failed: %m");
                                 goto child_fail;
                         }
diff --git a/src/shared/util.c b/src/shared/util.c
index a0755ef..43ec62e 100644
--- a/src/shared/util.c
+++ b/src/shared/util.c
@@ -4905,7 +4905,12 @@ int socket_from_display(const char *display, char **path) {
         return 0;
 }
 
-int get_user_creds(const char **username, uid_t *uid, gid_t *gid, const char **home) {
+int get_user_creds(
+                const char **username,
+                uid_t *uid, gid_t *gid,
+                const char **home,
+                const char **shell) {
+
         struct passwd *p;
         uid_t u;
 
@@ -4926,6 +4931,10 @@ int get_user_creds(const char **username, uid_t *uid, gid_t *gid, const char **h
 
                 if (home)
                         *home = "/root";
+
+                if (shell)
+                        *shell = "/bin/sh";
+
                 return 0;
         }
 
@@ -4957,6 +4966,9 @@ int get_user_creds(const char **username, uid_t *uid, gid_t *gid, const char **h
         if (home)
                 *home = p->pw_dir;
 
+        if (shell)
+                *shell = p->pw_shell;
+
         return 0;
 }
 
diff --git a/src/shared/util.h b/src/shared/util.h
index d3546ba..3915904 100644
--- a/src/shared/util.h
+++ b/src/shared/util.h
@@ -441,7 +441,7 @@ int fchmod_umask(int fd, mode_t mode);
 bool display_is_local(const char *display);
 int socket_from_display(const char *display, char **path);
 
-int get_user_creds(const char **username, uid_t *uid, gid_t *gid, const char **home);
+int get_user_creds(const char **username, uid_t *uid, gid_t *gid, const char **home, const char **shell);
 int get_group_creds(const char **groupname, gid_t *gid);
 
 int in_group(const char *name);
diff --git a/src/tmpfiles/tmpfiles.c b/src/tmpfiles/tmpfiles.c
index 3b52b98..7a453dc 100644
--- a/src/tmpfiles/tmpfiles.c
+++ b/src/tmpfiles/tmpfiles.c
@@ -1076,7 +1076,7 @@ static int parse_line(const char *fname, unsigned line, const char *buffer) {
         if (user && !streq(user, "-")) {
                 const char *u = user;
 
-                r = get_user_creds(&u, &i->uid, NULL, NULL);
+                r = get_user_creds(&u, &i->uid, NULL, NULL, NULL);
                 if (r < 0) {
                         log_error("[%s:%u] Unknown user '%s'.", fname, line, user);
                         goto finish;

commit b2896c905bef7be7ed9a760d9d61aa6ad0f614a3
Author: Auke Kok <auke-jan.h.kok at intel.com>
Date:   Fri Jul 13 22:28:43 2012 -0700

    unit: printf specifiers %u and %h: $USER and $HOME.
    
    These printf specifiers allow us to refer to $HOME and $USER
    in unit files. These are particularly helpful in instanced
    units that have "User=" set, and in systemd --user domains.
    
    The specifiers will return the pw_name and pw_dir fields
    if the unit file has a User= field.
    
    If the unit file does not have a User= field, the value
    substituted is either $USER or $HOME from the environment,
    or, if unset, the values from pw_name or pw_dir.
    
    This patch is somewhat after Ran Benita's original patch,
    which didn't get merged. I've split up the 2 specifiers
    and extended them to do what is logically expected from
    these specifiers.
    
    Note that expansion is done at `start` time, not after
    the units are parsed. Using `systemctl show` will just
    show the specifiers.

diff --git a/man/systemd.unit.xml b/man/systemd.unit.xml
index 3fd76f3..3236bfa 100644
--- a/man/systemd.unit.xml
+++ b/man/systemd.unit.xml
@@ -258,6 +258,16 @@
                         <entry>Runtime socket dir</entry>
                         <entry>This is either /run (for the system manager) or $XDG_RUNTIME_DIR (for user managers).</entry>
                       </row>
+                      <row>
+                        <entry><literal>%u</literal></entry>
+                        <entry>User name</entry>
+                        <entry>This is the name of the configured user of the unit, or (if none is set) the user running the systemd instance.</entry>
+                      </row>
+                      <row>
+                        <entry><literal>%h</literal></entry>
+                        <entry>User home directory</entry>
+                        <entry>This is the home directory of the configured user of the unit, or (if none is set) the user running the systemd instance.</entry>
+                      </row>
                     </tbody>
                   </tgroup>
                 </table>
diff --git a/src/core/unit.c b/src/core/unit.c
index 6914ccd..ed519b3 100644
--- a/src/core/unit.c
+++ b/src/core/unit.c
@@ -2221,6 +2221,48 @@ static char *specifier_runtime(char specifier, void *data, void *userdata) {
         return strdup("/run");
 }
 
+static char *specifier_user_name(char specifier, void *data, void *userdata) {
+        Service *s = userdata;
+        int r;
+        const char *username;
+
+        /* get USER env from our own env if set */
+        if (!s->exec_context.user)
+                return getusername_malloc();
+
+        /* fish username from passwd */
+        username = s->exec_context.user;
+        r = get_user_creds(&username, NULL, NULL, NULL);
+        if (r < 0)
+                return NULL;
+
+        return strdup(username);
+}
+
+static char *specifier_user_home(char specifier, void *data, void *userdata) {
+        Service *s = userdata;
+        int r;
+        const char *username, *home;
+
+        /* return HOME if set, otherwise from passwd */
+        if (!s->exec_context.user) {
+                char *h;
+
+                r = get_home_dir(&h);
+                if (r < 0)
+                        return NULL;
+
+                return h;
+        }
+
+        username = s->exec_context.user;
+        r = get_user_creds(&username, NULL, NULL, &home);
+        if (r < 0)
+               return NULL;
+
+        return strdup(home);
+}
+
 char *unit_name_printf(Unit *u, const char* format) {
 
         /*
@@ -2256,6 +2298,8 @@ char *unit_full_printf(Unit *u, const char *format) {
          * %r root cgroup path of this systemd instance (e.g. "/user/lennart/shared/systemd-4711")
          * %R parent of root cgroup path (e.g. "/usr/lennart/shared")
          * %t the runtime directory to place sockets in (e.g. "/run" or $XDG_RUNTIME_DIR)
+         * %u the username of the configured User or running user
+         * %h the homedir of the configured User or running user
          */
 
         const Specifier table[] = {
@@ -2270,6 +2314,8 @@ char *unit_full_printf(Unit *u, const char *format) {
                 { 'r', specifier_cgroup_root,         NULL },
                 { 'R', specifier_cgroup_root,         NULL },
                 { 't', specifier_runtime,             NULL },
+                { 'u', specifier_user_name,           NULL },
+                { 'h', specifier_user_home,           NULL },
                 { 0, NULL, NULL }
         };
 



More information about the systemd-commits mailing list