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