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