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