]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/util.c
util: introduce waitpid_loop()
[thirdparty/systemd.git] / src / 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
9 under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
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
16 General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
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>
60918275
LP
53
54#include "macro.h"
55#include "util.h"
1dccbe19
LP
56#include "ioprio.h"
57#include "missing.h"
a9f5d454 58#include "log.h"
65d2ebdc 59#include "strv.h"
e51bc1a2 60#include "label.h"
d06dacd0 61#include "exit-status.h"
56cf987f 62
e05797fb
LP
63bool streq_ptr(const char *a, const char *b) {
64
65 /* Like streq(), but tries to make sense of NULL pointers */
66
67 if (a && b)
68 return streq(a, b);
69
70 if (!a && !b)
71 return true;
72
73 return false;
74}
75
47be870b 76usec_t now(clockid_t clock_id) {
60918275
LP
77 struct timespec ts;
78
47be870b 79 assert_se(clock_gettime(clock_id, &ts) == 0);
60918275
LP
80
81 return timespec_load(&ts);
82}
83
63983207 84dual_timestamp* dual_timestamp_get(dual_timestamp *ts) {
871d7de4
LP
85 assert(ts);
86
87 ts->realtime = now(CLOCK_REALTIME);
88 ts->monotonic = now(CLOCK_MONOTONIC);
89
90 return ts;
91}
92
60918275
LP
93usec_t timespec_load(const struct timespec *ts) {
94 assert(ts);
95
96 return
97 (usec_t) ts->tv_sec * USEC_PER_SEC +
98 (usec_t) ts->tv_nsec / NSEC_PER_USEC;
99}
100
101struct timespec *timespec_store(struct timespec *ts, usec_t u) {
102 assert(ts);
103
104 ts->tv_sec = (time_t) (u / USEC_PER_SEC);
105 ts->tv_nsec = (long int) ((u % USEC_PER_SEC) * NSEC_PER_USEC);
106
107 return ts;
108}
109
110usec_t timeval_load(const struct timeval *tv) {
111 assert(tv);
112
113 return
114 (usec_t) tv->tv_sec * USEC_PER_SEC +
115 (usec_t) tv->tv_usec;
116}
117
118struct timeval *timeval_store(struct timeval *tv, usec_t u) {
119 assert(tv);
120
121 tv->tv_sec = (time_t) (u / USEC_PER_SEC);
122 tv->tv_usec = (suseconds_t) (u % USEC_PER_SEC);
123
124 return tv;
125}
126
127bool endswith(const char *s, const char *postfix) {
128 size_t sl, pl;
129
130 assert(s);
131 assert(postfix);
132
133 sl = strlen(s);
134 pl = strlen(postfix);
135
d4d0d4db
LP
136 if (pl == 0)
137 return true;
138
60918275
LP
139 if (sl < pl)
140 return false;
141
142 return memcmp(s + sl - pl, postfix, pl) == 0;
143}
144
145bool startswith(const char *s, const char *prefix) {
146 size_t sl, pl;
147
148 assert(s);
149 assert(prefix);
150
151 sl = strlen(s);
152 pl = strlen(prefix);
153
d4d0d4db
LP
154 if (pl == 0)
155 return true;
156
60918275
LP
157 if (sl < pl)
158 return false;
159
160 return memcmp(s, prefix, pl) == 0;
161}
162
3177a7fa
MAP
163bool startswith_no_case(const char *s, const char *prefix) {
164 size_t sl, pl;
165 unsigned i;
166
167 assert(s);
168 assert(prefix);
169
170 sl = strlen(s);
171 pl = strlen(prefix);
172
173 if (pl == 0)
174 return true;
175
176 if (sl < pl)
177 return false;
178
179 for(i = 0; i < pl; ++i) {
180 if (tolower(s[i]) != tolower(prefix[i]))
181 return false;
182 }
183
184 return true;
185}
186
79d6d816
LP
187bool first_word(const char *s, const char *word) {
188 size_t sl, wl;
189
190 assert(s);
191 assert(word);
192
193 sl = strlen(s);
194 wl = strlen(word);
195
196 if (sl < wl)
197 return false;
198
d4d0d4db
LP
199 if (wl == 0)
200 return true;
201
79d6d816
LP
202 if (memcmp(s, word, wl) != 0)
203 return false;
204
d4d0d4db
LP
205 return s[wl] == 0 ||
206 strchr(WHITESPACE, s[wl]);
79d6d816
LP
207}
208
42f4e3c4 209int close_nointr(int fd) {
60918275
LP
210 assert(fd >= 0);
211
212 for (;;) {
213 int r;
214
215 if ((r = close(fd)) >= 0)
216 return r;
217
218 if (errno != EINTR)
219 return r;
220 }
221}
85261803 222
85f136b5 223void close_nointr_nofail(int fd) {
80876c20 224 int saved_errno = errno;
85f136b5
LP
225
226 /* like close_nointr() but cannot fail, and guarantees errno
227 * is unchanged */
228
229 assert_se(close_nointr(fd) == 0);
80876c20
LP
230
231 errno = saved_errno;
85f136b5
LP
232}
233
5b6319dc
LP
234void close_many(const int fds[], unsigned n_fd) {
235 unsigned i;
236
237 for (i = 0; i < n_fd; i++)
238 close_nointr_nofail(fds[i]);
239}
240
85261803
LP
241int parse_boolean(const char *v) {
242 assert(v);
243
44d8db9e 244 if (streq(v, "1") || v[0] == 'y' || v[0] == 'Y' || v[0] == 't' || v[0] == 'T' || !strcasecmp(v, "on"))
85261803 245 return 1;
44d8db9e 246 else if (streq(v, "0") || v[0] == 'n' || v[0] == 'N' || v[0] == 'f' || v[0] == 'F' || !strcasecmp(v, "off"))
85261803
LP
247 return 0;
248
249 return -EINVAL;
250}
251
3ba686c1
LP
252int parse_pid(const char *s, pid_t* ret_pid) {
253 unsigned long ul;
254 pid_t pid;
255 int r;
256
257 assert(s);
258 assert(ret_pid);
259
260 if ((r = safe_atolu(s, &ul)) < 0)
261 return r;
262
263 pid = (pid_t) ul;
264
265 if ((unsigned long) pid != ul)
266 return -ERANGE;
267
268 if (pid <= 0)
269 return -ERANGE;
270
271 *ret_pid = pid;
272 return 0;
273}
274
85261803
LP
275int safe_atou(const char *s, unsigned *ret_u) {
276 char *x = NULL;
034c6ed7 277 unsigned long l;
85261803
LP
278
279 assert(s);
280 assert(ret_u);
281
282 errno = 0;
283 l = strtoul(s, &x, 0);
284
285 if (!x || *x || errno)
286 return errno ? -errno : -EINVAL;
287
034c6ed7 288 if ((unsigned long) (unsigned) l != l)
85261803
LP
289 return -ERANGE;
290
291 *ret_u = (unsigned) l;
292 return 0;
293}
294
295int safe_atoi(const char *s, int *ret_i) {
296 char *x = NULL;
034c6ed7 297 long l;
85261803
LP
298
299 assert(s);
300 assert(ret_i);
301
302 errno = 0;
303 l = strtol(s, &x, 0);
304
305 if (!x || *x || errno)
306 return errno ? -errno : -EINVAL;
307
034c6ed7 308 if ((long) (int) l != l)
85261803
LP
309 return -ERANGE;
310
034c6ed7
LP
311 *ret_i = (int) l;
312 return 0;
313}
314
034c6ed7
LP
315int safe_atollu(const char *s, long long unsigned *ret_llu) {
316 char *x = NULL;
317 unsigned long long l;
318
319 assert(s);
320 assert(ret_llu);
321
322 errno = 0;
323 l = strtoull(s, &x, 0);
324
325 if (!x || *x || errno)
326 return errno ? -errno : -EINVAL;
327
328 *ret_llu = l;
329 return 0;
330}
331
332int safe_atolli(const char *s, long long int *ret_lli) {
333 char *x = NULL;
334 long long l;
335
336 assert(s);
337 assert(ret_lli);
338
339 errno = 0;
340 l = strtoll(s, &x, 0);
341
342 if (!x || *x || errno)
343 return errno ? -errno : -EINVAL;
344
345 *ret_lli = l;
85261803
LP
346 return 0;
347}
a41e8209 348
a41e8209 349/* Split a string into words. */
65d2ebdc 350char *split(const char *c, size_t *l, const char *separator, char **state) {
a41e8209
LP
351 char *current;
352
353 current = *state ? *state : (char*) c;
354
355 if (!*current || *c == 0)
356 return NULL;
357
65d2ebdc
LP
358 current += strspn(current, separator);
359 *l = strcspn(current, separator);
82919e3d
LP
360 *state = current+*l;
361
362 return (char*) current;
363}
364
034c6ed7
LP
365/* Split a string into words, but consider strings enclosed in '' and
366 * "" as words even if they include spaces. */
367char *split_quoted(const char *c, size_t *l, char **state) {
0bab36f2
LP
368 char *current, *e;
369 bool escaped = false;
034c6ed7
LP
370
371 current = *state ? *state : (char*) c;
372
373 if (!*current || *c == 0)
374 return NULL;
375
376 current += strspn(current, WHITESPACE);
377
378 if (*current == '\'') {
379 current ++;
034c6ed7 380
0bab36f2
LP
381 for (e = current; *e; e++) {
382 if (escaped)
383 escaped = false;
384 else if (*e == '\\')
385 escaped = true;
386 else if (*e == '\'')
387 break;
388 }
389
390 *l = e-current;
391 *state = *e == 0 ? e : e+1;
034c6ed7
LP
392 } else if (*current == '\"') {
393 current ++;
034c6ed7 394
0bab36f2
LP
395 for (e = current; *e; e++) {
396 if (escaped)
397 escaped = false;
398 else if (*e == '\\')
399 escaped = true;
400 else if (*e == '\"')
401 break;
402 }
403
404 *l = e-current;
405 *state = *e == 0 ? e : e+1;
034c6ed7 406 } else {
0bab36f2
LP
407 for (e = current; *e; e++) {
408 if (escaped)
409 escaped = false;
410 else if (*e == '\\')
411 escaped = true;
412 else if (strchr(WHITESPACE, *e))
413 break;
414 }
415 *l = e-current;
416 *state = e;
034c6ed7
LP
417 }
418
419 return (char*) current;
420}
421
65d2ebdc
LP
422char **split_path_and_make_absolute(const char *p) {
423 char **l;
424 assert(p);
425
426 if (!(l = strv_split(p, ":")))
427 return NULL;
428
429 if (!strv_path_make_absolute_cwd(l)) {
430 strv_free(l);
431 return NULL;
432 }
433
434 return l;
435}
436
034c6ed7
LP
437int get_parent_of_pid(pid_t pid, pid_t *_ppid) {
438 int r;
439 FILE *f;
440 char fn[132], line[256], *p;
bb00e604 441 long unsigned ppid;
034c6ed7
LP
442
443 assert(pid >= 0);
444 assert(_ppid);
445
bb00e604 446 assert_se(snprintf(fn, sizeof(fn)-1, "/proc/%lu/stat", (unsigned long) pid) < (int) (sizeof(fn)-1));
034c6ed7
LP
447 fn[sizeof(fn)-1] = 0;
448
449 if (!(f = fopen(fn, "r")))
450 return -errno;
451
452 if (!(fgets(line, sizeof(line), f))) {
453 r = -errno;
454 fclose(f);
455 return r;
456 }
457
458 fclose(f);
459
460 /* Let's skip the pid and comm fields. The latter is enclosed
461 * in () but does not escape any () in its value, so let's
462 * skip over it manually */
463
464 if (!(p = strrchr(line, ')')))
465 return -EIO;
466
467 p++;
468
469 if (sscanf(p, " "
470 "%*c " /* state */
bb00e604 471 "%lu ", /* ppid */
034c6ed7
LP
472 &ppid) != 1)
473 return -EIO;
474
bb00e604 475 if ((long unsigned) (pid_t) ppid != ppid)
034c6ed7
LP
476 return -ERANGE;
477
478 *_ppid = (pid_t) ppid;
479
480 return 0;
481}
482
483int write_one_line_file(const char *fn, const char *line) {
484 FILE *f;
485 int r;
486
487 assert(fn);
488 assert(line);
489
490 if (!(f = fopen(fn, "we")))
491 return -errno;
492
493 if (fputs(line, f) < 0) {
494 r = -errno;
495 goto finish;
496 }
497
498 r = 0;
499finish:
500 fclose(f);
501 return r;
502}
503
504int read_one_line_file(const char *fn, char **line) {
505 FILE *f;
506 int r;
11316633 507 char t[2048], *c;
034c6ed7
LP
508
509 assert(fn);
510 assert(line);
511
512 if (!(f = fopen(fn, "re")))
513 return -errno;
514
515 if (!(fgets(t, sizeof(t), f))) {
516 r = -errno;
517 goto finish;
518 }
519
520 if (!(c = strdup(t))) {
521 r = -ENOMEM;
522 goto finish;
523 }
524
525 *line = c;
526 r = 0;
527
528finish:
529 fclose(f);
530 return r;
531}
44d8db9e 532
7072ced8
LP
533char *truncate_nl(char *s) {
534 assert(s);
535
536 s[strcspn(s, NEWLINE)] = 0;
537 return s;
538}
539
540int get_process_name(pid_t pid, char **name) {
541 char *p;
542 int r;
543
544 assert(pid >= 1);
545 assert(name);
546
bb00e604 547 if (asprintf(&p, "/proc/%lu/comm", (unsigned long) pid) < 0)
7072ced8
LP
548 return -ENOMEM;
549
550 r = read_one_line_file(p, name);
551 free(p);
552
553 if (r < 0)
554 return r;
555
556 truncate_nl(*name);
557 return 0;
558}
559
c59760ee
LP
560int get_process_cmdline(pid_t pid, size_t max_length, char **line) {
561 char *p, *r, *k;
562 int c;
563 bool space = false;
564 size_t left;
565 FILE *f;
566
567 assert(pid >= 1);
568 assert(max_length > 0);
569 assert(line);
570
571 if (asprintf(&p, "/proc/%lu/cmdline", (unsigned long) pid) < 0)
572 return -ENOMEM;
573
574 f = fopen(p, "r");
575 free(p);
576
577 if (!f)
578 return -errno;
579
580 if (!(r = new(char, max_length))) {
581 fclose(f);
582 return -ENOMEM;
583 }
584
585 k = r;
586 left = max_length;
587 while ((c = getc(f)) != EOF) {
588
589 if (isprint(c)) {
590 if (space) {
591 if (left <= 4)
592 break;
593
594 *(k++) = ' ';
057fbb58 595 left--;
c59760ee
LP
596 space = false;
597 }
598
599 if (left <= 4)
600 break;
601
602 *(k++) = (char) c;
057fbb58 603 left--;
c59760ee
LP
604 } else
605 space = true;
606 }
607
608 if (left <= 4) {
609 size_t n = MIN(left-1, 3U);
610 memcpy(k, "...", n);
611 k[n] = 0;
612 } else
613 *k = 0;
614
615 fclose(f);
616
35d2e7ec
LP
617 /* Kernel threads have no argv[] */
618 if (r[0] == 0) {
619 char *t;
620 int h;
621
622 free(r);
623
624 if ((h = get_process_name(pid, &t)) < 0)
625 return h;
626
627 h = asprintf(&r, "[%s]", t);
628 free(t);
629
630 if (h < 0)
631 return -ENOMEM;
632 }
fa776d8e 633
c59760ee
LP
634 *line = r;
635 return 0;
636}
637
fab56fc5
LP
638char *strnappend(const char *s, const char *suffix, size_t b) {
639 size_t a;
44d8db9e
LP
640 char *r;
641
fab56fc5
LP
642 if (!s && !suffix)
643 return strdup("");
644
645 if (!s)
646 return strndup(suffix, b);
647
648 if (!suffix)
649 return strdup(s);
650
44d8db9e
LP
651 assert(s);
652 assert(suffix);
653
654 a = strlen(s);
44d8db9e
LP
655
656 if (!(r = new(char, a+b+1)))
657 return NULL;
658
659 memcpy(r, s, a);
660 memcpy(r+a, suffix, b);
661 r[a+b] = 0;
662
663 return r;
664}
87f0e418 665
fab56fc5
LP
666char *strappend(const char *s, const char *suffix) {
667 return strnappend(s, suffix, suffix ? strlen(suffix) : 0);
668}
669
87f0e418
LP
670int readlink_malloc(const char *p, char **r) {
671 size_t l = 100;
672
673 assert(p);
674 assert(r);
675
676 for (;;) {
677 char *c;
678 ssize_t n;
679
680 if (!(c = new(char, l)))
681 return -ENOMEM;
682
683 if ((n = readlink(p, c, l-1)) < 0) {
684 int ret = -errno;
685 free(c);
686 return ret;
687 }
688
689 if ((size_t) n < l-1) {
690 c[n] = 0;
691 *r = c;
692 return 0;
693 }
694
695 free(c);
696 l *= 2;
697 }
698}
699
2c7108c4
LP
700int readlink_and_make_absolute(const char *p, char **r) {
701 char *target, *k;
702 int j;
703
704 assert(p);
705 assert(r);
706
707 if ((j = readlink_malloc(p, &target)) < 0)
708 return j;
709
710 k = file_in_same_dir(p, target);
711 free(target);
712
713 if (!k)
714 return -ENOMEM;
715
716 *r = k;
717 return 0;
718}
719
35d2e7ec
LP
720int parent_of_path(const char *path, char **_r) {
721 const char *e, *a = NULL, *b = NULL, *p;
722 char *r;
723 bool slash = false;
724
725 assert(path);
726 assert(_r);
727
728 if (!*path)
729 return -EINVAL;
730
731 for (e = path; *e; e++) {
732
733 if (!slash && *e == '/') {
734 a = b;
735 b = e;
736 slash = true;
737 } else if (slash && *e != '/')
738 slash = false;
739 }
740
741 if (*(e-1) == '/')
742 p = a;
743 else
744 p = b;
745
746 if (!p)
747 return -EINVAL;
748
749 if (p == path)
750 r = strdup("/");
751 else
752 r = strndup(path, p-path);
753
754 if (!r)
755 return -ENOMEM;
756
757 *_r = r;
758 return 0;
759}
760
761
87f0e418
LP
762char *file_name_from_path(const char *p) {
763 char *r;
764
765 assert(p);
766
767 if ((r = strrchr(p, '/')))
768 return r + 1;
769
770 return (char*) p;
771}
0301abf4
LP
772
773bool path_is_absolute(const char *p) {
774 assert(p);
775
776 return p[0] == '/';
777}
778
779bool is_path(const char *p) {
780
781 return !!strchr(p, '/');
782}
783
784char *path_make_absolute(const char *p, const char *prefix) {
785 char *r;
786
787 assert(p);
788
65d2ebdc
LP
789 /* Makes every item in the list an absolute path by prepending
790 * the prefix, if specified and necessary */
791
0301abf4
LP
792 if (path_is_absolute(p) || !prefix)
793 return strdup(p);
794
795 if (asprintf(&r, "%s/%s", prefix, p) < 0)
796 return NULL;
797
798 return r;
799}
2a987ee8 800
65d2ebdc
LP
801char *path_make_absolute_cwd(const char *p) {
802 char *cwd, *r;
803
804 assert(p);
805
806 /* Similar to path_make_absolute(), but prefixes with the
807 * current working directory. */
808
809 if (path_is_absolute(p))
810 return strdup(p);
811
812 if (!(cwd = get_current_dir_name()))
813 return NULL;
814
815 r = path_make_absolute(p, cwd);
816 free(cwd);
817
818 return r;
819}
820
821char **strv_path_make_absolute_cwd(char **l) {
822 char **s;
823
824 /* Goes through every item in the string list and makes it
825 * absolute. This works in place and won't rollback any
826 * changes on failure. */
827
828 STRV_FOREACH(s, l) {
829 char *t;
830
831 if (!(t = path_make_absolute_cwd(*s)))
832 return NULL;
833
834 free(*s);
835 *s = t;
836 }
837
838 return l;
839}
840
c3f6d675
LP
841char **strv_path_canonicalize(char **l) {
842 char **s;
843 unsigned k = 0;
844 bool enomem = false;
845
846 if (strv_isempty(l))
847 return l;
848
849 /* Goes through every item in the string list and canonicalize
850 * the path. This works in place and won't rollback any
851 * changes on failure. */
852
853 STRV_FOREACH(s, l) {
854 char *t, *u;
855
856 t = path_make_absolute_cwd(*s);
857 free(*s);
858
859 if (!t) {
860 enomem = true;
861 continue;
862 }
863
864 errno = 0;
865 u = canonicalize_file_name(t);
866 free(t);
867
868 if (!u) {
869 if (errno == ENOMEM || !errno)
870 enomem = true;
871
872 continue;
873 }
874
875 l[k++] = u;
876 }
877
878 l[k] = NULL;
879
880 if (enomem)
881 return NULL;
882
883 return l;
884}
885
2a987ee8
LP
886int reset_all_signal_handlers(void) {
887 int sig;
888
889 for (sig = 1; sig < _NSIG; sig++) {
890 struct sigaction sa;
891
892 if (sig == SIGKILL || sig == SIGSTOP)
893 continue;
894
895 zero(sa);
896 sa.sa_handler = SIG_DFL;
431c32bf 897 sa.sa_flags = SA_RESTART;
2a987ee8
LP
898
899 /* On Linux the first two RT signals are reserved by
900 * glibc, and sigaction() will return EINVAL for them. */
901 if ((sigaction(sig, &sa, NULL) < 0))
902 if (errno != EINVAL)
903 return -errno;
904 }
905
8e274523 906 return 0;
2a987ee8 907}
4a72ff34
LP
908
909char *strstrip(char *s) {
910 char *e, *l = NULL;
911
912 /* Drops trailing whitespace. Modifies the string in
913 * place. Returns pointer to first non-space character */
914
915 s += strspn(s, WHITESPACE);
916
917 for (e = s; *e; e++)
918 if (!strchr(WHITESPACE, *e))
919 l = e;
920
921 if (l)
922 *(l+1) = 0;
923 else
924 *s = 0;
925
926 return s;
4a72ff34
LP
927}
928
ee9b5e01
LP
929char *delete_chars(char *s, const char *bad) {
930 char *f, *t;
931
932 /* Drops all whitespace, regardless where in the string */
933
934 for (f = s, t = s; *f; f++) {
935 if (strchr(bad, *f))
936 continue;
937
938 *(t++) = *f;
939 }
940
941 *t = 0;
942
943 return s;
944}
945
4a72ff34
LP
946char *file_in_same_dir(const char *path, const char *filename) {
947 char *e, *r;
948 size_t k;
949
950 assert(path);
951 assert(filename);
952
953 /* This removes the last component of path and appends
954 * filename, unless the latter is absolute anyway or the
955 * former isn't */
956
957 if (path_is_absolute(filename))
958 return strdup(filename);
959
960 if (!(e = strrchr(path, '/')))
961 return strdup(filename);
962
963 k = strlen(filename);
964 if (!(r = new(char, e-path+1+k+1)))
965 return NULL;
966
967 memcpy(r, path, e-path+1);
968 memcpy(r+(e-path)+1, filename, k+1);
969
970 return r;
971}
fb624d04 972
8c6db833
LP
973int safe_mkdir(const char *path, mode_t mode, uid_t uid, gid_t gid) {
974 struct stat st;
975
56cf987f 976 if (label_mkdir(path, mode) >= 0)
8c6db833
LP
977 if (chmod_and_chown(path, mode, uid, gid) < 0)
978 return -errno;
979
980 if (lstat(path, &st) < 0)
981 return -errno;
982
983 if ((st.st_mode & 0777) != mode ||
984 st.st_uid != uid ||
985 st.st_gid != gid ||
986 !S_ISDIR(st.st_mode)) {
987 errno = EEXIST;
988 return -errno;
989 }
990
991 return 0;
992}
993
994
a9f5d454
LP
995int mkdir_parents(const char *path, mode_t mode) {
996 const char *p, *e;
997
998 assert(path);
999
1000 /* Creates every parent directory in the path except the last
1001 * component. */
1002
1003 p = path + strspn(path, "/");
1004 for (;;) {
1005 int r;
1006 char *t;
1007
1008 e = p + strcspn(p, "/");
1009 p = e + strspn(e, "/");
1010
1011 /* Is this the last component? If so, then we're
1012 * done */
1013 if (*p == 0)
1014 return 0;
1015
1016 if (!(t = strndup(path, e - path)))
1017 return -ENOMEM;
1018
56cf987f 1019 r = label_mkdir(t, mode);
a9f5d454
LP
1020 free(t);
1021
1022 if (r < 0 && errno != EEXIST)
1023 return -errno;
1024 }
1025}
1026
bbd67135
LP
1027int mkdir_p(const char *path, mode_t mode) {
1028 int r;
1029
1030 /* Like mkdir -p */
1031
1032 if ((r = mkdir_parents(path, mode)) < 0)
1033 return r;
1034
56cf987f 1035 if (label_mkdir(path, mode) < 0 && errno != EEXIST)
bbd67135
LP
1036 return -errno;
1037
1038 return 0;
1039}
1040
c32dd69b
LP
1041int rmdir_parents(const char *path, const char *stop) {
1042 size_t l;
1043 int r = 0;
1044
1045 assert(path);
1046 assert(stop);
1047
1048 l = strlen(path);
1049
1050 /* Skip trailing slashes */
1051 while (l > 0 && path[l-1] == '/')
1052 l--;
1053
1054 while (l > 0) {
1055 char *t;
1056
1057 /* Skip last component */
1058 while (l > 0 && path[l-1] != '/')
1059 l--;
1060
1061 /* Skip trailing slashes */
1062 while (l > 0 && path[l-1] == '/')
1063 l--;
1064
1065 if (l <= 0)
1066 break;
1067
1068 if (!(t = strndup(path, l)))
1069 return -ENOMEM;
1070
1071 if (path_startswith(stop, t)) {
1072 free(t);
1073 return 0;
1074 }
1075
1076 r = rmdir(t);
1077 free(t);
1078
1079 if (r < 0)
1080 if (errno != ENOENT)
1081 return -errno;
1082 }
1083
1084 return 0;
1085}
1086
1087
fb624d04
LP
1088char hexchar(int x) {
1089 static const char table[16] = "0123456789abcdef";
1090
1091 return table[x & 15];
1092}
4fe88d28
LP
1093
1094int unhexchar(char c) {
1095
1096 if (c >= '0' && c <= '9')
1097 return c - '0';
1098
1099 if (c >= 'a' && c <= 'f')
ea430986 1100 return c - 'a' + 10;
4fe88d28
LP
1101
1102 if (c >= 'A' && c <= 'F')
ea430986 1103 return c - 'A' + 10;
4fe88d28
LP
1104
1105 return -1;
1106}
1107
1108char octchar(int x) {
1109 return '0' + (x & 7);
1110}
1111
1112int unoctchar(char c) {
1113
1114 if (c >= '0' && c <= '7')
1115 return c - '0';
1116
1117 return -1;
1118}
1119
5af98f82
LP
1120char decchar(int x) {
1121 return '0' + (x % 10);
1122}
1123
1124int undecchar(char c) {
1125
1126 if (c >= '0' && c <= '9')
1127 return c - '0';
1128
1129 return -1;
1130}
1131
4fe88d28
LP
1132char *cescape(const char *s) {
1133 char *r, *t;
1134 const char *f;
1135
1136 assert(s);
1137
1138 /* Does C style string escaping. */
1139
1140 if (!(r = new(char, strlen(s)*4 + 1)))
1141 return NULL;
1142
1143 for (f = s, t = r; *f; f++)
1144
1145 switch (*f) {
1146
1147 case '\a':
1148 *(t++) = '\\';
1149 *(t++) = 'a';
1150 break;
1151 case '\b':
1152 *(t++) = '\\';
1153 *(t++) = 'b';
1154 break;
1155 case '\f':
1156 *(t++) = '\\';
1157 *(t++) = 'f';
1158 break;
1159 case '\n':
1160 *(t++) = '\\';
1161 *(t++) = 'n';
1162 break;
1163 case '\r':
1164 *(t++) = '\\';
1165 *(t++) = 'r';
1166 break;
1167 case '\t':
1168 *(t++) = '\\';
1169 *(t++) = 't';
1170 break;
1171 case '\v':
1172 *(t++) = '\\';
1173 *(t++) = 'v';
1174 break;
1175 case '\\':
1176 *(t++) = '\\';
1177 *(t++) = '\\';
1178 break;
1179 case '"':
1180 *(t++) = '\\';
1181 *(t++) = '"';
1182 break;
1183 case '\'':
1184 *(t++) = '\\';
1185 *(t++) = '\'';
1186 break;
1187
1188 default:
1189 /* For special chars we prefer octal over
1190 * hexadecimal encoding, simply because glib's
1191 * g_strescape() does the same */
1192 if ((*f < ' ') || (*f >= 127)) {
1193 *(t++) = '\\';
1194 *(t++) = octchar((unsigned char) *f >> 6);
1195 *(t++) = octchar((unsigned char) *f >> 3);
1196 *(t++) = octchar((unsigned char) *f);
1197 } else
1198 *(t++) = *f;
1199 break;
1200 }
1201
1202 *t = 0;
1203
1204 return r;
1205}
1206
6febfd0d 1207char *cunescape_length(const char *s, size_t length) {
4fe88d28
LP
1208 char *r, *t;
1209 const char *f;
1210
1211 assert(s);
1212
1213 /* Undoes C style string escaping */
1214
6febfd0d 1215 if (!(r = new(char, length+1)))
4fe88d28
LP
1216 return r;
1217
6febfd0d 1218 for (f = s, t = r; f < s + length; f++) {
4fe88d28
LP
1219
1220 if (*f != '\\') {
1221 *(t++) = *f;
1222 continue;
1223 }
1224
1225 f++;
1226
1227 switch (*f) {
1228
1229 case 'a':
1230 *(t++) = '\a';
1231 break;
1232 case 'b':
1233 *(t++) = '\b';
1234 break;
1235 case 'f':
1236 *(t++) = '\f';
1237 break;
1238 case 'n':
1239 *(t++) = '\n';
1240 break;
1241 case 'r':
1242 *(t++) = '\r';
1243 break;
1244 case 't':
1245 *(t++) = '\t';
1246 break;
1247 case 'v':
1248 *(t++) = '\v';
1249 break;
1250 case '\\':
1251 *(t++) = '\\';
1252 break;
1253 case '"':
1254 *(t++) = '"';
1255 break;
1256 case '\'':
1257 *(t++) = '\'';
1258 break;
1259
e167fb86
LP
1260 case 's':
1261 /* This is an extension of the XDG syntax files */
1262 *(t++) = ' ';
1263 break;
1264
4fe88d28
LP
1265 case 'x': {
1266 /* hexadecimal encoding */
1267 int a, b;
1268
1269 if ((a = unhexchar(f[1])) < 0 ||
1270 (b = unhexchar(f[2])) < 0) {
1271 /* Invalid escape code, let's take it literal then */
1272 *(t++) = '\\';
1273 *(t++) = 'x';
1274 } else {
1275 *(t++) = (char) ((a << 4) | b);
1276 f += 2;
1277 }
1278
1279 break;
1280 }
1281
1282 case '0':
1283 case '1':
1284 case '2':
1285 case '3':
1286 case '4':
1287 case '5':
1288 case '6':
1289 case '7': {
1290 /* octal encoding */
1291 int a, b, c;
1292
1293 if ((a = unoctchar(f[0])) < 0 ||
1294 (b = unoctchar(f[1])) < 0 ||
1295 (c = unoctchar(f[2])) < 0) {
1296 /* Invalid escape code, let's take it literal then */
1297 *(t++) = '\\';
1298 *(t++) = f[0];
1299 } else {
1300 *(t++) = (char) ((a << 6) | (b << 3) | c);
1301 f += 2;
1302 }
1303
1304 break;
1305 }
1306
1307 case 0:
1308 /* premature end of string.*/
1309 *(t++) = '\\';
1310 goto finish;
1311
1312 default:
1313 /* Invalid escape code, let's take it literal then */
1314 *(t++) = '\\';
f3d4cc01 1315 *(t++) = *f;
4fe88d28
LP
1316 break;
1317 }
1318 }
1319
1320finish:
1321 *t = 0;
1322 return r;
1323}
1324
6febfd0d
LP
1325char *cunescape(const char *s) {
1326 return cunescape_length(s, strlen(s));
1327}
4fe88d28
LP
1328
1329char *xescape(const char *s, const char *bad) {
1330 char *r, *t;
1331 const char *f;
1332
1333 /* Escapes all chars in bad, in addition to \ and all special
1334 * chars, in \xFF style escaping. May be reversed with
1335 * cunescape. */
1336
1337 if (!(r = new(char, strlen(s)*4+1)))
1338 return NULL;
1339
1340 for (f = s, t = r; *f; f++) {
1341
b866264a
LP
1342 if ((*f < ' ') || (*f >= 127) ||
1343 (*f == '\\') || strchr(bad, *f)) {
4fe88d28
LP
1344 *(t++) = '\\';
1345 *(t++) = 'x';
1346 *(t++) = hexchar(*f >> 4);
1347 *(t++) = hexchar(*f);
1348 } else
1349 *(t++) = *f;
1350 }
1351
1352 *t = 0;
1353
1354 return r;
1355}
1356
ea430986 1357char *bus_path_escape(const char *s) {
ea430986
LP
1358 char *r, *t;
1359 const char *f;
1360
47be870b
LP
1361 assert(s);
1362
ea430986
LP
1363 /* Escapes all chars that D-Bus' object path cannot deal
1364 * with. Can be reverse with bus_path_unescape() */
1365
1366 if (!(r = new(char, strlen(s)*3+1)))
1367 return NULL;
1368
1369 for (f = s, t = r; *f; f++) {
1370
1371 if (!(*f >= 'A' && *f <= 'Z') &&
1372 !(*f >= 'a' && *f <= 'z') &&
1373 !(*f >= '0' && *f <= '9')) {
1374 *(t++) = '_';
1375 *(t++) = hexchar(*f >> 4);
1376 *(t++) = hexchar(*f);
1377 } else
1378 *(t++) = *f;
1379 }
1380
1381 *t = 0;
1382
1383 return r;
1384}
1385
9e2f7c11 1386char *bus_path_unescape(const char *f) {
ea430986 1387 char *r, *t;
ea430986 1388
9e2f7c11 1389 assert(f);
47be870b 1390
9e2f7c11 1391 if (!(r = strdup(f)))
ea430986
LP
1392 return NULL;
1393
9e2f7c11 1394 for (t = r; *f; f++) {
ea430986
LP
1395
1396 if (*f == '_') {
1397 int a, b;
1398
1399 if ((a = unhexchar(f[1])) < 0 ||
1400 (b = unhexchar(f[2])) < 0) {
1401 /* Invalid escape code, let's take it literal then */
1402 *(t++) = '_';
1403 } else {
1404 *(t++) = (char) ((a << 4) | b);
1405 f += 2;
1406 }
1407 } else
1408 *(t++) = *f;
1409 }
1410
1411 *t = 0;
1412
1413 return r;
1414}
1415
4fe88d28
LP
1416char *path_kill_slashes(char *path) {
1417 char *f, *t;
1418 bool slash = false;
1419
1420 /* Removes redundant inner and trailing slashes. Modifies the
1421 * passed string in-place.
1422 *
1423 * ///foo///bar/ becomes /foo/bar
1424 */
1425
1426 for (f = path, t = path; *f; f++) {
1427
1428 if (*f == '/') {
1429 slash = true;
1430 continue;
1431 }
1432
1433 if (slash) {
1434 slash = false;
1435 *(t++) = '/';
1436 }
1437
1438 *(t++) = *f;
1439 }
1440
1441 /* Special rule, if we are talking of the root directory, a
1442 trailing slash is good */
1443
1444 if (t == path && slash)
1445 *(t++) = '/';
1446
1447 *t = 0;
1448 return path;
1449}
1450
1451bool path_startswith(const char *path, const char *prefix) {
1452 assert(path);
1453 assert(prefix);
1454
1455 if ((path[0] == '/') != (prefix[0] == '/'))
1456 return false;
1457
1458 for (;;) {
1459 size_t a, b;
1460
1461 path += strspn(path, "/");
1462 prefix += strspn(prefix, "/");
1463
1464 if (*prefix == 0)
1465 return true;
1466
1467 if (*path == 0)
1468 return false;
1469
1470 a = strcspn(path, "/");
1471 b = strcspn(prefix, "/");
1472
1473 if (a != b)
1474 return false;
1475
1476 if (memcmp(path, prefix, a) != 0)
1477 return false;
1478
1479 path += a;
1480 prefix += b;
1481 }
1482}
1483
15ae422b
LP
1484bool path_equal(const char *a, const char *b) {
1485 assert(a);
1486 assert(b);
1487
1488 if ((a[0] == '/') != (b[0] == '/'))
1489 return false;
1490
1491 for (;;) {
1492 size_t j, k;
1493
1494 a += strspn(a, "/");
1495 b += strspn(b, "/");
1496
1497 if (*a == 0 && *b == 0)
1498 return true;
1499
1500 if (*a == 0 || *b == 0)
1501 return false;
1502
1503 j = strcspn(a, "/");
1504 k = strcspn(b, "/");
1505
1506 if (j != k)
1507 return false;
1508
1509 if (memcmp(a, b, j) != 0)
1510 return false;
1511
1512 a += j;
1513 b += k;
1514 }
1515}
1516
67d51650 1517char *ascii_strlower(char *t) {
4fe88d28
LP
1518 char *p;
1519
67d51650 1520 assert(t);
4fe88d28 1521
67d51650 1522 for (p = t; *p; p++)
4fe88d28
LP
1523 if (*p >= 'A' && *p <= 'Z')
1524 *p = *p - 'A' + 'a';
1525
67d51650 1526 return t;
4fe88d28 1527}
1dccbe19 1528
c85dc17b
LP
1529bool ignore_file(const char *filename) {
1530 assert(filename);
1531
1532 return
1533 filename[0] == '.' ||
6c78be3c 1534 streq(filename, "lost+found") ||
c85dc17b
LP
1535 endswith(filename, "~") ||
1536 endswith(filename, ".rpmnew") ||
1537 endswith(filename, ".rpmsave") ||
1538 endswith(filename, ".rpmorig") ||
1539 endswith(filename, ".dpkg-old") ||
1540 endswith(filename, ".dpkg-new") ||
1541 endswith(filename, ".swp");
1542}
1543
3a0ecb08
LP
1544int fd_nonblock(int fd, bool nonblock) {
1545 int flags;
1546
1547 assert(fd >= 0);
1548
1549 if ((flags = fcntl(fd, F_GETFL, 0)) < 0)
1550 return -errno;
1551
1552 if (nonblock)
1553 flags |= O_NONBLOCK;
1554 else
1555 flags &= ~O_NONBLOCK;
1556
1557 if (fcntl(fd, F_SETFL, flags) < 0)
1558 return -errno;
1559
1560 return 0;
1561}
1562
1563int fd_cloexec(int fd, bool cloexec) {
1564 int flags;
1565
1566 assert(fd >= 0);
1567
1568 if ((flags = fcntl(fd, F_GETFD, 0)) < 0)
1569 return -errno;
1570
1571 if (cloexec)
1572 flags |= FD_CLOEXEC;
1573 else
1574 flags &= ~FD_CLOEXEC;
1575
1576 if (fcntl(fd, F_SETFD, flags) < 0)
1577 return -errno;
1578
1579 return 0;
1580}
1581
a0d40ac5
LP
1582int close_all_fds(const int except[], unsigned n_except) {
1583 DIR *d;
1584 struct dirent *de;
1585 int r = 0;
1586
1587 if (!(d = opendir("/proc/self/fd")))
1588 return -errno;
1589
1590 while ((de = readdir(d))) {
a7610064 1591 int fd = -1;
a0d40ac5 1592
a16e1123 1593 if (ignore_file(de->d_name))
a0d40ac5
LP
1594 continue;
1595
1596 if ((r = safe_atoi(de->d_name, &fd)) < 0)
1597 goto finish;
1598
1599 if (fd < 3)
1600 continue;
1601
1602 if (fd == dirfd(d))
1603 continue;
1604
1605 if (except) {
1606 bool found;
1607 unsigned i;
1608
1609 found = false;
1610 for (i = 0; i < n_except; i++)
1611 if (except[i] == fd) {
1612 found = true;
1613 break;
1614 }
1615
1616 if (found)
1617 continue;
1618 }
1619
2f357920
LP
1620 if ((r = close_nointr(fd)) < 0) {
1621 /* Valgrind has its own FD and doesn't want to have it closed */
1622 if (errno != EBADF)
1623 goto finish;
1624 }
a0d40ac5
LP
1625 }
1626
2f357920
LP
1627 r = 0;
1628
a0d40ac5
LP
1629finish:
1630 closedir(d);
1631 return r;
1632}
1633
db12775d
LP
1634bool chars_intersect(const char *a, const char *b) {
1635 const char *p;
1636
1637 /* Returns true if any of the chars in a are in b. */
1638 for (p = a; *p; p++)
1639 if (strchr(b, *p))
1640 return true;
1641
1642 return false;
1643}
1644
8b6c7120
LP
1645char *format_timestamp(char *buf, size_t l, usec_t t) {
1646 struct tm tm;
1647 time_t sec;
1648
1649 assert(buf);
1650 assert(l > 0);
1651
1652 if (t <= 0)
1653 return NULL;
1654
f872ec33 1655 sec = (time_t) (t / USEC_PER_SEC);
8b6c7120
LP
1656
1657 if (strftime(buf, l, "%a, %d %b %Y %H:%M:%S %z", localtime_r(&sec, &tm)) <= 0)
1658 return NULL;
1659
1660 return buf;
1661}
1662
584be568
LP
1663char *format_timestamp_pretty(char *buf, size_t l, usec_t t) {
1664 usec_t n, d;
1665
1666 n = now(CLOCK_REALTIME);
1667
1668 if (t <= 0 || t > n || t + USEC_PER_DAY*7 <= t)
1669 return NULL;
1670
1671 d = n - t;
1672
1673 if (d >= USEC_PER_YEAR)
1674 snprintf(buf, l, "%llu years and %llu months ago",
1675 (unsigned long long) (d / USEC_PER_YEAR),
1676 (unsigned long long) ((d % USEC_PER_YEAR) / USEC_PER_MONTH));
1677 else if (d >= USEC_PER_MONTH)
1678 snprintf(buf, l, "%llu months and %llu days ago",
1679 (unsigned long long) (d / USEC_PER_MONTH),
1680 (unsigned long long) ((d % USEC_PER_MONTH) / USEC_PER_DAY));
1681 else if (d >= USEC_PER_WEEK)
1682 snprintf(buf, l, "%llu weeks and %llu days ago",
1683 (unsigned long long) (d / USEC_PER_WEEK),
1684 (unsigned long long) ((d % USEC_PER_WEEK) / USEC_PER_DAY));
1685 else if (d >= 2*USEC_PER_DAY)
1686 snprintf(buf, l, "%llu days ago", (unsigned long long) (d / USEC_PER_DAY));
1687 else if (d >= 25*USEC_PER_HOUR)
1688 snprintf(buf, l, "1 day and %lluh ago",
1689 (unsigned long long) ((d - USEC_PER_DAY) / USEC_PER_HOUR));
1690 else if (d >= 6*USEC_PER_HOUR)
1691 snprintf(buf, l, "%lluh ago",
1692 (unsigned long long) (d / USEC_PER_HOUR));
1693 else if (d >= USEC_PER_HOUR)
1694 snprintf(buf, l, "%lluh %llumin ago",
1695 (unsigned long long) (d / USEC_PER_HOUR),
1696 (unsigned long long) ((d % USEC_PER_HOUR) / USEC_PER_MINUTE));
1697 else if (d >= 5*USEC_PER_MINUTE)
1698 snprintf(buf, l, "%llumin ago",
1699 (unsigned long long) (d / USEC_PER_MINUTE));
1700 else if (d >= USEC_PER_MINUTE)
1701 snprintf(buf, l, "%llumin %llus ago",
1702 (unsigned long long) (d / USEC_PER_MINUTE),
1703 (unsigned long long) ((d % USEC_PER_MINUTE) / USEC_PER_SEC));
1704 else if (d >= USEC_PER_SEC)
1705 snprintf(buf, l, "%llus ago",
1706 (unsigned long long) (d / USEC_PER_SEC));
1707 else if (d >= USEC_PER_MSEC)
1708 snprintf(buf, l, "%llums ago",
1709 (unsigned long long) (d / USEC_PER_MSEC));
1710 else if (d > 0)
1711 snprintf(buf, l, "%lluus ago",
1712 (unsigned long long) d);
1713 else
1714 snprintf(buf, l, "now");
1715
1716 buf[l-1] = 0;
1717 return buf;
1718}
1719
871d7de4
LP
1720char *format_timespan(char *buf, size_t l, usec_t t) {
1721 static const struct {
1722 const char *suffix;
1723 usec_t usec;
1724 } table[] = {
1725 { "w", USEC_PER_WEEK },
1726 { "d", USEC_PER_DAY },
1727 { "h", USEC_PER_HOUR },
1728 { "min", USEC_PER_MINUTE },
1729 { "s", USEC_PER_SEC },
1730 { "ms", USEC_PER_MSEC },
1731 { "us", 1 },
1732 };
1733
1734 unsigned i;
1735 char *p = buf;
1736
1737 assert(buf);
1738 assert(l > 0);
1739
1740 if (t == (usec_t) -1)
1741 return NULL;
1742
4502d22c
LP
1743 if (t == 0) {
1744 snprintf(p, l, "0");
1745 p[l-1] = 0;
1746 return p;
1747 }
1748
871d7de4
LP
1749 /* The result of this function can be parsed with parse_usec */
1750
1751 for (i = 0; i < ELEMENTSOF(table); i++) {
1752 int k;
1753 size_t n;
1754
1755 if (t < table[i].usec)
1756 continue;
1757
1758 if (l <= 1)
1759 break;
1760
1761 k = snprintf(p, l, "%s%llu%s", p > buf ? " " : "", (unsigned long long) (t / table[i].usec), table[i].suffix);
1762 n = MIN((size_t) k, l);
1763
1764 l -= n;
1765 p += n;
1766
1767 t %= table[i].usec;
1768 }
1769
1770 *p = 0;
1771
1772 return buf;
1773}
1774
42856c10
LP
1775bool fstype_is_network(const char *fstype) {
1776 static const char * const table[] = {
1777 "cifs",
1778 "smbfs",
1779 "ncpfs",
1780 "nfs",
ca139f94
LP
1781 "nfs4",
1782 "gfs",
1783 "gfs2"
42856c10
LP
1784 };
1785
1786 unsigned i;
1787
1788 for (i = 0; i < ELEMENTSOF(table); i++)
1789 if (streq(table[i], fstype))
1790 return true;
1791
1792 return false;
1793}
1794
601f6a1e
LP
1795int chvt(int vt) {
1796 int fd, r = 0;
1797
1798 if ((fd = open("/dev/tty0", O_RDWR|O_NOCTTY|O_CLOEXEC)) < 0)
1799 return -errno;
1800
1801 if (vt < 0) {
1802 int tiocl[2] = {
1803 TIOCL_GETKMSGREDIRECT,
1804 0
1805 };
1806
1807 if (ioctl(fd, TIOCLINUX, tiocl) < 0)
1808 return -errno;
1809
1810 vt = tiocl[0] <= 0 ? 1 : tiocl[0];
1811 }
1812
1813 if (ioctl(fd, VT_ACTIVATE, vt) < 0)
1814 r = -errno;
1815
a16e1123 1816 close_nointr_nofail(r);
601f6a1e
LP
1817 return r;
1818}
1819
80876c20
LP
1820int read_one_char(FILE *f, char *ret, bool *need_nl) {
1821 struct termios old_termios, new_termios;
1822 char c;
1823 char line[1024];
1824
1825 assert(f);
1826 assert(ret);
1827
1828 if (tcgetattr(fileno(f), &old_termios) >= 0) {
1829 new_termios = old_termios;
1830
1831 new_termios.c_lflag &= ~ICANON;
1832 new_termios.c_cc[VMIN] = 1;
1833 new_termios.c_cc[VTIME] = 0;
1834
1835 if (tcsetattr(fileno(f), TCSADRAIN, &new_termios) >= 0) {
1836 size_t k;
1837
1838 k = fread(&c, 1, 1, f);
1839
1840 tcsetattr(fileno(f), TCSADRAIN, &old_termios);
1841
1842 if (k <= 0)
1843 return -EIO;
1844
1845 if (need_nl)
1846 *need_nl = c != '\n';
1847
1848 *ret = c;
1849 return 0;
1850 }
1851 }
1852
1853 if (!(fgets(line, sizeof(line), f)))
1854 return -EIO;
1855
1856 truncate_nl(line);
1857
1858 if (strlen(line) != 1)
1859 return -EBADMSG;
1860
1861 if (need_nl)
1862 *need_nl = false;
1863
1864 *ret = line[0];
1865 return 0;
1866}
1867
1868int ask(char *ret, const char *replies, const char *text, ...) {
1869 assert(ret);
1870 assert(replies);
1871 assert(text);
1872
1873 for (;;) {
1874 va_list ap;
1875 char c;
1876 int r;
1877 bool need_nl = true;
1878
b1b2dc0c
LP
1879 fputs("\x1B[1m", stdout);
1880
80876c20
LP
1881 va_start(ap, text);
1882 vprintf(text, ap);
1883 va_end(ap);
1884
b1b2dc0c
LP
1885 fputs("\x1B[0m", stdout);
1886
80876c20
LP
1887 fflush(stdout);
1888
1889 if ((r = read_one_char(stdin, &c, &need_nl)) < 0) {
1890
1891 if (r == -EBADMSG) {
1892 puts("Bad input, please try again.");
1893 continue;
1894 }
1895
1896 putchar('\n');
1897 return r;
1898 }
1899
1900 if (need_nl)
1901 putchar('\n');
1902
1903 if (strchr(replies, c)) {
1904 *ret = c;
1905 return 0;
1906 }
1907
1908 puts("Read unexpected character, please try again.");
1909 }
1910}
1911
1912int reset_terminal(int fd) {
1913 struct termios termios;
1914 int r = 0;
3fe5e5d4
LP
1915 long arg;
1916
1917 /* Set terminal to some sane defaults */
80876c20
LP
1918
1919 assert(fd >= 0);
1920
eed1d0e3
LP
1921 /* We leave locked terminal attributes untouched, so that
1922 * Plymouth may set whatever it wants to set, and we don't
1923 * interfere with that. */
3fe5e5d4
LP
1924
1925 /* Disable exclusive mode, just in case */
1926 ioctl(fd, TIOCNXCL);
1927
1928 /* Enable console unicode mode */
1929 arg = K_UNICODE;
1930 ioctl(fd, KDSKBMODE, &arg);
80876c20
LP
1931
1932 if (tcgetattr(fd, &termios) < 0) {
1933 r = -errno;
1934 goto finish;
1935 }
1936
aaf694ca
LP
1937 /* We only reset the stuff that matters to the software. How
1938 * hardware is set up we don't touch assuming that somebody
1939 * else will do that for us */
1940
1941 termios.c_iflag &= ~(IGNBRK | BRKINT | ISTRIP | INLCR | IGNCR | IUCLC);
80876c20
LP
1942 termios.c_iflag |= ICRNL | IMAXBEL | IUTF8;
1943 termios.c_oflag |= ONLCR;
1944 termios.c_cflag |= CREAD;
1945 termios.c_lflag = ISIG | ICANON | IEXTEN | ECHO | ECHOE | ECHOK | ECHOCTL | ECHOPRT | ECHOKE;
1946
1947 termios.c_cc[VINTR] = 03; /* ^C */
1948 termios.c_cc[VQUIT] = 034; /* ^\ */
1949 termios.c_cc[VERASE] = 0177;
1950 termios.c_cc[VKILL] = 025; /* ^X */
1951 termios.c_cc[VEOF] = 04; /* ^D */
1952 termios.c_cc[VSTART] = 021; /* ^Q */
1953 termios.c_cc[VSTOP] = 023; /* ^S */
1954 termios.c_cc[VSUSP] = 032; /* ^Z */
1955 termios.c_cc[VLNEXT] = 026; /* ^V */
1956 termios.c_cc[VWERASE] = 027; /* ^W */
1957 termios.c_cc[VREPRINT] = 022; /* ^R */
aaf694ca
LP
1958 termios.c_cc[VEOL] = 0;
1959 termios.c_cc[VEOL2] = 0;
80876c20
LP
1960
1961 termios.c_cc[VTIME] = 0;
1962 termios.c_cc[VMIN] = 1;
1963
1964 if (tcsetattr(fd, TCSANOW, &termios) < 0)
1965 r = -errno;
1966
1967finish:
1968 /* Just in case, flush all crap out */
1969 tcflush(fd, TCIOFLUSH);
1970
1971 return r;
1972}
1973
1974int open_terminal(const char *name, int mode) {
1975 int fd, r;
1976
1977 if ((fd = open(name, mode)) < 0)
1978 return -errno;
1979
1980 if ((r = isatty(fd)) < 0) {
1981 close_nointr_nofail(fd);
1982 return -errno;
1983 }
1984
1985 if (!r) {
1986 close_nointr_nofail(fd);
1987 return -ENOTTY;
1988 }
1989
1990 return fd;
1991}
1992
1993int flush_fd(int fd) {
1994 struct pollfd pollfd;
1995
1996 zero(pollfd);
1997 pollfd.fd = fd;
1998 pollfd.events = POLLIN;
1999
2000 for (;;) {
2001 char buf[1024];
2002 ssize_t l;
2003 int r;
2004
2005 if ((r = poll(&pollfd, 1, 0)) < 0) {
2006
2007 if (errno == EINTR)
2008 continue;
2009
2010 return -errno;
2011 }
2012
2013 if (r == 0)
2014 return 0;
2015
2016 if ((l = read(fd, buf, sizeof(buf))) < 0) {
2017
2018 if (errno == EINTR)
2019 continue;
2020
2021 if (errno == EAGAIN)
2022 return 0;
2023
2024 return -errno;
2025 }
2026
2027 if (l <= 0)
2028 return 0;
2029 }
2030}
2031
21de3988 2032int acquire_terminal(const char *name, bool fail, bool force, bool ignore_tiocstty_eperm) {
bab45044 2033 int fd = -1, notify = -1, r, wd = -1;
80876c20
LP
2034
2035 assert(name);
2036
2037 /* We use inotify to be notified when the tty is closed. We
2038 * create the watch before checking if we can actually acquire
2039 * it, so that we don't lose any event.
2040 *
2041 * Note: strictly speaking this actually watches for the
2042 * device being closed, it does *not* really watch whether a
2043 * tty loses its controlling process. However, unless some
2044 * rogue process uses TIOCNOTTY on /dev/tty *after* closing
2045 * its tty otherwise this will not become a problem. As long
2046 * as the administrator makes sure not configure any service
2047 * on the same tty as an untrusted user this should not be a
2048 * problem. (Which he probably should not do anyway.) */
2049
2050 if (!fail && !force) {
2051 if ((notify = inotify_init1(IN_CLOEXEC)) < 0) {
2052 r = -errno;
2053 goto fail;
2054 }
2055
2056 if ((wd = inotify_add_watch(notify, name, IN_CLOSE)) < 0) {
2057 r = -errno;
2058 goto fail;
2059 }
2060 }
2061
2062 for (;;) {
e3d1855b
LP
2063 if (notify >= 0)
2064 if ((r = flush_fd(notify)) < 0)
2065 goto fail;
80876c20
LP
2066
2067 /* We pass here O_NOCTTY only so that we can check the return
2068 * value TIOCSCTTY and have a reliable way to figure out if we
2069 * successfully became the controlling process of the tty */
2070 if ((fd = open_terminal(name, O_RDWR|O_NOCTTY)) < 0)
2071 return -errno;
2072
2073 /* First, try to get the tty */
21de3988
LP
2074 r = ioctl(fd, TIOCSCTTY, force);
2075
2076 /* Sometimes it makes sense to ignore TIOCSCTTY
2077 * returning EPERM, i.e. when very likely we already
2078 * are have this controlling terminal. */
2079 if (r < 0 && errno == EPERM && ignore_tiocstty_eperm)
2080 r = 0;
2081
2082 if (r < 0 && (force || fail || errno != EPERM)) {
80876c20
LP
2083 r = -errno;
2084 goto fail;
2085 }
2086
2087 if (r >= 0)
2088 break;
2089
2090 assert(!fail);
2091 assert(!force);
2092 assert(notify >= 0);
2093
2094 for (;;) {
2095 struct inotify_event e;
2096 ssize_t l;
2097
2098 if ((l = read(notify, &e, sizeof(e))) != sizeof(e)) {
2099
2100 if (l < 0) {
2101
2102 if (errno == EINTR)
2103 continue;
2104
2105 r = -errno;
2106 } else
2107 r = -EIO;
2108
2109 goto fail;
2110 }
2111
2112 if (e.wd != wd || !(e.mask & IN_CLOSE)) {
7bc0351d 2113 r = -EIO;
80876c20
LP
2114 goto fail;
2115 }
2116
2117 break;
2118 }
2119
2120 /* We close the tty fd here since if the old session
2121 * ended our handle will be dead. It's important that
2122 * we do this after sleeping, so that we don't enter
2123 * an endless loop. */
2124 close_nointr_nofail(fd);
2125 }
2126
2127 if (notify >= 0)
a16e1123 2128 close_nointr_nofail(notify);
80876c20
LP
2129
2130 if ((r = reset_terminal(fd)) < 0)
2131 log_warning("Failed to reset terminal: %s", strerror(-r));
2132
2133 return fd;
2134
2135fail:
2136 if (fd >= 0)
a16e1123 2137 close_nointr_nofail(fd);
80876c20
LP
2138
2139 if (notify >= 0)
a16e1123 2140 close_nointr_nofail(notify);
80876c20
LP
2141
2142 return r;
2143}
2144
2145int release_terminal(void) {
2146 int r = 0, fd;
57cd2192 2147 struct sigaction sa_old, sa_new;
80876c20 2148
57cd2192 2149 if ((fd = open("/dev/tty", O_RDWR|O_NOCTTY|O_NDELAY)) < 0)
80876c20
LP
2150 return -errno;
2151
57cd2192
LP
2152 /* Temporarily ignore SIGHUP, so that we don't get SIGHUP'ed
2153 * by our own TIOCNOTTY */
2154
2155 zero(sa_new);
2156 sa_new.sa_handler = SIG_IGN;
2157 sa_new.sa_flags = SA_RESTART;
2158 assert_se(sigaction(SIGHUP, &sa_new, &sa_old) == 0);
2159
80876c20
LP
2160 if (ioctl(fd, TIOCNOTTY) < 0)
2161 r = -errno;
2162
57cd2192
LP
2163 assert_se(sigaction(SIGHUP, &sa_old, NULL) == 0);
2164
80876c20
LP
2165 close_nointr_nofail(fd);
2166 return r;
2167}
2168
9a34ec5f
LP
2169int sigaction_many(const struct sigaction *sa, ...) {
2170 va_list ap;
2171 int r = 0, sig;
2172
2173 va_start(ap, sa);
2174 while ((sig = va_arg(ap, int)) > 0)
2175 if (sigaction(sig, sa, NULL) < 0)
2176 r = -errno;
2177 va_end(ap);
2178
2179 return r;
2180}
2181
2182int ignore_signals(int sig, ...) {
a337c6fc 2183 struct sigaction sa;
9a34ec5f
LP
2184 va_list ap;
2185 int r = 0;
a337c6fc
LP
2186
2187 zero(sa);
2188 sa.sa_handler = SIG_IGN;
2189 sa.sa_flags = SA_RESTART;
2190
9a34ec5f
LP
2191 if (sigaction(sig, &sa, NULL) < 0)
2192 r = -errno;
2193
2194 va_start(ap, sig);
2195 while ((sig = va_arg(ap, int)) > 0)
2196 if (sigaction(sig, &sa, NULL) < 0)
2197 r = -errno;
2198 va_end(ap);
2199
2200 return r;
2201}
2202
2203int default_signals(int sig, ...) {
2204 struct sigaction sa;
2205 va_list ap;
2206 int r = 0;
2207
2208 zero(sa);
2209 sa.sa_handler = SIG_DFL;
2210 sa.sa_flags = SA_RESTART;
2211
2212 if (sigaction(sig, &sa, NULL) < 0)
2213 r = -errno;
2214
2215 va_start(ap, sig);
2216 while ((sig = va_arg(ap, int)) > 0)
2217 if (sigaction(sig, &sa, NULL) < 0)
2218 r = -errno;
2219 va_end(ap);
2220
2221 return r;
a337c6fc
LP
2222}
2223
8d567588
LP
2224int close_pipe(int p[]) {
2225 int a = 0, b = 0;
2226
2227 assert(p);
2228
2229 if (p[0] >= 0) {
2230 a = close_nointr(p[0]);
2231 p[0] = -1;
2232 }
2233
2234 if (p[1] >= 0) {
2235 b = close_nointr(p[1]);
2236 p[1] = -1;
2237 }
2238
2239 return a < 0 ? a : b;
2240}
2241
eb22ac37 2242ssize_t loop_read(int fd, void *buf, size_t nbytes, bool do_poll) {
8d567588
LP
2243 uint8_t *p;
2244 ssize_t n = 0;
2245
2246 assert(fd >= 0);
2247 assert(buf);
2248
2249 p = buf;
2250
2251 while (nbytes > 0) {
2252 ssize_t k;
2253
2254 if ((k = read(fd, p, nbytes)) <= 0) {
2255
eb22ac37 2256 if (k < 0 && errno == EINTR)
8d567588
LP
2257 continue;
2258
eb22ac37 2259 if (k < 0 && errno == EAGAIN && do_poll) {
8d567588
LP
2260 struct pollfd pollfd;
2261
2262 zero(pollfd);
2263 pollfd.fd = fd;
2264 pollfd.events = POLLIN;
2265
2266 if (poll(&pollfd, 1, -1) < 0) {
2267 if (errno == EINTR)
2268 continue;
2269
2270 return n > 0 ? n : -errno;
2271 }
2272
2273 if (pollfd.revents != POLLIN)
2274 return n > 0 ? n : -EIO;
2275
2276 continue;
2277 }
2278
2279 return n > 0 ? n : (k < 0 ? -errno : 0);
2280 }
2281
2282 p += k;
2283 nbytes -= k;
2284 n += k;
2285 }
2286
2287 return n;
2288}
2289
eb22ac37
LP
2290ssize_t loop_write(int fd, const void *buf, size_t nbytes, bool do_poll) {
2291 const uint8_t *p;
2292 ssize_t n = 0;
2293
2294 assert(fd >= 0);
2295 assert(buf);
2296
2297 p = buf;
2298
2299 while (nbytes > 0) {
2300 ssize_t k;
2301
2302 if ((k = write(fd, p, nbytes)) <= 0) {
2303
2304 if (k < 0 && errno == EINTR)
2305 continue;
2306
2307 if (k < 0 && errno == EAGAIN && do_poll) {
2308 struct pollfd pollfd;
2309
2310 zero(pollfd);
2311 pollfd.fd = fd;
2312 pollfd.events = POLLOUT;
2313
2314 if (poll(&pollfd, 1, -1) < 0) {
2315 if (errno == EINTR)
2316 continue;
2317
2318 return n > 0 ? n : -errno;
2319 }
2320
2321 if (pollfd.revents != POLLOUT)
2322 return n > 0 ? n : -EIO;
2323
2324 continue;
2325 }
2326
2327 return n > 0 ? n : (k < 0 ? -errno : 0);
2328 }
2329
2330 p += k;
2331 nbytes -= k;
2332 n += k;
2333 }
2334
2335 return n;
2336}
2337
8d567588
LP
2338int path_is_mount_point(const char *t) {
2339 struct stat a, b;
35d2e7ec
LP
2340 char *parent;
2341 int r;
8d567588
LP
2342
2343 if (lstat(t, &a) < 0) {
8d567588
LP
2344 if (errno == ENOENT)
2345 return 0;
2346
2347 return -errno;
2348 }
2349
35d2e7ec
LP
2350 if ((r = parent_of_path(t, &parent)) < 0)
2351 return r;
8d567588 2352
35d2e7ec
LP
2353 r = lstat(parent, &b);
2354 free(parent);
8d567588 2355
35d2e7ec
LP
2356 if (r < 0)
2357 return -errno;
8d567588
LP
2358
2359 return a.st_dev != b.st_dev;
2360}
2361
24a6e4a4
LP
2362int parse_usec(const char *t, usec_t *usec) {
2363 static const struct {
2364 const char *suffix;
2365 usec_t usec;
2366 } table[] = {
2367 { "sec", USEC_PER_SEC },
2368 { "s", USEC_PER_SEC },
2369 { "min", USEC_PER_MINUTE },
2370 { "hr", USEC_PER_HOUR },
2371 { "h", USEC_PER_HOUR },
2372 { "d", USEC_PER_DAY },
2373 { "w", USEC_PER_WEEK },
2374 { "msec", USEC_PER_MSEC },
2375 { "ms", USEC_PER_MSEC },
2376 { "m", USEC_PER_MINUTE },
2377 { "usec", 1ULL },
2378 { "us", 1ULL },
2379 { "", USEC_PER_SEC },
2380 };
2381
2382 const char *p;
2383 usec_t r = 0;
2384
2385 assert(t);
2386 assert(usec);
2387
2388 p = t;
2389 do {
2390 long long l;
2391 char *e;
2392 unsigned i;
2393
2394 errno = 0;
2395 l = strtoll(p, &e, 10);
2396
2397 if (errno != 0)
2398 return -errno;
2399
2400 if (l < 0)
2401 return -ERANGE;
2402
2403 if (e == p)
2404 return -EINVAL;
2405
2406 e += strspn(e, WHITESPACE);
2407
2408 for (i = 0; i < ELEMENTSOF(table); i++)
2409 if (startswith(e, table[i].suffix)) {
2410 r += (usec_t) l * table[i].usec;
2411 p = e + strlen(table[i].suffix);
2412 break;
2413 }
2414
2415 if (i >= ELEMENTSOF(table))
2416 return -EINVAL;
2417
2418 } while (*p != 0);
2419
2420 *usec = r;
2421
2422 return 0;
2423}
2424
843d2643
LP
2425int make_stdio(int fd) {
2426 int r, s, t;
2427
2428 assert(fd >= 0);
2429
2430 r = dup2(fd, STDIN_FILENO);
2431 s = dup2(fd, STDOUT_FILENO);
2432 t = dup2(fd, STDERR_FILENO);
2433
2434 if (fd >= 3)
2435 close_nointr_nofail(fd);
2436
2437 if (r < 0 || s < 0 || t < 0)
2438 return -errno;
2439
2440 return 0;
2441}
2442
cb8a8f78
LP
2443bool is_clean_exit(int code, int status) {
2444
2445 if (code == CLD_EXITED)
2446 return status == 0;
2447
2448 /* If a daemon does not implement handlers for some of the
2449 * signals that's not considered an unclean shutdown */
2450 if (code == CLD_KILLED)
2451 return
2452 status == SIGHUP ||
2453 status == SIGINT ||
2454 status == SIGTERM ||
2455 status == SIGPIPE;
2456
2457 return false;
2458}
2459
d06dacd0
LP
2460bool is_clean_exit_lsb(int code, int status) {
2461
2462 if (is_clean_exit(code, status))
2463 return true;
2464
2465 return
2466 code == CLD_EXITED &&
2467 (status == EXIT_NOTINSTALLED || status == EXIT_NOTCONFIGURED);
2468}
2469
8407a5d0
LP
2470bool is_device_path(const char *path) {
2471
2472 /* Returns true on paths that refer to a device, either in
2473 * sysfs or in /dev */
2474
2475 return
2476 path_startswith(path, "/dev/") ||
2477 path_startswith(path, "/sys/");
2478}
2479
01f78473
LP
2480int dir_is_empty(const char *path) {
2481 DIR *d;
2482 int r;
2483 struct dirent buf, *de;
2484
2485 if (!(d = opendir(path)))
2486 return -errno;
2487
2488 for (;;) {
2489 if ((r = readdir_r(d, &buf, &de)) > 0) {
2490 r = -r;
2491 break;
2492 }
2493
2494 if (!de) {
2495 r = 1;
2496 break;
2497 }
2498
2499 if (!ignore_file(de->d_name)) {
2500 r = 0;
2501 break;
2502 }
2503 }
2504
2505 closedir(d);
2506 return r;
2507}
2508
d3782d60
LP
2509unsigned long long random_ull(void) {
2510 int fd;
2511 uint64_t ull;
2512 ssize_t r;
2513
2514 if ((fd = open("/dev/urandom", O_RDONLY|O_CLOEXEC|O_NOCTTY)) < 0)
2515 goto fallback;
2516
eb22ac37 2517 r = loop_read(fd, &ull, sizeof(ull), true);
d3782d60
LP
2518 close_nointr_nofail(fd);
2519
2520 if (r != sizeof(ull))
2521 goto fallback;
2522
2523 return ull;
2524
2525fallback:
2526 return random() * RAND_MAX + random();
2527}
2528
5b6319dc
LP
2529void rename_process(const char name[8]) {
2530 assert(name);
2531
2532 prctl(PR_SET_NAME, name);
2533
2534 /* This is a like a poor man's setproctitle(). The string
2535 * passed should fit in 7 chars (i.e. the length of
2536 * "systemd") */
2537
2538 if (program_invocation_name)
2539 strncpy(program_invocation_name, name, strlen(program_invocation_name));
2540}
2541
7d793605
LP
2542void sigset_add_many(sigset_t *ss, ...) {
2543 va_list ap;
2544 int sig;
2545
2546 assert(ss);
2547
2548 va_start(ap, ss);
2549 while ((sig = va_arg(ap, int)) > 0)
2550 assert_se(sigaddset(ss, sig) == 0);
2551 va_end(ap);
2552}
2553
ef2f1067
LP
2554char* gethostname_malloc(void) {
2555 struct utsname u;
2556
2557 assert_se(uname(&u) >= 0);
2558
2559 if (u.nodename[0])
2560 return strdup(u.nodename);
2561
2562 return strdup(u.sysname);
2563}
2564
2565char* getlogname_malloc(void) {
2566 uid_t uid;
2567 long bufsize;
2568 char *buf, *name;
2569 struct passwd pwbuf, *pw = NULL;
2570 struct stat st;
2571
2572 if (isatty(STDIN_FILENO) && fstat(STDIN_FILENO, &st) >= 0)
2573 uid = st.st_uid;
2574 else
2575 uid = getuid();
2576
2577 /* Shortcut things to avoid NSS lookups */
2578 if (uid == 0)
2579 return strdup("root");
2580
2581 if ((bufsize = sysconf(_SC_GETPW_R_SIZE_MAX)) <= 0)
2582 bufsize = 4096;
2583
2584 if (!(buf = malloc(bufsize)))
2585 return NULL;
2586
2587 if (getpwuid_r(uid, &pwbuf, buf, bufsize, &pw) == 0 && pw) {
2588 name = strdup(pw->pw_name);
2589 free(buf);
2590 return name;
2591 }
2592
2593 free(buf);
2594
2595 if (asprintf(&name, "%lu", (unsigned long) uid) < 0)
2596 return NULL;
2597
2598 return name;
2599}
2600
8c6db833
LP
2601int getttyname_malloc(char **r) {
2602 char path[PATH_MAX], *p, *c;
618e02c7 2603 int k;
8c6db833
LP
2604
2605 assert(r);
ef2f1067 2606
618e02c7
LP
2607 if ((k = ttyname_r(STDIN_FILENO, path, sizeof(path))) != 0)
2608 return -k;
ef2f1067
LP
2609
2610 char_array_0(path);
2611
2612 p = path;
2613 if (startswith(path, "/dev/"))
2614 p += 5;
2615
8c6db833
LP
2616 if (!(c = strdup(p)))
2617 return -ENOMEM;
2618
2619 *r = c;
2620 return 0;
2621}
2622
2623static int rm_rf_children(int fd, bool only_dirs) {
2624 DIR *d;
2625 int ret = 0;
2626
2627 assert(fd >= 0);
2628
2629 /* This returns the first error we run into, but nevertheless
2630 * tries to go on */
2631
2632 if (!(d = fdopendir(fd))) {
2633 close_nointr_nofail(fd);
4c633005
LP
2634
2635 return errno == ENOENT ? 0 : -errno;
8c6db833
LP
2636 }
2637
2638 for (;;) {
2639 struct dirent buf, *de;
2640 bool is_dir;
2641 int r;
2642
2643 if ((r = readdir_r(d, &buf, &de)) != 0) {
2644 if (ret == 0)
2645 ret = -r;
2646 break;
2647 }
2648
2649 if (!de)
2650 break;
2651
2652 if (streq(de->d_name, ".") || streq(de->d_name, ".."))
2653 continue;
2654
2655 if (de->d_type == DT_UNKNOWN) {
2656 struct stat st;
2657
2658 if (fstatat(fd, de->d_name, &st, AT_SYMLINK_NOFOLLOW) < 0) {
4c633005 2659 if (ret == 0 && errno != ENOENT)
8c6db833
LP
2660 ret = -errno;
2661 continue;
2662 }
2663
2664 is_dir = S_ISDIR(st.st_mode);
2665 } else
2666 is_dir = de->d_type == DT_DIR;
2667
2668 if (is_dir) {
2669 int subdir_fd;
2670
2671 if ((subdir_fd = openat(fd, de->d_name, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC)) < 0) {
4c633005 2672 if (ret == 0 && errno != ENOENT)
8c6db833
LP
2673 ret = -errno;
2674 continue;
2675 }
2676
2677 if ((r = rm_rf_children(subdir_fd, only_dirs)) < 0) {
2678 if (ret == 0)
2679 ret = r;
2680 }
2681
2682 if (unlinkat(fd, de->d_name, AT_REMOVEDIR) < 0) {
4c633005 2683 if (ret == 0 && errno != ENOENT)
8c6db833
LP
2684 ret = -errno;
2685 }
2686 } else if (!only_dirs) {
2687
2688 if (unlinkat(fd, de->d_name, 0) < 0) {
4c633005 2689 if (ret == 0 && errno != ENOENT)
8c6db833
LP
2690 ret = -errno;
2691 }
2692 }
2693 }
2694
2695 closedir(d);
2696
2697 return ret;
2698}
2699
2700int rm_rf(const char *path, bool only_dirs, bool delete_root) {
2701 int fd;
2702 int r;
2703
2704 assert(path);
2705
2706 if ((fd = open(path, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC)) < 0) {
2707
2708 if (errno != ENOTDIR)
2709 return -errno;
2710
2711 if (delete_root && !only_dirs)
2712 if (unlink(path) < 0)
2713 return -errno;
2714
2715 return 0;
2716 }
2717
2718 r = rm_rf_children(fd, only_dirs);
2719
2720 if (delete_root)
2721 if (rmdir(path) < 0) {
2722 if (r == 0)
2723 r = -errno;
2724 }
2725
2726 return r;
2727}
2728
2729int chmod_and_chown(const char *path, mode_t mode, uid_t uid, gid_t gid) {
2730 assert(path);
2731
2732 /* Under the assumption that we are running privileged we
2733 * first change the access mode and only then hand out
2734 * ownership to avoid a window where access is too open. */
2735
2736 if (chmod(path, mode) < 0)
2737 return -errno;
2738
2739 if (chown(path, uid, gid) < 0)
2740 return -errno;
2741
2742 return 0;
ef2f1067
LP
2743}
2744
82c121a4
LP
2745cpu_set_t* cpu_set_malloc(unsigned *ncpus) {
2746 cpu_set_t *r;
2747 unsigned n = 1024;
2748
2749 /* Allocates the cpuset in the right size */
2750
2751 for (;;) {
2752 if (!(r = CPU_ALLOC(n)))
2753 return NULL;
2754
2755 if (sched_getaffinity(0, CPU_ALLOC_SIZE(n), r) >= 0) {
2756 CPU_ZERO_S(CPU_ALLOC_SIZE(n), r);
2757
2758 if (ncpus)
2759 *ncpus = n;
2760
2761 return r;
2762 }
2763
2764 CPU_FREE(r);
2765
2766 if (errno != EINVAL)
2767 return NULL;
2768
2769 n *= 2;
2770 }
2771}
2772
9e58ff9c
LP
2773void status_vprintf(const char *format, va_list ap) {
2774 char *s = NULL;
2775 int fd = -1;
2776
2777 assert(format);
2778
2779 /* This independent of logging, as status messages are
2780 * optional and go exclusively to the console. */
2781
2782 if (vasprintf(&s, format, ap) < 0)
2783 goto finish;
2784
2785 if ((fd = open_terminal("/dev/console", O_WRONLY|O_NOCTTY|O_CLOEXEC)) < 0)
2786 goto finish;
2787
2788 write(fd, s, strlen(s));
2789
2790finish:
2791 free(s);
2792
2793 if (fd >= 0)
2794 close_nointr_nofail(fd);
2795}
2796
c846ff47
LP
2797void status_printf(const char *format, ...) {
2798 va_list ap;
2799
2800 assert(format);
2801
2802 va_start(ap, format);
2803 status_vprintf(format, ap);
2804 va_end(ap);
2805}
2806
2807void status_welcome(void) {
2808
2809#if defined(TARGET_FEDORA)
2810 char *r;
2811
2812 if (read_one_line_file("/etc/system-release", &r) < 0)
2813 return;
2814
2815 truncate_nl(r);
2816
2817 /* This tries to mimic the color magic the old Red Hat sysinit
2818 * script did. */
2819
2820 if (startswith(r, "Red Hat"))
2e54424d 2821 status_printf("Welcome to \x1B[0;31m%s\x1B[0m!\n", r); /* Red for RHEL */
c846ff47 2822 else if (startswith(r, "Fedora"))
2e54424d 2823 status_printf("Welcome to \x1B[0;34m%s\x1B[0m!\n", r); /* Blue for Fedora */
c846ff47 2824 else
2e54424d 2825 status_printf("Welcome to %s!\n", r);
c846ff47
LP
2826
2827 free(r);
2828
2829#elif defined(TARGET_SUSE)
2830 char *r;
2831
2832 if (read_one_line_file("/etc/SuSE-release", &r) < 0)
2833 return;
2834
2835 truncate_nl(r);
2836
2e54424d 2837 status_printf("Welcome to \x1B[0;32m%s\x1B[0m!\n", r); /* Green for SUSE */
0d37b36b 2838 free(r);
5a6225fd 2839
0d37b36b
GSB
2840#elif defined(TARGET_GENTOO)
2841 char *r;
2842
2843 if (read_one_line_file("/etc/gentoo-release", &r) < 0)
2844 return;
2845
2846 truncate_nl(r);
2847
2848 status_printf("Welcome to \x1B[1;34m%s\x1B[0m!\n", r); /* Light Blue for Gentoo */
2849
c846ff47 2850 free(r);
5a6225fd
SD
2851
2852#elif defined(TARGET_DEBIAN)
2e78aa99 2853 char *r;
5a6225fd 2854
2e78aa99
LP
2855 if (read_one_line_file("/etc/debian_version", &r) < 0)
2856 return;
5a6225fd 2857
2e78aa99 2858 truncate_nl(r);
5a6225fd 2859
2e78aa99 2860 status_printf("Welcome to Debian \x1B[1;31m%s\x1B[0m!\n", r); /* Light Red for Debian */
5a6225fd 2861
2e78aa99 2862 free(r);
17dbb83d 2863#elif defined(TARGET_ARCH)
2e78aa99 2864 status_printf("Welcome to \x1B[1;36mArch Linux\x1B[0m!\n"); /* Cyan for Arch */
c846ff47
LP
2865#else
2866#warning "You probably should add a welcome text logic here."
2867#endif
2868}
2869
fab56fc5
LP
2870char *replace_env(const char *format, char **env) {
2871 enum {
2872 WORD,
c24eb49e 2873 CURLY,
fab56fc5
LP
2874 VARIABLE
2875 } state = WORD;
2876
2877 const char *e, *word = format;
2878 char *r = NULL, *k;
2879
2880 assert(format);
2881
2882 for (e = format; *e; e ++) {
2883
2884 switch (state) {
2885
2886 case WORD:
2887 if (*e == '$')
c24eb49e 2888 state = CURLY;
fab56fc5
LP
2889 break;
2890
c24eb49e
LP
2891 case CURLY:
2892 if (*e == '{') {
fab56fc5
LP
2893 if (!(k = strnappend(r, word, e-word-1)))
2894 goto fail;
2895
2896 free(r);
2897 r = k;
2898
2899 word = e-1;
2900 state = VARIABLE;
2901
2902 } else if (*e == '$') {
2903 if (!(k = strnappend(r, word, e-word)))
2904 goto fail;
2905
2906 free(r);
2907 r = k;
2908
2909 word = e+1;
2910 state = WORD;
2911 } else
2912 state = WORD;
2913 break;
2914
2915 case VARIABLE:
c24eb49e 2916 if (*e == '}') {
b95cf362 2917 const char *t;
fab56fc5 2918
b95cf362
LP
2919 if (!(t = strv_env_get_with_length(env, word+2, e-word-2)))
2920 t = "";
fab56fc5 2921
b95cf362
LP
2922 if (!(k = strappend(r, t)))
2923 goto fail;
fab56fc5 2924
b95cf362
LP
2925 free(r);
2926 r = k;
fab56fc5 2927
b95cf362 2928 word = e+1;
fab56fc5
LP
2929 state = WORD;
2930 }
2931 break;
2932 }
2933 }
2934
2935 if (!(k = strnappend(r, word, e-word)))
2936 goto fail;
2937
2938 free(r);
2939 return k;
2940
2941fail:
2942 free(r);
2943 return NULL;
2944}
2945
2946char **replace_env_argv(char **argv, char **env) {
2947 char **r, **i;
c24eb49e
LP
2948 unsigned k = 0, l = 0;
2949
2950 l = strv_length(argv);
fab56fc5 2951
c24eb49e 2952 if (!(r = new(char*, l+1)))
fab56fc5
LP
2953 return NULL;
2954
2955 STRV_FOREACH(i, argv) {
c24eb49e
LP
2956
2957 /* If $FOO appears as single word, replace it by the split up variable */
b95cf362
LP
2958 if ((*i)[0] == '$' && (*i)[1] != '{') {
2959 char *e;
2960 char **w, **m;
2961 unsigned q;
c24eb49e 2962
b95cf362 2963 if ((e = strv_env_get(env, *i+1))) {
c24eb49e
LP
2964
2965 if (!(m = strv_split_quoted(e))) {
2966 r[k] = NULL;
2967 strv_free(r);
2968 return NULL;
2969 }
b95cf362
LP
2970 } else
2971 m = NULL;
c24eb49e 2972
b95cf362
LP
2973 q = strv_length(m);
2974 l = l + q - 1;
c24eb49e 2975
b95cf362
LP
2976 if (!(w = realloc(r, sizeof(char*) * (l+1)))) {
2977 r[k] = NULL;
2978 strv_free(r);
2979 strv_free(m);
2980 return NULL;
2981 }
c24eb49e 2982
b95cf362
LP
2983 r = w;
2984 if (m) {
c24eb49e
LP
2985 memcpy(r + k, m, q * sizeof(char*));
2986 free(m);
c24eb49e 2987 }
b95cf362
LP
2988
2989 k += q;
2990 continue;
c24eb49e
LP
2991 }
2992
2993 /* If ${FOO} appears as part of a word, replace it by the variable as-is */
fab56fc5
LP
2994 if (!(r[k++] = replace_env(*i, env))) {
2995 strv_free(r);
2996 return NULL;
2997 }
2998 }
2999
3000 r[k] = NULL;
3001 return r;
3002}
3003
fa776d8e
LP
3004int columns(void) {
3005 static __thread int parsed_columns = 0;
3006 const char *e;
3007
3008 if (parsed_columns > 0)
3009 return parsed_columns;
3010
3011 if ((e = getenv("COLUMNS")))
3012 parsed_columns = atoi(e);
3013
3014 if (parsed_columns <= 0) {
3015 struct winsize ws;
3016 zero(ws);
3017
9ed95f43 3018 if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) >= 0)
fa776d8e
LP
3019 parsed_columns = ws.ws_col;
3020 }
3021
3022 if (parsed_columns <= 0)
3023 parsed_columns = 80;
3024
3025 return parsed_columns;
3026}
3027
b4f10a5e
LP
3028int running_in_chroot(void) {
3029 struct stat a, b;
3030
3031 zero(a);
3032 zero(b);
3033
3034 /* Only works as root */
3035
3036 if (stat("/proc/1/root", &a) < 0)
3037 return -errno;
3038
3039 if (stat("/", &b) < 0)
3040 return -errno;
3041
3042 return
3043 a.st_dev != b.st_dev ||
3044 a.st_ino != b.st_ino;
3045}
3046
8fe914ec
LP
3047char *ellipsize(const char *s, unsigned length, unsigned percent) {
3048 size_t l, x;
3049 char *r;
3050
3051 assert(s);
3052 assert(percent <= 100);
3053 assert(length >= 3);
3054
3055 l = strlen(s);
3056
3057 if (l <= 3 || l <= length)
3058 return strdup(s);
3059
3060 if (!(r = new0(char, length+1)))
3061 return r;
3062
3063 x = (length * percent) / 100;
3064
3065 if (x > length - 3)
3066 x = length - 3;
3067
3068 memcpy(r, s, x);
3069 r[x] = '.';
3070 r[x+1] = '.';
3071 r[x+2] = '.';
3072 memcpy(r + x + 3,
3073 s + l - (length - x - 3),
3074 length - x - 3);
3075
3076 return r;
3077}
3078
f6144808
LP
3079int touch(const char *path) {
3080 int fd;
3081
3082 assert(path);
3083
3084 if ((fd = open(path, O_WRONLY|O_CREAT|O_CLOEXEC|O_NOCTTY, 0666)) < 0)
3085 return -errno;
3086
3087 close_nointr_nofail(fd);
3088 return 0;
3089}
afea26ad 3090
11ce3427
LP
3091char *unquote(const char *s, const char quote) {
3092 size_t l;
3093 assert(s);
3094
3095 if ((l = strlen(s)) < 2)
3096 return strdup(s);
3097
3098 if (s[0] == quote && s[l-1] == quote)
3099 return strndup(s+1, l-2);
3100
3101 return strdup(s);
3102}
3103
2e78aa99
LP
3104int waitpid_loop(pid_t pid, int *status) {
3105 assert(pid >= 1);
3106 assert(status);
3107
3108 for (;;) {
3109 if (waitpid(pid, status, 0) < 0) {
3110
3111 if (errno == EINTR)
3112 continue;
3113
3114 return -errno;
3115 }
3116
3117 return 0;
3118 }
3119}
3120
1dccbe19
LP
3121static const char *const ioprio_class_table[] = {
3122 [IOPRIO_CLASS_NONE] = "none",
3123 [IOPRIO_CLASS_RT] = "realtime",
3124 [IOPRIO_CLASS_BE] = "best-effort",
3125 [IOPRIO_CLASS_IDLE] = "idle"
3126};
3127
3128DEFINE_STRING_TABLE_LOOKUP(ioprio_class, int);
3129
3130static const char *const sigchld_code_table[] = {
3131 [CLD_EXITED] = "exited",
3132 [CLD_KILLED] = "killed",
3133 [CLD_DUMPED] = "dumped",
3134 [CLD_TRAPPED] = "trapped",
3135 [CLD_STOPPED] = "stopped",
3136 [CLD_CONTINUED] = "continued",
3137};
3138
3139DEFINE_STRING_TABLE_LOOKUP(sigchld_code, int);
3140
3141static const char *const log_facility_table[LOG_NFACILITIES] = {
3142 [LOG_FAC(LOG_KERN)] = "kern",
3143 [LOG_FAC(LOG_USER)] = "user",
3144 [LOG_FAC(LOG_MAIL)] = "mail",
3145 [LOG_FAC(LOG_DAEMON)] = "daemon",
3146 [LOG_FAC(LOG_AUTH)] = "auth",
3147 [LOG_FAC(LOG_SYSLOG)] = "syslog",
3148 [LOG_FAC(LOG_LPR)] = "lpr",
3149 [LOG_FAC(LOG_NEWS)] = "news",
3150 [LOG_FAC(LOG_UUCP)] = "uucp",
3151 [LOG_FAC(LOG_CRON)] = "cron",
3152 [LOG_FAC(LOG_AUTHPRIV)] = "authpriv",
3153 [LOG_FAC(LOG_FTP)] = "ftp",
3154 [LOG_FAC(LOG_LOCAL0)] = "local0",
3155 [LOG_FAC(LOG_LOCAL1)] = "local1",
3156 [LOG_FAC(LOG_LOCAL2)] = "local2",
3157 [LOG_FAC(LOG_LOCAL3)] = "local3",
3158 [LOG_FAC(LOG_LOCAL4)] = "local4",
3159 [LOG_FAC(LOG_LOCAL5)] = "local5",
3160 [LOG_FAC(LOG_LOCAL6)] = "local6",
3161 [LOG_FAC(LOG_LOCAL7)] = "local7"
3162};
3163
3164DEFINE_STRING_TABLE_LOOKUP(log_facility, int);
3165
3166static const char *const log_level_table[] = {
3167 [LOG_EMERG] = "emerg",
3168 [LOG_ALERT] = "alert",
3169 [LOG_CRIT] = "crit",
3170 [LOG_ERR] = "err",
3171 [LOG_WARNING] = "warning",
3172 [LOG_NOTICE] = "notice",
3173 [LOG_INFO] = "info",
3174 [LOG_DEBUG] = "debug"
3175};
3176
3177DEFINE_STRING_TABLE_LOOKUP(log_level, int);
3178
3179static const char* const sched_policy_table[] = {
3180 [SCHED_OTHER] = "other",
3181 [SCHED_BATCH] = "batch",
3182 [SCHED_IDLE] = "idle",
3183 [SCHED_FIFO] = "fifo",
3184 [SCHED_RR] = "rr"
3185};
3186
3187DEFINE_STRING_TABLE_LOOKUP(sched_policy, int);
3188
3189static const char* const rlimit_table[] = {
3190 [RLIMIT_CPU] = "LimitCPU",
3191 [RLIMIT_FSIZE] = "LimitFSIZE",
3192 [RLIMIT_DATA] = "LimitDATA",
3193 [RLIMIT_STACK] = "LimitSTACK",
3194 [RLIMIT_CORE] = "LimitCORE",
3195 [RLIMIT_RSS] = "LimitRSS",
3196 [RLIMIT_NOFILE] = "LimitNOFILE",
3197 [RLIMIT_AS] = "LimitAS",
3198 [RLIMIT_NPROC] = "LimitNPROC",
3199 [RLIMIT_MEMLOCK] = "LimitMEMLOCK",
3200 [RLIMIT_LOCKS] = "LimitLOCKS",
3201 [RLIMIT_SIGPENDING] = "LimitSIGPENDING",
3202 [RLIMIT_MSGQUEUE] = "LimitMSGQUEUE",
3203 [RLIMIT_NICE] = "LimitNICE",
3204 [RLIMIT_RTPRIO] = "LimitRTPRIO",
3205 [RLIMIT_RTTIME] = "LimitRTTIME"
3206};
3207
3208DEFINE_STRING_TABLE_LOOKUP(rlimit, int);
4fd5948e
LP
3209
3210static const char* const ip_tos_table[] = {
3211 [IPTOS_LOWDELAY] = "low-delay",
3212 [IPTOS_THROUGHPUT] = "throughput",
3213 [IPTOS_RELIABILITY] = "reliability",
3214 [IPTOS_LOWCOST] = "low-cost",
3215};
3216
3217DEFINE_STRING_TABLE_LOOKUP(ip_tos, int);
2e22afe9
LP
3218
3219static const char *const signal_table[] = {
3220 [SIGHUP] = "HUP",
3221 [SIGINT] = "INT",
3222 [SIGQUIT] = "QUIT",
3223 [SIGILL] = "ILL",
3224 [SIGTRAP] = "TRAP",
3225 [SIGABRT] = "ABRT",
3226 [SIGBUS] = "BUS",
3227 [SIGFPE] = "FPE",
3228 [SIGKILL] = "KILL",
3229 [SIGUSR1] = "USR1",
3230 [SIGSEGV] = "SEGV",
3231 [SIGUSR2] = "USR2",
3232 [SIGPIPE] = "PIPE",
3233 [SIGALRM] = "ALRM",
3234 [SIGTERM] = "TERM",
f26ee0b9
LP
3235#ifdef SIGSTKFLT
3236 [SIGSTKFLT] = "STKFLT", /* Linux on SPARC doesn't know SIGSTKFLT */
3237#endif
2e22afe9
LP
3238 [SIGCHLD] = "CHLD",
3239 [SIGCONT] = "CONT",
3240 [SIGSTOP] = "STOP",
3241 [SIGTSTP] = "TSTP",
3242 [SIGTTIN] = "TTIN",
3243 [SIGTTOU] = "TTOU",
3244 [SIGURG] = "URG",
3245 [SIGXCPU] = "XCPU",
3246 [SIGXFSZ] = "XFSZ",
3247 [SIGVTALRM] = "VTALRM",
3248 [SIGPROF] = "PROF",
3249 [SIGWINCH] = "WINCH",
3250 [SIGIO] = "IO",
3251 [SIGPWR] = "PWR",
3252 [SIGSYS] = "SYS"
3253};
3254
3255DEFINE_STRING_TABLE_LOOKUP(signal, int);