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