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