]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/shared/util.c
debug-shell: add condition for tty device to run on
[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;
4010 const char *fn;
4011 size_t k;
4012 int fd;
4013
4014 assert(path);
4015 assert(_f);
4016 assert(_temp_path);
4017
4018 t = new(char, strlen(path) + 1 + 6 + 1);
4019 if (!t)
4020 return -ENOMEM;
4021
2b6bf07d
ZJS
4022 fn = basename(path);
4023 k = fn - path;
5a3ab509
LP
4024 memcpy(t, path, k);
4025 t[k] = '.';
4026 stpcpy(stpcpy(t+k+1, fn), "XXXXXX");
4027
2d5bdf5b 4028 fd = mkostemp_safe(t, O_WRONLY|O_CLOEXEC);
5a3ab509
LP
4029 if (fd < 0) {
4030 free(t);
4031 return -errno;
4032 }
4033
4034 f = fdopen(fd, "we");
4035 if (!f) {
4036 unlink(t);
4037 free(t);
4038 return -errno;
4039 }
4040
4041 *_f = f;
4042 *_temp_path = t;
4043
4044 return 0;
4045}
4046
6ea832a2 4047int terminal_vhangup_fd(int fd) {
5a3ab509
LP
4048 assert(fd >= 0);
4049
6ea832a2
LP
4050 if (ioctl(fd, TIOCVHANGUP) < 0)
4051 return -errno;
4052
4053 return 0;
4054}
4055
4056int terminal_vhangup(const char *name) {
03e334a1 4057 _cleanup_close_ int fd;
6ea832a2
LP
4058
4059 fd = open_terminal(name, O_RDWR|O_NOCTTY|O_CLOEXEC);
4060 if (fd < 0)
4061 return fd;
4062
03e334a1 4063 return terminal_vhangup_fd(fd);
6ea832a2
LP
4064}
4065
4066int vt_disallocate(const char *name) {
4067 int fd, r;
4068 unsigned u;
6ea832a2
LP
4069
4070 /* Deallocate the VT if possible. If not possible
4071 * (i.e. because it is the active one), at least clear it
4072 * entirely (including the scrollback buffer) */
4073
b83bc4e9
LP
4074 if (!startswith(name, "/dev/"))
4075 return -EINVAL;
4076
4077 if (!tty_is_vc(name)) {
4078 /* So this is not a VT. I guess we cannot deallocate
4079 * it then. But let's at least clear the screen */
4080
4081 fd = open_terminal(name, O_RDWR|O_NOCTTY|O_CLOEXEC);
4082 if (fd < 0)
4083 return fd;
4084
8585357a
LP
4085 loop_write(fd,
4086 "\033[r" /* clear scrolling region */
4087 "\033[H" /* move home */
4088 "\033[2J", /* clear screen */
4089 10, false);
03e334a1 4090 safe_close(fd);
b83bc4e9
LP
4091
4092 return 0;
4093 }
6ea832a2
LP
4094
4095 if (!startswith(name, "/dev/tty"))
4096 return -EINVAL;
4097
4098 r = safe_atou(name+8, &u);
4099 if (r < 0)
4100 return r;
4101
4102 if (u <= 0)
b83bc4e9 4103 return -EINVAL;
6ea832a2 4104
b83bc4e9 4105 /* Try to deallocate */
6ea832a2
LP
4106 fd = open_terminal("/dev/tty0", O_RDWR|O_NOCTTY|O_CLOEXEC);
4107 if (fd < 0)
4108 return fd;
4109
4110 r = ioctl(fd, VT_DISALLOCATE, u);
03e334a1 4111 safe_close(fd);
6ea832a2 4112
b83bc4e9
LP
4113 if (r >= 0)
4114 return 0;
6ea832a2 4115
b83bc4e9 4116 if (errno != EBUSY)
6ea832a2 4117 return -errno;
6ea832a2 4118
b83bc4e9
LP
4119 /* Couldn't deallocate, so let's clear it fully with
4120 * scrollback */
4121 fd = open_terminal(name, O_RDWR|O_NOCTTY|O_CLOEXEC);
6ea832a2 4122 if (fd < 0)
b83bc4e9 4123 return fd;
6ea832a2 4124
8585357a
LP
4125 loop_write(fd,
4126 "\033[r" /* clear scrolling region */
4127 "\033[H" /* move home */
4128 "\033[3J", /* clear screen including scrollback, requires Linux 2.6.40 */
4129 10, false);
03e334a1 4130 safe_close(fd);
6ea832a2 4131
b83bc4e9 4132 return 0;
6ea832a2
LP
4133}
4134
424a19f8
LP
4135int symlink_atomic(const char *from, const char *to) {
4136 char *x;
4137 _cleanup_free_ char *t;
34ca941c
LP
4138 const char *fn;
4139 size_t k;
9bf3b535 4140 uint64_t u;
34ca941c
LP
4141 unsigned i;
4142 int r;
4143
4144 assert(from);
4145 assert(to);
4146
4147 t = new(char, strlen(to) + 1 + 16 + 1);
4148 if (!t)
4149 return -ENOMEM;
4150
2b6bf07d 4151 fn = basename(to);
34ca941c
LP
4152 k = fn-to;
4153 memcpy(t, to, k);
4154 t[k] = '.';
4155 x = stpcpy(t+k+1, fn);
4156
9bf3b535 4157 u = random_u64();
34ca941c 4158 for (i = 0; i < 16; i++) {
9bf3b535
LP
4159 *(x++) = hexchar(u & 0xF);
4160 u >>= 4;
34ca941c
LP
4161 }
4162
4163 *x = 0;
4164
424a19f8
LP
4165 if (symlink(from, t) < 0)
4166 return -errno;
34ca941c
LP
4167
4168 if (rename(t, to) < 0) {
4169 r = -errno;
4170 unlink(t);
34ca941c
LP
4171 return r;
4172 }
4173
424a19f8 4174 return 0;
34ca941c
LP
4175}
4176
4d6d6518
LP
4177bool display_is_local(const char *display) {
4178 assert(display);
4179
4180 return
4181 display[0] == ':' &&
4182 display[1] >= '0' &&
4183 display[1] <= '9';
4184}
4185
4186int socket_from_display(const char *display, char **path) {
4187 size_t k;
4188 char *f, *c;
4189
4190 assert(display);
4191 assert(path);
4192
4193 if (!display_is_local(display))
4194 return -EINVAL;
4195
4196 k = strspn(display+1, "0123456789");
4197
f8294e41 4198 f = new(char, strlen("/tmp/.X11-unix/X") + k + 1);
4d6d6518
LP
4199 if (!f)
4200 return -ENOMEM;
4201
4202 c = stpcpy(f, "/tmp/.X11-unix/X");
4203 memcpy(c, display+1, k);
4204 c[k] = 0;
4205
4206 *path = f;
4207
4208 return 0;
4209}
4210
d05c5031
LP
4211int get_user_creds(
4212 const char **username,
4213 uid_t *uid, gid_t *gid,
4214 const char **home,
4215 const char **shell) {
4216
1cccf435 4217 struct passwd *p;
ddd88763 4218 uid_t u;
1cccf435
MV
4219
4220 assert(username);
4221 assert(*username);
1cccf435
MV
4222
4223 /* We enforce some special rules for uid=0: in order to avoid
4224 * NSS lookups for root we hardcode its data. */
4225
4226 if (streq(*username, "root") || streq(*username, "0")) {
4227 *username = "root";
4b67834e
LP
4228
4229 if (uid)
4230 *uid = 0;
4231
4232 if (gid)
4233 *gid = 0;
4234
4235 if (home)
4236 *home = "/root";
d05c5031
LP
4237
4238 if (shell)
4239 *shell = "/bin/sh";
4240
1cccf435
MV
4241 return 0;
4242 }
4243
ddd88763 4244 if (parse_uid(*username, &u) >= 0) {
1cccf435 4245 errno = 0;
ddd88763 4246 p = getpwuid(u);
1cccf435
MV
4247
4248 /* If there are multiple users with the same id, make
4249 * sure to leave $USER to the configured value instead
4250 * of the first occurrence in the database. However if
4251 * the uid was configured by a numeric uid, then let's
4252 * pick the real username from /etc/passwd. */
4253 if (p)
4254 *username = p->pw_name;
4255 } else {
4256 errno = 0;
4257 p = getpwnam(*username);
4258 }
4259
4260 if (!p)
8333c77e 4261 return errno > 0 ? -errno : -ESRCH;
1cccf435 4262
4b67834e
LP
4263 if (uid)
4264 *uid = p->pw_uid;
4265
4266 if (gid)
4267 *gid = p->pw_gid;
4268
4269 if (home)
4270 *home = p->pw_dir;
4271
d05c5031
LP
4272 if (shell)
4273 *shell = p->pw_shell;
4274
4b67834e
LP
4275 return 0;
4276}
4277
59164be4
LP
4278char* uid_to_name(uid_t uid) {
4279 struct passwd *p;
4280 char *r;
4281
4282 if (uid == 0)
4283 return strdup("root");
4284
4285 p = getpwuid(uid);
4286 if (p)
4287 return strdup(p->pw_name);
4288
de0671ee 4289 if (asprintf(&r, UID_FMT, uid) < 0)
59164be4
LP
4290 return NULL;
4291
4292 return r;
4293}
4294
4468addc
LP
4295char* gid_to_name(gid_t gid) {
4296 struct group *p;
4297 char *r;
4298
4299 if (gid == 0)
4300 return strdup("root");
4301
4302 p = getgrgid(gid);
4303 if (p)
4304 return strdup(p->gr_name);
4305
de0671ee 4306 if (asprintf(&r, GID_FMT, gid) < 0)
4468addc
LP
4307 return NULL;
4308
4309 return r;
4310}
4311
4b67834e
LP
4312int get_group_creds(const char **groupname, gid_t *gid) {
4313 struct group *g;
4314 gid_t id;
4315
4316 assert(groupname);
4317
4318 /* We enforce some special rules for gid=0: in order to avoid
4319 * NSS lookups for root we hardcode its data. */
4320
4321 if (streq(*groupname, "root") || streq(*groupname, "0")) {
4322 *groupname = "root";
4323
4324 if (gid)
4325 *gid = 0;
4326
4327 return 0;
4328 }
4329
4330 if (parse_gid(*groupname, &id) >= 0) {
4331 errno = 0;
4332 g = getgrgid(id);
4333
4334 if (g)
4335 *groupname = g->gr_name;
4336 } else {
4337 errno = 0;
4338 g = getgrnam(*groupname);
4339 }
4340
4341 if (!g)
8333c77e 4342 return errno > 0 ? -errno : -ESRCH;
4b67834e
LP
4343
4344 if (gid)
4345 *gid = g->gr_gid;
4346
1cccf435
MV
4347 return 0;
4348}
4349
4468addc
LP
4350int in_gid(gid_t gid) {
4351 gid_t *gids;
43673799
LP
4352 int ngroups_max, r, i;
4353
43673799
LP
4354 if (getgid() == gid)
4355 return 1;
4356
4357 if (getegid() == gid)
4358 return 1;
4359
4360 ngroups_max = sysconf(_SC_NGROUPS_MAX);
4361 assert(ngroups_max > 0);
4362
4363 gids = alloca(sizeof(gid_t) * ngroups_max);
4364
4365 r = getgroups(ngroups_max, gids);
4366 if (r < 0)
4367 return -errno;
4368
4369 for (i = 0; i < r; i++)
4370 if (gids[i] == gid)
4371 return 1;
4372
4373 return 0;
4374}
4375
4468addc
LP
4376int in_group(const char *name) {
4377 int r;
4378 gid_t gid;
4379
4380 r = get_group_creds(&name, &gid);
4381 if (r < 0)
4382 return r;
4383
4384 return in_gid(gid);
4385}
4386
8092a428 4387int glob_exists(const char *path) {
7fd1b19b 4388 _cleanup_globfree_ glob_t g = {};
8d98da3f 4389 int k;
8092a428
LP
4390
4391 assert(path);
4392
8092a428
LP
4393 errno = 0;
4394 k = glob(path, GLOB_NOSORT|GLOB_BRACE, NULL, &g);
4395
4396 if (k == GLOB_NOMATCH)
8d98da3f 4397 return 0;
8092a428 4398 else if (k == GLOB_NOSPACE)
8d98da3f 4399 return -ENOMEM;
8092a428 4400 else if (k == 0)
8d98da3f 4401 return !strv_isempty(g.gl_pathv);
8092a428 4402 else
8d98da3f
ZJS
4403 return errno ? -errno : -EIO;
4404}
8092a428 4405
8d98da3f
ZJS
4406int glob_extend(char ***strv, const char *path) {
4407 _cleanup_globfree_ glob_t g = {};
4408 int k;
4409 char **p;
4410
4411 errno = 0;
a8ccacf5 4412 k = glob(path, GLOB_NOSORT|GLOB_BRACE, NULL, &g);
8d98da3f
ZJS
4413
4414 if (k == GLOB_NOMATCH)
4415 return -ENOENT;
4416 else if (k == GLOB_NOSPACE)
4417 return -ENOMEM;
4418 else if (k != 0 || strv_isempty(g.gl_pathv))
4419 return errno ? -errno : -EIO;
4420
4421 STRV_FOREACH(p, g.gl_pathv) {
4422 k = strv_extend(strv, *p);
4423 if (k < 0)
4424 break;
4425 }
4426
4427 return k;
8092a428
LP
4428}
4429
83096483
LP
4430int dirent_ensure_type(DIR *d, struct dirent *de) {
4431 struct stat st;
4432
4433 assert(d);
4434 assert(de);
4435
4436 if (de->d_type != DT_UNKNOWN)
4437 return 0;
4438
4439 if (fstatat(dirfd(d), de->d_name, &st, AT_SYMLINK_NOFOLLOW) < 0)
4440 return -errno;
4441
4442 de->d_type =
4443 S_ISREG(st.st_mode) ? DT_REG :
4444 S_ISDIR(st.st_mode) ? DT_DIR :
4445 S_ISLNK(st.st_mode) ? DT_LNK :
4446 S_ISFIFO(st.st_mode) ? DT_FIFO :
4447 S_ISSOCK(st.st_mode) ? DT_SOCK :
4448 S_ISCHR(st.st_mode) ? DT_CHR :
4449 S_ISBLK(st.st_mode) ? DT_BLK :
4450 DT_UNKNOWN;
4451
4452 return 0;
4453}
4454
4455int in_search_path(const char *path, char **search) {
893fa014
ZJS
4456 char **i;
4457 _cleanup_free_ char *parent = NULL;
83096483
LP
4458 int r;
4459
9eb977db 4460 r = path_get_parent(path, &parent);
83096483
LP
4461 if (r < 0)
4462 return r;
4463
893fa014
ZJS
4464 STRV_FOREACH(i, search)
4465 if (path_equal(parent, *i))
4466 return 1;
83096483 4467
893fa014 4468 return 0;
83096483
LP
4469}
4470
034a2a52 4471int get_files_in_directory(const char *path, char ***list) {
893fa014
ZJS
4472 _cleanup_closedir_ DIR *d = NULL;
4473 size_t bufsize = 0, n = 0;
4474 _cleanup_strv_free_ char **l = NULL;
034a2a52
LP
4475
4476 assert(path);
d60ef526
LP
4477
4478 /* Returns all files in a directory in *list, and the number
4479 * of files as return value. If list is NULL returns only the
893fa014 4480 * number. */
034a2a52
LP
4481
4482 d = opendir(path);
8ea913b2
LP
4483 if (!d)
4484 return -errno;
4485
034a2a52 4486 for (;;) {
7d5e9c0f 4487 struct dirent *de;
034a2a52 4488
3fd11280
FW
4489 errno = 0;
4490 de = readdir(d);
4491 if (!de && errno != 0)
4492 return -errno;
034a2a52
LP
4493 if (!de)
4494 break;
4495
4496 dirent_ensure_type(d, de);
4497
4498 if (!dirent_is_file(de))
4499 continue;
4500
d60ef526 4501 if (list) {
893fa014
ZJS
4502 /* one extra slot is needed for the terminating NULL */
4503 if (!GREEDY_REALLOC(l, bufsize, n + 2))
4504 return -ENOMEM;
034a2a52 4505
893fa014
ZJS
4506 l[n] = strdup(de->d_name);
4507 if (!l[n])
4508 return -ENOMEM;
034a2a52 4509
893fa014 4510 l[++n] = NULL;
d60ef526 4511 } else
893fa014 4512 n++;
034a2a52
LP
4513 }
4514
893fa014
ZJS
4515 if (list) {
4516 *list = l;
4517 l = NULL; /* avoid freeing */
4518 }
034a2a52 4519
893fa014 4520 return n;
034a2a52
LP
4521}
4522
b7def684 4523char *strjoin(const char *x, ...) {
911a4828
LP
4524 va_list ap;
4525 size_t l;
4526 char *r, *p;
4527
4528 va_start(ap, x);
4529
4530 if (x) {
4531 l = strlen(x);
4532
4533 for (;;) {
4534 const char *t;
040f18ea 4535 size_t n;
911a4828
LP
4536
4537 t = va_arg(ap, const char *);
4538 if (!t)
4539 break;
4540
040f18ea 4541 n = strlen(t);
e98055de
LN
4542 if (n > ((size_t) -1) - l) {
4543 va_end(ap);
040f18ea 4544 return NULL;
e98055de 4545 }
040f18ea
LP
4546
4547 l += n;
911a4828
LP
4548 }
4549 } else
4550 l = 0;
4551
4552 va_end(ap);
4553
4554 r = new(char, l+1);
4555 if (!r)
4556 return NULL;
4557
4558 if (x) {
4559 p = stpcpy(r, x);
4560
4561 va_start(ap, x);
4562
4563 for (;;) {
4564 const char *t;
4565
4566 t = va_arg(ap, const char *);
4567 if (!t)
4568 break;
4569
4570 p = stpcpy(p, t);
4571 }
8ea913b2
LP
4572
4573 va_end(ap);
911a4828
LP
4574 } else
4575 r[0] = 0;
4576
4577 return r;
4578}
4579
b636465b 4580bool is_main_thread(void) {
ec202eae 4581 static thread_local int cached = 0;
b636465b
LP
4582
4583 if (_unlikely_(cached == 0))
4584 cached = getpid() == gettid() ? 1 : -1;
4585
4586 return cached > 0;
4587}
4588
94959f0f
LP
4589int block_get_whole_disk(dev_t d, dev_t *ret) {
4590 char *p, *s;
4591 int r;
4592 unsigned n, m;
4593
4594 assert(ret);
4595
4596 /* If it has a queue this is good enough for us */
4597 if (asprintf(&p, "/sys/dev/block/%u:%u/queue", major(d), minor(d)) < 0)
4598 return -ENOMEM;
4599
4600 r = access(p, F_OK);
4601 free(p);
4602
4603 if (r >= 0) {
4604 *ret = d;
4605 return 0;
4606 }
4607
4608 /* If it is a partition find the originating device */
4609 if (asprintf(&p, "/sys/dev/block/%u:%u/partition", major(d), minor(d)) < 0)
4610 return -ENOMEM;
4611
4612 r = access(p, F_OK);
4613 free(p);
4614
4615 if (r < 0)
4616 return -ENOENT;
4617
4618 /* Get parent dev_t */
4619 if (asprintf(&p, "/sys/dev/block/%u:%u/../dev", major(d), minor(d)) < 0)
4620 return -ENOMEM;
4621
4622 r = read_one_line_file(p, &s);
4623 free(p);
4624
4625 if (r < 0)
4626 return r;
4627
4628 r = sscanf(s, "%u:%u", &m, &n);
4629 free(s);
4630
4631 if (r != 2)
4632 return -EINVAL;
4633
4634 /* Only return this if it is really good enough for us. */
4635 if (asprintf(&p, "/sys/dev/block/%u:%u/queue", m, n) < 0)
4636 return -ENOMEM;
4637
4638 r = access(p, F_OK);
4639 free(p);
4640
4641 if (r >= 0) {
4642 *ret = makedev(m, n);
4643 return 0;
4644 }
4645
4646 return -ENOENT;
4647}
4648
8d53b453 4649int file_is_priv_sticky(const char *p) {
ad293f5a
LP
4650 struct stat st;
4651
4652 assert(p);
4653
4654 if (lstat(p, &st) < 0)
4655 return -errno;
4656
4657 return
8d53b453 4658 (st.st_uid == 0 || st.st_uid == getuid()) &&
ad293f5a
LP
4659 (st.st_mode & S_ISVTX);
4660}
94959f0f 4661
f41607a6
LP
4662static const char *const ioprio_class_table[] = {
4663 [IOPRIO_CLASS_NONE] = "none",
4664 [IOPRIO_CLASS_RT] = "realtime",
4665 [IOPRIO_CLASS_BE] = "best-effort",
4666 [IOPRIO_CLASS_IDLE] = "idle"
4667};
4668
f8b69d1d 4669DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(ioprio_class, int, INT_MAX);
f41607a6
LP
4670
4671static const char *const sigchld_code_table[] = {
4672 [CLD_EXITED] = "exited",
4673 [CLD_KILLED] = "killed",
4674 [CLD_DUMPED] = "dumped",
4675 [CLD_TRAPPED] = "trapped",
4676 [CLD_STOPPED] = "stopped",
4677 [CLD_CONTINUED] = "continued",
4678};
4679
4680DEFINE_STRING_TABLE_LOOKUP(sigchld_code, int);
4681
4682static const char *const log_facility_unshifted_table[LOG_NFACILITIES] = {
4683 [LOG_FAC(LOG_KERN)] = "kern",
4684 [LOG_FAC(LOG_USER)] = "user",
4685 [LOG_FAC(LOG_MAIL)] = "mail",
4686 [LOG_FAC(LOG_DAEMON)] = "daemon",
4687 [LOG_FAC(LOG_AUTH)] = "auth",
4688 [LOG_FAC(LOG_SYSLOG)] = "syslog",
4689 [LOG_FAC(LOG_LPR)] = "lpr",
4690 [LOG_FAC(LOG_NEWS)] = "news",
4691 [LOG_FAC(LOG_UUCP)] = "uucp",
4692 [LOG_FAC(LOG_CRON)] = "cron",
4693 [LOG_FAC(LOG_AUTHPRIV)] = "authpriv",
4694 [LOG_FAC(LOG_FTP)] = "ftp",
4695 [LOG_FAC(LOG_LOCAL0)] = "local0",
4696 [LOG_FAC(LOG_LOCAL1)] = "local1",
4697 [LOG_FAC(LOG_LOCAL2)] = "local2",
4698 [LOG_FAC(LOG_LOCAL3)] = "local3",
4699 [LOG_FAC(LOG_LOCAL4)] = "local4",
4700 [LOG_FAC(LOG_LOCAL5)] = "local5",
4701 [LOG_FAC(LOG_LOCAL6)] = "local6",
4702 [LOG_FAC(LOG_LOCAL7)] = "local7"
4703};
4704
f8b69d1d 4705DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(log_facility_unshifted, int, LOG_FAC(~0));
f41607a6
LP
4706
4707static const char *const log_level_table[] = {
4708 [LOG_EMERG] = "emerg",
4709 [LOG_ALERT] = "alert",
4710 [LOG_CRIT] = "crit",
4711 [LOG_ERR] = "err",
4712 [LOG_WARNING] = "warning",
4713 [LOG_NOTICE] = "notice",
4714 [LOG_INFO] = "info",
4715 [LOG_DEBUG] = "debug"
4716};
4717
f8b69d1d 4718DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(log_level, int, LOG_DEBUG);
f41607a6
LP
4719
4720static const char* const sched_policy_table[] = {
4721 [SCHED_OTHER] = "other",
4722 [SCHED_BATCH] = "batch",
4723 [SCHED_IDLE] = "idle",
4724 [SCHED_FIFO] = "fifo",
4725 [SCHED_RR] = "rr"
4726};
4727
f8b69d1d 4728DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(sched_policy, int, INT_MAX);
f41607a6 4729
517d56b1 4730static const char* const rlimit_table[_RLIMIT_MAX] = {
f41607a6
LP
4731 [RLIMIT_CPU] = "LimitCPU",
4732 [RLIMIT_FSIZE] = "LimitFSIZE",
4733 [RLIMIT_DATA] = "LimitDATA",
4734 [RLIMIT_STACK] = "LimitSTACK",
4735 [RLIMIT_CORE] = "LimitCORE",
4736 [RLIMIT_RSS] = "LimitRSS",
4737 [RLIMIT_NOFILE] = "LimitNOFILE",
4738 [RLIMIT_AS] = "LimitAS",
4739 [RLIMIT_NPROC] = "LimitNPROC",
4740 [RLIMIT_MEMLOCK] = "LimitMEMLOCK",
4741 [RLIMIT_LOCKS] = "LimitLOCKS",
4742 [RLIMIT_SIGPENDING] = "LimitSIGPENDING",
4743 [RLIMIT_MSGQUEUE] = "LimitMSGQUEUE",
4744 [RLIMIT_NICE] = "LimitNICE",
4745 [RLIMIT_RTPRIO] = "LimitRTPRIO",
4746 [RLIMIT_RTTIME] = "LimitRTTIME"
4747};
4748
4749DEFINE_STRING_TABLE_LOOKUP(rlimit, int);
4750
4751static const char* const ip_tos_table[] = {
4752 [IPTOS_LOWDELAY] = "low-delay",
4753 [IPTOS_THROUGHPUT] = "throughput",
4754 [IPTOS_RELIABILITY] = "reliability",
4755 [IPTOS_LOWCOST] = "low-cost",
4756};
4757
f8b69d1d 4758DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(ip_tos, int, 0xff);
f41607a6 4759
4e240ab0 4760static const char *const __signal_table[] = {
f41607a6
LP
4761 [SIGHUP] = "HUP",
4762 [SIGINT] = "INT",
4763 [SIGQUIT] = "QUIT",
4764 [SIGILL] = "ILL",
4765 [SIGTRAP] = "TRAP",
4766 [SIGABRT] = "ABRT",
4767 [SIGBUS] = "BUS",
4768 [SIGFPE] = "FPE",
4769 [SIGKILL] = "KILL",
4770 [SIGUSR1] = "USR1",
4771 [SIGSEGV] = "SEGV",
4772 [SIGUSR2] = "USR2",
4773 [SIGPIPE] = "PIPE",
4774 [SIGALRM] = "ALRM",
4775 [SIGTERM] = "TERM",
4776#ifdef SIGSTKFLT
4777 [SIGSTKFLT] = "STKFLT", /* Linux on SPARC doesn't know SIGSTKFLT */
4778#endif
4779 [SIGCHLD] = "CHLD",
4780 [SIGCONT] = "CONT",
4781 [SIGSTOP] = "STOP",
4782 [SIGTSTP] = "TSTP",
4783 [SIGTTIN] = "TTIN",
4784 [SIGTTOU] = "TTOU",
4785 [SIGURG] = "URG",
4786 [SIGXCPU] = "XCPU",
4787 [SIGXFSZ] = "XFSZ",
4788 [SIGVTALRM] = "VTALRM",
4789 [SIGPROF] = "PROF",
4790 [SIGWINCH] = "WINCH",
4791 [SIGIO] = "IO",
4792 [SIGPWR] = "PWR",
4793 [SIGSYS] = "SYS"
4794};
4795
4e240ab0
MS
4796DEFINE_PRIVATE_STRING_TABLE_LOOKUP(__signal, int);
4797
4798const char *signal_to_string(int signo) {
ec202eae 4799 static thread_local char buf[sizeof("RTMIN+")-1 + DECIMAL_STR_MAX(int) + 1];
4e240ab0
MS
4800 const char *name;
4801
4802 name = __signal_to_string(signo);
4803 if (name)
4804 return name;
4805
4806 if (signo >= SIGRTMIN && signo <= SIGRTMAX)
fa70beaa 4807 snprintf(buf, sizeof(buf), "RTMIN+%d", signo - SIGRTMIN);
4e240ab0 4808 else
fa70beaa
LP
4809 snprintf(buf, sizeof(buf), "%d", signo);
4810
4e240ab0
MS
4811 return buf;
4812}
4813
4814int signal_from_string(const char *s) {
4815 int signo;
4816 int offset = 0;
4817 unsigned u;
4818
040f18ea 4819 signo = __signal_from_string(s);
4e240ab0
MS
4820 if (signo > 0)
4821 return signo;
4822
4823 if (startswith(s, "RTMIN+")) {
4824 s += 6;
4825 offset = SIGRTMIN;
4826 }
4827 if (safe_atou(s, &u) >= 0) {
4828 signo = (int) u + offset;
4829 if (signo > 0 && signo < _NSIG)
4830 return signo;
4831 }
4832 return -1;
4833}
65457142
FC
4834
4835bool kexec_loaded(void) {
4836 bool loaded = false;
4837 char *s;
4838
4839 if (read_one_line_file("/sys/kernel/kexec_loaded", &s) >= 0) {
4840 if (s[0] == '1')
4841 loaded = true;
4842 free(s);
4843 }
4844 return loaded;
4845}
fb9de93d
LP
4846
4847int strdup_or_null(const char *a, char **b) {
4848 char *c;
4849
4850 assert(b);
4851
4852 if (!a) {
4853 *b = NULL;
4854 return 0;
4855 }
4856
4857 c = strdup(a);
4858 if (!c)
4859 return -ENOMEM;
4860
4861 *b = c;
4862 return 0;
4863}
64685e0c 4864
87d2c1ff
LP
4865int prot_from_flags(int flags) {
4866
4867 switch (flags & O_ACCMODE) {
4868
4869 case O_RDONLY:
4870 return PROT_READ;
4871
4872 case O_WRONLY:
4873 return PROT_WRITE;
4874
4875 case O_RDWR:
4876 return PROT_READ|PROT_WRITE;
4877
4878 default:
4879 return -EINVAL;
4880 }
7c99e0c1 4881}
689b9a22 4882
babfc091 4883char *format_bytes(char *buf, size_t l, off_t t) {
c0f99c21 4884 unsigned i;
babfc091
LP
4885
4886 static const struct {
4887 const char *suffix;
4888 off_t factor;
4889 } table[] = {
32895bb3
LP
4890 { "E", 1024ULL*1024ULL*1024ULL*1024ULL*1024ULL*1024ULL },
4891 { "P", 1024ULL*1024ULL*1024ULL*1024ULL*1024ULL },
babfc091
LP
4892 { "T", 1024ULL*1024ULL*1024ULL*1024ULL },
4893 { "G", 1024ULL*1024ULL*1024ULL },
4894 { "M", 1024ULL*1024ULL },
4895 { "K", 1024ULL },
4896 };
4897
4898 for (i = 0; i < ELEMENTSOF(table); i++) {
4899
4900 if (t >= table[i].factor) {
4901 snprintf(buf, l,
4902 "%llu.%llu%s",
4903 (unsigned long long) (t / table[i].factor),
4904 (unsigned long long) (((t*10ULL) / table[i].factor) % 10ULL),
4905 table[i].suffix);
4906
4907 goto finish;
4908 }
4909 }
4910
4911 snprintf(buf, l, "%lluB", (unsigned long long) t);
4912
4913finish:
4914 buf[l-1] = 0;
4915 return buf;
4916
4917}
55d7bfc1
LP
4918
4919void* memdup(const void *p, size_t l) {
4920 void *r;
4921
4922 assert(p);
4923
4924 r = malloc(l);
4925 if (!r)
4926 return NULL;
4927
4928 memcpy(r, p, l);
4929 return r;
4930}
bb99a35a
LP
4931
4932int fd_inc_sndbuf(int fd, size_t n) {
4933 int r, value;
4934 socklen_t l = sizeof(value);
4935
4936 r = getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &value, &l);
92d75ca4 4937 if (r >= 0 && l == sizeof(value) && (size_t) value >= n*2)
bb99a35a
LP
4938 return 0;
4939
92d75ca4
LP
4940 /* If we have the privileges we will ignore the kernel limit. */
4941
bb99a35a 4942 value = (int) n;
92d75ca4
LP
4943 if (setsockopt(fd, SOL_SOCKET, SO_SNDBUFFORCE, &value, sizeof(value)) < 0)
4944 if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &value, sizeof(value)) < 0)
4945 return -errno;
bb99a35a
LP
4946
4947 return 1;
4948}
4949
4950int fd_inc_rcvbuf(int fd, size_t n) {
4951 int r, value;
4952 socklen_t l = sizeof(value);
4953
4954 r = getsockopt(fd, SOL_SOCKET, SO_RCVBUF, &value, &l);
92d75ca4 4955 if (r >= 0 && l == sizeof(value) && (size_t) value >= n*2)
bb99a35a
LP
4956 return 0;
4957
92d75ca4 4958 /* If we have the privileges we will ignore the kernel limit. */
bb99a35a 4959
92d75ca4
LP
4960 value = (int) n;
4961 if (setsockopt(fd, SOL_SOCKET, SO_RCVBUFFORCE, &value, sizeof(value)) < 0)
4962 if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &value, sizeof(value)) < 0)
4963 return -errno;
bb99a35a
LP
4964 return 1;
4965}
6bb92a16 4966
9bdc770c 4967int fork_agent(pid_t *pid, const int except[], unsigned n_except, const char *path, ...) {
6bb92a16
LP
4968 pid_t parent_pid, agent_pid;
4969 int fd;
4970 bool stdout_is_tty, stderr_is_tty;
4971 unsigned n, i;
4972 va_list ap;
4973 char **l;
4974
4975 assert(pid);
4976 assert(path);
4977
4978 parent_pid = getpid();
4979
4980 /* Spawns a temporary TTY agent, making sure it goes away when
4981 * we go away */
4982
4983 agent_pid = fork();
4984 if (agent_pid < 0)
4985 return -errno;
4986
4987 if (agent_pid != 0) {
4988 *pid = agent_pid;
4989 return 0;
4990 }
4991
4992 /* In the child:
4993 *
4994 * Make sure the agent goes away when the parent dies */
4995 if (prctl(PR_SET_PDEATHSIG, SIGTERM) < 0)
4996 _exit(EXIT_FAILURE);
4997
4998 /* Check whether our parent died before we were able
4999 * to set the death signal */
5000 if (getppid() != parent_pid)
5001 _exit(EXIT_SUCCESS);
5002
5003 /* Don't leak fds to the agent */
9bdc770c 5004 close_all_fds(except, n_except);
6bb92a16
LP
5005
5006 stdout_is_tty = isatty(STDOUT_FILENO);
5007 stderr_is_tty = isatty(STDERR_FILENO);
5008
5009 if (!stdout_is_tty || !stderr_is_tty) {
5010 /* Detach from stdout/stderr. and reopen
5011 * /dev/tty for them. This is important to
5012 * ensure that when systemctl is started via
5013 * popen() or a similar call that expects to
5014 * read EOF we actually do generate EOF and
5015 * not delay this indefinitely by because we
5016 * keep an unused copy of stdin around. */
5017 fd = open("/dev/tty", O_WRONLY);
5018 if (fd < 0) {
5019 log_error("Failed to open /dev/tty: %m");
5020 _exit(EXIT_FAILURE);
5021 }
5022
5023 if (!stdout_is_tty)
5024 dup2(fd, STDOUT_FILENO);
5025
5026 if (!stderr_is_tty)
5027 dup2(fd, STDERR_FILENO);
5028
5029 if (fd > 2)
5030 close(fd);
5031 }
5032
5033 /* Count arguments */
5034 va_start(ap, path);
5035 for (n = 0; va_arg(ap, char*); n++)
5036 ;
5037 va_end(ap);
5038
5039 /* Allocate strv */
5040 l = alloca(sizeof(char *) * (n + 1));
5041
5042 /* Fill in arguments */
5043 va_start(ap, path);
5044 for (i = 0; i <= n; i++)
5045 l[i] = va_arg(ap, char*);
5046 va_end(ap);
5047
5048 execv(path, l);
5049 _exit(EXIT_FAILURE);
5050}
68faf98c
LP
5051
5052int setrlimit_closest(int resource, const struct rlimit *rlim) {
5053 struct rlimit highest, fixed;
5054
5055 assert(rlim);
5056
5057 if (setrlimit(resource, rlim) >= 0)
5058 return 0;
5059
5060 if (errno != EPERM)
5061 return -errno;
5062
5063 /* So we failed to set the desired setrlimit, then let's try
5064 * to get as close as we can */
5065 assert_se(getrlimit(resource, &highest) == 0);
5066
5067 fixed.rlim_cur = MIN(rlim->rlim_cur, highest.rlim_max);
5068 fixed.rlim_max = MIN(rlim->rlim_max, highest.rlim_max);
5069
5070 if (setrlimit(resource, &fixed) < 0)
5071 return -errno;
5072
5073 return 0;
5074}
3d9a4122 5075
ab94af92 5076int getenv_for_pid(pid_t pid, const char *field, char **_value) {
49aa47c7
LP
5077 _cleanup_fclose_ FILE *f = NULL;
5078 char *value = NULL;
ab94af92 5079 int r;
ab94af92
LP
5080 bool done = false;
5081 size_t l;
49aa47c7 5082 const char *path;
ab94af92 5083
49aa47c7 5084 assert(pid >= 0);
ab94af92
LP
5085 assert(field);
5086 assert(_value);
5087
b68fa010 5088 path = procfs_file_alloca(pid, "environ");
ab94af92
LP
5089
5090 f = fopen(path, "re");
5091 if (!f)
5092 return -errno;
5093
5094 l = strlen(field);
5095 r = 0;
5096
5097 do {
5098 char line[LINE_MAX];
5099 unsigned i;
5100
5101 for (i = 0; i < sizeof(line)-1; i++) {
5102 int c;
5103
5104 c = getc(f);
5105 if (_unlikely_(c == EOF)) {
5106 done = true;
5107 break;
5108 } else if (c == 0)
5109 break;
5110
5111 line[i] = c;
5112 }
5113 line[i] = 0;
5114
5115 if (memcmp(line, field, l) == 0 && line[l] == '=') {
5116 value = strdup(line + l + 1);
49aa47c7
LP
5117 if (!value)
5118 return -ENOMEM;
ab94af92
LP
5119
5120 r = 1;
5121 break;
5122 }
5123
5124 } while (!done);
5125
49aa47c7 5126 *_value = value;
ab94af92
LP
5127 return r;
5128}
d889a206 5129
49dbfa7b
LP
5130bool is_valid_documentation_url(const char *url) {
5131 assert(url);
5132
5133 if (startswith(url, "http://") && url[7])
5134 return true;
5135
5136 if (startswith(url, "https://") && url[8])
5137 return true;
5138
5139 if (startswith(url, "file:") && url[5])
5140 return true;
5141
5142 if (startswith(url, "info:") && url[5])
5143 return true;
5144
5145 if (startswith(url, "man:") && url[4])
5146 return true;
5147
5148 return false;
5149}
9be346c9
HH
5150
5151bool in_initrd(void) {
73020ab2 5152 static int saved = -1;
825c6fe5 5153 struct statfs s;
8f33b5b8 5154
825c6fe5
LP
5155 if (saved >= 0)
5156 return saved;
5157
5158 /* We make two checks here:
5159 *
5160 * 1. the flag file /etc/initrd-release must exist
5161 * 2. the root file system must be a memory file system
5162 *
5163 * The second check is extra paranoia, since misdetecting an
5164 * initrd can have bad bad consequences due the initrd
5165 * emptying when transititioning to the main systemd.
5166 */
5167
5168 saved = access("/etc/initrd-release", F_OK) >= 0 &&
5169 statfs("/", &s) >= 0 &&
943aad8c 5170 is_temporary_fs(&s);
9be346c9 5171
8f33b5b8 5172 return saved;
9be346c9 5173}
069cfc85
LP
5174
5175void warn_melody(void) {
e67f47e5 5176 _cleanup_close_ int fd = -1;
069cfc85
LP
5177
5178 fd = open("/dev/console", O_WRONLY|O_CLOEXEC|O_NOCTTY);
5179 if (fd < 0)
5180 return;
5181
040f18ea 5182 /* Yeah, this is synchronous. Kinda sucks. But well... */
069cfc85
LP
5183
5184 ioctl(fd, KIOCSOUND, (int)(1193180/440));
5185 usleep(125*USEC_PER_MSEC);
5186
5187 ioctl(fd, KIOCSOUND, (int)(1193180/220));
5188 usleep(125*USEC_PER_MSEC);
5189
5190 ioctl(fd, KIOCSOUND, (int)(1193180/220));
5191 usleep(125*USEC_PER_MSEC);
5192
5193 ioctl(fd, KIOCSOUND, 0);
069cfc85 5194}
cd3bd60a
LP
5195
5196int make_console_stdio(void) {
5197 int fd, r;
5198
5199 /* Make /dev/console the controlling terminal and stdin/stdout/stderr */
5200
5201 fd = acquire_terminal("/dev/console", false, true, true, (usec_t) -1);
5202 if (fd < 0) {
5203 log_error("Failed to acquire terminal: %s", strerror(-fd));
5204 return fd;
5205 }
5206
5207 r = make_stdio(fd);
5208 if (r < 0) {
5209 log_error("Failed to duplicate terminal fd: %s", strerror(-r));
5210 return r;
5211 }
5212
5213 return 0;
5214}
7c5f152a
LP
5215
5216int get_home_dir(char **_h) {
2cfbd749 5217 struct passwd *p;
7c5f152a 5218 const char *e;
2cfbd749 5219 char *h;
7c5f152a 5220 uid_t u;
7c5f152a
LP
5221
5222 assert(_h);
5223
5224 /* Take the user specified one */
5225 e = getenv("HOME");
5226 if (e) {
5227 h = strdup(e);
5228 if (!h)
5229 return -ENOMEM;
5230
5231 *_h = h;
5232 return 0;
5233 }
5234
5235 /* Hardcode home directory for root to avoid NSS */
5236 u = getuid();
5237 if (u == 0) {
5238 h = strdup("/root");
5239 if (!h)
5240 return -ENOMEM;
5241
5242 *_h = h;
5243 return 0;
5244 }
5245
5246 /* Check the database... */
5247 errno = 0;
5248 p = getpwuid(u);
5249 if (!p)
bcb161b0 5250 return errno > 0 ? -errno : -ESRCH;
7c5f152a
LP
5251
5252 if (!path_is_absolute(p->pw_dir))
5253 return -EINVAL;
5254
5255 h = strdup(p->pw_dir);
5256 if (!h)
5257 return -ENOMEM;
5258
5259 *_h = h;
5260 return 0;
5261}
5262
2cfbd749
LP
5263int get_shell(char **_s) {
5264 struct passwd *p;
5265 const char *e;
5266 char *s;
5267 uid_t u;
5268
5269 assert(_s);
5270
5271 /* Take the user specified one */
5272 e = getenv("SHELL");
5273 if (e) {
5274 s = strdup(e);
5275 if (!s)
5276 return -ENOMEM;
5277
5278 *_s = s;
5279 return 0;
5280 }
5281
5282 /* Hardcode home directory for root to avoid NSS */
5283 u = getuid();
5284 if (u == 0) {
5285 s = strdup("/bin/sh");
5286 if (!s)
5287 return -ENOMEM;
5288
5289 *_s = s;
5290 return 0;
5291 }
5292
5293 /* Check the database... */
5294 errno = 0;
5295 p = getpwuid(u);
5296 if (!p)
5297 return errno > 0 ? -errno : -ESRCH;
5298
5299 if (!path_is_absolute(p->pw_shell))
5300 return -EINVAL;
5301
5302 s = strdup(p->pw_shell);
5303 if (!s)
5304 return -ENOMEM;
5305
5306 *_s = s;
5307 return 0;
5308}
5309
0b507b17
LP
5310bool filename_is_safe(const char *p) {
5311
5312 if (isempty(p))
5313 return false;
5314
5315 if (strchr(p, '/'))
5316 return false;
5317
5318 if (streq(p, "."))
5319 return false;
5320
5321 if (streq(p, ".."))
5322 return false;
5323
5324 if (strlen(p) > FILENAME_MAX)
5325 return false;
5326
5327 return true;
5328}
5329
5330bool string_is_safe(const char *p) {
5331 const char *t;
5332
5333 assert(p);
5334
5335 for (t = p; *t; t++) {
01539d6e 5336 if (*t > 0 && *t < ' ')
0b507b17
LP
5337 return false;
5338
011afa76 5339 if (strchr("\\\"\'", *t))
0b507b17
LP
5340 return false;
5341 }
5342
5343 return true;
5344}
cfbc22ab 5345
ac4c8d6d
ZJS
5346/**
5347 * Check if a string contains control characters.
5348 * Spaces and tabs are not considered control characters.
5349 */
4d1a6904
LP
5350bool string_has_cc(const char *p) {
5351 const char *t;
5352
5353 assert(p);
5354
5355 for (t = p; *t; t++)
da2620a5 5356 if (*t > 0 && *t < ' ' && *t != '\t')
4d1a6904
LP
5357 return true;
5358
5359 return false;
5360}
5361
e884315e
LP
5362bool path_is_safe(const char *p) {
5363
5364 if (isempty(p))
5365 return false;
5366
5367 if (streq(p, "..") || startswith(p, "../") || endswith(p, "/..") || strstr(p, "/../"))
5368 return false;
5369
5370 if (strlen(p) > PATH_MAX)
5371 return false;
5372
5373 /* The following two checks are not really dangerous, but hey, they still are confusing */
5374 if (streq(p, ".") || startswith(p, "./") || endswith(p, "/.") || strstr(p, "/./"))
5375 return false;
5376
5377 if (strstr(p, "//"))
5378 return false;
5379
5380 return true;
5381}
5382
a9e12476
KS
5383/* hey glibc, APIs with callbacks without a user pointer are so useless */
5384void *xbsearch_r(const void *key, const void *base, size_t nmemb, size_t size,
1c574591 5385 int (*compar) (const void *, const void *, void *), void *arg) {
a9e12476
KS
5386 size_t l, u, idx;
5387 const void *p;
5388 int comparison;
5389
5390 l = 0;
5391 u = nmemb;
5392 while (l < u) {
5393 idx = (l + u) / 2;
5394 p = (void *)(((const char *) base) + (idx * size));
5395 comparison = compar(key, p, arg);
5396 if (comparison < 0)
5397 u = idx;
5398 else if (comparison > 0)
5399 l = idx + 1;
5400 else
5401 return (void *)p;
5402 }
5403 return NULL;
5404}
09017585
MS
5405
5406bool is_locale_utf8(void) {
5407 const char *set;
5408 static int cached_answer = -1;
5409
5410 if (cached_answer >= 0)
5411 goto out;
5412
5413 if (!setlocale(LC_ALL, "")) {
5414 cached_answer = true;
5415 goto out;
5416 }
5417
5418 set = nl_langinfo(CODESET);
5419 if (!set) {
5420 cached_answer = true;
5421 goto out;
5422 }
5423
f168c273 5424 if (streq(set, "UTF-8")) {
fee79e01
HH
5425 cached_answer = true;
5426 goto out;
5427 }
5428
6cf2f1d9
HH
5429 /* For LC_CTYPE=="C" return true, because CTYPE is effectly
5430 * unset and everything can do to UTF-8 nowadays. */
fee79e01
HH
5431 set = setlocale(LC_CTYPE, NULL);
5432 if (!set) {
5433 cached_answer = true;
5434 goto out;
5435 }
5436
6cf2f1d9
HH
5437 /* Check result, but ignore the result if C was set
5438 * explicitly. */
5439 cached_answer =
5440 streq(set, "C") &&
5441 !getenv("LC_ALL") &&
5442 !getenv("LC_CTYPE") &&
5443 !getenv("LANG");
fee79e01 5444
09017585 5445out:
6cf2f1d9 5446 return (bool) cached_answer;
09017585 5447}
c339d977
MS
5448
5449const char *draw_special_char(DrawSpecialChar ch) {
5450 static const char *draw_table[2][_DRAW_SPECIAL_CHAR_MAX] = {
6b01f1d3 5451
c339d977 5452 /* UTF-8 */ {
6b01f1d3 5453 [DRAW_TREE_VERTICAL] = "\342\224\202 ", /* │ */
45a5ff0d
MS
5454 [DRAW_TREE_BRANCH] = "\342\224\234\342\224\200", /* ├─ */
5455 [DRAW_TREE_RIGHT] = "\342\224\224\342\224\200", /* └─ */
55c0b89c 5456 [DRAW_TREE_SPACE] = " ", /* */
6b01f1d3
LP
5457 [DRAW_TRIANGULAR_BULLET] = "\342\200\243", /* ‣ */
5458 [DRAW_BLACK_CIRCLE] = "\342\227\217", /* ● */
5459 [DRAW_ARROW] = "\342\206\222", /* → */
13f8b8cb 5460 [DRAW_DASH] = "\342\200\223", /* – */
c339d977 5461 },
6b01f1d3 5462
c339d977 5463 /* ASCII fallback */ {
6b01f1d3 5464 [DRAW_TREE_VERTICAL] = "| ",
45a5ff0d
MS
5465 [DRAW_TREE_BRANCH] = "|-",
5466 [DRAW_TREE_RIGHT] = "`-",
55c0b89c 5467 [DRAW_TREE_SPACE] = " ",
6b01f1d3
LP
5468 [DRAW_TRIANGULAR_BULLET] = ">",
5469 [DRAW_BLACK_CIRCLE] = "*",
5470 [DRAW_ARROW] = "->",
13f8b8cb 5471 [DRAW_DASH] = "-",
c339d977
MS
5472 }
5473 };
5474
5475 return draw_table[!is_locale_utf8()][ch];
5476}
409bc9c3
LP
5477
5478char *strreplace(const char *text, const char *old_string, const char *new_string) {
5479 const char *f;
5480 char *t, *r;
5481 size_t l, old_len, new_len;
5482
5483 assert(text);
5484 assert(old_string);
5485 assert(new_string);
5486
5487 old_len = strlen(old_string);
5488 new_len = strlen(new_string);
5489
5490 l = strlen(text);
5491 r = new(char, l+1);
5492 if (!r)
5493 return NULL;
5494
5495 f = text;
5496 t = r;
5497 while (*f) {
5498 char *a;
5499 size_t d, nl;
5500
5501 if (!startswith(f, old_string)) {
5502 *(t++) = *(f++);
5503 continue;
5504 }
5505
5506 d = t - r;
5507 nl = l - old_len + new_len;
5508 a = realloc(r, nl + 1);
5509 if (!a)
5510 goto oom;
5511
5512 l = nl;
5513 r = a;
5514 t = r + d;
5515
5516 t = stpcpy(t, new_string);
5517 f += old_len;
5518 }
5519
5520 *t = 0;
5521 return r;
5522
5523oom:
5524 free(r);
5525 return NULL;
5526}
e8bc0ea2
LP
5527
5528char *strip_tab_ansi(char **ibuf, size_t *_isz) {
660ddc72 5529 const char *i, *begin = NULL;
e8bc0ea2
LP
5530 enum {
5531 STATE_OTHER,
5532 STATE_ESCAPE,
5533 STATE_BRACKET
5534 } state = STATE_OTHER;
5535 char *obuf = NULL;
5536 size_t osz = 0, isz;
5537 FILE *f;
5538
5539 assert(ibuf);
5540 assert(*ibuf);
5541
5542 /* Strips ANSI color and replaces TABs by 8 spaces */
5543
5544 isz = _isz ? *_isz : strlen(*ibuf);
5545
5546 f = open_memstream(&obuf, &osz);
5547 if (!f)
5548 return NULL;
5549
5550 for (i = *ibuf; i < *ibuf + isz + 1; i++) {
5551
5552 switch (state) {
5553
5554 case STATE_OTHER:
5555 if (i >= *ibuf + isz) /* EOT */
5556 break;
5557 else if (*i == '\x1B')
5558 state = STATE_ESCAPE;
5559 else if (*i == '\t')
5560 fputs(" ", f);
5561 else
5562 fputc(*i, f);
5563 break;
5564
5565 case STATE_ESCAPE:
5566 if (i >= *ibuf + isz) { /* EOT */
5567 fputc('\x1B', f);
5568 break;
5569 } else if (*i == '[') {
5570 state = STATE_BRACKET;
5571 begin = i + 1;
5572 } else {
5573 fputc('\x1B', f);
5574 fputc(*i, f);
5575 state = STATE_OTHER;
5576 }
5577
5578 break;
5579
5580 case STATE_BRACKET:
5581
5582 if (i >= *ibuf + isz || /* EOT */
5583 (!(*i >= '0' && *i <= '9') && *i != ';' && *i != 'm')) {
5584 fputc('\x1B', f);
5585 fputc('[', f);
5586 state = STATE_OTHER;
5587 i = begin-1;
5588 } else if (*i == 'm')
5589 state = STATE_OTHER;
5590 break;
5591 }
5592 }
5593
5594 if (ferror(f)) {
5595 fclose(f);
5596 free(obuf);
5597 return NULL;
5598 }
5599
5600 fclose(f);
5601
5602 free(*ibuf);
5603 *ibuf = obuf;
5604
5605 if (_isz)
5606 *_isz = osz;
5607
5608 return obuf;
5609}
240dbaa4
LP
5610
5611int on_ac_power(void) {
5612 bool found_offline = false, found_online = false;
5613 _cleanup_closedir_ DIR *d = NULL;
5614
5615 d = opendir("/sys/class/power_supply");
5616 if (!d)
5617 return -errno;
5618
5619 for (;;) {
5620 struct dirent *de;
240dbaa4
LP
5621 _cleanup_close_ int fd = -1, device = -1;
5622 char contents[6];
5623 ssize_t n;
240dbaa4 5624
3fd11280
FW
5625 errno = 0;
5626 de = readdir(d);
5627 if (!de && errno != 0)
5628 return -errno;
240dbaa4
LP
5629
5630 if (!de)
5631 break;
5632
5633 if (ignore_file(de->d_name))
5634 continue;
5635
5636 device = openat(dirfd(d), de->d_name, O_DIRECTORY|O_RDONLY|O_CLOEXEC|O_NOCTTY);
5637 if (device < 0) {
5638 if (errno == ENOENT || errno == ENOTDIR)
5639 continue;
5640
5641 return -errno;
5642 }
5643
5644 fd = openat(device, "type", O_RDONLY|O_CLOEXEC|O_NOCTTY);
5645 if (fd < 0) {
5646 if (errno == ENOENT)
5647 continue;
5648
5649 return -errno;
5650 }
5651
5652 n = read(fd, contents, sizeof(contents));
5653 if (n < 0)
5654 return -errno;
5655
5656 if (n != 6 || memcmp(contents, "Mains\n", 6))
5657 continue;
5658
03e334a1 5659 safe_close(fd);
240dbaa4
LP
5660 fd = openat(device, "online", O_RDONLY|O_CLOEXEC|O_NOCTTY);
5661 if (fd < 0) {
5662 if (errno == ENOENT)
5663 continue;
5664
5665 return -errno;
5666 }
5667
5668 n = read(fd, contents, sizeof(contents));
5669 if (n < 0)
5670 return -errno;
5671
5672 if (n != 2 || contents[1] != '\n')
5673 return -EIO;
5674
5675 if (contents[0] == '1') {
5676 found_online = true;
5677 break;
5678 } else if (contents[0] == '0')
5679 found_offline = true;
5680 else
5681 return -EIO;
5682 }
5683
5684 return found_online || !found_offline;
5685}
fabe5c0e 5686
4cf7ea55 5687static int search_and_fopen_internal(const char *path, const char *mode, const char *root, char **search, FILE **_f) {
fabe5c0e
LP
5688 char **i;
5689
5690 assert(path);
5691 assert(mode);
5692 assert(_f);
5693
4cf7ea55 5694 if (!path_strv_canonicalize_absolute_uniq(search, root))
fabe5c0e
LP
5695 return -ENOMEM;
5696
5697 STRV_FOREACH(i, search) {
5698 _cleanup_free_ char *p = NULL;
5699 FILE *f;
5700
5701 p = strjoin(*i, "/", path, NULL);
5702 if (!p)
5703 return -ENOMEM;
5704
5705 f = fopen(p, mode);
5706 if (f) {
5707 *_f = f;
5708 return 0;
5709 }
5710
5711 if (errno != ENOENT)
5712 return -errno;
5713 }
5714
5715 return -ENOENT;
5716}
5717
4cf7ea55 5718int search_and_fopen(const char *path, const char *mode, const char *root, const char **search, FILE **_f) {
fabe5c0e
LP
5719 _cleanup_strv_free_ char **copy = NULL;
5720
5721 assert(path);
5722 assert(mode);
5723 assert(_f);
5724
5725 if (path_is_absolute(path)) {
5726 FILE *f;
5727
5728 f = fopen(path, mode);
5729 if (f) {
5730 *_f = f;
5731 return 0;
5732 }
5733
5734 return -errno;
5735 }
5736
5737 copy = strv_copy((char**) search);
5738 if (!copy)
5739 return -ENOMEM;
5740
4cf7ea55 5741 return search_and_fopen_internal(path, mode, root, copy, _f);
fabe5c0e
LP
5742}
5743
4cf7ea55 5744int search_and_fopen_nulstr(const char *path, const char *mode, const char *root, const char *search, FILE **_f) {
fabe5c0e
LP
5745 _cleanup_strv_free_ char **s = NULL;
5746
5747 if (path_is_absolute(path)) {
5748 FILE *f;
5749
5750 f = fopen(path, mode);
5751 if (f) {
5752 *_f = f;
5753 return 0;
5754 }
5755
5756 return -errno;
5757 }
5758
5759 s = strv_split_nulstr(search);
5760 if (!s)
5761 return -ENOMEM;
5762
4cf7ea55 5763 return search_and_fopen_internal(path, mode, root, s, _f);
fabe5c0e 5764}
c17ec25e 5765
66e35261
LP
5766char *strextend(char **x, ...) {
5767 va_list ap;
5768 size_t f, l;
5769 char *r, *p;
5770
5771 assert(x);
5772
5773 l = f = *x ? strlen(*x) : 0;
5774
5775 va_start(ap, x);
5776 for (;;) {
5777 const char *t;
5778 size_t n;
5779
5780 t = va_arg(ap, const char *);
5781 if (!t)
5782 break;
5783
5784 n = strlen(t);
5785 if (n > ((size_t) -1) - l) {
5786 va_end(ap);
5787 return NULL;
5788 }
5789
5790 l += n;
5791 }
5792 va_end(ap);
5793
5794 r = realloc(*x, l+1);
5795 if (!r)
5796 return NULL;
5797
5798 p = r + f;
5799
5800 va_start(ap, x);
5801 for (;;) {
5802 const char *t;
5803
5804 t = va_arg(ap, const char *);
5805 if (!t)
5806 break;
5807
5808 p = stpcpy(p, t);
5809 }
5810 va_end(ap);
5811
5812 *p = 0;
5813 *x = r;
5814
5815 return r + l;
5816}
9a17484d
LP
5817
5818char *strrep(const char *s, unsigned n) {
5819 size_t l;
5820 char *r, *p;
5821 unsigned i;
5822
5823 assert(s);
5824
5825 l = strlen(s);
5826 p = r = malloc(l * n + 1);
5827 if (!r)
5828 return NULL;
5829
5830 for (i = 0; i < n; i++)
5831 p = stpcpy(p, s);
5832
5833 *p = 0;
5834 return r;
5835}
392d5b37 5836
ca2d3784
ZJS
5837void* greedy_realloc(void **p, size_t *allocated, size_t need, size_t size) {
5838 size_t a, newalloc;
392d5b37
LP
5839 void *q;
5840
98088803 5841 assert(p);
e93c33d4
SL
5842 assert(allocated);
5843
392d5b37
LP
5844 if (*allocated >= need)
5845 return *p;
5846
ca2d3784
ZJS
5847 newalloc = MAX(need * 2, 64u / size);
5848 a = newalloc * size;
98088803
LP
5849
5850 /* check for overflows */
ca2d3784 5851 if (a < size * need)
98088803
LP
5852 return NULL;
5853
392d5b37
LP
5854 q = realloc(*p, a);
5855 if (!q)
5856 return NULL;
5857
5858 *p = q;
ca2d3784 5859 *allocated = newalloc;
392d5b37
LP
5860 return q;
5861}
aa96c6cb 5862
ca2d3784 5863void* greedy_realloc0(void **p, size_t *allocated, size_t need, size_t size) {
98088803 5864 size_t prev;
4545a231
DH
5865 uint8_t *q;
5866
98088803
LP
5867 assert(p);
5868 assert(allocated);
5869
5870 prev = *allocated;
5871
ca2d3784 5872 q = greedy_realloc(p, allocated, need, size);
4545a231
DH
5873 if (!q)
5874 return NULL;
5875
5876 if (*allocated > prev)
ca2d3784 5877 memzero(q + prev * size, (*allocated - prev) * size);
4545a231
DH
5878
5879 return q;
5880}
5881
aa96c6cb
LP
5882bool id128_is_valid(const char *s) {
5883 size_t i, l;
5884
5885 l = strlen(s);
5886 if (l == 32) {
5887
5888 /* Simple formatted 128bit hex string */
5889
5890 for (i = 0; i < l; i++) {
5891 char c = s[i];
5892
5893 if (!(c >= '0' && c <= '9') &&
5894 !(c >= 'a' && c <= 'z') &&
5895 !(c >= 'A' && c <= 'Z'))
5896 return false;
5897 }
5898
5899 } else if (l == 36) {
5900
5901 /* Formatted UUID */
5902
5903 for (i = 0; i < l; i++) {
5904 char c = s[i];
5905
5906 if ((i == 8 || i == 13 || i == 18 || i == 23)) {
5907 if (c != '-')
5908 return false;
5909 } else {
5910 if (!(c >= '0' && c <= '9') &&
5911 !(c >= 'a' && c <= 'z') &&
5912 !(c >= 'A' && c <= 'Z'))
5913 return false;
5914 }
5915 }
5916
5917 } else
5918 return false;
5919
5920 return true;
5921}
7085053a 5922
d4ac85c6
LP
5923int split_pair(const char *s, const char *sep, char **l, char **r) {
5924 char *x, *a, *b;
5925
5926 assert(s);
5927 assert(sep);
5928 assert(l);
5929 assert(r);
5930
5931 if (isempty(sep))
5932 return -EINVAL;
5933
5934 x = strstr(s, sep);
5935 if (!x)
5936 return -EINVAL;
5937
5938 a = strndup(s, x - s);
5939 if (!a)
5940 return -ENOMEM;
5941
5942 b = strdup(x + strlen(sep));
5943 if (!b) {
5944 free(a);
5945 return -ENOMEM;
5946 }
5947
5948 *l = a;
5949 *r = b;
5950
5951 return 0;
5952}
295edddf 5953
74df0fca 5954int shall_restore_state(void) {
059cb385 5955 _cleanup_free_ char *line = NULL;
295edddf 5956 char *w, *state;
295edddf 5957 size_t l;
74df0fca 5958 int r;
295edddf 5959
74df0fca
LP
5960 r = proc_cmdline(&line);
5961 if (r < 0)
5962 return r;
5963 if (r == 0) /* Container ... */
5964 return 1;
295edddf 5965
059cb385 5966 r = 1;
74df0fca 5967
059cb385
LP
5968 FOREACH_WORD_QUOTED(w, l, line, state) {
5969 const char *e;
5970 char n[l+1];
5971 int k;
5972
5973 memcpy(n, w, l);
5974 n[l] = 0;
5975
5976 e = startswith(n, "systemd.restore_state=");
5977 if (!e)
5978 continue;
5979
5980 k = parse_boolean(e);
5981 if (k >= 0)
5982 r = k;
5983 }
5984
5985 return r;
74df0fca
LP
5986}
5987
5988int proc_cmdline(char **ret) {
5989 int r;
5990
5991 if (detect_container(NULL) > 0) {
39883f62 5992 char *buf = NULL, *p;
02bb6cda
LP
5993 size_t sz = 0;
5994
5995 r = read_full_file("/proc/1/cmdline", &buf, &sz);
5996 if (r < 0)
5997 return r;
5998
5999 for (p = buf; p + 1 < buf + sz; p++)
6000 if (*p == 0)
6001 *p = ' ';
6002
059cb385 6003 *p = 0;
02bb6cda
LP
6004 *ret = buf;
6005 return 1;
295edddf
TG
6006 }
6007
74df0fca
LP
6008 r = read_one_line_file("/proc/cmdline", ret);
6009 if (r < 0)
6010 return r;
295edddf 6011
74df0fca 6012 return 1;
295edddf 6013}
bc9fd78c 6014
059cb385 6015int parse_proc_cmdline(int (*parse_item)(const char *key, const char *value)) {
141a79f4
ZJS
6016 _cleanup_free_ char *line = NULL;
6017 char *w, *state;
6018 size_t l;
6019 int r;
6020
059cb385
LP
6021 assert(parse_item);
6022
141a79f4
ZJS
6023 r = proc_cmdline(&line);
6024 if (r < 0)
6025 log_warning("Failed to read /proc/cmdline, ignoring: %s", strerror(-r));
6026 if (r <= 0)
6027 return 0;
6028
6029 FOREACH_WORD_QUOTED(w, l, line, state) {
059cb385 6030 char word[l+1], *value;
141a79f4 6031
059cb385
LP
6032 memcpy(word, w, l);
6033 word[l] = 0;
141a79f4 6034
059cb385
LP
6035 /* Filter out arguments that are intended only for the
6036 * initrd */
6037 if (!in_initrd() && startswith(word, "rd."))
6038 continue;
6039
6040 value = strchr(word, '=');
6041 if (value)
6042 *(value++) = 0;
6043
6044 r = parse_item(word, value);
6045 if (r < 0)
141a79f4 6046 return r;
141a79f4
ZJS
6047 }
6048
6049 return 0;
6050}
6051
bc9fd78c
LP
6052int container_get_leader(const char *machine, pid_t *pid) {
6053 _cleanup_free_ char *s = NULL, *class = NULL;
6054 const char *p;
6055 pid_t leader;
6056 int r;
6057
6058 assert(machine);
6059 assert(pid);
6060
6061 p = strappenda("/run/systemd/machines/", machine);
6062 r = parse_env_file(p, NEWLINE, "LEADER", &s, "CLASS", &class, NULL);
6063 if (r == -ENOENT)
6064 return -EHOSTDOWN;
6065 if (r < 0)
6066 return r;
6067 if (!s)
6068 return -EIO;
6069
6070 if (!streq_ptr(class, "container"))
6071 return -EIO;
6072
6073 r = parse_pid(s, &leader);
6074 if (r < 0)
6075 return r;
6076 if (leader <= 1)
6077 return -EIO;
6078
6079 *pid = leader;
6080 return 0;
6081}
6082
878cd7e9
LP
6083int namespace_open(pid_t pid, int *pidns_fd, int *mntns_fd, int *netns_fd, int *root_fd) {
6084 _cleanup_close_ int pidnsfd = -1, mntnsfd = -1, netnsfd = -1;
359a06aa 6085 int rfd = -1;
bc9fd78c
LP
6086
6087 assert(pid >= 0);
bc9fd78c 6088
878cd7e9
LP
6089 if (mntns_fd) {
6090 const char *mntns;
a4475f57 6091
878cd7e9
LP
6092 mntns = procfs_file_alloca(pid, "ns/mnt");
6093 mntnsfd = open(mntns, O_RDONLY|O_NOCTTY|O_CLOEXEC);
6094 if (mntnsfd < 0)
6095 return -errno;
6096 }
bc9fd78c 6097
878cd7e9
LP
6098 if (pidns_fd) {
6099 const char *pidns;
6100
6101 pidns = procfs_file_alloca(pid, "ns/pid");
6102 pidnsfd = open(pidns, O_RDONLY|O_NOCTTY|O_CLOEXEC);
6103 if (pidnsfd < 0)
6104 return -errno;
6105 }
6106
6107 if (netns_fd) {
6108 const char *netns;
6109
6110 netns = procfs_file_alloca(pid, "ns/net");
6111 netnsfd = open(netns, O_RDONLY|O_NOCTTY|O_CLOEXEC);
6112 if (netnsfd < 0)
6113 return -errno;
6114 }
6115
6116 if (root_fd) {
6117 const char *root;
6118
6119 root = procfs_file_alloca(pid, "root");
6120 rfd = open(root, O_RDONLY|O_NOCTTY|O_CLOEXEC|O_DIRECTORY);
6121 if (rfd < 0)
6122 return -errno;
6123 }
6124
6125 if (pidns_fd)
6126 *pidns_fd = pidnsfd;
bc9fd78c 6127
878cd7e9
LP
6128 if (mntns_fd)
6129 *mntns_fd = mntnsfd;
6130
6131 if (netns_fd)
6132 *netns_fd = netnsfd;
6133
6134 if (root_fd)
6135 *root_fd = rfd;
6136
6137 pidnsfd = mntnsfd = netnsfd = -1;
bc9fd78c
LP
6138
6139 return 0;
6140}
6141
878cd7e9 6142int namespace_enter(int pidns_fd, int mntns_fd, int netns_fd, int root_fd) {
bc9fd78c 6143
878cd7e9
LP
6144 if (pidns_fd >= 0)
6145 if (setns(pidns_fd, CLONE_NEWPID) < 0)
6146 return -errno;
a4475f57 6147
878cd7e9
LP
6148 if (mntns_fd >= 0)
6149 if (setns(mntns_fd, CLONE_NEWNS) < 0)
6150 return -errno;
bc9fd78c 6151
878cd7e9
LP
6152 if (netns_fd >= 0)
6153 if (setns(netns_fd, CLONE_NEWNET) < 0)
6154 return -errno;
bc9fd78c 6155
878cd7e9
LP
6156 if (root_fd >= 0) {
6157 if (fchdir(root_fd) < 0)
6158 return -errno;
6159
6160 if (chroot(".") < 0)
6161 return -errno;
6162 }
bc9fd78c 6163
5e2b3214
LP
6164 if (setresgid(0, 0, 0) < 0)
6165 return -errno;
6166
878cd7e9
LP
6167 if (setgroups(0, NULL) < 0)
6168 return -errno;
6169
5e2b3214
LP
6170 if (setresuid(0, 0, 0) < 0)
6171 return -errno;
6172
bc9fd78c
LP
6173 return 0;
6174}
bf108e55 6175
9f5650ae
LP
6176bool pid_is_unwaited(pid_t pid) {
6177 /* Checks whether a PID is still valid at all, including a zombie */
6178
bf108e55
LP
6179 if (pid <= 0)
6180 return false;
6181
6182 if (kill(pid, 0) >= 0)
6183 return true;
6184
6185 return errno != ESRCH;
6186}
eff05270 6187
9f5650ae
LP
6188bool pid_is_alive(pid_t pid) {
6189 int r;
6190
6191 /* Checks whether a PID is still valid and not a zombie */
6192
6193 if (pid <= 0)
6194 return false;
6195
6196 r = get_process_state(pid);
6197 if (r == -ENOENT || r == 'Z')
6198 return false;
6199
6200 return true;
6201}
6202
eff05270
LP
6203int getpeercred(int fd, struct ucred *ucred) {
6204 socklen_t n = sizeof(struct ucred);
6205 struct ucred u;
6206 int r;
6207
6208 assert(fd >= 0);
6209 assert(ucred);
6210
6211 r = getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &u, &n);
6212 if (r < 0)
6213 return -errno;
6214
6215 if (n != sizeof(struct ucred))
6216 return -EIO;
6217
6218 /* Check if the data is actually useful and not suppressed due
6219 * to namespacing issues */
6220 if (u.pid <= 0)
6221 return -ENODATA;
6222
6223 *ucred = u;
6224 return 0;
6225}
6226
6227int getpeersec(int fd, char **ret) {
6228 socklen_t n = 64;
6229 char *s;
6230 int r;
6231
6232 assert(fd >= 0);
6233 assert(ret);
6234
6235 s = new0(char, n);
6236 if (!s)
6237 return -ENOMEM;
6238
6239 r = getsockopt(fd, SOL_SOCKET, SO_PEERSEC, s, &n);
6240 if (r < 0) {
6241 free(s);
6242
6243 if (errno != ERANGE)
6244 return -errno;
6245
6246 s = new0(char, n);
6247 if (!s)
6248 return -ENOMEM;
6249
6250 r = getsockopt(fd, SOL_SOCKET, SO_PEERSEC, s, &n);
6251 if (r < 0) {
6252 free(s);
6253 return -errno;
6254 }
6255 }
6256
ae98841e
LP
6257 if (isempty(s)) {
6258 free(s);
6259 return -ENOTSUP;
6260 }
6261
eff05270
LP
6262 *ret = s;
6263 return 0;
6264}
8e33886e 6265
0f010ef2 6266/* This is much like like mkostemp() but is subject to umask(). */
65b3903f 6267int mkostemp_safe(char *pattern, int flags) {
2d5bdf5b 6268 _cleanup_umask_ mode_t u;
0f010ef2 6269 int fd;
65b3903f 6270
d37a91e8 6271 assert(pattern);
65b3903f 6272
2d5bdf5b
LP
6273 u = umask(077);
6274
0f010ef2
ZJS
6275 fd = mkostemp(pattern, flags);
6276 if (fd < 0)
6277 return -errno;
65b3903f 6278
0f010ef2 6279 return fd;
65b3903f
ZJS
6280}
6281
8e33886e 6282int open_tmpfile(const char *path, int flags) {
8e33886e 6283 char *p;
a6afc4ae
LP
6284 int fd;
6285
6286 assert(path);
8e33886e
ZJS
6287
6288#ifdef O_TMPFILE
7736202c
LP
6289 /* Try O_TMPFILE first, if it is supported */
6290 fd = open(path, flags|O_TMPFILE, S_IRUSR|S_IWUSR);
8e33886e
ZJS
6291 if (fd >= 0)
6292 return fd;
6293#endif
7736202c
LP
6294
6295 /* Fall back to unguessable name + unlinking */
8e33886e
ZJS
6296 p = strappenda(path, "/systemd-tmp-XXXXXX");
6297
a6afc4ae 6298 fd = mkostemp_safe(p, flags);
8e33886e 6299 if (fd < 0)
65b3903f 6300 return fd;
8e33886e
ZJS
6301
6302 unlink(p);
6303 return fd;
6304}
fdb9161c
LP
6305
6306int fd_warn_permissions(const char *path, int fd) {
6307 struct stat st;
6308
6309 if (fstat(fd, &st) < 0)
6310 return -errno;
6311
6312 if (st.st_mode & 0111)
6313 log_warning("Configuration file %s is marked executable. Please remove executable permission bits. Proceeding anyway.", path);
6314
6315 if (st.st_mode & 0002)
6316 log_warning("Configuration file %s is marked world-writable. Please remove world writability permission bits. Proceeding anyway.", path);
6317
6318 if (getpid() == 1 && (st.st_mode & 0044) != 0044)
6319 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);
6320
6321 return 0;
6322}
6afc95b7 6323
ac45f971 6324unsigned long personality_from_string(const char *p) {
6afc95b7
LP
6325
6326 /* Parse a personality specifier. We introduce our own
6327 * identifiers that indicate specific ABIs, rather than just
6328 * hints regarding the register size, since we want to keep
6329 * things open for multiple locally supported ABIs for the
6330 * same register size. We try to reuse the ABI identifiers
6331 * used by libseccomp. */
6332
6333#if defined(__x86_64__)
6334
6335 if (streq(p, "x86"))
6336 return PER_LINUX32;
6337
6338 if (streq(p, "x86-64"))
6339 return PER_LINUX;
6340
6341#elif defined(__i386__)
6342
6343 if (streq(p, "x86"))
6344 return PER_LINUX;
6345#endif
6346
6347 /* personality(7) documents that 0xffffffffUL is used for
6348 * querying the current personality, hence let's use that here
6349 * as error indicator. */
6350 return 0xffffffffUL;
6351}
ac45f971
LP
6352
6353const char* personality_to_string(unsigned long p) {
6354
6355#if defined(__x86_64__)
6356
6357 if (p == PER_LINUX32)
6358 return "x86";
6359
6360 if (p == PER_LINUX)
6361 return "x86-64";
6362
6363#elif defined(__i386__)
6364
6365 if (p == PER_LINUX)
6366 return "x86";
6367#endif
6368
6369 return NULL;
6370}
1c231f56
LP
6371
6372uint64_t physical_memory(void) {
6373 long mem;
6374
6375 /* We return this as uint64_t in case we are running as 32bit
6376 * process on a 64bit kernel with huge amounts of memory */
6377
6378 mem = sysconf(_SC_PHYS_PAGES);
6379 assert(mem > 0);
6380
6381 return (uint64_t) mem * (uint64_t) page_size();
6382}
6db615c1
LP
6383
6384char* mount_test_option(const char *haystack, const char *needle) {
6385
6386 struct mntent me = {
6387 .mnt_opts = (char*) haystack
6388 };
6389
6390 assert(needle);
6391
6392 /* Like glibc's hasmntopt(), but works on a string, not a
6393 * struct mntent */
6394
6395 if (!haystack)
6396 return NULL;
6397
6398 return hasmntopt(&me, needle);
6399}
29bfbcd6
LP
6400
6401void hexdump(FILE *f, const void *p, size_t s) {
6402 const uint8_t *b = p;
6403 unsigned n = 0;
6404
6405 assert(s == 0 || b);
6406
6407 while (s > 0) {
6408 size_t i;
6409
6410 fprintf(f, "%04x ", n);
6411
6412 for (i = 0; i < 16; i++) {
6413
6414 if (i >= s)
6415 fputs(" ", f);
6416 else
6417 fprintf(f, "%02x ", b[i]);
6418
6419 if (i == 7)
6420 fputc(' ', f);
6421 }
6422
6423 fputc(' ', f);
6424
6425 for (i = 0; i < 16; i++) {
6426
6427 if (i >= s)
6428 fputc(' ', f);
6429 else
6430 fputc(isprint(b[i]) ? (char) b[i] : '.', f);
6431 }
6432
6433 fputc('\n', f);
6434
6435 if (s < 16)
6436 break;
6437
6438 n += 16;
6439 b += 16;
6440 s -= 16;
6441 }
6442}
c5220a94 6443
966bff26 6444int update_reboot_param_file(const char *param) {
c5220a94
MO
6445 int r = 0;
6446
6447 if (param) {
6448
6449 r = write_string_file(REBOOT_PARAM_FILE, param);
6450 if (r < 0)
6451 log_error("Failed to write reboot param to "
6452 REBOOT_PARAM_FILE": %s", strerror(-r));
6453 } else
6454 unlink(REBOOT_PARAM_FILE);
6455
6456 return r;
6457}
6d313367
LP
6458
6459int umount_recursive(const char *prefix, int flags) {
6460 bool again;
6461 int n = 0, r;
6462
6463 /* Try to umount everything recursively below a
6464 * directory. Also, take care of stacked mounts, and keep
6465 * unmounting them until they are gone. */
6466
6467 do {
6468 _cleanup_fclose_ FILE *proc_self_mountinfo = NULL;
6469
6470 again = false;
6471 r = 0;
6472
6473 proc_self_mountinfo = fopen("/proc/self/mountinfo", "re");
6474 if (!proc_self_mountinfo)
6475 return -errno;
6476
6477 for (;;) {
6478 _cleanup_free_ char *path = NULL, *p = NULL;
6479 int k;
6480
6481 k = fscanf(proc_self_mountinfo,
6482 "%*s " /* (1) mount id */
6483 "%*s " /* (2) parent id */
6484 "%*s " /* (3) major:minor */
6485 "%*s " /* (4) root */
6486 "%ms " /* (5) mount point */
6487 "%*s" /* (6) mount options */
6488 "%*[^-]" /* (7) optional fields */
6489 "- " /* (8) separator */
6490 "%*s " /* (9) file system type */
6491 "%*s" /* (10) mount source */
6492 "%*s" /* (11) mount options 2 */
6493 "%*[^\n]", /* some rubbish at the end */
6494 &path);
6d313367
LP
6495 if (k != 1) {
6496 if (k == EOF)
6497 break;
6498
6499 continue;
6500 }
6501
6502 p = cunescape(path);
6503 if (!p)
6504 return -ENOMEM;
6505
6506 if (!path_startswith(p, prefix))
6507 continue;
6508
6509 if (umount2(p, flags) < 0) {
6510 r = -errno;
6511 continue;
6512 }
6513
6514 again = true;
6515 n++;
6516
6517 break;
6518 }
6519
6520 } while (again);
6521
6522 return r ? r : n;
6523}
d6797c92
LP
6524
6525int bind_remount_recursive(const char *prefix, bool ro) {
6526 _cleanup_set_free_free_ Set *done = NULL;
6527 _cleanup_free_ char *cleaned = NULL;
6528 int r;
6529
6530 /* Recursively remount a directory (and all its submounts)
6531 * read-only or read-write. If the directory is already
6532 * mounted, we reuse the mount and simply mark it
6533 * MS_BIND|MS_RDONLY (or remove the MS_RDONLY for read-write
6534 * operation). If it isn't we first make it one. Afterwards we
6535 * apply MS_BIND|MS_RDONLY (or remove MS_RDONLY) to all
6536 * submounts we can access, too. When mounts are stacked on
6537 * the same mount point we only care for each individual
6538 * "top-level" mount on each point, as we cannot
6539 * influence/access the underlying mounts anyway. We do not
6540 * have any effect on future submounts that might get
6541 * propagated, they migt be writable. This includes future
6542 * submounts that have been triggered via autofs. */
6543
6544 cleaned = strdup(prefix);
6545 if (!cleaned)
6546 return -ENOMEM;
6547
6548 path_kill_slashes(cleaned);
6549
6550 done = set_new(string_hash_func, string_compare_func);
6551 if (!done)
6552 return -ENOMEM;
6553
6554 for (;;) {
6555 _cleanup_fclose_ FILE *proc_self_mountinfo = NULL;
6556 _cleanup_set_free_free_ Set *todo = NULL;
6557 bool top_autofs = false;
6558 char *x;
6559
6560 todo = set_new(string_hash_func, string_compare_func);
6561 if (!todo)
6562 return -ENOMEM;
6563
6564 proc_self_mountinfo = fopen("/proc/self/mountinfo", "re");
6565 if (!proc_self_mountinfo)
6566 return -errno;
6567
6568 for (;;) {
6569 _cleanup_free_ char *path = NULL, *p = NULL, *type = NULL;
6570 int k;
6571
6572 k = fscanf(proc_self_mountinfo,
6573 "%*s " /* (1) mount id */
6574 "%*s " /* (2) parent id */
6575 "%*s " /* (3) major:minor */
6576 "%*s " /* (4) root */
6577 "%ms " /* (5) mount point */
6578 "%*s" /* (6) mount options (superblock) */
6579 "%*[^-]" /* (7) optional fields */
6580 "- " /* (8) separator */
6581 "%ms " /* (9) file system type */
6582 "%*s" /* (10) mount source */
6583 "%*s" /* (11) mount options (bind mount) */
6584 "%*[^\n]", /* some rubbish at the end */
6585 &path,
6586 &type);
6587 if (k != 2) {
6588 if (k == EOF)
6589 break;
6590
6591 continue;
6592 }
6593
6594 p = cunescape(path);
6595 if (!p)
6596 return -ENOMEM;
6597
6598 /* Let's ignore autofs mounts. If they aren't
6599 * triggered yet, we want to avoid triggering
6600 * them, as we don't make any guarantees for
6601 * future submounts anyway. If they are
6602 * already triggered, then we will find
6603 * another entry for this. */
6604 if (streq(type, "autofs")) {
6605 top_autofs = top_autofs || path_equal(cleaned, p);
6606 continue;
6607 }
6608
6609 if (path_startswith(p, cleaned) &&
6610 !set_contains(done, p)) {
6611
6612 r = set_consume(todo, p);
6613 p = NULL;
6614
6615 if (r == -EEXIST)
6616 continue;
6617 if (r < 0)
6618 return r;
6619 }
6620 }
6621
6622 /* If we have no submounts to process anymore and if
6623 * the root is either already done, or an autofs, we
6624 * are done */
6625 if (set_isempty(todo) &&
6626 (top_autofs || set_contains(done, cleaned)))
6627 return 0;
6628
6629 if (!set_contains(done, cleaned) &&
6630 !set_contains(todo, cleaned)) {
6631 /* The prefix directory itself is not yet a
6632 * mount, make it one. */
6633 if (mount(cleaned, cleaned, NULL, MS_BIND|MS_REC, NULL) < 0)
6634 return -errno;
6635
6636 if (mount(NULL, prefix, NULL, MS_BIND|MS_REMOUNT|(ro ? MS_RDONLY : 0), NULL) < 0)
6637 return -errno;
6638
6639 x = strdup(cleaned);
6640 if (!x)
6641 return -ENOMEM;
6642
6643 r = set_consume(done, x);
6644 if (r < 0)
6645 return r;
6646 }
6647
6648 while ((x = set_steal_first(todo))) {
6649
6650 r = set_consume(done, x);
6651 if (r == -EEXIST)
6652 continue;
6653 if (r < 0)
6654 return r;
6655
6656 if (mount(NULL, x, NULL, MS_BIND|MS_REMOUNT|(ro ? MS_RDONLY : 0), NULL) < 0) {
6657
6658 /* Deal with mount points that are
6659 * obstructed by a later mount */
6660
6661 if (errno != ENOENT)
6662 return -errno;
6663 }
6664
6665 }
6666 }
6667}