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