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