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