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