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