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