chiark / gitweb /
util: add getusername_malloc(), get_shell(), get_home_dir()
[elogind.git] / src / shared / util.c
index 2aabd8d6346df41de2419754c4b56f56abd71979..a0755efb147593a2046e0feaf386986b047b4664 100644 (file)
@@ -2385,8 +2385,9 @@ int acquire_terminal(
                 bool ignore_tiocstty_eperm,
                 usec_t timeout) {
 
-        int fd = -1, notify = -1, r, wd = -1;
+        int fd = -1, notify = -1, r = 0, wd = -1;
         usec_t ts = 0;
+        struct sigaction sa_old, sa_new;
 
         assert(name);
 
@@ -2434,17 +2435,26 @@ int acquire_terminal(
                 if (fd < 0)
                         return fd;
 
+                /* Temporarily ignore SIGHUP, so that we don't get SIGHUP'ed
+                 * if we already own the tty. */
+                zero(sa_new);
+                sa_new.sa_handler = SIG_IGN;
+                sa_new.sa_flags = SA_RESTART;
+                assert_se(sigaction(SIGHUP, &sa_new, &sa_old) == 0);
+
                 /* First, try to get the tty */
-                r = ioctl(fd, TIOCSCTTY, force);
+                if (ioctl(fd, TIOCSCTTY, force) < 0)
+                        r = -errno;
+
+                assert_se(sigaction(SIGHUP, &sa_old, NULL) == 0);
 
                 /* Sometimes it makes sense to ignore TIOCSCTTY
                  * returning EPERM, i.e. when very likely we already
                  * are have this controlling terminal. */
-                if (r < 0 && errno == EPERM && ignore_tiocstty_eperm)
+                if (r < 0 && r == -EPERM && ignore_tiocstty_eperm)
                         r = 0;
 
-                if (r < 0 && (force || fail || errno != EPERM)) {
-                        r = -errno;
+                if (r < 0 && (force || fail || r != -EPERM)) {
                         goto fail;
                 }
 
@@ -3068,26 +3078,22 @@ bool hostname_is_set(void) {
         return !isempty(u.nodename) && !streq(u.nodename, "(none)");
 }
 
-char* getlogname_malloc(void) {
-        uid_t uid;
+
+static char *lookup_uid(uid_t uid) {
         long bufsize;
         char *buf, *name;
         struct passwd pwbuf, *pw = NULL;
-        struct stat st;
-
-        if (isatty(STDIN_FILENO) && fstat(STDIN_FILENO, &st) >= 0)
-                uid = st.st_uid;
-        else
-                uid = getuid();
 
         /* Shortcut things to avoid NSS lookups */
         if (uid == 0)
                 return strdup("root");
 
-        if ((bufsize = sysconf(_SC_GETPW_R_SIZE_MAX)) <= 0)
+        bufsize = sysconf(_SC_GETPW_R_SIZE_MAX);
+        if (bufsize <= 0)
                 bufsize = 4096;
 
-        if (!(buf = malloc(bufsize)))
+        buf = malloc(bufsize);
+        if (!buf)
                 return NULL;
 
         if (getpwuid_r(uid, &pwbuf, buf, bufsize, &pw) == 0 && pw) {
@@ -3104,6 +3110,28 @@ char* getlogname_malloc(void) {
         return name;
 }
 
+char* getlogname_malloc(void) {
+        uid_t uid;
+        struct stat st;
+
+        if (isatty(STDIN_FILENO) && fstat(STDIN_FILENO, &st) >= 0)
+                uid = st.st_uid;
+        else
+                uid = getuid();
+
+        return lookup_uid(uid);
+}
+
+char *getusername_malloc(void) {
+        const char *e;
+
+        e = getenv("USER");
+        if (e)
+                return strdup(e);
+
+        return lookup_uid(getuid());
+}
+
 int getttyname_malloc(int fd, char **r) {
         char path[PATH_MAX], *c;
         int k;
@@ -5865,3 +5893,97 @@ int make_console_stdio(void) {
 
         return 0;
 }
+
+int get_home_dir(char **_h) {
+        char *h;
+        const char *e;
+        uid_t u;
+        struct passwd *p;
+
+        assert(_h);
+
+        /* Take the user specified one */
+        e = getenv("HOME");
+        if (e) {
+                h = strdup(e);
+                if (!h)
+                        return -ENOMEM;
+
+                *_h = h;
+                return 0;
+        }
+
+        /* Hardcode home directory for root to avoid NSS */
+        u = getuid();
+        if (u == 0) {
+                h = strdup("/root");
+                if (!h)
+                        return -ENOMEM;
+
+                *_h = h;
+                return 0;
+        }
+
+        /* Check the database... */
+        errno = 0;
+        p = getpwuid(u);
+        if (!p)
+                return errno ? -errno : -ENOENT;
+
+        if (!path_is_absolute(p->pw_dir))
+                return -EINVAL;
+
+        h = strdup(p->pw_dir);
+        if (!h)
+                return -ENOMEM;
+
+        *_h = h;
+        return 0;
+}
+
+int get_shell(char **_sh) {
+        char *sh;
+        const char *e;
+        uid_t u;
+        struct passwd *p;
+
+        assert(_sh);
+
+        /* Take the user specified one */
+        e = getenv("SHELL");
+        if (e) {
+                sh = strdup(e);
+                if (!sh)
+                        return -ENOMEM;
+
+                *_sh = sh;
+                return 0;
+        }
+
+        /* Hardcode home directory for root to avoid NSS */
+        u = getuid();
+        if (u == 0) {
+                sh = strdup("/bin/sh");
+                if (!sh)
+                        return -ENOMEM;
+
+                *_sh = sh;
+                return 0;
+        }
+
+        /* Check the database... */
+        errno = 0;
+        p = getpwuid(u);
+        if (!p)
+                return errno ? -errno : -ESRCH;
+
+        if (!path_is_absolute(p->pw_shell))
+                return -EINVAL;
+
+        sh = strdup(p->pw_shell);
+        if (!sh)
+                return -ENOMEM;
+
+        *_sh = sh;
+        return 0;
+}