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