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