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