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