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