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