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