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