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