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