LCOV - code coverage report
Current view: top level - libsystemd/sd-login - sd-login.c (source / functions) Hit Total Coverage
Test: main_coverage.info Lines: 298 585 50.9 %
Date: 2019-08-22 15:41:25 Functions: 37 60 61.7 %

          Line data    Source code
       1             : /* SPDX-License-Identifier: LGPL-2.1+ */
       2             : 
       3             : #include <errno.h>
       4             : #include <poll.h>
       5             : #include <string.h>
       6             : #include <sys/inotify.h>
       7             : #include <unistd.h>
       8             : 
       9             : #include "sd-login.h"
      10             : 
      11             : #include "alloc-util.h"
      12             : #include "cgroup-util.h"
      13             : #include "dirent-util.h"
      14             : #include "env-file.h"
      15             : #include "escape.h"
      16             : #include "fd-util.h"
      17             : #include "format-util.h"
      18             : #include "fs-util.h"
      19             : #include "hostname-util.h"
      20             : #include "io-util.h"
      21             : #include "login-util.h"
      22             : #include "macro.h"
      23             : #include "parse-util.h"
      24             : #include "path-util.h"
      25             : #include "socket-util.h"
      26             : #include "string-util.h"
      27             : #include "strv.h"
      28             : #include "user-util.h"
      29             : #include "util.h"
      30             : 
      31             : /* Error codes:
      32             :  *
      33             :  *    invalid input parameters                → -EINVAL
      34             :  *    invalid fd                              → -EBADF
      35             :  *    process does not exist                  → -ESRCH
      36             :  *    cgroup does not exist                   → -ENOENT
      37             :  *    machine, session does not exist         → -ENXIO
      38             :  *    requested metadata on object is missing → -ENODATA
      39             :  */
      40             : 
      41           2 : _public_ int sd_pid_get_session(pid_t pid, char **session) {
      42             :         int r;
      43             : 
      44           2 :         assert_return(pid >= 0, -EINVAL);
      45           2 :         assert_return(session, -EINVAL);
      46             : 
      47           2 :         r = cg_pid_get_session(pid, session);
      48           2 :         return IN_SET(r, -ENXIO, -ENOMEDIUM) ? -ENODATA : r;
      49             : }
      50             : 
      51           1 : _public_ int sd_pid_get_unit(pid_t pid, char **unit) {
      52             :         int r;
      53             : 
      54           1 :         assert_return(pid >= 0, -EINVAL);
      55           1 :         assert_return(unit, -EINVAL);
      56             : 
      57           1 :         r = cg_pid_get_unit(pid, unit);
      58           1 :         return IN_SET(r, -ENXIO, -ENOMEDIUM) ? -ENODATA : r;
      59             : }
      60             : 
      61           1 : _public_ int sd_pid_get_user_unit(pid_t pid, char **unit) {
      62             :         int r;
      63             : 
      64           1 :         assert_return(pid >= 0, -EINVAL);
      65           1 :         assert_return(unit, -EINVAL);
      66             : 
      67           1 :         r = cg_pid_get_user_unit(pid, unit);
      68           1 :         return IN_SET(r, -ENXIO, -ENOMEDIUM) ? -ENODATA : r;
      69             : }
      70             : 
      71           0 : _public_ int sd_pid_get_machine_name(pid_t pid, char **name) {
      72             :         int r;
      73             : 
      74           0 :         assert_return(pid >= 0, -EINVAL);
      75           0 :         assert_return(name, -EINVAL);
      76             : 
      77           0 :         r = cg_pid_get_machine_name(pid, name);
      78           0 :         return IN_SET(r, -ENXIO, -ENOMEDIUM) ? -ENODATA : r;
      79             : }
      80             : 
      81           1 : _public_ int sd_pid_get_slice(pid_t pid, char **slice) {
      82             :         int r;
      83             : 
      84           1 :         assert_return(pid >= 0, -EINVAL);
      85           1 :         assert_return(slice, -EINVAL);
      86             : 
      87           1 :         r = cg_pid_get_slice(pid, slice);
      88           1 :         return IN_SET(r, -ENXIO, -ENOMEDIUM) ? -ENODATA : r;
      89             : }
      90             : 
      91           0 : _public_ int sd_pid_get_user_slice(pid_t pid, char **slice) {
      92             :         int r;
      93             : 
      94           0 :         assert_return(pid >= 0, -EINVAL);
      95           0 :         assert_return(slice, -EINVAL);
      96             : 
      97           0 :         r = cg_pid_get_user_slice(pid, slice);
      98           0 :         return IN_SET(r, -ENXIO, -ENOMEDIUM) ? -ENODATA : r;
      99             : }
     100             : 
     101           1 : _public_ int sd_pid_get_owner_uid(pid_t pid, uid_t *uid) {
     102             :         int r;
     103             : 
     104           1 :         assert_return(pid >= 0, -EINVAL);
     105           1 :         assert_return(uid, -EINVAL);
     106             : 
     107           1 :         r = cg_pid_get_owner_uid(pid, uid);
     108           1 :         return IN_SET(r, -ENXIO, -ENOMEDIUM) ? -ENODATA : r;
     109             : }
     110             : 
     111           1 : _public_ int sd_pid_get_cgroup(pid_t pid, char **cgroup) {
     112             :         char *c;
     113             :         int r;
     114             : 
     115           1 :         assert_return(pid >= 0, -EINVAL);
     116           1 :         assert_return(cgroup, -EINVAL);
     117             : 
     118           1 :         r = cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, pid, &c);
     119           1 :         if (r < 0)
     120           0 :                 return r;
     121             : 
     122             :         /* The internal APIs return the empty string for the root
     123             :          * cgroup, let's return the "/" in the public APIs instead, as
     124             :          * that's easier and less ambiguous for people to grok. */
     125           1 :         if (isempty(c)) {
     126           0 :                 free(c);
     127           0 :                 c = strdup("/");
     128           0 :                 if (!c)
     129           0 :                         return -ENOMEM;
     130             : 
     131             :         }
     132             : 
     133           1 :         *cgroup = c;
     134           1 :         return 0;
     135             : }
     136             : 
     137           2 : _public_ int sd_peer_get_session(int fd, char **session) {
     138           2 :         struct ucred ucred = {};
     139             :         int r;
     140             : 
     141           2 :         assert_return(fd >= 0, -EBADF);
     142           2 :         assert_return(session, -EINVAL);
     143             : 
     144           2 :         r = getpeercred(fd, &ucred);
     145           2 :         if (r < 0)
     146           0 :                 return r;
     147             : 
     148           2 :         return cg_pid_get_session(ucred.pid, session);
     149             : }
     150             : 
     151           0 : _public_ int sd_peer_get_owner_uid(int fd, uid_t *uid) {
     152             :         struct ucred ucred;
     153             :         int r;
     154             : 
     155           0 :         assert_return(fd >= 0, -EBADF);
     156           0 :         assert_return(uid, -EINVAL);
     157             : 
     158           0 :         r = getpeercred(fd, &ucred);
     159           0 :         if (r < 0)
     160           0 :                 return r;
     161             : 
     162           0 :         return cg_pid_get_owner_uid(ucred.pid, uid);
     163             : }
     164             : 
     165           0 : _public_ int sd_peer_get_unit(int fd, char **unit) {
     166             :         struct ucred ucred;
     167             :         int r;
     168             : 
     169           0 :         assert_return(fd >= 0, -EBADF);
     170           0 :         assert_return(unit, -EINVAL);
     171             : 
     172           0 :         r = getpeercred(fd, &ucred);
     173           0 :         if (r < 0)
     174           0 :                 return r;
     175             : 
     176           0 :         return cg_pid_get_unit(ucred.pid, unit);
     177             : }
     178             : 
     179           0 : _public_ int sd_peer_get_user_unit(int fd, char **unit) {
     180             :         struct ucred ucred;
     181             :         int r;
     182             : 
     183           0 :         assert_return(fd >= 0, -EBADF);
     184           0 :         assert_return(unit, -EINVAL);
     185             : 
     186           0 :         r = getpeercred(fd, &ucred);
     187           0 :         if (r < 0)
     188           0 :                 return r;
     189             : 
     190           0 :         return cg_pid_get_user_unit(ucred.pid, unit);
     191             : }
     192             : 
     193           0 : _public_ int sd_peer_get_machine_name(int fd, char **machine) {
     194             :         struct ucred ucred;
     195             :         int r;
     196             : 
     197           0 :         assert_return(fd >= 0, -EBADF);
     198           0 :         assert_return(machine, -EINVAL);
     199             : 
     200           0 :         r = getpeercred(fd, &ucred);
     201           0 :         if (r < 0)
     202           0 :                 return r;
     203             : 
     204           0 :         return cg_pid_get_machine_name(ucred.pid, machine);
     205             : }
     206             : 
     207           0 : _public_ int sd_peer_get_slice(int fd, char **slice) {
     208             :         struct ucred ucred;
     209             :         int r;
     210             : 
     211           0 :         assert_return(fd >= 0, -EBADF);
     212           0 :         assert_return(slice, -EINVAL);
     213             : 
     214           0 :         r = getpeercred(fd, &ucred);
     215           0 :         if (r < 0)
     216           0 :                 return r;
     217             : 
     218           0 :         return cg_pid_get_slice(ucred.pid, slice);
     219             : }
     220             : 
     221           0 : _public_ int sd_peer_get_user_slice(int fd, char **slice) {
     222             :         struct ucred ucred;
     223             :         int r;
     224             : 
     225           0 :         assert_return(fd >= 0, -EBADF);
     226           0 :         assert_return(slice, -EINVAL);
     227             : 
     228           0 :         r = getpeercred(fd, &ucred);
     229           0 :         if (r < 0)
     230           0 :                 return r;
     231             : 
     232           0 :         return cg_pid_get_user_slice(ucred.pid, slice);
     233             : }
     234             : 
     235           0 : _public_ int sd_peer_get_cgroup(int fd, char **cgroup) {
     236             :         struct ucred ucred;
     237             :         int r;
     238             : 
     239           0 :         assert_return(fd >= 0, -EBADF);
     240           0 :         assert_return(cgroup, -EINVAL);
     241             : 
     242           0 :         r = getpeercred(fd, &ucred);
     243           0 :         if (r < 0)
     244           0 :                 return r;
     245             : 
     246           0 :         return sd_pid_get_cgroup(ucred.pid, cgroup);
     247             : }
     248             : 
     249           6 : static int file_of_uid(uid_t uid, char **p) {
     250             : 
     251           6 :         assert_return(uid_is_valid(uid), -EINVAL);
     252           6 :         assert(p);
     253             : 
     254           6 :         if (asprintf(p, "/run/systemd/users/" UID_FMT, uid) < 0)
     255           0 :                 return -ENOMEM;
     256             : 
     257           6 :         return 0;
     258             : }
     259             : 
     260           1 : _public_ int sd_uid_get_state(uid_t uid, char**state) {
     261           1 :         _cleanup_free_ char *p = NULL, *s = NULL;
     262             :         int r;
     263             : 
     264           1 :         assert_return(state, -EINVAL);
     265             : 
     266           1 :         r = file_of_uid(uid, &p);
     267           1 :         if (r < 0)
     268           0 :                 return r;
     269             : 
     270           1 :         r = parse_env_file(NULL, p, "STATE", &s);
     271           1 :         if (r == -ENOENT) {
     272           0 :                 r = free_and_strdup(&s, "offline");
     273           0 :                 if (r < 0)
     274           0 :                         return r;
     275           1 :         } else if (r < 0)
     276           0 :                 return r;
     277           1 :         else if (isempty(s))
     278           0 :                 return -EIO;
     279             : 
     280           1 :         *state = TAKE_PTR(s);
     281           1 :         return 0;
     282             : }
     283             : 
     284           1 : _public_ int sd_uid_get_display(uid_t uid, char **session) {
     285           1 :         _cleanup_free_ char *p = NULL, *s = NULL;
     286             :         int r;
     287             : 
     288           1 :         assert_return(session, -EINVAL);
     289             : 
     290           1 :         r = file_of_uid(uid, &p);
     291           1 :         if (r < 0)
     292           0 :                 return r;
     293             : 
     294           1 :         r = parse_env_file(NULL, p, "DISPLAY", &s);
     295           1 :         if (r == -ENOENT)
     296           0 :                 return -ENODATA;
     297           1 :         if (r < 0)
     298           0 :                 return r;
     299           1 :         if (isempty(s))
     300           0 :                 return -ENODATA;
     301             : 
     302           1 :         *session = TAKE_PTR(s);
     303             : 
     304           1 :         return 0;
     305             : }
     306             : 
     307           9 : static int file_of_seat(const char *seat, char **_p) {
     308             :         char *p;
     309             :         int r;
     310             : 
     311           9 :         assert(_p);
     312             : 
     313           9 :         if (seat) {
     314           8 :                 if (!filename_is_valid(seat))
     315           0 :                         return -EINVAL;
     316             : 
     317           8 :                 p = path_join("/run/systemd/seats", seat);
     318             :         } else {
     319           1 :                 _cleanup_free_ char *buf = NULL;
     320             : 
     321           1 :                 r = sd_session_get_seat(NULL, &buf);
     322           1 :                 if (r < 0)
     323           0 :                         return r;
     324             : 
     325           1 :                 p = path_join("/run/systemd/seats", buf);
     326             :         }
     327           9 :         if (!p)
     328           0 :                 return -ENOMEM;
     329             : 
     330           9 :         *_p = TAKE_PTR(p);
     331           9 :         return 0;
     332             : }
     333             : 
     334           2 : _public_ int sd_uid_is_on_seat(uid_t uid, int require_active, const char *seat) {
     335           2 :         _cleanup_free_ char *t = NULL, *s = NULL, *p = NULL;
     336             :         size_t l;
     337             :         int r;
     338             :         const char *word, *variable, *state;
     339             : 
     340           2 :         assert_return(uid_is_valid(uid), -EINVAL);
     341             : 
     342           2 :         r = file_of_seat(seat, &p);
     343           2 :         if (r < 0)
     344           0 :                 return r;
     345             : 
     346           2 :         variable = require_active ? "ACTIVE_UID" : "UIDS";
     347             : 
     348           2 :         r = parse_env_file(NULL, p, variable, &s);
     349           2 :         if (r == -ENOENT)
     350           0 :                 return 0;
     351           2 :         if (r < 0)
     352           0 :                 return r;
     353           2 :         if (isempty(s))
     354           0 :                 return 0;
     355             : 
     356           2 :         if (asprintf(&t, UID_FMT, uid) < 0)
     357           0 :                 return -ENOMEM;
     358             : 
     359           2 :         FOREACH_WORD(word, l, s, state)
     360           2 :                 if (strneq(t, word, l))
     361           2 :                         return 1;
     362             : 
     363           0 :         return 0;
     364             : }
     365             : 
     366           4 : static int uid_get_array(uid_t uid, const char *variable, char ***array) {
     367           4 :         _cleanup_free_ char *p = NULL, *s = NULL;
     368             :         char **a;
     369             :         int r;
     370             : 
     371           4 :         assert(variable);
     372             : 
     373           4 :         r = file_of_uid(uid, &p);
     374           4 :         if (r < 0)
     375           0 :                 return r;
     376             : 
     377           4 :         r = parse_env_file(NULL, p, variable, &s);
     378           4 :         if (r == -ENOENT || (r >= 0 && isempty(s))) {
     379           0 :                 if (array)
     380           0 :                         *array = NULL;
     381           0 :                 return 0;
     382             :         }
     383           4 :         if (r < 0)
     384           0 :                 return r;
     385             : 
     386           4 :         a = strv_split(s, " ");
     387           4 :         if (!a)
     388           0 :                 return -ENOMEM;
     389             : 
     390           4 :         strv_uniq(a);
     391           4 :         r = (int) strv_length(a);
     392             : 
     393           4 :         if (array)
     394           2 :                 *array = a;
     395             :         else
     396           2 :                 strv_free(a);
     397             : 
     398           4 :         return r;
     399             : }
     400             : 
     401           2 : _public_ int sd_uid_get_sessions(uid_t uid, int require_active, char ***sessions) {
     402           2 :         return uid_get_array(
     403             :                         uid,
     404             :                         require_active == 0 ? "ONLINE_SESSIONS" :
     405           0 :                         require_active > 0  ? "ACTIVE_SESSIONS" :
     406             :                                               "SESSIONS",
     407             :                         sessions);
     408             : }
     409             : 
     410           2 : _public_ int sd_uid_get_seats(uid_t uid, int require_active, char ***seats) {
     411           2 :         return uid_get_array(
     412             :                         uid,
     413             :                         require_active == 0 ? "ONLINE_SEATS" :
     414           0 :                         require_active > 0  ? "ACTIVE_SEATS" :
     415             :                                               "SEATS",
     416             :                         seats);
     417             : }
     418             : 
     419          11 : static int file_of_session(const char *session, char **_p) {
     420             :         char *p;
     421             :         int r;
     422             : 
     423          11 :         assert(_p);
     424             : 
     425          11 :         if (session) {
     426          10 :                 if (!session_id_valid(session))
     427           0 :                         return -EINVAL;
     428             : 
     429          10 :                 p = path_join("/run/systemd/sessions", session);
     430             :         } else {
     431           1 :                 _cleanup_free_ char *buf = NULL;
     432             : 
     433           1 :                 r = sd_pid_get_session(0, &buf);
     434           1 :                 if (r < 0)
     435           0 :                         return r;
     436             : 
     437           1 :                 p = path_join("/run/systemd/sessions", buf);
     438             :         }
     439             : 
     440          11 :         if (!p)
     441           0 :                 return -ENOMEM;
     442             : 
     443          11 :         *_p = p;
     444          11 :         return 0;
     445             : }
     446             : 
     447           1 : _public_ int sd_session_is_active(const char *session) {
     448           1 :         _cleanup_free_ char *p = NULL, *s = NULL;
     449             :         int r;
     450             : 
     451           1 :         r = file_of_session(session, &p);
     452           1 :         if (r < 0)
     453           0 :                 return r;
     454             : 
     455           1 :         r = parse_env_file(NULL, p, "ACTIVE", &s);
     456           1 :         if (r == -ENOENT)
     457           0 :                 return -ENXIO;
     458           1 :         if (r < 0)
     459           0 :                 return r;
     460           1 :         if (isempty(s))
     461           0 :                 return -EIO;
     462             : 
     463           1 :         return parse_boolean(s);
     464             : }
     465             : 
     466           1 : _public_ int sd_session_is_remote(const char *session) {
     467           1 :         _cleanup_free_ char *p = NULL, *s = NULL;
     468             :         int r;
     469             : 
     470           1 :         r = file_of_session(session, &p);
     471           1 :         if (r < 0)
     472           0 :                 return r;
     473             : 
     474           1 :         r = parse_env_file(NULL, p, "REMOTE", &s);
     475           1 :         if (r == -ENOENT)
     476           0 :                 return -ENXIO;
     477           1 :         if (r < 0)
     478           0 :                 return r;
     479           1 :         if (isempty(s))
     480           0 :                 return -ENODATA;
     481             : 
     482           1 :         return parse_boolean(s);
     483             : }
     484             : 
     485           1 : _public_ int sd_session_get_state(const char *session, char **state) {
     486           1 :         _cleanup_free_ char *p = NULL, *s = NULL;
     487             :         int r;
     488             : 
     489           1 :         assert_return(state, -EINVAL);
     490             : 
     491           1 :         r = file_of_session(session, &p);
     492           1 :         if (r < 0)
     493           0 :                 return r;
     494             : 
     495           1 :         r = parse_env_file(NULL, p, "STATE", &s);
     496           1 :         if (r == -ENOENT)
     497           0 :                 return -ENXIO;
     498           1 :         if (r < 0)
     499           0 :                 return r;
     500           1 :         if (isempty(s))
     501           0 :                 return -EIO;
     502             : 
     503           1 :         *state = TAKE_PTR(s);
     504             : 
     505           1 :         return 0;
     506             : }
     507             : 
     508           1 : _public_ int sd_session_get_uid(const char *session, uid_t *uid) {
     509             :         int r;
     510           1 :         _cleanup_free_ char *p = NULL, *s = NULL;
     511             : 
     512           1 :         assert_return(uid, -EINVAL);
     513             : 
     514           1 :         r = file_of_session(session, &p);
     515           1 :         if (r < 0)
     516           0 :                 return r;
     517             : 
     518           1 :         r = parse_env_file(NULL, p, "UID", &s);
     519           1 :         if (r == -ENOENT)
     520           0 :                 return -ENXIO;
     521           1 :         if (r < 0)
     522           0 :                 return r;
     523           1 :         if (isempty(s))
     524           0 :                 return -EIO;
     525             : 
     526           1 :         return parse_uid(s, uid);
     527             : }
     528             : 
     529           7 : static int session_get_string(const char *session, const char *field, char **value) {
     530           7 :         _cleanup_free_ char *p = NULL, *s = NULL;
     531             :         int r;
     532             : 
     533           7 :         assert_return(value, -EINVAL);
     534           7 :         assert(field);
     535             : 
     536           7 :         r = file_of_session(session, &p);
     537           7 :         if (r < 0)
     538           0 :                 return r;
     539             : 
     540           7 :         r = parse_env_file(NULL, p, field, &s);
     541           7 :         if (r == -ENOENT)
     542           0 :                 return -ENXIO;
     543           7 :         if (r < 0)
     544           0 :                 return r;
     545           7 :         if (isempty(s))
     546           2 :                 return -ENODATA;
     547             : 
     548           5 :         *value = TAKE_PTR(s);
     549           5 :         return 0;
     550             : }
     551             : 
     552           2 : _public_ int sd_session_get_seat(const char *session, char **seat) {
     553           2 :         return session_get_string(session, "SEAT", seat);
     554             : }
     555             : 
     556           0 : _public_ int sd_session_get_tty(const char *session, char **tty) {
     557           0 :         return session_get_string(session, "TTY", tty);
     558             : }
     559             : 
     560           0 : _public_ int sd_session_get_vt(const char *session, unsigned *vtnr) {
     561           0 :         _cleanup_free_ char *vtnr_string = NULL;
     562             :         unsigned u;
     563             :         int r;
     564             : 
     565           0 :         assert_return(vtnr, -EINVAL);
     566             : 
     567           0 :         r = session_get_string(session, "VTNR", &vtnr_string);
     568           0 :         if (r < 0)
     569           0 :                 return r;
     570             : 
     571           0 :         r = safe_atou(vtnr_string, &u);
     572           0 :         if (r < 0)
     573           0 :                 return r;
     574             : 
     575           0 :         *vtnr = u;
     576           0 :         return 0;
     577             : }
     578             : 
     579           0 : _public_ int sd_session_get_service(const char *session, char **service) {
     580           0 :         return session_get_string(session, "SERVICE", service);
     581             : }
     582             : 
     583           1 : _public_ int sd_session_get_type(const char *session, char **type) {
     584           1 :         return session_get_string(session, "TYPE", type);
     585             : }
     586             : 
     587           1 : _public_ int sd_session_get_class(const char *session, char **class) {
     588           1 :         return session_get_string(session, "CLASS", class);
     589             : }
     590             : 
     591           0 : _public_ int sd_session_get_desktop(const char *session, char **desktop) {
     592           0 :         _cleanup_free_ char *escaped = NULL;
     593             :         char *t;
     594             :         int r;
     595             : 
     596           0 :         assert_return(desktop, -EINVAL);
     597             : 
     598           0 :         r = session_get_string(session, "DESKTOP", &escaped);
     599           0 :         if (r < 0)
     600           0 :                 return r;
     601             : 
     602           0 :         r = cunescape(escaped, 0, &t);
     603           0 :         if (r < 0)
     604           0 :                 return r;
     605             : 
     606           0 :         *desktop = t;
     607           0 :         return 0;
     608             : }
     609             : 
     610           1 : _public_ int sd_session_get_display(const char *session, char **display) {
     611           1 :         return session_get_string(session, "DISPLAY", display);
     612             : }
     613             : 
     614           1 : _public_ int sd_session_get_remote_user(const char *session, char **remote_user) {
     615           1 :         return session_get_string(session, "REMOTE_USER", remote_user);
     616             : }
     617             : 
     618           1 : _public_ int sd_session_get_remote_host(const char *session, char **remote_host) {
     619           1 :         return session_get_string(session, "REMOTE_HOST", remote_host);
     620             : }
     621             : 
     622           2 : _public_ int sd_seat_get_active(const char *seat, char **session, uid_t *uid) {
     623           2 :         _cleanup_free_ char *p = NULL, *s = NULL, *t = NULL;
     624             :         int r;
     625             : 
     626           2 :         assert_return(session || uid, -EINVAL);
     627             : 
     628           2 :         r = file_of_seat(seat, &p);
     629           2 :         if (r < 0)
     630           0 :                 return r;
     631             : 
     632           2 :         r = parse_env_file(NULL, p,
     633             :                            "ACTIVE", &s,
     634             :                            "ACTIVE_UID", &t);
     635           2 :         if (r == -ENOENT)
     636           0 :                 return -ENXIO;
     637           2 :         if (r < 0)
     638           0 :                 return r;
     639             : 
     640           2 :         if (session && !s)
     641           0 :                 return -ENODATA;
     642             : 
     643           2 :         if (uid && !t)
     644           0 :                 return -ENODATA;
     645             : 
     646           2 :         if (uid && t) {
     647           1 :                 r = parse_uid(t, uid);
     648           1 :                 if (r < 0)
     649           0 :                         return r;
     650             :         }
     651             : 
     652           2 :         if (session && s)
     653           2 :                 *session = TAKE_PTR(s);
     654             : 
     655           2 :         return 0;
     656             : }
     657             : 
     658           2 : _public_ int sd_seat_get_sessions(const char *seat, char ***sessions, uid_t **uids, unsigned *n_uids) {
     659           2 :         _cleanup_free_ char *p = NULL, *s = NULL, *t = NULL;
     660           2 :         _cleanup_strv_free_ char **a = NULL;
     661           2 :         _cleanup_free_ uid_t *b = NULL;
     662           2 :         unsigned n = 0;
     663             :         int r;
     664             : 
     665           2 :         r = file_of_seat(seat, &p);
     666           2 :         if (r < 0)
     667           0 :                 return r;
     668             : 
     669           2 :         r = parse_env_file(NULL, p,
     670             :                            "SESSIONS", &s,
     671             :                            "UIDS", &t);
     672           2 :         if (r == -ENOENT)
     673           0 :                 return -ENXIO;
     674           2 :         if (r < 0)
     675           0 :                 return r;
     676             : 
     677           2 :         if (s) {
     678           2 :                 a = strv_split(s, " ");
     679           2 :                 if (!a)
     680           0 :                         return -ENOMEM;
     681             :         }
     682             : 
     683           2 :         if (uids && t) {
     684             :                 const char *word, *state;
     685             :                 size_t l;
     686             : 
     687           2 :                 FOREACH_WORD(word, l, t, state)
     688           1 :                         n++;
     689             : 
     690           1 :                 if (n > 0) {
     691           1 :                         unsigned i = 0;
     692             : 
     693           1 :                         b = new(uid_t, n);
     694           1 :                         if (!b)
     695           0 :                                 return -ENOMEM;
     696             : 
     697           2 :                         FOREACH_WORD(word, l, t, state) {
     698           1 :                                 _cleanup_free_ char *k = NULL;
     699             : 
     700           1 :                                 k = strndup(word, l);
     701           1 :                                 if (!k)
     702           0 :                                         return -ENOMEM;
     703             : 
     704           1 :                                 r = parse_uid(k, b + i);
     705           1 :                                 if (r < 0)
     706           0 :                                         return r;
     707             : 
     708           1 :                                 i++;
     709             :                         }
     710             :                 }
     711             :         }
     712             : 
     713           2 :         r = (int) strv_length(a);
     714             : 
     715           2 :         if (sessions)
     716           1 :                 *sessions = TAKE_PTR(a);
     717             : 
     718           2 :         if (uids)
     719           1 :                 *uids = TAKE_PTR(b);
     720             : 
     721           2 :         if (n_uids)
     722           1 :                 *n_uids = n;
     723             : 
     724           2 :         return r;
     725             : }
     726             : 
     727           3 : static int seat_get_can(const char *seat, const char *variable) {
     728           3 :         _cleanup_free_ char *p = NULL, *s = NULL;
     729             :         int r;
     730             : 
     731           3 :         assert(variable);
     732             : 
     733           3 :         r = file_of_seat(seat, &p);
     734           3 :         if (r < 0)
     735           0 :                 return r;
     736             : 
     737           3 :         r = parse_env_file(NULL, p,
     738             :                            variable, &s);
     739           3 :         if (r == -ENOENT)
     740           0 :                 return -ENXIO;
     741           3 :         if (r < 0)
     742           0 :                 return r;
     743           3 :         if (isempty(s))
     744           0 :                 return -ENODATA;
     745             : 
     746           3 :         return parse_boolean(s);
     747             : }
     748             : 
     749           1 : _public_ int sd_seat_can_multi_session(const char *seat) {
     750           1 :         return seat_get_can(seat, "CAN_MULTI_SESSION");
     751             : }
     752             : 
     753           1 : _public_ int sd_seat_can_tty(const char *seat) {
     754           1 :         return seat_get_can(seat, "CAN_TTY");
     755             : }
     756             : 
     757           1 : _public_ int sd_seat_can_graphical(const char *seat) {
     758           1 :         return seat_get_can(seat, "CAN_GRAPHICAL");
     759             : }
     760             : 
     761           2 : _public_ int sd_get_seats(char ***seats) {
     762             :         int r;
     763             : 
     764           2 :         r = get_files_in_directory("/run/systemd/seats/", seats);
     765           2 :         if (r == -ENOENT) {
     766           0 :                 if (seats)
     767           0 :                         *seats = NULL;
     768           0 :                 return 0;
     769             :         }
     770           2 :         return r;
     771             : }
     772             : 
     773           2 : _public_ int sd_get_sessions(char ***sessions) {
     774             :         int r;
     775             : 
     776           2 :         r = get_files_in_directory("/run/systemd/sessions/", sessions);
     777           2 :         if (r == -ENOENT) {
     778           0 :                 if (sessions)
     779           0 :                         *sessions = NULL;
     780           0 :                 return 0;
     781             :         }
     782           2 :         return r;
     783             : }
     784             : 
     785           2 : _public_ int sd_get_uids(uid_t **users) {
     786           2 :         _cleanup_closedir_ DIR *d;
     787             :         struct dirent *de;
     788           2 :         int r = 0;
     789           2 :         unsigned n = 0;
     790           2 :         _cleanup_free_ uid_t *l = NULL;
     791             : 
     792           2 :         d = opendir("/run/systemd/users/");
     793           2 :         if (!d) {
     794           0 :                 if (errno == ENOENT) {
     795           0 :                         if (users)
     796           0 :                                 *users = NULL;
     797           0 :                         return 0;
     798             :                 }
     799           0 :                 return -errno;
     800             :         }
     801             : 
     802           8 :         FOREACH_DIRENT_ALL(de, d, return -errno) {
     803             :                 int k;
     804             :                 uid_t uid;
     805             : 
     806           6 :                 dirent_ensure_type(d, de);
     807             : 
     808           6 :                 if (!dirent_is_file(de))
     809           4 :                         continue;
     810             : 
     811           2 :                 k = parse_uid(de->d_name, &uid);
     812           2 :                 if (k < 0)
     813           0 :                         continue;
     814             : 
     815           2 :                 if (users) {
     816           1 :                         if ((unsigned) r >= n) {
     817             :                                 uid_t *t;
     818             : 
     819           1 :                                 n = MAX(16, 2*r);
     820           1 :                                 t = reallocarray(l, sizeof(uid_t), n);
     821           1 :                                 if (!t)
     822           0 :                                         return -ENOMEM;
     823             : 
     824           1 :                                 l = t;
     825             :                         }
     826             : 
     827           1 :                         assert((unsigned) r < n);
     828           1 :                         l[r++] = uid;
     829             :                 } else
     830           1 :                         r++;
     831             :         }
     832             : 
     833           2 :         if (users)
     834           1 :                 *users = TAKE_PTR(l);
     835             : 
     836           2 :         return r;
     837             : }
     838             : 
     839           2 : _public_ int sd_get_machine_names(char ***machines) {
     840           2 :         _cleanup_strv_free_ char **l = NULL;
     841             :         char **a, **b;
     842             :         int r;
     843             : 
     844           2 :         r = get_files_in_directory("/run/systemd/machines/", &l);
     845           2 :         if (r == -ENOENT) {
     846           0 :                 if (machines)
     847           0 :                         *machines = NULL;
     848           0 :                 return 0;
     849             :         }
     850           2 :         if (r < 0)
     851           0 :                 return r;
     852             : 
     853           2 :         if (l) {
     854           0 :                 r = 0;
     855             : 
     856             :                 /* Filter out the unit: symlinks */
     857           0 :                 for (a = b = l; *a; a++) {
     858           0 :                         if (startswith(*a, "unit:") || !machine_name_is_valid(*a))
     859           0 :                                 free(*a);
     860             :                         else {
     861           0 :                                 *b = *a;
     862           0 :                                 b++;
     863           0 :                                 r++;
     864             :                         }
     865             :                 }
     866             : 
     867           0 :                 *b = NULL;
     868             :         }
     869             : 
     870           2 :         if (machines)
     871           1 :                 *machines = TAKE_PTR(l);
     872             : 
     873           2 :         return r;
     874             : }
     875             : 
     876           0 : _public_ int sd_machine_get_class(const char *machine, char **class) {
     877           0 :         _cleanup_free_ char *c = NULL;
     878             :         const char *p;
     879             :         int r;
     880             : 
     881           0 :         assert_return(class, -EINVAL);
     882             : 
     883           0 :         if (streq(machine, ".host")) {
     884           0 :                 c = strdup("host");
     885           0 :                 if (!c)
     886           0 :                         return -ENOMEM;
     887             :         } else {
     888           0 :                 if (!machine_name_is_valid(machine))
     889           0 :                         return -EINVAL;
     890             : 
     891           0 :                 p = strjoina("/run/systemd/machines/", machine);
     892           0 :                 r = parse_env_file(NULL, p, "CLASS", &c);
     893           0 :                 if (r == -ENOENT)
     894           0 :                         return -ENXIO;
     895           0 :                 if (r < 0)
     896           0 :                         return r;
     897           0 :                 if (!c)
     898           0 :                         return -EIO;
     899             :         }
     900             : 
     901           0 :         *class = TAKE_PTR(c);
     902           0 :         return 0;
     903             : }
     904             : 
     905           0 : _public_ int sd_machine_get_ifindices(const char *machine, int **ifindices) {
     906           0 :         _cleanup_free_ char *netif = NULL;
     907           0 :         size_t l, allocated = 0, nr = 0;
     908           0 :         int *ni = NULL;
     909             :         const char *p, *word, *state;
     910             :         int r;
     911             : 
     912           0 :         assert_return(machine_name_is_valid(machine), -EINVAL);
     913           0 :         assert_return(ifindices, -EINVAL);
     914             : 
     915           0 :         p = strjoina("/run/systemd/machines/", machine);
     916           0 :         r = parse_env_file(NULL, p, "NETIF", &netif);
     917           0 :         if (r == -ENOENT)
     918           0 :                 return -ENXIO;
     919           0 :         if (r < 0)
     920           0 :                 return r;
     921           0 :         if (!netif) {
     922           0 :                 *ifindices = NULL;
     923           0 :                 return 0;
     924             :         }
     925             : 
     926           0 :         FOREACH_WORD(word, l, netif, state) {
     927           0 :                 char buf[l+1];
     928             :                 int ifi;
     929             : 
     930           0 :                 *(char*) (mempcpy(buf, word, l)) = 0;
     931             : 
     932           0 :                 if (parse_ifindex(buf, &ifi) < 0)
     933           0 :                         continue;
     934             : 
     935           0 :                 if (!GREEDY_REALLOC(ni, allocated, nr+1)) {
     936           0 :                         free(ni);
     937           0 :                         return -ENOMEM;
     938             :                 }
     939             : 
     940           0 :                 ni[nr++] = ifi;
     941             :         }
     942             : 
     943           0 :         *ifindices = ni;
     944           0 :         return nr;
     945             : }
     946             : 
     947           0 : static int MONITOR_TO_FD(sd_login_monitor *m) {
     948           0 :         return (int) (unsigned long) m - 1;
     949             : }
     950             : 
     951           0 : static sd_login_monitor* FD_TO_MONITOR(int fd) {
     952           0 :         return (sd_login_monitor*) (unsigned long) (fd + 1);
     953             : }
     954             : 
     955           0 : _public_ int sd_login_monitor_new(const char *category, sd_login_monitor **m) {
     956           0 :         _cleanup_close_ int fd = -1;
     957           0 :         bool good = false;
     958             :         int k;
     959             : 
     960           0 :         assert_return(m, -EINVAL);
     961             : 
     962           0 :         fd = inotify_init1(IN_NONBLOCK|IN_CLOEXEC);
     963           0 :         if (fd < 0)
     964           0 :                 return -errno;
     965             : 
     966           0 :         if (!category || streq(category, "seat")) {
     967           0 :                 k = inotify_add_watch(fd, "/run/systemd/seats/", IN_MOVED_TO|IN_DELETE);
     968           0 :                 if (k < 0)
     969           0 :                         return -errno;
     970             : 
     971           0 :                 good = true;
     972             :         }
     973             : 
     974           0 :         if (!category || streq(category, "session")) {
     975           0 :                 k = inotify_add_watch(fd, "/run/systemd/sessions/", IN_MOVED_TO|IN_DELETE);
     976           0 :                 if (k < 0)
     977           0 :                         return -errno;
     978             : 
     979           0 :                 good = true;
     980             :         }
     981             : 
     982           0 :         if (!category || streq(category, "uid")) {
     983           0 :                 k = inotify_add_watch(fd, "/run/systemd/users/", IN_MOVED_TO|IN_DELETE);
     984           0 :                 if (k < 0)
     985           0 :                         return -errno;
     986             : 
     987           0 :                 good = true;
     988             :         }
     989             : 
     990           0 :         if (!category || streq(category, "machine")) {
     991           0 :                 k = inotify_add_watch(fd, "/run/systemd/machines/", IN_MOVED_TO|IN_DELETE);
     992           0 :                 if (k < 0)
     993           0 :                         return -errno;
     994             : 
     995           0 :                 good = true;
     996             :         }
     997             : 
     998           0 :         if (!good)
     999           0 :                 return -EINVAL;
    1000             : 
    1001           0 :         *m = FD_TO_MONITOR(fd);
    1002           0 :         fd = -1;
    1003             : 
    1004           0 :         return 0;
    1005             : }
    1006             : 
    1007           0 : _public_ sd_login_monitor* sd_login_monitor_unref(sd_login_monitor *m) {
    1008             :         int fd;
    1009             : 
    1010           0 :         if (!m)
    1011           0 :                 return NULL;
    1012             : 
    1013           0 :         fd = MONITOR_TO_FD(m);
    1014           0 :         close_nointr(fd);
    1015             : 
    1016           0 :         return NULL;
    1017             : }
    1018             : 
    1019           0 : _public_ int sd_login_monitor_flush(sd_login_monitor *m) {
    1020             :         int r;
    1021             : 
    1022           0 :         assert_return(m, -EINVAL);
    1023             : 
    1024           0 :         r = flush_fd(MONITOR_TO_FD(m));
    1025           0 :         if (r < 0)
    1026           0 :                 return r;
    1027             : 
    1028           0 :         return 0;
    1029             : }
    1030             : 
    1031           0 : _public_ int sd_login_monitor_get_fd(sd_login_monitor *m) {
    1032             : 
    1033           0 :         assert_return(m, -EINVAL);
    1034             : 
    1035           0 :         return MONITOR_TO_FD(m);
    1036             : }
    1037             : 
    1038           0 : _public_ int sd_login_monitor_get_events(sd_login_monitor *m) {
    1039             : 
    1040           0 :         assert_return(m, -EINVAL);
    1041             : 
    1042             :         /* For now we will only return POLLIN here, since we don't
    1043             :          * need anything else ever for inotify.  However, let's have
    1044             :          * this API to keep our options open should we later on need
    1045             :          * it. */
    1046           0 :         return POLLIN;
    1047             : }
    1048             : 
    1049           0 : _public_ int sd_login_monitor_get_timeout(sd_login_monitor *m, uint64_t *timeout_usec) {
    1050             : 
    1051           0 :         assert_return(m, -EINVAL);
    1052           0 :         assert_return(timeout_usec, -EINVAL);
    1053             : 
    1054             :         /* For now we will only return (uint64_t) -1, since we don't
    1055             :          * need any timeout. However, let's have this API to keep our
    1056             :          * options open should we later on need it. */
    1057           0 :         *timeout_usec = (uint64_t) -1;
    1058           0 :         return 0;
    1059             : }

Generated by: LCOV version 1.14