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