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