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