]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/shared/util.c
bus: update bloom filter description a bit
[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) {
968d3d24 3872
b92bea5d
ZJS
3873 struct pollfd pollfd = {
3874 .fd = fd,
3875 .events = event,
3876 };
df50185b 3877
968d3d24
LP
3878 struct timespec ts;
3879 int r;
3880
3881 r = ppoll(&pollfd, 1, t == (usec_t) -1 ? NULL : timespec_store(&ts, t), NULL);
df50185b
LP
3882 if (r < 0)
3883 return -errno;
3884
3885 if (r == 0)
3886 return 0;
3887
3888 return pollfd.revents;
3889}
3890
5a3ab509
LP
3891int fopen_temporary(const char *path, FILE **_f, char **_temp_path) {
3892 FILE *f;
3893 char *t;
3894 const char *fn;
3895 size_t k;
3896 int fd;
3897
3898 assert(path);
3899 assert(_f);
3900 assert(_temp_path);
3901
3902 t = new(char, strlen(path) + 1 + 6 + 1);
3903 if (!t)
3904 return -ENOMEM;
3905
2b6bf07d
ZJS
3906 fn = basename(path);
3907 k = fn - path;
5a3ab509
LP
3908 memcpy(t, path, k);
3909 t[k] = '.';
3910 stpcpy(stpcpy(t+k+1, fn), "XXXXXX");
3911
3912 fd = mkostemp(t, O_WRONLY|O_CLOEXEC);
3913 if (fd < 0) {
3914 free(t);
3915 return -errno;
3916 }
3917
3918 f = fdopen(fd, "we");
3919 if (!f) {
3920 unlink(t);
3921 free(t);
3922 return -errno;
3923 }
3924
3925 *_f = f;
3926 *_temp_path = t;
3927
3928 return 0;
3929}
3930
6ea832a2 3931int terminal_vhangup_fd(int fd) {
5a3ab509
LP
3932 assert(fd >= 0);
3933
6ea832a2
LP
3934 if (ioctl(fd, TIOCVHANGUP) < 0)
3935 return -errno;
3936
3937 return 0;
3938}
3939
3940int terminal_vhangup(const char *name) {
3941 int fd, r;
3942
3943 fd = open_terminal(name, O_RDWR|O_NOCTTY|O_CLOEXEC);
3944 if (fd < 0)
3945 return fd;
3946
3947 r = terminal_vhangup_fd(fd);
3948 close_nointr_nofail(fd);
3949
3950 return r;
3951}
3952
3953int vt_disallocate(const char *name) {
3954 int fd, r;
3955 unsigned u;
6ea832a2
LP
3956
3957 /* Deallocate the VT if possible. If not possible
3958 * (i.e. because it is the active one), at least clear it
3959 * entirely (including the scrollback buffer) */
3960
b83bc4e9
LP
3961 if (!startswith(name, "/dev/"))
3962 return -EINVAL;
3963
3964 if (!tty_is_vc(name)) {
3965 /* So this is not a VT. I guess we cannot deallocate
3966 * it then. But let's at least clear the screen */
3967
3968 fd = open_terminal(name, O_RDWR|O_NOCTTY|O_CLOEXEC);
3969 if (fd < 0)
3970 return fd;
3971
8585357a
LP
3972 loop_write(fd,
3973 "\033[r" /* clear scrolling region */
3974 "\033[H" /* move home */
3975 "\033[2J", /* clear screen */
3976 10, false);
b83bc4e9
LP
3977 close_nointr_nofail(fd);
3978
3979 return 0;
3980 }
6ea832a2
LP
3981
3982 if (!startswith(name, "/dev/tty"))
3983 return -EINVAL;
3984
3985 r = safe_atou(name+8, &u);
3986 if (r < 0)
3987 return r;
3988
3989 if (u <= 0)
b83bc4e9 3990 return -EINVAL;
6ea832a2 3991
b83bc4e9 3992 /* Try to deallocate */
6ea832a2
LP
3993 fd = open_terminal("/dev/tty0", O_RDWR|O_NOCTTY|O_CLOEXEC);
3994 if (fd < 0)
3995 return fd;
3996
3997 r = ioctl(fd, VT_DISALLOCATE, u);
b83bc4e9 3998 close_nointr_nofail(fd);
6ea832a2 3999
b83bc4e9
LP
4000 if (r >= 0)
4001 return 0;
6ea832a2 4002
b83bc4e9 4003 if (errno != EBUSY)
6ea832a2 4004 return -errno;
6ea832a2 4005
b83bc4e9
LP
4006 /* Couldn't deallocate, so let's clear it fully with
4007 * scrollback */
4008 fd = open_terminal(name, O_RDWR|O_NOCTTY|O_CLOEXEC);
6ea832a2 4009 if (fd < 0)
b83bc4e9 4010 return fd;
6ea832a2 4011
8585357a
LP
4012 loop_write(fd,
4013 "\033[r" /* clear scrolling region */
4014 "\033[H" /* move home */
4015 "\033[3J", /* clear screen including scrollback, requires Linux 2.6.40 */
4016 10, false);
b83bc4e9 4017 close_nointr_nofail(fd);
6ea832a2 4018
b83bc4e9 4019 return 0;
6ea832a2
LP
4020}
4021
51045322
LP
4022int copy_file(const char *from, const char *to, int flags) {
4023 _cleanup_close_ int fdf = -1;
4024 int r, fdt;
34ca941c
LP
4025
4026 assert(from);
4027 assert(to);
4028
4029 fdf = open(from, O_RDONLY|O_CLOEXEC|O_NOCTTY);
4030 if (fdf < 0)
4031 return -errno;
4032
51045322
LP
4033 fdt = open(to, flags|O_WRONLY|O_CREAT|O_CLOEXEC|O_NOCTTY, 0644);
4034 if (fdt < 0)
34ca941c 4035 return -errno;
34ca941c
LP
4036
4037 for (;;) {
4038 char buf[PIPE_BUF];
4039 ssize_t n, k;
4040
4041 n = read(fdf, buf, sizeof(buf));
4042 if (n < 0) {
4043 r = -errno;
4044
34ca941c
LP
4045 close_nointr(fdt);
4046 unlink(to);
4047
4048 return r;
4049 }
4050
4051 if (n == 0)
4052 break;
4053
4054 errno = 0;
4055 k = loop_write(fdt, buf, n, false);
4056 if (n != k) {
4057 r = k < 0 ? k : (errno ? -errno : -EIO);
4058
34ca941c 4059 close_nointr(fdt);
34ca941c 4060 unlink(to);
51045322 4061
34ca941c
LP
4062 return r;
4063 }
4064 }
4065
34ca941c
LP
4066 r = close_nointr(fdt);
4067
4068 if (r < 0) {
4069 unlink(to);
4070 return r;
4071 }
4072
4073 return 0;
4074}
4075
424a19f8
LP
4076int symlink_atomic(const char *from, const char *to) {
4077 char *x;
4078 _cleanup_free_ char *t;
34ca941c
LP
4079 const char *fn;
4080 size_t k;
9bf3b535 4081 uint64_t u;
34ca941c
LP
4082 unsigned i;
4083 int r;
4084
4085 assert(from);
4086 assert(to);
4087
4088 t = new(char, strlen(to) + 1 + 16 + 1);
4089 if (!t)
4090 return -ENOMEM;
4091
2b6bf07d 4092 fn = basename(to);
34ca941c
LP
4093 k = fn-to;
4094 memcpy(t, to, k);
4095 t[k] = '.';
4096 x = stpcpy(t+k+1, fn);
4097
9bf3b535 4098 u = random_u64();
34ca941c 4099 for (i = 0; i < 16; i++) {
9bf3b535
LP
4100 *(x++) = hexchar(u & 0xF);
4101 u >>= 4;
34ca941c
LP
4102 }
4103
4104 *x = 0;
4105
424a19f8
LP
4106 if (symlink(from, t) < 0)
4107 return -errno;
34ca941c
LP
4108
4109 if (rename(t, to) < 0) {
4110 r = -errno;
4111 unlink(t);
34ca941c
LP
4112 return r;
4113 }
4114
424a19f8 4115 return 0;
34ca941c
LP
4116}
4117
4d6d6518
LP
4118bool display_is_local(const char *display) {
4119 assert(display);
4120
4121 return
4122 display[0] == ':' &&
4123 display[1] >= '0' &&
4124 display[1] <= '9';
4125}
4126
4127int socket_from_display(const char *display, char **path) {
4128 size_t k;
4129 char *f, *c;
4130
4131 assert(display);
4132 assert(path);
4133
4134 if (!display_is_local(display))
4135 return -EINVAL;
4136
4137 k = strspn(display+1, "0123456789");
4138
4139 f = new(char, sizeof("/tmp/.X11-unix/X") + k);
4140 if (!f)
4141 return -ENOMEM;
4142
4143 c = stpcpy(f, "/tmp/.X11-unix/X");
4144 memcpy(c, display+1, k);
4145 c[k] = 0;
4146
4147 *path = f;
4148
4149 return 0;
4150}
4151
d05c5031
LP
4152int get_user_creds(
4153 const char **username,
4154 uid_t *uid, gid_t *gid,
4155 const char **home,
4156 const char **shell) {
4157
1cccf435 4158 struct passwd *p;
ddd88763 4159 uid_t u;
1cccf435
MV
4160
4161 assert(username);
4162 assert(*username);
1cccf435
MV
4163
4164 /* We enforce some special rules for uid=0: in order to avoid
4165 * NSS lookups for root we hardcode its data. */
4166
4167 if (streq(*username, "root") || streq(*username, "0")) {
4168 *username = "root";
4b67834e
LP
4169
4170 if (uid)
4171 *uid = 0;
4172
4173 if (gid)
4174 *gid = 0;
4175
4176 if (home)
4177 *home = "/root";
d05c5031
LP
4178
4179 if (shell)
4180 *shell = "/bin/sh";
4181
1cccf435
MV
4182 return 0;
4183 }
4184
ddd88763 4185 if (parse_uid(*username, &u) >= 0) {
1cccf435 4186 errno = 0;
ddd88763 4187 p = getpwuid(u);
1cccf435
MV
4188
4189 /* If there are multiple users with the same id, make
4190 * sure to leave $USER to the configured value instead
4191 * of the first occurrence in the database. However if
4192 * the uid was configured by a numeric uid, then let's
4193 * pick the real username from /etc/passwd. */
4194 if (p)
4195 *username = p->pw_name;
4196 } else {
4197 errno = 0;
4198 p = getpwnam(*username);
4199 }
4200
4201 if (!p)
8333c77e 4202 return errno > 0 ? -errno : -ESRCH;
1cccf435 4203
4b67834e
LP
4204 if (uid)
4205 *uid = p->pw_uid;
4206
4207 if (gid)
4208 *gid = p->pw_gid;
4209
4210 if (home)
4211 *home = p->pw_dir;
4212
d05c5031
LP
4213 if (shell)
4214 *shell = p->pw_shell;
4215
4b67834e
LP
4216 return 0;
4217}
4218
59164be4
LP
4219char* uid_to_name(uid_t uid) {
4220 struct passwd *p;
4221 char *r;
4222
4223 if (uid == 0)
4224 return strdup("root");
4225
4226 p = getpwuid(uid);
4227 if (p)
4228 return strdup(p->pw_name);
4229
4230 if (asprintf(&r, "%lu", (unsigned long) uid) < 0)
4231 return NULL;
4232
4233 return r;
4234}
4235
4468addc
LP
4236char* gid_to_name(gid_t gid) {
4237 struct group *p;
4238 char *r;
4239
4240 if (gid == 0)
4241 return strdup("root");
4242
4243 p = getgrgid(gid);
4244 if (p)
4245 return strdup(p->gr_name);
4246
4247 if (asprintf(&r, "%lu", (unsigned long) gid) < 0)
4248 return NULL;
4249
4250 return r;
4251}
4252
4b67834e
LP
4253int get_group_creds(const char **groupname, gid_t *gid) {
4254 struct group *g;
4255 gid_t id;
4256
4257 assert(groupname);
4258
4259 /* We enforce some special rules for gid=0: in order to avoid
4260 * NSS lookups for root we hardcode its data. */
4261
4262 if (streq(*groupname, "root") || streq(*groupname, "0")) {
4263 *groupname = "root";
4264
4265 if (gid)
4266 *gid = 0;
4267
4268 return 0;
4269 }
4270
4271 if (parse_gid(*groupname, &id) >= 0) {
4272 errno = 0;
4273 g = getgrgid(id);
4274
4275 if (g)
4276 *groupname = g->gr_name;
4277 } else {
4278 errno = 0;
4279 g = getgrnam(*groupname);
4280 }
4281
4282 if (!g)
8333c77e 4283 return errno > 0 ? -errno : -ESRCH;
4b67834e
LP
4284
4285 if (gid)
4286 *gid = g->gr_gid;
4287
1cccf435
MV
4288 return 0;
4289}
4290
4468addc
LP
4291int in_gid(gid_t gid) {
4292 gid_t *gids;
43673799
LP
4293 int ngroups_max, r, i;
4294
43673799
LP
4295 if (getgid() == gid)
4296 return 1;
4297
4298 if (getegid() == gid)
4299 return 1;
4300
4301 ngroups_max = sysconf(_SC_NGROUPS_MAX);
4302 assert(ngroups_max > 0);
4303
4304 gids = alloca(sizeof(gid_t) * ngroups_max);
4305
4306 r = getgroups(ngroups_max, gids);
4307 if (r < 0)
4308 return -errno;
4309
4310 for (i = 0; i < r; i++)
4311 if (gids[i] == gid)
4312 return 1;
4313
4314 return 0;
4315}
4316
4468addc
LP
4317int in_group(const char *name) {
4318 int r;
4319 gid_t gid;
4320
4321 r = get_group_creds(&name, &gid);
4322 if (r < 0)
4323 return r;
4324
4325 return in_gid(gid);
4326}
4327
8092a428 4328int glob_exists(const char *path) {
7fd1b19b 4329 _cleanup_globfree_ glob_t g = {};
8d98da3f 4330 int k;
8092a428
LP
4331
4332 assert(path);
4333
8092a428
LP
4334 errno = 0;
4335 k = glob(path, GLOB_NOSORT|GLOB_BRACE, NULL, &g);
4336
4337 if (k == GLOB_NOMATCH)
8d98da3f 4338 return 0;
8092a428 4339 else if (k == GLOB_NOSPACE)
8d98da3f 4340 return -ENOMEM;
8092a428 4341 else if (k == 0)
8d98da3f 4342 return !strv_isempty(g.gl_pathv);
8092a428 4343 else
8d98da3f
ZJS
4344 return errno ? -errno : -EIO;
4345}
8092a428 4346
8d98da3f
ZJS
4347int glob_extend(char ***strv, const char *path) {
4348 _cleanup_globfree_ glob_t g = {};
4349 int k;
4350 char **p;
4351
4352 errno = 0;
a8ccacf5 4353 k = glob(path, GLOB_NOSORT|GLOB_BRACE, NULL, &g);
8d98da3f
ZJS
4354
4355 if (k == GLOB_NOMATCH)
4356 return -ENOENT;
4357 else if (k == GLOB_NOSPACE)
4358 return -ENOMEM;
4359 else if (k != 0 || strv_isempty(g.gl_pathv))
4360 return errno ? -errno : -EIO;
4361
4362 STRV_FOREACH(p, g.gl_pathv) {
4363 k = strv_extend(strv, *p);
4364 if (k < 0)
4365 break;
4366 }
4367
4368 return k;
8092a428
LP
4369}
4370
83096483
LP
4371int dirent_ensure_type(DIR *d, struct dirent *de) {
4372 struct stat st;
4373
4374 assert(d);
4375 assert(de);
4376
4377 if (de->d_type != DT_UNKNOWN)
4378 return 0;
4379
4380 if (fstatat(dirfd(d), de->d_name, &st, AT_SYMLINK_NOFOLLOW) < 0)
4381 return -errno;
4382
4383 de->d_type =
4384 S_ISREG(st.st_mode) ? DT_REG :
4385 S_ISDIR(st.st_mode) ? DT_DIR :
4386 S_ISLNK(st.st_mode) ? DT_LNK :
4387 S_ISFIFO(st.st_mode) ? DT_FIFO :
4388 S_ISSOCK(st.st_mode) ? DT_SOCK :
4389 S_ISCHR(st.st_mode) ? DT_CHR :
4390 S_ISBLK(st.st_mode) ? DT_BLK :
4391 DT_UNKNOWN;
4392
4393 return 0;
4394}
4395
4396int in_search_path(const char *path, char **search) {
893fa014
ZJS
4397 char **i;
4398 _cleanup_free_ char *parent = NULL;
83096483
LP
4399 int r;
4400
9eb977db 4401 r = path_get_parent(path, &parent);
83096483
LP
4402 if (r < 0)
4403 return r;
4404
893fa014
ZJS
4405 STRV_FOREACH(i, search)
4406 if (path_equal(parent, *i))
4407 return 1;
83096483 4408
893fa014 4409 return 0;
83096483
LP
4410}
4411
034a2a52 4412int get_files_in_directory(const char *path, char ***list) {
893fa014
ZJS
4413 _cleanup_closedir_ DIR *d = NULL;
4414 size_t bufsize = 0, n = 0;
4415 _cleanup_strv_free_ char **l = NULL;
034a2a52
LP
4416
4417 assert(path);
d60ef526
LP
4418
4419 /* Returns all files in a directory in *list, and the number
4420 * of files as return value. If list is NULL returns only the
893fa014 4421 * number. */
034a2a52
LP
4422
4423 d = opendir(path);
8ea913b2
LP
4424 if (!d)
4425 return -errno;
4426
034a2a52 4427 for (;;) {
7d5e9c0f 4428 struct dirent *de;
034a2a52 4429
3fd11280
FW
4430 errno = 0;
4431 de = readdir(d);
4432 if (!de && errno != 0)
4433 return -errno;
034a2a52
LP
4434 if (!de)
4435 break;
4436
4437 dirent_ensure_type(d, de);
4438
4439 if (!dirent_is_file(de))
4440 continue;
4441
d60ef526 4442 if (list) {
893fa014
ZJS
4443 /* one extra slot is needed for the terminating NULL */
4444 if (!GREEDY_REALLOC(l, bufsize, n + 2))
4445 return -ENOMEM;
034a2a52 4446
893fa014
ZJS
4447 l[n] = strdup(de->d_name);
4448 if (!l[n])
4449 return -ENOMEM;
034a2a52 4450
893fa014 4451 l[++n] = NULL;
d60ef526 4452 } else
893fa014 4453 n++;
034a2a52
LP
4454 }
4455
893fa014
ZJS
4456 if (list) {
4457 *list = l;
4458 l = NULL; /* avoid freeing */
4459 }
034a2a52 4460
893fa014 4461 return n;
034a2a52
LP
4462}
4463
b7def684 4464char *strjoin(const char *x, ...) {
911a4828
LP
4465 va_list ap;
4466 size_t l;
4467 char *r, *p;
4468
4469 va_start(ap, x);
4470
4471 if (x) {
4472 l = strlen(x);
4473
4474 for (;;) {
4475 const char *t;
040f18ea 4476 size_t n;
911a4828
LP
4477
4478 t = va_arg(ap, const char *);
4479 if (!t)
4480 break;
4481
040f18ea 4482 n = strlen(t);
e98055de
LN
4483 if (n > ((size_t) -1) - l) {
4484 va_end(ap);
040f18ea 4485 return NULL;
e98055de 4486 }
040f18ea
LP
4487
4488 l += n;
911a4828
LP
4489 }
4490 } else
4491 l = 0;
4492
4493 va_end(ap);
4494
4495 r = new(char, l+1);
4496 if (!r)
4497 return NULL;
4498
4499 if (x) {
4500 p = stpcpy(r, x);
4501
4502 va_start(ap, x);
4503
4504 for (;;) {
4505 const char *t;
4506
4507 t = va_arg(ap, const char *);
4508 if (!t)
4509 break;
4510
4511 p = stpcpy(p, t);
4512 }
8ea913b2
LP
4513
4514 va_end(ap);
911a4828
LP
4515 } else
4516 r[0] = 0;
4517
4518 return r;
4519}
4520
b636465b 4521bool is_main_thread(void) {
ec202eae 4522 static thread_local int cached = 0;
b636465b
LP
4523
4524 if (_unlikely_(cached == 0))
4525 cached = getpid() == gettid() ? 1 : -1;
4526
4527 return cached > 0;
4528}
4529
94959f0f
LP
4530int block_get_whole_disk(dev_t d, dev_t *ret) {
4531 char *p, *s;
4532 int r;
4533 unsigned n, m;
4534
4535 assert(ret);
4536
4537 /* If it has a queue this is good enough for us */
4538 if (asprintf(&p, "/sys/dev/block/%u:%u/queue", major(d), minor(d)) < 0)
4539 return -ENOMEM;
4540
4541 r = access(p, F_OK);
4542 free(p);
4543
4544 if (r >= 0) {
4545 *ret = d;
4546 return 0;
4547 }
4548
4549 /* If it is a partition find the originating device */
4550 if (asprintf(&p, "/sys/dev/block/%u:%u/partition", major(d), minor(d)) < 0)
4551 return -ENOMEM;
4552
4553 r = access(p, F_OK);
4554 free(p);
4555
4556 if (r < 0)
4557 return -ENOENT;
4558
4559 /* Get parent dev_t */
4560 if (asprintf(&p, "/sys/dev/block/%u:%u/../dev", major(d), minor(d)) < 0)
4561 return -ENOMEM;
4562
4563 r = read_one_line_file(p, &s);
4564 free(p);
4565
4566 if (r < 0)
4567 return r;
4568
4569 r = sscanf(s, "%u:%u", &m, &n);
4570 free(s);
4571
4572 if (r != 2)
4573 return -EINVAL;
4574
4575 /* Only return this if it is really good enough for us. */
4576 if (asprintf(&p, "/sys/dev/block/%u:%u/queue", m, n) < 0)
4577 return -ENOMEM;
4578
4579 r = access(p, F_OK);
4580 free(p);
4581
4582 if (r >= 0) {
4583 *ret = makedev(m, n);
4584 return 0;
4585 }
4586
4587 return -ENOENT;
4588}
4589
8d53b453 4590int file_is_priv_sticky(const char *p) {
ad293f5a
LP
4591 struct stat st;
4592
4593 assert(p);
4594
4595 if (lstat(p, &st) < 0)
4596 return -errno;
4597
4598 return
8d53b453 4599 (st.st_uid == 0 || st.st_uid == getuid()) &&
ad293f5a
LP
4600 (st.st_mode & S_ISVTX);
4601}
94959f0f 4602
f41607a6
LP
4603static const char *const ioprio_class_table[] = {
4604 [IOPRIO_CLASS_NONE] = "none",
4605 [IOPRIO_CLASS_RT] = "realtime",
4606 [IOPRIO_CLASS_BE] = "best-effort",
4607 [IOPRIO_CLASS_IDLE] = "idle"
4608};
4609
f8b69d1d 4610DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(ioprio_class, int, INT_MAX);
f41607a6
LP
4611
4612static const char *const sigchld_code_table[] = {
4613 [CLD_EXITED] = "exited",
4614 [CLD_KILLED] = "killed",
4615 [CLD_DUMPED] = "dumped",
4616 [CLD_TRAPPED] = "trapped",
4617 [CLD_STOPPED] = "stopped",
4618 [CLD_CONTINUED] = "continued",
4619};
4620
4621DEFINE_STRING_TABLE_LOOKUP(sigchld_code, int);
4622
4623static const char *const log_facility_unshifted_table[LOG_NFACILITIES] = {
4624 [LOG_FAC(LOG_KERN)] = "kern",
4625 [LOG_FAC(LOG_USER)] = "user",
4626 [LOG_FAC(LOG_MAIL)] = "mail",
4627 [LOG_FAC(LOG_DAEMON)] = "daemon",
4628 [LOG_FAC(LOG_AUTH)] = "auth",
4629 [LOG_FAC(LOG_SYSLOG)] = "syslog",
4630 [LOG_FAC(LOG_LPR)] = "lpr",
4631 [LOG_FAC(LOG_NEWS)] = "news",
4632 [LOG_FAC(LOG_UUCP)] = "uucp",
4633 [LOG_FAC(LOG_CRON)] = "cron",
4634 [LOG_FAC(LOG_AUTHPRIV)] = "authpriv",
4635 [LOG_FAC(LOG_FTP)] = "ftp",
4636 [LOG_FAC(LOG_LOCAL0)] = "local0",
4637 [LOG_FAC(LOG_LOCAL1)] = "local1",
4638 [LOG_FAC(LOG_LOCAL2)] = "local2",
4639 [LOG_FAC(LOG_LOCAL3)] = "local3",
4640 [LOG_FAC(LOG_LOCAL4)] = "local4",
4641 [LOG_FAC(LOG_LOCAL5)] = "local5",
4642 [LOG_FAC(LOG_LOCAL6)] = "local6",
4643 [LOG_FAC(LOG_LOCAL7)] = "local7"
4644};
4645
f8b69d1d 4646DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(log_facility_unshifted, int, LOG_FAC(~0));
f41607a6
LP
4647
4648static const char *const log_level_table[] = {
4649 [LOG_EMERG] = "emerg",
4650 [LOG_ALERT] = "alert",
4651 [LOG_CRIT] = "crit",
4652 [LOG_ERR] = "err",
4653 [LOG_WARNING] = "warning",
4654 [LOG_NOTICE] = "notice",
4655 [LOG_INFO] = "info",
4656 [LOG_DEBUG] = "debug"
4657};
4658
f8b69d1d 4659DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(log_level, int, LOG_DEBUG);
f41607a6
LP
4660
4661static const char* const sched_policy_table[] = {
4662 [SCHED_OTHER] = "other",
4663 [SCHED_BATCH] = "batch",
4664 [SCHED_IDLE] = "idle",
4665 [SCHED_FIFO] = "fifo",
4666 [SCHED_RR] = "rr"
4667};
4668
f8b69d1d 4669DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(sched_policy, int, INT_MAX);
f41607a6
LP
4670
4671static const char* const rlimit_table[] = {
4672 [RLIMIT_CPU] = "LimitCPU",
4673 [RLIMIT_FSIZE] = "LimitFSIZE",
4674 [RLIMIT_DATA] = "LimitDATA",
4675 [RLIMIT_STACK] = "LimitSTACK",
4676 [RLIMIT_CORE] = "LimitCORE",
4677 [RLIMIT_RSS] = "LimitRSS",
4678 [RLIMIT_NOFILE] = "LimitNOFILE",
4679 [RLIMIT_AS] = "LimitAS",
4680 [RLIMIT_NPROC] = "LimitNPROC",
4681 [RLIMIT_MEMLOCK] = "LimitMEMLOCK",
4682 [RLIMIT_LOCKS] = "LimitLOCKS",
4683 [RLIMIT_SIGPENDING] = "LimitSIGPENDING",
4684 [RLIMIT_MSGQUEUE] = "LimitMSGQUEUE",
4685 [RLIMIT_NICE] = "LimitNICE",
4686 [RLIMIT_RTPRIO] = "LimitRTPRIO",
4687 [RLIMIT_RTTIME] = "LimitRTTIME"
4688};
4689
4690DEFINE_STRING_TABLE_LOOKUP(rlimit, int);
4691
4692static const char* const ip_tos_table[] = {
4693 [IPTOS_LOWDELAY] = "low-delay",
4694 [IPTOS_THROUGHPUT] = "throughput",
4695 [IPTOS_RELIABILITY] = "reliability",
4696 [IPTOS_LOWCOST] = "low-cost",
4697};
4698
f8b69d1d 4699DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(ip_tos, int, 0xff);
f41607a6 4700
4e240ab0 4701static const char *const __signal_table[] = {
f41607a6
LP
4702 [SIGHUP] = "HUP",
4703 [SIGINT] = "INT",
4704 [SIGQUIT] = "QUIT",
4705 [SIGILL] = "ILL",
4706 [SIGTRAP] = "TRAP",
4707 [SIGABRT] = "ABRT",
4708 [SIGBUS] = "BUS",
4709 [SIGFPE] = "FPE",
4710 [SIGKILL] = "KILL",
4711 [SIGUSR1] = "USR1",
4712 [SIGSEGV] = "SEGV",
4713 [SIGUSR2] = "USR2",
4714 [SIGPIPE] = "PIPE",
4715 [SIGALRM] = "ALRM",
4716 [SIGTERM] = "TERM",
4717#ifdef SIGSTKFLT
4718 [SIGSTKFLT] = "STKFLT", /* Linux on SPARC doesn't know SIGSTKFLT */
4719#endif
4720 [SIGCHLD] = "CHLD",
4721 [SIGCONT] = "CONT",
4722 [SIGSTOP] = "STOP",
4723 [SIGTSTP] = "TSTP",
4724 [SIGTTIN] = "TTIN",
4725 [SIGTTOU] = "TTOU",
4726 [SIGURG] = "URG",
4727 [SIGXCPU] = "XCPU",
4728 [SIGXFSZ] = "XFSZ",
4729 [SIGVTALRM] = "VTALRM",
4730 [SIGPROF] = "PROF",
4731 [SIGWINCH] = "WINCH",
4732 [SIGIO] = "IO",
4733 [SIGPWR] = "PWR",
4734 [SIGSYS] = "SYS"
4735};
4736
4e240ab0
MS
4737DEFINE_PRIVATE_STRING_TABLE_LOOKUP(__signal, int);
4738
4739const char *signal_to_string(int signo) {
ec202eae 4740 static thread_local char buf[sizeof("RTMIN+")-1 + DECIMAL_STR_MAX(int) + 1];
4e240ab0
MS
4741 const char *name;
4742
4743 name = __signal_to_string(signo);
4744 if (name)
4745 return name;
4746
4747 if (signo >= SIGRTMIN && signo <= SIGRTMAX)
fa70beaa 4748 snprintf(buf, sizeof(buf), "RTMIN+%d", signo - SIGRTMIN);
4e240ab0 4749 else
fa70beaa
LP
4750 snprintf(buf, sizeof(buf), "%d", signo);
4751
4e240ab0
MS
4752 return buf;
4753}
4754
4755int signal_from_string(const char *s) {
4756 int signo;
4757 int offset = 0;
4758 unsigned u;
4759
040f18ea 4760 signo = __signal_from_string(s);
4e240ab0
MS
4761 if (signo > 0)
4762 return signo;
4763
4764 if (startswith(s, "RTMIN+")) {
4765 s += 6;
4766 offset = SIGRTMIN;
4767 }
4768 if (safe_atou(s, &u) >= 0) {
4769 signo = (int) u + offset;
4770 if (signo > 0 && signo < _NSIG)
4771 return signo;
4772 }
4773 return -1;
4774}
65457142
FC
4775
4776bool kexec_loaded(void) {
4777 bool loaded = false;
4778 char *s;
4779
4780 if (read_one_line_file("/sys/kernel/kexec_loaded", &s) >= 0) {
4781 if (s[0] == '1')
4782 loaded = true;
4783 free(s);
4784 }
4785 return loaded;
4786}
fb9de93d
LP
4787
4788int strdup_or_null(const char *a, char **b) {
4789 char *c;
4790
4791 assert(b);
4792
4793 if (!a) {
4794 *b = NULL;
4795 return 0;
4796 }
4797
4798 c = strdup(a);
4799 if (!c)
4800 return -ENOMEM;
4801
4802 *b = c;
4803 return 0;
4804}
64685e0c 4805
87d2c1ff
LP
4806int prot_from_flags(int flags) {
4807
4808 switch (flags & O_ACCMODE) {
4809
4810 case O_RDONLY:
4811 return PROT_READ;
4812
4813 case O_WRONLY:
4814 return PROT_WRITE;
4815
4816 case O_RDWR:
4817 return PROT_READ|PROT_WRITE;
4818
4819 default:
4820 return -EINVAL;
4821 }
7c99e0c1 4822}
689b9a22 4823
babfc091 4824char *format_bytes(char *buf, size_t l, off_t t) {
c0f99c21 4825 unsigned i;
babfc091
LP
4826
4827 static const struct {
4828 const char *suffix;
4829 off_t factor;
4830 } table[] = {
32895bb3
LP
4831 { "E", 1024ULL*1024ULL*1024ULL*1024ULL*1024ULL*1024ULL },
4832 { "P", 1024ULL*1024ULL*1024ULL*1024ULL*1024ULL },
babfc091
LP
4833 { "T", 1024ULL*1024ULL*1024ULL*1024ULL },
4834 { "G", 1024ULL*1024ULL*1024ULL },
4835 { "M", 1024ULL*1024ULL },
4836 { "K", 1024ULL },
4837 };
4838
4839 for (i = 0; i < ELEMENTSOF(table); i++) {
4840
4841 if (t >= table[i].factor) {
4842 snprintf(buf, l,
4843 "%llu.%llu%s",
4844 (unsigned long long) (t / table[i].factor),
4845 (unsigned long long) (((t*10ULL) / table[i].factor) % 10ULL),
4846 table[i].suffix);
4847
4848 goto finish;
4849 }
4850 }
4851
4852 snprintf(buf, l, "%lluB", (unsigned long long) t);
4853
4854finish:
4855 buf[l-1] = 0;
4856 return buf;
4857
4858}
55d7bfc1
LP
4859
4860void* memdup(const void *p, size_t l) {
4861 void *r;
4862
4863 assert(p);
4864
4865 r = malloc(l);
4866 if (!r)
4867 return NULL;
4868
4869 memcpy(r, p, l);
4870 return r;
4871}
bb99a35a
LP
4872
4873int fd_inc_sndbuf(int fd, size_t n) {
4874 int r, value;
4875 socklen_t l = sizeof(value);
4876
4877 r = getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &value, &l);
92d75ca4 4878 if (r >= 0 && l == sizeof(value) && (size_t) value >= n*2)
bb99a35a
LP
4879 return 0;
4880
92d75ca4
LP
4881 /* If we have the privileges we will ignore the kernel limit. */
4882
bb99a35a 4883 value = (int) n;
92d75ca4
LP
4884 if (setsockopt(fd, SOL_SOCKET, SO_SNDBUFFORCE, &value, sizeof(value)) < 0)
4885 if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &value, sizeof(value)) < 0)
4886 return -errno;
bb99a35a
LP
4887
4888 return 1;
4889}
4890
4891int fd_inc_rcvbuf(int fd, size_t n) {
4892 int r, value;
4893 socklen_t l = sizeof(value);
4894
4895 r = getsockopt(fd, SOL_SOCKET, SO_RCVBUF, &value, &l);
92d75ca4 4896 if (r >= 0 && l == sizeof(value) && (size_t) value >= n*2)
bb99a35a
LP
4897 return 0;
4898
92d75ca4 4899 /* If we have the privileges we will ignore the kernel limit. */
bb99a35a 4900
92d75ca4
LP
4901 value = (int) n;
4902 if (setsockopt(fd, SOL_SOCKET, SO_RCVBUFFORCE, &value, sizeof(value)) < 0)
4903 if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &value, sizeof(value)) < 0)
4904 return -errno;
bb99a35a
LP
4905 return 1;
4906}
6bb92a16 4907
9bdc770c 4908int fork_agent(pid_t *pid, const int except[], unsigned n_except, const char *path, ...) {
6bb92a16
LP
4909 pid_t parent_pid, agent_pid;
4910 int fd;
4911 bool stdout_is_tty, stderr_is_tty;
4912 unsigned n, i;
4913 va_list ap;
4914 char **l;
4915
4916 assert(pid);
4917 assert(path);
4918
4919 parent_pid = getpid();
4920
4921 /* Spawns a temporary TTY agent, making sure it goes away when
4922 * we go away */
4923
4924 agent_pid = fork();
4925 if (agent_pid < 0)
4926 return -errno;
4927
4928 if (agent_pid != 0) {
4929 *pid = agent_pid;
4930 return 0;
4931 }
4932
4933 /* In the child:
4934 *
4935 * Make sure the agent goes away when the parent dies */
4936 if (prctl(PR_SET_PDEATHSIG, SIGTERM) < 0)
4937 _exit(EXIT_FAILURE);
4938
4939 /* Check whether our parent died before we were able
4940 * to set the death signal */
4941 if (getppid() != parent_pid)
4942 _exit(EXIT_SUCCESS);
4943
4944 /* Don't leak fds to the agent */
9bdc770c 4945 close_all_fds(except, n_except);
6bb92a16
LP
4946
4947 stdout_is_tty = isatty(STDOUT_FILENO);
4948 stderr_is_tty = isatty(STDERR_FILENO);
4949
4950 if (!stdout_is_tty || !stderr_is_tty) {
4951 /* Detach from stdout/stderr. and reopen
4952 * /dev/tty for them. This is important to
4953 * ensure that when systemctl is started via
4954 * popen() or a similar call that expects to
4955 * read EOF we actually do generate EOF and
4956 * not delay this indefinitely by because we
4957 * keep an unused copy of stdin around. */
4958 fd = open("/dev/tty", O_WRONLY);
4959 if (fd < 0) {
4960 log_error("Failed to open /dev/tty: %m");
4961 _exit(EXIT_FAILURE);
4962 }
4963
4964 if (!stdout_is_tty)
4965 dup2(fd, STDOUT_FILENO);
4966
4967 if (!stderr_is_tty)
4968 dup2(fd, STDERR_FILENO);
4969
4970 if (fd > 2)
4971 close(fd);
4972 }
4973
4974 /* Count arguments */
4975 va_start(ap, path);
4976 for (n = 0; va_arg(ap, char*); n++)
4977 ;
4978 va_end(ap);
4979
4980 /* Allocate strv */
4981 l = alloca(sizeof(char *) * (n + 1));
4982
4983 /* Fill in arguments */
4984 va_start(ap, path);
4985 for (i = 0; i <= n; i++)
4986 l[i] = va_arg(ap, char*);
4987 va_end(ap);
4988
4989 execv(path, l);
4990 _exit(EXIT_FAILURE);
4991}
68faf98c
LP
4992
4993int setrlimit_closest(int resource, const struct rlimit *rlim) {
4994 struct rlimit highest, fixed;
4995
4996 assert(rlim);
4997
4998 if (setrlimit(resource, rlim) >= 0)
4999 return 0;
5000
5001 if (errno != EPERM)
5002 return -errno;
5003
5004 /* So we failed to set the desired setrlimit, then let's try
5005 * to get as close as we can */
5006 assert_se(getrlimit(resource, &highest) == 0);
5007
5008 fixed.rlim_cur = MIN(rlim->rlim_cur, highest.rlim_max);
5009 fixed.rlim_max = MIN(rlim->rlim_max, highest.rlim_max);
5010
5011 if (setrlimit(resource, &fixed) < 0)
5012 return -errno;
5013
5014 return 0;
5015}
3d9a4122 5016
ab94af92 5017int getenv_for_pid(pid_t pid, const char *field, char **_value) {
49aa47c7
LP
5018 _cleanup_fclose_ FILE *f = NULL;
5019 char *value = NULL;
ab94af92 5020 int r;
ab94af92
LP
5021 bool done = false;
5022 size_t l;
49aa47c7 5023 const char *path;
ab94af92 5024
49aa47c7 5025 assert(pid >= 0);
ab94af92
LP
5026 assert(field);
5027 assert(_value);
5028
b68fa010 5029 path = procfs_file_alloca(pid, "environ");
ab94af92
LP
5030
5031 f = fopen(path, "re");
5032 if (!f)
5033 return -errno;
5034
5035 l = strlen(field);
5036 r = 0;
5037
5038 do {
5039 char line[LINE_MAX];
5040 unsigned i;
5041
5042 for (i = 0; i < sizeof(line)-1; i++) {
5043 int c;
5044
5045 c = getc(f);
5046 if (_unlikely_(c == EOF)) {
5047 done = true;
5048 break;
5049 } else if (c == 0)
5050 break;
5051
5052 line[i] = c;
5053 }
5054 line[i] = 0;
5055
5056 if (memcmp(line, field, l) == 0 && line[l] == '=') {
5057 value = strdup(line + l + 1);
49aa47c7
LP
5058 if (!value)
5059 return -ENOMEM;
ab94af92
LP
5060
5061 r = 1;
5062 break;
5063 }
5064
5065 } while (!done);
5066
49aa47c7 5067 *_value = value;
ab94af92
LP
5068 return r;
5069}
d889a206 5070
49dbfa7b
LP
5071bool is_valid_documentation_url(const char *url) {
5072 assert(url);
5073
5074 if (startswith(url, "http://") && url[7])
5075 return true;
5076
5077 if (startswith(url, "https://") && url[8])
5078 return true;
5079
5080 if (startswith(url, "file:") && url[5])
5081 return true;
5082
5083 if (startswith(url, "info:") && url[5])
5084 return true;
5085
5086 if (startswith(url, "man:") && url[4])
5087 return true;
5088
5089 return false;
5090}
9be346c9
HH
5091
5092bool in_initrd(void) {
73020ab2 5093 static int saved = -1;
825c6fe5 5094 struct statfs s;
8f33b5b8 5095
825c6fe5
LP
5096 if (saved >= 0)
5097 return saved;
5098
5099 /* We make two checks here:
5100 *
5101 * 1. the flag file /etc/initrd-release must exist
5102 * 2. the root file system must be a memory file system
5103 *
5104 * The second check is extra paranoia, since misdetecting an
5105 * initrd can have bad bad consequences due the initrd
5106 * emptying when transititioning to the main systemd.
5107 */
5108
5109 saved = access("/etc/initrd-release", F_OK) >= 0 &&
5110 statfs("/", &s) >= 0 &&
943aad8c 5111 is_temporary_fs(&s);
9be346c9 5112
8f33b5b8 5113 return saved;
9be346c9 5114}
069cfc85
LP
5115
5116void warn_melody(void) {
e67f47e5 5117 _cleanup_close_ int fd = -1;
069cfc85
LP
5118
5119 fd = open("/dev/console", O_WRONLY|O_CLOEXEC|O_NOCTTY);
5120 if (fd < 0)
5121 return;
5122
040f18ea 5123 /* Yeah, this is synchronous. Kinda sucks. But well... */
069cfc85
LP
5124
5125 ioctl(fd, KIOCSOUND, (int)(1193180/440));
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, (int)(1193180/220));
5132 usleep(125*USEC_PER_MSEC);
5133
5134 ioctl(fd, KIOCSOUND, 0);
069cfc85 5135}
cd3bd60a
LP
5136
5137int make_console_stdio(void) {
5138 int fd, r;
5139
5140 /* Make /dev/console the controlling terminal and stdin/stdout/stderr */
5141
5142 fd = acquire_terminal("/dev/console", false, true, true, (usec_t) -1);
5143 if (fd < 0) {
5144 log_error("Failed to acquire terminal: %s", strerror(-fd));
5145 return fd;
5146 }
5147
5148 r = make_stdio(fd);
5149 if (r < 0) {
5150 log_error("Failed to duplicate terminal fd: %s", strerror(-r));
5151 return r;
5152 }
5153
5154 return 0;
5155}
7c5f152a
LP
5156
5157int get_home_dir(char **_h) {
2cfbd749 5158 struct passwd *p;
7c5f152a 5159 const char *e;
2cfbd749 5160 char *h;
7c5f152a 5161 uid_t u;
7c5f152a
LP
5162
5163 assert(_h);
5164
5165 /* Take the user specified one */
5166 e = getenv("HOME");
5167 if (e) {
5168 h = strdup(e);
5169 if (!h)
5170 return -ENOMEM;
5171
5172 *_h = h;
5173 return 0;
5174 }
5175
5176 /* Hardcode home directory for root to avoid NSS */
5177 u = getuid();
5178 if (u == 0) {
5179 h = strdup("/root");
5180 if (!h)
5181 return -ENOMEM;
5182
5183 *_h = h;
5184 return 0;
5185 }
5186
5187 /* Check the database... */
5188 errno = 0;
5189 p = getpwuid(u);
5190 if (!p)
bcb161b0 5191 return errno > 0 ? -errno : -ESRCH;
7c5f152a
LP
5192
5193 if (!path_is_absolute(p->pw_dir))
5194 return -EINVAL;
5195
5196 h = strdup(p->pw_dir);
5197 if (!h)
5198 return -ENOMEM;
5199
5200 *_h = h;
5201 return 0;
5202}
5203
2cfbd749
LP
5204int get_shell(char **_s) {
5205 struct passwd *p;
5206 const char *e;
5207 char *s;
5208 uid_t u;
5209
5210 assert(_s);
5211
5212 /* Take the user specified one */
5213 e = getenv("SHELL");
5214 if (e) {
5215 s = strdup(e);
5216 if (!s)
5217 return -ENOMEM;
5218
5219 *_s = s;
5220 return 0;
5221 }
5222
5223 /* Hardcode home directory for root to avoid NSS */
5224 u = getuid();
5225 if (u == 0) {
5226 s = strdup("/bin/sh");
5227 if (!s)
5228 return -ENOMEM;
5229
5230 *_s = s;
5231 return 0;
5232 }
5233
5234 /* Check the database... */
5235 errno = 0;
5236 p = getpwuid(u);
5237 if (!p)
5238 return errno > 0 ? -errno : -ESRCH;
5239
5240 if (!path_is_absolute(p->pw_shell))
5241 return -EINVAL;
5242
5243 s = strdup(p->pw_shell);
5244 if (!s)
5245 return -ENOMEM;
5246
5247 *_s = s;
5248 return 0;
5249}
5250
0b507b17
LP
5251bool filename_is_safe(const char *p) {
5252
5253 if (isempty(p))
5254 return false;
5255
5256 if (strchr(p, '/'))
5257 return false;
5258
5259 if (streq(p, "."))
5260 return false;
5261
5262 if (streq(p, ".."))
5263 return false;
5264
5265 if (strlen(p) > FILENAME_MAX)
5266 return false;
5267
5268 return true;
5269}
5270
5271bool string_is_safe(const char *p) {
5272 const char *t;
5273
5274 assert(p);
5275
5276 for (t = p; *t; t++) {
01539d6e 5277 if (*t > 0 && *t < ' ')
0b507b17
LP
5278 return false;
5279
011afa76 5280 if (strchr("\\\"\'", *t))
0b507b17
LP
5281 return false;
5282 }
5283
5284 return true;
5285}
cfbc22ab 5286
ac4c8d6d
ZJS
5287/**
5288 * Check if a string contains control characters.
5289 * Spaces and tabs are not considered control characters.
5290 */
4d1a6904
LP
5291bool string_has_cc(const char *p) {
5292 const char *t;
5293
5294 assert(p);
5295
5296 for (t = p; *t; t++)
da2620a5 5297 if (*t > 0 && *t < ' ' && *t != '\t')
4d1a6904
LP
5298 return true;
5299
5300 return false;
5301}
5302
e884315e
LP
5303bool path_is_safe(const char *p) {
5304
5305 if (isempty(p))
5306 return false;
5307
5308 if (streq(p, "..") || startswith(p, "../") || endswith(p, "/..") || strstr(p, "/../"))
5309 return false;
5310
5311 if (strlen(p) > PATH_MAX)
5312 return false;
5313
5314 /* The following two checks are not really dangerous, but hey, they still are confusing */
5315 if (streq(p, ".") || startswith(p, "./") || endswith(p, "/.") || strstr(p, "/./"))
5316 return false;
5317
5318 if (strstr(p, "//"))
5319 return false;
5320
5321 return true;
5322}
5323
a9e12476
KS
5324/* hey glibc, APIs with callbacks without a user pointer are so useless */
5325void *xbsearch_r(const void *key, const void *base, size_t nmemb, size_t size,
1c574591 5326 int (*compar) (const void *, const void *, void *), void *arg) {
a9e12476
KS
5327 size_t l, u, idx;
5328 const void *p;
5329 int comparison;
5330
5331 l = 0;
5332 u = nmemb;
5333 while (l < u) {
5334 idx = (l + u) / 2;
5335 p = (void *)(((const char *) base) + (idx * size));
5336 comparison = compar(key, p, arg);
5337 if (comparison < 0)
5338 u = idx;
5339 else if (comparison > 0)
5340 l = idx + 1;
5341 else
5342 return (void *)p;
5343 }
5344 return NULL;
5345}
09017585
MS
5346
5347bool is_locale_utf8(void) {
5348 const char *set;
5349 static int cached_answer = -1;
5350
5351 if (cached_answer >= 0)
5352 goto out;
5353
5354 if (!setlocale(LC_ALL, "")) {
5355 cached_answer = true;
5356 goto out;
5357 }
5358
5359 set = nl_langinfo(CODESET);
5360 if (!set) {
5361 cached_answer = true;
5362 goto out;
5363 }
5364
f168c273 5365 if (streq(set, "UTF-8")) {
fee79e01
HH
5366 cached_answer = true;
5367 goto out;
5368 }
5369
6cf2f1d9
HH
5370 /* For LC_CTYPE=="C" return true, because CTYPE is effectly
5371 * unset and everything can do to UTF-8 nowadays. */
fee79e01
HH
5372 set = setlocale(LC_CTYPE, NULL);
5373 if (!set) {
5374 cached_answer = true;
5375 goto out;
5376 }
5377
6cf2f1d9
HH
5378 /* Check result, but ignore the result if C was set
5379 * explicitly. */
5380 cached_answer =
5381 streq(set, "C") &&
5382 !getenv("LC_ALL") &&
5383 !getenv("LC_CTYPE") &&
5384 !getenv("LANG");
fee79e01 5385
09017585 5386out:
6cf2f1d9 5387 return (bool) cached_answer;
09017585 5388}
c339d977
MS
5389
5390const char *draw_special_char(DrawSpecialChar ch) {
5391 static const char *draw_table[2][_DRAW_SPECIAL_CHAR_MAX] = {
5392 /* UTF-8 */ {
45a5ff0d
MS
5393 [DRAW_TREE_VERT] = "\342\224\202 ", /* │ */
5394 [DRAW_TREE_BRANCH] = "\342\224\234\342\224\200", /* ├─ */
5395 [DRAW_TREE_RIGHT] = "\342\224\224\342\224\200", /* └─ */
55c0b89c 5396 [DRAW_TREE_SPACE] = " ", /* */
45a5ff0d 5397 [DRAW_TRIANGULAR_BULLET] = "\342\200\243 ", /* ‣ */
3deadb91 5398 [DRAW_BLACK_CIRCLE] = "\342\227\217 ", /* ● */
c339d977
MS
5399 },
5400 /* ASCII fallback */ {
45a5ff0d
MS
5401 [DRAW_TREE_VERT] = "| ",
5402 [DRAW_TREE_BRANCH] = "|-",
5403 [DRAW_TREE_RIGHT] = "`-",
55c0b89c 5404 [DRAW_TREE_SPACE] = " ",
45a5ff0d 5405 [DRAW_TRIANGULAR_BULLET] = "> ",
3deadb91 5406 [DRAW_BLACK_CIRCLE] = "* ",
c339d977
MS
5407 }
5408 };
5409
5410 return draw_table[!is_locale_utf8()][ch];
5411}
409bc9c3
LP
5412
5413char *strreplace(const char *text, const char *old_string, const char *new_string) {
5414 const char *f;
5415 char *t, *r;
5416 size_t l, old_len, new_len;
5417
5418 assert(text);
5419 assert(old_string);
5420 assert(new_string);
5421
5422 old_len = strlen(old_string);
5423 new_len = strlen(new_string);
5424
5425 l = strlen(text);
5426 r = new(char, l+1);
5427 if (!r)
5428 return NULL;
5429
5430 f = text;
5431 t = r;
5432 while (*f) {
5433 char *a;
5434 size_t d, nl;
5435
5436 if (!startswith(f, old_string)) {
5437 *(t++) = *(f++);
5438 continue;
5439 }
5440
5441 d = t - r;
5442 nl = l - old_len + new_len;
5443 a = realloc(r, nl + 1);
5444 if (!a)
5445 goto oom;
5446
5447 l = nl;
5448 r = a;
5449 t = r + d;
5450
5451 t = stpcpy(t, new_string);
5452 f += old_len;
5453 }
5454
5455 *t = 0;
5456 return r;
5457
5458oom:
5459 free(r);
5460 return NULL;
5461}
e8bc0ea2
LP
5462
5463char *strip_tab_ansi(char **ibuf, size_t *_isz) {
660ddc72 5464 const char *i, *begin = NULL;
e8bc0ea2
LP
5465 enum {
5466 STATE_OTHER,
5467 STATE_ESCAPE,
5468 STATE_BRACKET
5469 } state = STATE_OTHER;
5470 char *obuf = NULL;
5471 size_t osz = 0, isz;
5472 FILE *f;
5473
5474 assert(ibuf);
5475 assert(*ibuf);
5476
5477 /* Strips ANSI color and replaces TABs by 8 spaces */
5478
5479 isz = _isz ? *_isz : strlen(*ibuf);
5480
5481 f = open_memstream(&obuf, &osz);
5482 if (!f)
5483 return NULL;
5484
5485 for (i = *ibuf; i < *ibuf + isz + 1; i++) {
5486
5487 switch (state) {
5488
5489 case STATE_OTHER:
5490 if (i >= *ibuf + isz) /* EOT */
5491 break;
5492 else if (*i == '\x1B')
5493 state = STATE_ESCAPE;
5494 else if (*i == '\t')
5495 fputs(" ", f);
5496 else
5497 fputc(*i, f);
5498 break;
5499
5500 case STATE_ESCAPE:
5501 if (i >= *ibuf + isz) { /* EOT */
5502 fputc('\x1B', f);
5503 break;
5504 } else if (*i == '[') {
5505 state = STATE_BRACKET;
5506 begin = i + 1;
5507 } else {
5508 fputc('\x1B', f);
5509 fputc(*i, f);
5510 state = STATE_OTHER;
5511 }
5512
5513 break;
5514
5515 case STATE_BRACKET:
5516
5517 if (i >= *ibuf + isz || /* EOT */
5518 (!(*i >= '0' && *i <= '9') && *i != ';' && *i != 'm')) {
5519 fputc('\x1B', f);
5520 fputc('[', f);
5521 state = STATE_OTHER;
5522 i = begin-1;
5523 } else if (*i == 'm')
5524 state = STATE_OTHER;
5525 break;
5526 }
5527 }
5528
5529 if (ferror(f)) {
5530 fclose(f);
5531 free(obuf);
5532 return NULL;
5533 }
5534
5535 fclose(f);
5536
5537 free(*ibuf);
5538 *ibuf = obuf;
5539
5540 if (_isz)
5541 *_isz = osz;
5542
5543 return obuf;
5544}
240dbaa4
LP
5545
5546int on_ac_power(void) {
5547 bool found_offline = false, found_online = false;
5548 _cleanup_closedir_ DIR *d = NULL;
5549
5550 d = opendir("/sys/class/power_supply");
5551 if (!d)
5552 return -errno;
5553
5554 for (;;) {
5555 struct dirent *de;
240dbaa4
LP
5556 _cleanup_close_ int fd = -1, device = -1;
5557 char contents[6];
5558 ssize_t n;
240dbaa4 5559
3fd11280
FW
5560 errno = 0;
5561 de = readdir(d);
5562 if (!de && errno != 0)
5563 return -errno;
240dbaa4
LP
5564
5565 if (!de)
5566 break;
5567
5568 if (ignore_file(de->d_name))
5569 continue;
5570
5571 device = openat(dirfd(d), de->d_name, O_DIRECTORY|O_RDONLY|O_CLOEXEC|O_NOCTTY);
5572 if (device < 0) {
5573 if (errno == ENOENT || errno == ENOTDIR)
5574 continue;
5575
5576 return -errno;
5577 }
5578
5579 fd = openat(device, "type", O_RDONLY|O_CLOEXEC|O_NOCTTY);
5580 if (fd < 0) {
5581 if (errno == ENOENT)
5582 continue;
5583
5584 return -errno;
5585 }
5586
5587 n = read(fd, contents, sizeof(contents));
5588 if (n < 0)
5589 return -errno;
5590
5591 if (n != 6 || memcmp(contents, "Mains\n", 6))
5592 continue;
5593
5594 close_nointr_nofail(fd);
5595 fd = openat(device, "online", O_RDONLY|O_CLOEXEC|O_NOCTTY);
5596 if (fd < 0) {
5597 if (errno == ENOENT)
5598 continue;
5599
5600 return -errno;
5601 }
5602
5603 n = read(fd, contents, sizeof(contents));
5604 if (n < 0)
5605 return -errno;
5606
5607 if (n != 2 || contents[1] != '\n')
5608 return -EIO;
5609
5610 if (contents[0] == '1') {
5611 found_online = true;
5612 break;
5613 } else if (contents[0] == '0')
5614 found_offline = true;
5615 else
5616 return -EIO;
5617 }
5618
5619 return found_online || !found_offline;
5620}
fabe5c0e
LP
5621
5622static int search_and_fopen_internal(const char *path, const char *mode, char **search, FILE **_f) {
5623 char **i;
5624
5625 assert(path);
5626 assert(mode);
5627 assert(_f);
5628
5629 if (!path_strv_canonicalize_uniq(search))
5630 return -ENOMEM;
5631
5632 STRV_FOREACH(i, search) {
5633 _cleanup_free_ char *p = NULL;
5634 FILE *f;
5635
5636 p = strjoin(*i, "/", path, NULL);
5637 if (!p)
5638 return -ENOMEM;
5639
5640 f = fopen(p, mode);
5641 if (f) {
5642 *_f = f;
5643 return 0;
5644 }
5645
5646 if (errno != ENOENT)
5647 return -errno;
5648 }
5649
5650 return -ENOENT;
5651}
5652
5653int search_and_fopen(const char *path, const char *mode, const char **search, FILE **_f) {
5654 _cleanup_strv_free_ char **copy = NULL;
5655
5656 assert(path);
5657 assert(mode);
5658 assert(_f);
5659
5660 if (path_is_absolute(path)) {
5661 FILE *f;
5662
5663 f = fopen(path, mode);
5664 if (f) {
5665 *_f = f;
5666 return 0;
5667 }
5668
5669 return -errno;
5670 }
5671
5672 copy = strv_copy((char**) search);
5673 if (!copy)
5674 return -ENOMEM;
5675
5676 return search_and_fopen_internal(path, mode, copy, _f);
5677}
5678
5679int search_and_fopen_nulstr(const char *path, const char *mode, const char *search, FILE **_f) {
5680 _cleanup_strv_free_ char **s = NULL;
5681
5682 if (path_is_absolute(path)) {
5683 FILE *f;
5684
5685 f = fopen(path, mode);
5686 if (f) {
5687 *_f = f;
5688 return 0;
5689 }
5690
5691 return -errno;
5692 }
5693
5694 s = strv_split_nulstr(search);
5695 if (!s)
5696 return -ENOMEM;
5697
5698 return search_and_fopen_internal(path, mode, s, _f);
5699}
c17ec25e 5700
66e35261
LP
5701char *strextend(char **x, ...) {
5702 va_list ap;
5703 size_t f, l;
5704 char *r, *p;
5705
5706 assert(x);
5707
5708 l = f = *x ? strlen(*x) : 0;
5709
5710 va_start(ap, x);
5711 for (;;) {
5712 const char *t;
5713 size_t n;
5714
5715 t = va_arg(ap, const char *);
5716 if (!t)
5717 break;
5718
5719 n = strlen(t);
5720 if (n > ((size_t) -1) - l) {
5721 va_end(ap);
5722 return NULL;
5723 }
5724
5725 l += n;
5726 }
5727 va_end(ap);
5728
5729 r = realloc(*x, l+1);
5730 if (!r)
5731 return NULL;
5732
5733 p = r + f;
5734
5735 va_start(ap, x);
5736 for (;;) {
5737 const char *t;
5738
5739 t = va_arg(ap, const char *);
5740 if (!t)
5741 break;
5742
5743 p = stpcpy(p, t);
5744 }
5745 va_end(ap);
5746
5747 *p = 0;
5748 *x = r;
5749
5750 return r + l;
5751}
9a17484d
LP
5752
5753char *strrep(const char *s, unsigned n) {
5754 size_t l;
5755 char *r, *p;
5756 unsigned i;
5757
5758 assert(s);
5759
5760 l = strlen(s);
5761 p = r = malloc(l * n + 1);
5762 if (!r)
5763 return NULL;
5764
5765 for (i = 0; i < n; i++)
5766 p = stpcpy(p, s);
5767
5768 *p = 0;
5769 return r;
5770}
392d5b37
LP
5771
5772void* greedy_realloc(void **p, size_t *allocated, size_t need) {
5773 size_t a;
5774 void *q;
5775
98088803 5776 assert(p);
e93c33d4
SL
5777 assert(allocated);
5778
392d5b37
LP
5779 if (*allocated >= need)
5780 return *p;
5781
9607d947 5782 a = MAX(64u, need * 2);
98088803
LP
5783
5784 /* check for overflows */
5785 if (a < need)
5786 return NULL;
5787
392d5b37
LP
5788 q = realloc(*p, a);
5789 if (!q)
5790 return NULL;
5791
5792 *p = q;
5793 *allocated = a;
5794 return q;
5795}
aa96c6cb 5796
4545a231 5797void* greedy_realloc0(void **p, size_t *allocated, size_t need) {
98088803 5798 size_t prev;
4545a231
DH
5799 uint8_t *q;
5800
98088803
LP
5801 assert(p);
5802 assert(allocated);
5803
5804 prev = *allocated;
5805
4545a231
DH
5806 q = greedy_realloc(p, allocated, need);
5807 if (!q)
5808 return NULL;
5809
5810 if (*allocated > prev)
5811 memset(&q[prev], 0, *allocated - prev);
5812
5813 return q;
5814}
5815
aa96c6cb
LP
5816bool id128_is_valid(const char *s) {
5817 size_t i, l;
5818
5819 l = strlen(s);
5820 if (l == 32) {
5821
5822 /* Simple formatted 128bit hex string */
5823
5824 for (i = 0; i < l; i++) {
5825 char c = s[i];
5826
5827 if (!(c >= '0' && c <= '9') &&
5828 !(c >= 'a' && c <= 'z') &&
5829 !(c >= 'A' && c <= 'Z'))
5830 return false;
5831 }
5832
5833 } else if (l == 36) {
5834
5835 /* Formatted UUID */
5836
5837 for (i = 0; i < l; i++) {
5838 char c = s[i];
5839
5840 if ((i == 8 || i == 13 || i == 18 || i == 23)) {
5841 if (c != '-')
5842 return false;
5843 } else {
5844 if (!(c >= '0' && c <= '9') &&
5845 !(c >= 'a' && c <= 'z') &&
5846 !(c >= 'A' && c <= 'Z'))
5847 return false;
5848 }
5849 }
5850
5851 } else
5852 return false;
5853
5854 return true;
5855}
7085053a
DW
5856
5857void parse_user_at_host(char *arg, char **user, char **host) {
5858 assert(arg);
5859 assert(user);
5860 assert(host);
5861
5862 *host = strchr(arg, '@');
5863 if (*host == NULL)
5864 *host = arg;
5865 else {
5866 *host[0]++ = '\0';
5867 *user = arg;
5868 }
5869}
d4ac85c6
LP
5870
5871int split_pair(const char *s, const char *sep, char **l, char **r) {
5872 char *x, *a, *b;
5873
5874 assert(s);
5875 assert(sep);
5876 assert(l);
5877 assert(r);
5878
5879 if (isempty(sep))
5880 return -EINVAL;
5881
5882 x = strstr(s, sep);
5883 if (!x)
5884 return -EINVAL;
5885
5886 a = strndup(s, x - s);
5887 if (!a)
5888 return -ENOMEM;
5889
5890 b = strdup(x + strlen(sep));
5891 if (!b) {
5892 free(a);
5893 return -ENOMEM;
5894 }
5895
5896 *l = a;
5897 *r = b;
5898
5899 return 0;
5900}
295edddf 5901
74df0fca 5902int shall_restore_state(void) {
295edddf
TG
5903 _cleanup_free_ char *line;
5904 char *w, *state;
295edddf 5905 size_t l;
74df0fca 5906 int r;
295edddf 5907
74df0fca
LP
5908 r = proc_cmdline(&line);
5909 if (r < 0)
5910 return r;
5911 if (r == 0) /* Container ... */
5912 return 1;
295edddf 5913
74df0fca 5914 FOREACH_WORD_QUOTED(w, l, line, state)
85ca9433 5915 if (l == 23 && strneq(w, "systemd.restore_state=0", 23))
74df0fca
LP
5916 return 0;
5917
5918 return 1;
5919}
5920
5921int proc_cmdline(char **ret) {
5922 int r;
5923
5924 if (detect_container(NULL) > 0) {
02bb6cda
LP
5925 char *buf, *p;
5926 size_t sz = 0;
5927
5928 r = read_full_file("/proc/1/cmdline", &buf, &sz);
5929 if (r < 0)
5930 return r;
5931
5932 for (p = buf; p + 1 < buf + sz; p++)
5933 if (*p == 0)
5934 *p = ' ';
5935
5936 *p = 0;
5937 *ret = buf;
5938 return 1;
295edddf
TG
5939 }
5940
74df0fca
LP
5941 r = read_one_line_file("/proc/cmdline", ret);
5942 if (r < 0)
5943 return r;
295edddf 5944
74df0fca 5945 return 1;
295edddf 5946}
bc9fd78c
LP
5947
5948int container_get_leader(const char *machine, pid_t *pid) {
5949 _cleanup_free_ char *s = NULL, *class = NULL;
5950 const char *p;
5951 pid_t leader;
5952 int r;
5953
5954 assert(machine);
5955 assert(pid);
5956
5957 p = strappenda("/run/systemd/machines/", machine);
5958 r = parse_env_file(p, NEWLINE, "LEADER", &s, "CLASS", &class, NULL);
5959 if (r == -ENOENT)
5960 return -EHOSTDOWN;
5961 if (r < 0)
5962 return r;
5963 if (!s)
5964 return -EIO;
5965
5966 if (!streq_ptr(class, "container"))
5967 return -EIO;
5968
5969 r = parse_pid(s, &leader);
5970 if (r < 0)
5971 return r;
5972 if (leader <= 1)
5973 return -EIO;
5974
5975 *pid = leader;
5976 return 0;
5977}
5978
a4475f57
LP
5979int namespace_open(pid_t pid, int *pidns_fd, int *mntns_fd, int *root_fd) {
5980 _cleanup_close_ int pidnsfd = -1, mntnsfd = -1;
5981 const char *pidns, *mntns, *root;
bc9fd78c
LP
5982 int rfd;
5983
5984 assert(pid >= 0);
a4475f57
LP
5985 assert(pidns_fd);
5986 assert(mntns_fd);
bc9fd78c
LP
5987 assert(root_fd);
5988
a4475f57
LP
5989 mntns = procfs_file_alloca(pid, "ns/mnt");
5990 mntnsfd = open(mntns, O_RDONLY|O_NOCTTY|O_CLOEXEC);
5991 if (mntnsfd < 0)
5992 return -errno;
5993
5994 pidns = procfs_file_alloca(pid, "ns/pid");
5995 pidnsfd = open(pidns, O_RDONLY|O_NOCTTY|O_CLOEXEC);
5996 if (pidnsfd < 0)
bc9fd78c
LP
5997 return -errno;
5998
5999 root = procfs_file_alloca(pid, "root");
6000 rfd = open(root, O_RDONLY|O_NOCTTY|O_CLOEXEC|O_DIRECTORY);
6001 if (rfd < 0)
6002 return -errno;
6003
a4475f57
LP
6004 *pidns_fd = pidnsfd;
6005 *mntns_fd = mntnsfd;
bc9fd78c 6006 *root_fd = rfd;
a4475f57
LP
6007 pidnsfd = -1;
6008 mntnsfd = -1;
bc9fd78c
LP
6009
6010 return 0;
6011}
6012
a4475f57
LP
6013int namespace_enter(int pidns_fd, int mntns_fd, int root_fd) {
6014 assert(pidns_fd >= 0);
6015 assert(mntns_fd >= 0);
bc9fd78c
LP
6016 assert(root_fd >= 0);
6017
a4475f57
LP
6018 if (setns(pidns_fd, CLONE_NEWPID) < 0)
6019 return -errno;
6020
6021 if (setns(mntns_fd, CLONE_NEWNS) < 0)
bc9fd78c
LP
6022 return -errno;
6023
6024 if (fchdir(root_fd) < 0)
6025 return -errno;
6026
6027 if (chroot(".") < 0)
6028 return -errno;
6029
5e2b3214
LP
6030 if (setresgid(0, 0, 0) < 0)
6031 return -errno;
6032
6033 if (setresuid(0, 0, 0) < 0)
6034 return -errno;
6035
bc9fd78c
LP
6036 return 0;
6037}
bf108e55
LP
6038
6039bool pid_valid(pid_t pid) {
6040 if (pid <= 0)
6041 return false;
6042
6043 if (kill(pid, 0) >= 0)
6044 return true;
6045
6046 return errno != ESRCH;
6047}
eff05270
LP
6048
6049int getpeercred(int fd, struct ucred *ucred) {
6050 socklen_t n = sizeof(struct ucred);
6051 struct ucred u;
6052 int r;
6053
6054 assert(fd >= 0);
6055 assert(ucred);
6056
6057 r = getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &u, &n);
6058 if (r < 0)
6059 return -errno;
6060
6061 if (n != sizeof(struct ucred))
6062 return -EIO;
6063
6064 /* Check if the data is actually useful and not suppressed due
6065 * to namespacing issues */
6066 if (u.pid <= 0)
6067 return -ENODATA;
6068
6069 *ucred = u;
6070 return 0;
6071}
6072
6073int getpeersec(int fd, char **ret) {
6074 socklen_t n = 64;
6075 char *s;
6076 int r;
6077
6078 assert(fd >= 0);
6079 assert(ret);
6080
6081 s = new0(char, n);
6082 if (!s)
6083 return -ENOMEM;
6084
6085 r = getsockopt(fd, SOL_SOCKET, SO_PEERSEC, s, &n);
6086 if (r < 0) {
6087 free(s);
6088
6089 if (errno != ERANGE)
6090 return -errno;
6091
6092 s = new0(char, n);
6093 if (!s)
6094 return -ENOMEM;
6095
6096 r = getsockopt(fd, SOL_SOCKET, SO_PEERSEC, s, &n);
6097 if (r < 0) {
6098 free(s);
6099 return -errno;
6100 }
6101 }
6102
ae98841e
LP
6103 if (isempty(s)) {
6104 free(s);
6105 return -ENOTSUP;
6106 }
6107
eff05270
LP
6108 *ret = s;
6109 return 0;
6110}