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