]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/shared/util.c
docs: add new gudev functions to documentation
[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) {
833fce28
LP
2529 char fn[sizeof("/dev/char/")-1 + 2*DECIMAL_STR_MAX(unsigned) + 1 + 1], *b = NULL;
2530 _cleanup_free_ char *s = NULL;
2531 const char *p;
fc116c6a 2532 dev_t devnr;
833fce28 2533 int k;
fc116c6a
LP
2534
2535 assert(r);
2536
4d6d6518
LP
2537 k = get_ctty_devnr(pid, &devnr);
2538 if (k < 0)
fc116c6a
LP
2539 return k;
2540
2541 snprintf(fn, sizeof(fn), "/dev/char/%u:%u", major(devnr), minor(devnr));
fc116c6a 2542
23406ce5
LP
2543 k = readlink_malloc(fn, &s);
2544 if (k < 0) {
fc116c6a
LP
2545
2546 if (k != -ENOENT)
2547 return k;
2548
46824d0e
LP
2549 /* This is an ugly hack */
2550 if (major(devnr) == 136) {
833fce28
LP
2551 asprintf(&b, "pts/%lu", (unsigned long) minor(devnr));
2552 goto finish;
46824d0e
LP
2553 }
2554
fc116c6a
LP
2555 /* Probably something like the ptys which have no
2556 * symlink in /dev/char. Let's return something
2557 * vaguely useful. */
2558
23406ce5 2559 b = strdup(fn + 5);
833fce28 2560 goto finish;
fc116c6a
LP
2561 }
2562
2563 if (startswith(s, "/dev/"))
2564 p = s + 5;
2565 else if (startswith(s, "../"))
2566 p = s + 3;
2567 else
2568 p = s;
2569
2570 b = strdup(p);
fc116c6a 2571
833fce28 2572finish:
fc116c6a
LP
2573 if (!b)
2574 return -ENOMEM;
2575
2576 *r = b;
46824d0e
LP
2577 if (_devnr)
2578 *_devnr = devnr;
2579
fc116c6a
LP
2580 return 0;
2581}
2582
f56d5db9 2583int rm_rf_children_dangerous(int fd, bool only_dirs, bool honour_sticky, struct stat *root_dev) {
8c6db833
LP
2584 DIR *d;
2585 int ret = 0;
2586
2587 assert(fd >= 0);
2588
2589 /* This returns the first error we run into, but nevertheless
7925c22a 2590 * tries to go on. This closes the passed fd. */
8c6db833 2591
d4d046e3
LP
2592 d = fdopendir(fd);
2593 if (!d) {
8c6db833 2594 close_nointr_nofail(fd);
4c633005
LP
2595
2596 return errno == ENOENT ? 0 : -errno;
8c6db833
LP
2597 }
2598
2599 for (;;) {
7d5e9c0f 2600 struct dirent *de;
7925c22a
LP
2601 bool is_dir, keep_around;
2602 struct stat st;
8c6db833
LP
2603 int r;
2604
3fd11280
FW
2605 errno = 0;
2606 de = readdir(d);
2607 if (!de && errno != 0) {
2608 if (ret == 0)
2609 ret = -errno;
8c6db833
LP
2610 break;
2611 }
2612
2613 if (!de)
2614 break;
2615
2616 if (streq(de->d_name, ".") || streq(de->d_name, ".."))
2617 continue;
2618
7925c22a
LP
2619 if (de->d_type == DT_UNKNOWN ||
2620 honour_sticky ||
2621 (de->d_type == DT_DIR && root_dev)) {
8c6db833 2622 if (fstatat(fd, de->d_name, &st, AT_SYMLINK_NOFOLLOW) < 0) {
4c633005 2623 if (ret == 0 && errno != ENOENT)
8c6db833
LP
2624 ret = -errno;
2625 continue;
2626 }
2627
2628 is_dir = S_ISDIR(st.st_mode);
7925c22a
LP
2629 keep_around =
2630 honour_sticky &&
2631 (st.st_uid == 0 || st.st_uid == getuid()) &&
2632 (st.st_mode & S_ISVTX);
ad293f5a 2633 } else {
8c6db833 2634 is_dir = de->d_type == DT_DIR;
7925c22a 2635 keep_around = false;
ad293f5a 2636 }
8c6db833
LP
2637
2638 if (is_dir) {
2639 int subdir_fd;
8c6db833 2640
597f43c7 2641 /* if root_dev is set, remove subdirectories only, if device is same as dir */
7925c22a
LP
2642 if (root_dev && st.st_dev != root_dev->st_dev)
2643 continue;
8c6db833 2644
7925c22a
LP
2645 subdir_fd = openat(fd, de->d_name,
2646 O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW|O_NOATIME);
2647 if (subdir_fd < 0) {
2648 if (ret == 0 && errno != ENOENT)
2649 ret = -errno;
2650 continue;
2651 }
2652
b3d28469 2653 r = rm_rf_children_dangerous(subdir_fd, only_dirs, honour_sticky, root_dev);
7925c22a
LP
2654 if (r < 0 && ret == 0)
2655 ret = r;
2656
2657 if (!keep_around)
2658 if (unlinkat(fd, de->d_name, AT_REMOVEDIR) < 0) {
ad293f5a
LP
2659 if (ret == 0 && errno != ENOENT)
2660 ret = -errno;
2661 }
2662
2663 } else if (!only_dirs && !keep_around) {
8c6db833
LP
2664
2665 if (unlinkat(fd, de->d_name, 0) < 0) {
4c633005 2666 if (ret == 0 && errno != ENOENT)
8c6db833
LP
2667 ret = -errno;
2668 }
2669 }
2670 }
2671
2672 closedir(d);
2673
2674 return ret;
2675}
2676
44a6b1b6 2677_pure_ static int is_temporary_fs(struct statfs *s) {
943aad8c 2678 assert(s);
73020ab2
SL
2679
2680 return F_TYPE_EQUAL(s->f_type, TMPFS_MAGIC) ||
2681 F_TYPE_EQUAL(s->f_type, RAMFS_MAGIC);
943aad8c
ZJS
2682}
2683
f56d5db9
LP
2684int rm_rf_children(int fd, bool only_dirs, bool honour_sticky, struct stat *root_dev) {
2685 struct statfs s;
2686
2687 assert(fd >= 0);
2688
2689 if (fstatfs(fd, &s) < 0) {
2690 close_nointr_nofail(fd);
2691 return -errno;
2692 }
2693
2694 /* We refuse to clean disk file systems with this call. This
2695 * is extra paranoia just to be sure we never ever remove
2696 * non-state data */
943aad8c 2697 if (!is_temporary_fs(&s)) {
f56d5db9
LP
2698 log_error("Attempted to remove disk file system, and we can't allow that.");
2699 close_nointr_nofail(fd);
2700 return -EPERM;
2701 }
2702
2703 return rm_rf_children_dangerous(fd, only_dirs, honour_sticky, root_dev);
2704}
2705
2706static int rm_rf_internal(const char *path, bool only_dirs, bool delete_root, bool honour_sticky, bool dangerous) {
2707 int fd, r;
2708 struct statfs s;
8c6db833
LP
2709
2710 assert(path);
2711
f56d5db9
LP
2712 /* We refuse to clean the root file system with this
2713 * call. This is extra paranoia to never cause a really
2714 * seriously broken system. */
2715 if (path_equal(path, "/")) {
2716 log_error("Attempted to remove entire root file system, and we can't allow that.");
2717 return -EPERM;
2718 }
461b1822 2719
d4d046e3
LP
2720 fd = open(path, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW|O_NOATIME);
2721 if (fd < 0) {
8c6db833
LP
2722
2723 if (errno != ENOTDIR)
2724 return -errno;
2725
f56d5db9
LP
2726 if (!dangerous) {
2727 if (statfs(path, &s) < 0)
2728 return -errno;
2729
943aad8c 2730 if (!is_temporary_fs(&s)) {
f56d5db9
LP
2731 log_error("Attempted to remove disk file system, and we can't allow that.");
2732 return -EPERM;
2733 }
2734 }
2735
8c6db833 2736 if (delete_root && !only_dirs)
d4d046e3 2737 if (unlink(path) < 0 && errno != ENOENT)
8c6db833
LP
2738 return -errno;
2739
2740 return 0;
2741 }
2742
f56d5db9
LP
2743 if (!dangerous) {
2744 if (fstatfs(fd, &s) < 0) {
2745 close_nointr_nofail(fd);
2746 return -errno;
2747 }
ad293f5a 2748
943aad8c 2749 if (!is_temporary_fs(&s)) {
f56d5db9
LP
2750 log_error("Attempted to remove disk file system, and we can't allow that.");
2751 close_nointr_nofail(fd);
2752 return -EPERM;
2753 }
2754 }
2755
2756 r = rm_rf_children_dangerous(fd, only_dirs, honour_sticky, NULL);
ad293f5a
LP
2757 if (delete_root) {
2758
8d53b453 2759 if (honour_sticky && file_is_priv_sticky(path) > 0)
ad293f5a 2760 return r;
8c6db833 2761
e27796a0 2762 if (rmdir(path) < 0 && errno != ENOENT) {
8c6db833
LP
2763 if (r == 0)
2764 r = -errno;
2765 }
ad293f5a 2766 }
8c6db833
LP
2767
2768 return r;
2769}
2770
f56d5db9
LP
2771int rm_rf(const char *path, bool only_dirs, bool delete_root, bool honour_sticky) {
2772 return rm_rf_internal(path, only_dirs, delete_root, honour_sticky, false);
2773}
2774
2775int rm_rf_dangerous(const char *path, bool only_dirs, bool delete_root, bool honour_sticky) {
2776 return rm_rf_internal(path, only_dirs, delete_root, honour_sticky, true);
2777}
2778
8c6db833
LP
2779int chmod_and_chown(const char *path, mode_t mode, uid_t uid, gid_t gid) {
2780 assert(path);
2781
2782 /* Under the assumption that we are running privileged we
2783 * first change the access mode and only then hand out
2784 * ownership to avoid a window where access is too open. */
2785
8d53b453
LP
2786 if (mode != (mode_t) -1)
2787 if (chmod(path, mode) < 0)
2788 return -errno;
8c6db833 2789
8d53b453
LP
2790 if (uid != (uid_t) -1 || gid != (gid_t) -1)
2791 if (chown(path, uid, gid) < 0)
2792 return -errno;
8c6db833
LP
2793
2794 return 0;
ef2f1067
LP
2795}
2796
f4b47811
LP
2797int fchmod_and_fchown(int fd, mode_t mode, uid_t uid, gid_t gid) {
2798 assert(fd >= 0);
2799
2800 /* Under the assumption that we are running privileged we
2801 * first change the access mode and only then hand out
2802 * ownership to avoid a window where access is too open. */
2803
9588bc32
LP
2804 if (mode != (mode_t) -1)
2805 if (fchmod(fd, mode) < 0)
2806 return -errno;
f4b47811 2807
9588bc32
LP
2808 if (uid != (uid_t) -1 || gid != (gid_t) -1)
2809 if (fchown(fd, uid, gid) < 0)
2810 return -errno;
f4b47811
LP
2811
2812 return 0;
2813}
2814
82c121a4
LP
2815cpu_set_t* cpu_set_malloc(unsigned *ncpus) {
2816 cpu_set_t *r;
2817 unsigned n = 1024;
2818
2819 /* Allocates the cpuset in the right size */
2820
2821 for (;;) {
2822 if (!(r = CPU_ALLOC(n)))
2823 return NULL;
2824
2825 if (sched_getaffinity(0, CPU_ALLOC_SIZE(n), r) >= 0) {
2826 CPU_ZERO_S(CPU_ALLOC_SIZE(n), r);
2827
2828 if (ncpus)
2829 *ncpus = n;
2830
2831 return r;
2832 }
2833
2834 CPU_FREE(r);
2835
2836 if (errno != EINVAL)
2837 return NULL;
2838
2839 n *= 2;
2840 }
2841}
2842
984a2be4 2843int status_vprintf(const char *status, bool ellipse, bool ephemeral, const char *format, va_list ap) {
9ab7a8d2 2844 static const char status_indent[] = " "; /* "[" STATUS "] " */
669bec5d
LP
2845 _cleanup_free_ char *s = NULL;
2846 _cleanup_close_ int fd = -1;
b92bea5d 2847 struct iovec iovec[6] = {};
81beb750 2848 int n = 0;
984a2be4 2849 static bool prev_ephemeral;
9e58ff9c
LP
2850
2851 assert(format);
2852
9ab7a8d2 2853 /* This is independent of logging, as status messages are
9e58ff9c
LP
2854 * optional and go exclusively to the console. */
2855
2856 if (vasprintf(&s, format, ap) < 0)
669bec5d 2857 return log_oom();
9e58ff9c 2858
67e5cc4f 2859 fd = open_terminal("/dev/console", O_WRONLY|O_NOCTTY|O_CLOEXEC);
81beb750 2860 if (fd < 0)
669bec5d 2861 return fd;
9e58ff9c 2862
67e5cc4f 2863 if (ellipse) {
9ab7a8d2
MS
2864 char *e;
2865 size_t emax, sl;
2866 int c;
2867
67e5cc4f
LP
2868 c = fd_columns(fd);
2869 if (c <= 0)
2870 c = 80;
81beb750 2871
669bec5d 2872 sl = status ? sizeof(status_indent)-1 : 0;
9ab7a8d2
MS
2873
2874 emax = c - sl - 1;
2875 if (emax < 3)
2876 emax = 3;
81beb750 2877
67e5cc4f
LP
2878 e = ellipsize(s, emax, 75);
2879 if (e) {
2880 free(s);
2881 s = e;
2882 }
81beb750
LP
2883 }
2884
984a2be4
MS
2885 if (prev_ephemeral)
2886 IOVEC_SET_STRING(iovec[n++], "\r" ANSI_ERASE_TO_END_OF_LINE);
2887 prev_ephemeral = ephemeral;
2888
9ab7a8d2
MS
2889 if (status) {
2890 if (!isempty(status)) {
2891 IOVEC_SET_STRING(iovec[n++], "[");
2892 IOVEC_SET_STRING(iovec[n++], status);
2893 IOVEC_SET_STRING(iovec[n++], "] ");
2894 } else
2895 IOVEC_SET_STRING(iovec[n++], status_indent);
81beb750
LP
2896 }
2897
9ab7a8d2 2898 IOVEC_SET_STRING(iovec[n++], s);
984a2be4
MS
2899 if (!ephemeral)
2900 IOVEC_SET_STRING(iovec[n++], "\n");
81beb750 2901
669bec5d
LP
2902 if (writev(fd, iovec, n) < 0)
2903 return -errno;
9e58ff9c 2904
669bec5d 2905 return 0;
9e58ff9c
LP
2906}
2907
984a2be4 2908int status_printf(const char *status, bool ellipse, bool ephemeral, const char *format, ...) {
c846ff47 2909 va_list ap;
669bec5d 2910 int r;
c846ff47
LP
2911
2912 assert(format);
2913
2914 va_start(ap, format);
984a2be4 2915 r = status_vprintf(status, ellipse, ephemeral, format, ap);
c846ff47 2916 va_end(ap);
669bec5d
LP
2917
2918 return r;
c846ff47
LP
2919}
2920
fab56fc5
LP
2921char *replace_env(const char *format, char **env) {
2922 enum {
2923 WORD,
c24eb49e 2924 CURLY,
fab56fc5
LP
2925 VARIABLE
2926 } state = WORD;
2927
2928 const char *e, *word = format;
2929 char *r = NULL, *k;
2930
2931 assert(format);
2932
2933 for (e = format; *e; e ++) {
2934
2935 switch (state) {
2936
2937 case WORD:
2938 if (*e == '$')
c24eb49e 2939 state = CURLY;
fab56fc5
LP
2940 break;
2941
c24eb49e
LP
2942 case CURLY:
2943 if (*e == '{') {
fab56fc5
LP
2944 if (!(k = strnappend(r, word, e-word-1)))
2945 goto fail;
2946
2947 free(r);
2948 r = k;
2949
2950 word = e-1;
2951 state = VARIABLE;
2952
2953 } else if (*e == '$') {
2954 if (!(k = strnappend(r, word, e-word)))
2955 goto fail;
2956
2957 free(r);
2958 r = k;
2959
2960 word = e+1;
2961 state = WORD;
2962 } else
2963 state = WORD;
2964 break;
2965
2966 case VARIABLE:
c24eb49e 2967 if (*e == '}') {
b95cf362 2968 const char *t;
fab56fc5 2969
4d1a6904 2970 t = strempty(strv_env_get_n(env, word+2, e-word-2));
fab56fc5 2971
4d1a6904
LP
2972 k = strappend(r, t);
2973 if (!k)
b95cf362 2974 goto fail;
fab56fc5 2975
b95cf362
LP
2976 free(r);
2977 r = k;
fab56fc5 2978
b95cf362 2979 word = e+1;
fab56fc5
LP
2980 state = WORD;
2981 }
2982 break;
2983 }
2984 }
2985
2986 if (!(k = strnappend(r, word, e-word)))
2987 goto fail;
2988
2989 free(r);
2990 return k;
2991
2992fail:
2993 free(r);
2994 return NULL;
2995}
2996
2997char **replace_env_argv(char **argv, char **env) {
2998 char **r, **i;
c24eb49e
LP
2999 unsigned k = 0, l = 0;
3000
3001 l = strv_length(argv);
fab56fc5 3002
c24eb49e 3003 if (!(r = new(char*, l+1)))
fab56fc5
LP
3004 return NULL;
3005
3006 STRV_FOREACH(i, argv) {
c24eb49e
LP
3007
3008 /* If $FOO appears as single word, replace it by the split up variable */
b95cf362
LP
3009 if ((*i)[0] == '$' && (*i)[1] != '{') {
3010 char *e;
3011 char **w, **m;
3012 unsigned q;
c24eb49e 3013
4d1a6904
LP
3014 e = strv_env_get(env, *i+1);
3015 if (e) {
c24eb49e
LP
3016
3017 if (!(m = strv_split_quoted(e))) {
3018 r[k] = NULL;
3019 strv_free(r);
3020 return NULL;
3021 }
b95cf362
LP
3022 } else
3023 m = NULL;
c24eb49e 3024
b95cf362
LP
3025 q = strv_length(m);
3026 l = l + q - 1;
c24eb49e 3027
b95cf362
LP
3028 if (!(w = realloc(r, sizeof(char*) * (l+1)))) {
3029 r[k] = NULL;
3030 strv_free(r);
3031 strv_free(m);
3032 return NULL;
3033 }
c24eb49e 3034
b95cf362
LP
3035 r = w;
3036 if (m) {
c24eb49e
LP
3037 memcpy(r + k, m, q * sizeof(char*));
3038 free(m);
c24eb49e 3039 }
b95cf362
LP
3040
3041 k += q;
3042 continue;
c24eb49e
LP
3043 }
3044
3045 /* If ${FOO} appears as part of a word, replace it by the variable as-is */
fab56fc5
LP
3046 if (!(r[k++] = replace_env(*i, env))) {
3047 strv_free(r);
3048 return NULL;
3049 }
3050 }
3051
3052 r[k] = NULL;
3053 return r;
3054}
3055
81beb750 3056int fd_columns(int fd) {
b92bea5d 3057 struct winsize ws = {};
81beb750
LP
3058
3059 if (ioctl(fd, TIOCGWINSZ, &ws) < 0)
3060 return -errno;
3061
3062 if (ws.ws_col <= 0)
3063 return -EIO;
3064
3065 return ws.ws_col;
3066}
3067
28917d7d 3068unsigned columns(void) {
fa776d8e 3069 const char *e;
7009eec2 3070 int c;
fa776d8e 3071
28917d7d
LP
3072 if (_likely_(cached_columns > 0))
3073 return cached_columns;
11f96fac 3074
28917d7d
LP
3075 c = 0;
3076 e = getenv("COLUMNS");
3077 if (e)
7009eec2 3078 safe_atoi(e, &c);
fa776d8e 3079
28917d7d
LP
3080 if (c <= 0)
3081 c = fd_columns(STDOUT_FILENO);
fa776d8e 3082
28917d7d
LP
3083 if (c <= 0)
3084 c = 80;
11f96fac 3085
28917d7d
LP
3086 cached_columns = c;
3087 return c;
11f96fac
ZJS
3088}
3089
8f2d43a0 3090int fd_lines(int fd) {
b92bea5d 3091 struct winsize ws = {};
8f2d43a0
LP
3092
3093 if (ioctl(fd, TIOCGWINSZ, &ws) < 0)
3094 return -errno;
3095
3096 if (ws.ws_row <= 0)
3097 return -EIO;
3098
3099 return ws.ws_row;
3100}
3101
3102unsigned lines(void) {
8f2d43a0 3103 const char *e;
ed757c0c 3104 unsigned l;
8f2d43a0 3105
ed757c0c
LP
3106 if (_likely_(cached_lines > 0))
3107 return cached_lines;
8f2d43a0 3108
ed757c0c 3109 l = 0;
8f2d43a0
LP
3110 e = getenv("LINES");
3111 if (e)
ed757c0c 3112 safe_atou(e, &l);
8f2d43a0 3113
ed757c0c
LP
3114 if (l <= 0)
3115 l = fd_lines(STDOUT_FILENO);
8f2d43a0 3116
ed757c0c
LP
3117 if (l <= 0)
3118 l = 24;
8f2d43a0 3119
ed757c0c
LP
3120 cached_lines = l;
3121 return cached_lines;
3122}
3123
3124/* intended to be used as a SIGWINCH sighandler */
3125void columns_lines_cache_reset(int signum) {
3126 cached_columns = 0;
3127 cached_lines = 0;
3128}
3129
3130bool on_tty(void) {
3131 static int cached_on_tty = -1;
3132
3133 if (_unlikely_(cached_on_tty < 0))
3134 cached_on_tty = isatty(STDOUT_FILENO) > 0;
3135
3136 return cached_on_tty;
8f2d43a0
LP
3137}
3138
b4f10a5e 3139int running_in_chroot(void) {
b92bea5d 3140 struct stat a = {}, b = {};
b4f10a5e
LP
3141
3142 /* Only works as root */
b4f10a5e
LP
3143 if (stat("/proc/1/root", &a) < 0)
3144 return -errno;
3145
3146 if (stat("/", &b) < 0)
3147 return -errno;
3148
3149 return
3150 a.st_dev != b.st_dev ||
3151 a.st_ino != b.st_ino;
3152}
3153
f405e86d 3154static char *ascii_ellipsize_mem(const char *s, size_t old_length, size_t new_length, unsigned percent) {
72f59706 3155 size_t x;
8fe914ec
LP
3156 char *r;
3157
3158 assert(s);
3159 assert(percent <= 100);
72f59706 3160 assert(new_length >= 3);
8fe914ec 3161
72f59706
LP
3162 if (old_length <= 3 || old_length <= new_length)
3163 return strndup(s, old_length);
8fe914ec 3164
72f59706
LP
3165 r = new0(char, new_length+1);
3166 if (!r)
a6f0104a 3167 return NULL;
8fe914ec 3168
72f59706 3169 x = (new_length * percent) / 100;
8fe914ec 3170
72f59706
LP
3171 if (x > new_length - 3)
3172 x = new_length - 3;
8fe914ec
LP
3173
3174 memcpy(r, s, x);
3175 r[x] = '.';
3176 r[x+1] = '.';
3177 r[x+2] = '.';
3178 memcpy(r + x + 3,
72f59706
LP
3179 s + old_length - (new_length - x - 3),
3180 new_length - x - 3);
8fe914ec
LP
3181
3182 return r;
3183}
3184
f405e86d
SL
3185char *ellipsize_mem(const char *s, size_t old_length, size_t new_length, unsigned percent) {
3186 size_t x;
3187 char *e;
3188 const char *i, *j;
3189 unsigned k, len, len2;
3190
3191 assert(s);
3192 assert(percent <= 100);
3193 assert(new_length >= 3);
3194
3195 /* if no multibyte characters use ascii_ellipsize_mem for speed */
3196 if (ascii_is_valid(s))
3197 return ascii_ellipsize_mem(s, old_length, new_length, percent);
3198
3199 if (old_length <= 3 || old_length <= new_length)
3200 return strndup(s, old_length);
3201
3202 x = (new_length * percent) / 100;
3203
3204 if (x > new_length - 3)
3205 x = new_length - 3;
3206
3207 k = 0;
3208 for (i = s; k < x && i < s + old_length; i = utf8_next_char(i)) {
3209 int c;
3210
3211 c = utf8_encoded_to_unichar(i);
3212 if (c < 0)
3213 return NULL;
3214 k += unichar_iswide(c) ? 2 : 1;
3215 }
3216
3217 if (k > x) /* last character was wide and went over quota */
3218 x ++;
3219
3220 for (j = s + old_length; k < new_length && j > i; ) {
3221 int c;
3222
3223 j = utf8_prev_char(j);
3224 c = utf8_encoded_to_unichar(j);
3225 if (c < 0)
3226 return NULL;
3227 k += unichar_iswide(c) ? 2 : 1;
3228 }
3229 assert(i <= j);
3230
3231 /* we don't actually need to ellipsize */
3232 if (i == j)
3233 return memdup(s, old_length + 1);
3234
3235 /* make space for ellipsis */
3236 j = utf8_next_char(j);
3237
3238 len = i - s;
3239 len2 = s + old_length - j;
3240 e = new(char, len + 3 + len2 + 1);
3241 if (!e)
3242 return NULL;
3243
3244 /*
3245 printf("old_length=%zu new_length=%zu x=%zu len=%u len2=%u k=%u\n",
3246 old_length, new_length, x, len, len2, k);
3247 */
3248
3249 memcpy(e, s, len);
3250 e[len] = 0xe2; /* tri-dot ellipsis: … */
3251 e[len + 1] = 0x80;
3252 e[len + 2] = 0xa6;
3253
3254 memcpy(e + len + 3, j, len2 + 1);
3255
3256 return e;
3257}
3258
72f59706
LP
3259char *ellipsize(const char *s, size_t length, unsigned percent) {
3260 return ellipsize_mem(s, strlen(s), length, percent);
3261}
3262
f6144808
LP
3263int touch(const char *path) {
3264 int fd;
3265
3266 assert(path);
3267
73836c5c
LP
3268 /* This just opens the file for writing, ensuring it
3269 * exists. It doesn't call utimensat() the way /usr/bin/touch
3270 * does it. */
3271
3272 fd = open(path, O_WRONLY|O_CREAT|O_CLOEXEC|O_NOCTTY, 0644);
3273 if (fd < 0)
f6144808
LP
3274 return -errno;
3275
3276 close_nointr_nofail(fd);
3277 return 0;
3278}
afea26ad 3279
97c4a07d 3280char *unquote(const char *s, const char* quotes) {
11ce3427
LP
3281 size_t l;
3282 assert(s);
3283
73836c5c
LP
3284 /* This is rather stupid, simply removes the heading and
3285 * trailing quotes if there is one. Doesn't care about
57f30678
LP
3286 * escaping or anything. We should make this smarter one
3287 * day...*/
73836c5c 3288
31ed59c5
LP
3289 l = strlen(s);
3290 if (l < 2)
11ce3427
LP
3291 return strdup(s);
3292
97c4a07d 3293 if (strchr(quotes, s[0]) && s[l-1] == s[0])
11ce3427
LP
3294 return strndup(s+1, l-2);
3295
3296 return strdup(s);
3297}
3298
5f7c426e 3299char *normalize_env_assignment(const char *s) {
57f30678
LP
3300 _cleanup_free_ char *name = NULL, *value = NULL, *p = NULL;
3301 char *eq, *r;
5f7c426e 3302
57f30678
LP
3303 eq = strchr(s, '=');
3304 if (!eq) {
3305 char *t;
5f7c426e 3306
57f30678
LP
3307 r = strdup(s);
3308 if (!r)
5f7c426e
LP
3309 return NULL;
3310
57f30678
LP
3311 t = strstrip(r);
3312 if (t == r)
3313 return r;
3314
3315 memmove(r, t, strlen(t) + 1);
3316 return r;
5f7c426e
LP
3317 }
3318
57f30678
LP
3319 name = strndup(s, eq - s);
3320 if (!name)
5f7c426e
LP
3321 return NULL;
3322
57f30678
LP
3323 p = strdup(eq + 1);
3324 if (!p)
5f7c426e 3325 return NULL;
5f7c426e
LP
3326
3327 value = unquote(strstrip(p), QUOTES);
57f30678 3328 if (!value)
5f7c426e 3329 return NULL;
5f7c426e 3330
57f30678 3331 if (asprintf(&r, "%s=%s", strstrip(name), value) < 0)
5f7c426e
LP
3332 r = NULL;
3333
5f7c426e
LP
3334 return r;
3335}
3336
8e12a6ae 3337int wait_for_terminate(pid_t pid, siginfo_t *status) {
1968a360
LP
3338 siginfo_t dummy;
3339
2e78aa99 3340 assert(pid >= 1);
1968a360
LP
3341
3342 if (!status)
3343 status = &dummy;
2e78aa99
LP
3344
3345 for (;;) {
8e12a6ae
LP
3346 zero(*status);
3347
3348 if (waitid(P_PID, pid, status, WEXITED) < 0) {
2e78aa99
LP
3349
3350 if (errno == EINTR)
3351 continue;
3352
3353 return -errno;
3354 }
3355
3356 return 0;
3357 }
3358}
3359
97c4a07d
LP
3360int wait_for_terminate_and_warn(const char *name, pid_t pid) {
3361 int r;
3362 siginfo_t status;
3363
3364 assert(name);
3365 assert(pid > 1);
3366
d87be9b0
LP
3367 r = wait_for_terminate(pid, &status);
3368 if (r < 0) {
97c4a07d
LP
3369 log_warning("Failed to wait for %s: %s", name, strerror(-r));
3370 return r;
3371 }
3372
3373 if (status.si_code == CLD_EXITED) {
3374 if (status.si_status != 0) {
3375 log_warning("%s failed with error code %i.", name, status.si_status);
0a27cf3f 3376 return status.si_status;
97c4a07d
LP
3377 }
3378
3379 log_debug("%s succeeded.", name);
3380 return 0;
3381
3382 } else if (status.si_code == CLD_KILLED ||
3383 status.si_code == CLD_DUMPED) {
3384
3385 log_warning("%s terminated by signal %s.", name, signal_to_string(status.si_status));
3386 return -EPROTO;
3387 }
3388
3389 log_warning("%s failed due to unknown reason.", name);
3390 return -EPROTO;
97c4a07d
LP
3391}
3392
919ce0b7 3393noreturn void freeze(void) {
720ce21d
LP
3394
3395 /* Make sure nobody waits for us on a socket anymore */
3396 close_all_fds(NULL, 0);
3397
c29597a1
LP
3398 sync();
3399
3c14d26c
LP
3400 for (;;)
3401 pause();
3402}
3403
00dc5d76
LP
3404bool null_or_empty(struct stat *st) {
3405 assert(st);
3406
3407 if (S_ISREG(st->st_mode) && st->st_size <= 0)
3408 return true;
3409
c8f26f42 3410 if (S_ISCHR(st->st_mode) || S_ISBLK(st->st_mode))
00dc5d76
LP
3411 return true;
3412
3413 return false;
3414}
3415
83096483
LP
3416int null_or_empty_path(const char *fn) {
3417 struct stat st;
3418
3419 assert(fn);
3420
3421 if (stat(fn, &st) < 0)
3422 return -errno;
3423
3424 return null_or_empty(&st);
3425}
3426
a247755d 3427DIR *xopendirat(int fd, const char *name, int flags) {
c4731d11
LP
3428 int nfd;
3429 DIR *d;
3430
dd94c17e
LP
3431 assert(!(flags & O_CREAT));
3432
3433 nfd = openat(fd, name, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|flags, 0);
73836c5c 3434 if (nfd < 0)
c4731d11
LP
3435 return NULL;
3436
73836c5c
LP
3437 d = fdopendir(nfd);
3438 if (!d) {
c4731d11
LP
3439 close_nointr_nofail(nfd);
3440 return NULL;
3441 }
3442
3443 return d;
3b63d2d3
LP
3444}
3445
8a0867d6
LP
3446int signal_from_string_try_harder(const char *s) {
3447 int signo;
3448 assert(s);
3449
73836c5c
LP
3450 signo = signal_from_string(s);
3451 if (signo <= 0)
8a0867d6
LP
3452 if (startswith(s, "SIG"))
3453 return signal_from_string(s+3);
3454
3455 return signo;
3456}
3457
383182b5 3458static char *tag_to_udev_node(const char *tagvalue, const char *by) {
22f5f628
DR
3459 _cleanup_free_ char *t = NULL, *u = NULL;
3460 char *dn;
3461 size_t enc_len;
e23a0ce8 3462
383182b5
DR
3463 u = unquote(tagvalue, "\"\'");
3464 if (u == NULL)
3465 return NULL;
e23a0ce8 3466
1d5989fd 3467 enc_len = strlen(u) * 4 + 1;
22f5f628 3468 t = new(char, enc_len);
383182b5
DR
3469 if (t == NULL)
3470 return NULL;
e23a0ce8 3471
8f6ce71f 3472 if (encode_devnode_name(u, t, enc_len) < 0)
22f5f628 3473 return NULL;
e23a0ce8 3474
22f5f628 3475 if (asprintf(&dn, "/dev/disk/by-%s/%s", by, t) < 0)
383182b5 3476 return NULL;
e23a0ce8 3477
383182b5
DR
3478 return dn;
3479}
e23a0ce8 3480
383182b5 3481char *fstab_node_to_udev_node(const char *p) {
faa368e3
LP
3482 assert(p);
3483
383182b5
DR
3484 if (startswith(p, "LABEL="))
3485 return tag_to_udev_node(p+6, "label");
e23a0ce8 3486
383182b5
DR
3487 if (startswith(p, "UUID="))
3488 return tag_to_udev_node(p+5, "uuid");
e23a0ce8 3489
84cc2abf
DR
3490 if (startswith(p, "PARTUUID="))
3491 return tag_to_udev_node(p+9, "partuuid");
3492
3493 if (startswith(p, "PARTLABEL="))
3494 return tag_to_udev_node(p+10, "partlabel");
3495
e23a0ce8
LP
3496 return strdup(p);
3497}
3498
f212ac12
LP
3499bool tty_is_vc(const char *tty) {
3500 assert(tty);
3501
3502 if (startswith(tty, "/dev/"))
3503 tty += 5;
3504
98a28fef
LP
3505 return vtnr_from_tty(tty) >= 0;
3506}
3507
d1122ad5
LP
3508bool tty_is_console(const char *tty) {
3509 assert(tty);
3510
3511 if (startswith(tty, "/dev/"))
3512 tty += 5;
3513
3514 return streq(tty, "console");
3515}
3516
98a28fef
LP
3517int vtnr_from_tty(const char *tty) {
3518 int i, r;
3519
3520 assert(tty);
3521
3522 if (startswith(tty, "/dev/"))
3523 tty += 5;
3524
3525 if (!startswith(tty, "tty") )
3526 return -EINVAL;
3527
3528 if (tty[3] < '0' || tty[3] > '9')
3529 return -EINVAL;
3530
3531 r = safe_atoi(tty+3, &i);
3532 if (r < 0)
3533 return r;
3534
3535 if (i < 0 || i > 63)
3536 return -EINVAL;
3537
3538 return i;
f212ac12
LP
3539}
3540
21baf21a
MS
3541char *resolve_dev_console(char **active) {
3542 char *tty;
3543
3544 /* Resolve where /dev/console is pointing to, if /sys is actually ours
3545 * (i.e. not read-only-mounted which is a sign for container setups) */
3546
3547 if (path_is_read_only_fs("/sys") > 0)
3548 return NULL;
3549
3550 if (read_one_line_file("/sys/class/tty/console/active", active) < 0)
3551 return NULL;
3552
3553 /* If multiple log outputs are configured the last one is what
3554 * /dev/console points to */
3555 tty = strrchr(*active, ' ');
3556 if (tty)
3557 tty++;
3558 else
3559 tty = *active;
3560
8aa5429a
OB
3561 if (streq(tty, "tty0")) {
3562 char *tmp;
3563
3564 /* Get the active VC (e.g. tty1) */
3565 if (read_one_line_file("/sys/class/tty/tty0/active", &tmp) >= 0) {
3566 free(*active);
3567 tty = *active = tmp;
3568 }
3569 }
3570
21baf21a
MS
3571 return tty;
3572}
3573
3043935f 3574bool tty_is_vc_resolve(const char *tty) {
9588bc32 3575 _cleanup_free_ char *active = NULL;
3030ccd7 3576
e3aa71c3
LP
3577 assert(tty);
3578
3579 if (startswith(tty, "/dev/"))
3580 tty += 5;
3581
21baf21a
MS
3582 if (streq(tty, "console")) {
3583 tty = resolve_dev_console(&active);
3584 if (!tty)
3585 return false;
3586 }
3030ccd7 3587
9588bc32 3588 return tty_is_vc(tty);
3043935f
LP
3589}
3590
3591const char *default_term_for_tty(const char *tty) {
3592 assert(tty);
3593
acda6a05 3594 return tty_is_vc_resolve(tty) ? "TERM=linux" : "TERM=vt102";
e3aa71c3
LP
3595}
3596
87d2c1ff 3597bool dirent_is_file(const struct dirent *de) {
fb19a739
LP
3598 assert(de);
3599
3600 if (ignore_file(de->d_name))
3601 return false;
3602
3603 if (de->d_type != DT_REG &&
3604 de->d_type != DT_LNK &&
3605 de->d_type != DT_UNKNOWN)
3606 return false;
3607
3608 return true;
3609}
3610
87d2c1ff
LP
3611bool dirent_is_file_with_suffix(const struct dirent *de, const char *suffix) {
3612 assert(de);
3613
a228a22f
LP
3614 if (de->d_type != DT_REG &&
3615 de->d_type != DT_LNK &&
3616 de->d_type != DT_UNKNOWN)
3617 return false;
3618
3619 if (ignore_file_allow_backup(de->d_name))
87d2c1ff
LP
3620 return false;
3621
3622 return endswith(de->d_name, suffix);
3623}
3624
83cc030f
LP
3625void execute_directory(const char *directory, DIR *d, char *argv[]) {
3626 DIR *_d = NULL;
3627 struct dirent *de;
3628 Hashmap *pids = NULL;
3629
3630 assert(directory);
3631
650001c6
JJ
3632 /* Executes all binaries in a directory in parallel and
3633 * waits for them to finish. */
83cc030f
LP
3634
3635 if (!d) {
3636 if (!(_d = opendir(directory))) {
3637
3638 if (errno == ENOENT)
3639 return;
3640
3641 log_error("Failed to enumerate directory %s: %m", directory);
3642 return;
3643 }
3644
3645 d = _d;
3646 }
3647
3648 if (!(pids = hashmap_new(trivial_hash_func, trivial_compare_func))) {
3649 log_error("Failed to allocate set.");
3650 goto finish;
3651 }
3652
3653 while ((de = readdir(d))) {
3654 char *path;
3655 pid_t pid;
3656 int k;
3657
fb19a739 3658 if (!dirent_is_file(de))
83cc030f
LP
3659 continue;
3660
3661 if (asprintf(&path, "%s/%s", directory, de->d_name) < 0) {
0d0f0c50 3662 log_oom();
83cc030f
LP
3663 continue;
3664 }
3665
3666 if ((pid = fork()) < 0) {
3667 log_error("Failed to fork: %m");
3668 free(path);
3669 continue;
3670 }
3671
3672 if (pid == 0) {
3673 char *_argv[2];
3674 /* Child */
3675
3676 if (!argv) {
3677 _argv[0] = path;
3678 _argv[1] = NULL;
3679 argv = _argv;
3680 } else
6edd7d0a 3681 argv[0] = path;
83cc030f
LP
3682
3683 execv(path, argv);
3684
3685 log_error("Failed to execute %s: %m", path);
3686 _exit(EXIT_FAILURE);
3687 }
3688
3689 log_debug("Spawned %s as %lu", path, (unsigned long) pid);
3690
3691 if ((k = hashmap_put(pids, UINT_TO_PTR(pid), path)) < 0) {
3692 log_error("Failed to add PID to set: %s", strerror(-k));
3693 free(path);
3694 }
3695 }
3696
3697 while (!hashmap_isempty(pids)) {
ec3f9b53 3698 pid_t pid = PTR_TO_UINT(hashmap_first_key(pids));
b92bea5d 3699 siginfo_t si = {};
83cc030f
LP
3700 char *path;
3701
ec3f9b53 3702 if (waitid(P_PID, pid, &si, WEXITED) < 0) {
83cc030f
LP
3703
3704 if (errno == EINTR)
3705 continue;
3706
3707 log_error("waitid() failed: %m");
3708 goto finish;
3709 }
3710
3711 if ((path = hashmap_remove(pids, UINT_TO_PTR(si.si_pid)))) {
96342de6 3712 if (!is_clean_exit(si.si_code, si.si_status, NULL)) {
83cc030f
LP
3713 if (si.si_code == CLD_EXITED)
3714 log_error("%s exited with exit status %i.", path, si.si_status);
3715 else
3716 log_error("%s terminated by signal %s.", path, signal_to_string(si.si_status));
3717 } else
3718 log_debug("%s exited successfully.", path);
3719
3720 free(path);
3721 }
3722 }
3723
3724finish:
3725 if (_d)
3726 closedir(_d);
3727
3728 if (pids)
3729 hashmap_free_free(pids);
3730}
3731
430c18ed
LP
3732int kill_and_sigcont(pid_t pid, int sig) {
3733 int r;
3734
3735 r = kill(pid, sig) < 0 ? -errno : 0;
3736
3737 if (r >= 0)
3738 kill(pid, SIGCONT);
3739
3740 return r;
3741}
3742
05feefe0
LP
3743bool nulstr_contains(const char*nulstr, const char *needle) {
3744 const char *i;
3745
3746 if (!nulstr)
3747 return false;
3748
3749 NULSTR_FOREACH(i, nulstr)
3750 if (streq(i, needle))
3751 return true;
3752
3753 return false;
3754}
3755
6faa1114 3756bool plymouth_running(void) {
9408a2d2 3757 return access("/run/plymouth/pid", F_OK) >= 0;
6faa1114
LP
3758}
3759
9beb3f4d
LP
3760char* strshorten(char *s, size_t l) {
3761 assert(s);
3762
3763 if (l < strlen(s))
3764 s[l] = 0;
3765
3766 return s;
3767}
3768
3769static bool hostname_valid_char(char c) {
3770 return
3771 (c >= 'a' && c <= 'z') ||
3772 (c >= 'A' && c <= 'Z') ||
3773 (c >= '0' && c <= '9') ||
3774 c == '-' ||
3775 c == '_' ||
3776 c == '.';
3777}
3778
3779bool hostname_is_valid(const char *s) {
3780 const char *p;
aa3c5cf8 3781 bool dot;
9beb3f4d
LP
3782
3783 if (isempty(s))
3784 return false;
3785
aa3c5cf8
LP
3786 for (p = s, dot = true; *p; p++) {
3787 if (*p == '.') {
3788 if (dot)
3789 return false;
3790
3791 dot = true;
3792 } else {
3793 if (!hostname_valid_char(*p))
3794 return false;
3795
3796 dot = false;
3797 }
3798 }
3799
3800 if (dot)
3801 return false;
9beb3f4d
LP
3802
3803 if (p-s > HOST_NAME_MAX)
3804 return false;
3805
3806 return true;
3807}
3808
e724b063 3809char* hostname_cleanup(char *s, bool lowercase) {
9beb3f4d 3810 char *p, *d;
cec4ead9
LP
3811 bool dot;
3812
3813 for (p = s, d = s, dot = true; *p; p++) {
3814 if (*p == '.') {
e724b063 3815 if (dot)
cec4ead9 3816 continue;
9beb3f4d 3817
e724b063 3818 *(d++) = '.';
cec4ead9 3819 dot = true;
e724b063
LP
3820 } else if (hostname_valid_char(*p)) {
3821 *(d++) = lowercase ? tolower(*p) : *p;
cec4ead9 3822 dot = false;
e724b063 3823 }
cec4ead9 3824
cec4ead9 3825 }
9beb3f4d 3826
e724b063
LP
3827 if (dot && d > s)
3828 d[-1] = 0;
3829 else
3830 *d = 0;
3831
9beb3f4d 3832 strshorten(s, HOST_NAME_MAX);
cec4ead9 3833
9beb3f4d
LP
3834 return s;
3835}
3836
1325aa42 3837int pipe_eof(int fd) {
b92bea5d
ZJS
3838 struct pollfd pollfd = {
3839 .fd = fd,
3840 .events = POLLIN|POLLHUP,
3841 };
1325aa42 3842
d37a91e8
LP
3843 int r;
3844
1325aa42
LP
3845 r = poll(&pollfd, 1, 0);
3846 if (r < 0)
3847 return -errno;
3848
3849 if (r == 0)
3850 return 0;
3851
3852 return pollfd.revents & POLLHUP;
3853}
3854
8f2d43a0 3855int fd_wait_for_event(int fd, int event, usec_t t) {
968d3d24 3856
b92bea5d
ZJS
3857 struct pollfd pollfd = {
3858 .fd = fd,
3859 .events = event,
3860 };
df50185b 3861
968d3d24
LP
3862 struct timespec ts;
3863 int r;
3864
3865 r = ppoll(&pollfd, 1, t == (usec_t) -1 ? NULL : timespec_store(&ts, t), NULL);
df50185b
LP
3866 if (r < 0)
3867 return -errno;
3868
3869 if (r == 0)
3870 return 0;
3871
3872 return pollfd.revents;
3873}
3874
5a3ab509
LP
3875int fopen_temporary(const char *path, FILE **_f, char **_temp_path) {
3876 FILE *f;
3877 char *t;
3878 const char *fn;
3879 size_t k;
3880 int fd;
3881
3882 assert(path);
3883 assert(_f);
3884 assert(_temp_path);
3885
3886 t = new(char, strlen(path) + 1 + 6 + 1);
3887 if (!t)
3888 return -ENOMEM;
3889
2b6bf07d
ZJS
3890 fn = basename(path);
3891 k = fn - path;
5a3ab509
LP
3892 memcpy(t, path, k);
3893 t[k] = '.';
3894 stpcpy(stpcpy(t+k+1, fn), "XXXXXX");
3895
2d5bdf5b 3896 fd = mkostemp_safe(t, O_WRONLY|O_CLOEXEC);
5a3ab509
LP
3897 if (fd < 0) {
3898 free(t);
3899 return -errno;
3900 }
3901
3902 f = fdopen(fd, "we");
3903 if (!f) {
3904 unlink(t);
3905 free(t);
3906 return -errno;
3907 }
3908
3909 *_f = f;
3910 *_temp_path = t;
3911
3912 return 0;
3913}
3914
6ea832a2 3915int terminal_vhangup_fd(int fd) {
5a3ab509
LP
3916 assert(fd >= 0);
3917
6ea832a2
LP
3918 if (ioctl(fd, TIOCVHANGUP) < 0)
3919 return -errno;
3920
3921 return 0;
3922}
3923
3924int terminal_vhangup(const char *name) {
3925 int fd, r;
3926
3927 fd = open_terminal(name, O_RDWR|O_NOCTTY|O_CLOEXEC);
3928 if (fd < 0)
3929 return fd;
3930
3931 r = terminal_vhangup_fd(fd);
3932 close_nointr_nofail(fd);
3933
3934 return r;
3935}
3936
3937int vt_disallocate(const char *name) {
3938 int fd, r;
3939 unsigned u;
6ea832a2
LP
3940
3941 /* Deallocate the VT if possible. If not possible
3942 * (i.e. because it is the active one), at least clear it
3943 * entirely (including the scrollback buffer) */
3944
b83bc4e9
LP
3945 if (!startswith(name, "/dev/"))
3946 return -EINVAL;
3947
3948 if (!tty_is_vc(name)) {
3949 /* So this is not a VT. I guess we cannot deallocate
3950 * it then. But let's at least clear the screen */
3951
3952 fd = open_terminal(name, O_RDWR|O_NOCTTY|O_CLOEXEC);
3953 if (fd < 0)
3954 return fd;
3955
8585357a
LP
3956 loop_write(fd,
3957 "\033[r" /* clear scrolling region */
3958 "\033[H" /* move home */
3959 "\033[2J", /* clear screen */
3960 10, false);
b83bc4e9
LP
3961 close_nointr_nofail(fd);
3962
3963 return 0;
3964 }
6ea832a2
LP
3965
3966 if (!startswith(name, "/dev/tty"))
3967 return -EINVAL;
3968
3969 r = safe_atou(name+8, &u);
3970 if (r < 0)
3971 return r;
3972
3973 if (u <= 0)
b83bc4e9 3974 return -EINVAL;
6ea832a2 3975
b83bc4e9 3976 /* Try to deallocate */
6ea832a2
LP
3977 fd = open_terminal("/dev/tty0", O_RDWR|O_NOCTTY|O_CLOEXEC);
3978 if (fd < 0)
3979 return fd;
3980
3981 r = ioctl(fd, VT_DISALLOCATE, u);
b83bc4e9 3982 close_nointr_nofail(fd);
6ea832a2 3983
b83bc4e9
LP
3984 if (r >= 0)
3985 return 0;
6ea832a2 3986
b83bc4e9 3987 if (errno != EBUSY)
6ea832a2 3988 return -errno;
6ea832a2 3989
b83bc4e9
LP
3990 /* Couldn't deallocate, so let's clear it fully with
3991 * scrollback */
3992 fd = open_terminal(name, O_RDWR|O_NOCTTY|O_CLOEXEC);
6ea832a2 3993 if (fd < 0)
b83bc4e9 3994 return fd;
6ea832a2 3995
8585357a
LP
3996 loop_write(fd,
3997 "\033[r" /* clear scrolling region */
3998 "\033[H" /* move home */
3999 "\033[3J", /* clear screen including scrollback, requires Linux 2.6.40 */
4000 10, false);
b83bc4e9 4001 close_nointr_nofail(fd);
6ea832a2 4002
b83bc4e9 4003 return 0;
6ea832a2
LP
4004}
4005
51045322
LP
4006int copy_file(const char *from, const char *to, int flags) {
4007 _cleanup_close_ int fdf = -1;
4008 int r, fdt;
34ca941c
LP
4009
4010 assert(from);
4011 assert(to);
4012
4013 fdf = open(from, O_RDONLY|O_CLOEXEC|O_NOCTTY);
4014 if (fdf < 0)
4015 return -errno;
4016
51045322
LP
4017 fdt = open(to, flags|O_WRONLY|O_CREAT|O_CLOEXEC|O_NOCTTY, 0644);
4018 if (fdt < 0)
34ca941c 4019 return -errno;
34ca941c
LP
4020
4021 for (;;) {
4022 char buf[PIPE_BUF];
4023 ssize_t n, k;
4024
4025 n = read(fdf, buf, sizeof(buf));
4026 if (n < 0) {
4027 r = -errno;
4028
34ca941c
LP
4029 close_nointr(fdt);
4030 unlink(to);
4031
4032 return r;
4033 }
4034
4035 if (n == 0)
4036 break;
4037
4038 errno = 0;
4039 k = loop_write(fdt, buf, n, false);
4040 if (n != k) {
4041 r = k < 0 ? k : (errno ? -errno : -EIO);
4042
34ca941c 4043 close_nointr(fdt);
34ca941c 4044 unlink(to);
51045322 4045
34ca941c
LP
4046 return r;
4047 }
4048 }
4049
34ca941c
LP
4050 r = close_nointr(fdt);
4051
4052 if (r < 0) {
4053 unlink(to);
4054 return r;
4055 }
4056
4057 return 0;
4058}
4059
424a19f8
LP
4060int symlink_atomic(const char *from, const char *to) {
4061 char *x;
4062 _cleanup_free_ char *t;
34ca941c
LP
4063 const char *fn;
4064 size_t k;
9bf3b535 4065 uint64_t u;
34ca941c
LP
4066 unsigned i;
4067 int r;
4068
4069 assert(from);
4070 assert(to);
4071
4072 t = new(char, strlen(to) + 1 + 16 + 1);
4073 if (!t)
4074 return -ENOMEM;
4075
2b6bf07d 4076 fn = basename(to);
34ca941c
LP
4077 k = fn-to;
4078 memcpy(t, to, k);
4079 t[k] = '.';
4080 x = stpcpy(t+k+1, fn);
4081
9bf3b535 4082 u = random_u64();
34ca941c 4083 for (i = 0; i < 16; i++) {
9bf3b535
LP
4084 *(x++) = hexchar(u & 0xF);
4085 u >>= 4;
34ca941c
LP
4086 }
4087
4088 *x = 0;
4089
424a19f8
LP
4090 if (symlink(from, t) < 0)
4091 return -errno;
34ca941c
LP
4092
4093 if (rename(t, to) < 0) {
4094 r = -errno;
4095 unlink(t);
34ca941c
LP
4096 return r;
4097 }
4098
424a19f8 4099 return 0;
34ca941c
LP
4100}
4101
4d6d6518
LP
4102bool display_is_local(const char *display) {
4103 assert(display);
4104
4105 return
4106 display[0] == ':' &&
4107 display[1] >= '0' &&
4108 display[1] <= '9';
4109}
4110
4111int socket_from_display(const char *display, char **path) {
4112 size_t k;
4113 char *f, *c;
4114
4115 assert(display);
4116 assert(path);
4117
4118 if (!display_is_local(display))
4119 return -EINVAL;
4120
4121 k = strspn(display+1, "0123456789");
4122
4123 f = new(char, sizeof("/tmp/.X11-unix/X") + k);
4124 if (!f)
4125 return -ENOMEM;
4126
4127 c = stpcpy(f, "/tmp/.X11-unix/X");
4128 memcpy(c, display+1, k);
4129 c[k] = 0;
4130
4131 *path = f;
4132
4133 return 0;
4134}
4135
d05c5031
LP
4136int get_user_creds(
4137 const char **username,
4138 uid_t *uid, gid_t *gid,
4139 const char **home,
4140 const char **shell) {
4141
1cccf435 4142 struct passwd *p;
ddd88763 4143 uid_t u;
1cccf435
MV
4144
4145 assert(username);
4146 assert(*username);
1cccf435
MV
4147
4148 /* We enforce some special rules for uid=0: in order to avoid
4149 * NSS lookups for root we hardcode its data. */
4150
4151 if (streq(*username, "root") || streq(*username, "0")) {
4152 *username = "root";
4b67834e
LP
4153
4154 if (uid)
4155 *uid = 0;
4156
4157 if (gid)
4158 *gid = 0;
4159
4160 if (home)
4161 *home = "/root";
d05c5031
LP
4162
4163 if (shell)
4164 *shell = "/bin/sh";
4165
1cccf435
MV
4166 return 0;
4167 }
4168
ddd88763 4169 if (parse_uid(*username, &u) >= 0) {
1cccf435 4170 errno = 0;
ddd88763 4171 p = getpwuid(u);
1cccf435
MV
4172
4173 /* If there are multiple users with the same id, make
4174 * sure to leave $USER to the configured value instead
4175 * of the first occurrence in the database. However if
4176 * the uid was configured by a numeric uid, then let's
4177 * pick the real username from /etc/passwd. */
4178 if (p)
4179 *username = p->pw_name;
4180 } else {
4181 errno = 0;
4182 p = getpwnam(*username);
4183 }
4184
4185 if (!p)
8333c77e 4186 return errno > 0 ? -errno : -ESRCH;
1cccf435 4187
4b67834e
LP
4188 if (uid)
4189 *uid = p->pw_uid;
4190
4191 if (gid)
4192 *gid = p->pw_gid;
4193
4194 if (home)
4195 *home = p->pw_dir;
4196
d05c5031
LP
4197 if (shell)
4198 *shell = p->pw_shell;
4199
4b67834e
LP
4200 return 0;
4201}
4202
59164be4
LP
4203char* uid_to_name(uid_t uid) {
4204 struct passwd *p;
4205 char *r;
4206
4207 if (uid == 0)
4208 return strdup("root");
4209
4210 p = getpwuid(uid);
4211 if (p)
4212 return strdup(p->pw_name);
4213
4214 if (asprintf(&r, "%lu", (unsigned long) uid) < 0)
4215 return NULL;
4216
4217 return r;
4218}
4219
4468addc
LP
4220char* gid_to_name(gid_t gid) {
4221 struct group *p;
4222 char *r;
4223
4224 if (gid == 0)
4225 return strdup("root");
4226
4227 p = getgrgid(gid);
4228 if (p)
4229 return strdup(p->gr_name);
4230
4231 if (asprintf(&r, "%lu", (unsigned long) gid) < 0)
4232 return NULL;
4233
4234 return r;
4235}
4236
4b67834e
LP
4237int get_group_creds(const char **groupname, gid_t *gid) {
4238 struct group *g;
4239 gid_t id;
4240
4241 assert(groupname);
4242
4243 /* We enforce some special rules for gid=0: in order to avoid
4244 * NSS lookups for root we hardcode its data. */
4245
4246 if (streq(*groupname, "root") || streq(*groupname, "0")) {
4247 *groupname = "root";
4248
4249 if (gid)
4250 *gid = 0;
4251
4252 return 0;
4253 }
4254
4255 if (parse_gid(*groupname, &id) >= 0) {
4256 errno = 0;
4257 g = getgrgid(id);
4258
4259 if (g)
4260 *groupname = g->gr_name;
4261 } else {
4262 errno = 0;
4263 g = getgrnam(*groupname);
4264 }
4265
4266 if (!g)
8333c77e 4267 return errno > 0 ? -errno : -ESRCH;
4b67834e
LP
4268
4269 if (gid)
4270 *gid = g->gr_gid;
4271
1cccf435
MV
4272 return 0;
4273}
4274
4468addc
LP
4275int in_gid(gid_t gid) {
4276 gid_t *gids;
43673799
LP
4277 int ngroups_max, r, i;
4278
43673799
LP
4279 if (getgid() == gid)
4280 return 1;
4281
4282 if (getegid() == gid)
4283 return 1;
4284
4285 ngroups_max = sysconf(_SC_NGROUPS_MAX);
4286 assert(ngroups_max > 0);
4287
4288 gids = alloca(sizeof(gid_t) * ngroups_max);
4289
4290 r = getgroups(ngroups_max, gids);
4291 if (r < 0)
4292 return -errno;
4293
4294 for (i = 0; i < r; i++)
4295 if (gids[i] == gid)
4296 return 1;
4297
4298 return 0;
4299}
4300
4468addc
LP
4301int in_group(const char *name) {
4302 int r;
4303 gid_t gid;
4304
4305 r = get_group_creds(&name, &gid);
4306 if (r < 0)
4307 return r;
4308
4309 return in_gid(gid);
4310}
4311
8092a428 4312int glob_exists(const char *path) {
7fd1b19b 4313 _cleanup_globfree_ glob_t g = {};
8d98da3f 4314 int k;
8092a428
LP
4315
4316 assert(path);
4317
8092a428
LP
4318 errno = 0;
4319 k = glob(path, GLOB_NOSORT|GLOB_BRACE, NULL, &g);
4320
4321 if (k == GLOB_NOMATCH)
8d98da3f 4322 return 0;
8092a428 4323 else if (k == GLOB_NOSPACE)
8d98da3f 4324 return -ENOMEM;
8092a428 4325 else if (k == 0)
8d98da3f 4326 return !strv_isempty(g.gl_pathv);
8092a428 4327 else
8d98da3f
ZJS
4328 return errno ? -errno : -EIO;
4329}
8092a428 4330
8d98da3f
ZJS
4331int glob_extend(char ***strv, const char *path) {
4332 _cleanup_globfree_ glob_t g = {};
4333 int k;
4334 char **p;
4335
4336 errno = 0;
a8ccacf5 4337 k = glob(path, GLOB_NOSORT|GLOB_BRACE, NULL, &g);
8d98da3f
ZJS
4338
4339 if (k == GLOB_NOMATCH)
4340 return -ENOENT;
4341 else if (k == GLOB_NOSPACE)
4342 return -ENOMEM;
4343 else if (k != 0 || strv_isempty(g.gl_pathv))
4344 return errno ? -errno : -EIO;
4345
4346 STRV_FOREACH(p, g.gl_pathv) {
4347 k = strv_extend(strv, *p);
4348 if (k < 0)
4349 break;
4350 }
4351
4352 return k;
8092a428
LP
4353}
4354
83096483
LP
4355int dirent_ensure_type(DIR *d, struct dirent *de) {
4356 struct stat st;
4357
4358 assert(d);
4359 assert(de);
4360
4361 if (de->d_type != DT_UNKNOWN)
4362 return 0;
4363
4364 if (fstatat(dirfd(d), de->d_name, &st, AT_SYMLINK_NOFOLLOW) < 0)
4365 return -errno;
4366
4367 de->d_type =
4368 S_ISREG(st.st_mode) ? DT_REG :
4369 S_ISDIR(st.st_mode) ? DT_DIR :
4370 S_ISLNK(st.st_mode) ? DT_LNK :
4371 S_ISFIFO(st.st_mode) ? DT_FIFO :
4372 S_ISSOCK(st.st_mode) ? DT_SOCK :
4373 S_ISCHR(st.st_mode) ? DT_CHR :
4374 S_ISBLK(st.st_mode) ? DT_BLK :
4375 DT_UNKNOWN;
4376
4377 return 0;
4378}
4379
4380int in_search_path(const char *path, char **search) {
893fa014
ZJS
4381 char **i;
4382 _cleanup_free_ char *parent = NULL;
83096483
LP
4383 int r;
4384
9eb977db 4385 r = path_get_parent(path, &parent);
83096483
LP
4386 if (r < 0)
4387 return r;
4388
893fa014
ZJS
4389 STRV_FOREACH(i, search)
4390 if (path_equal(parent, *i))
4391 return 1;
83096483 4392
893fa014 4393 return 0;
83096483
LP
4394}
4395
034a2a52 4396int get_files_in_directory(const char *path, char ***list) {
893fa014
ZJS
4397 _cleanup_closedir_ DIR *d = NULL;
4398 size_t bufsize = 0, n = 0;
4399 _cleanup_strv_free_ char **l = NULL;
034a2a52
LP
4400
4401 assert(path);
d60ef526
LP
4402
4403 /* Returns all files in a directory in *list, and the number
4404 * of files as return value. If list is NULL returns only the
893fa014 4405 * number. */
034a2a52
LP
4406
4407 d = opendir(path);
8ea913b2
LP
4408 if (!d)
4409 return -errno;
4410
034a2a52 4411 for (;;) {
7d5e9c0f 4412 struct dirent *de;
034a2a52 4413
3fd11280
FW
4414 errno = 0;
4415 de = readdir(d);
4416 if (!de && errno != 0)
4417 return -errno;
034a2a52
LP
4418 if (!de)
4419 break;
4420
4421 dirent_ensure_type(d, de);
4422
4423 if (!dirent_is_file(de))
4424 continue;
4425
d60ef526 4426 if (list) {
893fa014
ZJS
4427 /* one extra slot is needed for the terminating NULL */
4428 if (!GREEDY_REALLOC(l, bufsize, n + 2))
4429 return -ENOMEM;
034a2a52 4430
893fa014
ZJS
4431 l[n] = strdup(de->d_name);
4432 if (!l[n])
4433 return -ENOMEM;
034a2a52 4434
893fa014 4435 l[++n] = NULL;
d60ef526 4436 } else
893fa014 4437 n++;
034a2a52
LP
4438 }
4439
893fa014
ZJS
4440 if (list) {
4441 *list = l;
4442 l = NULL; /* avoid freeing */
4443 }
034a2a52 4444
893fa014 4445 return n;
034a2a52
LP
4446}
4447
b7def684 4448char *strjoin(const char *x, ...) {
911a4828
LP
4449 va_list ap;
4450 size_t l;
4451 char *r, *p;
4452
4453 va_start(ap, x);
4454
4455 if (x) {
4456 l = strlen(x);
4457
4458 for (;;) {
4459 const char *t;
040f18ea 4460 size_t n;
911a4828
LP
4461
4462 t = va_arg(ap, const char *);
4463 if (!t)
4464 break;
4465
040f18ea 4466 n = strlen(t);
e98055de
LN
4467 if (n > ((size_t) -1) - l) {
4468 va_end(ap);
040f18ea 4469 return NULL;
e98055de 4470 }
040f18ea
LP
4471
4472 l += n;
911a4828
LP
4473 }
4474 } else
4475 l = 0;
4476
4477 va_end(ap);
4478
4479 r = new(char, l+1);
4480 if (!r)
4481 return NULL;
4482
4483 if (x) {
4484 p = stpcpy(r, x);
4485
4486 va_start(ap, x);
4487
4488 for (;;) {
4489 const char *t;
4490
4491 t = va_arg(ap, const char *);
4492 if (!t)
4493 break;
4494
4495 p = stpcpy(p, t);
4496 }
8ea913b2
LP
4497
4498 va_end(ap);
911a4828
LP
4499 } else
4500 r[0] = 0;
4501
4502 return r;
4503}
4504
b636465b 4505bool is_main_thread(void) {
ec202eae 4506 static thread_local int cached = 0;
b636465b
LP
4507
4508 if (_unlikely_(cached == 0))
4509 cached = getpid() == gettid() ? 1 : -1;
4510
4511 return cached > 0;
4512}
4513
94959f0f
LP
4514int block_get_whole_disk(dev_t d, dev_t *ret) {
4515 char *p, *s;
4516 int r;
4517 unsigned n, m;
4518
4519 assert(ret);
4520
4521 /* If it has a queue this is good enough for us */
4522 if (asprintf(&p, "/sys/dev/block/%u:%u/queue", major(d), minor(d)) < 0)
4523 return -ENOMEM;
4524
4525 r = access(p, F_OK);
4526 free(p);
4527
4528 if (r >= 0) {
4529 *ret = d;
4530 return 0;
4531 }
4532
4533 /* If it is a partition find the originating device */
4534 if (asprintf(&p, "/sys/dev/block/%u:%u/partition", major(d), minor(d)) < 0)
4535 return -ENOMEM;
4536
4537 r = access(p, F_OK);
4538 free(p);
4539
4540 if (r < 0)
4541 return -ENOENT;
4542
4543 /* Get parent dev_t */
4544 if (asprintf(&p, "/sys/dev/block/%u:%u/../dev", major(d), minor(d)) < 0)
4545 return -ENOMEM;
4546
4547 r = read_one_line_file(p, &s);
4548 free(p);
4549
4550 if (r < 0)
4551 return r;
4552
4553 r = sscanf(s, "%u:%u", &m, &n);
4554 free(s);
4555
4556 if (r != 2)
4557 return -EINVAL;
4558
4559 /* Only return this if it is really good enough for us. */
4560 if (asprintf(&p, "/sys/dev/block/%u:%u/queue", m, n) < 0)
4561 return -ENOMEM;
4562
4563 r = access(p, F_OK);
4564 free(p);
4565
4566 if (r >= 0) {
4567 *ret = makedev(m, n);
4568 return 0;
4569 }
4570
4571 return -ENOENT;
4572}
4573
8d53b453 4574int file_is_priv_sticky(const char *p) {
ad293f5a
LP
4575 struct stat st;
4576
4577 assert(p);
4578
4579 if (lstat(p, &st) < 0)
4580 return -errno;
4581
4582 return
8d53b453 4583 (st.st_uid == 0 || st.st_uid == getuid()) &&
ad293f5a
LP
4584 (st.st_mode & S_ISVTX);
4585}
94959f0f 4586
f41607a6
LP
4587static const char *const ioprio_class_table[] = {
4588 [IOPRIO_CLASS_NONE] = "none",
4589 [IOPRIO_CLASS_RT] = "realtime",
4590 [IOPRIO_CLASS_BE] = "best-effort",
4591 [IOPRIO_CLASS_IDLE] = "idle"
4592};
4593
f8b69d1d 4594DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(ioprio_class, int, INT_MAX);
f41607a6
LP
4595
4596static const char *const sigchld_code_table[] = {
4597 [CLD_EXITED] = "exited",
4598 [CLD_KILLED] = "killed",
4599 [CLD_DUMPED] = "dumped",
4600 [CLD_TRAPPED] = "trapped",
4601 [CLD_STOPPED] = "stopped",
4602 [CLD_CONTINUED] = "continued",
4603};
4604
4605DEFINE_STRING_TABLE_LOOKUP(sigchld_code, int);
4606
4607static const char *const log_facility_unshifted_table[LOG_NFACILITIES] = {
4608 [LOG_FAC(LOG_KERN)] = "kern",
4609 [LOG_FAC(LOG_USER)] = "user",
4610 [LOG_FAC(LOG_MAIL)] = "mail",
4611 [LOG_FAC(LOG_DAEMON)] = "daemon",
4612 [LOG_FAC(LOG_AUTH)] = "auth",
4613 [LOG_FAC(LOG_SYSLOG)] = "syslog",
4614 [LOG_FAC(LOG_LPR)] = "lpr",
4615 [LOG_FAC(LOG_NEWS)] = "news",
4616 [LOG_FAC(LOG_UUCP)] = "uucp",
4617 [LOG_FAC(LOG_CRON)] = "cron",
4618 [LOG_FAC(LOG_AUTHPRIV)] = "authpriv",
4619 [LOG_FAC(LOG_FTP)] = "ftp",
4620 [LOG_FAC(LOG_LOCAL0)] = "local0",
4621 [LOG_FAC(LOG_LOCAL1)] = "local1",
4622 [LOG_FAC(LOG_LOCAL2)] = "local2",
4623 [LOG_FAC(LOG_LOCAL3)] = "local3",
4624 [LOG_FAC(LOG_LOCAL4)] = "local4",
4625 [LOG_FAC(LOG_LOCAL5)] = "local5",
4626 [LOG_FAC(LOG_LOCAL6)] = "local6",
4627 [LOG_FAC(LOG_LOCAL7)] = "local7"
4628};
4629
f8b69d1d 4630DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(log_facility_unshifted, int, LOG_FAC(~0));
f41607a6
LP
4631
4632static const char *const log_level_table[] = {
4633 [LOG_EMERG] = "emerg",
4634 [LOG_ALERT] = "alert",
4635 [LOG_CRIT] = "crit",
4636 [LOG_ERR] = "err",
4637 [LOG_WARNING] = "warning",
4638 [LOG_NOTICE] = "notice",
4639 [LOG_INFO] = "info",
4640 [LOG_DEBUG] = "debug"
4641};
4642
f8b69d1d 4643DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(log_level, int, LOG_DEBUG);
f41607a6
LP
4644
4645static const char* const sched_policy_table[] = {
4646 [SCHED_OTHER] = "other",
4647 [SCHED_BATCH] = "batch",
4648 [SCHED_IDLE] = "idle",
4649 [SCHED_FIFO] = "fifo",
4650 [SCHED_RR] = "rr"
4651};
4652
f8b69d1d 4653DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(sched_policy, int, INT_MAX);
f41607a6
LP
4654
4655static const char* const rlimit_table[] = {
4656 [RLIMIT_CPU] = "LimitCPU",
4657 [RLIMIT_FSIZE] = "LimitFSIZE",
4658 [RLIMIT_DATA] = "LimitDATA",
4659 [RLIMIT_STACK] = "LimitSTACK",
4660 [RLIMIT_CORE] = "LimitCORE",
4661 [RLIMIT_RSS] = "LimitRSS",
4662 [RLIMIT_NOFILE] = "LimitNOFILE",
4663 [RLIMIT_AS] = "LimitAS",
4664 [RLIMIT_NPROC] = "LimitNPROC",
4665 [RLIMIT_MEMLOCK] = "LimitMEMLOCK",
4666 [RLIMIT_LOCKS] = "LimitLOCKS",
4667 [RLIMIT_SIGPENDING] = "LimitSIGPENDING",
4668 [RLIMIT_MSGQUEUE] = "LimitMSGQUEUE",
4669 [RLIMIT_NICE] = "LimitNICE",
4670 [RLIMIT_RTPRIO] = "LimitRTPRIO",
4671 [RLIMIT_RTTIME] = "LimitRTTIME"
4672};
4673
4674DEFINE_STRING_TABLE_LOOKUP(rlimit, int);
4675
4676static const char* const ip_tos_table[] = {
4677 [IPTOS_LOWDELAY] = "low-delay",
4678 [IPTOS_THROUGHPUT] = "throughput",
4679 [IPTOS_RELIABILITY] = "reliability",
4680 [IPTOS_LOWCOST] = "low-cost",
4681};
4682
f8b69d1d 4683DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(ip_tos, int, 0xff);
f41607a6 4684
4e240ab0 4685static const char *const __signal_table[] = {
f41607a6
LP
4686 [SIGHUP] = "HUP",
4687 [SIGINT] = "INT",
4688 [SIGQUIT] = "QUIT",
4689 [SIGILL] = "ILL",
4690 [SIGTRAP] = "TRAP",
4691 [SIGABRT] = "ABRT",
4692 [SIGBUS] = "BUS",
4693 [SIGFPE] = "FPE",
4694 [SIGKILL] = "KILL",
4695 [SIGUSR1] = "USR1",
4696 [SIGSEGV] = "SEGV",
4697 [SIGUSR2] = "USR2",
4698 [SIGPIPE] = "PIPE",
4699 [SIGALRM] = "ALRM",
4700 [SIGTERM] = "TERM",
4701#ifdef SIGSTKFLT
4702 [SIGSTKFLT] = "STKFLT", /* Linux on SPARC doesn't know SIGSTKFLT */
4703#endif
4704 [SIGCHLD] = "CHLD",
4705 [SIGCONT] = "CONT",
4706 [SIGSTOP] = "STOP",
4707 [SIGTSTP] = "TSTP",
4708 [SIGTTIN] = "TTIN",
4709 [SIGTTOU] = "TTOU",
4710 [SIGURG] = "URG",
4711 [SIGXCPU] = "XCPU",
4712 [SIGXFSZ] = "XFSZ",
4713 [SIGVTALRM] = "VTALRM",
4714 [SIGPROF] = "PROF",
4715 [SIGWINCH] = "WINCH",
4716 [SIGIO] = "IO",
4717 [SIGPWR] = "PWR",
4718 [SIGSYS] = "SYS"
4719};
4720
4e240ab0
MS
4721DEFINE_PRIVATE_STRING_TABLE_LOOKUP(__signal, int);
4722
4723const char *signal_to_string(int signo) {
ec202eae 4724 static thread_local char buf[sizeof("RTMIN+")-1 + DECIMAL_STR_MAX(int) + 1];
4e240ab0
MS
4725 const char *name;
4726
4727 name = __signal_to_string(signo);
4728 if (name)
4729 return name;
4730
4731 if (signo >= SIGRTMIN && signo <= SIGRTMAX)
fa70beaa 4732 snprintf(buf, sizeof(buf), "RTMIN+%d", signo - SIGRTMIN);
4e240ab0 4733 else
fa70beaa
LP
4734 snprintf(buf, sizeof(buf), "%d", signo);
4735
4e240ab0
MS
4736 return buf;
4737}
4738
4739int signal_from_string(const char *s) {
4740 int signo;
4741 int offset = 0;
4742 unsigned u;
4743
040f18ea 4744 signo = __signal_from_string(s);
4e240ab0
MS
4745 if (signo > 0)
4746 return signo;
4747
4748 if (startswith(s, "RTMIN+")) {
4749 s += 6;
4750 offset = SIGRTMIN;
4751 }
4752 if (safe_atou(s, &u) >= 0) {
4753 signo = (int) u + offset;
4754 if (signo > 0 && signo < _NSIG)
4755 return signo;
4756 }
4757 return -1;
4758}
65457142
FC
4759
4760bool kexec_loaded(void) {
4761 bool loaded = false;
4762 char *s;
4763
4764 if (read_one_line_file("/sys/kernel/kexec_loaded", &s) >= 0) {
4765 if (s[0] == '1')
4766 loaded = true;
4767 free(s);
4768 }
4769 return loaded;
4770}
fb9de93d
LP
4771
4772int strdup_or_null(const char *a, char **b) {
4773 char *c;
4774
4775 assert(b);
4776
4777 if (!a) {
4778 *b = NULL;
4779 return 0;
4780 }
4781
4782 c = strdup(a);
4783 if (!c)
4784 return -ENOMEM;
4785
4786 *b = c;
4787 return 0;
4788}
64685e0c 4789
87d2c1ff
LP
4790int prot_from_flags(int flags) {
4791
4792 switch (flags & O_ACCMODE) {
4793
4794 case O_RDONLY:
4795 return PROT_READ;
4796
4797 case O_WRONLY:
4798 return PROT_WRITE;
4799
4800 case O_RDWR:
4801 return PROT_READ|PROT_WRITE;
4802
4803 default:
4804 return -EINVAL;
4805 }
7c99e0c1 4806}
689b9a22 4807
babfc091 4808char *format_bytes(char *buf, size_t l, off_t t) {
c0f99c21 4809 unsigned i;
babfc091
LP
4810
4811 static const struct {
4812 const char *suffix;
4813 off_t factor;
4814 } table[] = {
32895bb3
LP
4815 { "E", 1024ULL*1024ULL*1024ULL*1024ULL*1024ULL*1024ULL },
4816 { "P", 1024ULL*1024ULL*1024ULL*1024ULL*1024ULL },
babfc091
LP
4817 { "T", 1024ULL*1024ULL*1024ULL*1024ULL },
4818 { "G", 1024ULL*1024ULL*1024ULL },
4819 { "M", 1024ULL*1024ULL },
4820 { "K", 1024ULL },
4821 };
4822
4823 for (i = 0; i < ELEMENTSOF(table); i++) {
4824
4825 if (t >= table[i].factor) {
4826 snprintf(buf, l,
4827 "%llu.%llu%s",
4828 (unsigned long long) (t / table[i].factor),
4829 (unsigned long long) (((t*10ULL) / table[i].factor) % 10ULL),
4830 table[i].suffix);
4831
4832 goto finish;
4833 }
4834 }
4835
4836 snprintf(buf, l, "%lluB", (unsigned long long) t);
4837
4838finish:
4839 buf[l-1] = 0;
4840 return buf;
4841
4842}
55d7bfc1
LP
4843
4844void* memdup(const void *p, size_t l) {
4845 void *r;
4846
4847 assert(p);
4848
4849 r = malloc(l);
4850 if (!r)
4851 return NULL;
4852
4853 memcpy(r, p, l);
4854 return r;
4855}
bb99a35a
LP
4856
4857int fd_inc_sndbuf(int fd, size_t n) {
4858 int r, value;
4859 socklen_t l = sizeof(value);
4860
4861 r = getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &value, &l);
92d75ca4 4862 if (r >= 0 && l == sizeof(value) && (size_t) value >= n*2)
bb99a35a
LP
4863 return 0;
4864
92d75ca4
LP
4865 /* If we have the privileges we will ignore the kernel limit. */
4866
bb99a35a 4867 value = (int) n;
92d75ca4
LP
4868 if (setsockopt(fd, SOL_SOCKET, SO_SNDBUFFORCE, &value, sizeof(value)) < 0)
4869 if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &value, sizeof(value)) < 0)
4870 return -errno;
bb99a35a
LP
4871
4872 return 1;
4873}
4874
4875int fd_inc_rcvbuf(int fd, size_t n) {
4876 int r, value;
4877 socklen_t l = sizeof(value);
4878
4879 r = getsockopt(fd, SOL_SOCKET, SO_RCVBUF, &value, &l);
92d75ca4 4880 if (r >= 0 && l == sizeof(value) && (size_t) value >= n*2)
bb99a35a
LP
4881 return 0;
4882
92d75ca4 4883 /* If we have the privileges we will ignore the kernel limit. */
bb99a35a 4884
92d75ca4
LP
4885 value = (int) n;
4886 if (setsockopt(fd, SOL_SOCKET, SO_RCVBUFFORCE, &value, sizeof(value)) < 0)
4887 if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &value, sizeof(value)) < 0)
4888 return -errno;
bb99a35a
LP
4889 return 1;
4890}
6bb92a16 4891
9bdc770c 4892int fork_agent(pid_t *pid, const int except[], unsigned n_except, const char *path, ...) {
6bb92a16
LP
4893 pid_t parent_pid, agent_pid;
4894 int fd;
4895 bool stdout_is_tty, stderr_is_tty;
4896 unsigned n, i;
4897 va_list ap;
4898 char **l;
4899
4900 assert(pid);
4901 assert(path);
4902
4903 parent_pid = getpid();
4904
4905 /* Spawns a temporary TTY agent, making sure it goes away when
4906 * we go away */
4907
4908 agent_pid = fork();
4909 if (agent_pid < 0)
4910 return -errno;
4911
4912 if (agent_pid != 0) {
4913 *pid = agent_pid;
4914 return 0;
4915 }
4916
4917 /* In the child:
4918 *
4919 * Make sure the agent goes away when the parent dies */
4920 if (prctl(PR_SET_PDEATHSIG, SIGTERM) < 0)
4921 _exit(EXIT_FAILURE);
4922
4923 /* Check whether our parent died before we were able
4924 * to set the death signal */
4925 if (getppid() != parent_pid)
4926 _exit(EXIT_SUCCESS);
4927
4928 /* Don't leak fds to the agent */
9bdc770c 4929 close_all_fds(except, n_except);
6bb92a16
LP
4930
4931 stdout_is_tty = isatty(STDOUT_FILENO);
4932 stderr_is_tty = isatty(STDERR_FILENO);
4933
4934 if (!stdout_is_tty || !stderr_is_tty) {
4935 /* Detach from stdout/stderr. and reopen
4936 * /dev/tty for them. This is important to
4937 * ensure that when systemctl is started via
4938 * popen() or a similar call that expects to
4939 * read EOF we actually do generate EOF and
4940 * not delay this indefinitely by because we
4941 * keep an unused copy of stdin around. */
4942 fd = open("/dev/tty", O_WRONLY);
4943 if (fd < 0) {
4944 log_error("Failed to open /dev/tty: %m");
4945 _exit(EXIT_FAILURE);
4946 }
4947
4948 if (!stdout_is_tty)
4949 dup2(fd, STDOUT_FILENO);
4950
4951 if (!stderr_is_tty)
4952 dup2(fd, STDERR_FILENO);
4953
4954 if (fd > 2)
4955 close(fd);
4956 }
4957
4958 /* Count arguments */
4959 va_start(ap, path);
4960 for (n = 0; va_arg(ap, char*); n++)
4961 ;
4962 va_end(ap);
4963
4964 /* Allocate strv */
4965 l = alloca(sizeof(char *) * (n + 1));
4966
4967 /* Fill in arguments */
4968 va_start(ap, path);
4969 for (i = 0; i <= n; i++)
4970 l[i] = va_arg(ap, char*);
4971 va_end(ap);
4972
4973 execv(path, l);
4974 _exit(EXIT_FAILURE);
4975}
68faf98c
LP
4976
4977int setrlimit_closest(int resource, const struct rlimit *rlim) {
4978 struct rlimit highest, fixed;
4979
4980 assert(rlim);
4981
4982 if (setrlimit(resource, rlim) >= 0)
4983 return 0;
4984
4985 if (errno != EPERM)
4986 return -errno;
4987
4988 /* So we failed to set the desired setrlimit, then let's try
4989 * to get as close as we can */
4990 assert_se(getrlimit(resource, &highest) == 0);
4991
4992 fixed.rlim_cur = MIN(rlim->rlim_cur, highest.rlim_max);
4993 fixed.rlim_max = MIN(rlim->rlim_max, highest.rlim_max);
4994
4995 if (setrlimit(resource, &fixed) < 0)
4996 return -errno;
4997
4998 return 0;
4999}
3d9a4122 5000
ab94af92 5001int getenv_for_pid(pid_t pid, const char *field, char **_value) {
49aa47c7
LP
5002 _cleanup_fclose_ FILE *f = NULL;
5003 char *value = NULL;
ab94af92 5004 int r;
ab94af92
LP
5005 bool done = false;
5006 size_t l;
49aa47c7 5007 const char *path;
ab94af92 5008
49aa47c7 5009 assert(pid >= 0);
ab94af92
LP
5010 assert(field);
5011 assert(_value);
5012
b68fa010 5013 path = procfs_file_alloca(pid, "environ");
ab94af92
LP
5014
5015 f = fopen(path, "re");
5016 if (!f)
5017 return -errno;
5018
5019 l = strlen(field);
5020 r = 0;
5021
5022 do {
5023 char line[LINE_MAX];
5024 unsigned i;
5025
5026 for (i = 0; i < sizeof(line)-1; i++) {
5027 int c;
5028
5029 c = getc(f);
5030 if (_unlikely_(c == EOF)) {
5031 done = true;
5032 break;
5033 } else if (c == 0)
5034 break;
5035
5036 line[i] = c;
5037 }
5038 line[i] = 0;
5039
5040 if (memcmp(line, field, l) == 0 && line[l] == '=') {
5041 value = strdup(line + l + 1);
49aa47c7
LP
5042 if (!value)
5043 return -ENOMEM;
ab94af92
LP
5044
5045 r = 1;
5046 break;
5047 }
5048
5049 } while (!done);
5050
49aa47c7 5051 *_value = value;
ab94af92
LP
5052 return r;
5053}
d889a206 5054
49dbfa7b
LP
5055bool is_valid_documentation_url(const char *url) {
5056 assert(url);
5057
5058 if (startswith(url, "http://") && url[7])
5059 return true;
5060
5061 if (startswith(url, "https://") && url[8])
5062 return true;
5063
5064 if (startswith(url, "file:") && url[5])
5065 return true;
5066
5067 if (startswith(url, "info:") && url[5])
5068 return true;
5069
5070 if (startswith(url, "man:") && url[4])
5071 return true;
5072
5073 return false;
5074}
9be346c9
HH
5075
5076bool in_initrd(void) {
73020ab2 5077 static int saved = -1;
825c6fe5 5078 struct statfs s;
8f33b5b8 5079
825c6fe5
LP
5080 if (saved >= 0)
5081 return saved;
5082
5083 /* We make two checks here:
5084 *
5085 * 1. the flag file /etc/initrd-release must exist
5086 * 2. the root file system must be a memory file system
5087 *
5088 * The second check is extra paranoia, since misdetecting an
5089 * initrd can have bad bad consequences due the initrd
5090 * emptying when transititioning to the main systemd.
5091 */
5092
5093 saved = access("/etc/initrd-release", F_OK) >= 0 &&
5094 statfs("/", &s) >= 0 &&
943aad8c 5095 is_temporary_fs(&s);
9be346c9 5096
8f33b5b8 5097 return saved;
9be346c9 5098}
069cfc85
LP
5099
5100void warn_melody(void) {
e67f47e5 5101 _cleanup_close_ int fd = -1;
069cfc85
LP
5102
5103 fd = open("/dev/console", O_WRONLY|O_CLOEXEC|O_NOCTTY);
5104 if (fd < 0)
5105 return;
5106
040f18ea 5107 /* Yeah, this is synchronous. Kinda sucks. But well... */
069cfc85
LP
5108
5109 ioctl(fd, KIOCSOUND, (int)(1193180/440));
5110 usleep(125*USEC_PER_MSEC);
5111
5112 ioctl(fd, KIOCSOUND, (int)(1193180/220));
5113 usleep(125*USEC_PER_MSEC);
5114
5115 ioctl(fd, KIOCSOUND, (int)(1193180/220));
5116 usleep(125*USEC_PER_MSEC);
5117
5118 ioctl(fd, KIOCSOUND, 0);
069cfc85 5119}
cd3bd60a
LP
5120
5121int make_console_stdio(void) {
5122 int fd, r;
5123
5124 /* Make /dev/console the controlling terminal and stdin/stdout/stderr */
5125
5126 fd = acquire_terminal("/dev/console", false, true, true, (usec_t) -1);
5127 if (fd < 0) {
5128 log_error("Failed to acquire terminal: %s", strerror(-fd));
5129 return fd;
5130 }
5131
5132 r = make_stdio(fd);
5133 if (r < 0) {
5134 log_error("Failed to duplicate terminal fd: %s", strerror(-r));
5135 return r;
5136 }
5137
5138 return 0;
5139}
7c5f152a
LP
5140
5141int get_home_dir(char **_h) {
2cfbd749 5142 struct passwd *p;
7c5f152a 5143 const char *e;
2cfbd749 5144 char *h;
7c5f152a 5145 uid_t u;
7c5f152a
LP
5146
5147 assert(_h);
5148
5149 /* Take the user specified one */
5150 e = getenv("HOME");
5151 if (e) {
5152 h = strdup(e);
5153 if (!h)
5154 return -ENOMEM;
5155
5156 *_h = h;
5157 return 0;
5158 }
5159
5160 /* Hardcode home directory for root to avoid NSS */
5161 u = getuid();
5162 if (u == 0) {
5163 h = strdup("/root");
5164 if (!h)
5165 return -ENOMEM;
5166
5167 *_h = h;
5168 return 0;
5169 }
5170
5171 /* Check the database... */
5172 errno = 0;
5173 p = getpwuid(u);
5174 if (!p)
bcb161b0 5175 return errno > 0 ? -errno : -ESRCH;
7c5f152a
LP
5176
5177 if (!path_is_absolute(p->pw_dir))
5178 return -EINVAL;
5179
5180 h = strdup(p->pw_dir);
5181 if (!h)
5182 return -ENOMEM;
5183
5184 *_h = h;
5185 return 0;
5186}
5187
2cfbd749
LP
5188int get_shell(char **_s) {
5189 struct passwd *p;
5190 const char *e;
5191 char *s;
5192 uid_t u;
5193
5194 assert(_s);
5195
5196 /* Take the user specified one */
5197 e = getenv("SHELL");
5198 if (e) {
5199 s = strdup(e);
5200 if (!s)
5201 return -ENOMEM;
5202
5203 *_s = s;
5204 return 0;
5205 }
5206
5207 /* Hardcode home directory for root to avoid NSS */
5208 u = getuid();
5209 if (u == 0) {
5210 s = strdup("/bin/sh");
5211 if (!s)
5212 return -ENOMEM;
5213
5214 *_s = s;
5215 return 0;
5216 }
5217
5218 /* Check the database... */
5219 errno = 0;
5220 p = getpwuid(u);
5221 if (!p)
5222 return errno > 0 ? -errno : -ESRCH;
5223
5224 if (!path_is_absolute(p->pw_shell))
5225 return -EINVAL;
5226
5227 s = strdup(p->pw_shell);
5228 if (!s)
5229 return -ENOMEM;
5230
5231 *_s = s;
5232 return 0;
5233}
5234
0b507b17
LP
5235bool filename_is_safe(const char *p) {
5236
5237 if (isempty(p))
5238 return false;
5239
5240 if (strchr(p, '/'))
5241 return false;
5242
5243 if (streq(p, "."))
5244 return false;
5245
5246 if (streq(p, ".."))
5247 return false;
5248
5249 if (strlen(p) > FILENAME_MAX)
5250 return false;
5251
5252 return true;
5253}
5254
5255bool string_is_safe(const char *p) {
5256 const char *t;
5257
5258 assert(p);
5259
5260 for (t = p; *t; t++) {
01539d6e 5261 if (*t > 0 && *t < ' ')
0b507b17
LP
5262 return false;
5263
011afa76 5264 if (strchr("\\\"\'", *t))
0b507b17
LP
5265 return false;
5266 }
5267
5268 return true;
5269}
cfbc22ab 5270
ac4c8d6d
ZJS
5271/**
5272 * Check if a string contains control characters.
5273 * Spaces and tabs are not considered control characters.
5274 */
4d1a6904
LP
5275bool string_has_cc(const char *p) {
5276 const char *t;
5277
5278 assert(p);
5279
5280 for (t = p; *t; t++)
da2620a5 5281 if (*t > 0 && *t < ' ' && *t != '\t')
4d1a6904
LP
5282 return true;
5283
5284 return false;
5285}
5286
e884315e
LP
5287bool path_is_safe(const char *p) {
5288
5289 if (isempty(p))
5290 return false;
5291
5292 if (streq(p, "..") || startswith(p, "../") || endswith(p, "/..") || strstr(p, "/../"))
5293 return false;
5294
5295 if (strlen(p) > PATH_MAX)
5296 return false;
5297
5298 /* The following two checks are not really dangerous, but hey, they still are confusing */
5299 if (streq(p, ".") || startswith(p, "./") || endswith(p, "/.") || strstr(p, "/./"))
5300 return false;
5301
5302 if (strstr(p, "//"))
5303 return false;
5304
5305 return true;
5306}
5307
a9e12476
KS
5308/* hey glibc, APIs with callbacks without a user pointer are so useless */
5309void *xbsearch_r(const void *key, const void *base, size_t nmemb, size_t size,
1c574591 5310 int (*compar) (const void *, const void *, void *), void *arg) {
a9e12476
KS
5311 size_t l, u, idx;
5312 const void *p;
5313 int comparison;
5314
5315 l = 0;
5316 u = nmemb;
5317 while (l < u) {
5318 idx = (l + u) / 2;
5319 p = (void *)(((const char *) base) + (idx * size));
5320 comparison = compar(key, p, arg);
5321 if (comparison < 0)
5322 u = idx;
5323 else if (comparison > 0)
5324 l = idx + 1;
5325 else
5326 return (void *)p;
5327 }
5328 return NULL;
5329}
09017585
MS
5330
5331bool is_locale_utf8(void) {
5332 const char *set;
5333 static int cached_answer = -1;
5334
5335 if (cached_answer >= 0)
5336 goto out;
5337
5338 if (!setlocale(LC_ALL, "")) {
5339 cached_answer = true;
5340 goto out;
5341 }
5342
5343 set = nl_langinfo(CODESET);
5344 if (!set) {
5345 cached_answer = true;
5346 goto out;
5347 }
5348
f168c273 5349 if (streq(set, "UTF-8")) {
fee79e01
HH
5350 cached_answer = true;
5351 goto out;
5352 }
5353
6cf2f1d9
HH
5354 /* For LC_CTYPE=="C" return true, because CTYPE is effectly
5355 * unset and everything can do to UTF-8 nowadays. */
fee79e01
HH
5356 set = setlocale(LC_CTYPE, NULL);
5357 if (!set) {
5358 cached_answer = true;
5359 goto out;
5360 }
5361
6cf2f1d9
HH
5362 /* Check result, but ignore the result if C was set
5363 * explicitly. */
5364 cached_answer =
5365 streq(set, "C") &&
5366 !getenv("LC_ALL") &&
5367 !getenv("LC_CTYPE") &&
5368 !getenv("LANG");
fee79e01 5369
09017585 5370out:
6cf2f1d9 5371 return (bool) cached_answer;
09017585 5372}
c339d977
MS
5373
5374const char *draw_special_char(DrawSpecialChar ch) {
5375 static const char *draw_table[2][_DRAW_SPECIAL_CHAR_MAX] = {
5376 /* UTF-8 */ {
45a5ff0d
MS
5377 [DRAW_TREE_VERT] = "\342\224\202 ", /* │ */
5378 [DRAW_TREE_BRANCH] = "\342\224\234\342\224\200", /* ├─ */
5379 [DRAW_TREE_RIGHT] = "\342\224\224\342\224\200", /* └─ */
55c0b89c 5380 [DRAW_TREE_SPACE] = " ", /* */
45a5ff0d 5381 [DRAW_TRIANGULAR_BULLET] = "\342\200\243 ", /* ‣ */
3deadb91 5382 [DRAW_BLACK_CIRCLE] = "\342\227\217 ", /* ● */
c339d977
MS
5383 },
5384 /* ASCII fallback */ {
45a5ff0d
MS
5385 [DRAW_TREE_VERT] = "| ",
5386 [DRAW_TREE_BRANCH] = "|-",
5387 [DRAW_TREE_RIGHT] = "`-",
55c0b89c 5388 [DRAW_TREE_SPACE] = " ",
45a5ff0d 5389 [DRAW_TRIANGULAR_BULLET] = "> ",
3deadb91 5390 [DRAW_BLACK_CIRCLE] = "* ",
c339d977
MS
5391 }
5392 };
5393
5394 return draw_table[!is_locale_utf8()][ch];
5395}
409bc9c3
LP
5396
5397char *strreplace(const char *text, const char *old_string, const char *new_string) {
5398 const char *f;
5399 char *t, *r;
5400 size_t l, old_len, new_len;
5401
5402 assert(text);
5403 assert(old_string);
5404 assert(new_string);
5405
5406 old_len = strlen(old_string);
5407 new_len = strlen(new_string);
5408
5409 l = strlen(text);
5410 r = new(char, l+1);
5411 if (!r)
5412 return NULL;
5413
5414 f = text;
5415 t = r;
5416 while (*f) {
5417 char *a;
5418 size_t d, nl;
5419
5420 if (!startswith(f, old_string)) {
5421 *(t++) = *(f++);
5422 continue;
5423 }
5424
5425 d = t - r;
5426 nl = l - old_len + new_len;
5427 a = realloc(r, nl + 1);
5428 if (!a)
5429 goto oom;
5430
5431 l = nl;
5432 r = a;
5433 t = r + d;
5434
5435 t = stpcpy(t, new_string);
5436 f += old_len;
5437 }
5438
5439 *t = 0;
5440 return r;
5441
5442oom:
5443 free(r);
5444 return NULL;
5445}
e8bc0ea2
LP
5446
5447char *strip_tab_ansi(char **ibuf, size_t *_isz) {
660ddc72 5448 const char *i, *begin = NULL;
e8bc0ea2
LP
5449 enum {
5450 STATE_OTHER,
5451 STATE_ESCAPE,
5452 STATE_BRACKET
5453 } state = STATE_OTHER;
5454 char *obuf = NULL;
5455 size_t osz = 0, isz;
5456 FILE *f;
5457
5458 assert(ibuf);
5459 assert(*ibuf);
5460
5461 /* Strips ANSI color and replaces TABs by 8 spaces */
5462
5463 isz = _isz ? *_isz : strlen(*ibuf);
5464
5465 f = open_memstream(&obuf, &osz);
5466 if (!f)
5467 return NULL;
5468
5469 for (i = *ibuf; i < *ibuf + isz + 1; i++) {
5470
5471 switch (state) {
5472
5473 case STATE_OTHER:
5474 if (i >= *ibuf + isz) /* EOT */
5475 break;
5476 else if (*i == '\x1B')
5477 state = STATE_ESCAPE;
5478 else if (*i == '\t')
5479 fputs(" ", f);
5480 else
5481 fputc(*i, f);
5482 break;
5483
5484 case STATE_ESCAPE:
5485 if (i >= *ibuf + isz) { /* EOT */
5486 fputc('\x1B', f);
5487 break;
5488 } else if (*i == '[') {
5489 state = STATE_BRACKET;
5490 begin = i + 1;
5491 } else {
5492 fputc('\x1B', f);
5493 fputc(*i, f);
5494 state = STATE_OTHER;
5495 }
5496
5497 break;
5498
5499 case STATE_BRACKET:
5500
5501 if (i >= *ibuf + isz || /* EOT */
5502 (!(*i >= '0' && *i <= '9') && *i != ';' && *i != 'm')) {
5503 fputc('\x1B', f);
5504 fputc('[', f);
5505 state = STATE_OTHER;
5506 i = begin-1;
5507 } else if (*i == 'm')
5508 state = STATE_OTHER;
5509 break;
5510 }
5511 }
5512
5513 if (ferror(f)) {
5514 fclose(f);
5515 free(obuf);
5516 return NULL;
5517 }
5518
5519 fclose(f);
5520
5521 free(*ibuf);
5522 *ibuf = obuf;
5523
5524 if (_isz)
5525 *_isz = osz;
5526
5527 return obuf;
5528}
240dbaa4
LP
5529
5530int on_ac_power(void) {
5531 bool found_offline = false, found_online = false;
5532 _cleanup_closedir_ DIR *d = NULL;
5533
5534 d = opendir("/sys/class/power_supply");
5535 if (!d)
5536 return -errno;
5537
5538 for (;;) {
5539 struct dirent *de;
240dbaa4
LP
5540 _cleanup_close_ int fd = -1, device = -1;
5541 char contents[6];
5542 ssize_t n;
240dbaa4 5543
3fd11280
FW
5544 errno = 0;
5545 de = readdir(d);
5546 if (!de && errno != 0)
5547 return -errno;
240dbaa4
LP
5548
5549 if (!de)
5550 break;
5551
5552 if (ignore_file(de->d_name))
5553 continue;
5554
5555 device = openat(dirfd(d), de->d_name, O_DIRECTORY|O_RDONLY|O_CLOEXEC|O_NOCTTY);
5556 if (device < 0) {
5557 if (errno == ENOENT || errno == ENOTDIR)
5558 continue;
5559
5560 return -errno;
5561 }
5562
5563 fd = openat(device, "type", O_RDONLY|O_CLOEXEC|O_NOCTTY);
5564 if (fd < 0) {
5565 if (errno == ENOENT)
5566 continue;
5567
5568 return -errno;
5569 }
5570
5571 n = read(fd, contents, sizeof(contents));
5572 if (n < 0)
5573 return -errno;
5574
5575 if (n != 6 || memcmp(contents, "Mains\n", 6))
5576 continue;
5577
5578 close_nointr_nofail(fd);
5579 fd = openat(device, "online", O_RDONLY|O_CLOEXEC|O_NOCTTY);
5580 if (fd < 0) {
5581 if (errno == ENOENT)
5582 continue;
5583
5584 return -errno;
5585 }
5586
5587 n = read(fd, contents, sizeof(contents));
5588 if (n < 0)
5589 return -errno;
5590
5591 if (n != 2 || contents[1] != '\n')
5592 return -EIO;
5593
5594 if (contents[0] == '1') {
5595 found_online = true;
5596 break;
5597 } else if (contents[0] == '0')
5598 found_offline = true;
5599 else
5600 return -EIO;
5601 }
5602
5603 return found_online || !found_offline;
5604}
fabe5c0e
LP
5605
5606static int search_and_fopen_internal(const char *path, const char *mode, char **search, FILE **_f) {
5607 char **i;
5608
5609 assert(path);
5610 assert(mode);
5611 assert(_f);
5612
112cfb18 5613 if (!path_strv_canonicalize_absolute_uniq(search, NULL))
fabe5c0e
LP
5614 return -ENOMEM;
5615
5616 STRV_FOREACH(i, search) {
5617 _cleanup_free_ char *p = NULL;
5618 FILE *f;
5619
5620 p = strjoin(*i, "/", path, NULL);
5621 if (!p)
5622 return -ENOMEM;
5623
5624 f = fopen(p, mode);
5625 if (f) {
5626 *_f = f;
5627 return 0;
5628 }
5629
5630 if (errno != ENOENT)
5631 return -errno;
5632 }
5633
5634 return -ENOENT;
5635}
5636
5637int search_and_fopen(const char *path, const char *mode, const char **search, FILE **_f) {
5638 _cleanup_strv_free_ char **copy = NULL;
5639
5640 assert(path);
5641 assert(mode);
5642 assert(_f);
5643
5644 if (path_is_absolute(path)) {
5645 FILE *f;
5646
5647 f = fopen(path, mode);
5648 if (f) {
5649 *_f = f;
5650 return 0;
5651 }
5652
5653 return -errno;
5654 }
5655
5656 copy = strv_copy((char**) search);
5657 if (!copy)
5658 return -ENOMEM;
5659
5660 return search_and_fopen_internal(path, mode, copy, _f);
5661}
5662
5663int search_and_fopen_nulstr(const char *path, const char *mode, const char *search, FILE **_f) {
5664 _cleanup_strv_free_ char **s = NULL;
5665
5666 if (path_is_absolute(path)) {
5667 FILE *f;
5668
5669 f = fopen(path, mode);
5670 if (f) {
5671 *_f = f;
5672 return 0;
5673 }
5674
5675 return -errno;
5676 }
5677
5678 s = strv_split_nulstr(search);
5679 if (!s)
5680 return -ENOMEM;
5681
5682 return search_and_fopen_internal(path, mode, s, _f);
5683}
c17ec25e 5684
66e35261
LP
5685char *strextend(char **x, ...) {
5686 va_list ap;
5687 size_t f, l;
5688 char *r, *p;
5689
5690 assert(x);
5691
5692 l = f = *x ? strlen(*x) : 0;
5693
5694 va_start(ap, x);
5695 for (;;) {
5696 const char *t;
5697 size_t n;
5698
5699 t = va_arg(ap, const char *);
5700 if (!t)
5701 break;
5702
5703 n = strlen(t);
5704 if (n > ((size_t) -1) - l) {
5705 va_end(ap);
5706 return NULL;
5707 }
5708
5709 l += n;
5710 }
5711 va_end(ap);
5712
5713 r = realloc(*x, l+1);
5714 if (!r)
5715 return NULL;
5716
5717 p = r + f;
5718
5719 va_start(ap, x);
5720 for (;;) {
5721 const char *t;
5722
5723 t = va_arg(ap, const char *);
5724 if (!t)
5725 break;
5726
5727 p = stpcpy(p, t);
5728 }
5729 va_end(ap);
5730
5731 *p = 0;
5732 *x = r;
5733
5734 return r + l;
5735}
9a17484d
LP
5736
5737char *strrep(const char *s, unsigned n) {
5738 size_t l;
5739 char *r, *p;
5740 unsigned i;
5741
5742 assert(s);
5743
5744 l = strlen(s);
5745 p = r = malloc(l * n + 1);
5746 if (!r)
5747 return NULL;
5748
5749 for (i = 0; i < n; i++)
5750 p = stpcpy(p, s);
5751
5752 *p = 0;
5753 return r;
5754}
392d5b37
LP
5755
5756void* greedy_realloc(void **p, size_t *allocated, size_t need) {
5757 size_t a;
5758 void *q;
5759
98088803 5760 assert(p);
e93c33d4
SL
5761 assert(allocated);
5762
392d5b37
LP
5763 if (*allocated >= need)
5764 return *p;
5765
9607d947 5766 a = MAX(64u, need * 2);
98088803
LP
5767
5768 /* check for overflows */
5769 if (a < need)
5770 return NULL;
5771
392d5b37
LP
5772 q = realloc(*p, a);
5773 if (!q)
5774 return NULL;
5775
5776 *p = q;
5777 *allocated = a;
5778 return q;
5779}
aa96c6cb 5780
4545a231 5781void* greedy_realloc0(void **p, size_t *allocated, size_t need) {
98088803 5782 size_t prev;
4545a231
DH
5783 uint8_t *q;
5784
98088803
LP
5785 assert(p);
5786 assert(allocated);
5787
5788 prev = *allocated;
5789
4545a231
DH
5790 q = greedy_realloc(p, allocated, need);
5791 if (!q)
5792 return NULL;
5793
5794 if (*allocated > prev)
29804cc1 5795 memzero(&q[prev], *allocated - prev);
4545a231
DH
5796
5797 return q;
5798}
5799
aa96c6cb
LP
5800bool id128_is_valid(const char *s) {
5801 size_t i, l;
5802
5803 l = strlen(s);
5804 if (l == 32) {
5805
5806 /* Simple formatted 128bit hex string */
5807
5808 for (i = 0; i < l; i++) {
5809 char c = s[i];
5810
5811 if (!(c >= '0' && c <= '9') &&
5812 !(c >= 'a' && c <= 'z') &&
5813 !(c >= 'A' && c <= 'Z'))
5814 return false;
5815 }
5816
5817 } else if (l == 36) {
5818
5819 /* Formatted UUID */
5820
5821 for (i = 0; i < l; i++) {
5822 char c = s[i];
5823
5824 if ((i == 8 || i == 13 || i == 18 || i == 23)) {
5825 if (c != '-')
5826 return false;
5827 } else {
5828 if (!(c >= '0' && c <= '9') &&
5829 !(c >= 'a' && c <= 'z') &&
5830 !(c >= 'A' && c <= 'Z'))
5831 return false;
5832 }
5833 }
5834
5835 } else
5836 return false;
5837
5838 return true;
5839}
7085053a 5840
d4ac85c6
LP
5841int split_pair(const char *s, const char *sep, char **l, char **r) {
5842 char *x, *a, *b;
5843
5844 assert(s);
5845 assert(sep);
5846 assert(l);
5847 assert(r);
5848
5849 if (isempty(sep))
5850 return -EINVAL;
5851
5852 x = strstr(s, sep);
5853 if (!x)
5854 return -EINVAL;
5855
5856 a = strndup(s, x - s);
5857 if (!a)
5858 return -ENOMEM;
5859
5860 b = strdup(x + strlen(sep));
5861 if (!b) {
5862 free(a);
5863 return -ENOMEM;
5864 }
5865
5866 *l = a;
5867 *r = b;
5868
5869 return 0;
5870}
295edddf 5871
74df0fca 5872int shall_restore_state(void) {
295edddf
TG
5873 _cleanup_free_ char *line;
5874 char *w, *state;
295edddf 5875 size_t l;
74df0fca 5876 int r;
295edddf 5877
74df0fca
LP
5878 r = proc_cmdline(&line);
5879 if (r < 0)
5880 return r;
5881 if (r == 0) /* Container ... */
5882 return 1;
295edddf 5883
74df0fca 5884 FOREACH_WORD_QUOTED(w, l, line, state)
85ca9433 5885 if (l == 23 && strneq(w, "systemd.restore_state=0", 23))
74df0fca
LP
5886 return 0;
5887
5888 return 1;
5889}
5890
5891int proc_cmdline(char **ret) {
5892 int r;
5893
5894 if (detect_container(NULL) > 0) {
39883f62 5895 char *buf = NULL, *p;
02bb6cda
LP
5896 size_t sz = 0;
5897
5898 r = read_full_file("/proc/1/cmdline", &buf, &sz);
5899 if (r < 0)
5900 return r;
5901
5902 for (p = buf; p + 1 < buf + sz; p++)
5903 if (*p == 0)
5904 *p = ' ';
5905
5906 *p = 0;
5907 *ret = buf;
5908 return 1;
295edddf
TG
5909 }
5910
74df0fca
LP
5911 r = read_one_line_file("/proc/cmdline", ret);
5912 if (r < 0)
5913 return r;
295edddf 5914
74df0fca 5915 return 1;
295edddf 5916}
bc9fd78c 5917
141a79f4
ZJS
5918int parse_proc_cmdline(int (*parse_word)(const char *word)) {
5919 _cleanup_free_ char *line = NULL;
5920 char *w, *state;
5921 size_t l;
5922 int r;
5923
5924 r = proc_cmdline(&line);
5925 if (r < 0)
5926 log_warning("Failed to read /proc/cmdline, ignoring: %s", strerror(-r));
5927 if (r <= 0)
5928 return 0;
5929
5930 FOREACH_WORD_QUOTED(w, l, line, state) {
5931 _cleanup_free_ char *word;
5932
5933 word = strndup(w, l);
5934 if (!word)
5935 return log_oom();
5936
5937 r = parse_word(word);
5938 if (r < 0) {
5939 log_error("Failed on cmdline argument %s: %s", word, strerror(-r));
5940 return r;
5941 }
5942 }
5943
5944 return 0;
5945}
5946
bc9fd78c
LP
5947int container_get_leader(const char *machine, pid_t *pid) {
5948 _cleanup_free_ char *s = NULL, *class = NULL;
5949 const char *p;
5950 pid_t leader;
5951 int r;
5952
5953 assert(machine);
5954 assert(pid);
5955
5956 p = strappenda("/run/systemd/machines/", machine);
5957 r = parse_env_file(p, NEWLINE, "LEADER", &s, "CLASS", &class, NULL);
5958 if (r == -ENOENT)
5959 return -EHOSTDOWN;
5960 if (r < 0)
5961 return r;
5962 if (!s)
5963 return -EIO;
5964
5965 if (!streq_ptr(class, "container"))
5966 return -EIO;
5967
5968 r = parse_pid(s, &leader);
5969 if (r < 0)
5970 return r;
5971 if (leader <= 1)
5972 return -EIO;
5973
5974 *pid = leader;
5975 return 0;
5976}
5977
a4475f57
LP
5978int namespace_open(pid_t pid, int *pidns_fd, int *mntns_fd, int *root_fd) {
5979 _cleanup_close_ int pidnsfd = -1, mntnsfd = -1;
5980 const char *pidns, *mntns, *root;
bc9fd78c
LP
5981 int rfd;
5982
5983 assert(pid >= 0);
a4475f57
LP
5984 assert(pidns_fd);
5985 assert(mntns_fd);
bc9fd78c
LP
5986 assert(root_fd);
5987
a4475f57
LP
5988 mntns = procfs_file_alloca(pid, "ns/mnt");
5989 mntnsfd = open(mntns, O_RDONLY|O_NOCTTY|O_CLOEXEC);
5990 if (mntnsfd < 0)
5991 return -errno;
5992
5993 pidns = procfs_file_alloca(pid, "ns/pid");
5994 pidnsfd = open(pidns, O_RDONLY|O_NOCTTY|O_CLOEXEC);
5995 if (pidnsfd < 0)
bc9fd78c
LP
5996 return -errno;
5997
5998 root = procfs_file_alloca(pid, "root");
5999 rfd = open(root, O_RDONLY|O_NOCTTY|O_CLOEXEC|O_DIRECTORY);
6000 if (rfd < 0)
6001 return -errno;
6002
a4475f57
LP
6003 *pidns_fd = pidnsfd;
6004 *mntns_fd = mntnsfd;
bc9fd78c 6005 *root_fd = rfd;
a4475f57
LP
6006 pidnsfd = -1;
6007 mntnsfd = -1;
bc9fd78c
LP
6008
6009 return 0;
6010}
6011
a4475f57
LP
6012int namespace_enter(int pidns_fd, int mntns_fd, int root_fd) {
6013 assert(pidns_fd >= 0);
6014 assert(mntns_fd >= 0);
bc9fd78c
LP
6015 assert(root_fd >= 0);
6016
a4475f57
LP
6017 if (setns(pidns_fd, CLONE_NEWPID) < 0)
6018 return -errno;
6019
6020 if (setns(mntns_fd, CLONE_NEWNS) < 0)
bc9fd78c
LP
6021 return -errno;
6022
6023 if (fchdir(root_fd) < 0)
6024 return -errno;
6025
6026 if (chroot(".") < 0)
6027 return -errno;
6028
5e2b3214
LP
6029 if (setresgid(0, 0, 0) < 0)
6030 return -errno;
6031
6032 if (setresuid(0, 0, 0) < 0)
6033 return -errno;
6034
bc9fd78c
LP
6035 return 0;
6036}
bf108e55 6037
9f5650ae
LP
6038bool pid_is_unwaited(pid_t pid) {
6039 /* Checks whether a PID is still valid at all, including a zombie */
6040
bf108e55
LP
6041 if (pid <= 0)
6042 return false;
6043
6044 if (kill(pid, 0) >= 0)
6045 return true;
6046
6047 return errno != ESRCH;
6048}
eff05270 6049
9f5650ae
LP
6050bool pid_is_alive(pid_t pid) {
6051 int r;
6052
6053 /* Checks whether a PID is still valid and not a zombie */
6054
6055 if (pid <= 0)
6056 return false;
6057
6058 r = get_process_state(pid);
6059 if (r == -ENOENT || r == 'Z')
6060 return false;
6061
6062 return true;
6063}
6064
eff05270
LP
6065int getpeercred(int fd, struct ucred *ucred) {
6066 socklen_t n = sizeof(struct ucred);
6067 struct ucred u;
6068 int r;
6069
6070 assert(fd >= 0);
6071 assert(ucred);
6072
6073 r = getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &u, &n);
6074 if (r < 0)
6075 return -errno;
6076
6077 if (n != sizeof(struct ucred))
6078 return -EIO;
6079
6080 /* Check if the data is actually useful and not suppressed due
6081 * to namespacing issues */
6082 if (u.pid <= 0)
6083 return -ENODATA;
6084
6085 *ucred = u;
6086 return 0;
6087}
6088
6089int getpeersec(int fd, char **ret) {
6090 socklen_t n = 64;
6091 char *s;
6092 int r;
6093
6094 assert(fd >= 0);
6095 assert(ret);
6096
6097 s = new0(char, n);
6098 if (!s)
6099 return -ENOMEM;
6100
6101 r = getsockopt(fd, SOL_SOCKET, SO_PEERSEC, s, &n);
6102 if (r < 0) {
6103 free(s);
6104
6105 if (errno != ERANGE)
6106 return -errno;
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 return -errno;
6116 }
6117 }
6118
ae98841e
LP
6119 if (isempty(s)) {
6120 free(s);
6121 return -ENOTSUP;
6122 }
6123
eff05270
LP
6124 *ret = s;
6125 return 0;
6126}
8e33886e 6127
0f010ef2 6128/* This is much like like mkostemp() but is subject to umask(). */
65b3903f 6129int mkostemp_safe(char *pattern, int flags) {
2d5bdf5b 6130 _cleanup_umask_ mode_t u;
0f010ef2 6131 int fd;
65b3903f 6132
d37a91e8 6133 assert(pattern);
65b3903f 6134
2d5bdf5b
LP
6135 u = umask(077);
6136
0f010ef2
ZJS
6137 fd = mkostemp(pattern, flags);
6138 if (fd < 0)
6139 return -errno;
65b3903f 6140
0f010ef2 6141 return fd;
65b3903f
ZJS
6142}
6143
8e33886e 6144int open_tmpfile(const char *path, int flags) {
8e33886e 6145 char *p;
a6afc4ae
LP
6146 int fd;
6147
6148 assert(path);
8e33886e
ZJS
6149
6150#ifdef O_TMPFILE
7736202c
LP
6151 /* Try O_TMPFILE first, if it is supported */
6152 fd = open(path, flags|O_TMPFILE, S_IRUSR|S_IWUSR);
8e33886e
ZJS
6153 if (fd >= 0)
6154 return fd;
6155#endif
7736202c
LP
6156
6157 /* Fall back to unguessable name + unlinking */
8e33886e
ZJS
6158 p = strappenda(path, "/systemd-tmp-XXXXXX");
6159
a6afc4ae 6160 fd = mkostemp_safe(p, flags);
8e33886e 6161 if (fd < 0)
65b3903f 6162 return fd;
8e33886e
ZJS
6163
6164 unlink(p);
6165 return fd;
6166}
fdb9161c
LP
6167
6168int fd_warn_permissions(const char *path, int fd) {
6169 struct stat st;
6170
6171 if (fstat(fd, &st) < 0)
6172 return -errno;
6173
6174 if (st.st_mode & 0111)
6175 log_warning("Configuration file %s is marked executable. Please remove executable permission bits. Proceeding anyway.", path);
6176
6177 if (st.st_mode & 0002)
6178 log_warning("Configuration file %s is marked world-writable. Please remove world writability permission bits. Proceeding anyway.", path);
6179
6180 if (getpid() == 1 && (st.st_mode & 0044) != 0044)
6181 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);
6182
6183 return 0;
6184}
6afc95b7 6185
ac45f971 6186unsigned long personality_from_string(const char *p) {
6afc95b7
LP
6187
6188 /* Parse a personality specifier. We introduce our own
6189 * identifiers that indicate specific ABIs, rather than just
6190 * hints regarding the register size, since we want to keep
6191 * things open for multiple locally supported ABIs for the
6192 * same register size. We try to reuse the ABI identifiers
6193 * used by libseccomp. */
6194
6195#if defined(__x86_64__)
6196
6197 if (streq(p, "x86"))
6198 return PER_LINUX32;
6199
6200 if (streq(p, "x86-64"))
6201 return PER_LINUX;
6202
6203#elif defined(__i386__)
6204
6205 if (streq(p, "x86"))
6206 return PER_LINUX;
6207#endif
6208
6209 /* personality(7) documents that 0xffffffffUL is used for
6210 * querying the current personality, hence let's use that here
6211 * as error indicator. */
6212 return 0xffffffffUL;
6213}
ac45f971
LP
6214
6215const char* personality_to_string(unsigned long p) {
6216
6217#if defined(__x86_64__)
6218
6219 if (p == PER_LINUX32)
6220 return "x86";
6221
6222 if (p == PER_LINUX)
6223 return "x86-64";
6224
6225#elif defined(__i386__)
6226
6227 if (p == PER_LINUX)
6228 return "x86";
6229#endif
6230
6231 return NULL;
6232}