chiark / gitweb /
3ae850d80116ba4201e7ec9d4b83a5d6ae40bf69
[elogind.git] / src / sd-login.c
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 General Public License as published by
10   the Free Software Foundation; either version 2 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   General Public License for more details.
17
18   You should have received a copy of the GNU 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
26 #include "util.h"
27 #include "cgroup-util.h"
28 #include "macro.h"
29 #include "sd-login.h"
30
31 _public_ int sd_pid_get_session(pid_t pid, char **session) {
32         int r;
33         char *cg_process, *cg_init, *p;
34
35         if (pid == 0)
36                 pid = getpid();
37
38         if (pid <= 0)
39                 return -EINVAL;
40
41         if (!session)
42                 return -EINVAL;
43
44         r = cg_get_by_pid(SYSTEMD_CGROUP_CONTROLLER, pid, &cg_process);
45         if (r < 0)
46                 return r;
47
48         r = cg_get_by_pid(SYSTEMD_CGROUP_CONTROLLER, 1, &cg_init);
49         if (r < 0) {
50                 free(cg_process);
51                 return r;
52         }
53
54         if (endswith(cg_init, "/system"))
55                 cg_init[strlen(cg_init)-7] = 0;
56         else if (streq(cg_init, "/"))
57                 cg_init[0] = 0;
58
59         if (startswith(cg_process, cg_init))
60                 p = cg_process + strlen(cg_init);
61         else
62                 p = cg_process;
63
64         free(cg_init);
65
66         if (!startswith(p, "/user/")) {
67                 free(cg_process);
68                 return -ENOENT;
69         }
70
71         p += 6;
72         if (startswith(p, "shared/") || streq(p, "shared")) {
73                 free(cg_process);
74                 return -ENOENT;
75         }
76
77         p = strchr(p, '/');
78         if (!p) {
79                 free(cg_process);
80                 return -ENOENT;
81         }
82
83         p++;
84         p = strndup(p, strcspn(p, "/"));
85         free(cg_process);
86
87         if (!p)
88                 return -ENOMEM;
89
90         *session = p;
91         return 0;
92 }
93
94 _public_ int sd_uid_get_state(uid_t uid, char**state) {
95         char *p, *s = NULL;
96         int r;
97
98         if (!state)
99                 return -EINVAL;
100
101         if (asprintf(&p, "/run/systemd/users/%lu", (unsigned long) uid) < 0)
102                 return -ENOMEM;
103
104         r = parse_env_file(p, NEWLINE, "STATE", &s, NULL);
105         free(p);
106
107         if (r == -ENOENT) {
108                 free(s);
109                 s = strdup("offline");
110                 if (!s)
111                         return -ENOMEM;
112
113                 *state = s;
114                 return 0;
115         } else if (r < 0) {
116                 free(s);
117                 return r;
118         } else if (!s)
119                 return -EIO;
120
121         *state = s;
122         return 0;
123 }
124
125 static int uid_is_on_seat_internal(uid_t uid, const char *seat, const char *variable) {
126         char *p, *w, *t, *state, *s = NULL;
127         size_t l;
128         int r;
129
130         if (!seat)
131                 return -EINVAL;
132
133         p = strappend("/run/systemd/seats/", seat);
134         if (!p)
135                 return -ENOMEM;
136
137         r = parse_env_file(p, NEWLINE, "UIDS", &s, NULL);
138         free(p);
139
140         if (r < 0) {
141                 free(s);
142                 return r;
143         }
144
145         if (!s)
146                 return -EIO;
147
148         if (asprintf(&t, "%lu", (unsigned long) uid) < 0) {
149                 free(s);
150                 return -ENOMEM;
151         }
152
153         FOREACH_WORD(w, l, s, state) {
154                 if (strncmp(t, w, l) == 0) {
155                         free(s);
156                         free(t);
157
158                         return 1;
159                 }
160         }
161
162         free(s);
163         free(t);
164
165         return 0;
166 }
167
168 _public_ int sd_uid_is_on_seat(uid_t uid, const char *seat) {
169         return uid_is_on_seat_internal(uid, seat, "UIDS");
170 }
171
172 _public_ int sd_uid_is_active_on_seat(uid_t uid, const char *seat) {
173         return uid_is_on_seat_internal(uid, seat, "ACTIVE_UID");
174 }
175
176 _public_ int sd_session_is_active(const char *session) {
177         int r;
178         char *p, *s = NULL;
179
180         if (!session)
181                 return -EINVAL;
182
183         p = strappend("/run/systemd/sessions/", session);
184         if (!p)
185                 return -ENOMEM;
186
187         r = parse_env_file(p, NEWLINE, "ACTIVE", &s, NULL);
188         free(p);
189
190         if (r < 0) {
191                 free(s);
192                 return r;
193         }
194
195         if (!s)
196                 return -EIO;
197
198         r = parse_boolean(s);
199         free(s);
200
201         return r;
202 }
203
204 _public_ int sd_session_get_uid(const char *session, uid_t *uid) {
205         int r;
206         char *p, *s = NULL;
207         unsigned long ul;
208
209         if (!session)
210                 return -EINVAL;
211         if (!uid)
212                 return -EINVAL;
213
214         p = strappend("/run/systemd/sessions/", session);
215         if (!p)
216                 return -ENOMEM;
217
218         r = parse_env_file(p, NEWLINE, "UID", &s, NULL);
219         free(p);
220
221         if (r < 0) {
222                 free(s);
223                 return r;
224         }
225
226         if (!s)
227                 return -EIO;
228
229         r = safe_atolu(s, &ul);
230         free(s);
231
232         if (r < 0)
233                 return r;
234
235         *uid = (uid_t) ul;
236         return 0;
237 }
238
239 _public_ int sd_session_get_seat(const char *session, char **seat) {
240         char *p, *s = NULL;
241         int r;
242
243         if (!session)
244                 return -EINVAL;
245         if (!seat)
246                 return -EINVAL;
247
248         p = strappend("/run/systemd/sessions/", session);
249         if (!p)
250                 return -ENOMEM;
251
252         r = parse_env_file(p, NEWLINE, "SEAT", &s, NULL);
253         free(p);
254
255         if (r < 0) {
256                 free(s);
257                 return r;
258         }
259
260         if (isempty(s))
261                 return -ENOENT;
262
263         *seat = s;
264         return 0;
265 }
266
267 _public_ int sd_seat_get_active(const char *seat, char **session, uid_t *uid) {
268         char *p, *s = NULL, *t = NULL;
269         int r;
270
271         if (!seat)
272                 return -EINVAL;
273         if (!session && !uid)
274                 return -EINVAL;
275
276         p = strappend("/run/systemd/seats/", seat);
277         if (!p)
278                 return -ENOMEM;
279
280         r = parse_env_file(p, NEWLINE,
281                            "ACTIVE", &s,
282                            "ACTIVE_UID", &t,
283                            NULL);
284         free(p);
285
286         if (r < 0) {
287                 free(s);
288                 free(t);
289                 return r;
290         }
291
292         if (session && !s)  {
293                 free(t);
294                 return -EIO;
295         }
296
297         if (uid && !t) {
298                 free(s);
299                 return -EIO;
300         }
301
302         if (uid && t) {
303                 unsigned long ul;
304
305                 r = safe_atolu(t, &ul);
306                 if (r < 0) {
307                         free(t);
308                         free(s);
309                         return r;
310                 }
311
312                 *uid = (uid_t) ul;
313         }
314
315         free(t);
316
317         if (session && s)
318                 *session = s;
319         else
320                 free(s);
321
322         return 0;
323 }