]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/shared/util.c
implement a union to pad out file_handle
[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
a337c6fc 2019
9a34ec5f
LP
2020 if (sigaction(sig, &sa, NULL) < 0)
2021 r = -errno;
2022
2023 va_start(ap, sig);
2024 while ((sig = va_arg(ap, int)) > 0)
2025 if (sigaction(sig, &sa, NULL) < 0)
2026 r = -errno;
2027 va_end(ap);
2028
2029 return r;
2030}
2031
2032int default_signals(int sig, ...) {
b92bea5d
ZJS
2033 struct sigaction sa = {
2034 .sa_handler = SIG_DFL,
2035 .sa_flags = SA_RESTART,
2036 };
9a34ec5f
LP
2037 va_list ap;
2038 int r = 0;
2039
9a34ec5f
LP
2040 if (sigaction(sig, &sa, NULL) < 0)
2041 r = -errno;
2042
2043 va_start(ap, sig);
2044 while ((sig = va_arg(ap, int)) > 0)
2045 if (sigaction(sig, &sa, NULL) < 0)
2046 r = -errno;
2047 va_end(ap);
2048
2049 return r;
a337c6fc
LP
2050}
2051
3d94f76c 2052void safe_close_pair(int p[]) {
8d567588
LP
2053 assert(p);
2054
3d94f76c
LP
2055 if (p[0] == p[1]) {
2056 /* Special case pairs which use the same fd in both
2057 * directions... */
2058 p[0] = p[1] = safe_close(p[0]);
2059 return;
8d567588
LP
2060 }
2061
3d94f76c
LP
2062 p[0] = safe_close(p[0]);
2063 p[1] = safe_close(p[1]);
8d567588
LP
2064}
2065
eb22ac37 2066ssize_t loop_read(int fd, void *buf, size_t nbytes, bool do_poll) {
7d5dd5e0 2067 uint8_t *p = buf;
8d567588
LP
2068 ssize_t n = 0;
2069
2070 assert(fd >= 0);
2071 assert(buf);
2072
8d567588
LP
2073 while (nbytes > 0) {
2074 ssize_t k;
2075
7d5dd5e0
LP
2076 k = read(fd, p, nbytes);
2077 if (k < 0 && errno == EINTR)
2078 continue;
8d567588 2079
7d5dd5e0 2080 if (k < 0 && errno == EAGAIN && do_poll) {
8d567588 2081
7d5dd5e0
LP
2082 /* We knowingly ignore any return value here,
2083 * and expect that any error/EOF is reported
2084 * via read() */
8d567588 2085
7d5dd5e0
LP
2086 fd_wait_for_event(fd, POLLIN, (usec_t) -1);
2087 continue;
2088 }
8d567588 2089
7d5dd5e0 2090 if (k <= 0)
8d567588 2091 return n > 0 ? n : (k < 0 ? -errno : 0);
8d567588
LP
2092
2093 p += k;
2094 nbytes -= k;
2095 n += k;
2096 }
2097
2098 return n;
2099}
2100
eb22ac37 2101ssize_t loop_write(int fd, const void *buf, size_t nbytes, bool do_poll) {
7d5dd5e0 2102 const uint8_t *p = buf;
eb22ac37
LP
2103 ssize_t n = 0;
2104
2105 assert(fd >= 0);
2106 assert(buf);
2107
eb22ac37
LP
2108 while (nbytes > 0) {
2109 ssize_t k;
2110
fe652127 2111 k = write(fd, p, nbytes);
7d5dd5e0
LP
2112 if (k < 0 && errno == EINTR)
2113 continue;
eb22ac37 2114
7d5dd5e0 2115 if (k < 0 && errno == EAGAIN && do_poll) {
eb22ac37 2116
7d5dd5e0
LP
2117 /* We knowingly ignore any return value here,
2118 * and expect that any error/EOF is reported
2119 * via write() */
eb22ac37 2120
7d5dd5e0
LP
2121 fd_wait_for_event(fd, POLLOUT, (usec_t) -1);
2122 continue;
2123 }
eb22ac37 2124
7d5dd5e0 2125 if (k <= 0)
eb22ac37 2126 return n > 0 ? n : (k < 0 ? -errno : 0);
eb22ac37
LP
2127
2128 p += k;
2129 nbytes -= k;
2130 n += k;
2131 }
2132
2133 return n;
2134}
2135
5556b5fe
LP
2136int parse_size(const char *t, off_t base, off_t *size) {
2137
2138 /* Soo, sometimes we want to parse IEC binary suffxies, and
2139 * sometimes SI decimal suffixes. This function can parse
2140 * both. Which one is the right way depends on the
2141 * context. Wikipedia suggests that SI is customary for
2142 * hardrware metrics and network speeds, while IEC is
2143 * customary for most data sizes used by software and volatile
2144 * (RAM) memory. Hence be careful which one you pick!
2145 *
2146 * In either case we use just K, M, G as suffix, and not Ki,
2147 * Mi, Gi or so (as IEC would suggest). That's because that's
2148 * frickin' ugly. But this means you really need to make sure
2149 * to document which base you are parsing when you use this
2150 * call. */
2151
2152 struct table {
ab1f0633 2153 const char *suffix;
b32ff512 2154 unsigned long long factor;
5556b5fe
LP
2155 };
2156
2157 static const struct table iec[] = {
32895bb3 2158 { "E", 1024ULL*1024ULL*1024ULL*1024ULL*1024ULL*1024ULL },
840292be
ZJS
2159 { "P", 1024ULL*1024ULL*1024ULL*1024ULL*1024ULL },
2160 { "T", 1024ULL*1024ULL*1024ULL*1024ULL },
2161 { "G", 1024ULL*1024ULL*1024ULL },
2162 { "M", 1024ULL*1024ULL },
2163 { "K", 1024ULL },
2164 { "B", 1 },
ab1f0633
LP
2165 { "", 1 },
2166 };
2167
5556b5fe 2168 static const struct table si[] = {
5556b5fe 2169 { "E", 1000ULL*1000ULL*1000ULL*1000ULL*1000ULL*1000ULL },
840292be
ZJS
2170 { "P", 1000ULL*1000ULL*1000ULL*1000ULL*1000ULL },
2171 { "T", 1000ULL*1000ULL*1000ULL*1000ULL },
2172 { "G", 1000ULL*1000ULL*1000ULL },
2173 { "M", 1000ULL*1000ULL },
2174 { "K", 1000ULL },
2175 { "B", 1 },
5556b5fe
LP
2176 { "", 1 },
2177 };
2178
2179 const struct table *table;
ab1f0633 2180 const char *p;
b32ff512 2181 unsigned long long r = 0;
840292be 2182 unsigned n_entries, start_pos = 0;
ab1f0633
LP
2183
2184 assert(t);
5556b5fe
LP
2185 assert(base == 1000 || base == 1024);
2186 assert(size);
2187
2188 if (base == 1000) {
2189 table = si;
2190 n_entries = ELEMENTSOF(si);
2191 } else {
2192 table = iec;
2193 n_entries = ELEMENTSOF(iec);
2194 }
ab1f0633
LP
2195
2196 p = t;
2197 do {
2198 long long l;
9480794b
ZJS
2199 unsigned long long l2;
2200 double frac = 0;
ab1f0633
LP
2201 char *e;
2202 unsigned i;
2203
2204 errno = 0;
2205 l = strtoll(p, &e, 10);
2206
8333c77e 2207 if (errno > 0)
ab1f0633
LP
2208 return -errno;
2209
2210 if (l < 0)
2211 return -ERANGE;
2212
2213 if (e == p)
2214 return -EINVAL;
2215
9480794b
ZJS
2216 if (*e == '.') {
2217 e++;
2218 if (*e >= '0' && *e <= '9') {
2219 char *e2;
2220
2221 /* strotoull itself would accept space/+/- */
2222 l2 = strtoull(e, &e2, 10);
2223
2224 if (errno == ERANGE)
2225 return -errno;
2226
2227 /* Ignore failure. E.g. 10.M is valid */
2228 frac = l2;
2229 for (; e < e2; e++)
2230 frac /= 10;
2231 }
2232 }
2233
ab1f0633
LP
2234 e += strspn(e, WHITESPACE);
2235
840292be 2236 for (i = start_pos; i < n_entries; i++)
ab1f0633 2237 if (startswith(e, table[i].suffix)) {
b32ff512 2238 unsigned long long tmp;
9480794b 2239 if ((unsigned long long) l + (frac > 0) > ULLONG_MAX / table[i].factor)
b32ff512 2240 return -ERANGE;
9480794b 2241 tmp = l * table[i].factor + (unsigned long long) (frac * table[i].factor);
b32ff512
ZJS
2242 if (tmp > ULLONG_MAX - r)
2243 return -ERANGE;
2244
2245 r += tmp;
2246 if ((unsigned long long) (off_t) r != r)
2247 return -ERANGE;
2248
ab1f0633 2249 p = e + strlen(table[i].suffix);
840292be
ZJS
2250
2251 start_pos = i + 1;
ab1f0633
LP
2252 break;
2253 }
2254
5556b5fe 2255 if (i >= n_entries)
ab1f0633
LP
2256 return -EINVAL;
2257
b32ff512 2258 } while (*p);
ab1f0633 2259
5556b5fe 2260 *size = r;
ab1f0633
LP
2261
2262 return 0;
2263}
2264
843d2643
LP
2265int make_stdio(int fd) {
2266 int r, s, t;
2267
2268 assert(fd >= 0);
2269
73836c5c
LP
2270 r = dup3(fd, STDIN_FILENO, 0);
2271 s = dup3(fd, STDOUT_FILENO, 0);
2272 t = dup3(fd, STDERR_FILENO, 0);
843d2643
LP
2273
2274 if (fd >= 3)
03e334a1 2275 safe_close(fd);
843d2643
LP
2276
2277 if (r < 0 || s < 0 || t < 0)
2278 return -errno;
2279
73836c5c 2280 /* We rely here that the new fd has O_CLOEXEC not set */
7862f62d 2281
843d2643
LP
2282 return 0;
2283}
2284
ade509ce
LP
2285int make_null_stdio(void) {
2286 int null_fd;
2287
cd3bd60a
LP
2288 null_fd = open("/dev/null", O_RDWR|O_NOCTTY);
2289 if (null_fd < 0)
ade509ce
LP
2290 return -errno;
2291
2292 return make_stdio(null_fd);
2293}
2294
8407a5d0
LP
2295bool is_device_path(const char *path) {
2296
2297 /* Returns true on paths that refer to a device, either in
2298 * sysfs or in /dev */
2299
2300 return
2301 path_startswith(path, "/dev/") ||
2302 path_startswith(path, "/sys/");
2303}
2304
01f78473 2305int dir_is_empty(const char *path) {
a05f97b3 2306 _cleanup_closedir_ DIR *d;
01f78473 2307
a05f97b3
LP
2308 d = opendir(path);
2309 if (!d)
01f78473
LP
2310 return -errno;
2311
2312 for (;;) {
7d5e9c0f 2313 struct dirent *de;
01f78473 2314
3fd11280
FW
2315 errno = 0;
2316 de = readdir(d);
2317 if (!de && errno != 0)
2318 return -errno;
01f78473 2319
a05f97b3
LP
2320 if (!de)
2321 return 1;
01f78473 2322
a05f97b3
LP
2323 if (!ignore_file(de->d_name))
2324 return 0;
2325 }
01f78473
LP
2326}
2327
844ec79b
ZJS
2328char* dirname_malloc(const char *path) {
2329 char *d, *dir, *dir2;
2330
2331 d = strdup(path);
2332 if (!d)
2333 return NULL;
2334 dir = dirname(d);
2335 assert(dir);
2336
2337 if (dir != d) {
2338 dir2 = strdup(dir);
2339 free(d);
2340 return dir2;
2341 }
2342
2343 return dir;
2344}
2345
b89446bb 2346int dev_urandom(void *p, size_t n) {
a05f97b3 2347 _cleanup_close_ int fd;
9bf3b535 2348 ssize_t k;
d3782d60 2349
ac0930c8
LP
2350 fd = open("/dev/urandom", O_RDONLY|O_CLOEXEC|O_NOCTTY);
2351 if (fd < 0)
b89446bb 2352 return errno == ENOENT ? -ENOSYS : -errno;
d3782d60 2353
9bf3b535 2354 k = loop_read(fd, p, n, true);
b89446bb
LP
2355 if (k < 0)
2356 return (int) k;
2357 if ((size_t) k != n)
2358 return -EIO;
2359
2360 return 0;
2361}
2362
2363void random_bytes(void *p, size_t n) {
2364 static bool srand_called = false;
2365 uint8_t *q;
2366 int r;
d3782d60 2367
b89446bb
LP
2368 r = dev_urandom(p, n);
2369 if (r >= 0)
2370 return;
d3782d60 2371
b89446bb
LP
2372 /* If some idiot made /dev/urandom unavailable to us, he'll
2373 * get a PRNG instead. */
d3782d60 2374
9bf3b535 2375 if (!srand_called) {
b89446bb 2376 unsigned x = 0;
a3b6fafe 2377
9bf3b535
LP
2378#ifdef HAVE_SYS_AUXV_H
2379 /* The kernel provides us with a bit of entropy in
2380 * auxv, so let's try to make use of that to seed the
2381 * pseudo-random generator. It's better than
2382 * nothing... */
a3b6fafe 2383
9bf3b535
LP
2384 void *auxv;
2385
2386 auxv = (void*) getauxval(AT_RANDOM);
2387 if (auxv)
b89446bb 2388 x ^= *(unsigned*) auxv;
9bf3b535 2389#endif
a3b6fafe 2390
b89446bb
LP
2391 x ^= (unsigned) now(CLOCK_REALTIME);
2392 x ^= (unsigned) gettid();
2393
2394 srand(x);
9bf3b535
LP
2395 srand_called = true;
2396 }
a3b6fafe 2397
9bf3b535
LP
2398 for (q = p; q < (uint8_t*) p + n; q ++)
2399 *q = rand();
a3b6fafe
LP
2400}
2401
5b6319dc
LP
2402void rename_process(const char name[8]) {
2403 assert(name);
2404
5d6b1584
LP
2405 /* This is a like a poor man's setproctitle(). It changes the
2406 * comm field, argv[0], and also the glibc's internally used
2407 * name of the process. For the first one a limit of 16 chars
2408 * applies, to the second one usually one of 10 (i.e. length
2409 * of "/sbin/init"), to the third one one of 7 (i.e. length of
2410 * "systemd"). If you pass a longer string it will be
2411 * truncated */
5b6319dc 2412
5d6b1584 2413 prctl(PR_SET_NAME, name);
5b6319dc
LP
2414
2415 if (program_invocation_name)
2416 strncpy(program_invocation_name, name, strlen(program_invocation_name));
9a0e6896
LP
2417
2418 if (saved_argc > 0) {
2419 int i;
2420
2421 if (saved_argv[0])
2422 strncpy(saved_argv[0], name, strlen(saved_argv[0]));
2423
2424 for (i = 1; i < saved_argc; i++) {
2425 if (!saved_argv[i])
2426 break;
2427
29804cc1 2428 memzero(saved_argv[i], strlen(saved_argv[i]));
9a0e6896
LP
2429 }
2430 }
5b6319dc
LP
2431}
2432
7d793605
LP
2433void sigset_add_many(sigset_t *ss, ...) {
2434 va_list ap;
2435 int sig;
2436
2437 assert(ss);
2438
2439 va_start(ap, ss);
2440 while ((sig = va_arg(ap, int)) > 0)
2441 assert_se(sigaddset(ss, sig) == 0);
2442 va_end(ap);
2443}
2444
ef2f1067
LP
2445char* gethostname_malloc(void) {
2446 struct utsname u;
2447
2448 assert_se(uname(&u) >= 0);
2449
344de609 2450 if (!isempty(u.nodename) && !streq(u.nodename, "(none)"))
ef2f1067
LP
2451 return strdup(u.nodename);
2452
2453 return strdup(u.sysname);
2454}
2455
344de609
LP
2456bool hostname_is_set(void) {
2457 struct utsname u;
2458
2459 assert_se(uname(&u) >= 0);
2460
2461 return !isempty(u.nodename) && !streq(u.nodename, "(none)");
2462}
2463
7c5f152a 2464static char *lookup_uid(uid_t uid) {
ef2f1067 2465 long bufsize;
a05f97b3
LP
2466 char *name;
2467 _cleanup_free_ char *buf = NULL;
ef2f1067 2468 struct passwd pwbuf, *pw = NULL;
ef2f1067
LP
2469
2470 /* Shortcut things to avoid NSS lookups */
2471 if (uid == 0)
2472 return strdup("root");
2473
7c5f152a
LP
2474 bufsize = sysconf(_SC_GETPW_R_SIZE_MAX);
2475 if (bufsize <= 0)
ef2f1067
LP
2476 bufsize = 4096;
2477
7c5f152a
LP
2478 buf = malloc(bufsize);
2479 if (!buf)
ef2f1067
LP
2480 return NULL;
2481
a05f97b3
LP
2482 if (getpwuid_r(uid, &pwbuf, buf, bufsize, &pw) == 0 && pw)
2483 return strdup(pw->pw_name);
ef2f1067
LP
2484
2485 if (asprintf(&name, "%lu", (unsigned long) uid) < 0)
2486 return NULL;
2487
2488 return name;
2489}
2490
7c5f152a
LP
2491char* getlogname_malloc(void) {
2492 uid_t uid;
2493 struct stat st;
2494
2495 if (isatty(STDIN_FILENO) && fstat(STDIN_FILENO, &st) >= 0)
2496 uid = st.st_uid;
2497 else
2498 uid = getuid();
2499
2500 return lookup_uid(uid);
2501}
2502
2503char *getusername_malloc(void) {
2504 const char *e;
2505
2506 e = getenv("USER");
2507 if (e)
2508 return strdup(e);
2509
2510 return lookup_uid(getuid());
2511}
2512
fc116c6a
LP
2513int getttyname_malloc(int fd, char **r) {
2514 char path[PATH_MAX], *c;
618e02c7 2515 int k;
8c6db833
LP
2516
2517 assert(r);
ef2f1067 2518
a05f97b3 2519 k = ttyname_r(fd, path, sizeof(path));
27373e44 2520 if (k > 0)
618e02c7 2521 return -k;
ef2f1067
LP
2522
2523 char_array_0(path);
2524
a05f97b3
LP
2525 c = strdup(startswith(path, "/dev/") ? path + 5 : path);
2526 if (!c)
8c6db833
LP
2527 return -ENOMEM;
2528
2529 *r = c;
2530 return 0;
2531}
2532
fc116c6a
LP
2533int getttyname_harder(int fd, char **r) {
2534 int k;
2535 char *s;
2536
a05f97b3
LP
2537 k = getttyname_malloc(fd, &s);
2538 if (k < 0)
fc116c6a
LP
2539 return k;
2540
2541 if (streq(s, "tty")) {
2542 free(s);
4d6d6518 2543 return get_ctty(0, NULL, r);
fc116c6a
LP
2544 }
2545
2546 *r = s;
2547 return 0;
2548}
2549
4d6d6518 2550int get_ctty_devnr(pid_t pid, dev_t *d) {
b4696bce
SP
2551 int r;
2552 _cleanup_free_ char *line = NULL;
2553 const char *p;
fc116c6a 2554 unsigned long ttynr;
fc116c6a 2555
49aa47c7 2556 assert(pid >= 0);
49aa47c7 2557
b4696bce
SP
2558 p = procfs_file_alloca(pid, "stat");
2559 r = read_one_line_file(p, &line);
2560 if (r < 0)
2561 return r;
fc116c6a 2562
4d6d6518
LP
2563 p = strrchr(line, ')');
2564 if (!p)
fc116c6a
LP
2565 return -EIO;
2566
2567 p++;
2568
2569 if (sscanf(p, " "
2570 "%*c " /* state */
2571 "%*d " /* ppid */
2572 "%*d " /* pgrp */
2573 "%*d " /* session */
2574 "%lu ", /* ttynr */
2575 &ttynr) != 1)
2576 return -EIO;
2577
11dc5d2b
LP
2578 if (major(ttynr) == 0 && minor(ttynr) == 0)
2579 return -ENOENT;
2580
0bee65f0
LP
2581 if (d)
2582 *d = (dev_t) ttynr;
2583
fc116c6a
LP
2584 return 0;
2585}
2586
4d6d6518 2587int get_ctty(pid_t pid, dev_t *_devnr, char **r) {
833fce28
LP
2588 char fn[sizeof("/dev/char/")-1 + 2*DECIMAL_STR_MAX(unsigned) + 1 + 1], *b = NULL;
2589 _cleanup_free_ char *s = NULL;
2590 const char *p;
fc116c6a 2591 dev_t devnr;
833fce28 2592 int k;
fc116c6a
LP
2593
2594 assert(r);
2595
4d6d6518
LP
2596 k = get_ctty_devnr(pid, &devnr);
2597 if (k < 0)
fc116c6a
LP
2598 return k;
2599
2600 snprintf(fn, sizeof(fn), "/dev/char/%u:%u", major(devnr), minor(devnr));
fc116c6a 2601
23406ce5
LP
2602 k = readlink_malloc(fn, &s);
2603 if (k < 0) {
fc116c6a
LP
2604
2605 if (k != -ENOENT)
2606 return k;
2607
46824d0e
LP
2608 /* This is an ugly hack */
2609 if (major(devnr) == 136) {
833fce28
LP
2610 asprintf(&b, "pts/%lu", (unsigned long) minor(devnr));
2611 goto finish;
46824d0e
LP
2612 }
2613
fc116c6a
LP
2614 /* Probably something like the ptys which have no
2615 * symlink in /dev/char. Let's return something
2616 * vaguely useful. */
2617
23406ce5 2618 b = strdup(fn + 5);
833fce28 2619 goto finish;
fc116c6a
LP
2620 }
2621
2622 if (startswith(s, "/dev/"))
2623 p = s + 5;
2624 else if (startswith(s, "../"))
2625 p = s + 3;
2626 else
2627 p = s;
2628
2629 b = strdup(p);
fc116c6a 2630
833fce28 2631finish:
fc116c6a
LP
2632 if (!b)
2633 return -ENOMEM;
2634
2635 *r = b;
46824d0e
LP
2636 if (_devnr)
2637 *_devnr = devnr;
2638
fc116c6a
LP
2639 return 0;
2640}
2641
f56d5db9 2642int rm_rf_children_dangerous(int fd, bool only_dirs, bool honour_sticky, struct stat *root_dev) {
8c6db833
LP
2643 DIR *d;
2644 int ret = 0;
2645
2646 assert(fd >= 0);
2647
2648 /* This returns the first error we run into, but nevertheless
7925c22a 2649 * tries to go on. This closes the passed fd. */
8c6db833 2650
d4d046e3
LP
2651 d = fdopendir(fd);
2652 if (!d) {
03e334a1 2653 safe_close(fd);
4c633005
LP
2654
2655 return errno == ENOENT ? 0 : -errno;
8c6db833
LP
2656 }
2657
2658 for (;;) {
7d5e9c0f 2659 struct dirent *de;
7925c22a
LP
2660 bool is_dir, keep_around;
2661 struct stat st;
8c6db833
LP
2662 int r;
2663
3fd11280
FW
2664 errno = 0;
2665 de = readdir(d);
2666 if (!de && errno != 0) {
2667 if (ret == 0)
2668 ret = -errno;
8c6db833
LP
2669 break;
2670 }
2671
2672 if (!de)
2673 break;
2674
2675 if (streq(de->d_name, ".") || streq(de->d_name, ".."))
2676 continue;
2677
7925c22a
LP
2678 if (de->d_type == DT_UNKNOWN ||
2679 honour_sticky ||
2680 (de->d_type == DT_DIR && root_dev)) {
8c6db833 2681 if (fstatat(fd, de->d_name, &st, AT_SYMLINK_NOFOLLOW) < 0) {
4c633005 2682 if (ret == 0 && errno != ENOENT)
8c6db833
LP
2683 ret = -errno;
2684 continue;
2685 }
2686
2687 is_dir = S_ISDIR(st.st_mode);
7925c22a
LP
2688 keep_around =
2689 honour_sticky &&
2690 (st.st_uid == 0 || st.st_uid == getuid()) &&
2691 (st.st_mode & S_ISVTX);
ad293f5a 2692 } else {
8c6db833 2693 is_dir = de->d_type == DT_DIR;
7925c22a 2694 keep_around = false;
ad293f5a 2695 }
8c6db833
LP
2696
2697 if (is_dir) {
2698 int subdir_fd;
8c6db833 2699
597f43c7 2700 /* if root_dev is set, remove subdirectories only, if device is same as dir */
7925c22a
LP
2701 if (root_dev && st.st_dev != root_dev->st_dev)
2702 continue;
8c6db833 2703
7925c22a
LP
2704 subdir_fd = openat(fd, de->d_name,
2705 O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW|O_NOATIME);
2706 if (subdir_fd < 0) {
2707 if (ret == 0 && errno != ENOENT)
2708 ret = -errno;
2709 continue;
2710 }
2711
b3d28469 2712 r = rm_rf_children_dangerous(subdir_fd, only_dirs, honour_sticky, root_dev);
7925c22a
LP
2713 if (r < 0 && ret == 0)
2714 ret = r;
2715
2716 if (!keep_around)
2717 if (unlinkat(fd, de->d_name, AT_REMOVEDIR) < 0) {
ad293f5a
LP
2718 if (ret == 0 && errno != ENOENT)
2719 ret = -errno;
2720 }
2721
2722 } else if (!only_dirs && !keep_around) {
8c6db833
LP
2723
2724 if (unlinkat(fd, de->d_name, 0) < 0) {
4c633005 2725 if (ret == 0 && errno != ENOENT)
8c6db833
LP
2726 ret = -errno;
2727 }
2728 }
2729 }
2730
2731 closedir(d);
2732
2733 return ret;
2734}
2735
44a6b1b6 2736_pure_ static int is_temporary_fs(struct statfs *s) {
943aad8c 2737 assert(s);
73020ab2
SL
2738
2739 return F_TYPE_EQUAL(s->f_type, TMPFS_MAGIC) ||
2740 F_TYPE_EQUAL(s->f_type, RAMFS_MAGIC);
943aad8c
ZJS
2741}
2742
f56d5db9
LP
2743int rm_rf_children(int fd, bool only_dirs, bool honour_sticky, struct stat *root_dev) {
2744 struct statfs s;
2745
2746 assert(fd >= 0);
2747
2748 if (fstatfs(fd, &s) < 0) {
03e334a1 2749 safe_close(fd);
f56d5db9
LP
2750 return -errno;
2751 }
2752
2753 /* We refuse to clean disk file systems with this call. This
2754 * is extra paranoia just to be sure we never ever remove
2755 * non-state data */
943aad8c 2756 if (!is_temporary_fs(&s)) {
f56d5db9 2757 log_error("Attempted to remove disk file system, and we can't allow that.");
03e334a1 2758 safe_close(fd);
f56d5db9
LP
2759 return -EPERM;
2760 }
2761
2762 return rm_rf_children_dangerous(fd, only_dirs, honour_sticky, root_dev);
2763}
2764
2765static int rm_rf_internal(const char *path, bool only_dirs, bool delete_root, bool honour_sticky, bool dangerous) {
2766 int fd, r;
2767 struct statfs s;
8c6db833
LP
2768
2769 assert(path);
2770
f56d5db9
LP
2771 /* We refuse to clean the root file system with this
2772 * call. This is extra paranoia to never cause a really
2773 * seriously broken system. */
2774 if (path_equal(path, "/")) {
2775 log_error("Attempted to remove entire root file system, and we can't allow that.");
2776 return -EPERM;
2777 }
461b1822 2778
d4d046e3
LP
2779 fd = open(path, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW|O_NOATIME);
2780 if (fd < 0) {
8c6db833
LP
2781
2782 if (errno != ENOTDIR)
2783 return -errno;
2784
f56d5db9
LP
2785 if (!dangerous) {
2786 if (statfs(path, &s) < 0)
2787 return -errno;
2788
943aad8c 2789 if (!is_temporary_fs(&s)) {
f56d5db9
LP
2790 log_error("Attempted to remove disk file system, and we can't allow that.");
2791 return -EPERM;
2792 }
2793 }
2794
8c6db833 2795 if (delete_root && !only_dirs)
d4d046e3 2796 if (unlink(path) < 0 && errno != ENOENT)
8c6db833
LP
2797 return -errno;
2798
2799 return 0;
2800 }
2801
f56d5db9
LP
2802 if (!dangerous) {
2803 if (fstatfs(fd, &s) < 0) {
03e334a1 2804 safe_close(fd);
f56d5db9
LP
2805 return -errno;
2806 }
ad293f5a 2807
943aad8c 2808 if (!is_temporary_fs(&s)) {
f56d5db9 2809 log_error("Attempted to remove disk file system, and we can't allow that.");
03e334a1 2810 safe_close(fd);
f56d5db9
LP
2811 return -EPERM;
2812 }
2813 }
2814
2815 r = rm_rf_children_dangerous(fd, only_dirs, honour_sticky, NULL);
ad293f5a
LP
2816 if (delete_root) {
2817
8d53b453 2818 if (honour_sticky && file_is_priv_sticky(path) > 0)
ad293f5a 2819 return r;
8c6db833 2820
e27796a0 2821 if (rmdir(path) < 0 && errno != ENOENT) {
8c6db833
LP
2822 if (r == 0)
2823 r = -errno;
2824 }
ad293f5a 2825 }
8c6db833
LP
2826
2827 return r;
2828}
2829
f56d5db9
LP
2830int rm_rf(const char *path, bool only_dirs, bool delete_root, bool honour_sticky) {
2831 return rm_rf_internal(path, only_dirs, delete_root, honour_sticky, false);
2832}
2833
2834int rm_rf_dangerous(const char *path, bool only_dirs, bool delete_root, bool honour_sticky) {
2835 return rm_rf_internal(path, only_dirs, delete_root, honour_sticky, true);
2836}
2837
8c6db833
LP
2838int chmod_and_chown(const char *path, mode_t mode, uid_t uid, gid_t gid) {
2839 assert(path);
2840
2841 /* Under the assumption that we are running privileged we
2842 * first change the access mode and only then hand out
2843 * ownership to avoid a window where access is too open. */
2844
8d53b453
LP
2845 if (mode != (mode_t) -1)
2846 if (chmod(path, mode) < 0)
2847 return -errno;
8c6db833 2848
8d53b453
LP
2849 if (uid != (uid_t) -1 || gid != (gid_t) -1)
2850 if (chown(path, uid, gid) < 0)
2851 return -errno;
8c6db833
LP
2852
2853 return 0;
ef2f1067
LP
2854}
2855
f4b47811
LP
2856int fchmod_and_fchown(int fd, mode_t mode, uid_t uid, gid_t gid) {
2857 assert(fd >= 0);
2858
2859 /* Under the assumption that we are running privileged we
2860 * first change the access mode and only then hand out
2861 * ownership to avoid a window where access is too open. */
2862
9588bc32
LP
2863 if (mode != (mode_t) -1)
2864 if (fchmod(fd, mode) < 0)
2865 return -errno;
f4b47811 2866
9588bc32
LP
2867 if (uid != (uid_t) -1 || gid != (gid_t) -1)
2868 if (fchown(fd, uid, gid) < 0)
2869 return -errno;
f4b47811
LP
2870
2871 return 0;
2872}
2873
82c121a4
LP
2874cpu_set_t* cpu_set_malloc(unsigned *ncpus) {
2875 cpu_set_t *r;
2876 unsigned n = 1024;
2877
2878 /* Allocates the cpuset in the right size */
2879
2880 for (;;) {
2881 if (!(r = CPU_ALLOC(n)))
2882 return NULL;
2883
2884 if (sched_getaffinity(0, CPU_ALLOC_SIZE(n), r) >= 0) {
2885 CPU_ZERO_S(CPU_ALLOC_SIZE(n), r);
2886
2887 if (ncpus)
2888 *ncpus = n;
2889
2890 return r;
2891 }
2892
2893 CPU_FREE(r);
2894
2895 if (errno != EINVAL)
2896 return NULL;
2897
2898 n *= 2;
2899 }
2900}
2901
984a2be4 2902int status_vprintf(const char *status, bool ellipse, bool ephemeral, const char *format, va_list ap) {
9ab7a8d2 2903 static const char status_indent[] = " "; /* "[" STATUS "] " */
669bec5d
LP
2904 _cleanup_free_ char *s = NULL;
2905 _cleanup_close_ int fd = -1;
b92bea5d 2906 struct iovec iovec[6] = {};
81beb750 2907 int n = 0;
984a2be4 2908 static bool prev_ephemeral;
9e58ff9c
LP
2909
2910 assert(format);
2911
9ab7a8d2 2912 /* This is independent of logging, as status messages are
9e58ff9c
LP
2913 * optional and go exclusively to the console. */
2914
2915 if (vasprintf(&s, format, ap) < 0)
669bec5d 2916 return log_oom();
9e58ff9c 2917
67e5cc4f 2918 fd = open_terminal("/dev/console", O_WRONLY|O_NOCTTY|O_CLOEXEC);
81beb750 2919 if (fd < 0)
669bec5d 2920 return fd;
9e58ff9c 2921
67e5cc4f 2922 if (ellipse) {
9ab7a8d2
MS
2923 char *e;
2924 size_t emax, sl;
2925 int c;
2926
67e5cc4f
LP
2927 c = fd_columns(fd);
2928 if (c <= 0)
2929 c = 80;
81beb750 2930
669bec5d 2931 sl = status ? sizeof(status_indent)-1 : 0;
9ab7a8d2
MS
2932
2933 emax = c - sl - 1;
2934 if (emax < 3)
2935 emax = 3;
81beb750 2936
67e5cc4f
LP
2937 e = ellipsize(s, emax, 75);
2938 if (e) {
2939 free(s);
2940 s = e;
2941 }
81beb750
LP
2942 }
2943
984a2be4
MS
2944 if (prev_ephemeral)
2945 IOVEC_SET_STRING(iovec[n++], "\r" ANSI_ERASE_TO_END_OF_LINE);
2946 prev_ephemeral = ephemeral;
2947
9ab7a8d2
MS
2948 if (status) {
2949 if (!isempty(status)) {
2950 IOVEC_SET_STRING(iovec[n++], "[");
2951 IOVEC_SET_STRING(iovec[n++], status);
2952 IOVEC_SET_STRING(iovec[n++], "] ");
2953 } else
2954 IOVEC_SET_STRING(iovec[n++], status_indent);
81beb750
LP
2955 }
2956
9ab7a8d2 2957 IOVEC_SET_STRING(iovec[n++], s);
984a2be4
MS
2958 if (!ephemeral)
2959 IOVEC_SET_STRING(iovec[n++], "\n");
81beb750 2960
669bec5d
LP
2961 if (writev(fd, iovec, n) < 0)
2962 return -errno;
9e58ff9c 2963
669bec5d 2964 return 0;
9e58ff9c
LP
2965}
2966
984a2be4 2967int status_printf(const char *status, bool ellipse, bool ephemeral, const char *format, ...) {
c846ff47 2968 va_list ap;
669bec5d 2969 int r;
c846ff47
LP
2970
2971 assert(format);
2972
2973 va_start(ap, format);
984a2be4 2974 r = status_vprintf(status, ellipse, ephemeral, format, ap);
c846ff47 2975 va_end(ap);
669bec5d
LP
2976
2977 return r;
c846ff47
LP
2978}
2979
fab56fc5
LP
2980char *replace_env(const char *format, char **env) {
2981 enum {
2982 WORD,
c24eb49e 2983 CURLY,
fab56fc5
LP
2984 VARIABLE
2985 } state = WORD;
2986
2987 const char *e, *word = format;
2988 char *r = NULL, *k;
2989
2990 assert(format);
2991
2992 for (e = format; *e; e ++) {
2993
2994 switch (state) {
2995
2996 case WORD:
2997 if (*e == '$')
c24eb49e 2998 state = CURLY;
fab56fc5
LP
2999 break;
3000
c24eb49e
LP
3001 case CURLY:
3002 if (*e == '{') {
fab56fc5
LP
3003 if (!(k = strnappend(r, word, e-word-1)))
3004 goto fail;
3005
3006 free(r);
3007 r = k;
3008
3009 word = e-1;
3010 state = VARIABLE;
3011
3012 } else if (*e == '$') {
3013 if (!(k = strnappend(r, word, e-word)))
3014 goto fail;
3015
3016 free(r);
3017 r = k;
3018
3019 word = e+1;
3020 state = WORD;
3021 } else
3022 state = WORD;
3023 break;
3024
3025 case VARIABLE:
c24eb49e 3026 if (*e == '}') {
b95cf362 3027 const char *t;
fab56fc5 3028
4d1a6904 3029 t = strempty(strv_env_get_n(env, word+2, e-word-2));
fab56fc5 3030
4d1a6904
LP
3031 k = strappend(r, t);
3032 if (!k)
b95cf362 3033 goto fail;
fab56fc5 3034
b95cf362
LP
3035 free(r);
3036 r = k;
fab56fc5 3037
b95cf362 3038 word = e+1;
fab56fc5
LP
3039 state = WORD;
3040 }
3041 break;
3042 }
3043 }
3044
3045 if (!(k = strnappend(r, word, e-word)))
3046 goto fail;
3047
3048 free(r);
3049 return k;
3050
3051fail:
3052 free(r);
3053 return NULL;
3054}
3055
3056char **replace_env_argv(char **argv, char **env) {
3057 char **r, **i;
c24eb49e
LP
3058 unsigned k = 0, l = 0;
3059
3060 l = strv_length(argv);
fab56fc5 3061
c24eb49e 3062 if (!(r = new(char*, l+1)))
fab56fc5
LP
3063 return NULL;
3064
3065 STRV_FOREACH(i, argv) {
c24eb49e
LP
3066
3067 /* If $FOO appears as single word, replace it by the split up variable */
b95cf362
LP
3068 if ((*i)[0] == '$' && (*i)[1] != '{') {
3069 char *e;
3070 char **w, **m;
3071 unsigned q;
c24eb49e 3072
4d1a6904
LP
3073 e = strv_env_get(env, *i+1);
3074 if (e) {
c24eb49e
LP
3075
3076 if (!(m = strv_split_quoted(e))) {
3077 r[k] = NULL;
3078 strv_free(r);
3079 return NULL;
3080 }
b95cf362
LP
3081 } else
3082 m = NULL;
c24eb49e 3083
b95cf362
LP
3084 q = strv_length(m);
3085 l = l + q - 1;
c24eb49e 3086
b95cf362
LP
3087 if (!(w = realloc(r, sizeof(char*) * (l+1)))) {
3088 r[k] = NULL;
3089 strv_free(r);
3090 strv_free(m);
3091 return NULL;
3092 }
c24eb49e 3093
b95cf362
LP
3094 r = w;
3095 if (m) {
c24eb49e
LP
3096 memcpy(r + k, m, q * sizeof(char*));
3097 free(m);
c24eb49e 3098 }
b95cf362
LP
3099
3100 k += q;
3101 continue;
c24eb49e
LP
3102 }
3103
3104 /* If ${FOO} appears as part of a word, replace it by the variable as-is */
fab56fc5
LP
3105 if (!(r[k++] = replace_env(*i, env))) {
3106 strv_free(r);
3107 return NULL;
3108 }
3109 }
3110
3111 r[k] = NULL;
3112 return r;
3113}
3114
81beb750 3115int fd_columns(int fd) {
b92bea5d 3116 struct winsize ws = {};
81beb750
LP
3117
3118 if (ioctl(fd, TIOCGWINSZ, &ws) < 0)
3119 return -errno;
3120
3121 if (ws.ws_col <= 0)
3122 return -EIO;
3123
3124 return ws.ws_col;
3125}
3126
28917d7d 3127unsigned columns(void) {
fa776d8e 3128 const char *e;
7009eec2 3129 int c;
fa776d8e 3130
28917d7d
LP
3131 if (_likely_(cached_columns > 0))
3132 return cached_columns;
11f96fac 3133
28917d7d
LP
3134 c = 0;
3135 e = getenv("COLUMNS");
3136 if (e)
7009eec2 3137 safe_atoi(e, &c);
fa776d8e 3138
28917d7d
LP
3139 if (c <= 0)
3140 c = fd_columns(STDOUT_FILENO);
fa776d8e 3141
28917d7d
LP
3142 if (c <= 0)
3143 c = 80;
11f96fac 3144
28917d7d
LP
3145 cached_columns = c;
3146 return c;
11f96fac
ZJS
3147}
3148
8f2d43a0 3149int fd_lines(int fd) {
b92bea5d 3150 struct winsize ws = {};
8f2d43a0
LP
3151
3152 if (ioctl(fd, TIOCGWINSZ, &ws) < 0)
3153 return -errno;
3154
3155 if (ws.ws_row <= 0)
3156 return -EIO;
3157
3158 return ws.ws_row;
3159}
3160
3161unsigned lines(void) {
8f2d43a0 3162 const char *e;
ed757c0c 3163 unsigned l;
8f2d43a0 3164
ed757c0c
LP
3165 if (_likely_(cached_lines > 0))
3166 return cached_lines;
8f2d43a0 3167
ed757c0c 3168 l = 0;
8f2d43a0
LP
3169 e = getenv("LINES");
3170 if (e)
ed757c0c 3171 safe_atou(e, &l);
8f2d43a0 3172
ed757c0c
LP
3173 if (l <= 0)
3174 l = fd_lines(STDOUT_FILENO);
8f2d43a0 3175
ed757c0c
LP
3176 if (l <= 0)
3177 l = 24;
8f2d43a0 3178
ed757c0c
LP
3179 cached_lines = l;
3180 return cached_lines;
3181}
3182
3183/* intended to be used as a SIGWINCH sighandler */
3184void columns_lines_cache_reset(int signum) {
3185 cached_columns = 0;
3186 cached_lines = 0;
3187}
3188
3189bool on_tty(void) {
3190 static int cached_on_tty = -1;
3191
3192 if (_unlikely_(cached_on_tty < 0))
3193 cached_on_tty = isatty(STDOUT_FILENO) > 0;
3194
3195 return cached_on_tty;
8f2d43a0
LP
3196}
3197
9d9951a4
HH
3198int files_same(const char *filea, const char *fileb) {
3199 struct stat a, b;
b4f10a5e 3200
9d9951a4 3201 if (stat(filea, &a) < 0)
b4f10a5e
LP
3202 return -errno;
3203
9d9951a4 3204 if (stat(fileb, &b) < 0)
b4f10a5e
LP
3205 return -errno;
3206
9d9951a4
HH
3207 return a.st_dev == b.st_dev &&
3208 a.st_ino == b.st_ino;
3209}
3210
3211int running_in_chroot(void) {
3212 int ret;
3213
3214 ret = files_same("/proc/1/root", "/");
3215 if (ret < 0)
3216 return ret;
3217
3218 return ret == 0;
b4f10a5e
LP
3219}
3220
f405e86d 3221static char *ascii_ellipsize_mem(const char *s, size_t old_length, size_t new_length, unsigned percent) {
72f59706 3222 size_t x;
8fe914ec
LP
3223 char *r;
3224
3225 assert(s);
3226 assert(percent <= 100);
72f59706 3227 assert(new_length >= 3);
8fe914ec 3228
72f59706
LP
3229 if (old_length <= 3 || old_length <= new_length)
3230 return strndup(s, old_length);
8fe914ec 3231
72f59706
LP
3232 r = new0(char, new_length+1);
3233 if (!r)
a6f0104a 3234 return NULL;
8fe914ec 3235
72f59706 3236 x = (new_length * percent) / 100;
8fe914ec 3237
72f59706
LP
3238 if (x > new_length - 3)
3239 x = new_length - 3;
8fe914ec
LP
3240
3241 memcpy(r, s, x);
3242 r[x] = '.';
3243 r[x+1] = '.';
3244 r[x+2] = '.';
3245 memcpy(r + x + 3,
72f59706
LP
3246 s + old_length - (new_length - x - 3),
3247 new_length - x - 3);
8fe914ec
LP
3248
3249 return r;
3250}
3251
f405e86d
SL
3252char *ellipsize_mem(const char *s, size_t old_length, size_t new_length, unsigned percent) {
3253 size_t x;
3254 char *e;
3255 const char *i, *j;
3256 unsigned k, len, len2;
3257
3258 assert(s);
3259 assert(percent <= 100);
3260 assert(new_length >= 3);
3261
3262 /* if no multibyte characters use ascii_ellipsize_mem for speed */
3263 if (ascii_is_valid(s))
3264 return ascii_ellipsize_mem(s, old_length, new_length, percent);
3265
3266 if (old_length <= 3 || old_length <= new_length)
3267 return strndup(s, old_length);
3268
3269 x = (new_length * percent) / 100;
3270
3271 if (x > new_length - 3)
3272 x = new_length - 3;
3273
3274 k = 0;
3275 for (i = s; k < x && i < s + old_length; i = utf8_next_char(i)) {
3276 int c;
3277
3278 c = utf8_encoded_to_unichar(i);
3279 if (c < 0)
3280 return NULL;
3281 k += unichar_iswide(c) ? 2 : 1;
3282 }
3283
3284 if (k > x) /* last character was wide and went over quota */
3285 x ++;
3286
3287 for (j = s + old_length; k < new_length && j > i; ) {
3288 int c;
3289
3290 j = utf8_prev_char(j);
3291 c = utf8_encoded_to_unichar(j);
3292 if (c < 0)
3293 return NULL;
3294 k += unichar_iswide(c) ? 2 : 1;
3295 }
3296 assert(i <= j);
3297
3298 /* we don't actually need to ellipsize */
3299 if (i == j)
3300 return memdup(s, old_length + 1);
3301
3302 /* make space for ellipsis */
3303 j = utf8_next_char(j);
3304
3305 len = i - s;
3306 len2 = s + old_length - j;
3307 e = new(char, len + 3 + len2 + 1);
3308 if (!e)
3309 return NULL;
3310
3311 /*
3312 printf("old_length=%zu new_length=%zu x=%zu len=%u len2=%u k=%u\n",
3313 old_length, new_length, x, len, len2, k);
3314 */
3315
3316 memcpy(e, s, len);
3317 e[len] = 0xe2; /* tri-dot ellipsis: … */
3318 e[len + 1] = 0x80;
3319 e[len + 2] = 0xa6;
3320
3321 memcpy(e + len + 3, j, len2 + 1);
3322
3323 return e;
3324}
3325
72f59706
LP
3326char *ellipsize(const char *s, size_t length, unsigned percent) {
3327 return ellipsize_mem(s, strlen(s), length, percent);
3328}
3329
f6144808 3330int touch(const char *path) {
03e334a1 3331 _cleanup_close_ int fd;
f6144808
LP
3332
3333 assert(path);
3334
73836c5c
LP
3335 /* This just opens the file for writing, ensuring it
3336 * exists. It doesn't call utimensat() the way /usr/bin/touch
3337 * does it. */
3338
3339 fd = open(path, O_WRONLY|O_CREAT|O_CLOEXEC|O_NOCTTY, 0644);
3340 if (fd < 0)
f6144808
LP
3341 return -errno;
3342
f6144808
LP
3343 return 0;
3344}
afea26ad 3345
97c4a07d 3346char *unquote(const char *s, const char* quotes) {
11ce3427
LP
3347 size_t l;
3348 assert(s);
3349
73836c5c
LP
3350 /* This is rather stupid, simply removes the heading and
3351 * trailing quotes if there is one. Doesn't care about
57f30678
LP
3352 * escaping or anything. We should make this smarter one
3353 * day...*/
73836c5c 3354
31ed59c5
LP
3355 l = strlen(s);
3356 if (l < 2)
11ce3427
LP
3357 return strdup(s);
3358
97c4a07d 3359 if (strchr(quotes, s[0]) && s[l-1] == s[0])
11ce3427
LP
3360 return strndup(s+1, l-2);
3361
3362 return strdup(s);
3363}
3364
5f7c426e 3365char *normalize_env_assignment(const char *s) {
57f30678
LP
3366 _cleanup_free_ char *name = NULL, *value = NULL, *p = NULL;
3367 char *eq, *r;
5f7c426e 3368
57f30678
LP
3369 eq = strchr(s, '=');
3370 if (!eq) {
3371 char *t;
5f7c426e 3372
57f30678
LP
3373 r = strdup(s);
3374 if (!r)
5f7c426e
LP
3375 return NULL;
3376
57f30678
LP
3377 t = strstrip(r);
3378 if (t == r)
3379 return r;
3380
3381 memmove(r, t, strlen(t) + 1);
3382 return r;
5f7c426e
LP
3383 }
3384
57f30678
LP
3385 name = strndup(s, eq - s);
3386 if (!name)
5f7c426e
LP
3387 return NULL;
3388
57f30678
LP
3389 p = strdup(eq + 1);
3390 if (!p)
5f7c426e 3391 return NULL;
5f7c426e
LP
3392
3393 value = unquote(strstrip(p), QUOTES);
57f30678 3394 if (!value)
5f7c426e 3395 return NULL;
5f7c426e 3396
57f30678 3397 if (asprintf(&r, "%s=%s", strstrip(name), value) < 0)
5f7c426e
LP
3398 r = NULL;
3399
5f7c426e
LP
3400 return r;
3401}
3402
8e12a6ae 3403int wait_for_terminate(pid_t pid, siginfo_t *status) {
1968a360
LP
3404 siginfo_t dummy;
3405
2e78aa99 3406 assert(pid >= 1);
1968a360
LP
3407
3408 if (!status)
3409 status = &dummy;
2e78aa99
LP
3410
3411 for (;;) {
8e12a6ae
LP
3412 zero(*status);
3413
3414 if (waitid(P_PID, pid, status, WEXITED) < 0) {
2e78aa99
LP
3415
3416 if (errno == EINTR)
3417 continue;
3418
3419 return -errno;
3420 }
3421
3422 return 0;
3423 }
3424}
3425
97c4a07d
LP
3426int wait_for_terminate_and_warn(const char *name, pid_t pid) {
3427 int r;
3428 siginfo_t status;
3429
3430 assert(name);
3431 assert(pid > 1);
3432
d87be9b0
LP
3433 r = wait_for_terminate(pid, &status);
3434 if (r < 0) {
97c4a07d
LP
3435 log_warning("Failed to wait for %s: %s", name, strerror(-r));
3436 return r;
3437 }
3438
3439 if (status.si_code == CLD_EXITED) {
3440 if (status.si_status != 0) {
3441 log_warning("%s failed with error code %i.", name, status.si_status);
0a27cf3f 3442 return status.si_status;
97c4a07d
LP
3443 }
3444
3445 log_debug("%s succeeded.", name);
3446 return 0;
3447
3448 } else if (status.si_code == CLD_KILLED ||
3449 status.si_code == CLD_DUMPED) {
3450
3451 log_warning("%s terminated by signal %s.", name, signal_to_string(status.si_status));
3452 return -EPROTO;
3453 }
3454
3455 log_warning("%s failed due to unknown reason.", name);
3456 return -EPROTO;
97c4a07d
LP
3457}
3458
919ce0b7 3459noreturn void freeze(void) {
720ce21d
LP
3460
3461 /* Make sure nobody waits for us on a socket anymore */
3462 close_all_fds(NULL, 0);
3463
c29597a1
LP
3464 sync();
3465
3c14d26c
LP
3466 for (;;)
3467 pause();
3468}
3469
00dc5d76
LP
3470bool null_or_empty(struct stat *st) {
3471 assert(st);
3472
3473 if (S_ISREG(st->st_mode) && st->st_size <= 0)
3474 return true;
3475
c8f26f42 3476 if (S_ISCHR(st->st_mode) || S_ISBLK(st->st_mode))
00dc5d76
LP
3477 return true;
3478
3479 return false;
3480}
3481
83096483
LP
3482int null_or_empty_path(const char *fn) {
3483 struct stat st;
3484
3485 assert(fn);
3486
3487 if (stat(fn, &st) < 0)
3488 return -errno;
3489
3490 return null_or_empty(&st);
3491}
3492
a247755d 3493DIR *xopendirat(int fd, const char *name, int flags) {
c4731d11
LP
3494 int nfd;
3495 DIR *d;
3496
dd94c17e
LP
3497 assert(!(flags & O_CREAT));
3498
3499 nfd = openat(fd, name, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|flags, 0);
73836c5c 3500 if (nfd < 0)
c4731d11
LP
3501 return NULL;
3502
73836c5c
LP
3503 d = fdopendir(nfd);
3504 if (!d) {
03e334a1 3505 safe_close(nfd);
c4731d11
LP
3506 return NULL;
3507 }
3508
3509 return d;
3b63d2d3
LP
3510}
3511
8a0867d6
LP
3512int signal_from_string_try_harder(const char *s) {
3513 int signo;
3514 assert(s);
3515
73836c5c
LP
3516 signo = signal_from_string(s);
3517 if (signo <= 0)
8a0867d6
LP
3518 if (startswith(s, "SIG"))
3519 return signal_from_string(s+3);
3520
3521 return signo;
3522}
3523
383182b5 3524static char *tag_to_udev_node(const char *tagvalue, const char *by) {
22f5f628 3525 _cleanup_free_ char *t = NULL, *u = NULL;
22f5f628 3526 size_t enc_len;
e23a0ce8 3527
383182b5 3528 u = unquote(tagvalue, "\"\'");
6db615c1 3529 if (!u)
383182b5 3530 return NULL;
e23a0ce8 3531
1d5989fd 3532 enc_len = strlen(u) * 4 + 1;
22f5f628 3533 t = new(char, enc_len);
6db615c1 3534 if (!t)
383182b5 3535 return NULL;
e23a0ce8 3536
8f6ce71f 3537 if (encode_devnode_name(u, t, enc_len) < 0)
22f5f628 3538 return NULL;
e23a0ce8 3539
6db615c1 3540 return strjoin("/dev/disk/by-", by, "/", t, NULL);
383182b5 3541}
e23a0ce8 3542
383182b5 3543char *fstab_node_to_udev_node(const char *p) {
faa368e3
LP
3544 assert(p);
3545
383182b5
DR
3546 if (startswith(p, "LABEL="))
3547 return tag_to_udev_node(p+6, "label");
e23a0ce8 3548
383182b5
DR
3549 if (startswith(p, "UUID="))
3550 return tag_to_udev_node(p+5, "uuid");
e23a0ce8 3551
84cc2abf
DR
3552 if (startswith(p, "PARTUUID="))
3553 return tag_to_udev_node(p+9, "partuuid");
3554
3555 if (startswith(p, "PARTLABEL="))
3556 return tag_to_udev_node(p+10, "partlabel");
3557
e23a0ce8
LP
3558 return strdup(p);
3559}
3560
f212ac12
LP
3561bool tty_is_vc(const char *tty) {
3562 assert(tty);
3563
3564 if (startswith(tty, "/dev/"))
3565 tty += 5;
3566
98a28fef
LP
3567 return vtnr_from_tty(tty) >= 0;
3568}
3569
d1122ad5
LP
3570bool tty_is_console(const char *tty) {
3571 assert(tty);
3572
3573 if (startswith(tty, "/dev/"))
3574 tty += 5;
3575
3576 return streq(tty, "console");
3577}
3578
98a28fef
LP
3579int vtnr_from_tty(const char *tty) {
3580 int i, r;
3581
3582 assert(tty);
3583
3584 if (startswith(tty, "/dev/"))
3585 tty += 5;
3586
3587 if (!startswith(tty, "tty") )
3588 return -EINVAL;
3589
3590 if (tty[3] < '0' || tty[3] > '9')
3591 return -EINVAL;
3592
3593 r = safe_atoi(tty+3, &i);
3594 if (r < 0)
3595 return r;
3596
3597 if (i < 0 || i > 63)
3598 return -EINVAL;
3599
3600 return i;
f212ac12
LP
3601}
3602
21baf21a
MS
3603char *resolve_dev_console(char **active) {
3604 char *tty;
3605
3606 /* Resolve where /dev/console is pointing to, if /sys is actually ours
3607 * (i.e. not read-only-mounted which is a sign for container setups) */
3608
3609 if (path_is_read_only_fs("/sys") > 0)
3610 return NULL;
3611
3612 if (read_one_line_file("/sys/class/tty/console/active", active) < 0)
3613 return NULL;
3614
3615 /* If multiple log outputs are configured the last one is what
3616 * /dev/console points to */
3617 tty = strrchr(*active, ' ');
3618 if (tty)
3619 tty++;
3620 else
3621 tty = *active;
3622
8aa5429a
OB
3623 if (streq(tty, "tty0")) {
3624 char *tmp;
3625
3626 /* Get the active VC (e.g. tty1) */
3627 if (read_one_line_file("/sys/class/tty/tty0/active", &tmp) >= 0) {
3628 free(*active);
3629 tty = *active = tmp;
3630 }
3631 }
3632
21baf21a
MS
3633 return tty;
3634}
3635
3043935f 3636bool tty_is_vc_resolve(const char *tty) {
9588bc32 3637 _cleanup_free_ char *active = NULL;
3030ccd7 3638
e3aa71c3
LP
3639 assert(tty);
3640
3641 if (startswith(tty, "/dev/"))
3642 tty += 5;
3643
21baf21a
MS
3644 if (streq(tty, "console")) {
3645 tty = resolve_dev_console(&active);
3646 if (!tty)
3647 return false;
3648 }
3030ccd7 3649
9588bc32 3650 return tty_is_vc(tty);
3043935f
LP
3651}
3652
3653const char *default_term_for_tty(const char *tty) {
3654 assert(tty);
3655
acda6a05 3656 return tty_is_vc_resolve(tty) ? "TERM=linux" : "TERM=vt102";
e3aa71c3
LP
3657}
3658
87d2c1ff 3659bool dirent_is_file(const struct dirent *de) {
fb19a739
LP
3660 assert(de);
3661
3662 if (ignore_file(de->d_name))
3663 return false;
3664
3665 if (de->d_type != DT_REG &&
3666 de->d_type != DT_LNK &&
3667 de->d_type != DT_UNKNOWN)
3668 return false;
3669
3670 return true;
3671}
3672
87d2c1ff
LP
3673bool dirent_is_file_with_suffix(const struct dirent *de, const char *suffix) {
3674 assert(de);
3675
a228a22f
LP
3676 if (de->d_type != DT_REG &&
3677 de->d_type != DT_LNK &&
3678 de->d_type != DT_UNKNOWN)
3679 return false;
3680
3681 if (ignore_file_allow_backup(de->d_name))
87d2c1ff
LP
3682 return false;
3683
3684 return endswith(de->d_name, suffix);
3685}
3686
aa62a893
LP
3687void execute_directory(const char *directory, DIR *d, usec_t timeout, char *argv[]) {
3688 pid_t executor_pid;
3689 int r;
83cc030f
LP
3690
3691 assert(directory);
3692
aa62a893
LP
3693 /* Executes all binaries in a directory in parallel and waits
3694 * for them to finish. Optionally a timeout is applied. */
83cc030f 3695
aa62a893
LP
3696 executor_pid = fork();
3697 if (executor_pid < 0) {
3698 log_error("Failed to fork: %m");
3699 return;
83cc030f 3700
aa62a893
LP
3701 } else if (executor_pid == 0) {
3702 _cleanup_hashmap_free_free_ Hashmap *pids = NULL;
3703 _cleanup_closedir_ DIR *_d = NULL;
3704 struct dirent *de;
3705 sigset_t ss;
83cc030f 3706
aa62a893
LP
3707 /* We fork this all off from a child process so that
3708 * we can somewhat cleanly make use of SIGALRM to set
3709 * a time limit */
83cc030f 3710
aa62a893 3711 reset_all_signal_handlers();
83cc030f 3712
aa62a893
LP
3713 assert_se(sigemptyset(&ss) == 0);
3714 assert_se(sigprocmask(SIG_SETMASK, &ss, NULL) == 0);
83cc030f 3715
aa62a893 3716 assert_se(prctl(PR_SET_PDEATHSIG, SIGTERM) == 0);
83cc030f 3717
aa62a893
LP
3718 if (!d) {
3719 d = _d = opendir(directory);
3720 if (!d) {
3721 if (errno == ENOENT)
3722 _exit(EXIT_SUCCESS);
83cc030f 3723
aa62a893
LP
3724 log_error("Failed to enumerate directory %s: %m", directory);
3725 _exit(EXIT_FAILURE);
3726 }
83cc030f
LP
3727 }
3728
aa62a893
LP
3729 pids = hashmap_new(NULL, NULL);
3730 if (!pids) {
3731 log_oom();
3732 _exit(EXIT_FAILURE);
83cc030f
LP
3733 }
3734
aa62a893
LP
3735 FOREACH_DIRENT(de, d, break) {
3736 _cleanup_free_ char *path = NULL;
3737 pid_t pid;
83cc030f 3738
aa62a893
LP
3739 if (!dirent_is_file(de))
3740 continue;
83cc030f 3741
aa62a893
LP
3742 if (asprintf(&path, "%s/%s", directory, de->d_name) < 0) {
3743 log_oom();
3744 _exit(EXIT_FAILURE);
3745 }
83cc030f 3746
aa62a893
LP
3747 pid = fork();
3748 if (pid < 0) {
3749 log_error("Failed to fork: %m");
3750 continue;
3751 } else if (pid == 0) {
3752 char *_argv[2];
83cc030f 3753
aa62a893 3754 assert_se(prctl(PR_SET_PDEATHSIG, SIGTERM) == 0);
83cc030f 3755
aa62a893
LP
3756 if (!argv) {
3757 _argv[0] = path;
3758 _argv[1] = NULL;
3759 argv = _argv;
3760 } else
3761 argv[0] = path;
83cc030f 3762
aa62a893
LP
3763 execv(path, argv);
3764 log_error("Failed to execute %s: %m", path);
3765 _exit(EXIT_FAILURE);
3766 }
83cc030f 3767
83cc030f 3768
aa62a893 3769 log_debug("Spawned %s as " PID_FMT ".", path, pid);
83cc030f 3770
aa62a893
LP
3771 r = hashmap_put(pids, UINT_TO_PTR(pid), path);
3772 if (r < 0) {
3773 log_oom();
3774 _exit(EXIT_FAILURE);
3775 }
3776
3777 path = NULL;
83cc030f
LP
3778 }
3779
aa62a893
LP
3780 /* Abort execution of this process after the
3781 * timout. We simply rely on SIGALRM as default action
3782 * terminating the process, and turn on alarm(). */
3783
3784 if (timeout != (usec_t) -1)
3785 alarm((timeout + USEC_PER_SEC - 1) / USEC_PER_SEC);
3786
3787 while (!hashmap_isempty(pids)) {
3788 _cleanup_free_ char *path = NULL;
3789 pid_t pid;
3790
3791 pid = PTR_TO_UINT(hashmap_first_key(pids));
3792 assert(pid > 0);
83cc030f 3793
aa62a893
LP
3794 path = hashmap_remove(pids, UINT_TO_PTR(pid));
3795 assert(path);
3796
3797 wait_for_terminate_and_warn(path, pid);
83cc030f 3798 }
83cc030f 3799
aa62a893
LP
3800 _exit(EXIT_SUCCESS);
3801 }
83cc030f 3802
aa62a893 3803 wait_for_terminate_and_warn(directory, executor_pid);
83cc030f
LP
3804}
3805
430c18ed
LP
3806int kill_and_sigcont(pid_t pid, int sig) {
3807 int r;
3808
3809 r = kill(pid, sig) < 0 ? -errno : 0;
3810
3811 if (r >= 0)
3812 kill(pid, SIGCONT);
3813
3814 return r;
3815}
3816
05feefe0
LP
3817bool nulstr_contains(const char*nulstr, const char *needle) {
3818 const char *i;
3819
3820 if (!nulstr)
3821 return false;
3822
3823 NULSTR_FOREACH(i, nulstr)
3824 if (streq(i, needle))
3825 return true;
3826
3827 return false;
3828}
3829
6faa1114 3830bool plymouth_running(void) {
9408a2d2 3831 return access("/run/plymouth/pid", F_OK) >= 0;
6faa1114
LP
3832}
3833
9beb3f4d
LP
3834char* strshorten(char *s, size_t l) {
3835 assert(s);
3836
3837 if (l < strlen(s))
3838 s[l] = 0;
3839
3840 return s;
3841}
3842
3843static bool hostname_valid_char(char c) {
3844 return
3845 (c >= 'a' && c <= 'z') ||
3846 (c >= 'A' && c <= 'Z') ||
3847 (c >= '0' && c <= '9') ||
3848 c == '-' ||
3849 c == '_' ||
3850 c == '.';
3851}
3852
3853bool hostname_is_valid(const char *s) {
3854 const char *p;
aa3c5cf8 3855 bool dot;
9beb3f4d
LP
3856
3857 if (isempty(s))
3858 return false;
3859
aa3c5cf8
LP
3860 for (p = s, dot = true; *p; p++) {
3861 if (*p == '.') {
3862 if (dot)
3863 return false;
3864
3865 dot = true;
3866 } else {
3867 if (!hostname_valid_char(*p))
3868 return false;
3869
3870 dot = false;
3871 }
3872 }
3873
3874 if (dot)
3875 return false;
9beb3f4d
LP
3876
3877 if (p-s > HOST_NAME_MAX)
3878 return false;
3879
3880 return true;
3881}
3882
e724b063 3883char* hostname_cleanup(char *s, bool lowercase) {
9beb3f4d 3884 char *p, *d;
cec4ead9
LP
3885 bool dot;
3886
3887 for (p = s, d = s, dot = true; *p; p++) {
3888 if (*p == '.') {
e724b063 3889 if (dot)
cec4ead9 3890 continue;
9beb3f4d 3891
e724b063 3892 *(d++) = '.';
cec4ead9 3893 dot = true;
e724b063
LP
3894 } else if (hostname_valid_char(*p)) {
3895 *(d++) = lowercase ? tolower(*p) : *p;
cec4ead9 3896 dot = false;
e724b063 3897 }
cec4ead9 3898
cec4ead9 3899 }
9beb3f4d 3900
e724b063
LP
3901 if (dot && d > s)
3902 d[-1] = 0;
3903 else
3904 *d = 0;
3905
9beb3f4d 3906 strshorten(s, HOST_NAME_MAX);
cec4ead9 3907
9beb3f4d
LP
3908 return s;
3909}
3910
1325aa42 3911int pipe_eof(int fd) {
b92bea5d
ZJS
3912 struct pollfd pollfd = {
3913 .fd = fd,
3914 .events = POLLIN|POLLHUP,
3915 };
1325aa42 3916
d37a91e8
LP
3917 int r;
3918
1325aa42
LP
3919 r = poll(&pollfd, 1, 0);
3920 if (r < 0)
3921 return -errno;
3922
3923 if (r == 0)
3924 return 0;
3925
3926 return pollfd.revents & POLLHUP;
3927}
3928
8f2d43a0 3929int fd_wait_for_event(int fd, int event, usec_t t) {
968d3d24 3930
b92bea5d
ZJS
3931 struct pollfd pollfd = {
3932 .fd = fd,
3933 .events = event,
3934 };
df50185b 3935
968d3d24
LP
3936 struct timespec ts;
3937 int r;
3938
3939 r = ppoll(&pollfd, 1, t == (usec_t) -1 ? NULL : timespec_store(&ts, t), NULL);
df50185b
LP
3940 if (r < 0)
3941 return -errno;
3942
3943 if (r == 0)
3944 return 0;
3945
3946 return pollfd.revents;
3947}
3948
5a3ab509
LP
3949int fopen_temporary(const char *path, FILE **_f, char **_temp_path) {
3950 FILE *f;
3951 char *t;
3952 const char *fn;
3953 size_t k;
3954 int fd;
3955
3956 assert(path);
3957 assert(_f);
3958 assert(_temp_path);
3959
3960 t = new(char, strlen(path) + 1 + 6 + 1);
3961 if (!t)
3962 return -ENOMEM;
3963
2b6bf07d
ZJS
3964 fn = basename(path);
3965 k = fn - path;
5a3ab509
LP
3966 memcpy(t, path, k);
3967 t[k] = '.';
3968 stpcpy(stpcpy(t+k+1, fn), "XXXXXX");
3969
2d5bdf5b 3970 fd = mkostemp_safe(t, O_WRONLY|O_CLOEXEC);
5a3ab509
LP
3971 if (fd < 0) {
3972 free(t);
3973 return -errno;
3974 }
3975
3976 f = fdopen(fd, "we");
3977 if (!f) {
3978 unlink(t);
3979 free(t);
3980 return -errno;
3981 }
3982
3983 *_f = f;
3984 *_temp_path = t;
3985
3986 return 0;
3987}
3988
6ea832a2 3989int terminal_vhangup_fd(int fd) {
5a3ab509
LP
3990 assert(fd >= 0);
3991
6ea832a2
LP
3992 if (ioctl(fd, TIOCVHANGUP) < 0)
3993 return -errno;
3994
3995 return 0;
3996}
3997
3998int terminal_vhangup(const char *name) {
03e334a1 3999 _cleanup_close_ int fd;
6ea832a2
LP
4000
4001 fd = open_terminal(name, O_RDWR|O_NOCTTY|O_CLOEXEC);
4002 if (fd < 0)
4003 return fd;
4004
03e334a1 4005 return terminal_vhangup_fd(fd);
6ea832a2
LP
4006}
4007
4008int vt_disallocate(const char *name) {
4009 int fd, r;
4010 unsigned u;
6ea832a2
LP
4011
4012 /* Deallocate the VT if possible. If not possible
4013 * (i.e. because it is the active one), at least clear it
4014 * entirely (including the scrollback buffer) */
4015
b83bc4e9
LP
4016 if (!startswith(name, "/dev/"))
4017 return -EINVAL;
4018
4019 if (!tty_is_vc(name)) {
4020 /* So this is not a VT. I guess we cannot deallocate
4021 * it then. But let's at least clear the screen */
4022
4023 fd = open_terminal(name, O_RDWR|O_NOCTTY|O_CLOEXEC);
4024 if (fd < 0)
4025 return fd;
4026
8585357a
LP
4027 loop_write(fd,
4028 "\033[r" /* clear scrolling region */
4029 "\033[H" /* move home */
4030 "\033[2J", /* clear screen */
4031 10, false);
03e334a1 4032 safe_close(fd);
b83bc4e9
LP
4033
4034 return 0;
4035 }
6ea832a2
LP
4036
4037 if (!startswith(name, "/dev/tty"))
4038 return -EINVAL;
4039
4040 r = safe_atou(name+8, &u);
4041 if (r < 0)
4042 return r;
4043
4044 if (u <= 0)
b83bc4e9 4045 return -EINVAL;
6ea832a2 4046
b83bc4e9 4047 /* Try to deallocate */
6ea832a2
LP
4048 fd = open_terminal("/dev/tty0", O_RDWR|O_NOCTTY|O_CLOEXEC);
4049 if (fd < 0)
4050 return fd;
4051
4052 r = ioctl(fd, VT_DISALLOCATE, u);
03e334a1 4053 safe_close(fd);
6ea832a2 4054
b83bc4e9
LP
4055 if (r >= 0)
4056 return 0;
6ea832a2 4057
b83bc4e9 4058 if (errno != EBUSY)
6ea832a2 4059 return -errno;
6ea832a2 4060
b83bc4e9
LP
4061 /* Couldn't deallocate, so let's clear it fully with
4062 * scrollback */
4063 fd = open_terminal(name, O_RDWR|O_NOCTTY|O_CLOEXEC);
6ea832a2 4064 if (fd < 0)
b83bc4e9 4065 return fd;
6ea832a2 4066
8585357a
LP
4067 loop_write(fd,
4068 "\033[r" /* clear scrolling region */
4069 "\033[H" /* move home */
4070 "\033[3J", /* clear screen including scrollback, requires Linux 2.6.40 */
4071 10, false);
03e334a1 4072 safe_close(fd);
6ea832a2 4073
b83bc4e9 4074 return 0;
6ea832a2
LP
4075}
4076
51045322
LP
4077int copy_file(const char *from, const char *to, int flags) {
4078 _cleanup_close_ int fdf = -1;
4079 int r, fdt;
34ca941c
LP
4080
4081 assert(from);
4082 assert(to);
4083
4084 fdf = open(from, O_RDONLY|O_CLOEXEC|O_NOCTTY);
4085 if (fdf < 0)
4086 return -errno;
4087
51045322
LP
4088 fdt = open(to, flags|O_WRONLY|O_CREAT|O_CLOEXEC|O_NOCTTY, 0644);
4089 if (fdt < 0)
34ca941c 4090 return -errno;
34ca941c
LP
4091
4092 for (;;) {
4093 char buf[PIPE_BUF];
4094 ssize_t n, k;
4095
4096 n = read(fdf, buf, sizeof(buf));
4097 if (n < 0) {
4098 r = -errno;
4099
34ca941c
LP
4100 close_nointr(fdt);
4101 unlink(to);
4102
4103 return r;
4104 }
4105
4106 if (n == 0)
4107 break;
4108
4109 errno = 0;
4110 k = loop_write(fdt, buf, n, false);
4111 if (n != k) {
4112 r = k < 0 ? k : (errno ? -errno : -EIO);
4113
34ca941c 4114 close_nointr(fdt);
34ca941c 4115 unlink(to);
51045322 4116
34ca941c
LP
4117 return r;
4118 }
4119 }
4120
34ca941c
LP
4121 r = close_nointr(fdt);
4122
4123 if (r < 0) {
4124 unlink(to);
4125 return r;
4126 }
4127
4128 return 0;
4129}
4130
424a19f8
LP
4131int symlink_atomic(const char *from, const char *to) {
4132 char *x;
4133 _cleanup_free_ char *t;
34ca941c
LP
4134 const char *fn;
4135 size_t k;
9bf3b535 4136 uint64_t u;
34ca941c
LP
4137 unsigned i;
4138 int r;
4139
4140 assert(from);
4141 assert(to);
4142
4143 t = new(char, strlen(to) + 1 + 16 + 1);
4144 if (!t)
4145 return -ENOMEM;
4146
2b6bf07d 4147 fn = basename(to);
34ca941c
LP
4148 k = fn-to;
4149 memcpy(t, to, k);
4150 t[k] = '.';
4151 x = stpcpy(t+k+1, fn);
4152
9bf3b535 4153 u = random_u64();
34ca941c 4154 for (i = 0; i < 16; i++) {
9bf3b535
LP
4155 *(x++) = hexchar(u & 0xF);
4156 u >>= 4;
34ca941c
LP
4157 }
4158
4159 *x = 0;
4160
424a19f8
LP
4161 if (symlink(from, t) < 0)
4162 return -errno;
34ca941c
LP
4163
4164 if (rename(t, to) < 0) {
4165 r = -errno;
4166 unlink(t);
34ca941c
LP
4167 return r;
4168 }
4169
424a19f8 4170 return 0;
34ca941c
LP
4171}
4172
4d6d6518
LP
4173bool display_is_local(const char *display) {
4174 assert(display);
4175
4176 return
4177 display[0] == ':' &&
4178 display[1] >= '0' &&
4179 display[1] <= '9';
4180}
4181
4182int socket_from_display(const char *display, char **path) {
4183 size_t k;
4184 char *f, *c;
4185
4186 assert(display);
4187 assert(path);
4188
4189 if (!display_is_local(display))
4190 return -EINVAL;
4191
4192 k = strspn(display+1, "0123456789");
4193
f8294e41 4194 f = new(char, strlen("/tmp/.X11-unix/X") + k + 1);
4d6d6518
LP
4195 if (!f)
4196 return -ENOMEM;
4197
4198 c = stpcpy(f, "/tmp/.X11-unix/X");
4199 memcpy(c, display+1, k);
4200 c[k] = 0;
4201
4202 *path = f;
4203
4204 return 0;
4205}
4206
d05c5031
LP
4207int get_user_creds(
4208 const char **username,
4209 uid_t *uid, gid_t *gid,
4210 const char **home,
4211 const char **shell) {
4212
1cccf435 4213 struct passwd *p;
ddd88763 4214 uid_t u;
1cccf435
MV
4215
4216 assert(username);
4217 assert(*username);
1cccf435
MV
4218
4219 /* We enforce some special rules for uid=0: in order to avoid
4220 * NSS lookups for root we hardcode its data. */
4221
4222 if (streq(*username, "root") || streq(*username, "0")) {
4223 *username = "root";
4b67834e
LP
4224
4225 if (uid)
4226 *uid = 0;
4227
4228 if (gid)
4229 *gid = 0;
4230
4231 if (home)
4232 *home = "/root";
d05c5031
LP
4233
4234 if (shell)
4235 *shell = "/bin/sh";
4236
1cccf435
MV
4237 return 0;
4238 }
4239
ddd88763 4240 if (parse_uid(*username, &u) >= 0) {
1cccf435 4241 errno = 0;
ddd88763 4242 p = getpwuid(u);
1cccf435
MV
4243
4244 /* If there are multiple users with the same id, make
4245 * sure to leave $USER to the configured value instead
4246 * of the first occurrence in the database. However if
4247 * the uid was configured by a numeric uid, then let's
4248 * pick the real username from /etc/passwd. */
4249 if (p)
4250 *username = p->pw_name;
4251 } else {
4252 errno = 0;
4253 p = getpwnam(*username);
4254 }
4255
4256 if (!p)
8333c77e 4257 return errno > 0 ? -errno : -ESRCH;
1cccf435 4258
4b67834e
LP
4259 if (uid)
4260 *uid = p->pw_uid;
4261
4262 if (gid)
4263 *gid = p->pw_gid;
4264
4265 if (home)
4266 *home = p->pw_dir;
4267
d05c5031
LP
4268 if (shell)
4269 *shell = p->pw_shell;
4270
4b67834e
LP
4271 return 0;
4272}
4273
59164be4
LP
4274char* uid_to_name(uid_t uid) {
4275 struct passwd *p;
4276 char *r;
4277
4278 if (uid == 0)
4279 return strdup("root");
4280
4281 p = getpwuid(uid);
4282 if (p)
4283 return strdup(p->pw_name);
4284
4285 if (asprintf(&r, "%lu", (unsigned long) uid) < 0)
4286 return NULL;
4287
4288 return r;
4289}
4290
4468addc
LP
4291char* gid_to_name(gid_t gid) {
4292 struct group *p;
4293 char *r;
4294
4295 if (gid == 0)
4296 return strdup("root");
4297
4298 p = getgrgid(gid);
4299 if (p)
4300 return strdup(p->gr_name);
4301
4302 if (asprintf(&r, "%lu", (unsigned long) gid) < 0)
4303 return NULL;
4304
4305 return r;
4306}
4307
4b67834e
LP
4308int get_group_creds(const char **groupname, gid_t *gid) {
4309 struct group *g;
4310 gid_t id;
4311
4312 assert(groupname);
4313
4314 /* We enforce some special rules for gid=0: in order to avoid
4315 * NSS lookups for root we hardcode its data. */
4316
4317 if (streq(*groupname, "root") || streq(*groupname, "0")) {
4318 *groupname = "root";
4319
4320 if (gid)
4321 *gid = 0;
4322
4323 return 0;
4324 }
4325
4326 if (parse_gid(*groupname, &id) >= 0) {
4327 errno = 0;
4328 g = getgrgid(id);
4329
4330 if (g)
4331 *groupname = g->gr_name;
4332 } else {
4333 errno = 0;
4334 g = getgrnam(*groupname);
4335 }
4336
4337 if (!g)
8333c77e 4338 return errno > 0 ? -errno : -ESRCH;
4b67834e
LP
4339
4340 if (gid)
4341 *gid = g->gr_gid;
4342
1cccf435
MV
4343 return 0;
4344}
4345
4468addc
LP
4346int in_gid(gid_t gid) {
4347 gid_t *gids;
43673799
LP
4348 int ngroups_max, r, i;
4349
43673799
LP
4350 if (getgid() == gid)
4351 return 1;
4352
4353 if (getegid() == gid)
4354 return 1;
4355
4356 ngroups_max = sysconf(_SC_NGROUPS_MAX);
4357 assert(ngroups_max > 0);
4358
4359 gids = alloca(sizeof(gid_t) * ngroups_max);
4360
4361 r = getgroups(ngroups_max, gids);
4362 if (r < 0)
4363 return -errno;
4364
4365 for (i = 0; i < r; i++)
4366 if (gids[i] == gid)
4367 return 1;
4368
4369 return 0;
4370}
4371
4468addc
LP
4372int in_group(const char *name) {
4373 int r;
4374 gid_t gid;
4375
4376 r = get_group_creds(&name, &gid);
4377 if (r < 0)
4378 return r;
4379
4380 return in_gid(gid);
4381}
4382
8092a428 4383int glob_exists(const char *path) {
7fd1b19b 4384 _cleanup_globfree_ glob_t g = {};
8d98da3f 4385 int k;
8092a428
LP
4386
4387 assert(path);
4388
8092a428
LP
4389 errno = 0;
4390 k = glob(path, GLOB_NOSORT|GLOB_BRACE, NULL, &g);
4391
4392 if (k == GLOB_NOMATCH)
8d98da3f 4393 return 0;
8092a428 4394 else if (k == GLOB_NOSPACE)
8d98da3f 4395 return -ENOMEM;
8092a428 4396 else if (k == 0)
8d98da3f 4397 return !strv_isempty(g.gl_pathv);
8092a428 4398 else
8d98da3f
ZJS
4399 return errno ? -errno : -EIO;
4400}
8092a428 4401
8d98da3f
ZJS
4402int glob_extend(char ***strv, const char *path) {
4403 _cleanup_globfree_ glob_t g = {};
4404 int k;
4405 char **p;
4406
4407 errno = 0;
a8ccacf5 4408 k = glob(path, GLOB_NOSORT|GLOB_BRACE, NULL, &g);
8d98da3f
ZJS
4409
4410 if (k == GLOB_NOMATCH)
4411 return -ENOENT;
4412 else if (k == GLOB_NOSPACE)
4413 return -ENOMEM;
4414 else if (k != 0 || strv_isempty(g.gl_pathv))
4415 return errno ? -errno : -EIO;
4416
4417 STRV_FOREACH(p, g.gl_pathv) {
4418 k = strv_extend(strv, *p);
4419 if (k < 0)
4420 break;
4421 }
4422
4423 return k;
8092a428
LP
4424}
4425
83096483
LP
4426int dirent_ensure_type(DIR *d, struct dirent *de) {
4427 struct stat st;
4428
4429 assert(d);
4430 assert(de);
4431
4432 if (de->d_type != DT_UNKNOWN)
4433 return 0;
4434
4435 if (fstatat(dirfd(d), de->d_name, &st, AT_SYMLINK_NOFOLLOW) < 0)
4436 return -errno;
4437
4438 de->d_type =
4439 S_ISREG(st.st_mode) ? DT_REG :
4440 S_ISDIR(st.st_mode) ? DT_DIR :
4441 S_ISLNK(st.st_mode) ? DT_LNK :
4442 S_ISFIFO(st.st_mode) ? DT_FIFO :
4443 S_ISSOCK(st.st_mode) ? DT_SOCK :
4444 S_ISCHR(st.st_mode) ? DT_CHR :
4445 S_ISBLK(st.st_mode) ? DT_BLK :
4446 DT_UNKNOWN;
4447
4448 return 0;
4449}
4450
4451int in_search_path(const char *path, char **search) {
893fa014
ZJS
4452 char **i;
4453 _cleanup_free_ char *parent = NULL;
83096483
LP
4454 int r;
4455
9eb977db 4456 r = path_get_parent(path, &parent);
83096483
LP
4457 if (r < 0)
4458 return r;
4459
893fa014
ZJS
4460 STRV_FOREACH(i, search)
4461 if (path_equal(parent, *i))
4462 return 1;
83096483 4463
893fa014 4464 return 0;
83096483
LP
4465}
4466
034a2a52 4467int get_files_in_directory(const char *path, char ***list) {
893fa014
ZJS
4468 _cleanup_closedir_ DIR *d = NULL;
4469 size_t bufsize = 0, n = 0;
4470 _cleanup_strv_free_ char **l = NULL;
034a2a52
LP
4471
4472 assert(path);
d60ef526
LP
4473
4474 /* Returns all files in a directory in *list, and the number
4475 * of files as return value. If list is NULL returns only the
893fa014 4476 * number. */
034a2a52
LP
4477
4478 d = opendir(path);
8ea913b2
LP
4479 if (!d)
4480 return -errno;
4481
034a2a52 4482 for (;;) {
7d5e9c0f 4483 struct dirent *de;
034a2a52 4484
3fd11280
FW
4485 errno = 0;
4486 de = readdir(d);
4487 if (!de && errno != 0)
4488 return -errno;
034a2a52
LP
4489 if (!de)
4490 break;
4491
4492 dirent_ensure_type(d, de);
4493
4494 if (!dirent_is_file(de))
4495 continue;
4496
d60ef526 4497 if (list) {
893fa014
ZJS
4498 /* one extra slot is needed for the terminating NULL */
4499 if (!GREEDY_REALLOC(l, bufsize, n + 2))
4500 return -ENOMEM;
034a2a52 4501
893fa014
ZJS
4502 l[n] = strdup(de->d_name);
4503 if (!l[n])
4504 return -ENOMEM;
034a2a52 4505
893fa014 4506 l[++n] = NULL;
d60ef526 4507 } else
893fa014 4508 n++;
034a2a52
LP
4509 }
4510
893fa014
ZJS
4511 if (list) {
4512 *list = l;
4513 l = NULL; /* avoid freeing */
4514 }
034a2a52 4515
893fa014 4516 return n;
034a2a52
LP
4517}
4518
b7def684 4519char *strjoin(const char *x, ...) {
911a4828
LP
4520 va_list ap;
4521 size_t l;
4522 char *r, *p;
4523
4524 va_start(ap, x);
4525
4526 if (x) {
4527 l = strlen(x);
4528
4529 for (;;) {
4530 const char *t;
040f18ea 4531 size_t n;
911a4828
LP
4532
4533 t = va_arg(ap, const char *);
4534 if (!t)
4535 break;
4536
040f18ea 4537 n = strlen(t);
e98055de
LN
4538 if (n > ((size_t) -1) - l) {
4539 va_end(ap);
040f18ea 4540 return NULL;
e98055de 4541 }
040f18ea
LP
4542
4543 l += n;
911a4828
LP
4544 }
4545 } else
4546 l = 0;
4547
4548 va_end(ap);
4549
4550 r = new(char, l+1);
4551 if (!r)
4552 return NULL;
4553
4554 if (x) {
4555 p = stpcpy(r, x);
4556
4557 va_start(ap, x);
4558
4559 for (;;) {
4560 const char *t;
4561
4562 t = va_arg(ap, const char *);
4563 if (!t)
4564 break;
4565
4566 p = stpcpy(p, t);
4567 }
8ea913b2
LP
4568
4569 va_end(ap);
911a4828
LP
4570 } else
4571 r[0] = 0;
4572
4573 return r;
4574}
4575
b636465b 4576bool is_main_thread(void) {
ec202eae 4577 static thread_local int cached = 0;
b636465b
LP
4578
4579 if (_unlikely_(cached == 0))
4580 cached = getpid() == gettid() ? 1 : -1;
4581
4582 return cached > 0;
4583}
4584
94959f0f
LP
4585int block_get_whole_disk(dev_t d, dev_t *ret) {
4586 char *p, *s;
4587 int r;
4588 unsigned n, m;
4589
4590 assert(ret);
4591
4592 /* If it has a queue this is good enough for us */
4593 if (asprintf(&p, "/sys/dev/block/%u:%u/queue", major(d), minor(d)) < 0)
4594 return -ENOMEM;
4595
4596 r = access(p, F_OK);
4597 free(p);
4598
4599 if (r >= 0) {
4600 *ret = d;
4601 return 0;
4602 }
4603
4604 /* If it is a partition find the originating device */
4605 if (asprintf(&p, "/sys/dev/block/%u:%u/partition", major(d), minor(d)) < 0)
4606 return -ENOMEM;
4607
4608 r = access(p, F_OK);
4609 free(p);
4610
4611 if (r < 0)
4612 return -ENOENT;
4613
4614 /* Get parent dev_t */
4615 if (asprintf(&p, "/sys/dev/block/%u:%u/../dev", major(d), minor(d)) < 0)
4616 return -ENOMEM;
4617
4618 r = read_one_line_file(p, &s);
4619 free(p);
4620
4621 if (r < 0)
4622 return r;
4623
4624 r = sscanf(s, "%u:%u", &m, &n);
4625 free(s);
4626
4627 if (r != 2)
4628 return -EINVAL;
4629
4630 /* Only return this if it is really good enough for us. */
4631 if (asprintf(&p, "/sys/dev/block/%u:%u/queue", m, n) < 0)
4632 return -ENOMEM;
4633
4634 r = access(p, F_OK);
4635 free(p);
4636
4637 if (r >= 0) {
4638 *ret = makedev(m, n);
4639 return 0;
4640 }
4641
4642 return -ENOENT;
4643}
4644
8d53b453 4645int file_is_priv_sticky(const char *p) {
ad293f5a
LP
4646 struct stat st;
4647
4648 assert(p);
4649
4650 if (lstat(p, &st) < 0)
4651 return -errno;
4652
4653 return
8d53b453 4654 (st.st_uid == 0 || st.st_uid == getuid()) &&
ad293f5a
LP
4655 (st.st_mode & S_ISVTX);
4656}
94959f0f 4657
f41607a6
LP
4658static const char *const ioprio_class_table[] = {
4659 [IOPRIO_CLASS_NONE] = "none",
4660 [IOPRIO_CLASS_RT] = "realtime",
4661 [IOPRIO_CLASS_BE] = "best-effort",
4662 [IOPRIO_CLASS_IDLE] = "idle"
4663};
4664
f8b69d1d 4665DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(ioprio_class, int, INT_MAX);
f41607a6
LP
4666
4667static const char *const sigchld_code_table[] = {
4668 [CLD_EXITED] = "exited",
4669 [CLD_KILLED] = "killed",
4670 [CLD_DUMPED] = "dumped",
4671 [CLD_TRAPPED] = "trapped",
4672 [CLD_STOPPED] = "stopped",
4673 [CLD_CONTINUED] = "continued",
4674};
4675
4676DEFINE_STRING_TABLE_LOOKUP(sigchld_code, int);
4677
4678static const char *const log_facility_unshifted_table[LOG_NFACILITIES] = {
4679 [LOG_FAC(LOG_KERN)] = "kern",
4680 [LOG_FAC(LOG_USER)] = "user",
4681 [LOG_FAC(LOG_MAIL)] = "mail",
4682 [LOG_FAC(LOG_DAEMON)] = "daemon",
4683 [LOG_FAC(LOG_AUTH)] = "auth",
4684 [LOG_FAC(LOG_SYSLOG)] = "syslog",
4685 [LOG_FAC(LOG_LPR)] = "lpr",
4686 [LOG_FAC(LOG_NEWS)] = "news",
4687 [LOG_FAC(LOG_UUCP)] = "uucp",
4688 [LOG_FAC(LOG_CRON)] = "cron",
4689 [LOG_FAC(LOG_AUTHPRIV)] = "authpriv",
4690 [LOG_FAC(LOG_FTP)] = "ftp",
4691 [LOG_FAC(LOG_LOCAL0)] = "local0",
4692 [LOG_FAC(LOG_LOCAL1)] = "local1",
4693 [LOG_FAC(LOG_LOCAL2)] = "local2",
4694 [LOG_FAC(LOG_LOCAL3)] = "local3",
4695 [LOG_FAC(LOG_LOCAL4)] = "local4",
4696 [LOG_FAC(LOG_LOCAL5)] = "local5",
4697 [LOG_FAC(LOG_LOCAL6)] = "local6",
4698 [LOG_FAC(LOG_LOCAL7)] = "local7"
4699};
4700
f8b69d1d 4701DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(log_facility_unshifted, int, LOG_FAC(~0));
f41607a6
LP
4702
4703static const char *const log_level_table[] = {
4704 [LOG_EMERG] = "emerg",
4705 [LOG_ALERT] = "alert",
4706 [LOG_CRIT] = "crit",
4707 [LOG_ERR] = "err",
4708 [LOG_WARNING] = "warning",
4709 [LOG_NOTICE] = "notice",
4710 [LOG_INFO] = "info",
4711 [LOG_DEBUG] = "debug"
4712};
4713
f8b69d1d 4714DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(log_level, int, LOG_DEBUG);
f41607a6
LP
4715
4716static const char* const sched_policy_table[] = {
4717 [SCHED_OTHER] = "other",
4718 [SCHED_BATCH] = "batch",
4719 [SCHED_IDLE] = "idle",
4720 [SCHED_FIFO] = "fifo",
4721 [SCHED_RR] = "rr"
4722};
4723
f8b69d1d 4724DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(sched_policy, int, INT_MAX);
f41607a6 4725
517d56b1 4726static const char* const rlimit_table[_RLIMIT_MAX] = {
f41607a6
LP
4727 [RLIMIT_CPU] = "LimitCPU",
4728 [RLIMIT_FSIZE] = "LimitFSIZE",
4729 [RLIMIT_DATA] = "LimitDATA",
4730 [RLIMIT_STACK] = "LimitSTACK",
4731 [RLIMIT_CORE] = "LimitCORE",
4732 [RLIMIT_RSS] = "LimitRSS",
4733 [RLIMIT_NOFILE] = "LimitNOFILE",
4734 [RLIMIT_AS] = "LimitAS",
4735 [RLIMIT_NPROC] = "LimitNPROC",
4736 [RLIMIT_MEMLOCK] = "LimitMEMLOCK",
4737 [RLIMIT_LOCKS] = "LimitLOCKS",
4738 [RLIMIT_SIGPENDING] = "LimitSIGPENDING",
4739 [RLIMIT_MSGQUEUE] = "LimitMSGQUEUE",
4740 [RLIMIT_NICE] = "LimitNICE",
4741 [RLIMIT_RTPRIO] = "LimitRTPRIO",
4742 [RLIMIT_RTTIME] = "LimitRTTIME"
4743};
4744
4745DEFINE_STRING_TABLE_LOOKUP(rlimit, int);
4746
4747static const char* const ip_tos_table[] = {
4748 [IPTOS_LOWDELAY] = "low-delay",
4749 [IPTOS_THROUGHPUT] = "throughput",
4750 [IPTOS_RELIABILITY] = "reliability",
4751 [IPTOS_LOWCOST] = "low-cost",
4752};
4753
f8b69d1d 4754DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(ip_tos, int, 0xff);
f41607a6 4755
4e240ab0 4756static const char *const __signal_table[] = {
f41607a6
LP
4757 [SIGHUP] = "HUP",
4758 [SIGINT] = "INT",
4759 [SIGQUIT] = "QUIT",
4760 [SIGILL] = "ILL",
4761 [SIGTRAP] = "TRAP",
4762 [SIGABRT] = "ABRT",
4763 [SIGBUS] = "BUS",
4764 [SIGFPE] = "FPE",
4765 [SIGKILL] = "KILL",
4766 [SIGUSR1] = "USR1",
4767 [SIGSEGV] = "SEGV",
4768 [SIGUSR2] = "USR2",
4769 [SIGPIPE] = "PIPE",
4770 [SIGALRM] = "ALRM",
4771 [SIGTERM] = "TERM",
4772#ifdef SIGSTKFLT
4773 [SIGSTKFLT] = "STKFLT", /* Linux on SPARC doesn't know SIGSTKFLT */
4774#endif
4775 [SIGCHLD] = "CHLD",
4776 [SIGCONT] = "CONT",
4777 [SIGSTOP] = "STOP",
4778 [SIGTSTP] = "TSTP",
4779 [SIGTTIN] = "TTIN",
4780 [SIGTTOU] = "TTOU",
4781 [SIGURG] = "URG",
4782 [SIGXCPU] = "XCPU",
4783 [SIGXFSZ] = "XFSZ",
4784 [SIGVTALRM] = "VTALRM",
4785 [SIGPROF] = "PROF",
4786 [SIGWINCH] = "WINCH",
4787 [SIGIO] = "IO",
4788 [SIGPWR] = "PWR",
4789 [SIGSYS] = "SYS"
4790};
4791
4e240ab0
MS
4792DEFINE_PRIVATE_STRING_TABLE_LOOKUP(__signal, int);
4793
4794const char *signal_to_string(int signo) {
ec202eae 4795 static thread_local char buf[sizeof("RTMIN+")-1 + DECIMAL_STR_MAX(int) + 1];
4e240ab0
MS
4796 const char *name;
4797
4798 name = __signal_to_string(signo);
4799 if (name)
4800 return name;
4801
4802 if (signo >= SIGRTMIN && signo <= SIGRTMAX)
fa70beaa 4803 snprintf(buf, sizeof(buf), "RTMIN+%d", signo - SIGRTMIN);
4e240ab0 4804 else
fa70beaa
LP
4805 snprintf(buf, sizeof(buf), "%d", signo);
4806
4e240ab0
MS
4807 return buf;
4808}
4809
4810int signal_from_string(const char *s) {
4811 int signo;
4812 int offset = 0;
4813 unsigned u;
4814
040f18ea 4815 signo = __signal_from_string(s);
4e240ab0
MS
4816 if (signo > 0)
4817 return signo;
4818
4819 if (startswith(s, "RTMIN+")) {
4820 s += 6;
4821 offset = SIGRTMIN;
4822 }
4823 if (safe_atou(s, &u) >= 0) {
4824 signo = (int) u + offset;
4825 if (signo > 0 && signo < _NSIG)
4826 return signo;
4827 }
4828 return -1;
4829}
65457142
FC
4830
4831bool kexec_loaded(void) {
4832 bool loaded = false;
4833 char *s;
4834
4835 if (read_one_line_file("/sys/kernel/kexec_loaded", &s) >= 0) {
4836 if (s[0] == '1')
4837 loaded = true;
4838 free(s);
4839 }
4840 return loaded;
4841}
fb9de93d
LP
4842
4843int strdup_or_null(const char *a, char **b) {
4844 char *c;
4845
4846 assert(b);
4847
4848 if (!a) {
4849 *b = NULL;
4850 return 0;
4851 }
4852
4853 c = strdup(a);
4854 if (!c)
4855 return -ENOMEM;
4856
4857 *b = c;
4858 return 0;
4859}
64685e0c 4860
87d2c1ff
LP
4861int prot_from_flags(int flags) {
4862
4863 switch (flags & O_ACCMODE) {
4864
4865 case O_RDONLY:
4866 return PROT_READ;
4867
4868 case O_WRONLY:
4869 return PROT_WRITE;
4870
4871 case O_RDWR:
4872 return PROT_READ|PROT_WRITE;
4873
4874 default:
4875 return -EINVAL;
4876 }
7c99e0c1 4877}
689b9a22 4878
babfc091 4879char *format_bytes(char *buf, size_t l, off_t t) {
c0f99c21 4880 unsigned i;
babfc091
LP
4881
4882 static const struct {
4883 const char *suffix;
4884 off_t factor;
4885 } table[] = {
32895bb3
LP
4886 { "E", 1024ULL*1024ULL*1024ULL*1024ULL*1024ULL*1024ULL },
4887 { "P", 1024ULL*1024ULL*1024ULL*1024ULL*1024ULL },
babfc091
LP
4888 { "T", 1024ULL*1024ULL*1024ULL*1024ULL },
4889 { "G", 1024ULL*1024ULL*1024ULL },
4890 { "M", 1024ULL*1024ULL },
4891 { "K", 1024ULL },
4892 };
4893
4894 for (i = 0; i < ELEMENTSOF(table); i++) {
4895
4896 if (t >= table[i].factor) {
4897 snprintf(buf, l,
4898 "%llu.%llu%s",
4899 (unsigned long long) (t / table[i].factor),
4900 (unsigned long long) (((t*10ULL) / table[i].factor) % 10ULL),
4901 table[i].suffix);
4902
4903 goto finish;
4904 }
4905 }
4906
4907 snprintf(buf, l, "%lluB", (unsigned long long) t);
4908
4909finish:
4910 buf[l-1] = 0;
4911 return buf;
4912
4913}
55d7bfc1
LP
4914
4915void* memdup(const void *p, size_t l) {
4916 void *r;
4917
4918 assert(p);
4919
4920 r = malloc(l);
4921 if (!r)
4922 return NULL;
4923
4924 memcpy(r, p, l);
4925 return r;
4926}
bb99a35a
LP
4927
4928int fd_inc_sndbuf(int fd, size_t n) {
4929 int r, value;
4930 socklen_t l = sizeof(value);
4931
4932 r = getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &value, &l);
92d75ca4 4933 if (r >= 0 && l == sizeof(value) && (size_t) value >= n*2)
bb99a35a
LP
4934 return 0;
4935
92d75ca4
LP
4936 /* If we have the privileges we will ignore the kernel limit. */
4937
bb99a35a 4938 value = (int) n;
92d75ca4
LP
4939 if (setsockopt(fd, SOL_SOCKET, SO_SNDBUFFORCE, &value, sizeof(value)) < 0)
4940 if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &value, sizeof(value)) < 0)
4941 return -errno;
bb99a35a
LP
4942
4943 return 1;
4944}
4945
4946int fd_inc_rcvbuf(int fd, size_t n) {
4947 int r, value;
4948 socklen_t l = sizeof(value);
4949
4950 r = getsockopt(fd, SOL_SOCKET, SO_RCVBUF, &value, &l);
92d75ca4 4951 if (r >= 0 && l == sizeof(value) && (size_t) value >= n*2)
bb99a35a
LP
4952 return 0;
4953
92d75ca4 4954 /* If we have the privileges we will ignore the kernel limit. */
bb99a35a 4955
92d75ca4
LP
4956 value = (int) n;
4957 if (setsockopt(fd, SOL_SOCKET, SO_RCVBUFFORCE, &value, sizeof(value)) < 0)
4958 if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &value, sizeof(value)) < 0)
4959 return -errno;
bb99a35a
LP
4960 return 1;
4961}
6bb92a16 4962
9bdc770c 4963int fork_agent(pid_t *pid, const int except[], unsigned n_except, const char *path, ...) {
6bb92a16
LP
4964 pid_t parent_pid, agent_pid;
4965 int fd;
4966 bool stdout_is_tty, stderr_is_tty;
4967 unsigned n, i;
4968 va_list ap;
4969 char **l;
4970
4971 assert(pid);
4972 assert(path);
4973
4974 parent_pid = getpid();
4975
4976 /* Spawns a temporary TTY agent, making sure it goes away when
4977 * we go away */
4978
4979 agent_pid = fork();
4980 if (agent_pid < 0)
4981 return -errno;
4982
4983 if (agent_pid != 0) {
4984 *pid = agent_pid;
4985 return 0;
4986 }
4987
4988 /* In the child:
4989 *
4990 * Make sure the agent goes away when the parent dies */
4991 if (prctl(PR_SET_PDEATHSIG, SIGTERM) < 0)
4992 _exit(EXIT_FAILURE);
4993
4994 /* Check whether our parent died before we were able
4995 * to set the death signal */
4996 if (getppid() != parent_pid)
4997 _exit(EXIT_SUCCESS);
4998
4999 /* Don't leak fds to the agent */
9bdc770c 5000 close_all_fds(except, n_except);
6bb92a16
LP
5001
5002 stdout_is_tty = isatty(STDOUT_FILENO);
5003 stderr_is_tty = isatty(STDERR_FILENO);
5004
5005 if (!stdout_is_tty || !stderr_is_tty) {
5006 /* Detach from stdout/stderr. and reopen
5007 * /dev/tty for them. This is important to
5008 * ensure that when systemctl is started via
5009 * popen() or a similar call that expects to
5010 * read EOF we actually do generate EOF and
5011 * not delay this indefinitely by because we
5012 * keep an unused copy of stdin around. */
5013 fd = open("/dev/tty", O_WRONLY);
5014 if (fd < 0) {
5015 log_error("Failed to open /dev/tty: %m");
5016 _exit(EXIT_FAILURE);
5017 }
5018
5019 if (!stdout_is_tty)
5020 dup2(fd, STDOUT_FILENO);
5021
5022 if (!stderr_is_tty)
5023 dup2(fd, STDERR_FILENO);
5024
5025 if (fd > 2)
5026 close(fd);
5027 }
5028
5029 /* Count arguments */
5030 va_start(ap, path);
5031 for (n = 0; va_arg(ap, char*); n++)
5032 ;
5033 va_end(ap);
5034
5035 /* Allocate strv */
5036 l = alloca(sizeof(char *) * (n + 1));
5037
5038 /* Fill in arguments */
5039 va_start(ap, path);
5040 for (i = 0; i <= n; i++)
5041 l[i] = va_arg(ap, char*);
5042 va_end(ap);
5043
5044 execv(path, l);
5045 _exit(EXIT_FAILURE);
5046}
68faf98c
LP
5047
5048int setrlimit_closest(int resource, const struct rlimit *rlim) {
5049 struct rlimit highest, fixed;
5050
5051 assert(rlim);
5052
5053 if (setrlimit(resource, rlim) >= 0)
5054 return 0;
5055
5056 if (errno != EPERM)
5057 return -errno;
5058
5059 /* So we failed to set the desired setrlimit, then let's try
5060 * to get as close as we can */
5061 assert_se(getrlimit(resource, &highest) == 0);
5062
5063 fixed.rlim_cur = MIN(rlim->rlim_cur, highest.rlim_max);
5064 fixed.rlim_max = MIN(rlim->rlim_max, highest.rlim_max);
5065
5066 if (setrlimit(resource, &fixed) < 0)
5067 return -errno;
5068
5069 return 0;
5070}
3d9a4122 5071
ab94af92 5072int getenv_for_pid(pid_t pid, const char *field, char **_value) {
49aa47c7
LP
5073 _cleanup_fclose_ FILE *f = NULL;
5074 char *value = NULL;
ab94af92 5075 int r;
ab94af92
LP
5076 bool done = false;
5077 size_t l;
49aa47c7 5078 const char *path;
ab94af92 5079
49aa47c7 5080 assert(pid >= 0);
ab94af92
LP
5081 assert(field);
5082 assert(_value);
5083
b68fa010 5084 path = procfs_file_alloca(pid, "environ");
ab94af92
LP
5085
5086 f = fopen(path, "re");
5087 if (!f)
5088 return -errno;
5089
5090 l = strlen(field);
5091 r = 0;
5092
5093 do {
5094 char line[LINE_MAX];
5095 unsigned i;
5096
5097 for (i = 0; i < sizeof(line)-1; i++) {
5098 int c;
5099
5100 c = getc(f);
5101 if (_unlikely_(c == EOF)) {
5102 done = true;
5103 break;
5104 } else if (c == 0)
5105 break;
5106
5107 line[i] = c;
5108 }
5109 line[i] = 0;
5110
5111 if (memcmp(line, field, l) == 0 && line[l] == '=') {
5112 value = strdup(line + l + 1);
49aa47c7
LP
5113 if (!value)
5114 return -ENOMEM;
ab94af92
LP
5115
5116 r = 1;
5117 break;
5118 }
5119
5120 } while (!done);
5121
49aa47c7 5122 *_value = value;
ab94af92
LP
5123 return r;
5124}
d889a206 5125
49dbfa7b
LP
5126bool is_valid_documentation_url(const char *url) {
5127 assert(url);
5128
5129 if (startswith(url, "http://") && url[7])
5130 return true;
5131
5132 if (startswith(url, "https://") && url[8])
5133 return true;
5134
5135 if (startswith(url, "file:") && url[5])
5136 return true;
5137
5138 if (startswith(url, "info:") && url[5])
5139 return true;
5140
5141 if (startswith(url, "man:") && url[4])
5142 return true;
5143
5144 return false;
5145}
9be346c9
HH
5146
5147bool in_initrd(void) {
73020ab2 5148 static int saved = -1;
825c6fe5 5149 struct statfs s;
8f33b5b8 5150
825c6fe5
LP
5151 if (saved >= 0)
5152 return saved;
5153
5154 /* We make two checks here:
5155 *
5156 * 1. the flag file /etc/initrd-release must exist
5157 * 2. the root file system must be a memory file system
5158 *
5159 * The second check is extra paranoia, since misdetecting an
5160 * initrd can have bad bad consequences due the initrd
5161 * emptying when transititioning to the main systemd.
5162 */
5163
5164 saved = access("/etc/initrd-release", F_OK) >= 0 &&
5165 statfs("/", &s) >= 0 &&
943aad8c 5166 is_temporary_fs(&s);
9be346c9 5167
8f33b5b8 5168 return saved;
9be346c9 5169}
069cfc85
LP
5170
5171void warn_melody(void) {
e67f47e5 5172 _cleanup_close_ int fd = -1;
069cfc85
LP
5173
5174 fd = open("/dev/console", O_WRONLY|O_CLOEXEC|O_NOCTTY);
5175 if (fd < 0)
5176 return;
5177
040f18ea 5178 /* Yeah, this is synchronous. Kinda sucks. But well... */
069cfc85
LP
5179
5180 ioctl(fd, KIOCSOUND, (int)(1193180/440));
5181 usleep(125*USEC_PER_MSEC);
5182
5183 ioctl(fd, KIOCSOUND, (int)(1193180/220));
5184 usleep(125*USEC_PER_MSEC);
5185
5186 ioctl(fd, KIOCSOUND, (int)(1193180/220));
5187 usleep(125*USEC_PER_MSEC);
5188
5189 ioctl(fd, KIOCSOUND, 0);
069cfc85 5190}
cd3bd60a
LP
5191
5192int make_console_stdio(void) {
5193 int fd, r;
5194
5195 /* Make /dev/console the controlling terminal and stdin/stdout/stderr */
5196
5197 fd = acquire_terminal("/dev/console", false, true, true, (usec_t) -1);
5198 if (fd < 0) {
5199 log_error("Failed to acquire terminal: %s", strerror(-fd));
5200 return fd;
5201 }
5202
5203 r = make_stdio(fd);
5204 if (r < 0) {
5205 log_error("Failed to duplicate terminal fd: %s", strerror(-r));
5206 return r;
5207 }
5208
5209 return 0;
5210}
7c5f152a
LP
5211
5212int get_home_dir(char **_h) {
2cfbd749 5213 struct passwd *p;
7c5f152a 5214 const char *e;
2cfbd749 5215 char *h;
7c5f152a 5216 uid_t u;
7c5f152a
LP
5217
5218 assert(_h);
5219
5220 /* Take the user specified one */
5221 e = getenv("HOME");
5222 if (e) {
5223 h = strdup(e);
5224 if (!h)
5225 return -ENOMEM;
5226
5227 *_h = h;
5228 return 0;
5229 }
5230
5231 /* Hardcode home directory for root to avoid NSS */
5232 u = getuid();
5233 if (u == 0) {
5234 h = strdup("/root");
5235 if (!h)
5236 return -ENOMEM;
5237
5238 *_h = h;
5239 return 0;
5240 }
5241
5242 /* Check the database... */
5243 errno = 0;
5244 p = getpwuid(u);
5245 if (!p)
bcb161b0 5246 return errno > 0 ? -errno : -ESRCH;
7c5f152a
LP
5247
5248 if (!path_is_absolute(p->pw_dir))
5249 return -EINVAL;
5250
5251 h = strdup(p->pw_dir);
5252 if (!h)
5253 return -ENOMEM;
5254
5255 *_h = h;
5256 return 0;
5257}
5258
2cfbd749
LP
5259int get_shell(char **_s) {
5260 struct passwd *p;
5261 const char *e;
5262 char *s;
5263 uid_t u;
5264
5265 assert(_s);
5266
5267 /* Take the user specified one */
5268 e = getenv("SHELL");
5269 if (e) {
5270 s = strdup(e);
5271 if (!s)
5272 return -ENOMEM;
5273
5274 *_s = s;
5275 return 0;
5276 }
5277
5278 /* Hardcode home directory for root to avoid NSS */
5279 u = getuid();
5280 if (u == 0) {
5281 s = strdup("/bin/sh");
5282 if (!s)
5283 return -ENOMEM;
5284
5285 *_s = s;
5286 return 0;
5287 }
5288
5289 /* Check the database... */
5290 errno = 0;
5291 p = getpwuid(u);
5292 if (!p)
5293 return errno > 0 ? -errno : -ESRCH;
5294
5295 if (!path_is_absolute(p->pw_shell))
5296 return -EINVAL;
5297
5298 s = strdup(p->pw_shell);
5299 if (!s)
5300 return -ENOMEM;
5301
5302 *_s = s;
5303 return 0;
5304}
5305
0b507b17
LP
5306bool filename_is_safe(const char *p) {
5307
5308 if (isempty(p))
5309 return false;
5310
5311 if (strchr(p, '/'))
5312 return false;
5313
5314 if (streq(p, "."))
5315 return false;
5316
5317 if (streq(p, ".."))
5318 return false;
5319
5320 if (strlen(p) > FILENAME_MAX)
5321 return false;
5322
5323 return true;
5324}
5325
5326bool string_is_safe(const char *p) {
5327 const char *t;
5328
5329 assert(p);
5330
5331 for (t = p; *t; t++) {
01539d6e 5332 if (*t > 0 && *t < ' ')
0b507b17
LP
5333 return false;
5334
011afa76 5335 if (strchr("\\\"\'", *t))
0b507b17
LP
5336 return false;
5337 }
5338
5339 return true;
5340}
cfbc22ab 5341
ac4c8d6d
ZJS
5342/**
5343 * Check if a string contains control characters.
5344 * Spaces and tabs are not considered control characters.
5345 */
4d1a6904
LP
5346bool string_has_cc(const char *p) {
5347 const char *t;
5348
5349 assert(p);
5350
5351 for (t = p; *t; t++)
da2620a5 5352 if (*t > 0 && *t < ' ' && *t != '\t')
4d1a6904
LP
5353 return true;
5354
5355 return false;
5356}
5357
e884315e
LP
5358bool path_is_safe(const char *p) {
5359
5360 if (isempty(p))
5361 return false;
5362
5363 if (streq(p, "..") || startswith(p, "../") || endswith(p, "/..") || strstr(p, "/../"))
5364 return false;
5365
5366 if (strlen(p) > PATH_MAX)
5367 return false;
5368
5369 /* The following two checks are not really dangerous, but hey, they still are confusing */
5370 if (streq(p, ".") || startswith(p, "./") || endswith(p, "/.") || strstr(p, "/./"))
5371 return false;
5372
5373 if (strstr(p, "//"))
5374 return false;
5375
5376 return true;
5377}
5378
a9e12476
KS
5379/* hey glibc, APIs with callbacks without a user pointer are so useless */
5380void *xbsearch_r(const void *key, const void *base, size_t nmemb, size_t size,
1c574591 5381 int (*compar) (const void *, const void *, void *), void *arg) {
a9e12476
KS
5382 size_t l, u, idx;
5383 const void *p;
5384 int comparison;
5385
5386 l = 0;
5387 u = nmemb;
5388 while (l < u) {
5389 idx = (l + u) / 2;
5390 p = (void *)(((const char *) base) + (idx * size));
5391 comparison = compar(key, p, arg);
5392 if (comparison < 0)
5393 u = idx;
5394 else if (comparison > 0)
5395 l = idx + 1;
5396 else
5397 return (void *)p;
5398 }
5399 return NULL;
5400}
09017585
MS
5401
5402bool is_locale_utf8(void) {
5403 const char *set;
5404 static int cached_answer = -1;
5405
5406 if (cached_answer >= 0)
5407 goto out;
5408
5409 if (!setlocale(LC_ALL, "")) {
5410 cached_answer = true;
5411 goto out;
5412 }
5413
5414 set = nl_langinfo(CODESET);
5415 if (!set) {
5416 cached_answer = true;
5417 goto out;
5418 }
5419
f168c273 5420 if (streq(set, "UTF-8")) {
fee79e01
HH
5421 cached_answer = true;
5422 goto out;
5423 }
5424
6cf2f1d9
HH
5425 /* For LC_CTYPE=="C" return true, because CTYPE is effectly
5426 * unset and everything can do to UTF-8 nowadays. */
fee79e01
HH
5427 set = setlocale(LC_CTYPE, NULL);
5428 if (!set) {
5429 cached_answer = true;
5430 goto out;
5431 }
5432
6cf2f1d9
HH
5433 /* Check result, but ignore the result if C was set
5434 * explicitly. */
5435 cached_answer =
5436 streq(set, "C") &&
5437 !getenv("LC_ALL") &&
5438 !getenv("LC_CTYPE") &&
5439 !getenv("LANG");
fee79e01 5440
09017585 5441out:
6cf2f1d9 5442 return (bool) cached_answer;
09017585 5443}
c339d977
MS
5444
5445const char *draw_special_char(DrawSpecialChar ch) {
5446 static const char *draw_table[2][_DRAW_SPECIAL_CHAR_MAX] = {
5447 /* UTF-8 */ {
45a5ff0d
MS
5448 [DRAW_TREE_VERT] = "\342\224\202 ", /* │ */
5449 [DRAW_TREE_BRANCH] = "\342\224\234\342\224\200", /* ├─ */
5450 [DRAW_TREE_RIGHT] = "\342\224\224\342\224\200", /* └─ */
55c0b89c 5451 [DRAW_TREE_SPACE] = " ", /* */
45a5ff0d 5452 [DRAW_TRIANGULAR_BULLET] = "\342\200\243 ", /* ‣ */
3deadb91 5453 [DRAW_BLACK_CIRCLE] = "\342\227\217 ", /* ● */
c339d977
MS
5454 },
5455 /* ASCII fallback */ {
45a5ff0d
MS
5456 [DRAW_TREE_VERT] = "| ",
5457 [DRAW_TREE_BRANCH] = "|-",
5458 [DRAW_TREE_RIGHT] = "`-",
55c0b89c 5459 [DRAW_TREE_SPACE] = " ",
45a5ff0d 5460 [DRAW_TRIANGULAR_BULLET] = "> ",
3deadb91 5461 [DRAW_BLACK_CIRCLE] = "* ",
c339d977
MS
5462 }
5463 };
5464
5465 return draw_table[!is_locale_utf8()][ch];
5466}
409bc9c3
LP
5467
5468char *strreplace(const char *text, const char *old_string, const char *new_string) {
5469 const char *f;
5470 char *t, *r;
5471 size_t l, old_len, new_len;
5472
5473 assert(text);
5474 assert(old_string);
5475 assert(new_string);
5476
5477 old_len = strlen(old_string);
5478 new_len = strlen(new_string);
5479
5480 l = strlen(text);
5481 r = new(char, l+1);
5482 if (!r)
5483 return NULL;
5484
5485 f = text;
5486 t = r;
5487 while (*f) {
5488 char *a;
5489 size_t d, nl;
5490
5491 if (!startswith(f, old_string)) {
5492 *(t++) = *(f++);
5493 continue;
5494 }
5495
5496 d = t - r;
5497 nl = l - old_len + new_len;
5498 a = realloc(r, nl + 1);
5499 if (!a)
5500 goto oom;
5501
5502 l = nl;
5503 r = a;
5504 t = r + d;
5505
5506 t = stpcpy(t, new_string);
5507 f += old_len;
5508 }
5509
5510 *t = 0;
5511 return r;
5512
5513oom:
5514 free(r);
5515 return NULL;
5516}
e8bc0ea2
LP
5517
5518char *strip_tab_ansi(char **ibuf, size_t *_isz) {
660ddc72 5519 const char *i, *begin = NULL;
e8bc0ea2
LP
5520 enum {
5521 STATE_OTHER,
5522 STATE_ESCAPE,
5523 STATE_BRACKET
5524 } state = STATE_OTHER;
5525 char *obuf = NULL;
5526 size_t osz = 0, isz;
5527 FILE *f;
5528
5529 assert(ibuf);
5530 assert(*ibuf);
5531
5532 /* Strips ANSI color and replaces TABs by 8 spaces */
5533
5534 isz = _isz ? *_isz : strlen(*ibuf);
5535
5536 f = open_memstream(&obuf, &osz);
5537 if (!f)
5538 return NULL;
5539
5540 for (i = *ibuf; i < *ibuf + isz + 1; i++) {
5541
5542 switch (state) {
5543
5544 case STATE_OTHER:
5545 if (i >= *ibuf + isz) /* EOT */
5546 break;
5547 else if (*i == '\x1B')
5548 state = STATE_ESCAPE;
5549 else if (*i == '\t')
5550 fputs(" ", f);
5551 else
5552 fputc(*i, f);
5553 break;
5554
5555 case STATE_ESCAPE:
5556 if (i >= *ibuf + isz) { /* EOT */
5557 fputc('\x1B', f);
5558 break;
5559 } else if (*i == '[') {
5560 state = STATE_BRACKET;
5561 begin = i + 1;
5562 } else {
5563 fputc('\x1B', f);
5564 fputc(*i, f);
5565 state = STATE_OTHER;
5566 }
5567
5568 break;
5569
5570 case STATE_BRACKET:
5571
5572 if (i >= *ibuf + isz || /* EOT */
5573 (!(*i >= '0' && *i <= '9') && *i != ';' && *i != 'm')) {
5574 fputc('\x1B', f);
5575 fputc('[', f);
5576 state = STATE_OTHER;
5577 i = begin-1;
5578 } else if (*i == 'm')
5579 state = STATE_OTHER;
5580 break;
5581 }
5582 }
5583
5584 if (ferror(f)) {
5585 fclose(f);
5586 free(obuf);
5587 return NULL;
5588 }
5589
5590 fclose(f);
5591
5592 free(*ibuf);
5593 *ibuf = obuf;
5594
5595 if (_isz)
5596 *_isz = osz;
5597
5598 return obuf;
5599}
240dbaa4
LP
5600
5601int on_ac_power(void) {
5602 bool found_offline = false, found_online = false;
5603 _cleanup_closedir_ DIR *d = NULL;
5604
5605 d = opendir("/sys/class/power_supply");
5606 if (!d)
5607 return -errno;
5608
5609 for (;;) {
5610 struct dirent *de;
240dbaa4
LP
5611 _cleanup_close_ int fd = -1, device = -1;
5612 char contents[6];
5613 ssize_t n;
240dbaa4 5614
3fd11280
FW
5615 errno = 0;
5616 de = readdir(d);
5617 if (!de && errno != 0)
5618 return -errno;
240dbaa4
LP
5619
5620 if (!de)
5621 break;
5622
5623 if (ignore_file(de->d_name))
5624 continue;
5625
5626 device = openat(dirfd(d), de->d_name, O_DIRECTORY|O_RDONLY|O_CLOEXEC|O_NOCTTY);
5627 if (device < 0) {
5628 if (errno == ENOENT || errno == ENOTDIR)
5629 continue;
5630
5631 return -errno;
5632 }
5633
5634 fd = openat(device, "type", O_RDONLY|O_CLOEXEC|O_NOCTTY);
5635 if (fd < 0) {
5636 if (errno == ENOENT)
5637 continue;
5638
5639 return -errno;
5640 }
5641
5642 n = read(fd, contents, sizeof(contents));
5643 if (n < 0)
5644 return -errno;
5645
5646 if (n != 6 || memcmp(contents, "Mains\n", 6))
5647 continue;
5648
03e334a1 5649 safe_close(fd);
240dbaa4
LP
5650 fd = openat(device, "online", O_RDONLY|O_CLOEXEC|O_NOCTTY);
5651 if (fd < 0) {
5652 if (errno == ENOENT)
5653 continue;
5654
5655 return -errno;
5656 }
5657
5658 n = read(fd, contents, sizeof(contents));
5659 if (n < 0)
5660 return -errno;
5661
5662 if (n != 2 || contents[1] != '\n')
5663 return -EIO;
5664
5665 if (contents[0] == '1') {
5666 found_online = true;
5667 break;
5668 } else if (contents[0] == '0')
5669 found_offline = true;
5670 else
5671 return -EIO;
5672 }
5673
5674 return found_online || !found_offline;
5675}
fabe5c0e 5676
4cf7ea55 5677static int search_and_fopen_internal(const char *path, const char *mode, const char *root, char **search, FILE **_f) {
fabe5c0e
LP
5678 char **i;
5679
5680 assert(path);
5681 assert(mode);
5682 assert(_f);
5683
4cf7ea55 5684 if (!path_strv_canonicalize_absolute_uniq(search, root))
fabe5c0e
LP
5685 return -ENOMEM;
5686
5687 STRV_FOREACH(i, search) {
5688 _cleanup_free_ char *p = NULL;
5689 FILE *f;
5690
5691 p = strjoin(*i, "/", path, NULL);
5692 if (!p)
5693 return -ENOMEM;
5694
5695 f = fopen(p, mode);
5696 if (f) {
5697 *_f = f;
5698 return 0;
5699 }
5700
5701 if (errno != ENOENT)
5702 return -errno;
5703 }
5704
5705 return -ENOENT;
5706}
5707
4cf7ea55 5708int search_and_fopen(const char *path, const char *mode, const char *root, const char **search, FILE **_f) {
fabe5c0e
LP
5709 _cleanup_strv_free_ char **copy = NULL;
5710
5711 assert(path);
5712 assert(mode);
5713 assert(_f);
5714
5715 if (path_is_absolute(path)) {
5716 FILE *f;
5717
5718 f = fopen(path, mode);
5719 if (f) {
5720 *_f = f;
5721 return 0;
5722 }
5723
5724 return -errno;
5725 }
5726
5727 copy = strv_copy((char**) search);
5728 if (!copy)
5729 return -ENOMEM;
5730
4cf7ea55 5731 return search_and_fopen_internal(path, mode, root, copy, _f);
fabe5c0e
LP
5732}
5733
4cf7ea55 5734int search_and_fopen_nulstr(const char *path, const char *mode, const char *root, const char *search, FILE **_f) {
fabe5c0e
LP
5735 _cleanup_strv_free_ char **s = NULL;
5736
5737 if (path_is_absolute(path)) {
5738 FILE *f;
5739
5740 f = fopen(path, mode);
5741 if (f) {
5742 *_f = f;
5743 return 0;
5744 }
5745
5746 return -errno;
5747 }
5748
5749 s = strv_split_nulstr(search);
5750 if (!s)
5751 return -ENOMEM;
5752
4cf7ea55 5753 return search_and_fopen_internal(path, mode, root, s, _f);
fabe5c0e 5754}
c17ec25e 5755
66e35261
LP
5756char *strextend(char **x, ...) {
5757 va_list ap;
5758 size_t f, l;
5759 char *r, *p;
5760
5761 assert(x);
5762
5763 l = f = *x ? strlen(*x) : 0;
5764
5765 va_start(ap, x);
5766 for (;;) {
5767 const char *t;
5768 size_t n;
5769
5770 t = va_arg(ap, const char *);
5771 if (!t)
5772 break;
5773
5774 n = strlen(t);
5775 if (n > ((size_t) -1) - l) {
5776 va_end(ap);
5777 return NULL;
5778 }
5779
5780 l += n;
5781 }
5782 va_end(ap);
5783
5784 r = realloc(*x, l+1);
5785 if (!r)
5786 return NULL;
5787
5788 p = r + f;
5789
5790 va_start(ap, x);
5791 for (;;) {
5792 const char *t;
5793
5794 t = va_arg(ap, const char *);
5795 if (!t)
5796 break;
5797
5798 p = stpcpy(p, t);
5799 }
5800 va_end(ap);
5801
5802 *p = 0;
5803 *x = r;
5804
5805 return r + l;
5806}
9a17484d
LP
5807
5808char *strrep(const char *s, unsigned n) {
5809 size_t l;
5810 char *r, *p;
5811 unsigned i;
5812
5813 assert(s);
5814
5815 l = strlen(s);
5816 p = r = malloc(l * n + 1);
5817 if (!r)
5818 return NULL;
5819
5820 for (i = 0; i < n; i++)
5821 p = stpcpy(p, s);
5822
5823 *p = 0;
5824 return r;
5825}
392d5b37 5826
ca2d3784
ZJS
5827void* greedy_realloc(void **p, size_t *allocated, size_t need, size_t size) {
5828 size_t a, newalloc;
392d5b37
LP
5829 void *q;
5830
98088803 5831 assert(p);
e93c33d4
SL
5832 assert(allocated);
5833
392d5b37
LP
5834 if (*allocated >= need)
5835 return *p;
5836
ca2d3784
ZJS
5837 newalloc = MAX(need * 2, 64u / size);
5838 a = newalloc * size;
98088803
LP
5839
5840 /* check for overflows */
ca2d3784 5841 if (a < size * need)
98088803
LP
5842 return NULL;
5843
392d5b37
LP
5844 q = realloc(*p, a);
5845 if (!q)
5846 return NULL;
5847
5848 *p = q;
ca2d3784 5849 *allocated = newalloc;
392d5b37
LP
5850 return q;
5851}
aa96c6cb 5852
ca2d3784 5853void* greedy_realloc0(void **p, size_t *allocated, size_t need, size_t size) {
98088803 5854 size_t prev;
4545a231
DH
5855 uint8_t *q;
5856
98088803
LP
5857 assert(p);
5858 assert(allocated);
5859
5860 prev = *allocated;
5861
ca2d3784 5862 q = greedy_realloc(p, allocated, need, size);
4545a231
DH
5863 if (!q)
5864 return NULL;
5865
5866 if (*allocated > prev)
ca2d3784 5867 memzero(q + prev * size, (*allocated - prev) * size);
4545a231
DH
5868
5869 return q;
5870}
5871
aa96c6cb
LP
5872bool id128_is_valid(const char *s) {
5873 size_t i, l;
5874
5875 l = strlen(s);
5876 if (l == 32) {
5877
5878 /* Simple formatted 128bit hex string */
5879
5880 for (i = 0; i < l; i++) {
5881 char c = s[i];
5882
5883 if (!(c >= '0' && c <= '9') &&
5884 !(c >= 'a' && c <= 'z') &&
5885 !(c >= 'A' && c <= 'Z'))
5886 return false;
5887 }
5888
5889 } else if (l == 36) {
5890
5891 /* Formatted UUID */
5892
5893 for (i = 0; i < l; i++) {
5894 char c = s[i];
5895
5896 if ((i == 8 || i == 13 || i == 18 || i == 23)) {
5897 if (c != '-')
5898 return false;
5899 } else {
5900 if (!(c >= '0' && c <= '9') &&
5901 !(c >= 'a' && c <= 'z') &&
5902 !(c >= 'A' && c <= 'Z'))
5903 return false;
5904 }
5905 }
5906
5907 } else
5908 return false;
5909
5910 return true;
5911}
7085053a 5912
d4ac85c6
LP
5913int split_pair(const char *s, const char *sep, char **l, char **r) {
5914 char *x, *a, *b;
5915
5916 assert(s);
5917 assert(sep);
5918 assert(l);
5919 assert(r);
5920
5921 if (isempty(sep))
5922 return -EINVAL;
5923
5924 x = strstr(s, sep);
5925 if (!x)
5926 return -EINVAL;
5927
5928 a = strndup(s, x - s);
5929 if (!a)
5930 return -ENOMEM;
5931
5932 b = strdup(x + strlen(sep));
5933 if (!b) {
5934 free(a);
5935 return -ENOMEM;
5936 }
5937
5938 *l = a;
5939 *r = b;
5940
5941 return 0;
5942}
295edddf 5943
74df0fca 5944int shall_restore_state(void) {
059cb385 5945 _cleanup_free_ char *line = NULL;
295edddf 5946 char *w, *state;
295edddf 5947 size_t l;
74df0fca 5948 int r;
295edddf 5949
74df0fca
LP
5950 r = proc_cmdline(&line);
5951 if (r < 0)
5952 return r;
5953 if (r == 0) /* Container ... */
5954 return 1;
295edddf 5955
059cb385 5956 r = 1;
74df0fca 5957
059cb385
LP
5958 FOREACH_WORD_QUOTED(w, l, line, state) {
5959 const char *e;
5960 char n[l+1];
5961 int k;
5962
5963 memcpy(n, w, l);
5964 n[l] = 0;
5965
5966 e = startswith(n, "systemd.restore_state=");
5967 if (!e)
5968 continue;
5969
5970 k = parse_boolean(e);
5971 if (k >= 0)
5972 r = k;
5973 }
5974
5975 return r;
74df0fca
LP
5976}
5977
5978int proc_cmdline(char **ret) {
5979 int r;
5980
5981 if (detect_container(NULL) > 0) {
39883f62 5982 char *buf = NULL, *p;
02bb6cda
LP
5983 size_t sz = 0;
5984
5985 r = read_full_file("/proc/1/cmdline", &buf, &sz);
5986 if (r < 0)
5987 return r;
5988
5989 for (p = buf; p + 1 < buf + sz; p++)
5990 if (*p == 0)
5991 *p = ' ';
5992
059cb385 5993 *p = 0;
02bb6cda
LP
5994 *ret = buf;
5995 return 1;
295edddf
TG
5996 }
5997
74df0fca
LP
5998 r = read_one_line_file("/proc/cmdline", ret);
5999 if (r < 0)
6000 return r;
295edddf 6001
74df0fca 6002 return 1;
295edddf 6003}
bc9fd78c 6004
059cb385 6005int parse_proc_cmdline(int (*parse_item)(const char *key, const char *value)) {
141a79f4
ZJS
6006 _cleanup_free_ char *line = NULL;
6007 char *w, *state;
6008 size_t l;
6009 int r;
6010
059cb385
LP
6011 assert(parse_item);
6012
141a79f4
ZJS
6013 r = proc_cmdline(&line);
6014 if (r < 0)
6015 log_warning("Failed to read /proc/cmdline, ignoring: %s", strerror(-r));
6016 if (r <= 0)
6017 return 0;
6018
6019 FOREACH_WORD_QUOTED(w, l, line, state) {
059cb385 6020 char word[l+1], *value;
141a79f4 6021
059cb385
LP
6022 memcpy(word, w, l);
6023 word[l] = 0;
141a79f4 6024
059cb385
LP
6025 /* Filter out arguments that are intended only for the
6026 * initrd */
6027 if (!in_initrd() && startswith(word, "rd."))
6028 continue;
6029
6030 value = strchr(word, '=');
6031 if (value)
6032 *(value++) = 0;
6033
6034 r = parse_item(word, value);
6035 if (r < 0)
141a79f4 6036 return r;
141a79f4
ZJS
6037 }
6038
6039 return 0;
6040}
6041
bc9fd78c
LP
6042int container_get_leader(const char *machine, pid_t *pid) {
6043 _cleanup_free_ char *s = NULL, *class = NULL;
6044 const char *p;
6045 pid_t leader;
6046 int r;
6047
6048 assert(machine);
6049 assert(pid);
6050
6051 p = strappenda("/run/systemd/machines/", machine);
6052 r = parse_env_file(p, NEWLINE, "LEADER", &s, "CLASS", &class, NULL);
6053 if (r == -ENOENT)
6054 return -EHOSTDOWN;
6055 if (r < 0)
6056 return r;
6057 if (!s)
6058 return -EIO;
6059
6060 if (!streq_ptr(class, "container"))
6061 return -EIO;
6062
6063 r = parse_pid(s, &leader);
6064 if (r < 0)
6065 return r;
6066 if (leader <= 1)
6067 return -EIO;
6068
6069 *pid = leader;
6070 return 0;
6071}
6072
a4475f57
LP
6073int namespace_open(pid_t pid, int *pidns_fd, int *mntns_fd, int *root_fd) {
6074 _cleanup_close_ int pidnsfd = -1, mntnsfd = -1;
6075 const char *pidns, *mntns, *root;
bc9fd78c
LP
6076 int rfd;
6077
6078 assert(pid >= 0);
a4475f57
LP
6079 assert(pidns_fd);
6080 assert(mntns_fd);
bc9fd78c
LP
6081 assert(root_fd);
6082
a4475f57
LP
6083 mntns = procfs_file_alloca(pid, "ns/mnt");
6084 mntnsfd = open(mntns, O_RDONLY|O_NOCTTY|O_CLOEXEC);
6085 if (mntnsfd < 0)
6086 return -errno;
6087
6088 pidns = procfs_file_alloca(pid, "ns/pid");
6089 pidnsfd = open(pidns, O_RDONLY|O_NOCTTY|O_CLOEXEC);
6090 if (pidnsfd < 0)
bc9fd78c
LP
6091 return -errno;
6092
6093 root = procfs_file_alloca(pid, "root");
6094 rfd = open(root, O_RDONLY|O_NOCTTY|O_CLOEXEC|O_DIRECTORY);
6095 if (rfd < 0)
6096 return -errno;
6097
a4475f57
LP
6098 *pidns_fd = pidnsfd;
6099 *mntns_fd = mntnsfd;
bc9fd78c 6100 *root_fd = rfd;
a4475f57
LP
6101 pidnsfd = -1;
6102 mntnsfd = -1;
bc9fd78c
LP
6103
6104 return 0;
6105}
6106
a4475f57
LP
6107int namespace_enter(int pidns_fd, int mntns_fd, int root_fd) {
6108 assert(pidns_fd >= 0);
6109 assert(mntns_fd >= 0);
bc9fd78c
LP
6110 assert(root_fd >= 0);
6111
a4475f57
LP
6112 if (setns(pidns_fd, CLONE_NEWPID) < 0)
6113 return -errno;
6114
6115 if (setns(mntns_fd, CLONE_NEWNS) < 0)
bc9fd78c
LP
6116 return -errno;
6117
6118 if (fchdir(root_fd) < 0)
6119 return -errno;
6120
6121 if (chroot(".") < 0)
6122 return -errno;
6123
5e2b3214
LP
6124 if (setresgid(0, 0, 0) < 0)
6125 return -errno;
6126
6127 if (setresuid(0, 0, 0) < 0)
6128 return -errno;
6129
bc9fd78c
LP
6130 return 0;
6131}
bf108e55 6132
9f5650ae
LP
6133bool pid_is_unwaited(pid_t pid) {
6134 /* Checks whether a PID is still valid at all, including a zombie */
6135
bf108e55
LP
6136 if (pid <= 0)
6137 return false;
6138
6139 if (kill(pid, 0) >= 0)
6140 return true;
6141
6142 return errno != ESRCH;
6143}
eff05270 6144
9f5650ae
LP
6145bool pid_is_alive(pid_t pid) {
6146 int r;
6147
6148 /* Checks whether a PID is still valid and not a zombie */
6149
6150 if (pid <= 0)
6151 return false;
6152
6153 r = get_process_state(pid);
6154 if (r == -ENOENT || r == 'Z')
6155 return false;
6156
6157 return true;
6158}
6159
eff05270
LP
6160int getpeercred(int fd, struct ucred *ucred) {
6161 socklen_t n = sizeof(struct ucred);
6162 struct ucred u;
6163 int r;
6164
6165 assert(fd >= 0);
6166 assert(ucred);
6167
6168 r = getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &u, &n);
6169 if (r < 0)
6170 return -errno;
6171
6172 if (n != sizeof(struct ucred))
6173 return -EIO;
6174
6175 /* Check if the data is actually useful and not suppressed due
6176 * to namespacing issues */
6177 if (u.pid <= 0)
6178 return -ENODATA;
6179
6180 *ucred = u;
6181 return 0;
6182}
6183
6184int getpeersec(int fd, char **ret) {
6185 socklen_t n = 64;
6186 char *s;
6187 int r;
6188
6189 assert(fd >= 0);
6190 assert(ret);
6191
6192 s = new0(char, n);
6193 if (!s)
6194 return -ENOMEM;
6195
6196 r = getsockopt(fd, SOL_SOCKET, SO_PEERSEC, s, &n);
6197 if (r < 0) {
6198 free(s);
6199
6200 if (errno != ERANGE)
6201 return -errno;
6202
6203 s = new0(char, n);
6204 if (!s)
6205 return -ENOMEM;
6206
6207 r = getsockopt(fd, SOL_SOCKET, SO_PEERSEC, s, &n);
6208 if (r < 0) {
6209 free(s);
6210 return -errno;
6211 }
6212 }
6213
ae98841e
LP
6214 if (isempty(s)) {
6215 free(s);
6216 return -ENOTSUP;
6217 }
6218
eff05270
LP
6219 *ret = s;
6220 return 0;
6221}
8e33886e 6222
0f010ef2 6223/* This is much like like mkostemp() but is subject to umask(). */
65b3903f 6224int mkostemp_safe(char *pattern, int flags) {
2d5bdf5b 6225 _cleanup_umask_ mode_t u;
0f010ef2 6226 int fd;
65b3903f 6227
d37a91e8 6228 assert(pattern);
65b3903f 6229
2d5bdf5b
LP
6230 u = umask(077);
6231
0f010ef2
ZJS
6232 fd = mkostemp(pattern, flags);
6233 if (fd < 0)
6234 return -errno;
65b3903f 6235
0f010ef2 6236 return fd;
65b3903f
ZJS
6237}
6238
8e33886e 6239int open_tmpfile(const char *path, int flags) {
8e33886e 6240 char *p;
a6afc4ae
LP
6241 int fd;
6242
6243 assert(path);
8e33886e
ZJS
6244
6245#ifdef O_TMPFILE
7736202c
LP
6246 /* Try O_TMPFILE first, if it is supported */
6247 fd = open(path, flags|O_TMPFILE, S_IRUSR|S_IWUSR);
8e33886e
ZJS
6248 if (fd >= 0)
6249 return fd;
6250#endif
7736202c
LP
6251
6252 /* Fall back to unguessable name + unlinking */
8e33886e
ZJS
6253 p = strappenda(path, "/systemd-tmp-XXXXXX");
6254
a6afc4ae 6255 fd = mkostemp_safe(p, flags);
8e33886e 6256 if (fd < 0)
65b3903f 6257 return fd;
8e33886e
ZJS
6258
6259 unlink(p);
6260 return fd;
6261}
fdb9161c
LP
6262
6263int fd_warn_permissions(const char *path, int fd) {
6264 struct stat st;
6265
6266 if (fstat(fd, &st) < 0)
6267 return -errno;
6268
6269 if (st.st_mode & 0111)
6270 log_warning("Configuration file %s is marked executable. Please remove executable permission bits. Proceeding anyway.", path);
6271
6272 if (st.st_mode & 0002)
6273 log_warning("Configuration file %s is marked world-writable. Please remove world writability permission bits. Proceeding anyway.", path);
6274
6275 if (getpid() == 1 && (st.st_mode & 0044) != 0044)
6276 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);
6277
6278 return 0;
6279}
6afc95b7 6280
ac45f971 6281unsigned long personality_from_string(const char *p) {
6afc95b7
LP
6282
6283 /* Parse a personality specifier. We introduce our own
6284 * identifiers that indicate specific ABIs, rather than just
6285 * hints regarding the register size, since we want to keep
6286 * things open for multiple locally supported ABIs for the
6287 * same register size. We try to reuse the ABI identifiers
6288 * used by libseccomp. */
6289
6290#if defined(__x86_64__)
6291
6292 if (streq(p, "x86"))
6293 return PER_LINUX32;
6294
6295 if (streq(p, "x86-64"))
6296 return PER_LINUX;
6297
6298#elif defined(__i386__)
6299
6300 if (streq(p, "x86"))
6301 return PER_LINUX;
6302#endif
6303
6304 /* personality(7) documents that 0xffffffffUL is used for
6305 * querying the current personality, hence let's use that here
6306 * as error indicator. */
6307 return 0xffffffffUL;
6308}
ac45f971
LP
6309
6310const char* personality_to_string(unsigned long p) {
6311
6312#if defined(__x86_64__)
6313
6314 if (p == PER_LINUX32)
6315 return "x86";
6316
6317 if (p == PER_LINUX)
6318 return "x86-64";
6319
6320#elif defined(__i386__)
6321
6322 if (p == PER_LINUX)
6323 return "x86";
6324#endif
6325
6326 return NULL;
6327}
1c231f56
LP
6328
6329uint64_t physical_memory(void) {
6330 long mem;
6331
6332 /* We return this as uint64_t in case we are running as 32bit
6333 * process on a 64bit kernel with huge amounts of memory */
6334
6335 mem = sysconf(_SC_PHYS_PAGES);
6336 assert(mem > 0);
6337
6338 return (uint64_t) mem * (uint64_t) page_size();
6339}
6db615c1
LP
6340
6341char* mount_test_option(const char *haystack, const char *needle) {
6342
6343 struct mntent me = {
6344 .mnt_opts = (char*) haystack
6345 };
6346
6347 assert(needle);
6348
6349 /* Like glibc's hasmntopt(), but works on a string, not a
6350 * struct mntent */
6351
6352 if (!haystack)
6353 return NULL;
6354
6355 return hasmntopt(&me, needle);
6356}
29bfbcd6
LP
6357
6358void hexdump(FILE *f, const void *p, size_t s) {
6359 const uint8_t *b = p;
6360 unsigned n = 0;
6361
6362 assert(s == 0 || b);
6363
6364 while (s > 0) {
6365 size_t i;
6366
6367 fprintf(f, "%04x ", n);
6368
6369 for (i = 0; i < 16; i++) {
6370
6371 if (i >= s)
6372 fputs(" ", f);
6373 else
6374 fprintf(f, "%02x ", b[i]);
6375
6376 if (i == 7)
6377 fputc(' ', f);
6378 }
6379
6380 fputc(' ', f);
6381
6382 for (i = 0; i < 16; i++) {
6383
6384 if (i >= s)
6385 fputc(' ', f);
6386 else
6387 fputc(isprint(b[i]) ? (char) b[i] : '.', f);
6388 }
6389
6390 fputc('\n', f);
6391
6392 if (s < 16)
6393 break;
6394
6395 n += 16;
6396 b += 16;
6397 s -= 16;
6398 }
6399}