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