]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/shared/util.c
strbuf: replace quick sort with bubble sort
[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
1876 if ((r = poll(&pollfd, 1, 0)) < 0) {
1877
1878 if (errno == EINTR)
1879 continue;
1880
1881 return -errno;
1882 }
1883
1884 if (r == 0)
1885 return 0;
1886
1887 if ((l = read(fd, buf, sizeof(buf))) < 0) {
1888
1889 if (errno == EINTR)
1890 continue;
1891
1892 if (errno == EAGAIN)
1893 return 0;
1894
1895 return -errno;
1896 }
1897
1898 if (l <= 0)
1899 return 0;
1900 }
1901}
1902
af6da548
LP
1903int acquire_terminal(
1904 const char *name,
1905 bool fail,
1906 bool force,
1907 bool ignore_tiocstty_eperm,
1908 usec_t timeout) {
1909
4a0ff478 1910 int fd = -1, notify = -1, r = 0, wd = -1;
af6da548 1911 usec_t ts = 0;
32c4bef8 1912 struct sigaction sa_old, sa_new;
80876c20
LP
1913
1914 assert(name);
1915
1916 /* We use inotify to be notified when the tty is closed. We
1917 * create the watch before checking if we can actually acquire
1918 * it, so that we don't lose any event.
1919 *
1920 * Note: strictly speaking this actually watches for the
1921 * device being closed, it does *not* really watch whether a
1922 * tty loses its controlling process. However, unless some
1923 * rogue process uses TIOCNOTTY on /dev/tty *after* closing
1924 * its tty otherwise this will not become a problem. As long
1925 * as the administrator makes sure not configure any service
1926 * on the same tty as an untrusted user this should not be a
1927 * problem. (Which he probably should not do anyway.) */
1928
af6da548
LP
1929 if (timeout != (usec_t) -1)
1930 ts = now(CLOCK_MONOTONIC);
1931
80876c20 1932 if (!fail && !force) {
af6da548
LP
1933 notify = inotify_init1(IN_CLOEXEC | (timeout != (usec_t) -1 ? IN_NONBLOCK : 0));
1934 if (notify < 0) {
80876c20
LP
1935 r = -errno;
1936 goto fail;
1937 }
1938
af6da548
LP
1939 wd = inotify_add_watch(notify, name, IN_CLOSE);
1940 if (wd < 0) {
80876c20
LP
1941 r = -errno;
1942 goto fail;
1943 }
1944 }
1945
1946 for (;;) {
af6da548
LP
1947 if (notify >= 0) {
1948 r = flush_fd(notify);
1949 if (r < 0)
e3d1855b 1950 goto fail;
af6da548 1951 }
80876c20
LP
1952
1953 /* We pass here O_NOCTTY only so that we can check the return
1954 * value TIOCSCTTY and have a reliable way to figure out if we
1955 * successfully became the controlling process of the tty */
af6da548
LP
1956 fd = open_terminal(name, O_RDWR|O_NOCTTY|O_CLOEXEC);
1957 if (fd < 0)
6ea832a2 1958 return fd;
80876c20 1959
32c4bef8
LP
1960 /* Temporarily ignore SIGHUP, so that we don't get SIGHUP'ed
1961 * if we already own the tty. */
1962 zero(sa_new);
1963 sa_new.sa_handler = SIG_IGN;
1964 sa_new.sa_flags = SA_RESTART;
1965 assert_se(sigaction(SIGHUP, &sa_new, &sa_old) == 0);
1966
80876c20 1967 /* First, try to get the tty */
32c4bef8
LP
1968 if (ioctl(fd, TIOCSCTTY, force) < 0)
1969 r = -errno;
1970
1971 assert_se(sigaction(SIGHUP, &sa_old, NULL) == 0);
21de3988
LP
1972
1973 /* Sometimes it makes sense to ignore TIOCSCTTY
1974 * returning EPERM, i.e. when very likely we already
1975 * are have this controlling terminal. */
32c4bef8 1976 if (r < 0 && r == -EPERM && ignore_tiocstty_eperm)
21de3988
LP
1977 r = 0;
1978
32c4bef8 1979 if (r < 0 && (force || fail || r != -EPERM)) {
80876c20
LP
1980 goto fail;
1981 }
1982
1983 if (r >= 0)
1984 break;
1985
1986 assert(!fail);
1987 assert(!force);
1988 assert(notify >= 0);
1989
1990 for (;;) {
f601daa7 1991 uint8_t inotify_buffer[sizeof(struct inotify_event) + FILENAME_MAX];
80876c20 1992 ssize_t l;
f601daa7 1993 struct inotify_event *e;
80876c20 1994
af6da548
LP
1995 if (timeout != (usec_t) -1) {
1996 usec_t n;
1997
1998 n = now(CLOCK_MONOTONIC);
1999 if (ts + timeout < n) {
2000 r = -ETIMEDOUT;
2001 goto fail;
2002 }
2003
2004 r = fd_wait_for_event(fd, POLLIN, ts + timeout - n);
2005 if (r < 0)
2006 goto fail;
2007
2008 if (r == 0) {
2009 r = -ETIMEDOUT;
2010 goto fail;
2011 }
2012 }
2013
2014 l = read(notify, inotify_buffer, sizeof(inotify_buffer));
2015 if (l < 0) {
80876c20 2016
af6da548 2017 if (errno == EINTR || errno == EAGAIN)
f601daa7
LP
2018 continue;
2019
2020 r = -errno;
2021 goto fail;
2022 }
2023
2024 e = (struct inotify_event*) inotify_buffer;
80876c20 2025
f601daa7
LP
2026 while (l > 0) {
2027 size_t step;
80876c20 2028
f601daa7 2029 if (e->wd != wd || !(e->mask & IN_CLOSE)) {
80876c20 2030 r = -EIO;
f601daa7
LP
2031 goto fail;
2032 }
80876c20 2033
f601daa7
LP
2034 step = sizeof(struct inotify_event) + e->len;
2035 assert(step <= (size_t) l);
80876c20 2036
f601daa7
LP
2037 e = (struct inotify_event*) ((uint8_t*) e + step);
2038 l -= step;
80876c20
LP
2039 }
2040
2041 break;
2042 }
2043
2044 /* We close the tty fd here since if the old session
2045 * ended our handle will be dead. It's important that
2046 * we do this after sleeping, so that we don't enter
2047 * an endless loop. */
2048 close_nointr_nofail(fd);
2049 }
2050
2051 if (notify >= 0)
a16e1123 2052 close_nointr_nofail(notify);
80876c20 2053
512947d4
MS
2054 r = reset_terminal_fd(fd, true);
2055 if (r < 0)
80876c20
LP
2056 log_warning("Failed to reset terminal: %s", strerror(-r));
2057
2058 return fd;
2059
2060fail:
2061 if (fd >= 0)
a16e1123 2062 close_nointr_nofail(fd);
80876c20
LP
2063
2064 if (notify >= 0)
a16e1123 2065 close_nointr_nofail(notify);
80876c20
LP
2066
2067 return r;
2068}
2069
2070int release_terminal(void) {
2071 int r = 0, fd;
57cd2192 2072 struct sigaction sa_old, sa_new;
80876c20 2073
ccaa6149 2074 if ((fd = open("/dev/tty", O_RDWR|O_NOCTTY|O_NDELAY|O_CLOEXEC)) < 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 close_nointr_nofail(fd);
2091 return r;
2092}
2093
9a34ec5f
LP
2094int sigaction_many(const struct sigaction *sa, ...) {
2095 va_list ap;
2096 int r = 0, sig;
2097
2098 va_start(ap, sa);
2099 while ((sig = va_arg(ap, int)) > 0)
2100 if (sigaction(sig, sa, NULL) < 0)
2101 r = -errno;
2102 va_end(ap);
2103
2104 return r;
2105}
2106
2107int ignore_signals(int sig, ...) {
a337c6fc 2108 struct sigaction sa;
9a34ec5f
LP
2109 va_list ap;
2110 int r = 0;
a337c6fc
LP
2111
2112 zero(sa);
2113 sa.sa_handler = SIG_IGN;
2114 sa.sa_flags = SA_RESTART;
2115
9a34ec5f
LP
2116 if (sigaction(sig, &sa, NULL) < 0)
2117 r = -errno;
2118
2119 va_start(ap, sig);
2120 while ((sig = va_arg(ap, int)) > 0)
2121 if (sigaction(sig, &sa, NULL) < 0)
2122 r = -errno;
2123 va_end(ap);
2124
2125 return r;
2126}
2127
2128int default_signals(int sig, ...) {
2129 struct sigaction sa;
2130 va_list ap;
2131 int r = 0;
2132
2133 zero(sa);
2134 sa.sa_handler = SIG_DFL;
2135 sa.sa_flags = SA_RESTART;
2136
2137 if (sigaction(sig, &sa, NULL) < 0)
2138 r = -errno;
2139
2140 va_start(ap, sig);
2141 while ((sig = va_arg(ap, int)) > 0)
2142 if (sigaction(sig, &sa, NULL) < 0)
2143 r = -errno;
2144 va_end(ap);
2145
2146 return r;
a337c6fc
LP
2147}
2148
8d567588
LP
2149int close_pipe(int p[]) {
2150 int a = 0, b = 0;
2151
2152 assert(p);
2153
2154 if (p[0] >= 0) {
2155 a = close_nointr(p[0]);
2156 p[0] = -1;
2157 }
2158
2159 if (p[1] >= 0) {
2160 b = close_nointr(p[1]);
2161 p[1] = -1;
2162 }
2163
2164 return a < 0 ? a : b;
2165}
2166
eb22ac37 2167ssize_t loop_read(int fd, void *buf, size_t nbytes, bool do_poll) {
8d567588
LP
2168 uint8_t *p;
2169 ssize_t n = 0;
2170
2171 assert(fd >= 0);
2172 assert(buf);
2173
2174 p = buf;
2175
2176 while (nbytes > 0) {
2177 ssize_t k;
2178
2179 if ((k = read(fd, p, nbytes)) <= 0) {
2180
eb22ac37 2181 if (k < 0 && errno == EINTR)
8d567588
LP
2182 continue;
2183
eb22ac37 2184 if (k < 0 && errno == EAGAIN && do_poll) {
8d567588
LP
2185 struct pollfd pollfd;
2186
2187 zero(pollfd);
2188 pollfd.fd = fd;
2189 pollfd.events = POLLIN;
2190
2191 if (poll(&pollfd, 1, -1) < 0) {
2192 if (errno == EINTR)
2193 continue;
2194
2195 return n > 0 ? n : -errno;
2196 }
2197
2198 if (pollfd.revents != POLLIN)
2199 return n > 0 ? n : -EIO;
2200
2201 continue;
2202 }
2203
2204 return n > 0 ? n : (k < 0 ? -errno : 0);
2205 }
2206
2207 p += k;
2208 nbytes -= k;
2209 n += k;
2210 }
2211
2212 return n;
2213}
2214
eb22ac37
LP
2215ssize_t loop_write(int fd, const void *buf, size_t nbytes, bool do_poll) {
2216 const uint8_t *p;
2217 ssize_t n = 0;
2218
2219 assert(fd >= 0);
2220 assert(buf);
2221
2222 p = buf;
2223
2224 while (nbytes > 0) {
2225 ssize_t k;
2226
fe652127
LP
2227 k = write(fd, p, nbytes);
2228 if (k <= 0) {
eb22ac37
LP
2229
2230 if (k < 0 && errno == EINTR)
2231 continue;
2232
2233 if (k < 0 && errno == EAGAIN && do_poll) {
2234 struct pollfd pollfd;
2235
2236 zero(pollfd);
2237 pollfd.fd = fd;
2238 pollfd.events = POLLOUT;
2239
2240 if (poll(&pollfd, 1, -1) < 0) {
2241 if (errno == EINTR)
2242 continue;
2243
2244 return n > 0 ? n : -errno;
2245 }
2246
2247 if (pollfd.revents != POLLOUT)
2248 return n > 0 ? n : -EIO;
2249
2250 continue;
2251 }
2252
2253 return n > 0 ? n : (k < 0 ? -errno : 0);
2254 }
2255
2256 p += k;
2257 nbytes -= k;
2258 n += k;
2259 }
2260
2261 return n;
2262}
2263
ab1f0633
LP
2264int parse_bytes(const char *t, off_t *bytes) {
2265 static const struct {
2266 const char *suffix;
2267 off_t factor;
2268 } table[] = {
2269 { "B", 1 },
2270 { "K", 1024ULL },
2271 { "M", 1024ULL*1024ULL },
2272 { "G", 1024ULL*1024ULL*1024ULL },
2273 { "T", 1024ULL*1024ULL*1024ULL*1024ULL },
32895bb3
LP
2274 { "P", 1024ULL*1024ULL*1024ULL*1024ULL*1024ULL },
2275 { "E", 1024ULL*1024ULL*1024ULL*1024ULL*1024ULL*1024ULL },
ab1f0633
LP
2276 { "", 1 },
2277 };
2278
2279 const char *p;
2280 off_t r = 0;
2281
2282 assert(t);
2283 assert(bytes);
2284
2285 p = t;
2286 do {
2287 long long l;
2288 char *e;
2289 unsigned i;
2290
2291 errno = 0;
2292 l = strtoll(p, &e, 10);
2293
8333c77e 2294 if (errno > 0)
ab1f0633
LP
2295 return -errno;
2296
2297 if (l < 0)
2298 return -ERANGE;
2299
2300 if (e == p)
2301 return -EINVAL;
2302
2303 e += strspn(e, WHITESPACE);
2304
2305 for (i = 0; i < ELEMENTSOF(table); i++)
2306 if (startswith(e, table[i].suffix)) {
2307 r += (off_t) l * table[i].factor;
2308 p = e + strlen(table[i].suffix);
2309 break;
2310 }
2311
2312 if (i >= ELEMENTSOF(table))
2313 return -EINVAL;
2314
2315 } while (*p != 0);
2316
2317 *bytes = r;
2318
2319 return 0;
2320}
2321
843d2643
LP
2322int make_stdio(int fd) {
2323 int r, s, t;
2324
2325 assert(fd >= 0);
2326
73836c5c
LP
2327 r = dup3(fd, STDIN_FILENO, 0);
2328 s = dup3(fd, STDOUT_FILENO, 0);
2329 t = dup3(fd, STDERR_FILENO, 0);
843d2643
LP
2330
2331 if (fd >= 3)
2332 close_nointr_nofail(fd);
2333
2334 if (r < 0 || s < 0 || t < 0)
2335 return -errno;
2336
73836c5c 2337 /* We rely here that the new fd has O_CLOEXEC not set */
7862f62d 2338
843d2643
LP
2339 return 0;
2340}
2341
ade509ce
LP
2342int make_null_stdio(void) {
2343 int null_fd;
2344
cd3bd60a
LP
2345 null_fd = open("/dev/null", O_RDWR|O_NOCTTY);
2346 if (null_fd < 0)
ade509ce
LP
2347 return -errno;
2348
2349 return make_stdio(null_fd);
2350}
2351
8407a5d0
LP
2352bool is_device_path(const char *path) {
2353
2354 /* Returns true on paths that refer to a device, either in
2355 * sysfs or in /dev */
2356
2357 return
2358 path_startswith(path, "/dev/") ||
2359 path_startswith(path, "/sys/");
2360}
2361
01f78473 2362int dir_is_empty(const char *path) {
a05f97b3 2363 _cleanup_closedir_ DIR *d;
01f78473 2364 int r;
01f78473 2365
a05f97b3
LP
2366 d = opendir(path);
2367 if (!d)
01f78473
LP
2368 return -errno;
2369
2370 for (;;) {
7d5e9c0f
LP
2371 struct dirent *de;
2372 union dirent_storage buf;
01f78473 2373
7d5e9c0f 2374 r = readdir_r(d, &buf.de, &de);
a05f97b3
LP
2375 if (r > 0)
2376 return -r;
01f78473 2377
a05f97b3
LP
2378 if (!de)
2379 return 1;
01f78473 2380
a05f97b3
LP
2381 if (!ignore_file(de->d_name))
2382 return 0;
2383 }
01f78473
LP
2384}
2385
844ec79b
ZJS
2386char* dirname_malloc(const char *path) {
2387 char *d, *dir, *dir2;
2388
2389 d = strdup(path);
2390 if (!d)
2391 return NULL;
2392 dir = dirname(d);
2393 assert(dir);
2394
2395 if (dir != d) {
2396 dir2 = strdup(dir);
2397 free(d);
2398 return dir2;
2399 }
2400
2401 return dir;
2402}
2403
d3782d60 2404unsigned long long random_ull(void) {
a05f97b3 2405 _cleanup_close_ int fd;
d3782d60
LP
2406 uint64_t ull;
2407 ssize_t r;
2408
ac0930c8
LP
2409 fd = open("/dev/urandom", O_RDONLY|O_CLOEXEC|O_NOCTTY);
2410 if (fd < 0)
d3782d60
LP
2411 goto fallback;
2412
eb22ac37 2413 r = loop_read(fd, &ull, sizeof(ull), true);
d3782d60
LP
2414 if (r != sizeof(ull))
2415 goto fallback;
2416
2417 return ull;
2418
2419fallback:
2420 return random() * RAND_MAX + random();
2421}
2422
5b6319dc
LP
2423void rename_process(const char name[8]) {
2424 assert(name);
2425
5d6b1584
LP
2426 /* This is a like a poor man's setproctitle(). It changes the
2427 * comm field, argv[0], and also the glibc's internally used
2428 * name of the process. For the first one a limit of 16 chars
2429 * applies, to the second one usually one of 10 (i.e. length
2430 * of "/sbin/init"), to the third one one of 7 (i.e. length of
2431 * "systemd"). If you pass a longer string it will be
2432 * truncated */
5b6319dc 2433
5d6b1584 2434 prctl(PR_SET_NAME, name);
5b6319dc
LP
2435
2436 if (program_invocation_name)
2437 strncpy(program_invocation_name, name, strlen(program_invocation_name));
9a0e6896
LP
2438
2439 if (saved_argc > 0) {
2440 int i;
2441
2442 if (saved_argv[0])
2443 strncpy(saved_argv[0], name, strlen(saved_argv[0]));
2444
2445 for (i = 1; i < saved_argc; i++) {
2446 if (!saved_argv[i])
2447 break;
2448
2449 memset(saved_argv[i], 0, strlen(saved_argv[i]));
2450 }
2451 }
5b6319dc
LP
2452}
2453
7d793605
LP
2454void sigset_add_many(sigset_t *ss, ...) {
2455 va_list ap;
2456 int sig;
2457
2458 assert(ss);
2459
2460 va_start(ap, ss);
2461 while ((sig = va_arg(ap, int)) > 0)
2462 assert_se(sigaddset(ss, sig) == 0);
2463 va_end(ap);
2464}
2465
ef2f1067
LP
2466char* gethostname_malloc(void) {
2467 struct utsname u;
2468
2469 assert_se(uname(&u) >= 0);
2470
344de609 2471 if (!isempty(u.nodename) && !streq(u.nodename, "(none)"))
ef2f1067
LP
2472 return strdup(u.nodename);
2473
2474 return strdup(u.sysname);
2475}
2476
344de609
LP
2477bool hostname_is_set(void) {
2478 struct utsname u;
2479
2480 assert_se(uname(&u) >= 0);
2481
2482 return !isempty(u.nodename) && !streq(u.nodename, "(none)");
2483}
2484
7c5f152a 2485static char *lookup_uid(uid_t uid) {
ef2f1067 2486 long bufsize;
a05f97b3
LP
2487 char *name;
2488 _cleanup_free_ char *buf = NULL;
ef2f1067 2489 struct passwd pwbuf, *pw = NULL;
ef2f1067
LP
2490
2491 /* Shortcut things to avoid NSS lookups */
2492 if (uid == 0)
2493 return strdup("root");
2494
7c5f152a
LP
2495 bufsize = sysconf(_SC_GETPW_R_SIZE_MAX);
2496 if (bufsize <= 0)
ef2f1067
LP
2497 bufsize = 4096;
2498
7c5f152a
LP
2499 buf = malloc(bufsize);
2500 if (!buf)
ef2f1067
LP
2501 return NULL;
2502
a05f97b3
LP
2503 if (getpwuid_r(uid, &pwbuf, buf, bufsize, &pw) == 0 && pw)
2504 return strdup(pw->pw_name);
ef2f1067
LP
2505
2506 if (asprintf(&name, "%lu", (unsigned long) uid) < 0)
2507 return NULL;
2508
2509 return name;
2510}
2511
7c5f152a
LP
2512char* getlogname_malloc(void) {
2513 uid_t uid;
2514 struct stat st;
2515
2516 if (isatty(STDIN_FILENO) && fstat(STDIN_FILENO, &st) >= 0)
2517 uid = st.st_uid;
2518 else
2519 uid = getuid();
2520
2521 return lookup_uid(uid);
2522}
2523
2524char *getusername_malloc(void) {
2525 const char *e;
2526
2527 e = getenv("USER");
2528 if (e)
2529 return strdup(e);
2530
2531 return lookup_uid(getuid());
2532}
2533
fc116c6a
LP
2534int getttyname_malloc(int fd, char **r) {
2535 char path[PATH_MAX], *c;
618e02c7 2536 int k;
8c6db833
LP
2537
2538 assert(r);
ef2f1067 2539
a05f97b3
LP
2540 k = ttyname_r(fd, path, sizeof(path));
2541 if (k != 0)
618e02c7 2542 return -k;
ef2f1067
LP
2543
2544 char_array_0(path);
2545
a05f97b3
LP
2546 c = strdup(startswith(path, "/dev/") ? path + 5 : path);
2547 if (!c)
8c6db833
LP
2548 return -ENOMEM;
2549
2550 *r = c;
2551 return 0;
2552}
2553
fc116c6a
LP
2554int getttyname_harder(int fd, char **r) {
2555 int k;
2556 char *s;
2557
a05f97b3
LP
2558 k = getttyname_malloc(fd, &s);
2559 if (k < 0)
fc116c6a
LP
2560 return k;
2561
2562 if (streq(s, "tty")) {
2563 free(s);
4d6d6518 2564 return get_ctty(0, NULL, r);
fc116c6a
LP
2565 }
2566
2567 *r = s;
2568 return 0;
2569}
2570
4d6d6518 2571int get_ctty_devnr(pid_t pid, dev_t *d) {
fc116c6a 2572 int k;
4d6d6518 2573 char line[LINE_MAX], *p, *fn;
fc116c6a
LP
2574 unsigned long ttynr;
2575 FILE *f;
2576
4d6d6518
LP
2577 if (asprintf(&fn, "/proc/%lu/stat", (unsigned long) (pid <= 0 ? getpid() : pid)) < 0)
2578 return -ENOMEM;
2579
2580 f = fopen(fn, "re");
2581 free(fn);
2582 if (!f)
fc116c6a
LP
2583 return -errno;
2584
4d6d6518 2585 if (!fgets(line, sizeof(line), f)) {
35d50f55 2586 k = feof(f) ? -EIO : -errno;
fc116c6a
LP
2587 fclose(f);
2588 return k;
2589 }
2590
2591 fclose(f);
2592
4d6d6518
LP
2593 p = strrchr(line, ')');
2594 if (!p)
fc116c6a
LP
2595 return -EIO;
2596
2597 p++;
2598
2599 if (sscanf(p, " "
2600 "%*c " /* state */
2601 "%*d " /* ppid */
2602 "%*d " /* pgrp */
2603 "%*d " /* session */
2604 "%lu ", /* ttynr */
2605 &ttynr) != 1)
2606 return -EIO;
2607
11dc5d2b
LP
2608 if (major(ttynr) == 0 && minor(ttynr) == 0)
2609 return -ENOENT;
2610
fc116c6a
LP
2611 *d = (dev_t) ttynr;
2612 return 0;
2613}
2614
4d6d6518 2615int get_ctty(pid_t pid, dev_t *_devnr, char **r) {
fc116c6a 2616 int k;
20c03b7b 2617 char fn[PATH_MAX], *s, *b, *p;
fc116c6a
LP
2618 dev_t devnr;
2619
2620 assert(r);
2621
4d6d6518
LP
2622 k = get_ctty_devnr(pid, &devnr);
2623 if (k < 0)
fc116c6a
LP
2624 return k;
2625
2626 snprintf(fn, sizeof(fn), "/dev/char/%u:%u", major(devnr), minor(devnr));
2627 char_array_0(fn);
2628
23406ce5
LP
2629 k = readlink_malloc(fn, &s);
2630 if (k < 0) {
fc116c6a
LP
2631
2632 if (k != -ENOENT)
2633 return k;
2634
46824d0e
LP
2635 /* This is an ugly hack */
2636 if (major(devnr) == 136) {
2637 if (asprintf(&b, "pts/%lu", (unsigned long) minor(devnr)) < 0)
2638 return -ENOMEM;
2639
2640 *r = b;
2641 if (_devnr)
2642 *_devnr = devnr;
2643
2644 return 0;
2645 }
2646
fc116c6a
LP
2647 /* Probably something like the ptys which have no
2648 * symlink in /dev/char. Let's return something
2649 * vaguely useful. */
2650
23406ce5
LP
2651 b = strdup(fn + 5);
2652 if (!b)
fc116c6a
LP
2653 return -ENOMEM;
2654
2655 *r = b;
46824d0e
LP
2656 if (_devnr)
2657 *_devnr = devnr;
2658
fc116c6a
LP
2659 return 0;
2660 }
2661
2662 if (startswith(s, "/dev/"))
2663 p = s + 5;
2664 else if (startswith(s, "../"))
2665 p = s + 3;
2666 else
2667 p = s;
2668
2669 b = strdup(p);
2670 free(s);
2671
2672 if (!b)
2673 return -ENOMEM;
2674
2675 *r = b;
46824d0e
LP
2676 if (_devnr)
2677 *_devnr = devnr;
2678
fc116c6a
LP
2679 return 0;
2680}
2681
f56d5db9 2682int rm_rf_children_dangerous(int fd, bool only_dirs, bool honour_sticky, struct stat *root_dev) {
8c6db833
LP
2683 DIR *d;
2684 int ret = 0;
2685
2686 assert(fd >= 0);
2687
2688 /* This returns the first error we run into, but nevertheless
7925c22a 2689 * tries to go on. This closes the passed fd. */
8c6db833 2690
d4d046e3
LP
2691 d = fdopendir(fd);
2692 if (!d) {
8c6db833 2693 close_nointr_nofail(fd);
4c633005
LP
2694
2695 return errno == ENOENT ? 0 : -errno;
8c6db833
LP
2696 }
2697
2698 for (;;) {
7d5e9c0f
LP
2699 struct dirent *de;
2700 union dirent_storage buf;
7925c22a
LP
2701 bool is_dir, keep_around;
2702 struct stat st;
8c6db833
LP
2703 int r;
2704
7d5e9c0f 2705 r = readdir_r(d, &buf.de, &de);
d4d046e3
LP
2706 if (r != 0 && ret == 0) {
2707 ret = -r;
8c6db833
LP
2708 break;
2709 }
2710
2711 if (!de)
2712 break;
2713
2714 if (streq(de->d_name, ".") || streq(de->d_name, ".."))
2715 continue;
2716
7925c22a
LP
2717 if (de->d_type == DT_UNKNOWN ||
2718 honour_sticky ||
2719 (de->d_type == DT_DIR && root_dev)) {
8c6db833 2720 if (fstatat(fd, de->d_name, &st, AT_SYMLINK_NOFOLLOW) < 0) {
4c633005 2721 if (ret == 0 && errno != ENOENT)
8c6db833
LP
2722 ret = -errno;
2723 continue;
2724 }
2725
2726 is_dir = S_ISDIR(st.st_mode);
7925c22a
LP
2727 keep_around =
2728 honour_sticky &&
2729 (st.st_uid == 0 || st.st_uid == getuid()) &&
2730 (st.st_mode & S_ISVTX);
ad293f5a 2731 } else {
8c6db833 2732 is_dir = de->d_type == DT_DIR;
7925c22a 2733 keep_around = false;
ad293f5a 2734 }
8c6db833
LP
2735
2736 if (is_dir) {
2737 int subdir_fd;
8c6db833 2738
597f43c7 2739 /* if root_dev is set, remove subdirectories only, if device is same as dir */
7925c22a
LP
2740 if (root_dev && st.st_dev != root_dev->st_dev)
2741 continue;
8c6db833 2742
7925c22a
LP
2743 subdir_fd = openat(fd, de->d_name,
2744 O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW|O_NOATIME);
2745 if (subdir_fd < 0) {
2746 if (ret == 0 && errno != ENOENT)
2747 ret = -errno;
2748 continue;
2749 }
2750
b3d28469 2751 r = rm_rf_children_dangerous(subdir_fd, only_dirs, honour_sticky, root_dev);
7925c22a
LP
2752 if (r < 0 && ret == 0)
2753 ret = r;
2754
2755 if (!keep_around)
2756 if (unlinkat(fd, de->d_name, AT_REMOVEDIR) < 0) {
ad293f5a
LP
2757 if (ret == 0 && errno != ENOENT)
2758 ret = -errno;
2759 }
2760
2761 } else if (!only_dirs && !keep_around) {
8c6db833
LP
2762
2763 if (unlinkat(fd, de->d_name, 0) < 0) {
4c633005 2764 if (ret == 0 && errno != ENOENT)
8c6db833
LP
2765 ret = -errno;
2766 }
2767 }
2768 }
2769
2770 closedir(d);
2771
2772 return ret;
2773}
2774
943aad8c
ZJS
2775static int is_temporary_fs(struct statfs *s) {
2776 assert(s);
2777 return s->f_type == TMPFS_MAGIC ||
2778 (long)s->f_type == (long)RAMFS_MAGIC;
2779}
2780
f56d5db9
LP
2781int rm_rf_children(int fd, bool only_dirs, bool honour_sticky, struct stat *root_dev) {
2782 struct statfs s;
2783
2784 assert(fd >= 0);
2785
2786 if (fstatfs(fd, &s) < 0) {
2787 close_nointr_nofail(fd);
2788 return -errno;
2789 }
2790
2791 /* We refuse to clean disk file systems with this call. This
2792 * is extra paranoia just to be sure we never ever remove
2793 * non-state data */
943aad8c 2794 if (!is_temporary_fs(&s)) {
f56d5db9
LP
2795 log_error("Attempted to remove disk file system, and we can't allow that.");
2796 close_nointr_nofail(fd);
2797 return -EPERM;
2798 }
2799
2800 return rm_rf_children_dangerous(fd, only_dirs, honour_sticky, root_dev);
2801}
2802
2803static int rm_rf_internal(const char *path, bool only_dirs, bool delete_root, bool honour_sticky, bool dangerous) {
2804 int fd, r;
2805 struct statfs s;
8c6db833
LP
2806
2807 assert(path);
2808
f56d5db9
LP
2809 /* We refuse to clean the root file system with this
2810 * call. This is extra paranoia to never cause a really
2811 * seriously broken system. */
2812 if (path_equal(path, "/")) {
2813 log_error("Attempted to remove entire root file system, and we can't allow that.");
2814 return -EPERM;
2815 }
461b1822 2816
d4d046e3
LP
2817 fd = open(path, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW|O_NOATIME);
2818 if (fd < 0) {
8c6db833
LP
2819
2820 if (errno != ENOTDIR)
2821 return -errno;
2822
f56d5db9
LP
2823 if (!dangerous) {
2824 if (statfs(path, &s) < 0)
2825 return -errno;
2826
943aad8c 2827 if (!is_temporary_fs(&s)) {
f56d5db9
LP
2828 log_error("Attempted to remove disk file system, and we can't allow that.");
2829 return -EPERM;
2830 }
2831 }
2832
8c6db833 2833 if (delete_root && !only_dirs)
d4d046e3 2834 if (unlink(path) < 0 && errno != ENOENT)
8c6db833
LP
2835 return -errno;
2836
2837 return 0;
2838 }
2839
f56d5db9
LP
2840 if (!dangerous) {
2841 if (fstatfs(fd, &s) < 0) {
2842 close_nointr_nofail(fd);
2843 return -errno;
2844 }
ad293f5a 2845
943aad8c 2846 if (!is_temporary_fs(&s)) {
f56d5db9
LP
2847 log_error("Attempted to remove disk file system, and we can't allow that.");
2848 close_nointr_nofail(fd);
2849 return -EPERM;
2850 }
2851 }
2852
2853 r = rm_rf_children_dangerous(fd, only_dirs, honour_sticky, NULL);
ad293f5a
LP
2854 if (delete_root) {
2855
8d53b453 2856 if (honour_sticky && file_is_priv_sticky(path) > 0)
ad293f5a 2857 return r;
8c6db833 2858
e27796a0 2859 if (rmdir(path) < 0 && errno != ENOENT) {
8c6db833
LP
2860 if (r == 0)
2861 r = -errno;
2862 }
ad293f5a 2863 }
8c6db833
LP
2864
2865 return r;
2866}
2867
f56d5db9
LP
2868int rm_rf(const char *path, bool only_dirs, bool delete_root, bool honour_sticky) {
2869 return rm_rf_internal(path, only_dirs, delete_root, honour_sticky, false);
2870}
2871
2872int rm_rf_dangerous(const char *path, bool only_dirs, bool delete_root, bool honour_sticky) {
2873 return rm_rf_internal(path, only_dirs, delete_root, honour_sticky, true);
2874}
2875
8c6db833
LP
2876int chmod_and_chown(const char *path, mode_t mode, uid_t uid, gid_t gid) {
2877 assert(path);
2878
2879 /* Under the assumption that we are running privileged we
2880 * first change the access mode and only then hand out
2881 * ownership to avoid a window where access is too open. */
2882
8d53b453
LP
2883 if (mode != (mode_t) -1)
2884 if (chmod(path, mode) < 0)
2885 return -errno;
8c6db833 2886
8d53b453
LP
2887 if (uid != (uid_t) -1 || gid != (gid_t) -1)
2888 if (chown(path, uid, gid) < 0)
2889 return -errno;
8c6db833
LP
2890
2891 return 0;
ef2f1067
LP
2892}
2893
f4b47811
LP
2894int fchmod_and_fchown(int fd, mode_t mode, uid_t uid, gid_t gid) {
2895 assert(fd >= 0);
2896
2897 /* Under the assumption that we are running privileged we
2898 * first change the access mode and only then hand out
2899 * ownership to avoid a window where access is too open. */
2900
2901 if (fchmod(fd, mode) < 0)
2902 return -errno;
2903
2904 if (fchown(fd, uid, gid) < 0)
2905 return -errno;
2906
2907 return 0;
2908}
2909
82c121a4
LP
2910cpu_set_t* cpu_set_malloc(unsigned *ncpus) {
2911 cpu_set_t *r;
2912 unsigned n = 1024;
2913
2914 /* Allocates the cpuset in the right size */
2915
2916 for (;;) {
2917 if (!(r = CPU_ALLOC(n)))
2918 return NULL;
2919
2920 if (sched_getaffinity(0, CPU_ALLOC_SIZE(n), r) >= 0) {
2921 CPU_ZERO_S(CPU_ALLOC_SIZE(n), r);
2922
2923 if (ncpus)
2924 *ncpus = n;
2925
2926 return r;
2927 }
2928
2929 CPU_FREE(r);
2930
2931 if (errno != EINVAL)
2932 return NULL;
2933
2934 n *= 2;
2935 }
2936}
2937
984a2be4 2938int status_vprintf(const char *status, bool ellipse, bool ephemeral, const char *format, va_list ap) {
9ab7a8d2 2939 static const char status_indent[] = " "; /* "[" STATUS "] " */
669bec5d
LP
2940 _cleanup_free_ char *s = NULL;
2941 _cleanup_close_ int fd = -1;
984a2be4 2942 struct iovec iovec[6];
81beb750 2943 int n = 0;
984a2be4 2944 static bool prev_ephemeral;
9e58ff9c
LP
2945
2946 assert(format);
2947
9ab7a8d2 2948 /* This is independent of logging, as status messages are
9e58ff9c
LP
2949 * optional and go exclusively to the console. */
2950
2951 if (vasprintf(&s, format, ap) < 0)
669bec5d 2952 return log_oom();
9e58ff9c 2953
67e5cc4f 2954 fd = open_terminal("/dev/console", O_WRONLY|O_NOCTTY|O_CLOEXEC);
81beb750 2955 if (fd < 0)
669bec5d 2956 return fd;
9e58ff9c 2957
67e5cc4f 2958 if (ellipse) {
9ab7a8d2
MS
2959 char *e;
2960 size_t emax, sl;
2961 int c;
2962
67e5cc4f
LP
2963 c = fd_columns(fd);
2964 if (c <= 0)
2965 c = 80;
81beb750 2966
669bec5d 2967 sl = status ? sizeof(status_indent)-1 : 0;
9ab7a8d2
MS
2968
2969 emax = c - sl - 1;
2970 if (emax < 3)
2971 emax = 3;
81beb750 2972
67e5cc4f
LP
2973 e = ellipsize(s, emax, 75);
2974 if (e) {
2975 free(s);
2976 s = e;
2977 }
81beb750
LP
2978 }
2979
2980 zero(iovec);
81beb750 2981
984a2be4
MS
2982 if (prev_ephemeral)
2983 IOVEC_SET_STRING(iovec[n++], "\r" ANSI_ERASE_TO_END_OF_LINE);
2984 prev_ephemeral = ephemeral;
2985
9ab7a8d2
MS
2986 if (status) {
2987 if (!isempty(status)) {
2988 IOVEC_SET_STRING(iovec[n++], "[");
2989 IOVEC_SET_STRING(iovec[n++], status);
2990 IOVEC_SET_STRING(iovec[n++], "] ");
2991 } else
2992 IOVEC_SET_STRING(iovec[n++], status_indent);
81beb750
LP
2993 }
2994
9ab7a8d2 2995 IOVEC_SET_STRING(iovec[n++], s);
984a2be4
MS
2996 if (!ephemeral)
2997 IOVEC_SET_STRING(iovec[n++], "\n");
81beb750 2998
669bec5d
LP
2999 if (writev(fd, iovec, n) < 0)
3000 return -errno;
9e58ff9c 3001
669bec5d 3002 return 0;
9e58ff9c
LP
3003}
3004
984a2be4 3005int status_printf(const char *status, bool ellipse, bool ephemeral, const char *format, ...) {
c846ff47 3006 va_list ap;
669bec5d 3007 int r;
c846ff47
LP
3008
3009 assert(format);
3010
3011 va_start(ap, format);
984a2be4 3012 r = status_vprintf(status, ellipse, ephemeral, format, ap);
c846ff47 3013 va_end(ap);
669bec5d
LP
3014
3015 return r;
c846ff47
LP
3016}
3017
669bec5d 3018int status_welcome(void) {
10aa7034 3019 int r;
669bec5d
LP
3020 _cleanup_free_ char *pretty_name = NULL, *ansi_color = NULL;
3021
3022 r = parse_env_file("/etc/os-release", NEWLINE,
3023 "PRETTY_NAME", &pretty_name,
3024 "ANSI_COLOR", &ansi_color,
3025 NULL);
3026 if (r < 0 && r != -ENOENT)
3027 log_warning("Failed to read /etc/os-release: %s", strerror(-r));
3028
f620dff8 3029 return status_printf(NULL, false, false,
669bec5d
LP
3030 "\nWelcome to \x1B[%sm%s\x1B[0m!\n",
3031 isempty(ansi_color) ? "1" : ansi_color,
3032 isempty(pretty_name) ? "Linux" : pretty_name);
c846ff47
LP
3033}
3034
fab56fc5
LP
3035char *replace_env(const char *format, char **env) {
3036 enum {
3037 WORD,
c24eb49e 3038 CURLY,
fab56fc5
LP
3039 VARIABLE
3040 } state = WORD;
3041
3042 const char *e, *word = format;
3043 char *r = NULL, *k;
3044
3045 assert(format);
3046
3047 for (e = format; *e; e ++) {
3048
3049 switch (state) {
3050
3051 case WORD:
3052 if (*e == '$')
c24eb49e 3053 state = CURLY;
fab56fc5
LP
3054 break;
3055
c24eb49e
LP
3056 case CURLY:
3057 if (*e == '{') {
fab56fc5
LP
3058 if (!(k = strnappend(r, word, e-word-1)))
3059 goto fail;
3060
3061 free(r);
3062 r = k;
3063
3064 word = e-1;
3065 state = VARIABLE;
3066
3067 } else if (*e == '$') {
3068 if (!(k = strnappend(r, word, e-word)))
3069 goto fail;
3070
3071 free(r);
3072 r = k;
3073
3074 word = e+1;
3075 state = WORD;
3076 } else
3077 state = WORD;
3078 break;
3079
3080 case VARIABLE:
c24eb49e 3081 if (*e == '}') {
b95cf362 3082 const char *t;
fab56fc5 3083
4d1a6904 3084 t = strempty(strv_env_get_n(env, word+2, e-word-2));
fab56fc5 3085
4d1a6904
LP
3086 k = strappend(r, t);
3087 if (!k)
b95cf362 3088 goto fail;
fab56fc5 3089
b95cf362
LP
3090 free(r);
3091 r = k;
fab56fc5 3092
b95cf362 3093 word = e+1;
fab56fc5
LP
3094 state = WORD;
3095 }
3096 break;
3097 }
3098 }
3099
3100 if (!(k = strnappend(r, word, e-word)))
3101 goto fail;
3102
3103 free(r);
3104 return k;
3105
3106fail:
3107 free(r);
3108 return NULL;
3109}
3110
3111char **replace_env_argv(char **argv, char **env) {
3112 char **r, **i;
c24eb49e
LP
3113 unsigned k = 0, l = 0;
3114
3115 l = strv_length(argv);
fab56fc5 3116
c24eb49e 3117 if (!(r = new(char*, l+1)))
fab56fc5
LP
3118 return NULL;
3119
3120 STRV_FOREACH(i, argv) {
c24eb49e
LP
3121
3122 /* If $FOO appears as single word, replace it by the split up variable */
b95cf362
LP
3123 if ((*i)[0] == '$' && (*i)[1] != '{') {
3124 char *e;
3125 char **w, **m;
3126 unsigned q;
c24eb49e 3127
4d1a6904
LP
3128 e = strv_env_get(env, *i+1);
3129 if (e) {
c24eb49e
LP
3130
3131 if (!(m = strv_split_quoted(e))) {
3132 r[k] = NULL;
3133 strv_free(r);
3134 return NULL;
3135 }
b95cf362
LP
3136 } else
3137 m = NULL;
c24eb49e 3138
b95cf362
LP
3139 q = strv_length(m);
3140 l = l + q - 1;
c24eb49e 3141
b95cf362
LP
3142 if (!(w = realloc(r, sizeof(char*) * (l+1)))) {
3143 r[k] = NULL;
3144 strv_free(r);
3145 strv_free(m);
3146 return NULL;
3147 }
c24eb49e 3148
b95cf362
LP
3149 r = w;
3150 if (m) {
c24eb49e
LP
3151 memcpy(r + k, m, q * sizeof(char*));
3152 free(m);
c24eb49e 3153 }
b95cf362
LP
3154
3155 k += q;
3156 continue;
c24eb49e
LP
3157 }
3158
3159 /* If ${FOO} appears as part of a word, replace it by the variable as-is */
fab56fc5
LP
3160 if (!(r[k++] = replace_env(*i, env))) {
3161 strv_free(r);
3162 return NULL;
3163 }
3164 }
3165
3166 r[k] = NULL;
3167 return r;
3168}
3169
81beb750
LP
3170int fd_columns(int fd) {
3171 struct winsize ws;
3172 zero(ws);
3173
3174 if (ioctl(fd, TIOCGWINSZ, &ws) < 0)
3175 return -errno;
3176
3177 if (ws.ws_col <= 0)
3178 return -EIO;
3179
3180 return ws.ws_col;
3181}
3182
28917d7d 3183unsigned columns(void) {
fa776d8e 3184 const char *e;
7009eec2 3185 int c;
fa776d8e 3186
28917d7d
LP
3187 if (_likely_(cached_columns > 0))
3188 return cached_columns;
11f96fac 3189
28917d7d
LP
3190 c = 0;
3191 e = getenv("COLUMNS");
3192 if (e)
7009eec2 3193 safe_atoi(e, &c);
fa776d8e 3194
28917d7d
LP
3195 if (c <= 0)
3196 c = fd_columns(STDOUT_FILENO);
fa776d8e 3197
28917d7d
LP
3198 if (c <= 0)
3199 c = 80;
11f96fac 3200
28917d7d
LP
3201 cached_columns = c;
3202 return c;
11f96fac
ZJS
3203}
3204
8f2d43a0
LP
3205int fd_lines(int fd) {
3206 struct winsize ws;
3207 zero(ws);
3208
3209 if (ioctl(fd, TIOCGWINSZ, &ws) < 0)
3210 return -errno;
3211
3212 if (ws.ws_row <= 0)
3213 return -EIO;
3214
3215 return ws.ws_row;
3216}
3217
3218unsigned lines(void) {
8f2d43a0 3219 const char *e;
ed757c0c 3220 unsigned l;
8f2d43a0 3221
ed757c0c
LP
3222 if (_likely_(cached_lines > 0))
3223 return cached_lines;
8f2d43a0 3224
ed757c0c 3225 l = 0;
8f2d43a0
LP
3226 e = getenv("LINES");
3227 if (e)
ed757c0c 3228 safe_atou(e, &l);
8f2d43a0 3229
ed757c0c
LP
3230 if (l <= 0)
3231 l = fd_lines(STDOUT_FILENO);
8f2d43a0 3232
ed757c0c
LP
3233 if (l <= 0)
3234 l = 24;
8f2d43a0 3235
ed757c0c
LP
3236 cached_lines = l;
3237 return cached_lines;
3238}
3239
3240/* intended to be used as a SIGWINCH sighandler */
3241void columns_lines_cache_reset(int signum) {
3242 cached_columns = 0;
3243 cached_lines = 0;
3244}
3245
3246bool on_tty(void) {
3247 static int cached_on_tty = -1;
3248
3249 if (_unlikely_(cached_on_tty < 0))
3250 cached_on_tty = isatty(STDOUT_FILENO) > 0;
3251
3252 return cached_on_tty;
8f2d43a0
LP
3253}
3254
b4f10a5e
LP
3255int running_in_chroot(void) {
3256 struct stat a, b;
3257
3258 zero(a);
3259 zero(b);
3260
3261 /* Only works as root */
3262
3263 if (stat("/proc/1/root", &a) < 0)
3264 return -errno;
3265
3266 if (stat("/", &b) < 0)
3267 return -errno;
3268
3269 return
3270 a.st_dev != b.st_dev ||
3271 a.st_ino != b.st_ino;
3272}
3273
72f59706
LP
3274char *ellipsize_mem(const char *s, size_t old_length, size_t new_length, unsigned percent) {
3275 size_t x;
8fe914ec
LP
3276 char *r;
3277
3278 assert(s);
3279 assert(percent <= 100);
72f59706 3280 assert(new_length >= 3);
8fe914ec 3281
72f59706
LP
3282 if (old_length <= 3 || old_length <= new_length)
3283 return strndup(s, old_length);
8fe914ec 3284
72f59706
LP
3285 r = new0(char, new_length+1);
3286 if (!r)
8fe914ec
LP
3287 return r;
3288
72f59706 3289 x = (new_length * percent) / 100;
8fe914ec 3290
72f59706
LP
3291 if (x > new_length - 3)
3292 x = new_length - 3;
8fe914ec
LP
3293
3294 memcpy(r, s, x);
3295 r[x] = '.';
3296 r[x+1] = '.';
3297 r[x+2] = '.';
3298 memcpy(r + x + 3,
72f59706
LP
3299 s + old_length - (new_length - x - 3),
3300 new_length - x - 3);
8fe914ec
LP
3301
3302 return r;
3303}
3304
72f59706
LP
3305char *ellipsize(const char *s, size_t length, unsigned percent) {
3306 return ellipsize_mem(s, strlen(s), length, percent);
3307}
3308
f6144808
LP
3309int touch(const char *path) {
3310 int fd;
3311
3312 assert(path);
3313
73836c5c
LP
3314 /* This just opens the file for writing, ensuring it
3315 * exists. It doesn't call utimensat() the way /usr/bin/touch
3316 * does it. */
3317
3318 fd = open(path, O_WRONLY|O_CREAT|O_CLOEXEC|O_NOCTTY, 0644);
3319 if (fd < 0)
f6144808
LP
3320 return -errno;
3321
3322 close_nointr_nofail(fd);
3323 return 0;
3324}
afea26ad 3325
97c4a07d 3326char *unquote(const char *s, const char* quotes) {
11ce3427
LP
3327 size_t l;
3328 assert(s);
3329
73836c5c
LP
3330 /* This is rather stupid, simply removes the heading and
3331 * trailing quotes if there is one. Doesn't care about
57f30678
LP
3332 * escaping or anything. We should make this smarter one
3333 * day...*/
73836c5c 3334
31ed59c5
LP
3335 l = strlen(s);
3336 if (l < 2)
11ce3427
LP
3337 return strdup(s);
3338
97c4a07d 3339 if (strchr(quotes, s[0]) && s[l-1] == s[0])
11ce3427
LP
3340 return strndup(s+1, l-2);
3341
3342 return strdup(s);
3343}
3344
5f7c426e 3345char *normalize_env_assignment(const char *s) {
57f30678
LP
3346 _cleanup_free_ char *name = NULL, *value = NULL, *p = NULL;
3347 char *eq, *r;
5f7c426e 3348
57f30678
LP
3349 eq = strchr(s, '=');
3350 if (!eq) {
3351 char *t;
5f7c426e 3352
57f30678
LP
3353 r = strdup(s);
3354 if (!r)
5f7c426e
LP
3355 return NULL;
3356
57f30678
LP
3357 t = strstrip(r);
3358 if (t == r)
3359 return r;
3360
3361 memmove(r, t, strlen(t) + 1);
3362 return r;
5f7c426e
LP
3363 }
3364
57f30678
LP
3365 name = strndup(s, eq - s);
3366 if (!name)
5f7c426e
LP
3367 return NULL;
3368
57f30678
LP
3369 p = strdup(eq + 1);
3370 if (!p)
5f7c426e 3371 return NULL;
5f7c426e
LP
3372
3373 value = unquote(strstrip(p), QUOTES);
57f30678 3374 if (!value)
5f7c426e 3375 return NULL;
5f7c426e 3376
57f30678 3377 if (asprintf(&r, "%s=%s", strstrip(name), value) < 0)
5f7c426e
LP
3378 r = NULL;
3379
5f7c426e
LP
3380 return r;
3381}
3382
8e12a6ae 3383int wait_for_terminate(pid_t pid, siginfo_t *status) {
1968a360
LP
3384 siginfo_t dummy;
3385
2e78aa99 3386 assert(pid >= 1);
1968a360
LP
3387
3388 if (!status)
3389 status = &dummy;
2e78aa99
LP
3390
3391 for (;;) {
8e12a6ae
LP
3392 zero(*status);
3393
3394 if (waitid(P_PID, pid, status, WEXITED) < 0) {
2e78aa99
LP
3395
3396 if (errno == EINTR)
3397 continue;
3398
3399 return -errno;
3400 }
3401
3402 return 0;
3403 }
3404}
3405
97c4a07d
LP
3406int wait_for_terminate_and_warn(const char *name, pid_t pid) {
3407 int r;
3408 siginfo_t status;
3409
3410 assert(name);
3411 assert(pid > 1);
3412
d87be9b0
LP
3413 r = wait_for_terminate(pid, &status);
3414 if (r < 0) {
97c4a07d
LP
3415 log_warning("Failed to wait for %s: %s", name, strerror(-r));
3416 return r;
3417 }
3418
3419 if (status.si_code == CLD_EXITED) {
3420 if (status.si_status != 0) {
3421 log_warning("%s failed with error code %i.", name, status.si_status);
0a27cf3f 3422 return status.si_status;
97c4a07d
LP
3423 }
3424
3425 log_debug("%s succeeded.", name);
3426 return 0;
3427
3428 } else if (status.si_code == CLD_KILLED ||
3429 status.si_code == CLD_DUMPED) {
3430
3431 log_warning("%s terminated by signal %s.", name, signal_to_string(status.si_status));
3432 return -EPROTO;
3433 }
3434
3435 log_warning("%s failed due to unknown reason.", name);
3436 return -EPROTO;
97c4a07d
LP
3437}
3438
6a39419f 3439_noreturn_ void freeze(void) {
720ce21d
LP
3440
3441 /* Make sure nobody waits for us on a socket anymore */
3442 close_all_fds(NULL, 0);
3443
c29597a1
LP
3444 sync();
3445
3c14d26c
LP
3446 for (;;)
3447 pause();
3448}
3449
00dc5d76
LP
3450bool null_or_empty(struct stat *st) {
3451 assert(st);
3452
3453 if (S_ISREG(st->st_mode) && st->st_size <= 0)
3454 return true;
3455
c8f26f42 3456 if (S_ISCHR(st->st_mode) || S_ISBLK(st->st_mode))
00dc5d76
LP
3457 return true;
3458
3459 return false;
3460}
3461
83096483
LP
3462int null_or_empty_path(const char *fn) {
3463 struct stat st;
3464
3465 assert(fn);
3466
3467 if (stat(fn, &st) < 0)
3468 return -errno;
3469
3470 return null_or_empty(&st);
3471}
3472
a247755d 3473DIR *xopendirat(int fd, const char *name, int flags) {
c4731d11
LP
3474 int nfd;
3475 DIR *d;
3476
73836c5c
LP
3477 nfd = openat(fd, name, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|flags);
3478 if (nfd < 0)
c4731d11
LP
3479 return NULL;
3480
73836c5c
LP
3481 d = fdopendir(nfd);
3482 if (!d) {
c4731d11
LP
3483 close_nointr_nofail(nfd);
3484 return NULL;
3485 }
3486
3487 return d;
3b63d2d3
LP
3488}
3489
8a0867d6
LP
3490int signal_from_string_try_harder(const char *s) {
3491 int signo;
3492 assert(s);
3493
73836c5c
LP
3494 signo = signal_from_string(s);
3495 if (signo <= 0)
8a0867d6
LP
3496 if (startswith(s, "SIG"))
3497 return signal_from_string(s+3);
3498
3499 return signo;
3500}
3501
383182b5 3502static char *tag_to_udev_node(const char *tagvalue, const char *by) {
e23a0ce8
LP
3503 char *dn, *t, *u;
3504 int r;
3505
3506 /* FIXME: to follow udev's logic 100% we need to leave valid
3507 * UTF8 chars unescaped */
3508
383182b5
DR
3509 u = unquote(tagvalue, "\"\'");
3510 if (u == NULL)
3511 return NULL;
e23a0ce8 3512
383182b5
DR
3513 t = xescape(u, "/ ");
3514 free(u);
e23a0ce8 3515
383182b5
DR
3516 if (t == NULL)
3517 return NULL;
e23a0ce8 3518
383182b5
DR
3519 r = asprintf(&dn, "/dev/disk/by-%s/%s", by, t);
3520 free(t);
e23a0ce8 3521
383182b5
DR
3522 if (r < 0)
3523 return NULL;
e23a0ce8 3524
383182b5
DR
3525 return dn;
3526}
e23a0ce8 3527
383182b5 3528char *fstab_node_to_udev_node(const char *p) {
faa368e3
LP
3529 assert(p);
3530
383182b5
DR
3531 if (startswith(p, "LABEL="))
3532 return tag_to_udev_node(p+6, "label");
e23a0ce8 3533
383182b5
DR
3534 if (startswith(p, "UUID="))
3535 return tag_to_udev_node(p+5, "uuid");
e23a0ce8 3536
84cc2abf
DR
3537 if (startswith(p, "PARTUUID="))
3538 return tag_to_udev_node(p+9, "partuuid");
3539
3540 if (startswith(p, "PARTLABEL="))
3541 return tag_to_udev_node(p+10, "partlabel");
3542
e23a0ce8
LP
3543 return strdup(p);
3544}
3545
f212ac12
LP
3546bool tty_is_vc(const char *tty) {
3547 assert(tty);
3548
3549 if (startswith(tty, "/dev/"))
3550 tty += 5;
3551
98a28fef
LP
3552 return vtnr_from_tty(tty) >= 0;
3553}
3554
d1122ad5
LP
3555bool tty_is_console(const char *tty) {
3556 assert(tty);
3557
3558 if (startswith(tty, "/dev/"))
3559 tty += 5;
3560
3561 return streq(tty, "console");
3562}
3563
98a28fef
LP
3564int vtnr_from_tty(const char *tty) {
3565 int i, r;
3566
3567 assert(tty);
3568
3569 if (startswith(tty, "/dev/"))
3570 tty += 5;
3571
3572 if (!startswith(tty, "tty") )
3573 return -EINVAL;
3574
3575 if (tty[3] < '0' || tty[3] > '9')
3576 return -EINVAL;
3577
3578 r = safe_atoi(tty+3, &i);
3579 if (r < 0)
3580 return r;
3581
3582 if (i < 0 || i > 63)
3583 return -EINVAL;
3584
3585 return i;
f212ac12
LP
3586}
3587
21baf21a
MS
3588char *resolve_dev_console(char **active) {
3589 char *tty;
3590
3591 /* Resolve where /dev/console is pointing to, if /sys is actually ours
3592 * (i.e. not read-only-mounted which is a sign for container setups) */
3593
3594 if (path_is_read_only_fs("/sys") > 0)
3595 return NULL;
3596
3597 if (read_one_line_file("/sys/class/tty/console/active", active) < 0)
3598 return NULL;
3599
3600 /* If multiple log outputs are configured the last one is what
3601 * /dev/console points to */
3602 tty = strrchr(*active, ' ');
3603 if (tty)
3604 tty++;
3605 else
3606 tty = *active;
3607
3608 return tty;
3609}
3610
3043935f 3611bool tty_is_vc_resolve(const char *tty) {
3030ccd7 3612 char *active = NULL;
3043935f 3613 bool b;
3030ccd7 3614
e3aa71c3
LP
3615 assert(tty);
3616
3617 if (startswith(tty, "/dev/"))
3618 tty += 5;
3619
21baf21a
MS
3620 if (streq(tty, "console")) {
3621 tty = resolve_dev_console(&active);
3622 if (!tty)
3623 return false;
3624 }
3030ccd7 3625
3043935f 3626 b = tty_is_vc(tty);
3030ccd7 3627 free(active);
e3aa71c3 3628
3043935f
LP
3629 return b;
3630}
3631
3632const char *default_term_for_tty(const char *tty) {
3633 assert(tty);
3634
acda6a05 3635 return tty_is_vc_resolve(tty) ? "TERM=linux" : "TERM=vt102";
e3aa71c3
LP
3636}
3637
87d2c1ff 3638bool dirent_is_file(const struct dirent *de) {
fb19a739
LP
3639 assert(de);
3640
3641 if (ignore_file(de->d_name))
3642 return false;
3643
3644 if (de->d_type != DT_REG &&
3645 de->d_type != DT_LNK &&
3646 de->d_type != DT_UNKNOWN)
3647 return false;
3648
3649 return true;
3650}
3651
87d2c1ff
LP
3652bool dirent_is_file_with_suffix(const struct dirent *de, const char *suffix) {
3653 assert(de);
3654
a228a22f
LP
3655 if (de->d_type != DT_REG &&
3656 de->d_type != DT_LNK &&
3657 de->d_type != DT_UNKNOWN)
3658 return false;
3659
3660 if (ignore_file_allow_backup(de->d_name))
87d2c1ff
LP
3661 return false;
3662
3663 return endswith(de->d_name, suffix);
3664}
3665
83cc030f
LP
3666void execute_directory(const char *directory, DIR *d, char *argv[]) {
3667 DIR *_d = NULL;
3668 struct dirent *de;
3669 Hashmap *pids = NULL;
3670
3671 assert(directory);
3672
650001c6
JJ
3673 /* Executes all binaries in a directory in parallel and
3674 * waits for them to finish. */
83cc030f
LP
3675
3676 if (!d) {
3677 if (!(_d = opendir(directory))) {
3678
3679 if (errno == ENOENT)
3680 return;
3681
3682 log_error("Failed to enumerate directory %s: %m", directory);
3683 return;
3684 }
3685
3686 d = _d;
3687 }
3688
3689 if (!(pids = hashmap_new(trivial_hash_func, trivial_compare_func))) {
3690 log_error("Failed to allocate set.");
3691 goto finish;
3692 }
3693
3694 while ((de = readdir(d))) {
3695 char *path;
3696 pid_t pid;
3697 int k;
3698
fb19a739 3699 if (!dirent_is_file(de))
83cc030f
LP
3700 continue;
3701
3702 if (asprintf(&path, "%s/%s", directory, de->d_name) < 0) {
0d0f0c50 3703 log_oom();
83cc030f
LP
3704 continue;
3705 }
3706
3707 if ((pid = fork()) < 0) {
3708 log_error("Failed to fork: %m");
3709 free(path);
3710 continue;
3711 }
3712
3713 if (pid == 0) {
3714 char *_argv[2];
3715 /* Child */
3716
3717 if (!argv) {
3718 _argv[0] = path;
3719 _argv[1] = NULL;
3720 argv = _argv;
3721 } else
6edd7d0a 3722 argv[0] = path;
83cc030f
LP
3723
3724 execv(path, argv);
3725
3726 log_error("Failed to execute %s: %m", path);
3727 _exit(EXIT_FAILURE);
3728 }
3729
3730 log_debug("Spawned %s as %lu", path, (unsigned long) pid);
3731
3732 if ((k = hashmap_put(pids, UINT_TO_PTR(pid), path)) < 0) {
3733 log_error("Failed to add PID to set: %s", strerror(-k));
3734 free(path);
3735 }
3736 }
3737
3738 while (!hashmap_isempty(pids)) {
ec3f9b53 3739 pid_t pid = PTR_TO_UINT(hashmap_first_key(pids));
83cc030f
LP
3740 siginfo_t si;
3741 char *path;
3742
3743 zero(si);
ec3f9b53 3744 if (waitid(P_PID, pid, &si, WEXITED) < 0) {
83cc030f
LP
3745
3746 if (errno == EINTR)
3747 continue;
3748
3749 log_error("waitid() failed: %m");
3750 goto finish;
3751 }
3752
3753 if ((path = hashmap_remove(pids, UINT_TO_PTR(si.si_pid)))) {
96342de6 3754 if (!is_clean_exit(si.si_code, si.si_status, NULL)) {
83cc030f
LP
3755 if (si.si_code == CLD_EXITED)
3756 log_error("%s exited with exit status %i.", path, si.si_status);
3757 else
3758 log_error("%s terminated by signal %s.", path, signal_to_string(si.si_status));
3759 } else
3760 log_debug("%s exited successfully.", path);
3761
3762 free(path);
3763 }
3764 }
3765
3766finish:
3767 if (_d)
3768 closedir(_d);
3769
3770 if (pids)
3771 hashmap_free_free(pids);
3772}
3773
430c18ed
LP
3774int kill_and_sigcont(pid_t pid, int sig) {
3775 int r;
3776
3777 r = kill(pid, sig) < 0 ? -errno : 0;
3778
3779 if (r >= 0)
3780 kill(pid, SIGCONT);
3781
3782 return r;
3783}
3784
05feefe0
LP
3785bool nulstr_contains(const char*nulstr, const char *needle) {
3786 const char *i;
3787
3788 if (!nulstr)
3789 return false;
3790
3791 NULSTR_FOREACH(i, nulstr)
3792 if (streq(i, needle))
3793 return true;
3794
3795 return false;
3796}
3797
6faa1114 3798bool plymouth_running(void) {
9408a2d2 3799 return access("/run/plymouth/pid", F_OK) >= 0;
6faa1114
LP
3800}
3801
9beb3f4d
LP
3802char* strshorten(char *s, size_t l) {
3803 assert(s);
3804
3805 if (l < strlen(s))
3806 s[l] = 0;
3807
3808 return s;
3809}
3810
3811static bool hostname_valid_char(char c) {
3812 return
3813 (c >= 'a' && c <= 'z') ||
3814 (c >= 'A' && c <= 'Z') ||
3815 (c >= '0' && c <= '9') ||
3816 c == '-' ||
3817 c == '_' ||
3818 c == '.';
3819}
3820
3821bool hostname_is_valid(const char *s) {
3822 const char *p;
aa3c5cf8 3823 bool dot;
9beb3f4d
LP
3824
3825 if (isempty(s))
3826 return false;
3827
aa3c5cf8
LP
3828 for (p = s, dot = true; *p; p++) {
3829 if (*p == '.') {
3830 if (dot)
3831 return false;
3832
3833 dot = true;
3834 } else {
3835 if (!hostname_valid_char(*p))
3836 return false;
3837
3838 dot = false;
3839 }
3840 }
3841
3842 if (dot)
3843 return false;
9beb3f4d
LP
3844
3845 if (p-s > HOST_NAME_MAX)
3846 return false;
3847
3848 return true;
3849}
3850
3851char* hostname_cleanup(char *s) {
3852 char *p, *d;
3853
3854 for (p = s, d = s; *p; p++)
3855 if ((*p >= 'a' && *p <= 'z') ||
3856 (*p >= 'A' && *p <= 'Z') ||
3857 (*p >= '0' && *p <= '9') ||
3858 *p == '-' ||
3859 *p == '_' ||
3860 *p == '.')
3861 *(d++) = *p;
3862
3863 *d = 0;
3864
3865 strshorten(s, HOST_NAME_MAX);
3866 return s;
3867}
3868
1325aa42
LP
3869int pipe_eof(int fd) {
3870 struct pollfd pollfd;
3871 int r;
3872
3873 zero(pollfd);
3874 pollfd.fd = fd;
3875 pollfd.events = POLLIN|POLLHUP;
3876
3877 r = poll(&pollfd, 1, 0);
3878 if (r < 0)
3879 return -errno;
3880
3881 if (r == 0)
3882 return 0;
3883
3884 return pollfd.revents & POLLHUP;
3885}
3886
8f2d43a0 3887int fd_wait_for_event(int fd, int event, usec_t t) {
df50185b
LP
3888 struct pollfd pollfd;
3889 int r;
3890
3891 zero(pollfd);
3892 pollfd.fd = fd;
3893 pollfd.events = event;
3894
8f2d43a0 3895 r = poll(&pollfd, 1, t == (usec_t) -1 ? -1 : (int) (t / USEC_PER_MSEC));
df50185b
LP
3896 if (r < 0)
3897 return -errno;
3898
3899 if (r == 0)
3900 return 0;
3901
3902 return pollfd.revents;
3903}
3904
5a3ab509
LP
3905int fopen_temporary(const char *path, FILE **_f, char **_temp_path) {
3906 FILE *f;
3907 char *t;
3908 const char *fn;
3909 size_t k;
3910 int fd;
3911
3912 assert(path);
3913 assert(_f);
3914 assert(_temp_path);
3915
3916 t = new(char, strlen(path) + 1 + 6 + 1);
3917 if (!t)
3918 return -ENOMEM;
3919
9eb977db 3920 fn = path_get_file_name(path);
5a3ab509
LP
3921 k = fn-path;
3922 memcpy(t, path, k);
3923 t[k] = '.';
3924 stpcpy(stpcpy(t+k+1, fn), "XXXXXX");
3925
3926 fd = mkostemp(t, O_WRONLY|O_CLOEXEC);
3927 if (fd < 0) {
3928 free(t);
3929 return -errno;
3930 }
3931
3932 f = fdopen(fd, "we");
3933 if (!f) {
3934 unlink(t);
3935 free(t);
3936 return -errno;
3937 }
3938
3939 *_f = f;
3940 *_temp_path = t;
3941
3942 return 0;
3943}
3944
6ea832a2 3945int terminal_vhangup_fd(int fd) {
5a3ab509
LP
3946 assert(fd >= 0);
3947
6ea832a2
LP
3948 if (ioctl(fd, TIOCVHANGUP) < 0)
3949 return -errno;
3950
3951 return 0;
3952}
3953
3954int terminal_vhangup(const char *name) {
3955 int fd, r;
3956
3957 fd = open_terminal(name, O_RDWR|O_NOCTTY|O_CLOEXEC);
3958 if (fd < 0)
3959 return fd;
3960
3961 r = terminal_vhangup_fd(fd);
3962 close_nointr_nofail(fd);
3963
3964 return r;
3965}
3966
3967int vt_disallocate(const char *name) {
3968 int fd, r;
3969 unsigned u;
6ea832a2
LP
3970
3971 /* Deallocate the VT if possible. If not possible
3972 * (i.e. because it is the active one), at least clear it
3973 * entirely (including the scrollback buffer) */
3974
b83bc4e9
LP
3975 if (!startswith(name, "/dev/"))
3976 return -EINVAL;
3977
3978 if (!tty_is_vc(name)) {
3979 /* So this is not a VT. I guess we cannot deallocate
3980 * it then. But let's at least clear the screen */
3981
3982 fd = open_terminal(name, O_RDWR|O_NOCTTY|O_CLOEXEC);
3983 if (fd < 0)
3984 return fd;
3985
8585357a
LP
3986 loop_write(fd,
3987 "\033[r" /* clear scrolling region */
3988 "\033[H" /* move home */
3989 "\033[2J", /* clear screen */
3990 10, false);
b83bc4e9
LP
3991 close_nointr_nofail(fd);
3992
3993 return 0;
3994 }
6ea832a2
LP
3995
3996 if (!startswith(name, "/dev/tty"))
3997 return -EINVAL;
3998
3999 r = safe_atou(name+8, &u);
4000 if (r < 0)
4001 return r;
4002
4003 if (u <= 0)
b83bc4e9 4004 return -EINVAL;
6ea832a2 4005
b83bc4e9 4006 /* Try to deallocate */
6ea832a2
LP
4007 fd = open_terminal("/dev/tty0", O_RDWR|O_NOCTTY|O_CLOEXEC);
4008 if (fd < 0)
4009 return fd;
4010
4011 r = ioctl(fd, VT_DISALLOCATE, u);
b83bc4e9 4012 close_nointr_nofail(fd);
6ea832a2 4013
b83bc4e9
LP
4014 if (r >= 0)
4015 return 0;
6ea832a2 4016
b83bc4e9 4017 if (errno != EBUSY)
6ea832a2 4018 return -errno;
6ea832a2 4019
b83bc4e9
LP
4020 /* Couldn't deallocate, so let's clear it fully with
4021 * scrollback */
4022 fd = open_terminal(name, O_RDWR|O_NOCTTY|O_CLOEXEC);
6ea832a2 4023 if (fd < 0)
b83bc4e9 4024 return fd;
6ea832a2 4025
8585357a
LP
4026 loop_write(fd,
4027 "\033[r" /* clear scrolling region */
4028 "\033[H" /* move home */
4029 "\033[3J", /* clear screen including scrollback, requires Linux 2.6.40 */
4030 10, false);
b83bc4e9 4031 close_nointr_nofail(fd);
6ea832a2 4032
b83bc4e9 4033 return 0;
6ea832a2
LP
4034}
4035
34ca941c
LP
4036int copy_file(const char *from, const char *to) {
4037 int r, fdf, fdt;
4038
4039 assert(from);
4040 assert(to);
4041
4042 fdf = open(from, O_RDONLY|O_CLOEXEC|O_NOCTTY);
4043 if (fdf < 0)
4044 return -errno;
4045
4046 fdt = open(to, O_WRONLY|O_CREAT|O_EXCL|O_CLOEXEC|O_NOCTTY, 0644);
4047 if (fdt < 0) {
4048 close_nointr_nofail(fdf);
4049 return -errno;
4050 }
4051
4052 for (;;) {
4053 char buf[PIPE_BUF];
4054 ssize_t n, k;
4055
4056 n = read(fdf, buf, sizeof(buf));
4057 if (n < 0) {
4058 r = -errno;
4059
4060 close_nointr_nofail(fdf);
4061 close_nointr(fdt);
4062 unlink(to);
4063
4064 return r;
4065 }
4066
4067 if (n == 0)
4068 break;
4069
4070 errno = 0;
4071 k = loop_write(fdt, buf, n, false);
4072 if (n != k) {
4073 r = k < 0 ? k : (errno ? -errno : -EIO);
4074
4075 close_nointr_nofail(fdf);
4076 close_nointr(fdt);
4077
4078 unlink(to);
4079 return r;
4080 }
4081 }
4082
4083 close_nointr_nofail(fdf);
4084 r = close_nointr(fdt);
4085
4086 if (r < 0) {
4087 unlink(to);
4088 return r;
4089 }
4090
4091 return 0;
4092}
4093
424a19f8
LP
4094int symlink_atomic(const char *from, const char *to) {
4095 char *x;
4096 _cleanup_free_ char *t;
34ca941c
LP
4097 const char *fn;
4098 size_t k;
4099 unsigned long long ull;
4100 unsigned i;
4101 int r;
4102
4103 assert(from);
4104 assert(to);
4105
4106 t = new(char, strlen(to) + 1 + 16 + 1);
4107 if (!t)
4108 return -ENOMEM;
4109
9eb977db 4110 fn = path_get_file_name(to);
34ca941c
LP
4111 k = fn-to;
4112 memcpy(t, to, k);
4113 t[k] = '.';
4114 x = stpcpy(t+k+1, fn);
4115
4116 ull = random_ull();
4117 for (i = 0; i < 16; i++) {
4118 *(x++) = hexchar(ull & 0xF);
4119 ull >>= 4;
4120 }
4121
4122 *x = 0;
4123
424a19f8
LP
4124 if (symlink(from, t) < 0)
4125 return -errno;
34ca941c
LP
4126
4127 if (rename(t, to) < 0) {
4128 r = -errno;
4129 unlink(t);
34ca941c
LP
4130 return r;
4131 }
4132
424a19f8 4133 return 0;
34ca941c
LP
4134}
4135
4d6d6518
LP
4136bool display_is_local(const char *display) {
4137 assert(display);
4138
4139 return
4140 display[0] == ':' &&
4141 display[1] >= '0' &&
4142 display[1] <= '9';
4143}
4144
4145int socket_from_display(const char *display, char **path) {
4146 size_t k;
4147 char *f, *c;
4148
4149 assert(display);
4150 assert(path);
4151
4152 if (!display_is_local(display))
4153 return -EINVAL;
4154
4155 k = strspn(display+1, "0123456789");
4156
4157 f = new(char, sizeof("/tmp/.X11-unix/X") + k);
4158 if (!f)
4159 return -ENOMEM;
4160
4161 c = stpcpy(f, "/tmp/.X11-unix/X");
4162 memcpy(c, display+1, k);
4163 c[k] = 0;
4164
4165 *path = f;
4166
4167 return 0;
4168}
4169
d05c5031
LP
4170int get_user_creds(
4171 const char **username,
4172 uid_t *uid, gid_t *gid,
4173 const char **home,
4174 const char **shell) {
4175
1cccf435 4176 struct passwd *p;
ddd88763 4177 uid_t u;
1cccf435
MV
4178
4179 assert(username);
4180 assert(*username);
1cccf435
MV
4181
4182 /* We enforce some special rules for uid=0: in order to avoid
4183 * NSS lookups for root we hardcode its data. */
4184
4185 if (streq(*username, "root") || streq(*username, "0")) {
4186 *username = "root";
4b67834e
LP
4187
4188 if (uid)
4189 *uid = 0;
4190
4191 if (gid)
4192 *gid = 0;
4193
4194 if (home)
4195 *home = "/root";
d05c5031
LP
4196
4197 if (shell)
4198 *shell = "/bin/sh";
4199
1cccf435
MV
4200 return 0;
4201 }
4202
ddd88763 4203 if (parse_uid(*username, &u) >= 0) {
1cccf435 4204 errno = 0;
ddd88763 4205 p = getpwuid(u);
1cccf435
MV
4206
4207 /* If there are multiple users with the same id, make
4208 * sure to leave $USER to the configured value instead
4209 * of the first occurrence in the database. However if
4210 * the uid was configured by a numeric uid, then let's
4211 * pick the real username from /etc/passwd. */
4212 if (p)
4213 *username = p->pw_name;
4214 } else {
4215 errno = 0;
4216 p = getpwnam(*username);
4217 }
4218
4219 if (!p)
8333c77e 4220 return errno > 0 ? -errno : -ESRCH;
1cccf435 4221
4b67834e
LP
4222 if (uid)
4223 *uid = p->pw_uid;
4224
4225 if (gid)
4226 *gid = p->pw_gid;
4227
4228 if (home)
4229 *home = p->pw_dir;
4230
d05c5031
LP
4231 if (shell)
4232 *shell = p->pw_shell;
4233
4b67834e
LP
4234 return 0;
4235}
4236
59164be4
LP
4237char* uid_to_name(uid_t uid) {
4238 struct passwd *p;
4239 char *r;
4240
4241 if (uid == 0)
4242 return strdup("root");
4243
4244 p = getpwuid(uid);
4245 if (p)
4246 return strdup(p->pw_name);
4247
4248 if (asprintf(&r, "%lu", (unsigned long) uid) < 0)
4249 return NULL;
4250
4251 return r;
4252}
4253
4468addc
LP
4254char* gid_to_name(gid_t gid) {
4255 struct group *p;
4256 char *r;
4257
4258 if (gid == 0)
4259 return strdup("root");
4260
4261 p = getgrgid(gid);
4262 if (p)
4263 return strdup(p->gr_name);
4264
4265 if (asprintf(&r, "%lu", (unsigned long) gid) < 0)
4266 return NULL;
4267
4268 return r;
4269}
4270
4b67834e
LP
4271int get_group_creds(const char **groupname, gid_t *gid) {
4272 struct group *g;
4273 gid_t id;
4274
4275 assert(groupname);
4276
4277 /* We enforce some special rules for gid=0: in order to avoid
4278 * NSS lookups for root we hardcode its data. */
4279
4280 if (streq(*groupname, "root") || streq(*groupname, "0")) {
4281 *groupname = "root";
4282
4283 if (gid)
4284 *gid = 0;
4285
4286 return 0;
4287 }
4288
4289 if (parse_gid(*groupname, &id) >= 0) {
4290 errno = 0;
4291 g = getgrgid(id);
4292
4293 if (g)
4294 *groupname = g->gr_name;
4295 } else {
4296 errno = 0;
4297 g = getgrnam(*groupname);
4298 }
4299
4300 if (!g)
8333c77e 4301 return errno > 0 ? -errno : -ESRCH;
4b67834e
LP
4302
4303 if (gid)
4304 *gid = g->gr_gid;
4305
1cccf435
MV
4306 return 0;
4307}
4308
4468addc
LP
4309int in_gid(gid_t gid) {
4310 gid_t *gids;
43673799
LP
4311 int ngroups_max, r, i;
4312
43673799
LP
4313 if (getgid() == gid)
4314 return 1;
4315
4316 if (getegid() == gid)
4317 return 1;
4318
4319 ngroups_max = sysconf(_SC_NGROUPS_MAX);
4320 assert(ngroups_max > 0);
4321
4322 gids = alloca(sizeof(gid_t) * ngroups_max);
4323
4324 r = getgroups(ngroups_max, gids);
4325 if (r < 0)
4326 return -errno;
4327
4328 for (i = 0; i < r; i++)
4329 if (gids[i] == gid)
4330 return 1;
4331
4332 return 0;
4333}
4334
4468addc
LP
4335int in_group(const char *name) {
4336 int r;
4337 gid_t gid;
4338
4339 r = get_group_creds(&name, &gid);
4340 if (r < 0)
4341 return r;
4342
4343 return in_gid(gid);
4344}
4345
8092a428
LP
4346int glob_exists(const char *path) {
4347 glob_t g;
4348 int r, k;
4349
4350 assert(path);
4351
4352 zero(g);
4353 errno = 0;
4354 k = glob(path, GLOB_NOSORT|GLOB_BRACE, NULL, &g);
4355
4356 if (k == GLOB_NOMATCH)
4357 r = 0;
4358 else if (k == GLOB_NOSPACE)
4359 r = -ENOMEM;
4360 else if (k == 0)
4361 r = !strv_isempty(g.gl_pathv);
4362 else
4363 r = errno ? -errno : -EIO;
4364
4365 globfree(&g);
4366
4367 return r;
4368}
4369
83096483
LP
4370int dirent_ensure_type(DIR *d, struct dirent *de) {
4371 struct stat st;
4372
4373 assert(d);
4374 assert(de);
4375
4376 if (de->d_type != DT_UNKNOWN)
4377 return 0;
4378
4379 if (fstatat(dirfd(d), de->d_name, &st, AT_SYMLINK_NOFOLLOW) < 0)
4380 return -errno;
4381
4382 de->d_type =
4383 S_ISREG(st.st_mode) ? DT_REG :
4384 S_ISDIR(st.st_mode) ? DT_DIR :
4385 S_ISLNK(st.st_mode) ? DT_LNK :
4386 S_ISFIFO(st.st_mode) ? DT_FIFO :
4387 S_ISSOCK(st.st_mode) ? DT_SOCK :
4388 S_ISCHR(st.st_mode) ? DT_CHR :
4389 S_ISBLK(st.st_mode) ? DT_BLK :
4390 DT_UNKNOWN;
4391
4392 return 0;
4393}
4394
4395int in_search_path(const char *path, char **search) {
4396 char **i, *parent;
4397 int r;
4398
9eb977db 4399 r = path_get_parent(path, &parent);
83096483
LP
4400 if (r < 0)
4401 return r;
4402
4403 r = 0;
4404
4405 STRV_FOREACH(i, search) {
4406 if (path_equal(parent, *i)) {
4407 r = 1;
4408 break;
4409 }
4410 }
4411
4412 free(parent);
4413
4414 return r;
4415}
4416
034a2a52
LP
4417int get_files_in_directory(const char *path, char ***list) {
4418 DIR *d;
4419 int r = 0;
4420 unsigned n = 0;
4421 char **l = NULL;
4422
4423 assert(path);
d60ef526
LP
4424
4425 /* Returns all files in a directory in *list, and the number
4426 * of files as return value. If list is NULL returns only the
4427 * number */
034a2a52
LP
4428
4429 d = opendir(path);
8ea913b2
LP
4430 if (!d)
4431 return -errno;
4432
034a2a52 4433 for (;;) {
7d5e9c0f
LP
4434 struct dirent *de;
4435 union dirent_storage buf;
034a2a52
LP
4436 int k;
4437
7d5e9c0f 4438 k = readdir_r(d, &buf.de, &de);
034a2a52
LP
4439 if (k != 0) {
4440 r = -k;
4441 goto finish;
4442 }
4443
4444 if (!de)
4445 break;
4446
4447 dirent_ensure_type(d, de);
4448
4449 if (!dirent_is_file(de))
4450 continue;
4451
d60ef526
LP
4452 if (list) {
4453 if ((unsigned) r >= n) {
4454 char **t;
034a2a52 4455
d60ef526
LP
4456 n = MAX(16, 2*r);
4457 t = realloc(l, sizeof(char*) * n);
4458 if (!t) {
4459 r = -ENOMEM;
4460 goto finish;
4461 }
034a2a52 4462
d60ef526
LP
4463 l = t;
4464 }
034a2a52 4465
d60ef526 4466 assert((unsigned) r < n);
034a2a52 4467
d60ef526
LP
4468 l[r] = strdup(de->d_name);
4469 if (!l[r]) {
4470 r = -ENOMEM;
4471 goto finish;
4472 }
034a2a52 4473
d60ef526
LP
4474 l[++r] = NULL;
4475 } else
4476 r++;
034a2a52
LP
4477 }
4478
4479finish:
4480 if (d)
4481 closedir(d);
4482
d60ef526
LP
4483 if (r >= 0) {
4484 if (list)
4485 *list = l;
4486 } else
034a2a52
LP
4487 strv_free(l);
4488
4489 return r;
4490}
4491
b7def684 4492char *strjoin(const char *x, ...) {
911a4828
LP
4493 va_list ap;
4494 size_t l;
4495 char *r, *p;
4496
4497 va_start(ap, x);
4498
4499 if (x) {
4500 l = strlen(x);
4501
4502 for (;;) {
4503 const char *t;
040f18ea 4504 size_t n;
911a4828
LP
4505
4506 t = va_arg(ap, const char *);
4507 if (!t)
4508 break;
4509
040f18ea 4510 n = strlen(t);
e98055de
LN
4511 if (n > ((size_t) -1) - l) {
4512 va_end(ap);
040f18ea 4513 return NULL;
e98055de 4514 }
040f18ea
LP
4515
4516 l += n;
911a4828
LP
4517 }
4518 } else
4519 l = 0;
4520
4521 va_end(ap);
4522
4523 r = new(char, l+1);
4524 if (!r)
4525 return NULL;
4526
4527 if (x) {
4528 p = stpcpy(r, x);
4529
4530 va_start(ap, x);
4531
4532 for (;;) {
4533 const char *t;
4534
4535 t = va_arg(ap, const char *);
4536 if (!t)
4537 break;
4538
4539 p = stpcpy(p, t);
4540 }
8ea913b2
LP
4541
4542 va_end(ap);
911a4828
LP
4543 } else
4544 r[0] = 0;
4545
4546 return r;
4547}
4548
b636465b
LP
4549bool is_main_thread(void) {
4550 static __thread int cached = 0;
4551
4552 if (_unlikely_(cached == 0))
4553 cached = getpid() == gettid() ? 1 : -1;
4554
4555 return cached > 0;
4556}
4557
94959f0f
LP
4558int block_get_whole_disk(dev_t d, dev_t *ret) {
4559 char *p, *s;
4560 int r;
4561 unsigned n, m;
4562
4563 assert(ret);
4564
4565 /* If it has a queue this is good enough for us */
4566 if (asprintf(&p, "/sys/dev/block/%u:%u/queue", major(d), minor(d)) < 0)
4567 return -ENOMEM;
4568
4569 r = access(p, F_OK);
4570 free(p);
4571
4572 if (r >= 0) {
4573 *ret = d;
4574 return 0;
4575 }
4576
4577 /* If it is a partition find the originating device */
4578 if (asprintf(&p, "/sys/dev/block/%u:%u/partition", major(d), minor(d)) < 0)
4579 return -ENOMEM;
4580
4581 r = access(p, F_OK);
4582 free(p);
4583
4584 if (r < 0)
4585 return -ENOENT;
4586
4587 /* Get parent dev_t */
4588 if (asprintf(&p, "/sys/dev/block/%u:%u/../dev", major(d), minor(d)) < 0)
4589 return -ENOMEM;
4590
4591 r = read_one_line_file(p, &s);
4592 free(p);
4593
4594 if (r < 0)
4595 return r;
4596
4597 r = sscanf(s, "%u:%u", &m, &n);
4598 free(s);
4599
4600 if (r != 2)
4601 return -EINVAL;
4602
4603 /* Only return this if it is really good enough for us. */
4604 if (asprintf(&p, "/sys/dev/block/%u:%u/queue", m, n) < 0)
4605 return -ENOMEM;
4606
4607 r = access(p, F_OK);
4608 free(p);
4609
4610 if (r >= 0) {
4611 *ret = makedev(m, n);
4612 return 0;
4613 }
4614
4615 return -ENOENT;
4616}
4617
8d53b453 4618int file_is_priv_sticky(const char *p) {
ad293f5a
LP
4619 struct stat st;
4620
4621 assert(p);
4622
4623 if (lstat(p, &st) < 0)
4624 return -errno;
4625
4626 return
8d53b453 4627 (st.st_uid == 0 || st.st_uid == getuid()) &&
ad293f5a
LP
4628 (st.st_mode & S_ISVTX);
4629}
94959f0f 4630
f41607a6
LP
4631static const char *const ioprio_class_table[] = {
4632 [IOPRIO_CLASS_NONE] = "none",
4633 [IOPRIO_CLASS_RT] = "realtime",
4634 [IOPRIO_CLASS_BE] = "best-effort",
4635 [IOPRIO_CLASS_IDLE] = "idle"
4636};
4637
f8b69d1d 4638DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(ioprio_class, int, INT_MAX);
f41607a6
LP
4639
4640static const char *const sigchld_code_table[] = {
4641 [CLD_EXITED] = "exited",
4642 [CLD_KILLED] = "killed",
4643 [CLD_DUMPED] = "dumped",
4644 [CLD_TRAPPED] = "trapped",
4645 [CLD_STOPPED] = "stopped",
4646 [CLD_CONTINUED] = "continued",
4647};
4648
4649DEFINE_STRING_TABLE_LOOKUP(sigchld_code, int);
4650
4651static const char *const log_facility_unshifted_table[LOG_NFACILITIES] = {
4652 [LOG_FAC(LOG_KERN)] = "kern",
4653 [LOG_FAC(LOG_USER)] = "user",
4654 [LOG_FAC(LOG_MAIL)] = "mail",
4655 [LOG_FAC(LOG_DAEMON)] = "daemon",
4656 [LOG_FAC(LOG_AUTH)] = "auth",
4657 [LOG_FAC(LOG_SYSLOG)] = "syslog",
4658 [LOG_FAC(LOG_LPR)] = "lpr",
4659 [LOG_FAC(LOG_NEWS)] = "news",
4660 [LOG_FAC(LOG_UUCP)] = "uucp",
4661 [LOG_FAC(LOG_CRON)] = "cron",
4662 [LOG_FAC(LOG_AUTHPRIV)] = "authpriv",
4663 [LOG_FAC(LOG_FTP)] = "ftp",
4664 [LOG_FAC(LOG_LOCAL0)] = "local0",
4665 [LOG_FAC(LOG_LOCAL1)] = "local1",
4666 [LOG_FAC(LOG_LOCAL2)] = "local2",
4667 [LOG_FAC(LOG_LOCAL3)] = "local3",
4668 [LOG_FAC(LOG_LOCAL4)] = "local4",
4669 [LOG_FAC(LOG_LOCAL5)] = "local5",
4670 [LOG_FAC(LOG_LOCAL6)] = "local6",
4671 [LOG_FAC(LOG_LOCAL7)] = "local7"
4672};
4673
f8b69d1d 4674DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(log_facility_unshifted, int, LOG_FAC(~0));
f41607a6
LP
4675
4676static const char *const log_level_table[] = {
4677 [LOG_EMERG] = "emerg",
4678 [LOG_ALERT] = "alert",
4679 [LOG_CRIT] = "crit",
4680 [LOG_ERR] = "err",
4681 [LOG_WARNING] = "warning",
4682 [LOG_NOTICE] = "notice",
4683 [LOG_INFO] = "info",
4684 [LOG_DEBUG] = "debug"
4685};
4686
f8b69d1d 4687DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(log_level, int, LOG_DEBUG);
f41607a6
LP
4688
4689static const char* const sched_policy_table[] = {
4690 [SCHED_OTHER] = "other",
4691 [SCHED_BATCH] = "batch",
4692 [SCHED_IDLE] = "idle",
4693 [SCHED_FIFO] = "fifo",
4694 [SCHED_RR] = "rr"
4695};
4696
f8b69d1d 4697DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(sched_policy, int, INT_MAX);
f41607a6
LP
4698
4699static const char* const rlimit_table[] = {
4700 [RLIMIT_CPU] = "LimitCPU",
4701 [RLIMIT_FSIZE] = "LimitFSIZE",
4702 [RLIMIT_DATA] = "LimitDATA",
4703 [RLIMIT_STACK] = "LimitSTACK",
4704 [RLIMIT_CORE] = "LimitCORE",
4705 [RLIMIT_RSS] = "LimitRSS",
4706 [RLIMIT_NOFILE] = "LimitNOFILE",
4707 [RLIMIT_AS] = "LimitAS",
4708 [RLIMIT_NPROC] = "LimitNPROC",
4709 [RLIMIT_MEMLOCK] = "LimitMEMLOCK",
4710 [RLIMIT_LOCKS] = "LimitLOCKS",
4711 [RLIMIT_SIGPENDING] = "LimitSIGPENDING",
4712 [RLIMIT_MSGQUEUE] = "LimitMSGQUEUE",
4713 [RLIMIT_NICE] = "LimitNICE",
4714 [RLIMIT_RTPRIO] = "LimitRTPRIO",
4715 [RLIMIT_RTTIME] = "LimitRTTIME"
4716};
4717
4718DEFINE_STRING_TABLE_LOOKUP(rlimit, int);
4719
4720static const char* const ip_tos_table[] = {
4721 [IPTOS_LOWDELAY] = "low-delay",
4722 [IPTOS_THROUGHPUT] = "throughput",
4723 [IPTOS_RELIABILITY] = "reliability",
4724 [IPTOS_LOWCOST] = "low-cost",
4725};
4726
f8b69d1d 4727DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(ip_tos, int, 0xff);
f41607a6 4728
4e240ab0 4729static const char *const __signal_table[] = {
f41607a6
LP
4730 [SIGHUP] = "HUP",
4731 [SIGINT] = "INT",
4732 [SIGQUIT] = "QUIT",
4733 [SIGILL] = "ILL",
4734 [SIGTRAP] = "TRAP",
4735 [SIGABRT] = "ABRT",
4736 [SIGBUS] = "BUS",
4737 [SIGFPE] = "FPE",
4738 [SIGKILL] = "KILL",
4739 [SIGUSR1] = "USR1",
4740 [SIGSEGV] = "SEGV",
4741 [SIGUSR2] = "USR2",
4742 [SIGPIPE] = "PIPE",
4743 [SIGALRM] = "ALRM",
4744 [SIGTERM] = "TERM",
4745#ifdef SIGSTKFLT
4746 [SIGSTKFLT] = "STKFLT", /* Linux on SPARC doesn't know SIGSTKFLT */
4747#endif
4748 [SIGCHLD] = "CHLD",
4749 [SIGCONT] = "CONT",
4750 [SIGSTOP] = "STOP",
4751 [SIGTSTP] = "TSTP",
4752 [SIGTTIN] = "TTIN",
4753 [SIGTTOU] = "TTOU",
4754 [SIGURG] = "URG",
4755 [SIGXCPU] = "XCPU",
4756 [SIGXFSZ] = "XFSZ",
4757 [SIGVTALRM] = "VTALRM",
4758 [SIGPROF] = "PROF",
4759 [SIGWINCH] = "WINCH",
4760 [SIGIO] = "IO",
4761 [SIGPWR] = "PWR",
4762 [SIGSYS] = "SYS"
4763};
4764
4e240ab0
MS
4765DEFINE_PRIVATE_STRING_TABLE_LOOKUP(__signal, int);
4766
4767const char *signal_to_string(int signo) {
4768 static __thread char buf[12];
4769 const char *name;
4770
4771 name = __signal_to_string(signo);
4772 if (name)
4773 return name;
4774
4775 if (signo >= SIGRTMIN && signo <= SIGRTMAX)
4776 snprintf(buf, sizeof(buf) - 1, "RTMIN+%d", signo - SIGRTMIN);
4777 else
4778 snprintf(buf, sizeof(buf) - 1, "%d", signo);
4779 char_array_0(buf);
4780 return buf;
4781}
4782
4783int signal_from_string(const char *s) {
4784 int signo;
4785 int offset = 0;
4786 unsigned u;
4787
040f18ea 4788 signo = __signal_from_string(s);
4e240ab0
MS
4789 if (signo > 0)
4790 return signo;
4791
4792 if (startswith(s, "RTMIN+")) {
4793 s += 6;
4794 offset = SIGRTMIN;
4795 }
4796 if (safe_atou(s, &u) >= 0) {
4797 signo = (int) u + offset;
4798 if (signo > 0 && signo < _NSIG)
4799 return signo;
4800 }
4801 return -1;
4802}
65457142
FC
4803
4804bool kexec_loaded(void) {
4805 bool loaded = false;
4806 char *s;
4807
4808 if (read_one_line_file("/sys/kernel/kexec_loaded", &s) >= 0) {
4809 if (s[0] == '1')
4810 loaded = true;
4811 free(s);
4812 }
4813 return loaded;
4814}
fb9de93d
LP
4815
4816int strdup_or_null(const char *a, char **b) {
4817 char *c;
4818
4819 assert(b);
4820
4821 if (!a) {
4822 *b = NULL;
4823 return 0;
4824 }
4825
4826 c = strdup(a);
4827 if (!c)
4828 return -ENOMEM;
4829
4830 *b = c;
4831 return 0;
4832}
64685e0c 4833
87d2c1ff
LP
4834int prot_from_flags(int flags) {
4835
4836 switch (flags & O_ACCMODE) {
4837
4838 case O_RDONLY:
4839 return PROT_READ;
4840
4841 case O_WRONLY:
4842 return PROT_WRITE;
4843
4844 case O_RDWR:
4845 return PROT_READ|PROT_WRITE;
4846
4847 default:
4848 return -EINVAL;
4849 }
7c99e0c1 4850}
689b9a22 4851
babfc091 4852char *format_bytes(char *buf, size_t l, off_t t) {
c0f99c21 4853 unsigned i;
babfc091
LP
4854
4855 static const struct {
4856 const char *suffix;
4857 off_t factor;
4858 } table[] = {
32895bb3
LP
4859 { "E", 1024ULL*1024ULL*1024ULL*1024ULL*1024ULL*1024ULL },
4860 { "P", 1024ULL*1024ULL*1024ULL*1024ULL*1024ULL },
babfc091
LP
4861 { "T", 1024ULL*1024ULL*1024ULL*1024ULL },
4862 { "G", 1024ULL*1024ULL*1024ULL },
4863 { "M", 1024ULL*1024ULL },
4864 { "K", 1024ULL },
4865 };
4866
4867 for (i = 0; i < ELEMENTSOF(table); i++) {
4868
4869 if (t >= table[i].factor) {
4870 snprintf(buf, l,
4871 "%llu.%llu%s",
4872 (unsigned long long) (t / table[i].factor),
4873 (unsigned long long) (((t*10ULL) / table[i].factor) % 10ULL),
4874 table[i].suffix);
4875
4876 goto finish;
4877 }
4878 }
4879
4880 snprintf(buf, l, "%lluB", (unsigned long long) t);
4881
4882finish:
4883 buf[l-1] = 0;
4884 return buf;
4885
4886}
55d7bfc1
LP
4887
4888void* memdup(const void *p, size_t l) {
4889 void *r;
4890
4891 assert(p);
4892
4893 r = malloc(l);
4894 if (!r)
4895 return NULL;
4896
4897 memcpy(r, p, l);
4898 return r;
4899}
bb99a35a
LP
4900
4901int fd_inc_sndbuf(int fd, size_t n) {
4902 int r, value;
4903 socklen_t l = sizeof(value);
4904
4905 r = getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &value, &l);
4906 if (r >= 0 &&
4907 l == sizeof(value) &&
4908 (size_t) value >= n*2)
4909 return 0;
4910
4911 value = (int) n;
4912 r = setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &value, sizeof(value));
4913 if (r < 0)
4914 return -errno;
4915
4916 return 1;
4917}
4918
4919int fd_inc_rcvbuf(int fd, size_t n) {
4920 int r, value;
4921 socklen_t l = sizeof(value);
4922
4923 r = getsockopt(fd, SOL_SOCKET, SO_RCVBUF, &value, &l);
4924 if (r >= 0 &&
4925 l == sizeof(value) &&
4926 (size_t) value >= n*2)
4927 return 0;
4928
4929 value = (int) n;
4930 r = setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &value, sizeof(value));
4931 if (r < 0)
4932 return -errno;
4933
4934 return 1;
4935}
6bb92a16 4936
9bdc770c 4937int fork_agent(pid_t *pid, const int except[], unsigned n_except, const char *path, ...) {
6bb92a16
LP
4938 pid_t parent_pid, agent_pid;
4939 int fd;
4940 bool stdout_is_tty, stderr_is_tty;
4941 unsigned n, i;
4942 va_list ap;
4943 char **l;
4944
4945 assert(pid);
4946 assert(path);
4947
4948 parent_pid = getpid();
4949
4950 /* Spawns a temporary TTY agent, making sure it goes away when
4951 * we go away */
4952
4953 agent_pid = fork();
4954 if (agent_pid < 0)
4955 return -errno;
4956
4957 if (agent_pid != 0) {
4958 *pid = agent_pid;
4959 return 0;
4960 }
4961
4962 /* In the child:
4963 *
4964 * Make sure the agent goes away when the parent dies */
4965 if (prctl(PR_SET_PDEATHSIG, SIGTERM) < 0)
4966 _exit(EXIT_FAILURE);
4967
4968 /* Check whether our parent died before we were able
4969 * to set the death signal */
4970 if (getppid() != parent_pid)
4971 _exit(EXIT_SUCCESS);
4972
4973 /* Don't leak fds to the agent */
9bdc770c 4974 close_all_fds(except, n_except);
6bb92a16
LP
4975
4976 stdout_is_tty = isatty(STDOUT_FILENO);
4977 stderr_is_tty = isatty(STDERR_FILENO);
4978
4979 if (!stdout_is_tty || !stderr_is_tty) {
4980 /* Detach from stdout/stderr. and reopen
4981 * /dev/tty for them. This is important to
4982 * ensure that when systemctl is started via
4983 * popen() or a similar call that expects to
4984 * read EOF we actually do generate EOF and
4985 * not delay this indefinitely by because we
4986 * keep an unused copy of stdin around. */
4987 fd = open("/dev/tty", O_WRONLY);
4988 if (fd < 0) {
4989 log_error("Failed to open /dev/tty: %m");
4990 _exit(EXIT_FAILURE);
4991 }
4992
4993 if (!stdout_is_tty)
4994 dup2(fd, STDOUT_FILENO);
4995
4996 if (!stderr_is_tty)
4997 dup2(fd, STDERR_FILENO);
4998
4999 if (fd > 2)
5000 close(fd);
5001 }
5002
5003 /* Count arguments */
5004 va_start(ap, path);
5005 for (n = 0; va_arg(ap, char*); n++)
5006 ;
5007 va_end(ap);
5008
5009 /* Allocate strv */
5010 l = alloca(sizeof(char *) * (n + 1));
5011
5012 /* Fill in arguments */
5013 va_start(ap, path);
5014 for (i = 0; i <= n; i++)
5015 l[i] = va_arg(ap, char*);
5016 va_end(ap);
5017
5018 execv(path, l);
5019 _exit(EXIT_FAILURE);
5020}
68faf98c
LP
5021
5022int setrlimit_closest(int resource, const struct rlimit *rlim) {
5023 struct rlimit highest, fixed;
5024
5025 assert(rlim);
5026
5027 if (setrlimit(resource, rlim) >= 0)
5028 return 0;
5029
5030 if (errno != EPERM)
5031 return -errno;
5032
5033 /* So we failed to set the desired setrlimit, then let's try
5034 * to get as close as we can */
5035 assert_se(getrlimit(resource, &highest) == 0);
5036
5037 fixed.rlim_cur = MIN(rlim->rlim_cur, highest.rlim_max);
5038 fixed.rlim_max = MIN(rlim->rlim_max, highest.rlim_max);
5039
5040 if (setrlimit(resource, &fixed) < 0)
5041 return -errno;
5042
5043 return 0;
5044}
3d9a4122 5045
ab94af92
LP
5046int getenv_for_pid(pid_t pid, const char *field, char **_value) {
5047 char path[sizeof("/proc/")-1+10+sizeof("/environ")], *value = NULL;
5048 int r;
5049 FILE *f;
5050 bool done = false;
5051 size_t l;
5052
5053 assert(field);
5054 assert(_value);
5055
5056 if (pid == 0)
5057 pid = getpid();
5058
5059 snprintf(path, sizeof(path), "/proc/%lu/environ", (unsigned long) pid);
5060 char_array_0(path);
5061
5062 f = fopen(path, "re");
5063 if (!f)
5064 return -errno;
5065
5066 l = strlen(field);
5067 r = 0;
5068
5069 do {
5070 char line[LINE_MAX];
5071 unsigned i;
5072
5073 for (i = 0; i < sizeof(line)-1; i++) {
5074 int c;
5075
5076 c = getc(f);
5077 if (_unlikely_(c == EOF)) {
5078 done = true;
5079 break;
5080 } else if (c == 0)
5081 break;
5082
5083 line[i] = c;
5084 }
5085 line[i] = 0;
5086
5087 if (memcmp(line, field, l) == 0 && line[l] == '=') {
5088 value = strdup(line + l + 1);
5089 if (!value) {
5090 r = -ENOMEM;
5091 break;
5092 }
5093
5094 r = 1;
5095 break;
5096 }
5097
5098 } while (!done);
5099
5100 fclose(f);
5101
5102 if (r >= 0)
5103 *_value = value;
5104
5105 return r;
5106}
d889a206
LP
5107
5108int can_sleep(const char *type) {
e67f47e5 5109 char *w, *state;
d889a206 5110 size_t l, k;
d889a206 5111 int r;
e67f47e5 5112 _cleanup_free_ char *p = NULL;
d889a206
LP
5113
5114 assert(type);
5115
679b7d79
LP
5116 /* If /sys is read-only we cannot sleep */
5117 if (access("/sys/power/state", W_OK) < 0)
5118 return false;
5119
d889a206
LP
5120 r = read_one_line_file("/sys/power/state", &p);
5121 if (r < 0)
679b7d79 5122 return false;
d889a206
LP
5123
5124 k = strlen(type);
e67f47e5
LP
5125 FOREACH_WORD_SEPARATOR(w, l, p, WHITESPACE, state)
5126 if (l == k && memcmp(w, type, l) == 0)
5127 return true;
d889a206 5128
e67f47e5 5129 return false;
d889a206 5130}
49dbfa7b 5131
6524990f
LP
5132int can_sleep_disk(const char *type) {
5133 char *w, *state;
5134 size_t l, k;
5135 int r;
5136 _cleanup_free_ char *p = NULL;
5137
5138 assert(type);
5139
679b7d79
LP
5140 /* If /sys is read-only we cannot sleep */
5141 if (access("/sys/power/state", W_OK) < 0 ||
5142 access("/sys/power/disk", W_OK) < 0)
5143 return false;
5144
6524990f
LP
5145 r = read_one_line_file("/sys/power/disk", &p);
5146 if (r < 0)
679b7d79 5147 return false;
6524990f
LP
5148
5149 k = strlen(type);
5150 FOREACH_WORD_SEPARATOR(w, l, p, WHITESPACE, state) {
5151 if (l == k && memcmp(w, type, l) == 0)
5152 return true;
5153
5154 if (l == k + 2 && w[0] == '[' && memcmp(w + 1, type, l - 2) == 0 && w[l-1] == ']')
5155 return true;
5156 }
5157
5158 return false;
5159}
5160
49dbfa7b
LP
5161bool is_valid_documentation_url(const char *url) {
5162 assert(url);
5163
5164 if (startswith(url, "http://") && url[7])
5165 return true;
5166
5167 if (startswith(url, "https://") && url[8])
5168 return true;
5169
5170 if (startswith(url, "file:") && url[5])
5171 return true;
5172
5173 if (startswith(url, "info:") && url[5])
5174 return true;
5175
5176 if (startswith(url, "man:") && url[4])
5177 return true;
5178
5179 return false;
5180}
9be346c9
HH
5181
5182bool in_initrd(void) {
a05f97b3 5183 static __thread int saved = -1;
825c6fe5 5184 struct statfs s;
8f33b5b8 5185
825c6fe5
LP
5186 if (saved >= 0)
5187 return saved;
5188
5189 /* We make two checks here:
5190 *
5191 * 1. the flag file /etc/initrd-release must exist
5192 * 2. the root file system must be a memory file system
5193 *
5194 * The second check is extra paranoia, since misdetecting an
5195 * initrd can have bad bad consequences due the initrd
5196 * emptying when transititioning to the main systemd.
5197 */
5198
5199 saved = access("/etc/initrd-release", F_OK) >= 0 &&
5200 statfs("/", &s) >= 0 &&
943aad8c 5201 is_temporary_fs(&s);
9be346c9 5202
8f33b5b8 5203 return saved;
9be346c9 5204}
069cfc85
LP
5205
5206void warn_melody(void) {
e67f47e5 5207 _cleanup_close_ int fd = -1;
069cfc85
LP
5208
5209 fd = open("/dev/console", O_WRONLY|O_CLOEXEC|O_NOCTTY);
5210 if (fd < 0)
5211 return;
5212
040f18ea 5213 /* Yeah, this is synchronous. Kinda sucks. But well... */
069cfc85
LP
5214
5215 ioctl(fd, KIOCSOUND, (int)(1193180/440));
5216 usleep(125*USEC_PER_MSEC);
5217
5218 ioctl(fd, KIOCSOUND, (int)(1193180/220));
5219 usleep(125*USEC_PER_MSEC);
5220
5221 ioctl(fd, KIOCSOUND, (int)(1193180/220));
5222 usleep(125*USEC_PER_MSEC);
5223
5224 ioctl(fd, KIOCSOUND, 0);
069cfc85 5225}
cd3bd60a
LP
5226
5227int make_console_stdio(void) {
5228 int fd, r;
5229
5230 /* Make /dev/console the controlling terminal and stdin/stdout/stderr */
5231
5232 fd = acquire_terminal("/dev/console", false, true, true, (usec_t) -1);
5233 if (fd < 0) {
5234 log_error("Failed to acquire terminal: %s", strerror(-fd));
5235 return fd;
5236 }
5237
5238 r = make_stdio(fd);
5239 if (r < 0) {
5240 log_error("Failed to duplicate terminal fd: %s", strerror(-r));
5241 return r;
5242 }
5243
5244 return 0;
5245}
7c5f152a
LP
5246
5247int get_home_dir(char **_h) {
5248 char *h;
5249 const char *e;
5250 uid_t u;
5251 struct passwd *p;
5252
5253 assert(_h);
5254
5255 /* Take the user specified one */
5256 e = getenv("HOME");
5257 if (e) {
5258 h = strdup(e);
5259 if (!h)
5260 return -ENOMEM;
5261
5262 *_h = h;
5263 return 0;
5264 }
5265
5266 /* Hardcode home directory for root to avoid NSS */
5267 u = getuid();
5268 if (u == 0) {
5269 h = strdup("/root");
5270 if (!h)
5271 return -ENOMEM;
5272
5273 *_h = h;
5274 return 0;
5275 }
5276
5277 /* Check the database... */
5278 errno = 0;
5279 p = getpwuid(u);
5280 if (!p)
e67f47e5 5281 return errno ? -errno : -ESRCH;
7c5f152a
LP
5282
5283 if (!path_is_absolute(p->pw_dir))
5284 return -EINVAL;
5285
5286 h = strdup(p->pw_dir);
5287 if (!h)
5288 return -ENOMEM;
5289
5290 *_h = h;
5291 return 0;
5292}
5293
2fbe635a
LP
5294void fclosep(FILE **f) {
5295 if (*f)
5296 fclose(*f);
5297}
e67f47e5 5298
e985665d
ZJS
5299void pclosep(FILE **f) {
5300 if (*f)
5301 pclose(*f);
5302}
5303
e67f47e5
LP
5304void closep(int *fd) {
5305 if (*fd >= 0)
5306 close_nointr_nofail(*fd);
5307}
a05f97b3
LP
5308
5309void closedirp(DIR **d) {
5310 if (*d)
5311 closedir(*d);
5312}
25ea79fe 5313
0b507b17
LP
5314bool filename_is_safe(const char *p) {
5315
5316 if (isempty(p))
5317 return false;
5318
5319 if (strchr(p, '/'))
5320 return false;
5321
5322 if (streq(p, "."))
5323 return false;
5324
5325 if (streq(p, ".."))
5326 return false;
5327
5328 if (strlen(p) > FILENAME_MAX)
5329 return false;
5330
5331 return true;
5332}
5333
5334bool string_is_safe(const char *p) {
5335 const char *t;
5336
5337 assert(p);
5338
5339 for (t = p; *t; t++) {
01539d6e 5340 if (*t > 0 && *t < ' ')
0b507b17
LP
5341 return false;
5342
011afa76 5343 if (strchr("\\\"\'", *t))
0b507b17
LP
5344 return false;
5345 }
5346
5347 return true;
5348}
cfbc22ab 5349
4d1a6904
LP
5350bool string_has_cc(const char *p) {
5351 const char *t;
5352
5353 assert(p);
5354
5355 for (t = p; *t; t++)
5356 if (*t > 0 && *t < ' ')
5357 return true;
5358
5359 return false;
5360}
5361
e884315e
LP
5362bool path_is_safe(const char *p) {
5363
5364 if (isempty(p))
5365 return false;
5366
5367 if (streq(p, "..") || startswith(p, "../") || endswith(p, "/..") || strstr(p, "/../"))
5368 return false;
5369
5370 if (strlen(p) > PATH_MAX)
5371 return false;
5372
5373 /* The following two checks are not really dangerous, but hey, they still are confusing */
5374 if (streq(p, ".") || startswith(p, "./") || endswith(p, "/.") || strstr(p, "/./"))
5375 return false;
5376
5377 if (strstr(p, "//"))
5378 return false;
5379
5380 return true;
5381}
5382
a9e12476
KS
5383/* hey glibc, APIs with callbacks without a user pointer are so useless */
5384void *xbsearch_r(const void *key, const void *base, size_t nmemb, size_t size,
1c574591 5385 int (*compar) (const void *, const void *, void *), void *arg) {
a9e12476
KS
5386 size_t l, u, idx;
5387 const void *p;
5388 int comparison;
5389
5390 l = 0;
5391 u = nmemb;
5392 while (l < u) {
5393 idx = (l + u) / 2;
5394 p = (void *)(((const char *) base) + (idx * size));
5395 comparison = compar(key, p, arg);
5396 if (comparison < 0)
5397 u = idx;
5398 else if (comparison > 0)
5399 l = idx + 1;
5400 else
5401 return (void *)p;
5402 }
5403 return NULL;
5404}
09017585
MS
5405
5406bool is_locale_utf8(void) {
5407 const char *set;
5408 static int cached_answer = -1;
5409
5410 if (cached_answer >= 0)
5411 goto out;
5412
5413 if (!setlocale(LC_ALL, "")) {
5414 cached_answer = true;
5415 goto out;
5416 }
5417
5418 set = nl_langinfo(CODESET);
5419 if (!set) {
5420 cached_answer = true;
5421 goto out;
5422 }
5423
5424 cached_answer = streq(set, "UTF-8");
5425out:
5426 return (bool)cached_answer;
5427}
c339d977
MS
5428
5429const char *draw_special_char(DrawSpecialChar ch) {
5430 static const char *draw_table[2][_DRAW_SPECIAL_CHAR_MAX] = {
5431 /* UTF-8 */ {
45a5ff0d
MS
5432 [DRAW_TREE_VERT] = "\342\224\202 ", /* │ */
5433 [DRAW_TREE_BRANCH] = "\342\224\234\342\224\200", /* ├─ */
5434 [DRAW_TREE_RIGHT] = "\342\224\224\342\224\200", /* └─ */
55c0b89c 5435 [DRAW_TREE_SPACE] = " ", /* */
45a5ff0d 5436 [DRAW_TRIANGULAR_BULLET] = "\342\200\243 ", /* ‣ */
c339d977
MS
5437 },
5438 /* ASCII fallback */ {
45a5ff0d
MS
5439 [DRAW_TREE_VERT] = "| ",
5440 [DRAW_TREE_BRANCH] = "|-",
5441 [DRAW_TREE_RIGHT] = "`-",
55c0b89c 5442 [DRAW_TREE_SPACE] = " ",
45a5ff0d 5443 [DRAW_TRIANGULAR_BULLET] = "> ",
c339d977
MS
5444 }
5445 };
5446
5447 return draw_table[!is_locale_utf8()][ch];
5448}
409bc9c3
LP
5449
5450char *strreplace(const char *text, const char *old_string, const char *new_string) {
5451 const char *f;
5452 char *t, *r;
5453 size_t l, old_len, new_len;
5454
5455 assert(text);
5456 assert(old_string);
5457 assert(new_string);
5458
5459 old_len = strlen(old_string);
5460 new_len = strlen(new_string);
5461
5462 l = strlen(text);
5463 r = new(char, l+1);
5464 if (!r)
5465 return NULL;
5466
5467 f = text;
5468 t = r;
5469 while (*f) {
5470 char *a;
5471 size_t d, nl;
5472
5473 if (!startswith(f, old_string)) {
5474 *(t++) = *(f++);
5475 continue;
5476 }
5477
5478 d = t - r;
5479 nl = l - old_len + new_len;
5480 a = realloc(r, nl + 1);
5481 if (!a)
5482 goto oom;
5483
5484 l = nl;
5485 r = a;
5486 t = r + d;
5487
5488 t = stpcpy(t, new_string);
5489 f += old_len;
5490 }
5491
5492 *t = 0;
5493 return r;
5494
5495oom:
5496 free(r);
5497 return NULL;
5498}
e8bc0ea2
LP
5499
5500char *strip_tab_ansi(char **ibuf, size_t *_isz) {
660ddc72 5501 const char *i, *begin = NULL;
e8bc0ea2
LP
5502 enum {
5503 STATE_OTHER,
5504 STATE_ESCAPE,
5505 STATE_BRACKET
5506 } state = STATE_OTHER;
5507 char *obuf = NULL;
5508 size_t osz = 0, isz;
5509 FILE *f;
5510
5511 assert(ibuf);
5512 assert(*ibuf);
5513
5514 /* Strips ANSI color and replaces TABs by 8 spaces */
5515
5516 isz = _isz ? *_isz : strlen(*ibuf);
5517
5518 f = open_memstream(&obuf, &osz);
5519 if (!f)
5520 return NULL;
5521
5522 for (i = *ibuf; i < *ibuf + isz + 1; i++) {
5523
5524 switch (state) {
5525
5526 case STATE_OTHER:
5527 if (i >= *ibuf + isz) /* EOT */
5528 break;
5529 else if (*i == '\x1B')
5530 state = STATE_ESCAPE;
5531 else if (*i == '\t')
5532 fputs(" ", f);
5533 else
5534 fputc(*i, f);
5535 break;
5536
5537 case STATE_ESCAPE:
5538 if (i >= *ibuf + isz) { /* EOT */
5539 fputc('\x1B', f);
5540 break;
5541 } else if (*i == '[') {
5542 state = STATE_BRACKET;
5543 begin = i + 1;
5544 } else {
5545 fputc('\x1B', f);
5546 fputc(*i, f);
5547 state = STATE_OTHER;
5548 }
5549
5550 break;
5551
5552 case STATE_BRACKET:
5553
5554 if (i >= *ibuf + isz || /* EOT */
5555 (!(*i >= '0' && *i <= '9') && *i != ';' && *i != 'm')) {
5556 fputc('\x1B', f);
5557 fputc('[', f);
5558 state = STATE_OTHER;
5559 i = begin-1;
5560 } else if (*i == 'm')
5561 state = STATE_OTHER;
5562 break;
5563 }
5564 }
5565
5566 if (ferror(f)) {
5567 fclose(f);
5568 free(obuf);
5569 return NULL;
5570 }
5571
5572 fclose(f);
5573
5574 free(*ibuf);
5575 *ibuf = obuf;
5576
5577 if (_isz)
5578 *_isz = osz;
5579
5580 return obuf;
5581}
240dbaa4
LP
5582
5583int on_ac_power(void) {
5584 bool found_offline = false, found_online = false;
5585 _cleanup_closedir_ DIR *d = NULL;
5586
5587 d = opendir("/sys/class/power_supply");
5588 if (!d)
5589 return -errno;
5590
5591 for (;;) {
5592 struct dirent *de;
5593 union dirent_storage buf;
240dbaa4
LP
5594 _cleanup_close_ int fd = -1, device = -1;
5595 char contents[6];
5596 ssize_t n;
5597 int k;
5598
5599 k = readdir_r(d, &buf.de, &de);
5600 if (k != 0)
5601 return -k;
5602
5603 if (!de)
5604 break;
5605
5606 if (ignore_file(de->d_name))
5607 continue;
5608
5609 device = openat(dirfd(d), de->d_name, O_DIRECTORY|O_RDONLY|O_CLOEXEC|O_NOCTTY);
5610 if (device < 0) {
5611 if (errno == ENOENT || errno == ENOTDIR)
5612 continue;
5613
5614 return -errno;
5615 }
5616
5617 fd = openat(device, "type", O_RDONLY|O_CLOEXEC|O_NOCTTY);
5618 if (fd < 0) {
5619 if (errno == ENOENT)
5620 continue;
5621
5622 return -errno;
5623 }
5624
5625 n = read(fd, contents, sizeof(contents));
5626 if (n < 0)
5627 return -errno;
5628
5629 if (n != 6 || memcmp(contents, "Mains\n", 6))
5630 continue;
5631
5632 close_nointr_nofail(fd);
5633 fd = openat(device, "online", O_RDONLY|O_CLOEXEC|O_NOCTTY);
5634 if (fd < 0) {
5635 if (errno == ENOENT)
5636 continue;
5637
5638 return -errno;
5639 }
5640
5641 n = read(fd, contents, sizeof(contents));
5642 if (n < 0)
5643 return -errno;
5644
5645 if (n != 2 || contents[1] != '\n')
5646 return -EIO;
5647
5648 if (contents[0] == '1') {
5649 found_online = true;
5650 break;
5651 } else if (contents[0] == '0')
5652 found_offline = true;
5653 else
5654 return -EIO;
5655 }
5656
5657 return found_online || !found_offline;
5658}
fabe5c0e
LP
5659
5660static int search_and_fopen_internal(const char *path, const char *mode, char **search, FILE **_f) {
5661 char **i;
5662
5663 assert(path);
5664 assert(mode);
5665 assert(_f);
5666
5667 if (!path_strv_canonicalize_uniq(search))
5668 return -ENOMEM;
5669
5670 STRV_FOREACH(i, search) {
5671 _cleanup_free_ char *p = NULL;
5672 FILE *f;
5673
5674 p = strjoin(*i, "/", path, NULL);
5675 if (!p)
5676 return -ENOMEM;
5677
5678 f = fopen(p, mode);
5679 if (f) {
5680 *_f = f;
5681 return 0;
5682 }
5683
5684 if (errno != ENOENT)
5685 return -errno;
5686 }
5687
5688 return -ENOENT;
5689}
5690
5691int search_and_fopen(const char *path, const char *mode, const char **search, FILE **_f) {
5692 _cleanup_strv_free_ char **copy = NULL;
5693
5694 assert(path);
5695 assert(mode);
5696 assert(_f);
5697
5698 if (path_is_absolute(path)) {
5699 FILE *f;
5700
5701 f = fopen(path, mode);
5702 if (f) {
5703 *_f = f;
5704 return 0;
5705 }
5706
5707 return -errno;
5708 }
5709
5710 copy = strv_copy((char**) search);
5711 if (!copy)
5712 return -ENOMEM;
5713
5714 return search_and_fopen_internal(path, mode, copy, _f);
5715}
5716
5717int search_and_fopen_nulstr(const char *path, const char *mode, const char *search, FILE **_f) {
5718 _cleanup_strv_free_ char **s = NULL;
5719
5720 if (path_is_absolute(path)) {
5721 FILE *f;
5722
5723 f = fopen(path, mode);
5724 if (f) {
5725 *_f = f;
5726 return 0;
5727 }
5728
5729 return -errno;
5730 }
5731
5732 s = strv_split_nulstr(search);
5733 if (!s)
5734 return -ENOMEM;
5735
5736 return search_and_fopen_internal(path, mode, s, _f);
5737}
c17ec25e 5738
d34cd374 5739int create_tmp_dir(char template[], char** dir_name) {
c17ec25e 5740 int r = 0;
d34cd374 5741 char *d, *dt;
c17ec25e
MS
5742 mode_t _cleanup_umask_ u;
5743
5744 assert(dir_name);
5745
d34cd374 5746 u = umask(0077);
c17ec25e
MS
5747 d = mkdtemp(template);
5748 if (!d) {
d34cd374
ZJS
5749 log_error("Can't create directory %s: %m", template);
5750 return -errno;
c17ec25e
MS
5751 }
5752
d34cd374
ZJS
5753 dt = strjoin(d, "/tmp", NULL);
5754 if (!dt) {
c17ec25e 5755 r = log_oom();
f36a783c 5756 goto fail3;
c17ec25e
MS
5757 }
5758
d34cd374
ZJS
5759 umask(0000);
5760 r = mkdir(dt, 0777);
5761 if (r) {
5762 log_error("Can't create directory %s: %m", dt);
5763 r = -errno;
f36a783c 5764 goto fail2;
d34cd374
ZJS
5765 }
5766 log_debug("Created temporary directory %s", dt);
5767
5768 r = chmod(dt, 0777 | S_ISVTX);
5769 if (r < 0) {
5770 log_error("Failed to chmod %s: %m", dt);
5771 r = -errno;
5772 goto fail1;
c17ec25e 5773 }
d34cd374 5774 log_debug("Set sticky bit on %s", dt);
c17ec25e 5775
d34cd374 5776 *dir_name = dt;
c17ec25e
MS
5777
5778 return 0;
d34cd374
ZJS
5779fail1:
5780 rmdir(dt);
5781fail2:
f36a783c
VP
5782 free(dt);
5783fail3:
d34cd374 5784 rmdir(template);
c17ec25e
MS
5785 return r;
5786}
66e35261
LP
5787
5788char *strextend(char **x, ...) {
5789 va_list ap;
5790 size_t f, l;
5791 char *r, *p;
5792
5793 assert(x);
5794
5795 l = f = *x ? strlen(*x) : 0;
5796
5797 va_start(ap, x);
5798 for (;;) {
5799 const char *t;
5800 size_t n;
5801
5802 t = va_arg(ap, const char *);
5803 if (!t)
5804 break;
5805
5806 n = strlen(t);
5807 if (n > ((size_t) -1) - l) {
5808 va_end(ap);
5809 return NULL;
5810 }
5811
5812 l += n;
5813 }
5814 va_end(ap);
5815
5816 r = realloc(*x, l+1);
5817 if (!r)
5818 return NULL;
5819
5820 p = r + f;
5821
5822 va_start(ap, x);
5823 for (;;) {
5824 const char *t;
5825
5826 t = va_arg(ap, const char *);
5827 if (!t)
5828 break;
5829
5830 p = stpcpy(p, t);
5831 }
5832 va_end(ap);
5833
5834 *p = 0;
5835 *x = r;
5836
5837 return r + l;
5838}
9a17484d
LP
5839
5840char *strrep(const char *s, unsigned n) {
5841 size_t l;
5842 char *r, *p;
5843 unsigned i;
5844
5845 assert(s);
5846
5847 l = strlen(s);
5848 p = r = malloc(l * n + 1);
5849 if (!r)
5850 return NULL;
5851
5852 for (i = 0; i < n; i++)
5853 p = stpcpy(p, s);
5854
5855 *p = 0;
5856 return r;
5857}
392d5b37
LP
5858
5859void* greedy_realloc(void **p, size_t *allocated, size_t need) {
5860 size_t a;
5861 void *q;
5862
5863 if (*allocated >= need)
5864 return *p;
5865
5866 a = MAX(64, need * 2);
5867 q = realloc(*p, a);
5868 if (!q)
5869 return NULL;
5870
5871 *p = q;
5872 *allocated = a;
5873 return q;
5874}