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