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