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