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