chiark / gitweb /
Merge pull request #7 from elogind/dev_v228-r1
[elogind.git] / src / libelogind / sd-login / sd-login.c
index 7d6a4b78cfeaab2ade669b6080ecd92d0122583f..ac22fa3454ce57a5fc757c5726c3309752d67acd 100644 (file)
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include <unistd.h>
-#include <string.h>
 #include <errno.h>
-#include <sys/inotify.h>
 #include <poll.h>
+#include <string.h>
+#include <sys/inotify.h>
+#include <unistd.h>
 
-#include "util.h"
+#include "sd-login.h"
+
+#include "alloc-util.h"
 #include "cgroup-util.h"
-#include "macro.h"
-#include "strv.h"
+#include "dirent-util.h"
+#include "escape.h"
+#include "fd-util.h"
 #include "fileio.h"
-#include "login-util.h"
 #include "formats-util.h"
+#include "fs-util.h"
 #include "hostname-util.h"
-#include "sd-login.h"
+#include "io-util.h"
+#include "login-util.h"
+#include "macro.h"
+#include "parse-util.h"
+#include "path-util.h"
+#include "socket-util.h"
+#include "string-util.h"
+#include "strv.h"
+#include "user-util.h"
+#include "util.h"
+
+/* Error codes:
+ *
+ *    invalid input parameters                → -EINVAL
+ *    invalid fd                              → -EBADF
+ *    process does not exist                  → -ESRCH
+ *    cgroup does not exist                   → -ENOENT
+ *    machine, session does not exist         → -ENXIO
+ *    requested metadata on object is missing → -ENODATA
+ */
 
 _public_ int sd_pid_get_session(pid_t pid, char **session) {
 
@@ -48,7 +70,11 @@ _public_ int sd_pid_get_unit(pid_t pid, char **unit) {
         assert_return(pid >= 0, -EINVAL);
         assert_return(unit, -EINVAL);
 
+#if 0 /// elogind does not support systemd units
         return cg_pid_get_unit(pid, unit);
+#else
+        return -ESRCH;
+#endif // 0
 }
 
 _public_ int sd_pid_get_user_unit(pid_t pid, char **unit) {
@@ -56,7 +82,11 @@ _public_ int sd_pid_get_user_unit(pid_t pid, char **unit) {
         assert_return(pid >= 0, -EINVAL);
         assert_return(unit, -EINVAL);
 
+#if 0 /// elogind does not support systemd units
         return cg_pid_get_user_unit(pid, unit);
+#else
+        return -ESRCH;
+#endif // 0
 }
 
 _public_ int sd_pid_get_machine_name(pid_t pid, char **name) {
@@ -64,7 +94,11 @@ _public_ int sd_pid_get_machine_name(pid_t pid, char **name) {
         assert_return(pid >= 0, -EINVAL);
         assert_return(name, -EINVAL);
 
+#if 0 /// elogind does not support systemd units
         return cg_pid_get_machine_name(pid, name);
+#else
+        return -ESRCH;
+#endif // 0
 }
 
 _public_ int sd_pid_get_slice(pid_t pid, char **slice) {
@@ -72,7 +106,11 @@ _public_ int sd_pid_get_slice(pid_t pid, char **slice) {
         assert_return(pid >= 0, -EINVAL);
         assert_return(slice, -EINVAL);
 
+#if 0 /// elogind does not support systemd slices
         return cg_pid_get_slice(pid, slice);
+#else
+        return -ESRCH;
+#endif // 0
 }
 
 _public_ int sd_pid_get_user_slice(pid_t pid, char **slice) {
@@ -80,7 +118,11 @@ _public_ int sd_pid_get_user_slice(pid_t pid, char **slice) {
         assert_return(pid >= 0, -EINVAL);
         assert_return(slice, -EINVAL);
 
+#if 0 /// elogind does not support systemd slices
         return cg_pid_get_user_slice(pid, slice);
+#else
+        return -ESRCH;
+#endif // 0
 }
 
 _public_ int sd_pid_get_owner_uid(pid_t pid, uid_t *uid) {
@@ -88,7 +130,37 @@ _public_ int sd_pid_get_owner_uid(pid_t pid, uid_t *uid) {
         assert_return(pid >= 0, -EINVAL);
         assert_return(uid, -EINVAL);
 
+#if 0 /// elogind does not support systemd slices
         return cg_pid_get_owner_uid(pid, uid);
+#else
+        return -ESRCH;
+#endif // 0
+}
+
+_public_ int sd_pid_get_cgroup(pid_t pid, char **cgroup) {
+        char *c;
+        int r;
+
+        assert_return(pid >= 0, -EINVAL);
+        assert_return(cgroup, -EINVAL);
+
+        r = cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, pid, &c);
+        if (r < 0)
+                return r;
+
+        /* The internal APIs return the empty string for the root
+         * cgroup, let's return the "/" in the public APIs instead, as
+         * that's easier and less ambigious for people to grok. */
+        if (isempty(c)) {
+                free(c);
+                c = strdup("/");
+                if (!c)
+                        return -ENOMEM;
+
+        }
+
+        *cgroup = c;
+        return 0;
 }
 
 _public_ int sd_peer_get_session(int fd, char **session) {
@@ -102,7 +174,11 @@ _public_ int sd_peer_get_session(int fd, char **session) {
         if (r < 0)
                 return r;
 
+#if 0 /// elogind does not support systemd scopes
         return cg_pid_get_session(ucred.pid, session);
+#else
+        return -ESRCH;
+#endif // 0
 }
 
 _public_ int sd_peer_get_owner_uid(int fd, uid_t *uid) {
@@ -116,7 +192,11 @@ _public_ int sd_peer_get_owner_uid(int fd, uid_t *uid) {
         if (r < 0)
                 return r;
 
+#if 0 /// elogind does not support systemd units
         return cg_pid_get_owner_uid(ucred.pid, uid);
+#else
+        return -ESRCH;
+#endif // 0
 }
 
 _public_ int sd_peer_get_unit(int fd, char **unit) {
@@ -130,7 +210,11 @@ _public_ int sd_peer_get_unit(int fd, char **unit) {
         if (r < 0)
                 return r;
 
+#if 0 /// elogind does not support systemd units
         return cg_pid_get_unit(ucred.pid, unit);
+#else
+        return -ESRCH;
+#endif // 0
 }
 
 _public_ int sd_peer_get_user_unit(int fd, char **unit) {
@@ -144,7 +228,11 @@ _public_ int sd_peer_get_user_unit(int fd, char **unit) {
         if (r < 0)
                 return r;
 
+#if 0 /// elogind does not support systemd units
         return cg_pid_get_user_unit(ucred.pid, unit);
+#else
+        return -ESRCH;
+#endif // 0
 }
 
 _public_ int sd_peer_get_machine_name(int fd, char **machine) {
@@ -158,7 +246,11 @@ _public_ int sd_peer_get_machine_name(int fd, char **machine) {
         if (r < 0)
                 return r;
 
+#if 0 /// elogind does not support systemd units
         return cg_pid_get_machine_name(ucred.pid, machine);
+#else
+        return -ESRCH;
+#endif // 0
 }
 
 _public_ int sd_peer_get_slice(int fd, char **slice) {
@@ -172,7 +264,11 @@ _public_ int sd_peer_get_slice(int fd, char **slice) {
         if (r < 0)
                 return r;
 
+#if 0 /// elogind does not support systemd slices
         return cg_pid_get_slice(ucred.pid, slice);
+#else
+        return -ESRCH;
+#endif // 0
 }
 
 _public_ int sd_peer_get_user_slice(int fd, char **slice) {
@@ -186,10 +282,30 @@ _public_ int sd_peer_get_user_slice(int fd, char **slice) {
         if (r < 0)
                 return r;
 
+#if 0 /// elogind does not support systemd slices
         return cg_pid_get_user_slice(ucred.pid, slice);
+#else
+        return -ESRCH;
+#endif // 0
+}
+
+_public_ int sd_peer_get_cgroup(int fd, char **cgroup) {
+        struct ucred ucred;
+        int r;
+
+        assert_return(fd >= 0, -EBADF);
+        assert_return(cgroup, -EINVAL);
+
+        r = getpeercred(fd, &ucred);
+        if (r < 0)
+                return r;
+
+        return sd_pid_get_cgroup(ucred.pid, cgroup);
 }
 
 static int file_of_uid(uid_t uid, char **p) {
+
+        assert_return(uid_is_valid(uid), -EINVAL);
         assert(p);
 
         if (asprintf(p, "/run/systemd/users/" UID_FMT, uid) < 0)
@@ -216,11 +332,15 @@ _public_ int sd_uid_get_state(uid_t uid, char**state) {
                 if (!s)
                         return -ENOMEM;
 
-        } else if (r < 0) {
+        }
+        if (r < 0) {
                 free(s);
                 return r;
-        } else if (!s)
+        }
+        if (isempty(s)) {
+                free(s);
                 return -EIO;
+        }
 
         *state = s;
         return 0;
@@ -238,12 +358,11 @@ _public_ int sd_uid_get_display(uid_t uid, char **session) {
 
         r = parse_env_file(p, NEWLINE, "DISPLAY", &s, NULL);
         if (r == -ENOENT)
-                return -ENXIO;
+                return -ENODATA;
         if (r < 0)
                 return r;
-
         if (isempty(s))
-                return -ENXIO;
+                return -ENODATA;
 
         *session = s;
         s = NULL;
@@ -251,35 +370,63 @@ _public_ int sd_uid_get_display(uid_t uid, char **session) {
         return 0;
 }
 
-_public_ int sd_uid_is_on_seat(uid_t uid, int require_active, const char *seat) {
-        _cleanup_free_ char *t = NULL, *s = NULL, *p = NULL;
-        size_t l;
+static int file_of_seat(const char *seat, char **_p) {
+        char *p;
         int r;
-        const char *word, *variable, *state;
 
-        assert_return(seat, -EINVAL);
+        assert(_p);
 
-        variable = require_active ? "ACTIVE_UID" : "UIDS";
+        if (seat) {
+                if (!filename_is_valid(seat))
+                        return -EINVAL;
 
         p = strappend("/run/systemd/seats/", seat);
+        } else {
+                _cleanup_free_ char *buf = NULL;
+
+                r = sd_session_get_seat(NULL, &buf);
+                if (r < 0)
+                        return r;
+
+                p = strappend("/run/systemd/seats/", buf);
+        }
+
         if (!p)
                 return -ENOMEM;
 
-        r = parse_env_file(p, NEWLINE, variable, &s, NULL);
+        *_p = p;
+        p = NULL;
+        return 0;
+}
 
+_public_ int sd_uid_is_on_seat(uid_t uid, int require_active, const char *seat) {
+        _cleanup_free_ char *t = NULL, *s = NULL, *p = NULL;
+        size_t l;
+        int r;
+        const char *word, *variable, *state;
+
+        assert_return(uid_is_valid(uid), -EINVAL);
+
+        r = file_of_seat(seat, &p);
         if (r < 0)
                 return r;
 
-        if (!s)
-                return -EIO;
+        variable = require_active ? "ACTIVE_UID" : "UIDS";
+
+        r = parse_env_file(p, NEWLINE, variable, &s, NULL);
+        if (r == -ENOENT)
+                return 0;
+        if (r < 0)
+                return r;
+        if (isempty(s))
+                return 0;
 
         if (asprintf(&t, UID_FMT, uid) < 0)
                 return -ENOMEM;
 
-        FOREACH_WORD(word, l, s, state) {
+        FOREACH_WORD(word, l, s, state)
                 if (strneq(t, word, l))
                         return 1;
-        }
 
         return 0;
 }
@@ -289,31 +436,22 @@ static int uid_get_array(uid_t uid, const char *variable, char ***array) {
         char **a;
         int r;
 
+        assert(variable);
+
         r = file_of_uid(uid, &p);
         if (r < 0)
                 return r;
 
-        r = parse_env_file(p, NEWLINE,
-                           variable, &s,
-                           NULL);
-        if (r < 0) {
-                if (r == -ENOENT) {
+        r = parse_env_file(p, NEWLINE, variable, &s, NULL);
+        if (r == -ENOENT || (r >= 0 && isempty(s))) {
                         if (array)
                                 *array = NULL;
                         return 0;
                 }
-
+        if (r < 0)
                 return r;
-        }
-
-        if (!s) {
-                if (array)
-                        *array = NULL;
-                return 0;
-        }
 
         a = strv_split(s, " ");
-
         if (!a)
                 return -ENOMEM;
 
@@ -375,37 +513,39 @@ static int file_of_session(const char *session, char **_p) {
 }
 
 _public_ int sd_session_is_active(const char *session) {
-        int r;
         _cleanup_free_ char *p = NULL, *s = NULL;
+        int r;
 
         r = file_of_session(session, &p);
         if (r < 0)
                 return r;
 
         r = parse_env_file(p, NEWLINE, "ACTIVE", &s, NULL);
+        if (r == -ENOENT)
+                return -ENXIO;
         if (r < 0)
                 return r;
-
-        if (!s)
+        if (isempty(s))
                 return -EIO;
 
         return parse_boolean(s);
 }
 
 _public_ int sd_session_is_remote(const char *session) {
-        int r;
         _cleanup_free_ char *p = NULL, *s = NULL;
+        int r;
 
         r = file_of_session(session, &p);
         if (r < 0)
                 return r;
 
         r = parse_env_file(p, NEWLINE, "REMOTE", &s, NULL);
+        if (r == -ENOENT)
+                return -ENXIO;
         if (r < 0)
                 return r;
-
-        if (!s)
-                return -EIO;
+        if (isempty(s))
+                return -ENODATA;
 
         return parse_boolean(s);
 }
@@ -421,9 +561,11 @@ _public_ int sd_session_get_state(const char *session, char **state) {
                 return r;
 
         r = parse_env_file(p, NEWLINE, "STATE", &s, NULL);
+        if (r == -ENOENT)
+                return -ENXIO;
         if (r < 0)
                 return r;
-        else if (!s)
+        if (isempty(s))
                 return -EIO;
 
         *state = s;
@@ -443,10 +585,11 @@ _public_ int sd_session_get_uid(const char *session, uid_t *uid) {
                 return r;
 
         r = parse_env_file(p, NEWLINE, "UID", &s, NULL);
+        if (r == -ENOENT)
+                return -ENXIO;
         if (r < 0)
                 return r;
-
-        if (!s)
+        if (isempty(s))
                 return -EIO;
 
         return parse_uid(s, uid);
@@ -457,17 +600,19 @@ static int session_get_string(const char *session, const char *field, char **val
         int r;
 
         assert_return(value, -EINVAL);
+        assert(field);
 
         r = file_of_session(session, &p);
         if (r < 0)
                 return r;
 
         r = parse_env_file(p, NEWLINE, field, &s, NULL);
+        if (r == -ENOENT)
+                return -ENXIO;
         if (r < 0)
                 return r;
-
         if (isempty(s))
-                return -ENXIO;
+                return -ENODATA;
 
         *value = s;
         s = NULL;
@@ -487,6 +632,8 @@ _public_ int sd_session_get_vt(const char *session, unsigned *vtnr) {
         unsigned u;
         int r;
 
+        assert_return(vtnr, -EINVAL);
+
         r = session_get_string(session, "VTNR", &vtnr_string);
         if (r < 0)
                 return r;
@@ -542,32 +689,6 @@ _public_ int sd_session_get_remote_host(const char *session, char **remote_host)
         return session_get_string(session, "REMOTE_HOST", remote_host);
 }
 
-static int file_of_seat(const char *seat, char **_p) {
-        char *p;
-        int r;
-
-        assert(_p);
-
-        if (seat)
-                p = strappend("/run/systemd/seats/", seat);
-        else {
-                _cleanup_free_ char *buf = NULL;
-
-                r = sd_session_get_seat(NULL, &buf);
-                if (r < 0)
-                        return r;
-
-                p = strappend("/run/systemd/seats/", buf);
-        }
-
-        if (!p)
-                return -ENOMEM;
-
-        *_p = p;
-        p = NULL;
-        return 0;
-}
-
 _public_ int sd_seat_get_active(const char *seat, char **session, uid_t *uid) {
         _cleanup_free_ char *p = NULL, *s = NULL, *t = NULL;
         int r;
@@ -582,14 +703,16 @@ _public_ int sd_seat_get_active(const char *seat, char **session, uid_t *uid) {
                            "ACTIVE", &s,
                            "ACTIVE_UID", &t,
                            NULL);
+        if (r == -ENOENT)
+                return -ENXIO;
         if (r < 0)
                 return r;
 
         if (session && !s)
-                return -ENOENT;
+                return -ENODATA;
 
         if (uid && !t)
-                return -ENOENT;
+                return -ENODATA;
 
         if (uid && t) {
                 r = parse_uid(t, uid);
@@ -620,7 +743,8 @@ _public_ int sd_seat_get_sessions(const char *seat, char ***sessions, uid_t **ui
                            "SESSIONS", &s,
                            "ACTIVE_SESSIONS", &t,
                            NULL);
-
+        if (r == -ENOENT)
+                return -ENXIO;
         if (r < 0)
                 return r;
 
@@ -652,7 +776,6 @@ _public_ int sd_seat_get_sessions(const char *seat, char ***sessions, uid_t **ui
                                         return -ENOMEM;
 
                                 r = parse_uid(k, b + i);
-
                                 if (r < 0)
                                         continue;
 
@@ -683,7 +806,7 @@ static int seat_get_can(const char *seat, const char *variable) {
         _cleanup_free_ char *p = NULL, *s = NULL;
         int r;
 
-        assert_return(variable, -EINVAL);
+        assert(variable);
 
         r = file_of_seat(seat, &p);
         if (r < 0)
@@ -692,10 +815,12 @@ static int seat_get_can(const char *seat, const char *variable) {
         r = parse_env_file(p, NEWLINE,
                            variable, &s,
                            NULL);
+        if (r == -ENOENT)
+                return -ENXIO;
         if (r < 0)
                 return r;
-        if (!s)
-                return 0;
+        if (isempty(s))
+                return -ENODATA;
 
         return parse_boolean(s);
 }
@@ -819,6 +944,8 @@ _public_ int sd_machine_get_class(const char *machine, char **class) {
 
         p = strjoina("/run/systemd/machines/", machine);
         r = parse_env_file(p, NEWLINE, "CLASS", &c, NULL);
+        if (r == -ENOENT)
+                return -ENXIO;
         if (r < 0)
                 return r;
         if (!c)
@@ -842,6 +969,8 @@ _public_ int sd_machine_get_ifindices(const char *machine, int **ifindices) {
 
         p = strjoina("/run/systemd/machines/", machine);
         r = parse_env_file(p, NEWLINE, "NETIF", &netif, NULL);
+        if (r == -ENOENT)
+                return -ENXIO;
         if (r < 0)
                 return r;
         if (!netif) {
@@ -855,9 +984,7 @@ _public_ int sd_machine_get_ifindices(const char *machine, int **ifindices) {
 
                 *(char*) (mempcpy(buf, word, l)) = 0;
 
-                if (safe_atoi(buf, &ifi) < 0)
-                        continue;
-                if (ifi <= 0)
+                if (parse_ifindex(buf, &ifi) < 0)
                         continue;
 
                 if (!GREEDY_REALLOC(ni, allocated, nr+1)) {