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