]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/shared/util.c
build-sys: make rc-local support part of SYSV compat
[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
4447int get_group_creds(const char **groupname, gid_t *gid) {
4448 struct group *g;
4449 gid_t id;
4450
4451 assert(groupname);
4452
4453 /* We enforce some special rules for gid=0: in order to avoid
4454 * NSS lookups for root we hardcode its data. */
4455
4456 if (streq(*groupname, "root") || streq(*groupname, "0")) {
4457 *groupname = "root";
4458
4459 if (gid)
4460 *gid = 0;
4461
4462 return 0;
4463 }
4464
4465 if (parse_gid(*groupname, &id) >= 0) {
4466 errno = 0;
4467 g = getgrgid(id);
4468
4469 if (g)
4470 *groupname = g->gr_name;
4471 } else {
4472 errno = 0;
4473 g = getgrnam(*groupname);
4474 }
4475
4476 if (!g)
4477 return errno != 0 ? -errno : -ESRCH;
4478
4479 if (gid)
4480 *gid = g->gr_gid;
4481
1cccf435
MV
4482 return 0;
4483}
4484
43673799
LP
4485int in_group(const char *name) {
4486 gid_t gid, *gids;
4487 int ngroups_max, r, i;
4488
4489 r = get_group_creds(&name, &gid);
4490 if (r < 0)
4491 return r;
4492
4493 if (getgid() == gid)
4494 return 1;
4495
4496 if (getegid() == gid)
4497 return 1;
4498
4499 ngroups_max = sysconf(_SC_NGROUPS_MAX);
4500 assert(ngroups_max > 0);
4501
4502 gids = alloca(sizeof(gid_t) * ngroups_max);
4503
4504 r = getgroups(ngroups_max, gids);
4505 if (r < 0)
4506 return -errno;
4507
4508 for (i = 0; i < r; i++)
4509 if (gids[i] == gid)
4510 return 1;
4511
4512 return 0;
4513}
4514
8092a428
LP
4515int glob_exists(const char *path) {
4516 glob_t g;
4517 int r, k;
4518
4519 assert(path);
4520
4521 zero(g);
4522 errno = 0;
4523 k = glob(path, GLOB_NOSORT|GLOB_BRACE, NULL, &g);
4524
4525 if (k == GLOB_NOMATCH)
4526 r = 0;
4527 else if (k == GLOB_NOSPACE)
4528 r = -ENOMEM;
4529 else if (k == 0)
4530 r = !strv_isempty(g.gl_pathv);
4531 else
4532 r = errno ? -errno : -EIO;
4533
4534 globfree(&g);
4535
4536 return r;
4537}
4538
83096483
LP
4539int dirent_ensure_type(DIR *d, struct dirent *de) {
4540 struct stat st;
4541
4542 assert(d);
4543 assert(de);
4544
4545 if (de->d_type != DT_UNKNOWN)
4546 return 0;
4547
4548 if (fstatat(dirfd(d), de->d_name, &st, AT_SYMLINK_NOFOLLOW) < 0)
4549 return -errno;
4550
4551 de->d_type =
4552 S_ISREG(st.st_mode) ? DT_REG :
4553 S_ISDIR(st.st_mode) ? DT_DIR :
4554 S_ISLNK(st.st_mode) ? DT_LNK :
4555 S_ISFIFO(st.st_mode) ? DT_FIFO :
4556 S_ISSOCK(st.st_mode) ? DT_SOCK :
4557 S_ISCHR(st.st_mode) ? DT_CHR :
4558 S_ISBLK(st.st_mode) ? DT_BLK :
4559 DT_UNKNOWN;
4560
4561 return 0;
4562}
4563
4564int in_search_path(const char *path, char **search) {
4565 char **i, *parent;
4566 int r;
4567
9eb977db 4568 r = path_get_parent(path, &parent);
83096483
LP
4569 if (r < 0)
4570 return r;
4571
4572 r = 0;
4573
4574 STRV_FOREACH(i, search) {
4575 if (path_equal(parent, *i)) {
4576 r = 1;
4577 break;
4578 }
4579 }
4580
4581 free(parent);
4582
4583 return r;
4584}
4585
034a2a52
LP
4586int get_files_in_directory(const char *path, char ***list) {
4587 DIR *d;
4588 int r = 0;
4589 unsigned n = 0;
4590 char **l = NULL;
4591
4592 assert(path);
d60ef526
LP
4593
4594 /* Returns all files in a directory in *list, and the number
4595 * of files as return value. If list is NULL returns only the
4596 * number */
034a2a52
LP
4597
4598 d = opendir(path);
8ea913b2
LP
4599 if (!d)
4600 return -errno;
4601
034a2a52 4602 for (;;) {
7d5e9c0f
LP
4603 struct dirent *de;
4604 union dirent_storage buf;
034a2a52
LP
4605 int k;
4606
7d5e9c0f 4607 k = readdir_r(d, &buf.de, &de);
034a2a52
LP
4608 if (k != 0) {
4609 r = -k;
4610 goto finish;
4611 }
4612
4613 if (!de)
4614 break;
4615
4616 dirent_ensure_type(d, de);
4617
4618 if (!dirent_is_file(de))
4619 continue;
4620
d60ef526
LP
4621 if (list) {
4622 if ((unsigned) r >= n) {
4623 char **t;
034a2a52 4624
d60ef526
LP
4625 n = MAX(16, 2*r);
4626 t = realloc(l, sizeof(char*) * n);
4627 if (!t) {
4628 r = -ENOMEM;
4629 goto finish;
4630 }
034a2a52 4631
d60ef526
LP
4632 l = t;
4633 }
034a2a52 4634
d60ef526 4635 assert((unsigned) r < n);
034a2a52 4636
d60ef526
LP
4637 l[r] = strdup(de->d_name);
4638 if (!l[r]) {
4639 r = -ENOMEM;
4640 goto finish;
4641 }
034a2a52 4642
d60ef526
LP
4643 l[++r] = NULL;
4644 } else
4645 r++;
034a2a52
LP
4646 }
4647
4648finish:
4649 if (d)
4650 closedir(d);
4651
d60ef526
LP
4652 if (r >= 0) {
4653 if (list)
4654 *list = l;
4655 } else
034a2a52
LP
4656 strv_free(l);
4657
4658 return r;
4659}
4660
b7def684 4661char *strjoin(const char *x, ...) {
911a4828
LP
4662 va_list ap;
4663 size_t l;
4664 char *r, *p;
4665
4666 va_start(ap, x);
4667
4668 if (x) {
4669 l = strlen(x);
4670
4671 for (;;) {
4672 const char *t;
040f18ea 4673 size_t n;
911a4828
LP
4674
4675 t = va_arg(ap, const char *);
4676 if (!t)
4677 break;
4678
040f18ea 4679 n = strlen(t);
e98055de
LN
4680 if (n > ((size_t) -1) - l) {
4681 va_end(ap);
040f18ea 4682 return NULL;
e98055de 4683 }
040f18ea
LP
4684
4685 l += n;
911a4828
LP
4686 }
4687 } else
4688 l = 0;
4689
4690 va_end(ap);
4691
4692 r = new(char, l+1);
4693 if (!r)
4694 return NULL;
4695
4696 if (x) {
4697 p = stpcpy(r, x);
4698
4699 va_start(ap, x);
4700
4701 for (;;) {
4702 const char *t;
4703
4704 t = va_arg(ap, const char *);
4705 if (!t)
4706 break;
4707
4708 p = stpcpy(p, t);
4709 }
8ea913b2
LP
4710
4711 va_end(ap);
911a4828
LP
4712 } else
4713 r[0] = 0;
4714
4715 return r;
4716}
4717
b636465b
LP
4718bool is_main_thread(void) {
4719 static __thread int cached = 0;
4720
4721 if (_unlikely_(cached == 0))
4722 cached = getpid() == gettid() ? 1 : -1;
4723
4724 return cached > 0;
4725}
4726
94959f0f
LP
4727int block_get_whole_disk(dev_t d, dev_t *ret) {
4728 char *p, *s;
4729 int r;
4730 unsigned n, m;
4731
4732 assert(ret);
4733
4734 /* If it has a queue this is good enough for us */
4735 if (asprintf(&p, "/sys/dev/block/%u:%u/queue", major(d), minor(d)) < 0)
4736 return -ENOMEM;
4737
4738 r = access(p, F_OK);
4739 free(p);
4740
4741 if (r >= 0) {
4742 *ret = d;
4743 return 0;
4744 }
4745
4746 /* If it is a partition find the originating device */
4747 if (asprintf(&p, "/sys/dev/block/%u:%u/partition", major(d), minor(d)) < 0)
4748 return -ENOMEM;
4749
4750 r = access(p, F_OK);
4751 free(p);
4752
4753 if (r < 0)
4754 return -ENOENT;
4755
4756 /* Get parent dev_t */
4757 if (asprintf(&p, "/sys/dev/block/%u:%u/../dev", major(d), minor(d)) < 0)
4758 return -ENOMEM;
4759
4760 r = read_one_line_file(p, &s);
4761 free(p);
4762
4763 if (r < 0)
4764 return r;
4765
4766 r = sscanf(s, "%u:%u", &m, &n);
4767 free(s);
4768
4769 if (r != 2)
4770 return -EINVAL;
4771
4772 /* Only return this if it is really good enough for us. */
4773 if (asprintf(&p, "/sys/dev/block/%u:%u/queue", m, n) < 0)
4774 return -ENOMEM;
4775
4776 r = access(p, F_OK);
4777 free(p);
4778
4779 if (r >= 0) {
4780 *ret = makedev(m, n);
4781 return 0;
4782 }
4783
4784 return -ENOENT;
4785}
4786
8d53b453 4787int file_is_priv_sticky(const char *p) {
ad293f5a
LP
4788 struct stat st;
4789
4790 assert(p);
4791
4792 if (lstat(p, &st) < 0)
4793 return -errno;
4794
4795 return
8d53b453 4796 (st.st_uid == 0 || st.st_uid == getuid()) &&
ad293f5a
LP
4797 (st.st_mode & S_ISVTX);
4798}
94959f0f 4799
f41607a6
LP
4800static const char *const ioprio_class_table[] = {
4801 [IOPRIO_CLASS_NONE] = "none",
4802 [IOPRIO_CLASS_RT] = "realtime",
4803 [IOPRIO_CLASS_BE] = "best-effort",
4804 [IOPRIO_CLASS_IDLE] = "idle"
4805};
4806
f8b69d1d 4807DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(ioprio_class, int, INT_MAX);
f41607a6
LP
4808
4809static const char *const sigchld_code_table[] = {
4810 [CLD_EXITED] = "exited",
4811 [CLD_KILLED] = "killed",
4812 [CLD_DUMPED] = "dumped",
4813 [CLD_TRAPPED] = "trapped",
4814 [CLD_STOPPED] = "stopped",
4815 [CLD_CONTINUED] = "continued",
4816};
4817
4818DEFINE_STRING_TABLE_LOOKUP(sigchld_code, int);
4819
4820static const char *const log_facility_unshifted_table[LOG_NFACILITIES] = {
4821 [LOG_FAC(LOG_KERN)] = "kern",
4822 [LOG_FAC(LOG_USER)] = "user",
4823 [LOG_FAC(LOG_MAIL)] = "mail",
4824 [LOG_FAC(LOG_DAEMON)] = "daemon",
4825 [LOG_FAC(LOG_AUTH)] = "auth",
4826 [LOG_FAC(LOG_SYSLOG)] = "syslog",
4827 [LOG_FAC(LOG_LPR)] = "lpr",
4828 [LOG_FAC(LOG_NEWS)] = "news",
4829 [LOG_FAC(LOG_UUCP)] = "uucp",
4830 [LOG_FAC(LOG_CRON)] = "cron",
4831 [LOG_FAC(LOG_AUTHPRIV)] = "authpriv",
4832 [LOG_FAC(LOG_FTP)] = "ftp",
4833 [LOG_FAC(LOG_LOCAL0)] = "local0",
4834 [LOG_FAC(LOG_LOCAL1)] = "local1",
4835 [LOG_FAC(LOG_LOCAL2)] = "local2",
4836 [LOG_FAC(LOG_LOCAL3)] = "local3",
4837 [LOG_FAC(LOG_LOCAL4)] = "local4",
4838 [LOG_FAC(LOG_LOCAL5)] = "local5",
4839 [LOG_FAC(LOG_LOCAL6)] = "local6",
4840 [LOG_FAC(LOG_LOCAL7)] = "local7"
4841};
4842
f8b69d1d 4843DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(log_facility_unshifted, int, LOG_FAC(~0));
f41607a6
LP
4844
4845static const char *const log_level_table[] = {
4846 [LOG_EMERG] = "emerg",
4847 [LOG_ALERT] = "alert",
4848 [LOG_CRIT] = "crit",
4849 [LOG_ERR] = "err",
4850 [LOG_WARNING] = "warning",
4851 [LOG_NOTICE] = "notice",
4852 [LOG_INFO] = "info",
4853 [LOG_DEBUG] = "debug"
4854};
4855
f8b69d1d 4856DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(log_level, int, LOG_DEBUG);
f41607a6
LP
4857
4858static const char* const sched_policy_table[] = {
4859 [SCHED_OTHER] = "other",
4860 [SCHED_BATCH] = "batch",
4861 [SCHED_IDLE] = "idle",
4862 [SCHED_FIFO] = "fifo",
4863 [SCHED_RR] = "rr"
4864};
4865
f8b69d1d 4866DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(sched_policy, int, INT_MAX);
f41607a6
LP
4867
4868static const char* const rlimit_table[] = {
4869 [RLIMIT_CPU] = "LimitCPU",
4870 [RLIMIT_FSIZE] = "LimitFSIZE",
4871 [RLIMIT_DATA] = "LimitDATA",
4872 [RLIMIT_STACK] = "LimitSTACK",
4873 [RLIMIT_CORE] = "LimitCORE",
4874 [RLIMIT_RSS] = "LimitRSS",
4875 [RLIMIT_NOFILE] = "LimitNOFILE",
4876 [RLIMIT_AS] = "LimitAS",
4877 [RLIMIT_NPROC] = "LimitNPROC",
4878 [RLIMIT_MEMLOCK] = "LimitMEMLOCK",
4879 [RLIMIT_LOCKS] = "LimitLOCKS",
4880 [RLIMIT_SIGPENDING] = "LimitSIGPENDING",
4881 [RLIMIT_MSGQUEUE] = "LimitMSGQUEUE",
4882 [RLIMIT_NICE] = "LimitNICE",
4883 [RLIMIT_RTPRIO] = "LimitRTPRIO",
4884 [RLIMIT_RTTIME] = "LimitRTTIME"
4885};
4886
4887DEFINE_STRING_TABLE_LOOKUP(rlimit, int);
4888
4889static const char* const ip_tos_table[] = {
4890 [IPTOS_LOWDELAY] = "low-delay",
4891 [IPTOS_THROUGHPUT] = "throughput",
4892 [IPTOS_RELIABILITY] = "reliability",
4893 [IPTOS_LOWCOST] = "low-cost",
4894};
4895
f8b69d1d 4896DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(ip_tos, int, 0xff);
f41607a6 4897
4e240ab0 4898static const char *const __signal_table[] = {
f41607a6
LP
4899 [SIGHUP] = "HUP",
4900 [SIGINT] = "INT",
4901 [SIGQUIT] = "QUIT",
4902 [SIGILL] = "ILL",
4903 [SIGTRAP] = "TRAP",
4904 [SIGABRT] = "ABRT",
4905 [SIGBUS] = "BUS",
4906 [SIGFPE] = "FPE",
4907 [SIGKILL] = "KILL",
4908 [SIGUSR1] = "USR1",
4909 [SIGSEGV] = "SEGV",
4910 [SIGUSR2] = "USR2",
4911 [SIGPIPE] = "PIPE",
4912 [SIGALRM] = "ALRM",
4913 [SIGTERM] = "TERM",
4914#ifdef SIGSTKFLT
4915 [SIGSTKFLT] = "STKFLT", /* Linux on SPARC doesn't know SIGSTKFLT */
4916#endif
4917 [SIGCHLD] = "CHLD",
4918 [SIGCONT] = "CONT",
4919 [SIGSTOP] = "STOP",
4920 [SIGTSTP] = "TSTP",
4921 [SIGTTIN] = "TTIN",
4922 [SIGTTOU] = "TTOU",
4923 [SIGURG] = "URG",
4924 [SIGXCPU] = "XCPU",
4925 [SIGXFSZ] = "XFSZ",
4926 [SIGVTALRM] = "VTALRM",
4927 [SIGPROF] = "PROF",
4928 [SIGWINCH] = "WINCH",
4929 [SIGIO] = "IO",
4930 [SIGPWR] = "PWR",
4931 [SIGSYS] = "SYS"
4932};
4933
4e240ab0
MS
4934DEFINE_PRIVATE_STRING_TABLE_LOOKUP(__signal, int);
4935
4936const char *signal_to_string(int signo) {
4937 static __thread char buf[12];
4938 const char *name;
4939
4940 name = __signal_to_string(signo);
4941 if (name)
4942 return name;
4943
4944 if (signo >= SIGRTMIN && signo <= SIGRTMAX)
4945 snprintf(buf, sizeof(buf) - 1, "RTMIN+%d", signo - SIGRTMIN);
4946 else
4947 snprintf(buf, sizeof(buf) - 1, "%d", signo);
4948 char_array_0(buf);
4949 return buf;
4950}
4951
4952int signal_from_string(const char *s) {
4953 int signo;
4954 int offset = 0;
4955 unsigned u;
4956
040f18ea 4957 signo = __signal_from_string(s);
4e240ab0
MS
4958 if (signo > 0)
4959 return signo;
4960
4961 if (startswith(s, "RTMIN+")) {
4962 s += 6;
4963 offset = SIGRTMIN;
4964 }
4965 if (safe_atou(s, &u) >= 0) {
4966 signo = (int) u + offset;
4967 if (signo > 0 && signo < _NSIG)
4968 return signo;
4969 }
4970 return -1;
4971}
65457142
FC
4972
4973bool kexec_loaded(void) {
4974 bool loaded = false;
4975 char *s;
4976
4977 if (read_one_line_file("/sys/kernel/kexec_loaded", &s) >= 0) {
4978 if (s[0] == '1')
4979 loaded = true;
4980 free(s);
4981 }
4982 return loaded;
4983}
fb9de93d
LP
4984
4985int strdup_or_null(const char *a, char **b) {
4986 char *c;
4987
4988 assert(b);
4989
4990 if (!a) {
4991 *b = NULL;
4992 return 0;
4993 }
4994
4995 c = strdup(a);
4996 if (!c)
4997 return -ENOMEM;
4998
4999 *b = c;
5000 return 0;
5001}
64685e0c 5002
87d2c1ff
LP
5003int prot_from_flags(int flags) {
5004
5005 switch (flags & O_ACCMODE) {
5006
5007 case O_RDONLY:
5008 return PROT_READ;
5009
5010 case O_WRONLY:
5011 return PROT_WRITE;
5012
5013 case O_RDWR:
5014 return PROT_READ|PROT_WRITE;
5015
5016 default:
5017 return -EINVAL;
5018 }
7c99e0c1 5019}
689b9a22 5020
babfc091 5021char *format_bytes(char *buf, size_t l, off_t t) {
c0f99c21 5022 unsigned i;
babfc091
LP
5023
5024 static const struct {
5025 const char *suffix;
5026 off_t factor;
5027 } table[] = {
32895bb3
LP
5028 { "E", 1024ULL*1024ULL*1024ULL*1024ULL*1024ULL*1024ULL },
5029 { "P", 1024ULL*1024ULL*1024ULL*1024ULL*1024ULL },
babfc091
LP
5030 { "T", 1024ULL*1024ULL*1024ULL*1024ULL },
5031 { "G", 1024ULL*1024ULL*1024ULL },
5032 { "M", 1024ULL*1024ULL },
5033 { "K", 1024ULL },
5034 };
5035
5036 for (i = 0; i < ELEMENTSOF(table); i++) {
5037
5038 if (t >= table[i].factor) {
5039 snprintf(buf, l,
5040 "%llu.%llu%s",
5041 (unsigned long long) (t / table[i].factor),
5042 (unsigned long long) (((t*10ULL) / table[i].factor) % 10ULL),
5043 table[i].suffix);
5044
5045 goto finish;
5046 }
5047 }
5048
5049 snprintf(buf, l, "%lluB", (unsigned long long) t);
5050
5051finish:
5052 buf[l-1] = 0;
5053 return buf;
5054
5055}
55d7bfc1
LP
5056
5057void* memdup(const void *p, size_t l) {
5058 void *r;
5059
5060 assert(p);
5061
5062 r = malloc(l);
5063 if (!r)
5064 return NULL;
5065
5066 memcpy(r, p, l);
5067 return r;
5068}
bb99a35a
LP
5069
5070int fd_inc_sndbuf(int fd, size_t n) {
5071 int r, value;
5072 socklen_t l = sizeof(value);
5073
5074 r = getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &value, &l);
5075 if (r >= 0 &&
5076 l == sizeof(value) &&
5077 (size_t) value >= n*2)
5078 return 0;
5079
5080 value = (int) n;
5081 r = setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &value, sizeof(value));
5082 if (r < 0)
5083 return -errno;
5084
5085 return 1;
5086}
5087
5088int fd_inc_rcvbuf(int fd, size_t n) {
5089 int r, value;
5090 socklen_t l = sizeof(value);
5091
5092 r = getsockopt(fd, SOL_SOCKET, SO_RCVBUF, &value, &l);
5093 if (r >= 0 &&
5094 l == sizeof(value) &&
5095 (size_t) value >= n*2)
5096 return 0;
5097
5098 value = (int) n;
5099 r = setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &value, sizeof(value));
5100 if (r < 0)
5101 return -errno;
5102
5103 return 1;
5104}
6bb92a16 5105
9bdc770c 5106int fork_agent(pid_t *pid, const int except[], unsigned n_except, const char *path, ...) {
6bb92a16
LP
5107 pid_t parent_pid, agent_pid;
5108 int fd;
5109 bool stdout_is_tty, stderr_is_tty;
5110 unsigned n, i;
5111 va_list ap;
5112 char **l;
5113
5114 assert(pid);
5115 assert(path);
5116
5117 parent_pid = getpid();
5118
5119 /* Spawns a temporary TTY agent, making sure it goes away when
5120 * we go away */
5121
5122 agent_pid = fork();
5123 if (agent_pid < 0)
5124 return -errno;
5125
5126 if (agent_pid != 0) {
5127 *pid = agent_pid;
5128 return 0;
5129 }
5130
5131 /* In the child:
5132 *
5133 * Make sure the agent goes away when the parent dies */
5134 if (prctl(PR_SET_PDEATHSIG, SIGTERM) < 0)
5135 _exit(EXIT_FAILURE);
5136
5137 /* Check whether our parent died before we were able
5138 * to set the death signal */
5139 if (getppid() != parent_pid)
5140 _exit(EXIT_SUCCESS);
5141
5142 /* Don't leak fds to the agent */
9bdc770c 5143 close_all_fds(except, n_except);
6bb92a16
LP
5144
5145 stdout_is_tty = isatty(STDOUT_FILENO);
5146 stderr_is_tty = isatty(STDERR_FILENO);
5147
5148 if (!stdout_is_tty || !stderr_is_tty) {
5149 /* Detach from stdout/stderr. and reopen
5150 * /dev/tty for them. This is important to
5151 * ensure that when systemctl is started via
5152 * popen() or a similar call that expects to
5153 * read EOF we actually do generate EOF and
5154 * not delay this indefinitely by because we
5155 * keep an unused copy of stdin around. */
5156 fd = open("/dev/tty", O_WRONLY);
5157 if (fd < 0) {
5158 log_error("Failed to open /dev/tty: %m");
5159 _exit(EXIT_FAILURE);
5160 }
5161
5162 if (!stdout_is_tty)
5163 dup2(fd, STDOUT_FILENO);
5164
5165 if (!stderr_is_tty)
5166 dup2(fd, STDERR_FILENO);
5167
5168 if (fd > 2)
5169 close(fd);
5170 }
5171
5172 /* Count arguments */
5173 va_start(ap, path);
5174 for (n = 0; va_arg(ap, char*); n++)
5175 ;
5176 va_end(ap);
5177
5178 /* Allocate strv */
5179 l = alloca(sizeof(char *) * (n + 1));
5180
5181 /* Fill in arguments */
5182 va_start(ap, path);
5183 for (i = 0; i <= n; i++)
5184 l[i] = va_arg(ap, char*);
5185 va_end(ap);
5186
5187 execv(path, l);
5188 _exit(EXIT_FAILURE);
5189}
68faf98c
LP
5190
5191int setrlimit_closest(int resource, const struct rlimit *rlim) {
5192 struct rlimit highest, fixed;
5193
5194 assert(rlim);
5195
5196 if (setrlimit(resource, rlim) >= 0)
5197 return 0;
5198
5199 if (errno != EPERM)
5200 return -errno;
5201
5202 /* So we failed to set the desired setrlimit, then let's try
5203 * to get as close as we can */
5204 assert_se(getrlimit(resource, &highest) == 0);
5205
5206 fixed.rlim_cur = MIN(rlim->rlim_cur, highest.rlim_max);
5207 fixed.rlim_max = MIN(rlim->rlim_max, highest.rlim_max);
5208
5209 if (setrlimit(resource, &fixed) < 0)
5210 return -errno;
5211
5212 return 0;
5213}
3d9a4122 5214
ab94af92
LP
5215int getenv_for_pid(pid_t pid, const char *field, char **_value) {
5216 char path[sizeof("/proc/")-1+10+sizeof("/environ")], *value = NULL;
5217 int r;
5218 FILE *f;
5219 bool done = false;
5220 size_t l;
5221
5222 assert(field);
5223 assert(_value);
5224
5225 if (pid == 0)
5226 pid = getpid();
5227
5228 snprintf(path, sizeof(path), "/proc/%lu/environ", (unsigned long) pid);
5229 char_array_0(path);
5230
5231 f = fopen(path, "re");
5232 if (!f)
5233 return -errno;
5234
5235 l = strlen(field);
5236 r = 0;
5237
5238 do {
5239 char line[LINE_MAX];
5240 unsigned i;
5241
5242 for (i = 0; i < sizeof(line)-1; i++) {
5243 int c;
5244
5245 c = getc(f);
5246 if (_unlikely_(c == EOF)) {
5247 done = true;
5248 break;
5249 } else if (c == 0)
5250 break;
5251
5252 line[i] = c;
5253 }
5254 line[i] = 0;
5255
5256 if (memcmp(line, field, l) == 0 && line[l] == '=') {
5257 value = strdup(line + l + 1);
5258 if (!value) {
5259 r = -ENOMEM;
5260 break;
5261 }
5262
5263 r = 1;
5264 break;
5265 }
5266
5267 } while (!done);
5268
5269 fclose(f);
5270
5271 if (r >= 0)
5272 *_value = value;
5273
5274 return r;
5275}
d889a206
LP
5276
5277int can_sleep(const char *type) {
e67f47e5 5278 char *w, *state;
d889a206 5279 size_t l, k;
d889a206 5280 int r;
e67f47e5 5281 _cleanup_free_ char *p = NULL;
d889a206
LP
5282
5283 assert(type);
5284
679b7d79
LP
5285 /* If /sys is read-only we cannot sleep */
5286 if (access("/sys/power/state", W_OK) < 0)
5287 return false;
5288
d889a206
LP
5289 r = read_one_line_file("/sys/power/state", &p);
5290 if (r < 0)
679b7d79 5291 return false;
d889a206
LP
5292
5293 k = strlen(type);
e67f47e5
LP
5294 FOREACH_WORD_SEPARATOR(w, l, p, WHITESPACE, state)
5295 if (l == k && memcmp(w, type, l) == 0)
5296 return true;
d889a206 5297
e67f47e5 5298 return false;
d889a206 5299}
49dbfa7b 5300
6524990f
LP
5301int can_sleep_disk(const char *type) {
5302 char *w, *state;
5303 size_t l, k;
5304 int r;
5305 _cleanup_free_ char *p = NULL;
5306
5307 assert(type);
5308
679b7d79
LP
5309 /* If /sys is read-only we cannot sleep */
5310 if (access("/sys/power/state", W_OK) < 0 ||
5311 access("/sys/power/disk", W_OK) < 0)
5312 return false;
5313
6524990f
LP
5314 r = read_one_line_file("/sys/power/disk", &p);
5315 if (r < 0)
679b7d79 5316 return false;
6524990f
LP
5317
5318 k = strlen(type);
5319 FOREACH_WORD_SEPARATOR(w, l, p, WHITESPACE, state) {
5320 if (l == k && memcmp(w, type, l) == 0)
5321 return true;
5322
5323 if (l == k + 2 && w[0] == '[' && memcmp(w + 1, type, l - 2) == 0 && w[l-1] == ']')
5324 return true;
5325 }
5326
5327 return false;
5328}
5329
49dbfa7b
LP
5330bool is_valid_documentation_url(const char *url) {
5331 assert(url);
5332
5333 if (startswith(url, "http://") && url[7])
5334 return true;
5335
5336 if (startswith(url, "https://") && url[8])
5337 return true;
5338
5339 if (startswith(url, "file:") && url[5])
5340 return true;
5341
5342 if (startswith(url, "info:") && url[5])
5343 return true;
5344
5345 if (startswith(url, "man:") && url[4])
5346 return true;
5347
5348 return false;
5349}
9be346c9
HH
5350
5351bool in_initrd(void) {
a05f97b3 5352 static __thread int saved = -1;
825c6fe5 5353 struct statfs s;
8f33b5b8 5354
825c6fe5
LP
5355 if (saved >= 0)
5356 return saved;
5357
5358 /* We make two checks here:
5359 *
5360 * 1. the flag file /etc/initrd-release must exist
5361 * 2. the root file system must be a memory file system
5362 *
5363 * The second check is extra paranoia, since misdetecting an
5364 * initrd can have bad bad consequences due the initrd
5365 * emptying when transititioning to the main systemd.
5366 */
5367
5368 saved = access("/etc/initrd-release", F_OK) >= 0 &&
5369 statfs("/", &s) >= 0 &&
943aad8c 5370 is_temporary_fs(&s);
9be346c9 5371
8f33b5b8 5372 return saved;
9be346c9 5373}
069cfc85
LP
5374
5375void warn_melody(void) {
e67f47e5 5376 _cleanup_close_ int fd = -1;
069cfc85
LP
5377
5378 fd = open("/dev/console", O_WRONLY|O_CLOEXEC|O_NOCTTY);
5379 if (fd < 0)
5380 return;
5381
040f18ea 5382 /* Yeah, this is synchronous. Kinda sucks. But well... */
069cfc85
LP
5383
5384 ioctl(fd, KIOCSOUND, (int)(1193180/440));
5385 usleep(125*USEC_PER_MSEC);
5386
5387 ioctl(fd, KIOCSOUND, (int)(1193180/220));
5388 usleep(125*USEC_PER_MSEC);
5389
5390 ioctl(fd, KIOCSOUND, (int)(1193180/220));
5391 usleep(125*USEC_PER_MSEC);
5392
5393 ioctl(fd, KIOCSOUND, 0);
069cfc85 5394}
cd3bd60a
LP
5395
5396int make_console_stdio(void) {
5397 int fd, r;
5398
5399 /* Make /dev/console the controlling terminal and stdin/stdout/stderr */
5400
5401 fd = acquire_terminal("/dev/console", false, true, true, (usec_t) -1);
5402 if (fd < 0) {
5403 log_error("Failed to acquire terminal: %s", strerror(-fd));
5404 return fd;
5405 }
5406
5407 r = make_stdio(fd);
5408 if (r < 0) {
5409 log_error("Failed to duplicate terminal fd: %s", strerror(-r));
5410 return r;
5411 }
5412
5413 return 0;
5414}
7c5f152a
LP
5415
5416int get_home_dir(char **_h) {
5417 char *h;
5418 const char *e;
5419 uid_t u;
5420 struct passwd *p;
5421
5422 assert(_h);
5423
5424 /* Take the user specified one */
5425 e = getenv("HOME");
5426 if (e) {
5427 h = strdup(e);
5428 if (!h)
5429 return -ENOMEM;
5430
5431 *_h = h;
5432 return 0;
5433 }
5434
5435 /* Hardcode home directory for root to avoid NSS */
5436 u = getuid();
5437 if (u == 0) {
5438 h = strdup("/root");
5439 if (!h)
5440 return -ENOMEM;
5441
5442 *_h = h;
5443 return 0;
5444 }
5445
5446 /* Check the database... */
5447 errno = 0;
5448 p = getpwuid(u);
5449 if (!p)
e67f47e5 5450 return errno ? -errno : -ESRCH;
7c5f152a
LP
5451
5452 if (!path_is_absolute(p->pw_dir))
5453 return -EINVAL;
5454
5455 h = strdup(p->pw_dir);
5456 if (!h)
5457 return -ENOMEM;
5458
5459 *_h = h;
5460 return 0;
5461}
5462
5463int get_shell(char **_sh) {
5464 char *sh;
5465 const char *e;
5466 uid_t u;
5467 struct passwd *p;
5468
5469 assert(_sh);
5470
5471 /* Take the user specified one */
5472 e = getenv("SHELL");
5473 if (e) {
5474 sh = strdup(e);
5475 if (!sh)
5476 return -ENOMEM;
5477
5478 *_sh = sh;
5479 return 0;
5480 }
5481
5482 /* Hardcode home directory for root to avoid NSS */
5483 u = getuid();
5484 if (u == 0) {
5485 sh = strdup("/bin/sh");
5486 if (!sh)
5487 return -ENOMEM;
5488
5489 *_sh = sh;
5490 return 0;
5491 }
5492
5493 /* Check the database... */
5494 errno = 0;
5495 p = getpwuid(u);
5496 if (!p)
5497 return errno ? -errno : -ESRCH;
5498
5499 if (!path_is_absolute(p->pw_shell))
5500 return -EINVAL;
5501
5502 sh = strdup(p->pw_shell);
5503 if (!sh)
5504 return -ENOMEM;
5505
5506 *_sh = sh;
5507 return 0;
5508}
2fbe635a
LP
5509
5510void freep(void *p) {
5511 free(*(void**) p);
5512}
5513
5514void fclosep(FILE **f) {
5515 if (*f)
5516 fclose(*f);
5517}
e67f47e5
LP
5518
5519void closep(int *fd) {
5520 if (*fd >= 0)
5521 close_nointr_nofail(*fd);
5522}
a05f97b3
LP
5523
5524void closedirp(DIR **d) {
5525 if (*d)
5526 closedir(*d);
5527}
25ea79fe
ZJS
5528
5529void umaskp(mode_t *u) {
5530 umask(*u);
5531}
0b507b17
LP
5532
5533bool filename_is_safe(const char *p) {
5534
5535 if (isempty(p))
5536 return false;
5537
5538 if (strchr(p, '/'))
5539 return false;
5540
5541 if (streq(p, "."))
5542 return false;
5543
5544 if (streq(p, ".."))
5545 return false;
5546
5547 if (strlen(p) > FILENAME_MAX)
5548 return false;
5549
5550 return true;
5551}
5552
5553bool string_is_safe(const char *p) {
5554 const char *t;
5555
5556 assert(p);
5557
5558 for (t = p; *t; t++) {
01539d6e 5559 if (*t > 0 && *t < ' ')
0b507b17
LP
5560 return false;
5561
011afa76 5562 if (strchr("\\\"\'", *t))
0b507b17
LP
5563 return false;
5564 }
5565
5566 return true;
5567}
cfbc22ab 5568
a9e12476
KS
5569/* hey glibc, APIs with callbacks without a user pointer are so useless */
5570void *xbsearch_r(const void *key, const void *base, size_t nmemb, size_t size,
1c574591 5571 int (*compar) (const void *, const void *, void *), void *arg) {
a9e12476
KS
5572 size_t l, u, idx;
5573 const void *p;
5574 int comparison;
5575
5576 l = 0;
5577 u = nmemb;
5578 while (l < u) {
5579 idx = (l + u) / 2;
5580 p = (void *)(((const char *) base) + (idx * size));
5581 comparison = compar(key, p, arg);
5582 if (comparison < 0)
5583 u = idx;
5584 else if (comparison > 0)
5585 l = idx + 1;
5586 else
5587 return (void *)p;
5588 }
5589 return NULL;
5590}
09017585
MS
5591
5592bool is_locale_utf8(void) {
5593 const char *set;
5594 static int cached_answer = -1;
5595
5596 if (cached_answer >= 0)
5597 goto out;
5598
5599 if (!setlocale(LC_ALL, "")) {
5600 cached_answer = true;
5601 goto out;
5602 }
5603
5604 set = nl_langinfo(CODESET);
5605 if (!set) {
5606 cached_answer = true;
5607 goto out;
5608 }
5609
5610 cached_answer = streq(set, "UTF-8");
5611out:
5612 return (bool)cached_answer;
5613}
c339d977
MS
5614
5615const char *draw_special_char(DrawSpecialChar ch) {
5616 static const char *draw_table[2][_DRAW_SPECIAL_CHAR_MAX] = {
5617 /* UTF-8 */ {
45a5ff0d
MS
5618 [DRAW_TREE_VERT] = "\342\224\202 ", /* │ */
5619 [DRAW_TREE_BRANCH] = "\342\224\234\342\224\200", /* ├─ */
5620 [DRAW_TREE_RIGHT] = "\342\224\224\342\224\200", /* └─ */
5621 [DRAW_TRIANGULAR_BULLET] = "\342\200\243 ", /* ‣ */
c339d977
MS
5622 },
5623 /* ASCII fallback */ {
45a5ff0d
MS
5624 [DRAW_TREE_VERT] = "| ",
5625 [DRAW_TREE_BRANCH] = "|-",
5626 [DRAW_TREE_RIGHT] = "`-",
5627 [DRAW_TRIANGULAR_BULLET] = "> ",
c339d977
MS
5628 }
5629 };
5630
5631 return draw_table[!is_locale_utf8()][ch];
5632}
409bc9c3
LP
5633
5634char *strreplace(const char *text, const char *old_string, const char *new_string) {
5635 const char *f;
5636 char *t, *r;
5637 size_t l, old_len, new_len;
5638
5639 assert(text);
5640 assert(old_string);
5641 assert(new_string);
5642
5643 old_len = strlen(old_string);
5644 new_len = strlen(new_string);
5645
5646 l = strlen(text);
5647 r = new(char, l+1);
5648 if (!r)
5649 return NULL;
5650
5651 f = text;
5652 t = r;
5653 while (*f) {
5654 char *a;
5655 size_t d, nl;
5656
5657 if (!startswith(f, old_string)) {
5658 *(t++) = *(f++);
5659 continue;
5660 }
5661
5662 d = t - r;
5663 nl = l - old_len + new_len;
5664 a = realloc(r, nl + 1);
5665 if (!a)
5666 goto oom;
5667
5668 l = nl;
5669 r = a;
5670 t = r + d;
5671
5672 t = stpcpy(t, new_string);
5673 f += old_len;
5674 }
5675
5676 *t = 0;
5677 return r;
5678
5679oom:
5680 free(r);
5681 return NULL;
5682}
e8bc0ea2
LP
5683
5684char *strip_tab_ansi(char **ibuf, size_t *_isz) {
5685 const char *i, *begin;
5686 enum {
5687 STATE_OTHER,
5688 STATE_ESCAPE,
5689 STATE_BRACKET
5690 } state = STATE_OTHER;
5691 char *obuf = NULL;
5692 size_t osz = 0, isz;
5693 FILE *f;
5694
5695 assert(ibuf);
5696 assert(*ibuf);
5697
5698 /* Strips ANSI color and replaces TABs by 8 spaces */
5699
5700 isz = _isz ? *_isz : strlen(*ibuf);
5701
5702 f = open_memstream(&obuf, &osz);
5703 if (!f)
5704 return NULL;
5705
5706 for (i = *ibuf; i < *ibuf + isz + 1; i++) {
5707
5708 switch (state) {
5709
5710 case STATE_OTHER:
5711 if (i >= *ibuf + isz) /* EOT */
5712 break;
5713 else if (*i == '\x1B')
5714 state = STATE_ESCAPE;
5715 else if (*i == '\t')
5716 fputs(" ", f);
5717 else
5718 fputc(*i, f);
5719 break;
5720
5721 case STATE_ESCAPE:
5722 if (i >= *ibuf + isz) { /* EOT */
5723 fputc('\x1B', f);
5724 break;
5725 } else if (*i == '[') {
5726 state = STATE_BRACKET;
5727 begin = i + 1;
5728 } else {
5729 fputc('\x1B', f);
5730 fputc(*i, f);
5731 state = STATE_OTHER;
5732 }
5733
5734 break;
5735
5736 case STATE_BRACKET:
5737
5738 if (i >= *ibuf + isz || /* EOT */
5739 (!(*i >= '0' && *i <= '9') && *i != ';' && *i != 'm')) {
5740 fputc('\x1B', f);
5741 fputc('[', f);
5742 state = STATE_OTHER;
5743 i = begin-1;
5744 } else if (*i == 'm')
5745 state = STATE_OTHER;
5746 break;
5747 }
5748 }
5749
5750 if (ferror(f)) {
5751 fclose(f);
5752 free(obuf);
5753 return NULL;
5754 }
5755
5756 fclose(f);
5757
5758 free(*ibuf);
5759 *ibuf = obuf;
5760
5761 if (_isz)
5762 *_isz = osz;
5763
5764 return obuf;
5765}
240dbaa4
LP
5766
5767int on_ac_power(void) {
5768 bool found_offline = false, found_online = false;
5769 _cleanup_closedir_ DIR *d = NULL;
5770
5771 d = opendir("/sys/class/power_supply");
5772 if (!d)
5773 return -errno;
5774
5775 for (;;) {
5776 struct dirent *de;
5777 union dirent_storage buf;
5778 _cleanup_free_ char *p = NULL;
5779 _cleanup_close_ int fd = -1, device = -1;
5780 char contents[6];
5781 ssize_t n;
5782 int k;
5783
5784 k = readdir_r(d, &buf.de, &de);
5785 if (k != 0)
5786 return -k;
5787
5788 if (!de)
5789 break;
5790
5791 if (ignore_file(de->d_name))
5792 continue;
5793
5794 device = openat(dirfd(d), de->d_name, O_DIRECTORY|O_RDONLY|O_CLOEXEC|O_NOCTTY);
5795 if (device < 0) {
5796 if (errno == ENOENT || errno == ENOTDIR)
5797 continue;
5798
5799 return -errno;
5800 }
5801
5802 fd = openat(device, "type", O_RDONLY|O_CLOEXEC|O_NOCTTY);
5803 if (fd < 0) {
5804 if (errno == ENOENT)
5805 continue;
5806
5807 return -errno;
5808 }
5809
5810 n = read(fd, contents, sizeof(contents));
5811 if (n < 0)
5812 return -errno;
5813
5814 if (n != 6 || memcmp(contents, "Mains\n", 6))
5815 continue;
5816
5817 close_nointr_nofail(fd);
5818 fd = openat(device, "online", O_RDONLY|O_CLOEXEC|O_NOCTTY);
5819 if (fd < 0) {
5820 if (errno == ENOENT)
5821 continue;
5822
5823 return -errno;
5824 }
5825
5826 n = read(fd, contents, sizeof(contents));
5827 if (n < 0)
5828 return -errno;
5829
5830 if (n != 2 || contents[1] != '\n')
5831 return -EIO;
5832
5833 if (contents[0] == '1') {
5834 found_online = true;
5835 break;
5836 } else if (contents[0] == '0')
5837 found_offline = true;
5838 else
5839 return -EIO;
5840 }
5841
5842 return found_online || !found_offline;
5843}