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