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