LCOV - code coverage report
Current view: top level - libsystemd/sd-login - sd-login.c (source / functions) Hit Total Coverage
Test: systemd test coverage Lines: 16 528 3.0 %
Date: 2015-07-29 18:47:03 Functions: 3 58 5.2 %

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

Generated by: LCOV version 1.11