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