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