]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/shared/util.c
journal: initialize libgcrypt explicitly, before using HMAC
[thirdparty/systemd.git] / src / shared / util.c
CommitLineData
d6c9574f 1/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
60918275 2
a7334b09
LP
3/***
4 This file is part of systemd.
5
6 Copyright 2010 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
a7334b09
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.
a7334b09 17
5430f7f2 18 You should have received a copy of the GNU Lesser General Public License
a7334b09
LP
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20***/
21
60918275
LP
22#include <assert.h>
23#include <string.h>
24#include <unistd.h>
25#include <errno.h>
85261803 26#include <stdlib.h>
034c6ed7
LP
27#include <signal.h>
28#include <stdio.h>
1dccbe19
LP
29#include <syslog.h>
30#include <sched.h>
31#include <sys/resource.h>
ef886c6a 32#include <linux/sched.h>
a9f5d454
LP
33#include <sys/types.h>
34#include <sys/stat.h>
3a0ecb08 35#include <fcntl.h>
a0d40ac5 36#include <dirent.h>
601f6a1e
LP
37#include <sys/ioctl.h>
38#include <linux/vt.h>
39#include <linux/tiocl.h>
80876c20
LP
40#include <termios.h>
41#include <stdarg.h>
42#include <sys/inotify.h>
43#include <sys/poll.h>
8d567588 44#include <libgen.h>
3177a7fa 45#include <ctype.h>
5b6319dc 46#include <sys/prctl.h>
ef2f1067
LP
47#include <sys/utsname.h>
48#include <pwd.h>
4fd5948e 49#include <netinet/ip.h>
3fe5e5d4 50#include <linux/kd.h>
afea26ad 51#include <dlfcn.h>
2e78aa99 52#include <sys/wait.h>
7948c4df 53#include <sys/time.h>
8092a428 54#include <glob.h>
4b67834e 55#include <grp.h>
87d2c1ff 56#include <sys/mman.h>
825c6fe5
LP
57#include <sys/vfs.h>
58#include <linux/magic.h>
60918275
LP
59
60#include "macro.h"
61#include "util.h"
1dccbe19
LP
62#include "ioprio.h"
63#include "missing.h"
a9f5d454 64#include "log.h"
65d2ebdc 65#include "strv.h"
e51bc1a2 66#include "label.h"
9eb977db 67#include "path-util.h"
d06dacd0 68#include "exit-status.h"
83cc030f 69#include "hashmap.h"
56cf987f 70
9a0e6896
LP
71int saved_argc = 0;
72char **saved_argv = NULL;
73
37f85e66 74size_t page_size(void) {
75 static __thread size_t pgsz = 0;
76 long r;
77
87d2c1ff 78 if (_likely_(pgsz > 0))
37f85e66 79 return pgsz;
80
81 assert_se((r = sysconf(_SC_PAGESIZE)) > 0);
82
83 pgsz = (size_t) r;
84
85 return pgsz;
86}
87
e05797fb
LP
88bool streq_ptr(const char *a, const char *b) {
89
90 /* Like streq(), but tries to make sense of NULL pointers */
91
92 if (a && b)
93 return streq(a, b);
94
95 if (!a && !b)
96 return true;
97
98 return false;
99}
100
47be870b 101usec_t now(clockid_t clock_id) {
60918275
LP
102 struct timespec ts;
103
47be870b 104 assert_se(clock_gettime(clock_id, &ts) == 0);
60918275
LP
105
106 return timespec_load(&ts);
107}
108
63983207 109dual_timestamp* dual_timestamp_get(dual_timestamp *ts) {
871d7de4
LP
110 assert(ts);
111
112 ts->realtime = now(CLOCK_REALTIME);
113 ts->monotonic = now(CLOCK_MONOTONIC);
114
115 return ts;
116}
117
a185c5aa
LP
118dual_timestamp* dual_timestamp_from_realtime(dual_timestamp *ts, usec_t u) {
119 int64_t delta;
120 assert(ts);
121
122 ts->realtime = u;
123
124 if (u == 0)
125 ts->monotonic = 0;
126 else {
127 delta = (int64_t) now(CLOCK_REALTIME) - (int64_t) u;
128
129 ts->monotonic = now(CLOCK_MONOTONIC);
130
131 if ((int64_t) ts->monotonic > delta)
132 ts->monotonic -= delta;
133 else
134 ts->monotonic = 0;
135 }
136
137 return ts;
138}
139
60918275
LP
140usec_t timespec_load(const struct timespec *ts) {
141 assert(ts);
142
143 return
144 (usec_t) ts->tv_sec * USEC_PER_SEC +
145 (usec_t) ts->tv_nsec / NSEC_PER_USEC;
146}
147
148struct timespec *timespec_store(struct timespec *ts, usec_t u) {
149 assert(ts);
150
151 ts->tv_sec = (time_t) (u / USEC_PER_SEC);
152 ts->tv_nsec = (long int) ((u % USEC_PER_SEC) * NSEC_PER_USEC);
153
154 return ts;
155}
156
157usec_t timeval_load(const struct timeval *tv) {
158 assert(tv);
159
160 return
161 (usec_t) tv->tv_sec * USEC_PER_SEC +
162 (usec_t) tv->tv_usec;
163}
164
165struct timeval *timeval_store(struct timeval *tv, usec_t u) {
166 assert(tv);
167
168 tv->tv_sec = (time_t) (u / USEC_PER_SEC);
169 tv->tv_usec = (suseconds_t) (u % USEC_PER_SEC);
170
171 return tv;
172}
173
174bool endswith(const char *s, const char *postfix) {
175 size_t sl, pl;
176
177 assert(s);
178 assert(postfix);
179
180 sl = strlen(s);
181 pl = strlen(postfix);
182
d4d0d4db
LP
183 if (pl == 0)
184 return true;
185
60918275
LP
186 if (sl < pl)
187 return false;
188
189 return memcmp(s + sl - pl, postfix, pl) == 0;
190}
191
192bool startswith(const char *s, const char *prefix) {
193 size_t sl, pl;
194
195 assert(s);
196 assert(prefix);
197
198 sl = strlen(s);
199 pl = strlen(prefix);
200
d4d0d4db
LP
201 if (pl == 0)
202 return true;
203
60918275
LP
204 if (sl < pl)
205 return false;
206
207 return memcmp(s, prefix, pl) == 0;
208}
209
3177a7fa
MAP
210bool startswith_no_case(const char *s, const char *prefix) {
211 size_t sl, pl;
212 unsigned i;
213
214 assert(s);
215 assert(prefix);
216
217 sl = strlen(s);
218 pl = strlen(prefix);
219
220 if (pl == 0)
221 return true;
222
223 if (sl < pl)
224 return false;
225
226 for(i = 0; i < pl; ++i) {
227 if (tolower(s[i]) != tolower(prefix[i]))
228 return false;
229 }
230
231 return true;
232}
233
79d6d816
LP
234bool first_word(const char *s, const char *word) {
235 size_t sl, wl;
236
237 assert(s);
238 assert(word);
239
240 sl = strlen(s);
241 wl = strlen(word);
242
243 if (sl < wl)
244 return false;
245
d4d0d4db
LP
246 if (wl == 0)
247 return true;
248
79d6d816
LP
249 if (memcmp(s, word, wl) != 0)
250 return false;
251
d4d0d4db
LP
252 return s[wl] == 0 ||
253 strchr(WHITESPACE, s[wl]);
79d6d816
LP
254}
255
42f4e3c4 256int close_nointr(int fd) {
60918275
LP
257 assert(fd >= 0);
258
259 for (;;) {
260 int r;
261
48f82119
LP
262 r = close(fd);
263 if (r >= 0)
60918275
LP
264 return r;
265
266 if (errno != EINTR)
48f82119 267 return -errno;
60918275
LP
268 }
269}
85261803 270
85f136b5 271void close_nointr_nofail(int fd) {
80876c20 272 int saved_errno = errno;
85f136b5
LP
273
274 /* like close_nointr() but cannot fail, and guarantees errno
275 * is unchanged */
276
277 assert_se(close_nointr(fd) == 0);
80876c20
LP
278
279 errno = saved_errno;
85f136b5
LP
280}
281
5b6319dc
LP
282void close_many(const int fds[], unsigned n_fd) {
283 unsigned i;
284
285 for (i = 0; i < n_fd; i++)
286 close_nointr_nofail(fds[i]);
287}
288
85261803
LP
289int parse_boolean(const char *v) {
290 assert(v);
291
44d8db9e 292 if (streq(v, "1") || v[0] == 'y' || v[0] == 'Y' || v[0] == 't' || v[0] == 'T' || !strcasecmp(v, "on"))
85261803 293 return 1;
44d8db9e 294 else if (streq(v, "0") || v[0] == 'n' || v[0] == 'N' || v[0] == 'f' || v[0] == 'F' || !strcasecmp(v, "off"))
85261803
LP
295 return 0;
296
297 return -EINVAL;
298}
299
3ba686c1 300int parse_pid(const char *s, pid_t* ret_pid) {
0b172489 301 unsigned long ul = 0;
3ba686c1
LP
302 pid_t pid;
303 int r;
304
305 assert(s);
306 assert(ret_pid);
307
308 if ((r = safe_atolu(s, &ul)) < 0)
309 return r;
310
311 pid = (pid_t) ul;
312
313 if ((unsigned long) pid != ul)
314 return -ERANGE;
315
316 if (pid <= 0)
317 return -ERANGE;
318
319 *ret_pid = pid;
320 return 0;
321}
322
034a2a52
LP
323int parse_uid(const char *s, uid_t* ret_uid) {
324 unsigned long ul = 0;
325 uid_t uid;
326 int r;
327
328 assert(s);
329 assert(ret_uid);
330
331 if ((r = safe_atolu(s, &ul)) < 0)
332 return r;
333
334 uid = (uid_t) ul;
335
336 if ((unsigned long) uid != ul)
337 return -ERANGE;
338
339 *ret_uid = uid;
340 return 0;
341}
342
85261803
LP
343int safe_atou(const char *s, unsigned *ret_u) {
344 char *x = NULL;
034c6ed7 345 unsigned long l;
85261803
LP
346
347 assert(s);
348 assert(ret_u);
349
350 errno = 0;
351 l = strtoul(s, &x, 0);
352
353 if (!x || *x || errno)
354 return errno ? -errno : -EINVAL;
355
034c6ed7 356 if ((unsigned long) (unsigned) l != l)
85261803
LP
357 return -ERANGE;
358
359 *ret_u = (unsigned) l;
360 return 0;
361}
362
363int safe_atoi(const char *s, int *ret_i) {
364 char *x = NULL;
034c6ed7 365 long l;
85261803
LP
366
367 assert(s);
368 assert(ret_i);
369
370 errno = 0;
371 l = strtol(s, &x, 0);
372
373 if (!x || *x || errno)
374 return errno ? -errno : -EINVAL;
375
034c6ed7 376 if ((long) (int) l != l)
85261803
LP
377 return -ERANGE;
378
034c6ed7
LP
379 *ret_i = (int) l;
380 return 0;
381}
382
034c6ed7
LP
383int safe_atollu(const char *s, long long unsigned *ret_llu) {
384 char *x = NULL;
385 unsigned long long l;
386
387 assert(s);
388 assert(ret_llu);
389
390 errno = 0;
391 l = strtoull(s, &x, 0);
392
393 if (!x || *x || errno)
394 return errno ? -errno : -EINVAL;
395
396 *ret_llu = l;
397 return 0;
398}
399
400int safe_atolli(const char *s, long long int *ret_lli) {
401 char *x = NULL;
402 long long l;
403
404 assert(s);
405 assert(ret_lli);
406
407 errno = 0;
408 l = strtoll(s, &x, 0);
409
410 if (!x || *x || errno)
411 return errno ? -errno : -EINVAL;
412
413 *ret_lli = l;
85261803
LP
414 return 0;
415}
a41e8209 416
a41e8209 417/* Split a string into words. */
65d2ebdc 418char *split(const char *c, size_t *l, const char *separator, char **state) {
a41e8209
LP
419 char *current;
420
421 current = *state ? *state : (char*) c;
422
423 if (!*current || *c == 0)
424 return NULL;
425
65d2ebdc
LP
426 current += strspn(current, separator);
427 *l = strcspn(current, separator);
82919e3d
LP
428 *state = current+*l;
429
430 return (char*) current;
431}
432
034c6ed7
LP
433/* Split a string into words, but consider strings enclosed in '' and
434 * "" as words even if they include spaces. */
435char *split_quoted(const char *c, size_t *l, char **state) {
0bab36f2
LP
436 char *current, *e;
437 bool escaped = false;
034c6ed7
LP
438
439 current = *state ? *state : (char*) c;
440
441 if (!*current || *c == 0)
442 return NULL;
443
444 current += strspn(current, WHITESPACE);
445
446 if (*current == '\'') {
447 current ++;
034c6ed7 448
0bab36f2
LP
449 for (e = current; *e; e++) {
450 if (escaped)
451 escaped = false;
452 else if (*e == '\\')
453 escaped = true;
454 else if (*e == '\'')
455 break;
456 }
457
458 *l = e-current;
459 *state = *e == 0 ? e : e+1;
034c6ed7
LP
460 } else if (*current == '\"') {
461 current ++;
034c6ed7 462
0bab36f2
LP
463 for (e = current; *e; e++) {
464 if (escaped)
465 escaped = false;
466 else if (*e == '\\')
467 escaped = true;
468 else if (*e == '\"')
469 break;
470 }
471
472 *l = e-current;
473 *state = *e == 0 ? e : e+1;
034c6ed7 474 } else {
0bab36f2
LP
475 for (e = current; *e; e++) {
476 if (escaped)
477 escaped = false;
478 else if (*e == '\\')
479 escaped = true;
480 else if (strchr(WHITESPACE, *e))
481 break;
482 }
483 *l = e-current;
484 *state = e;
034c6ed7
LP
485 }
486
487 return (char*) current;
488}
489
034c6ed7
LP
490int get_parent_of_pid(pid_t pid, pid_t *_ppid) {
491 int r;
492 FILE *f;
20c03b7b 493 char fn[PATH_MAX], line[LINE_MAX], *p;
bb00e604 494 long unsigned ppid;
034c6ed7 495
8480e784 496 assert(pid > 0);
034c6ed7
LP
497 assert(_ppid);
498
bb00e604 499 assert_se(snprintf(fn, sizeof(fn)-1, "/proc/%lu/stat", (unsigned long) pid) < (int) (sizeof(fn)-1));
8480e784 500 char_array_0(fn);
034c6ed7 501
ccaa6149 502 if (!(f = fopen(fn, "re")))
034c6ed7
LP
503 return -errno;
504
505 if (!(fgets(line, sizeof(line), f))) {
35d50f55 506 r = feof(f) ? -EIO : -errno;
034c6ed7
LP
507 fclose(f);
508 return r;
509 }
510
511 fclose(f);
512
513 /* Let's skip the pid and comm fields. The latter is enclosed
514 * in () but does not escape any () in its value, so let's
515 * skip over it manually */
516
517 if (!(p = strrchr(line, ')')))
518 return -EIO;
519
520 p++;
521
522 if (sscanf(p, " "
523 "%*c " /* state */
bb00e604 524 "%lu ", /* ppid */
034c6ed7
LP
525 &ppid) != 1)
526 return -EIO;
527
bb00e604 528 if ((long unsigned) (pid_t) ppid != ppid)
034c6ed7
LP
529 return -ERANGE;
530
531 *_ppid = (pid_t) ppid;
532
533 return 0;
534}
535
7640a5de
LP
536int get_starttime_of_pid(pid_t pid, unsigned long long *st) {
537 int r;
538 FILE *f;
539 char fn[PATH_MAX], line[LINE_MAX], *p;
540
541 assert(pid > 0);
542 assert(st);
543
544 assert_se(snprintf(fn, sizeof(fn)-1, "/proc/%lu/stat", (unsigned long) pid) < (int) (sizeof(fn)-1));
545 char_array_0(fn);
546
ccaa6149 547 if (!(f = fopen(fn, "re")))
7640a5de
LP
548 return -errno;
549
550 if (!(fgets(line, sizeof(line), f))) {
35d50f55 551 r = feof(f) ? -EIO : -errno;
7640a5de
LP
552 fclose(f);
553 return r;
554 }
555
556 fclose(f);
557
558 /* Let's skip the pid and comm fields. The latter is enclosed
559 * in () but does not escape any () in its value, so let's
560 * skip over it manually */
561
562 if (!(p = strrchr(line, ')')))
563 return -EIO;
564
565 p++;
566
567 if (sscanf(p, " "
568 "%*c " /* state */
569 "%*d " /* ppid */
570 "%*d " /* pgrp */
571 "%*d " /* session */
572 "%*d " /* tty_nr */
573 "%*d " /* tpgid */
574 "%*u " /* flags */
575 "%*u " /* minflt */
576 "%*u " /* cminflt */
577 "%*u " /* majflt */
578 "%*u " /* cmajflt */
579 "%*u " /* utime */
580 "%*u " /* stime */
581 "%*d " /* cutime */
582 "%*d " /* cstime */
583 "%*d " /* priority */
584 "%*d " /* nice */
585 "%*d " /* num_threads */
586 "%*d " /* itrealvalue */
587 "%llu " /* starttime */,
588 st) != 1)
589 return -EIO;
590
591 return 0;
592}
593
034c6ed7
LP
594int write_one_line_file(const char *fn, const char *line) {
595 FILE *f;
596 int r;
597
598 assert(fn);
599 assert(line);
600
03ad1136
LP
601 f = fopen(fn, "we");
602 if (!f)
034c6ed7
LP
603 return -errno;
604
34ca941c 605 errno = 0;
034c6ed7
LP
606 if (fputs(line, f) < 0) {
607 r = -errno;
608 goto finish;
609 }
610
8e1bd70d
LP
611 if (!endswith(line, "\n"))
612 fputc('\n', f);
613
151b190e
LP
614 fflush(f);
615
616 if (ferror(f)) {
617 if (errno != 0)
618 r = -errno;
619 else
620 r = -EIO;
621 } else
622 r = 0;
623
034c6ed7
LP
624finish:
625 fclose(f);
626 return r;
627}
628
34ca941c
LP
629int fchmod_umask(int fd, mode_t m) {
630 mode_t u;
631 int r;
632
633 u = umask(0777);
634 r = fchmod(fd, m & (~u)) < 0 ? -errno : 0;
635 umask(u);
636
637 return r;
638}
639
640int write_one_line_file_atomic(const char *fn, const char *line) {
641 FILE *f;
642 int r;
643 char *p;
644
645 assert(fn);
646 assert(line);
647
648 r = fopen_temporary(fn, &f, &p);
649 if (r < 0)
650 return r;
651
652 fchmod_umask(fileno(f), 0644);
653
654 errno = 0;
655 if (fputs(line, f) < 0) {
656 r = -errno;
657 goto finish;
658 }
659
660 if (!endswith(line, "\n"))
661 fputc('\n', f);
662
663 fflush(f);
664
665 if (ferror(f)) {
666 if (errno != 0)
667 r = -errno;
668 else
669 r = -EIO;
670 } else {
671 if (rename(p, fn) < 0)
672 r = -errno;
673 else
674 r = 0;
675 }
676
677finish:
678 if (r < 0)
679 unlink(p);
680
681 fclose(f);
682 free(p);
683
684 return r;
685}
686
034c6ed7
LP
687int read_one_line_file(const char *fn, char **line) {
688 FILE *f;
689 int r;
97c4a07d 690 char t[LINE_MAX], *c;
034c6ed7
LP
691
692 assert(fn);
693 assert(line);
694
4099a281
LP
695 f = fopen(fn, "re");
696 if (!f)
034c6ed7
LP
697 return -errno;
698
4099a281
LP
699 if (!fgets(t, sizeof(t), f)) {
700
701 if (ferror(f)) {
702 r = -errno;
703 goto finish;
704 }
705
706 t[0] = 0;
034c6ed7
LP
707 }
708
4099a281
LP
709 c = strdup(t);
710 if (!c) {
034c6ed7
LP
711 r = -ENOMEM;
712 goto finish;
713 }
714
6f9a471a
LP
715 truncate_nl(c);
716
034c6ed7
LP
717 *line = c;
718 r = 0;
719
720finish:
721 fclose(f);
722 return r;
723}
44d8db9e 724
34ca941c 725int read_full_file(const char *fn, char **contents, size_t *size) {
97c4a07d
LP
726 FILE *f;
727 int r;
728 size_t n, l;
729 char *buf = NULL;
730 struct stat st;
731
732 if (!(f = fopen(fn, "re")))
733 return -errno;
734
735 if (fstat(fileno(f), &st) < 0) {
736 r = -errno;
737 goto finish;
738 }
739
34ca941c
LP
740 /* Safety check */
741 if (st.st_size > 4*1024*1024) {
742 r = -E2BIG;
743 goto finish;
744 }
745
97c4a07d
LP
746 n = st.st_size > 0 ? st.st_size : LINE_MAX;
747 l = 0;
748
749 for (;;) {
750 char *t;
751 size_t k;
752
753 if (!(t = realloc(buf, n+1))) {
754 r = -ENOMEM;
755 goto finish;
756 }
757
758 buf = t;
759 k = fread(buf + l, 1, n - l, f);
760
761 if (k <= 0) {
762 if (ferror(f)) {
763 r = -errno;
764 goto finish;
765 }
766
767 break;
768 }
769
770 l += k;
771 n *= 2;
772
773 /* Safety check */
774 if (n > 4*1024*1024) {
775 r = -E2BIG;
776 goto finish;
777 }
778 }
779
f8440af5 780 buf[l] = 0;
97c4a07d
LP
781 *contents = buf;
782 buf = NULL;
783
34ca941c
LP
784 if (size)
785 *size = l;
786
97c4a07d
LP
787 r = 0;
788
789finish:
790 fclose(f);
791 free(buf);
792
793 return r;
794}
795
796int parse_env_file(
797 const char *fname,
c899f8c6 798 const char *separator, ...) {
97c4a07d 799
ce8a6aa1 800 int r = 0;
44d91056 801 char *contents = NULL, *p;
97c4a07d
LP
802
803 assert(fname);
c899f8c6 804 assert(separator);
97c4a07d 805
34ca941c 806 if ((r = read_full_file(fname, &contents, NULL)) < 0)
97c4a07d
LP
807 return r;
808
809 p = contents;
810 for (;;) {
811 const char *key = NULL;
812
c899f8c6 813 p += strspn(p, separator);
97c4a07d
LP
814 p += strspn(p, WHITESPACE);
815
816 if (!*p)
817 break;
818
819 if (!strchr(COMMENTS, *p)) {
820 va_list ap;
821 char **value;
822
c899f8c6 823 va_start(ap, separator);
97c4a07d
LP
824 while ((key = va_arg(ap, char *))) {
825 size_t n;
826 char *v;
827
828 value = va_arg(ap, char **);
829
830 n = strlen(key);
831 if (strncmp(p, key, n) != 0 ||
832 p[n] != '=')
833 continue;
834
835 p += n + 1;
c899f8c6 836 n = strcspn(p, separator);
97c4a07d
LP
837
838 if (n >= 2 &&
e7db37dd
LP
839 strchr(QUOTES, p[0]) &&
840 p[n-1] == p[0])
97c4a07d
LP
841 v = strndup(p+1, n-2);
842 else
843 v = strndup(p, n);
844
845 if (!v) {
846 r = -ENOMEM;
847 va_end(ap);
848 goto fail;
849 }
850
dd36de4d
KS
851 if (v[0] == '\0') {
852 /* return empty value strings as NULL */
853 free(v);
854 v = NULL;
855 }
856
97c4a07d
LP
857 free(*value);
858 *value = v;
859
860 p += n;
ce8a6aa1
LP
861
862 r ++;
97c4a07d
LP
863 break;
864 }
865 va_end(ap);
866 }
867
868 if (!key)
c899f8c6 869 p += strcspn(p, separator);
97c4a07d
LP
870 }
871
97c4a07d
LP
872fail:
873 free(contents);
874 return r;
875}
876
8c7be95e
LP
877int load_env_file(
878 const char *fname,
879 char ***rl) {
880
881 FILE *f;
6a39419f 882 char **m = NULL;
8c7be95e
LP
883 int r;
884
885 assert(fname);
886 assert(rl);
887
888 if (!(f = fopen(fname, "re")))
889 return -errno;
890
891 while (!feof(f)) {
892 char l[LINE_MAX], *p, *u;
893 char **t;
894
895 if (!fgets(l, sizeof(l), f)) {
896 if (feof(f))
897 break;
898
899 r = -errno;
900 goto finish;
901 }
902
903 p = strstrip(l);
904
905 if (!*p)
906 continue;
907
908 if (strchr(COMMENTS, *p))
909 continue;
910
911 if (!(u = normalize_env_assignment(p))) {
0d0f0c50 912 r = log_oom();
8c7be95e
LP
913 goto finish;
914 }
915
916 t = strv_append(m, u);
917 free(u);
918
919 if (!t) {
0d0f0c50 920 r = log_oom();
8c7be95e
LP
921 goto finish;
922 }
923
924 strv_free(m);
925 m = t;
926 }
927
928 r = 0;
929
930 *rl = m;
931 m = NULL;
932
933finish:
934 if (f)
935 fclose(f);
936
937 strv_free(m);
938
939 return r;
940}
941
7640a5de 942int write_env_file(const char *fname, char **l) {
34ca941c 943 char **i, *p;
7640a5de
LP
944 FILE *f;
945 int r;
946
34ca941c
LP
947 r = fopen_temporary(fname, &f, &p);
948 if (r < 0)
949 return r;
7640a5de 950
34ca941c
LP
951 fchmod_umask(fileno(f), 0644);
952
953 errno = 0;
7640a5de
LP
954 STRV_FOREACH(i, l) {
955 fputs(*i, f);
956 fputc('\n', f);
957 }
958
959 fflush(f);
960
34ca941c
LP
961 if (ferror(f)) {
962 if (errno != 0)
963 r = -errno;
964 else
965 r = -EIO;
966 } else {
967 if (rename(p, fname) < 0)
968 r = -errno;
969 else
970 r = 0;
971 }
972
973 if (r < 0)
974 unlink(p);
975
7640a5de 976 fclose(f);
34ca941c 977 free(p);
7640a5de
LP
978
979 return r;
980}
981
7072ced8
LP
982char *truncate_nl(char *s) {
983 assert(s);
984
985 s[strcspn(s, NEWLINE)] = 0;
986 return s;
987}
988
87d2c1ff 989int get_process_comm(pid_t pid, char **name) {
7072ced8
LP
990 int r;
991
7072ced8
LP
992 assert(name);
993
87d2c1ff
LP
994 if (pid == 0)
995 r = read_one_line_file("/proc/self/comm", name);
996 else {
997 char *p;
998 if (asprintf(&p, "/proc/%lu/comm", (unsigned long) pid) < 0)
999 return -ENOMEM;
7072ced8 1000
87d2c1ff
LP
1001 r = read_one_line_file(p, name);
1002 free(p);
1003 }
7072ced8 1004
87d2c1ff 1005 return r;
7072ced8
LP
1006}
1007
87d2c1ff
LP
1008int get_process_cmdline(pid_t pid, size_t max_length, bool comm_fallback, char **line) {
1009 char *r, *k;
c59760ee
LP
1010 int c;
1011 bool space = false;
1012 size_t left;
1013 FILE *f;
1014
c59760ee
LP
1015 assert(max_length > 0);
1016 assert(line);
1017
87d2c1ff
LP
1018 if (pid == 0)
1019 f = fopen("/proc/self/cmdline", "re");
1020 else {
1021 char *p;
1022 if (asprintf(&p, "/proc/%lu/cmdline", (unsigned long) pid) < 0)
1023 return -ENOMEM;
c59760ee 1024
87d2c1ff
LP
1025 f = fopen(p, "re");
1026 free(p);
1027 }
c59760ee
LP
1028
1029 if (!f)
1030 return -errno;
1031
87d2c1ff
LP
1032 r = new(char, max_length);
1033 if (!r) {
c59760ee
LP
1034 fclose(f);
1035 return -ENOMEM;
1036 }
1037
1038 k = r;
1039 left = max_length;
1040 while ((c = getc(f)) != EOF) {
1041
1042 if (isprint(c)) {
1043 if (space) {
1044 if (left <= 4)
1045 break;
1046
1047 *(k++) = ' ';
057fbb58 1048 left--;
c59760ee
LP
1049 space = false;
1050 }
1051
1052 if (left <= 4)
1053 break;
1054
1055 *(k++) = (char) c;
057fbb58 1056 left--;
c59760ee
LP
1057 } else
1058 space = true;
1059 }
1060
1061 if (left <= 4) {
1062 size_t n = MIN(left-1, 3U);
1063 memcpy(k, "...", n);
1064 k[n] = 0;
1065 } else
1066 *k = 0;
1067
1068 fclose(f);
1069
35d2e7ec
LP
1070 /* Kernel threads have no argv[] */
1071 if (r[0] == 0) {
1072 char *t;
1073 int h;
1074
1075 free(r);
1076
87d2c1ff
LP
1077 if (!comm_fallback)
1078 return -ENOENT;
1079
1080 h = get_process_comm(pid, &t);
1081 if (h < 0)
35d2e7ec
LP
1082 return h;
1083
b7def684 1084 r = strjoin("[", t, "]", NULL);
35d2e7ec
LP
1085 free(t);
1086
87d2c1ff 1087 if (!r)
35d2e7ec
LP
1088 return -ENOMEM;
1089 }
fa776d8e 1090
c59760ee
LP
1091 *line = r;
1092 return 0;
1093}
1094
1e5678d0
LP
1095int is_kernel_thread(pid_t pid) {
1096 char *p;
1097 size_t count;
1098 char c;
1099 bool eof;
1100 FILE *f;
1101
1102 if (pid == 0)
1103 return 0;
1104
1105 if (asprintf(&p, "/proc/%lu/cmdline", (unsigned long) pid) < 0)
1106 return -ENOMEM;
1107
1108 f = fopen(p, "re");
1109 free(p);
1110
1111 if (!f)
1112 return -errno;
1113
1114 count = fread(&c, 1, 1, f);
1115 eof = feof(f);
1116 fclose(f);
1117
1118 /* Kernel threads have an empty cmdline */
1119
1120 if (count <= 0)
1121 return eof ? 1 : -errno;
1122
1123 return 0;
1124}
1125
87d2c1ff
LP
1126int get_process_exe(pid_t pid, char **name) {
1127 int r;
1128
1129 assert(name);
1130
1131 if (pid == 0)
1132 r = readlink_malloc("/proc/self/exe", name);
1133 else {
1134 char *p;
1135 if (asprintf(&p, "/proc/%lu/exe", (unsigned long) pid) < 0)
1136 return -ENOMEM;
1137
1138 r = readlink_malloc(p, name);
1139 free(p);
1140 }
1141
1142 return r;
1143}
1144
7e4ab3c5
LP
1145int get_process_uid(pid_t pid, uid_t *uid) {
1146 char *p;
1147 FILE *f;
1148 int r;
1149
1150 assert(uid);
1151
1152 if (pid == 0)
1153 return getuid();
1154
1155 if (asprintf(&p, "/proc/%lu/status", (unsigned long) pid) < 0)
1156 return -ENOMEM;
1157
1158 f = fopen(p, "re");
1159 free(p);
1160
1161 if (!f)
1162 return -errno;
1163
1164 while (!feof(f)) {
1165 char line[LINE_MAX], *l;
1166
1167 if (!fgets(line, sizeof(line), f)) {
1168 if (feof(f))
1169 break;
1170
1171 r = -errno;
1172 goto finish;
1173 }
1174
1175 l = strstrip(line);
1176
1177 if (startswith(l, "Uid:")) {
1178 l += 4;
1179 l += strspn(l, WHITESPACE);
1180
1181 l[strcspn(l, WHITESPACE)] = 0;
1182
1183 r = parse_uid(l, uid);
1184 goto finish;
1185 }
1186 }
1187
1188 r = -EIO;
1189
1190finish:
1191 fclose(f);
1192
1193 return r;
1194}
1195
fab56fc5
LP
1196char *strnappend(const char *s, const char *suffix, size_t b) {
1197 size_t a;
44d8db9e
LP
1198 char *r;
1199
fab56fc5
LP
1200 if (!s && !suffix)
1201 return strdup("");
1202
1203 if (!s)
1204 return strndup(suffix, b);
1205
1206 if (!suffix)
1207 return strdup(s);
1208
44d8db9e
LP
1209 assert(s);
1210 assert(suffix);
1211
1212 a = strlen(s);
44d8db9e
LP
1213
1214 if (!(r = new(char, a+b+1)))
1215 return NULL;
1216
1217 memcpy(r, s, a);
1218 memcpy(r+a, suffix, b);
1219 r[a+b] = 0;
1220
1221 return r;
1222}
87f0e418 1223
fab56fc5
LP
1224char *strappend(const char *s, const char *suffix) {
1225 return strnappend(s, suffix, suffix ? strlen(suffix) : 0);
1226}
1227
87f0e418
LP
1228int readlink_malloc(const char *p, char **r) {
1229 size_t l = 100;
1230
1231 assert(p);
1232 assert(r);
1233
1234 for (;;) {
1235 char *c;
1236 ssize_t n;
1237
1238 if (!(c = new(char, l)))
1239 return -ENOMEM;
1240
1241 if ((n = readlink(p, c, l-1)) < 0) {
1242 int ret = -errno;
1243 free(c);
1244 return ret;
1245 }
1246
1247 if ((size_t) n < l-1) {
1248 c[n] = 0;
1249 *r = c;
1250 return 0;
1251 }
1252
1253 free(c);
1254 l *= 2;
1255 }
1256}
1257
2c7108c4
LP
1258int readlink_and_make_absolute(const char *p, char **r) {
1259 char *target, *k;
1260 int j;
1261
1262 assert(p);
1263 assert(r);
1264
1265 if ((j = readlink_malloc(p, &target)) < 0)
1266 return j;
1267
1268 k = file_in_same_dir(p, target);
1269 free(target);
1270
1271 if (!k)
1272 return -ENOMEM;
1273
1274 *r = k;
1275 return 0;
1276}
1277
83096483
LP
1278int readlink_and_canonicalize(const char *p, char **r) {
1279 char *t, *s;
1280 int j;
1281
1282 assert(p);
1283 assert(r);
1284
1285 j = readlink_and_make_absolute(p, &t);
1286 if (j < 0)
1287 return j;
1288
1289 s = canonicalize_file_name(t);
1290 if (s) {
1291 free(t);
1292 *r = s;
1293 } else
1294 *r = t;
1295
1296 path_kill_slashes(*r);
1297
1298 return 0;
1299}
1300
2a987ee8
LP
1301int reset_all_signal_handlers(void) {
1302 int sig;
1303
1304 for (sig = 1; sig < _NSIG; sig++) {
1305 struct sigaction sa;
1306
1307 if (sig == SIGKILL || sig == SIGSTOP)
1308 continue;
1309
1310 zero(sa);
1311 sa.sa_handler = SIG_DFL;
431c32bf 1312 sa.sa_flags = SA_RESTART;
2a987ee8
LP
1313
1314 /* On Linux the first two RT signals are reserved by
1315 * glibc, and sigaction() will return EINVAL for them. */
1316 if ((sigaction(sig, &sa, NULL) < 0))
1317 if (errno != EINVAL)
1318 return -errno;
1319 }
1320
8e274523 1321 return 0;
2a987ee8 1322}
4a72ff34
LP
1323
1324char *strstrip(char *s) {
57a8eca8 1325 char *e;
4a72ff34
LP
1326
1327 /* Drops trailing whitespace. Modifies the string in
1328 * place. Returns pointer to first non-space character */
1329
1330 s += strspn(s, WHITESPACE);
1331
57a8eca8
LP
1332 for (e = strchr(s, 0); e > s; e --)
1333 if (!strchr(WHITESPACE, e[-1]))
1334 break;
4a72ff34 1335
57a8eca8 1336 *e = 0;
4a72ff34
LP
1337
1338 return s;
4a72ff34
LP
1339}
1340
ee9b5e01
LP
1341char *delete_chars(char *s, const char *bad) {
1342 char *f, *t;
1343
1344 /* Drops all whitespace, regardless where in the string */
1345
1346 for (f = s, t = s; *f; f++) {
1347 if (strchr(bad, *f))
1348 continue;
1349
1350 *(t++) = *f;
1351 }
1352
1353 *t = 0;
1354
1355 return s;
1356}
1357
ab1f0633
LP
1358bool in_charset(const char *s, const char* charset) {
1359 const char *i;
1360
1361 assert(s);
1362 assert(charset);
1363
1364 for (i = s; *i; i++)
1365 if (!strchr(charset, *i))
1366 return false;
1367
1368 return true;
1369}
1370
4a72ff34
LP
1371char *file_in_same_dir(const char *path, const char *filename) {
1372 char *e, *r;
1373 size_t k;
1374
1375 assert(path);
1376 assert(filename);
1377
1378 /* This removes the last component of path and appends
1379 * filename, unless the latter is absolute anyway or the
1380 * former isn't */
1381
1382 if (path_is_absolute(filename))
1383 return strdup(filename);
1384
1385 if (!(e = strrchr(path, '/')))
1386 return strdup(filename);
1387
1388 k = strlen(filename);
1389 if (!(r = new(char, e-path+1+k+1)))
1390 return NULL;
1391
1392 memcpy(r, path, e-path+1);
1393 memcpy(r+(e-path)+1, filename, k+1);
1394
1395 return r;
1396}
fb624d04 1397
c32dd69b
LP
1398int rmdir_parents(const char *path, const char *stop) {
1399 size_t l;
1400 int r = 0;
1401
1402 assert(path);
1403 assert(stop);
1404
1405 l = strlen(path);
1406
1407 /* Skip trailing slashes */
1408 while (l > 0 && path[l-1] == '/')
1409 l--;
1410
1411 while (l > 0) {
1412 char *t;
1413
1414 /* Skip last component */
1415 while (l > 0 && path[l-1] != '/')
1416 l--;
1417
1418 /* Skip trailing slashes */
1419 while (l > 0 && path[l-1] == '/')
1420 l--;
1421
1422 if (l <= 0)
1423 break;
1424
1425 if (!(t = strndup(path, l)))
1426 return -ENOMEM;
1427
1428 if (path_startswith(stop, t)) {
1429 free(t);
1430 return 0;
1431 }
1432
1433 r = rmdir(t);
1434 free(t);
1435
1436 if (r < 0)
1437 if (errno != ENOENT)
1438 return -errno;
1439 }
1440
1441 return 0;
1442}
1443
1444
fb624d04
LP
1445char hexchar(int x) {
1446 static const char table[16] = "0123456789abcdef";
1447
1448 return table[x & 15];
1449}
4fe88d28
LP
1450
1451int unhexchar(char c) {
1452
1453 if (c >= '0' && c <= '9')
1454 return c - '0';
1455
1456 if (c >= 'a' && c <= 'f')
ea430986 1457 return c - 'a' + 10;
4fe88d28
LP
1458
1459 if (c >= 'A' && c <= 'F')
ea430986 1460 return c - 'A' + 10;
4fe88d28
LP
1461
1462 return -1;
1463}
1464
1465char octchar(int x) {
1466 return '0' + (x & 7);
1467}
1468
1469int unoctchar(char c) {
1470
1471 if (c >= '0' && c <= '7')
1472 return c - '0';
1473
1474 return -1;
1475}
1476
5af98f82
LP
1477char decchar(int x) {
1478 return '0' + (x % 10);
1479}
1480
1481int undecchar(char c) {
1482
1483 if (c >= '0' && c <= '9')
1484 return c - '0';
1485
1486 return -1;
1487}
1488
4fe88d28
LP
1489char *cescape(const char *s) {
1490 char *r, *t;
1491 const char *f;
1492
1493 assert(s);
1494
1495 /* Does C style string escaping. */
1496
f8e2fb7b
LP
1497 r = new(char, strlen(s)*4 + 1);
1498 if (!r)
4fe88d28
LP
1499 return NULL;
1500
1501 for (f = s, t = r; *f; f++)
1502
1503 switch (*f) {
1504
1505 case '\a':
1506 *(t++) = '\\';
1507 *(t++) = 'a';
1508 break;
1509 case '\b':
1510 *(t++) = '\\';
1511 *(t++) = 'b';
1512 break;
1513 case '\f':
1514 *(t++) = '\\';
1515 *(t++) = 'f';
1516 break;
1517 case '\n':
1518 *(t++) = '\\';
1519 *(t++) = 'n';
1520 break;
1521 case '\r':
1522 *(t++) = '\\';
1523 *(t++) = 'r';
1524 break;
1525 case '\t':
1526 *(t++) = '\\';
1527 *(t++) = 't';
1528 break;
1529 case '\v':
1530 *(t++) = '\\';
1531 *(t++) = 'v';
1532 break;
1533 case '\\':
1534 *(t++) = '\\';
1535 *(t++) = '\\';
1536 break;
1537 case '"':
1538 *(t++) = '\\';
1539 *(t++) = '"';
1540 break;
1541 case '\'':
1542 *(t++) = '\\';
1543 *(t++) = '\'';
1544 break;
1545
1546 default:
1547 /* For special chars we prefer octal over
1548 * hexadecimal encoding, simply because glib's
1549 * g_strescape() does the same */
1550 if ((*f < ' ') || (*f >= 127)) {
1551 *(t++) = '\\';
1552 *(t++) = octchar((unsigned char) *f >> 6);
1553 *(t++) = octchar((unsigned char) *f >> 3);
1554 *(t++) = octchar((unsigned char) *f);
1555 } else
1556 *(t++) = *f;
1557 break;
1558 }
1559
1560 *t = 0;
1561
1562 return r;
1563}
1564
5b4c61cd 1565char *cunescape_length_with_prefix(const char *s, size_t length, const char *prefix) {
4fe88d28
LP
1566 char *r, *t;
1567 const char *f;
5b4c61cd 1568 size_t pl;
4fe88d28
LP
1569
1570 assert(s);
1571
5b4c61cd
LP
1572 /* Undoes C style string escaping, and optionally prefixes it. */
1573
1574 pl = prefix ? strlen(prefix) : 0;
4fe88d28 1575
5b4c61cd 1576 r = new(char, pl+length+1);
7f110ff9 1577 if (!r)
4fe88d28
LP
1578 return r;
1579
5b4c61cd
LP
1580 if (prefix)
1581 memcpy(r, prefix, pl);
1582
1583 for (f = s, t = r + pl; f < s + length; f++) {
4fe88d28
LP
1584
1585 if (*f != '\\') {
1586 *(t++) = *f;
1587 continue;
1588 }
1589
1590 f++;
1591
1592 switch (*f) {
1593
1594 case 'a':
1595 *(t++) = '\a';
1596 break;
1597 case 'b':
1598 *(t++) = '\b';
1599 break;
1600 case 'f':
1601 *(t++) = '\f';
1602 break;
1603 case 'n':
1604 *(t++) = '\n';
1605 break;
1606 case 'r':
1607 *(t++) = '\r';
1608 break;
1609 case 't':
1610 *(t++) = '\t';
1611 break;
1612 case 'v':
1613 *(t++) = '\v';
1614 break;
1615 case '\\':
1616 *(t++) = '\\';
1617 break;
1618 case '"':
1619 *(t++) = '"';
1620 break;
1621 case '\'':
1622 *(t++) = '\'';
1623 break;
1624
e167fb86
LP
1625 case 's':
1626 /* This is an extension of the XDG syntax files */
1627 *(t++) = ' ';
1628 break;
1629
4fe88d28
LP
1630 case 'x': {
1631 /* hexadecimal encoding */
1632 int a, b;
1633
7f110ff9
LP
1634 a = unhexchar(f[1]);
1635 b = unhexchar(f[2]);
1636
1637 if (a < 0 || b < 0) {
4fe88d28
LP
1638 /* Invalid escape code, let's take it literal then */
1639 *(t++) = '\\';
1640 *(t++) = 'x';
1641 } else {
1642 *(t++) = (char) ((a << 4) | b);
1643 f += 2;
1644 }
1645
1646 break;
1647 }
1648
1649 case '0':
1650 case '1':
1651 case '2':
1652 case '3':
1653 case '4':
1654 case '5':
1655 case '6':
1656 case '7': {
1657 /* octal encoding */
1658 int a, b, c;
1659
7f110ff9
LP
1660 a = unoctchar(f[0]);
1661 b = unoctchar(f[1]);
1662 c = unoctchar(f[2]);
1663
1664 if (a < 0 || b < 0 || c < 0) {
4fe88d28
LP
1665 /* Invalid escape code, let's take it literal then */
1666 *(t++) = '\\';
1667 *(t++) = f[0];
1668 } else {
1669 *(t++) = (char) ((a << 6) | (b << 3) | c);
1670 f += 2;
1671 }
1672
1673 break;
1674 }
1675
1676 case 0:
1677 /* premature end of string.*/
1678 *(t++) = '\\';
1679 goto finish;
1680
1681 default:
1682 /* Invalid escape code, let's take it literal then */
1683 *(t++) = '\\';
f3d4cc01 1684 *(t++) = *f;
4fe88d28
LP
1685 break;
1686 }
1687 }
1688
1689finish:
1690 *t = 0;
1691 return r;
1692}
1693
5b4c61cd
LP
1694char *cunescape_length(const char *s, size_t length) {
1695 return cunescape_length_with_prefix(s, length, NULL);
1696}
1697
6febfd0d 1698char *cunescape(const char *s) {
5b4c61cd
LP
1699 assert(s);
1700
6febfd0d
LP
1701 return cunescape_length(s, strlen(s));
1702}
4fe88d28
LP
1703
1704char *xescape(const char *s, const char *bad) {
1705 char *r, *t;
1706 const char *f;
1707
1708 /* Escapes all chars in bad, in addition to \ and all special
1709 * chars, in \xFF style escaping. May be reversed with
1710 * cunescape. */
1711
1712 if (!(r = new(char, strlen(s)*4+1)))
1713 return NULL;
1714
1715 for (f = s, t = r; *f; f++) {
1716
b866264a
LP
1717 if ((*f < ' ') || (*f >= 127) ||
1718 (*f == '\\') || strchr(bad, *f)) {
4fe88d28
LP
1719 *(t++) = '\\';
1720 *(t++) = 'x';
1721 *(t++) = hexchar(*f >> 4);
1722 *(t++) = hexchar(*f);
1723 } else
1724 *(t++) = *f;
1725 }
1726
1727 *t = 0;
1728
1729 return r;
1730}
1731
ea430986 1732char *bus_path_escape(const char *s) {
ea430986
LP
1733 char *r, *t;
1734 const char *f;
1735
47be870b
LP
1736 assert(s);
1737
ea430986
LP
1738 /* Escapes all chars that D-Bus' object path cannot deal
1739 * with. Can be reverse with bus_path_unescape() */
1740
1741 if (!(r = new(char, strlen(s)*3+1)))
1742 return NULL;
1743
1744 for (f = s, t = r; *f; f++) {
1745
1746 if (!(*f >= 'A' && *f <= 'Z') &&
1747 !(*f >= 'a' && *f <= 'z') &&
1748 !(*f >= '0' && *f <= '9')) {
1749 *(t++) = '_';
1750 *(t++) = hexchar(*f >> 4);
1751 *(t++) = hexchar(*f);
1752 } else
1753 *(t++) = *f;
1754 }
1755
1756 *t = 0;
1757
1758 return r;
1759}
1760
9e2f7c11 1761char *bus_path_unescape(const char *f) {
ea430986 1762 char *r, *t;
ea430986 1763
9e2f7c11 1764 assert(f);
47be870b 1765
9e2f7c11 1766 if (!(r = strdup(f)))
ea430986
LP
1767 return NULL;
1768
9e2f7c11 1769 for (t = r; *f; f++) {
ea430986
LP
1770
1771 if (*f == '_') {
1772 int a, b;
1773
1774 if ((a = unhexchar(f[1])) < 0 ||
1775 (b = unhexchar(f[2])) < 0) {
1776 /* Invalid escape code, let's take it literal then */
1777 *(t++) = '_';
1778 } else {
1779 *(t++) = (char) ((a << 4) | b);
1780 f += 2;
1781 }
1782 } else
1783 *(t++) = *f;
1784 }
1785
1786 *t = 0;
1787
1788 return r;
1789}
1790
67d51650 1791char *ascii_strlower(char *t) {
4fe88d28
LP
1792 char *p;
1793
67d51650 1794 assert(t);
4fe88d28 1795
67d51650 1796 for (p = t; *p; p++)
4fe88d28
LP
1797 if (*p >= 'A' && *p <= 'Z')
1798 *p = *p - 'A' + 'a';
1799
67d51650 1800 return t;
4fe88d28 1801}
1dccbe19 1802
c85dc17b
LP
1803bool ignore_file(const char *filename) {
1804 assert(filename);
1805
1806 return
1807 filename[0] == '.' ||
6c78be3c 1808 streq(filename, "lost+found") ||
e472d476
LP
1809 streq(filename, "aquota.user") ||
1810 streq(filename, "aquota.group") ||
c85dc17b
LP
1811 endswith(filename, "~") ||
1812 endswith(filename, ".rpmnew") ||
1813 endswith(filename, ".rpmsave") ||
1814 endswith(filename, ".rpmorig") ||
1815 endswith(filename, ".dpkg-old") ||
1816 endswith(filename, ".dpkg-new") ||
1817 endswith(filename, ".swp");
1818}
1819
3a0ecb08
LP
1820int fd_nonblock(int fd, bool nonblock) {
1821 int flags;
1822
1823 assert(fd >= 0);
1824
1825 if ((flags = fcntl(fd, F_GETFL, 0)) < 0)
1826 return -errno;
1827
1828 if (nonblock)
1829 flags |= O_NONBLOCK;
1830 else
1831 flags &= ~O_NONBLOCK;
1832
1833 if (fcntl(fd, F_SETFL, flags) < 0)
1834 return -errno;
1835
1836 return 0;
1837}
1838
1839int fd_cloexec(int fd, bool cloexec) {
1840 int flags;
1841
1842 assert(fd >= 0);
1843
1844 if ((flags = fcntl(fd, F_GETFD, 0)) < 0)
1845 return -errno;
1846
1847 if (cloexec)
1848 flags |= FD_CLOEXEC;
1849 else
1850 flags &= ~FD_CLOEXEC;
1851
1852 if (fcntl(fd, F_SETFD, flags) < 0)
1853 return -errno;
1854
1855 return 0;
1856}
1857
b19be9eb
LP
1858static bool fd_in_set(int fd, const int fdset[], unsigned n_fdset) {
1859 unsigned i;
1860
1861 assert(n_fdset == 0 || fdset);
1862
1863 for (i = 0; i < n_fdset; i++)
1864 if (fdset[i] == fd)
1865 return true;
1866
1867 return false;
1868}
1869
a0d40ac5
LP
1870int close_all_fds(const int except[], unsigned n_except) {
1871 DIR *d;
1872 struct dirent *de;
1873 int r = 0;
1874
b19be9eb
LP
1875 assert(n_except == 0 || except);
1876
1877 d = opendir("/proc/self/fd");
1878 if (!d) {
1879 int fd;
1880 struct rlimit rl;
1881
1882 /* When /proc isn't available (for example in chroots)
1883 * the fallback is brute forcing through the fd
1884 * table */
1885
1886 assert_se(getrlimit(RLIMIT_NOFILE, &rl) >= 0);
1887 for (fd = 3; fd < (int) rl.rlim_max; fd ++) {
1888
1889 if (fd_in_set(fd, except, n_except))
1890 continue;
1891
1892 if (close_nointr(fd) < 0)
1893 if (errno != EBADF && r == 0)
1894 r = -errno;
1895 }
1896
1897 return r;
1898 }
a0d40ac5
LP
1899
1900 while ((de = readdir(d))) {
a7610064 1901 int fd = -1;
a0d40ac5 1902
a16e1123 1903 if (ignore_file(de->d_name))
a0d40ac5
LP
1904 continue;
1905
720ce21d
LP
1906 if (safe_atoi(de->d_name, &fd) < 0)
1907 /* Let's better ignore this, just in case */
1908 continue;
a0d40ac5
LP
1909
1910 if (fd < 3)
1911 continue;
1912
1913 if (fd == dirfd(d))
1914 continue;
1915
b19be9eb
LP
1916 if (fd_in_set(fd, except, n_except))
1917 continue;
a0d40ac5 1918
720ce21d 1919 if (close_nointr(fd) < 0) {
2f357920 1920 /* Valgrind has its own FD and doesn't want to have it closed */
720ce21d
LP
1921 if (errno != EBADF && r == 0)
1922 r = -errno;
2f357920 1923 }
a0d40ac5
LP
1924 }
1925
a0d40ac5
LP
1926 closedir(d);
1927 return r;
1928}
1929
db12775d
LP
1930bool chars_intersect(const char *a, const char *b) {
1931 const char *p;
1932
1933 /* Returns true if any of the chars in a are in b. */
1934 for (p = a; *p; p++)
1935 if (strchr(b, *p))
1936 return true;
1937
1938 return false;
1939}
1940
8b6c7120
LP
1941char *format_timestamp(char *buf, size_t l, usec_t t) {
1942 struct tm tm;
1943 time_t sec;
1944
1945 assert(buf);
1946 assert(l > 0);
1947
1948 if (t <= 0)
1949 return NULL;
1950
f872ec33 1951 sec = (time_t) (t / USEC_PER_SEC);
8b6c7120
LP
1952
1953 if (strftime(buf, l, "%a, %d %b %Y %H:%M:%S %z", localtime_r(&sec, &tm)) <= 0)
1954 return NULL;
1955
1956 return buf;
1957}
1958
584be568
LP
1959char *format_timestamp_pretty(char *buf, size_t l, usec_t t) {
1960 usec_t n, d;
1961
1962 n = now(CLOCK_REALTIME);
1963
1964 if (t <= 0 || t > n || t + USEC_PER_DAY*7 <= t)
1965 return NULL;
1966
1967 d = n - t;
1968
1969 if (d >= USEC_PER_YEAR)
1970 snprintf(buf, l, "%llu years and %llu months ago",
1971 (unsigned long long) (d / USEC_PER_YEAR),
1972 (unsigned long long) ((d % USEC_PER_YEAR) / USEC_PER_MONTH));
1973 else if (d >= USEC_PER_MONTH)
1974 snprintf(buf, l, "%llu months and %llu days ago",
1975 (unsigned long long) (d / USEC_PER_MONTH),
1976 (unsigned long long) ((d % USEC_PER_MONTH) / USEC_PER_DAY));
1977 else if (d >= USEC_PER_WEEK)
1978 snprintf(buf, l, "%llu weeks and %llu days ago",
1979 (unsigned long long) (d / USEC_PER_WEEK),
1980 (unsigned long long) ((d % USEC_PER_WEEK) / USEC_PER_DAY));
1981 else if (d >= 2*USEC_PER_DAY)
1982 snprintf(buf, l, "%llu days ago", (unsigned long long) (d / USEC_PER_DAY));
1983 else if (d >= 25*USEC_PER_HOUR)
1984 snprintf(buf, l, "1 day and %lluh ago",
1985 (unsigned long long) ((d - USEC_PER_DAY) / USEC_PER_HOUR));
1986 else if (d >= 6*USEC_PER_HOUR)
1987 snprintf(buf, l, "%lluh ago",
1988 (unsigned long long) (d / USEC_PER_HOUR));
1989 else if (d >= USEC_PER_HOUR)
1990 snprintf(buf, l, "%lluh %llumin ago",
1991 (unsigned long long) (d / USEC_PER_HOUR),
1992 (unsigned long long) ((d % USEC_PER_HOUR) / USEC_PER_MINUTE));
1993 else if (d >= 5*USEC_PER_MINUTE)
1994 snprintf(buf, l, "%llumin ago",
1995 (unsigned long long) (d / USEC_PER_MINUTE));
1996 else if (d >= USEC_PER_MINUTE)
1997 snprintf(buf, l, "%llumin %llus ago",
1998 (unsigned long long) (d / USEC_PER_MINUTE),
1999 (unsigned long long) ((d % USEC_PER_MINUTE) / USEC_PER_SEC));
2000 else if (d >= USEC_PER_SEC)
2001 snprintf(buf, l, "%llus ago",
2002 (unsigned long long) (d / USEC_PER_SEC));
2003 else if (d >= USEC_PER_MSEC)
2004 snprintf(buf, l, "%llums ago",
2005 (unsigned long long) (d / USEC_PER_MSEC));
2006 else if (d > 0)
2007 snprintf(buf, l, "%lluus ago",
2008 (unsigned long long) d);
2009 else
2010 snprintf(buf, l, "now");
2011
2012 buf[l-1] = 0;
2013 return buf;
2014}
2015
871d7de4
LP
2016char *format_timespan(char *buf, size_t l, usec_t t) {
2017 static const struct {
2018 const char *suffix;
2019 usec_t usec;
2020 } table[] = {
2021 { "w", USEC_PER_WEEK },
2022 { "d", USEC_PER_DAY },
2023 { "h", USEC_PER_HOUR },
2024 { "min", USEC_PER_MINUTE },
2025 { "s", USEC_PER_SEC },
2026 { "ms", USEC_PER_MSEC },
2027 { "us", 1 },
2028 };
2029
2030 unsigned i;
2031 char *p = buf;
2032
2033 assert(buf);
2034 assert(l > 0);
2035
2036 if (t == (usec_t) -1)
2037 return NULL;
2038
4502d22c
LP
2039 if (t == 0) {
2040 snprintf(p, l, "0");
2041 p[l-1] = 0;
2042 return p;
2043 }
2044
871d7de4
LP
2045 /* The result of this function can be parsed with parse_usec */
2046
2047 for (i = 0; i < ELEMENTSOF(table); i++) {
2048 int k;
2049 size_t n;
2050
2051 if (t < table[i].usec)
2052 continue;
2053
2054 if (l <= 1)
2055 break;
2056
2057 k = snprintf(p, l, "%s%llu%s", p > buf ? " " : "", (unsigned long long) (t / table[i].usec), table[i].suffix);
2058 n = MIN((size_t) k, l);
2059
2060 l -= n;
2061 p += n;
2062
2063 t %= table[i].usec;
2064 }
2065
2066 *p = 0;
2067
2068 return buf;
2069}
2070
42856c10
LP
2071bool fstype_is_network(const char *fstype) {
2072 static const char * const table[] = {
2073 "cifs",
2074 "smbfs",
2075 "ncpfs",
2076 "nfs",
ca139f94
LP
2077 "nfs4",
2078 "gfs",
2079 "gfs2"
42856c10
LP
2080 };
2081
2082 unsigned i;
2083
2084 for (i = 0; i < ELEMENTSOF(table); i++)
2085 if (streq(table[i], fstype))
2086 return true;
2087
2088 return false;
2089}
2090
601f6a1e
LP
2091int chvt(int vt) {
2092 int fd, r = 0;
2093
74bc3bdc 2094 if ((fd = open_terminal("/dev/tty0", O_RDWR|O_NOCTTY|O_CLOEXEC)) < 0)
601f6a1e
LP
2095 return -errno;
2096
2097 if (vt < 0) {
2098 int tiocl[2] = {
2099 TIOCL_GETKMSGREDIRECT,
2100 0
2101 };
2102
678abaf9
TJ
2103 if (ioctl(fd, TIOCLINUX, tiocl) < 0) {
2104 r = -errno;
2105 goto fail;
2106 }
601f6a1e
LP
2107
2108 vt = tiocl[0] <= 0 ? 1 : tiocl[0];
2109 }
2110
2111 if (ioctl(fd, VT_ACTIVATE, vt) < 0)
2112 r = -errno;
2113
678abaf9
TJ
2114fail:
2115 close_nointr_nofail(fd);
601f6a1e
LP
2116 return r;
2117}
2118
8f2d43a0 2119int read_one_char(FILE *f, char *ret, usec_t t, bool *need_nl) {
80876c20
LP
2120 struct termios old_termios, new_termios;
2121 char c;
20c03b7b 2122 char line[LINE_MAX];
80876c20
LP
2123
2124 assert(f);
2125 assert(ret);
2126
2127 if (tcgetattr(fileno(f), &old_termios) >= 0) {
2128 new_termios = old_termios;
2129
2130 new_termios.c_lflag &= ~ICANON;
2131 new_termios.c_cc[VMIN] = 1;
2132 new_termios.c_cc[VTIME] = 0;
2133
2134 if (tcsetattr(fileno(f), TCSADRAIN, &new_termios) >= 0) {
2135 size_t k;
2136
8f2d43a0
LP
2137 if (t != (usec_t) -1) {
2138 if (fd_wait_for_event(fileno(f), POLLIN, t) <= 0) {
2139 tcsetattr(fileno(f), TCSADRAIN, &old_termios);
2140 return -ETIMEDOUT;
2141 }
2142 }
2143
80876c20
LP
2144 k = fread(&c, 1, 1, f);
2145
2146 tcsetattr(fileno(f), TCSADRAIN, &old_termios);
2147
2148 if (k <= 0)
2149 return -EIO;
2150
2151 if (need_nl)
2152 *need_nl = c != '\n';
2153
2154 *ret = c;
2155 return 0;
2156 }
2157 }
2158
8f2d43a0
LP
2159 if (t != (usec_t) -1)
2160 if (fd_wait_for_event(fileno(f), POLLIN, t) <= 0)
2161 return -ETIMEDOUT;
2162
2163 if (!fgets(line, sizeof(line), f))
80876c20
LP
2164 return -EIO;
2165
2166 truncate_nl(line);
2167
2168 if (strlen(line) != 1)
2169 return -EBADMSG;
2170
2171 if (need_nl)
2172 *need_nl = false;
2173
2174 *ret = line[0];
2175 return 0;
2176}
2177
2178int ask(char *ret, const char *replies, const char *text, ...) {
1b39d4b9
LP
2179 bool on_tty;
2180
80876c20
LP
2181 assert(ret);
2182 assert(replies);
2183 assert(text);
2184
1b39d4b9
LP
2185 on_tty = isatty(STDOUT_FILENO);
2186
80876c20
LP
2187 for (;;) {
2188 va_list ap;
2189 char c;
2190 int r;
2191 bool need_nl = true;
2192
1b39d4b9 2193 if (on_tty)
c1072ea0 2194 fputs(ANSI_HIGHLIGHT_ON, stdout);
b1b2dc0c 2195
80876c20
LP
2196 va_start(ap, text);
2197 vprintf(text, ap);
2198 va_end(ap);
2199
1b39d4b9 2200 if (on_tty)
c1072ea0 2201 fputs(ANSI_HIGHLIGHT_OFF, stdout);
b1b2dc0c 2202
80876c20
LP
2203 fflush(stdout);
2204
8f2d43a0
LP
2205 r = read_one_char(stdin, &c, (usec_t) -1, &need_nl);
2206 if (r < 0) {
80876c20
LP
2207
2208 if (r == -EBADMSG) {
2209 puts("Bad input, please try again.");
2210 continue;
2211 }
2212
2213 putchar('\n');
2214 return r;
2215 }
2216
2217 if (need_nl)
2218 putchar('\n');
2219
2220 if (strchr(replies, c)) {
2221 *ret = c;
2222 return 0;
2223 }
2224
2225 puts("Read unexpected character, please try again.");
2226 }
2227}
2228
512947d4 2229int reset_terminal_fd(int fd, bool switch_to_text) {
80876c20
LP
2230 struct termios termios;
2231 int r = 0;
3fe5e5d4
LP
2232
2233 /* Set terminal to some sane defaults */
80876c20
LP
2234
2235 assert(fd >= 0);
2236
eed1d0e3
LP
2237 /* We leave locked terminal attributes untouched, so that
2238 * Plymouth may set whatever it wants to set, and we don't
2239 * interfere with that. */
3fe5e5d4
LP
2240
2241 /* Disable exclusive mode, just in case */
2242 ioctl(fd, TIOCNXCL);
2243
5c0100a5 2244 /* Switch to text mode */
512947d4
MS
2245 if (switch_to_text)
2246 ioctl(fd, KDSETMODE, KD_TEXT);
5c0100a5 2247
3fe5e5d4 2248 /* Enable console unicode mode */
df465b3f 2249 ioctl(fd, KDSKBMODE, K_UNICODE);
80876c20
LP
2250
2251 if (tcgetattr(fd, &termios) < 0) {
2252 r = -errno;
2253 goto finish;
2254 }
2255
aaf694ca
LP
2256 /* We only reset the stuff that matters to the software. How
2257 * hardware is set up we don't touch assuming that somebody
2258 * else will do that for us */
2259
2260 termios.c_iflag &= ~(IGNBRK | BRKINT | ISTRIP | INLCR | IGNCR | IUCLC);
80876c20
LP
2261 termios.c_iflag |= ICRNL | IMAXBEL | IUTF8;
2262 termios.c_oflag |= ONLCR;
2263 termios.c_cflag |= CREAD;
2264 termios.c_lflag = ISIG | ICANON | IEXTEN | ECHO | ECHOE | ECHOK | ECHOCTL | ECHOPRT | ECHOKE;
2265
2266 termios.c_cc[VINTR] = 03; /* ^C */
2267 termios.c_cc[VQUIT] = 034; /* ^\ */
2268 termios.c_cc[VERASE] = 0177;
2269 termios.c_cc[VKILL] = 025; /* ^X */
2270 termios.c_cc[VEOF] = 04; /* ^D */
2271 termios.c_cc[VSTART] = 021; /* ^Q */
2272 termios.c_cc[VSTOP] = 023; /* ^S */
2273 termios.c_cc[VSUSP] = 032; /* ^Z */
2274 termios.c_cc[VLNEXT] = 026; /* ^V */
2275 termios.c_cc[VWERASE] = 027; /* ^W */
2276 termios.c_cc[VREPRINT] = 022; /* ^R */
aaf694ca
LP
2277 termios.c_cc[VEOL] = 0;
2278 termios.c_cc[VEOL2] = 0;
80876c20
LP
2279
2280 termios.c_cc[VTIME] = 0;
2281 termios.c_cc[VMIN] = 1;
2282
2283 if (tcsetattr(fd, TCSANOW, &termios) < 0)
2284 r = -errno;
2285
2286finish:
2287 /* Just in case, flush all crap out */
2288 tcflush(fd, TCIOFLUSH);
2289
2290 return r;
2291}
2292
6ea832a2
LP
2293int reset_terminal(const char *name) {
2294 int fd, r;
2295
2296 fd = open_terminal(name, O_RDWR|O_NOCTTY|O_CLOEXEC);
2297 if (fd < 0)
2298 return fd;
2299
512947d4 2300 r = reset_terminal_fd(fd, true);
6ea832a2
LP
2301 close_nointr_nofail(fd);
2302
2303 return r;
2304}
2305
80876c20
LP
2306int open_terminal(const char *name, int mode) {
2307 int fd, r;
f73f76ac 2308 unsigned c = 0;
80876c20 2309
f73f76ac
LP
2310 /*
2311 * If a TTY is in the process of being closed opening it might
2312 * cause EIO. This is horribly awful, but unlikely to be
2313 * changed in the kernel. Hence we work around this problem by
2314 * retrying a couple of times.
2315 *
2316 * https://bugs.launchpad.net/ubuntu/+source/linux/+bug/554172/comments/245
2317 */
2318
2319 for (;;) {
af6da548
LP
2320 fd = open(name, mode);
2321 if (fd >= 0)
f73f76ac
LP
2322 break;
2323
2324 if (errno != EIO)
2325 return -errno;
2326
af6da548 2327 /* Max 1s in total */
f73f76ac
LP
2328 if (c >= 20)
2329 return -errno;
2330
2331 usleep(50 * USEC_PER_MSEC);
2332 c++;
2333 }
2334
2335 if (fd < 0)
80876c20
LP
2336 return -errno;
2337
af6da548
LP
2338 r = isatty(fd);
2339 if (r < 0) {
80876c20
LP
2340 close_nointr_nofail(fd);
2341 return -errno;
2342 }
2343
2344 if (!r) {
2345 close_nointr_nofail(fd);
2346 return -ENOTTY;
2347 }
2348
2349 return fd;
2350}
2351
2352int flush_fd(int fd) {
2353 struct pollfd pollfd;
2354
2355 zero(pollfd);
2356 pollfd.fd = fd;
2357 pollfd.events = POLLIN;
2358
2359 for (;;) {
20c03b7b 2360 char buf[LINE_MAX];
80876c20
LP
2361 ssize_t l;
2362 int r;
2363
2364 if ((r = poll(&pollfd, 1, 0)) < 0) {
2365
2366 if (errno == EINTR)
2367 continue;
2368
2369 return -errno;
2370 }
2371
2372 if (r == 0)
2373 return 0;
2374
2375 if ((l = read(fd, buf, sizeof(buf))) < 0) {
2376
2377 if (errno == EINTR)
2378 continue;
2379
2380 if (errno == EAGAIN)
2381 return 0;
2382
2383 return -errno;
2384 }
2385
2386 if (l <= 0)
2387 return 0;
2388 }
2389}
2390
af6da548
LP
2391int acquire_terminal(
2392 const char *name,
2393 bool fail,
2394 bool force,
2395 bool ignore_tiocstty_eperm,
2396 usec_t timeout) {
2397
4a0ff478 2398 int fd = -1, notify = -1, r = 0, wd = -1;
af6da548 2399 usec_t ts = 0;
32c4bef8 2400 struct sigaction sa_old, sa_new;
80876c20
LP
2401
2402 assert(name);
2403
2404 /* We use inotify to be notified when the tty is closed. We
2405 * create the watch before checking if we can actually acquire
2406 * it, so that we don't lose any event.
2407 *
2408 * Note: strictly speaking this actually watches for the
2409 * device being closed, it does *not* really watch whether a
2410 * tty loses its controlling process. However, unless some
2411 * rogue process uses TIOCNOTTY on /dev/tty *after* closing
2412 * its tty otherwise this will not become a problem. As long
2413 * as the administrator makes sure not configure any service
2414 * on the same tty as an untrusted user this should not be a
2415 * problem. (Which he probably should not do anyway.) */
2416
af6da548
LP
2417 if (timeout != (usec_t) -1)
2418 ts = now(CLOCK_MONOTONIC);
2419
80876c20 2420 if (!fail && !force) {
af6da548
LP
2421 notify = inotify_init1(IN_CLOEXEC | (timeout != (usec_t) -1 ? IN_NONBLOCK : 0));
2422 if (notify < 0) {
80876c20
LP
2423 r = -errno;
2424 goto fail;
2425 }
2426
af6da548
LP
2427 wd = inotify_add_watch(notify, name, IN_CLOSE);
2428 if (wd < 0) {
80876c20
LP
2429 r = -errno;
2430 goto fail;
2431 }
2432 }
2433
2434 for (;;) {
af6da548
LP
2435 if (notify >= 0) {
2436 r = flush_fd(notify);
2437 if (r < 0)
e3d1855b 2438 goto fail;
af6da548 2439 }
80876c20
LP
2440
2441 /* We pass here O_NOCTTY only so that we can check the return
2442 * value TIOCSCTTY and have a reliable way to figure out if we
2443 * successfully became the controlling process of the tty */
af6da548
LP
2444 fd = open_terminal(name, O_RDWR|O_NOCTTY|O_CLOEXEC);
2445 if (fd < 0)
6ea832a2 2446 return fd;
80876c20 2447
32c4bef8
LP
2448 /* Temporarily ignore SIGHUP, so that we don't get SIGHUP'ed
2449 * if we already own the tty. */
2450 zero(sa_new);
2451 sa_new.sa_handler = SIG_IGN;
2452 sa_new.sa_flags = SA_RESTART;
2453 assert_se(sigaction(SIGHUP, &sa_new, &sa_old) == 0);
2454
80876c20 2455 /* First, try to get the tty */
32c4bef8
LP
2456 if (ioctl(fd, TIOCSCTTY, force) < 0)
2457 r = -errno;
2458
2459 assert_se(sigaction(SIGHUP, &sa_old, NULL) == 0);
21de3988
LP
2460
2461 /* Sometimes it makes sense to ignore TIOCSCTTY
2462 * returning EPERM, i.e. when very likely we already
2463 * are have this controlling terminal. */
32c4bef8 2464 if (r < 0 && r == -EPERM && ignore_tiocstty_eperm)
21de3988
LP
2465 r = 0;
2466
32c4bef8 2467 if (r < 0 && (force || fail || r != -EPERM)) {
80876c20
LP
2468 goto fail;
2469 }
2470
2471 if (r >= 0)
2472 break;
2473
2474 assert(!fail);
2475 assert(!force);
2476 assert(notify >= 0);
2477
2478 for (;;) {
f601daa7 2479 uint8_t inotify_buffer[sizeof(struct inotify_event) + FILENAME_MAX];
80876c20 2480 ssize_t l;
f601daa7 2481 struct inotify_event *e;
80876c20 2482
af6da548
LP
2483 if (timeout != (usec_t) -1) {
2484 usec_t n;
2485
2486 n = now(CLOCK_MONOTONIC);
2487 if (ts + timeout < n) {
2488 r = -ETIMEDOUT;
2489 goto fail;
2490 }
2491
2492 r = fd_wait_for_event(fd, POLLIN, ts + timeout - n);
2493 if (r < 0)
2494 goto fail;
2495
2496 if (r == 0) {
2497 r = -ETIMEDOUT;
2498 goto fail;
2499 }
2500 }
2501
2502 l = read(notify, inotify_buffer, sizeof(inotify_buffer));
2503 if (l < 0) {
80876c20 2504
af6da548 2505 if (errno == EINTR || errno == EAGAIN)
f601daa7
LP
2506 continue;
2507
2508 r = -errno;
2509 goto fail;
2510 }
2511
2512 e = (struct inotify_event*) inotify_buffer;
80876c20 2513
f601daa7
LP
2514 while (l > 0) {
2515 size_t step;
80876c20 2516
f601daa7 2517 if (e->wd != wd || !(e->mask & IN_CLOSE)) {
80876c20 2518 r = -EIO;
f601daa7
LP
2519 goto fail;
2520 }
80876c20 2521
f601daa7
LP
2522 step = sizeof(struct inotify_event) + e->len;
2523 assert(step <= (size_t) l);
80876c20 2524
f601daa7
LP
2525 e = (struct inotify_event*) ((uint8_t*) e + step);
2526 l -= step;
80876c20
LP
2527 }
2528
2529 break;
2530 }
2531
2532 /* We close the tty fd here since if the old session
2533 * ended our handle will be dead. It's important that
2534 * we do this after sleeping, so that we don't enter
2535 * an endless loop. */
2536 close_nointr_nofail(fd);
2537 }
2538
2539 if (notify >= 0)
a16e1123 2540 close_nointr_nofail(notify);
80876c20 2541
512947d4
MS
2542 r = reset_terminal_fd(fd, true);
2543 if (r < 0)
80876c20
LP
2544 log_warning("Failed to reset terminal: %s", strerror(-r));
2545
2546 return fd;
2547
2548fail:
2549 if (fd >= 0)
a16e1123 2550 close_nointr_nofail(fd);
80876c20
LP
2551
2552 if (notify >= 0)
a16e1123 2553 close_nointr_nofail(notify);
80876c20
LP
2554
2555 return r;
2556}
2557
2558int release_terminal(void) {
2559 int r = 0, fd;
57cd2192 2560 struct sigaction sa_old, sa_new;
80876c20 2561
ccaa6149 2562 if ((fd = open("/dev/tty", O_RDWR|O_NOCTTY|O_NDELAY|O_CLOEXEC)) < 0)
80876c20
LP
2563 return -errno;
2564
57cd2192
LP
2565 /* Temporarily ignore SIGHUP, so that we don't get SIGHUP'ed
2566 * by our own TIOCNOTTY */
2567
2568 zero(sa_new);
2569 sa_new.sa_handler = SIG_IGN;
2570 sa_new.sa_flags = SA_RESTART;
2571 assert_se(sigaction(SIGHUP, &sa_new, &sa_old) == 0);
2572
80876c20
LP
2573 if (ioctl(fd, TIOCNOTTY) < 0)
2574 r = -errno;
2575
57cd2192
LP
2576 assert_se(sigaction(SIGHUP, &sa_old, NULL) == 0);
2577
80876c20
LP
2578 close_nointr_nofail(fd);
2579 return r;
2580}
2581
9a34ec5f
LP
2582int sigaction_many(const struct sigaction *sa, ...) {
2583 va_list ap;
2584 int r = 0, sig;
2585
2586 va_start(ap, sa);
2587 while ((sig = va_arg(ap, int)) > 0)
2588 if (sigaction(sig, sa, NULL) < 0)
2589 r = -errno;
2590 va_end(ap);
2591
2592 return r;
2593}
2594
2595int ignore_signals(int sig, ...) {
a337c6fc 2596 struct sigaction sa;
9a34ec5f
LP
2597 va_list ap;
2598 int r = 0;
a337c6fc
LP
2599
2600 zero(sa);
2601 sa.sa_handler = SIG_IGN;
2602 sa.sa_flags = SA_RESTART;
2603
9a34ec5f
LP
2604 if (sigaction(sig, &sa, NULL) < 0)
2605 r = -errno;
2606
2607 va_start(ap, sig);
2608 while ((sig = va_arg(ap, int)) > 0)
2609 if (sigaction(sig, &sa, NULL) < 0)
2610 r = -errno;
2611 va_end(ap);
2612
2613 return r;
2614}
2615
2616int default_signals(int sig, ...) {
2617 struct sigaction sa;
2618 va_list ap;
2619 int r = 0;
2620
2621 zero(sa);
2622 sa.sa_handler = SIG_DFL;
2623 sa.sa_flags = SA_RESTART;
2624
2625 if (sigaction(sig, &sa, NULL) < 0)
2626 r = -errno;
2627
2628 va_start(ap, sig);
2629 while ((sig = va_arg(ap, int)) > 0)
2630 if (sigaction(sig, &sa, NULL) < 0)
2631 r = -errno;
2632 va_end(ap);
2633
2634 return r;
a337c6fc
LP
2635}
2636
8d567588
LP
2637int close_pipe(int p[]) {
2638 int a = 0, b = 0;
2639
2640 assert(p);
2641
2642 if (p[0] >= 0) {
2643 a = close_nointr(p[0]);
2644 p[0] = -1;
2645 }
2646
2647 if (p[1] >= 0) {
2648 b = close_nointr(p[1]);
2649 p[1] = -1;
2650 }
2651
2652 return a < 0 ? a : b;
2653}
2654
eb22ac37 2655ssize_t loop_read(int fd, void *buf, size_t nbytes, bool do_poll) {
8d567588
LP
2656 uint8_t *p;
2657 ssize_t n = 0;
2658
2659 assert(fd >= 0);
2660 assert(buf);
2661
2662 p = buf;
2663
2664 while (nbytes > 0) {
2665 ssize_t k;
2666
2667 if ((k = read(fd, p, nbytes)) <= 0) {
2668
eb22ac37 2669 if (k < 0 && errno == EINTR)
8d567588
LP
2670 continue;
2671
eb22ac37 2672 if (k < 0 && errno == EAGAIN && do_poll) {
8d567588
LP
2673 struct pollfd pollfd;
2674
2675 zero(pollfd);
2676 pollfd.fd = fd;
2677 pollfd.events = POLLIN;
2678
2679 if (poll(&pollfd, 1, -1) < 0) {
2680 if (errno == EINTR)
2681 continue;
2682
2683 return n > 0 ? n : -errno;
2684 }
2685
2686 if (pollfd.revents != POLLIN)
2687 return n > 0 ? n : -EIO;
2688
2689 continue;
2690 }
2691
2692 return n > 0 ? n : (k < 0 ? -errno : 0);
2693 }
2694
2695 p += k;
2696 nbytes -= k;
2697 n += k;
2698 }
2699
2700 return n;
2701}
2702
eb22ac37
LP
2703ssize_t loop_write(int fd, const void *buf, size_t nbytes, bool do_poll) {
2704 const uint8_t *p;
2705 ssize_t n = 0;
2706
2707 assert(fd >= 0);
2708 assert(buf);
2709
2710 p = buf;
2711
2712 while (nbytes > 0) {
2713 ssize_t k;
2714
fe652127
LP
2715 k = write(fd, p, nbytes);
2716 if (k <= 0) {
eb22ac37
LP
2717
2718 if (k < 0 && errno == EINTR)
2719 continue;
2720
2721 if (k < 0 && errno == EAGAIN && do_poll) {
2722 struct pollfd pollfd;
2723
2724 zero(pollfd);
2725 pollfd.fd = fd;
2726 pollfd.events = POLLOUT;
2727
2728 if (poll(&pollfd, 1, -1) < 0) {
2729 if (errno == EINTR)
2730 continue;
2731
2732 return n > 0 ? n : -errno;
2733 }
2734
2735 if (pollfd.revents != POLLOUT)
2736 return n > 0 ? n : -EIO;
2737
2738 continue;
2739 }
2740
2741 return n > 0 ? n : (k < 0 ? -errno : 0);
2742 }
2743
2744 p += k;
2745 nbytes -= k;
2746 n += k;
2747 }
2748
2749 return n;
2750}
2751
24a6e4a4
LP
2752int parse_usec(const char *t, usec_t *usec) {
2753 static const struct {
2754 const char *suffix;
2755 usec_t usec;
2756 } table[] = {
2757 { "sec", USEC_PER_SEC },
2758 { "s", USEC_PER_SEC },
2759 { "min", USEC_PER_MINUTE },
2760 { "hr", USEC_PER_HOUR },
2761 { "h", USEC_PER_HOUR },
2762 { "d", USEC_PER_DAY },
2763 { "w", USEC_PER_WEEK },
2764 { "msec", USEC_PER_MSEC },
2765 { "ms", USEC_PER_MSEC },
2766 { "m", USEC_PER_MINUTE },
2767 { "usec", 1ULL },
2768 { "us", 1ULL },
d88a251b 2769 { "", USEC_PER_SEC }, /* default is sec */
24a6e4a4
LP
2770 };
2771
2772 const char *p;
2773 usec_t r = 0;
2774
2775 assert(t);
2776 assert(usec);
2777
2778 p = t;
2779 do {
2780 long long l;
2781 char *e;
2782 unsigned i;
2783
2784 errno = 0;
2785 l = strtoll(p, &e, 10);
2786
2787 if (errno != 0)
2788 return -errno;
2789
2790 if (l < 0)
2791 return -ERANGE;
2792
2793 if (e == p)
2794 return -EINVAL;
2795
2796 e += strspn(e, WHITESPACE);
2797
2798 for (i = 0; i < ELEMENTSOF(table); i++)
2799 if (startswith(e, table[i].suffix)) {
2800 r += (usec_t) l * table[i].usec;
2801 p = e + strlen(table[i].suffix);
2802 break;
2803 }
2804
2805 if (i >= ELEMENTSOF(table))
2806 return -EINVAL;
2807
2808 } while (*p != 0);
2809
2810 *usec = r;
2811
2812 return 0;
2813}
2814
d88a251b
LP
2815int parse_nsec(const char *t, nsec_t *nsec) {
2816 static const struct {
2817 const char *suffix;
2818 nsec_t nsec;
2819 } table[] = {
2820 { "sec", NSEC_PER_SEC },
2821 { "s", NSEC_PER_SEC },
2822 { "min", NSEC_PER_MINUTE },
2823 { "hr", NSEC_PER_HOUR },
2824 { "h", NSEC_PER_HOUR },
2825 { "d", NSEC_PER_DAY },
2826 { "w", NSEC_PER_WEEK },
2827 { "msec", NSEC_PER_MSEC },
2828 { "ms", NSEC_PER_MSEC },
2829 { "m", NSEC_PER_MINUTE },
2830 { "usec", NSEC_PER_USEC },
2831 { "us", NSEC_PER_USEC },
2832 { "nsec", 1ULL },
2833 { "ns", 1ULL },
2834 { "", 1ULL }, /* default is nsec */
2835 };
2836
2837 const char *p;
2838 nsec_t r = 0;
2839
2840 assert(t);
2841 assert(nsec);
2842
2843 p = t;
2844 do {
2845 long long l;
2846 char *e;
2847 unsigned i;
2848
2849 errno = 0;
2850 l = strtoll(p, &e, 10);
2851
2852 if (errno != 0)
2853 return -errno;
2854
2855 if (l < 0)
2856 return -ERANGE;
2857
2858 if (e == p)
2859 return -EINVAL;
2860
2861 e += strspn(e, WHITESPACE);
2862
2863 for (i = 0; i < ELEMENTSOF(table); i++)
2864 if (startswith(e, table[i].suffix)) {
2865 r += (nsec_t) l * table[i].nsec;
2866 p = e + strlen(table[i].suffix);
2867 break;
2868 }
2869
2870 if (i >= ELEMENTSOF(table))
2871 return -EINVAL;
2872
2873 } while (*p != 0);
2874
2875 *nsec = r;
2876
2877 return 0;
2878}
2879
ab1f0633
LP
2880int parse_bytes(const char *t, off_t *bytes) {
2881 static const struct {
2882 const char *suffix;
2883 off_t factor;
2884 } table[] = {
2885 { "B", 1 },
2886 { "K", 1024ULL },
2887 { "M", 1024ULL*1024ULL },
2888 { "G", 1024ULL*1024ULL*1024ULL },
2889 { "T", 1024ULL*1024ULL*1024ULL*1024ULL },
32895bb3
LP
2890 { "P", 1024ULL*1024ULL*1024ULL*1024ULL*1024ULL },
2891 { "E", 1024ULL*1024ULL*1024ULL*1024ULL*1024ULL*1024ULL },
ab1f0633
LP
2892 { "", 1 },
2893 };
2894
2895 const char *p;
2896 off_t r = 0;
2897
2898 assert(t);
2899 assert(bytes);
2900
2901 p = t;
2902 do {
2903 long long l;
2904 char *e;
2905 unsigned i;
2906
2907 errno = 0;
2908 l = strtoll(p, &e, 10);
2909
2910 if (errno != 0)
2911 return -errno;
2912
2913 if (l < 0)
2914 return -ERANGE;
2915
2916 if (e == p)
2917 return -EINVAL;
2918
2919 e += strspn(e, WHITESPACE);
2920
2921 for (i = 0; i < ELEMENTSOF(table); i++)
2922 if (startswith(e, table[i].suffix)) {
2923 r += (off_t) l * table[i].factor;
2924 p = e + strlen(table[i].suffix);
2925 break;
2926 }
2927
2928 if (i >= ELEMENTSOF(table))
2929 return -EINVAL;
2930
2931 } while (*p != 0);
2932
2933 *bytes = r;
2934
2935 return 0;
2936}
2937
843d2643
LP
2938int make_stdio(int fd) {
2939 int r, s, t;
2940
2941 assert(fd >= 0);
2942
2943 r = dup2(fd, STDIN_FILENO);
2944 s = dup2(fd, STDOUT_FILENO);
2945 t = dup2(fd, STDERR_FILENO);
2946
2947 if (fd >= 3)
2948 close_nointr_nofail(fd);
2949
2950 if (r < 0 || s < 0 || t < 0)
2951 return -errno;
2952
7862f62d
LP
2953 fd_cloexec(STDIN_FILENO, false);
2954 fd_cloexec(STDOUT_FILENO, false);
2955 fd_cloexec(STDERR_FILENO, false);
2956
843d2643
LP
2957 return 0;
2958}
2959
ade509ce
LP
2960int make_null_stdio(void) {
2961 int null_fd;
2962
cd3bd60a
LP
2963 null_fd = open("/dev/null", O_RDWR|O_NOCTTY);
2964 if (null_fd < 0)
ade509ce
LP
2965 return -errno;
2966
2967 return make_stdio(null_fd);
2968}
2969
8407a5d0
LP
2970bool is_device_path(const char *path) {
2971
2972 /* Returns true on paths that refer to a device, either in
2973 * sysfs or in /dev */
2974
2975 return
2976 path_startswith(path, "/dev/") ||
2977 path_startswith(path, "/sys/");
2978}
2979
01f78473
LP
2980int dir_is_empty(const char *path) {
2981 DIR *d;
2982 int r;
2983 struct dirent buf, *de;
2984
2985 if (!(d = opendir(path)))
2986 return -errno;
2987
2988 for (;;) {
2989 if ((r = readdir_r(d, &buf, &de)) > 0) {
2990 r = -r;
2991 break;
2992 }
2993
2994 if (!de) {
2995 r = 1;
2996 break;
2997 }
2998
2999 if (!ignore_file(de->d_name)) {
3000 r = 0;
3001 break;
3002 }
3003 }
3004
3005 closedir(d);
3006 return r;
3007}
3008
d3782d60
LP
3009unsigned long long random_ull(void) {
3010 int fd;
3011 uint64_t ull;
3012 ssize_t r;
3013
ac0930c8
LP
3014 fd = open("/dev/urandom", O_RDONLY|O_CLOEXEC|O_NOCTTY);
3015 if (fd < 0)
d3782d60
LP
3016 goto fallback;
3017
eb22ac37 3018 r = loop_read(fd, &ull, sizeof(ull), true);
d3782d60
LP
3019 close_nointr_nofail(fd);
3020
3021 if (r != sizeof(ull))
3022 goto fallback;
3023
3024 return ull;
3025
3026fallback:
3027 return random() * RAND_MAX + random();
3028}
3029
5b6319dc
LP
3030void rename_process(const char name[8]) {
3031 assert(name);
3032
5d6b1584
LP
3033 /* This is a like a poor man's setproctitle(). It changes the
3034 * comm field, argv[0], and also the glibc's internally used
3035 * name of the process. For the first one a limit of 16 chars
3036 * applies, to the second one usually one of 10 (i.e. length
3037 * of "/sbin/init"), to the third one one of 7 (i.e. length of
3038 * "systemd"). If you pass a longer string it will be
3039 * truncated */
5b6319dc 3040
5d6b1584 3041 prctl(PR_SET_NAME, name);
5b6319dc
LP
3042
3043 if (program_invocation_name)
3044 strncpy(program_invocation_name, name, strlen(program_invocation_name));
9a0e6896
LP
3045
3046 if (saved_argc > 0) {
3047 int i;
3048
3049 if (saved_argv[0])
3050 strncpy(saved_argv[0], name, strlen(saved_argv[0]));
3051
3052 for (i = 1; i < saved_argc; i++) {
3053 if (!saved_argv[i])
3054 break;
3055
3056 memset(saved_argv[i], 0, strlen(saved_argv[i]));
3057 }
3058 }
5b6319dc
LP
3059}
3060
7d793605
LP
3061void sigset_add_many(sigset_t *ss, ...) {
3062 va_list ap;
3063 int sig;
3064
3065 assert(ss);
3066
3067 va_start(ap, ss);
3068 while ((sig = va_arg(ap, int)) > 0)
3069 assert_se(sigaddset(ss, sig) == 0);
3070 va_end(ap);
3071}
3072
ef2f1067
LP
3073char* gethostname_malloc(void) {
3074 struct utsname u;
3075
3076 assert_se(uname(&u) >= 0);
3077
344de609 3078 if (!isempty(u.nodename) && !streq(u.nodename, "(none)"))
ef2f1067
LP
3079 return strdup(u.nodename);
3080
3081 return strdup(u.sysname);
3082}
3083
344de609
LP
3084bool hostname_is_set(void) {
3085 struct utsname u;
3086
3087 assert_se(uname(&u) >= 0);
3088
3089 return !isempty(u.nodename) && !streq(u.nodename, "(none)");
3090}
3091
7c5f152a 3092static char *lookup_uid(uid_t uid) {
ef2f1067
LP
3093 long bufsize;
3094 char *buf, *name;
3095 struct passwd pwbuf, *pw = NULL;
ef2f1067
LP
3096
3097 /* Shortcut things to avoid NSS lookups */
3098 if (uid == 0)
3099 return strdup("root");
3100
7c5f152a
LP
3101 bufsize = sysconf(_SC_GETPW_R_SIZE_MAX);
3102 if (bufsize <= 0)
ef2f1067
LP
3103 bufsize = 4096;
3104
7c5f152a
LP
3105 buf = malloc(bufsize);
3106 if (!buf)
ef2f1067
LP
3107 return NULL;
3108
3109 if (getpwuid_r(uid, &pwbuf, buf, bufsize, &pw) == 0 && pw) {
3110 name = strdup(pw->pw_name);
3111 free(buf);
3112 return name;
3113 }
3114
3115 free(buf);
3116
3117 if (asprintf(&name, "%lu", (unsigned long) uid) < 0)
3118 return NULL;
3119
3120 return name;
3121}
3122
7c5f152a
LP
3123char* getlogname_malloc(void) {
3124 uid_t uid;
3125 struct stat st;
3126
3127 if (isatty(STDIN_FILENO) && fstat(STDIN_FILENO, &st) >= 0)
3128 uid = st.st_uid;
3129 else
3130 uid = getuid();
3131
3132 return lookup_uid(uid);
3133}
3134
3135char *getusername_malloc(void) {
3136 const char *e;
3137
3138 e = getenv("USER");
3139 if (e)
3140 return strdup(e);
3141
3142 return lookup_uid(getuid());
3143}
3144
fc116c6a
LP
3145int getttyname_malloc(int fd, char **r) {
3146 char path[PATH_MAX], *c;
618e02c7 3147 int k;
8c6db833
LP
3148
3149 assert(r);
ef2f1067 3150
fc116c6a 3151 if ((k = ttyname_r(fd, path, sizeof(path))) != 0)
618e02c7 3152 return -k;
ef2f1067
LP
3153
3154 char_array_0(path);
3155
fc116c6a 3156 if (!(c = strdup(startswith(path, "/dev/") ? path + 5 : path)))
8c6db833
LP
3157 return -ENOMEM;
3158
3159 *r = c;
3160 return 0;
3161}
3162
fc116c6a
LP
3163int getttyname_harder(int fd, char **r) {
3164 int k;
3165 char *s;
3166
3167 if ((k = getttyname_malloc(fd, &s)) < 0)
3168 return k;
3169
3170 if (streq(s, "tty")) {
3171 free(s);
4d6d6518 3172 return get_ctty(0, NULL, r);
fc116c6a
LP
3173 }
3174
3175 *r = s;
3176 return 0;
3177}
3178
4d6d6518 3179int get_ctty_devnr(pid_t pid, dev_t *d) {
fc116c6a 3180 int k;
4d6d6518 3181 char line[LINE_MAX], *p, *fn;
fc116c6a
LP
3182 unsigned long ttynr;
3183 FILE *f;
3184
4d6d6518
LP
3185 if (asprintf(&fn, "/proc/%lu/stat", (unsigned long) (pid <= 0 ? getpid() : pid)) < 0)
3186 return -ENOMEM;
3187
3188 f = fopen(fn, "re");
3189 free(fn);
3190 if (!f)
fc116c6a
LP
3191 return -errno;
3192
4d6d6518 3193 if (!fgets(line, sizeof(line), f)) {
35d50f55 3194 k = feof(f) ? -EIO : -errno;
fc116c6a
LP
3195 fclose(f);
3196 return k;
3197 }
3198
3199 fclose(f);
3200
4d6d6518
LP
3201 p = strrchr(line, ')');
3202 if (!p)
fc116c6a
LP
3203 return -EIO;
3204
3205 p++;
3206
3207 if (sscanf(p, " "
3208 "%*c " /* state */
3209 "%*d " /* ppid */
3210 "%*d " /* pgrp */
3211 "%*d " /* session */
3212 "%lu ", /* ttynr */
3213 &ttynr) != 1)
3214 return -EIO;
3215
3216 *d = (dev_t) ttynr;
3217 return 0;
3218}
3219
4d6d6518 3220int get_ctty(pid_t pid, dev_t *_devnr, char **r) {
fc116c6a 3221 int k;
20c03b7b 3222 char fn[PATH_MAX], *s, *b, *p;
fc116c6a
LP
3223 dev_t devnr;
3224
3225 assert(r);
3226
4d6d6518
LP
3227 k = get_ctty_devnr(pid, &devnr);
3228 if (k < 0)
fc116c6a
LP
3229 return k;
3230
3231 snprintf(fn, sizeof(fn), "/dev/char/%u:%u", major(devnr), minor(devnr));
3232 char_array_0(fn);
3233
3234 if ((k = readlink_malloc(fn, &s)) < 0) {
3235
3236 if (k != -ENOENT)
3237 return k;
3238
46824d0e
LP
3239 /* This is an ugly hack */
3240 if (major(devnr) == 136) {
3241 if (asprintf(&b, "pts/%lu", (unsigned long) minor(devnr)) < 0)
3242 return -ENOMEM;
3243
3244 *r = b;
3245 if (_devnr)
3246 *_devnr = devnr;
3247
3248 return 0;
3249 }
3250
fc116c6a
LP
3251 /* Probably something like the ptys which have no
3252 * symlink in /dev/char. Let's return something
3253 * vaguely useful. */
3254
3255 if (!(b = strdup(fn + 5)))
3256 return -ENOMEM;
3257
3258 *r = b;
46824d0e
LP
3259 if (_devnr)
3260 *_devnr = devnr;
3261
fc116c6a
LP
3262 return 0;
3263 }
3264
3265 if (startswith(s, "/dev/"))
3266 p = s + 5;
3267 else if (startswith(s, "../"))
3268 p = s + 3;
3269 else
3270 p = s;
3271
3272 b = strdup(p);
3273 free(s);
3274
3275 if (!b)
3276 return -ENOMEM;
3277
3278 *r = b;
46824d0e
LP
3279 if (_devnr)
3280 *_devnr = devnr;
3281
fc116c6a
LP
3282 return 0;
3283}
3284
f56d5db9 3285int rm_rf_children_dangerous(int fd, bool only_dirs, bool honour_sticky, struct stat *root_dev) {
8c6db833
LP
3286 DIR *d;
3287 int ret = 0;
3288
3289 assert(fd >= 0);
3290
3291 /* This returns the first error we run into, but nevertheless
7925c22a 3292 * tries to go on. This closes the passed fd. */
8c6db833 3293
d4d046e3
LP
3294 d = fdopendir(fd);
3295 if (!d) {
8c6db833 3296 close_nointr_nofail(fd);
4c633005
LP
3297
3298 return errno == ENOENT ? 0 : -errno;
8c6db833
LP
3299 }
3300
3301 for (;;) {
3302 struct dirent buf, *de;
7925c22a
LP
3303 bool is_dir, keep_around;
3304 struct stat st;
8c6db833
LP
3305 int r;
3306
d4d046e3
LP
3307 r = readdir_r(d, &buf, &de);
3308 if (r != 0 && ret == 0) {
3309 ret = -r;
8c6db833
LP
3310 break;
3311 }
3312
3313 if (!de)
3314 break;
3315
3316 if (streq(de->d_name, ".") || streq(de->d_name, ".."))
3317 continue;
3318
7925c22a
LP
3319 if (de->d_type == DT_UNKNOWN ||
3320 honour_sticky ||
3321 (de->d_type == DT_DIR && root_dev)) {
8c6db833 3322 if (fstatat(fd, de->d_name, &st, AT_SYMLINK_NOFOLLOW) < 0) {
4c633005 3323 if (ret == 0 && errno != ENOENT)
8c6db833
LP
3324 ret = -errno;
3325 continue;
3326 }
3327
3328 is_dir = S_ISDIR(st.st_mode);
7925c22a
LP
3329 keep_around =
3330 honour_sticky &&
3331 (st.st_uid == 0 || st.st_uid == getuid()) &&
3332 (st.st_mode & S_ISVTX);
ad293f5a 3333 } else {
8c6db833 3334 is_dir = de->d_type == DT_DIR;
7925c22a 3335 keep_around = false;
ad293f5a 3336 }
8c6db833
LP
3337
3338 if (is_dir) {
3339 int subdir_fd;
8c6db833 3340
597f43c7 3341 /* if root_dev is set, remove subdirectories only, if device is same as dir */
7925c22a
LP
3342 if (root_dev && st.st_dev != root_dev->st_dev)
3343 continue;
8c6db833 3344
7925c22a
LP
3345 subdir_fd = openat(fd, de->d_name,
3346 O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW|O_NOATIME);
3347 if (subdir_fd < 0) {
3348 if (ret == 0 && errno != ENOENT)
3349 ret = -errno;
3350 continue;
3351 }
3352
3353 r = rm_rf_children(subdir_fd, only_dirs, honour_sticky, root_dev);
3354 if (r < 0 && ret == 0)
3355 ret = r;
3356
3357 if (!keep_around)
3358 if (unlinkat(fd, de->d_name, AT_REMOVEDIR) < 0) {
ad293f5a
LP
3359 if (ret == 0 && errno != ENOENT)
3360 ret = -errno;
3361 }
3362
3363 } else if (!only_dirs && !keep_around) {
8c6db833
LP
3364
3365 if (unlinkat(fd, de->d_name, 0) < 0) {
4c633005 3366 if (ret == 0 && errno != ENOENT)
8c6db833
LP
3367 ret = -errno;
3368 }
3369 }
3370 }
3371
3372 closedir(d);
3373
3374 return ret;
3375}
3376
f56d5db9
LP
3377int rm_rf_children(int fd, bool only_dirs, bool honour_sticky, struct stat *root_dev) {
3378 struct statfs s;
3379
3380 assert(fd >= 0);
3381
3382 if (fstatfs(fd, &s) < 0) {
3383 close_nointr_nofail(fd);
3384 return -errno;
3385 }
3386
3387 /* We refuse to clean disk file systems with this call. This
3388 * is extra paranoia just to be sure we never ever remove
3389 * non-state data */
3390
3391 if (s.f_type != TMPFS_MAGIC &&
3392 s.f_type != RAMFS_MAGIC) {
3393 log_error("Attempted to remove disk file system, and we can't allow that.");
3394 close_nointr_nofail(fd);
3395 return -EPERM;
3396 }
3397
3398 return rm_rf_children_dangerous(fd, only_dirs, honour_sticky, root_dev);
3399}
3400
3401static int rm_rf_internal(const char *path, bool only_dirs, bool delete_root, bool honour_sticky, bool dangerous) {
3402 int fd, r;
3403 struct statfs s;
8c6db833
LP
3404
3405 assert(path);
3406
f56d5db9
LP
3407 /* We refuse to clean the root file system with this
3408 * call. This is extra paranoia to never cause a really
3409 * seriously broken system. */
3410 if (path_equal(path, "/")) {
3411 log_error("Attempted to remove entire root file system, and we can't allow that.");
3412 return -EPERM;
3413 }
461b1822 3414
d4d046e3
LP
3415 fd = open(path, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW|O_NOATIME);
3416 if (fd < 0) {
8c6db833
LP
3417
3418 if (errno != ENOTDIR)
3419 return -errno;
3420
f56d5db9
LP
3421 if (!dangerous) {
3422 if (statfs(path, &s) < 0)
3423 return -errno;
3424
3425 if (s.f_type != TMPFS_MAGIC &&
3426 s.f_type != RAMFS_MAGIC) {
3427 log_error("Attempted to remove disk file system, and we can't allow that.");
3428 return -EPERM;
3429 }
3430 }
3431
8c6db833 3432 if (delete_root && !only_dirs)
d4d046e3 3433 if (unlink(path) < 0 && errno != ENOENT)
8c6db833
LP
3434 return -errno;
3435
3436 return 0;
3437 }
3438
f56d5db9
LP
3439 if (!dangerous) {
3440 if (fstatfs(fd, &s) < 0) {
3441 close_nointr_nofail(fd);
3442 return -errno;
3443 }
ad293f5a 3444
f56d5db9
LP
3445 if (s.f_type != TMPFS_MAGIC &&
3446 s.f_type != RAMFS_MAGIC) {
3447 log_error("Attempted to remove disk file system, and we can't allow that.");
3448 close_nointr_nofail(fd);
3449 return -EPERM;
3450 }
3451 }
3452
3453 r = rm_rf_children_dangerous(fd, only_dirs, honour_sticky, NULL);
ad293f5a
LP
3454 if (delete_root) {
3455
8d53b453 3456 if (honour_sticky && file_is_priv_sticky(path) > 0)
ad293f5a 3457 return r;
8c6db833 3458
e27796a0 3459 if (rmdir(path) < 0 && errno != ENOENT) {
8c6db833
LP
3460 if (r == 0)
3461 r = -errno;
3462 }
ad293f5a 3463 }
8c6db833
LP
3464
3465 return r;
3466}
3467
f56d5db9
LP
3468int rm_rf(const char *path, bool only_dirs, bool delete_root, bool honour_sticky) {
3469 return rm_rf_internal(path, only_dirs, delete_root, honour_sticky, false);
3470}
3471
3472int rm_rf_dangerous(const char *path, bool only_dirs, bool delete_root, bool honour_sticky) {
3473 return rm_rf_internal(path, only_dirs, delete_root, honour_sticky, true);
3474}
3475
8c6db833
LP
3476int chmod_and_chown(const char *path, mode_t mode, uid_t uid, gid_t gid) {
3477 assert(path);
3478
3479 /* Under the assumption that we are running privileged we
3480 * first change the access mode and only then hand out
3481 * ownership to avoid a window where access is too open. */
3482
8d53b453
LP
3483 if (mode != (mode_t) -1)
3484 if (chmod(path, mode) < 0)
3485 return -errno;
8c6db833 3486
8d53b453
LP
3487 if (uid != (uid_t) -1 || gid != (gid_t) -1)
3488 if (chown(path, uid, gid) < 0)
3489 return -errno;
8c6db833
LP
3490
3491 return 0;
ef2f1067
LP
3492}
3493
f4b47811
LP
3494int fchmod_and_fchown(int fd, mode_t mode, uid_t uid, gid_t gid) {
3495 assert(fd >= 0);
3496
3497 /* Under the assumption that we are running privileged we
3498 * first change the access mode and only then hand out
3499 * ownership to avoid a window where access is too open. */
3500
3501 if (fchmod(fd, mode) < 0)
3502 return -errno;
3503
3504 if (fchown(fd, uid, gid) < 0)
3505 return -errno;
3506
3507 return 0;
3508}
3509
82c121a4
LP
3510cpu_set_t* cpu_set_malloc(unsigned *ncpus) {
3511 cpu_set_t *r;
3512 unsigned n = 1024;
3513
3514 /* Allocates the cpuset in the right size */
3515
3516 for (;;) {
3517 if (!(r = CPU_ALLOC(n)))
3518 return NULL;
3519
3520 if (sched_getaffinity(0, CPU_ALLOC_SIZE(n), r) >= 0) {
3521 CPU_ZERO_S(CPU_ALLOC_SIZE(n), r);
3522
3523 if (ncpus)
3524 *ncpus = n;
3525
3526 return r;
3527 }
3528
3529 CPU_FREE(r);
3530
3531 if (errno != EINVAL)
3532 return NULL;
3533
3534 n *= 2;
3535 }
3536}
3537
67e5cc4f 3538void status_vprintf(const char *status, bool ellipse, const char *format, va_list ap) {
9ab7a8d2
MS
3539 char *s = NULL;
3540 static const char status_indent[] = " "; /* "[" STATUS "] " */
3541 int fd = -1;
81beb750
LP
3542 struct iovec iovec[5];
3543 int n = 0;
9e58ff9c
LP
3544
3545 assert(format);
3546
9ab7a8d2 3547 /* This is independent of logging, as status messages are
9e58ff9c
LP
3548 * optional and go exclusively to the console. */
3549
3550 if (vasprintf(&s, format, ap) < 0)
3551 goto finish;
3552
67e5cc4f 3553 fd = open_terminal("/dev/console", O_WRONLY|O_NOCTTY|O_CLOEXEC);
81beb750 3554 if (fd < 0)
9e58ff9c
LP
3555 goto finish;
3556
67e5cc4f 3557 if (ellipse) {
9ab7a8d2
MS
3558 char *e;
3559 size_t emax, sl;
3560 int c;
3561
67e5cc4f
LP
3562 c = fd_columns(fd);
3563 if (c <= 0)
3564 c = 80;
81beb750 3565
9ab7a8d2
MS
3566 sl = status ? strlen(status_indent) : 0;
3567
3568 emax = c - sl - 1;
3569 if (emax < 3)
3570 emax = 3;
81beb750 3571
67e5cc4f
LP
3572 e = ellipsize(s, emax, 75);
3573 if (e) {
3574 free(s);
3575 s = e;
3576 }
81beb750
LP
3577 }
3578
3579 zero(iovec);
81beb750 3580
9ab7a8d2
MS
3581 if (status) {
3582 if (!isempty(status)) {
3583 IOVEC_SET_STRING(iovec[n++], "[");
3584 IOVEC_SET_STRING(iovec[n++], status);
3585 IOVEC_SET_STRING(iovec[n++], "] ");
3586 } else
3587 IOVEC_SET_STRING(iovec[n++], status_indent);
81beb750
LP
3588 }
3589
9ab7a8d2
MS
3590 IOVEC_SET_STRING(iovec[n++], s);
3591 IOVEC_SET_STRING(iovec[n++], "\n");
81beb750
LP
3592
3593 writev(fd, iovec, n);
9e58ff9c
LP
3594
3595finish:
3596 free(s);
3597
3598 if (fd >= 0)
3599 close_nointr_nofail(fd);
3600}
3601
67e5cc4f 3602void status_printf(const char *status, bool ellipse, const char *format, ...) {
c846ff47
LP
3603 va_list ap;
3604
3605 assert(format);
3606
3607 va_start(ap, format);
67e5cc4f 3608 status_vprintf(status, ellipse, format, ap);
c846ff47
LP
3609 va_end(ap);
3610}
3611
3612void status_welcome(void) {
10aa7034
LP
3613 char *pretty_name = NULL, *ansi_color = NULL;
3614 const char *const_pretty = NULL, *const_color = NULL;
3615 int r;
c846ff47 3616
10aa7034
LP
3617 if ((r = parse_env_file("/etc/os-release", NEWLINE,
3618 "PRETTY_NAME", &pretty_name,
3619 "ANSI_COLOR", &ansi_color,
3620 NULL)) < 0) {
c846ff47 3621
10aa7034
LP
3622 if (r != -ENOENT)
3623 log_warning("Failed to read /etc/os-release: %s", strerror(-r));
3624 }
c846ff47 3625
10aa7034
LP
3626 if (!pretty_name && !const_pretty)
3627 const_pretty = "Linux";
3628
3629 if (!ansi_color && !const_color)
3630 const_color = "1";
3631
81beb750 3632 status_printf(NULL,
67e5cc4f 3633 false,
81beb750 3634 "\nWelcome to \x1B[%sm%s\x1B[0m!\n",
10aa7034
LP
3635 const_color ? const_color : ansi_color,
3636 const_pretty ? const_pretty : pretty_name);
86a3475b
LP
3637
3638 free(ansi_color);
3639 free(pretty_name);
c846ff47
LP
3640}
3641
fab56fc5
LP
3642char *replace_env(const char *format, char **env) {
3643 enum {
3644 WORD,
c24eb49e 3645 CURLY,
fab56fc5
LP
3646 VARIABLE
3647 } state = WORD;
3648
3649 const char *e, *word = format;
3650 char *r = NULL, *k;
3651
3652 assert(format);
3653
3654 for (e = format; *e; e ++) {
3655
3656 switch (state) {
3657
3658 case WORD:
3659 if (*e == '$')
c24eb49e 3660 state = CURLY;
fab56fc5
LP
3661 break;
3662
c24eb49e
LP
3663 case CURLY:
3664 if (*e == '{') {
fab56fc5
LP
3665 if (!(k = strnappend(r, word, e-word-1)))
3666 goto fail;
3667
3668 free(r);
3669 r = k;
3670
3671 word = e-1;
3672 state = VARIABLE;
3673
3674 } else if (*e == '$') {
3675 if (!(k = strnappend(r, word, e-word)))
3676 goto fail;
3677
3678 free(r);
3679 r = k;
3680
3681 word = e+1;
3682 state = WORD;
3683 } else
3684 state = WORD;
3685 break;
3686
3687 case VARIABLE:
c24eb49e 3688 if (*e == '}') {
b95cf362 3689 const char *t;
fab56fc5 3690
b95cf362
LP
3691 if (!(t = strv_env_get_with_length(env, word+2, e-word-2)))
3692 t = "";
fab56fc5 3693
b95cf362
LP
3694 if (!(k = strappend(r, t)))
3695 goto fail;
fab56fc5 3696
b95cf362
LP
3697 free(r);
3698 r = k;
fab56fc5 3699
b95cf362 3700 word = e+1;
fab56fc5
LP
3701 state = WORD;
3702 }
3703 break;
3704 }
3705 }
3706
3707 if (!(k = strnappend(r, word, e-word)))
3708 goto fail;
3709
3710 free(r);
3711 return k;
3712
3713fail:
3714 free(r);
3715 return NULL;
3716}
3717
3718char **replace_env_argv(char **argv, char **env) {
3719 char **r, **i;
c24eb49e
LP
3720 unsigned k = 0, l = 0;
3721
3722 l = strv_length(argv);
fab56fc5 3723
c24eb49e 3724 if (!(r = new(char*, l+1)))
fab56fc5
LP
3725 return NULL;
3726
3727 STRV_FOREACH(i, argv) {
c24eb49e
LP
3728
3729 /* If $FOO appears as single word, replace it by the split up variable */
b95cf362
LP
3730 if ((*i)[0] == '$' && (*i)[1] != '{') {
3731 char *e;
3732 char **w, **m;
3733 unsigned q;
c24eb49e 3734
b95cf362 3735 if ((e = strv_env_get(env, *i+1))) {
c24eb49e
LP
3736
3737 if (!(m = strv_split_quoted(e))) {
3738 r[k] = NULL;
3739 strv_free(r);
3740 return NULL;
3741 }
b95cf362
LP
3742 } else
3743 m = NULL;
c24eb49e 3744
b95cf362
LP
3745 q = strv_length(m);
3746 l = l + q - 1;
c24eb49e 3747
b95cf362
LP
3748 if (!(w = realloc(r, sizeof(char*) * (l+1)))) {
3749 r[k] = NULL;
3750 strv_free(r);
3751 strv_free(m);
3752 return NULL;
3753 }
c24eb49e 3754
b95cf362
LP
3755 r = w;
3756 if (m) {
c24eb49e
LP
3757 memcpy(r + k, m, q * sizeof(char*));
3758 free(m);
c24eb49e 3759 }
b95cf362
LP
3760
3761 k += q;
3762 continue;
c24eb49e
LP
3763 }
3764
3765 /* If ${FOO} appears as part of a word, replace it by the variable as-is */
fab56fc5
LP
3766 if (!(r[k++] = replace_env(*i, env))) {
3767 strv_free(r);
3768 return NULL;
3769 }
3770 }
3771
3772 r[k] = NULL;
3773 return r;
3774}
3775
81beb750
LP
3776int fd_columns(int fd) {
3777 struct winsize ws;
3778 zero(ws);
3779
3780 if (ioctl(fd, TIOCGWINSZ, &ws) < 0)
3781 return -errno;
3782
3783 if (ws.ws_col <= 0)
3784 return -EIO;
3785
3786 return ws.ws_col;
3787}
3788
11f96fac
ZJS
3789static unsigned columns_cached(bool cached) {
3790 static __thread int parsed_columns = 0, env_columns = -1;
fa776d8e
LP
3791 const char *e;
3792
11f96fac 3793 if (_likely_(parsed_columns > 0 && cached))
fa776d8e
LP
3794 return parsed_columns;
3795
11f96fac
ZJS
3796 if (_unlikely_(env_columns == -1)) {
3797 e = getenv("COLUMNS");
3798 if (e)
3799 env_columns = atoi(e);
3800 else
3801 env_columns = 0;
3802 }
fa776d8e 3803
11f96fac
ZJS
3804 if (env_columns > 0) {
3805 parsed_columns = env_columns;
3806 return parsed_columns;
3807 }
3808
3809 if (parsed_columns <= 0 || !cached)
81beb750 3810 parsed_columns = fd_columns(STDOUT_FILENO);
fa776d8e
LP
3811
3812 if (parsed_columns <= 0)
3813 parsed_columns = 80;
3814
3815 return parsed_columns;
3816}
3817
11f96fac
ZJS
3818unsigned columns(void) {
3819 return columns_cached(true);
3820}
3821
3822unsigned columns_uncached(void) {
3823 return columns_cached(false);
3824}
3825
8f2d43a0
LP
3826int fd_lines(int fd) {
3827 struct winsize ws;
3828 zero(ws);
3829
3830 if (ioctl(fd, TIOCGWINSZ, &ws) < 0)
3831 return -errno;
3832
3833 if (ws.ws_row <= 0)
3834 return -EIO;
3835
3836 return ws.ws_row;
3837}
3838
3839unsigned lines(void) {
3840 static __thread int parsed_lines = 0;
3841 const char *e;
3842
3843 if (_likely_(parsed_lines > 0))
3844 return parsed_lines;
3845
3846 e = getenv("LINES");
3847 if (e)
3848 parsed_lines = atoi(e);
3849
3850 if (parsed_lines <= 0)
3851 parsed_lines = fd_lines(STDOUT_FILENO);
3852
3853 if (parsed_lines <= 0)
3854 parsed_lines = 25;
3855
3856 return parsed_lines;
3857}
3858
b4f10a5e
LP
3859int running_in_chroot(void) {
3860 struct stat a, b;
3861
3862 zero(a);
3863 zero(b);
3864
3865 /* Only works as root */
3866
3867 if (stat("/proc/1/root", &a) < 0)
3868 return -errno;
3869
3870 if (stat("/", &b) < 0)
3871 return -errno;
3872
3873 return
3874 a.st_dev != b.st_dev ||
3875 a.st_ino != b.st_ino;
3876}
3877
72f59706
LP
3878char *ellipsize_mem(const char *s, size_t old_length, size_t new_length, unsigned percent) {
3879 size_t x;
8fe914ec
LP
3880 char *r;
3881
3882 assert(s);
3883 assert(percent <= 100);
72f59706 3884 assert(new_length >= 3);
8fe914ec 3885
72f59706
LP
3886 if (old_length <= 3 || old_length <= new_length)
3887 return strndup(s, old_length);
8fe914ec 3888
72f59706
LP
3889 r = new0(char, new_length+1);
3890 if (!r)
8fe914ec
LP
3891 return r;
3892
72f59706 3893 x = (new_length * percent) / 100;
8fe914ec 3894
72f59706
LP
3895 if (x > new_length - 3)
3896 x = new_length - 3;
8fe914ec
LP
3897
3898 memcpy(r, s, x);
3899 r[x] = '.';
3900 r[x+1] = '.';
3901 r[x+2] = '.';
3902 memcpy(r + x + 3,
72f59706
LP
3903 s + old_length - (new_length - x - 3),
3904 new_length - x - 3);
8fe914ec
LP
3905
3906 return r;
3907}
3908
72f59706
LP
3909char *ellipsize(const char *s, size_t length, unsigned percent) {
3910 return ellipsize_mem(s, strlen(s), length, percent);
3911}
3912
f6144808
LP
3913int touch(const char *path) {
3914 int fd;
3915
3916 assert(path);
3917
14f3c825 3918 if ((fd = open(path, O_WRONLY|O_CREAT|O_CLOEXEC|O_NOCTTY, 0644)) < 0)
f6144808
LP
3919 return -errno;
3920
3921 close_nointr_nofail(fd);
3922 return 0;
3923}
afea26ad 3924
97c4a07d 3925char *unquote(const char *s, const char* quotes) {
11ce3427
LP
3926 size_t l;
3927 assert(s);
3928
31ed59c5
LP
3929 l = strlen(s);
3930 if (l < 2)
11ce3427
LP
3931 return strdup(s);
3932
97c4a07d 3933 if (strchr(quotes, s[0]) && s[l-1] == s[0])
11ce3427
LP
3934 return strndup(s+1, l-2);
3935
3936 return strdup(s);
3937}
3938
5f7c426e
LP
3939char *normalize_env_assignment(const char *s) {
3940 char *name, *value, *p, *r;
3941
3942 p = strchr(s, '=');
3943
3944 if (!p) {
3945 if (!(r = strdup(s)))
3946 return NULL;
3947
3948 return strstrip(r);
3949 }
3950
3951 if (!(name = strndup(s, p - s)))
3952 return NULL;
3953
3954 if (!(p = strdup(p+1))) {
3955 free(name);
3956 return NULL;
3957 }
3958
3959 value = unquote(strstrip(p), QUOTES);
3960 free(p);
3961
3962 if (!value) {
5f7c426e
LP
3963 free(name);
3964 return NULL;
3965 }
3966
3967 if (asprintf(&r, "%s=%s", name, value) < 0)
3968 r = NULL;
3969
3970 free(value);
3971 free(name);
3972
3973 return r;
3974}
3975
8e12a6ae 3976int wait_for_terminate(pid_t pid, siginfo_t *status) {
1968a360
LP
3977 siginfo_t dummy;
3978
2e78aa99 3979 assert(pid >= 1);
1968a360
LP
3980
3981 if (!status)
3982 status = &dummy;
2e78aa99
LP
3983
3984 for (;;) {
8e12a6ae
LP
3985 zero(*status);
3986
3987 if (waitid(P_PID, pid, status, WEXITED) < 0) {
2e78aa99
LP
3988
3989 if (errno == EINTR)
3990 continue;
3991
3992 return -errno;
3993 }
3994
3995 return 0;
3996 }
3997}
3998
97c4a07d
LP
3999int wait_for_terminate_and_warn(const char *name, pid_t pid) {
4000 int r;
4001 siginfo_t status;
4002
4003 assert(name);
4004 assert(pid > 1);
4005
4006 if ((r = wait_for_terminate(pid, &status)) < 0) {
4007 log_warning("Failed to wait for %s: %s", name, strerror(-r));
4008 return r;
4009 }
4010
4011 if (status.si_code == CLD_EXITED) {
4012 if (status.si_status != 0) {
4013 log_warning("%s failed with error code %i.", name, status.si_status);
0a27cf3f 4014 return status.si_status;
97c4a07d
LP
4015 }
4016
4017 log_debug("%s succeeded.", name);
4018 return 0;
4019
4020 } else if (status.si_code == CLD_KILLED ||
4021 status.si_code == CLD_DUMPED) {
4022
4023 log_warning("%s terminated by signal %s.", name, signal_to_string(status.si_status));
4024 return -EPROTO;
4025 }
4026
4027 log_warning("%s failed due to unknown reason.", name);
4028 return -EPROTO;
4029
4030}
4031
6a39419f 4032_noreturn_ void freeze(void) {
720ce21d
LP
4033
4034 /* Make sure nobody waits for us on a socket anymore */
4035 close_all_fds(NULL, 0);
4036
c29597a1
LP
4037 sync();
4038
3c14d26c
LP
4039 for (;;)
4040 pause();
4041}
4042
00dc5d76
LP
4043bool null_or_empty(struct stat *st) {
4044 assert(st);
4045
4046 if (S_ISREG(st->st_mode) && st->st_size <= 0)
4047 return true;
4048
c8f26f42 4049 if (S_ISCHR(st->st_mode) || S_ISBLK(st->st_mode))
00dc5d76
LP
4050 return true;
4051
4052 return false;
4053}
4054
83096483
LP
4055int null_or_empty_path(const char *fn) {
4056 struct stat st;
4057
4058 assert(fn);
4059
4060 if (stat(fn, &st) < 0)
4061 return -errno;
4062
4063 return null_or_empty(&st);
4064}
4065
a247755d 4066DIR *xopendirat(int fd, const char *name, int flags) {
c4731d11
LP
4067 int nfd;
4068 DIR *d;
4069
4070 if ((nfd = openat(fd, name, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|flags)) < 0)
4071 return NULL;
4072
4073 if (!(d = fdopendir(nfd))) {
4074 close_nointr_nofail(nfd);
4075 return NULL;
4076 }
4077
4078 return d;
3b63d2d3
LP
4079}
4080
8a0867d6
LP
4081int signal_from_string_try_harder(const char *s) {
4082 int signo;
4083 assert(s);
4084
4085 if ((signo = signal_from_string(s)) <= 0)
4086 if (startswith(s, "SIG"))
4087 return signal_from_string(s+3);
4088
4089 return signo;
4090}
4091
10717a1a
LP
4092void dual_timestamp_serialize(FILE *f, const char *name, dual_timestamp *t) {
4093
4094 assert(f);
4095 assert(name);
4096 assert(t);
4097
4098 if (!dual_timestamp_is_set(t))
4099 return;
4100
4101 fprintf(f, "%s=%llu %llu\n",
4102 name,
4103 (unsigned long long) t->realtime,
4104 (unsigned long long) t->monotonic);
4105}
4106
799fd0fd 4107void dual_timestamp_deserialize(const char *value, dual_timestamp *t) {
10717a1a
LP
4108 unsigned long long a, b;
4109
10717a1a
LP
4110 assert(value);
4111 assert(t);
4112
4113 if (sscanf(value, "%lli %llu", &a, &b) != 2)
4114 log_debug("Failed to parse finish timestamp value %s", value);
4115 else {
4116 t->realtime = a;
4117 t->monotonic = b;
4118 }
4119}
4120
e23a0ce8
LP
4121char *fstab_node_to_udev_node(const char *p) {
4122 char *dn, *t, *u;
4123 int r;
4124
4125 /* FIXME: to follow udev's logic 100% we need to leave valid
4126 * UTF8 chars unescaped */
4127
4128 if (startswith(p, "LABEL=")) {
4129
4130 if (!(u = unquote(p+6, "\"\'")))
4131 return NULL;
4132
4133 t = xescape(u, "/ ");
4134 free(u);
4135
4136 if (!t)
4137 return NULL;
4138
4139 r = asprintf(&dn, "/dev/disk/by-label/%s", t);
4140 free(t);
4141
4142 if (r < 0)
4143 return NULL;
4144
4145 return dn;
4146 }
4147
4148 if (startswith(p, "UUID=")) {
4149
4150 if (!(u = unquote(p+5, "\"\'")))
4151 return NULL;
4152
4153 t = xescape(u, "/ ");
4154 free(u);
4155
4156 if (!t)
4157 return NULL;
4158
0058d7b9 4159 r = asprintf(&dn, "/dev/disk/by-uuid/%s", t);
e23a0ce8
LP
4160 free(t);
4161
4162 if (r < 0)
4163 return NULL;
4164
4165 return dn;
4166 }
4167
4168 return strdup(p);
4169}
4170
f212ac12
LP
4171bool tty_is_vc(const char *tty) {
4172 assert(tty);
4173
4174 if (startswith(tty, "/dev/"))
4175 tty += 5;
4176
98a28fef
LP
4177 return vtnr_from_tty(tty) >= 0;
4178}
4179
d1122ad5
LP
4180bool tty_is_console(const char *tty) {
4181 assert(tty);
4182
4183 if (startswith(tty, "/dev/"))
4184 tty += 5;
4185
4186 return streq(tty, "console");
4187}
4188
98a28fef
LP
4189int vtnr_from_tty(const char *tty) {
4190 int i, r;
4191
4192 assert(tty);
4193
4194 if (startswith(tty, "/dev/"))
4195 tty += 5;
4196
4197 if (!startswith(tty, "tty") )
4198 return -EINVAL;
4199
4200 if (tty[3] < '0' || tty[3] > '9')
4201 return -EINVAL;
4202
4203 r = safe_atoi(tty+3, &i);
4204 if (r < 0)
4205 return r;
4206
4207 if (i < 0 || i > 63)
4208 return -EINVAL;
4209
4210 return i;
f212ac12
LP
4211}
4212
3043935f 4213bool tty_is_vc_resolve(const char *tty) {
3030ccd7 4214 char *active = NULL;
3043935f 4215 bool b;
3030ccd7 4216
e3aa71c3
LP
4217 assert(tty);
4218
4219 if (startswith(tty, "/dev/"))
4220 tty += 5;
4221
3d9a4122
LP
4222 /* Resolve where /dev/console is pointing to, if /sys is
4223 * actually ours (i.e. not read-only-mounted which is a sign
4224 * for container setups) */
4225 if (streq(tty, "console") && path_is_read_only_fs("/sys") <= 0)
3030ccd7 4226 if (read_one_line_file("/sys/class/tty/console/active", &active) >= 0) {
079a09fb
LP
4227 /* If multiple log outputs are configured the
4228 * last one is what /dev/console points to */
3043935f
LP
4229 tty = strrchr(active, ' ');
4230 if (tty)
079a09fb
LP
4231 tty++;
4232 else
4233 tty = active;
3030ccd7
LP
4234 }
4235
3043935f 4236 b = tty_is_vc(tty);
3030ccd7 4237 free(active);
e3aa71c3 4238
3043935f
LP
4239 return b;
4240}
4241
4242const char *default_term_for_tty(const char *tty) {
4243 assert(tty);
4244
acda6a05 4245 return tty_is_vc_resolve(tty) ? "TERM=linux" : "TERM=vt102";
e3aa71c3
LP
4246}
4247
87d2c1ff 4248bool dirent_is_file(const struct dirent *de) {
fb19a739
LP
4249 assert(de);
4250
4251 if (ignore_file(de->d_name))
4252 return false;
4253
4254 if (de->d_type != DT_REG &&
4255 de->d_type != DT_LNK &&
4256 de->d_type != DT_UNKNOWN)
4257 return false;
4258
4259 return true;
4260}
4261
87d2c1ff
LP
4262bool dirent_is_file_with_suffix(const struct dirent *de, const char *suffix) {
4263 assert(de);
4264
4265 if (!dirent_is_file(de))
4266 return false;
4267
4268 return endswith(de->d_name, suffix);
4269}
4270
83cc030f
LP
4271void execute_directory(const char *directory, DIR *d, char *argv[]) {
4272 DIR *_d = NULL;
4273 struct dirent *de;
4274 Hashmap *pids = NULL;
4275
4276 assert(directory);
4277
4278 /* Executes all binaries in a directory in parallel and waits
4279 * until all they all finished. */
4280
4281 if (!d) {
4282 if (!(_d = opendir(directory))) {
4283
4284 if (errno == ENOENT)
4285 return;
4286
4287 log_error("Failed to enumerate directory %s: %m", directory);
4288 return;
4289 }
4290
4291 d = _d;
4292 }
4293
4294 if (!(pids = hashmap_new(trivial_hash_func, trivial_compare_func))) {
4295 log_error("Failed to allocate set.");
4296 goto finish;
4297 }
4298
4299 while ((de = readdir(d))) {
4300 char *path;
4301 pid_t pid;
4302 int k;
4303
fb19a739 4304 if (!dirent_is_file(de))
83cc030f
LP
4305 continue;
4306
4307 if (asprintf(&path, "%s/%s", directory, de->d_name) < 0) {
0d0f0c50 4308 log_oom();
83cc030f
LP
4309 continue;
4310 }
4311
4312 if ((pid = fork()) < 0) {
4313 log_error("Failed to fork: %m");
4314 free(path);
4315 continue;
4316 }
4317
4318 if (pid == 0) {
4319 char *_argv[2];
4320 /* Child */
4321
4322 if (!argv) {
4323 _argv[0] = path;
4324 _argv[1] = NULL;
4325 argv = _argv;
4326 } else
6edd7d0a 4327 argv[0] = path;
83cc030f
LP
4328
4329 execv(path, argv);
4330
4331 log_error("Failed to execute %s: %m", path);
4332 _exit(EXIT_FAILURE);
4333 }
4334
4335 log_debug("Spawned %s as %lu", path, (unsigned long) pid);
4336
4337 if ((k = hashmap_put(pids, UINT_TO_PTR(pid), path)) < 0) {
4338 log_error("Failed to add PID to set: %s", strerror(-k));
4339 free(path);
4340 }
4341 }
4342
4343 while (!hashmap_isempty(pids)) {
ec3f9b53 4344 pid_t pid = PTR_TO_UINT(hashmap_first_key(pids));
83cc030f
LP
4345 siginfo_t si;
4346 char *path;
4347
4348 zero(si);
ec3f9b53 4349 if (waitid(P_PID, pid, &si, WEXITED) < 0) {
83cc030f
LP
4350
4351 if (errno == EINTR)
4352 continue;
4353
4354 log_error("waitid() failed: %m");
4355 goto finish;
4356 }
4357
4358 if ((path = hashmap_remove(pids, UINT_TO_PTR(si.si_pid)))) {
96342de6 4359 if (!is_clean_exit(si.si_code, si.si_status, NULL)) {
83cc030f
LP
4360 if (si.si_code == CLD_EXITED)
4361 log_error("%s exited with exit status %i.", path, si.si_status);
4362 else
4363 log_error("%s terminated by signal %s.", path, signal_to_string(si.si_status));
4364 } else
4365 log_debug("%s exited successfully.", path);
4366
4367 free(path);
4368 }
4369 }
4370
4371finish:
4372 if (_d)
4373 closedir(_d);
4374
4375 if (pids)
4376 hashmap_free_free(pids);
4377}
4378
430c18ed
LP
4379int kill_and_sigcont(pid_t pid, int sig) {
4380 int r;
4381
4382 r = kill(pid, sig) < 0 ? -errno : 0;
4383
4384 if (r >= 0)
4385 kill(pid, SIGCONT);
4386
4387 return r;
4388}
4389
05feefe0
LP
4390bool nulstr_contains(const char*nulstr, const char *needle) {
4391 const char *i;
4392
4393 if (!nulstr)
4394 return false;
4395
4396 NULSTR_FOREACH(i, nulstr)
4397 if (streq(i, needle))
4398 return true;
4399
4400 return false;
4401}
4402
6faa1114 4403bool plymouth_running(void) {
9408a2d2 4404 return access("/run/plymouth/pid", F_OK) >= 0;
6faa1114
LP
4405}
4406
7c3b203c
LP
4407void parse_syslog_priority(char **p, int *priority) {
4408 int a = 0, b = 0, c = 0;
4409 int k;
4410
4411 assert(p);
4412 assert(*p);
4413 assert(priority);
4414
4415 if ((*p)[0] != '<')
4416 return;
4417
4418 if (!strchr(*p, '>'))
4419 return;
4420
4421 if ((*p)[2] == '>') {
4422 c = undecchar((*p)[1]);
4423 k = 3;
4424 } else if ((*p)[3] == '>') {
4425 b = undecchar((*p)[1]);
4426 c = undecchar((*p)[2]);
4427 k = 4;
4428 } else if ((*p)[4] == '>') {
4429 a = undecchar((*p)[1]);
4430 b = undecchar((*p)[2]);
4431 c = undecchar((*p)[3]);
4432 k = 5;
4433 } else
4434 return;
4435
4436 if (a < 0 || b < 0 || c < 0)
4437 return;
4438
4439 *priority = a*100+b*10+c;
4440 *p += k;
4441}
4442
87d2c1ff
LP
4443void skip_syslog_pid(char **buf) {
4444 char *p;
4445
4446 assert(buf);
4447 assert(*buf);
4448
4449 p = *buf;
4450
4451 if (*p != '[')
4452 return;
4453
4454 p++;
4455 p += strspn(p, "0123456789");
4456
4457 if (*p != ']')
4458 return;
4459
4460 p++;
4461
4462 *buf = p;
4463}
4464
4465void skip_syslog_date(char **buf) {
4466 enum {
4467 LETTER,
4468 SPACE,
4469 NUMBER,
4470 SPACE_OR_NUMBER,
4471 COLON
4472 } sequence[] = {
4473 LETTER, LETTER, LETTER,
4474 SPACE,
4475 SPACE_OR_NUMBER, NUMBER,
4476 SPACE,
4477 SPACE_OR_NUMBER, NUMBER,
4478 COLON,
4479 SPACE_OR_NUMBER, NUMBER,
4480 COLON,
4481 SPACE_OR_NUMBER, NUMBER,
4482 SPACE
4483 };
4484
4485 char *p;
4486 unsigned i;
4487
4488 assert(buf);
4489 assert(*buf);
4490
4491 p = *buf;
4492
4493 for (i = 0; i < ELEMENTSOF(sequence); i++, p++) {
4494
4495 if (!*p)
4496 return;
4497
4498 switch (sequence[i]) {
4499
4500 case SPACE:
4501 if (*p != ' ')
4502 return;
4503 break;
4504
4505 case SPACE_OR_NUMBER:
4506 if (*p == ' ')
4507 break;
4508
4509 /* fall through */
4510
4511 case NUMBER:
4512 if (*p < '0' || *p > '9')
4513 return;
4514
4515 break;
4516
4517 case LETTER:
4518 if (!(*p >= 'A' && *p <= 'Z') &&
4519 !(*p >= 'a' && *p <= 'z'))
4520 return;
4521
4522 break;
4523
4524 case COLON:
4525 if (*p != ':')
4526 return;
4527 break;
4528
4529 }
4530 }
4531
4532 *buf = p;
4533}
4534
9beb3f4d
LP
4535char* strshorten(char *s, size_t l) {
4536 assert(s);
4537
4538 if (l < strlen(s))
4539 s[l] = 0;
4540
4541 return s;
4542}
4543
4544static bool hostname_valid_char(char c) {
4545 return
4546 (c >= 'a' && c <= 'z') ||
4547 (c >= 'A' && c <= 'Z') ||
4548 (c >= '0' && c <= '9') ||
4549 c == '-' ||
4550 c == '_' ||
4551 c == '.';
4552}
4553
4554bool hostname_is_valid(const char *s) {
4555 const char *p;
4556
4557 if (isempty(s))
4558 return false;
4559
4560 for (p = s; *p; p++)
4561 if (!hostname_valid_char(*p))
4562 return false;
4563
4564 if (p-s > HOST_NAME_MAX)
4565 return false;
4566
4567 return true;
4568}
4569
4570char* hostname_cleanup(char *s) {
4571 char *p, *d;
4572
4573 for (p = s, d = s; *p; p++)
4574 if ((*p >= 'a' && *p <= 'z') ||
4575 (*p >= 'A' && *p <= 'Z') ||
4576 (*p >= '0' && *p <= '9') ||
4577 *p == '-' ||
4578 *p == '_' ||
4579 *p == '.')
4580 *(d++) = *p;
4581
4582 *d = 0;
4583
4584 strshorten(s, HOST_NAME_MAX);
4585 return s;
4586}
4587
1325aa42
LP
4588int pipe_eof(int fd) {
4589 struct pollfd pollfd;
4590 int r;
4591
4592 zero(pollfd);
4593 pollfd.fd = fd;
4594 pollfd.events = POLLIN|POLLHUP;
4595
4596 r = poll(&pollfd, 1, 0);
4597 if (r < 0)
4598 return -errno;
4599
4600 if (r == 0)
4601 return 0;
4602
4603 return pollfd.revents & POLLHUP;
4604}
4605
8f2d43a0 4606int fd_wait_for_event(int fd, int event, usec_t t) {
df50185b
LP
4607 struct pollfd pollfd;
4608 int r;
4609
4610 zero(pollfd);
4611 pollfd.fd = fd;
4612 pollfd.events = event;
4613
8f2d43a0 4614 r = poll(&pollfd, 1, t == (usec_t) -1 ? -1 : (int) (t / USEC_PER_MSEC));
df50185b
LP
4615 if (r < 0)
4616 return -errno;
4617
4618 if (r == 0)
4619 return 0;
4620
4621 return pollfd.revents;
4622}
4623
5a3ab509
LP
4624int fopen_temporary(const char *path, FILE **_f, char **_temp_path) {
4625 FILE *f;
4626 char *t;
4627 const char *fn;
4628 size_t k;
4629 int fd;
4630
4631 assert(path);
4632 assert(_f);
4633 assert(_temp_path);
4634
4635 t = new(char, strlen(path) + 1 + 6 + 1);
4636 if (!t)
4637 return -ENOMEM;
4638
9eb977db 4639 fn = path_get_file_name(path);
5a3ab509
LP
4640 k = fn-path;
4641 memcpy(t, path, k);
4642 t[k] = '.';
4643 stpcpy(stpcpy(t+k+1, fn), "XXXXXX");
4644
4645 fd = mkostemp(t, O_WRONLY|O_CLOEXEC);
4646 if (fd < 0) {
4647 free(t);
4648 return -errno;
4649 }
4650
4651 f = fdopen(fd, "we");
4652 if (!f) {
4653 unlink(t);
4654 free(t);
4655 return -errno;
4656 }
4657
4658 *_f = f;
4659 *_temp_path = t;
4660
4661 return 0;
4662}
4663
6ea832a2 4664int terminal_vhangup_fd(int fd) {
5a3ab509
LP
4665 assert(fd >= 0);
4666
6ea832a2
LP
4667 if (ioctl(fd, TIOCVHANGUP) < 0)
4668 return -errno;
4669
4670 return 0;
4671}
4672
4673int terminal_vhangup(const char *name) {
4674 int fd, r;
4675
4676 fd = open_terminal(name, O_RDWR|O_NOCTTY|O_CLOEXEC);
4677 if (fd < 0)
4678 return fd;
4679
4680 r = terminal_vhangup_fd(fd);
4681 close_nointr_nofail(fd);
4682
4683 return r;
4684}
4685
4686int vt_disallocate(const char *name) {
4687 int fd, r;
4688 unsigned u;
6ea832a2
LP
4689
4690 /* Deallocate the VT if possible. If not possible
4691 * (i.e. because it is the active one), at least clear it
4692 * entirely (including the scrollback buffer) */
4693
b83bc4e9
LP
4694 if (!startswith(name, "/dev/"))
4695 return -EINVAL;
4696
4697 if (!tty_is_vc(name)) {
4698 /* So this is not a VT. I guess we cannot deallocate
4699 * it then. But let's at least clear the screen */
4700
4701 fd = open_terminal(name, O_RDWR|O_NOCTTY|O_CLOEXEC);
4702 if (fd < 0)
4703 return fd;
4704
8585357a
LP
4705 loop_write(fd,
4706 "\033[r" /* clear scrolling region */
4707 "\033[H" /* move home */
4708 "\033[2J", /* clear screen */
4709 10, false);
b83bc4e9
LP
4710 close_nointr_nofail(fd);
4711
4712 return 0;
4713 }
6ea832a2
LP
4714
4715 if (!startswith(name, "/dev/tty"))
4716 return -EINVAL;
4717
4718 r = safe_atou(name+8, &u);
4719 if (r < 0)
4720 return r;
4721
4722 if (u <= 0)
b83bc4e9 4723 return -EINVAL;
6ea832a2 4724
b83bc4e9 4725 /* Try to deallocate */
6ea832a2
LP
4726 fd = open_terminal("/dev/tty0", O_RDWR|O_NOCTTY|O_CLOEXEC);
4727 if (fd < 0)
4728 return fd;
4729
4730 r = ioctl(fd, VT_DISALLOCATE, u);
b83bc4e9 4731 close_nointr_nofail(fd);
6ea832a2 4732
b83bc4e9
LP
4733 if (r >= 0)
4734 return 0;
6ea832a2 4735
b83bc4e9 4736 if (errno != EBUSY)
6ea832a2 4737 return -errno;
6ea832a2 4738
b83bc4e9
LP
4739 /* Couldn't deallocate, so let's clear it fully with
4740 * scrollback */
4741 fd = open_terminal(name, O_RDWR|O_NOCTTY|O_CLOEXEC);
6ea832a2 4742 if (fd < 0)
b83bc4e9 4743 return fd;
6ea832a2 4744
8585357a
LP
4745 loop_write(fd,
4746 "\033[r" /* clear scrolling region */
4747 "\033[H" /* move home */
4748 "\033[3J", /* clear screen including scrollback, requires Linux 2.6.40 */
4749 10, false);
b83bc4e9 4750 close_nointr_nofail(fd);
6ea832a2 4751
b83bc4e9 4752 return 0;
6ea832a2
LP
4753}
4754
34ca941c
LP
4755int copy_file(const char *from, const char *to) {
4756 int r, fdf, fdt;
4757
4758 assert(from);
4759 assert(to);
4760
4761 fdf = open(from, O_RDONLY|O_CLOEXEC|O_NOCTTY);
4762 if (fdf < 0)
4763 return -errno;
4764
4765 fdt = open(to, O_WRONLY|O_CREAT|O_EXCL|O_CLOEXEC|O_NOCTTY, 0644);
4766 if (fdt < 0) {
4767 close_nointr_nofail(fdf);
4768 return -errno;
4769 }
4770
4771 for (;;) {
4772 char buf[PIPE_BUF];
4773 ssize_t n, k;
4774
4775 n = read(fdf, buf, sizeof(buf));
4776 if (n < 0) {
4777 r = -errno;
4778
4779 close_nointr_nofail(fdf);
4780 close_nointr(fdt);
4781 unlink(to);
4782
4783 return r;
4784 }
4785
4786 if (n == 0)
4787 break;
4788
4789 errno = 0;
4790 k = loop_write(fdt, buf, n, false);
4791 if (n != k) {
4792 r = k < 0 ? k : (errno ? -errno : -EIO);
4793
4794 close_nointr_nofail(fdf);
4795 close_nointr(fdt);
4796
4797 unlink(to);
4798 return r;
4799 }
4800 }
4801
4802 close_nointr_nofail(fdf);
4803 r = close_nointr(fdt);
4804
4805 if (r < 0) {
4806 unlink(to);
4807 return r;
4808 }
4809
4810 return 0;
4811}
4812
4813int symlink_or_copy(const char *from, const char *to) {
4814 char *pf = NULL, *pt = NULL;
4815 struct stat a, b;
4816 int r;
4817
4818 assert(from);
4819 assert(to);
4820
9eb977db
KS
4821 if (path_get_parent(from, &pf) < 0 ||
4822 path_get_parent(to, &pt) < 0) {
34ca941c
LP
4823 r = -ENOMEM;
4824 goto finish;
4825 }
4826
4827 if (stat(pf, &a) < 0 ||
4828 stat(pt, &b) < 0) {
4829 r = -errno;
4830 goto finish;
4831 }
4832
4833 if (a.st_dev != b.st_dev) {
4834 free(pf);
4835 free(pt);
4836
4837 return copy_file(from, to);
4838 }
4839
4840 if (symlink(from, to) < 0) {
4841 r = -errno;
4842 goto finish;
4843 }
4844
4845 r = 0;
4846
4847finish:
4848 free(pf);
4849 free(pt);
4850
4851 return r;
4852}
4853
4854int symlink_or_copy_atomic(const char *from, const char *to) {
4855 char *t, *x;
4856 const char *fn;
4857 size_t k;
4858 unsigned long long ull;
4859 unsigned i;
4860 int r;
4861
4862 assert(from);
4863 assert(to);
4864
4865 t = new(char, strlen(to) + 1 + 16 + 1);
4866 if (!t)
4867 return -ENOMEM;
4868
9eb977db 4869 fn = path_get_file_name(to);
34ca941c
LP
4870 k = fn-to;
4871 memcpy(t, to, k);
4872 t[k] = '.';
4873 x = stpcpy(t+k+1, fn);
4874
4875 ull = random_ull();
4876 for (i = 0; i < 16; i++) {
4877 *(x++) = hexchar(ull & 0xF);
4878 ull >>= 4;
4879 }
4880
4881 *x = 0;
4882
4883 r = symlink_or_copy(from, t);
4884 if (r < 0) {
4885 unlink(t);
4886 free(t);
4887 return r;
4888 }
4889
4890 if (rename(t, to) < 0) {
4891 r = -errno;
4892 unlink(t);
4893 free(t);
4894 return r;
4895 }
4896
4897 free(t);
4898 return r;
4899}
4900
4d6d6518
LP
4901bool display_is_local(const char *display) {
4902 assert(display);
4903
4904 return
4905 display[0] == ':' &&
4906 display[1] >= '0' &&
4907 display[1] <= '9';
4908}
4909
4910int socket_from_display(const char *display, char **path) {
4911 size_t k;
4912 char *f, *c;
4913
4914 assert(display);
4915 assert(path);
4916
4917 if (!display_is_local(display))
4918 return -EINVAL;
4919
4920 k = strspn(display+1, "0123456789");
4921
4922 f = new(char, sizeof("/tmp/.X11-unix/X") + k);
4923 if (!f)
4924 return -ENOMEM;
4925
4926 c = stpcpy(f, "/tmp/.X11-unix/X");
4927 memcpy(c, display+1, k);
4928 c[k] = 0;
4929
4930 *path = f;
4931
4932 return 0;
4933}
4934
d05c5031
LP
4935int get_user_creds(
4936 const char **username,
4937 uid_t *uid, gid_t *gid,
4938 const char **home,
4939 const char **shell) {
4940
1cccf435 4941 struct passwd *p;
ddd88763 4942 uid_t u;
1cccf435
MV
4943
4944 assert(username);
4945 assert(*username);
1cccf435
MV
4946
4947 /* We enforce some special rules for uid=0: in order to avoid
4948 * NSS lookups for root we hardcode its data. */
4949
4950 if (streq(*username, "root") || streq(*username, "0")) {
4951 *username = "root";
4b67834e
LP
4952
4953 if (uid)
4954 *uid = 0;
4955
4956 if (gid)
4957 *gid = 0;
4958
4959 if (home)
4960 *home = "/root";
d05c5031
LP
4961
4962 if (shell)
4963 *shell = "/bin/sh";
4964
1cccf435
MV
4965 return 0;
4966 }
4967
ddd88763 4968 if (parse_uid(*username, &u) >= 0) {
1cccf435 4969 errno = 0;
ddd88763 4970 p = getpwuid(u);
1cccf435
MV
4971
4972 /* If there are multiple users with the same id, make
4973 * sure to leave $USER to the configured value instead
4974 * of the first occurrence in the database. However if
4975 * the uid was configured by a numeric uid, then let's
4976 * pick the real username from /etc/passwd. */
4977 if (p)
4978 *username = p->pw_name;
4979 } else {
4980 errno = 0;
4981 p = getpwnam(*username);
4982 }
4983
4984 if (!p)
4985 return errno != 0 ? -errno : -ESRCH;
4986
4b67834e
LP
4987 if (uid)
4988 *uid = p->pw_uid;
4989
4990 if (gid)
4991 *gid = p->pw_gid;
4992
4993 if (home)
4994 *home = p->pw_dir;
4995
d05c5031
LP
4996 if (shell)
4997 *shell = p->pw_shell;
4998
4b67834e
LP
4999 return 0;
5000}
5001
5002int get_group_creds(const char **groupname, gid_t *gid) {
5003 struct group *g;
5004 gid_t id;
5005
5006 assert(groupname);
5007
5008 /* We enforce some special rules for gid=0: in order to avoid
5009 * NSS lookups for root we hardcode its data. */
5010
5011 if (streq(*groupname, "root") || streq(*groupname, "0")) {
5012 *groupname = "root";
5013
5014 if (gid)
5015 *gid = 0;
5016
5017 return 0;
5018 }
5019
5020 if (parse_gid(*groupname, &id) >= 0) {
5021 errno = 0;
5022 g = getgrgid(id);
5023
5024 if (g)
5025 *groupname = g->gr_name;
5026 } else {
5027 errno = 0;
5028 g = getgrnam(*groupname);
5029 }
5030
5031 if (!g)
5032 return errno != 0 ? -errno : -ESRCH;
5033
5034 if (gid)
5035 *gid = g->gr_gid;
5036
1cccf435
MV
5037 return 0;
5038}
5039
43673799
LP
5040int in_group(const char *name) {
5041 gid_t gid, *gids;
5042 int ngroups_max, r, i;
5043
5044 r = get_group_creds(&name, &gid);
5045 if (r < 0)
5046 return r;
5047
5048 if (getgid() == gid)
5049 return 1;
5050
5051 if (getegid() == gid)
5052 return 1;
5053
5054 ngroups_max = sysconf(_SC_NGROUPS_MAX);
5055 assert(ngroups_max > 0);
5056
5057 gids = alloca(sizeof(gid_t) * ngroups_max);
5058
5059 r = getgroups(ngroups_max, gids);
5060 if (r < 0)
5061 return -errno;
5062
5063 for (i = 0; i < r; i++)
5064 if (gids[i] == gid)
5065 return 1;
5066
5067 return 0;
5068}
5069
8092a428
LP
5070int glob_exists(const char *path) {
5071 glob_t g;
5072 int r, k;
5073
5074 assert(path);
5075
5076 zero(g);
5077 errno = 0;
5078 k = glob(path, GLOB_NOSORT|GLOB_BRACE, NULL, &g);
5079
5080 if (k == GLOB_NOMATCH)
5081 r = 0;
5082 else if (k == GLOB_NOSPACE)
5083 r = -ENOMEM;
5084 else if (k == 0)
5085 r = !strv_isempty(g.gl_pathv);
5086 else
5087 r = errno ? -errno : -EIO;
5088
5089 globfree(&g);
5090
5091 return r;
5092}
5093
83096483
LP
5094int dirent_ensure_type(DIR *d, struct dirent *de) {
5095 struct stat st;
5096
5097 assert(d);
5098 assert(de);
5099
5100 if (de->d_type != DT_UNKNOWN)
5101 return 0;
5102
5103 if (fstatat(dirfd(d), de->d_name, &st, AT_SYMLINK_NOFOLLOW) < 0)
5104 return -errno;
5105
5106 de->d_type =
5107 S_ISREG(st.st_mode) ? DT_REG :
5108 S_ISDIR(st.st_mode) ? DT_DIR :
5109 S_ISLNK(st.st_mode) ? DT_LNK :
5110 S_ISFIFO(st.st_mode) ? DT_FIFO :
5111 S_ISSOCK(st.st_mode) ? DT_SOCK :
5112 S_ISCHR(st.st_mode) ? DT_CHR :
5113 S_ISBLK(st.st_mode) ? DT_BLK :
5114 DT_UNKNOWN;
5115
5116 return 0;
5117}
5118
5119int in_search_path(const char *path, char **search) {
5120 char **i, *parent;
5121 int r;
5122
9eb977db 5123 r = path_get_parent(path, &parent);
83096483
LP
5124 if (r < 0)
5125 return r;
5126
5127 r = 0;
5128
5129 STRV_FOREACH(i, search) {
5130 if (path_equal(parent, *i)) {
5131 r = 1;
5132 break;
5133 }
5134 }
5135
5136 free(parent);
5137
5138 return r;
5139}
5140
034a2a52
LP
5141int get_files_in_directory(const char *path, char ***list) {
5142 DIR *d;
5143 int r = 0;
5144 unsigned n = 0;
5145 char **l = NULL;
5146
5147 assert(path);
d60ef526
LP
5148
5149 /* Returns all files in a directory in *list, and the number
5150 * of files as return value. If list is NULL returns only the
5151 * number */
034a2a52
LP
5152
5153 d = opendir(path);
8ea913b2
LP
5154 if (!d)
5155 return -errno;
5156
034a2a52
LP
5157 for (;;) {
5158 struct dirent buffer, *de;
5159 int k;
5160
5161 k = readdir_r(d, &buffer, &de);
5162 if (k != 0) {
5163 r = -k;
5164 goto finish;
5165 }
5166
5167 if (!de)
5168 break;
5169
5170 dirent_ensure_type(d, de);
5171
5172 if (!dirent_is_file(de))
5173 continue;
5174
d60ef526
LP
5175 if (list) {
5176 if ((unsigned) r >= n) {
5177 char **t;
034a2a52 5178
d60ef526
LP
5179 n = MAX(16, 2*r);
5180 t = realloc(l, sizeof(char*) * n);
5181 if (!t) {
5182 r = -ENOMEM;
5183 goto finish;
5184 }
034a2a52 5185
d60ef526
LP
5186 l = t;
5187 }
034a2a52 5188
d60ef526 5189 assert((unsigned) r < n);
034a2a52 5190
d60ef526
LP
5191 l[r] = strdup(de->d_name);
5192 if (!l[r]) {
5193 r = -ENOMEM;
5194 goto finish;
5195 }
034a2a52 5196
d60ef526
LP
5197 l[++r] = NULL;
5198 } else
5199 r++;
034a2a52
LP
5200 }
5201
5202finish:
5203 if (d)
5204 closedir(d);
5205
d60ef526
LP
5206 if (r >= 0) {
5207 if (list)
5208 *list = l;
5209 } else
034a2a52
LP
5210 strv_free(l);
5211
5212 return r;
5213}
5214
b7def684 5215char *strjoin(const char *x, ...) {
911a4828
LP
5216 va_list ap;
5217 size_t l;
5218 char *r, *p;
5219
5220 va_start(ap, x);
5221
5222 if (x) {
5223 l = strlen(x);
5224
5225 for (;;) {
5226 const char *t;
5227
5228 t = va_arg(ap, const char *);
5229 if (!t)
5230 break;
5231
5232 l += strlen(t);
5233 }
5234 } else
5235 l = 0;
5236
5237 va_end(ap);
5238
5239 r = new(char, l+1);
5240 if (!r)
5241 return NULL;
5242
5243 if (x) {
5244 p = stpcpy(r, x);
5245
5246 va_start(ap, x);
5247
5248 for (;;) {
5249 const char *t;
5250
5251 t = va_arg(ap, const char *);
5252 if (!t)
5253 break;
5254
5255 p = stpcpy(p, t);
5256 }
8ea913b2
LP
5257
5258 va_end(ap);
911a4828
LP
5259 } else
5260 r[0] = 0;
5261
5262 return r;
5263}
5264
b636465b
LP
5265bool is_main_thread(void) {
5266 static __thread int cached = 0;
5267
5268 if (_unlikely_(cached == 0))
5269 cached = getpid() == gettid() ? 1 : -1;
5270
5271 return cached > 0;
5272}
5273
94959f0f
LP
5274int block_get_whole_disk(dev_t d, dev_t *ret) {
5275 char *p, *s;
5276 int r;
5277 unsigned n, m;
5278
5279 assert(ret);
5280
5281 /* If it has a queue this is good enough for us */
5282 if (asprintf(&p, "/sys/dev/block/%u:%u/queue", major(d), minor(d)) < 0)
5283 return -ENOMEM;
5284
5285 r = access(p, F_OK);
5286 free(p);
5287
5288 if (r >= 0) {
5289 *ret = d;
5290 return 0;
5291 }
5292
5293 /* If it is a partition find the originating device */
5294 if (asprintf(&p, "/sys/dev/block/%u:%u/partition", major(d), minor(d)) < 0)
5295 return -ENOMEM;
5296
5297 r = access(p, F_OK);
5298 free(p);
5299
5300 if (r < 0)
5301 return -ENOENT;
5302
5303 /* Get parent dev_t */
5304 if (asprintf(&p, "/sys/dev/block/%u:%u/../dev", major(d), minor(d)) < 0)
5305 return -ENOMEM;
5306
5307 r = read_one_line_file(p, &s);
5308 free(p);
5309
5310 if (r < 0)
5311 return r;
5312
5313 r = sscanf(s, "%u:%u", &m, &n);
5314 free(s);
5315
5316 if (r != 2)
5317 return -EINVAL;
5318
5319 /* Only return this if it is really good enough for us. */
5320 if (asprintf(&p, "/sys/dev/block/%u:%u/queue", m, n) < 0)
5321 return -ENOMEM;
5322
5323 r = access(p, F_OK);
5324 free(p);
5325
5326 if (r >= 0) {
5327 *ret = makedev(m, n);
5328 return 0;
5329 }
5330
5331 return -ENOENT;
5332}
5333
8d53b453 5334int file_is_priv_sticky(const char *p) {
ad293f5a
LP
5335 struct stat st;
5336
5337 assert(p);
5338
5339 if (lstat(p, &st) < 0)
5340 return -errno;
5341
5342 return
8d53b453 5343 (st.st_uid == 0 || st.st_uid == getuid()) &&
ad293f5a
LP
5344 (st.st_mode & S_ISVTX);
5345}
94959f0f 5346
f41607a6
LP
5347static const char *const ioprio_class_table[] = {
5348 [IOPRIO_CLASS_NONE] = "none",
5349 [IOPRIO_CLASS_RT] = "realtime",
5350 [IOPRIO_CLASS_BE] = "best-effort",
5351 [IOPRIO_CLASS_IDLE] = "idle"
5352};
5353
5354DEFINE_STRING_TABLE_LOOKUP(ioprio_class, int);
5355
5356static const char *const sigchld_code_table[] = {
5357 [CLD_EXITED] = "exited",
5358 [CLD_KILLED] = "killed",
5359 [CLD_DUMPED] = "dumped",
5360 [CLD_TRAPPED] = "trapped",
5361 [CLD_STOPPED] = "stopped",
5362 [CLD_CONTINUED] = "continued",
5363};
5364
5365DEFINE_STRING_TABLE_LOOKUP(sigchld_code, int);
5366
5367static const char *const log_facility_unshifted_table[LOG_NFACILITIES] = {
5368 [LOG_FAC(LOG_KERN)] = "kern",
5369 [LOG_FAC(LOG_USER)] = "user",
5370 [LOG_FAC(LOG_MAIL)] = "mail",
5371 [LOG_FAC(LOG_DAEMON)] = "daemon",
5372 [LOG_FAC(LOG_AUTH)] = "auth",
5373 [LOG_FAC(LOG_SYSLOG)] = "syslog",
5374 [LOG_FAC(LOG_LPR)] = "lpr",
5375 [LOG_FAC(LOG_NEWS)] = "news",
5376 [LOG_FAC(LOG_UUCP)] = "uucp",
5377 [LOG_FAC(LOG_CRON)] = "cron",
5378 [LOG_FAC(LOG_AUTHPRIV)] = "authpriv",
5379 [LOG_FAC(LOG_FTP)] = "ftp",
5380 [LOG_FAC(LOG_LOCAL0)] = "local0",
5381 [LOG_FAC(LOG_LOCAL1)] = "local1",
5382 [LOG_FAC(LOG_LOCAL2)] = "local2",
5383 [LOG_FAC(LOG_LOCAL3)] = "local3",
5384 [LOG_FAC(LOG_LOCAL4)] = "local4",
5385 [LOG_FAC(LOG_LOCAL5)] = "local5",
5386 [LOG_FAC(LOG_LOCAL6)] = "local6",
5387 [LOG_FAC(LOG_LOCAL7)] = "local7"
5388};
5389
5390DEFINE_STRING_TABLE_LOOKUP(log_facility_unshifted, int);
5391
5392static const char *const log_level_table[] = {
5393 [LOG_EMERG] = "emerg",
5394 [LOG_ALERT] = "alert",
5395 [LOG_CRIT] = "crit",
5396 [LOG_ERR] = "err",
5397 [LOG_WARNING] = "warning",
5398 [LOG_NOTICE] = "notice",
5399 [LOG_INFO] = "info",
5400 [LOG_DEBUG] = "debug"
5401};
5402
5403DEFINE_STRING_TABLE_LOOKUP(log_level, int);
5404
5405static const char* const sched_policy_table[] = {
5406 [SCHED_OTHER] = "other",
5407 [SCHED_BATCH] = "batch",
5408 [SCHED_IDLE] = "idle",
5409 [SCHED_FIFO] = "fifo",
5410 [SCHED_RR] = "rr"
5411};
5412
5413DEFINE_STRING_TABLE_LOOKUP(sched_policy, int);
5414
5415static const char* const rlimit_table[] = {
5416 [RLIMIT_CPU] = "LimitCPU",
5417 [RLIMIT_FSIZE] = "LimitFSIZE",
5418 [RLIMIT_DATA] = "LimitDATA",
5419 [RLIMIT_STACK] = "LimitSTACK",
5420 [RLIMIT_CORE] = "LimitCORE",
5421 [RLIMIT_RSS] = "LimitRSS",
5422 [RLIMIT_NOFILE] = "LimitNOFILE",
5423 [RLIMIT_AS] = "LimitAS",
5424 [RLIMIT_NPROC] = "LimitNPROC",
5425 [RLIMIT_MEMLOCK] = "LimitMEMLOCK",
5426 [RLIMIT_LOCKS] = "LimitLOCKS",
5427 [RLIMIT_SIGPENDING] = "LimitSIGPENDING",
5428 [RLIMIT_MSGQUEUE] = "LimitMSGQUEUE",
5429 [RLIMIT_NICE] = "LimitNICE",
5430 [RLIMIT_RTPRIO] = "LimitRTPRIO",
5431 [RLIMIT_RTTIME] = "LimitRTTIME"
5432};
5433
5434DEFINE_STRING_TABLE_LOOKUP(rlimit, int);
5435
5436static const char* const ip_tos_table[] = {
5437 [IPTOS_LOWDELAY] = "low-delay",
5438 [IPTOS_THROUGHPUT] = "throughput",
5439 [IPTOS_RELIABILITY] = "reliability",
5440 [IPTOS_LOWCOST] = "low-cost",
5441};
5442
5443DEFINE_STRING_TABLE_LOOKUP(ip_tos, int);
5444
4e240ab0 5445static const char *const __signal_table[] = {
f41607a6
LP
5446 [SIGHUP] = "HUP",
5447 [SIGINT] = "INT",
5448 [SIGQUIT] = "QUIT",
5449 [SIGILL] = "ILL",
5450 [SIGTRAP] = "TRAP",
5451 [SIGABRT] = "ABRT",
5452 [SIGBUS] = "BUS",
5453 [SIGFPE] = "FPE",
5454 [SIGKILL] = "KILL",
5455 [SIGUSR1] = "USR1",
5456 [SIGSEGV] = "SEGV",
5457 [SIGUSR2] = "USR2",
5458 [SIGPIPE] = "PIPE",
5459 [SIGALRM] = "ALRM",
5460 [SIGTERM] = "TERM",
5461#ifdef SIGSTKFLT
5462 [SIGSTKFLT] = "STKFLT", /* Linux on SPARC doesn't know SIGSTKFLT */
5463#endif
5464 [SIGCHLD] = "CHLD",
5465 [SIGCONT] = "CONT",
5466 [SIGSTOP] = "STOP",
5467 [SIGTSTP] = "TSTP",
5468 [SIGTTIN] = "TTIN",
5469 [SIGTTOU] = "TTOU",
5470 [SIGURG] = "URG",
5471 [SIGXCPU] = "XCPU",
5472 [SIGXFSZ] = "XFSZ",
5473 [SIGVTALRM] = "VTALRM",
5474 [SIGPROF] = "PROF",
5475 [SIGWINCH] = "WINCH",
5476 [SIGIO] = "IO",
5477 [SIGPWR] = "PWR",
5478 [SIGSYS] = "SYS"
5479};
5480
4e240ab0
MS
5481DEFINE_PRIVATE_STRING_TABLE_LOOKUP(__signal, int);
5482
5483const char *signal_to_string(int signo) {
5484 static __thread char buf[12];
5485 const char *name;
5486
5487 name = __signal_to_string(signo);
5488 if (name)
5489 return name;
5490
5491 if (signo >= SIGRTMIN && signo <= SIGRTMAX)
5492 snprintf(buf, sizeof(buf) - 1, "RTMIN+%d", signo - SIGRTMIN);
5493 else
5494 snprintf(buf, sizeof(buf) - 1, "%d", signo);
5495 char_array_0(buf);
5496 return buf;
5497}
5498
5499int signal_from_string(const char *s) {
5500 int signo;
5501 int offset = 0;
5502 unsigned u;
5503
5504 signo =__signal_from_string(s);
5505 if (signo > 0)
5506 return signo;
5507
5508 if (startswith(s, "RTMIN+")) {
5509 s += 6;
5510 offset = SIGRTMIN;
5511 }
5512 if (safe_atou(s, &u) >= 0) {
5513 signo = (int) u + offset;
5514 if (signo > 0 && signo < _NSIG)
5515 return signo;
5516 }
5517 return -1;
5518}
65457142
FC
5519
5520bool kexec_loaded(void) {
5521 bool loaded = false;
5522 char *s;
5523
5524 if (read_one_line_file("/sys/kernel/kexec_loaded", &s) >= 0) {
5525 if (s[0] == '1')
5526 loaded = true;
5527 free(s);
5528 }
5529 return loaded;
5530}
fb9de93d
LP
5531
5532int strdup_or_null(const char *a, char **b) {
5533 char *c;
5534
5535 assert(b);
5536
5537 if (!a) {
5538 *b = NULL;
5539 return 0;
5540 }
5541
5542 c = strdup(a);
5543 if (!c)
5544 return -ENOMEM;
5545
5546 *b = c;
5547 return 0;
5548}
64685e0c 5549
87d2c1ff
LP
5550int prot_from_flags(int flags) {
5551
5552 switch (flags & O_ACCMODE) {
5553
5554 case O_RDONLY:
5555 return PROT_READ;
5556
5557 case O_WRONLY:
5558 return PROT_WRITE;
5559
5560 case O_RDWR:
5561 return PROT_READ|PROT_WRITE;
5562
5563 default:
5564 return -EINVAL;
5565 }
7c99e0c1 5566}
689b9a22 5567
babfc091 5568char *format_bytes(char *buf, size_t l, off_t t) {
c0f99c21 5569 unsigned i;
babfc091
LP
5570
5571 static const struct {
5572 const char *suffix;
5573 off_t factor;
5574 } table[] = {
32895bb3
LP
5575 { "E", 1024ULL*1024ULL*1024ULL*1024ULL*1024ULL*1024ULL },
5576 { "P", 1024ULL*1024ULL*1024ULL*1024ULL*1024ULL },
babfc091
LP
5577 { "T", 1024ULL*1024ULL*1024ULL*1024ULL },
5578 { "G", 1024ULL*1024ULL*1024ULL },
5579 { "M", 1024ULL*1024ULL },
5580 { "K", 1024ULL },
5581 };
5582
5583 for (i = 0; i < ELEMENTSOF(table); i++) {
5584
5585 if (t >= table[i].factor) {
5586 snprintf(buf, l,
5587 "%llu.%llu%s",
5588 (unsigned long long) (t / table[i].factor),
5589 (unsigned long long) (((t*10ULL) / table[i].factor) % 10ULL),
5590 table[i].suffix);
5591
5592 goto finish;
5593 }
5594 }
5595
5596 snprintf(buf, l, "%lluB", (unsigned long long) t);
5597
5598finish:
5599 buf[l-1] = 0;
5600 return buf;
5601
5602}
55d7bfc1
LP
5603
5604void* memdup(const void *p, size_t l) {
5605 void *r;
5606
5607 assert(p);
5608
5609 r = malloc(l);
5610 if (!r)
5611 return NULL;
5612
5613 memcpy(r, p, l);
5614 return r;
5615}
bb99a35a
LP
5616
5617int fd_inc_sndbuf(int fd, size_t n) {
5618 int r, value;
5619 socklen_t l = sizeof(value);
5620
5621 r = getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &value, &l);
5622 if (r >= 0 &&
5623 l == sizeof(value) &&
5624 (size_t) value >= n*2)
5625 return 0;
5626
5627 value = (int) n;
5628 r = setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &value, sizeof(value));
5629 if (r < 0)
5630 return -errno;
5631
5632 return 1;
5633}
5634
5635int fd_inc_rcvbuf(int fd, size_t n) {
5636 int r, value;
5637 socklen_t l = sizeof(value);
5638
5639 r = getsockopt(fd, SOL_SOCKET, SO_RCVBUF, &value, &l);
5640 if (r >= 0 &&
5641 l == sizeof(value) &&
5642 (size_t) value >= n*2)
5643 return 0;
5644
5645 value = (int) n;
5646 r = setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &value, sizeof(value));
5647 if (r < 0)
5648 return -errno;
5649
5650 return 1;
5651}
6bb92a16 5652
9bdc770c 5653int fork_agent(pid_t *pid, const int except[], unsigned n_except, const char *path, ...) {
6bb92a16
LP
5654 pid_t parent_pid, agent_pid;
5655 int fd;
5656 bool stdout_is_tty, stderr_is_tty;
5657 unsigned n, i;
5658 va_list ap;
5659 char **l;
5660
5661 assert(pid);
5662 assert(path);
5663
5664 parent_pid = getpid();
5665
5666 /* Spawns a temporary TTY agent, making sure it goes away when
5667 * we go away */
5668
5669 agent_pid = fork();
5670 if (agent_pid < 0)
5671 return -errno;
5672
5673 if (agent_pid != 0) {
5674 *pid = agent_pid;
5675 return 0;
5676 }
5677
5678 /* In the child:
5679 *
5680 * Make sure the agent goes away when the parent dies */
5681 if (prctl(PR_SET_PDEATHSIG, SIGTERM) < 0)
5682 _exit(EXIT_FAILURE);
5683
5684 /* Check whether our parent died before we were able
5685 * to set the death signal */
5686 if (getppid() != parent_pid)
5687 _exit(EXIT_SUCCESS);
5688
5689 /* Don't leak fds to the agent */
9bdc770c 5690 close_all_fds(except, n_except);
6bb92a16
LP
5691
5692 stdout_is_tty = isatty(STDOUT_FILENO);
5693 stderr_is_tty = isatty(STDERR_FILENO);
5694
5695 if (!stdout_is_tty || !stderr_is_tty) {
5696 /* Detach from stdout/stderr. and reopen
5697 * /dev/tty for them. This is important to
5698 * ensure that when systemctl is started via
5699 * popen() or a similar call that expects to
5700 * read EOF we actually do generate EOF and
5701 * not delay this indefinitely by because we
5702 * keep an unused copy of stdin around. */
5703 fd = open("/dev/tty", O_WRONLY);
5704 if (fd < 0) {
5705 log_error("Failed to open /dev/tty: %m");
5706 _exit(EXIT_FAILURE);
5707 }
5708
5709 if (!stdout_is_tty)
5710 dup2(fd, STDOUT_FILENO);
5711
5712 if (!stderr_is_tty)
5713 dup2(fd, STDERR_FILENO);
5714
5715 if (fd > 2)
5716 close(fd);
5717 }
5718
5719 /* Count arguments */
5720 va_start(ap, path);
5721 for (n = 0; va_arg(ap, char*); n++)
5722 ;
5723 va_end(ap);
5724
5725 /* Allocate strv */
5726 l = alloca(sizeof(char *) * (n + 1));
5727
5728 /* Fill in arguments */
5729 va_start(ap, path);
5730 for (i = 0; i <= n; i++)
5731 l[i] = va_arg(ap, char*);
5732 va_end(ap);
5733
5734 execv(path, l);
5735 _exit(EXIT_FAILURE);
5736}
68faf98c
LP
5737
5738int setrlimit_closest(int resource, const struct rlimit *rlim) {
5739 struct rlimit highest, fixed;
5740
5741 assert(rlim);
5742
5743 if (setrlimit(resource, rlim) >= 0)
5744 return 0;
5745
5746 if (errno != EPERM)
5747 return -errno;
5748
5749 /* So we failed to set the desired setrlimit, then let's try
5750 * to get as close as we can */
5751 assert_se(getrlimit(resource, &highest) == 0);
5752
5753 fixed.rlim_cur = MIN(rlim->rlim_cur, highest.rlim_max);
5754 fixed.rlim_max = MIN(rlim->rlim_max, highest.rlim_max);
5755
5756 if (setrlimit(resource, &fixed) < 0)
5757 return -errno;
5758
5759 return 0;
5760}
3d9a4122 5761
ab94af92
LP
5762int getenv_for_pid(pid_t pid, const char *field, char **_value) {
5763 char path[sizeof("/proc/")-1+10+sizeof("/environ")], *value = NULL;
5764 int r;
5765 FILE *f;
5766 bool done = false;
5767 size_t l;
5768
5769 assert(field);
5770 assert(_value);
5771
5772 if (pid == 0)
5773 pid = getpid();
5774
5775 snprintf(path, sizeof(path), "/proc/%lu/environ", (unsigned long) pid);
5776 char_array_0(path);
5777
5778 f = fopen(path, "re");
5779 if (!f)
5780 return -errno;
5781
5782 l = strlen(field);
5783 r = 0;
5784
5785 do {
5786 char line[LINE_MAX];
5787 unsigned i;
5788
5789 for (i = 0; i < sizeof(line)-1; i++) {
5790 int c;
5791
5792 c = getc(f);
5793 if (_unlikely_(c == EOF)) {
5794 done = true;
5795 break;
5796 } else if (c == 0)
5797 break;
5798
5799 line[i] = c;
5800 }
5801 line[i] = 0;
5802
5803 if (memcmp(line, field, l) == 0 && line[l] == '=') {
5804 value = strdup(line + l + 1);
5805 if (!value) {
5806 r = -ENOMEM;
5807 break;
5808 }
5809
5810 r = 1;
5811 break;
5812 }
5813
5814 } while (!done);
5815
5816 fclose(f);
5817
5818 if (r >= 0)
5819 *_value = value;
5820
5821 return r;
5822}
d889a206
LP
5823
5824int can_sleep(const char *type) {
5825 char *p, *w, *state;
5826 size_t l, k;
5827 bool found = false;
5828 int r;
5829
5830 assert(type);
5831
5832 r = read_one_line_file("/sys/power/state", &p);
5833 if (r < 0)
5834 return r == -ENOENT ? 0 : r;
5835
5836 k = strlen(type);
5837
5838 FOREACH_WORD_SEPARATOR(w, l, p, WHITESPACE, state) {
5839 if (l == k && strncmp(w, type, l) == 0) {
5840 found = true;
5841 break;
5842 }
5843 }
5844
5845 free(p);
5846 return found;
5847}
49dbfa7b
LP
5848
5849bool is_valid_documentation_url(const char *url) {
5850 assert(url);
5851
5852 if (startswith(url, "http://") && url[7])
5853 return true;
5854
5855 if (startswith(url, "https://") && url[8])
5856 return true;
5857
5858 if (startswith(url, "file:") && url[5])
5859 return true;
5860
5861 if (startswith(url, "info:") && url[5])
5862 return true;
5863
5864 if (startswith(url, "man:") && url[4])
5865 return true;
5866
5867 return false;
5868}
9be346c9
HH
5869
5870bool in_initrd(void) {
8f33b5b8 5871 static int saved = -1;
825c6fe5 5872 struct statfs s;
8f33b5b8 5873
825c6fe5
LP
5874 if (saved >= 0)
5875 return saved;
5876
5877 /* We make two checks here:
5878 *
5879 * 1. the flag file /etc/initrd-release must exist
5880 * 2. the root file system must be a memory file system
5881 *
5882 * The second check is extra paranoia, since misdetecting an
5883 * initrd can have bad bad consequences due the initrd
5884 * emptying when transititioning to the main systemd.
5885 */
5886
5887 saved = access("/etc/initrd-release", F_OK) >= 0 &&
5888 statfs("/", &s) >= 0 &&
5889 (s.f_type == TMPFS_MAGIC || s.f_type == RAMFS_MAGIC);
9be346c9 5890
8f33b5b8 5891 return saved;
9be346c9 5892}
069cfc85
LP
5893
5894void warn_melody(void) {
5895 int fd;
5896
5897 fd = open("/dev/console", O_WRONLY|O_CLOEXEC|O_NOCTTY);
5898 if (fd < 0)
5899 return;
5900
5901 /* Yeah, this is synchronous. Kinda sucks. Bute well... */
5902
5903 ioctl(fd, KIOCSOUND, (int)(1193180/440));
5904 usleep(125*USEC_PER_MSEC);
5905
5906 ioctl(fd, KIOCSOUND, (int)(1193180/220));
5907 usleep(125*USEC_PER_MSEC);
5908
5909 ioctl(fd, KIOCSOUND, (int)(1193180/220));
5910 usleep(125*USEC_PER_MSEC);
5911
5912 ioctl(fd, KIOCSOUND, 0);
5913 close_nointr_nofail(fd);
5914}
cd3bd60a
LP
5915
5916int make_console_stdio(void) {
5917 int fd, r;
5918
5919 /* Make /dev/console the controlling terminal and stdin/stdout/stderr */
5920
5921 fd = acquire_terminal("/dev/console", false, true, true, (usec_t) -1);
5922 if (fd < 0) {
5923 log_error("Failed to acquire terminal: %s", strerror(-fd));
5924 return fd;
5925 }
5926
5927 r = make_stdio(fd);
5928 if (r < 0) {
5929 log_error("Failed to duplicate terminal fd: %s", strerror(-r));
5930 return r;
5931 }
5932
5933 return 0;
5934}
7c5f152a
LP
5935
5936int get_home_dir(char **_h) {
5937 char *h;
5938 const char *e;
5939 uid_t u;
5940 struct passwd *p;
5941
5942 assert(_h);
5943
5944 /* Take the user specified one */
5945 e = getenv("HOME");
5946 if (e) {
5947 h = strdup(e);
5948 if (!h)
5949 return -ENOMEM;
5950
5951 *_h = h;
5952 return 0;
5953 }
5954
5955 /* Hardcode home directory for root to avoid NSS */
5956 u = getuid();
5957 if (u == 0) {
5958 h = strdup("/root");
5959 if (!h)
5960 return -ENOMEM;
5961
5962 *_h = h;
5963 return 0;
5964 }
5965
5966 /* Check the database... */
5967 errno = 0;
5968 p = getpwuid(u);
5969 if (!p)
5970 return errno ? -errno : -ENOENT;
5971
5972 if (!path_is_absolute(p->pw_dir))
5973 return -EINVAL;
5974
5975 h = strdup(p->pw_dir);
5976 if (!h)
5977 return -ENOMEM;
5978
5979 *_h = h;
5980 return 0;
5981}
5982
5983int get_shell(char **_sh) {
5984 char *sh;
5985 const char *e;
5986 uid_t u;
5987 struct passwd *p;
5988
5989 assert(_sh);
5990
5991 /* Take the user specified one */
5992 e = getenv("SHELL");
5993 if (e) {
5994 sh = strdup(e);
5995 if (!sh)
5996 return -ENOMEM;
5997
5998 *_sh = sh;
5999 return 0;
6000 }
6001
6002 /* Hardcode home directory for root to avoid NSS */
6003 u = getuid();
6004 if (u == 0) {
6005 sh = strdup("/bin/sh");
6006 if (!sh)
6007 return -ENOMEM;
6008
6009 *_sh = sh;
6010 return 0;
6011 }
6012
6013 /* Check the database... */
6014 errno = 0;
6015 p = getpwuid(u);
6016 if (!p)
6017 return errno ? -errno : -ESRCH;
6018
6019 if (!path_is_absolute(p->pw_shell))
6020 return -EINVAL;
6021
6022 sh = strdup(p->pw_shell);
6023 if (!sh)
6024 return -ENOMEM;
6025
6026 *_sh = sh;
6027 return 0;
6028}