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