]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/shared/util.c
systemctl: add command set-log-level
[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
37f85e66 83size_t page_size(void) {
84 static __thread size_t pgsz = 0;
85 long r;
86
87d2c1ff 87 if (_likely_(pgsz > 0))
37f85e66 88 return pgsz;
89
e67f47e5
LP
90 r = sysconf(_SC_PAGESIZE);
91 assert(r > 0);
37f85e66 92
93 pgsz = (size_t) r;
37f85e66 94 return pgsz;
95}
96
e05797fb
LP
97bool streq_ptr(const char *a, const char *b) {
98
99 /* Like streq(), but tries to make sense of NULL pointers */
100
101 if (a && b)
102 return streq(a, b);
103
104 if (!a && !b)
105 return true;
106
107 return false;
108}
109
8c7c140f 110char* endswith(const char *s, const char *postfix) {
60918275
LP
111 size_t sl, pl;
112
113 assert(s);
114 assert(postfix);
115
116 sl = strlen(s);
117 pl = strlen(postfix);
118
d4d0d4db 119 if (pl == 0)
8c7c140f 120 return (char*) s + sl;
d4d0d4db 121
60918275 122 if (sl < pl)
8c7c140f
LP
123 return NULL;
124
125 if (memcmp(s + sl - pl, postfix, pl) != 0)
126 return NULL;
60918275 127
8c7c140f 128 return (char*) s + sl - pl;
60918275
LP
129}
130
e8988fc2
LP
131char* startswith(const char *s, const char *prefix) {
132 const char *a, *b;
60918275
LP
133
134 assert(s);
135 assert(prefix);
136
e8988fc2
LP
137 a = s, b = prefix;
138 for (;;) {
139 if (*b == 0)
140 return (char*) a;
141 if (*a != *b)
142 return NULL;
60918275 143
e8988fc2
LP
144 a++, b++;
145 }
60918275
LP
146}
147
e8988fc2
LP
148char* startswith_no_case(const char *s, const char *prefix) {
149 const char *a, *b;
3177a7fa
MAP
150
151 assert(s);
152 assert(prefix);
153
e8988fc2
LP
154 a = s, b = prefix;
155 for (;;) {
156 if (*b == 0)
157 return (char*) a;
158 if (tolower(*a) != tolower(*b))
159 return NULL;
3177a7fa 160
e8988fc2
LP
161 a++, b++;
162 }
3177a7fa
MAP
163}
164
79d6d816
LP
165bool first_word(const char *s, const char *word) {
166 size_t sl, wl;
167
168 assert(s);
169 assert(word);
170
171 sl = strlen(s);
172 wl = strlen(word);
173
174 if (sl < wl)
175 return false;
176
d4d0d4db
LP
177 if (wl == 0)
178 return true;
179
79d6d816
LP
180 if (memcmp(s, word, wl) != 0)
181 return false;
182
d4d0d4db
LP
183 return s[wl] == 0 ||
184 strchr(WHITESPACE, s[wl]);
79d6d816
LP
185}
186
42f4e3c4 187int close_nointr(int fd) {
b0ee8068 188 int r;
60918275 189
b0ee8068
CW
190 assert(fd >= 0);
191 r = close(fd);
192
193 /* Just ignore EINTR; a retry loop is the wrong
194 * thing to do on Linux.
195 *
196 * http://lkml.indiana.edu/hypermail/linux/kernel/0509.1/0877.html
197 * https://bugzilla.gnome.org/show_bug.cgi?id=682819
198 * http://utcc.utoronto.ca/~cks/space/blog/unix/CloseEINTR
199 * https://sites.google.com/site/michaelsafyan/software-engineering/checkforeintrwheninvokingclosethinkagain
200 */
201 if (_unlikely_(r < 0 && errno == EINTR))
202 return 0;
203 else if (r >= 0)
204 return r;
205 else
206 return -errno;
60918275 207}
85261803 208
85f136b5 209void close_nointr_nofail(int fd) {
5c0aa72a 210 PROTECT_ERRNO;
85f136b5
LP
211
212 /* like close_nointr() but cannot fail, and guarantees errno
213 * is unchanged */
214
215 assert_se(close_nointr(fd) == 0);
216}
217
5b6319dc
LP
218void close_many(const int fds[], unsigned n_fd) {
219 unsigned i;
220
2c93b4ef
LP
221 assert(fds || n_fd <= 0);
222
5b6319dc
LP
223 for (i = 0; i < n_fd; i++)
224 close_nointr_nofail(fds[i]);
225}
226
4b73a0c0
LP
227int unlink_noerrno(const char *path) {
228 PROTECT_ERRNO;
229 int r;
230
231 r = unlink(path);
232 if (r < 0)
233 return -errno;
234
235 return 0;
236}
237
85261803
LP
238int parse_boolean(const char *v) {
239 assert(v);
240
b43d1d01 241 if (streq(v, "1") || v[0] == 'y' || v[0] == 'Y' || v[0] == 't' || v[0] == 'T' || strcaseeq(v, "on"))
85261803 242 return 1;
b43d1d01 243 else if (streq(v, "0") || v[0] == 'n' || v[0] == 'N' || v[0] == 'f' || v[0] == 'F' || strcaseeq(v, "off"))
85261803
LP
244 return 0;
245
246 return -EINVAL;
247}
248
3ba686c1 249int parse_pid(const char *s, pid_t* ret_pid) {
0b172489 250 unsigned long ul = 0;
3ba686c1
LP
251 pid_t pid;
252 int r;
253
254 assert(s);
255 assert(ret_pid);
256
e67f47e5
LP
257 r = safe_atolu(s, &ul);
258 if (r < 0)
3ba686c1
LP
259 return r;
260
261 pid = (pid_t) ul;
262
263 if ((unsigned long) pid != ul)
264 return -ERANGE;
265
266 if (pid <= 0)
267 return -ERANGE;
268
269 *ret_pid = pid;
270 return 0;
271}
272
034a2a52
LP
273int parse_uid(const char *s, uid_t* ret_uid) {
274 unsigned long ul = 0;
275 uid_t uid;
276 int r;
277
278 assert(s);
279 assert(ret_uid);
280
e67f47e5
LP
281 r = safe_atolu(s, &ul);
282 if (r < 0)
034a2a52
LP
283 return r;
284
285 uid = (uid_t) ul;
286
287 if ((unsigned long) uid != ul)
288 return -ERANGE;
289
290 *ret_uid = uid;
291 return 0;
292}
293
85261803
LP
294int safe_atou(const char *s, unsigned *ret_u) {
295 char *x = NULL;
034c6ed7 296 unsigned long l;
85261803
LP
297
298 assert(s);
299 assert(ret_u);
300
301 errno = 0;
302 l = strtoul(s, &x, 0);
303
f3910003 304 if (!x || x == s || *x || errno)
48deb058 305 return errno > 0 ? -errno : -EINVAL;
85261803 306
034c6ed7 307 if ((unsigned long) (unsigned) l != l)
85261803
LP
308 return -ERANGE;
309
310 *ret_u = (unsigned) l;
311 return 0;
312}
313
314int safe_atoi(const char *s, int *ret_i) {
315 char *x = NULL;
034c6ed7 316 long l;
85261803
LP
317
318 assert(s);
319 assert(ret_i);
320
321 errno = 0;
322 l = strtol(s, &x, 0);
323
f3910003 324 if (!x || x == s || *x || errno)
48deb058 325 return errno > 0 ? -errno : -EINVAL;
85261803 326
034c6ed7 327 if ((long) (int) l != l)
85261803
LP
328 return -ERANGE;
329
034c6ed7
LP
330 *ret_i = (int) l;
331 return 0;
332}
333
034c6ed7
LP
334int safe_atollu(const char *s, long long unsigned *ret_llu) {
335 char *x = NULL;
336 unsigned long long l;
337
338 assert(s);
339 assert(ret_llu);
340
341 errno = 0;
342 l = strtoull(s, &x, 0);
343
f3910003 344 if (!x || x == s || *x || errno)
034c6ed7
LP
345 return errno ? -errno : -EINVAL;
346
347 *ret_llu = l;
348 return 0;
349}
350
351int safe_atolli(const char *s, long long int *ret_lli) {
352 char *x = NULL;
353 long long l;
354
355 assert(s);
356 assert(ret_lli);
357
358 errno = 0;
359 l = strtoll(s, &x, 0);
360
f3910003 361 if (!x || x == s || *x || errno)
034c6ed7
LP
362 return errno ? -errno : -EINVAL;
363
364 *ret_lli = l;
85261803
LP
365 return 0;
366}
a41e8209 367
f7900e25
TA
368int safe_atod(const char *s, double *ret_d) {
369 char *x = NULL;
370 double d;
371
372 assert(s);
373 assert(ret_d);
374
d6dd604b
LP
375 RUN_WITH_LOCALE(LC_NUMERIC_MASK, "C") {
376 errno = 0;
377 d = strtod(s, &x);
378 }
f7900e25
TA
379
380 if (!x || x == s || *x || errno)
381 return errno ? -errno : -EINVAL;
382
383 *ret_d = (double) d;
384 return 0;
385}
386
a41e8209 387/* Split a string into words. */
65d2ebdc 388char *split(const char *c, size_t *l, const char *separator, char **state) {
a41e8209
LP
389 char *current;
390
391 current = *state ? *state : (char*) c;
392
393 if (!*current || *c == 0)
394 return NULL;
395
65d2ebdc
LP
396 current += strspn(current, separator);
397 *l = strcspn(current, separator);
82919e3d
LP
398 *state = current+*l;
399
400 return (char*) current;
401}
402
034c6ed7
LP
403/* Split a string into words, but consider strings enclosed in '' and
404 * "" as words even if they include spaces. */
405char *split_quoted(const char *c, size_t *l, char **state) {
0bab36f2
LP
406 char *current, *e;
407 bool escaped = false;
034c6ed7
LP
408
409 current = *state ? *state : (char*) c;
410
411 if (!*current || *c == 0)
412 return NULL;
413
414 current += strspn(current, WHITESPACE);
415
416 if (*current == '\'') {
417 current ++;
034c6ed7 418
0bab36f2
LP
419 for (e = current; *e; e++) {
420 if (escaped)
421 escaped = false;
422 else if (*e == '\\')
423 escaped = true;
424 else if (*e == '\'')
425 break;
426 }
427
428 *l = e-current;
429 *state = *e == 0 ? e : e+1;
034c6ed7
LP
430 } else if (*current == '\"') {
431 current ++;
034c6ed7 432
0bab36f2
LP
433 for (e = current; *e; e++) {
434 if (escaped)
435 escaped = false;
436 else if (*e == '\\')
437 escaped = true;
438 else if (*e == '\"')
439 break;
440 }
441
442 *l = e-current;
443 *state = *e == 0 ? e : e+1;
034c6ed7 444 } else {
0bab36f2
LP
445 for (e = current; *e; e++) {
446 if (escaped)
447 escaped = false;
448 else if (*e == '\\')
449 escaped = true;
450 else if (strchr(WHITESPACE, *e))
451 break;
452 }
453 *l = e-current;
454 *state = e;
034c6ed7
LP
455 }
456
457 return (char*) current;
458}
459
034c6ed7
LP
460int get_parent_of_pid(pid_t pid, pid_t *_ppid) {
461 int r;
2fbe635a 462 _cleanup_fclose_ FILE *f = NULL;
49aa47c7 463 char line[LINE_MAX];
bb00e604 464 long unsigned ppid;
49aa47c7 465 const char *p;
034c6ed7 466
49aa47c7 467 assert(pid >= 0);
034c6ed7
LP
468 assert(_ppid);
469
49aa47c7
LP
470 if (pid == 0) {
471 *_ppid = getppid();
472 return 0;
473 }
034c6ed7 474
49aa47c7
LP
475 p = procfs_file_alloca(pid, "stat");
476 f = fopen(p, "re");
2fbe635a 477 if (!f)
034c6ed7
LP
478 return -errno;
479
2fbe635a 480 if (!fgets(line, sizeof(line), f)) {
35d50f55 481 r = feof(f) ? -EIO : -errno;
034c6ed7
LP
482 return r;
483 }
484
034c6ed7
LP
485 /* Let's skip the pid and comm fields. The latter is enclosed
486 * in () but does not escape any () in its value, so let's
487 * skip over it manually */
488
2fbe635a
LP
489 p = strrchr(line, ')');
490 if (!p)
034c6ed7
LP
491 return -EIO;
492
493 p++;
494
495 if (sscanf(p, " "
496 "%*c " /* state */
bb00e604 497 "%lu ", /* ppid */
034c6ed7
LP
498 &ppid) != 1)
499 return -EIO;
500
bb00e604 501 if ((long unsigned) (pid_t) ppid != ppid)
034c6ed7
LP
502 return -ERANGE;
503
504 *_ppid = (pid_t) ppid;
505
506 return 0;
507}
508
7640a5de 509int get_starttime_of_pid(pid_t pid, unsigned long long *st) {
e67f47e5 510 _cleanup_fclose_ FILE *f = NULL;
49aa47c7
LP
511 char line[LINE_MAX];
512 const char *p;
7640a5de 513
49aa47c7 514 assert(pid >= 0);
7640a5de
LP
515 assert(st);
516
49aa47c7
LP
517 if (pid == 0)
518 p = "/proc/self/stat";
519 else
520 p = procfs_file_alloca(pid, "stat");
7640a5de 521
49aa47c7 522 f = fopen(p, "re");
e67f47e5 523 if (!f)
7640a5de
LP
524 return -errno;
525
e67f47e5
LP
526 if (!fgets(line, sizeof(line), f)) {
527 if (ferror(f))
528 return -errno;
7640a5de 529
e67f47e5
LP
530 return -EIO;
531 }
7640a5de
LP
532
533 /* Let's skip the pid and comm fields. The latter is enclosed
534 * in () but does not escape any () in its value, so let's
535 * skip over it manually */
536
e67f47e5
LP
537 p = strrchr(line, ')');
538 if (!p)
7640a5de
LP
539 return -EIO;
540
541 p++;
542
543 if (sscanf(p, " "
544 "%*c " /* state */
545 "%*d " /* ppid */
546 "%*d " /* pgrp */
547 "%*d " /* session */
548 "%*d " /* tty_nr */
549 "%*d " /* tpgid */
550 "%*u " /* flags */
551 "%*u " /* minflt */
552 "%*u " /* cminflt */
553 "%*u " /* majflt */
554 "%*u " /* cmajflt */
555 "%*u " /* utime */
556 "%*u " /* stime */
557 "%*d " /* cutime */
558 "%*d " /* cstime */
559 "%*d " /* priority */
560 "%*d " /* nice */
561 "%*d " /* num_threads */
562 "%*d " /* itrealvalue */
563 "%llu " /* starttime */,
564 st) != 1)
565 return -EIO;
566
567 return 0;
568}
569
34ca941c
LP
570int fchmod_umask(int fd, mode_t m) {
571 mode_t u;
572 int r;
573
574 u = umask(0777);
575 r = fchmod(fd, m & (~u)) < 0 ? -errno : 0;
576 umask(u);
577
578 return r;
579}
580
7072ced8
LP
581char *truncate_nl(char *s) {
582 assert(s);
583
584 s[strcspn(s, NEWLINE)] = 0;
585 return s;
586}
587
87d2c1ff 588int get_process_comm(pid_t pid, char **name) {
49aa47c7 589 const char *p;
7072ced8 590
7072ced8 591 assert(name);
49aa47c7 592 assert(pid >= 0);
7072ced8 593
87d2c1ff 594 if (pid == 0)
49aa47c7
LP
595 p = "/proc/self/comm";
596 else
597 p = procfs_file_alloca(pid, "comm");
7072ced8 598
49aa47c7 599 return read_one_line_file(p, name);
7072ced8
LP
600}
601
87d2c1ff 602int get_process_cmdline(pid_t pid, size_t max_length, bool comm_fallback, char **line) {
49aa47c7 603 _cleanup_fclose_ FILE *f = NULL;
9bdbc2e2 604 char *r = NULL, *k;
49aa47c7 605 const char *p;
c59760ee 606 int c;
c59760ee 607
c59760ee 608 assert(line);
49aa47c7 609 assert(pid >= 0);
c59760ee 610
87d2c1ff 611 if (pid == 0)
49aa47c7
LP
612 p = "/proc/self/cmdline";
613 else
614 p = procfs_file_alloca(pid, "cmdline");
c59760ee 615
49aa47c7 616 f = fopen(p, "re");
c59760ee
LP
617 if (!f)
618 return -errno;
49aa47c7 619
9bdbc2e2 620 if (max_length == 0) {
49aa47c7
LP
621 size_t len = 0, allocated = 0;
622
9bdbc2e2 623 while ((c = getc(f)) != EOF) {
49aa47c7
LP
624
625 if (!GREEDY_REALLOC(r, allocated, len+2)) {
9bdbc2e2 626 free(r);
9bdbc2e2
LN
627 return -ENOMEM;
628 }
49aa47c7
LP
629
630 r[len++] = isprint(c) ? c : ' ';
9bdbc2e2 631 }
49aa47c7
LP
632
633 if (len > 0)
634 r[len-1] = 0;
635
9bdbc2e2
LN
636 } else {
637 bool space = false;
638 size_t left;
49aa47c7 639
9bdbc2e2 640 r = new(char, max_length);
49aa47c7 641 if (!r)
9bdbc2e2 642 return -ENOMEM;
c59760ee 643
9bdbc2e2
LN
644 k = r;
645 left = max_length;
646 while ((c = getc(f)) != EOF) {
c59760ee 647
9bdbc2e2
LN
648 if (isprint(c)) {
649 if (space) {
650 if (left <= 4)
651 break;
652
653 *(k++) = ' ';
654 left--;
655 space = false;
656 }
c59760ee 657
c59760ee
LP
658 if (left <= 4)
659 break;
660
9bdbc2e2 661 *(k++) = (char) c;
057fbb58 662 left--;
9bdbc2e2
LN
663 } else
664 space = true;
665 }
c59760ee 666
9bdbc2e2
LN
667 if (left <= 4) {
668 size_t n = MIN(left-1, 3U);
669 memcpy(k, "...", n);
670 k[n] = 0;
671 } else
672 *k = 0;
c59760ee
LP
673 }
674
35d2e7ec 675 /* Kernel threads have no argv[] */
9bdbc2e2 676 if (r == NULL || r[0] == 0) {
35d2e7ec
LP
677 char *t;
678 int h;
679
680 free(r);
681
87d2c1ff
LP
682 if (!comm_fallback)
683 return -ENOENT;
684
685 h = get_process_comm(pid, &t);
686 if (h < 0)
35d2e7ec
LP
687 return h;
688
b7def684 689 r = strjoin("[", t, "]", NULL);
35d2e7ec
LP
690 free(t);
691
87d2c1ff 692 if (!r)
35d2e7ec
LP
693 return -ENOMEM;
694 }
fa776d8e 695
c59760ee
LP
696 *line = r;
697 return 0;
698}
699
1e5678d0 700int is_kernel_thread(pid_t pid) {
49aa47c7 701 const char *p;
1e5678d0
LP
702 size_t count;
703 char c;
704 bool eof;
705 FILE *f;
706
707 if (pid == 0)
708 return 0;
709
49aa47c7 710 assert(pid > 0);
1e5678d0 711
49aa47c7
LP
712 p = procfs_file_alloca(pid, "cmdline");
713 f = fopen(p, "re");
1e5678d0
LP
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
49aa47c7 729
87d2c1ff 730int get_process_exe(pid_t pid, char **name) {
49aa47c7 731 const char *p;
87d2c1ff 732
49aa47c7 733 assert(pid >= 0);
87d2c1ff
LP
734 assert(name);
735
736 if (pid == 0)
49aa47c7
LP
737 p = "/proc/self/exe";
738 else
739 p = procfs_file_alloca(pid, "exe");
87d2c1ff 740
49aa47c7 741 return readlink_malloc(p, name);
87d2c1ff
LP
742}
743
901c3d0d 744static int get_process_id(pid_t pid, const char *field, uid_t *uid) {
f74e605f 745 _cleanup_fclose_ FILE *f = NULL;
9db11a99 746 char line[LINE_MAX];
49aa47c7 747 const char *p;
7e4ab3c5 748
f74e605f 749 assert(field);
7e4ab3c5
LP
750 assert(uid);
751
752 if (pid == 0)
753 return getuid();
754
49aa47c7
LP
755 p = procfs_file_alloca(pid, "status");
756 f = fopen(p, "re");
7e4ab3c5
LP
757 if (!f)
758 return -errno;
759
9db11a99 760 FOREACH_LINE(line, f, return -errno) {
f74e605f 761 char *l;
7e4ab3c5
LP
762
763 l = strstrip(line);
764
901c3d0d
LP
765 if (startswith(l, field)) {
766 l += strlen(field);
7e4ab3c5
LP
767 l += strspn(l, WHITESPACE);
768
769 l[strcspn(l, WHITESPACE)] = 0;
770
f74e605f 771 return parse_uid(l, uid);
7e4ab3c5
LP
772 }
773 }
774
f74e605f 775 return -EIO;
7e4ab3c5
LP
776}
777
901c3d0d
LP
778int get_process_uid(pid_t pid, uid_t *uid) {
779 return get_process_id(pid, "Uid:", uid);
780}
781
782int get_process_gid(pid_t pid, gid_t *gid) {
49aa47c7 783 assert_cc(sizeof(uid_t) == sizeof(gid_t));
901c3d0d
LP
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
44a6b1b6 1452_pure_ static 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
44a6b1b6 1515_pure_ static bool fd_in_set(int fd, const int fdset[], unsigned n_fdset) {
b19be9eb
LP
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 };
7fd1b19b 2076 _cleanup_close_ int 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) {
49aa47c7
LP
2569 _cleanup_fclose_ FILE *f = NULL;
2570 char line[LINE_MAX], *p;
fc116c6a 2571 unsigned long ttynr;
49aa47c7
LP
2572 const char *fn;
2573 int k;
fc116c6a 2574
49aa47c7
LP
2575 assert(pid >= 0);
2576 assert(d);
2577
2578 if (pid == 0)
2579 fn = "/proc/self/stat";
2580 else
2581 fn = procfs_file_alloca(pid, "stat");
4d6d6518
LP
2582
2583 f = fopen(fn, "re");
4d6d6518 2584 if (!f)
fc116c6a
LP
2585 return -errno;
2586
4d6d6518 2587 if (!fgets(line, sizeof(line), f)) {
35d50f55 2588 k = feof(f) ? -EIO : -errno;
fc116c6a
LP
2589 return k;
2590 }
2591
4d6d6518
LP
2592 p = strrchr(line, ')');
2593 if (!p)
fc116c6a
LP
2594 return -EIO;
2595
2596 p++;
2597
2598 if (sscanf(p, " "
2599 "%*c " /* state */
2600 "%*d " /* ppid */
2601 "%*d " /* pgrp */
2602 "%*d " /* session */
2603 "%lu ", /* ttynr */
2604 &ttynr) != 1)
2605 return -EIO;
2606
11dc5d2b
LP
2607 if (major(ttynr) == 0 && minor(ttynr) == 0)
2608 return -ENOENT;
2609
fc116c6a
LP
2610 *d = (dev_t) ttynr;
2611 return 0;
2612}
2613
4d6d6518 2614int get_ctty(pid_t pid, dev_t *_devnr, char **r) {
fc116c6a 2615 int k;
fa70beaa 2616 char fn[sizeof("/dev/char/")-1 + 2*DECIMAL_STR_MAX(unsigned) + 1 + 1], *s, *b, *p;
fc116c6a
LP
2617 dev_t devnr;
2618
2619 assert(r);
2620
4d6d6518
LP
2621 k = get_ctty_devnr(pid, &devnr);
2622 if (k < 0)
fc116c6a
LP
2623 return k;
2624
2625 snprintf(fn, sizeof(fn), "/dev/char/%u:%u", major(devnr), minor(devnr));
fc116c6a 2626
23406ce5
LP
2627 k = readlink_malloc(fn, &s);
2628 if (k < 0) {
fc116c6a
LP
2629
2630 if (k != -ENOENT)
2631 return k;
2632
46824d0e
LP
2633 /* This is an ugly hack */
2634 if (major(devnr) == 136) {
2635 if (asprintf(&b, "pts/%lu", (unsigned long) minor(devnr)) < 0)
2636 return -ENOMEM;
2637
2638 *r = b;
2639 if (_devnr)
2640 *_devnr = devnr;
2641
2642 return 0;
2643 }
2644
fc116c6a
LP
2645 /* Probably something like the ptys which have no
2646 * symlink in /dev/char. Let's return something
2647 * vaguely useful. */
2648
23406ce5
LP
2649 b = strdup(fn + 5);
2650 if (!b)
fc116c6a
LP
2651 return -ENOMEM;
2652
2653 *r = b;
46824d0e
LP
2654 if (_devnr)
2655 *_devnr = devnr;
2656
fc116c6a
LP
2657 return 0;
2658 }
2659
2660 if (startswith(s, "/dev/"))
2661 p = s + 5;
2662 else if (startswith(s, "../"))
2663 p = s + 3;
2664 else
2665 p = s;
2666
2667 b = strdup(p);
2668 free(s);
2669
2670 if (!b)
2671 return -ENOMEM;
2672
2673 *r = b;
46824d0e
LP
2674 if (_devnr)
2675 *_devnr = devnr;
2676
fc116c6a
LP
2677 return 0;
2678}
2679
f56d5db9 2680int rm_rf_children_dangerous(int fd, bool only_dirs, bool honour_sticky, struct stat *root_dev) {
8c6db833
LP
2681 DIR *d;
2682 int ret = 0;
2683
2684 assert(fd >= 0);
2685
2686 /* This returns the first error we run into, but nevertheless
7925c22a 2687 * tries to go on. This closes the passed fd. */
8c6db833 2688
d4d046e3
LP
2689 d = fdopendir(fd);
2690 if (!d) {
8c6db833 2691 close_nointr_nofail(fd);
4c633005
LP
2692
2693 return errno == ENOENT ? 0 : -errno;
8c6db833
LP
2694 }
2695
2696 for (;;) {
7d5e9c0f
LP
2697 struct dirent *de;
2698 union dirent_storage buf;
7925c22a
LP
2699 bool is_dir, keep_around;
2700 struct stat st;
8c6db833
LP
2701 int r;
2702
7d5e9c0f 2703 r = readdir_r(d, &buf.de, &de);
d4d046e3
LP
2704 if (r != 0 && ret == 0) {
2705 ret = -r;
8c6db833
LP
2706 break;
2707 }
2708
2709 if (!de)
2710 break;
2711
2712 if (streq(de->d_name, ".") || streq(de->d_name, ".."))
2713 continue;
2714
7925c22a
LP
2715 if (de->d_type == DT_UNKNOWN ||
2716 honour_sticky ||
2717 (de->d_type == DT_DIR && root_dev)) {
8c6db833 2718 if (fstatat(fd, de->d_name, &st, AT_SYMLINK_NOFOLLOW) < 0) {
4c633005 2719 if (ret == 0 && errno != ENOENT)
8c6db833
LP
2720 ret = -errno;
2721 continue;
2722 }
2723
2724 is_dir = S_ISDIR(st.st_mode);
7925c22a
LP
2725 keep_around =
2726 honour_sticky &&
2727 (st.st_uid == 0 || st.st_uid == getuid()) &&
2728 (st.st_mode & S_ISVTX);
ad293f5a 2729 } else {
8c6db833 2730 is_dir = de->d_type == DT_DIR;
7925c22a 2731 keep_around = false;
ad293f5a 2732 }
8c6db833
LP
2733
2734 if (is_dir) {
2735 int subdir_fd;
8c6db833 2736
597f43c7 2737 /* if root_dev is set, remove subdirectories only, if device is same as dir */
7925c22a
LP
2738 if (root_dev && st.st_dev != root_dev->st_dev)
2739 continue;
8c6db833 2740
7925c22a
LP
2741 subdir_fd = openat(fd, de->d_name,
2742 O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW|O_NOATIME);
2743 if (subdir_fd < 0) {
2744 if (ret == 0 && errno != ENOENT)
2745 ret = -errno;
2746 continue;
2747 }
2748
b3d28469 2749 r = rm_rf_children_dangerous(subdir_fd, only_dirs, honour_sticky, root_dev);
7925c22a
LP
2750 if (r < 0 && ret == 0)
2751 ret = r;
2752
2753 if (!keep_around)
2754 if (unlinkat(fd, de->d_name, AT_REMOVEDIR) < 0) {
ad293f5a
LP
2755 if (ret == 0 && errno != ENOENT)
2756 ret = -errno;
2757 }
2758
2759 } else if (!only_dirs && !keep_around) {
8c6db833
LP
2760
2761 if (unlinkat(fd, de->d_name, 0) < 0) {
4c633005 2762 if (ret == 0 && errno != ENOENT)
8c6db833
LP
2763 ret = -errno;
2764 }
2765 }
2766 }
2767
2768 closedir(d);
2769
2770 return ret;
2771}
2772
44a6b1b6 2773_pure_ static int is_temporary_fs(struct statfs *s) {
943aad8c 2774 assert(s);
bdd29249
HH
2775 return
2776 F_TYPE_CMP(s->f_type, TMPFS_MAGIC) ||
2777 F_TYPE_CMP(s->f_type, RAMFS_MAGIC);
943aad8c
ZJS
2778}
2779
f56d5db9
LP
2780int rm_rf_children(int fd, bool only_dirs, bool honour_sticky, struct stat *root_dev) {
2781 struct statfs s;
2782
2783 assert(fd >= 0);
2784
2785 if (fstatfs(fd, &s) < 0) {
2786 close_nointr_nofail(fd);
2787 return -errno;
2788 }
2789
2790 /* We refuse to clean disk file systems with this call. This
2791 * is extra paranoia just to be sure we never ever remove
2792 * non-state data */
943aad8c 2793 if (!is_temporary_fs(&s)) {
f56d5db9
LP
2794 log_error("Attempted to remove disk file system, and we can't allow that.");
2795 close_nointr_nofail(fd);
2796 return -EPERM;
2797 }
2798
2799 return rm_rf_children_dangerous(fd, only_dirs, honour_sticky, root_dev);
2800}
2801
2802static int rm_rf_internal(const char *path, bool only_dirs, bool delete_root, bool honour_sticky, bool dangerous) {
2803 int fd, r;
2804 struct statfs s;
8c6db833
LP
2805
2806 assert(path);
2807
f56d5db9
LP
2808 /* We refuse to clean the root file system with this
2809 * call. This is extra paranoia to never cause a really
2810 * seriously broken system. */
2811 if (path_equal(path, "/")) {
2812 log_error("Attempted to remove entire root file system, and we can't allow that.");
2813 return -EPERM;
2814 }
461b1822 2815
d4d046e3
LP
2816 fd = open(path, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW|O_NOATIME);
2817 if (fd < 0) {
8c6db833
LP
2818
2819 if (errno != ENOTDIR)
2820 return -errno;
2821
f56d5db9
LP
2822 if (!dangerous) {
2823 if (statfs(path, &s) < 0)
2824 return -errno;
2825
943aad8c 2826 if (!is_temporary_fs(&s)) {
f56d5db9
LP
2827 log_error("Attempted to remove disk file system, and we can't allow that.");
2828 return -EPERM;
2829 }
2830 }
2831
8c6db833 2832 if (delete_root && !only_dirs)
d4d046e3 2833 if (unlink(path) < 0 && errno != ENOENT)
8c6db833
LP
2834 return -errno;
2835
2836 return 0;
2837 }
2838
f56d5db9
LP
2839 if (!dangerous) {
2840 if (fstatfs(fd, &s) < 0) {
2841 close_nointr_nofail(fd);
2842 return -errno;
2843 }
ad293f5a 2844
943aad8c 2845 if (!is_temporary_fs(&s)) {
f56d5db9
LP
2846 log_error("Attempted to remove disk file system, and we can't allow that.");
2847 close_nointr_nofail(fd);
2848 return -EPERM;
2849 }
2850 }
2851
2852 r = rm_rf_children_dangerous(fd, only_dirs, honour_sticky, NULL);
ad293f5a
LP
2853 if (delete_root) {
2854
8d53b453 2855 if (honour_sticky && file_is_priv_sticky(path) > 0)
ad293f5a 2856 return r;
8c6db833 2857
e27796a0 2858 if (rmdir(path) < 0 && errno != ENOENT) {
8c6db833
LP
2859 if (r == 0)
2860 r = -errno;
2861 }
ad293f5a 2862 }
8c6db833
LP
2863
2864 return r;
2865}
2866
f56d5db9
LP
2867int rm_rf(const char *path, bool only_dirs, bool delete_root, bool honour_sticky) {
2868 return rm_rf_internal(path, only_dirs, delete_root, honour_sticky, false);
2869}
2870
2871int rm_rf_dangerous(const char *path, bool only_dirs, bool delete_root, bool honour_sticky) {
2872 return rm_rf_internal(path, only_dirs, delete_root, honour_sticky, true);
2873}
2874
8c6db833
LP
2875int chmod_and_chown(const char *path, mode_t mode, uid_t uid, gid_t gid) {
2876 assert(path);
2877
2878 /* Under the assumption that we are running privileged we
2879 * first change the access mode and only then hand out
2880 * ownership to avoid a window where access is too open. */
2881
8d53b453
LP
2882 if (mode != (mode_t) -1)
2883 if (chmod(path, mode) < 0)
2884 return -errno;
8c6db833 2885
8d53b453
LP
2886 if (uid != (uid_t) -1 || gid != (gid_t) -1)
2887 if (chown(path, uid, gid) < 0)
2888 return -errno;
8c6db833
LP
2889
2890 return 0;
ef2f1067
LP
2891}
2892
f4b47811
LP
2893int fchmod_and_fchown(int fd, mode_t mode, uid_t uid, gid_t gid) {
2894 assert(fd >= 0);
2895
2896 /* Under the assumption that we are running privileged we
2897 * first change the access mode and only then hand out
2898 * ownership to avoid a window where access is too open. */
2899
2900 if (fchmod(fd, mode) < 0)
2901 return -errno;
2902
2903 if (fchown(fd, uid, gid) < 0)
2904 return -errno;
2905
2906 return 0;
2907}
2908
82c121a4
LP
2909cpu_set_t* cpu_set_malloc(unsigned *ncpus) {
2910 cpu_set_t *r;
2911 unsigned n = 1024;
2912
2913 /* Allocates the cpuset in the right size */
2914
2915 for (;;) {
2916 if (!(r = CPU_ALLOC(n)))
2917 return NULL;
2918
2919 if (sched_getaffinity(0, CPU_ALLOC_SIZE(n), r) >= 0) {
2920 CPU_ZERO_S(CPU_ALLOC_SIZE(n), r);
2921
2922 if (ncpus)
2923 *ncpus = n;
2924
2925 return r;
2926 }
2927
2928 CPU_FREE(r);
2929
2930 if (errno != EINVAL)
2931 return NULL;
2932
2933 n *= 2;
2934 }
2935}
2936
984a2be4 2937int status_vprintf(const char *status, bool ellipse, bool ephemeral, const char *format, va_list ap) {
9ab7a8d2 2938 static const char status_indent[] = " "; /* "[" STATUS "] " */
669bec5d
LP
2939 _cleanup_free_ char *s = NULL;
2940 _cleanup_close_ int fd = -1;
b92bea5d 2941 struct iovec iovec[6] = {};
81beb750 2942 int n = 0;
984a2be4 2943 static bool prev_ephemeral;
9e58ff9c
LP
2944
2945 assert(format);
2946
9ab7a8d2 2947 /* This is independent of logging, as status messages are
9e58ff9c
LP
2948 * optional and go exclusively to the console. */
2949
2950 if (vasprintf(&s, format, ap) < 0)
669bec5d 2951 return log_oom();
9e58ff9c 2952
67e5cc4f 2953 fd = open_terminal("/dev/console", O_WRONLY|O_NOCTTY|O_CLOEXEC);
81beb750 2954 if (fd < 0)
669bec5d 2955 return fd;
9e58ff9c 2956
67e5cc4f 2957 if (ellipse) {
9ab7a8d2
MS
2958 char *e;
2959 size_t emax, sl;
2960 int c;
2961
67e5cc4f
LP
2962 c = fd_columns(fd);
2963 if (c <= 0)
2964 c = 80;
81beb750 2965
669bec5d 2966 sl = status ? sizeof(status_indent)-1 : 0;
9ab7a8d2
MS
2967
2968 emax = c - sl - 1;
2969 if (emax < 3)
2970 emax = 3;
81beb750 2971
67e5cc4f
LP
2972 e = ellipsize(s, emax, 75);
2973 if (e) {
2974 free(s);
2975 s = e;
2976 }
81beb750
LP
2977 }
2978
984a2be4
MS
2979 if (prev_ephemeral)
2980 IOVEC_SET_STRING(iovec[n++], "\r" ANSI_ERASE_TO_END_OF_LINE);
2981 prev_ephemeral = ephemeral;
2982
9ab7a8d2
MS
2983 if (status) {
2984 if (!isempty(status)) {
2985 IOVEC_SET_STRING(iovec[n++], "[");
2986 IOVEC_SET_STRING(iovec[n++], status);
2987 IOVEC_SET_STRING(iovec[n++], "] ");
2988 } else
2989 IOVEC_SET_STRING(iovec[n++], status_indent);
81beb750
LP
2990 }
2991
9ab7a8d2 2992 IOVEC_SET_STRING(iovec[n++], s);
984a2be4
MS
2993 if (!ephemeral)
2994 IOVEC_SET_STRING(iovec[n++], "\n");
81beb750 2995
669bec5d
LP
2996 if (writev(fd, iovec, n) < 0)
2997 return -errno;
9e58ff9c 2998
669bec5d 2999 return 0;
9e58ff9c
LP
3000}
3001
984a2be4 3002int status_printf(const char *status, bool ellipse, bool ephemeral, const char *format, ...) {
c846ff47 3003 va_list ap;
669bec5d 3004 int r;
c846ff47
LP
3005
3006 assert(format);
3007
3008 va_start(ap, format);
984a2be4 3009 r = status_vprintf(status, ellipse, ephemeral, format, ap);
c846ff47 3010 va_end(ap);
669bec5d
LP
3011
3012 return r;
c846ff47
LP
3013}
3014
669bec5d 3015int status_welcome(void) {
10aa7034 3016 int r;
669bec5d
LP
3017 _cleanup_free_ char *pretty_name = NULL, *ansi_color = NULL;
3018
3019 r = parse_env_file("/etc/os-release", NEWLINE,
3020 "PRETTY_NAME", &pretty_name,
3021 "ANSI_COLOR", &ansi_color,
3022 NULL);
3023 if (r < 0 && r != -ENOENT)
3024 log_warning("Failed to read /etc/os-release: %s", strerror(-r));
3025
f620dff8 3026 return status_printf(NULL, false, false,
669bec5d
LP
3027 "\nWelcome to \x1B[%sm%s\x1B[0m!\n",
3028 isempty(ansi_color) ? "1" : ansi_color,
3029 isempty(pretty_name) ? "Linux" : pretty_name);
c846ff47
LP
3030}
3031
fab56fc5
LP
3032char *replace_env(const char *format, char **env) {
3033 enum {
3034 WORD,
c24eb49e 3035 CURLY,
fab56fc5
LP
3036 VARIABLE
3037 } state = WORD;
3038
3039 const char *e, *word = format;
3040 char *r = NULL, *k;
3041
3042 assert(format);
3043
3044 for (e = format; *e; e ++) {
3045
3046 switch (state) {
3047
3048 case WORD:
3049 if (*e == '$')
c24eb49e 3050 state = CURLY;
fab56fc5
LP
3051 break;
3052
c24eb49e
LP
3053 case CURLY:
3054 if (*e == '{') {
fab56fc5
LP
3055 if (!(k = strnappend(r, word, e-word-1)))
3056 goto fail;
3057
3058 free(r);
3059 r = k;
3060
3061 word = e-1;
3062 state = VARIABLE;
3063
3064 } else if (*e == '$') {
3065 if (!(k = strnappend(r, word, e-word)))
3066 goto fail;
3067
3068 free(r);
3069 r = k;
3070
3071 word = e+1;
3072 state = WORD;
3073 } else
3074 state = WORD;
3075 break;
3076
3077 case VARIABLE:
c24eb49e 3078 if (*e == '}') {
b95cf362 3079 const char *t;
fab56fc5 3080
4d1a6904 3081 t = strempty(strv_env_get_n(env, word+2, e-word-2));
fab56fc5 3082
4d1a6904
LP
3083 k = strappend(r, t);
3084 if (!k)
b95cf362 3085 goto fail;
fab56fc5 3086
b95cf362
LP
3087 free(r);
3088 r = k;
fab56fc5 3089
b95cf362 3090 word = e+1;
fab56fc5
LP
3091 state = WORD;
3092 }
3093 break;
3094 }
3095 }
3096
3097 if (!(k = strnappend(r, word, e-word)))
3098 goto fail;
3099
3100 free(r);
3101 return k;
3102
3103fail:
3104 free(r);
3105 return NULL;
3106}
3107
3108char **replace_env_argv(char **argv, char **env) {
3109 char **r, **i;
c24eb49e
LP
3110 unsigned k = 0, l = 0;
3111
3112 l = strv_length(argv);
fab56fc5 3113
c24eb49e 3114 if (!(r = new(char*, l+1)))
fab56fc5
LP
3115 return NULL;
3116
3117 STRV_FOREACH(i, argv) {
c24eb49e
LP
3118
3119 /* If $FOO appears as single word, replace it by the split up variable */
b95cf362
LP
3120 if ((*i)[0] == '$' && (*i)[1] != '{') {
3121 char *e;
3122 char **w, **m;
3123 unsigned q;
c24eb49e 3124
4d1a6904
LP
3125 e = strv_env_get(env, *i+1);
3126 if (e) {
c24eb49e
LP
3127
3128 if (!(m = strv_split_quoted(e))) {
3129 r[k] = NULL;
3130 strv_free(r);
3131 return NULL;
3132 }
b95cf362
LP
3133 } else
3134 m = NULL;
c24eb49e 3135
b95cf362
LP
3136 q = strv_length(m);
3137 l = l + q - 1;
c24eb49e 3138
b95cf362
LP
3139 if (!(w = realloc(r, sizeof(char*) * (l+1)))) {
3140 r[k] = NULL;
3141 strv_free(r);
3142 strv_free(m);
3143 return NULL;
3144 }
c24eb49e 3145
b95cf362
LP
3146 r = w;
3147 if (m) {
c24eb49e
LP
3148 memcpy(r + k, m, q * sizeof(char*));
3149 free(m);
c24eb49e 3150 }
b95cf362
LP
3151
3152 k += q;
3153 continue;
c24eb49e
LP
3154 }
3155
3156 /* If ${FOO} appears as part of a word, replace it by the variable as-is */
fab56fc5
LP
3157 if (!(r[k++] = replace_env(*i, env))) {
3158 strv_free(r);
3159 return NULL;
3160 }
3161 }
3162
3163 r[k] = NULL;
3164 return r;
3165}
3166
81beb750 3167int fd_columns(int fd) {
b92bea5d 3168 struct winsize ws = {};
81beb750
LP
3169
3170 if (ioctl(fd, TIOCGWINSZ, &ws) < 0)
3171 return -errno;
3172
3173 if (ws.ws_col <= 0)
3174 return -EIO;
3175
3176 return ws.ws_col;
3177}
3178
28917d7d 3179unsigned columns(void) {
fa776d8e 3180 const char *e;
7009eec2 3181 int c;
fa776d8e 3182
28917d7d
LP
3183 if (_likely_(cached_columns > 0))
3184 return cached_columns;
11f96fac 3185
28917d7d
LP
3186 c = 0;
3187 e = getenv("COLUMNS");
3188 if (e)
7009eec2 3189 safe_atoi(e, &c);
fa776d8e 3190
28917d7d
LP
3191 if (c <= 0)
3192 c = fd_columns(STDOUT_FILENO);
fa776d8e 3193
28917d7d
LP
3194 if (c <= 0)
3195 c = 80;
11f96fac 3196
28917d7d
LP
3197 cached_columns = c;
3198 return c;
11f96fac
ZJS
3199}
3200
8f2d43a0 3201int fd_lines(int fd) {
b92bea5d 3202 struct winsize ws = {};
8f2d43a0
LP
3203
3204 if (ioctl(fd, TIOCGWINSZ, &ws) < 0)
3205 return -errno;
3206
3207 if (ws.ws_row <= 0)
3208 return -EIO;
3209
3210 return ws.ws_row;
3211}
3212
3213unsigned lines(void) {
8f2d43a0 3214 const char *e;
ed757c0c 3215 unsigned l;
8f2d43a0 3216
ed757c0c
LP
3217 if (_likely_(cached_lines > 0))
3218 return cached_lines;
8f2d43a0 3219
ed757c0c 3220 l = 0;
8f2d43a0
LP
3221 e = getenv("LINES");
3222 if (e)
ed757c0c 3223 safe_atou(e, &l);
8f2d43a0 3224
ed757c0c
LP
3225 if (l <= 0)
3226 l = fd_lines(STDOUT_FILENO);
8f2d43a0 3227
ed757c0c
LP
3228 if (l <= 0)
3229 l = 24;
8f2d43a0 3230
ed757c0c
LP
3231 cached_lines = l;
3232 return cached_lines;
3233}
3234
3235/* intended to be used as a SIGWINCH sighandler */
3236void columns_lines_cache_reset(int signum) {
3237 cached_columns = 0;
3238 cached_lines = 0;
3239}
3240
3241bool on_tty(void) {
3242 static int cached_on_tty = -1;
3243
3244 if (_unlikely_(cached_on_tty < 0))
3245 cached_on_tty = isatty(STDOUT_FILENO) > 0;
3246
3247 return cached_on_tty;
8f2d43a0
LP
3248}
3249
b4f10a5e 3250int running_in_chroot(void) {
b92bea5d 3251 struct stat a = {}, b = {};
b4f10a5e
LP
3252
3253 /* Only works as root */
b4f10a5e
LP
3254 if (stat("/proc/1/root", &a) < 0)
3255 return -errno;
3256
3257 if (stat("/", &b) < 0)
3258 return -errno;
3259
3260 return
3261 a.st_dev != b.st_dev ||
3262 a.st_ino != b.st_ino;
3263}
3264
72f59706
LP
3265char *ellipsize_mem(const char *s, size_t old_length, size_t new_length, unsigned percent) {
3266 size_t x;
8fe914ec
LP
3267 char *r;
3268
3269 assert(s);
3270 assert(percent <= 100);
72f59706 3271 assert(new_length >= 3);
8fe914ec 3272
72f59706
LP
3273 if (old_length <= 3 || old_length <= new_length)
3274 return strndup(s, old_length);
8fe914ec 3275
72f59706
LP
3276 r = new0(char, new_length+1);
3277 if (!r)
8fe914ec
LP
3278 return r;
3279
72f59706 3280 x = (new_length * percent) / 100;
8fe914ec 3281
72f59706
LP
3282 if (x > new_length - 3)
3283 x = new_length - 3;
8fe914ec
LP
3284
3285 memcpy(r, s, x);
3286 r[x] = '.';
3287 r[x+1] = '.';
3288 r[x+2] = '.';
3289 memcpy(r + x + 3,
72f59706
LP
3290 s + old_length - (new_length - x - 3),
3291 new_length - x - 3);
8fe914ec
LP
3292
3293 return r;
3294}
3295
72f59706
LP
3296char *ellipsize(const char *s, size_t length, unsigned percent) {
3297 return ellipsize_mem(s, strlen(s), length, percent);
3298}
3299
f6144808
LP
3300int touch(const char *path) {
3301 int fd;
3302
3303 assert(path);
3304
73836c5c
LP
3305 /* This just opens the file for writing, ensuring it
3306 * exists. It doesn't call utimensat() the way /usr/bin/touch
3307 * does it. */
3308
3309 fd = open(path, O_WRONLY|O_CREAT|O_CLOEXEC|O_NOCTTY, 0644);
3310 if (fd < 0)
f6144808
LP
3311 return -errno;
3312
3313 close_nointr_nofail(fd);
3314 return 0;
3315}
afea26ad 3316
97c4a07d 3317char *unquote(const char *s, const char* quotes) {
11ce3427
LP
3318 size_t l;
3319 assert(s);
3320
73836c5c
LP
3321 /* This is rather stupid, simply removes the heading and
3322 * trailing quotes if there is one. Doesn't care about
57f30678
LP
3323 * escaping or anything. We should make this smarter one
3324 * day...*/
73836c5c 3325
31ed59c5
LP
3326 l = strlen(s);
3327 if (l < 2)
11ce3427
LP
3328 return strdup(s);
3329
97c4a07d 3330 if (strchr(quotes, s[0]) && s[l-1] == s[0])
11ce3427
LP
3331 return strndup(s+1, l-2);
3332
3333 return strdup(s);
3334}
3335
5f7c426e 3336char *normalize_env_assignment(const char *s) {
57f30678
LP
3337 _cleanup_free_ char *name = NULL, *value = NULL, *p = NULL;
3338 char *eq, *r;
5f7c426e 3339
57f30678
LP
3340 eq = strchr(s, '=');
3341 if (!eq) {
3342 char *t;
5f7c426e 3343
57f30678
LP
3344 r = strdup(s);
3345 if (!r)
5f7c426e
LP
3346 return NULL;
3347
57f30678
LP
3348 t = strstrip(r);
3349 if (t == r)
3350 return r;
3351
3352 memmove(r, t, strlen(t) + 1);
3353 return r;
5f7c426e
LP
3354 }
3355
57f30678
LP
3356 name = strndup(s, eq - s);
3357 if (!name)
5f7c426e
LP
3358 return NULL;
3359
57f30678
LP
3360 p = strdup(eq + 1);
3361 if (!p)
5f7c426e 3362 return NULL;
5f7c426e
LP
3363
3364 value = unquote(strstrip(p), QUOTES);
57f30678 3365 if (!value)
5f7c426e 3366 return NULL;
5f7c426e 3367
57f30678 3368 if (asprintf(&r, "%s=%s", strstrip(name), value) < 0)
5f7c426e
LP
3369 r = NULL;
3370
5f7c426e
LP
3371 return r;
3372}
3373
8e12a6ae 3374int wait_for_terminate(pid_t pid, siginfo_t *status) {
1968a360
LP
3375 siginfo_t dummy;
3376
2e78aa99 3377 assert(pid >= 1);
1968a360
LP
3378
3379 if (!status)
3380 status = &dummy;
2e78aa99
LP
3381
3382 for (;;) {
8e12a6ae
LP
3383 zero(*status);
3384
3385 if (waitid(P_PID, pid, status, WEXITED) < 0) {
2e78aa99
LP
3386
3387 if (errno == EINTR)
3388 continue;
3389
3390 return -errno;
3391 }
3392
3393 return 0;
3394 }
3395}
3396
97c4a07d
LP
3397int wait_for_terminate_and_warn(const char *name, pid_t pid) {
3398 int r;
3399 siginfo_t status;
3400
3401 assert(name);
3402 assert(pid > 1);
3403
d87be9b0
LP
3404 r = wait_for_terminate(pid, &status);
3405 if (r < 0) {
97c4a07d
LP
3406 log_warning("Failed to wait for %s: %s", name, strerror(-r));
3407 return r;
3408 }
3409
3410 if (status.si_code == CLD_EXITED) {
3411 if (status.si_status != 0) {
3412 log_warning("%s failed with error code %i.", name, status.si_status);
0a27cf3f 3413 return status.si_status;
97c4a07d
LP
3414 }
3415
3416 log_debug("%s succeeded.", name);
3417 return 0;
3418
3419 } else if (status.si_code == CLD_KILLED ||
3420 status.si_code == CLD_DUMPED) {
3421
3422 log_warning("%s terminated by signal %s.", name, signal_to_string(status.si_status));
3423 return -EPROTO;
3424 }
3425
3426 log_warning("%s failed due to unknown reason.", name);
3427 return -EPROTO;
97c4a07d
LP
3428}
3429
6a39419f 3430_noreturn_ void freeze(void) {
720ce21d
LP
3431
3432 /* Make sure nobody waits for us on a socket anymore */
3433 close_all_fds(NULL, 0);
3434
c29597a1
LP
3435 sync();
3436
3c14d26c
LP
3437 for (;;)
3438 pause();
3439}
3440
00dc5d76
LP
3441bool null_or_empty(struct stat *st) {
3442 assert(st);
3443
3444 if (S_ISREG(st->st_mode) && st->st_size <= 0)
3445 return true;
3446
c8f26f42 3447 if (S_ISCHR(st->st_mode) || S_ISBLK(st->st_mode))
00dc5d76
LP
3448 return true;
3449
3450 return false;
3451}
3452
83096483
LP
3453int null_or_empty_path(const char *fn) {
3454 struct stat st;
3455
3456 assert(fn);
3457
3458 if (stat(fn, &st) < 0)
3459 return -errno;
3460
3461 return null_or_empty(&st);
3462}
3463
a247755d 3464DIR *xopendirat(int fd, const char *name, int flags) {
c4731d11
LP
3465 int nfd;
3466 DIR *d;
3467
73836c5c
LP
3468 nfd = openat(fd, name, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|flags);
3469 if (nfd < 0)
c4731d11
LP
3470 return NULL;
3471
73836c5c
LP
3472 d = fdopendir(nfd);
3473 if (!d) {
c4731d11
LP
3474 close_nointr_nofail(nfd);
3475 return NULL;
3476 }
3477
3478 return d;
3b63d2d3
LP
3479}
3480
8a0867d6
LP
3481int signal_from_string_try_harder(const char *s) {
3482 int signo;
3483 assert(s);
3484
73836c5c
LP
3485 signo = signal_from_string(s);
3486 if (signo <= 0)
8a0867d6
LP
3487 if (startswith(s, "SIG"))
3488 return signal_from_string(s+3);
3489
3490 return signo;
3491}
3492
383182b5 3493static char *tag_to_udev_node(const char *tagvalue, const char *by) {
e23a0ce8
LP
3494 char *dn, *t, *u;
3495 int r;
3496
3497 /* FIXME: to follow udev's logic 100% we need to leave valid
3498 * UTF8 chars unescaped */
3499
383182b5
DR
3500 u = unquote(tagvalue, "\"\'");
3501 if (u == NULL)
3502 return NULL;
e23a0ce8 3503
383182b5
DR
3504 t = xescape(u, "/ ");
3505 free(u);
e23a0ce8 3506
383182b5
DR
3507 if (t == NULL)
3508 return NULL;
e23a0ce8 3509
383182b5
DR
3510 r = asprintf(&dn, "/dev/disk/by-%s/%s", by, t);
3511 free(t);
e23a0ce8 3512
383182b5
DR
3513 if (r < 0)
3514 return NULL;
e23a0ce8 3515
383182b5
DR
3516 return dn;
3517}
e23a0ce8 3518
383182b5 3519char *fstab_node_to_udev_node(const char *p) {
faa368e3
LP
3520 assert(p);
3521
383182b5
DR
3522 if (startswith(p, "LABEL="))
3523 return tag_to_udev_node(p+6, "label");
e23a0ce8 3524
383182b5
DR
3525 if (startswith(p, "UUID="))
3526 return tag_to_udev_node(p+5, "uuid");
e23a0ce8 3527
84cc2abf
DR
3528 if (startswith(p, "PARTUUID="))
3529 return tag_to_udev_node(p+9, "partuuid");
3530
3531 if (startswith(p, "PARTLABEL="))
3532 return tag_to_udev_node(p+10, "partlabel");
3533
e23a0ce8
LP
3534 return strdup(p);
3535}
3536
f212ac12
LP
3537bool tty_is_vc(const char *tty) {
3538 assert(tty);
3539
3540 if (startswith(tty, "/dev/"))
3541 tty += 5;
3542
98a28fef
LP
3543 return vtnr_from_tty(tty) >= 0;
3544}
3545
d1122ad5
LP
3546bool tty_is_console(const char *tty) {
3547 assert(tty);
3548
3549 if (startswith(tty, "/dev/"))
3550 tty += 5;
3551
3552 return streq(tty, "console");
3553}
3554
98a28fef
LP
3555int vtnr_from_tty(const char *tty) {
3556 int i, r;
3557
3558 assert(tty);
3559
3560 if (startswith(tty, "/dev/"))
3561 tty += 5;
3562
3563 if (!startswith(tty, "tty") )
3564 return -EINVAL;
3565
3566 if (tty[3] < '0' || tty[3] > '9')
3567 return -EINVAL;
3568
3569 r = safe_atoi(tty+3, &i);
3570 if (r < 0)
3571 return r;
3572
3573 if (i < 0 || i > 63)
3574 return -EINVAL;
3575
3576 return i;
f212ac12
LP
3577}
3578
21baf21a
MS
3579char *resolve_dev_console(char **active) {
3580 char *tty;
3581
3582 /* Resolve where /dev/console is pointing to, if /sys is actually ours
3583 * (i.e. not read-only-mounted which is a sign for container setups) */
3584
3585 if (path_is_read_only_fs("/sys") > 0)
3586 return NULL;
3587
3588 if (read_one_line_file("/sys/class/tty/console/active", active) < 0)
3589 return NULL;
3590
3591 /* If multiple log outputs are configured the last one is what
3592 * /dev/console points to */
3593 tty = strrchr(*active, ' ');
3594 if (tty)
3595 tty++;
3596 else
3597 tty = *active;
3598
3599 return tty;
3600}
3601
3043935f 3602bool tty_is_vc_resolve(const char *tty) {
3030ccd7 3603 char *active = NULL;
3043935f 3604 bool b;
3030ccd7 3605
e3aa71c3
LP
3606 assert(tty);
3607
3608 if (startswith(tty, "/dev/"))
3609 tty += 5;
3610
21baf21a
MS
3611 if (streq(tty, "console")) {
3612 tty = resolve_dev_console(&active);
3613 if (!tty)
3614 return false;
3615 }
3030ccd7 3616
3043935f 3617 b = tty_is_vc(tty);
3030ccd7 3618 free(active);
e3aa71c3 3619
3043935f
LP
3620 return b;
3621}
3622
3623const char *default_term_for_tty(const char *tty) {
3624 assert(tty);
3625
acda6a05 3626 return tty_is_vc_resolve(tty) ? "TERM=linux" : "TERM=vt102";
e3aa71c3
LP
3627}
3628
87d2c1ff 3629bool dirent_is_file(const struct dirent *de) {
fb19a739
LP
3630 assert(de);
3631
3632 if (ignore_file(de->d_name))
3633 return false;
3634
3635 if (de->d_type != DT_REG &&
3636 de->d_type != DT_LNK &&
3637 de->d_type != DT_UNKNOWN)
3638 return false;
3639
3640 return true;
3641}
3642
87d2c1ff
LP
3643bool dirent_is_file_with_suffix(const struct dirent *de, const char *suffix) {
3644 assert(de);
3645
a228a22f
LP
3646 if (de->d_type != DT_REG &&
3647 de->d_type != DT_LNK &&
3648 de->d_type != DT_UNKNOWN)
3649 return false;
3650
3651 if (ignore_file_allow_backup(de->d_name))
87d2c1ff
LP
3652 return false;
3653
3654 return endswith(de->d_name, suffix);
3655}
3656
83cc030f
LP
3657void execute_directory(const char *directory, DIR *d, char *argv[]) {
3658 DIR *_d = NULL;
3659 struct dirent *de;
3660 Hashmap *pids = NULL;
3661
3662 assert(directory);
3663
650001c6
JJ
3664 /* Executes all binaries in a directory in parallel and
3665 * waits for them to finish. */
83cc030f
LP
3666
3667 if (!d) {
3668 if (!(_d = opendir(directory))) {
3669
3670 if (errno == ENOENT)
3671 return;
3672
3673 log_error("Failed to enumerate directory %s: %m", directory);
3674 return;
3675 }
3676
3677 d = _d;
3678 }
3679
3680 if (!(pids = hashmap_new(trivial_hash_func, trivial_compare_func))) {
3681 log_error("Failed to allocate set.");
3682 goto finish;
3683 }
3684
3685 while ((de = readdir(d))) {
3686 char *path;
3687 pid_t pid;
3688 int k;
3689
fb19a739 3690 if (!dirent_is_file(de))
83cc030f
LP
3691 continue;
3692
3693 if (asprintf(&path, "%s/%s", directory, de->d_name) < 0) {
0d0f0c50 3694 log_oom();
83cc030f
LP
3695 continue;
3696 }
3697
3698 if ((pid = fork()) < 0) {
3699 log_error("Failed to fork: %m");
3700 free(path);
3701 continue;
3702 }
3703
3704 if (pid == 0) {
3705 char *_argv[2];
3706 /* Child */
3707
3708 if (!argv) {
3709 _argv[0] = path;
3710 _argv[1] = NULL;
3711 argv = _argv;
3712 } else
6edd7d0a 3713 argv[0] = path;
83cc030f
LP
3714
3715 execv(path, argv);
3716
3717 log_error("Failed to execute %s: %m", path);
3718 _exit(EXIT_FAILURE);
3719 }
3720
3721 log_debug("Spawned %s as %lu", path, (unsigned long) pid);
3722
3723 if ((k = hashmap_put(pids, UINT_TO_PTR(pid), path)) < 0) {
3724 log_error("Failed to add PID to set: %s", strerror(-k));
3725 free(path);
3726 }
3727 }
3728
3729 while (!hashmap_isempty(pids)) {
ec3f9b53 3730 pid_t pid = PTR_TO_UINT(hashmap_first_key(pids));
b92bea5d 3731 siginfo_t si = {};
83cc030f
LP
3732 char *path;
3733
ec3f9b53 3734 if (waitid(P_PID, pid, &si, WEXITED) < 0) {
83cc030f
LP
3735
3736 if (errno == EINTR)
3737 continue;
3738
3739 log_error("waitid() failed: %m");
3740 goto finish;
3741 }
3742
3743 if ((path = hashmap_remove(pids, UINT_TO_PTR(si.si_pid)))) {
96342de6 3744 if (!is_clean_exit(si.si_code, si.si_status, NULL)) {
83cc030f
LP
3745 if (si.si_code == CLD_EXITED)
3746 log_error("%s exited with exit status %i.", path, si.si_status);
3747 else
3748 log_error("%s terminated by signal %s.", path, signal_to_string(si.si_status));
3749 } else
3750 log_debug("%s exited successfully.", path);
3751
3752 free(path);
3753 }
3754 }
3755
3756finish:
3757 if (_d)
3758 closedir(_d);
3759
3760 if (pids)
3761 hashmap_free_free(pids);
3762}
3763
430c18ed
LP
3764int kill_and_sigcont(pid_t pid, int sig) {
3765 int r;
3766
3767 r = kill(pid, sig) < 0 ? -errno : 0;
3768
3769 if (r >= 0)
3770 kill(pid, SIGCONT);
3771
3772 return r;
3773}
3774
05feefe0
LP
3775bool nulstr_contains(const char*nulstr, const char *needle) {
3776 const char *i;
3777
3778 if (!nulstr)
3779 return false;
3780
3781 NULSTR_FOREACH(i, nulstr)
3782 if (streq(i, needle))
3783 return true;
3784
3785 return false;
3786}
3787
6faa1114 3788bool plymouth_running(void) {
9408a2d2 3789 return access("/run/plymouth/pid", F_OK) >= 0;
6faa1114
LP
3790}
3791
9beb3f4d
LP
3792char* strshorten(char *s, size_t l) {
3793 assert(s);
3794
3795 if (l < strlen(s))
3796 s[l] = 0;
3797
3798 return s;
3799}
3800
3801static bool hostname_valid_char(char c) {
3802 return
3803 (c >= 'a' && c <= 'z') ||
3804 (c >= 'A' && c <= 'Z') ||
3805 (c >= '0' && c <= '9') ||
3806 c == '-' ||
3807 c == '_' ||
3808 c == '.';
3809}
3810
3811bool hostname_is_valid(const char *s) {
3812 const char *p;
aa3c5cf8 3813 bool dot;
9beb3f4d
LP
3814
3815 if (isempty(s))
3816 return false;
3817
aa3c5cf8
LP
3818 for (p = s, dot = true; *p; p++) {
3819 if (*p == '.') {
3820 if (dot)
3821 return false;
3822
3823 dot = true;
3824 } else {
3825 if (!hostname_valid_char(*p))
3826 return false;
3827
3828 dot = false;
3829 }
3830 }
3831
3832 if (dot)
3833 return false;
9beb3f4d
LP
3834
3835 if (p-s > HOST_NAME_MAX)
3836 return false;
3837
3838 return true;
3839}
3840
e724b063 3841char* hostname_cleanup(char *s, bool lowercase) {
9beb3f4d 3842 char *p, *d;
cec4ead9
LP
3843 bool dot;
3844
3845 for (p = s, d = s, dot = true; *p; p++) {
3846 if (*p == '.') {
e724b063 3847 if (dot)
cec4ead9 3848 continue;
9beb3f4d 3849
e724b063 3850 *(d++) = '.';
cec4ead9 3851 dot = true;
e724b063
LP
3852 } else if (hostname_valid_char(*p)) {
3853 *(d++) = lowercase ? tolower(*p) : *p;
cec4ead9 3854 dot = false;
e724b063 3855 }
cec4ead9 3856
cec4ead9 3857 }
9beb3f4d 3858
e724b063
LP
3859 if (dot && d > s)
3860 d[-1] = 0;
3861 else
3862 *d = 0;
3863
9beb3f4d 3864 strshorten(s, HOST_NAME_MAX);
cec4ead9 3865
9beb3f4d
LP
3866 return s;
3867}
3868
1325aa42 3869int pipe_eof(int fd) {
1325aa42 3870 int r;
b92bea5d
ZJS
3871 struct pollfd pollfd = {
3872 .fd = fd,
3873 .events = POLLIN|POLLHUP,
3874 };
1325aa42
LP
3875
3876 r = poll(&pollfd, 1, 0);
3877 if (r < 0)
3878 return -errno;
3879
3880 if (r == 0)
3881 return 0;
3882
3883 return pollfd.revents & POLLHUP;
3884}
3885
8f2d43a0 3886int fd_wait_for_event(int fd, int event, usec_t t) {
df50185b 3887 int r;
b92bea5d
ZJS
3888 struct pollfd pollfd = {
3889 .fd = fd,
3890 .events = event,
3891 };
df50185b 3892
8f2d43a0 3893 r = poll(&pollfd, 1, t == (usec_t) -1 ? -1 : (int) (t / USEC_PER_MSEC));
df50185b
LP
3894 if (r < 0)
3895 return -errno;
3896
3897 if (r == 0)
3898 return 0;
3899
3900 return pollfd.revents;
3901}
3902
5a3ab509
LP
3903int fopen_temporary(const char *path, FILE **_f, char **_temp_path) {
3904 FILE *f;
3905 char *t;
3906 const char *fn;
3907 size_t k;
3908 int fd;
3909
3910 assert(path);
3911 assert(_f);
3912 assert(_temp_path);
3913
3914 t = new(char, strlen(path) + 1 + 6 + 1);
3915 if (!t)
3916 return -ENOMEM;
3917
9eb977db 3918 fn = path_get_file_name(path);
5a3ab509
LP
3919 k = fn-path;
3920 memcpy(t, path, k);
3921 t[k] = '.';
3922 stpcpy(stpcpy(t+k+1, fn), "XXXXXX");
3923
3924 fd = mkostemp(t, O_WRONLY|O_CLOEXEC);
3925 if (fd < 0) {
3926 free(t);
3927 return -errno;
3928 }
3929
3930 f = fdopen(fd, "we");
3931 if (!f) {
3932 unlink(t);
3933 free(t);
3934 return -errno;
3935 }
3936
3937 *_f = f;
3938 *_temp_path = t;
3939
3940 return 0;
3941}
3942
6ea832a2 3943int terminal_vhangup_fd(int fd) {
5a3ab509
LP
3944 assert(fd >= 0);
3945
6ea832a2
LP
3946 if (ioctl(fd, TIOCVHANGUP) < 0)
3947 return -errno;
3948
3949 return 0;
3950}
3951
3952int terminal_vhangup(const char *name) {
3953 int fd, r;
3954
3955 fd = open_terminal(name, O_RDWR|O_NOCTTY|O_CLOEXEC);
3956 if (fd < 0)
3957 return fd;
3958
3959 r = terminal_vhangup_fd(fd);
3960 close_nointr_nofail(fd);
3961
3962 return r;
3963}
3964
3965int vt_disallocate(const char *name) {
3966 int fd, r;
3967 unsigned u;
6ea832a2
LP
3968
3969 /* Deallocate the VT if possible. If not possible
3970 * (i.e. because it is the active one), at least clear it
3971 * entirely (including the scrollback buffer) */
3972
b83bc4e9
LP
3973 if (!startswith(name, "/dev/"))
3974 return -EINVAL;
3975
3976 if (!tty_is_vc(name)) {
3977 /* So this is not a VT. I guess we cannot deallocate
3978 * it then. But let's at least clear the screen */
3979
3980 fd = open_terminal(name, O_RDWR|O_NOCTTY|O_CLOEXEC);
3981 if (fd < 0)
3982 return fd;
3983
8585357a
LP
3984 loop_write(fd,
3985 "\033[r" /* clear scrolling region */
3986 "\033[H" /* move home */
3987 "\033[2J", /* clear screen */
3988 10, false);
b83bc4e9
LP
3989 close_nointr_nofail(fd);
3990
3991 return 0;
3992 }
6ea832a2
LP
3993
3994 if (!startswith(name, "/dev/tty"))
3995 return -EINVAL;
3996
3997 r = safe_atou(name+8, &u);
3998 if (r < 0)
3999 return r;
4000
4001 if (u <= 0)
b83bc4e9 4002 return -EINVAL;
6ea832a2 4003
b83bc4e9 4004 /* Try to deallocate */
6ea832a2
LP
4005 fd = open_terminal("/dev/tty0", O_RDWR|O_NOCTTY|O_CLOEXEC);
4006 if (fd < 0)
4007 return fd;
4008
4009 r = ioctl(fd, VT_DISALLOCATE, u);
b83bc4e9 4010 close_nointr_nofail(fd);
6ea832a2 4011
b83bc4e9
LP
4012 if (r >= 0)
4013 return 0;
6ea832a2 4014
b83bc4e9 4015 if (errno != EBUSY)
6ea832a2 4016 return -errno;
6ea832a2 4017
b83bc4e9
LP
4018 /* Couldn't deallocate, so let's clear it fully with
4019 * scrollback */
4020 fd = open_terminal(name, O_RDWR|O_NOCTTY|O_CLOEXEC);
6ea832a2 4021 if (fd < 0)
b83bc4e9 4022 return fd;
6ea832a2 4023
8585357a
LP
4024 loop_write(fd,
4025 "\033[r" /* clear scrolling region */
4026 "\033[H" /* move home */
4027 "\033[3J", /* clear screen including scrollback, requires Linux 2.6.40 */
4028 10, false);
b83bc4e9 4029 close_nointr_nofail(fd);
6ea832a2 4030
b83bc4e9 4031 return 0;
6ea832a2
LP
4032}
4033
34ca941c
LP
4034int copy_file(const char *from, const char *to) {
4035 int r, fdf, fdt;
4036
4037 assert(from);
4038 assert(to);
4039
4040 fdf = open(from, O_RDONLY|O_CLOEXEC|O_NOCTTY);
4041 if (fdf < 0)
4042 return -errno;
4043
4044 fdt = open(to, O_WRONLY|O_CREAT|O_EXCL|O_CLOEXEC|O_NOCTTY, 0644);
4045 if (fdt < 0) {
4046 close_nointr_nofail(fdf);
4047 return -errno;
4048 }
4049
4050 for (;;) {
4051 char buf[PIPE_BUF];
4052 ssize_t n, k;
4053
4054 n = read(fdf, buf, sizeof(buf));
4055 if (n < 0) {
4056 r = -errno;
4057
4058 close_nointr_nofail(fdf);
4059 close_nointr(fdt);
4060 unlink(to);
4061
4062 return r;
4063 }
4064
4065 if (n == 0)
4066 break;
4067
4068 errno = 0;
4069 k = loop_write(fdt, buf, n, false);
4070 if (n != k) {
4071 r = k < 0 ? k : (errno ? -errno : -EIO);
4072
4073 close_nointr_nofail(fdf);
4074 close_nointr(fdt);
4075
4076 unlink(to);
4077 return r;
4078 }
4079 }
4080
4081 close_nointr_nofail(fdf);
4082 r = close_nointr(fdt);
4083
4084 if (r < 0) {
4085 unlink(to);
4086 return r;
4087 }
4088
4089 return 0;
4090}
4091
424a19f8
LP
4092int symlink_atomic(const char *from, const char *to) {
4093 char *x;
4094 _cleanup_free_ char *t;
34ca941c
LP
4095 const char *fn;
4096 size_t k;
4097 unsigned long long ull;
4098 unsigned i;
4099 int r;
4100
4101 assert(from);
4102 assert(to);
4103
4104 t = new(char, strlen(to) + 1 + 16 + 1);
4105 if (!t)
4106 return -ENOMEM;
4107
9eb977db 4108 fn = path_get_file_name(to);
34ca941c
LP
4109 k = fn-to;
4110 memcpy(t, to, k);
4111 t[k] = '.';
4112 x = stpcpy(t+k+1, fn);
4113
4114 ull = random_ull();
4115 for (i = 0; i < 16; i++) {
4116 *(x++) = hexchar(ull & 0xF);
4117 ull >>= 4;
4118 }
4119
4120 *x = 0;
4121
424a19f8
LP
4122 if (symlink(from, t) < 0)
4123 return -errno;
34ca941c
LP
4124
4125 if (rename(t, to) < 0) {
4126 r = -errno;
4127 unlink(t);
34ca941c
LP
4128 return r;
4129 }
4130
424a19f8 4131 return 0;
34ca941c
LP
4132}
4133
4d6d6518
LP
4134bool display_is_local(const char *display) {
4135 assert(display);
4136
4137 return
4138 display[0] == ':' &&
4139 display[1] >= '0' &&
4140 display[1] <= '9';
4141}
4142
4143int socket_from_display(const char *display, char **path) {
4144 size_t k;
4145 char *f, *c;
4146
4147 assert(display);
4148 assert(path);
4149
4150 if (!display_is_local(display))
4151 return -EINVAL;
4152
4153 k = strspn(display+1, "0123456789");
4154
4155 f = new(char, sizeof("/tmp/.X11-unix/X") + k);
4156 if (!f)
4157 return -ENOMEM;
4158
4159 c = stpcpy(f, "/tmp/.X11-unix/X");
4160 memcpy(c, display+1, k);
4161 c[k] = 0;
4162
4163 *path = f;
4164
4165 return 0;
4166}
4167
d05c5031
LP
4168int get_user_creds(
4169 const char **username,
4170 uid_t *uid, gid_t *gid,
4171 const char **home,
4172 const char **shell) {
4173
1cccf435 4174 struct passwd *p;
ddd88763 4175 uid_t u;
1cccf435
MV
4176
4177 assert(username);
4178 assert(*username);
1cccf435
MV
4179
4180 /* We enforce some special rules for uid=0: in order to avoid
4181 * NSS lookups for root we hardcode its data. */
4182
4183 if (streq(*username, "root") || streq(*username, "0")) {
4184 *username = "root";
4b67834e
LP
4185
4186 if (uid)
4187 *uid = 0;
4188
4189 if (gid)
4190 *gid = 0;
4191
4192 if (home)
4193 *home = "/root";
d05c5031
LP
4194
4195 if (shell)
4196 *shell = "/bin/sh";
4197
1cccf435
MV
4198 return 0;
4199 }
4200
ddd88763 4201 if (parse_uid(*username, &u) >= 0) {
1cccf435 4202 errno = 0;
ddd88763 4203 p = getpwuid(u);
1cccf435
MV
4204
4205 /* If there are multiple users with the same id, make
4206 * sure to leave $USER to the configured value instead
4207 * of the first occurrence in the database. However if
4208 * the uid was configured by a numeric uid, then let's
4209 * pick the real username from /etc/passwd. */
4210 if (p)
4211 *username = p->pw_name;
4212 } else {
4213 errno = 0;
4214 p = getpwnam(*username);
4215 }
4216
4217 if (!p)
8333c77e 4218 return errno > 0 ? -errno : -ESRCH;
1cccf435 4219
4b67834e
LP
4220 if (uid)
4221 *uid = p->pw_uid;
4222
4223 if (gid)
4224 *gid = p->pw_gid;
4225
4226 if (home)
4227 *home = p->pw_dir;
4228
d05c5031
LP
4229 if (shell)
4230 *shell = p->pw_shell;
4231
4b67834e
LP
4232 return 0;
4233}
4234
59164be4
LP
4235char* uid_to_name(uid_t uid) {
4236 struct passwd *p;
4237 char *r;
4238
4239 if (uid == 0)
4240 return strdup("root");
4241
4242 p = getpwuid(uid);
4243 if (p)
4244 return strdup(p->pw_name);
4245
4246 if (asprintf(&r, "%lu", (unsigned long) uid) < 0)
4247 return NULL;
4248
4249 return r;
4250}
4251
4468addc
LP
4252char* gid_to_name(gid_t gid) {
4253 struct group *p;
4254 char *r;
4255
4256 if (gid == 0)
4257 return strdup("root");
4258
4259 p = getgrgid(gid);
4260 if (p)
4261 return strdup(p->gr_name);
4262
4263 if (asprintf(&r, "%lu", (unsigned long) gid) < 0)
4264 return NULL;
4265
4266 return r;
4267}
4268
4b67834e
LP
4269int get_group_creds(const char **groupname, gid_t *gid) {
4270 struct group *g;
4271 gid_t id;
4272
4273 assert(groupname);
4274
4275 /* We enforce some special rules for gid=0: in order to avoid
4276 * NSS lookups for root we hardcode its data. */
4277
4278 if (streq(*groupname, "root") || streq(*groupname, "0")) {
4279 *groupname = "root";
4280
4281 if (gid)
4282 *gid = 0;
4283
4284 return 0;
4285 }
4286
4287 if (parse_gid(*groupname, &id) >= 0) {
4288 errno = 0;
4289 g = getgrgid(id);
4290
4291 if (g)
4292 *groupname = g->gr_name;
4293 } else {
4294 errno = 0;
4295 g = getgrnam(*groupname);
4296 }
4297
4298 if (!g)
8333c77e 4299 return errno > 0 ? -errno : -ESRCH;
4b67834e
LP
4300
4301 if (gid)
4302 *gid = g->gr_gid;
4303
1cccf435
MV
4304 return 0;
4305}
4306
4468addc
LP
4307int in_gid(gid_t gid) {
4308 gid_t *gids;
43673799
LP
4309 int ngroups_max, r, i;
4310
43673799
LP
4311 if (getgid() == gid)
4312 return 1;
4313
4314 if (getegid() == gid)
4315 return 1;
4316
4317 ngroups_max = sysconf(_SC_NGROUPS_MAX);
4318 assert(ngroups_max > 0);
4319
4320 gids = alloca(sizeof(gid_t) * ngroups_max);
4321
4322 r = getgroups(ngroups_max, gids);
4323 if (r < 0)
4324 return -errno;
4325
4326 for (i = 0; i < r; i++)
4327 if (gids[i] == gid)
4328 return 1;
4329
4330 return 0;
4331}
4332
4468addc
LP
4333int in_group(const char *name) {
4334 int r;
4335 gid_t gid;
4336
4337 r = get_group_creds(&name, &gid);
4338 if (r < 0)
4339 return r;
4340
4341 return in_gid(gid);
4342}
4343
8092a428 4344int glob_exists(const char *path) {
7fd1b19b 4345 _cleanup_globfree_ glob_t g = {};
8092a428
LP
4346 int r, k;
4347
4348 assert(path);
4349
8092a428
LP
4350 errno = 0;
4351 k = glob(path, GLOB_NOSORT|GLOB_BRACE, NULL, &g);
4352
4353 if (k == GLOB_NOMATCH)
4354 r = 0;
4355 else if (k == GLOB_NOSPACE)
4356 r = -ENOMEM;
4357 else if (k == 0)
4358 r = !strv_isempty(g.gl_pathv);
4359 else
4360 r = errno ? -errno : -EIO;
4361
8092a428
LP
4362 return r;
4363}
4364
83096483
LP
4365int dirent_ensure_type(DIR *d, struct dirent *de) {
4366 struct stat st;
4367
4368 assert(d);
4369 assert(de);
4370
4371 if (de->d_type != DT_UNKNOWN)
4372 return 0;
4373
4374 if (fstatat(dirfd(d), de->d_name, &st, AT_SYMLINK_NOFOLLOW) < 0)
4375 return -errno;
4376
4377 de->d_type =
4378 S_ISREG(st.st_mode) ? DT_REG :
4379 S_ISDIR(st.st_mode) ? DT_DIR :
4380 S_ISLNK(st.st_mode) ? DT_LNK :
4381 S_ISFIFO(st.st_mode) ? DT_FIFO :
4382 S_ISSOCK(st.st_mode) ? DT_SOCK :
4383 S_ISCHR(st.st_mode) ? DT_CHR :
4384 S_ISBLK(st.st_mode) ? DT_BLK :
4385 DT_UNKNOWN;
4386
4387 return 0;
4388}
4389
4390int in_search_path(const char *path, char **search) {
4391 char **i, *parent;
4392 int r;
4393
9eb977db 4394 r = path_get_parent(path, &parent);
83096483
LP
4395 if (r < 0)
4396 return r;
4397
4398 r = 0;
4399
4400 STRV_FOREACH(i, search) {
4401 if (path_equal(parent, *i)) {
4402 r = 1;
4403 break;
4404 }
4405 }
4406
4407 free(parent);
4408
4409 return r;
4410}
4411
034a2a52
LP
4412int get_files_in_directory(const char *path, char ***list) {
4413 DIR *d;
4414 int r = 0;
4415 unsigned n = 0;
4416 char **l = NULL;
4417
4418 assert(path);
d60ef526
LP
4419
4420 /* Returns all files in a directory in *list, and the number
4421 * of files as return value. If list is NULL returns only the
4422 * number */
034a2a52
LP
4423
4424 d = opendir(path);
8ea913b2
LP
4425 if (!d)
4426 return -errno;
4427
034a2a52 4428 for (;;) {
7d5e9c0f
LP
4429 struct dirent *de;
4430 union dirent_storage buf;
034a2a52
LP
4431 int k;
4432
7d5e9c0f 4433 k = readdir_r(d, &buf.de, &de);
034a2a52
LP
4434 if (k != 0) {
4435 r = -k;
4436 goto finish;
4437 }
4438
4439 if (!de)
4440 break;
4441
4442 dirent_ensure_type(d, de);
4443
4444 if (!dirent_is_file(de))
4445 continue;
4446
d60ef526
LP
4447 if (list) {
4448 if ((unsigned) r >= n) {
4449 char **t;
034a2a52 4450
d60ef526
LP
4451 n = MAX(16, 2*r);
4452 t = realloc(l, sizeof(char*) * n);
4453 if (!t) {
4454 r = -ENOMEM;
4455 goto finish;
4456 }
034a2a52 4457
d60ef526
LP
4458 l = t;
4459 }
034a2a52 4460
d60ef526 4461 assert((unsigned) r < n);
034a2a52 4462
d60ef526
LP
4463 l[r] = strdup(de->d_name);
4464 if (!l[r]) {
4465 r = -ENOMEM;
4466 goto finish;
4467 }
034a2a52 4468
d60ef526
LP
4469 l[++r] = NULL;
4470 } else
4471 r++;
034a2a52
LP
4472 }
4473
4474finish:
4475 if (d)
4476 closedir(d);
4477
d60ef526
LP
4478 if (r >= 0) {
4479 if (list)
4480 *list = l;
4481 } else
034a2a52
LP
4482 strv_free(l);
4483
4484 return r;
4485}
4486
b7def684 4487char *strjoin(const char *x, ...) {
911a4828
LP
4488 va_list ap;
4489 size_t l;
4490 char *r, *p;
4491
4492 va_start(ap, x);
4493
4494 if (x) {
4495 l = strlen(x);
4496
4497 for (;;) {
4498 const char *t;
040f18ea 4499 size_t n;
911a4828
LP
4500
4501 t = va_arg(ap, const char *);
4502 if (!t)
4503 break;
4504
040f18ea 4505 n = strlen(t);
e98055de
LN
4506 if (n > ((size_t) -1) - l) {
4507 va_end(ap);
040f18ea 4508 return NULL;
e98055de 4509 }
040f18ea
LP
4510
4511 l += n;
911a4828
LP
4512 }
4513 } else
4514 l = 0;
4515
4516 va_end(ap);
4517
4518 r = new(char, l+1);
4519 if (!r)
4520 return NULL;
4521
4522 if (x) {
4523 p = stpcpy(r, x);
4524
4525 va_start(ap, x);
4526
4527 for (;;) {
4528 const char *t;
4529
4530 t = va_arg(ap, const char *);
4531 if (!t)
4532 break;
4533
4534 p = stpcpy(p, t);
4535 }
8ea913b2
LP
4536
4537 va_end(ap);
911a4828
LP
4538 } else
4539 r[0] = 0;
4540
4541 return r;
4542}
4543
b636465b
LP
4544bool is_main_thread(void) {
4545 static __thread int cached = 0;
4546
4547 if (_unlikely_(cached == 0))
4548 cached = getpid() == gettid() ? 1 : -1;
4549
4550 return cached > 0;
4551}
4552
94959f0f
LP
4553int block_get_whole_disk(dev_t d, dev_t *ret) {
4554 char *p, *s;
4555 int r;
4556 unsigned n, m;
4557
4558 assert(ret);
4559
4560 /* If it has a queue this is good enough for us */
4561 if (asprintf(&p, "/sys/dev/block/%u:%u/queue", major(d), minor(d)) < 0)
4562 return -ENOMEM;
4563
4564 r = access(p, F_OK);
4565 free(p);
4566
4567 if (r >= 0) {
4568 *ret = d;
4569 return 0;
4570 }
4571
4572 /* If it is a partition find the originating device */
4573 if (asprintf(&p, "/sys/dev/block/%u:%u/partition", major(d), minor(d)) < 0)
4574 return -ENOMEM;
4575
4576 r = access(p, F_OK);
4577 free(p);
4578
4579 if (r < 0)
4580 return -ENOENT;
4581
4582 /* Get parent dev_t */
4583 if (asprintf(&p, "/sys/dev/block/%u:%u/../dev", major(d), minor(d)) < 0)
4584 return -ENOMEM;
4585
4586 r = read_one_line_file(p, &s);
4587 free(p);
4588
4589 if (r < 0)
4590 return r;
4591
4592 r = sscanf(s, "%u:%u", &m, &n);
4593 free(s);
4594
4595 if (r != 2)
4596 return -EINVAL;
4597
4598 /* Only return this if it is really good enough for us. */
4599 if (asprintf(&p, "/sys/dev/block/%u:%u/queue", m, n) < 0)
4600 return -ENOMEM;
4601
4602 r = access(p, F_OK);
4603 free(p);
4604
4605 if (r >= 0) {
4606 *ret = makedev(m, n);
4607 return 0;
4608 }
4609
4610 return -ENOENT;
4611}
4612
8d53b453 4613int file_is_priv_sticky(const char *p) {
ad293f5a
LP
4614 struct stat st;
4615
4616 assert(p);
4617
4618 if (lstat(p, &st) < 0)
4619 return -errno;
4620
4621 return
8d53b453 4622 (st.st_uid == 0 || st.st_uid == getuid()) &&
ad293f5a
LP
4623 (st.st_mode & S_ISVTX);
4624}
94959f0f 4625
f41607a6
LP
4626static const char *const ioprio_class_table[] = {
4627 [IOPRIO_CLASS_NONE] = "none",
4628 [IOPRIO_CLASS_RT] = "realtime",
4629 [IOPRIO_CLASS_BE] = "best-effort",
4630 [IOPRIO_CLASS_IDLE] = "idle"
4631};
4632
f8b69d1d 4633DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(ioprio_class, int, INT_MAX);
f41607a6
LP
4634
4635static const char *const sigchld_code_table[] = {
4636 [CLD_EXITED] = "exited",
4637 [CLD_KILLED] = "killed",
4638 [CLD_DUMPED] = "dumped",
4639 [CLD_TRAPPED] = "trapped",
4640 [CLD_STOPPED] = "stopped",
4641 [CLD_CONTINUED] = "continued",
4642};
4643
4644DEFINE_STRING_TABLE_LOOKUP(sigchld_code, int);
4645
4646static const char *const log_facility_unshifted_table[LOG_NFACILITIES] = {
4647 [LOG_FAC(LOG_KERN)] = "kern",
4648 [LOG_FAC(LOG_USER)] = "user",
4649 [LOG_FAC(LOG_MAIL)] = "mail",
4650 [LOG_FAC(LOG_DAEMON)] = "daemon",
4651 [LOG_FAC(LOG_AUTH)] = "auth",
4652 [LOG_FAC(LOG_SYSLOG)] = "syslog",
4653 [LOG_FAC(LOG_LPR)] = "lpr",
4654 [LOG_FAC(LOG_NEWS)] = "news",
4655 [LOG_FAC(LOG_UUCP)] = "uucp",
4656 [LOG_FAC(LOG_CRON)] = "cron",
4657 [LOG_FAC(LOG_AUTHPRIV)] = "authpriv",
4658 [LOG_FAC(LOG_FTP)] = "ftp",
4659 [LOG_FAC(LOG_LOCAL0)] = "local0",
4660 [LOG_FAC(LOG_LOCAL1)] = "local1",
4661 [LOG_FAC(LOG_LOCAL2)] = "local2",
4662 [LOG_FAC(LOG_LOCAL3)] = "local3",
4663 [LOG_FAC(LOG_LOCAL4)] = "local4",
4664 [LOG_FAC(LOG_LOCAL5)] = "local5",
4665 [LOG_FAC(LOG_LOCAL6)] = "local6",
4666 [LOG_FAC(LOG_LOCAL7)] = "local7"
4667};
4668
f8b69d1d 4669DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(log_facility_unshifted, int, LOG_FAC(~0));
f41607a6
LP
4670
4671static const char *const log_level_table[] = {
4672 [LOG_EMERG] = "emerg",
4673 [LOG_ALERT] = "alert",
4674 [LOG_CRIT] = "crit",
4675 [LOG_ERR] = "err",
4676 [LOG_WARNING] = "warning",
4677 [LOG_NOTICE] = "notice",
4678 [LOG_INFO] = "info",
4679 [LOG_DEBUG] = "debug"
4680};
4681
f8b69d1d 4682DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(log_level, int, LOG_DEBUG);
f41607a6
LP
4683
4684static const char* const sched_policy_table[] = {
4685 [SCHED_OTHER] = "other",
4686 [SCHED_BATCH] = "batch",
4687 [SCHED_IDLE] = "idle",
4688 [SCHED_FIFO] = "fifo",
4689 [SCHED_RR] = "rr"
4690};
4691
f8b69d1d 4692DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(sched_policy, int, INT_MAX);
f41607a6
LP
4693
4694static const char* const rlimit_table[] = {
4695 [RLIMIT_CPU] = "LimitCPU",
4696 [RLIMIT_FSIZE] = "LimitFSIZE",
4697 [RLIMIT_DATA] = "LimitDATA",
4698 [RLIMIT_STACK] = "LimitSTACK",
4699 [RLIMIT_CORE] = "LimitCORE",
4700 [RLIMIT_RSS] = "LimitRSS",
4701 [RLIMIT_NOFILE] = "LimitNOFILE",
4702 [RLIMIT_AS] = "LimitAS",
4703 [RLIMIT_NPROC] = "LimitNPROC",
4704 [RLIMIT_MEMLOCK] = "LimitMEMLOCK",
4705 [RLIMIT_LOCKS] = "LimitLOCKS",
4706 [RLIMIT_SIGPENDING] = "LimitSIGPENDING",
4707 [RLIMIT_MSGQUEUE] = "LimitMSGQUEUE",
4708 [RLIMIT_NICE] = "LimitNICE",
4709 [RLIMIT_RTPRIO] = "LimitRTPRIO",
4710 [RLIMIT_RTTIME] = "LimitRTTIME"
4711};
4712
4713DEFINE_STRING_TABLE_LOOKUP(rlimit, int);
4714
4715static const char* const ip_tos_table[] = {
4716 [IPTOS_LOWDELAY] = "low-delay",
4717 [IPTOS_THROUGHPUT] = "throughput",
4718 [IPTOS_RELIABILITY] = "reliability",
4719 [IPTOS_LOWCOST] = "low-cost",
4720};
4721
f8b69d1d 4722DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(ip_tos, int, 0xff);
f41607a6 4723
4e240ab0 4724static const char *const __signal_table[] = {
f41607a6
LP
4725 [SIGHUP] = "HUP",
4726 [SIGINT] = "INT",
4727 [SIGQUIT] = "QUIT",
4728 [SIGILL] = "ILL",
4729 [SIGTRAP] = "TRAP",
4730 [SIGABRT] = "ABRT",
4731 [SIGBUS] = "BUS",
4732 [SIGFPE] = "FPE",
4733 [SIGKILL] = "KILL",
4734 [SIGUSR1] = "USR1",
4735 [SIGSEGV] = "SEGV",
4736 [SIGUSR2] = "USR2",
4737 [SIGPIPE] = "PIPE",
4738 [SIGALRM] = "ALRM",
4739 [SIGTERM] = "TERM",
4740#ifdef SIGSTKFLT
4741 [SIGSTKFLT] = "STKFLT", /* Linux on SPARC doesn't know SIGSTKFLT */
4742#endif
4743 [SIGCHLD] = "CHLD",
4744 [SIGCONT] = "CONT",
4745 [SIGSTOP] = "STOP",
4746 [SIGTSTP] = "TSTP",
4747 [SIGTTIN] = "TTIN",
4748 [SIGTTOU] = "TTOU",
4749 [SIGURG] = "URG",
4750 [SIGXCPU] = "XCPU",
4751 [SIGXFSZ] = "XFSZ",
4752 [SIGVTALRM] = "VTALRM",
4753 [SIGPROF] = "PROF",
4754 [SIGWINCH] = "WINCH",
4755 [SIGIO] = "IO",
4756 [SIGPWR] = "PWR",
4757 [SIGSYS] = "SYS"
4758};
4759
4e240ab0
MS
4760DEFINE_PRIVATE_STRING_TABLE_LOOKUP(__signal, int);
4761
4762const char *signal_to_string(int signo) {
fa70beaa 4763 static __thread char buf[sizeof("RTMIN+")-1 + DECIMAL_STR_MAX(int) + 1];
4e240ab0
MS
4764 const char *name;
4765
4766 name = __signal_to_string(signo);
4767 if (name)
4768 return name;
4769
4770 if (signo >= SIGRTMIN && signo <= SIGRTMAX)
fa70beaa 4771 snprintf(buf, sizeof(buf), "RTMIN+%d", signo - SIGRTMIN);
4e240ab0 4772 else
fa70beaa
LP
4773 snprintf(buf, sizeof(buf), "%d", signo);
4774
4e240ab0
MS
4775 return buf;
4776}
4777
4778int signal_from_string(const char *s) {
4779 int signo;
4780 int offset = 0;
4781 unsigned u;
4782
040f18ea 4783 signo = __signal_from_string(s);
4e240ab0
MS
4784 if (signo > 0)
4785 return signo;
4786
4787 if (startswith(s, "RTMIN+")) {
4788 s += 6;
4789 offset = SIGRTMIN;
4790 }
4791 if (safe_atou(s, &u) >= 0) {
4792 signo = (int) u + offset;
4793 if (signo > 0 && signo < _NSIG)
4794 return signo;
4795 }
4796 return -1;
4797}
65457142
FC
4798
4799bool kexec_loaded(void) {
4800 bool loaded = false;
4801 char *s;
4802
4803 if (read_one_line_file("/sys/kernel/kexec_loaded", &s) >= 0) {
4804 if (s[0] == '1')
4805 loaded = true;
4806 free(s);
4807 }
4808 return loaded;
4809}
fb9de93d
LP
4810
4811int strdup_or_null(const char *a, char **b) {
4812 char *c;
4813
4814 assert(b);
4815
4816 if (!a) {
4817 *b = NULL;
4818 return 0;
4819 }
4820
4821 c = strdup(a);
4822 if (!c)
4823 return -ENOMEM;
4824
4825 *b = c;
4826 return 0;
4827}
64685e0c 4828
87d2c1ff
LP
4829int prot_from_flags(int flags) {
4830
4831 switch (flags & O_ACCMODE) {
4832
4833 case O_RDONLY:
4834 return PROT_READ;
4835
4836 case O_WRONLY:
4837 return PROT_WRITE;
4838
4839 case O_RDWR:
4840 return PROT_READ|PROT_WRITE;
4841
4842 default:
4843 return -EINVAL;
4844 }
7c99e0c1 4845}
689b9a22 4846
babfc091 4847char *format_bytes(char *buf, size_t l, off_t t) {
c0f99c21 4848 unsigned i;
babfc091
LP
4849
4850 static const struct {
4851 const char *suffix;
4852 off_t factor;
4853 } table[] = {
32895bb3
LP
4854 { "E", 1024ULL*1024ULL*1024ULL*1024ULL*1024ULL*1024ULL },
4855 { "P", 1024ULL*1024ULL*1024ULL*1024ULL*1024ULL },
babfc091
LP
4856 { "T", 1024ULL*1024ULL*1024ULL*1024ULL },
4857 { "G", 1024ULL*1024ULL*1024ULL },
4858 { "M", 1024ULL*1024ULL },
4859 { "K", 1024ULL },
4860 };
4861
4862 for (i = 0; i < ELEMENTSOF(table); i++) {
4863
4864 if (t >= table[i].factor) {
4865 snprintf(buf, l,
4866 "%llu.%llu%s",
4867 (unsigned long long) (t / table[i].factor),
4868 (unsigned long long) (((t*10ULL) / table[i].factor) % 10ULL),
4869 table[i].suffix);
4870
4871 goto finish;
4872 }
4873 }
4874
4875 snprintf(buf, l, "%lluB", (unsigned long long) t);
4876
4877finish:
4878 buf[l-1] = 0;
4879 return buf;
4880
4881}
55d7bfc1
LP
4882
4883void* memdup(const void *p, size_t l) {
4884 void *r;
4885
4886 assert(p);
4887
4888 r = malloc(l);
4889 if (!r)
4890 return NULL;
4891
4892 memcpy(r, p, l);
4893 return r;
4894}
bb99a35a
LP
4895
4896int fd_inc_sndbuf(int fd, size_t n) {
4897 int r, value;
4898 socklen_t l = sizeof(value);
4899
4900 r = getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &value, &l);
4901 if (r >= 0 &&
4902 l == sizeof(value) &&
4903 (size_t) value >= n*2)
4904 return 0;
4905
4906 value = (int) n;
4907 r = setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &value, sizeof(value));
4908 if (r < 0)
4909 return -errno;
4910
4911 return 1;
4912}
4913
4914int fd_inc_rcvbuf(int fd, size_t n) {
4915 int r, value;
4916 socklen_t l = sizeof(value);
4917
4918 r = getsockopt(fd, SOL_SOCKET, SO_RCVBUF, &value, &l);
4919 if (r >= 0 &&
4920 l == sizeof(value) &&
4921 (size_t) value >= n*2)
4922 return 0;
4923
4924 value = (int) n;
4925 r = setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &value, sizeof(value));
4926 if (r < 0)
4927 return -errno;
4928
4929 return 1;
4930}
6bb92a16 4931
9bdc770c 4932int fork_agent(pid_t *pid, const int except[], unsigned n_except, const char *path, ...) {
6bb92a16
LP
4933 pid_t parent_pid, agent_pid;
4934 int fd;
4935 bool stdout_is_tty, stderr_is_tty;
4936 unsigned n, i;
4937 va_list ap;
4938 char **l;
4939
4940 assert(pid);
4941 assert(path);
4942
4943 parent_pid = getpid();
4944
4945 /* Spawns a temporary TTY agent, making sure it goes away when
4946 * we go away */
4947
4948 agent_pid = fork();
4949 if (agent_pid < 0)
4950 return -errno;
4951
4952 if (agent_pid != 0) {
4953 *pid = agent_pid;
4954 return 0;
4955 }
4956
4957 /* In the child:
4958 *
4959 * Make sure the agent goes away when the parent dies */
4960 if (prctl(PR_SET_PDEATHSIG, SIGTERM) < 0)
4961 _exit(EXIT_FAILURE);
4962
4963 /* Check whether our parent died before we were able
4964 * to set the death signal */
4965 if (getppid() != parent_pid)
4966 _exit(EXIT_SUCCESS);
4967
4968 /* Don't leak fds to the agent */
9bdc770c 4969 close_all_fds(except, n_except);
6bb92a16
LP
4970
4971 stdout_is_tty = isatty(STDOUT_FILENO);
4972 stderr_is_tty = isatty(STDERR_FILENO);
4973
4974 if (!stdout_is_tty || !stderr_is_tty) {
4975 /* Detach from stdout/stderr. and reopen
4976 * /dev/tty for them. This is important to
4977 * ensure that when systemctl is started via
4978 * popen() or a similar call that expects to
4979 * read EOF we actually do generate EOF and
4980 * not delay this indefinitely by because we
4981 * keep an unused copy of stdin around. */
4982 fd = open("/dev/tty", O_WRONLY);
4983 if (fd < 0) {
4984 log_error("Failed to open /dev/tty: %m");
4985 _exit(EXIT_FAILURE);
4986 }
4987
4988 if (!stdout_is_tty)
4989 dup2(fd, STDOUT_FILENO);
4990
4991 if (!stderr_is_tty)
4992 dup2(fd, STDERR_FILENO);
4993
4994 if (fd > 2)
4995 close(fd);
4996 }
4997
4998 /* Count arguments */
4999 va_start(ap, path);
5000 for (n = 0; va_arg(ap, char*); n++)
5001 ;
5002 va_end(ap);
5003
5004 /* Allocate strv */
5005 l = alloca(sizeof(char *) * (n + 1));
5006
5007 /* Fill in arguments */
5008 va_start(ap, path);
5009 for (i = 0; i <= n; i++)
5010 l[i] = va_arg(ap, char*);
5011 va_end(ap);
5012
5013 execv(path, l);
5014 _exit(EXIT_FAILURE);
5015}
68faf98c
LP
5016
5017int setrlimit_closest(int resource, const struct rlimit *rlim) {
5018 struct rlimit highest, fixed;
5019
5020 assert(rlim);
5021
5022 if (setrlimit(resource, rlim) >= 0)
5023 return 0;
5024
5025 if (errno != EPERM)
5026 return -errno;
5027
5028 /* So we failed to set the desired setrlimit, then let's try
5029 * to get as close as we can */
5030 assert_se(getrlimit(resource, &highest) == 0);
5031
5032 fixed.rlim_cur = MIN(rlim->rlim_cur, highest.rlim_max);
5033 fixed.rlim_max = MIN(rlim->rlim_max, highest.rlim_max);
5034
5035 if (setrlimit(resource, &fixed) < 0)
5036 return -errno;
5037
5038 return 0;
5039}
3d9a4122 5040
ab94af92 5041int getenv_for_pid(pid_t pid, const char *field, char **_value) {
49aa47c7
LP
5042 _cleanup_fclose_ FILE *f = NULL;
5043 char *value = NULL;
ab94af92 5044 int r;
ab94af92
LP
5045 bool done = false;
5046 size_t l;
49aa47c7 5047 const char *path;
ab94af92 5048
49aa47c7 5049 assert(pid >= 0);
ab94af92
LP
5050 assert(field);
5051 assert(_value);
5052
5053 if (pid == 0)
49aa47c7
LP
5054 path = "/proc/self/environ";
5055 else
5056 path = procfs_file_alloca(pid, "environ");
ab94af92
LP
5057
5058 f = fopen(path, "re");
5059 if (!f)
5060 return -errno;
5061
5062 l = strlen(field);
5063 r = 0;
5064
5065 do {
5066 char line[LINE_MAX];
5067 unsigned i;
5068
5069 for (i = 0; i < sizeof(line)-1; i++) {
5070 int c;
5071
5072 c = getc(f);
5073 if (_unlikely_(c == EOF)) {
5074 done = true;
5075 break;
5076 } else if (c == 0)
5077 break;
5078
5079 line[i] = c;
5080 }
5081 line[i] = 0;
5082
5083 if (memcmp(line, field, l) == 0 && line[l] == '=') {
5084 value = strdup(line + l + 1);
49aa47c7
LP
5085 if (!value)
5086 return -ENOMEM;
ab94af92
LP
5087
5088 r = 1;
5089 break;
5090 }
5091
5092 } while (!done);
5093
49aa47c7 5094 *_value = value;
ab94af92
LP
5095 return r;
5096}
d889a206 5097
49dbfa7b
LP
5098bool is_valid_documentation_url(const char *url) {
5099 assert(url);
5100
5101 if (startswith(url, "http://") && url[7])
5102 return true;
5103
5104 if (startswith(url, "https://") && url[8])
5105 return true;
5106
5107 if (startswith(url, "file:") && url[5])
5108 return true;
5109
5110 if (startswith(url, "info:") && url[5])
5111 return true;
5112
5113 if (startswith(url, "man:") && url[4])
5114 return true;
5115
5116 return false;
5117}
9be346c9
HH
5118
5119bool in_initrd(void) {
a05f97b3 5120 static __thread int saved = -1;
825c6fe5 5121 struct statfs s;
8f33b5b8 5122
825c6fe5
LP
5123 if (saved >= 0)
5124 return saved;
5125
5126 /* We make two checks here:
5127 *
5128 * 1. the flag file /etc/initrd-release must exist
5129 * 2. the root file system must be a memory file system
5130 *
5131 * The second check is extra paranoia, since misdetecting an
5132 * initrd can have bad bad consequences due the initrd
5133 * emptying when transititioning to the main systemd.
5134 */
5135
5136 saved = access("/etc/initrd-release", F_OK) >= 0 &&
5137 statfs("/", &s) >= 0 &&
943aad8c 5138 is_temporary_fs(&s);
9be346c9 5139
8f33b5b8 5140 return saved;
9be346c9 5141}
069cfc85
LP
5142
5143void warn_melody(void) {
e67f47e5 5144 _cleanup_close_ int fd = -1;
069cfc85
LP
5145
5146 fd = open("/dev/console", O_WRONLY|O_CLOEXEC|O_NOCTTY);
5147 if (fd < 0)
5148 return;
5149
040f18ea 5150 /* Yeah, this is synchronous. Kinda sucks. But well... */
069cfc85
LP
5151
5152 ioctl(fd, KIOCSOUND, (int)(1193180/440));
5153 usleep(125*USEC_PER_MSEC);
5154
5155 ioctl(fd, KIOCSOUND, (int)(1193180/220));
5156 usleep(125*USEC_PER_MSEC);
5157
5158 ioctl(fd, KIOCSOUND, (int)(1193180/220));
5159 usleep(125*USEC_PER_MSEC);
5160
5161 ioctl(fd, KIOCSOUND, 0);
069cfc85 5162}
cd3bd60a
LP
5163
5164int make_console_stdio(void) {
5165 int fd, r;
5166
5167 /* Make /dev/console the controlling terminal and stdin/stdout/stderr */
5168
5169 fd = acquire_terminal("/dev/console", false, true, true, (usec_t) -1);
5170 if (fd < 0) {
5171 log_error("Failed to acquire terminal: %s", strerror(-fd));
5172 return fd;
5173 }
5174
5175 r = make_stdio(fd);
5176 if (r < 0) {
5177 log_error("Failed to duplicate terminal fd: %s", strerror(-r));
5178 return r;
5179 }
5180
5181 return 0;
5182}
7c5f152a
LP
5183
5184int get_home_dir(char **_h) {
5185 char *h;
5186 const char *e;
5187 uid_t u;
5188 struct passwd *p;
5189
5190 assert(_h);
5191
5192 /* Take the user specified one */
5193 e = getenv("HOME");
5194 if (e) {
5195 h = strdup(e);
5196 if (!h)
5197 return -ENOMEM;
5198
5199 *_h = h;
5200 return 0;
5201 }
5202
5203 /* Hardcode home directory for root to avoid NSS */
5204 u = getuid();
5205 if (u == 0) {
5206 h = strdup("/root");
5207 if (!h)
5208 return -ENOMEM;
5209
5210 *_h = h;
5211 return 0;
5212 }
5213
5214 /* Check the database... */
5215 errno = 0;
5216 p = getpwuid(u);
5217 if (!p)
bcb161b0 5218 return errno > 0 ? -errno : -ESRCH;
7c5f152a
LP
5219
5220 if (!path_is_absolute(p->pw_dir))
5221 return -EINVAL;
5222
5223 h = strdup(p->pw_dir);
5224 if (!h)
5225 return -ENOMEM;
5226
5227 *_h = h;
5228 return 0;
5229}
5230
0b507b17
LP
5231bool filename_is_safe(const char *p) {
5232
5233 if (isempty(p))
5234 return false;
5235
5236 if (strchr(p, '/'))
5237 return false;
5238
5239 if (streq(p, "."))
5240 return false;
5241
5242 if (streq(p, ".."))
5243 return false;
5244
5245 if (strlen(p) > FILENAME_MAX)
5246 return false;
5247
5248 return true;
5249}
5250
5251bool string_is_safe(const char *p) {
5252 const char *t;
5253
5254 assert(p);
5255
5256 for (t = p; *t; t++) {
01539d6e 5257 if (*t > 0 && *t < ' ')
0b507b17
LP
5258 return false;
5259
011afa76 5260 if (strchr("\\\"\'", *t))
0b507b17
LP
5261 return false;
5262 }
5263
5264 return true;
5265}
cfbc22ab 5266
4d1a6904
LP
5267bool string_has_cc(const char *p) {
5268 const char *t;
5269
5270 assert(p);
5271
5272 for (t = p; *t; t++)
5273 if (*t > 0 && *t < ' ')
5274 return true;
5275
5276 return false;
5277}
5278
e884315e
LP
5279bool path_is_safe(const char *p) {
5280
5281 if (isempty(p))
5282 return false;
5283
5284 if (streq(p, "..") || startswith(p, "../") || endswith(p, "/..") || strstr(p, "/../"))
5285 return false;
5286
5287 if (strlen(p) > PATH_MAX)
5288 return false;
5289
5290 /* The following two checks are not really dangerous, but hey, they still are confusing */
5291 if (streq(p, ".") || startswith(p, "./") || endswith(p, "/.") || strstr(p, "/./"))
5292 return false;
5293
5294 if (strstr(p, "//"))
5295 return false;
5296
5297 return true;
5298}
5299
a9e12476
KS
5300/* hey glibc, APIs with callbacks without a user pointer are so useless */
5301void *xbsearch_r(const void *key, const void *base, size_t nmemb, size_t size,
1c574591 5302 int (*compar) (const void *, const void *, void *), void *arg) {
a9e12476
KS
5303 size_t l, u, idx;
5304 const void *p;
5305 int comparison;
5306
5307 l = 0;
5308 u = nmemb;
5309 while (l < u) {
5310 idx = (l + u) / 2;
5311 p = (void *)(((const char *) base) + (idx * size));
5312 comparison = compar(key, p, arg);
5313 if (comparison < 0)
5314 u = idx;
5315 else if (comparison > 0)
5316 l = idx + 1;
5317 else
5318 return (void *)p;
5319 }
5320 return NULL;
5321}
09017585
MS
5322
5323bool is_locale_utf8(void) {
5324 const char *set;
5325 static int cached_answer = -1;
5326
5327 if (cached_answer >= 0)
5328 goto out;
5329
5330 if (!setlocale(LC_ALL, "")) {
5331 cached_answer = true;
5332 goto out;
5333 }
5334
5335 set = nl_langinfo(CODESET);
5336 if (!set) {
5337 cached_answer = true;
5338 goto out;
5339 }
5340
fee79e01
HH
5341 if(streq(set, "UTF-8")) {
5342 cached_answer = true;
5343 goto out;
5344 }
5345
5346 /* For LC_CTYPE=="C" return true,
5347 * because CTYPE is effectly unset and
5348 * everything defaults to UTF-8 nowadays. */
5349
5350 set = setlocale(LC_CTYPE, NULL);
5351 if (!set) {
5352 cached_answer = true;
5353 goto out;
5354 }
5355
5356 cached_answer = streq(set, "C");
5357
09017585
MS
5358out:
5359 return (bool)cached_answer;
5360}
c339d977
MS
5361
5362const char *draw_special_char(DrawSpecialChar ch) {
5363 static const char *draw_table[2][_DRAW_SPECIAL_CHAR_MAX] = {
5364 /* UTF-8 */ {
45a5ff0d
MS
5365 [DRAW_TREE_VERT] = "\342\224\202 ", /* │ */
5366 [DRAW_TREE_BRANCH] = "\342\224\234\342\224\200", /* ├─ */
5367 [DRAW_TREE_RIGHT] = "\342\224\224\342\224\200", /* └─ */
55c0b89c 5368 [DRAW_TREE_SPACE] = " ", /* */
45a5ff0d 5369 [DRAW_TRIANGULAR_BULLET] = "\342\200\243 ", /* ‣ */
c339d977
MS
5370 },
5371 /* ASCII fallback */ {
45a5ff0d
MS
5372 [DRAW_TREE_VERT] = "| ",
5373 [DRAW_TREE_BRANCH] = "|-",
5374 [DRAW_TREE_RIGHT] = "`-",
55c0b89c 5375 [DRAW_TREE_SPACE] = " ",
45a5ff0d 5376 [DRAW_TRIANGULAR_BULLET] = "> ",
c339d977
MS
5377 }
5378 };
5379
5380 return draw_table[!is_locale_utf8()][ch];
5381}
409bc9c3
LP
5382
5383char *strreplace(const char *text, const char *old_string, const char *new_string) {
5384 const char *f;
5385 char *t, *r;
5386 size_t l, old_len, new_len;
5387
5388 assert(text);
5389 assert(old_string);
5390 assert(new_string);
5391
5392 old_len = strlen(old_string);
5393 new_len = strlen(new_string);
5394
5395 l = strlen(text);
5396 r = new(char, l+1);
5397 if (!r)
5398 return NULL;
5399
5400 f = text;
5401 t = r;
5402 while (*f) {
5403 char *a;
5404 size_t d, nl;
5405
5406 if (!startswith(f, old_string)) {
5407 *(t++) = *(f++);
5408 continue;
5409 }
5410
5411 d = t - r;
5412 nl = l - old_len + new_len;
5413 a = realloc(r, nl + 1);
5414 if (!a)
5415 goto oom;
5416
5417 l = nl;
5418 r = a;
5419 t = r + d;
5420
5421 t = stpcpy(t, new_string);
5422 f += old_len;
5423 }
5424
5425 *t = 0;
5426 return r;
5427
5428oom:
5429 free(r);
5430 return NULL;
5431}
e8bc0ea2
LP
5432
5433char *strip_tab_ansi(char **ibuf, size_t *_isz) {
660ddc72 5434 const char *i, *begin = NULL;
e8bc0ea2
LP
5435 enum {
5436 STATE_OTHER,
5437 STATE_ESCAPE,
5438 STATE_BRACKET
5439 } state = STATE_OTHER;
5440 char *obuf = NULL;
5441 size_t osz = 0, isz;
5442 FILE *f;
5443
5444 assert(ibuf);
5445 assert(*ibuf);
5446
5447 /* Strips ANSI color and replaces TABs by 8 spaces */
5448
5449 isz = _isz ? *_isz : strlen(*ibuf);
5450
5451 f = open_memstream(&obuf, &osz);
5452 if (!f)
5453 return NULL;
5454
5455 for (i = *ibuf; i < *ibuf + isz + 1; i++) {
5456
5457 switch (state) {
5458
5459 case STATE_OTHER:
5460 if (i >= *ibuf + isz) /* EOT */
5461 break;
5462 else if (*i == '\x1B')
5463 state = STATE_ESCAPE;
5464 else if (*i == '\t')
5465 fputs(" ", f);
5466 else
5467 fputc(*i, f);
5468 break;
5469
5470 case STATE_ESCAPE:
5471 if (i >= *ibuf + isz) { /* EOT */
5472 fputc('\x1B', f);
5473 break;
5474 } else if (*i == '[') {
5475 state = STATE_BRACKET;
5476 begin = i + 1;
5477 } else {
5478 fputc('\x1B', f);
5479 fputc(*i, f);
5480 state = STATE_OTHER;
5481 }
5482
5483 break;
5484
5485 case STATE_BRACKET:
5486
5487 if (i >= *ibuf + isz || /* EOT */
5488 (!(*i >= '0' && *i <= '9') && *i != ';' && *i != 'm')) {
5489 fputc('\x1B', f);
5490 fputc('[', f);
5491 state = STATE_OTHER;
5492 i = begin-1;
5493 } else if (*i == 'm')
5494 state = STATE_OTHER;
5495 break;
5496 }
5497 }
5498
5499 if (ferror(f)) {
5500 fclose(f);
5501 free(obuf);
5502 return NULL;
5503 }
5504
5505 fclose(f);
5506
5507 free(*ibuf);
5508 *ibuf = obuf;
5509
5510 if (_isz)
5511 *_isz = osz;
5512
5513 return obuf;
5514}
240dbaa4
LP
5515
5516int on_ac_power(void) {
5517 bool found_offline = false, found_online = false;
5518 _cleanup_closedir_ DIR *d = NULL;
5519
5520 d = opendir("/sys/class/power_supply");
5521 if (!d)
5522 return -errno;
5523
5524 for (;;) {
5525 struct dirent *de;
5526 union dirent_storage buf;
240dbaa4
LP
5527 _cleanup_close_ int fd = -1, device = -1;
5528 char contents[6];
5529 ssize_t n;
5530 int k;
5531
5532 k = readdir_r(d, &buf.de, &de);
5533 if (k != 0)
5534 return -k;
5535
5536 if (!de)
5537 break;
5538
5539 if (ignore_file(de->d_name))
5540 continue;
5541
5542 device = openat(dirfd(d), de->d_name, O_DIRECTORY|O_RDONLY|O_CLOEXEC|O_NOCTTY);
5543 if (device < 0) {
5544 if (errno == ENOENT || errno == ENOTDIR)
5545 continue;
5546
5547 return -errno;
5548 }
5549
5550 fd = openat(device, "type", O_RDONLY|O_CLOEXEC|O_NOCTTY);
5551 if (fd < 0) {
5552 if (errno == ENOENT)
5553 continue;
5554
5555 return -errno;
5556 }
5557
5558 n = read(fd, contents, sizeof(contents));
5559 if (n < 0)
5560 return -errno;
5561
5562 if (n != 6 || memcmp(contents, "Mains\n", 6))
5563 continue;
5564
5565 close_nointr_nofail(fd);
5566 fd = openat(device, "online", O_RDONLY|O_CLOEXEC|O_NOCTTY);
5567 if (fd < 0) {
5568 if (errno == ENOENT)
5569 continue;
5570
5571 return -errno;
5572 }
5573
5574 n = read(fd, contents, sizeof(contents));
5575 if (n < 0)
5576 return -errno;
5577
5578 if (n != 2 || contents[1] != '\n')
5579 return -EIO;
5580
5581 if (contents[0] == '1') {
5582 found_online = true;
5583 break;
5584 } else if (contents[0] == '0')
5585 found_offline = true;
5586 else
5587 return -EIO;
5588 }
5589
5590 return found_online || !found_offline;
5591}
fabe5c0e
LP
5592
5593static int search_and_fopen_internal(const char *path, const char *mode, char **search, FILE **_f) {
5594 char **i;
5595
5596 assert(path);
5597 assert(mode);
5598 assert(_f);
5599
5600 if (!path_strv_canonicalize_uniq(search))
5601 return -ENOMEM;
5602
5603 STRV_FOREACH(i, search) {
5604 _cleanup_free_ char *p = NULL;
5605 FILE *f;
5606
5607 p = strjoin(*i, "/", path, NULL);
5608 if (!p)
5609 return -ENOMEM;
5610
5611 f = fopen(p, mode);
5612 if (f) {
5613 *_f = f;
5614 return 0;
5615 }
5616
5617 if (errno != ENOENT)
5618 return -errno;
5619 }
5620
5621 return -ENOENT;
5622}
5623
5624int search_and_fopen(const char *path, const char *mode, const char **search, FILE **_f) {
5625 _cleanup_strv_free_ char **copy = NULL;
5626
5627 assert(path);
5628 assert(mode);
5629 assert(_f);
5630
5631 if (path_is_absolute(path)) {
5632 FILE *f;
5633
5634 f = fopen(path, mode);
5635 if (f) {
5636 *_f = f;
5637 return 0;
5638 }
5639
5640 return -errno;
5641 }
5642
5643 copy = strv_copy((char**) search);
5644 if (!copy)
5645 return -ENOMEM;
5646
5647 return search_and_fopen_internal(path, mode, copy, _f);
5648}
5649
5650int search_and_fopen_nulstr(const char *path, const char *mode, const char *search, FILE **_f) {
5651 _cleanup_strv_free_ char **s = NULL;
5652
5653 if (path_is_absolute(path)) {
5654 FILE *f;
5655
5656 f = fopen(path, mode);
5657 if (f) {
5658 *_f = f;
5659 return 0;
5660 }
5661
5662 return -errno;
5663 }
5664
5665 s = strv_split_nulstr(search);
5666 if (!s)
5667 return -ENOMEM;
5668
5669 return search_and_fopen_internal(path, mode, s, _f);
5670}
c17ec25e 5671
d34cd374 5672int create_tmp_dir(char template[], char** dir_name) {
c17ec25e 5673 int r = 0;
d34cd374 5674 char *d, *dt;
c17ec25e
MS
5675
5676 assert(dir_name);
5677
5c0d398d
LP
5678 RUN_WITH_UMASK(0077) {
5679 d = mkdtemp(template);
5680 }
c17ec25e 5681 if (!d) {
d34cd374
ZJS
5682 log_error("Can't create directory %s: %m", template);
5683 return -errno;
c17ec25e
MS
5684 }
5685
d34cd374
ZJS
5686 dt = strjoin(d, "/tmp", NULL);
5687 if (!dt) {
c17ec25e 5688 r = log_oom();
f36a783c 5689 goto fail3;
c17ec25e
MS
5690 }
5691
5c0d398d
LP
5692 RUN_WITH_UMASK(0000) {
5693 r = mkdir(dt, 0777);
5694 }
5695 if (r < 0) {
d34cd374
ZJS
5696 log_error("Can't create directory %s: %m", dt);
5697 r = -errno;
f36a783c 5698 goto fail2;
d34cd374
ZJS
5699 }
5700 log_debug("Created temporary directory %s", dt);
5701
5702 r = chmod(dt, 0777 | S_ISVTX);
5703 if (r < 0) {
5704 log_error("Failed to chmod %s: %m", dt);
5705 r = -errno;
5706 goto fail1;
c17ec25e 5707 }
d34cd374 5708 log_debug("Set sticky bit on %s", dt);
c17ec25e 5709
d34cd374 5710 *dir_name = dt;
c17ec25e
MS
5711
5712 return 0;
d34cd374
ZJS
5713fail1:
5714 rmdir(dt);
5715fail2:
f36a783c
VP
5716 free(dt);
5717fail3:
d34cd374 5718 rmdir(template);
c17ec25e
MS
5719 return r;
5720}
66e35261
LP
5721
5722char *strextend(char **x, ...) {
5723 va_list ap;
5724 size_t f, l;
5725 char *r, *p;
5726
5727 assert(x);
5728
5729 l = f = *x ? strlen(*x) : 0;
5730
5731 va_start(ap, x);
5732 for (;;) {
5733 const char *t;
5734 size_t n;
5735
5736 t = va_arg(ap, const char *);
5737 if (!t)
5738 break;
5739
5740 n = strlen(t);
5741 if (n > ((size_t) -1) - l) {
5742 va_end(ap);
5743 return NULL;
5744 }
5745
5746 l += n;
5747 }
5748 va_end(ap);
5749
5750 r = realloc(*x, l+1);
5751 if (!r)
5752 return NULL;
5753
5754 p = r + f;
5755
5756 va_start(ap, x);
5757 for (;;) {
5758 const char *t;
5759
5760 t = va_arg(ap, const char *);
5761 if (!t)
5762 break;
5763
5764 p = stpcpy(p, t);
5765 }
5766 va_end(ap);
5767
5768 *p = 0;
5769 *x = r;
5770
5771 return r + l;
5772}
9a17484d
LP
5773
5774char *strrep(const char *s, unsigned n) {
5775 size_t l;
5776 char *r, *p;
5777 unsigned i;
5778
5779 assert(s);
5780
5781 l = strlen(s);
5782 p = r = malloc(l * n + 1);
5783 if (!r)
5784 return NULL;
5785
5786 for (i = 0; i < n; i++)
5787 p = stpcpy(p, s);
5788
5789 *p = 0;
5790 return r;
5791}
392d5b37
LP
5792
5793void* greedy_realloc(void **p, size_t *allocated, size_t need) {
5794 size_t a;
5795 void *q;
5796
5797 if (*allocated >= need)
5798 return *p;
5799
9607d947 5800 a = MAX(64u, need * 2);
392d5b37
LP
5801 q = realloc(*p, a);
5802 if (!q)
5803 return NULL;
5804
5805 *p = q;
5806 *allocated = a;
5807 return q;
5808}
aa96c6cb
LP
5809
5810bool id128_is_valid(const char *s) {
5811 size_t i, l;
5812
5813 l = strlen(s);
5814 if (l == 32) {
5815
5816 /* Simple formatted 128bit hex string */
5817
5818 for (i = 0; i < l; i++) {
5819 char c = s[i];
5820
5821 if (!(c >= '0' && c <= '9') &&
5822 !(c >= 'a' && c <= 'z') &&
5823 !(c >= 'A' && c <= 'Z'))
5824 return false;
5825 }
5826
5827 } else if (l == 36) {
5828
5829 /* Formatted UUID */
5830
5831 for (i = 0; i < l; i++) {
5832 char c = s[i];
5833
5834 if ((i == 8 || i == 13 || i == 18 || i == 23)) {
5835 if (c != '-')
5836 return false;
5837 } else {
5838 if (!(c >= '0' && c <= '9') &&
5839 !(c >= 'a' && c <= 'z') &&
5840 !(c >= 'A' && c <= 'Z'))
5841 return false;
5842 }
5843 }
5844
5845 } else
5846 return false;
5847
5848 return true;
5849}