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