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