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