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