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