chiark / gitweb /
logind: introduce libsystemd-login.so as fast path to access logind data
authorLennart Poettering <lennart@poettering.net>
Thu, 14 Jul 2011 20:50:01 +0000 (22:50 +0200)
committerLennart Poettering <lennart@poettering.net>
Thu, 14 Jul 2011 20:51:28 +0000 (22:51 +0200)
.gitignore
Makefile.am
TODO
libsystemd-login.pc.in [new file with mode: 0644]
src/sd-login.c [new file with mode: 0644]
src/sd-login.h [new file with mode: 0644]
src/test-login.c [new file with mode: 0644]
systemd.pc.in

index b108fd987589a9759615b6de1b22d8aa080612fc..cd25404577462f13f9022f8a815fcaae3921b1cd 100644 (file)
@@ -1,3 +1,5 @@
+libsystemd-login.pc
+test-login
 systemd-loginctl
 systemd-localed
 systemd-timedated
index 53167ff20ee31ad650ee9c27418f269b4b7870e4..445cc1e37e35d7c11186809bc8d2769ff7544929 100644 (file)
@@ -19,6 +19,10 @@ ACLOCAL_AMFLAGS = -I m4
 
 SUBDIRS = po
 
+LIBSYSTEMD_LOGIN_CURRENT=0
+LIBSYSTEMD_LOGIN_REVISION=0
+LIBSYSTEMD_LOGIN_AGE=0
+
 # Dirs of external packages
 dbuspolicydir=@dbuspolicydir@
 dbussessionservicedir=@dbussessionservicedir@
@@ -35,6 +39,7 @@ pkgsysconfdir=$(sysconfdir)/systemd
 userunitdir=$(prefix)/lib/systemd/user
 tmpfilesdir=$(prefix)/lib/tmpfiles.d
 usergeneratordir=$(pkglibexecdir)/user-generators
+pkgincludedir=$(includedir)/systemd
 
 # And these are the special ones for /
 rootdir=@rootdir@
@@ -183,6 +188,12 @@ systemgenerator_PROGRAMS += \
        systemd-cryptsetup-generator
 endif
 
+lib_LTLIBRARIES = \
+        libsystemd-login.la
+
+pkginclude_HEADERS = \
+        src/sd-login.h
+
 noinst_PROGRAMS = \
        test-engine \
        test-job-type \
@@ -192,7 +203,8 @@ noinst_PROGRAMS = \
        test-daemon \
        test-cgroup \
        test-env-replace \
-       test-strv
+       test-strv \
+        test-login
 
 if HAVE_PAM
 pamlib_LTLIBRARIES = \
@@ -410,6 +422,7 @@ EXTRA_DIST = \
        units/quotacheck.service.in \
         units/user@.service.in \
        systemd.pc.in \
+        libsystemd-login.pc.in \
        introspect.awk \
         src/73-seat-late.rules.in
 
@@ -472,7 +485,8 @@ dist_doc_DATA = \
        src/sd-readahead.c
 
 pkgconfigdata_DATA = \
-       systemd.pc
+       systemd.pc \
+        libsystemd-login.pc
 
 # Passed through intltool only
 polkitpolicy_in_files = \
@@ -801,6 +815,16 @@ test_strv_CFLAGS = \
 test_strv_LDADD = \
        libsystemd-basic.la
 
+test_login_SOURCES = \
+       src/test-login.c
+
+test_login_CFLAGS = \
+       $(AM_CFLAGS)
+
+test_login_LDADD = \
+       libsystemd-basic.la \
+        libsystemd-login.la
+
 systemd_logger_SOURCES = \
        src/logger.c \
        src/tcpwrap.c
@@ -946,6 +970,7 @@ systemd_uaccess_CFLAGS = \
 
 systemd_uaccess_LDADD = \
        libsystemd-basic.la \
+       libsystemd-daemon.la \
         $(UDEV_LIBS) \
         $(ACL_LIBS)
 
@@ -1339,6 +1364,21 @@ pam_systemd_la_LIBADD = \
        $(PAM_LIBS) \
         $(DBUS_LIBS)
 
+libsystemd_login_la_CFLAGS = \
+        $(AM_CFLAGS) \
+       -fvisibility=hidden
+
+libsystemd_login_la_LDFLAGS = \
+        -shared \
+        -version-info $(LIBSYSTEMD_LOGIN_CURRENT):$(LIBSYSTEMD_LOGIN_REVISION):$(LIBSYSTEMD_LOGIN_AGE)
+
+libsystemd_login_la_SOURCES = \
+        src/sd-login.c \
+        src/cgroup-util.c
+
+libsystemd_login_la_LIBADD = \
+       libsystemd-basic.la
+
 SED_PROCESS = \
        $(AM_V_GEN)$(MKDIR_P) $(dir $@) && \
        $(SED)  -e 's,@rootlibexecdir\@,$(rootlibexecdir),g' \
@@ -1355,6 +1395,9 @@ SED_PROCESS = \
                -e 's,@PACKAGE_NAME\@,$(PACKAGE_NAME),g' \
                -e 's,@PACKAGE_URL\@,$(PACKAGE_URL),g' \
                -e 's,@prefix\@,$(prefix),g' \
+               -e 's,@exec_prefix\@,$(exec_prefix),g' \
+               -e 's,@libdir\@,$(libdir),g' \
+               -e 's,@includedir\@,$(includedir),g' \
                < $< > $@ || rm $@
 
 units/%: units/%.in Makefile
diff --git a/TODO b/TODO
index 8a807b48f9aebc0a8eab439a580a2fdbc40d8033..1577565e0336cf12980da13285c807589e681030 100644 (file)
--- a/TODO
+++ b/TODO
@@ -20,6 +20,8 @@ F15 External:
 
 Features:
 
+* logind: ensure ACLs are updated on login and logout
+
 * warn if the user stops a service but not its associated socket
 
 * ensure we always set the facility when logging to kmsg
diff --git a/libsystemd-login.pc.in b/libsystemd-login.pc.in
new file mode 100644 (file)
index 0000000..cd36a9c
--- /dev/null
@@ -0,0 +1,18 @@
+#  This file is part of systemd.
+#
+#  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.
+
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: systemd
+Description: systemd Login Utility Library
+URL: @PACKAGE_URL@
+Version: @PACKAGE_VERSION@
+Libs: -L${libdir} -lsystemd-login
+Cflags: -I${includedir}
diff --git a/src/sd-login.c b/src/sd-login.c
new file mode 100644 (file)
index 0000000..3ae850d
--- /dev/null
@@ -0,0 +1,323 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/***
+  This file is part of systemd.
+
+  Copyright 2011 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/>.
+***/
+
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+
+#include "util.h"
+#include "cgroup-util.h"
+#include "macro.h"
+#include "sd-login.h"
+
+_public_ int sd_pid_get_session(pid_t pid, char **session) {
+        int r;
+        char *cg_process, *cg_init, *p;
+
+        if (pid == 0)
+                pid = getpid();
+
+        if (pid <= 0)
+                return -EINVAL;
+
+        if (!session)
+                return -EINVAL;
+
+        r = cg_get_by_pid(SYSTEMD_CGROUP_CONTROLLER, pid, &cg_process);
+        if (r < 0)
+                return r;
+
+        r = cg_get_by_pid(SYSTEMD_CGROUP_CONTROLLER, 1, &cg_init);
+        if (r < 0) {
+                free(cg_process);
+                return r;
+        }
+
+        if (endswith(cg_init, "/system"))
+                cg_init[strlen(cg_init)-7] = 0;
+        else if (streq(cg_init, "/"))
+                cg_init[0] = 0;
+
+        if (startswith(cg_process, cg_init))
+                p = cg_process + strlen(cg_init);
+        else
+                p = cg_process;
+
+        free(cg_init);
+
+        if (!startswith(p, "/user/")) {
+                free(cg_process);
+                return -ENOENT;
+        }
+
+        p += 6;
+        if (startswith(p, "shared/") || streq(p, "shared")) {
+                free(cg_process);
+                return -ENOENT;
+        }
+
+        p = strchr(p, '/');
+        if (!p) {
+                free(cg_process);
+                return -ENOENT;
+        }
+
+        p++;
+        p = strndup(p, strcspn(p, "/"));
+        free(cg_process);
+
+        if (!p)
+                return -ENOMEM;
+
+        *session = p;
+        return 0;
+}
+
+_public_ int sd_uid_get_state(uid_t uid, char**state) {
+        char *p, *s = NULL;
+        int r;
+
+        if (!state)
+                return -EINVAL;
+
+        if (asprintf(&p, "/run/systemd/users/%lu", (unsigned long) uid) < 0)
+                return -ENOMEM;
+
+        r = parse_env_file(p, NEWLINE, "STATE", &s, NULL);
+        free(p);
+
+        if (r == -ENOENT) {
+                free(s);
+                s = strdup("offline");
+                if (!s)
+                        return -ENOMEM;
+
+                *state = s;
+                return 0;
+        } else if (r < 0) {
+                free(s);
+                return r;
+        } else if (!s)
+                return -EIO;
+
+        *state = s;
+        return 0;
+}
+
+static int uid_is_on_seat_internal(uid_t uid, const char *seat, const char *variable) {
+        char *p, *w, *t, *state, *s = NULL;
+        size_t l;
+        int r;
+
+        if (!seat)
+                return -EINVAL;
+
+        p = strappend("/run/systemd/seats/", seat);
+        if (!p)
+                return -ENOMEM;
+
+        r = parse_env_file(p, NEWLINE, "UIDS", &s, NULL);
+        free(p);
+
+        if (r < 0) {
+                free(s);
+                return r;
+        }
+
+        if (!s)
+                return -EIO;
+
+        if (asprintf(&t, "%lu", (unsigned long) uid) < 0) {
+                free(s);
+                return -ENOMEM;
+        }
+
+        FOREACH_WORD(w, l, s, state) {
+                if (strncmp(t, w, l) == 0) {
+                        free(s);
+                        free(t);
+
+                        return 1;
+                }
+        }
+
+        free(s);
+        free(t);
+
+        return 0;
+}
+
+_public_ int sd_uid_is_on_seat(uid_t uid, const char *seat) {
+        return uid_is_on_seat_internal(uid, seat, "UIDS");
+}
+
+_public_ int sd_uid_is_active_on_seat(uid_t uid, const char *seat) {
+        return uid_is_on_seat_internal(uid, seat, "ACTIVE_UID");
+}
+
+_public_ int sd_session_is_active(const char *session) {
+        int r;
+        char *p, *s = NULL;
+
+        if (!session)
+                return -EINVAL;
+
+        p = strappend("/run/systemd/sessions/", session);
+        if (!p)
+                return -ENOMEM;
+
+        r = parse_env_file(p, NEWLINE, "ACTIVE", &s, NULL);
+        free(p);
+
+        if (r < 0) {
+                free(s);
+                return r;
+        }
+
+        if (!s)
+                return -EIO;
+
+        r = parse_boolean(s);
+        free(s);
+
+        return r;
+}
+
+_public_ int sd_session_get_uid(const char *session, uid_t *uid) {
+        int r;
+        char *p, *s = NULL;
+        unsigned long ul;
+
+        if (!session)
+                return -EINVAL;
+        if (!uid)
+                return -EINVAL;
+
+        p = strappend("/run/systemd/sessions/", session);
+        if (!p)
+                return -ENOMEM;
+
+        r = parse_env_file(p, NEWLINE, "UID", &s, NULL);
+        free(p);
+
+        if (r < 0) {
+                free(s);
+                return r;
+        }
+
+        if (!s)
+                return -EIO;
+
+        r = safe_atolu(s, &ul);
+        free(s);
+
+        if (r < 0)
+                return r;
+
+        *uid = (uid_t) ul;
+        return 0;
+}
+
+_public_ int sd_session_get_seat(const char *session, char **seat) {
+        char *p, *s = NULL;
+        int r;
+
+        if (!session)
+                return -EINVAL;
+        if (!seat)
+                return -EINVAL;
+
+        p = strappend("/run/systemd/sessions/", session);
+        if (!p)
+                return -ENOMEM;
+
+        r = parse_env_file(p, NEWLINE, "SEAT", &s, NULL);
+        free(p);
+
+        if (r < 0) {
+                free(s);
+                return r;
+        }
+
+        if (isempty(s))
+                return -ENOENT;
+
+        *seat = s;
+        return 0;
+}
+
+_public_ int sd_seat_get_active(const char *seat, char **session, uid_t *uid) {
+        char *p, *s = NULL, *t = NULL;
+        int r;
+
+        if (!seat)
+                return -EINVAL;
+        if (!session && !uid)
+                return -EINVAL;
+
+        p = strappend("/run/systemd/seats/", seat);
+        if (!p)
+                return -ENOMEM;
+
+        r = parse_env_file(p, NEWLINE,
+                           "ACTIVE", &s,
+                           "ACTIVE_UID", &t,
+                           NULL);
+        free(p);
+
+        if (r < 0) {
+                free(s);
+                free(t);
+                return r;
+        }
+
+        if (session && !s)  {
+                free(t);
+                return -EIO;
+        }
+
+        if (uid && !t) {
+                free(s);
+                return -EIO;
+        }
+
+        if (uid && t) {
+                unsigned long ul;
+
+                r = safe_atolu(t, &ul);
+                if (r < 0) {
+                        free(t);
+                        free(s);
+                        return r;
+                }
+
+                *uid = (uid_t) ul;
+        }
+
+        free(t);
+
+        if (session && s)
+                *session = s;
+        else
+                free(s);
+
+        return 0;
+}
diff --git a/src/sd-login.h b/src/sd-login.h
new file mode 100644 (file)
index 0000000..f23ac80
--- /dev/null
@@ -0,0 +1,51 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+#ifndef foosdloginhfoo
+#define foosdloginhfoo
+
+/***
+  This file is part of systemd.
+
+  Copyright 2011 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/>.
+***/
+
+#include <sys/types.h>
+
+/* Get session from PID */
+int sd_pid_get_session(pid_t pid, char **session);
+
+/* Get state from uid. Possible states: offline, lingering, online, active */
+int sd_uid_get_state(uid_t uid, char**state);
+
+/* Return 1 if uid has session on seat */
+int sd_uid_is_on_seat(uid_t uid, const char *seat);
+
+/* Return 1 if uid has active session on seat */
+int sd_uid_is_active_on_seat(uid_t uid, const char *seat);
+
+/* Return 1 if the session is a active */
+int sd_session_is_active(const char *session);
+
+/* Determine user id of session */
+int sd_session_get_uid(const char *session, uid_t *uid);
+
+/* Determine seat of session */
+int sd_session_get_seat(const char *session, char **seat);
+
+/* Return active session and user of seat */
+int sd_seat_get_active(const char *seat, char **session, uid_t *uid);
+
+#endif
diff --git a/src/test-login.c b/src/test-login.c
new file mode 100644 (file)
index 0000000..97313fc
--- /dev/null
@@ -0,0 +1,65 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/***
+  This file is part of systemd.
+
+  Copyright 2011 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/>.
+***/
+
+#include "sd-login.h"
+#include "util.h"
+
+int main(int argc, char* argv[]) {
+    int r, k;
+    uid_t u, u2;
+        char *seat;
+        char *session;
+        char *state;
+        char *session2;
+
+        assert_se(sd_pid_get_session(0, &session) == 0);
+        printf("session = %s\n", session);
+
+        r = sd_session_is_active(session);
+        assert_se(r >= 0);
+        printf("active = %s\n", yes_no(r));
+
+        assert_se(sd_session_get_uid(session, &u) >= 0);
+        printf("uid = %lu\n", (unsigned long) u);
+
+        assert_se(sd_session_get_seat(session, &seat) >= 0);
+        printf("seat = %s\n", seat);
+
+        assert_se(sd_uid_get_state(u, &state) >= 0);
+        printf("state = %s\n", state);
+
+        assert_se(sd_uid_is_on_seat(u, seat) > 0);
+
+        k = sd_uid_is_active_on_seat(u, seat);
+        assert_se(k >= 0);
+        assert_se(!!r == !!r);
+
+        assert_se(sd_seat_get_active(seat, &session2, &u2) >= 0);
+        printf("session2 = %s\n", session2);
+        printf("uid2 = %lu\n", (unsigned long) u2);
+
+        free(session);
+        free(state);
+        free(session2);
+        free(seat);
+
+        return 0;
+}
index 2e2217ec4bdc550aa9a0f0404935efce01d92a43..29376e55b0a8ac40438991434e0b799579da39ef 100644 (file)
@@ -6,7 +6,7 @@
 #  (at your option) any later version.
 
 prefix=@prefix@
-exec_prefix=${prefix}
+exec_prefix=@exec_prefix@
 systemdsystemunitdir=@systemunitdir@
 systemduserunitdir=@userunitdir@
 systemdsystemconfdir=@pkgsysconfdir@/system