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