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