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