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