chiark / gitweb /
sd-login: build test code again
[elogind.git] / src / util.c
index 2d4f2291932963fdfade7286741efe0d6d49deee..cbfac6ec3b3b22c1bebfa0ba6406497d14465d10 100644 (file)
@@ -54,6 +54,7 @@
 #include <sys/time.h>
 #include <linux/rtc.h>
 #include <glob.h>
+#include <grp.h>
 
 #include "macro.h"
 #include "util.h"
@@ -5262,28 +5263,31 @@ 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) {
         struct passwd *p;
-        unsigned long lu;
+        uid_t u;
 
         assert(username);
         assert(*username);
-        assert(uid);
-        assert(gid);
-        assert(home);
 
         /* We enforce some special rules for uid=0: in order to avoid
          * NSS lookups for root we hardcode its data. */
 
         if (streq(*username, "root") || streq(*username, "0")) {
                 *username = "root";
-                *uid = 0;
-                *gid = 0;
-                *home = "/root";
+
+                if (uid)
+                        *uid = 0;
+
+                if (gid)
+                        *gid = 0;
+
+                if (home)
+                        *home = "/root";
                 return 0;
         }
 
-        if (safe_atolu(*username, &lu) >= 0) {
+        if (parse_uid(*username, &u) >= 0) {
                 errno = 0;
-                p = getpwuid((uid_t) lu);
+                p = getpwuid(u);
 
                 /* If there are multiple users with the same id, make
                  * sure to leave $USER to the configured value instead
@@ -5300,9 +5304,53 @@ int get_user_creds(const char **username, uid_t *uid, gid_t *gid, const char **h
         if (!p)
                 return errno != 0 ? -errno : -ESRCH;
 
-        *uid = p->pw_uid;
-        *gid = p->pw_gid;
-        *home = p->pw_dir;
+        if (uid)
+                *uid = p->pw_uid;
+
+        if (gid)
+                *gid = p->pw_gid;
+
+        if (home)
+                *home = p->pw_dir;
+
+        return 0;
+}
+
+int get_group_creds(const char **groupname, gid_t *gid) {
+        struct group *g;
+        gid_t id;
+
+        assert(groupname);
+
+        /* We enforce some special rules for gid=0: in order to avoid
+         * NSS lookups for root we hardcode its data. */
+
+        if (streq(*groupname, "root") || streq(*groupname, "0")) {
+                *groupname = "root";
+
+                if (gid)
+                        *gid = 0;
+
+                return 0;
+        }
+
+        if (parse_gid(*groupname, &id) >= 0) {
+                errno = 0;
+                g = getgrgid(id);
+
+                if (g)
+                        *groupname = g->gr_name;
+        } else {
+                errno = 0;
+                g = getgrnam(*groupname);
+        }
+
+        if (!g)
+                return errno != 0 ? -errno : -ESRCH;
+
+        if (gid)
+                *gid = g->gr_gid;
+
         return 0;
 }
 
@@ -5384,7 +5432,10 @@ int get_files_in_directory(const char *path, char ***list) {
         char **l = NULL;
 
         assert(path);
-        assert(list);
+
+        /* Returns all files in a directory in *list, and the number
+         * of files as return value. If list is NULL returns only the
+         * number */
 
         d = opendir(path);
         for (;;) {
@@ -5405,37 +5456,41 @@ int get_files_in_directory(const char *path, char ***list) {
                 if (!dirent_is_file(de))
                         continue;
 
-                if ((unsigned) r >= n) {
-                        char **t;
+                if (list) {
+                        if ((unsigned) r >= n) {
+                                char **t;
 
-                        n = MAX(16, 2*r);
-                        t = realloc(l, sizeof(char*) * n);
-                        if (!t) {
-                                r = -ENOMEM;
-                                goto finish;
-                        }
+                                n = MAX(16, 2*r);
+                                t = realloc(l, sizeof(char*) * n);
+                                if (!t) {
+                                        r = -ENOMEM;
+                                        goto finish;
+                                }
 
-                        l = t;
-                }
+                                l = t;
+                        }
 
-                assert((unsigned) r < n);
+                        assert((unsigned) r < n);
 
-                l[r] = strdup(de->d_name);
-                if (!l[r]) {
-                        r = -ENOMEM;
-                        goto finish;
-                }
+                        l[r] = strdup(de->d_name);
+                        if (!l[r]) {
+                                r = -ENOMEM;
+                                goto finish;
+                        }
 
-                l[++r] = NULL;
+                        l[++r] = NULL;
+                } else
+                        r++;
         }
 
 finish:
         if (d)
                 closedir(d);
 
-        if (r >= 0)
-                *list = l;
-        else
+        if (r >= 0) {
+                if (list)
+                        *list = l;
+        } else
                 strv_free(l);
 
         return r;