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