]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/shared/util.c
tmpfiles: set up selinux label proeprly when creating fifos
[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"
1517 "ncpfs\0"
dac70dc7 1518 "ncp\0"
a05f97b3
LP
1519 "nfs\0"
1520 "nfs4\0"
1521 "gfs\0"
67608cad
LP
1522 "gfs2\0"
1523 "glusterfs\0";
1524
1525 const char *x;
1526
1527 x = startswith(fstype, "fuse.");
1528 if (x)
1529 fstype = x;
42856c10 1530
a05f97b3 1531 return nulstr_contains(table, fstype);
42856c10
LP
1532}
1533
601f6a1e 1534int chvt(int vt) {
a05f97b3 1535 _cleanup_close_ int fd;
601f6a1e 1536
a05f97b3
LP
1537 fd = open_terminal("/dev/tty0", O_RDWR|O_NOCTTY|O_CLOEXEC);
1538 if (fd < 0)
601f6a1e
LP
1539 return -errno;
1540
1541 if (vt < 0) {
1542 int tiocl[2] = {
1543 TIOCL_GETKMSGREDIRECT,
1544 0
1545 };
1546
a05f97b3
LP
1547 if (ioctl(fd, TIOCLINUX, tiocl) < 0)
1548 return -errno;
601f6a1e
LP
1549
1550 vt = tiocl[0] <= 0 ? 1 : tiocl[0];
1551 }
1552
1553 if (ioctl(fd, VT_ACTIVATE, vt) < 0)
a05f97b3 1554 return -errno;
601f6a1e 1555
a05f97b3 1556 return 0;
601f6a1e
LP
1557}
1558
8f2d43a0 1559int read_one_char(FILE *f, char *ret, usec_t t, bool *need_nl) {
80876c20
LP
1560 struct termios old_termios, new_termios;
1561 char c;
20c03b7b 1562 char line[LINE_MAX];
80876c20
LP
1563
1564 assert(f);
1565 assert(ret);
1566
1567 if (tcgetattr(fileno(f), &old_termios) >= 0) {
1568 new_termios = old_termios;
1569
1570 new_termios.c_lflag &= ~ICANON;
1571 new_termios.c_cc[VMIN] = 1;
1572 new_termios.c_cc[VTIME] = 0;
1573
1574 if (tcsetattr(fileno(f), TCSADRAIN, &new_termios) >= 0) {
1575 size_t k;
1576
8f2d43a0
LP
1577 if (t != (usec_t) -1) {
1578 if (fd_wait_for_event(fileno(f), POLLIN, t) <= 0) {
1579 tcsetattr(fileno(f), TCSADRAIN, &old_termios);
1580 return -ETIMEDOUT;
1581 }
1582 }
1583
80876c20
LP
1584 k = fread(&c, 1, 1, f);
1585
1586 tcsetattr(fileno(f), TCSADRAIN, &old_termios);
1587
1588 if (k <= 0)
1589 return -EIO;
1590
1591 if (need_nl)
1592 *need_nl = c != '\n';
1593
1594 *ret = c;
1595 return 0;
1596 }
1597 }
1598
8f2d43a0
LP
1599 if (t != (usec_t) -1)
1600 if (fd_wait_for_event(fileno(f), POLLIN, t) <= 0)
1601 return -ETIMEDOUT;
1602
1603 if (!fgets(line, sizeof(line), f))
80876c20
LP
1604 return -EIO;
1605
1606 truncate_nl(line);
1607
1608 if (strlen(line) != 1)
1609 return -EBADMSG;
1610
1611 if (need_nl)
1612 *need_nl = false;
1613
1614 *ret = line[0];
1615 return 0;
1616}
1617
1618int ask(char *ret, const char *replies, const char *text, ...) {
1b39d4b9 1619
80876c20
LP
1620 assert(ret);
1621 assert(replies);
1622 assert(text);
1623
1624 for (;;) {
1625 va_list ap;
1626 char c;
1627 int r;
1628 bool need_nl = true;
1629
8481248b 1630 if (on_tty())
c1072ea0 1631 fputs(ANSI_HIGHLIGHT_ON, stdout);
b1b2dc0c 1632
80876c20
LP
1633 va_start(ap, text);
1634 vprintf(text, ap);
1635 va_end(ap);
1636
8481248b 1637 if (on_tty())
c1072ea0 1638 fputs(ANSI_HIGHLIGHT_OFF, stdout);
b1b2dc0c 1639
80876c20
LP
1640 fflush(stdout);
1641
8f2d43a0
LP
1642 r = read_one_char(stdin, &c, (usec_t) -1, &need_nl);
1643 if (r < 0) {
80876c20
LP
1644
1645 if (r == -EBADMSG) {
1646 puts("Bad input, please try again.");
1647 continue;
1648 }
1649
1650 putchar('\n');
1651 return r;
1652 }
1653
1654 if (need_nl)
1655 putchar('\n');
1656
1657 if (strchr(replies, c)) {
1658 *ret = c;
1659 return 0;
1660 }
1661
1662 puts("Read unexpected character, please try again.");
1663 }
1664}
1665
512947d4 1666int reset_terminal_fd(int fd, bool switch_to_text) {
80876c20
LP
1667 struct termios termios;
1668 int r = 0;
3fe5e5d4
LP
1669
1670 /* Set terminal to some sane defaults */
80876c20
LP
1671
1672 assert(fd >= 0);
1673
eed1d0e3
LP
1674 /* We leave locked terminal attributes untouched, so that
1675 * Plymouth may set whatever it wants to set, and we don't
1676 * interfere with that. */
3fe5e5d4
LP
1677
1678 /* Disable exclusive mode, just in case */
1679 ioctl(fd, TIOCNXCL);
1680
5c0100a5 1681 /* Switch to text mode */
512947d4
MS
1682 if (switch_to_text)
1683 ioctl(fd, KDSETMODE, KD_TEXT);
5c0100a5 1684
3fe5e5d4 1685 /* Enable console unicode mode */
df465b3f 1686 ioctl(fd, KDSKBMODE, K_UNICODE);
80876c20
LP
1687
1688 if (tcgetattr(fd, &termios) < 0) {
1689 r = -errno;
1690 goto finish;
1691 }
1692
aaf694ca
LP
1693 /* We only reset the stuff that matters to the software. How
1694 * hardware is set up we don't touch assuming that somebody
1695 * else will do that for us */
1696
1697 termios.c_iflag &= ~(IGNBRK | BRKINT | ISTRIP | INLCR | IGNCR | IUCLC);
80876c20
LP
1698 termios.c_iflag |= ICRNL | IMAXBEL | IUTF8;
1699 termios.c_oflag |= ONLCR;
1700 termios.c_cflag |= CREAD;
1701 termios.c_lflag = ISIG | ICANON | IEXTEN | ECHO | ECHOE | ECHOK | ECHOCTL | ECHOPRT | ECHOKE;
1702
1703 termios.c_cc[VINTR] = 03; /* ^C */
1704 termios.c_cc[VQUIT] = 034; /* ^\ */
1705 termios.c_cc[VERASE] = 0177;
1706 termios.c_cc[VKILL] = 025; /* ^X */
1707 termios.c_cc[VEOF] = 04; /* ^D */
1708 termios.c_cc[VSTART] = 021; /* ^Q */
1709 termios.c_cc[VSTOP] = 023; /* ^S */
1710 termios.c_cc[VSUSP] = 032; /* ^Z */
1711 termios.c_cc[VLNEXT] = 026; /* ^V */
1712 termios.c_cc[VWERASE] = 027; /* ^W */
1713 termios.c_cc[VREPRINT] = 022; /* ^R */
aaf694ca
LP
1714 termios.c_cc[VEOL] = 0;
1715 termios.c_cc[VEOL2] = 0;
80876c20
LP
1716
1717 termios.c_cc[VTIME] = 0;
1718 termios.c_cc[VMIN] = 1;
1719
1720 if (tcsetattr(fd, TCSANOW, &termios) < 0)
1721 r = -errno;
1722
1723finish:
1724 /* Just in case, flush all crap out */
1725 tcflush(fd, TCIOFLUSH);
1726
1727 return r;
1728}
1729
6ea832a2 1730int reset_terminal(const char *name) {
03e334a1 1731 _cleanup_close_ int fd = -1;
6ea832a2
LP
1732
1733 fd = open_terminal(name, O_RDWR|O_NOCTTY|O_CLOEXEC);
1734 if (fd < 0)
1735 return fd;
1736
03e334a1 1737 return reset_terminal_fd(fd, true);
6ea832a2
LP
1738}
1739
80876c20
LP
1740int open_terminal(const char *name, int mode) {
1741 int fd, r;
f73f76ac 1742 unsigned c = 0;
80876c20 1743
f73f76ac
LP
1744 /*
1745 * If a TTY is in the process of being closed opening it might
1746 * cause EIO. This is horribly awful, but unlikely to be
1747 * changed in the kernel. Hence we work around this problem by
1748 * retrying a couple of times.
1749 *
1750 * https://bugs.launchpad.net/ubuntu/+source/linux/+bug/554172/comments/245
1751 */
1752
dd94c17e
LP
1753 assert(!(mode & O_CREAT));
1754
f73f76ac 1755 for (;;) {
dd94c17e 1756 fd = open(name, mode, 0);
af6da548 1757 if (fd >= 0)
f73f76ac
LP
1758 break;
1759
1760 if (errno != EIO)
1761 return -errno;
1762
af6da548 1763 /* Max 1s in total */
f73f76ac
LP
1764 if (c >= 20)
1765 return -errno;
1766
1767 usleep(50 * USEC_PER_MSEC);
1768 c++;
1769 }
1770
1771 if (fd < 0)
80876c20
LP
1772 return -errno;
1773
af6da548
LP
1774 r = isatty(fd);
1775 if (r < 0) {
03e334a1 1776 safe_close(fd);
80876c20
LP
1777 return -errno;
1778 }
1779
1780 if (!r) {
03e334a1 1781 safe_close(fd);
80876c20
LP
1782 return -ENOTTY;
1783 }
1784
1785 return fd;
1786}
1787
1788int flush_fd(int fd) {
b92bea5d
ZJS
1789 struct pollfd pollfd = {
1790 .fd = fd,
1791 .events = POLLIN,
1792 };
80876c20
LP
1793
1794 for (;;) {
20c03b7b 1795 char buf[LINE_MAX];
80876c20
LP
1796 ssize_t l;
1797 int r;
1798
e62d8c39
ZJS
1799 r = poll(&pollfd, 1, 0);
1800 if (r < 0) {
80876c20
LP
1801 if (errno == EINTR)
1802 continue;
1803
1804 return -errno;
80876c20 1805
e62d8c39 1806 } else if (r == 0)
80876c20
LP
1807 return 0;
1808
e62d8c39
ZJS
1809 l = read(fd, buf, sizeof(buf));
1810 if (l < 0) {
80876c20
LP
1811
1812 if (errno == EINTR)
1813 continue;
1814
1815 if (errno == EAGAIN)
1816 return 0;
1817
1818 return -errno;
e62d8c39 1819 } else if (l == 0)
80876c20
LP
1820 return 0;
1821 }
1822}
1823
af6da548
LP
1824int acquire_terminal(
1825 const char *name,
1826 bool fail,
1827 bool force,
1828 bool ignore_tiocstty_eperm,
1829 usec_t timeout) {
1830
4a0ff478 1831 int fd = -1, notify = -1, r = 0, wd = -1;
af6da548 1832 usec_t ts = 0;
80876c20
LP
1833
1834 assert(name);
1835
1836 /* We use inotify to be notified when the tty is closed. We
1837 * create the watch before checking if we can actually acquire
1838 * it, so that we don't lose any event.
1839 *
1840 * Note: strictly speaking this actually watches for the
1841 * device being closed, it does *not* really watch whether a
1842 * tty loses its controlling process. However, unless some
1843 * rogue process uses TIOCNOTTY on /dev/tty *after* closing
1844 * its tty otherwise this will not become a problem. As long
1845 * as the administrator makes sure not configure any service
1846 * on the same tty as an untrusted user this should not be a
1847 * problem. (Which he probably should not do anyway.) */
1848
af6da548
LP
1849 if (timeout != (usec_t) -1)
1850 ts = now(CLOCK_MONOTONIC);
1851
80876c20 1852 if (!fail && !force) {
af6da548
LP
1853 notify = inotify_init1(IN_CLOEXEC | (timeout != (usec_t) -1 ? IN_NONBLOCK : 0));
1854 if (notify < 0) {
80876c20
LP
1855 r = -errno;
1856 goto fail;
1857 }
1858
af6da548
LP
1859 wd = inotify_add_watch(notify, name, IN_CLOSE);
1860 if (wd < 0) {
80876c20
LP
1861 r = -errno;
1862 goto fail;
1863 }
1864 }
1865
1866 for (;;) {
b92bea5d
ZJS
1867 struct sigaction sa_old, sa_new = {
1868 .sa_handler = SIG_IGN,
1869 .sa_flags = SA_RESTART,
1870 };
1871
af6da548
LP
1872 if (notify >= 0) {
1873 r = flush_fd(notify);
1874 if (r < 0)
e3d1855b 1875 goto fail;
af6da548 1876 }
80876c20
LP
1877
1878 /* We pass here O_NOCTTY only so that we can check the return
1879 * value TIOCSCTTY and have a reliable way to figure out if we
1880 * successfully became the controlling process of the tty */
af6da548
LP
1881 fd = open_terminal(name, O_RDWR|O_NOCTTY|O_CLOEXEC);
1882 if (fd < 0)
6ea832a2 1883 return fd;
80876c20 1884
32c4bef8
LP
1885 /* Temporarily ignore SIGHUP, so that we don't get SIGHUP'ed
1886 * if we already own the tty. */
32c4bef8
LP
1887 assert_se(sigaction(SIGHUP, &sa_new, &sa_old) == 0);
1888
80876c20 1889 /* First, try to get the tty */
32c4bef8
LP
1890 if (ioctl(fd, TIOCSCTTY, force) < 0)
1891 r = -errno;
1892
1893 assert_se(sigaction(SIGHUP, &sa_old, NULL) == 0);
21de3988
LP
1894
1895 /* Sometimes it makes sense to ignore TIOCSCTTY
1896 * returning EPERM, i.e. when very likely we already
1897 * are have this controlling terminal. */
32c4bef8 1898 if (r < 0 && r == -EPERM && ignore_tiocstty_eperm)
21de3988
LP
1899 r = 0;
1900
32c4bef8 1901 if (r < 0 && (force || fail || r != -EPERM)) {
80876c20
LP
1902 goto fail;
1903 }
1904
1905 if (r >= 0)
1906 break;
1907
1908 assert(!fail);
1909 assert(!force);
1910 assert(notify >= 0);
1911
1912 for (;;) {
f601daa7 1913 uint8_t inotify_buffer[sizeof(struct inotify_event) + FILENAME_MAX];
80876c20 1914 ssize_t l;
f601daa7 1915 struct inotify_event *e;
80876c20 1916
af6da548
LP
1917 if (timeout != (usec_t) -1) {
1918 usec_t n;
1919
1920 n = now(CLOCK_MONOTONIC);
1921 if (ts + timeout < n) {
1922 r = -ETIMEDOUT;
1923 goto fail;
1924 }
1925
1926 r = fd_wait_for_event(fd, POLLIN, ts + timeout - n);
1927 if (r < 0)
1928 goto fail;
1929
1930 if (r == 0) {
1931 r = -ETIMEDOUT;
1932 goto fail;
1933 }
1934 }
1935
1936 l = read(notify, inotify_buffer, sizeof(inotify_buffer));
1937 if (l < 0) {
80876c20 1938
af6da548 1939 if (errno == EINTR || errno == EAGAIN)
f601daa7
LP
1940 continue;
1941
1942 r = -errno;
1943 goto fail;
1944 }
1945
1946 e = (struct inotify_event*) inotify_buffer;
80876c20 1947
f601daa7
LP
1948 while (l > 0) {
1949 size_t step;
80876c20 1950
f601daa7 1951 if (e->wd != wd || !(e->mask & IN_CLOSE)) {
80876c20 1952 r = -EIO;
f601daa7
LP
1953 goto fail;
1954 }
80876c20 1955
f601daa7
LP
1956 step = sizeof(struct inotify_event) + e->len;
1957 assert(step <= (size_t) l);
80876c20 1958
f601daa7
LP
1959 e = (struct inotify_event*) ((uint8_t*) e + step);
1960 l -= step;
80876c20
LP
1961 }
1962
1963 break;
1964 }
1965
1966 /* We close the tty fd here since if the old session
1967 * ended our handle will be dead. It's important that
1968 * we do this after sleeping, so that we don't enter
1969 * an endless loop. */
03e334a1 1970 safe_close(fd);
80876c20
LP
1971 }
1972
03e334a1 1973 safe_close(notify);
80876c20 1974
512947d4
MS
1975 r = reset_terminal_fd(fd, true);
1976 if (r < 0)
80876c20
LP
1977 log_warning("Failed to reset terminal: %s", strerror(-r));
1978
1979 return fd;
1980
1981fail:
03e334a1
LP
1982 safe_close(fd);
1983 safe_close(notify);
80876c20
LP
1984
1985 return r;
1986}
1987
1988int release_terminal(void) {
e62d8c39 1989 int r = 0;
b92bea5d
ZJS
1990 struct sigaction sa_old, sa_new = {
1991 .sa_handler = SIG_IGN,
1992 .sa_flags = SA_RESTART,
1993 };
7fd1b19b 1994 _cleanup_close_ int fd;
80876c20 1995
e62d8c39
ZJS
1996 fd = open("/dev/tty", O_RDWR|O_NOCTTY|O_NDELAY|O_CLOEXEC);
1997 if (fd < 0)
80876c20
LP
1998 return -errno;
1999
57cd2192
LP
2000 /* Temporarily ignore SIGHUP, so that we don't get SIGHUP'ed
2001 * by our own TIOCNOTTY */
57cd2192
LP
2002 assert_se(sigaction(SIGHUP, &sa_new, &sa_old) == 0);
2003
80876c20
LP
2004 if (ioctl(fd, TIOCNOTTY) < 0)
2005 r = -errno;
2006
57cd2192
LP
2007 assert_se(sigaction(SIGHUP, &sa_old, NULL) == 0);
2008
80876c20
LP
2009 return r;
2010}
2011
9a34ec5f
LP
2012int sigaction_many(const struct sigaction *sa, ...) {
2013 va_list ap;
2014 int r = 0, sig;
2015
2016 va_start(ap, sa);
2017 while ((sig = va_arg(ap, int)) > 0)
2018 if (sigaction(sig, sa, NULL) < 0)
2019 r = -errno;
2020 va_end(ap);
2021
2022 return r;
2023}
2024
2025int ignore_signals(int sig, ...) {
b92bea5d
ZJS
2026 struct sigaction sa = {
2027 .sa_handler = SIG_IGN,
2028 .sa_flags = SA_RESTART,
2029 };
9a34ec5f
LP
2030 va_list ap;
2031 int r = 0;
a337c6fc 2032
9a34ec5f
LP
2033 if (sigaction(sig, &sa, NULL) < 0)
2034 r = -errno;
2035
2036 va_start(ap, sig);
2037 while ((sig = va_arg(ap, int)) > 0)
2038 if (sigaction(sig, &sa, NULL) < 0)
2039 r = -errno;
2040 va_end(ap);
2041
2042 return r;
2043}
2044
2045int default_signals(int sig, ...) {
b92bea5d
ZJS
2046 struct sigaction sa = {
2047 .sa_handler = SIG_DFL,
2048 .sa_flags = SA_RESTART,
2049 };
9a34ec5f
LP
2050 va_list ap;
2051 int r = 0;
2052
9a34ec5f
LP
2053 if (sigaction(sig, &sa, NULL) < 0)
2054 r = -errno;
2055
2056 va_start(ap, sig);
2057 while ((sig = va_arg(ap, int)) > 0)
2058 if (sigaction(sig, &sa, NULL) < 0)
2059 r = -errno;
2060 va_end(ap);
2061
2062 return r;
a337c6fc
LP
2063}
2064
3d94f76c 2065void safe_close_pair(int p[]) {
8d567588
LP
2066 assert(p);
2067
3d94f76c
LP
2068 if (p[0] == p[1]) {
2069 /* Special case pairs which use the same fd in both
2070 * directions... */
2071 p[0] = p[1] = safe_close(p[0]);
2072 return;
8d567588
LP
2073 }
2074
3d94f76c
LP
2075 p[0] = safe_close(p[0]);
2076 p[1] = safe_close(p[1]);
8d567588
LP
2077}
2078
eb22ac37 2079ssize_t loop_read(int fd, void *buf, size_t nbytes, bool do_poll) {
7d5dd5e0 2080 uint8_t *p = buf;
8d567588
LP
2081 ssize_t n = 0;
2082
2083 assert(fd >= 0);
2084 assert(buf);
2085
8d567588
LP
2086 while (nbytes > 0) {
2087 ssize_t k;
2088
7d5dd5e0
LP
2089 k = read(fd, p, nbytes);
2090 if (k < 0 && errno == EINTR)
2091 continue;
8d567588 2092
7d5dd5e0 2093 if (k < 0 && errno == EAGAIN && do_poll) {
8d567588 2094
7d5dd5e0
LP
2095 /* We knowingly ignore any return value here,
2096 * and expect that any error/EOF is reported
2097 * via read() */
8d567588 2098
7d5dd5e0
LP
2099 fd_wait_for_event(fd, POLLIN, (usec_t) -1);
2100 continue;
2101 }
8d567588 2102
7d5dd5e0 2103 if (k <= 0)
8d567588 2104 return n > 0 ? n : (k < 0 ? -errno : 0);
8d567588
LP
2105
2106 p += k;
2107 nbytes -= k;
2108 n += k;
2109 }
2110
2111 return n;
2112}
2113
eb22ac37 2114ssize_t loop_write(int fd, const void *buf, size_t nbytes, bool do_poll) {
7d5dd5e0 2115 const uint8_t *p = buf;
eb22ac37
LP
2116 ssize_t n = 0;
2117
2118 assert(fd >= 0);
2119 assert(buf);
2120
eb22ac37
LP
2121 while (nbytes > 0) {
2122 ssize_t k;
2123
fe652127 2124 k = write(fd, p, nbytes);
7d5dd5e0
LP
2125 if (k < 0 && errno == EINTR)
2126 continue;
eb22ac37 2127
7d5dd5e0 2128 if (k < 0 && errno == EAGAIN && do_poll) {
eb22ac37 2129
7d5dd5e0
LP
2130 /* We knowingly ignore any return value here,
2131 * and expect that any error/EOF is reported
2132 * via write() */
eb22ac37 2133
7d5dd5e0
LP
2134 fd_wait_for_event(fd, POLLOUT, (usec_t) -1);
2135 continue;
2136 }
eb22ac37 2137
7d5dd5e0 2138 if (k <= 0)
eb22ac37 2139 return n > 0 ? n : (k < 0 ? -errno : 0);
eb22ac37
LP
2140
2141 p += k;
2142 nbytes -= k;
2143 n += k;
2144 }
2145
2146 return n;
2147}
2148
5556b5fe
LP
2149int parse_size(const char *t, off_t base, off_t *size) {
2150
2151 /* Soo, sometimes we want to parse IEC binary suffxies, and
2152 * sometimes SI decimal suffixes. This function can parse
2153 * both. Which one is the right way depends on the
2154 * context. Wikipedia suggests that SI is customary for
2155 * hardrware metrics and network speeds, while IEC is
2156 * customary for most data sizes used by software and volatile
2157 * (RAM) memory. Hence be careful which one you pick!
2158 *
2159 * In either case we use just K, M, G as suffix, and not Ki,
2160 * Mi, Gi or so (as IEC would suggest). That's because that's
2161 * frickin' ugly. But this means you really need to make sure
2162 * to document which base you are parsing when you use this
2163 * call. */
2164
2165 struct table {
ab1f0633 2166 const char *suffix;
b32ff512 2167 unsigned long long factor;
5556b5fe
LP
2168 };
2169
2170 static const struct table iec[] = {
32895bb3 2171 { "E", 1024ULL*1024ULL*1024ULL*1024ULL*1024ULL*1024ULL },
840292be
ZJS
2172 { "P", 1024ULL*1024ULL*1024ULL*1024ULL*1024ULL },
2173 { "T", 1024ULL*1024ULL*1024ULL*1024ULL },
2174 { "G", 1024ULL*1024ULL*1024ULL },
2175 { "M", 1024ULL*1024ULL },
2176 { "K", 1024ULL },
2177 { "B", 1 },
ab1f0633
LP
2178 { "", 1 },
2179 };
2180
5556b5fe 2181 static const struct table si[] = {
5556b5fe 2182 { "E", 1000ULL*1000ULL*1000ULL*1000ULL*1000ULL*1000ULL },
840292be
ZJS
2183 { "P", 1000ULL*1000ULL*1000ULL*1000ULL*1000ULL },
2184 { "T", 1000ULL*1000ULL*1000ULL*1000ULL },
2185 { "G", 1000ULL*1000ULL*1000ULL },
2186 { "M", 1000ULL*1000ULL },
2187 { "K", 1000ULL },
2188 { "B", 1 },
5556b5fe
LP
2189 { "", 1 },
2190 };
2191
2192 const struct table *table;
ab1f0633 2193 const char *p;
b32ff512 2194 unsigned long long r = 0;
840292be 2195 unsigned n_entries, start_pos = 0;
ab1f0633
LP
2196
2197 assert(t);
5556b5fe
LP
2198 assert(base == 1000 || base == 1024);
2199 assert(size);
2200
2201 if (base == 1000) {
2202 table = si;
2203 n_entries = ELEMENTSOF(si);
2204 } else {
2205 table = iec;
2206 n_entries = ELEMENTSOF(iec);
2207 }
ab1f0633
LP
2208
2209 p = t;
2210 do {
2211 long long l;
9480794b
ZJS
2212 unsigned long long l2;
2213 double frac = 0;
ab1f0633
LP
2214 char *e;
2215 unsigned i;
2216
2217 errno = 0;
2218 l = strtoll(p, &e, 10);
2219
8333c77e 2220 if (errno > 0)
ab1f0633
LP
2221 return -errno;
2222
2223 if (l < 0)
2224 return -ERANGE;
2225
2226 if (e == p)
2227 return -EINVAL;
2228
9480794b
ZJS
2229 if (*e == '.') {
2230 e++;
2231 if (*e >= '0' && *e <= '9') {
2232 char *e2;
2233
2234 /* strotoull itself would accept space/+/- */
2235 l2 = strtoull(e, &e2, 10);
2236
2237 if (errno == ERANGE)
2238 return -errno;
2239
2240 /* Ignore failure. E.g. 10.M is valid */
2241 frac = l2;
2242 for (; e < e2; e++)
2243 frac /= 10;
2244 }
2245 }
2246
ab1f0633
LP
2247 e += strspn(e, WHITESPACE);
2248
840292be 2249 for (i = start_pos; i < n_entries; i++)
ab1f0633 2250 if (startswith(e, table[i].suffix)) {
b32ff512 2251 unsigned long long tmp;
9480794b 2252 if ((unsigned long long) l + (frac > 0) > ULLONG_MAX / table[i].factor)
b32ff512 2253 return -ERANGE;
9480794b 2254 tmp = l * table[i].factor + (unsigned long long) (frac * table[i].factor);
b32ff512
ZJS
2255 if (tmp > ULLONG_MAX - r)
2256 return -ERANGE;
2257
2258 r += tmp;
2259 if ((unsigned long long) (off_t) r != r)
2260 return -ERANGE;
2261
ab1f0633 2262 p = e + strlen(table[i].suffix);
840292be
ZJS
2263
2264 start_pos = i + 1;
ab1f0633
LP
2265 break;
2266 }
2267
5556b5fe 2268 if (i >= n_entries)
ab1f0633
LP
2269 return -EINVAL;
2270
b32ff512 2271 } while (*p);
ab1f0633 2272
5556b5fe 2273 *size = r;
ab1f0633
LP
2274
2275 return 0;
2276}
2277
843d2643
LP
2278int make_stdio(int fd) {
2279 int r, s, t;
2280
2281 assert(fd >= 0);
2282
73836c5c
LP
2283 r = dup3(fd, STDIN_FILENO, 0);
2284 s = dup3(fd, STDOUT_FILENO, 0);
2285 t = dup3(fd, STDERR_FILENO, 0);
843d2643
LP
2286
2287 if (fd >= 3)
03e334a1 2288 safe_close(fd);
843d2643
LP
2289
2290 if (r < 0 || s < 0 || t < 0)
2291 return -errno;
2292
73836c5c 2293 /* We rely here that the new fd has O_CLOEXEC not set */
7862f62d 2294
843d2643
LP
2295 return 0;
2296}
2297
ade509ce
LP
2298int make_null_stdio(void) {
2299 int null_fd;
2300
cd3bd60a
LP
2301 null_fd = open("/dev/null", O_RDWR|O_NOCTTY);
2302 if (null_fd < 0)
ade509ce
LP
2303 return -errno;
2304
2305 return make_stdio(null_fd);
2306}
2307
8407a5d0
LP
2308bool is_device_path(const char *path) {
2309
2310 /* Returns true on paths that refer to a device, either in
2311 * sysfs or in /dev */
2312
2313 return
2314 path_startswith(path, "/dev/") ||
2315 path_startswith(path, "/sys/");
2316}
2317
01f78473 2318int dir_is_empty(const char *path) {
a05f97b3 2319 _cleanup_closedir_ DIR *d;
01f78473 2320
a05f97b3
LP
2321 d = opendir(path);
2322 if (!d)
01f78473
LP
2323 return -errno;
2324
2325 for (;;) {
7d5e9c0f 2326 struct dirent *de;
01f78473 2327
3fd11280
FW
2328 errno = 0;
2329 de = readdir(d);
2330 if (!de && errno != 0)
2331 return -errno;
01f78473 2332
a05f97b3
LP
2333 if (!de)
2334 return 1;
01f78473 2335
a05f97b3
LP
2336 if (!ignore_file(de->d_name))
2337 return 0;
2338 }
01f78473
LP
2339}
2340
844ec79b
ZJS
2341char* dirname_malloc(const char *path) {
2342 char *d, *dir, *dir2;
2343
2344 d = strdup(path);
2345 if (!d)
2346 return NULL;
2347 dir = dirname(d);
2348 assert(dir);
2349
2350 if (dir != d) {
2351 dir2 = strdup(dir);
2352 free(d);
2353 return dir2;
2354 }
2355
2356 return dir;
2357}
2358
b89446bb 2359int dev_urandom(void *p, size_t n) {
a05f97b3 2360 _cleanup_close_ int fd;
9bf3b535 2361 ssize_t k;
d3782d60 2362
ac0930c8
LP
2363 fd = open("/dev/urandom", O_RDONLY|O_CLOEXEC|O_NOCTTY);
2364 if (fd < 0)
b89446bb 2365 return errno == ENOENT ? -ENOSYS : -errno;
d3782d60 2366
9bf3b535 2367 k = loop_read(fd, p, n, true);
b89446bb
LP
2368 if (k < 0)
2369 return (int) k;
2370 if ((size_t) k != n)
2371 return -EIO;
2372
2373 return 0;
2374}
2375
2376void random_bytes(void *p, size_t n) {
2377 static bool srand_called = false;
2378 uint8_t *q;
2379 int r;
d3782d60 2380
b89446bb
LP
2381 r = dev_urandom(p, n);
2382 if (r >= 0)
2383 return;
d3782d60 2384
b89446bb
LP
2385 /* If some idiot made /dev/urandom unavailable to us, he'll
2386 * get a PRNG instead. */
d3782d60 2387
9bf3b535 2388 if (!srand_called) {
b89446bb 2389 unsigned x = 0;
a3b6fafe 2390
9bf3b535
LP
2391#ifdef HAVE_SYS_AUXV_H
2392 /* The kernel provides us with a bit of entropy in
2393 * auxv, so let's try to make use of that to seed the
2394 * pseudo-random generator. It's better than
2395 * nothing... */
a3b6fafe 2396
9bf3b535
LP
2397 void *auxv;
2398
2399 auxv = (void*) getauxval(AT_RANDOM);
2400 if (auxv)
b89446bb 2401 x ^= *(unsigned*) auxv;
9bf3b535 2402#endif
a3b6fafe 2403
b89446bb
LP
2404 x ^= (unsigned) now(CLOCK_REALTIME);
2405 x ^= (unsigned) gettid();
2406
2407 srand(x);
9bf3b535
LP
2408 srand_called = true;
2409 }
a3b6fafe 2410
9bf3b535
LP
2411 for (q = p; q < (uint8_t*) p + n; q ++)
2412 *q = rand();
a3b6fafe
LP
2413}
2414
5b6319dc
LP
2415void rename_process(const char name[8]) {
2416 assert(name);
2417
5d6b1584
LP
2418 /* This is a like a poor man's setproctitle(). It changes the
2419 * comm field, argv[0], and also the glibc's internally used
2420 * name of the process. For the first one a limit of 16 chars
2421 * applies, to the second one usually one of 10 (i.e. length
2422 * of "/sbin/init"), to the third one one of 7 (i.e. length of
2423 * "systemd"). If you pass a longer string it will be
2424 * truncated */
5b6319dc 2425
5d6b1584 2426 prctl(PR_SET_NAME, name);
5b6319dc
LP
2427
2428 if (program_invocation_name)
2429 strncpy(program_invocation_name, name, strlen(program_invocation_name));
9a0e6896
LP
2430
2431 if (saved_argc > 0) {
2432 int i;
2433
2434 if (saved_argv[0])
2435 strncpy(saved_argv[0], name, strlen(saved_argv[0]));
2436
2437 for (i = 1; i < saved_argc; i++) {
2438 if (!saved_argv[i])
2439 break;
2440
29804cc1 2441 memzero(saved_argv[i], strlen(saved_argv[i]));
9a0e6896
LP
2442 }
2443 }
5b6319dc
LP
2444}
2445
7d793605
LP
2446void sigset_add_many(sigset_t *ss, ...) {
2447 va_list ap;
2448 int sig;
2449
2450 assert(ss);
2451
2452 va_start(ap, ss);
2453 while ((sig = va_arg(ap, int)) > 0)
2454 assert_se(sigaddset(ss, sig) == 0);
2455 va_end(ap);
2456}
2457
856a5a7d
LP
2458int sigprocmask_many(int how, ...) {
2459 va_list ap;
2460 sigset_t ss;
2461 int sig;
2462
2463 assert_se(sigemptyset(&ss) == 0);
2464
2465 va_start(ap, how);
2466 while ((sig = va_arg(ap, int)) > 0)
2467 assert_se(sigaddset(&ss, sig) == 0);
2468 va_end(ap);
2469
2470 if (sigprocmask(how, &ss, NULL) < 0)
2471 return -errno;
2472
2473 return 0;
2474}
2475
ef2f1067
LP
2476char* gethostname_malloc(void) {
2477 struct utsname u;
2478
2479 assert_se(uname(&u) >= 0);
2480
344de609 2481 if (!isempty(u.nodename) && !streq(u.nodename, "(none)"))
ef2f1067
LP
2482 return strdup(u.nodename);
2483
2484 return strdup(u.sysname);
2485}
2486
344de609
LP
2487bool hostname_is_set(void) {
2488 struct utsname u;
2489
2490 assert_se(uname(&u) >= 0);
2491
2492 return !isempty(u.nodename) && !streq(u.nodename, "(none)");
2493}
2494
7c5f152a 2495static char *lookup_uid(uid_t uid) {
ef2f1067 2496 long bufsize;
a05f97b3
LP
2497 char *name;
2498 _cleanup_free_ char *buf = NULL;
ef2f1067 2499 struct passwd pwbuf, *pw = NULL;
ef2f1067
LP
2500
2501 /* Shortcut things to avoid NSS lookups */
2502 if (uid == 0)
2503 return strdup("root");
2504
7c5f152a
LP
2505 bufsize = sysconf(_SC_GETPW_R_SIZE_MAX);
2506 if (bufsize <= 0)
ef2f1067
LP
2507 bufsize = 4096;
2508
7c5f152a
LP
2509 buf = malloc(bufsize);
2510 if (!buf)
ef2f1067
LP
2511 return NULL;
2512
a05f97b3
LP
2513 if (getpwuid_r(uid, &pwbuf, buf, bufsize, &pw) == 0 && pw)
2514 return strdup(pw->pw_name);
ef2f1067 2515
de0671ee 2516 if (asprintf(&name, UID_FMT, uid) < 0)
ef2f1067
LP
2517 return NULL;
2518
2519 return name;
2520}
2521
7c5f152a
LP
2522char* getlogname_malloc(void) {
2523 uid_t uid;
2524 struct stat st;
2525
2526 if (isatty(STDIN_FILENO) && fstat(STDIN_FILENO, &st) >= 0)
2527 uid = st.st_uid;
2528 else
2529 uid = getuid();
2530
2531 return lookup_uid(uid);
2532}
2533
2534char *getusername_malloc(void) {
2535 const char *e;
2536
2537 e = getenv("USER");
2538 if (e)
2539 return strdup(e);
2540
2541 return lookup_uid(getuid());
2542}
2543
fc116c6a
LP
2544int getttyname_malloc(int fd, char **r) {
2545 char path[PATH_MAX], *c;
618e02c7 2546 int k;
8c6db833
LP
2547
2548 assert(r);
ef2f1067 2549
a05f97b3 2550 k = ttyname_r(fd, path, sizeof(path));
27373e44 2551 if (k > 0)
618e02c7 2552 return -k;
ef2f1067
LP
2553
2554 char_array_0(path);
2555
a05f97b3
LP
2556 c = strdup(startswith(path, "/dev/") ? path + 5 : path);
2557 if (!c)
8c6db833
LP
2558 return -ENOMEM;
2559
2560 *r = c;
2561 return 0;
2562}
2563
fc116c6a
LP
2564int getttyname_harder(int fd, char **r) {
2565 int k;
2566 char *s;
2567
a05f97b3
LP
2568 k = getttyname_malloc(fd, &s);
2569 if (k < 0)
fc116c6a
LP
2570 return k;
2571
2572 if (streq(s, "tty")) {
2573 free(s);
4d6d6518 2574 return get_ctty(0, NULL, r);
fc116c6a
LP
2575 }
2576
2577 *r = s;
2578 return 0;
2579}
2580
4d6d6518 2581int get_ctty_devnr(pid_t pid, dev_t *d) {
b4696bce
SP
2582 int r;
2583 _cleanup_free_ char *line = NULL;
2584 const char *p;
fc116c6a 2585 unsigned long ttynr;
fc116c6a 2586
49aa47c7 2587 assert(pid >= 0);
49aa47c7 2588
b4696bce
SP
2589 p = procfs_file_alloca(pid, "stat");
2590 r = read_one_line_file(p, &line);
2591 if (r < 0)
2592 return r;
fc116c6a 2593
4d6d6518
LP
2594 p = strrchr(line, ')');
2595 if (!p)
fc116c6a
LP
2596 return -EIO;
2597
2598 p++;
2599
2600 if (sscanf(p, " "
2601 "%*c " /* state */
2602 "%*d " /* ppid */
2603 "%*d " /* pgrp */
2604 "%*d " /* session */
2605 "%lu ", /* ttynr */
2606 &ttynr) != 1)
2607 return -EIO;
2608
11dc5d2b
LP
2609 if (major(ttynr) == 0 && minor(ttynr) == 0)
2610 return -ENOENT;
2611
0bee65f0
LP
2612 if (d)
2613 *d = (dev_t) ttynr;
2614
fc116c6a
LP
2615 return 0;
2616}
2617
4d6d6518 2618int get_ctty(pid_t pid, dev_t *_devnr, char **r) {
833fce28
LP
2619 char fn[sizeof("/dev/char/")-1 + 2*DECIMAL_STR_MAX(unsigned) + 1 + 1], *b = NULL;
2620 _cleanup_free_ char *s = NULL;
2621 const char *p;
fc116c6a 2622 dev_t devnr;
833fce28 2623 int k;
fc116c6a
LP
2624
2625 assert(r);
2626
4d6d6518
LP
2627 k = get_ctty_devnr(pid, &devnr);
2628 if (k < 0)
fc116c6a
LP
2629 return k;
2630
2631 snprintf(fn, sizeof(fn), "/dev/char/%u:%u", major(devnr), minor(devnr));
fc116c6a 2632
23406ce5
LP
2633 k = readlink_malloc(fn, &s);
2634 if (k < 0) {
fc116c6a
LP
2635
2636 if (k != -ENOENT)
2637 return k;
2638
46824d0e
LP
2639 /* This is an ugly hack */
2640 if (major(devnr) == 136) {
de0671ee 2641 asprintf(&b, "pts/%u", minor(devnr));
833fce28 2642 goto finish;
46824d0e
LP
2643 }
2644
fc116c6a
LP
2645 /* Probably something like the ptys which have no
2646 * symlink in /dev/char. Let's return something
2647 * vaguely useful. */
2648
23406ce5 2649 b = strdup(fn + 5);
833fce28 2650 goto finish;
fc116c6a
LP
2651 }
2652
2653 if (startswith(s, "/dev/"))
2654 p = s + 5;
2655 else if (startswith(s, "../"))
2656 p = s + 3;
2657 else
2658 p = s;
2659
2660 b = strdup(p);
fc116c6a 2661
833fce28 2662finish:
fc116c6a
LP
2663 if (!b)
2664 return -ENOMEM;
2665
2666 *r = b;
46824d0e
LP
2667 if (_devnr)
2668 *_devnr = devnr;
2669
fc116c6a
LP
2670 return 0;
2671}
2672
f56d5db9 2673int rm_rf_children_dangerous(int fd, bool only_dirs, bool honour_sticky, struct stat *root_dev) {
8c6db833
LP
2674 DIR *d;
2675 int ret = 0;
2676
2677 assert(fd >= 0);
2678
2679 /* This returns the first error we run into, but nevertheless
7925c22a 2680 * tries to go on. This closes the passed fd. */
8c6db833 2681
d4d046e3
LP
2682 d = fdopendir(fd);
2683 if (!d) {
03e334a1 2684 safe_close(fd);
4c633005
LP
2685
2686 return errno == ENOENT ? 0 : -errno;
8c6db833
LP
2687 }
2688
2689 for (;;) {
7d5e9c0f 2690 struct dirent *de;
7925c22a
LP
2691 bool is_dir, keep_around;
2692 struct stat st;
8c6db833
LP
2693 int r;
2694
3fd11280
FW
2695 errno = 0;
2696 de = readdir(d);
2697 if (!de && errno != 0) {
2698 if (ret == 0)
2699 ret = -errno;
8c6db833
LP
2700 break;
2701 }
2702
2703 if (!de)
2704 break;
2705
2706 if (streq(de->d_name, ".") || streq(de->d_name, ".."))
2707 continue;
2708
7925c22a
LP
2709 if (de->d_type == DT_UNKNOWN ||
2710 honour_sticky ||
2711 (de->d_type == DT_DIR && root_dev)) {
8c6db833 2712 if (fstatat(fd, de->d_name, &st, AT_SYMLINK_NOFOLLOW) < 0) {
4c633005 2713 if (ret == 0 && errno != ENOENT)
8c6db833
LP
2714 ret = -errno;
2715 continue;
2716 }
2717
2718 is_dir = S_ISDIR(st.st_mode);
7925c22a
LP
2719 keep_around =
2720 honour_sticky &&
2721 (st.st_uid == 0 || st.st_uid == getuid()) &&
2722 (st.st_mode & S_ISVTX);
ad293f5a 2723 } else {
8c6db833 2724 is_dir = de->d_type == DT_DIR;
7925c22a 2725 keep_around = false;
ad293f5a 2726 }
8c6db833
LP
2727
2728 if (is_dir) {
2729 int subdir_fd;
8c6db833 2730
597f43c7 2731 /* if root_dev is set, remove subdirectories only, if device is same as dir */
7925c22a
LP
2732 if (root_dev && st.st_dev != root_dev->st_dev)
2733 continue;
8c6db833 2734
7925c22a
LP
2735 subdir_fd = openat(fd, de->d_name,
2736 O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW|O_NOATIME);
2737 if (subdir_fd < 0) {
2738 if (ret == 0 && errno != ENOENT)
2739 ret = -errno;
2740 continue;
2741 }
2742
b3d28469 2743 r = rm_rf_children_dangerous(subdir_fd, only_dirs, honour_sticky, root_dev);
7925c22a
LP
2744 if (r < 0 && ret == 0)
2745 ret = r;
2746
2747 if (!keep_around)
2748 if (unlinkat(fd, de->d_name, AT_REMOVEDIR) < 0) {
ad293f5a
LP
2749 if (ret == 0 && errno != ENOENT)
2750 ret = -errno;
2751 }
2752
2753 } else if (!only_dirs && !keep_around) {
8c6db833
LP
2754
2755 if (unlinkat(fd, de->d_name, 0) < 0) {
4c633005 2756 if (ret == 0 && errno != ENOENT)
8c6db833
LP
2757 ret = -errno;
2758 }
2759 }
2760 }
2761
2762 closedir(d);
2763
2764 return ret;
2765}
2766
44a6b1b6 2767_pure_ static int is_temporary_fs(struct statfs *s) {
943aad8c 2768 assert(s);
73020ab2
SL
2769
2770 return F_TYPE_EQUAL(s->f_type, TMPFS_MAGIC) ||
2771 F_TYPE_EQUAL(s->f_type, RAMFS_MAGIC);
943aad8c
ZJS
2772}
2773
f56d5db9
LP
2774int rm_rf_children(int fd, bool only_dirs, bool honour_sticky, struct stat *root_dev) {
2775 struct statfs s;
2776
2777 assert(fd >= 0);
2778
2779 if (fstatfs(fd, &s) < 0) {
03e334a1 2780 safe_close(fd);
f56d5db9
LP
2781 return -errno;
2782 }
2783
2784 /* We refuse to clean disk file systems with this call. This
2785 * is extra paranoia just to be sure we never ever remove
2786 * non-state data */
943aad8c 2787 if (!is_temporary_fs(&s)) {
f56d5db9 2788 log_error("Attempted to remove disk file system, and we can't allow that.");
03e334a1 2789 safe_close(fd);
f56d5db9
LP
2790 return -EPERM;
2791 }
2792
2793 return rm_rf_children_dangerous(fd, only_dirs, honour_sticky, root_dev);
2794}
2795
2796static int rm_rf_internal(const char *path, bool only_dirs, bool delete_root, bool honour_sticky, bool dangerous) {
2797 int fd, r;
2798 struct statfs s;
8c6db833
LP
2799
2800 assert(path);
2801
f56d5db9
LP
2802 /* We refuse to clean the root file system with this
2803 * call. This is extra paranoia to never cause a really
2804 * seriously broken system. */
2805 if (path_equal(path, "/")) {
2806 log_error("Attempted to remove entire root file system, and we can't allow that.");
2807 return -EPERM;
2808 }
461b1822 2809
d4d046e3
LP
2810 fd = open(path, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW|O_NOATIME);
2811 if (fd < 0) {
8c6db833
LP
2812
2813 if (errno != ENOTDIR)
2814 return -errno;
2815
f56d5db9
LP
2816 if (!dangerous) {
2817 if (statfs(path, &s) < 0)
2818 return -errno;
2819
943aad8c 2820 if (!is_temporary_fs(&s)) {
f56d5db9
LP
2821 log_error("Attempted to remove disk file system, and we can't allow that.");
2822 return -EPERM;
2823 }
2824 }
2825
8c6db833 2826 if (delete_root && !only_dirs)
d4d046e3 2827 if (unlink(path) < 0 && errno != ENOENT)
8c6db833
LP
2828 return -errno;
2829
2830 return 0;
2831 }
2832
f56d5db9
LP
2833 if (!dangerous) {
2834 if (fstatfs(fd, &s) < 0) {
03e334a1 2835 safe_close(fd);
f56d5db9
LP
2836 return -errno;
2837 }
ad293f5a 2838
943aad8c 2839 if (!is_temporary_fs(&s)) {
f56d5db9 2840 log_error("Attempted to remove disk file system, and we can't allow that.");
03e334a1 2841 safe_close(fd);
f56d5db9
LP
2842 return -EPERM;
2843 }
2844 }
2845
2846 r = rm_rf_children_dangerous(fd, only_dirs, honour_sticky, NULL);
ad293f5a
LP
2847 if (delete_root) {
2848
8d53b453 2849 if (honour_sticky && file_is_priv_sticky(path) > 0)
ad293f5a 2850 return r;
8c6db833 2851
e27796a0 2852 if (rmdir(path) < 0 && errno != ENOENT) {
8c6db833
LP
2853 if (r == 0)
2854 r = -errno;
2855 }
ad293f5a 2856 }
8c6db833
LP
2857
2858 return r;
2859}
2860
f56d5db9
LP
2861int rm_rf(const char *path, bool only_dirs, bool delete_root, bool honour_sticky) {
2862 return rm_rf_internal(path, only_dirs, delete_root, honour_sticky, false);
2863}
2864
2865int rm_rf_dangerous(const char *path, bool only_dirs, bool delete_root, bool honour_sticky) {
2866 return rm_rf_internal(path, only_dirs, delete_root, honour_sticky, true);
2867}
2868
8c6db833
LP
2869int chmod_and_chown(const char *path, mode_t mode, uid_t uid, gid_t gid) {
2870 assert(path);
2871
2872 /* Under the assumption that we are running privileged we
2873 * first change the access mode and only then hand out
2874 * ownership to avoid a window where access is too open. */
2875
8d53b453
LP
2876 if (mode != (mode_t) -1)
2877 if (chmod(path, mode) < 0)
2878 return -errno;
8c6db833 2879
8d53b453
LP
2880 if (uid != (uid_t) -1 || gid != (gid_t) -1)
2881 if (chown(path, uid, gid) < 0)
2882 return -errno;
8c6db833
LP
2883
2884 return 0;
ef2f1067
LP
2885}
2886
f4b47811
LP
2887int fchmod_and_fchown(int fd, mode_t mode, uid_t uid, gid_t gid) {
2888 assert(fd >= 0);
2889
2890 /* Under the assumption that we are running privileged we
2891 * first change the access mode and only then hand out
2892 * ownership to avoid a window where access is too open. */
2893
9588bc32
LP
2894 if (mode != (mode_t) -1)
2895 if (fchmod(fd, mode) < 0)
2896 return -errno;
f4b47811 2897
9588bc32
LP
2898 if (uid != (uid_t) -1 || gid != (gid_t) -1)
2899 if (fchown(fd, uid, gid) < 0)
2900 return -errno;
f4b47811
LP
2901
2902 return 0;
2903}
2904
82c121a4
LP
2905cpu_set_t* cpu_set_malloc(unsigned *ncpus) {
2906 cpu_set_t *r;
2907 unsigned n = 1024;
2908
2909 /* Allocates the cpuset in the right size */
2910
2911 for (;;) {
2912 if (!(r = CPU_ALLOC(n)))
2913 return NULL;
2914
2915 if (sched_getaffinity(0, CPU_ALLOC_SIZE(n), r) >= 0) {
2916 CPU_ZERO_S(CPU_ALLOC_SIZE(n), r);
2917
2918 if (ncpus)
2919 *ncpus = n;
2920
2921 return r;
2922 }
2923
2924 CPU_FREE(r);
2925
2926 if (errno != EINVAL)
2927 return NULL;
2928
2929 n *= 2;
2930 }
2931}
2932
984a2be4 2933int status_vprintf(const char *status, bool ellipse, bool ephemeral, const char *format, va_list ap) {
9ab7a8d2 2934 static const char status_indent[] = " "; /* "[" STATUS "] " */
669bec5d
LP
2935 _cleanup_free_ char *s = NULL;
2936 _cleanup_close_ int fd = -1;
b92bea5d 2937 struct iovec iovec[6] = {};
81beb750 2938 int n = 0;
984a2be4 2939 static bool prev_ephemeral;
9e58ff9c
LP
2940
2941 assert(format);
2942
9ab7a8d2 2943 /* This is independent of logging, as status messages are
9e58ff9c
LP
2944 * optional and go exclusively to the console. */
2945
2946 if (vasprintf(&s, format, ap) < 0)
669bec5d 2947 return log_oom();
9e58ff9c 2948
67e5cc4f 2949 fd = open_terminal("/dev/console", O_WRONLY|O_NOCTTY|O_CLOEXEC);
81beb750 2950 if (fd < 0)
669bec5d 2951 return fd;
9e58ff9c 2952
67e5cc4f 2953 if (ellipse) {
9ab7a8d2
MS
2954 char *e;
2955 size_t emax, sl;
2956 int c;
2957
67e5cc4f
LP
2958 c = fd_columns(fd);
2959 if (c <= 0)
2960 c = 80;
81beb750 2961
669bec5d 2962 sl = status ? sizeof(status_indent)-1 : 0;
9ab7a8d2
MS
2963
2964 emax = c - sl - 1;
2965 if (emax < 3)
2966 emax = 3;
81beb750 2967
67e5cc4f
LP
2968 e = ellipsize(s, emax, 75);
2969 if (e) {
2970 free(s);
2971 s = e;
2972 }
81beb750
LP
2973 }
2974
984a2be4
MS
2975 if (prev_ephemeral)
2976 IOVEC_SET_STRING(iovec[n++], "\r" ANSI_ERASE_TO_END_OF_LINE);
2977 prev_ephemeral = ephemeral;
2978
9ab7a8d2
MS
2979 if (status) {
2980 if (!isempty(status)) {
2981 IOVEC_SET_STRING(iovec[n++], "[");
2982 IOVEC_SET_STRING(iovec[n++], status);
2983 IOVEC_SET_STRING(iovec[n++], "] ");
2984 } else
2985 IOVEC_SET_STRING(iovec[n++], status_indent);
81beb750
LP
2986 }
2987
9ab7a8d2 2988 IOVEC_SET_STRING(iovec[n++], s);
984a2be4
MS
2989 if (!ephemeral)
2990 IOVEC_SET_STRING(iovec[n++], "\n");
81beb750 2991
669bec5d
LP
2992 if (writev(fd, iovec, n) < 0)
2993 return -errno;
9e58ff9c 2994
669bec5d 2995 return 0;
9e58ff9c
LP
2996}
2997
984a2be4 2998int status_printf(const char *status, bool ellipse, bool ephemeral, const char *format, ...) {
c846ff47 2999 va_list ap;
669bec5d 3000 int r;
c846ff47
LP
3001
3002 assert(format);
3003
3004 va_start(ap, format);
984a2be4 3005 r = status_vprintf(status, ellipse, ephemeral, format, ap);
c846ff47 3006 va_end(ap);
669bec5d
LP
3007
3008 return r;
c846ff47
LP
3009}
3010
fab56fc5
LP
3011char *replace_env(const char *format, char **env) {
3012 enum {
3013 WORD,
c24eb49e 3014 CURLY,
fab56fc5
LP
3015 VARIABLE
3016 } state = WORD;
3017
3018 const char *e, *word = format;
3019 char *r = NULL, *k;
3020
3021 assert(format);
3022
3023 for (e = format; *e; e ++) {
3024
3025 switch (state) {
3026
3027 case WORD:
3028 if (*e == '$')
c24eb49e 3029 state = CURLY;
fab56fc5
LP
3030 break;
3031
c24eb49e
LP
3032 case CURLY:
3033 if (*e == '{') {
fab56fc5
LP
3034 if (!(k = strnappend(r, word, e-word-1)))
3035 goto fail;
3036
3037 free(r);
3038 r = k;
3039
3040 word = e-1;
3041 state = VARIABLE;
3042
3043 } else if (*e == '$') {
3044 if (!(k = strnappend(r, word, e-word)))
3045 goto fail;
3046
3047 free(r);
3048 r = k;
3049
3050 word = e+1;
3051 state = WORD;
3052 } else
3053 state = WORD;
3054 break;
3055
3056 case VARIABLE:
c24eb49e 3057 if (*e == '}') {
b95cf362 3058 const char *t;
fab56fc5 3059
4d1a6904 3060 t = strempty(strv_env_get_n(env, word+2, e-word-2));
fab56fc5 3061
4d1a6904
LP
3062 k = strappend(r, t);
3063 if (!k)
b95cf362 3064 goto fail;
fab56fc5 3065
b95cf362
LP
3066 free(r);
3067 r = k;
fab56fc5 3068
b95cf362 3069 word = e+1;
fab56fc5
LP
3070 state = WORD;
3071 }
3072 break;
3073 }
3074 }
3075
3076 if (!(k = strnappend(r, word, e-word)))
3077 goto fail;
3078
3079 free(r);
3080 return k;
3081
3082fail:
3083 free(r);
3084 return NULL;
3085}
3086
3087char **replace_env_argv(char **argv, char **env) {
3088 char **r, **i;
c24eb49e
LP
3089 unsigned k = 0, l = 0;
3090
3091 l = strv_length(argv);
fab56fc5 3092
c24eb49e 3093 if (!(r = new(char*, l+1)))
fab56fc5
LP
3094 return NULL;
3095
3096 STRV_FOREACH(i, argv) {
c24eb49e
LP
3097
3098 /* If $FOO appears as single word, replace it by the split up variable */
b95cf362
LP
3099 if ((*i)[0] == '$' && (*i)[1] != '{') {
3100 char *e;
3101 char **w, **m;
3102 unsigned q;
c24eb49e 3103
4d1a6904
LP
3104 e = strv_env_get(env, *i+1);
3105 if (e) {
c24eb49e
LP
3106
3107 if (!(m = strv_split_quoted(e))) {
3108 r[k] = NULL;
3109 strv_free(r);
3110 return NULL;
3111 }
b95cf362
LP
3112 } else
3113 m = NULL;
c24eb49e 3114
b95cf362
LP
3115 q = strv_length(m);
3116 l = l + q - 1;
c24eb49e 3117
b95cf362
LP
3118 if (!(w = realloc(r, sizeof(char*) * (l+1)))) {
3119 r[k] = NULL;
3120 strv_free(r);
3121 strv_free(m);
3122 return NULL;
3123 }
c24eb49e 3124
b95cf362
LP
3125 r = w;
3126 if (m) {
c24eb49e
LP
3127 memcpy(r + k, m, q * sizeof(char*));
3128 free(m);
c24eb49e 3129 }
b95cf362
LP
3130
3131 k += q;
3132 continue;
c24eb49e
LP
3133 }
3134
3135 /* If ${FOO} appears as part of a word, replace it by the variable as-is */
fab56fc5
LP
3136 if (!(r[k++] = replace_env(*i, env))) {
3137 strv_free(r);
3138 return NULL;
3139 }
3140 }
3141
3142 r[k] = NULL;
3143 return r;
3144}
3145
81beb750 3146int fd_columns(int fd) {
b92bea5d 3147 struct winsize ws = {};
81beb750
LP
3148
3149 if (ioctl(fd, TIOCGWINSZ, &ws) < 0)
3150 return -errno;
3151
3152 if (ws.ws_col <= 0)
3153 return -EIO;
3154
3155 return ws.ws_col;
3156}
3157
28917d7d 3158unsigned columns(void) {
fa776d8e 3159 const char *e;
7009eec2 3160 int c;
fa776d8e 3161
28917d7d
LP
3162 if (_likely_(cached_columns > 0))
3163 return cached_columns;
11f96fac 3164
28917d7d
LP
3165 c = 0;
3166 e = getenv("COLUMNS");
3167 if (e)
7009eec2 3168 safe_atoi(e, &c);
fa776d8e 3169
28917d7d
LP
3170 if (c <= 0)
3171 c = fd_columns(STDOUT_FILENO);
fa776d8e 3172
28917d7d
LP
3173 if (c <= 0)
3174 c = 80;
11f96fac 3175
28917d7d
LP
3176 cached_columns = c;
3177 return c;
11f96fac
ZJS
3178}
3179
8f2d43a0 3180int fd_lines(int fd) {
b92bea5d 3181 struct winsize ws = {};
8f2d43a0
LP
3182
3183 if (ioctl(fd, TIOCGWINSZ, &ws) < 0)
3184 return -errno;
3185
3186 if (ws.ws_row <= 0)
3187 return -EIO;
3188
3189 return ws.ws_row;
3190}
3191
3192unsigned lines(void) {
8f2d43a0 3193 const char *e;
ed757c0c 3194 unsigned l;
8f2d43a0 3195
ed757c0c
LP
3196 if (_likely_(cached_lines > 0))
3197 return cached_lines;
8f2d43a0 3198
ed757c0c 3199 l = 0;
8f2d43a0
LP
3200 e = getenv("LINES");
3201 if (e)
ed757c0c 3202 safe_atou(e, &l);
8f2d43a0 3203
ed757c0c
LP
3204 if (l <= 0)
3205 l = fd_lines(STDOUT_FILENO);
8f2d43a0 3206
ed757c0c
LP
3207 if (l <= 0)
3208 l = 24;
8f2d43a0 3209
ed757c0c
LP
3210 cached_lines = l;
3211 return cached_lines;
3212}
3213
3214/* intended to be used as a SIGWINCH sighandler */
3215void columns_lines_cache_reset(int signum) {
3216 cached_columns = 0;
3217 cached_lines = 0;
3218}
3219
3220bool on_tty(void) {
3221 static int cached_on_tty = -1;
3222
3223 if (_unlikely_(cached_on_tty < 0))
3224 cached_on_tty = isatty(STDOUT_FILENO) > 0;
3225
3226 return cached_on_tty;
8f2d43a0
LP
3227}
3228
9d9951a4
HH
3229int files_same(const char *filea, const char *fileb) {
3230 struct stat a, b;
b4f10a5e 3231
9d9951a4 3232 if (stat(filea, &a) < 0)
b4f10a5e
LP
3233 return -errno;
3234
9d9951a4 3235 if (stat(fileb, &b) < 0)
b4f10a5e
LP
3236 return -errno;
3237
9d9951a4
HH
3238 return a.st_dev == b.st_dev &&
3239 a.st_ino == b.st_ino;
3240}
3241
3242int running_in_chroot(void) {
3243 int ret;
3244
3245 ret = files_same("/proc/1/root", "/");
3246 if (ret < 0)
3247 return ret;
3248
3249 return ret == 0;
b4f10a5e
LP
3250}
3251
f405e86d 3252static char *ascii_ellipsize_mem(const char *s, size_t old_length, size_t new_length, unsigned percent) {
72f59706 3253 size_t x;
8fe914ec
LP
3254 char *r;
3255
3256 assert(s);
3257 assert(percent <= 100);
72f59706 3258 assert(new_length >= 3);
8fe914ec 3259
72f59706
LP
3260 if (old_length <= 3 || old_length <= new_length)
3261 return strndup(s, old_length);
8fe914ec 3262
72f59706
LP
3263 r = new0(char, new_length+1);
3264 if (!r)
a6f0104a 3265 return NULL;
8fe914ec 3266
72f59706 3267 x = (new_length * percent) / 100;
8fe914ec 3268
72f59706
LP
3269 if (x > new_length - 3)
3270 x = new_length - 3;
8fe914ec
LP
3271
3272 memcpy(r, s, x);
3273 r[x] = '.';
3274 r[x+1] = '.';
3275 r[x+2] = '.';
3276 memcpy(r + x + 3,
72f59706
LP
3277 s + old_length - (new_length - x - 3),
3278 new_length - x - 3);
8fe914ec
LP
3279
3280 return r;
3281}
3282
f405e86d
SL
3283char *ellipsize_mem(const char *s, size_t old_length, size_t new_length, unsigned percent) {
3284 size_t x;
3285 char *e;
3286 const char *i, *j;
3287 unsigned k, len, len2;
3288
3289 assert(s);
3290 assert(percent <= 100);
3291 assert(new_length >= 3);
3292
3293 /* if no multibyte characters use ascii_ellipsize_mem for speed */
3294 if (ascii_is_valid(s))
3295 return ascii_ellipsize_mem(s, old_length, new_length, percent);
3296
3297 if (old_length <= 3 || old_length <= new_length)
3298 return strndup(s, old_length);
3299
3300 x = (new_length * percent) / 100;
3301
3302 if (x > new_length - 3)
3303 x = new_length - 3;
3304
3305 k = 0;
3306 for (i = s; k < x && i < s + old_length; i = utf8_next_char(i)) {
3307 int c;
3308
3309 c = utf8_encoded_to_unichar(i);
3310 if (c < 0)
3311 return NULL;
3312 k += unichar_iswide(c) ? 2 : 1;
3313 }
3314
3315 if (k > x) /* last character was wide and went over quota */
3316 x ++;
3317
3318 for (j = s + old_length; k < new_length && j > i; ) {
3319 int c;
3320
3321 j = utf8_prev_char(j);
3322 c = utf8_encoded_to_unichar(j);
3323 if (c < 0)
3324 return NULL;
3325 k += unichar_iswide(c) ? 2 : 1;
3326 }
3327 assert(i <= j);
3328
3329 /* we don't actually need to ellipsize */
3330 if (i == j)
3331 return memdup(s, old_length + 1);
3332
3333 /* make space for ellipsis */
3334 j = utf8_next_char(j);
3335
3336 len = i - s;
3337 len2 = s + old_length - j;
3338 e = new(char, len + 3 + len2 + 1);
3339 if (!e)
3340 return NULL;
3341
3342 /*
3343 printf("old_length=%zu new_length=%zu x=%zu len=%u len2=%u k=%u\n",
3344 old_length, new_length, x, len, len2, k);
3345 */
3346
3347 memcpy(e, s, len);
3348 e[len] = 0xe2; /* tri-dot ellipsis: … */
3349 e[len + 1] = 0x80;
3350 e[len + 2] = 0xa6;
3351
3352 memcpy(e + len + 3, j, len2 + 1);
3353
3354 return e;
3355}
3356
72f59706
LP
3357char *ellipsize(const char *s, size_t length, unsigned percent) {
3358 return ellipsize_mem(s, strlen(s), length, percent);
3359}
3360
c38dfac9 3361int touch_file(const char *path, bool parents, usec_t stamp, uid_t uid, gid_t gid, mode_t mode) {
03e334a1 3362 _cleanup_close_ int fd;
c38dfac9 3363 int r;
f6144808
LP
3364
3365 assert(path);
3366
c38dfac9
KS
3367 if (parents)
3368 mkdir_parents(path, 0755);
73836c5c 3369
c38dfac9 3370 fd = open(path, O_WRONLY|O_CREAT|O_CLOEXEC|O_NOCTTY, mode > 0 ? mode : 0644);
73836c5c 3371 if (fd < 0)
f6144808
LP
3372 return -errno;
3373
c38dfac9
KS
3374 if (mode > 0) {
3375 r = fchmod(fd, mode);
3376 if (r < 0)
3377 return -errno;
3378 }
3379
359efc59 3380 if (uid != (uid_t) -1 || gid != (gid_t) -1) {
c38dfac9
KS
3381 r = fchown(fd, uid, gid);
3382 if (r < 0)
3383 return -errno;
3384 }
3385
359efc59 3386 if (stamp != (usec_t) -1) {
c38dfac9
KS
3387 struct timespec ts[2];
3388
3389 timespec_store(&ts[0], stamp);
359efc59 3390 ts[1] = ts[0];
c38dfac9
KS
3391 r = futimens(fd, ts);
3392 } else
3393 r = futimens(fd, NULL);
3394 if (r < 0)
3395 return -errno;
3396
f6144808
LP
3397 return 0;
3398}
afea26ad 3399
c38dfac9 3400int touch(const char *path) {
359efc59 3401 return touch_file(path, false, (usec_t) -1, (uid_t) -1, (gid_t) -1, 0);
c38dfac9
KS
3402}
3403
97c4a07d 3404char *unquote(const char *s, const char* quotes) {
11ce3427
LP
3405 size_t l;
3406 assert(s);
3407
73836c5c
LP
3408 /* This is rather stupid, simply removes the heading and
3409 * trailing quotes if there is one. Doesn't care about
57f30678
LP
3410 * escaping or anything. We should make this smarter one
3411 * day...*/
73836c5c 3412
31ed59c5
LP
3413 l = strlen(s);
3414 if (l < 2)
11ce3427
LP
3415 return strdup(s);
3416
97c4a07d 3417 if (strchr(quotes, s[0]) && s[l-1] == s[0])
11ce3427
LP
3418 return strndup(s+1, l-2);
3419
3420 return strdup(s);
3421}
3422
5f7c426e 3423char *normalize_env_assignment(const char *s) {
57f30678
LP
3424 _cleanup_free_ char *name = NULL, *value = NULL, *p = NULL;
3425 char *eq, *r;
5f7c426e 3426
57f30678
LP
3427 eq = strchr(s, '=');
3428 if (!eq) {
3429 char *t;
5f7c426e 3430
57f30678
LP
3431 r = strdup(s);
3432 if (!r)
5f7c426e
LP
3433 return NULL;
3434
57f30678
LP
3435 t = strstrip(r);
3436 if (t == r)
3437 return r;
3438
3439 memmove(r, t, strlen(t) + 1);
3440 return r;
5f7c426e
LP
3441 }
3442
57f30678
LP
3443 name = strndup(s, eq - s);
3444 if (!name)
5f7c426e
LP
3445 return NULL;
3446
57f30678
LP
3447 p = strdup(eq + 1);
3448 if (!p)
5f7c426e 3449 return NULL;
5f7c426e
LP
3450
3451 value = unquote(strstrip(p), QUOTES);
57f30678 3452 if (!value)
5f7c426e 3453 return NULL;
5f7c426e 3454
57f30678 3455 if (asprintf(&r, "%s=%s", strstrip(name), value) < 0)
5f7c426e
LP
3456 r = NULL;
3457
5f7c426e
LP
3458 return r;
3459}
3460
8e12a6ae 3461int wait_for_terminate(pid_t pid, siginfo_t *status) {
1968a360
LP
3462 siginfo_t dummy;
3463
2e78aa99 3464 assert(pid >= 1);
1968a360
LP
3465
3466 if (!status)
3467 status = &dummy;
2e78aa99
LP
3468
3469 for (;;) {
8e12a6ae
LP
3470 zero(*status);
3471
3472 if (waitid(P_PID, pid, status, WEXITED) < 0) {
2e78aa99
LP
3473
3474 if (errno == EINTR)
3475 continue;
3476
3477 return -errno;
3478 }
3479
3480 return 0;
3481 }
3482}
3483
97c4a07d
LP
3484int wait_for_terminate_and_warn(const char *name, pid_t pid) {
3485 int r;
3486 siginfo_t status;
3487
3488 assert(name);
3489 assert(pid > 1);
3490
d87be9b0
LP
3491 r = wait_for_terminate(pid, &status);
3492 if (r < 0) {
97c4a07d
LP
3493 log_warning("Failed to wait for %s: %s", name, strerror(-r));
3494 return r;
3495 }
3496
3497 if (status.si_code == CLD_EXITED) {
3498 if (status.si_status != 0) {
3499 log_warning("%s failed with error code %i.", name, status.si_status);
0a27cf3f 3500 return status.si_status;
97c4a07d
LP
3501 }
3502
3503 log_debug("%s succeeded.", name);
3504 return 0;
3505
3506 } else if (status.si_code == CLD_KILLED ||
3507 status.si_code == CLD_DUMPED) {
3508
3509 log_warning("%s terminated by signal %s.", name, signal_to_string(status.si_status));
3510 return -EPROTO;
3511 }
3512
3513 log_warning("%s failed due to unknown reason.", name);
3514 return -EPROTO;
97c4a07d
LP
3515}
3516
919ce0b7 3517noreturn void freeze(void) {
720ce21d
LP
3518
3519 /* Make sure nobody waits for us on a socket anymore */
3520 close_all_fds(NULL, 0);
3521
c29597a1
LP
3522 sync();
3523
3c14d26c
LP
3524 for (;;)
3525 pause();
3526}
3527
00dc5d76
LP
3528bool null_or_empty(struct stat *st) {
3529 assert(st);
3530
3531 if (S_ISREG(st->st_mode) && st->st_size <= 0)
3532 return true;
3533
c8f26f42 3534 if (S_ISCHR(st->st_mode) || S_ISBLK(st->st_mode))
00dc5d76
LP
3535 return true;
3536
3537 return false;
3538}
3539
83096483
LP
3540int null_or_empty_path(const char *fn) {
3541 struct stat st;
3542
3543 assert(fn);
3544
3545 if (stat(fn, &st) < 0)
3546 return -errno;
3547
3548 return null_or_empty(&st);
3549}
3550
a247755d 3551DIR *xopendirat(int fd, const char *name, int flags) {
c4731d11
LP
3552 int nfd;
3553 DIR *d;
3554
dd94c17e
LP
3555 assert(!(flags & O_CREAT));
3556
3557 nfd = openat(fd, name, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|flags, 0);
73836c5c 3558 if (nfd < 0)
c4731d11
LP
3559 return NULL;
3560
73836c5c
LP
3561 d = fdopendir(nfd);
3562 if (!d) {
03e334a1 3563 safe_close(nfd);
c4731d11
LP
3564 return NULL;
3565 }
3566
3567 return d;
3b63d2d3
LP
3568}
3569
8a0867d6
LP
3570int signal_from_string_try_harder(const char *s) {
3571 int signo;
3572 assert(s);
3573
73836c5c
LP
3574 signo = signal_from_string(s);
3575 if (signo <= 0)
8a0867d6
LP
3576 if (startswith(s, "SIG"))
3577 return signal_from_string(s+3);
3578
3579 return signo;
3580}
3581
383182b5 3582static char *tag_to_udev_node(const char *tagvalue, const char *by) {
22f5f628 3583 _cleanup_free_ char *t = NULL, *u = NULL;
22f5f628 3584 size_t enc_len;
e23a0ce8 3585
383182b5 3586 u = unquote(tagvalue, "\"\'");
6db615c1 3587 if (!u)
383182b5 3588 return NULL;
e23a0ce8 3589
1d5989fd 3590 enc_len = strlen(u) * 4 + 1;
22f5f628 3591 t = new(char, enc_len);
6db615c1 3592 if (!t)
383182b5 3593 return NULL;
e23a0ce8 3594
8f6ce71f 3595 if (encode_devnode_name(u, t, enc_len) < 0)
22f5f628 3596 return NULL;
e23a0ce8 3597
6db615c1 3598 return strjoin("/dev/disk/by-", by, "/", t, NULL);
383182b5 3599}
e23a0ce8 3600
383182b5 3601char *fstab_node_to_udev_node(const char *p) {
faa368e3
LP
3602 assert(p);
3603
383182b5
DR
3604 if (startswith(p, "LABEL="))
3605 return tag_to_udev_node(p+6, "label");
e23a0ce8 3606
383182b5
DR
3607 if (startswith(p, "UUID="))
3608 return tag_to_udev_node(p+5, "uuid");
e23a0ce8 3609
84cc2abf
DR
3610 if (startswith(p, "PARTUUID="))
3611 return tag_to_udev_node(p+9, "partuuid");
3612
3613 if (startswith(p, "PARTLABEL="))
3614 return tag_to_udev_node(p+10, "partlabel");
3615
e23a0ce8
LP
3616 return strdup(p);
3617}
3618
f212ac12
LP
3619bool tty_is_vc(const char *tty) {
3620 assert(tty);
3621
3622 if (startswith(tty, "/dev/"))
3623 tty += 5;
3624
98a28fef
LP
3625 return vtnr_from_tty(tty) >= 0;
3626}
3627
d1122ad5
LP
3628bool tty_is_console(const char *tty) {
3629 assert(tty);
3630
3631 if (startswith(tty, "/dev/"))
3632 tty += 5;
3633
3634 return streq(tty, "console");
3635}
3636
98a28fef
LP
3637int vtnr_from_tty(const char *tty) {
3638 int i, r;
3639
3640 assert(tty);
3641
3642 if (startswith(tty, "/dev/"))
3643 tty += 5;
3644
3645 if (!startswith(tty, "tty") )
3646 return -EINVAL;
3647
3648 if (tty[3] < '0' || tty[3] > '9')
3649 return -EINVAL;
3650
3651 r = safe_atoi(tty+3, &i);
3652 if (r < 0)
3653 return r;
3654
3655 if (i < 0 || i > 63)
3656 return -EINVAL;
3657
3658 return i;
f212ac12
LP
3659}
3660
21baf21a
MS
3661char *resolve_dev_console(char **active) {
3662 char *tty;
3663
3664 /* Resolve where /dev/console is pointing to, if /sys is actually ours
3665 * (i.e. not read-only-mounted which is a sign for container setups) */
3666
3667 if (path_is_read_only_fs("/sys") > 0)
3668 return NULL;
3669
3670 if (read_one_line_file("/sys/class/tty/console/active", active) < 0)
3671 return NULL;
3672
3673 /* If multiple log outputs are configured the last one is what
3674 * /dev/console points to */
3675 tty = strrchr(*active, ' ');
3676 if (tty)
3677 tty++;
3678 else
3679 tty = *active;
3680
8aa5429a
OB
3681 if (streq(tty, "tty0")) {
3682 char *tmp;
3683
3684 /* Get the active VC (e.g. tty1) */
3685 if (read_one_line_file("/sys/class/tty/tty0/active", &tmp) >= 0) {
3686 free(*active);
3687 tty = *active = tmp;
3688 }
3689 }
3690
21baf21a
MS
3691 return tty;
3692}
3693
3043935f 3694bool tty_is_vc_resolve(const char *tty) {
9588bc32 3695 _cleanup_free_ char *active = NULL;
3030ccd7 3696
e3aa71c3
LP
3697 assert(tty);
3698
3699 if (startswith(tty, "/dev/"))
3700 tty += 5;
3701
21baf21a
MS
3702 if (streq(tty, "console")) {
3703 tty = resolve_dev_console(&active);
3704 if (!tty)
3705 return false;
3706 }
3030ccd7 3707
9588bc32 3708 return tty_is_vc(tty);
3043935f
LP
3709}
3710
3711const char *default_term_for_tty(const char *tty) {
3712 assert(tty);
3713
acda6a05 3714 return tty_is_vc_resolve(tty) ? "TERM=linux" : "TERM=vt102";
e3aa71c3
LP
3715}
3716
87d2c1ff 3717bool dirent_is_file(const struct dirent *de) {
fb19a739
LP
3718 assert(de);
3719
3720 if (ignore_file(de->d_name))
3721 return false;
3722
3723 if (de->d_type != DT_REG &&
3724 de->d_type != DT_LNK &&
3725 de->d_type != DT_UNKNOWN)
3726 return false;
3727
3728 return true;
3729}
3730
87d2c1ff
LP
3731bool dirent_is_file_with_suffix(const struct dirent *de, const char *suffix) {
3732 assert(de);
3733
a228a22f
LP
3734 if (de->d_type != DT_REG &&
3735 de->d_type != DT_LNK &&
3736 de->d_type != DT_UNKNOWN)
3737 return false;
3738
3739 if (ignore_file_allow_backup(de->d_name))
87d2c1ff
LP
3740 return false;
3741
3742 return endswith(de->d_name, suffix);
3743}
3744
aa62a893
LP
3745void execute_directory(const char *directory, DIR *d, usec_t timeout, char *argv[]) {
3746 pid_t executor_pid;
3747 int r;
83cc030f
LP
3748
3749 assert(directory);
3750
aa62a893
LP
3751 /* Executes all binaries in a directory in parallel and waits
3752 * for them to finish. Optionally a timeout is applied. */
83cc030f 3753
aa62a893
LP
3754 executor_pid = fork();
3755 if (executor_pid < 0) {
3756 log_error("Failed to fork: %m");
3757 return;
83cc030f 3758
aa62a893
LP
3759 } else if (executor_pid == 0) {
3760 _cleanup_hashmap_free_free_ Hashmap *pids = NULL;
3761 _cleanup_closedir_ DIR *_d = NULL;
3762 struct dirent *de;
3763 sigset_t ss;
83cc030f 3764
aa62a893
LP
3765 /* We fork this all off from a child process so that
3766 * we can somewhat cleanly make use of SIGALRM to set
3767 * a time limit */
83cc030f 3768
aa62a893 3769 reset_all_signal_handlers();
83cc030f 3770
aa62a893
LP
3771 assert_se(sigemptyset(&ss) == 0);
3772 assert_se(sigprocmask(SIG_SETMASK, &ss, NULL) == 0);
83cc030f 3773
aa62a893 3774 assert_se(prctl(PR_SET_PDEATHSIG, SIGTERM) == 0);
83cc030f 3775
aa62a893
LP
3776 if (!d) {
3777 d = _d = opendir(directory);
3778 if (!d) {
3779 if (errno == ENOENT)
3780 _exit(EXIT_SUCCESS);
83cc030f 3781
aa62a893
LP
3782 log_error("Failed to enumerate directory %s: %m", directory);
3783 _exit(EXIT_FAILURE);
3784 }
83cc030f
LP
3785 }
3786
aa62a893
LP
3787 pids = hashmap_new(NULL, NULL);
3788 if (!pids) {
3789 log_oom();
3790 _exit(EXIT_FAILURE);
83cc030f
LP
3791 }
3792
aa62a893
LP
3793 FOREACH_DIRENT(de, d, break) {
3794 _cleanup_free_ char *path = NULL;
3795 pid_t pid;
83cc030f 3796
aa62a893
LP
3797 if (!dirent_is_file(de))
3798 continue;
83cc030f 3799
aa62a893
LP
3800 if (asprintf(&path, "%s/%s", directory, de->d_name) < 0) {
3801 log_oom();
3802 _exit(EXIT_FAILURE);
3803 }
83cc030f 3804
aa62a893
LP
3805 pid = fork();
3806 if (pid < 0) {
3807 log_error("Failed to fork: %m");
3808 continue;
3809 } else if (pid == 0) {
3810 char *_argv[2];
83cc030f 3811
aa62a893 3812 assert_se(prctl(PR_SET_PDEATHSIG, SIGTERM) == 0);
83cc030f 3813
aa62a893
LP
3814 if (!argv) {
3815 _argv[0] = path;
3816 _argv[1] = NULL;
3817 argv = _argv;
3818 } else
3819 argv[0] = path;
83cc030f 3820
aa62a893
LP
3821 execv(path, argv);
3822 log_error("Failed to execute %s: %m", path);
3823 _exit(EXIT_FAILURE);
3824 }
83cc030f 3825
83cc030f 3826
aa62a893 3827 log_debug("Spawned %s as " PID_FMT ".", path, pid);
83cc030f 3828
aa62a893
LP
3829 r = hashmap_put(pids, UINT_TO_PTR(pid), path);
3830 if (r < 0) {
3831 log_oom();
3832 _exit(EXIT_FAILURE);
3833 }
3834
3835 path = NULL;
83cc030f
LP
3836 }
3837
aa62a893
LP
3838 /* Abort execution of this process after the
3839 * timout. We simply rely on SIGALRM as default action
3840 * terminating the process, and turn on alarm(). */
3841
3842 if (timeout != (usec_t) -1)
3843 alarm((timeout + USEC_PER_SEC - 1) / USEC_PER_SEC);
3844
3845 while (!hashmap_isempty(pids)) {
3846 _cleanup_free_ char *path = NULL;
3847 pid_t pid;
3848
3849 pid = PTR_TO_UINT(hashmap_first_key(pids));
3850 assert(pid > 0);
83cc030f 3851
aa62a893
LP
3852 path = hashmap_remove(pids, UINT_TO_PTR(pid));
3853 assert(path);
3854
3855 wait_for_terminate_and_warn(path, pid);
83cc030f 3856 }
83cc030f 3857
aa62a893
LP
3858 _exit(EXIT_SUCCESS);
3859 }
83cc030f 3860
aa62a893 3861 wait_for_terminate_and_warn(directory, executor_pid);
83cc030f
LP
3862}
3863
430c18ed
LP
3864int kill_and_sigcont(pid_t pid, int sig) {
3865 int r;
3866
3867 r = kill(pid, sig) < 0 ? -errno : 0;
3868
3869 if (r >= 0)
3870 kill(pid, SIGCONT);
3871
3872 return r;
3873}
3874
05feefe0
LP
3875bool nulstr_contains(const char*nulstr, const char *needle) {
3876 const char *i;
3877
3878 if (!nulstr)
3879 return false;
3880
3881 NULSTR_FOREACH(i, nulstr)
3882 if (streq(i, needle))
3883 return true;
3884
3885 return false;
3886}
3887
6faa1114 3888bool plymouth_running(void) {
9408a2d2 3889 return access("/run/plymouth/pid", F_OK) >= 0;
6faa1114
LP
3890}
3891
9beb3f4d
LP
3892char* strshorten(char *s, size_t l) {
3893 assert(s);
3894
3895 if (l < strlen(s))
3896 s[l] = 0;
3897
3898 return s;
3899}
3900
3901static bool hostname_valid_char(char c) {
3902 return
3903 (c >= 'a' && c <= 'z') ||
3904 (c >= 'A' && c <= 'Z') ||
3905 (c >= '0' && c <= '9') ||
3906 c == '-' ||
3907 c == '_' ||
3908 c == '.';
3909}
3910
3911bool hostname_is_valid(const char *s) {
3912 const char *p;
aa3c5cf8 3913 bool dot;
9beb3f4d
LP
3914
3915 if (isempty(s))
3916 return false;
3917
aa3c5cf8
LP
3918 for (p = s, dot = true; *p; p++) {
3919 if (*p == '.') {
3920 if (dot)
3921 return false;
3922
3923 dot = true;
3924 } else {
3925 if (!hostname_valid_char(*p))
3926 return false;
3927
3928 dot = false;
3929 }
3930 }
3931
3932 if (dot)
3933 return false;
9beb3f4d
LP
3934
3935 if (p-s > HOST_NAME_MAX)
3936 return false;
3937
3938 return true;
3939}
3940
e724b063 3941char* hostname_cleanup(char *s, bool lowercase) {
9beb3f4d 3942 char *p, *d;
cec4ead9
LP
3943 bool dot;
3944
3945 for (p = s, d = s, dot = true; *p; p++) {
3946 if (*p == '.') {
e724b063 3947 if (dot)
cec4ead9 3948 continue;
9beb3f4d 3949
e724b063 3950 *(d++) = '.';
cec4ead9 3951 dot = true;
e724b063
LP
3952 } else if (hostname_valid_char(*p)) {
3953 *(d++) = lowercase ? tolower(*p) : *p;
cec4ead9 3954 dot = false;
e724b063 3955 }
cec4ead9 3956
cec4ead9 3957 }
9beb3f4d 3958
e724b063
LP
3959 if (dot && d > s)
3960 d[-1] = 0;
3961 else
3962 *d = 0;
3963
9beb3f4d 3964 strshorten(s, HOST_NAME_MAX);
cec4ead9 3965
9beb3f4d
LP
3966 return s;
3967}
3968
1325aa42 3969int pipe_eof(int fd) {
b92bea5d
ZJS
3970 struct pollfd pollfd = {
3971 .fd = fd,
3972 .events = POLLIN|POLLHUP,
3973 };
1325aa42 3974
d37a91e8
LP
3975 int r;
3976
1325aa42
LP
3977 r = poll(&pollfd, 1, 0);
3978 if (r < 0)
3979 return -errno;
3980
3981 if (r == 0)
3982 return 0;
3983
3984 return pollfd.revents & POLLHUP;
3985}
3986
8f2d43a0 3987int fd_wait_for_event(int fd, int event, usec_t t) {
968d3d24 3988
b92bea5d
ZJS
3989 struct pollfd pollfd = {
3990 .fd = fd,
3991 .events = event,
3992 };
df50185b 3993
968d3d24
LP
3994 struct timespec ts;
3995 int r;
3996
3997 r = ppoll(&pollfd, 1, t == (usec_t) -1 ? NULL : timespec_store(&ts, t), NULL);
df50185b
LP
3998 if (r < 0)
3999 return -errno;
4000
4001 if (r == 0)
4002 return 0;
4003
4004 return pollfd.revents;
4005}
4006
5a3ab509
LP
4007int fopen_temporary(const char *path, FILE **_f, char **_temp_path) {
4008 FILE *f;
4009 char *t;
5a3ab509
LP
4010 int fd;
4011
4012 assert(path);
4013 assert(_f);
4014 assert(_temp_path);
4015
1b992147 4016 t = strappend(path, ".XXXXXX");
5a3ab509
LP
4017 if (!t)
4018 return -ENOMEM;
4019
2d5bdf5b 4020 fd = mkostemp_safe(t, O_WRONLY|O_CLOEXEC);
5a3ab509
LP
4021 if (fd < 0) {
4022 free(t);
4023 return -errno;
4024 }
4025
4026 f = fdopen(fd, "we");
4027 if (!f) {
4028 unlink(t);
4029 free(t);
4030 return -errno;
4031 }
4032
4033 *_f = f;
4034 *_temp_path = t;
4035
4036 return 0;
4037}
4038
6ea832a2 4039int terminal_vhangup_fd(int fd) {
5a3ab509
LP
4040 assert(fd >= 0);
4041
6ea832a2
LP
4042 if (ioctl(fd, TIOCVHANGUP) < 0)
4043 return -errno;
4044
4045 return 0;
4046}
4047
4048int terminal_vhangup(const char *name) {
03e334a1 4049 _cleanup_close_ int fd;
6ea832a2
LP
4050
4051 fd = open_terminal(name, O_RDWR|O_NOCTTY|O_CLOEXEC);
4052 if (fd < 0)
4053 return fd;
4054
03e334a1 4055 return terminal_vhangup_fd(fd);
6ea832a2
LP
4056}
4057
4058int vt_disallocate(const char *name) {
4059 int fd, r;
4060 unsigned u;
6ea832a2
LP
4061
4062 /* Deallocate the VT if possible. If not possible
4063 * (i.e. because it is the active one), at least clear it
4064 * entirely (including the scrollback buffer) */
4065
b83bc4e9
LP
4066 if (!startswith(name, "/dev/"))
4067 return -EINVAL;
4068
4069 if (!tty_is_vc(name)) {
4070 /* So this is not a VT. I guess we cannot deallocate
4071 * it then. But let's at least clear the screen */
4072
4073 fd = open_terminal(name, O_RDWR|O_NOCTTY|O_CLOEXEC);
4074 if (fd < 0)
4075 return fd;
4076
8585357a
LP
4077 loop_write(fd,
4078 "\033[r" /* clear scrolling region */
4079 "\033[H" /* move home */
4080 "\033[2J", /* clear screen */
4081 10, false);
03e334a1 4082 safe_close(fd);
b83bc4e9
LP
4083
4084 return 0;
4085 }
6ea832a2
LP
4086
4087 if (!startswith(name, "/dev/tty"))
4088 return -EINVAL;
4089
4090 r = safe_atou(name+8, &u);
4091 if (r < 0)
4092 return r;
4093
4094 if (u <= 0)
b83bc4e9 4095 return -EINVAL;
6ea832a2 4096
b83bc4e9 4097 /* Try to deallocate */
6ea832a2
LP
4098 fd = open_terminal("/dev/tty0", O_RDWR|O_NOCTTY|O_CLOEXEC);
4099 if (fd < 0)
4100 return fd;
4101
4102 r = ioctl(fd, VT_DISALLOCATE, u);
03e334a1 4103 safe_close(fd);
6ea832a2 4104
b83bc4e9
LP
4105 if (r >= 0)
4106 return 0;
6ea832a2 4107
b83bc4e9 4108 if (errno != EBUSY)
6ea832a2 4109 return -errno;
6ea832a2 4110
b83bc4e9
LP
4111 /* Couldn't deallocate, so let's clear it fully with
4112 * scrollback */
4113 fd = open_terminal(name, O_RDWR|O_NOCTTY|O_CLOEXEC);
6ea832a2 4114 if (fd < 0)
b83bc4e9 4115 return fd;
6ea832a2 4116
8585357a
LP
4117 loop_write(fd,
4118 "\033[r" /* clear scrolling region */
4119 "\033[H" /* move home */
4120 "\033[3J", /* clear screen including scrollback, requires Linux 2.6.40 */
4121 10, false);
03e334a1 4122 safe_close(fd);
6ea832a2 4123
b83bc4e9 4124 return 0;
6ea832a2
LP
4125}
4126
424a19f8
LP
4127int symlink_atomic(const char *from, const char *to) {
4128 char *x;
4129 _cleanup_free_ char *t;
34ca941c
LP
4130 const char *fn;
4131 size_t k;
9bf3b535 4132 uint64_t u;
34ca941c
LP
4133 unsigned i;
4134 int r;
4135
4136 assert(from);
4137 assert(to);
4138
4139 t = new(char, strlen(to) + 1 + 16 + 1);
4140 if (!t)
4141 return -ENOMEM;
4142
2b6bf07d 4143 fn = basename(to);
34ca941c
LP
4144 k = fn-to;
4145 memcpy(t, to, k);
4146 t[k] = '.';
4147 x = stpcpy(t+k+1, fn);
4148
9bf3b535 4149 u = random_u64();
34ca941c 4150 for (i = 0; i < 16; i++) {
9bf3b535
LP
4151 *(x++) = hexchar(u & 0xF);
4152 u >>= 4;
34ca941c
LP
4153 }
4154
4155 *x = 0;
4156
424a19f8
LP
4157 if (symlink(from, t) < 0)
4158 return -errno;
34ca941c
LP
4159
4160 if (rename(t, to) < 0) {
4161 r = -errno;
4162 unlink(t);
34ca941c
LP
4163 return r;
4164 }
4165
424a19f8 4166 return 0;
34ca941c
LP
4167}
4168
4d6d6518
LP
4169bool display_is_local(const char *display) {
4170 assert(display);
4171
4172 return
4173 display[0] == ':' &&
4174 display[1] >= '0' &&
4175 display[1] <= '9';
4176}
4177
4178int socket_from_display(const char *display, char **path) {
4179 size_t k;
4180 char *f, *c;
4181
4182 assert(display);
4183 assert(path);
4184
4185 if (!display_is_local(display))
4186 return -EINVAL;
4187
4188 k = strspn(display+1, "0123456789");
4189
f8294e41 4190 f = new(char, strlen("/tmp/.X11-unix/X") + k + 1);
4d6d6518
LP
4191 if (!f)
4192 return -ENOMEM;
4193
4194 c = stpcpy(f, "/tmp/.X11-unix/X");
4195 memcpy(c, display+1, k);
4196 c[k] = 0;
4197
4198 *path = f;
4199
4200 return 0;
4201}
4202
d05c5031
LP
4203int get_user_creds(
4204 const char **username,
4205 uid_t *uid, gid_t *gid,
4206 const char **home,
4207 const char **shell) {
4208
1cccf435 4209 struct passwd *p;
ddd88763 4210 uid_t u;
1cccf435
MV
4211
4212 assert(username);
4213 assert(*username);
1cccf435
MV
4214
4215 /* We enforce some special rules for uid=0: in order to avoid
4216 * NSS lookups for root we hardcode its data. */
4217
4218 if (streq(*username, "root") || streq(*username, "0")) {
4219 *username = "root";
4b67834e
LP
4220
4221 if (uid)
4222 *uid = 0;
4223
4224 if (gid)
4225 *gid = 0;
4226
4227 if (home)
4228 *home = "/root";
d05c5031
LP
4229
4230 if (shell)
4231 *shell = "/bin/sh";
4232
1cccf435
MV
4233 return 0;
4234 }
4235
ddd88763 4236 if (parse_uid(*username, &u) >= 0) {
1cccf435 4237 errno = 0;
ddd88763 4238 p = getpwuid(u);
1cccf435
MV
4239
4240 /* If there are multiple users with the same id, make
4241 * sure to leave $USER to the configured value instead
4242 * of the first occurrence in the database. However if
4243 * the uid was configured by a numeric uid, then let's
4244 * pick the real username from /etc/passwd. */
4245 if (p)
4246 *username = p->pw_name;
4247 } else {
4248 errno = 0;
4249 p = getpwnam(*username);
4250 }
4251
4252 if (!p)
8333c77e 4253 return errno > 0 ? -errno : -ESRCH;
1cccf435 4254
4b67834e
LP
4255 if (uid)
4256 *uid = p->pw_uid;
4257
4258 if (gid)
4259 *gid = p->pw_gid;
4260
4261 if (home)
4262 *home = p->pw_dir;
4263
d05c5031
LP
4264 if (shell)
4265 *shell = p->pw_shell;
4266
4b67834e
LP
4267 return 0;
4268}
4269
59164be4
LP
4270char* uid_to_name(uid_t uid) {
4271 struct passwd *p;
4272 char *r;
4273
4274 if (uid == 0)
4275 return strdup("root");
4276
4277 p = getpwuid(uid);
4278 if (p)
4279 return strdup(p->pw_name);
4280
de0671ee 4281 if (asprintf(&r, UID_FMT, uid) < 0)
59164be4
LP
4282 return NULL;
4283
4284 return r;
4285}
4286
4468addc
LP
4287char* gid_to_name(gid_t gid) {
4288 struct group *p;
4289 char *r;
4290
4291 if (gid == 0)
4292 return strdup("root");
4293
4294 p = getgrgid(gid);
4295 if (p)
4296 return strdup(p->gr_name);
4297
de0671ee 4298 if (asprintf(&r, GID_FMT, gid) < 0)
4468addc
LP
4299 return NULL;
4300
4301 return r;
4302}
4303
4b67834e
LP
4304int get_group_creds(const char **groupname, gid_t *gid) {
4305 struct group *g;
4306 gid_t id;
4307
4308 assert(groupname);
4309
4310 /* We enforce some special rules for gid=0: in order to avoid
4311 * NSS lookups for root we hardcode its data. */
4312
4313 if (streq(*groupname, "root") || streq(*groupname, "0")) {
4314 *groupname = "root";
4315
4316 if (gid)
4317 *gid = 0;
4318
4319 return 0;
4320 }
4321
4322 if (parse_gid(*groupname, &id) >= 0) {
4323 errno = 0;
4324 g = getgrgid(id);
4325
4326 if (g)
4327 *groupname = g->gr_name;
4328 } else {
4329 errno = 0;
4330 g = getgrnam(*groupname);
4331 }
4332
4333 if (!g)
8333c77e 4334 return errno > 0 ? -errno : -ESRCH;
4b67834e
LP
4335
4336 if (gid)
4337 *gid = g->gr_gid;
4338
1cccf435
MV
4339 return 0;
4340}
4341
4468addc
LP
4342int in_gid(gid_t gid) {
4343 gid_t *gids;
43673799
LP
4344 int ngroups_max, r, i;
4345
43673799
LP
4346 if (getgid() == gid)
4347 return 1;
4348
4349 if (getegid() == gid)
4350 return 1;
4351
4352 ngroups_max = sysconf(_SC_NGROUPS_MAX);
4353 assert(ngroups_max > 0);
4354
4355 gids = alloca(sizeof(gid_t) * ngroups_max);
4356
4357 r = getgroups(ngroups_max, gids);
4358 if (r < 0)
4359 return -errno;
4360
4361 for (i = 0; i < r; i++)
4362 if (gids[i] == gid)
4363 return 1;
4364
4365 return 0;
4366}
4367
4468addc
LP
4368int in_group(const char *name) {
4369 int r;
4370 gid_t gid;
4371
4372 r = get_group_creds(&name, &gid);
4373 if (r < 0)
4374 return r;
4375
4376 return in_gid(gid);
4377}
4378
8092a428 4379int glob_exists(const char *path) {
7fd1b19b 4380 _cleanup_globfree_ glob_t g = {};
8d98da3f 4381 int k;
8092a428
LP
4382
4383 assert(path);
4384
8092a428
LP
4385 errno = 0;
4386 k = glob(path, GLOB_NOSORT|GLOB_BRACE, NULL, &g);
4387
4388 if (k == GLOB_NOMATCH)
8d98da3f 4389 return 0;
8092a428 4390 else if (k == GLOB_NOSPACE)
8d98da3f 4391 return -ENOMEM;
8092a428 4392 else if (k == 0)
8d98da3f 4393 return !strv_isempty(g.gl_pathv);
8092a428 4394 else
8d98da3f
ZJS
4395 return errno ? -errno : -EIO;
4396}
8092a428 4397
8d98da3f
ZJS
4398int glob_extend(char ***strv, const char *path) {
4399 _cleanup_globfree_ glob_t g = {};
4400 int k;
4401 char **p;
4402
4403 errno = 0;
a8ccacf5 4404 k = glob(path, GLOB_NOSORT|GLOB_BRACE, NULL, &g);
8d98da3f
ZJS
4405
4406 if (k == GLOB_NOMATCH)
4407 return -ENOENT;
4408 else if (k == GLOB_NOSPACE)
4409 return -ENOMEM;
4410 else if (k != 0 || strv_isempty(g.gl_pathv))
4411 return errno ? -errno : -EIO;
4412
4413 STRV_FOREACH(p, g.gl_pathv) {
4414 k = strv_extend(strv, *p);
4415 if (k < 0)
4416 break;
4417 }
4418
4419 return k;
8092a428
LP
4420}
4421
83096483
LP
4422int dirent_ensure_type(DIR *d, struct dirent *de) {
4423 struct stat st;
4424
4425 assert(d);
4426 assert(de);
4427
4428 if (de->d_type != DT_UNKNOWN)
4429 return 0;
4430
4431 if (fstatat(dirfd(d), de->d_name, &st, AT_SYMLINK_NOFOLLOW) < 0)
4432 return -errno;
4433
4434 de->d_type =
4435 S_ISREG(st.st_mode) ? DT_REG :
4436 S_ISDIR(st.st_mode) ? DT_DIR :
4437 S_ISLNK(st.st_mode) ? DT_LNK :
4438 S_ISFIFO(st.st_mode) ? DT_FIFO :
4439 S_ISSOCK(st.st_mode) ? DT_SOCK :
4440 S_ISCHR(st.st_mode) ? DT_CHR :
4441 S_ISBLK(st.st_mode) ? DT_BLK :
4442 DT_UNKNOWN;
4443
4444 return 0;
4445}
4446
4447int in_search_path(const char *path, char **search) {
893fa014
ZJS
4448 char **i;
4449 _cleanup_free_ char *parent = NULL;
83096483
LP
4450 int r;
4451
9eb977db 4452 r = path_get_parent(path, &parent);
83096483
LP
4453 if (r < 0)
4454 return r;
4455
893fa014
ZJS
4456 STRV_FOREACH(i, search)
4457 if (path_equal(parent, *i))
4458 return 1;
83096483 4459
893fa014 4460 return 0;
83096483
LP
4461}
4462
034a2a52 4463int get_files_in_directory(const char *path, char ***list) {
893fa014
ZJS
4464 _cleanup_closedir_ DIR *d = NULL;
4465 size_t bufsize = 0, n = 0;
4466 _cleanup_strv_free_ char **l = NULL;
034a2a52
LP
4467
4468 assert(path);
d60ef526
LP
4469
4470 /* Returns all files in a directory in *list, and the number
4471 * of files as return value. If list is NULL returns only the
893fa014 4472 * number. */
034a2a52
LP
4473
4474 d = opendir(path);
8ea913b2
LP
4475 if (!d)
4476 return -errno;
4477
034a2a52 4478 for (;;) {
7d5e9c0f 4479 struct dirent *de;
034a2a52 4480
3fd11280
FW
4481 errno = 0;
4482 de = readdir(d);
4483 if (!de && errno != 0)
4484 return -errno;
034a2a52
LP
4485 if (!de)
4486 break;
4487
4488 dirent_ensure_type(d, de);
4489
4490 if (!dirent_is_file(de))
4491 continue;
4492
d60ef526 4493 if (list) {
893fa014
ZJS
4494 /* one extra slot is needed for the terminating NULL */
4495 if (!GREEDY_REALLOC(l, bufsize, n + 2))
4496 return -ENOMEM;
034a2a52 4497
893fa014
ZJS
4498 l[n] = strdup(de->d_name);
4499 if (!l[n])
4500 return -ENOMEM;
034a2a52 4501
893fa014 4502 l[++n] = NULL;
d60ef526 4503 } else
893fa014 4504 n++;
034a2a52
LP
4505 }
4506
893fa014
ZJS
4507 if (list) {
4508 *list = l;
4509 l = NULL; /* avoid freeing */
4510 }
034a2a52 4511
893fa014 4512 return n;
034a2a52
LP
4513}
4514
b7def684 4515char *strjoin(const char *x, ...) {
911a4828
LP
4516 va_list ap;
4517 size_t l;
4518 char *r, *p;
4519
4520 va_start(ap, x);
4521
4522 if (x) {
4523 l = strlen(x);
4524
4525 for (;;) {
4526 const char *t;
040f18ea 4527 size_t n;
911a4828
LP
4528
4529 t = va_arg(ap, const char *);
4530 if (!t)
4531 break;
4532
040f18ea 4533 n = strlen(t);
e98055de
LN
4534 if (n > ((size_t) -1) - l) {
4535 va_end(ap);
040f18ea 4536 return NULL;
e98055de 4537 }
040f18ea
LP
4538
4539 l += n;
911a4828
LP
4540 }
4541 } else
4542 l = 0;
4543
4544 va_end(ap);
4545
4546 r = new(char, l+1);
4547 if (!r)
4548 return NULL;
4549
4550 if (x) {
4551 p = stpcpy(r, x);
4552
4553 va_start(ap, x);
4554
4555 for (;;) {
4556 const char *t;
4557
4558 t = va_arg(ap, const char *);
4559 if (!t)
4560 break;
4561
4562 p = stpcpy(p, t);
4563 }
8ea913b2
LP
4564
4565 va_end(ap);
911a4828
LP
4566 } else
4567 r[0] = 0;
4568
4569 return r;
4570}
4571
b636465b 4572bool is_main_thread(void) {
ec202eae 4573 static thread_local int cached = 0;
b636465b
LP
4574
4575 if (_unlikely_(cached == 0))
4576 cached = getpid() == gettid() ? 1 : -1;
4577
4578 return cached > 0;
4579}
4580
94959f0f
LP
4581int block_get_whole_disk(dev_t d, dev_t *ret) {
4582 char *p, *s;
4583 int r;
4584 unsigned n, m;
4585
4586 assert(ret);
4587
4588 /* If it has a queue this is good enough for us */
4589 if (asprintf(&p, "/sys/dev/block/%u:%u/queue", major(d), minor(d)) < 0)
4590 return -ENOMEM;
4591
4592 r = access(p, F_OK);
4593 free(p);
4594
4595 if (r >= 0) {
4596 *ret = d;
4597 return 0;
4598 }
4599
4600 /* If it is a partition find the originating device */
4601 if (asprintf(&p, "/sys/dev/block/%u:%u/partition", major(d), minor(d)) < 0)
4602 return -ENOMEM;
4603
4604 r = access(p, F_OK);
4605 free(p);
4606
4607 if (r < 0)
4608 return -ENOENT;
4609
4610 /* Get parent dev_t */
4611 if (asprintf(&p, "/sys/dev/block/%u:%u/../dev", major(d), minor(d)) < 0)
4612 return -ENOMEM;
4613
4614 r = read_one_line_file(p, &s);
4615 free(p);
4616
4617 if (r < 0)
4618 return r;
4619
4620 r = sscanf(s, "%u:%u", &m, &n);
4621 free(s);
4622
4623 if (r != 2)
4624 return -EINVAL;
4625
4626 /* Only return this if it is really good enough for us. */
4627 if (asprintf(&p, "/sys/dev/block/%u:%u/queue", m, n) < 0)
4628 return -ENOMEM;
4629
4630 r = access(p, F_OK);
4631 free(p);
4632
4633 if (r >= 0) {
4634 *ret = makedev(m, n);
4635 return 0;
4636 }
4637
4638 return -ENOENT;
4639}
4640
8d53b453 4641int file_is_priv_sticky(const char *p) {
ad293f5a
LP
4642 struct stat st;
4643
4644 assert(p);
4645
4646 if (lstat(p, &st) < 0)
4647 return -errno;
4648
4649 return
8d53b453 4650 (st.st_uid == 0 || st.st_uid == getuid()) &&
ad293f5a
LP
4651 (st.st_mode & S_ISVTX);
4652}
94959f0f 4653
f41607a6
LP
4654static const char *const ioprio_class_table[] = {
4655 [IOPRIO_CLASS_NONE] = "none",
4656 [IOPRIO_CLASS_RT] = "realtime",
4657 [IOPRIO_CLASS_BE] = "best-effort",
4658 [IOPRIO_CLASS_IDLE] = "idle"
4659};
4660
f8b69d1d 4661DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(ioprio_class, int, INT_MAX);
f41607a6
LP
4662
4663static const char *const sigchld_code_table[] = {
4664 [CLD_EXITED] = "exited",
4665 [CLD_KILLED] = "killed",
4666 [CLD_DUMPED] = "dumped",
4667 [CLD_TRAPPED] = "trapped",
4668 [CLD_STOPPED] = "stopped",
4669 [CLD_CONTINUED] = "continued",
4670};
4671
4672DEFINE_STRING_TABLE_LOOKUP(sigchld_code, int);
4673
4674static const char *const log_facility_unshifted_table[LOG_NFACILITIES] = {
4675 [LOG_FAC(LOG_KERN)] = "kern",
4676 [LOG_FAC(LOG_USER)] = "user",
4677 [LOG_FAC(LOG_MAIL)] = "mail",
4678 [LOG_FAC(LOG_DAEMON)] = "daemon",
4679 [LOG_FAC(LOG_AUTH)] = "auth",
4680 [LOG_FAC(LOG_SYSLOG)] = "syslog",
4681 [LOG_FAC(LOG_LPR)] = "lpr",
4682 [LOG_FAC(LOG_NEWS)] = "news",
4683 [LOG_FAC(LOG_UUCP)] = "uucp",
4684 [LOG_FAC(LOG_CRON)] = "cron",
4685 [LOG_FAC(LOG_AUTHPRIV)] = "authpriv",
4686 [LOG_FAC(LOG_FTP)] = "ftp",
4687 [LOG_FAC(LOG_LOCAL0)] = "local0",
4688 [LOG_FAC(LOG_LOCAL1)] = "local1",
4689 [LOG_FAC(LOG_LOCAL2)] = "local2",
4690 [LOG_FAC(LOG_LOCAL3)] = "local3",
4691 [LOG_FAC(LOG_LOCAL4)] = "local4",
4692 [LOG_FAC(LOG_LOCAL5)] = "local5",
4693 [LOG_FAC(LOG_LOCAL6)] = "local6",
4694 [LOG_FAC(LOG_LOCAL7)] = "local7"
4695};
4696
f8b69d1d 4697DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(log_facility_unshifted, int, LOG_FAC(~0));
f41607a6
LP
4698
4699static const char *const log_level_table[] = {
4700 [LOG_EMERG] = "emerg",
4701 [LOG_ALERT] = "alert",
4702 [LOG_CRIT] = "crit",
4703 [LOG_ERR] = "err",
4704 [LOG_WARNING] = "warning",
4705 [LOG_NOTICE] = "notice",
4706 [LOG_INFO] = "info",
4707 [LOG_DEBUG] = "debug"
4708};
4709
f8b69d1d 4710DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(log_level, int, LOG_DEBUG);
f41607a6
LP
4711
4712static const char* const sched_policy_table[] = {
4713 [SCHED_OTHER] = "other",
4714 [SCHED_BATCH] = "batch",
4715 [SCHED_IDLE] = "idle",
4716 [SCHED_FIFO] = "fifo",
4717 [SCHED_RR] = "rr"
4718};
4719
f8b69d1d 4720DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(sched_policy, int, INT_MAX);
f41607a6 4721
517d56b1 4722static const char* const rlimit_table[_RLIMIT_MAX] = {
f41607a6
LP
4723 [RLIMIT_CPU] = "LimitCPU",
4724 [RLIMIT_FSIZE] = "LimitFSIZE",
4725 [RLIMIT_DATA] = "LimitDATA",
4726 [RLIMIT_STACK] = "LimitSTACK",
4727 [RLIMIT_CORE] = "LimitCORE",
4728 [RLIMIT_RSS] = "LimitRSS",
4729 [RLIMIT_NOFILE] = "LimitNOFILE",
4730 [RLIMIT_AS] = "LimitAS",
4731 [RLIMIT_NPROC] = "LimitNPROC",
4732 [RLIMIT_MEMLOCK] = "LimitMEMLOCK",
4733 [RLIMIT_LOCKS] = "LimitLOCKS",
4734 [RLIMIT_SIGPENDING] = "LimitSIGPENDING",
4735 [RLIMIT_MSGQUEUE] = "LimitMSGQUEUE",
4736 [RLIMIT_NICE] = "LimitNICE",
4737 [RLIMIT_RTPRIO] = "LimitRTPRIO",
4738 [RLIMIT_RTTIME] = "LimitRTTIME"
4739};
4740
4741DEFINE_STRING_TABLE_LOOKUP(rlimit, int);
4742
4743static const char* const ip_tos_table[] = {
4744 [IPTOS_LOWDELAY] = "low-delay",
4745 [IPTOS_THROUGHPUT] = "throughput",
4746 [IPTOS_RELIABILITY] = "reliability",
4747 [IPTOS_LOWCOST] = "low-cost",
4748};
4749
f8b69d1d 4750DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(ip_tos, int, 0xff);
f41607a6 4751
4e240ab0 4752static const char *const __signal_table[] = {
f41607a6
LP
4753 [SIGHUP] = "HUP",
4754 [SIGINT] = "INT",
4755 [SIGQUIT] = "QUIT",
4756 [SIGILL] = "ILL",
4757 [SIGTRAP] = "TRAP",
4758 [SIGABRT] = "ABRT",
4759 [SIGBUS] = "BUS",
4760 [SIGFPE] = "FPE",
4761 [SIGKILL] = "KILL",
4762 [SIGUSR1] = "USR1",
4763 [SIGSEGV] = "SEGV",
4764 [SIGUSR2] = "USR2",
4765 [SIGPIPE] = "PIPE",
4766 [SIGALRM] = "ALRM",
4767 [SIGTERM] = "TERM",
4768#ifdef SIGSTKFLT
4769 [SIGSTKFLT] = "STKFLT", /* Linux on SPARC doesn't know SIGSTKFLT */
4770#endif
4771 [SIGCHLD] = "CHLD",
4772 [SIGCONT] = "CONT",
4773 [SIGSTOP] = "STOP",
4774 [SIGTSTP] = "TSTP",
4775 [SIGTTIN] = "TTIN",
4776 [SIGTTOU] = "TTOU",
4777 [SIGURG] = "URG",
4778 [SIGXCPU] = "XCPU",
4779 [SIGXFSZ] = "XFSZ",
4780 [SIGVTALRM] = "VTALRM",
4781 [SIGPROF] = "PROF",
4782 [SIGWINCH] = "WINCH",
4783 [SIGIO] = "IO",
4784 [SIGPWR] = "PWR",
4785 [SIGSYS] = "SYS"
4786};
4787
4e240ab0
MS
4788DEFINE_PRIVATE_STRING_TABLE_LOOKUP(__signal, int);
4789
4790const char *signal_to_string(int signo) {
ec202eae 4791 static thread_local char buf[sizeof("RTMIN+")-1 + DECIMAL_STR_MAX(int) + 1];
4e240ab0
MS
4792 const char *name;
4793
4794 name = __signal_to_string(signo);
4795 if (name)
4796 return name;
4797
4798 if (signo >= SIGRTMIN && signo <= SIGRTMAX)
fa70beaa 4799 snprintf(buf, sizeof(buf), "RTMIN+%d", signo - SIGRTMIN);
4e240ab0 4800 else
fa70beaa
LP
4801 snprintf(buf, sizeof(buf), "%d", signo);
4802
4e240ab0
MS
4803 return buf;
4804}
4805
4806int signal_from_string(const char *s) {
4807 int signo;
4808 int offset = 0;
4809 unsigned u;
4810
040f18ea 4811 signo = __signal_from_string(s);
4e240ab0
MS
4812 if (signo > 0)
4813 return signo;
4814
4815 if (startswith(s, "RTMIN+")) {
4816 s += 6;
4817 offset = SIGRTMIN;
4818 }
4819 if (safe_atou(s, &u) >= 0) {
4820 signo = (int) u + offset;
4821 if (signo > 0 && signo < _NSIG)
4822 return signo;
4823 }
4824 return -1;
4825}
65457142
FC
4826
4827bool kexec_loaded(void) {
4828 bool loaded = false;
4829 char *s;
4830
4831 if (read_one_line_file("/sys/kernel/kexec_loaded", &s) >= 0) {
4832 if (s[0] == '1')
4833 loaded = true;
4834 free(s);
4835 }
4836 return loaded;
4837}
fb9de93d
LP
4838
4839int strdup_or_null(const char *a, char **b) {
4840 char *c;
4841
4842 assert(b);
4843
4844 if (!a) {
4845 *b = NULL;
4846 return 0;
4847 }
4848
4849 c = strdup(a);
4850 if (!c)
4851 return -ENOMEM;
4852
4853 *b = c;
4854 return 0;
4855}
64685e0c 4856
87d2c1ff
LP
4857int prot_from_flags(int flags) {
4858
4859 switch (flags & O_ACCMODE) {
4860
4861 case O_RDONLY:
4862 return PROT_READ;
4863
4864 case O_WRONLY:
4865 return PROT_WRITE;
4866
4867 case O_RDWR:
4868 return PROT_READ|PROT_WRITE;
4869
4870 default:
4871 return -EINVAL;
4872 }
7c99e0c1 4873}
689b9a22 4874
babfc091 4875char *format_bytes(char *buf, size_t l, off_t t) {
c0f99c21 4876 unsigned i;
babfc091
LP
4877
4878 static const struct {
4879 const char *suffix;
4880 off_t factor;
4881 } table[] = {
32895bb3
LP
4882 { "E", 1024ULL*1024ULL*1024ULL*1024ULL*1024ULL*1024ULL },
4883 { "P", 1024ULL*1024ULL*1024ULL*1024ULL*1024ULL },
babfc091
LP
4884 { "T", 1024ULL*1024ULL*1024ULL*1024ULL },
4885 { "G", 1024ULL*1024ULL*1024ULL },
4886 { "M", 1024ULL*1024ULL },
4887 { "K", 1024ULL },
4888 };
4889
4890 for (i = 0; i < ELEMENTSOF(table); i++) {
4891
4892 if (t >= table[i].factor) {
4893 snprintf(buf, l,
4894 "%llu.%llu%s",
4895 (unsigned long long) (t / table[i].factor),
4896 (unsigned long long) (((t*10ULL) / table[i].factor) % 10ULL),
4897 table[i].suffix);
4898
4899 goto finish;
4900 }
4901 }
4902
4903 snprintf(buf, l, "%lluB", (unsigned long long) t);
4904
4905finish:
4906 buf[l-1] = 0;
4907 return buf;
4908
4909}
55d7bfc1
LP
4910
4911void* memdup(const void *p, size_t l) {
4912 void *r;
4913
4914 assert(p);
4915
4916 r = malloc(l);
4917 if (!r)
4918 return NULL;
4919
4920 memcpy(r, p, l);
4921 return r;
4922}
bb99a35a
LP
4923
4924int fd_inc_sndbuf(int fd, size_t n) {
4925 int r, value;
4926 socklen_t l = sizeof(value);
4927
4928 r = getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &value, &l);
92d75ca4 4929 if (r >= 0 && l == sizeof(value) && (size_t) value >= n*2)
bb99a35a
LP
4930 return 0;
4931
92d75ca4
LP
4932 /* If we have the privileges we will ignore the kernel limit. */
4933
bb99a35a 4934 value = (int) n;
92d75ca4
LP
4935 if (setsockopt(fd, SOL_SOCKET, SO_SNDBUFFORCE, &value, sizeof(value)) < 0)
4936 if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &value, sizeof(value)) < 0)
4937 return -errno;
bb99a35a
LP
4938
4939 return 1;
4940}
4941
4942int fd_inc_rcvbuf(int fd, size_t n) {
4943 int r, value;
4944 socklen_t l = sizeof(value);
4945
4946 r = getsockopt(fd, SOL_SOCKET, SO_RCVBUF, &value, &l);
92d75ca4 4947 if (r >= 0 && l == sizeof(value) && (size_t) value >= n*2)
bb99a35a
LP
4948 return 0;
4949
92d75ca4 4950 /* If we have the privileges we will ignore the kernel limit. */
bb99a35a 4951
92d75ca4
LP
4952 value = (int) n;
4953 if (setsockopt(fd, SOL_SOCKET, SO_RCVBUFFORCE, &value, sizeof(value)) < 0)
4954 if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &value, sizeof(value)) < 0)
4955 return -errno;
bb99a35a
LP
4956 return 1;
4957}
6bb92a16 4958
9bdc770c 4959int fork_agent(pid_t *pid, const int except[], unsigned n_except, const char *path, ...) {
6bb92a16
LP
4960 pid_t parent_pid, agent_pid;
4961 int fd;
4962 bool stdout_is_tty, stderr_is_tty;
4963 unsigned n, i;
4964 va_list ap;
4965 char **l;
4966
4967 assert(pid);
4968 assert(path);
4969
4970 parent_pid = getpid();
4971
4972 /* Spawns a temporary TTY agent, making sure it goes away when
4973 * we go away */
4974
4975 agent_pid = fork();
4976 if (agent_pid < 0)
4977 return -errno;
4978
4979 if (agent_pid != 0) {
4980 *pid = agent_pid;
4981 return 0;
4982 }
4983
4984 /* In the child:
4985 *
4986 * Make sure the agent goes away when the parent dies */
4987 if (prctl(PR_SET_PDEATHSIG, SIGTERM) < 0)
4988 _exit(EXIT_FAILURE);
4989
4990 /* Check whether our parent died before we were able
4991 * to set the death signal */
4992 if (getppid() != parent_pid)
4993 _exit(EXIT_SUCCESS);
4994
4995 /* Don't leak fds to the agent */
9bdc770c 4996 close_all_fds(except, n_except);
6bb92a16
LP
4997
4998 stdout_is_tty = isatty(STDOUT_FILENO);
4999 stderr_is_tty = isatty(STDERR_FILENO);
5000
5001 if (!stdout_is_tty || !stderr_is_tty) {
5002 /* Detach from stdout/stderr. and reopen
5003 * /dev/tty for them. This is important to
5004 * ensure that when systemctl is started via
5005 * popen() or a similar call that expects to
5006 * read EOF we actually do generate EOF and
5007 * not delay this indefinitely by because we
5008 * keep an unused copy of stdin around. */
5009 fd = open("/dev/tty", O_WRONLY);
5010 if (fd < 0) {
5011 log_error("Failed to open /dev/tty: %m");
5012 _exit(EXIT_FAILURE);
5013 }
5014
5015 if (!stdout_is_tty)
5016 dup2(fd, STDOUT_FILENO);
5017
5018 if (!stderr_is_tty)
5019 dup2(fd, STDERR_FILENO);
5020
5021 if (fd > 2)
5022 close(fd);
5023 }
5024
5025 /* Count arguments */
5026 va_start(ap, path);
5027 for (n = 0; va_arg(ap, char*); n++)
5028 ;
5029 va_end(ap);
5030
5031 /* Allocate strv */
5032 l = alloca(sizeof(char *) * (n + 1));
5033
5034 /* Fill in arguments */
5035 va_start(ap, path);
5036 for (i = 0; i <= n; i++)
5037 l[i] = va_arg(ap, char*);
5038 va_end(ap);
5039
5040 execv(path, l);
5041 _exit(EXIT_FAILURE);
5042}
68faf98c
LP
5043
5044int setrlimit_closest(int resource, const struct rlimit *rlim) {
5045 struct rlimit highest, fixed;
5046
5047 assert(rlim);
5048
5049 if (setrlimit(resource, rlim) >= 0)
5050 return 0;
5051
5052 if (errno != EPERM)
5053 return -errno;
5054
5055 /* So we failed to set the desired setrlimit, then let's try
5056 * to get as close as we can */
5057 assert_se(getrlimit(resource, &highest) == 0);
5058
5059 fixed.rlim_cur = MIN(rlim->rlim_cur, highest.rlim_max);
5060 fixed.rlim_max = MIN(rlim->rlim_max, highest.rlim_max);
5061
5062 if (setrlimit(resource, &fixed) < 0)
5063 return -errno;
5064
5065 return 0;
5066}
3d9a4122 5067
ab94af92 5068int getenv_for_pid(pid_t pid, const char *field, char **_value) {
49aa47c7
LP
5069 _cleanup_fclose_ FILE *f = NULL;
5070 char *value = NULL;
ab94af92 5071 int r;
ab94af92
LP
5072 bool done = false;
5073 size_t l;
49aa47c7 5074 const char *path;
ab94af92 5075
49aa47c7 5076 assert(pid >= 0);
ab94af92
LP
5077 assert(field);
5078 assert(_value);
5079
b68fa010 5080 path = procfs_file_alloca(pid, "environ");
ab94af92
LP
5081
5082 f = fopen(path, "re");
5083 if (!f)
5084 return -errno;
5085
5086 l = strlen(field);
5087 r = 0;
5088
5089 do {
5090 char line[LINE_MAX];
5091 unsigned i;
5092
5093 for (i = 0; i < sizeof(line)-1; i++) {
5094 int c;
5095
5096 c = getc(f);
5097 if (_unlikely_(c == EOF)) {
5098 done = true;
5099 break;
5100 } else if (c == 0)
5101 break;
5102
5103 line[i] = c;
5104 }
5105 line[i] = 0;
5106
5107 if (memcmp(line, field, l) == 0 && line[l] == '=') {
5108 value = strdup(line + l + 1);
49aa47c7
LP
5109 if (!value)
5110 return -ENOMEM;
ab94af92
LP
5111
5112 r = 1;
5113 break;
5114 }
5115
5116 } while (!done);
5117
49aa47c7 5118 *_value = value;
ab94af92
LP
5119 return r;
5120}
d889a206 5121
49dbfa7b
LP
5122bool is_valid_documentation_url(const char *url) {
5123 assert(url);
5124
5125 if (startswith(url, "http://") && url[7])
5126 return true;
5127
5128 if (startswith(url, "https://") && url[8])
5129 return true;
5130
5131 if (startswith(url, "file:") && url[5])
5132 return true;
5133
5134 if (startswith(url, "info:") && url[5])
5135 return true;
5136
5137 if (startswith(url, "man:") && url[4])
5138 return true;
5139
5140 return false;
5141}
9be346c9
HH
5142
5143bool in_initrd(void) {
73020ab2 5144 static int saved = -1;
825c6fe5 5145 struct statfs s;
8f33b5b8 5146
825c6fe5
LP
5147 if (saved >= 0)
5148 return saved;
5149
5150 /* We make two checks here:
5151 *
5152 * 1. the flag file /etc/initrd-release must exist
5153 * 2. the root file system must be a memory file system
5154 *
5155 * The second check is extra paranoia, since misdetecting an
5156 * initrd can have bad bad consequences due the initrd
5157 * emptying when transititioning to the main systemd.
5158 */
5159
5160 saved = access("/etc/initrd-release", F_OK) >= 0 &&
5161 statfs("/", &s) >= 0 &&
943aad8c 5162 is_temporary_fs(&s);
9be346c9 5163
8f33b5b8 5164 return saved;
9be346c9 5165}
069cfc85
LP
5166
5167void warn_melody(void) {
e67f47e5 5168 _cleanup_close_ int fd = -1;
069cfc85
LP
5169
5170 fd = open("/dev/console", O_WRONLY|O_CLOEXEC|O_NOCTTY);
5171 if (fd < 0)
5172 return;
5173
040f18ea 5174 /* Yeah, this is synchronous. Kinda sucks. But well... */
069cfc85
LP
5175
5176 ioctl(fd, KIOCSOUND, (int)(1193180/440));
5177 usleep(125*USEC_PER_MSEC);
5178
5179 ioctl(fd, KIOCSOUND, (int)(1193180/220));
5180 usleep(125*USEC_PER_MSEC);
5181
5182 ioctl(fd, KIOCSOUND, (int)(1193180/220));
5183 usleep(125*USEC_PER_MSEC);
5184
5185 ioctl(fd, KIOCSOUND, 0);
069cfc85 5186}
cd3bd60a
LP
5187
5188int make_console_stdio(void) {
5189 int fd, r;
5190
5191 /* Make /dev/console the controlling terminal and stdin/stdout/stderr */
5192
5193 fd = acquire_terminal("/dev/console", false, true, true, (usec_t) -1);
5194 if (fd < 0) {
5195 log_error("Failed to acquire terminal: %s", strerror(-fd));
5196 return fd;
5197 }
5198
5199 r = make_stdio(fd);
5200 if (r < 0) {
5201 log_error("Failed to duplicate terminal fd: %s", strerror(-r));
5202 return r;
5203 }
5204
5205 return 0;
5206}
7c5f152a
LP
5207
5208int get_home_dir(char **_h) {
2cfbd749 5209 struct passwd *p;
7c5f152a 5210 const char *e;
2cfbd749 5211 char *h;
7c5f152a 5212 uid_t u;
7c5f152a
LP
5213
5214 assert(_h);
5215
5216 /* Take the user specified one */
5217 e = getenv("HOME");
5218 if (e) {
5219 h = strdup(e);
5220 if (!h)
5221 return -ENOMEM;
5222
5223 *_h = h;
5224 return 0;
5225 }
5226
5227 /* Hardcode home directory for root to avoid NSS */
5228 u = getuid();
5229 if (u == 0) {
5230 h = strdup("/root");
5231 if (!h)
5232 return -ENOMEM;
5233
5234 *_h = h;
5235 return 0;
5236 }
5237
5238 /* Check the database... */
5239 errno = 0;
5240 p = getpwuid(u);
5241 if (!p)
bcb161b0 5242 return errno > 0 ? -errno : -ESRCH;
7c5f152a
LP
5243
5244 if (!path_is_absolute(p->pw_dir))
5245 return -EINVAL;
5246
5247 h = strdup(p->pw_dir);
5248 if (!h)
5249 return -ENOMEM;
5250
5251 *_h = h;
5252 return 0;
5253}
5254
2cfbd749
LP
5255int get_shell(char **_s) {
5256 struct passwd *p;
5257 const char *e;
5258 char *s;
5259 uid_t u;
5260
5261 assert(_s);
5262
5263 /* Take the user specified one */
5264 e = getenv("SHELL");
5265 if (e) {
5266 s = strdup(e);
5267 if (!s)
5268 return -ENOMEM;
5269
5270 *_s = s;
5271 return 0;
5272 }
5273
5274 /* Hardcode home directory for root to avoid NSS */
5275 u = getuid();
5276 if (u == 0) {
5277 s = strdup("/bin/sh");
5278 if (!s)
5279 return -ENOMEM;
5280
5281 *_s = s;
5282 return 0;
5283 }
5284
5285 /* Check the database... */
5286 errno = 0;
5287 p = getpwuid(u);
5288 if (!p)
5289 return errno > 0 ? -errno : -ESRCH;
5290
5291 if (!path_is_absolute(p->pw_shell))
5292 return -EINVAL;
5293
5294 s = strdup(p->pw_shell);
5295 if (!s)
5296 return -ENOMEM;
5297
5298 *_s = s;
5299 return 0;
5300}
5301
0b507b17
LP
5302bool filename_is_safe(const char *p) {
5303
5304 if (isempty(p))
5305 return false;
5306
5307 if (strchr(p, '/'))
5308 return false;
5309
5310 if (streq(p, "."))
5311 return false;
5312
5313 if (streq(p, ".."))
5314 return false;
5315
5316 if (strlen(p) > FILENAME_MAX)
5317 return false;
5318
5319 return true;
5320}
5321
5322bool string_is_safe(const char *p) {
5323 const char *t;
5324
5325 assert(p);
5326
5327 for (t = p; *t; t++) {
01539d6e 5328 if (*t > 0 && *t < ' ')
0b507b17
LP
5329 return false;
5330
011afa76 5331 if (strchr("\\\"\'", *t))
0b507b17
LP
5332 return false;
5333 }
5334
5335 return true;
5336}
cfbc22ab 5337
ac4c8d6d
ZJS
5338/**
5339 * Check if a string contains control characters.
5340 * Spaces and tabs are not considered control characters.
5341 */
4d1a6904
LP
5342bool string_has_cc(const char *p) {
5343 const char *t;
5344
5345 assert(p);
5346
5347 for (t = p; *t; t++)
da2620a5 5348 if (*t > 0 && *t < ' ' && *t != '\t')
4d1a6904
LP
5349 return true;
5350
5351 return false;
5352}
5353
e884315e
LP
5354bool path_is_safe(const char *p) {
5355
5356 if (isempty(p))
5357 return false;
5358
5359 if (streq(p, "..") || startswith(p, "../") || endswith(p, "/..") || strstr(p, "/../"))
5360 return false;
5361
5362 if (strlen(p) > PATH_MAX)
5363 return false;
5364
5365 /* The following two checks are not really dangerous, but hey, they still are confusing */
5366 if (streq(p, ".") || startswith(p, "./") || endswith(p, "/.") || strstr(p, "/./"))
5367 return false;
5368
5369 if (strstr(p, "//"))
5370 return false;
5371
5372 return true;
5373}
5374
a9e12476
KS
5375/* hey glibc, APIs with callbacks without a user pointer are so useless */
5376void *xbsearch_r(const void *key, const void *base, size_t nmemb, size_t size,
1c574591 5377 int (*compar) (const void *, const void *, void *), void *arg) {
a9e12476
KS
5378 size_t l, u, idx;
5379 const void *p;
5380 int comparison;
5381
5382 l = 0;
5383 u = nmemb;
5384 while (l < u) {
5385 idx = (l + u) / 2;
5386 p = (void *)(((const char *) base) + (idx * size));
5387 comparison = compar(key, p, arg);
5388 if (comparison < 0)
5389 u = idx;
5390 else if (comparison > 0)
5391 l = idx + 1;
5392 else
5393 return (void *)p;
5394 }
5395 return NULL;
5396}
09017585
MS
5397
5398bool is_locale_utf8(void) {
5399 const char *set;
5400 static int cached_answer = -1;
5401
5402 if (cached_answer >= 0)
5403 goto out;
5404
5405 if (!setlocale(LC_ALL, "")) {
5406 cached_answer = true;
5407 goto out;
5408 }
5409
5410 set = nl_langinfo(CODESET);
5411 if (!set) {
5412 cached_answer = true;
5413 goto out;
5414 }
5415
f168c273 5416 if (streq(set, "UTF-8")) {
fee79e01
HH
5417 cached_answer = true;
5418 goto out;
5419 }
5420
6cf2f1d9
HH
5421 /* For LC_CTYPE=="C" return true, because CTYPE is effectly
5422 * unset and everything can do to UTF-8 nowadays. */
fee79e01
HH
5423 set = setlocale(LC_CTYPE, NULL);
5424 if (!set) {
5425 cached_answer = true;
5426 goto out;
5427 }
5428
6cf2f1d9
HH
5429 /* Check result, but ignore the result if C was set
5430 * explicitly. */
5431 cached_answer =
5432 streq(set, "C") &&
5433 !getenv("LC_ALL") &&
5434 !getenv("LC_CTYPE") &&
5435 !getenv("LANG");
fee79e01 5436
09017585 5437out:
6cf2f1d9 5438 return (bool) cached_answer;
09017585 5439}
c339d977
MS
5440
5441const char *draw_special_char(DrawSpecialChar ch) {
5442 static const char *draw_table[2][_DRAW_SPECIAL_CHAR_MAX] = {
6b01f1d3 5443
c339d977 5444 /* UTF-8 */ {
6b01f1d3 5445 [DRAW_TREE_VERTICAL] = "\342\224\202 ", /* │ */
45a5ff0d
MS
5446 [DRAW_TREE_BRANCH] = "\342\224\234\342\224\200", /* ├─ */
5447 [DRAW_TREE_RIGHT] = "\342\224\224\342\224\200", /* └─ */
55c0b89c 5448 [DRAW_TREE_SPACE] = " ", /* */
6b01f1d3
LP
5449 [DRAW_TRIANGULAR_BULLET] = "\342\200\243", /* ‣ */
5450 [DRAW_BLACK_CIRCLE] = "\342\227\217", /* ● */
5451 [DRAW_ARROW] = "\342\206\222", /* → */
13f8b8cb 5452 [DRAW_DASH] = "\342\200\223", /* – */
c339d977 5453 },
6b01f1d3 5454
c339d977 5455 /* ASCII fallback */ {
6b01f1d3 5456 [DRAW_TREE_VERTICAL] = "| ",
45a5ff0d
MS
5457 [DRAW_TREE_BRANCH] = "|-",
5458 [DRAW_TREE_RIGHT] = "`-",
55c0b89c 5459 [DRAW_TREE_SPACE] = " ",
6b01f1d3
LP
5460 [DRAW_TRIANGULAR_BULLET] = ">",
5461 [DRAW_BLACK_CIRCLE] = "*",
5462 [DRAW_ARROW] = "->",
13f8b8cb 5463 [DRAW_DASH] = "-",
c339d977
MS
5464 }
5465 };
5466
5467 return draw_table[!is_locale_utf8()][ch];
5468}
409bc9c3
LP
5469
5470char *strreplace(const char *text, const char *old_string, const char *new_string) {
5471 const char *f;
5472 char *t, *r;
5473 size_t l, old_len, new_len;
5474
5475 assert(text);
5476 assert(old_string);
5477 assert(new_string);
5478
5479 old_len = strlen(old_string);
5480 new_len = strlen(new_string);
5481
5482 l = strlen(text);
5483 r = new(char, l+1);
5484 if (!r)
5485 return NULL;
5486
5487 f = text;
5488 t = r;
5489 while (*f) {
5490 char *a;
5491 size_t d, nl;
5492
5493 if (!startswith(f, old_string)) {
5494 *(t++) = *(f++);
5495 continue;
5496 }
5497
5498 d = t - r;
5499 nl = l - old_len + new_len;
5500 a = realloc(r, nl + 1);
5501 if (!a)
5502 goto oom;
5503
5504 l = nl;
5505 r = a;
5506 t = r + d;
5507
5508 t = stpcpy(t, new_string);
5509 f += old_len;
5510 }
5511
5512 *t = 0;
5513 return r;
5514
5515oom:
5516 free(r);
5517 return NULL;
5518}
e8bc0ea2
LP
5519
5520char *strip_tab_ansi(char **ibuf, size_t *_isz) {
660ddc72 5521 const char *i, *begin = NULL;
e8bc0ea2
LP
5522 enum {
5523 STATE_OTHER,
5524 STATE_ESCAPE,
5525 STATE_BRACKET
5526 } state = STATE_OTHER;
5527 char *obuf = NULL;
5528 size_t osz = 0, isz;
5529 FILE *f;
5530
5531 assert(ibuf);
5532 assert(*ibuf);
5533
5534 /* Strips ANSI color and replaces TABs by 8 spaces */
5535
5536 isz = _isz ? *_isz : strlen(*ibuf);
5537
5538 f = open_memstream(&obuf, &osz);
5539 if (!f)
5540 return NULL;
5541
5542 for (i = *ibuf; i < *ibuf + isz + 1; i++) {
5543
5544 switch (state) {
5545
5546 case STATE_OTHER:
5547 if (i >= *ibuf + isz) /* EOT */
5548 break;
5549 else if (*i == '\x1B')
5550 state = STATE_ESCAPE;
5551 else if (*i == '\t')
5552 fputs(" ", f);
5553 else
5554 fputc(*i, f);
5555 break;
5556
5557 case STATE_ESCAPE:
5558 if (i >= *ibuf + isz) { /* EOT */
5559 fputc('\x1B', f);
5560 break;
5561 } else if (*i == '[') {
5562 state = STATE_BRACKET;
5563 begin = i + 1;
5564 } else {
5565 fputc('\x1B', f);
5566 fputc(*i, f);
5567 state = STATE_OTHER;
5568 }
5569
5570 break;
5571
5572 case STATE_BRACKET:
5573
5574 if (i >= *ibuf + isz || /* EOT */
5575 (!(*i >= '0' && *i <= '9') && *i != ';' && *i != 'm')) {
5576 fputc('\x1B', f);
5577 fputc('[', f);
5578 state = STATE_OTHER;
5579 i = begin-1;
5580 } else if (*i == 'm')
5581 state = STATE_OTHER;
5582 break;
5583 }
5584 }
5585
5586 if (ferror(f)) {
5587 fclose(f);
5588 free(obuf);
5589 return NULL;
5590 }
5591
5592 fclose(f);
5593
5594 free(*ibuf);
5595 *ibuf = obuf;
5596
5597 if (_isz)
5598 *_isz = osz;
5599
5600 return obuf;
5601}
240dbaa4
LP
5602
5603int on_ac_power(void) {
5604 bool found_offline = false, found_online = false;
5605 _cleanup_closedir_ DIR *d = NULL;
5606
5607 d = opendir("/sys/class/power_supply");
5608 if (!d)
5609 return -errno;
5610
5611 for (;;) {
5612 struct dirent *de;
240dbaa4
LP
5613 _cleanup_close_ int fd = -1, device = -1;
5614 char contents[6];
5615 ssize_t n;
240dbaa4 5616
3fd11280
FW
5617 errno = 0;
5618 de = readdir(d);
5619 if (!de && errno != 0)
5620 return -errno;
240dbaa4
LP
5621
5622 if (!de)
5623 break;
5624
5625 if (ignore_file(de->d_name))
5626 continue;
5627
5628 device = openat(dirfd(d), de->d_name, O_DIRECTORY|O_RDONLY|O_CLOEXEC|O_NOCTTY);
5629 if (device < 0) {
5630 if (errno == ENOENT || errno == ENOTDIR)
5631 continue;
5632
5633 return -errno;
5634 }
5635
5636 fd = openat(device, "type", O_RDONLY|O_CLOEXEC|O_NOCTTY);
5637 if (fd < 0) {
5638 if (errno == ENOENT)
5639 continue;
5640
5641 return -errno;
5642 }
5643
5644 n = read(fd, contents, sizeof(contents));
5645 if (n < 0)
5646 return -errno;
5647
5648 if (n != 6 || memcmp(contents, "Mains\n", 6))
5649 continue;
5650
03e334a1 5651 safe_close(fd);
240dbaa4
LP
5652 fd = openat(device, "online", O_RDONLY|O_CLOEXEC|O_NOCTTY);
5653 if (fd < 0) {
5654 if (errno == ENOENT)
5655 continue;
5656
5657 return -errno;
5658 }
5659
5660 n = read(fd, contents, sizeof(contents));
5661 if (n < 0)
5662 return -errno;
5663
5664 if (n != 2 || contents[1] != '\n')
5665 return -EIO;
5666
5667 if (contents[0] == '1') {
5668 found_online = true;
5669 break;
5670 } else if (contents[0] == '0')
5671 found_offline = true;
5672 else
5673 return -EIO;
5674 }
5675
5676 return found_online || !found_offline;
5677}
fabe5c0e 5678
4cf7ea55 5679static int search_and_fopen_internal(const char *path, const char *mode, const char *root, char **search, FILE **_f) {
fabe5c0e
LP
5680 char **i;
5681
5682 assert(path);
5683 assert(mode);
5684 assert(_f);
5685
4cf7ea55 5686 if (!path_strv_canonicalize_absolute_uniq(search, root))
fabe5c0e
LP
5687 return -ENOMEM;
5688
5689 STRV_FOREACH(i, search) {
5690 _cleanup_free_ char *p = NULL;
5691 FILE *f;
5692
5693 p = strjoin(*i, "/", path, NULL);
5694 if (!p)
5695 return -ENOMEM;
5696
5697 f = fopen(p, mode);
5698 if (f) {
5699 *_f = f;
5700 return 0;
5701 }
5702
5703 if (errno != ENOENT)
5704 return -errno;
5705 }
5706
5707 return -ENOENT;
5708}
5709
4cf7ea55 5710int search_and_fopen(const char *path, const char *mode, const char *root, const char **search, FILE **_f) {
fabe5c0e
LP
5711 _cleanup_strv_free_ char **copy = NULL;
5712
5713 assert(path);
5714 assert(mode);
5715 assert(_f);
5716
5717 if (path_is_absolute(path)) {
5718 FILE *f;
5719
5720 f = fopen(path, mode);
5721 if (f) {
5722 *_f = f;
5723 return 0;
5724 }
5725
5726 return -errno;
5727 }
5728
5729 copy = strv_copy((char**) search);
5730 if (!copy)
5731 return -ENOMEM;
5732
4cf7ea55 5733 return search_and_fopen_internal(path, mode, root, copy, _f);
fabe5c0e
LP
5734}
5735
4cf7ea55 5736int search_and_fopen_nulstr(const char *path, const char *mode, const char *root, const char *search, FILE **_f) {
fabe5c0e
LP
5737 _cleanup_strv_free_ char **s = NULL;
5738
5739 if (path_is_absolute(path)) {
5740 FILE *f;
5741
5742 f = fopen(path, mode);
5743 if (f) {
5744 *_f = f;
5745 return 0;
5746 }
5747
5748 return -errno;
5749 }
5750
5751 s = strv_split_nulstr(search);
5752 if (!s)
5753 return -ENOMEM;
5754
4cf7ea55 5755 return search_and_fopen_internal(path, mode, root, s, _f);
fabe5c0e 5756}
c17ec25e 5757
66e35261
LP
5758char *strextend(char **x, ...) {
5759 va_list ap;
5760 size_t f, l;
5761 char *r, *p;
5762
5763 assert(x);
5764
5765 l = f = *x ? strlen(*x) : 0;
5766
5767 va_start(ap, x);
5768 for (;;) {
5769 const char *t;
5770 size_t n;
5771
5772 t = va_arg(ap, const char *);
5773 if (!t)
5774 break;
5775
5776 n = strlen(t);
5777 if (n > ((size_t) -1) - l) {
5778 va_end(ap);
5779 return NULL;
5780 }
5781
5782 l += n;
5783 }
5784 va_end(ap);
5785
5786 r = realloc(*x, l+1);
5787 if (!r)
5788 return NULL;
5789
5790 p = r + f;
5791
5792 va_start(ap, x);
5793 for (;;) {
5794 const char *t;
5795
5796 t = va_arg(ap, const char *);
5797 if (!t)
5798 break;
5799
5800 p = stpcpy(p, t);
5801 }
5802 va_end(ap);
5803
5804 *p = 0;
5805 *x = r;
5806
5807 return r + l;
5808}
9a17484d
LP
5809
5810char *strrep(const char *s, unsigned n) {
5811 size_t l;
5812 char *r, *p;
5813 unsigned i;
5814
5815 assert(s);
5816
5817 l = strlen(s);
5818 p = r = malloc(l * n + 1);
5819 if (!r)
5820 return NULL;
5821
5822 for (i = 0; i < n; i++)
5823 p = stpcpy(p, s);
5824
5825 *p = 0;
5826 return r;
5827}
392d5b37 5828
ca2d3784
ZJS
5829void* greedy_realloc(void **p, size_t *allocated, size_t need, size_t size) {
5830 size_t a, newalloc;
392d5b37
LP
5831 void *q;
5832
98088803 5833 assert(p);
e93c33d4
SL
5834 assert(allocated);
5835
392d5b37
LP
5836 if (*allocated >= need)
5837 return *p;
5838
ca2d3784
ZJS
5839 newalloc = MAX(need * 2, 64u / size);
5840 a = newalloc * size;
98088803
LP
5841
5842 /* check for overflows */
ca2d3784 5843 if (a < size * need)
98088803
LP
5844 return NULL;
5845
392d5b37
LP
5846 q = realloc(*p, a);
5847 if (!q)
5848 return NULL;
5849
5850 *p = q;
ca2d3784 5851 *allocated = newalloc;
392d5b37
LP
5852 return q;
5853}
aa96c6cb 5854
ca2d3784 5855void* greedy_realloc0(void **p, size_t *allocated, size_t need, size_t size) {
98088803 5856 size_t prev;
4545a231
DH
5857 uint8_t *q;
5858
98088803
LP
5859 assert(p);
5860 assert(allocated);
5861
5862 prev = *allocated;
5863
ca2d3784 5864 q = greedy_realloc(p, allocated, need, size);
4545a231
DH
5865 if (!q)
5866 return NULL;
5867
5868 if (*allocated > prev)
ca2d3784 5869 memzero(q + prev * size, (*allocated - prev) * size);
4545a231
DH
5870
5871 return q;
5872}
5873
aa96c6cb
LP
5874bool id128_is_valid(const char *s) {
5875 size_t i, l;
5876
5877 l = strlen(s);
5878 if (l == 32) {
5879
5880 /* Simple formatted 128bit hex string */
5881
5882 for (i = 0; i < l; i++) {
5883 char c = s[i];
5884
5885 if (!(c >= '0' && c <= '9') &&
5886 !(c >= 'a' && c <= 'z') &&
5887 !(c >= 'A' && c <= 'Z'))
5888 return false;
5889 }
5890
5891 } else if (l == 36) {
5892
5893 /* Formatted UUID */
5894
5895 for (i = 0; i < l; i++) {
5896 char c = s[i];
5897
5898 if ((i == 8 || i == 13 || i == 18 || i == 23)) {
5899 if (c != '-')
5900 return false;
5901 } else {
5902 if (!(c >= '0' && c <= '9') &&
5903 !(c >= 'a' && c <= 'z') &&
5904 !(c >= 'A' && c <= 'Z'))
5905 return false;
5906 }
5907 }
5908
5909 } else
5910 return false;
5911
5912 return true;
5913}
7085053a 5914
d4ac85c6
LP
5915int split_pair(const char *s, const char *sep, char **l, char **r) {
5916 char *x, *a, *b;
5917
5918 assert(s);
5919 assert(sep);
5920 assert(l);
5921 assert(r);
5922
5923 if (isempty(sep))
5924 return -EINVAL;
5925
5926 x = strstr(s, sep);
5927 if (!x)
5928 return -EINVAL;
5929
5930 a = strndup(s, x - s);
5931 if (!a)
5932 return -ENOMEM;
5933
5934 b = strdup(x + strlen(sep));
5935 if (!b) {
5936 free(a);
5937 return -ENOMEM;
5938 }
5939
5940 *l = a;
5941 *r = b;
5942
5943 return 0;
5944}
295edddf 5945
74df0fca 5946int shall_restore_state(void) {
059cb385 5947 _cleanup_free_ char *line = NULL;
295edddf 5948 char *w, *state;
295edddf 5949 size_t l;
74df0fca 5950 int r;
295edddf 5951
74df0fca
LP
5952 r = proc_cmdline(&line);
5953 if (r < 0)
5954 return r;
5955 if (r == 0) /* Container ... */
5956 return 1;
295edddf 5957
059cb385 5958 r = 1;
74df0fca 5959
059cb385
LP
5960 FOREACH_WORD_QUOTED(w, l, line, state) {
5961 const char *e;
5962 char n[l+1];
5963 int k;
5964
5965 memcpy(n, w, l);
5966 n[l] = 0;
5967
5968 e = startswith(n, "systemd.restore_state=");
5969 if (!e)
5970 continue;
5971
5972 k = parse_boolean(e);
5973 if (k >= 0)
5974 r = k;
5975 }
5976
5977 return r;
74df0fca
LP
5978}
5979
5980int proc_cmdline(char **ret) {
5981 int r;
5982
5983 if (detect_container(NULL) > 0) {
39883f62 5984 char *buf = NULL, *p;
02bb6cda
LP
5985 size_t sz = 0;
5986
5987 r = read_full_file("/proc/1/cmdline", &buf, &sz);
5988 if (r < 0)
5989 return r;
5990
5991 for (p = buf; p + 1 < buf + sz; p++)
5992 if (*p == 0)
5993 *p = ' ';
5994
059cb385 5995 *p = 0;
02bb6cda
LP
5996 *ret = buf;
5997 return 1;
295edddf
TG
5998 }
5999
74df0fca
LP
6000 r = read_one_line_file("/proc/cmdline", ret);
6001 if (r < 0)
6002 return r;
295edddf 6003
74df0fca 6004 return 1;
295edddf 6005}
bc9fd78c 6006
059cb385 6007int parse_proc_cmdline(int (*parse_item)(const char *key, const char *value)) {
141a79f4
ZJS
6008 _cleanup_free_ char *line = NULL;
6009 char *w, *state;
6010 size_t l;
6011 int r;
6012
059cb385
LP
6013 assert(parse_item);
6014
141a79f4
ZJS
6015 r = proc_cmdline(&line);
6016 if (r < 0)
6017 log_warning("Failed to read /proc/cmdline, ignoring: %s", strerror(-r));
6018 if (r <= 0)
6019 return 0;
6020
6021 FOREACH_WORD_QUOTED(w, l, line, state) {
059cb385 6022 char word[l+1], *value;
141a79f4 6023
059cb385
LP
6024 memcpy(word, w, l);
6025 word[l] = 0;
141a79f4 6026
059cb385
LP
6027 /* Filter out arguments that are intended only for the
6028 * initrd */
6029 if (!in_initrd() && startswith(word, "rd."))
6030 continue;
6031
6032 value = strchr(word, '=');
6033 if (value)
6034 *(value++) = 0;
6035
6036 r = parse_item(word, value);
6037 if (r < 0)
141a79f4 6038 return r;
141a79f4
ZJS
6039 }
6040
6041 return 0;
6042}
6043
bc9fd78c
LP
6044int container_get_leader(const char *machine, pid_t *pid) {
6045 _cleanup_free_ char *s = NULL, *class = NULL;
6046 const char *p;
6047 pid_t leader;
6048 int r;
6049
6050 assert(machine);
6051 assert(pid);
6052
6053 p = strappenda("/run/systemd/machines/", machine);
6054 r = parse_env_file(p, NEWLINE, "LEADER", &s, "CLASS", &class, NULL);
6055 if (r == -ENOENT)
6056 return -EHOSTDOWN;
6057 if (r < 0)
6058 return r;
6059 if (!s)
6060 return -EIO;
6061
6062 if (!streq_ptr(class, "container"))
6063 return -EIO;
6064
6065 r = parse_pid(s, &leader);
6066 if (r < 0)
6067 return r;
6068 if (leader <= 1)
6069 return -EIO;
6070
6071 *pid = leader;
6072 return 0;
6073}
6074
878cd7e9
LP
6075int namespace_open(pid_t pid, int *pidns_fd, int *mntns_fd, int *netns_fd, int *root_fd) {
6076 _cleanup_close_ int pidnsfd = -1, mntnsfd = -1, netnsfd = -1;
359a06aa 6077 int rfd = -1;
bc9fd78c
LP
6078
6079 assert(pid >= 0);
bc9fd78c 6080
878cd7e9
LP
6081 if (mntns_fd) {
6082 const char *mntns;
a4475f57 6083
878cd7e9
LP
6084 mntns = procfs_file_alloca(pid, "ns/mnt");
6085 mntnsfd = open(mntns, O_RDONLY|O_NOCTTY|O_CLOEXEC);
6086 if (mntnsfd < 0)
6087 return -errno;
6088 }
bc9fd78c 6089
878cd7e9
LP
6090 if (pidns_fd) {
6091 const char *pidns;
6092
6093 pidns = procfs_file_alloca(pid, "ns/pid");
6094 pidnsfd = open(pidns, O_RDONLY|O_NOCTTY|O_CLOEXEC);
6095 if (pidnsfd < 0)
6096 return -errno;
6097 }
6098
6099 if (netns_fd) {
6100 const char *netns;
6101
6102 netns = procfs_file_alloca(pid, "ns/net");
6103 netnsfd = open(netns, O_RDONLY|O_NOCTTY|O_CLOEXEC);
6104 if (netnsfd < 0)
6105 return -errno;
6106 }
6107
6108 if (root_fd) {
6109 const char *root;
6110
6111 root = procfs_file_alloca(pid, "root");
6112 rfd = open(root, O_RDONLY|O_NOCTTY|O_CLOEXEC|O_DIRECTORY);
6113 if (rfd < 0)
6114 return -errno;
6115 }
6116
6117 if (pidns_fd)
6118 *pidns_fd = pidnsfd;
bc9fd78c 6119
878cd7e9
LP
6120 if (mntns_fd)
6121 *mntns_fd = mntnsfd;
6122
6123 if (netns_fd)
6124 *netns_fd = netnsfd;
6125
6126 if (root_fd)
6127 *root_fd = rfd;
6128
6129 pidnsfd = mntnsfd = netnsfd = -1;
bc9fd78c
LP
6130
6131 return 0;
6132}
6133
878cd7e9 6134int namespace_enter(int pidns_fd, int mntns_fd, int netns_fd, int root_fd) {
bc9fd78c 6135
878cd7e9
LP
6136 if (pidns_fd >= 0)
6137 if (setns(pidns_fd, CLONE_NEWPID) < 0)
6138 return -errno;
a4475f57 6139
878cd7e9
LP
6140 if (mntns_fd >= 0)
6141 if (setns(mntns_fd, CLONE_NEWNS) < 0)
6142 return -errno;
bc9fd78c 6143
878cd7e9
LP
6144 if (netns_fd >= 0)
6145 if (setns(netns_fd, CLONE_NEWNET) < 0)
6146 return -errno;
bc9fd78c 6147
878cd7e9
LP
6148 if (root_fd >= 0) {
6149 if (fchdir(root_fd) < 0)
6150 return -errno;
6151
6152 if (chroot(".") < 0)
6153 return -errno;
6154 }
bc9fd78c 6155
5e2b3214
LP
6156 if (setresgid(0, 0, 0) < 0)
6157 return -errno;
6158
878cd7e9
LP
6159 if (setgroups(0, NULL) < 0)
6160 return -errno;
6161
5e2b3214
LP
6162 if (setresuid(0, 0, 0) < 0)
6163 return -errno;
6164
bc9fd78c
LP
6165 return 0;
6166}
bf108e55 6167
9f5650ae
LP
6168bool pid_is_unwaited(pid_t pid) {
6169 /* Checks whether a PID is still valid at all, including a zombie */
6170
bf108e55
LP
6171 if (pid <= 0)
6172 return false;
6173
6174 if (kill(pid, 0) >= 0)
6175 return true;
6176
6177 return errno != ESRCH;
6178}
eff05270 6179
9f5650ae
LP
6180bool pid_is_alive(pid_t pid) {
6181 int r;
6182
6183 /* Checks whether a PID is still valid and not a zombie */
6184
6185 if (pid <= 0)
6186 return false;
6187
6188 r = get_process_state(pid);
6189 if (r == -ENOENT || r == 'Z')
6190 return false;
6191
6192 return true;
6193}
6194
eff05270
LP
6195int getpeercred(int fd, struct ucred *ucred) {
6196 socklen_t n = sizeof(struct ucred);
6197 struct ucred u;
6198 int r;
6199
6200 assert(fd >= 0);
6201 assert(ucred);
6202
6203 r = getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &u, &n);
6204 if (r < 0)
6205 return -errno;
6206
6207 if (n != sizeof(struct ucred))
6208 return -EIO;
6209
6210 /* Check if the data is actually useful and not suppressed due
6211 * to namespacing issues */
6212 if (u.pid <= 0)
6213 return -ENODATA;
6214
6215 *ucred = u;
6216 return 0;
6217}
6218
6219int getpeersec(int fd, char **ret) {
6220 socklen_t n = 64;
6221 char *s;
6222 int r;
6223
6224 assert(fd >= 0);
6225 assert(ret);
6226
6227 s = new0(char, n);
6228 if (!s)
6229 return -ENOMEM;
6230
6231 r = getsockopt(fd, SOL_SOCKET, SO_PEERSEC, s, &n);
6232 if (r < 0) {
6233 free(s);
6234
6235 if (errno != ERANGE)
6236 return -errno;
6237
6238 s = new0(char, n);
6239 if (!s)
6240 return -ENOMEM;
6241
6242 r = getsockopt(fd, SOL_SOCKET, SO_PEERSEC, s, &n);
6243 if (r < 0) {
6244 free(s);
6245 return -errno;
6246 }
6247 }
6248
ae98841e
LP
6249 if (isempty(s)) {
6250 free(s);
6251 return -ENOTSUP;
6252 }
6253
eff05270
LP
6254 *ret = s;
6255 return 0;
6256}
8e33886e 6257
0f010ef2 6258/* This is much like like mkostemp() but is subject to umask(). */
65b3903f 6259int mkostemp_safe(char *pattern, int flags) {
2d5bdf5b 6260 _cleanup_umask_ mode_t u;
0f010ef2 6261 int fd;
65b3903f 6262
d37a91e8 6263 assert(pattern);
65b3903f 6264
2d5bdf5b
LP
6265 u = umask(077);
6266
0f010ef2
ZJS
6267 fd = mkostemp(pattern, flags);
6268 if (fd < 0)
6269 return -errno;
65b3903f 6270
0f010ef2 6271 return fd;
65b3903f
ZJS
6272}
6273
8e33886e 6274int open_tmpfile(const char *path, int flags) {
8e33886e 6275 char *p;
a6afc4ae
LP
6276 int fd;
6277
6278 assert(path);
8e33886e
ZJS
6279
6280#ifdef O_TMPFILE
7736202c
LP
6281 /* Try O_TMPFILE first, if it is supported */
6282 fd = open(path, flags|O_TMPFILE, S_IRUSR|S_IWUSR);
8e33886e
ZJS
6283 if (fd >= 0)
6284 return fd;
6285#endif
7736202c
LP
6286
6287 /* Fall back to unguessable name + unlinking */
8e33886e
ZJS
6288 p = strappenda(path, "/systemd-tmp-XXXXXX");
6289
a6afc4ae 6290 fd = mkostemp_safe(p, flags);
8e33886e 6291 if (fd < 0)
65b3903f 6292 return fd;
8e33886e
ZJS
6293
6294 unlink(p);
6295 return fd;
6296}
fdb9161c
LP
6297
6298int fd_warn_permissions(const char *path, int fd) {
6299 struct stat st;
6300
6301 if (fstat(fd, &st) < 0)
6302 return -errno;
6303
6304 if (st.st_mode & 0111)
6305 log_warning("Configuration file %s is marked executable. Please remove executable permission bits. Proceeding anyway.", path);
6306
6307 if (st.st_mode & 0002)
6308 log_warning("Configuration file %s is marked world-writable. Please remove world writability permission bits. Proceeding anyway.", path);
6309
6310 if (getpid() == 1 && (st.st_mode & 0044) != 0044)
6311 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);
6312
6313 return 0;
6314}
6afc95b7 6315
ac45f971 6316unsigned long personality_from_string(const char *p) {
6afc95b7
LP
6317
6318 /* Parse a personality specifier. We introduce our own
6319 * identifiers that indicate specific ABIs, rather than just
6320 * hints regarding the register size, since we want to keep
6321 * things open for multiple locally supported ABIs for the
6322 * same register size. We try to reuse the ABI identifiers
6323 * used by libseccomp. */
6324
6325#if defined(__x86_64__)
6326
6327 if (streq(p, "x86"))
6328 return PER_LINUX32;
6329
6330 if (streq(p, "x86-64"))
6331 return PER_LINUX;
6332
6333#elif defined(__i386__)
6334
6335 if (streq(p, "x86"))
6336 return PER_LINUX;
6337#endif
6338
6339 /* personality(7) documents that 0xffffffffUL is used for
6340 * querying the current personality, hence let's use that here
6341 * as error indicator. */
6342 return 0xffffffffUL;
6343}
ac45f971
LP
6344
6345const char* personality_to_string(unsigned long p) {
6346
6347#if defined(__x86_64__)
6348
6349 if (p == PER_LINUX32)
6350 return "x86";
6351
6352 if (p == PER_LINUX)
6353 return "x86-64";
6354
6355#elif defined(__i386__)
6356
6357 if (p == PER_LINUX)
6358 return "x86";
6359#endif
6360
6361 return NULL;
6362}
1c231f56
LP
6363
6364uint64_t physical_memory(void) {
6365 long mem;
6366
6367 /* We return this as uint64_t in case we are running as 32bit
6368 * process on a 64bit kernel with huge amounts of memory */
6369
6370 mem = sysconf(_SC_PHYS_PAGES);
6371 assert(mem > 0);
6372
6373 return (uint64_t) mem * (uint64_t) page_size();
6374}
6db615c1
LP
6375
6376char* mount_test_option(const char *haystack, const char *needle) {
6377
6378 struct mntent me = {
6379 .mnt_opts = (char*) haystack
6380 };
6381
6382 assert(needle);
6383
6384 /* Like glibc's hasmntopt(), but works on a string, not a
6385 * struct mntent */
6386
6387 if (!haystack)
6388 return NULL;
6389
6390 return hasmntopt(&me, needle);
6391}
29bfbcd6
LP
6392
6393void hexdump(FILE *f, const void *p, size_t s) {
6394 const uint8_t *b = p;
6395 unsigned n = 0;
6396
6397 assert(s == 0 || b);
6398
6399 while (s > 0) {
6400 size_t i;
6401
6402 fprintf(f, "%04x ", n);
6403
6404 for (i = 0; i < 16; i++) {
6405
6406 if (i >= s)
6407 fputs(" ", f);
6408 else
6409 fprintf(f, "%02x ", b[i]);
6410
6411 if (i == 7)
6412 fputc(' ', f);
6413 }
6414
6415 fputc(' ', f);
6416
6417 for (i = 0; i < 16; i++) {
6418
6419 if (i >= s)
6420 fputc(' ', f);
6421 else
6422 fputc(isprint(b[i]) ? (char) b[i] : '.', f);
6423 }
6424
6425 fputc('\n', f);
6426
6427 if (s < 16)
6428 break;
6429
6430 n += 16;
6431 b += 16;
6432 s -= 16;
6433 }
6434}
c5220a94 6435
966bff26 6436int update_reboot_param_file(const char *param) {
c5220a94
MO
6437 int r = 0;
6438
6439 if (param) {
6440
6441 r = write_string_file(REBOOT_PARAM_FILE, param);
6442 if (r < 0)
6443 log_error("Failed to write reboot param to "
6444 REBOOT_PARAM_FILE": %s", strerror(-r));
6445 } else
6446 unlink(REBOOT_PARAM_FILE);
6447
6448 return r;
6449}
6d313367
LP
6450
6451int umount_recursive(const char *prefix, int flags) {
6452 bool again;
6453 int n = 0, r;
6454
6455 /* Try to umount everything recursively below a
6456 * directory. Also, take care of stacked mounts, and keep
6457 * unmounting them until they are gone. */
6458
6459 do {
6460 _cleanup_fclose_ FILE *proc_self_mountinfo = NULL;
6461
6462 again = false;
6463 r = 0;
6464
6465 proc_self_mountinfo = fopen("/proc/self/mountinfo", "re");
6466 if (!proc_self_mountinfo)
6467 return -errno;
6468
6469 for (;;) {
6470 _cleanup_free_ char *path = NULL, *p = NULL;
6471 int k;
6472
6473 k = fscanf(proc_self_mountinfo,
6474 "%*s " /* (1) mount id */
6475 "%*s " /* (2) parent id */
6476 "%*s " /* (3) major:minor */
6477 "%*s " /* (4) root */
6478 "%ms " /* (5) mount point */
6479 "%*s" /* (6) mount options */
6480 "%*[^-]" /* (7) optional fields */
6481 "- " /* (8) separator */
6482 "%*s " /* (9) file system type */
6483 "%*s" /* (10) mount source */
6484 "%*s" /* (11) mount options 2 */
6485 "%*[^\n]", /* some rubbish at the end */
6486 &path);
6d313367
LP
6487 if (k != 1) {
6488 if (k == EOF)
6489 break;
6490
6491 continue;
6492 }
6493
6494 p = cunescape(path);
6495 if (!p)
6496 return -ENOMEM;
6497
6498 if (!path_startswith(p, prefix))
6499 continue;
6500
6501 if (umount2(p, flags) < 0) {
6502 r = -errno;
6503 continue;
6504 }
6505
6506 again = true;
6507 n++;
6508
6509 break;
6510 }
6511
6512 } while (again);
6513
6514 return r ? r : n;
6515}
d6797c92
LP
6516
6517int bind_remount_recursive(const char *prefix, bool ro) {
6518 _cleanup_set_free_free_ Set *done = NULL;
6519 _cleanup_free_ char *cleaned = NULL;
6520 int r;
6521
6522 /* Recursively remount a directory (and all its submounts)
6523 * read-only or read-write. If the directory is already
6524 * mounted, we reuse the mount and simply mark it
6525 * MS_BIND|MS_RDONLY (or remove the MS_RDONLY for read-write
6526 * operation). If it isn't we first make it one. Afterwards we
6527 * apply MS_BIND|MS_RDONLY (or remove MS_RDONLY) to all
6528 * submounts we can access, too. When mounts are stacked on
6529 * the same mount point we only care for each individual
6530 * "top-level" mount on each point, as we cannot
6531 * influence/access the underlying mounts anyway. We do not
6532 * have any effect on future submounts that might get
6533 * propagated, they migt be writable. This includes future
6534 * submounts that have been triggered via autofs. */
6535
6536 cleaned = strdup(prefix);
6537 if (!cleaned)
6538 return -ENOMEM;
6539
6540 path_kill_slashes(cleaned);
6541
6542 done = set_new(string_hash_func, string_compare_func);
6543 if (!done)
6544 return -ENOMEM;
6545
6546 for (;;) {
6547 _cleanup_fclose_ FILE *proc_self_mountinfo = NULL;
6548 _cleanup_set_free_free_ Set *todo = NULL;
6549 bool top_autofs = false;
6550 char *x;
6551
6552 todo = set_new(string_hash_func, string_compare_func);
6553 if (!todo)
6554 return -ENOMEM;
6555
6556 proc_self_mountinfo = fopen("/proc/self/mountinfo", "re");
6557 if (!proc_self_mountinfo)
6558 return -errno;
6559
6560 for (;;) {
6561 _cleanup_free_ char *path = NULL, *p = NULL, *type = NULL;
6562 int k;
6563
6564 k = fscanf(proc_self_mountinfo,
6565 "%*s " /* (1) mount id */
6566 "%*s " /* (2) parent id */
6567 "%*s " /* (3) major:minor */
6568 "%*s " /* (4) root */
6569 "%ms " /* (5) mount point */
6570 "%*s" /* (6) mount options (superblock) */
6571 "%*[^-]" /* (7) optional fields */
6572 "- " /* (8) separator */
6573 "%ms " /* (9) file system type */
6574 "%*s" /* (10) mount source */
6575 "%*s" /* (11) mount options (bind mount) */
6576 "%*[^\n]", /* some rubbish at the end */
6577 &path,
6578 &type);
6579 if (k != 2) {
6580 if (k == EOF)
6581 break;
6582
6583 continue;
6584 }
6585
6586 p = cunescape(path);
6587 if (!p)
6588 return -ENOMEM;
6589
6590 /* Let's ignore autofs mounts. If they aren't
6591 * triggered yet, we want to avoid triggering
6592 * them, as we don't make any guarantees for
6593 * future submounts anyway. If they are
6594 * already triggered, then we will find
6595 * another entry for this. */
6596 if (streq(type, "autofs")) {
6597 top_autofs = top_autofs || path_equal(cleaned, p);
6598 continue;
6599 }
6600
6601 if (path_startswith(p, cleaned) &&
6602 !set_contains(done, p)) {
6603
6604 r = set_consume(todo, p);
6605 p = NULL;
6606
6607 if (r == -EEXIST)
6608 continue;
6609 if (r < 0)
6610 return r;
6611 }
6612 }
6613
6614 /* If we have no submounts to process anymore and if
6615 * the root is either already done, or an autofs, we
6616 * are done */
6617 if (set_isempty(todo) &&
6618 (top_autofs || set_contains(done, cleaned)))
6619 return 0;
6620
6621 if (!set_contains(done, cleaned) &&
6622 !set_contains(todo, cleaned)) {
6623 /* The prefix directory itself is not yet a
6624 * mount, make it one. */
6625 if (mount(cleaned, cleaned, NULL, MS_BIND|MS_REC, NULL) < 0)
6626 return -errno;
6627
6628 if (mount(NULL, prefix, NULL, MS_BIND|MS_REMOUNT|(ro ? MS_RDONLY : 0), NULL) < 0)
6629 return -errno;
6630
6631 x = strdup(cleaned);
6632 if (!x)
6633 return -ENOMEM;
6634
6635 r = set_consume(done, x);
6636 if (r < 0)
6637 return r;
6638 }
6639
6640 while ((x = set_steal_first(todo))) {
6641
6642 r = set_consume(done, x);
6643 if (r == -EEXIST)
6644 continue;
6645 if (r < 0)
6646 return r;
6647
6648 if (mount(NULL, x, NULL, MS_BIND|MS_REMOUNT|(ro ? MS_RDONLY : 0), NULL) < 0) {
6649
6650 /* Deal with mount points that are
6651 * obstructed by a later mount */
6652
6653 if (errno != ENOENT)
6654 return -errno;
6655 }
6656
6657 }
6658 }
6659}
1b992147
LP
6660
6661int fflush_and_check(FILE *f) {
45c196a7 6662 assert(f);
1b992147
LP
6663
6664 errno = 0;
6665 fflush(f);
6666
6667 if (ferror(f))
6668 return errno ? -errno : -EIO;
6669
6670 return 0;
6671}