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