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