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 : }
|