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