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