]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/shared/util.c
getty-generator: properly escape instance names
[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) {
dede0e33 2674 _cleanup_closedir_ DIR *d = NULL;
8c6db833
LP
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);
dede0e33
ZJS
2697 if (!de) {
2698 if (errno != 0 && ret == 0)
3fd11280 2699 ret = -errno;
dede0e33 2700 return ret;
8c6db833
LP
2701 }
2702
8c6db833
LP
2703 if (streq(de->d_name, ".") || streq(de->d_name, ".."))
2704 continue;
2705
7925c22a
LP
2706 if (de->d_type == DT_UNKNOWN ||
2707 honour_sticky ||
2708 (de->d_type == DT_DIR && root_dev)) {
8c6db833 2709 if (fstatat(fd, de->d_name, &st, AT_SYMLINK_NOFOLLOW) < 0) {
4c633005 2710 if (ret == 0 && errno != ENOENT)
8c6db833
LP
2711 ret = -errno;
2712 continue;
2713 }
2714
2715 is_dir = S_ISDIR(st.st_mode);
7925c22a
LP
2716 keep_around =
2717 honour_sticky &&
2718 (st.st_uid == 0 || st.st_uid == getuid()) &&
2719 (st.st_mode & S_ISVTX);
ad293f5a 2720 } else {
8c6db833 2721 is_dir = de->d_type == DT_DIR;
7925c22a 2722 keep_around = false;
ad293f5a 2723 }
8c6db833
LP
2724
2725 if (is_dir) {
2726 int subdir_fd;
8c6db833 2727
597f43c7 2728 /* if root_dev is set, remove subdirectories only, if device is same as dir */
7925c22a
LP
2729 if (root_dev && st.st_dev != root_dev->st_dev)
2730 continue;
8c6db833 2731
7925c22a
LP
2732 subdir_fd = openat(fd, de->d_name,
2733 O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW|O_NOATIME);
2734 if (subdir_fd < 0) {
2735 if (ret == 0 && errno != ENOENT)
2736 ret = -errno;
2737 continue;
2738 }
2739
b3d28469 2740 r = rm_rf_children_dangerous(subdir_fd, only_dirs, honour_sticky, root_dev);
7925c22a
LP
2741 if (r < 0 && ret == 0)
2742 ret = r;
2743
2744 if (!keep_around)
2745 if (unlinkat(fd, de->d_name, AT_REMOVEDIR) < 0) {
ad293f5a
LP
2746 if (ret == 0 && errno != ENOENT)
2747 ret = -errno;
2748 }
2749
2750 } else if (!only_dirs && !keep_around) {
8c6db833
LP
2751
2752 if (unlinkat(fd, de->d_name, 0) < 0) {
4c633005 2753 if (ret == 0 && errno != ENOENT)
8c6db833
LP
2754 ret = -errno;
2755 }
2756 }
2757 }
8c6db833
LP
2758}
2759
44a6b1b6 2760_pure_ static int is_temporary_fs(struct statfs *s) {
943aad8c 2761 assert(s);
73020ab2
SL
2762
2763 return F_TYPE_EQUAL(s->f_type, TMPFS_MAGIC) ||
2764 F_TYPE_EQUAL(s->f_type, RAMFS_MAGIC);
943aad8c
ZJS
2765}
2766
f56d5db9
LP
2767int rm_rf_children(int fd, bool only_dirs, bool honour_sticky, struct stat *root_dev) {
2768 struct statfs s;
2769
2770 assert(fd >= 0);
2771
2772 if (fstatfs(fd, &s) < 0) {
03e334a1 2773 safe_close(fd);
f56d5db9
LP
2774 return -errno;
2775 }
2776
2777 /* We refuse to clean disk file systems with this call. This
2778 * is extra paranoia just to be sure we never ever remove
2779 * non-state data */
943aad8c 2780 if (!is_temporary_fs(&s)) {
f56d5db9 2781 log_error("Attempted to remove disk file system, and we can't allow that.");
03e334a1 2782 safe_close(fd);
f56d5db9
LP
2783 return -EPERM;
2784 }
2785
2786 return rm_rf_children_dangerous(fd, only_dirs, honour_sticky, root_dev);
2787}
2788
2789static int rm_rf_internal(const char *path, bool only_dirs, bool delete_root, bool honour_sticky, bool dangerous) {
2790 int fd, r;
2791 struct statfs s;
8c6db833
LP
2792
2793 assert(path);
2794
f56d5db9
LP
2795 /* We refuse to clean the root file system with this
2796 * call. This is extra paranoia to never cause a really
2797 * seriously broken system. */
2798 if (path_equal(path, "/")) {
2799 log_error("Attempted to remove entire root file system, and we can't allow that.");
2800 return -EPERM;
2801 }
461b1822 2802
d4d046e3
LP
2803 fd = open(path, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW|O_NOATIME);
2804 if (fd < 0) {
8c6db833
LP
2805
2806 if (errno != ENOTDIR)
2807 return -errno;
2808
f56d5db9
LP
2809 if (!dangerous) {
2810 if (statfs(path, &s) < 0)
2811 return -errno;
2812
943aad8c 2813 if (!is_temporary_fs(&s)) {
f56d5db9
LP
2814 log_error("Attempted to remove disk file system, and we can't allow that.");
2815 return -EPERM;
2816 }
2817 }
2818
8c6db833 2819 if (delete_root && !only_dirs)
d4d046e3 2820 if (unlink(path) < 0 && errno != ENOENT)
8c6db833
LP
2821 return -errno;
2822
2823 return 0;
2824 }
2825
f56d5db9
LP
2826 if (!dangerous) {
2827 if (fstatfs(fd, &s) < 0) {
03e334a1 2828 safe_close(fd);
f56d5db9
LP
2829 return -errno;
2830 }
ad293f5a 2831
943aad8c 2832 if (!is_temporary_fs(&s)) {
f56d5db9 2833 log_error("Attempted to remove disk file system, and we can't allow that.");
03e334a1 2834 safe_close(fd);
f56d5db9
LP
2835 return -EPERM;
2836 }
2837 }
2838
2839 r = rm_rf_children_dangerous(fd, only_dirs, honour_sticky, NULL);
ad293f5a
LP
2840 if (delete_root) {
2841
8d53b453 2842 if (honour_sticky && file_is_priv_sticky(path) > 0)
ad293f5a 2843 return r;
8c6db833 2844
e27796a0 2845 if (rmdir(path) < 0 && errno != ENOENT) {
8c6db833
LP
2846 if (r == 0)
2847 r = -errno;
2848 }
ad293f5a 2849 }
8c6db833
LP
2850
2851 return r;
2852}
2853
f56d5db9
LP
2854int rm_rf(const char *path, bool only_dirs, bool delete_root, bool honour_sticky) {
2855 return rm_rf_internal(path, only_dirs, delete_root, honour_sticky, false);
2856}
2857
2858int rm_rf_dangerous(const char *path, bool only_dirs, bool delete_root, bool honour_sticky) {
2859 return rm_rf_internal(path, only_dirs, delete_root, honour_sticky, true);
2860}
2861
8c6db833
LP
2862int chmod_and_chown(const char *path, mode_t mode, uid_t uid, gid_t gid) {
2863 assert(path);
2864
2865 /* Under the assumption that we are running privileged we
2866 * first change the access mode and only then hand out
2867 * ownership to avoid a window where access is too open. */
2868
8d53b453
LP
2869 if (mode != (mode_t) -1)
2870 if (chmod(path, mode) < 0)
2871 return -errno;
8c6db833 2872
8d53b453
LP
2873 if (uid != (uid_t) -1 || gid != (gid_t) -1)
2874 if (chown(path, uid, gid) < 0)
2875 return -errno;
8c6db833
LP
2876
2877 return 0;
ef2f1067
LP
2878}
2879
f4b47811
LP
2880int fchmod_and_fchown(int fd, mode_t mode, uid_t uid, gid_t gid) {
2881 assert(fd >= 0);
2882
2883 /* Under the assumption that we are running privileged we
2884 * first change the access mode and only then hand out
2885 * ownership to avoid a window where access is too open. */
2886
9588bc32
LP
2887 if (mode != (mode_t) -1)
2888 if (fchmod(fd, mode) < 0)
2889 return -errno;
f4b47811 2890
9588bc32
LP
2891 if (uid != (uid_t) -1 || gid != (gid_t) -1)
2892 if (fchown(fd, uid, gid) < 0)
2893 return -errno;
f4b47811
LP
2894
2895 return 0;
2896}
2897
82c121a4
LP
2898cpu_set_t* cpu_set_malloc(unsigned *ncpus) {
2899 cpu_set_t *r;
2900 unsigned n = 1024;
2901
2902 /* Allocates the cpuset in the right size */
2903
2904 for (;;) {
2905 if (!(r = CPU_ALLOC(n)))
2906 return NULL;
2907
2908 if (sched_getaffinity(0, CPU_ALLOC_SIZE(n), r) >= 0) {
2909 CPU_ZERO_S(CPU_ALLOC_SIZE(n), r);
2910
2911 if (ncpus)
2912 *ncpus = n;
2913
2914 return r;
2915 }
2916
2917 CPU_FREE(r);
2918
2919 if (errno != EINVAL)
2920 return NULL;
2921
2922 n *= 2;
2923 }
2924}
2925
984a2be4 2926int status_vprintf(const char *status, bool ellipse, bool ephemeral, const char *format, va_list ap) {
9ab7a8d2 2927 static const char status_indent[] = " "; /* "[" STATUS "] " */
669bec5d
LP
2928 _cleanup_free_ char *s = NULL;
2929 _cleanup_close_ int fd = -1;
b92bea5d 2930 struct iovec iovec[6] = {};
81beb750 2931 int n = 0;
984a2be4 2932 static bool prev_ephemeral;
9e58ff9c
LP
2933
2934 assert(format);
2935
9ab7a8d2 2936 /* This is independent of logging, as status messages are
9e58ff9c
LP
2937 * optional and go exclusively to the console. */
2938
2939 if (vasprintf(&s, format, ap) < 0)
669bec5d 2940 return log_oom();
9e58ff9c 2941
67e5cc4f 2942 fd = open_terminal("/dev/console", O_WRONLY|O_NOCTTY|O_CLOEXEC);
81beb750 2943 if (fd < 0)
669bec5d 2944 return fd;
9e58ff9c 2945
67e5cc4f 2946 if (ellipse) {
9ab7a8d2
MS
2947 char *e;
2948 size_t emax, sl;
2949 int c;
2950
67e5cc4f
LP
2951 c = fd_columns(fd);
2952 if (c <= 0)
2953 c = 80;
81beb750 2954
669bec5d 2955 sl = status ? sizeof(status_indent)-1 : 0;
9ab7a8d2
MS
2956
2957 emax = c - sl - 1;
2958 if (emax < 3)
2959 emax = 3;
81beb750 2960
67e5cc4f
LP
2961 e = ellipsize(s, emax, 75);
2962 if (e) {
2963 free(s);
2964 s = e;
2965 }
81beb750
LP
2966 }
2967
984a2be4
MS
2968 if (prev_ephemeral)
2969 IOVEC_SET_STRING(iovec[n++], "\r" ANSI_ERASE_TO_END_OF_LINE);
2970 prev_ephemeral = ephemeral;
2971
9ab7a8d2
MS
2972 if (status) {
2973 if (!isempty(status)) {
2974 IOVEC_SET_STRING(iovec[n++], "[");
2975 IOVEC_SET_STRING(iovec[n++], status);
2976 IOVEC_SET_STRING(iovec[n++], "] ");
2977 } else
2978 IOVEC_SET_STRING(iovec[n++], status_indent);
81beb750
LP
2979 }
2980
9ab7a8d2 2981 IOVEC_SET_STRING(iovec[n++], s);
984a2be4
MS
2982 if (!ephemeral)
2983 IOVEC_SET_STRING(iovec[n++], "\n");
81beb750 2984
669bec5d
LP
2985 if (writev(fd, iovec, n) < 0)
2986 return -errno;
9e58ff9c 2987
669bec5d 2988 return 0;
9e58ff9c
LP
2989}
2990
984a2be4 2991int status_printf(const char *status, bool ellipse, bool ephemeral, const char *format, ...) {
c846ff47 2992 va_list ap;
669bec5d 2993 int r;
c846ff47
LP
2994
2995 assert(format);
2996
2997 va_start(ap, format);
984a2be4 2998 r = status_vprintf(status, ellipse, ephemeral, format, ap);
c846ff47 2999 va_end(ap);
669bec5d
LP
3000
3001 return r;
c846ff47
LP
3002}
3003
fab56fc5
LP
3004char *replace_env(const char *format, char **env) {
3005 enum {
3006 WORD,
c24eb49e 3007 CURLY,
fab56fc5
LP
3008 VARIABLE
3009 } state = WORD;
3010
3011 const char *e, *word = format;
3012 char *r = NULL, *k;
3013
3014 assert(format);
3015
3016 for (e = format; *e; e ++) {
3017
3018 switch (state) {
3019
3020 case WORD:
3021 if (*e == '$')
c24eb49e 3022 state = CURLY;
fab56fc5
LP
3023 break;
3024
c24eb49e
LP
3025 case CURLY:
3026 if (*e == '{') {
fab56fc5
LP
3027 if (!(k = strnappend(r, word, e-word-1)))
3028 goto fail;
3029
3030 free(r);
3031 r = k;
3032
3033 word = e-1;
3034 state = VARIABLE;
3035
3036 } else if (*e == '$') {
3037 if (!(k = strnappend(r, word, e-word)))
3038 goto fail;
3039
3040 free(r);
3041 r = k;
3042
3043 word = e+1;
3044 state = WORD;
3045 } else
3046 state = WORD;
3047 break;
3048
3049 case VARIABLE:
c24eb49e 3050 if (*e == '}') {
b95cf362 3051 const char *t;
fab56fc5 3052
4d1a6904 3053 t = strempty(strv_env_get_n(env, word+2, e-word-2));
fab56fc5 3054
4d1a6904
LP
3055 k = strappend(r, t);
3056 if (!k)
b95cf362 3057 goto fail;
fab56fc5 3058
b95cf362
LP
3059 free(r);
3060 r = k;
fab56fc5 3061
b95cf362 3062 word = e+1;
fab56fc5
LP
3063 state = WORD;
3064 }
3065 break;
3066 }
3067 }
3068
3069 if (!(k = strnappend(r, word, e-word)))
3070 goto fail;
3071
3072 free(r);
3073 return k;
3074
3075fail:
3076 free(r);
3077 return NULL;
3078}
3079
3080char **replace_env_argv(char **argv, char **env) {
3081 char **r, **i;
c24eb49e
LP
3082 unsigned k = 0, l = 0;
3083
3084 l = strv_length(argv);
fab56fc5 3085
c24eb49e 3086 if (!(r = new(char*, l+1)))
fab56fc5
LP
3087 return NULL;
3088
3089 STRV_FOREACH(i, argv) {
c24eb49e
LP
3090
3091 /* If $FOO appears as single word, replace it by the split up variable */
b95cf362
LP
3092 if ((*i)[0] == '$' && (*i)[1] != '{') {
3093 char *e;
3094 char **w, **m;
3095 unsigned q;
c24eb49e 3096
4d1a6904
LP
3097 e = strv_env_get(env, *i+1);
3098 if (e) {
c24eb49e
LP
3099
3100 if (!(m = strv_split_quoted(e))) {
3101 r[k] = NULL;
3102 strv_free(r);
3103 return NULL;
3104 }
b95cf362
LP
3105 } else
3106 m = NULL;
c24eb49e 3107
b95cf362
LP
3108 q = strv_length(m);
3109 l = l + q - 1;
c24eb49e 3110
b95cf362
LP
3111 if (!(w = realloc(r, sizeof(char*) * (l+1)))) {
3112 r[k] = NULL;
3113 strv_free(r);
3114 strv_free(m);
3115 return NULL;
3116 }
c24eb49e 3117
b95cf362
LP
3118 r = w;
3119 if (m) {
c24eb49e
LP
3120 memcpy(r + k, m, q * sizeof(char*));
3121 free(m);
c24eb49e 3122 }
b95cf362
LP
3123
3124 k += q;
3125 continue;
c24eb49e
LP
3126 }
3127
3128 /* If ${FOO} appears as part of a word, replace it by the variable as-is */
fab56fc5
LP
3129 if (!(r[k++] = replace_env(*i, env))) {
3130 strv_free(r);
3131 return NULL;
3132 }
3133 }
3134
3135 r[k] = NULL;
3136 return r;
3137}
3138
81beb750 3139int fd_columns(int fd) {
b92bea5d 3140 struct winsize ws = {};
81beb750
LP
3141
3142 if (ioctl(fd, TIOCGWINSZ, &ws) < 0)
3143 return -errno;
3144
3145 if (ws.ws_col <= 0)
3146 return -EIO;
3147
3148 return ws.ws_col;
3149}
3150
28917d7d 3151unsigned columns(void) {
fa776d8e 3152 const char *e;
7009eec2 3153 int c;
fa776d8e 3154
28917d7d
LP
3155 if (_likely_(cached_columns > 0))
3156 return cached_columns;
11f96fac 3157
28917d7d
LP
3158 c = 0;
3159 e = getenv("COLUMNS");
3160 if (e)
7009eec2 3161 safe_atoi(e, &c);
fa776d8e 3162
28917d7d
LP
3163 if (c <= 0)
3164 c = fd_columns(STDOUT_FILENO);
fa776d8e 3165
28917d7d
LP
3166 if (c <= 0)
3167 c = 80;
11f96fac 3168
28917d7d
LP
3169 cached_columns = c;
3170 return c;
11f96fac
ZJS
3171}
3172
8f2d43a0 3173int fd_lines(int fd) {
b92bea5d 3174 struct winsize ws = {};
8f2d43a0
LP
3175
3176 if (ioctl(fd, TIOCGWINSZ, &ws) < 0)
3177 return -errno;
3178
3179 if (ws.ws_row <= 0)
3180 return -EIO;
3181
3182 return ws.ws_row;
3183}
3184
3185unsigned lines(void) {
8f2d43a0 3186 const char *e;
ed757c0c 3187 unsigned l;
8f2d43a0 3188
ed757c0c
LP
3189 if (_likely_(cached_lines > 0))
3190 return cached_lines;
8f2d43a0 3191
ed757c0c 3192 l = 0;
8f2d43a0
LP
3193 e = getenv("LINES");
3194 if (e)
ed757c0c 3195 safe_atou(e, &l);
8f2d43a0 3196
ed757c0c
LP
3197 if (l <= 0)
3198 l = fd_lines(STDOUT_FILENO);
8f2d43a0 3199
ed757c0c
LP
3200 if (l <= 0)
3201 l = 24;
8f2d43a0 3202
ed757c0c
LP
3203 cached_lines = l;
3204 return cached_lines;
3205}
3206
3207/* intended to be used as a SIGWINCH sighandler */
3208void columns_lines_cache_reset(int signum) {
3209 cached_columns = 0;
3210 cached_lines = 0;
3211}
3212
3213bool on_tty(void) {
3214 static int cached_on_tty = -1;
3215
3216 if (_unlikely_(cached_on_tty < 0))
3217 cached_on_tty = isatty(STDOUT_FILENO) > 0;
3218
3219 return cached_on_tty;
8f2d43a0
LP
3220}
3221
9d9951a4
HH
3222int files_same(const char *filea, const char *fileb) {
3223 struct stat a, b;
b4f10a5e 3224
9d9951a4 3225 if (stat(filea, &a) < 0)
b4f10a5e
LP
3226 return -errno;
3227
9d9951a4 3228 if (stat(fileb, &b) < 0)
b4f10a5e
LP
3229 return -errno;
3230
9d9951a4
HH
3231 return a.st_dev == b.st_dev &&
3232 a.st_ino == b.st_ino;
3233}
3234
3235int running_in_chroot(void) {
3236 int ret;
3237
3238 ret = files_same("/proc/1/root", "/");
3239 if (ret < 0)
3240 return ret;
3241
3242 return ret == 0;
b4f10a5e
LP
3243}
3244
f405e86d 3245static char *ascii_ellipsize_mem(const char *s, size_t old_length, size_t new_length, unsigned percent) {
72f59706 3246 size_t x;
8fe914ec
LP
3247 char *r;
3248
3249 assert(s);
3250 assert(percent <= 100);
72f59706 3251 assert(new_length >= 3);
8fe914ec 3252
72f59706
LP
3253 if (old_length <= 3 || old_length <= new_length)
3254 return strndup(s, old_length);
8fe914ec 3255
72f59706
LP
3256 r = new0(char, new_length+1);
3257 if (!r)
a6f0104a 3258 return NULL;
8fe914ec 3259
72f59706 3260 x = (new_length * percent) / 100;
8fe914ec 3261
72f59706
LP
3262 if (x > new_length - 3)
3263 x = new_length - 3;
8fe914ec
LP
3264
3265 memcpy(r, s, x);
3266 r[x] = '.';
3267 r[x+1] = '.';
3268 r[x+2] = '.';
3269 memcpy(r + x + 3,
72f59706
LP
3270 s + old_length - (new_length - x - 3),
3271 new_length - x - 3);
8fe914ec
LP
3272
3273 return r;
3274}
3275
f405e86d
SL
3276char *ellipsize_mem(const char *s, size_t old_length, size_t new_length, unsigned percent) {
3277 size_t x;
3278 char *e;
3279 const char *i, *j;
3280 unsigned k, len, len2;
3281
3282 assert(s);
3283 assert(percent <= 100);
3284 assert(new_length >= 3);
3285
3286 /* if no multibyte characters use ascii_ellipsize_mem for speed */
3287 if (ascii_is_valid(s))
3288 return ascii_ellipsize_mem(s, old_length, new_length, percent);
3289
3290 if (old_length <= 3 || old_length <= new_length)
3291 return strndup(s, old_length);
3292
3293 x = (new_length * percent) / 100;
3294
3295 if (x > new_length - 3)
3296 x = new_length - 3;
3297
3298 k = 0;
3299 for (i = s; k < x && i < s + old_length; i = utf8_next_char(i)) {
3300 int c;
3301
3302 c = utf8_encoded_to_unichar(i);
3303 if (c < 0)
3304 return NULL;
3305 k += unichar_iswide(c) ? 2 : 1;
3306 }
3307
3308 if (k > x) /* last character was wide and went over quota */
3309 x ++;
3310
3311 for (j = s + old_length; k < new_length && j > i; ) {
3312 int c;
3313
3314 j = utf8_prev_char(j);
3315 c = utf8_encoded_to_unichar(j);
3316 if (c < 0)
3317 return NULL;
3318 k += unichar_iswide(c) ? 2 : 1;
3319 }
3320 assert(i <= j);
3321
3322 /* we don't actually need to ellipsize */
3323 if (i == j)
3324 return memdup(s, old_length + 1);
3325
3326 /* make space for ellipsis */
3327 j = utf8_next_char(j);
3328
3329 len = i - s;
3330 len2 = s + old_length - j;
3331 e = new(char, len + 3 + len2 + 1);
3332 if (!e)
3333 return NULL;
3334
3335 /*
3336 printf("old_length=%zu new_length=%zu x=%zu len=%u len2=%u k=%u\n",
3337 old_length, new_length, x, len, len2, k);
3338 */
3339
3340 memcpy(e, s, len);
3341 e[len] = 0xe2; /* tri-dot ellipsis: … */
3342 e[len + 1] = 0x80;
3343 e[len + 2] = 0xa6;
3344
3345 memcpy(e + len + 3, j, len2 + 1);
3346
3347 return e;
3348}
3349
72f59706
LP
3350char *ellipsize(const char *s, size_t length, unsigned percent) {
3351 return ellipsize_mem(s, strlen(s), length, percent);
3352}
3353
c38dfac9 3354int touch_file(const char *path, bool parents, usec_t stamp, uid_t uid, gid_t gid, mode_t mode) {
03e334a1 3355 _cleanup_close_ int fd;
c38dfac9 3356 int r;
f6144808
LP
3357
3358 assert(path);
3359
c38dfac9
KS
3360 if (parents)
3361 mkdir_parents(path, 0755);
73836c5c 3362
c38dfac9 3363 fd = open(path, O_WRONLY|O_CREAT|O_CLOEXEC|O_NOCTTY, mode > 0 ? mode : 0644);
73836c5c 3364 if (fd < 0)
f6144808
LP
3365 return -errno;
3366
c38dfac9
KS
3367 if (mode > 0) {
3368 r = fchmod(fd, mode);
3369 if (r < 0)
3370 return -errno;
3371 }
3372
359efc59 3373 if (uid != (uid_t) -1 || gid != (gid_t) -1) {
c38dfac9
KS
3374 r = fchown(fd, uid, gid);
3375 if (r < 0)
3376 return -errno;
3377 }
3378
359efc59 3379 if (stamp != (usec_t) -1) {
c38dfac9
KS
3380 struct timespec ts[2];
3381
3382 timespec_store(&ts[0], stamp);
359efc59 3383 ts[1] = ts[0];
c38dfac9
KS
3384 r = futimens(fd, ts);
3385 } else
3386 r = futimens(fd, NULL);
3387 if (r < 0)
3388 return -errno;
3389
f6144808
LP
3390 return 0;
3391}
afea26ad 3392
c38dfac9 3393int touch(const char *path) {
359efc59 3394 return touch_file(path, false, (usec_t) -1, (uid_t) -1, (gid_t) -1, 0);
c38dfac9
KS
3395}
3396
97c4a07d 3397char *unquote(const char *s, const char* quotes) {
11ce3427
LP
3398 size_t l;
3399 assert(s);
3400
73836c5c
LP
3401 /* This is rather stupid, simply removes the heading and
3402 * trailing quotes if there is one. Doesn't care about
57f30678
LP
3403 * escaping or anything. We should make this smarter one
3404 * day...*/
73836c5c 3405
31ed59c5
LP
3406 l = strlen(s);
3407 if (l < 2)
11ce3427
LP
3408 return strdup(s);
3409
97c4a07d 3410 if (strchr(quotes, s[0]) && s[l-1] == s[0])
11ce3427
LP
3411 return strndup(s+1, l-2);
3412
3413 return strdup(s);
3414}
3415
5f7c426e 3416char *normalize_env_assignment(const char *s) {
57f30678
LP
3417 _cleanup_free_ char *name = NULL, *value = NULL, *p = NULL;
3418 char *eq, *r;
5f7c426e 3419
57f30678
LP
3420 eq = strchr(s, '=');
3421 if (!eq) {
3422 char *t;
5f7c426e 3423
57f30678
LP
3424 r = strdup(s);
3425 if (!r)
5f7c426e
LP
3426 return NULL;
3427
57f30678
LP
3428 t = strstrip(r);
3429 if (t == r)
3430 return r;
3431
3432 memmove(r, t, strlen(t) + 1);
3433 return r;
5f7c426e
LP
3434 }
3435
57f30678
LP
3436 name = strndup(s, eq - s);
3437 if (!name)
5f7c426e
LP
3438 return NULL;
3439
57f30678
LP
3440 p = strdup(eq + 1);
3441 if (!p)
5f7c426e 3442 return NULL;
5f7c426e
LP
3443
3444 value = unquote(strstrip(p), QUOTES);
57f30678 3445 if (!value)
5f7c426e 3446 return NULL;
5f7c426e 3447
57f30678 3448 if (asprintf(&r, "%s=%s", strstrip(name), value) < 0)
5f7c426e
LP
3449 r = NULL;
3450
5f7c426e
LP
3451 return r;
3452}
3453
8e12a6ae 3454int wait_for_terminate(pid_t pid, siginfo_t *status) {
1968a360
LP
3455 siginfo_t dummy;
3456
2e78aa99 3457 assert(pid >= 1);
1968a360
LP
3458
3459 if (!status)
3460 status = &dummy;
2e78aa99
LP
3461
3462 for (;;) {
8e12a6ae
LP
3463 zero(*status);
3464
3465 if (waitid(P_PID, pid, status, WEXITED) < 0) {
2e78aa99
LP
3466
3467 if (errno == EINTR)
3468 continue;
3469
3470 return -errno;
3471 }
3472
3473 return 0;
3474 }
3475}
3476
97c4a07d
LP
3477int wait_for_terminate_and_warn(const char *name, pid_t pid) {
3478 int r;
3479 siginfo_t status;
3480
3481 assert(name);
3482 assert(pid > 1);
3483
d87be9b0
LP
3484 r = wait_for_terminate(pid, &status);
3485 if (r < 0) {
97c4a07d
LP
3486 log_warning("Failed to wait for %s: %s", name, strerror(-r));
3487 return r;
3488 }
3489
3490 if (status.si_code == CLD_EXITED) {
3491 if (status.si_status != 0) {
3492 log_warning("%s failed with error code %i.", name, status.si_status);
0a27cf3f 3493 return status.si_status;
97c4a07d
LP
3494 }
3495
3496 log_debug("%s succeeded.", name);
3497 return 0;
3498
3499 } else if (status.si_code == CLD_KILLED ||
3500 status.si_code == CLD_DUMPED) {
3501
3502 log_warning("%s terminated by signal %s.", name, signal_to_string(status.si_status));
3503 return -EPROTO;
3504 }
3505
3506 log_warning("%s failed due to unknown reason.", name);
3507 return -EPROTO;
97c4a07d
LP
3508}
3509
919ce0b7 3510noreturn void freeze(void) {
720ce21d
LP
3511
3512 /* Make sure nobody waits for us on a socket anymore */
3513 close_all_fds(NULL, 0);
3514
c29597a1
LP
3515 sync();
3516
3c14d26c
LP
3517 for (;;)
3518 pause();
3519}
3520
00dc5d76
LP
3521bool null_or_empty(struct stat *st) {
3522 assert(st);
3523
3524 if (S_ISREG(st->st_mode) && st->st_size <= 0)
3525 return true;
3526
c8f26f42 3527 if (S_ISCHR(st->st_mode) || S_ISBLK(st->st_mode))
00dc5d76
LP
3528 return true;
3529
3530 return false;
3531}
3532
83096483
LP
3533int null_or_empty_path(const char *fn) {
3534 struct stat st;
3535
3536 assert(fn);
3537
3538 if (stat(fn, &st) < 0)
3539 return -errno;
3540
3541 return null_or_empty(&st);
3542}
3543
a247755d 3544DIR *xopendirat(int fd, const char *name, int flags) {
c4731d11
LP
3545 int nfd;
3546 DIR *d;
3547
dd94c17e
LP
3548 assert(!(flags & O_CREAT));
3549
3550 nfd = openat(fd, name, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|flags, 0);
73836c5c 3551 if (nfd < 0)
c4731d11
LP
3552 return NULL;
3553
73836c5c
LP
3554 d = fdopendir(nfd);
3555 if (!d) {
03e334a1 3556 safe_close(nfd);
c4731d11
LP
3557 return NULL;
3558 }
3559
3560 return d;
3b63d2d3
LP
3561}
3562
8a0867d6
LP
3563int signal_from_string_try_harder(const char *s) {
3564 int signo;
3565 assert(s);
3566
73836c5c
LP
3567 signo = signal_from_string(s);
3568 if (signo <= 0)
8a0867d6
LP
3569 if (startswith(s, "SIG"))
3570 return signal_from_string(s+3);
3571
3572 return signo;
3573}
3574
383182b5 3575static char *tag_to_udev_node(const char *tagvalue, const char *by) {
22f5f628 3576 _cleanup_free_ char *t = NULL, *u = NULL;
22f5f628 3577 size_t enc_len;
e23a0ce8 3578
383182b5 3579 u = unquote(tagvalue, "\"\'");
6db615c1 3580 if (!u)
383182b5 3581 return NULL;
e23a0ce8 3582
1d5989fd 3583 enc_len = strlen(u) * 4 + 1;
22f5f628 3584 t = new(char, enc_len);
6db615c1 3585 if (!t)
383182b5 3586 return NULL;
e23a0ce8 3587
8f6ce71f 3588 if (encode_devnode_name(u, t, enc_len) < 0)
22f5f628 3589 return NULL;
e23a0ce8 3590
6db615c1 3591 return strjoin("/dev/disk/by-", by, "/", t, NULL);
383182b5 3592}
e23a0ce8 3593
383182b5 3594char *fstab_node_to_udev_node(const char *p) {
faa368e3
LP
3595 assert(p);
3596
383182b5
DR
3597 if (startswith(p, "LABEL="))
3598 return tag_to_udev_node(p+6, "label");
e23a0ce8 3599
383182b5
DR
3600 if (startswith(p, "UUID="))
3601 return tag_to_udev_node(p+5, "uuid");
e23a0ce8 3602
84cc2abf
DR
3603 if (startswith(p, "PARTUUID="))
3604 return tag_to_udev_node(p+9, "partuuid");
3605
3606 if (startswith(p, "PARTLABEL="))
3607 return tag_to_udev_node(p+10, "partlabel");
3608
e23a0ce8
LP
3609 return strdup(p);
3610}
3611
f212ac12
LP
3612bool tty_is_vc(const char *tty) {
3613 assert(tty);
3614
3615 if (startswith(tty, "/dev/"))
3616 tty += 5;
3617
98a28fef
LP
3618 return vtnr_from_tty(tty) >= 0;
3619}
3620
d1122ad5
LP
3621bool tty_is_console(const char *tty) {
3622 assert(tty);
3623
3624 if (startswith(tty, "/dev/"))
3625 tty += 5;
3626
3627 return streq(tty, "console");
3628}
3629
98a28fef
LP
3630int vtnr_from_tty(const char *tty) {
3631 int i, r;
3632
3633 assert(tty);
3634
3635 if (startswith(tty, "/dev/"))
3636 tty += 5;
3637
3638 if (!startswith(tty, "tty") )
3639 return -EINVAL;
3640
3641 if (tty[3] < '0' || tty[3] > '9')
3642 return -EINVAL;
3643
3644 r = safe_atoi(tty+3, &i);
3645 if (r < 0)
3646 return r;
3647
3648 if (i < 0 || i > 63)
3649 return -EINVAL;
3650
3651 return i;
f212ac12
LP
3652}
3653
21baf21a
MS
3654char *resolve_dev_console(char **active) {
3655 char *tty;
3656
3657 /* Resolve where /dev/console is pointing to, if /sys is actually ours
3658 * (i.e. not read-only-mounted which is a sign for container setups) */
3659
3660 if (path_is_read_only_fs("/sys") > 0)
3661 return NULL;
3662
3663 if (read_one_line_file("/sys/class/tty/console/active", active) < 0)
3664 return NULL;
3665
3666 /* If multiple log outputs are configured the last one is what
3667 * /dev/console points to */
3668 tty = strrchr(*active, ' ');
3669 if (tty)
3670 tty++;
3671 else
3672 tty = *active;
3673
8aa5429a
OB
3674 if (streq(tty, "tty0")) {
3675 char *tmp;
3676
3677 /* Get the active VC (e.g. tty1) */
3678 if (read_one_line_file("/sys/class/tty/tty0/active", &tmp) >= 0) {
3679 free(*active);
3680 tty = *active = tmp;
3681 }
3682 }
3683
21baf21a
MS
3684 return tty;
3685}
3686
3043935f 3687bool tty_is_vc_resolve(const char *tty) {
9588bc32 3688 _cleanup_free_ char *active = NULL;
3030ccd7 3689
e3aa71c3
LP
3690 assert(tty);
3691
3692 if (startswith(tty, "/dev/"))
3693 tty += 5;
3694
21baf21a
MS
3695 if (streq(tty, "console")) {
3696 tty = resolve_dev_console(&active);
3697 if (!tty)
3698 return false;
3699 }
3030ccd7 3700
9588bc32 3701 return tty_is_vc(tty);
3043935f
LP
3702}
3703
3704const char *default_term_for_tty(const char *tty) {
3705 assert(tty);
3706
acda6a05 3707 return tty_is_vc_resolve(tty) ? "TERM=linux" : "TERM=vt102";
e3aa71c3
LP
3708}
3709
87d2c1ff 3710bool dirent_is_file(const struct dirent *de) {
fb19a739
LP
3711 assert(de);
3712
3713 if (ignore_file(de->d_name))
3714 return false;
3715
3716 if (de->d_type != DT_REG &&
3717 de->d_type != DT_LNK &&
3718 de->d_type != DT_UNKNOWN)
3719 return false;
3720
3721 return true;
3722}
3723
87d2c1ff
LP
3724bool dirent_is_file_with_suffix(const struct dirent *de, const char *suffix) {
3725 assert(de);
3726
a228a22f
LP
3727 if (de->d_type != DT_REG &&
3728 de->d_type != DT_LNK &&
3729 de->d_type != DT_UNKNOWN)
3730 return false;
3731
3732 if (ignore_file_allow_backup(de->d_name))
87d2c1ff
LP
3733 return false;
3734
3735 return endswith(de->d_name, suffix);
3736}
3737
aa62a893
LP
3738void execute_directory(const char *directory, DIR *d, usec_t timeout, char *argv[]) {
3739 pid_t executor_pid;
3740 int r;
83cc030f
LP
3741
3742 assert(directory);
3743
aa62a893
LP
3744 /* Executes all binaries in a directory in parallel and waits
3745 * for them to finish. Optionally a timeout is applied. */
83cc030f 3746
aa62a893
LP
3747 executor_pid = fork();
3748 if (executor_pid < 0) {
3749 log_error("Failed to fork: %m");
3750 return;
83cc030f 3751
aa62a893
LP
3752 } else if (executor_pid == 0) {
3753 _cleanup_hashmap_free_free_ Hashmap *pids = NULL;
3754 _cleanup_closedir_ DIR *_d = NULL;
3755 struct dirent *de;
3756 sigset_t ss;
83cc030f 3757
aa62a893
LP
3758 /* We fork this all off from a child process so that
3759 * we can somewhat cleanly make use of SIGALRM to set
3760 * a time limit */
83cc030f 3761
aa62a893 3762 reset_all_signal_handlers();
83cc030f 3763
aa62a893
LP
3764 assert_se(sigemptyset(&ss) == 0);
3765 assert_se(sigprocmask(SIG_SETMASK, &ss, NULL) == 0);
83cc030f 3766
aa62a893 3767 assert_se(prctl(PR_SET_PDEATHSIG, SIGTERM) == 0);
83cc030f 3768
aa62a893
LP
3769 if (!d) {
3770 d = _d = opendir(directory);
3771 if (!d) {
3772 if (errno == ENOENT)
3773 _exit(EXIT_SUCCESS);
83cc030f 3774
aa62a893
LP
3775 log_error("Failed to enumerate directory %s: %m", directory);
3776 _exit(EXIT_FAILURE);
3777 }
83cc030f
LP
3778 }
3779
aa62a893
LP
3780 pids = hashmap_new(NULL, NULL);
3781 if (!pids) {
3782 log_oom();
3783 _exit(EXIT_FAILURE);
83cc030f
LP
3784 }
3785
aa62a893
LP
3786 FOREACH_DIRENT(de, d, break) {
3787 _cleanup_free_ char *path = NULL;
3788 pid_t pid;
83cc030f 3789
aa62a893
LP
3790 if (!dirent_is_file(de))
3791 continue;
83cc030f 3792
aa62a893
LP
3793 if (asprintf(&path, "%s/%s", directory, de->d_name) < 0) {
3794 log_oom();
3795 _exit(EXIT_FAILURE);
3796 }
83cc030f 3797
aa62a893
LP
3798 pid = fork();
3799 if (pid < 0) {
3800 log_error("Failed to fork: %m");
3801 continue;
3802 } else if (pid == 0) {
3803 char *_argv[2];
83cc030f 3804
aa62a893 3805 assert_se(prctl(PR_SET_PDEATHSIG, SIGTERM) == 0);
83cc030f 3806
aa62a893
LP
3807 if (!argv) {
3808 _argv[0] = path;
3809 _argv[1] = NULL;
3810 argv = _argv;
3811 } else
3812 argv[0] = path;
83cc030f 3813
aa62a893
LP
3814 execv(path, argv);
3815 log_error("Failed to execute %s: %m", path);
3816 _exit(EXIT_FAILURE);
3817 }
83cc030f 3818
83cc030f 3819
aa62a893 3820 log_debug("Spawned %s as " PID_FMT ".", path, pid);
83cc030f 3821
aa62a893
LP
3822 r = hashmap_put(pids, UINT_TO_PTR(pid), path);
3823 if (r < 0) {
3824 log_oom();
3825 _exit(EXIT_FAILURE);
3826 }
3827
3828 path = NULL;
83cc030f
LP
3829 }
3830
aa62a893
LP
3831 /* Abort execution of this process after the
3832 * timout. We simply rely on SIGALRM as default action
3833 * terminating the process, and turn on alarm(). */
3834
3835 if (timeout != (usec_t) -1)
3836 alarm((timeout + USEC_PER_SEC - 1) / USEC_PER_SEC);
3837
3838 while (!hashmap_isempty(pids)) {
3839 _cleanup_free_ char *path = NULL;
3840 pid_t pid;
3841
3842 pid = PTR_TO_UINT(hashmap_first_key(pids));
3843 assert(pid > 0);
83cc030f 3844
aa62a893
LP
3845 path = hashmap_remove(pids, UINT_TO_PTR(pid));
3846 assert(path);
3847
3848 wait_for_terminate_and_warn(path, pid);
83cc030f 3849 }
83cc030f 3850
aa62a893
LP
3851 _exit(EXIT_SUCCESS);
3852 }
83cc030f 3853
aa62a893 3854 wait_for_terminate_and_warn(directory, executor_pid);
83cc030f
LP
3855}
3856
430c18ed
LP
3857int kill_and_sigcont(pid_t pid, int sig) {
3858 int r;
3859
3860 r = kill(pid, sig) < 0 ? -errno : 0;
3861
3862 if (r >= 0)
3863 kill(pid, SIGCONT);
3864
3865 return r;
3866}
3867
05feefe0
LP
3868bool nulstr_contains(const char*nulstr, const char *needle) {
3869 const char *i;
3870
3871 if (!nulstr)
3872 return false;
3873
3874 NULSTR_FOREACH(i, nulstr)
3875 if (streq(i, needle))
3876 return true;
3877
3878 return false;
3879}
3880
6faa1114 3881bool plymouth_running(void) {
9408a2d2 3882 return access("/run/plymouth/pid", F_OK) >= 0;
6faa1114
LP
3883}
3884
9beb3f4d
LP
3885char* strshorten(char *s, size_t l) {
3886 assert(s);
3887
3888 if (l < strlen(s))
3889 s[l] = 0;
3890
3891 return s;
3892}
3893
3894static bool hostname_valid_char(char c) {
3895 return
3896 (c >= 'a' && c <= 'z') ||
3897 (c >= 'A' && c <= 'Z') ||
3898 (c >= '0' && c <= '9') ||
3899 c == '-' ||
3900 c == '_' ||
3901 c == '.';
3902}
3903
3904bool hostname_is_valid(const char *s) {
3905 const char *p;
aa3c5cf8 3906 bool dot;
9beb3f4d
LP
3907
3908 if (isempty(s))
3909 return false;
3910
aa3c5cf8
LP
3911 for (p = s, dot = true; *p; p++) {
3912 if (*p == '.') {
3913 if (dot)
3914 return false;
3915
3916 dot = true;
3917 } else {
3918 if (!hostname_valid_char(*p))
3919 return false;
3920
3921 dot = false;
3922 }
3923 }
3924
3925 if (dot)
3926 return false;
9beb3f4d
LP
3927
3928 if (p-s > HOST_NAME_MAX)
3929 return false;
3930
3931 return true;
3932}
3933
e724b063 3934char* hostname_cleanup(char *s, bool lowercase) {
9beb3f4d 3935 char *p, *d;
cec4ead9
LP
3936 bool dot;
3937
3938 for (p = s, d = s, dot = true; *p; p++) {
3939 if (*p == '.') {
e724b063 3940 if (dot)
cec4ead9 3941 continue;
9beb3f4d 3942
e724b063 3943 *(d++) = '.';
cec4ead9 3944 dot = true;
e724b063
LP
3945 } else if (hostname_valid_char(*p)) {
3946 *(d++) = lowercase ? tolower(*p) : *p;
cec4ead9 3947 dot = false;
e724b063 3948 }
cec4ead9 3949
cec4ead9 3950 }
9beb3f4d 3951
e724b063
LP
3952 if (dot && d > s)
3953 d[-1] = 0;
3954 else
3955 *d = 0;
3956
9beb3f4d 3957 strshorten(s, HOST_NAME_MAX);
cec4ead9 3958
9beb3f4d
LP
3959 return s;
3960}
3961
1325aa42 3962int pipe_eof(int fd) {
b92bea5d
ZJS
3963 struct pollfd pollfd = {
3964 .fd = fd,
3965 .events = POLLIN|POLLHUP,
3966 };
1325aa42 3967
d37a91e8
LP
3968 int r;
3969
1325aa42
LP
3970 r = poll(&pollfd, 1, 0);
3971 if (r < 0)
3972 return -errno;
3973
3974 if (r == 0)
3975 return 0;
3976
3977 return pollfd.revents & POLLHUP;
3978}
3979
8f2d43a0 3980int fd_wait_for_event(int fd, int event, usec_t t) {
968d3d24 3981
b92bea5d
ZJS
3982 struct pollfd pollfd = {
3983 .fd = fd,
3984 .events = event,
3985 };
df50185b 3986
968d3d24
LP
3987 struct timespec ts;
3988 int r;
3989
3990 r = ppoll(&pollfd, 1, t == (usec_t) -1 ? NULL : timespec_store(&ts, t), NULL);
df50185b
LP
3991 if (r < 0)
3992 return -errno;
3993
3994 if (r == 0)
3995 return 0;
3996
3997 return pollfd.revents;
3998}
3999
5a3ab509
LP
4000int fopen_temporary(const char *path, FILE **_f, char **_temp_path) {
4001 FILE *f;
4002 char *t;
5a3ab509
LP
4003 int fd;
4004
4005 assert(path);
4006 assert(_f);
4007 assert(_temp_path);
4008
2e78fa79 4009 t = tempfn_xxxxxx(path);
5a3ab509
LP
4010 if (!t)
4011 return -ENOMEM;
4012
2d5bdf5b 4013 fd = mkostemp_safe(t, O_WRONLY|O_CLOEXEC);
5a3ab509
LP
4014 if (fd < 0) {
4015 free(t);
4016 return -errno;
4017 }
4018
4019 f = fdopen(fd, "we");
4020 if (!f) {
4021 unlink(t);
4022 free(t);
4023 return -errno;
4024 }
4025
4026 *_f = f;
4027 *_temp_path = t;
4028
4029 return 0;
4030}
4031
6ea832a2 4032int terminal_vhangup_fd(int fd) {
5a3ab509
LP
4033 assert(fd >= 0);
4034
6ea832a2
LP
4035 if (ioctl(fd, TIOCVHANGUP) < 0)
4036 return -errno;
4037
4038 return 0;
4039}
4040
4041int terminal_vhangup(const char *name) {
03e334a1 4042 _cleanup_close_ int fd;
6ea832a2
LP
4043
4044 fd = open_terminal(name, O_RDWR|O_NOCTTY|O_CLOEXEC);
4045 if (fd < 0)
4046 return fd;
4047
03e334a1 4048 return terminal_vhangup_fd(fd);
6ea832a2
LP
4049}
4050
4051int vt_disallocate(const char *name) {
4052 int fd, r;
4053 unsigned u;
6ea832a2
LP
4054
4055 /* Deallocate the VT if possible. If not possible
4056 * (i.e. because it is the active one), at least clear it
4057 * entirely (including the scrollback buffer) */
4058
b83bc4e9
LP
4059 if (!startswith(name, "/dev/"))
4060 return -EINVAL;
4061
4062 if (!tty_is_vc(name)) {
4063 /* So this is not a VT. I guess we cannot deallocate
4064 * it then. But let's at least clear the screen */
4065
4066 fd = open_terminal(name, O_RDWR|O_NOCTTY|O_CLOEXEC);
4067 if (fd < 0)
4068 return fd;
4069
8585357a
LP
4070 loop_write(fd,
4071 "\033[r" /* clear scrolling region */
4072 "\033[H" /* move home */
4073 "\033[2J", /* clear screen */
4074 10, false);
03e334a1 4075 safe_close(fd);
b83bc4e9
LP
4076
4077 return 0;
4078 }
6ea832a2
LP
4079
4080 if (!startswith(name, "/dev/tty"))
4081 return -EINVAL;
4082
4083 r = safe_atou(name+8, &u);
4084 if (r < 0)
4085 return r;
4086
4087 if (u <= 0)
b83bc4e9 4088 return -EINVAL;
6ea832a2 4089
b83bc4e9 4090 /* Try to deallocate */
6ea832a2
LP
4091 fd = open_terminal("/dev/tty0", O_RDWR|O_NOCTTY|O_CLOEXEC);
4092 if (fd < 0)
4093 return fd;
4094
4095 r = ioctl(fd, VT_DISALLOCATE, u);
03e334a1 4096 safe_close(fd);
6ea832a2 4097
b83bc4e9
LP
4098 if (r >= 0)
4099 return 0;
6ea832a2 4100
b83bc4e9 4101 if (errno != EBUSY)
6ea832a2 4102 return -errno;
6ea832a2 4103
b83bc4e9
LP
4104 /* Couldn't deallocate, so let's clear it fully with
4105 * scrollback */
4106 fd = open_terminal(name, O_RDWR|O_NOCTTY|O_CLOEXEC);
6ea832a2 4107 if (fd < 0)
b83bc4e9 4108 return fd;
6ea832a2 4109
8585357a
LP
4110 loop_write(fd,
4111 "\033[r" /* clear scrolling region */
4112 "\033[H" /* move home */
4113 "\033[3J", /* clear screen including scrollback, requires Linux 2.6.40 */
4114 10, false);
03e334a1 4115 safe_close(fd);
6ea832a2 4116
b83bc4e9 4117 return 0;
6ea832a2
LP
4118}
4119
424a19f8 4120int symlink_atomic(const char *from, const char *to) {
2e78fa79 4121 _cleanup_free_ char *t = NULL;
34ca941c
LP
4122
4123 assert(from);
4124 assert(to);
4125
2e78fa79 4126 t = tempfn_random(to);
34ca941c
LP
4127 if (!t)
4128 return -ENOMEM;
4129
424a19f8
LP
4130 if (symlink(from, t) < 0)
4131 return -errno;
34ca941c
LP
4132
4133 if (rename(t, to) < 0) {
2e78fa79
LP
4134 unlink_noerrno(t);
4135 return -errno;
34ca941c
LP
4136 }
4137
424a19f8 4138 return 0;
34ca941c
LP
4139}
4140
1554afae
LP
4141int mknod_atomic(const char *path, mode_t mode, dev_t dev) {
4142 _cleanup_free_ char *t = NULL;
4143
4144 assert(path);
4145
4146 t = tempfn_random(path);
4147 if (!t)
4148 return -ENOMEM;
4149
4150 if (mknod(t, mode, dev) < 0)
4151 return -errno;
4152
4153 if (rename(t, path) < 0) {
4154 unlink_noerrno(t);
4155 return -errno;
4156 }
4157
4158 return 0;
4159}
4160
4161int mkfifo_atomic(const char *path, mode_t mode) {
4162 _cleanup_free_ char *t = NULL;
4163
4164 assert(path);
4165
4166 t = tempfn_random(path);
4167 if (!t)
4168 return -ENOMEM;
4169
4170 if (mkfifo(t, mode) < 0)
4171 return -errno;
4172
4173 if (rename(t, path) < 0) {
4174 unlink_noerrno(t);
4175 return -errno;
4176 }
4177
4178 return 0;
4179}
4180
4d6d6518
LP
4181bool display_is_local(const char *display) {
4182 assert(display);
4183
4184 return
4185 display[0] == ':' &&
4186 display[1] >= '0' &&
4187 display[1] <= '9';
4188}
4189
4190int socket_from_display(const char *display, char **path) {
4191 size_t k;
4192 char *f, *c;
4193
4194 assert(display);
4195 assert(path);
4196
4197 if (!display_is_local(display))
4198 return -EINVAL;
4199
4200 k = strspn(display+1, "0123456789");
4201
f8294e41 4202 f = new(char, strlen("/tmp/.X11-unix/X") + k + 1);
4d6d6518
LP
4203 if (!f)
4204 return -ENOMEM;
4205
4206 c = stpcpy(f, "/tmp/.X11-unix/X");
4207 memcpy(c, display+1, k);
4208 c[k] = 0;
4209
4210 *path = f;
4211
4212 return 0;
4213}
4214
d05c5031
LP
4215int get_user_creds(
4216 const char **username,
4217 uid_t *uid, gid_t *gid,
4218 const char **home,
4219 const char **shell) {
4220
1cccf435 4221 struct passwd *p;
ddd88763 4222 uid_t u;
1cccf435
MV
4223
4224 assert(username);
4225 assert(*username);
1cccf435
MV
4226
4227 /* We enforce some special rules for uid=0: in order to avoid
4228 * NSS lookups for root we hardcode its data. */
4229
4230 if (streq(*username, "root") || streq(*username, "0")) {
4231 *username = "root";
4b67834e
LP
4232
4233 if (uid)
4234 *uid = 0;
4235
4236 if (gid)
4237 *gid = 0;
4238
4239 if (home)
4240 *home = "/root";
d05c5031
LP
4241
4242 if (shell)
4243 *shell = "/bin/sh";
4244
1cccf435
MV
4245 return 0;
4246 }
4247
ddd88763 4248 if (parse_uid(*username, &u) >= 0) {
1cccf435 4249 errno = 0;
ddd88763 4250 p = getpwuid(u);
1cccf435
MV
4251
4252 /* If there are multiple users with the same id, make
4253 * sure to leave $USER to the configured value instead
4254 * of the first occurrence in the database. However if
4255 * the uid was configured by a numeric uid, then let's
4256 * pick the real username from /etc/passwd. */
4257 if (p)
4258 *username = p->pw_name;
4259 } else {
4260 errno = 0;
4261 p = getpwnam(*username);
4262 }
4263
4264 if (!p)
8333c77e 4265 return errno > 0 ? -errno : -ESRCH;
1cccf435 4266
4b67834e
LP
4267 if (uid)
4268 *uid = p->pw_uid;
4269
4270 if (gid)
4271 *gid = p->pw_gid;
4272
4273 if (home)
4274 *home = p->pw_dir;
4275
d05c5031
LP
4276 if (shell)
4277 *shell = p->pw_shell;
4278
4b67834e
LP
4279 return 0;
4280}
4281
59164be4
LP
4282char* uid_to_name(uid_t uid) {
4283 struct passwd *p;
4284 char *r;
4285
4286 if (uid == 0)
4287 return strdup("root");
4288
4289 p = getpwuid(uid);
4290 if (p)
4291 return strdup(p->pw_name);
4292
de0671ee 4293 if (asprintf(&r, UID_FMT, uid) < 0)
59164be4
LP
4294 return NULL;
4295
4296 return r;
4297}
4298
4468addc
LP
4299char* gid_to_name(gid_t gid) {
4300 struct group *p;
4301 char *r;
4302
4303 if (gid == 0)
4304 return strdup("root");
4305
4306 p = getgrgid(gid);
4307 if (p)
4308 return strdup(p->gr_name);
4309
de0671ee 4310 if (asprintf(&r, GID_FMT, gid) < 0)
4468addc
LP
4311 return NULL;
4312
4313 return r;
4314}
4315
4b67834e
LP
4316int get_group_creds(const char **groupname, gid_t *gid) {
4317 struct group *g;
4318 gid_t id;
4319
4320 assert(groupname);
4321
4322 /* We enforce some special rules for gid=0: in order to avoid
4323 * NSS lookups for root we hardcode its data. */
4324
4325 if (streq(*groupname, "root") || streq(*groupname, "0")) {
4326 *groupname = "root";
4327
4328 if (gid)
4329 *gid = 0;
4330
4331 return 0;
4332 }
4333
4334 if (parse_gid(*groupname, &id) >= 0) {
4335 errno = 0;
4336 g = getgrgid(id);
4337
4338 if (g)
4339 *groupname = g->gr_name;
4340 } else {
4341 errno = 0;
4342 g = getgrnam(*groupname);
4343 }
4344
4345 if (!g)
8333c77e 4346 return errno > 0 ? -errno : -ESRCH;
4b67834e
LP
4347
4348 if (gid)
4349 *gid = g->gr_gid;
4350
1cccf435
MV
4351 return 0;
4352}
4353
4468addc
LP
4354int in_gid(gid_t gid) {
4355 gid_t *gids;
43673799
LP
4356 int ngroups_max, r, i;
4357
43673799
LP
4358 if (getgid() == gid)
4359 return 1;
4360
4361 if (getegid() == gid)
4362 return 1;
4363
4364 ngroups_max = sysconf(_SC_NGROUPS_MAX);
4365 assert(ngroups_max > 0);
4366
4367 gids = alloca(sizeof(gid_t) * ngroups_max);
4368
4369 r = getgroups(ngroups_max, gids);
4370 if (r < 0)
4371 return -errno;
4372
4373 for (i = 0; i < r; i++)
4374 if (gids[i] == gid)
4375 return 1;
4376
4377 return 0;
4378}
4379
4468addc
LP
4380int in_group(const char *name) {
4381 int r;
4382 gid_t gid;
4383
4384 r = get_group_creds(&name, &gid);
4385 if (r < 0)
4386 return r;
4387
4388 return in_gid(gid);
4389}
4390
8092a428 4391int glob_exists(const char *path) {
7fd1b19b 4392 _cleanup_globfree_ glob_t g = {};
8d98da3f 4393 int k;
8092a428
LP
4394
4395 assert(path);
4396
8092a428
LP
4397 errno = 0;
4398 k = glob(path, GLOB_NOSORT|GLOB_BRACE, NULL, &g);
4399
4400 if (k == GLOB_NOMATCH)
8d98da3f 4401 return 0;
8092a428 4402 else if (k == GLOB_NOSPACE)
8d98da3f 4403 return -ENOMEM;
8092a428 4404 else if (k == 0)
8d98da3f 4405 return !strv_isempty(g.gl_pathv);
8092a428 4406 else
8d98da3f
ZJS
4407 return errno ? -errno : -EIO;
4408}
8092a428 4409
8d98da3f
ZJS
4410int glob_extend(char ***strv, const char *path) {
4411 _cleanup_globfree_ glob_t g = {};
4412 int k;
4413 char **p;
4414
4415 errno = 0;
a8ccacf5 4416 k = glob(path, GLOB_NOSORT|GLOB_BRACE, NULL, &g);
8d98da3f
ZJS
4417
4418 if (k == GLOB_NOMATCH)
4419 return -ENOENT;
4420 else if (k == GLOB_NOSPACE)
4421 return -ENOMEM;
4422 else if (k != 0 || strv_isempty(g.gl_pathv))
4423 return errno ? -errno : -EIO;
4424
4425 STRV_FOREACH(p, g.gl_pathv) {
4426 k = strv_extend(strv, *p);
4427 if (k < 0)
4428 break;
4429 }
4430
4431 return k;
8092a428
LP
4432}
4433
83096483
LP
4434int dirent_ensure_type(DIR *d, struct dirent *de) {
4435 struct stat st;
4436
4437 assert(d);
4438 assert(de);
4439
4440 if (de->d_type != DT_UNKNOWN)
4441 return 0;
4442
4443 if (fstatat(dirfd(d), de->d_name, &st, AT_SYMLINK_NOFOLLOW) < 0)
4444 return -errno;
4445
4446 de->d_type =
4447 S_ISREG(st.st_mode) ? DT_REG :
4448 S_ISDIR(st.st_mode) ? DT_DIR :
4449 S_ISLNK(st.st_mode) ? DT_LNK :
4450 S_ISFIFO(st.st_mode) ? DT_FIFO :
4451 S_ISSOCK(st.st_mode) ? DT_SOCK :
4452 S_ISCHR(st.st_mode) ? DT_CHR :
4453 S_ISBLK(st.st_mode) ? DT_BLK :
4454 DT_UNKNOWN;
4455
4456 return 0;
4457}
4458
034a2a52 4459int get_files_in_directory(const char *path, char ***list) {
893fa014
ZJS
4460 _cleanup_closedir_ DIR *d = NULL;
4461 size_t bufsize = 0, n = 0;
4462 _cleanup_strv_free_ char **l = NULL;
034a2a52
LP
4463
4464 assert(path);
d60ef526
LP
4465
4466 /* Returns all files in a directory in *list, and the number
4467 * of files as return value. If list is NULL returns only the
893fa014 4468 * number. */
034a2a52
LP
4469
4470 d = opendir(path);
8ea913b2
LP
4471 if (!d)
4472 return -errno;
4473
034a2a52 4474 for (;;) {
7d5e9c0f 4475 struct dirent *de;
034a2a52 4476
3fd11280
FW
4477 errno = 0;
4478 de = readdir(d);
4479 if (!de && errno != 0)
4480 return -errno;
034a2a52
LP
4481 if (!de)
4482 break;
4483
4484 dirent_ensure_type(d, de);
4485
4486 if (!dirent_is_file(de))
4487 continue;
4488
d60ef526 4489 if (list) {
893fa014
ZJS
4490 /* one extra slot is needed for the terminating NULL */
4491 if (!GREEDY_REALLOC(l, bufsize, n + 2))
4492 return -ENOMEM;
034a2a52 4493
893fa014
ZJS
4494 l[n] = strdup(de->d_name);
4495 if (!l[n])
4496 return -ENOMEM;
034a2a52 4497
893fa014 4498 l[++n] = NULL;
d60ef526 4499 } else
893fa014 4500 n++;
034a2a52
LP
4501 }
4502
893fa014
ZJS
4503 if (list) {
4504 *list = l;
4505 l = NULL; /* avoid freeing */
4506 }
034a2a52 4507
893fa014 4508 return n;
034a2a52
LP
4509}
4510
b7def684 4511char *strjoin(const char *x, ...) {
911a4828
LP
4512 va_list ap;
4513 size_t l;
4514 char *r, *p;
4515
4516 va_start(ap, x);
4517
4518 if (x) {
4519 l = strlen(x);
4520
4521 for (;;) {
4522 const char *t;
040f18ea 4523 size_t n;
911a4828
LP
4524
4525 t = va_arg(ap, const char *);
4526 if (!t)
4527 break;
4528
040f18ea 4529 n = strlen(t);
e98055de
LN
4530 if (n > ((size_t) -1) - l) {
4531 va_end(ap);
040f18ea 4532 return NULL;
e98055de 4533 }
040f18ea
LP
4534
4535 l += n;
911a4828
LP
4536 }
4537 } else
4538 l = 0;
4539
4540 va_end(ap);
4541
4542 r = new(char, l+1);
4543 if (!r)
4544 return NULL;
4545
4546 if (x) {
4547 p = stpcpy(r, x);
4548
4549 va_start(ap, x);
4550
4551 for (;;) {
4552 const char *t;
4553
4554 t = va_arg(ap, const char *);
4555 if (!t)
4556 break;
4557
4558 p = stpcpy(p, t);
4559 }
8ea913b2
LP
4560
4561 va_end(ap);
911a4828
LP
4562 } else
4563 r[0] = 0;
4564
4565 return r;
4566}
4567
b636465b 4568bool is_main_thread(void) {
ec202eae 4569 static thread_local int cached = 0;
b636465b
LP
4570
4571 if (_unlikely_(cached == 0))
4572 cached = getpid() == gettid() ? 1 : -1;
4573
4574 return cached > 0;
4575}
4576
94959f0f
LP
4577int block_get_whole_disk(dev_t d, dev_t *ret) {
4578 char *p, *s;
4579 int r;
4580 unsigned n, m;
4581
4582 assert(ret);
4583
4584 /* If it has a queue this is good enough for us */
4585 if (asprintf(&p, "/sys/dev/block/%u:%u/queue", major(d), minor(d)) < 0)
4586 return -ENOMEM;
4587
4588 r = access(p, F_OK);
4589 free(p);
4590
4591 if (r >= 0) {
4592 *ret = d;
4593 return 0;
4594 }
4595
4596 /* If it is a partition find the originating device */
4597 if (asprintf(&p, "/sys/dev/block/%u:%u/partition", major(d), minor(d)) < 0)
4598 return -ENOMEM;
4599
4600 r = access(p, F_OK);
4601 free(p);
4602
4603 if (r < 0)
4604 return -ENOENT;
4605
4606 /* Get parent dev_t */
4607 if (asprintf(&p, "/sys/dev/block/%u:%u/../dev", major(d), minor(d)) < 0)
4608 return -ENOMEM;
4609
4610 r = read_one_line_file(p, &s);
4611 free(p);
4612
4613 if (r < 0)
4614 return r;
4615
4616 r = sscanf(s, "%u:%u", &m, &n);
4617 free(s);
4618
4619 if (r != 2)
4620 return -EINVAL;
4621
4622 /* Only return this if it is really good enough for us. */
4623 if (asprintf(&p, "/sys/dev/block/%u:%u/queue", m, n) < 0)
4624 return -ENOMEM;
4625
4626 r = access(p, F_OK);
4627 free(p);
4628
4629 if (r >= 0) {
4630 *ret = makedev(m, n);
4631 return 0;
4632 }
4633
4634 return -ENOENT;
4635}
4636
8d53b453 4637int file_is_priv_sticky(const char *p) {
ad293f5a
LP
4638 struct stat st;
4639
4640 assert(p);
4641
4642 if (lstat(p, &st) < 0)
4643 return -errno;
4644
4645 return
8d53b453 4646 (st.st_uid == 0 || st.st_uid == getuid()) &&
ad293f5a
LP
4647 (st.st_mode & S_ISVTX);
4648}
94959f0f 4649
f41607a6
LP
4650static const char *const ioprio_class_table[] = {
4651 [IOPRIO_CLASS_NONE] = "none",
4652 [IOPRIO_CLASS_RT] = "realtime",
4653 [IOPRIO_CLASS_BE] = "best-effort",
4654 [IOPRIO_CLASS_IDLE] = "idle"
4655};
4656
f8b69d1d 4657DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(ioprio_class, int, INT_MAX);
f41607a6
LP
4658
4659static const char *const sigchld_code_table[] = {
4660 [CLD_EXITED] = "exited",
4661 [CLD_KILLED] = "killed",
4662 [CLD_DUMPED] = "dumped",
4663 [CLD_TRAPPED] = "trapped",
4664 [CLD_STOPPED] = "stopped",
4665 [CLD_CONTINUED] = "continued",
4666};
4667
4668DEFINE_STRING_TABLE_LOOKUP(sigchld_code, int);
4669
4670static const char *const log_facility_unshifted_table[LOG_NFACILITIES] = {
4671 [LOG_FAC(LOG_KERN)] = "kern",
4672 [LOG_FAC(LOG_USER)] = "user",
4673 [LOG_FAC(LOG_MAIL)] = "mail",
4674 [LOG_FAC(LOG_DAEMON)] = "daemon",
4675 [LOG_FAC(LOG_AUTH)] = "auth",
4676 [LOG_FAC(LOG_SYSLOG)] = "syslog",
4677 [LOG_FAC(LOG_LPR)] = "lpr",
4678 [LOG_FAC(LOG_NEWS)] = "news",
4679 [LOG_FAC(LOG_UUCP)] = "uucp",
4680 [LOG_FAC(LOG_CRON)] = "cron",
4681 [LOG_FAC(LOG_AUTHPRIV)] = "authpriv",
4682 [LOG_FAC(LOG_FTP)] = "ftp",
4683 [LOG_FAC(LOG_LOCAL0)] = "local0",
4684 [LOG_FAC(LOG_LOCAL1)] = "local1",
4685 [LOG_FAC(LOG_LOCAL2)] = "local2",
4686 [LOG_FAC(LOG_LOCAL3)] = "local3",
4687 [LOG_FAC(LOG_LOCAL4)] = "local4",
4688 [LOG_FAC(LOG_LOCAL5)] = "local5",
4689 [LOG_FAC(LOG_LOCAL6)] = "local6",
4690 [LOG_FAC(LOG_LOCAL7)] = "local7"
4691};
4692
f8b69d1d 4693DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(log_facility_unshifted, int, LOG_FAC(~0));
f41607a6
LP
4694
4695static const char *const log_level_table[] = {
4696 [LOG_EMERG] = "emerg",
4697 [LOG_ALERT] = "alert",
4698 [LOG_CRIT] = "crit",
4699 [LOG_ERR] = "err",
4700 [LOG_WARNING] = "warning",
4701 [LOG_NOTICE] = "notice",
4702 [LOG_INFO] = "info",
4703 [LOG_DEBUG] = "debug"
4704};
4705
f8b69d1d 4706DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(log_level, int, LOG_DEBUG);
f41607a6
LP
4707
4708static const char* const sched_policy_table[] = {
4709 [SCHED_OTHER] = "other",
4710 [SCHED_BATCH] = "batch",
4711 [SCHED_IDLE] = "idle",
4712 [SCHED_FIFO] = "fifo",
4713 [SCHED_RR] = "rr"
4714};
4715
f8b69d1d 4716DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(sched_policy, int, INT_MAX);
f41607a6 4717
517d56b1 4718static const char* const rlimit_table[_RLIMIT_MAX] = {
f41607a6
LP
4719 [RLIMIT_CPU] = "LimitCPU",
4720 [RLIMIT_FSIZE] = "LimitFSIZE",
4721 [RLIMIT_DATA] = "LimitDATA",
4722 [RLIMIT_STACK] = "LimitSTACK",
4723 [RLIMIT_CORE] = "LimitCORE",
4724 [RLIMIT_RSS] = "LimitRSS",
4725 [RLIMIT_NOFILE] = "LimitNOFILE",
4726 [RLIMIT_AS] = "LimitAS",
4727 [RLIMIT_NPROC] = "LimitNPROC",
4728 [RLIMIT_MEMLOCK] = "LimitMEMLOCK",
4729 [RLIMIT_LOCKS] = "LimitLOCKS",
4730 [RLIMIT_SIGPENDING] = "LimitSIGPENDING",
4731 [RLIMIT_MSGQUEUE] = "LimitMSGQUEUE",
4732 [RLIMIT_NICE] = "LimitNICE",
4733 [RLIMIT_RTPRIO] = "LimitRTPRIO",
4734 [RLIMIT_RTTIME] = "LimitRTTIME"
4735};
4736
4737DEFINE_STRING_TABLE_LOOKUP(rlimit, int);
4738
4739static const char* const ip_tos_table[] = {
4740 [IPTOS_LOWDELAY] = "low-delay",
4741 [IPTOS_THROUGHPUT] = "throughput",
4742 [IPTOS_RELIABILITY] = "reliability",
4743 [IPTOS_LOWCOST] = "low-cost",
4744};
4745
f8b69d1d 4746DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(ip_tos, int, 0xff);
f41607a6 4747
4e240ab0 4748static const char *const __signal_table[] = {
f41607a6
LP
4749 [SIGHUP] = "HUP",
4750 [SIGINT] = "INT",
4751 [SIGQUIT] = "QUIT",
4752 [SIGILL] = "ILL",
4753 [SIGTRAP] = "TRAP",
4754 [SIGABRT] = "ABRT",
4755 [SIGBUS] = "BUS",
4756 [SIGFPE] = "FPE",
4757 [SIGKILL] = "KILL",
4758 [SIGUSR1] = "USR1",
4759 [SIGSEGV] = "SEGV",
4760 [SIGUSR2] = "USR2",
4761 [SIGPIPE] = "PIPE",
4762 [SIGALRM] = "ALRM",
4763 [SIGTERM] = "TERM",
4764#ifdef SIGSTKFLT
4765 [SIGSTKFLT] = "STKFLT", /* Linux on SPARC doesn't know SIGSTKFLT */
4766#endif
4767 [SIGCHLD] = "CHLD",
4768 [SIGCONT] = "CONT",
4769 [SIGSTOP] = "STOP",
4770 [SIGTSTP] = "TSTP",
4771 [SIGTTIN] = "TTIN",
4772 [SIGTTOU] = "TTOU",
4773 [SIGURG] = "URG",
4774 [SIGXCPU] = "XCPU",
4775 [SIGXFSZ] = "XFSZ",
4776 [SIGVTALRM] = "VTALRM",
4777 [SIGPROF] = "PROF",
4778 [SIGWINCH] = "WINCH",
4779 [SIGIO] = "IO",
4780 [SIGPWR] = "PWR",
4781 [SIGSYS] = "SYS"
4782};
4783
4e240ab0
MS
4784DEFINE_PRIVATE_STRING_TABLE_LOOKUP(__signal, int);
4785
4786const char *signal_to_string(int signo) {
ec202eae 4787 static thread_local char buf[sizeof("RTMIN+")-1 + DECIMAL_STR_MAX(int) + 1];
4e240ab0
MS
4788 const char *name;
4789
4790 name = __signal_to_string(signo);
4791 if (name)
4792 return name;
4793
4794 if (signo >= SIGRTMIN && signo <= SIGRTMAX)
fa70beaa 4795 snprintf(buf, sizeof(buf), "RTMIN+%d", signo - SIGRTMIN);
4e240ab0 4796 else
fa70beaa
LP
4797 snprintf(buf, sizeof(buf), "%d", signo);
4798
4e240ab0
MS
4799 return buf;
4800}
4801
4802int signal_from_string(const char *s) {
4803 int signo;
4804 int offset = 0;
4805 unsigned u;
4806
040f18ea 4807 signo = __signal_from_string(s);
4e240ab0
MS
4808 if (signo > 0)
4809 return signo;
4810
4811 if (startswith(s, "RTMIN+")) {
4812 s += 6;
4813 offset = SIGRTMIN;
4814 }
4815 if (safe_atou(s, &u) >= 0) {
4816 signo = (int) u + offset;
4817 if (signo > 0 && signo < _NSIG)
4818 return signo;
4819 }
4820 return -1;
4821}
65457142
FC
4822
4823bool kexec_loaded(void) {
4824 bool loaded = false;
4825 char *s;
4826
4827 if (read_one_line_file("/sys/kernel/kexec_loaded", &s) >= 0) {
4828 if (s[0] == '1')
4829 loaded = true;
4830 free(s);
4831 }
4832 return loaded;
4833}
fb9de93d
LP
4834
4835int strdup_or_null(const char *a, char **b) {
4836 char *c;
4837
4838 assert(b);
4839
4840 if (!a) {
4841 *b = NULL;
4842 return 0;
4843 }
4844
4845 c = strdup(a);
4846 if (!c)
4847 return -ENOMEM;
4848
4849 *b = c;
4850 return 0;
4851}
64685e0c 4852
87d2c1ff
LP
4853int prot_from_flags(int flags) {
4854
4855 switch (flags & O_ACCMODE) {
4856
4857 case O_RDONLY:
4858 return PROT_READ;
4859
4860 case O_WRONLY:
4861 return PROT_WRITE;
4862
4863 case O_RDWR:
4864 return PROT_READ|PROT_WRITE;
4865
4866 default:
4867 return -EINVAL;
4868 }
7c99e0c1 4869}
689b9a22 4870
babfc091 4871char *format_bytes(char *buf, size_t l, off_t t) {
c0f99c21 4872 unsigned i;
babfc091
LP
4873
4874 static const struct {
4875 const char *suffix;
4876 off_t factor;
4877 } table[] = {
32895bb3
LP
4878 { "E", 1024ULL*1024ULL*1024ULL*1024ULL*1024ULL*1024ULL },
4879 { "P", 1024ULL*1024ULL*1024ULL*1024ULL*1024ULL },
babfc091
LP
4880 { "T", 1024ULL*1024ULL*1024ULL*1024ULL },
4881 { "G", 1024ULL*1024ULL*1024ULL },
4882 { "M", 1024ULL*1024ULL },
4883 { "K", 1024ULL },
4884 };
4885
4886 for (i = 0; i < ELEMENTSOF(table); i++) {
4887
4888 if (t >= table[i].factor) {
4889 snprintf(buf, l,
4890 "%llu.%llu%s",
4891 (unsigned long long) (t / table[i].factor),
4892 (unsigned long long) (((t*10ULL) / table[i].factor) % 10ULL),
4893 table[i].suffix);
4894
4895 goto finish;
4896 }
4897 }
4898
4899 snprintf(buf, l, "%lluB", (unsigned long long) t);
4900
4901finish:
4902 buf[l-1] = 0;
4903 return buf;
4904
4905}
55d7bfc1
LP
4906
4907void* memdup(const void *p, size_t l) {
4908 void *r;
4909
4910 assert(p);
4911
4912 r = malloc(l);
4913 if (!r)
4914 return NULL;
4915
4916 memcpy(r, p, l);
4917 return r;
4918}
bb99a35a
LP
4919
4920int fd_inc_sndbuf(int fd, size_t n) {
4921 int r, value;
4922 socklen_t l = sizeof(value);
4923
4924 r = getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &value, &l);
92d75ca4 4925 if (r >= 0 && l == sizeof(value) && (size_t) value >= n*2)
bb99a35a
LP
4926 return 0;
4927
92d75ca4
LP
4928 /* If we have the privileges we will ignore the kernel limit. */
4929
bb99a35a 4930 value = (int) n;
92d75ca4
LP
4931 if (setsockopt(fd, SOL_SOCKET, SO_SNDBUFFORCE, &value, sizeof(value)) < 0)
4932 if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &value, sizeof(value)) < 0)
4933 return -errno;
bb99a35a
LP
4934
4935 return 1;
4936}
4937
4938int fd_inc_rcvbuf(int fd, size_t n) {
4939 int r, value;
4940 socklen_t l = sizeof(value);
4941
4942 r = getsockopt(fd, SOL_SOCKET, SO_RCVBUF, &value, &l);
92d75ca4 4943 if (r >= 0 && l == sizeof(value) && (size_t) value >= n*2)
bb99a35a
LP
4944 return 0;
4945
92d75ca4 4946 /* If we have the privileges we will ignore the kernel limit. */
bb99a35a 4947
92d75ca4
LP
4948 value = (int) n;
4949 if (setsockopt(fd, SOL_SOCKET, SO_RCVBUFFORCE, &value, sizeof(value)) < 0)
4950 if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &value, sizeof(value)) < 0)
4951 return -errno;
bb99a35a
LP
4952 return 1;
4953}
6bb92a16 4954
9bdc770c 4955int fork_agent(pid_t *pid, const int except[], unsigned n_except, const char *path, ...) {
6bb92a16
LP
4956 pid_t parent_pid, agent_pid;
4957 int fd;
4958 bool stdout_is_tty, stderr_is_tty;
4959 unsigned n, i;
4960 va_list ap;
4961 char **l;
4962
4963 assert(pid);
4964 assert(path);
4965
4966 parent_pid = getpid();
4967
4968 /* Spawns a temporary TTY agent, making sure it goes away when
4969 * we go away */
4970
4971 agent_pid = fork();
4972 if (agent_pid < 0)
4973 return -errno;
4974
4975 if (agent_pid != 0) {
4976 *pid = agent_pid;
4977 return 0;
4978 }
4979
4980 /* In the child:
4981 *
4982 * Make sure the agent goes away when the parent dies */
4983 if (prctl(PR_SET_PDEATHSIG, SIGTERM) < 0)
4984 _exit(EXIT_FAILURE);
4985
4986 /* Check whether our parent died before we were able
4987 * to set the death signal */
4988 if (getppid() != parent_pid)
4989 _exit(EXIT_SUCCESS);
4990
4991 /* Don't leak fds to the agent */
9bdc770c 4992 close_all_fds(except, n_except);
6bb92a16
LP
4993
4994 stdout_is_tty = isatty(STDOUT_FILENO);
4995 stderr_is_tty = isatty(STDERR_FILENO);
4996
4997 if (!stdout_is_tty || !stderr_is_tty) {
4998 /* Detach from stdout/stderr. and reopen
4999 * /dev/tty for them. This is important to
5000 * ensure that when systemctl is started via
5001 * popen() or a similar call that expects to
5002 * read EOF we actually do generate EOF and
5003 * not delay this indefinitely by because we
5004 * keep an unused copy of stdin around. */
5005 fd = open("/dev/tty", O_WRONLY);
5006 if (fd < 0) {
5007 log_error("Failed to open /dev/tty: %m");
5008 _exit(EXIT_FAILURE);
5009 }
5010
5011 if (!stdout_is_tty)
5012 dup2(fd, STDOUT_FILENO);
5013
5014 if (!stderr_is_tty)
5015 dup2(fd, STDERR_FILENO);
5016
5017 if (fd > 2)
5018 close(fd);
5019 }
5020
5021 /* Count arguments */
5022 va_start(ap, path);
5023 for (n = 0; va_arg(ap, char*); n++)
5024 ;
5025 va_end(ap);
5026
5027 /* Allocate strv */
5028 l = alloca(sizeof(char *) * (n + 1));
5029
5030 /* Fill in arguments */
5031 va_start(ap, path);
5032 for (i = 0; i <= n; i++)
5033 l[i] = va_arg(ap, char*);
5034 va_end(ap);
5035
5036 execv(path, l);
5037 _exit(EXIT_FAILURE);
5038}
68faf98c
LP
5039
5040int setrlimit_closest(int resource, const struct rlimit *rlim) {
5041 struct rlimit highest, fixed;
5042
5043 assert(rlim);
5044
5045 if (setrlimit(resource, rlim) >= 0)
5046 return 0;
5047
5048 if (errno != EPERM)
5049 return -errno;
5050
5051 /* So we failed to set the desired setrlimit, then let's try
5052 * to get as close as we can */
5053 assert_se(getrlimit(resource, &highest) == 0);
5054
5055 fixed.rlim_cur = MIN(rlim->rlim_cur, highest.rlim_max);
5056 fixed.rlim_max = MIN(rlim->rlim_max, highest.rlim_max);
5057
5058 if (setrlimit(resource, &fixed) < 0)
5059 return -errno;
5060
5061 return 0;
5062}
3d9a4122 5063
ab94af92 5064int getenv_for_pid(pid_t pid, const char *field, char **_value) {
49aa47c7
LP
5065 _cleanup_fclose_ FILE *f = NULL;
5066 char *value = NULL;
ab94af92 5067 int r;
ab94af92
LP
5068 bool done = false;
5069 size_t l;
49aa47c7 5070 const char *path;
ab94af92 5071
49aa47c7 5072 assert(pid >= 0);
ab94af92
LP
5073 assert(field);
5074 assert(_value);
5075
b68fa010 5076 path = procfs_file_alloca(pid, "environ");
ab94af92
LP
5077
5078 f = fopen(path, "re");
5079 if (!f)
5080 return -errno;
5081
5082 l = strlen(field);
5083 r = 0;
5084
5085 do {
5086 char line[LINE_MAX];
5087 unsigned i;
5088
5089 for (i = 0; i < sizeof(line)-1; i++) {
5090 int c;
5091
5092 c = getc(f);
5093 if (_unlikely_(c == EOF)) {
5094 done = true;
5095 break;
5096 } else if (c == 0)
5097 break;
5098
5099 line[i] = c;
5100 }
5101 line[i] = 0;
5102
5103 if (memcmp(line, field, l) == 0 && line[l] == '=') {
5104 value = strdup(line + l + 1);
49aa47c7
LP
5105 if (!value)
5106 return -ENOMEM;
ab94af92
LP
5107
5108 r = 1;
5109 break;
5110 }
5111
5112 } while (!done);
5113
49aa47c7 5114 *_value = value;
ab94af92
LP
5115 return r;
5116}
d889a206 5117
49dbfa7b
LP
5118bool is_valid_documentation_url(const char *url) {
5119 assert(url);
5120
5121 if (startswith(url, "http://") && url[7])
5122 return true;
5123
5124 if (startswith(url, "https://") && url[8])
5125 return true;
5126
5127 if (startswith(url, "file:") && url[5])
5128 return true;
5129
5130 if (startswith(url, "info:") && url[5])
5131 return true;
5132
5133 if (startswith(url, "man:") && url[4])
5134 return true;
5135
5136 return false;
5137}
9be346c9
HH
5138
5139bool in_initrd(void) {
73020ab2 5140 static int saved = -1;
825c6fe5 5141 struct statfs s;
8f33b5b8 5142
825c6fe5
LP
5143 if (saved >= 0)
5144 return saved;
5145
5146 /* We make two checks here:
5147 *
5148 * 1. the flag file /etc/initrd-release must exist
5149 * 2. the root file system must be a memory file system
5150 *
5151 * The second check is extra paranoia, since misdetecting an
5152 * initrd can have bad bad consequences due the initrd
5153 * emptying when transititioning to the main systemd.
5154 */
5155
5156 saved = access("/etc/initrd-release", F_OK) >= 0 &&
5157 statfs("/", &s) >= 0 &&
943aad8c 5158 is_temporary_fs(&s);
9be346c9 5159
8f33b5b8 5160 return saved;
9be346c9 5161}
069cfc85
LP
5162
5163void warn_melody(void) {
e67f47e5 5164 _cleanup_close_ int fd = -1;
069cfc85
LP
5165
5166 fd = open("/dev/console", O_WRONLY|O_CLOEXEC|O_NOCTTY);
5167 if (fd < 0)
5168 return;
5169
040f18ea 5170 /* Yeah, this is synchronous. Kinda sucks. But well... */
069cfc85
LP
5171
5172 ioctl(fd, KIOCSOUND, (int)(1193180/440));
5173 usleep(125*USEC_PER_MSEC);
5174
5175 ioctl(fd, KIOCSOUND, (int)(1193180/220));
5176 usleep(125*USEC_PER_MSEC);
5177
5178 ioctl(fd, KIOCSOUND, (int)(1193180/220));
5179 usleep(125*USEC_PER_MSEC);
5180
5181 ioctl(fd, KIOCSOUND, 0);
069cfc85 5182}
cd3bd60a
LP
5183
5184int make_console_stdio(void) {
5185 int fd, r;
5186
5187 /* Make /dev/console the controlling terminal and stdin/stdout/stderr */
5188
5189 fd = acquire_terminal("/dev/console", false, true, true, (usec_t) -1);
5190 if (fd < 0) {
5191 log_error("Failed to acquire terminal: %s", strerror(-fd));
5192 return fd;
5193 }
5194
5195 r = make_stdio(fd);
5196 if (r < 0) {
5197 log_error("Failed to duplicate terminal fd: %s", strerror(-r));
5198 return r;
5199 }
5200
5201 return 0;
5202}
7c5f152a
LP
5203
5204int get_home_dir(char **_h) {
2cfbd749 5205 struct passwd *p;
7c5f152a 5206 const char *e;
2cfbd749 5207 char *h;
7c5f152a 5208 uid_t u;
7c5f152a
LP
5209
5210 assert(_h);
5211
5212 /* Take the user specified one */
5213 e = getenv("HOME");
5214 if (e) {
5215 h = strdup(e);
5216 if (!h)
5217 return -ENOMEM;
5218
5219 *_h = h;
5220 return 0;
5221 }
5222
5223 /* Hardcode home directory for root to avoid NSS */
5224 u = getuid();
5225 if (u == 0) {
5226 h = strdup("/root");
5227 if (!h)
5228 return -ENOMEM;
5229
5230 *_h = h;
5231 return 0;
5232 }
5233
5234 /* Check the database... */
5235 errno = 0;
5236 p = getpwuid(u);
5237 if (!p)
bcb161b0 5238 return errno > 0 ? -errno : -ESRCH;
7c5f152a
LP
5239
5240 if (!path_is_absolute(p->pw_dir))
5241 return -EINVAL;
5242
5243 h = strdup(p->pw_dir);
5244 if (!h)
5245 return -ENOMEM;
5246
5247 *_h = h;
5248 return 0;
5249}
5250
2cfbd749
LP
5251int get_shell(char **_s) {
5252 struct passwd *p;
5253 const char *e;
5254 char *s;
5255 uid_t u;
5256
5257 assert(_s);
5258
5259 /* Take the user specified one */
5260 e = getenv("SHELL");
5261 if (e) {
5262 s = strdup(e);
5263 if (!s)
5264 return -ENOMEM;
5265
5266 *_s = s;
5267 return 0;
5268 }
5269
5270 /* Hardcode home directory for root to avoid NSS */
5271 u = getuid();
5272 if (u == 0) {
5273 s = strdup("/bin/sh");
5274 if (!s)
5275 return -ENOMEM;
5276
5277 *_s = s;
5278 return 0;
5279 }
5280
5281 /* Check the database... */
5282 errno = 0;
5283 p = getpwuid(u);
5284 if (!p)
5285 return errno > 0 ? -errno : -ESRCH;
5286
5287 if (!path_is_absolute(p->pw_shell))
5288 return -EINVAL;
5289
5290 s = strdup(p->pw_shell);
5291 if (!s)
5292 return -ENOMEM;
5293
5294 *_s = s;
5295 return 0;
5296}
5297
0b507b17
LP
5298bool filename_is_safe(const char *p) {
5299
5300 if (isempty(p))
5301 return false;
5302
5303 if (strchr(p, '/'))
5304 return false;
5305
5306 if (streq(p, "."))
5307 return false;
5308
5309 if (streq(p, ".."))
5310 return false;
5311
5312 if (strlen(p) > FILENAME_MAX)
5313 return false;
5314
5315 return true;
5316}
5317
5318bool string_is_safe(const char *p) {
5319 const char *t;
5320
5321 assert(p);
5322
5323 for (t = p; *t; t++) {
01539d6e 5324 if (*t > 0 && *t < ' ')
0b507b17
LP
5325 return false;
5326
011afa76 5327 if (strchr("\\\"\'", *t))
0b507b17
LP
5328 return false;
5329 }
5330
5331 return true;
5332}
cfbc22ab 5333
ac4c8d6d
ZJS
5334/**
5335 * Check if a string contains control characters.
5336 * Spaces and tabs are not considered control characters.
5337 */
4d1a6904
LP
5338bool string_has_cc(const char *p) {
5339 const char *t;
5340
5341 assert(p);
5342
5343 for (t = p; *t; t++)
da2620a5 5344 if (*t > 0 && *t < ' ' && *t != '\t')
4d1a6904
LP
5345 return true;
5346
5347 return false;
5348}
5349
e884315e
LP
5350bool path_is_safe(const char *p) {
5351
5352 if (isempty(p))
5353 return false;
5354
5355 if (streq(p, "..") || startswith(p, "../") || endswith(p, "/..") || strstr(p, "/../"))
5356 return false;
5357
5358 if (strlen(p) > PATH_MAX)
5359 return false;
5360
5361 /* The following two checks are not really dangerous, but hey, they still are confusing */
5362 if (streq(p, ".") || startswith(p, "./") || endswith(p, "/.") || strstr(p, "/./"))
5363 return false;
5364
5365 if (strstr(p, "//"))
5366 return false;
5367
5368 return true;
5369}
5370
a9e12476
KS
5371/* hey glibc, APIs with callbacks without a user pointer are so useless */
5372void *xbsearch_r(const void *key, const void *base, size_t nmemb, size_t size,
1c574591 5373 int (*compar) (const void *, const void *, void *), void *arg) {
a9e12476
KS
5374 size_t l, u, idx;
5375 const void *p;
5376 int comparison;
5377
5378 l = 0;
5379 u = nmemb;
5380 while (l < u) {
5381 idx = (l + u) / 2;
5382 p = (void *)(((const char *) base) + (idx * size));
5383 comparison = compar(key, p, arg);
5384 if (comparison < 0)
5385 u = idx;
5386 else if (comparison > 0)
5387 l = idx + 1;
5388 else
5389 return (void *)p;
5390 }
5391 return NULL;
5392}
09017585
MS
5393
5394bool is_locale_utf8(void) {
5395 const char *set;
5396 static int cached_answer = -1;
5397
5398 if (cached_answer >= 0)
5399 goto out;
5400
5401 if (!setlocale(LC_ALL, "")) {
5402 cached_answer = true;
5403 goto out;
5404 }
5405
5406 set = nl_langinfo(CODESET);
5407 if (!set) {
5408 cached_answer = true;
5409 goto out;
5410 }
5411
f168c273 5412 if (streq(set, "UTF-8")) {
fee79e01
HH
5413 cached_answer = true;
5414 goto out;
5415 }
5416
6cf2f1d9
HH
5417 /* For LC_CTYPE=="C" return true, because CTYPE is effectly
5418 * unset and everything can do to UTF-8 nowadays. */
fee79e01
HH
5419 set = setlocale(LC_CTYPE, NULL);
5420 if (!set) {
5421 cached_answer = true;
5422 goto out;
5423 }
5424
6cf2f1d9
HH
5425 /* Check result, but ignore the result if C was set
5426 * explicitly. */
5427 cached_answer =
5428 streq(set, "C") &&
5429 !getenv("LC_ALL") &&
5430 !getenv("LC_CTYPE") &&
5431 !getenv("LANG");
fee79e01 5432
09017585 5433out:
6cf2f1d9 5434 return (bool) cached_answer;
09017585 5435}
c339d977
MS
5436
5437const char *draw_special_char(DrawSpecialChar ch) {
5438 static const char *draw_table[2][_DRAW_SPECIAL_CHAR_MAX] = {
6b01f1d3 5439
c339d977 5440 /* UTF-8 */ {
6b01f1d3 5441 [DRAW_TREE_VERTICAL] = "\342\224\202 ", /* │ */
45a5ff0d
MS
5442 [DRAW_TREE_BRANCH] = "\342\224\234\342\224\200", /* ├─ */
5443 [DRAW_TREE_RIGHT] = "\342\224\224\342\224\200", /* └─ */
55c0b89c 5444 [DRAW_TREE_SPACE] = " ", /* */
6b01f1d3
LP
5445 [DRAW_TRIANGULAR_BULLET] = "\342\200\243", /* ‣ */
5446 [DRAW_BLACK_CIRCLE] = "\342\227\217", /* ● */
5447 [DRAW_ARROW] = "\342\206\222", /* → */
13f8b8cb 5448 [DRAW_DASH] = "\342\200\223", /* – */
c339d977 5449 },
6b01f1d3 5450
c339d977 5451 /* ASCII fallback */ {
6b01f1d3 5452 [DRAW_TREE_VERTICAL] = "| ",
45a5ff0d
MS
5453 [DRAW_TREE_BRANCH] = "|-",
5454 [DRAW_TREE_RIGHT] = "`-",
55c0b89c 5455 [DRAW_TREE_SPACE] = " ",
6b01f1d3
LP
5456 [DRAW_TRIANGULAR_BULLET] = ">",
5457 [DRAW_BLACK_CIRCLE] = "*",
5458 [DRAW_ARROW] = "->",
13f8b8cb 5459 [DRAW_DASH] = "-",
c339d977
MS
5460 }
5461 };
5462
5463 return draw_table[!is_locale_utf8()][ch];
5464}
409bc9c3
LP
5465
5466char *strreplace(const char *text, const char *old_string, const char *new_string) {
5467 const char *f;
5468 char *t, *r;
5469 size_t l, old_len, new_len;
5470
5471 assert(text);
5472 assert(old_string);
5473 assert(new_string);
5474
5475 old_len = strlen(old_string);
5476 new_len = strlen(new_string);
5477
5478 l = strlen(text);
5479 r = new(char, l+1);
5480 if (!r)
5481 return NULL;
5482
5483 f = text;
5484 t = r;
5485 while (*f) {
5486 char *a;
5487 size_t d, nl;
5488
5489 if (!startswith(f, old_string)) {
5490 *(t++) = *(f++);
5491 continue;
5492 }
5493
5494 d = t - r;
5495 nl = l - old_len + new_len;
5496 a = realloc(r, nl + 1);
5497 if (!a)
5498 goto oom;
5499
5500 l = nl;
5501 r = a;
5502 t = r + d;
5503
5504 t = stpcpy(t, new_string);
5505 f += old_len;
5506 }
5507
5508 *t = 0;
5509 return r;
5510
5511oom:
5512 free(r);
5513 return NULL;
5514}
e8bc0ea2
LP
5515
5516char *strip_tab_ansi(char **ibuf, size_t *_isz) {
660ddc72 5517 const char *i, *begin = NULL;
e8bc0ea2
LP
5518 enum {
5519 STATE_OTHER,
5520 STATE_ESCAPE,
5521 STATE_BRACKET
5522 } state = STATE_OTHER;
5523 char *obuf = NULL;
5524 size_t osz = 0, isz;
5525 FILE *f;
5526
5527 assert(ibuf);
5528 assert(*ibuf);
5529
5530 /* Strips ANSI color and replaces TABs by 8 spaces */
5531
5532 isz = _isz ? *_isz : strlen(*ibuf);
5533
5534 f = open_memstream(&obuf, &osz);
5535 if (!f)
5536 return NULL;
5537
5538 for (i = *ibuf; i < *ibuf + isz + 1; i++) {
5539
5540 switch (state) {
5541
5542 case STATE_OTHER:
5543 if (i >= *ibuf + isz) /* EOT */
5544 break;
5545 else if (*i == '\x1B')
5546 state = STATE_ESCAPE;
5547 else if (*i == '\t')
5548 fputs(" ", f);
5549 else
5550 fputc(*i, f);
5551 break;
5552
5553 case STATE_ESCAPE:
5554 if (i >= *ibuf + isz) { /* EOT */
5555 fputc('\x1B', f);
5556 break;
5557 } else if (*i == '[') {
5558 state = STATE_BRACKET;
5559 begin = i + 1;
5560 } else {
5561 fputc('\x1B', f);
5562 fputc(*i, f);
5563 state = STATE_OTHER;
5564 }
5565
5566 break;
5567
5568 case STATE_BRACKET:
5569
5570 if (i >= *ibuf + isz || /* EOT */
5571 (!(*i >= '0' && *i <= '9') && *i != ';' && *i != 'm')) {
5572 fputc('\x1B', f);
5573 fputc('[', f);
5574 state = STATE_OTHER;
5575 i = begin-1;
5576 } else if (*i == 'm')
5577 state = STATE_OTHER;
5578 break;
5579 }
5580 }
5581
5582 if (ferror(f)) {
5583 fclose(f);
5584 free(obuf);
5585 return NULL;
5586 }
5587
5588 fclose(f);
5589
5590 free(*ibuf);
5591 *ibuf = obuf;
5592
5593 if (_isz)
5594 *_isz = osz;
5595
5596 return obuf;
5597}
240dbaa4
LP
5598
5599int on_ac_power(void) {
5600 bool found_offline = false, found_online = false;
5601 _cleanup_closedir_ DIR *d = NULL;
5602
5603 d = opendir("/sys/class/power_supply");
5604 if (!d)
5605 return -errno;
5606
5607 for (;;) {
5608 struct dirent *de;
240dbaa4
LP
5609 _cleanup_close_ int fd = -1, device = -1;
5610 char contents[6];
5611 ssize_t n;
240dbaa4 5612
3fd11280
FW
5613 errno = 0;
5614 de = readdir(d);
5615 if (!de && errno != 0)
5616 return -errno;
240dbaa4
LP
5617
5618 if (!de)
5619 break;
5620
5621 if (ignore_file(de->d_name))
5622 continue;
5623
5624 device = openat(dirfd(d), de->d_name, O_DIRECTORY|O_RDONLY|O_CLOEXEC|O_NOCTTY);
5625 if (device < 0) {
5626 if (errno == ENOENT || errno == ENOTDIR)
5627 continue;
5628
5629 return -errno;
5630 }
5631
5632 fd = openat(device, "type", O_RDONLY|O_CLOEXEC|O_NOCTTY);
5633 if (fd < 0) {
5634 if (errno == ENOENT)
5635 continue;
5636
5637 return -errno;
5638 }
5639
5640 n = read(fd, contents, sizeof(contents));
5641 if (n < 0)
5642 return -errno;
5643
5644 if (n != 6 || memcmp(contents, "Mains\n", 6))
5645 continue;
5646
03e334a1 5647 safe_close(fd);
240dbaa4
LP
5648 fd = openat(device, "online", O_RDONLY|O_CLOEXEC|O_NOCTTY);
5649 if (fd < 0) {
5650 if (errno == ENOENT)
5651 continue;
5652
5653 return -errno;
5654 }
5655
5656 n = read(fd, contents, sizeof(contents));
5657 if (n < 0)
5658 return -errno;
5659
5660 if (n != 2 || contents[1] != '\n')
5661 return -EIO;
5662
5663 if (contents[0] == '1') {
5664 found_online = true;
5665 break;
5666 } else if (contents[0] == '0')
5667 found_offline = true;
5668 else
5669 return -EIO;
5670 }
5671
5672 return found_online || !found_offline;
5673}
fabe5c0e 5674
4cf7ea55 5675static int search_and_fopen_internal(const char *path, const char *mode, const char *root, char **search, FILE **_f) {
fabe5c0e
LP
5676 char **i;
5677
5678 assert(path);
5679 assert(mode);
5680 assert(_f);
5681
4cf7ea55 5682 if (!path_strv_canonicalize_absolute_uniq(search, root))
fabe5c0e
LP
5683 return -ENOMEM;
5684
5685 STRV_FOREACH(i, search) {
5686 _cleanup_free_ char *p = NULL;
5687 FILE *f;
5688
5689 p = strjoin(*i, "/", path, NULL);
5690 if (!p)
5691 return -ENOMEM;
5692
5693 f = fopen(p, mode);
5694 if (f) {
5695 *_f = f;
5696 return 0;
5697 }
5698
5699 if (errno != ENOENT)
5700 return -errno;
5701 }
5702
5703 return -ENOENT;
5704}
5705
4cf7ea55 5706int search_and_fopen(const char *path, const char *mode, const char *root, const char **search, FILE **_f) {
fabe5c0e
LP
5707 _cleanup_strv_free_ char **copy = NULL;
5708
5709 assert(path);
5710 assert(mode);
5711 assert(_f);
5712
5713 if (path_is_absolute(path)) {
5714 FILE *f;
5715
5716 f = fopen(path, mode);
5717 if (f) {
5718 *_f = f;
5719 return 0;
5720 }
5721
5722 return -errno;
5723 }
5724
5725 copy = strv_copy((char**) search);
5726 if (!copy)
5727 return -ENOMEM;
5728
4cf7ea55 5729 return search_and_fopen_internal(path, mode, root, copy, _f);
fabe5c0e
LP
5730}
5731
4cf7ea55 5732int search_and_fopen_nulstr(const char *path, const char *mode, const char *root, const char *search, FILE **_f) {
fabe5c0e
LP
5733 _cleanup_strv_free_ char **s = NULL;
5734
5735 if (path_is_absolute(path)) {
5736 FILE *f;
5737
5738 f = fopen(path, mode);
5739 if (f) {
5740 *_f = f;
5741 return 0;
5742 }
5743
5744 return -errno;
5745 }
5746
5747 s = strv_split_nulstr(search);
5748 if (!s)
5749 return -ENOMEM;
5750
4cf7ea55 5751 return search_and_fopen_internal(path, mode, root, s, _f);
fabe5c0e 5752}
c17ec25e 5753
66e35261
LP
5754char *strextend(char **x, ...) {
5755 va_list ap;
5756 size_t f, l;
5757 char *r, *p;
5758
5759 assert(x);
5760
5761 l = f = *x ? strlen(*x) : 0;
5762
5763 va_start(ap, x);
5764 for (;;) {
5765 const char *t;
5766 size_t n;
5767
5768 t = va_arg(ap, const char *);
5769 if (!t)
5770 break;
5771
5772 n = strlen(t);
5773 if (n > ((size_t) -1) - l) {
5774 va_end(ap);
5775 return NULL;
5776 }
5777
5778 l += n;
5779 }
5780 va_end(ap);
5781
5782 r = realloc(*x, l+1);
5783 if (!r)
5784 return NULL;
5785
5786 p = r + f;
5787
5788 va_start(ap, x);
5789 for (;;) {
5790 const char *t;
5791
5792 t = va_arg(ap, const char *);
5793 if (!t)
5794 break;
5795
5796 p = stpcpy(p, t);
5797 }
5798 va_end(ap);
5799
5800 *p = 0;
5801 *x = r;
5802
5803 return r + l;
5804}
9a17484d
LP
5805
5806char *strrep(const char *s, unsigned n) {
5807 size_t l;
5808 char *r, *p;
5809 unsigned i;
5810
5811 assert(s);
5812
5813 l = strlen(s);
5814 p = r = malloc(l * n + 1);
5815 if (!r)
5816 return NULL;
5817
5818 for (i = 0; i < n; i++)
5819 p = stpcpy(p, s);
5820
5821 *p = 0;
5822 return r;
5823}
392d5b37 5824
ca2d3784
ZJS
5825void* greedy_realloc(void **p, size_t *allocated, size_t need, size_t size) {
5826 size_t a, newalloc;
392d5b37
LP
5827 void *q;
5828
98088803 5829 assert(p);
e93c33d4
SL
5830 assert(allocated);
5831
392d5b37
LP
5832 if (*allocated >= need)
5833 return *p;
5834
ca2d3784
ZJS
5835 newalloc = MAX(need * 2, 64u / size);
5836 a = newalloc * size;
98088803
LP
5837
5838 /* check for overflows */
ca2d3784 5839 if (a < size * need)
98088803
LP
5840 return NULL;
5841
392d5b37
LP
5842 q = realloc(*p, a);
5843 if (!q)
5844 return NULL;
5845
5846 *p = q;
ca2d3784 5847 *allocated = newalloc;
392d5b37
LP
5848 return q;
5849}
aa96c6cb 5850
ca2d3784 5851void* greedy_realloc0(void **p, size_t *allocated, size_t need, size_t size) {
98088803 5852 size_t prev;
4545a231
DH
5853 uint8_t *q;
5854
98088803
LP
5855 assert(p);
5856 assert(allocated);
5857
5858 prev = *allocated;
5859
ca2d3784 5860 q = greedy_realloc(p, allocated, need, size);
4545a231
DH
5861 if (!q)
5862 return NULL;
5863
5864 if (*allocated > prev)
ca2d3784 5865 memzero(q + prev * size, (*allocated - prev) * size);
4545a231
DH
5866
5867 return q;
5868}
5869
aa96c6cb
LP
5870bool id128_is_valid(const char *s) {
5871 size_t i, l;
5872
5873 l = strlen(s);
5874 if (l == 32) {
5875
5876 /* Simple formatted 128bit hex string */
5877
5878 for (i = 0; i < l; i++) {
5879 char c = s[i];
5880
5881 if (!(c >= '0' && c <= '9') &&
5882 !(c >= 'a' && c <= 'z') &&
5883 !(c >= 'A' && c <= 'Z'))
5884 return false;
5885 }
5886
5887 } else if (l == 36) {
5888
5889 /* Formatted UUID */
5890
5891 for (i = 0; i < l; i++) {
5892 char c = s[i];
5893
5894 if ((i == 8 || i == 13 || i == 18 || i == 23)) {
5895 if (c != '-')
5896 return false;
5897 } else {
5898 if (!(c >= '0' && c <= '9') &&
5899 !(c >= 'a' && c <= 'z') &&
5900 !(c >= 'A' && c <= 'Z'))
5901 return false;
5902 }
5903 }
5904
5905 } else
5906 return false;
5907
5908 return true;
5909}
7085053a 5910
d4ac85c6
LP
5911int split_pair(const char *s, const char *sep, char **l, char **r) {
5912 char *x, *a, *b;
5913
5914 assert(s);
5915 assert(sep);
5916 assert(l);
5917 assert(r);
5918
5919 if (isempty(sep))
5920 return -EINVAL;
5921
5922 x = strstr(s, sep);
5923 if (!x)
5924 return -EINVAL;
5925
5926 a = strndup(s, x - s);
5927 if (!a)
5928 return -ENOMEM;
5929
5930 b = strdup(x + strlen(sep));
5931 if (!b) {
5932 free(a);
5933 return -ENOMEM;
5934 }
5935
5936 *l = a;
5937 *r = b;
5938
5939 return 0;
5940}
295edddf 5941
74df0fca 5942int shall_restore_state(void) {
059cb385 5943 _cleanup_free_ char *line = NULL;
295edddf 5944 char *w, *state;
295edddf 5945 size_t l;
74df0fca 5946 int r;
295edddf 5947
74df0fca
LP
5948 r = proc_cmdline(&line);
5949 if (r < 0)
5950 return r;
5951 if (r == 0) /* Container ... */
5952 return 1;
295edddf 5953
059cb385 5954 r = 1;
74df0fca 5955
059cb385
LP
5956 FOREACH_WORD_QUOTED(w, l, line, state) {
5957 const char *e;
5958 char n[l+1];
5959 int k;
5960
5961 memcpy(n, w, l);
5962 n[l] = 0;
5963
5964 e = startswith(n, "systemd.restore_state=");
5965 if (!e)
5966 continue;
5967
5968 k = parse_boolean(e);
5969 if (k >= 0)
5970 r = k;
5971 }
5972
5973 return r;
74df0fca
LP
5974}
5975
5976int proc_cmdline(char **ret) {
5977 int r;
5978
5979 if (detect_container(NULL) > 0) {
39883f62 5980 char *buf = NULL, *p;
02bb6cda
LP
5981 size_t sz = 0;
5982
5983 r = read_full_file("/proc/1/cmdline", &buf, &sz);
5984 if (r < 0)
5985 return r;
5986
5987 for (p = buf; p + 1 < buf + sz; p++)
5988 if (*p == 0)
5989 *p = ' ';
5990
059cb385 5991 *p = 0;
02bb6cda
LP
5992 *ret = buf;
5993 return 1;
295edddf
TG
5994 }
5995
74df0fca
LP
5996 r = read_one_line_file("/proc/cmdline", ret);
5997 if (r < 0)
5998 return r;
295edddf 5999
74df0fca 6000 return 1;
295edddf 6001}
bc9fd78c 6002
059cb385 6003int parse_proc_cmdline(int (*parse_item)(const char *key, const char *value)) {
141a79f4
ZJS
6004 _cleanup_free_ char *line = NULL;
6005 char *w, *state;
6006 size_t l;
6007 int r;
6008
059cb385
LP
6009 assert(parse_item);
6010
141a79f4
ZJS
6011 r = proc_cmdline(&line);
6012 if (r < 0)
6013 log_warning("Failed to read /proc/cmdline, ignoring: %s", strerror(-r));
6014 if (r <= 0)
6015 return 0;
6016
6017 FOREACH_WORD_QUOTED(w, l, line, state) {
059cb385 6018 char word[l+1], *value;
141a79f4 6019
059cb385
LP
6020 memcpy(word, w, l);
6021 word[l] = 0;
141a79f4 6022
059cb385
LP
6023 /* Filter out arguments that are intended only for the
6024 * initrd */
6025 if (!in_initrd() && startswith(word, "rd."))
6026 continue;
6027
6028 value = strchr(word, '=');
6029 if (value)
6030 *(value++) = 0;
6031
6032 r = parse_item(word, value);
6033 if (r < 0)
141a79f4 6034 return r;
141a79f4
ZJS
6035 }
6036
6037 return 0;
6038}
6039
bc9fd78c
LP
6040int container_get_leader(const char *machine, pid_t *pid) {
6041 _cleanup_free_ char *s = NULL, *class = NULL;
6042 const char *p;
6043 pid_t leader;
6044 int r;
6045
6046 assert(machine);
6047 assert(pid);
6048
6049 p = strappenda("/run/systemd/machines/", machine);
6050 r = parse_env_file(p, NEWLINE, "LEADER", &s, "CLASS", &class, NULL);
6051 if (r == -ENOENT)
6052 return -EHOSTDOWN;
6053 if (r < 0)
6054 return r;
6055 if (!s)
6056 return -EIO;
6057
6058 if (!streq_ptr(class, "container"))
6059 return -EIO;
6060
6061 r = parse_pid(s, &leader);
6062 if (r < 0)
6063 return r;
6064 if (leader <= 1)
6065 return -EIO;
6066
6067 *pid = leader;
6068 return 0;
6069}
6070
878cd7e9
LP
6071int namespace_open(pid_t pid, int *pidns_fd, int *mntns_fd, int *netns_fd, int *root_fd) {
6072 _cleanup_close_ int pidnsfd = -1, mntnsfd = -1, netnsfd = -1;
359a06aa 6073 int rfd = -1;
bc9fd78c
LP
6074
6075 assert(pid >= 0);
bc9fd78c 6076
878cd7e9
LP
6077 if (mntns_fd) {
6078 const char *mntns;
a4475f57 6079
878cd7e9
LP
6080 mntns = procfs_file_alloca(pid, "ns/mnt");
6081 mntnsfd = open(mntns, O_RDONLY|O_NOCTTY|O_CLOEXEC);
6082 if (mntnsfd < 0)
6083 return -errno;
6084 }
bc9fd78c 6085
878cd7e9
LP
6086 if (pidns_fd) {
6087 const char *pidns;
6088
6089 pidns = procfs_file_alloca(pid, "ns/pid");
6090 pidnsfd = open(pidns, O_RDONLY|O_NOCTTY|O_CLOEXEC);
6091 if (pidnsfd < 0)
6092 return -errno;
6093 }
6094
6095 if (netns_fd) {
6096 const char *netns;
6097
6098 netns = procfs_file_alloca(pid, "ns/net");
6099 netnsfd = open(netns, O_RDONLY|O_NOCTTY|O_CLOEXEC);
6100 if (netnsfd < 0)
6101 return -errno;
6102 }
6103
6104 if (root_fd) {
6105 const char *root;
6106
6107 root = procfs_file_alloca(pid, "root");
6108 rfd = open(root, O_RDONLY|O_NOCTTY|O_CLOEXEC|O_DIRECTORY);
6109 if (rfd < 0)
6110 return -errno;
6111 }
6112
6113 if (pidns_fd)
6114 *pidns_fd = pidnsfd;
bc9fd78c 6115
878cd7e9
LP
6116 if (mntns_fd)
6117 *mntns_fd = mntnsfd;
6118
6119 if (netns_fd)
6120 *netns_fd = netnsfd;
6121
6122 if (root_fd)
6123 *root_fd = rfd;
6124
6125 pidnsfd = mntnsfd = netnsfd = -1;
bc9fd78c
LP
6126
6127 return 0;
6128}
6129
878cd7e9 6130int namespace_enter(int pidns_fd, int mntns_fd, int netns_fd, int root_fd) {
bc9fd78c 6131
878cd7e9
LP
6132 if (pidns_fd >= 0)
6133 if (setns(pidns_fd, CLONE_NEWPID) < 0)
6134 return -errno;
a4475f57 6135
878cd7e9
LP
6136 if (mntns_fd >= 0)
6137 if (setns(mntns_fd, CLONE_NEWNS) < 0)
6138 return -errno;
bc9fd78c 6139
878cd7e9
LP
6140 if (netns_fd >= 0)
6141 if (setns(netns_fd, CLONE_NEWNET) < 0)
6142 return -errno;
bc9fd78c 6143
878cd7e9
LP
6144 if (root_fd >= 0) {
6145 if (fchdir(root_fd) < 0)
6146 return -errno;
6147
6148 if (chroot(".") < 0)
6149 return -errno;
6150 }
bc9fd78c 6151
5e2b3214
LP
6152 if (setresgid(0, 0, 0) < 0)
6153 return -errno;
6154
878cd7e9
LP
6155 if (setgroups(0, NULL) < 0)
6156 return -errno;
6157
5e2b3214
LP
6158 if (setresuid(0, 0, 0) < 0)
6159 return -errno;
6160
bc9fd78c
LP
6161 return 0;
6162}
bf108e55 6163
9f5650ae
LP
6164bool pid_is_unwaited(pid_t pid) {
6165 /* Checks whether a PID is still valid at all, including a zombie */
6166
bf108e55
LP
6167 if (pid <= 0)
6168 return false;
6169
6170 if (kill(pid, 0) >= 0)
6171 return true;
6172
6173 return errno != ESRCH;
6174}
eff05270 6175
9f5650ae
LP
6176bool pid_is_alive(pid_t pid) {
6177 int r;
6178
6179 /* Checks whether a PID is still valid and not a zombie */
6180
6181 if (pid <= 0)
6182 return false;
6183
6184 r = get_process_state(pid);
6185 if (r == -ENOENT || r == 'Z')
6186 return false;
6187
6188 return true;
6189}
6190
eff05270
LP
6191int getpeercred(int fd, struct ucred *ucred) {
6192 socklen_t n = sizeof(struct ucred);
6193 struct ucred u;
6194 int r;
6195
6196 assert(fd >= 0);
6197 assert(ucred);
6198
6199 r = getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &u, &n);
6200 if (r < 0)
6201 return -errno;
6202
6203 if (n != sizeof(struct ucred))
6204 return -EIO;
6205
6206 /* Check if the data is actually useful and not suppressed due
6207 * to namespacing issues */
6208 if (u.pid <= 0)
6209 return -ENODATA;
6210
6211 *ucred = u;
6212 return 0;
6213}
6214
6215int getpeersec(int fd, char **ret) {
6216 socklen_t n = 64;
6217 char *s;
6218 int r;
6219
6220 assert(fd >= 0);
6221 assert(ret);
6222
6223 s = new0(char, n);
6224 if (!s)
6225 return -ENOMEM;
6226
6227 r = getsockopt(fd, SOL_SOCKET, SO_PEERSEC, s, &n);
6228 if (r < 0) {
6229 free(s);
6230
6231 if (errno != ERANGE)
6232 return -errno;
6233
6234 s = new0(char, n);
6235 if (!s)
6236 return -ENOMEM;
6237
6238 r = getsockopt(fd, SOL_SOCKET, SO_PEERSEC, s, &n);
6239 if (r < 0) {
6240 free(s);
6241 return -errno;
6242 }
6243 }
6244
ae98841e
LP
6245 if (isempty(s)) {
6246 free(s);
6247 return -ENOTSUP;
6248 }
6249
eff05270
LP
6250 *ret = s;
6251 return 0;
6252}
8e33886e 6253
0f010ef2 6254/* This is much like like mkostemp() but is subject to umask(). */
65b3903f 6255int mkostemp_safe(char *pattern, int flags) {
2d5bdf5b 6256 _cleanup_umask_ mode_t u;
0f010ef2 6257 int fd;
65b3903f 6258
d37a91e8 6259 assert(pattern);
65b3903f 6260
2d5bdf5b
LP
6261 u = umask(077);
6262
0f010ef2
ZJS
6263 fd = mkostemp(pattern, flags);
6264 if (fd < 0)
6265 return -errno;
65b3903f 6266
0f010ef2 6267 return fd;
65b3903f
ZJS
6268}
6269
8e33886e 6270int open_tmpfile(const char *path, int flags) {
8e33886e 6271 char *p;
a6afc4ae
LP
6272 int fd;
6273
6274 assert(path);
8e33886e
ZJS
6275
6276#ifdef O_TMPFILE
7736202c
LP
6277 /* Try O_TMPFILE first, if it is supported */
6278 fd = open(path, flags|O_TMPFILE, S_IRUSR|S_IWUSR);
8e33886e
ZJS
6279 if (fd >= 0)
6280 return fd;
6281#endif
7736202c
LP
6282
6283 /* Fall back to unguessable name + unlinking */
8e33886e
ZJS
6284 p = strappenda(path, "/systemd-tmp-XXXXXX");
6285
a6afc4ae 6286 fd = mkostemp_safe(p, flags);
8e33886e 6287 if (fd < 0)
65b3903f 6288 return fd;
8e33886e
ZJS
6289
6290 unlink(p);
6291 return fd;
6292}
fdb9161c
LP
6293
6294int fd_warn_permissions(const char *path, int fd) {
6295 struct stat st;
6296
6297 if (fstat(fd, &st) < 0)
6298 return -errno;
6299
6300 if (st.st_mode & 0111)
6301 log_warning("Configuration file %s is marked executable. Please remove executable permission bits. Proceeding anyway.", path);
6302
6303 if (st.st_mode & 0002)
6304 log_warning("Configuration file %s is marked world-writable. Please remove world writability permission bits. Proceeding anyway.", path);
6305
6306 if (getpid() == 1 && (st.st_mode & 0044) != 0044)
6307 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);
6308
6309 return 0;
6310}
6afc95b7 6311
ac45f971 6312unsigned long personality_from_string(const char *p) {
6afc95b7
LP
6313
6314 /* Parse a personality specifier. We introduce our own
6315 * identifiers that indicate specific ABIs, rather than just
6316 * hints regarding the register size, since we want to keep
6317 * things open for multiple locally supported ABIs for the
6318 * same register size. We try to reuse the ABI identifiers
6319 * used by libseccomp. */
6320
6321#if defined(__x86_64__)
6322
6323 if (streq(p, "x86"))
6324 return PER_LINUX32;
6325
6326 if (streq(p, "x86-64"))
6327 return PER_LINUX;
6328
6329#elif defined(__i386__)
6330
6331 if (streq(p, "x86"))
6332 return PER_LINUX;
6333#endif
6334
6335 /* personality(7) documents that 0xffffffffUL is used for
6336 * querying the current personality, hence let's use that here
6337 * as error indicator. */
6338 return 0xffffffffUL;
6339}
ac45f971
LP
6340
6341const char* personality_to_string(unsigned long p) {
6342
6343#if defined(__x86_64__)
6344
6345 if (p == PER_LINUX32)
6346 return "x86";
6347
6348 if (p == PER_LINUX)
6349 return "x86-64";
6350
6351#elif defined(__i386__)
6352
6353 if (p == PER_LINUX)
6354 return "x86";
6355#endif
6356
6357 return NULL;
6358}
1c231f56
LP
6359
6360uint64_t physical_memory(void) {
6361 long mem;
6362
6363 /* We return this as uint64_t in case we are running as 32bit
6364 * process on a 64bit kernel with huge amounts of memory */
6365
6366 mem = sysconf(_SC_PHYS_PAGES);
6367 assert(mem > 0);
6368
6369 return (uint64_t) mem * (uint64_t) page_size();
6370}
6db615c1
LP
6371
6372char* mount_test_option(const char *haystack, const char *needle) {
6373
6374 struct mntent me = {
6375 .mnt_opts = (char*) haystack
6376 };
6377
6378 assert(needle);
6379
6380 /* Like glibc's hasmntopt(), but works on a string, not a
6381 * struct mntent */
6382
6383 if (!haystack)
6384 return NULL;
6385
6386 return hasmntopt(&me, needle);
6387}
29bfbcd6
LP
6388
6389void hexdump(FILE *f, const void *p, size_t s) {
6390 const uint8_t *b = p;
6391 unsigned n = 0;
6392
6393 assert(s == 0 || b);
6394
6395 while (s > 0) {
6396 size_t i;
6397
6398 fprintf(f, "%04x ", n);
6399
6400 for (i = 0; i < 16; i++) {
6401
6402 if (i >= s)
6403 fputs(" ", f);
6404 else
6405 fprintf(f, "%02x ", b[i]);
6406
6407 if (i == 7)
6408 fputc(' ', f);
6409 }
6410
6411 fputc(' ', f);
6412
6413 for (i = 0; i < 16; i++) {
6414
6415 if (i >= s)
6416 fputc(' ', f);
6417 else
6418 fputc(isprint(b[i]) ? (char) b[i] : '.', f);
6419 }
6420
6421 fputc('\n', f);
6422
6423 if (s < 16)
6424 break;
6425
6426 n += 16;
6427 b += 16;
6428 s -= 16;
6429 }
6430}
c5220a94 6431
966bff26 6432int update_reboot_param_file(const char *param) {
c5220a94
MO
6433 int r = 0;
6434
6435 if (param) {
6436
6437 r = write_string_file(REBOOT_PARAM_FILE, param);
6438 if (r < 0)
6439 log_error("Failed to write reboot param to "
6440 REBOOT_PARAM_FILE": %s", strerror(-r));
6441 } else
6442 unlink(REBOOT_PARAM_FILE);
6443
6444 return r;
6445}
6d313367
LP
6446
6447int umount_recursive(const char *prefix, int flags) {
6448 bool again;
6449 int n = 0, r;
6450
6451 /* Try to umount everything recursively below a
6452 * directory. Also, take care of stacked mounts, and keep
6453 * unmounting them until they are gone. */
6454
6455 do {
6456 _cleanup_fclose_ FILE *proc_self_mountinfo = NULL;
6457
6458 again = false;
6459 r = 0;
6460
6461 proc_self_mountinfo = fopen("/proc/self/mountinfo", "re");
6462 if (!proc_self_mountinfo)
6463 return -errno;
6464
6465 for (;;) {
6466 _cleanup_free_ char *path = NULL, *p = NULL;
6467 int k;
6468
6469 k = fscanf(proc_self_mountinfo,
6470 "%*s " /* (1) mount id */
6471 "%*s " /* (2) parent id */
6472 "%*s " /* (3) major:minor */
6473 "%*s " /* (4) root */
6474 "%ms " /* (5) mount point */
6475 "%*s" /* (6) mount options */
6476 "%*[^-]" /* (7) optional fields */
6477 "- " /* (8) separator */
6478 "%*s " /* (9) file system type */
6479 "%*s" /* (10) mount source */
6480 "%*s" /* (11) mount options 2 */
6481 "%*[^\n]", /* some rubbish at the end */
6482 &path);
6d313367
LP
6483 if (k != 1) {
6484 if (k == EOF)
6485 break;
6486
6487 continue;
6488 }
6489
6490 p = cunescape(path);
6491 if (!p)
6492 return -ENOMEM;
6493
6494 if (!path_startswith(p, prefix))
6495 continue;
6496
6497 if (umount2(p, flags) < 0) {
6498 r = -errno;
6499 continue;
6500 }
6501
6502 again = true;
6503 n++;
6504
6505 break;
6506 }
6507
6508 } while (again);
6509
6510 return r ? r : n;
6511}
d6797c92
LP
6512
6513int bind_remount_recursive(const char *prefix, bool ro) {
6514 _cleanup_set_free_free_ Set *done = NULL;
6515 _cleanup_free_ char *cleaned = NULL;
6516 int r;
6517
6518 /* Recursively remount a directory (and all its submounts)
6519 * read-only or read-write. If the directory is already
6520 * mounted, we reuse the mount and simply mark it
6521 * MS_BIND|MS_RDONLY (or remove the MS_RDONLY for read-write
6522 * operation). If it isn't we first make it one. Afterwards we
6523 * apply MS_BIND|MS_RDONLY (or remove MS_RDONLY) to all
6524 * submounts we can access, too. When mounts are stacked on
6525 * the same mount point we only care for each individual
6526 * "top-level" mount on each point, as we cannot
6527 * influence/access the underlying mounts anyway. We do not
6528 * have any effect on future submounts that might get
6529 * propagated, they migt be writable. This includes future
6530 * submounts that have been triggered via autofs. */
6531
6532 cleaned = strdup(prefix);
6533 if (!cleaned)
6534 return -ENOMEM;
6535
6536 path_kill_slashes(cleaned);
6537
6538 done = set_new(string_hash_func, string_compare_func);
6539 if (!done)
6540 return -ENOMEM;
6541
6542 for (;;) {
6543 _cleanup_fclose_ FILE *proc_self_mountinfo = NULL;
6544 _cleanup_set_free_free_ Set *todo = NULL;
6545 bool top_autofs = false;
6546 char *x;
6547
6548 todo = set_new(string_hash_func, string_compare_func);
6549 if (!todo)
6550 return -ENOMEM;
6551
6552 proc_self_mountinfo = fopen("/proc/self/mountinfo", "re");
6553 if (!proc_self_mountinfo)
6554 return -errno;
6555
6556 for (;;) {
6557 _cleanup_free_ char *path = NULL, *p = NULL, *type = NULL;
6558 int k;
6559
6560 k = fscanf(proc_self_mountinfo,
6561 "%*s " /* (1) mount id */
6562 "%*s " /* (2) parent id */
6563 "%*s " /* (3) major:minor */
6564 "%*s " /* (4) root */
6565 "%ms " /* (5) mount point */
6566 "%*s" /* (6) mount options (superblock) */
6567 "%*[^-]" /* (7) optional fields */
6568 "- " /* (8) separator */
6569 "%ms " /* (9) file system type */
6570 "%*s" /* (10) mount source */
6571 "%*s" /* (11) mount options (bind mount) */
6572 "%*[^\n]", /* some rubbish at the end */
6573 &path,
6574 &type);
6575 if (k != 2) {
6576 if (k == EOF)
6577 break;
6578
6579 continue;
6580 }
6581
6582 p = cunescape(path);
6583 if (!p)
6584 return -ENOMEM;
6585
6586 /* Let's ignore autofs mounts. If they aren't
6587 * triggered yet, we want to avoid triggering
6588 * them, as we don't make any guarantees for
6589 * future submounts anyway. If they are
6590 * already triggered, then we will find
6591 * another entry for this. */
6592 if (streq(type, "autofs")) {
6593 top_autofs = top_autofs || path_equal(cleaned, p);
6594 continue;
6595 }
6596
6597 if (path_startswith(p, cleaned) &&
6598 !set_contains(done, p)) {
6599
6600 r = set_consume(todo, p);
6601 p = NULL;
6602
6603 if (r == -EEXIST)
6604 continue;
6605 if (r < 0)
6606 return r;
6607 }
6608 }
6609
6610 /* If we have no submounts to process anymore and if
6611 * the root is either already done, or an autofs, we
6612 * are done */
6613 if (set_isempty(todo) &&
6614 (top_autofs || set_contains(done, cleaned)))
6615 return 0;
6616
6617 if (!set_contains(done, cleaned) &&
6618 !set_contains(todo, cleaned)) {
6619 /* The prefix directory itself is not yet a
6620 * mount, make it one. */
6621 if (mount(cleaned, cleaned, NULL, MS_BIND|MS_REC, NULL) < 0)
6622 return -errno;
6623
6624 if (mount(NULL, prefix, NULL, MS_BIND|MS_REMOUNT|(ro ? MS_RDONLY : 0), NULL) < 0)
6625 return -errno;
6626
6627 x = strdup(cleaned);
6628 if (!x)
6629 return -ENOMEM;
6630
6631 r = set_consume(done, x);
6632 if (r < 0)
6633 return r;
6634 }
6635
6636 while ((x = set_steal_first(todo))) {
6637
6638 r = set_consume(done, x);
6639 if (r == -EEXIST)
6640 continue;
6641 if (r < 0)
6642 return r;
6643
6644 if (mount(NULL, x, NULL, MS_BIND|MS_REMOUNT|(ro ? MS_RDONLY : 0), NULL) < 0) {
6645
6646 /* Deal with mount points that are
6647 * obstructed by a later mount */
6648
6649 if (errno != ENOENT)
6650 return -errno;
6651 }
6652
6653 }
6654 }
6655}
1b992147
LP
6656
6657int fflush_and_check(FILE *f) {
45c196a7 6658 assert(f);
1b992147
LP
6659
6660 errno = 0;
6661 fflush(f);
6662
6663 if (ferror(f))
6664 return errno ? -errno : -EIO;
6665
6666 return 0;
6667}
2e78fa79
LP
6668
6669char *tempfn_xxxxxx(const char *p) {
6670 const char *fn;
6671 char *t;
6672 size_t k;
6673
6674 assert(p);
6675
6676 t = new(char, strlen(p) + 1 + 6 + 1);
6677 if (!t)
6678 return NULL;
6679
6680 fn = basename(p);
6681 k = fn - p;
6682
6683 strcpy(stpcpy(stpcpy(mempcpy(t, p, k), "."), fn), "XXXXXX");
6684
6685 return t;
6686}
6687
6688char *tempfn_random(const char *p) {
6689 const char *fn;
6690 char *t, *x;
6691 uint64_t u;
6692 size_t k;
6693 unsigned i;
6694
6695 assert(p);
6696
6697 t = new(char, strlen(p) + 1 + 16 + 1);
6698 if (!t)
6699 return NULL;
6700
6701 fn = basename(p);
6702 k = fn - p;
6703
6704 x = stpcpy(stpcpy(mempcpy(t, p, k), "."), fn);
6705
6706 u = random_u64();
6707 for (i = 0; i < 16; i++) {
6708 *(x++) = hexchar(u & 0xF);
6709 u >>= 4;
6710 }
6711
6712 *x = 0;
6713
6714 return t;
6715}