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