]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/shared/util.c
systemctl: show the name of failing unit in red
[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;
3840
3841 for (p = s, d = s; *p; p++)
3842 if ((*p >= 'a' && *p <= 'z') ||
3843 (*p >= 'A' && *p <= 'Z') ||
3844 (*p >= '0' && *p <= '9') ||
3845 *p == '-' ||
3846 *p == '_' ||
3847 *p == '.')
3848 *(d++) = *p;
3849
3850 *d = 0;
3851
3852 strshorten(s, HOST_NAME_MAX);
3853 return s;
3854}
3855
1325aa42 3856int pipe_eof(int fd) {
1325aa42 3857 int r;
b92bea5d
ZJS
3858 struct pollfd pollfd = {
3859 .fd = fd,
3860 .events = POLLIN|POLLHUP,
3861 };
1325aa42
LP
3862
3863 r = poll(&pollfd, 1, 0);
3864 if (r < 0)
3865 return -errno;
3866
3867 if (r == 0)
3868 return 0;
3869
3870 return pollfd.revents & POLLHUP;
3871}
3872
8f2d43a0 3873int fd_wait_for_event(int fd, int event, usec_t t) {
df50185b 3874 int r;
b92bea5d
ZJS
3875 struct pollfd pollfd = {
3876 .fd = fd,
3877 .events = event,
3878 };
df50185b 3879
8f2d43a0 3880 r = poll(&pollfd, 1, t == (usec_t) -1 ? -1 : (int) (t / USEC_PER_MSEC));
df50185b
LP
3881 if (r < 0)
3882 return -errno;
3883
3884 if (r == 0)
3885 return 0;
3886
3887 return pollfd.revents;
3888}
3889
5a3ab509
LP
3890int fopen_temporary(const char *path, FILE **_f, char **_temp_path) {
3891 FILE *f;
3892 char *t;
3893 const char *fn;
3894 size_t k;
3895 int fd;
3896
3897 assert(path);
3898 assert(_f);
3899 assert(_temp_path);
3900
3901 t = new(char, strlen(path) + 1 + 6 + 1);
3902 if (!t)
3903 return -ENOMEM;
3904
9eb977db 3905 fn = path_get_file_name(path);
5a3ab509
LP
3906 k = fn-path;
3907 memcpy(t, path, k);
3908 t[k] = '.';
3909 stpcpy(stpcpy(t+k+1, fn), "XXXXXX");
3910
3911 fd = mkostemp(t, O_WRONLY|O_CLOEXEC);
3912 if (fd < 0) {
3913 free(t);
3914 return -errno;
3915 }
3916
3917 f = fdopen(fd, "we");
3918 if (!f) {
3919 unlink(t);
3920 free(t);
3921 return -errno;
3922 }
3923
3924 *_f = f;
3925 *_temp_path = t;
3926
3927 return 0;
3928}
3929
6ea832a2 3930int terminal_vhangup_fd(int fd) {
5a3ab509
LP
3931 assert(fd >= 0);
3932
6ea832a2
LP
3933 if (ioctl(fd, TIOCVHANGUP) < 0)
3934 return -errno;
3935
3936 return 0;
3937}
3938
3939int terminal_vhangup(const char *name) {
3940 int fd, r;
3941
3942 fd = open_terminal(name, O_RDWR|O_NOCTTY|O_CLOEXEC);
3943 if (fd < 0)
3944 return fd;
3945
3946 r = terminal_vhangup_fd(fd);
3947 close_nointr_nofail(fd);
3948
3949 return r;
3950}
3951
3952int vt_disallocate(const char *name) {
3953 int fd, r;
3954 unsigned u;
6ea832a2
LP
3955
3956 /* Deallocate the VT if possible. If not possible
3957 * (i.e. because it is the active one), at least clear it
3958 * entirely (including the scrollback buffer) */
3959
b83bc4e9
LP
3960 if (!startswith(name, "/dev/"))
3961 return -EINVAL;
3962
3963 if (!tty_is_vc(name)) {
3964 /* So this is not a VT. I guess we cannot deallocate
3965 * it then. But let's at least clear the screen */
3966
3967 fd = open_terminal(name, O_RDWR|O_NOCTTY|O_CLOEXEC);
3968 if (fd < 0)
3969 return fd;
3970
8585357a
LP
3971 loop_write(fd,
3972 "\033[r" /* clear scrolling region */
3973 "\033[H" /* move home */
3974 "\033[2J", /* clear screen */
3975 10, false);
b83bc4e9
LP
3976 close_nointr_nofail(fd);
3977
3978 return 0;
3979 }
6ea832a2
LP
3980
3981 if (!startswith(name, "/dev/tty"))
3982 return -EINVAL;
3983
3984 r = safe_atou(name+8, &u);
3985 if (r < 0)
3986 return r;
3987
3988 if (u <= 0)
b83bc4e9 3989 return -EINVAL;
6ea832a2 3990
b83bc4e9 3991 /* Try to deallocate */
6ea832a2
LP
3992 fd = open_terminal("/dev/tty0", O_RDWR|O_NOCTTY|O_CLOEXEC);
3993 if (fd < 0)
3994 return fd;
3995
3996 r = ioctl(fd, VT_DISALLOCATE, u);
b83bc4e9 3997 close_nointr_nofail(fd);
6ea832a2 3998
b83bc4e9
LP
3999 if (r >= 0)
4000 return 0;
6ea832a2 4001
b83bc4e9 4002 if (errno != EBUSY)
6ea832a2 4003 return -errno;
6ea832a2 4004
b83bc4e9
LP
4005 /* Couldn't deallocate, so let's clear it fully with
4006 * scrollback */
4007 fd = open_terminal(name, O_RDWR|O_NOCTTY|O_CLOEXEC);
6ea832a2 4008 if (fd < 0)
b83bc4e9 4009 return fd;
6ea832a2 4010
8585357a
LP
4011 loop_write(fd,
4012 "\033[r" /* clear scrolling region */
4013 "\033[H" /* move home */
4014 "\033[3J", /* clear screen including scrollback, requires Linux 2.6.40 */
4015 10, false);
b83bc4e9 4016 close_nointr_nofail(fd);
6ea832a2 4017
b83bc4e9 4018 return 0;
6ea832a2
LP
4019}
4020
34ca941c
LP
4021int copy_file(const char *from, const char *to) {
4022 int r, fdf, fdt;
4023
4024 assert(from);
4025 assert(to);
4026
4027 fdf = open(from, O_RDONLY|O_CLOEXEC|O_NOCTTY);
4028 if (fdf < 0)
4029 return -errno;
4030
4031 fdt = open(to, O_WRONLY|O_CREAT|O_EXCL|O_CLOEXEC|O_NOCTTY, 0644);
4032 if (fdt < 0) {
4033 close_nointr_nofail(fdf);
4034 return -errno;
4035 }
4036
4037 for (;;) {
4038 char buf[PIPE_BUF];
4039 ssize_t n, k;
4040
4041 n = read(fdf, buf, sizeof(buf));
4042 if (n < 0) {
4043 r = -errno;
4044
4045 close_nointr_nofail(fdf);
4046 close_nointr(fdt);
4047 unlink(to);
4048
4049 return r;
4050 }
4051
4052 if (n == 0)
4053 break;
4054
4055 errno = 0;
4056 k = loop_write(fdt, buf, n, false);
4057 if (n != k) {
4058 r = k < 0 ? k : (errno ? -errno : -EIO);
4059
4060 close_nointr_nofail(fdf);
4061 close_nointr(fdt);
4062
4063 unlink(to);
4064 return r;
4065 }
4066 }
4067
4068 close_nointr_nofail(fdf);
4069 r = close_nointr(fdt);
4070
4071 if (r < 0) {
4072 unlink(to);
4073 return r;
4074 }
4075
4076 return 0;
4077}
4078
424a19f8
LP
4079int symlink_atomic(const char *from, const char *to) {
4080 char *x;
4081 _cleanup_free_ char *t;
34ca941c
LP
4082 const char *fn;
4083 size_t k;
4084 unsigned long long ull;
4085 unsigned i;
4086 int r;
4087
4088 assert(from);
4089 assert(to);
4090
4091 t = new(char, strlen(to) + 1 + 16 + 1);
4092 if (!t)
4093 return -ENOMEM;
4094
9eb977db 4095 fn = path_get_file_name(to);
34ca941c
LP
4096 k = fn-to;
4097 memcpy(t, to, k);
4098 t[k] = '.';
4099 x = stpcpy(t+k+1, fn);
4100
4101 ull = random_ull();
4102 for (i = 0; i < 16; i++) {
4103 *(x++) = hexchar(ull & 0xF);
4104 ull >>= 4;
4105 }
4106
4107 *x = 0;
4108
424a19f8
LP
4109 if (symlink(from, t) < 0)
4110 return -errno;
34ca941c
LP
4111
4112 if (rename(t, to) < 0) {
4113 r = -errno;
4114 unlink(t);
34ca941c
LP
4115 return r;
4116 }
4117
424a19f8 4118 return 0;
34ca941c
LP
4119}
4120
4d6d6518
LP
4121bool display_is_local(const char *display) {
4122 assert(display);
4123
4124 return
4125 display[0] == ':' &&
4126 display[1] >= '0' &&
4127 display[1] <= '9';
4128}
4129
4130int socket_from_display(const char *display, char **path) {
4131 size_t k;
4132 char *f, *c;
4133
4134 assert(display);
4135 assert(path);
4136
4137 if (!display_is_local(display))
4138 return -EINVAL;
4139
4140 k = strspn(display+1, "0123456789");
4141
4142 f = new(char, sizeof("/tmp/.X11-unix/X") + k);
4143 if (!f)
4144 return -ENOMEM;
4145
4146 c = stpcpy(f, "/tmp/.X11-unix/X");
4147 memcpy(c, display+1, k);
4148 c[k] = 0;
4149
4150 *path = f;
4151
4152 return 0;
4153}
4154
d05c5031
LP
4155int get_user_creds(
4156 const char **username,
4157 uid_t *uid, gid_t *gid,
4158 const char **home,
4159 const char **shell) {
4160
1cccf435 4161 struct passwd *p;
ddd88763 4162 uid_t u;
1cccf435
MV
4163
4164 assert(username);
4165 assert(*username);
1cccf435
MV
4166
4167 /* We enforce some special rules for uid=0: in order to avoid
4168 * NSS lookups for root we hardcode its data. */
4169
4170 if (streq(*username, "root") || streq(*username, "0")) {
4171 *username = "root";
4b67834e
LP
4172
4173 if (uid)
4174 *uid = 0;
4175
4176 if (gid)
4177 *gid = 0;
4178
4179 if (home)
4180 *home = "/root";
d05c5031
LP
4181
4182 if (shell)
4183 *shell = "/bin/sh";
4184
1cccf435
MV
4185 return 0;
4186 }
4187
ddd88763 4188 if (parse_uid(*username, &u) >= 0) {
1cccf435 4189 errno = 0;
ddd88763 4190 p = getpwuid(u);
1cccf435
MV
4191
4192 /* If there are multiple users with the same id, make
4193 * sure to leave $USER to the configured value instead
4194 * of the first occurrence in the database. However if
4195 * the uid was configured by a numeric uid, then let's
4196 * pick the real username from /etc/passwd. */
4197 if (p)
4198 *username = p->pw_name;
4199 } else {
4200 errno = 0;
4201 p = getpwnam(*username);
4202 }
4203
4204 if (!p)
8333c77e 4205 return errno > 0 ? -errno : -ESRCH;
1cccf435 4206
4b67834e
LP
4207 if (uid)
4208 *uid = p->pw_uid;
4209
4210 if (gid)
4211 *gid = p->pw_gid;
4212
4213 if (home)
4214 *home = p->pw_dir;
4215
d05c5031
LP
4216 if (shell)
4217 *shell = p->pw_shell;
4218
4b67834e
LP
4219 return 0;
4220}
4221
59164be4
LP
4222char* uid_to_name(uid_t uid) {
4223 struct passwd *p;
4224 char *r;
4225
4226 if (uid == 0)
4227 return strdup("root");
4228
4229 p = getpwuid(uid);
4230 if (p)
4231 return strdup(p->pw_name);
4232
4233 if (asprintf(&r, "%lu", (unsigned long) uid) < 0)
4234 return NULL;
4235
4236 return r;
4237}
4238
4468addc
LP
4239char* gid_to_name(gid_t gid) {
4240 struct group *p;
4241 char *r;
4242
4243 if (gid == 0)
4244 return strdup("root");
4245
4246 p = getgrgid(gid);
4247 if (p)
4248 return strdup(p->gr_name);
4249
4250 if (asprintf(&r, "%lu", (unsigned long) gid) < 0)
4251 return NULL;
4252
4253 return r;
4254}
4255
4b67834e
LP
4256int get_group_creds(const char **groupname, gid_t *gid) {
4257 struct group *g;
4258 gid_t id;
4259
4260 assert(groupname);
4261
4262 /* We enforce some special rules for gid=0: in order to avoid
4263 * NSS lookups for root we hardcode its data. */
4264
4265 if (streq(*groupname, "root") || streq(*groupname, "0")) {
4266 *groupname = "root";
4267
4268 if (gid)
4269 *gid = 0;
4270
4271 return 0;
4272 }
4273
4274 if (parse_gid(*groupname, &id) >= 0) {
4275 errno = 0;
4276 g = getgrgid(id);
4277
4278 if (g)
4279 *groupname = g->gr_name;
4280 } else {
4281 errno = 0;
4282 g = getgrnam(*groupname);
4283 }
4284
4285 if (!g)
8333c77e 4286 return errno > 0 ? -errno : -ESRCH;
4b67834e
LP
4287
4288 if (gid)
4289 *gid = g->gr_gid;
4290
1cccf435
MV
4291 return 0;
4292}
4293
4468addc
LP
4294int in_gid(gid_t gid) {
4295 gid_t *gids;
43673799
LP
4296 int ngroups_max, r, i;
4297
43673799
LP
4298 if (getgid() == gid)
4299 return 1;
4300
4301 if (getegid() == gid)
4302 return 1;
4303
4304 ngroups_max = sysconf(_SC_NGROUPS_MAX);
4305 assert(ngroups_max > 0);
4306
4307 gids = alloca(sizeof(gid_t) * ngroups_max);
4308
4309 r = getgroups(ngroups_max, gids);
4310 if (r < 0)
4311 return -errno;
4312
4313 for (i = 0; i < r; i++)
4314 if (gids[i] == gid)
4315 return 1;
4316
4317 return 0;
4318}
4319
4468addc
LP
4320int in_group(const char *name) {
4321 int r;
4322 gid_t gid;
4323
4324 r = get_group_creds(&name, &gid);
4325 if (r < 0)
4326 return r;
4327
4328 return in_gid(gid);
4329}
4330
8092a428 4331int glob_exists(const char *path) {
c84a9488 4332 glob_t _cleanup_globfree_ g = {};
8092a428
LP
4333 int r, k;
4334
4335 assert(path);
4336
8092a428
LP
4337 errno = 0;
4338 k = glob(path, GLOB_NOSORT|GLOB_BRACE, NULL, &g);
4339
4340 if (k == GLOB_NOMATCH)
4341 r = 0;
4342 else if (k == GLOB_NOSPACE)
4343 r = -ENOMEM;
4344 else if (k == 0)
4345 r = !strv_isempty(g.gl_pathv);
4346 else
4347 r = errno ? -errno : -EIO;
4348
8092a428
LP
4349 return r;
4350}
4351
83096483
LP
4352int dirent_ensure_type(DIR *d, struct dirent *de) {
4353 struct stat st;
4354
4355 assert(d);
4356 assert(de);
4357
4358 if (de->d_type != DT_UNKNOWN)
4359 return 0;
4360
4361 if (fstatat(dirfd(d), de->d_name, &st, AT_SYMLINK_NOFOLLOW) < 0)
4362 return -errno;
4363
4364 de->d_type =
4365 S_ISREG(st.st_mode) ? DT_REG :
4366 S_ISDIR(st.st_mode) ? DT_DIR :
4367 S_ISLNK(st.st_mode) ? DT_LNK :
4368 S_ISFIFO(st.st_mode) ? DT_FIFO :
4369 S_ISSOCK(st.st_mode) ? DT_SOCK :
4370 S_ISCHR(st.st_mode) ? DT_CHR :
4371 S_ISBLK(st.st_mode) ? DT_BLK :
4372 DT_UNKNOWN;
4373
4374 return 0;
4375}
4376
4377int in_search_path(const char *path, char **search) {
4378 char **i, *parent;
4379 int r;
4380
9eb977db 4381 r = path_get_parent(path, &parent);
83096483
LP
4382 if (r < 0)
4383 return r;
4384
4385 r = 0;
4386
4387 STRV_FOREACH(i, search) {
4388 if (path_equal(parent, *i)) {
4389 r = 1;
4390 break;
4391 }
4392 }
4393
4394 free(parent);
4395
4396 return r;
4397}
4398
034a2a52
LP
4399int get_files_in_directory(const char *path, char ***list) {
4400 DIR *d;
4401 int r = 0;
4402 unsigned n = 0;
4403 char **l = NULL;
4404
4405 assert(path);
d60ef526
LP
4406
4407 /* Returns all files in a directory in *list, and the number
4408 * of files as return value. If list is NULL returns only the
4409 * number */
034a2a52
LP
4410
4411 d = opendir(path);
8ea913b2
LP
4412 if (!d)
4413 return -errno;
4414
034a2a52 4415 for (;;) {
7d5e9c0f
LP
4416 struct dirent *de;
4417 union dirent_storage buf;
034a2a52
LP
4418 int k;
4419
7d5e9c0f 4420 k = readdir_r(d, &buf.de, &de);
034a2a52
LP
4421 if (k != 0) {
4422 r = -k;
4423 goto finish;
4424 }
4425
4426 if (!de)
4427 break;
4428
4429 dirent_ensure_type(d, de);
4430
4431 if (!dirent_is_file(de))
4432 continue;
4433
d60ef526
LP
4434 if (list) {
4435 if ((unsigned) r >= n) {
4436 char **t;
034a2a52 4437
d60ef526
LP
4438 n = MAX(16, 2*r);
4439 t = realloc(l, sizeof(char*) * n);
4440 if (!t) {
4441 r = -ENOMEM;
4442 goto finish;
4443 }
034a2a52 4444
d60ef526
LP
4445 l = t;
4446 }
034a2a52 4447
d60ef526 4448 assert((unsigned) r < n);
034a2a52 4449
d60ef526
LP
4450 l[r] = strdup(de->d_name);
4451 if (!l[r]) {
4452 r = -ENOMEM;
4453 goto finish;
4454 }
034a2a52 4455
d60ef526
LP
4456 l[++r] = NULL;
4457 } else
4458 r++;
034a2a52
LP
4459 }
4460
4461finish:
4462 if (d)
4463 closedir(d);
4464
d60ef526
LP
4465 if (r >= 0) {
4466 if (list)
4467 *list = l;
4468 } else
034a2a52
LP
4469 strv_free(l);
4470
4471 return r;
4472}
4473
b7def684 4474char *strjoin(const char *x, ...) {
911a4828
LP
4475 va_list ap;
4476 size_t l;
4477 char *r, *p;
4478
4479 va_start(ap, x);
4480
4481 if (x) {
4482 l = strlen(x);
4483
4484 for (;;) {
4485 const char *t;
040f18ea 4486 size_t n;
911a4828
LP
4487
4488 t = va_arg(ap, const char *);
4489 if (!t)
4490 break;
4491
040f18ea 4492 n = strlen(t);
e98055de
LN
4493 if (n > ((size_t) -1) - l) {
4494 va_end(ap);
040f18ea 4495 return NULL;
e98055de 4496 }
040f18ea
LP
4497
4498 l += n;
911a4828
LP
4499 }
4500 } else
4501 l = 0;
4502
4503 va_end(ap);
4504
4505 r = new(char, l+1);
4506 if (!r)
4507 return NULL;
4508
4509 if (x) {
4510 p = stpcpy(r, x);
4511
4512 va_start(ap, x);
4513
4514 for (;;) {
4515 const char *t;
4516
4517 t = va_arg(ap, const char *);
4518 if (!t)
4519 break;
4520
4521 p = stpcpy(p, t);
4522 }
8ea913b2
LP
4523
4524 va_end(ap);
911a4828
LP
4525 } else
4526 r[0] = 0;
4527
4528 return r;
4529}
4530
b636465b
LP
4531bool is_main_thread(void) {
4532 static __thread int cached = 0;
4533
4534 if (_unlikely_(cached == 0))
4535 cached = getpid() == gettid() ? 1 : -1;
4536
4537 return cached > 0;
4538}
4539
94959f0f
LP
4540int block_get_whole_disk(dev_t d, dev_t *ret) {
4541 char *p, *s;
4542 int r;
4543 unsigned n, m;
4544
4545 assert(ret);
4546
4547 /* If it has a queue this is good enough for us */
4548 if (asprintf(&p, "/sys/dev/block/%u:%u/queue", major(d), minor(d)) < 0)
4549 return -ENOMEM;
4550
4551 r = access(p, F_OK);
4552 free(p);
4553
4554 if (r >= 0) {
4555 *ret = d;
4556 return 0;
4557 }
4558
4559 /* If it is a partition find the originating device */
4560 if (asprintf(&p, "/sys/dev/block/%u:%u/partition", major(d), minor(d)) < 0)
4561 return -ENOMEM;
4562
4563 r = access(p, F_OK);
4564 free(p);
4565
4566 if (r < 0)
4567 return -ENOENT;
4568
4569 /* Get parent dev_t */
4570 if (asprintf(&p, "/sys/dev/block/%u:%u/../dev", major(d), minor(d)) < 0)
4571 return -ENOMEM;
4572
4573 r = read_one_line_file(p, &s);
4574 free(p);
4575
4576 if (r < 0)
4577 return r;
4578
4579 r = sscanf(s, "%u:%u", &m, &n);
4580 free(s);
4581
4582 if (r != 2)
4583 return -EINVAL;
4584
4585 /* Only return this if it is really good enough for us. */
4586 if (asprintf(&p, "/sys/dev/block/%u:%u/queue", m, n) < 0)
4587 return -ENOMEM;
4588
4589 r = access(p, F_OK);
4590 free(p);
4591
4592 if (r >= 0) {
4593 *ret = makedev(m, n);
4594 return 0;
4595 }
4596
4597 return -ENOENT;
4598}
4599
8d53b453 4600int file_is_priv_sticky(const char *p) {
ad293f5a
LP
4601 struct stat st;
4602
4603 assert(p);
4604
4605 if (lstat(p, &st) < 0)
4606 return -errno;
4607
4608 return
8d53b453 4609 (st.st_uid == 0 || st.st_uid == getuid()) &&
ad293f5a
LP
4610 (st.st_mode & S_ISVTX);
4611}
94959f0f 4612
f41607a6
LP
4613static const char *const ioprio_class_table[] = {
4614 [IOPRIO_CLASS_NONE] = "none",
4615 [IOPRIO_CLASS_RT] = "realtime",
4616 [IOPRIO_CLASS_BE] = "best-effort",
4617 [IOPRIO_CLASS_IDLE] = "idle"
4618};
4619
f8b69d1d 4620DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(ioprio_class, int, INT_MAX);
f41607a6
LP
4621
4622static const char *const sigchld_code_table[] = {
4623 [CLD_EXITED] = "exited",
4624 [CLD_KILLED] = "killed",
4625 [CLD_DUMPED] = "dumped",
4626 [CLD_TRAPPED] = "trapped",
4627 [CLD_STOPPED] = "stopped",
4628 [CLD_CONTINUED] = "continued",
4629};
4630
4631DEFINE_STRING_TABLE_LOOKUP(sigchld_code, int);
4632
4633static const char *const log_facility_unshifted_table[LOG_NFACILITIES] = {
4634 [LOG_FAC(LOG_KERN)] = "kern",
4635 [LOG_FAC(LOG_USER)] = "user",
4636 [LOG_FAC(LOG_MAIL)] = "mail",
4637 [LOG_FAC(LOG_DAEMON)] = "daemon",
4638 [LOG_FAC(LOG_AUTH)] = "auth",
4639 [LOG_FAC(LOG_SYSLOG)] = "syslog",
4640 [LOG_FAC(LOG_LPR)] = "lpr",
4641 [LOG_FAC(LOG_NEWS)] = "news",
4642 [LOG_FAC(LOG_UUCP)] = "uucp",
4643 [LOG_FAC(LOG_CRON)] = "cron",
4644 [LOG_FAC(LOG_AUTHPRIV)] = "authpriv",
4645 [LOG_FAC(LOG_FTP)] = "ftp",
4646 [LOG_FAC(LOG_LOCAL0)] = "local0",
4647 [LOG_FAC(LOG_LOCAL1)] = "local1",
4648 [LOG_FAC(LOG_LOCAL2)] = "local2",
4649 [LOG_FAC(LOG_LOCAL3)] = "local3",
4650 [LOG_FAC(LOG_LOCAL4)] = "local4",
4651 [LOG_FAC(LOG_LOCAL5)] = "local5",
4652 [LOG_FAC(LOG_LOCAL6)] = "local6",
4653 [LOG_FAC(LOG_LOCAL7)] = "local7"
4654};
4655
f8b69d1d 4656DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(log_facility_unshifted, int, LOG_FAC(~0));
f41607a6
LP
4657
4658static const char *const log_level_table[] = {
4659 [LOG_EMERG] = "emerg",
4660 [LOG_ALERT] = "alert",
4661 [LOG_CRIT] = "crit",
4662 [LOG_ERR] = "err",
4663 [LOG_WARNING] = "warning",
4664 [LOG_NOTICE] = "notice",
4665 [LOG_INFO] = "info",
4666 [LOG_DEBUG] = "debug"
4667};
4668
f8b69d1d 4669DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(log_level, int, LOG_DEBUG);
f41607a6
LP
4670
4671static const char* const sched_policy_table[] = {
4672 [SCHED_OTHER] = "other",
4673 [SCHED_BATCH] = "batch",
4674 [SCHED_IDLE] = "idle",
4675 [SCHED_FIFO] = "fifo",
4676 [SCHED_RR] = "rr"
4677};
4678
f8b69d1d 4679DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(sched_policy, int, INT_MAX);
f41607a6
LP
4680
4681static const char* const rlimit_table[] = {
4682 [RLIMIT_CPU] = "LimitCPU",
4683 [RLIMIT_FSIZE] = "LimitFSIZE",
4684 [RLIMIT_DATA] = "LimitDATA",
4685 [RLIMIT_STACK] = "LimitSTACK",
4686 [RLIMIT_CORE] = "LimitCORE",
4687 [RLIMIT_RSS] = "LimitRSS",
4688 [RLIMIT_NOFILE] = "LimitNOFILE",
4689 [RLIMIT_AS] = "LimitAS",
4690 [RLIMIT_NPROC] = "LimitNPROC",
4691 [RLIMIT_MEMLOCK] = "LimitMEMLOCK",
4692 [RLIMIT_LOCKS] = "LimitLOCKS",
4693 [RLIMIT_SIGPENDING] = "LimitSIGPENDING",
4694 [RLIMIT_MSGQUEUE] = "LimitMSGQUEUE",
4695 [RLIMIT_NICE] = "LimitNICE",
4696 [RLIMIT_RTPRIO] = "LimitRTPRIO",
4697 [RLIMIT_RTTIME] = "LimitRTTIME"
4698};
4699
4700DEFINE_STRING_TABLE_LOOKUP(rlimit, int);
4701
4702static const char* const ip_tos_table[] = {
4703 [IPTOS_LOWDELAY] = "low-delay",
4704 [IPTOS_THROUGHPUT] = "throughput",
4705 [IPTOS_RELIABILITY] = "reliability",
4706 [IPTOS_LOWCOST] = "low-cost",
4707};
4708
f8b69d1d 4709DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(ip_tos, int, 0xff);
f41607a6 4710
4e240ab0 4711static const char *const __signal_table[] = {
f41607a6
LP
4712 [SIGHUP] = "HUP",
4713 [SIGINT] = "INT",
4714 [SIGQUIT] = "QUIT",
4715 [SIGILL] = "ILL",
4716 [SIGTRAP] = "TRAP",
4717 [SIGABRT] = "ABRT",
4718 [SIGBUS] = "BUS",
4719 [SIGFPE] = "FPE",
4720 [SIGKILL] = "KILL",
4721 [SIGUSR1] = "USR1",
4722 [SIGSEGV] = "SEGV",
4723 [SIGUSR2] = "USR2",
4724 [SIGPIPE] = "PIPE",
4725 [SIGALRM] = "ALRM",
4726 [SIGTERM] = "TERM",
4727#ifdef SIGSTKFLT
4728 [SIGSTKFLT] = "STKFLT", /* Linux on SPARC doesn't know SIGSTKFLT */
4729#endif
4730 [SIGCHLD] = "CHLD",
4731 [SIGCONT] = "CONT",
4732 [SIGSTOP] = "STOP",
4733 [SIGTSTP] = "TSTP",
4734 [SIGTTIN] = "TTIN",
4735 [SIGTTOU] = "TTOU",
4736 [SIGURG] = "URG",
4737 [SIGXCPU] = "XCPU",
4738 [SIGXFSZ] = "XFSZ",
4739 [SIGVTALRM] = "VTALRM",
4740 [SIGPROF] = "PROF",
4741 [SIGWINCH] = "WINCH",
4742 [SIGIO] = "IO",
4743 [SIGPWR] = "PWR",
4744 [SIGSYS] = "SYS"
4745};
4746
4e240ab0
MS
4747DEFINE_PRIVATE_STRING_TABLE_LOOKUP(__signal, int);
4748
4749const char *signal_to_string(int signo) {
fa70beaa 4750 static __thread char buf[sizeof("RTMIN+")-1 + DECIMAL_STR_MAX(int) + 1];
4e240ab0
MS
4751 const char *name;
4752
4753 name = __signal_to_string(signo);
4754 if (name)
4755 return name;
4756
4757 if (signo >= SIGRTMIN && signo <= SIGRTMAX)
fa70beaa 4758 snprintf(buf, sizeof(buf), "RTMIN+%d", signo - SIGRTMIN);
4e240ab0 4759 else
fa70beaa
LP
4760 snprintf(buf, sizeof(buf), "%d", signo);
4761
4e240ab0
MS
4762 return buf;
4763}
4764
4765int signal_from_string(const char *s) {
4766 int signo;
4767 int offset = 0;
4768 unsigned u;
4769
040f18ea 4770 signo = __signal_from_string(s);
4e240ab0
MS
4771 if (signo > 0)
4772 return signo;
4773
4774 if (startswith(s, "RTMIN+")) {
4775 s += 6;
4776 offset = SIGRTMIN;
4777 }
4778 if (safe_atou(s, &u) >= 0) {
4779 signo = (int) u + offset;
4780 if (signo > 0 && signo < _NSIG)
4781 return signo;
4782 }
4783 return -1;
4784}
65457142
FC
4785
4786bool kexec_loaded(void) {
4787 bool loaded = false;
4788 char *s;
4789
4790 if (read_one_line_file("/sys/kernel/kexec_loaded", &s) >= 0) {
4791 if (s[0] == '1')
4792 loaded = true;
4793 free(s);
4794 }
4795 return loaded;
4796}
fb9de93d
LP
4797
4798int strdup_or_null(const char *a, char **b) {
4799 char *c;
4800
4801 assert(b);
4802
4803 if (!a) {
4804 *b = NULL;
4805 return 0;
4806 }
4807
4808 c = strdup(a);
4809 if (!c)
4810 return -ENOMEM;
4811
4812 *b = c;
4813 return 0;
4814}
64685e0c 4815
87d2c1ff
LP
4816int prot_from_flags(int flags) {
4817
4818 switch (flags & O_ACCMODE) {
4819
4820 case O_RDONLY:
4821 return PROT_READ;
4822
4823 case O_WRONLY:
4824 return PROT_WRITE;
4825
4826 case O_RDWR:
4827 return PROT_READ|PROT_WRITE;
4828
4829 default:
4830 return -EINVAL;
4831 }
7c99e0c1 4832}
689b9a22 4833
babfc091 4834char *format_bytes(char *buf, size_t l, off_t t) {
c0f99c21 4835 unsigned i;
babfc091
LP
4836
4837 static const struct {
4838 const char *suffix;
4839 off_t factor;
4840 } table[] = {
32895bb3
LP
4841 { "E", 1024ULL*1024ULL*1024ULL*1024ULL*1024ULL*1024ULL },
4842 { "P", 1024ULL*1024ULL*1024ULL*1024ULL*1024ULL },
babfc091
LP
4843 { "T", 1024ULL*1024ULL*1024ULL*1024ULL },
4844 { "G", 1024ULL*1024ULL*1024ULL },
4845 { "M", 1024ULL*1024ULL },
4846 { "K", 1024ULL },
4847 };
4848
4849 for (i = 0; i < ELEMENTSOF(table); i++) {
4850
4851 if (t >= table[i].factor) {
4852 snprintf(buf, l,
4853 "%llu.%llu%s",
4854 (unsigned long long) (t / table[i].factor),
4855 (unsigned long long) (((t*10ULL) / table[i].factor) % 10ULL),
4856 table[i].suffix);
4857
4858 goto finish;
4859 }
4860 }
4861
4862 snprintf(buf, l, "%lluB", (unsigned long long) t);
4863
4864finish:
4865 buf[l-1] = 0;
4866 return buf;
4867
4868}
55d7bfc1
LP
4869
4870void* memdup(const void *p, size_t l) {
4871 void *r;
4872
4873 assert(p);
4874
4875 r = malloc(l);
4876 if (!r)
4877 return NULL;
4878
4879 memcpy(r, p, l);
4880 return r;
4881}
bb99a35a
LP
4882
4883int fd_inc_sndbuf(int fd, size_t n) {
4884 int r, value;
4885 socklen_t l = sizeof(value);
4886
4887 r = getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &value, &l);
4888 if (r >= 0 &&
4889 l == sizeof(value) &&
4890 (size_t) value >= n*2)
4891 return 0;
4892
4893 value = (int) n;
4894 r = setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &value, sizeof(value));
4895 if (r < 0)
4896 return -errno;
4897
4898 return 1;
4899}
4900
4901int fd_inc_rcvbuf(int fd, size_t n) {
4902 int r, value;
4903 socklen_t l = sizeof(value);
4904
4905 r = getsockopt(fd, SOL_SOCKET, SO_RCVBUF, &value, &l);
4906 if (r >= 0 &&
4907 l == sizeof(value) &&
4908 (size_t) value >= n*2)
4909 return 0;
4910
4911 value = (int) n;
4912 r = setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &value, sizeof(value));
4913 if (r < 0)
4914 return -errno;
4915
4916 return 1;
4917}
6bb92a16 4918
9bdc770c 4919int fork_agent(pid_t *pid, const int except[], unsigned n_except, const char *path, ...) {
6bb92a16
LP
4920 pid_t parent_pid, agent_pid;
4921 int fd;
4922 bool stdout_is_tty, stderr_is_tty;
4923 unsigned n, i;
4924 va_list ap;
4925 char **l;
4926
4927 assert(pid);
4928 assert(path);
4929
4930 parent_pid = getpid();
4931
4932 /* Spawns a temporary TTY agent, making sure it goes away when
4933 * we go away */
4934
4935 agent_pid = fork();
4936 if (agent_pid < 0)
4937 return -errno;
4938
4939 if (agent_pid != 0) {
4940 *pid = agent_pid;
4941 return 0;
4942 }
4943
4944 /* In the child:
4945 *
4946 * Make sure the agent goes away when the parent dies */
4947 if (prctl(PR_SET_PDEATHSIG, SIGTERM) < 0)
4948 _exit(EXIT_FAILURE);
4949
4950 /* Check whether our parent died before we were able
4951 * to set the death signal */
4952 if (getppid() != parent_pid)
4953 _exit(EXIT_SUCCESS);
4954
4955 /* Don't leak fds to the agent */
9bdc770c 4956 close_all_fds(except, n_except);
6bb92a16
LP
4957
4958 stdout_is_tty = isatty(STDOUT_FILENO);
4959 stderr_is_tty = isatty(STDERR_FILENO);
4960
4961 if (!stdout_is_tty || !stderr_is_tty) {
4962 /* Detach from stdout/stderr. and reopen
4963 * /dev/tty for them. This is important to
4964 * ensure that when systemctl is started via
4965 * popen() or a similar call that expects to
4966 * read EOF we actually do generate EOF and
4967 * not delay this indefinitely by because we
4968 * keep an unused copy of stdin around. */
4969 fd = open("/dev/tty", O_WRONLY);
4970 if (fd < 0) {
4971 log_error("Failed to open /dev/tty: %m");
4972 _exit(EXIT_FAILURE);
4973 }
4974
4975 if (!stdout_is_tty)
4976 dup2(fd, STDOUT_FILENO);
4977
4978 if (!stderr_is_tty)
4979 dup2(fd, STDERR_FILENO);
4980
4981 if (fd > 2)
4982 close(fd);
4983 }
4984
4985 /* Count arguments */
4986 va_start(ap, path);
4987 for (n = 0; va_arg(ap, char*); n++)
4988 ;
4989 va_end(ap);
4990
4991 /* Allocate strv */
4992 l = alloca(sizeof(char *) * (n + 1));
4993
4994 /* Fill in arguments */
4995 va_start(ap, path);
4996 for (i = 0; i <= n; i++)
4997 l[i] = va_arg(ap, char*);
4998 va_end(ap);
4999
5000 execv(path, l);
5001 _exit(EXIT_FAILURE);
5002}
68faf98c
LP
5003
5004int setrlimit_closest(int resource, const struct rlimit *rlim) {
5005 struct rlimit highest, fixed;
5006
5007 assert(rlim);
5008
5009 if (setrlimit(resource, rlim) >= 0)
5010 return 0;
5011
5012 if (errno != EPERM)
5013 return -errno;
5014
5015 /* So we failed to set the desired setrlimit, then let's try
5016 * to get as close as we can */
5017 assert_se(getrlimit(resource, &highest) == 0);
5018
5019 fixed.rlim_cur = MIN(rlim->rlim_cur, highest.rlim_max);
5020 fixed.rlim_max = MIN(rlim->rlim_max, highest.rlim_max);
5021
5022 if (setrlimit(resource, &fixed) < 0)
5023 return -errno;
5024
5025 return 0;
5026}
3d9a4122 5027
ab94af92 5028int getenv_for_pid(pid_t pid, const char *field, char **_value) {
fa70beaa 5029 char path[sizeof("/proc/")-1 + DECIMAL_STR_MAX(pid_t) + sizeof("/environ")], *value = NULL;
ab94af92
LP
5030 int r;
5031 FILE *f;
5032 bool done = false;
5033 size_t l;
5034
5035 assert(field);
5036 assert(_value);
5037
5038 if (pid == 0)
5039 pid = getpid();
5040
5041 snprintf(path, sizeof(path), "/proc/%lu/environ", (unsigned long) pid);
ab94af92
LP
5042
5043 f = fopen(path, "re");
5044 if (!f)
5045 return -errno;
5046
5047 l = strlen(field);
5048 r = 0;
5049
5050 do {
5051 char line[LINE_MAX];
5052 unsigned i;
5053
5054 for (i = 0; i < sizeof(line)-1; i++) {
5055 int c;
5056
5057 c = getc(f);
5058 if (_unlikely_(c == EOF)) {
5059 done = true;
5060 break;
5061 } else if (c == 0)
5062 break;
5063
5064 line[i] = c;
5065 }
5066 line[i] = 0;
5067
5068 if (memcmp(line, field, l) == 0 && line[l] == '=') {
5069 value = strdup(line + l + 1);
5070 if (!value) {
5071 r = -ENOMEM;
5072 break;
5073 }
5074
5075 r = 1;
5076 break;
5077 }
5078
5079 } while (!done);
5080
5081 fclose(f);
5082
5083 if (r >= 0)
5084 *_value = value;
5085
5086 return r;
5087}
d889a206
LP
5088
5089int can_sleep(const char *type) {
e67f47e5 5090 char *w, *state;
d889a206 5091 size_t l, k;
d889a206 5092 int r;
e67f47e5 5093 _cleanup_free_ char *p = NULL;
d889a206
LP
5094
5095 assert(type);
5096
679b7d79
LP
5097 /* If /sys is read-only we cannot sleep */
5098 if (access("/sys/power/state", W_OK) < 0)
5099 return false;
5100
d889a206
LP
5101 r = read_one_line_file("/sys/power/state", &p);
5102 if (r < 0)
679b7d79 5103 return false;
d889a206
LP
5104
5105 k = strlen(type);
e67f47e5
LP
5106 FOREACH_WORD_SEPARATOR(w, l, p, WHITESPACE, state)
5107 if (l == k && memcmp(w, type, l) == 0)
5108 return true;
d889a206 5109
e67f47e5 5110 return false;
d889a206 5111}
49dbfa7b 5112
6524990f
LP
5113int can_sleep_disk(const char *type) {
5114 char *w, *state;
5115 size_t l, k;
5116 int r;
5117 _cleanup_free_ char *p = NULL;
5118
5119 assert(type);
5120
679b7d79
LP
5121 /* If /sys is read-only we cannot sleep */
5122 if (access("/sys/power/state", W_OK) < 0 ||
5123 access("/sys/power/disk", W_OK) < 0)
5124 return false;
5125
6524990f
LP
5126 r = read_one_line_file("/sys/power/disk", &p);
5127 if (r < 0)
679b7d79 5128 return false;
6524990f
LP
5129
5130 k = strlen(type);
5131 FOREACH_WORD_SEPARATOR(w, l, p, WHITESPACE, state) {
5132 if (l == k && memcmp(w, type, l) == 0)
5133 return true;
5134
5135 if (l == k + 2 && w[0] == '[' && memcmp(w + 1, type, l - 2) == 0 && w[l-1] == ']')
5136 return true;
5137 }
5138
5139 return false;
5140}
5141
49dbfa7b
LP
5142bool is_valid_documentation_url(const char *url) {
5143 assert(url);
5144
5145 if (startswith(url, "http://") && url[7])
5146 return true;
5147
5148 if (startswith(url, "https://") && url[8])
5149 return true;
5150
5151 if (startswith(url, "file:") && url[5])
5152 return true;
5153
5154 if (startswith(url, "info:") && url[5])
5155 return true;
5156
5157 if (startswith(url, "man:") && url[4])
5158 return true;
5159
5160 return false;
5161}
9be346c9
HH
5162
5163bool in_initrd(void) {
a05f97b3 5164 static __thread int saved = -1;
825c6fe5 5165 struct statfs s;
8f33b5b8 5166
825c6fe5
LP
5167 if (saved >= 0)
5168 return saved;
5169
5170 /* We make two checks here:
5171 *
5172 * 1. the flag file /etc/initrd-release must exist
5173 * 2. the root file system must be a memory file system
5174 *
5175 * The second check is extra paranoia, since misdetecting an
5176 * initrd can have bad bad consequences due the initrd
5177 * emptying when transititioning to the main systemd.
5178 */
5179
5180 saved = access("/etc/initrd-release", F_OK) >= 0 &&
5181 statfs("/", &s) >= 0 &&
943aad8c 5182 is_temporary_fs(&s);
9be346c9 5183
8f33b5b8 5184 return saved;
9be346c9 5185}
069cfc85
LP
5186
5187void warn_melody(void) {
e67f47e5 5188 _cleanup_close_ int fd = -1;
069cfc85
LP
5189
5190 fd = open("/dev/console", O_WRONLY|O_CLOEXEC|O_NOCTTY);
5191 if (fd < 0)
5192 return;
5193
040f18ea 5194 /* Yeah, this is synchronous. Kinda sucks. But well... */
069cfc85
LP
5195
5196 ioctl(fd, KIOCSOUND, (int)(1193180/440));
5197 usleep(125*USEC_PER_MSEC);
5198
5199 ioctl(fd, KIOCSOUND, (int)(1193180/220));
5200 usleep(125*USEC_PER_MSEC);
5201
5202 ioctl(fd, KIOCSOUND, (int)(1193180/220));
5203 usleep(125*USEC_PER_MSEC);
5204
5205 ioctl(fd, KIOCSOUND, 0);
069cfc85 5206}
cd3bd60a
LP
5207
5208int make_console_stdio(void) {
5209 int fd, r;
5210
5211 /* Make /dev/console the controlling terminal and stdin/stdout/stderr */
5212
5213 fd = acquire_terminal("/dev/console", false, true, true, (usec_t) -1);
5214 if (fd < 0) {
5215 log_error("Failed to acquire terminal: %s", strerror(-fd));
5216 return fd;
5217 }
5218
5219 r = make_stdio(fd);
5220 if (r < 0) {
5221 log_error("Failed to duplicate terminal fd: %s", strerror(-r));
5222 return r;
5223 }
5224
5225 return 0;
5226}
7c5f152a
LP
5227
5228int get_home_dir(char **_h) {
5229 char *h;
5230 const char *e;
5231 uid_t u;
5232 struct passwd *p;
5233
5234 assert(_h);
5235
5236 /* Take the user specified one */
5237 e = getenv("HOME");
5238 if (e) {
5239 h = strdup(e);
5240 if (!h)
5241 return -ENOMEM;
5242
5243 *_h = h;
5244 return 0;
5245 }
5246
5247 /* Hardcode home directory for root to avoid NSS */
5248 u = getuid();
5249 if (u == 0) {
5250 h = strdup("/root");
5251 if (!h)
5252 return -ENOMEM;
5253
5254 *_h = h;
5255 return 0;
5256 }
5257
5258 /* Check the database... */
5259 errno = 0;
5260 p = getpwuid(u);
5261 if (!p)
e67f47e5 5262 return errno ? -errno : -ESRCH;
7c5f152a
LP
5263
5264 if (!path_is_absolute(p->pw_dir))
5265 return -EINVAL;
5266
5267 h = strdup(p->pw_dir);
5268 if (!h)
5269 return -ENOMEM;
5270
5271 *_h = h;
5272 return 0;
5273}
5274
2fbe635a
LP
5275void fclosep(FILE **f) {
5276 if (*f)
5277 fclose(*f);
5278}
e67f47e5 5279
e985665d
ZJS
5280void pclosep(FILE **f) {
5281 if (*f)
5282 pclose(*f);
5283}
5284
e67f47e5
LP
5285void closep(int *fd) {
5286 if (*fd >= 0)
5287 close_nointr_nofail(*fd);
5288}
a05f97b3
LP
5289
5290void closedirp(DIR **d) {
5291 if (*d)
5292 closedir(*d);
5293}
25ea79fe 5294
0b507b17
LP
5295bool filename_is_safe(const char *p) {
5296
5297 if (isempty(p))
5298 return false;
5299
5300 if (strchr(p, '/'))
5301 return false;
5302
5303 if (streq(p, "."))
5304 return false;
5305
5306 if (streq(p, ".."))
5307 return false;
5308
5309 if (strlen(p) > FILENAME_MAX)
5310 return false;
5311
5312 return true;
5313}
5314
5315bool string_is_safe(const char *p) {
5316 const char *t;
5317
5318 assert(p);
5319
5320 for (t = p; *t; t++) {
01539d6e 5321 if (*t > 0 && *t < ' ')
0b507b17
LP
5322 return false;
5323
011afa76 5324 if (strchr("\\\"\'", *t))
0b507b17
LP
5325 return false;
5326 }
5327
5328 return true;
5329}
cfbc22ab 5330
4d1a6904
LP
5331bool string_has_cc(const char *p) {
5332 const char *t;
5333
5334 assert(p);
5335
5336 for (t = p; *t; t++)
5337 if (*t > 0 && *t < ' ')
5338 return true;
5339
5340 return false;
5341}
5342
e884315e
LP
5343bool path_is_safe(const char *p) {
5344
5345 if (isempty(p))
5346 return false;
5347
5348 if (streq(p, "..") || startswith(p, "../") || endswith(p, "/..") || strstr(p, "/../"))
5349 return false;
5350
5351 if (strlen(p) > PATH_MAX)
5352 return false;
5353
5354 /* The following two checks are not really dangerous, but hey, they still are confusing */
5355 if (streq(p, ".") || startswith(p, "./") || endswith(p, "/.") || strstr(p, "/./"))
5356 return false;
5357
5358 if (strstr(p, "//"))
5359 return false;
5360
5361 return true;
5362}
5363
a9e12476
KS
5364/* hey glibc, APIs with callbacks without a user pointer are so useless */
5365void *xbsearch_r(const void *key, const void *base, size_t nmemb, size_t size,
1c574591 5366 int (*compar) (const void *, const void *, void *), void *arg) {
a9e12476
KS
5367 size_t l, u, idx;
5368 const void *p;
5369 int comparison;
5370
5371 l = 0;
5372 u = nmemb;
5373 while (l < u) {
5374 idx = (l + u) / 2;
5375 p = (void *)(((const char *) base) + (idx * size));
5376 comparison = compar(key, p, arg);
5377 if (comparison < 0)
5378 u = idx;
5379 else if (comparison > 0)
5380 l = idx + 1;
5381 else
5382 return (void *)p;
5383 }
5384 return NULL;
5385}
09017585
MS
5386
5387bool is_locale_utf8(void) {
5388 const char *set;
5389 static int cached_answer = -1;
5390
5391 if (cached_answer >= 0)
5392 goto out;
5393
5394 if (!setlocale(LC_ALL, "")) {
5395 cached_answer = true;
5396 goto out;
5397 }
5398
5399 set = nl_langinfo(CODESET);
5400 if (!set) {
5401 cached_answer = true;
5402 goto out;
5403 }
5404
5405 cached_answer = streq(set, "UTF-8");
5406out:
5407 return (bool)cached_answer;
5408}
c339d977
MS
5409
5410const char *draw_special_char(DrawSpecialChar ch) {
5411 static const char *draw_table[2][_DRAW_SPECIAL_CHAR_MAX] = {
5412 /* UTF-8 */ {
45a5ff0d
MS
5413 [DRAW_TREE_VERT] = "\342\224\202 ", /* │ */
5414 [DRAW_TREE_BRANCH] = "\342\224\234\342\224\200", /* ├─ */
5415 [DRAW_TREE_RIGHT] = "\342\224\224\342\224\200", /* └─ */
55c0b89c 5416 [DRAW_TREE_SPACE] = " ", /* */
45a5ff0d 5417 [DRAW_TRIANGULAR_BULLET] = "\342\200\243 ", /* ‣ */
c339d977
MS
5418 },
5419 /* ASCII fallback */ {
45a5ff0d
MS
5420 [DRAW_TREE_VERT] = "| ",
5421 [DRAW_TREE_BRANCH] = "|-",
5422 [DRAW_TREE_RIGHT] = "`-",
55c0b89c 5423 [DRAW_TREE_SPACE] = " ",
45a5ff0d 5424 [DRAW_TRIANGULAR_BULLET] = "> ",
c339d977
MS
5425 }
5426 };
5427
5428 return draw_table[!is_locale_utf8()][ch];
5429}
409bc9c3
LP
5430
5431char *strreplace(const char *text, const char *old_string, const char *new_string) {
5432 const char *f;
5433 char *t, *r;
5434 size_t l, old_len, new_len;
5435
5436 assert(text);
5437 assert(old_string);
5438 assert(new_string);
5439
5440 old_len = strlen(old_string);
5441 new_len = strlen(new_string);
5442
5443 l = strlen(text);
5444 r = new(char, l+1);
5445 if (!r)
5446 return NULL;
5447
5448 f = text;
5449 t = r;
5450 while (*f) {
5451 char *a;
5452 size_t d, nl;
5453
5454 if (!startswith(f, old_string)) {
5455 *(t++) = *(f++);
5456 continue;
5457 }
5458
5459 d = t - r;
5460 nl = l - old_len + new_len;
5461 a = realloc(r, nl + 1);
5462 if (!a)
5463 goto oom;
5464
5465 l = nl;
5466 r = a;
5467 t = r + d;
5468
5469 t = stpcpy(t, new_string);
5470 f += old_len;
5471 }
5472
5473 *t = 0;
5474 return r;
5475
5476oom:
5477 free(r);
5478 return NULL;
5479}
e8bc0ea2
LP
5480
5481char *strip_tab_ansi(char **ibuf, size_t *_isz) {
660ddc72 5482 const char *i, *begin = NULL;
e8bc0ea2
LP
5483 enum {
5484 STATE_OTHER,
5485 STATE_ESCAPE,
5486 STATE_BRACKET
5487 } state = STATE_OTHER;
5488 char *obuf = NULL;
5489 size_t osz = 0, isz;
5490 FILE *f;
5491
5492 assert(ibuf);
5493 assert(*ibuf);
5494
5495 /* Strips ANSI color and replaces TABs by 8 spaces */
5496
5497 isz = _isz ? *_isz : strlen(*ibuf);
5498
5499 f = open_memstream(&obuf, &osz);
5500 if (!f)
5501 return NULL;
5502
5503 for (i = *ibuf; i < *ibuf + isz + 1; i++) {
5504
5505 switch (state) {
5506
5507 case STATE_OTHER:
5508 if (i >= *ibuf + isz) /* EOT */
5509 break;
5510 else if (*i == '\x1B')
5511 state = STATE_ESCAPE;
5512 else if (*i == '\t')
5513 fputs(" ", f);
5514 else
5515 fputc(*i, f);
5516 break;
5517
5518 case STATE_ESCAPE:
5519 if (i >= *ibuf + isz) { /* EOT */
5520 fputc('\x1B', f);
5521 break;
5522 } else if (*i == '[') {
5523 state = STATE_BRACKET;
5524 begin = i + 1;
5525 } else {
5526 fputc('\x1B', f);
5527 fputc(*i, f);
5528 state = STATE_OTHER;
5529 }
5530
5531 break;
5532
5533 case STATE_BRACKET:
5534
5535 if (i >= *ibuf + isz || /* EOT */
5536 (!(*i >= '0' && *i <= '9') && *i != ';' && *i != 'm')) {
5537 fputc('\x1B', f);
5538 fputc('[', f);
5539 state = STATE_OTHER;
5540 i = begin-1;
5541 } else if (*i == 'm')
5542 state = STATE_OTHER;
5543 break;
5544 }
5545 }
5546
5547 if (ferror(f)) {
5548 fclose(f);
5549 free(obuf);
5550 return NULL;
5551 }
5552
5553 fclose(f);
5554
5555 free(*ibuf);
5556 *ibuf = obuf;
5557
5558 if (_isz)
5559 *_isz = osz;
5560
5561 return obuf;
5562}
240dbaa4
LP
5563
5564int on_ac_power(void) {
5565 bool found_offline = false, found_online = false;
5566 _cleanup_closedir_ DIR *d = NULL;
5567
5568 d = opendir("/sys/class/power_supply");
5569 if (!d)
5570 return -errno;
5571
5572 for (;;) {
5573 struct dirent *de;
5574 union dirent_storage buf;
240dbaa4
LP
5575 _cleanup_close_ int fd = -1, device = -1;
5576 char contents[6];
5577 ssize_t n;
5578 int k;
5579
5580 k = readdir_r(d, &buf.de, &de);
5581 if (k != 0)
5582 return -k;
5583
5584 if (!de)
5585 break;
5586
5587 if (ignore_file(de->d_name))
5588 continue;
5589
5590 device = openat(dirfd(d), de->d_name, O_DIRECTORY|O_RDONLY|O_CLOEXEC|O_NOCTTY);
5591 if (device < 0) {
5592 if (errno == ENOENT || errno == ENOTDIR)
5593 continue;
5594
5595 return -errno;
5596 }
5597
5598 fd = openat(device, "type", O_RDONLY|O_CLOEXEC|O_NOCTTY);
5599 if (fd < 0) {
5600 if (errno == ENOENT)
5601 continue;
5602
5603 return -errno;
5604 }
5605
5606 n = read(fd, contents, sizeof(contents));
5607 if (n < 0)
5608 return -errno;
5609
5610 if (n != 6 || memcmp(contents, "Mains\n", 6))
5611 continue;
5612
5613 close_nointr_nofail(fd);
5614 fd = openat(device, "online", O_RDONLY|O_CLOEXEC|O_NOCTTY);
5615 if (fd < 0) {
5616 if (errno == ENOENT)
5617 continue;
5618
5619 return -errno;
5620 }
5621
5622 n = read(fd, contents, sizeof(contents));
5623 if (n < 0)
5624 return -errno;
5625
5626 if (n != 2 || contents[1] != '\n')
5627 return -EIO;
5628
5629 if (contents[0] == '1') {
5630 found_online = true;
5631 break;
5632 } else if (contents[0] == '0')
5633 found_offline = true;
5634 else
5635 return -EIO;
5636 }
5637
5638 return found_online || !found_offline;
5639}
fabe5c0e
LP
5640
5641static int search_and_fopen_internal(const char *path, const char *mode, char **search, FILE **_f) {
5642 char **i;
5643
5644 assert(path);
5645 assert(mode);
5646 assert(_f);
5647
5648 if (!path_strv_canonicalize_uniq(search))
5649 return -ENOMEM;
5650
5651 STRV_FOREACH(i, search) {
5652 _cleanup_free_ char *p = NULL;
5653 FILE *f;
5654
5655 p = strjoin(*i, "/", path, NULL);
5656 if (!p)
5657 return -ENOMEM;
5658
5659 f = fopen(p, mode);
5660 if (f) {
5661 *_f = f;
5662 return 0;
5663 }
5664
5665 if (errno != ENOENT)
5666 return -errno;
5667 }
5668
5669 return -ENOENT;
5670}
5671
5672int search_and_fopen(const char *path, const char *mode, const char **search, FILE **_f) {
5673 _cleanup_strv_free_ char **copy = NULL;
5674
5675 assert(path);
5676 assert(mode);
5677 assert(_f);
5678
5679 if (path_is_absolute(path)) {
5680 FILE *f;
5681
5682 f = fopen(path, mode);
5683 if (f) {
5684 *_f = f;
5685 return 0;
5686 }
5687
5688 return -errno;
5689 }
5690
5691 copy = strv_copy((char**) search);
5692 if (!copy)
5693 return -ENOMEM;
5694
5695 return search_and_fopen_internal(path, mode, copy, _f);
5696}
5697
5698int search_and_fopen_nulstr(const char *path, const char *mode, const char *search, FILE **_f) {
5699 _cleanup_strv_free_ char **s = NULL;
5700
5701 if (path_is_absolute(path)) {
5702 FILE *f;
5703
5704 f = fopen(path, mode);
5705 if (f) {
5706 *_f = f;
5707 return 0;
5708 }
5709
5710 return -errno;
5711 }
5712
5713 s = strv_split_nulstr(search);
5714 if (!s)
5715 return -ENOMEM;
5716
5717 return search_and_fopen_internal(path, mode, s, _f);
5718}
c17ec25e 5719
d34cd374 5720int create_tmp_dir(char template[], char** dir_name) {
c17ec25e 5721 int r = 0;
d34cd374 5722 char *d, *dt;
c17ec25e
MS
5723
5724 assert(dir_name);
5725
5c0d398d
LP
5726 RUN_WITH_UMASK(0077) {
5727 d = mkdtemp(template);
5728 }
c17ec25e 5729 if (!d) {
d34cd374
ZJS
5730 log_error("Can't create directory %s: %m", template);
5731 return -errno;
c17ec25e
MS
5732 }
5733
d34cd374
ZJS
5734 dt = strjoin(d, "/tmp", NULL);
5735 if (!dt) {
c17ec25e 5736 r = log_oom();
f36a783c 5737 goto fail3;
c17ec25e
MS
5738 }
5739
5c0d398d
LP
5740 RUN_WITH_UMASK(0000) {
5741 r = mkdir(dt, 0777);
5742 }
5743 if (r < 0) {
d34cd374
ZJS
5744 log_error("Can't create directory %s: %m", dt);
5745 r = -errno;
f36a783c 5746 goto fail2;
d34cd374
ZJS
5747 }
5748 log_debug("Created temporary directory %s", dt);
5749
5750 r = chmod(dt, 0777 | S_ISVTX);
5751 if (r < 0) {
5752 log_error("Failed to chmod %s: %m", dt);
5753 r = -errno;
5754 goto fail1;
c17ec25e 5755 }
d34cd374 5756 log_debug("Set sticky bit on %s", dt);
c17ec25e 5757
d34cd374 5758 *dir_name = dt;
c17ec25e
MS
5759
5760 return 0;
d34cd374
ZJS
5761fail1:
5762 rmdir(dt);
5763fail2:
f36a783c
VP
5764 free(dt);
5765fail3:
d34cd374 5766 rmdir(template);
c17ec25e
MS
5767 return r;
5768}
66e35261
LP
5769
5770char *strextend(char **x, ...) {
5771 va_list ap;
5772 size_t f, l;
5773 char *r, *p;
5774
5775 assert(x);
5776
5777 l = f = *x ? strlen(*x) : 0;
5778
5779 va_start(ap, x);
5780 for (;;) {
5781 const char *t;
5782 size_t n;
5783
5784 t = va_arg(ap, const char *);
5785 if (!t)
5786 break;
5787
5788 n = strlen(t);
5789 if (n > ((size_t) -1) - l) {
5790 va_end(ap);
5791 return NULL;
5792 }
5793
5794 l += n;
5795 }
5796 va_end(ap);
5797
5798 r = realloc(*x, l+1);
5799 if (!r)
5800 return NULL;
5801
5802 p = r + f;
5803
5804 va_start(ap, x);
5805 for (;;) {
5806 const char *t;
5807
5808 t = va_arg(ap, const char *);
5809 if (!t)
5810 break;
5811
5812 p = stpcpy(p, t);
5813 }
5814 va_end(ap);
5815
5816 *p = 0;
5817 *x = r;
5818
5819 return r + l;
5820}
9a17484d
LP
5821
5822char *strrep(const char *s, unsigned n) {
5823 size_t l;
5824 char *r, *p;
5825 unsigned i;
5826
5827 assert(s);
5828
5829 l = strlen(s);
5830 p = r = malloc(l * n + 1);
5831 if (!r)
5832 return NULL;
5833
5834 for (i = 0; i < n; i++)
5835 p = stpcpy(p, s);
5836
5837 *p = 0;
5838 return r;
5839}
392d5b37
LP
5840
5841void* greedy_realloc(void **p, size_t *allocated, size_t need) {
5842 size_t a;
5843 void *q;
5844
5845 if (*allocated >= need)
5846 return *p;
5847
9607d947 5848 a = MAX(64u, need * 2);
392d5b37
LP
5849 q = realloc(*p, a);
5850 if (!q)
5851 return NULL;
5852
5853 *p = q;
5854 *allocated = a;
5855 return q;
5856}