]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/util.c
timer: fully implement timer units
[thirdparty/systemd.git] / src / util.c
CommitLineData
60918275
LP
1/*-*- Mode: C; c-basic-offset: 8 -*-*/
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>
60918275
LP
46
47#include "macro.h"
48#include "util.h"
1dccbe19
LP
49#include "ioprio.h"
50#include "missing.h"
a9f5d454 51#include "log.h"
65d2ebdc 52#include "strv.h"
60918275 53
e05797fb
LP
54bool streq_ptr(const char *a, const char *b) {
55
56 /* Like streq(), but tries to make sense of NULL pointers */
57
58 if (a && b)
59 return streq(a, b);
60
61 if (!a && !b)
62 return true;
63
64 return false;
65}
66
47be870b 67usec_t now(clockid_t clock_id) {
60918275
LP
68 struct timespec ts;
69
47be870b 70 assert_se(clock_gettime(clock_id, &ts) == 0);
60918275
LP
71
72 return timespec_load(&ts);
73}
74
871d7de4
LP
75timestamp* timestamp_get(timestamp *ts) {
76 assert(ts);
77
78 ts->realtime = now(CLOCK_REALTIME);
79 ts->monotonic = now(CLOCK_MONOTONIC);
80
81 return ts;
82}
83
60918275
LP
84usec_t timespec_load(const struct timespec *ts) {
85 assert(ts);
86
87 return
88 (usec_t) ts->tv_sec * USEC_PER_SEC +
89 (usec_t) ts->tv_nsec / NSEC_PER_USEC;
90}
91
92struct timespec *timespec_store(struct timespec *ts, usec_t u) {
93 assert(ts);
94
95 ts->tv_sec = (time_t) (u / USEC_PER_SEC);
96 ts->tv_nsec = (long int) ((u % USEC_PER_SEC) * NSEC_PER_USEC);
97
98 return ts;
99}
100
101usec_t timeval_load(const struct timeval *tv) {
102 assert(tv);
103
104 return
105 (usec_t) tv->tv_sec * USEC_PER_SEC +
106 (usec_t) tv->tv_usec;
107}
108
109struct timeval *timeval_store(struct timeval *tv, usec_t u) {
110 assert(tv);
111
112 tv->tv_sec = (time_t) (u / USEC_PER_SEC);
113 tv->tv_usec = (suseconds_t) (u % USEC_PER_SEC);
114
115 return tv;
116}
117
118bool endswith(const char *s, const char *postfix) {
119 size_t sl, pl;
120
121 assert(s);
122 assert(postfix);
123
124 sl = strlen(s);
125 pl = strlen(postfix);
126
d4d0d4db
LP
127 if (pl == 0)
128 return true;
129
60918275
LP
130 if (sl < pl)
131 return false;
132
133 return memcmp(s + sl - pl, postfix, pl) == 0;
134}
135
136bool startswith(const char *s, const char *prefix) {
137 size_t sl, pl;
138
139 assert(s);
140 assert(prefix);
141
142 sl = strlen(s);
143 pl = strlen(prefix);
144
d4d0d4db
LP
145 if (pl == 0)
146 return true;
147
60918275
LP
148 if (sl < pl)
149 return false;
150
151 return memcmp(s, prefix, pl) == 0;
152}
153
3177a7fa
MAP
154bool startswith_no_case(const char *s, const char *prefix) {
155 size_t sl, pl;
156 unsigned i;
157
158 assert(s);
159 assert(prefix);
160
161 sl = strlen(s);
162 pl = strlen(prefix);
163
164 if (pl == 0)
165 return true;
166
167 if (sl < pl)
168 return false;
169
170 for(i = 0; i < pl; ++i) {
171 if (tolower(s[i]) != tolower(prefix[i]))
172 return false;
173 }
174
175 return true;
176}
177
79d6d816
LP
178bool first_word(const char *s, const char *word) {
179 size_t sl, wl;
180
181 assert(s);
182 assert(word);
183
184 sl = strlen(s);
185 wl = strlen(word);
186
187 if (sl < wl)
188 return false;
189
d4d0d4db
LP
190 if (wl == 0)
191 return true;
192
79d6d816
LP
193 if (memcmp(s, word, wl) != 0)
194 return false;
195
d4d0d4db
LP
196 return s[wl] == 0 ||
197 strchr(WHITESPACE, s[wl]);
79d6d816
LP
198}
199
42f4e3c4 200int close_nointr(int fd) {
60918275
LP
201 assert(fd >= 0);
202
203 for (;;) {
204 int r;
205
206 if ((r = close(fd)) >= 0)
207 return r;
208
209 if (errno != EINTR)
210 return r;
211 }
212}
85261803 213
85f136b5 214void close_nointr_nofail(int fd) {
80876c20 215 int saved_errno = errno;
85f136b5
LP
216
217 /* like close_nointr() but cannot fail, and guarantees errno
218 * is unchanged */
219
220 assert_se(close_nointr(fd) == 0);
80876c20
LP
221
222 errno = saved_errno;
85f136b5
LP
223}
224
85261803
LP
225int parse_boolean(const char *v) {
226 assert(v);
227
44d8db9e 228 if (streq(v, "1") || v[0] == 'y' || v[0] == 'Y' || v[0] == 't' || v[0] == 'T' || !strcasecmp(v, "on"))
85261803 229 return 1;
44d8db9e 230 else if (streq(v, "0") || v[0] == 'n' || v[0] == 'N' || v[0] == 'f' || v[0] == 'F' || !strcasecmp(v, "off"))
85261803
LP
231 return 0;
232
233 return -EINVAL;
234}
235
236int safe_atou(const char *s, unsigned *ret_u) {
237 char *x = NULL;
034c6ed7 238 unsigned long l;
85261803
LP
239
240 assert(s);
241 assert(ret_u);
242
243 errno = 0;
244 l = strtoul(s, &x, 0);
245
246 if (!x || *x || errno)
247 return errno ? -errno : -EINVAL;
248
034c6ed7 249 if ((unsigned long) (unsigned) l != l)
85261803
LP
250 return -ERANGE;
251
252 *ret_u = (unsigned) l;
253 return 0;
254}
255
256int safe_atoi(const char *s, int *ret_i) {
257 char *x = NULL;
034c6ed7 258 long l;
85261803
LP
259
260 assert(s);
261 assert(ret_i);
262
263 errno = 0;
264 l = strtol(s, &x, 0);
265
266 if (!x || *x || errno)
267 return errno ? -errno : -EINVAL;
268
034c6ed7 269 if ((long) (int) l != l)
85261803
LP
270 return -ERANGE;
271
034c6ed7
LP
272 *ret_i = (int) l;
273 return 0;
274}
275
276int safe_atolu(const char *s, long unsigned *ret_lu) {
277 char *x = NULL;
278 unsigned long l;
279
280 assert(s);
281 assert(ret_lu);
282
283 errno = 0;
284 l = strtoul(s, &x, 0);
285
286 if (!x || *x || errno)
287 return errno ? -errno : -EINVAL;
288
289 *ret_lu = l;
290 return 0;
291}
292
293int safe_atoli(const char *s, long int *ret_li) {
294 char *x = NULL;
295 long l;
296
297 assert(s);
298 assert(ret_li);
299
300 errno = 0;
301 l = strtol(s, &x, 0);
302
303 if (!x || *x || errno)
304 return errno ? -errno : -EINVAL;
305
306 *ret_li = l;
307 return 0;
308}
309
310int safe_atollu(const char *s, long long unsigned *ret_llu) {
311 char *x = NULL;
312 unsigned long long l;
313
314 assert(s);
315 assert(ret_llu);
316
317 errno = 0;
318 l = strtoull(s, &x, 0);
319
320 if (!x || *x || errno)
321 return errno ? -errno : -EINVAL;
322
323 *ret_llu = l;
324 return 0;
325}
326
327int safe_atolli(const char *s, long long int *ret_lli) {
328 char *x = NULL;
329 long long l;
330
331 assert(s);
332 assert(ret_lli);
333
334 errno = 0;
335 l = strtoll(s, &x, 0);
336
337 if (!x || *x || errno)
338 return errno ? -errno : -EINVAL;
339
340 *ret_lli = l;
85261803
LP
341 return 0;
342}
a41e8209 343
a41e8209 344/* Split a string into words. */
65d2ebdc 345char *split(const char *c, size_t *l, const char *separator, char **state) {
a41e8209
LP
346 char *current;
347
348 current = *state ? *state : (char*) c;
349
350 if (!*current || *c == 0)
351 return NULL;
352
65d2ebdc
LP
353 current += strspn(current, separator);
354 *l = strcspn(current, separator);
82919e3d
LP
355 *state = current+*l;
356
357 return (char*) current;
358}
359
034c6ed7
LP
360/* Split a string into words, but consider strings enclosed in '' and
361 * "" as words even if they include spaces. */
362char *split_quoted(const char *c, size_t *l, char **state) {
363 char *current;
364
365 current = *state ? *state : (char*) c;
366
367 if (!*current || *c == 0)
368 return NULL;
369
370 current += strspn(current, WHITESPACE);
371
372 if (*current == '\'') {
373 current ++;
374 *l = strcspn(current, "'");
375 *state = current+*l;
376
377 if (**state == '\'')
378 (*state)++;
379 } else if (*current == '\"') {
380 current ++;
b858b600 381 *l = strcspn(current, "\"");
034c6ed7
LP
382 *state = current+*l;
383
384 if (**state == '\"')
385 (*state)++;
386 } else {
387 *l = strcspn(current, WHITESPACE);
388 *state = current+*l;
389 }
390
44d8db9e
LP
391 /* FIXME: Cannot deal with strings that have spaces AND ticks
392 * in them */
393
034c6ed7
LP
394 return (char*) current;
395}
396
65d2ebdc
LP
397char **split_path_and_make_absolute(const char *p) {
398 char **l;
399 assert(p);
400
401 if (!(l = strv_split(p, ":")))
402 return NULL;
403
404 if (!strv_path_make_absolute_cwd(l)) {
405 strv_free(l);
406 return NULL;
407 }
408
409 return l;
410}
411
034c6ed7
LP
412int get_parent_of_pid(pid_t pid, pid_t *_ppid) {
413 int r;
414 FILE *f;
415 char fn[132], line[256], *p;
416 long long unsigned ppid;
417
418 assert(pid >= 0);
419 assert(_ppid);
420
421 assert_se(snprintf(fn, sizeof(fn)-1, "/proc/%llu/stat", (unsigned long long) pid) < (int) (sizeof(fn)-1));
422 fn[sizeof(fn)-1] = 0;
423
424 if (!(f = fopen(fn, "r")))
425 return -errno;
426
427 if (!(fgets(line, sizeof(line), f))) {
428 r = -errno;
429 fclose(f);
430 return r;
431 }
432
433 fclose(f);
434
435 /* Let's skip the pid and comm fields. The latter is enclosed
436 * in () but does not escape any () in its value, so let's
437 * skip over it manually */
438
439 if (!(p = strrchr(line, ')')))
440 return -EIO;
441
442 p++;
443
444 if (sscanf(p, " "
445 "%*c " /* state */
446 "%llu ", /* ppid */
447 &ppid) != 1)
448 return -EIO;
449
450 if ((long long unsigned) (pid_t) ppid != ppid)
451 return -ERANGE;
452
453 *_ppid = (pid_t) ppid;
454
455 return 0;
456}
457
458int write_one_line_file(const char *fn, const char *line) {
459 FILE *f;
460 int r;
461
462 assert(fn);
463 assert(line);
464
465 if (!(f = fopen(fn, "we")))
466 return -errno;
467
468 if (fputs(line, f) < 0) {
469 r = -errno;
470 goto finish;
471 }
472
473 r = 0;
474finish:
475 fclose(f);
476 return r;
477}
478
479int read_one_line_file(const char *fn, char **line) {
480 FILE *f;
481 int r;
11316633 482 char t[2048], *c;
034c6ed7
LP
483
484 assert(fn);
485 assert(line);
486
487 if (!(f = fopen(fn, "re")))
488 return -errno;
489
490 if (!(fgets(t, sizeof(t), f))) {
491 r = -errno;
492 goto finish;
493 }
494
495 if (!(c = strdup(t))) {
496 r = -ENOMEM;
497 goto finish;
498 }
499
500 *line = c;
501 r = 0;
502
503finish:
504 fclose(f);
505 return r;
506}
44d8db9e 507
7072ced8
LP
508char *truncate_nl(char *s) {
509 assert(s);
510
511 s[strcspn(s, NEWLINE)] = 0;
512 return s;
513}
514
515int get_process_name(pid_t pid, char **name) {
516 char *p;
517 int r;
518
519 assert(pid >= 1);
520 assert(name);
521
522 if (asprintf(&p, "/proc/%llu/comm", (unsigned long long) pid) < 0)
523 return -ENOMEM;
524
525 r = read_one_line_file(p, name);
526 free(p);
527
528 if (r < 0)
529 return r;
530
531 truncate_nl(*name);
532 return 0;
533}
534
44d8db9e
LP
535char *strappend(const char *s, const char *suffix) {
536 size_t a, b;
537 char *r;
538
539 assert(s);
540 assert(suffix);
541
542 a = strlen(s);
543 b = strlen(suffix);
544
545 if (!(r = new(char, a+b+1)))
546 return NULL;
547
548 memcpy(r, s, a);
549 memcpy(r+a, suffix, b);
550 r[a+b] = 0;
551
552 return r;
553}
87f0e418
LP
554
555int readlink_malloc(const char *p, char **r) {
556 size_t l = 100;
557
558 assert(p);
559 assert(r);
560
561 for (;;) {
562 char *c;
563 ssize_t n;
564
565 if (!(c = new(char, l)))
566 return -ENOMEM;
567
568 if ((n = readlink(p, c, l-1)) < 0) {
569 int ret = -errno;
570 free(c);
571 return ret;
572 }
573
574 if ((size_t) n < l-1) {
575 c[n] = 0;
576 *r = c;
577 return 0;
578 }
579
580 free(c);
581 l *= 2;
582 }
583}
584
585char *file_name_from_path(const char *p) {
586 char *r;
587
588 assert(p);
589
590 if ((r = strrchr(p, '/')))
591 return r + 1;
592
593 return (char*) p;
594}
0301abf4
LP
595
596bool path_is_absolute(const char *p) {
597 assert(p);
598
599 return p[0] == '/';
600}
601
602bool is_path(const char *p) {
603
604 return !!strchr(p, '/');
605}
606
607char *path_make_absolute(const char *p, const char *prefix) {
608 char *r;
609
610 assert(p);
611
65d2ebdc
LP
612 /* Makes every item in the list an absolute path by prepending
613 * the prefix, if specified and necessary */
614
0301abf4
LP
615 if (path_is_absolute(p) || !prefix)
616 return strdup(p);
617
618 if (asprintf(&r, "%s/%s", prefix, p) < 0)
619 return NULL;
620
621 return r;
622}
2a987ee8 623
65d2ebdc
LP
624char *path_make_absolute_cwd(const char *p) {
625 char *cwd, *r;
626
627 assert(p);
628
629 /* Similar to path_make_absolute(), but prefixes with the
630 * current working directory. */
631
632 if (path_is_absolute(p))
633 return strdup(p);
634
635 if (!(cwd = get_current_dir_name()))
636 return NULL;
637
638 r = path_make_absolute(p, cwd);
639 free(cwd);
640
641 return r;
642}
643
644char **strv_path_make_absolute_cwd(char **l) {
645 char **s;
646
647 /* Goes through every item in the string list and makes it
648 * absolute. This works in place and won't rollback any
649 * changes on failure. */
650
651 STRV_FOREACH(s, l) {
652 char *t;
653
654 if (!(t = path_make_absolute_cwd(*s)))
655 return NULL;
656
657 free(*s);
658 *s = t;
659 }
660
661 return l;
662}
663
c3f6d675
LP
664char **strv_path_canonicalize(char **l) {
665 char **s;
666 unsigned k = 0;
667 bool enomem = false;
668
669 if (strv_isempty(l))
670 return l;
671
672 /* Goes through every item in the string list and canonicalize
673 * the path. This works in place and won't rollback any
674 * changes on failure. */
675
676 STRV_FOREACH(s, l) {
677 char *t, *u;
678
679 t = path_make_absolute_cwd(*s);
680 free(*s);
681
682 if (!t) {
683 enomem = true;
684 continue;
685 }
686
687 errno = 0;
688 u = canonicalize_file_name(t);
689 free(t);
690
691 if (!u) {
692 if (errno == ENOMEM || !errno)
693 enomem = true;
694
695 continue;
696 }
697
698 l[k++] = u;
699 }
700
701 l[k] = NULL;
702
703 if (enomem)
704 return NULL;
705
706 return l;
707}
708
2a987ee8
LP
709int reset_all_signal_handlers(void) {
710 int sig;
711
712 for (sig = 1; sig < _NSIG; sig++) {
713 struct sigaction sa;
714
715 if (sig == SIGKILL || sig == SIGSTOP)
716 continue;
717
718 zero(sa);
719 sa.sa_handler = SIG_DFL;
431c32bf 720 sa.sa_flags = SA_RESTART;
2a987ee8
LP
721
722 /* On Linux the first two RT signals are reserved by
723 * glibc, and sigaction() will return EINVAL for them. */
724 if ((sigaction(sig, &sa, NULL) < 0))
725 if (errno != EINVAL)
726 return -errno;
727 }
728
8e274523 729 return 0;
2a987ee8 730}
4a72ff34
LP
731
732char *strstrip(char *s) {
733 char *e, *l = NULL;
734
735 /* Drops trailing whitespace. Modifies the string in
736 * place. Returns pointer to first non-space character */
737
738 s += strspn(s, WHITESPACE);
739
740 for (e = s; *e; e++)
741 if (!strchr(WHITESPACE, *e))
742 l = e;
743
744 if (l)
745 *(l+1) = 0;
746 else
747 *s = 0;
748
749 return s;
4a72ff34
LP
750}
751
ee9b5e01
LP
752char *delete_chars(char *s, const char *bad) {
753 char *f, *t;
754
755 /* Drops all whitespace, regardless where in the string */
756
757 for (f = s, t = s; *f; f++) {
758 if (strchr(bad, *f))
759 continue;
760
761 *(t++) = *f;
762 }
763
764 *t = 0;
765
766 return s;
767}
768
4a72ff34
LP
769char *file_in_same_dir(const char *path, const char *filename) {
770 char *e, *r;
771 size_t k;
772
773 assert(path);
774 assert(filename);
775
776 /* This removes the last component of path and appends
777 * filename, unless the latter is absolute anyway or the
778 * former isn't */
779
780 if (path_is_absolute(filename))
781 return strdup(filename);
782
783 if (!(e = strrchr(path, '/')))
784 return strdup(filename);
785
786 k = strlen(filename);
787 if (!(r = new(char, e-path+1+k+1)))
788 return NULL;
789
790 memcpy(r, path, e-path+1);
791 memcpy(r+(e-path)+1, filename, k+1);
792
793 return r;
794}
fb624d04 795
a9f5d454
LP
796int mkdir_parents(const char *path, mode_t mode) {
797 const char *p, *e;
798
799 assert(path);
800
801 /* Creates every parent directory in the path except the last
802 * component. */
803
804 p = path + strspn(path, "/");
805 for (;;) {
806 int r;
807 char *t;
808
809 e = p + strcspn(p, "/");
810 p = e + strspn(e, "/");
811
812 /* Is this the last component? If so, then we're
813 * done */
814 if (*p == 0)
815 return 0;
816
817 if (!(t = strndup(path, e - path)))
818 return -ENOMEM;
819
820 r = mkdir(t, mode);
821
822 free(t);
823
824 if (r < 0 && errno != EEXIST)
825 return -errno;
826 }
827}
828
bbd67135
LP
829int mkdir_p(const char *path, mode_t mode) {
830 int r;
831
832 /* Like mkdir -p */
833
834 if ((r = mkdir_parents(path, mode)) < 0)
835 return r;
836
837 if (mkdir(path, mode) < 0)
838 return -errno;
839
840 return 0;
841}
842
fb624d04
LP
843char hexchar(int x) {
844 static const char table[16] = "0123456789abcdef";
845
846 return table[x & 15];
847}
4fe88d28
LP
848
849int unhexchar(char c) {
850
851 if (c >= '0' && c <= '9')
852 return c - '0';
853
854 if (c >= 'a' && c <= 'f')
ea430986 855 return c - 'a' + 10;
4fe88d28
LP
856
857 if (c >= 'A' && c <= 'F')
ea430986 858 return c - 'A' + 10;
4fe88d28
LP
859
860 return -1;
861}
862
863char octchar(int x) {
864 return '0' + (x & 7);
865}
866
867int unoctchar(char c) {
868
869 if (c >= '0' && c <= '7')
870 return c - '0';
871
872 return -1;
873}
874
5af98f82
LP
875char decchar(int x) {
876 return '0' + (x % 10);
877}
878
879int undecchar(char c) {
880
881 if (c >= '0' && c <= '9')
882 return c - '0';
883
884 return -1;
885}
886
4fe88d28
LP
887char *cescape(const char *s) {
888 char *r, *t;
889 const char *f;
890
891 assert(s);
892
893 /* Does C style string escaping. */
894
895 if (!(r = new(char, strlen(s)*4 + 1)))
896 return NULL;
897
898 for (f = s, t = r; *f; f++)
899
900 switch (*f) {
901
902 case '\a':
903 *(t++) = '\\';
904 *(t++) = 'a';
905 break;
906 case '\b':
907 *(t++) = '\\';
908 *(t++) = 'b';
909 break;
910 case '\f':
911 *(t++) = '\\';
912 *(t++) = 'f';
913 break;
914 case '\n':
915 *(t++) = '\\';
916 *(t++) = 'n';
917 break;
918 case '\r':
919 *(t++) = '\\';
920 *(t++) = 'r';
921 break;
922 case '\t':
923 *(t++) = '\\';
924 *(t++) = 't';
925 break;
926 case '\v':
927 *(t++) = '\\';
928 *(t++) = 'v';
929 break;
930 case '\\':
931 *(t++) = '\\';
932 *(t++) = '\\';
933 break;
934 case '"':
935 *(t++) = '\\';
936 *(t++) = '"';
937 break;
938 case '\'':
939 *(t++) = '\\';
940 *(t++) = '\'';
941 break;
942
943 default:
944 /* For special chars we prefer octal over
945 * hexadecimal encoding, simply because glib's
946 * g_strescape() does the same */
947 if ((*f < ' ') || (*f >= 127)) {
948 *(t++) = '\\';
949 *(t++) = octchar((unsigned char) *f >> 6);
950 *(t++) = octchar((unsigned char) *f >> 3);
951 *(t++) = octchar((unsigned char) *f);
952 } else
953 *(t++) = *f;
954 break;
955 }
956
957 *t = 0;
958
959 return r;
960}
961
962char *cunescape(const char *s) {
963 char *r, *t;
964 const char *f;
965
966 assert(s);
967
968 /* Undoes C style string escaping */
969
970 if (!(r = new(char, strlen(s)+1)))
971 return r;
972
973 for (f = s, t = r; *f; f++) {
974
975 if (*f != '\\') {
976 *(t++) = *f;
977 continue;
978 }
979
980 f++;
981
982 switch (*f) {
983
984 case 'a':
985 *(t++) = '\a';
986 break;
987 case 'b':
988 *(t++) = '\b';
989 break;
990 case 'f':
991 *(t++) = '\f';
992 break;
993 case 'n':
994 *(t++) = '\n';
995 break;
996 case 'r':
997 *(t++) = '\r';
998 break;
999 case 't':
1000 *(t++) = '\t';
1001 break;
1002 case 'v':
1003 *(t++) = '\v';
1004 break;
1005 case '\\':
1006 *(t++) = '\\';
1007 break;
1008 case '"':
1009 *(t++) = '"';
1010 break;
1011 case '\'':
1012 *(t++) = '\'';
1013 break;
1014
1015 case 'x': {
1016 /* hexadecimal encoding */
1017 int a, b;
1018
1019 if ((a = unhexchar(f[1])) < 0 ||
1020 (b = unhexchar(f[2])) < 0) {
1021 /* Invalid escape code, let's take it literal then */
1022 *(t++) = '\\';
1023 *(t++) = 'x';
1024 } else {
1025 *(t++) = (char) ((a << 4) | b);
1026 f += 2;
1027 }
1028
1029 break;
1030 }
1031
1032 case '0':
1033 case '1':
1034 case '2':
1035 case '3':
1036 case '4':
1037 case '5':
1038 case '6':
1039 case '7': {
1040 /* octal encoding */
1041 int a, b, c;
1042
1043 if ((a = unoctchar(f[0])) < 0 ||
1044 (b = unoctchar(f[1])) < 0 ||
1045 (c = unoctchar(f[2])) < 0) {
1046 /* Invalid escape code, let's take it literal then */
1047 *(t++) = '\\';
1048 *(t++) = f[0];
1049 } else {
1050 *(t++) = (char) ((a << 6) | (b << 3) | c);
1051 f += 2;
1052 }
1053
1054 break;
1055 }
1056
1057 case 0:
1058 /* premature end of string.*/
1059 *(t++) = '\\';
1060 goto finish;
1061
1062 default:
1063 /* Invalid escape code, let's take it literal then */
1064 *(t++) = '\\';
1065 *(t++) = 'f';
1066 break;
1067 }
1068 }
1069
1070finish:
1071 *t = 0;
1072 return r;
1073}
1074
1075
1076char *xescape(const char *s, const char *bad) {
1077 char *r, *t;
1078 const char *f;
1079
1080 /* Escapes all chars in bad, in addition to \ and all special
1081 * chars, in \xFF style escaping. May be reversed with
1082 * cunescape. */
1083
1084 if (!(r = new(char, strlen(s)*4+1)))
1085 return NULL;
1086
1087 for (f = s, t = r; *f; f++) {
1088
b866264a
LP
1089 if ((*f < ' ') || (*f >= 127) ||
1090 (*f == '\\') || strchr(bad, *f)) {
4fe88d28
LP
1091 *(t++) = '\\';
1092 *(t++) = 'x';
1093 *(t++) = hexchar(*f >> 4);
1094 *(t++) = hexchar(*f);
1095 } else
1096 *(t++) = *f;
1097 }
1098
1099 *t = 0;
1100
1101 return r;
1102}
1103
ea430986 1104char *bus_path_escape(const char *s) {
ea430986
LP
1105 char *r, *t;
1106 const char *f;
1107
47be870b
LP
1108 assert(s);
1109
ea430986
LP
1110 /* Escapes all chars that D-Bus' object path cannot deal
1111 * with. Can be reverse with bus_path_unescape() */
1112
1113 if (!(r = new(char, strlen(s)*3+1)))
1114 return NULL;
1115
1116 for (f = s, t = r; *f; f++) {
1117
1118 if (!(*f >= 'A' && *f <= 'Z') &&
1119 !(*f >= 'a' && *f <= 'z') &&
1120 !(*f >= '0' && *f <= '9')) {
1121 *(t++) = '_';
1122 *(t++) = hexchar(*f >> 4);
1123 *(t++) = hexchar(*f);
1124 } else
1125 *(t++) = *f;
1126 }
1127
1128 *t = 0;
1129
1130 return r;
1131}
1132
9e2f7c11 1133char *bus_path_unescape(const char *f) {
ea430986 1134 char *r, *t;
ea430986 1135
9e2f7c11 1136 assert(f);
47be870b 1137
9e2f7c11 1138 if (!(r = strdup(f)))
ea430986
LP
1139 return NULL;
1140
9e2f7c11 1141 for (t = r; *f; f++) {
ea430986
LP
1142
1143 if (*f == '_') {
1144 int a, b;
1145
1146 if ((a = unhexchar(f[1])) < 0 ||
1147 (b = unhexchar(f[2])) < 0) {
1148 /* Invalid escape code, let's take it literal then */
1149 *(t++) = '_';
1150 } else {
1151 *(t++) = (char) ((a << 4) | b);
1152 f += 2;
1153 }
1154 } else
1155 *(t++) = *f;
1156 }
1157
1158 *t = 0;
1159
1160 return r;
1161}
1162
4fe88d28
LP
1163char *path_kill_slashes(char *path) {
1164 char *f, *t;
1165 bool slash = false;
1166
1167 /* Removes redundant inner and trailing slashes. Modifies the
1168 * passed string in-place.
1169 *
1170 * ///foo///bar/ becomes /foo/bar
1171 */
1172
1173 for (f = path, t = path; *f; f++) {
1174
1175 if (*f == '/') {
1176 slash = true;
1177 continue;
1178 }
1179
1180 if (slash) {
1181 slash = false;
1182 *(t++) = '/';
1183 }
1184
1185 *(t++) = *f;
1186 }
1187
1188 /* Special rule, if we are talking of the root directory, a
1189 trailing slash is good */
1190
1191 if (t == path && slash)
1192 *(t++) = '/';
1193
1194 *t = 0;
1195 return path;
1196}
1197
1198bool path_startswith(const char *path, const char *prefix) {
1199 assert(path);
1200 assert(prefix);
1201
1202 if ((path[0] == '/') != (prefix[0] == '/'))
1203 return false;
1204
1205 for (;;) {
1206 size_t a, b;
1207
1208 path += strspn(path, "/");
1209 prefix += strspn(prefix, "/");
1210
1211 if (*prefix == 0)
1212 return true;
1213
1214 if (*path == 0)
1215 return false;
1216
1217 a = strcspn(path, "/");
1218 b = strcspn(prefix, "/");
1219
1220 if (a != b)
1221 return false;
1222
1223 if (memcmp(path, prefix, a) != 0)
1224 return false;
1225
1226 path += a;
1227 prefix += b;
1228 }
1229}
1230
15ae422b
LP
1231bool path_equal(const char *a, const char *b) {
1232 assert(a);
1233 assert(b);
1234
1235 if ((a[0] == '/') != (b[0] == '/'))
1236 return false;
1237
1238 for (;;) {
1239 size_t j, k;
1240
1241 a += strspn(a, "/");
1242 b += strspn(b, "/");
1243
1244 if (*a == 0 && *b == 0)
1245 return true;
1246
1247 if (*a == 0 || *b == 0)
1248 return false;
1249
1250 j = strcspn(a, "/");
1251 k = strcspn(b, "/");
1252
1253 if (j != k)
1254 return false;
1255
1256 if (memcmp(a, b, j) != 0)
1257 return false;
1258
1259 a += j;
1260 b += k;
1261 }
1262}
1263
67d51650 1264char *ascii_strlower(char *t) {
4fe88d28
LP
1265 char *p;
1266
67d51650 1267 assert(t);
4fe88d28 1268
67d51650 1269 for (p = t; *p; p++)
4fe88d28
LP
1270 if (*p >= 'A' && *p <= 'Z')
1271 *p = *p - 'A' + 'a';
1272
67d51650 1273 return t;
4fe88d28 1274}
1dccbe19 1275
c85dc17b
LP
1276bool ignore_file(const char *filename) {
1277 assert(filename);
1278
1279 return
1280 filename[0] == '.' ||
6c78be3c 1281 streq(filename, "lost+found") ||
c85dc17b
LP
1282 endswith(filename, "~") ||
1283 endswith(filename, ".rpmnew") ||
1284 endswith(filename, ".rpmsave") ||
1285 endswith(filename, ".rpmorig") ||
1286 endswith(filename, ".dpkg-old") ||
1287 endswith(filename, ".dpkg-new") ||
1288 endswith(filename, ".swp");
1289}
1290
3a0ecb08
LP
1291int fd_nonblock(int fd, bool nonblock) {
1292 int flags;
1293
1294 assert(fd >= 0);
1295
1296 if ((flags = fcntl(fd, F_GETFL, 0)) < 0)
1297 return -errno;
1298
1299 if (nonblock)
1300 flags |= O_NONBLOCK;
1301 else
1302 flags &= ~O_NONBLOCK;
1303
1304 if (fcntl(fd, F_SETFL, flags) < 0)
1305 return -errno;
1306
1307 return 0;
1308}
1309
1310int fd_cloexec(int fd, bool cloexec) {
1311 int flags;
1312
1313 assert(fd >= 0);
1314
1315 if ((flags = fcntl(fd, F_GETFD, 0)) < 0)
1316 return -errno;
1317
1318 if (cloexec)
1319 flags |= FD_CLOEXEC;
1320 else
1321 flags &= ~FD_CLOEXEC;
1322
1323 if (fcntl(fd, F_SETFD, flags) < 0)
1324 return -errno;
1325
1326 return 0;
1327}
1328
a0d40ac5
LP
1329int close_all_fds(const int except[], unsigned n_except) {
1330 DIR *d;
1331 struct dirent *de;
1332 int r = 0;
1333
1334 if (!(d = opendir("/proc/self/fd")))
1335 return -errno;
1336
1337 while ((de = readdir(d))) {
a7610064 1338 int fd = -1;
a0d40ac5 1339
a16e1123 1340 if (ignore_file(de->d_name))
a0d40ac5
LP
1341 continue;
1342
1343 if ((r = safe_atoi(de->d_name, &fd)) < 0)
1344 goto finish;
1345
1346 if (fd < 3)
1347 continue;
1348
1349 if (fd == dirfd(d))
1350 continue;
1351
1352 if (except) {
1353 bool found;
1354 unsigned i;
1355
1356 found = false;
1357 for (i = 0; i < n_except; i++)
1358 if (except[i] == fd) {
1359 found = true;
1360 break;
1361 }
1362
1363 if (found)
1364 continue;
1365 }
1366
2f357920
LP
1367 if ((r = close_nointr(fd)) < 0) {
1368 /* Valgrind has its own FD and doesn't want to have it closed */
1369 if (errno != EBADF)
1370 goto finish;
1371 }
a0d40ac5
LP
1372 }
1373
2f357920
LP
1374 r = 0;
1375
a0d40ac5
LP
1376finish:
1377 closedir(d);
1378 return r;
1379}
1380
db12775d
LP
1381bool chars_intersect(const char *a, const char *b) {
1382 const char *p;
1383
1384 /* Returns true if any of the chars in a are in b. */
1385 for (p = a; *p; p++)
1386 if (strchr(b, *p))
1387 return true;
1388
1389 return false;
1390}
1391
8b6c7120
LP
1392char *format_timestamp(char *buf, size_t l, usec_t t) {
1393 struct tm tm;
1394 time_t sec;
1395
1396 assert(buf);
1397 assert(l > 0);
1398
1399 if (t <= 0)
1400 return NULL;
1401
1402 sec = (time_t) t / USEC_PER_SEC;
1403
1404 if (strftime(buf, l, "%a, %d %b %Y %H:%M:%S %z", localtime_r(&sec, &tm)) <= 0)
1405 return NULL;
1406
1407 return buf;
1408}
1409
871d7de4
LP
1410char *format_timespan(char *buf, size_t l, usec_t t) {
1411 static const struct {
1412 const char *suffix;
1413 usec_t usec;
1414 } table[] = {
1415 { "w", USEC_PER_WEEK },
1416 { "d", USEC_PER_DAY },
1417 { "h", USEC_PER_HOUR },
1418 { "min", USEC_PER_MINUTE },
1419 { "s", USEC_PER_SEC },
1420 { "ms", USEC_PER_MSEC },
1421 { "us", 1 },
1422 };
1423
1424 unsigned i;
1425 char *p = buf;
1426
1427 assert(buf);
1428 assert(l > 0);
1429
1430 if (t == (usec_t) -1)
1431 return NULL;
1432
1433 /* The result of this function can be parsed with parse_usec */
1434
1435 for (i = 0; i < ELEMENTSOF(table); i++) {
1436 int k;
1437 size_t n;
1438
1439 if (t < table[i].usec)
1440 continue;
1441
1442 if (l <= 1)
1443 break;
1444
1445 k = snprintf(p, l, "%s%llu%s", p > buf ? " " : "", (unsigned long long) (t / table[i].usec), table[i].suffix);
1446 n = MIN((size_t) k, l);
1447
1448 l -= n;
1449 p += n;
1450
1451 t %= table[i].usec;
1452 }
1453
1454 *p = 0;
1455
1456 return buf;
1457}
1458
42856c10
LP
1459bool fstype_is_network(const char *fstype) {
1460 static const char * const table[] = {
1461 "cifs",
1462 "smbfs",
1463 "ncpfs",
1464 "nfs",
ca139f94
LP
1465 "nfs4",
1466 "gfs",
1467 "gfs2"
42856c10
LP
1468 };
1469
1470 unsigned i;
1471
1472 for (i = 0; i < ELEMENTSOF(table); i++)
1473 if (streq(table[i], fstype))
1474 return true;
1475
1476 return false;
1477}
1478
601f6a1e
LP
1479int chvt(int vt) {
1480 int fd, r = 0;
1481
1482 if ((fd = open("/dev/tty0", O_RDWR|O_NOCTTY|O_CLOEXEC)) < 0)
1483 return -errno;
1484
1485 if (vt < 0) {
1486 int tiocl[2] = {
1487 TIOCL_GETKMSGREDIRECT,
1488 0
1489 };
1490
1491 if (ioctl(fd, TIOCLINUX, tiocl) < 0)
1492 return -errno;
1493
1494 vt = tiocl[0] <= 0 ? 1 : tiocl[0];
1495 }
1496
1497 if (ioctl(fd, VT_ACTIVATE, vt) < 0)
1498 r = -errno;
1499
a16e1123 1500 close_nointr_nofail(r);
601f6a1e
LP
1501 return r;
1502}
1503
80876c20
LP
1504int read_one_char(FILE *f, char *ret, bool *need_nl) {
1505 struct termios old_termios, new_termios;
1506 char c;
1507 char line[1024];
1508
1509 assert(f);
1510 assert(ret);
1511
1512 if (tcgetattr(fileno(f), &old_termios) >= 0) {
1513 new_termios = old_termios;
1514
1515 new_termios.c_lflag &= ~ICANON;
1516 new_termios.c_cc[VMIN] = 1;
1517 new_termios.c_cc[VTIME] = 0;
1518
1519 if (tcsetattr(fileno(f), TCSADRAIN, &new_termios) >= 0) {
1520 size_t k;
1521
1522 k = fread(&c, 1, 1, f);
1523
1524 tcsetattr(fileno(f), TCSADRAIN, &old_termios);
1525
1526 if (k <= 0)
1527 return -EIO;
1528
1529 if (need_nl)
1530 *need_nl = c != '\n';
1531
1532 *ret = c;
1533 return 0;
1534 }
1535 }
1536
1537 if (!(fgets(line, sizeof(line), f)))
1538 return -EIO;
1539
1540 truncate_nl(line);
1541
1542 if (strlen(line) != 1)
1543 return -EBADMSG;
1544
1545 if (need_nl)
1546 *need_nl = false;
1547
1548 *ret = line[0];
1549 return 0;
1550}
1551
1552int ask(char *ret, const char *replies, const char *text, ...) {
1553 assert(ret);
1554 assert(replies);
1555 assert(text);
1556
1557 for (;;) {
1558 va_list ap;
1559 char c;
1560 int r;
1561 bool need_nl = true;
1562
b1b2dc0c
LP
1563 fputs("\x1B[1m", stdout);
1564
80876c20
LP
1565 va_start(ap, text);
1566 vprintf(text, ap);
1567 va_end(ap);
1568
b1b2dc0c
LP
1569 fputs("\x1B[0m", stdout);
1570
80876c20
LP
1571 fflush(stdout);
1572
1573 if ((r = read_one_char(stdin, &c, &need_nl)) < 0) {
1574
1575 if (r == -EBADMSG) {
1576 puts("Bad input, please try again.");
1577 continue;
1578 }
1579
1580 putchar('\n');
1581 return r;
1582 }
1583
1584 if (need_nl)
1585 putchar('\n');
1586
1587 if (strchr(replies, c)) {
1588 *ret = c;
1589 return 0;
1590 }
1591
1592 puts("Read unexpected character, please try again.");
1593 }
1594}
1595
1596int reset_terminal(int fd) {
1597 struct termios termios;
1598 int r = 0;
1599
1600 assert(fd >= 0);
1601
aaf694ca 1602 /* Set terminal to some sane defaults */
80876c20
LP
1603
1604 if (tcgetattr(fd, &termios) < 0) {
1605 r = -errno;
1606 goto finish;
1607 }
1608
aaf694ca
LP
1609 /* We only reset the stuff that matters to the software. How
1610 * hardware is set up we don't touch assuming that somebody
1611 * else will do that for us */
1612
1613 termios.c_iflag &= ~(IGNBRK | BRKINT | ISTRIP | INLCR | IGNCR | IUCLC);
80876c20
LP
1614 termios.c_iflag |= ICRNL | IMAXBEL | IUTF8;
1615 termios.c_oflag |= ONLCR;
1616 termios.c_cflag |= CREAD;
1617 termios.c_lflag = ISIG | ICANON | IEXTEN | ECHO | ECHOE | ECHOK | ECHOCTL | ECHOPRT | ECHOKE;
1618
1619 termios.c_cc[VINTR] = 03; /* ^C */
1620 termios.c_cc[VQUIT] = 034; /* ^\ */
1621 termios.c_cc[VERASE] = 0177;
1622 termios.c_cc[VKILL] = 025; /* ^X */
1623 termios.c_cc[VEOF] = 04; /* ^D */
1624 termios.c_cc[VSTART] = 021; /* ^Q */
1625 termios.c_cc[VSTOP] = 023; /* ^S */
1626 termios.c_cc[VSUSP] = 032; /* ^Z */
1627 termios.c_cc[VLNEXT] = 026; /* ^V */
1628 termios.c_cc[VWERASE] = 027; /* ^W */
1629 termios.c_cc[VREPRINT] = 022; /* ^R */
aaf694ca
LP
1630 termios.c_cc[VEOL] = 0;
1631 termios.c_cc[VEOL2] = 0;
80876c20
LP
1632
1633 termios.c_cc[VTIME] = 0;
1634 termios.c_cc[VMIN] = 1;
1635
1636 if (tcsetattr(fd, TCSANOW, &termios) < 0)
1637 r = -errno;
1638
1639finish:
1640 /* Just in case, flush all crap out */
1641 tcflush(fd, TCIOFLUSH);
1642
1643 return r;
1644}
1645
1646int open_terminal(const char *name, int mode) {
1647 int fd, r;
1648
1649 if ((fd = open(name, mode)) < 0)
1650 return -errno;
1651
1652 if ((r = isatty(fd)) < 0) {
1653 close_nointr_nofail(fd);
1654 return -errno;
1655 }
1656
1657 if (!r) {
1658 close_nointr_nofail(fd);
1659 return -ENOTTY;
1660 }
1661
1662 return fd;
1663}
1664
1665int flush_fd(int fd) {
1666 struct pollfd pollfd;
1667
1668 zero(pollfd);
1669 pollfd.fd = fd;
1670 pollfd.events = POLLIN;
1671
1672 for (;;) {
1673 char buf[1024];
1674 ssize_t l;
1675 int r;
1676
1677 if ((r = poll(&pollfd, 1, 0)) < 0) {
1678
1679 if (errno == EINTR)
1680 continue;
1681
1682 return -errno;
1683 }
1684
1685 if (r == 0)
1686 return 0;
1687
1688 if ((l = read(fd, buf, sizeof(buf))) < 0) {
1689
1690 if (errno == EINTR)
1691 continue;
1692
1693 if (errno == EAGAIN)
1694 return 0;
1695
1696 return -errno;
1697 }
1698
1699 if (l <= 0)
1700 return 0;
1701 }
1702}
1703
21de3988 1704int acquire_terminal(const char *name, bool fail, bool force, bool ignore_tiocstty_eperm) {
bab45044 1705 int fd = -1, notify = -1, r, wd = -1;
80876c20
LP
1706
1707 assert(name);
1708
1709 /* We use inotify to be notified when the tty is closed. We
1710 * create the watch before checking if we can actually acquire
1711 * it, so that we don't lose any event.
1712 *
1713 * Note: strictly speaking this actually watches for the
1714 * device being closed, it does *not* really watch whether a
1715 * tty loses its controlling process. However, unless some
1716 * rogue process uses TIOCNOTTY on /dev/tty *after* closing
1717 * its tty otherwise this will not become a problem. As long
1718 * as the administrator makes sure not configure any service
1719 * on the same tty as an untrusted user this should not be a
1720 * problem. (Which he probably should not do anyway.) */
1721
1722 if (!fail && !force) {
1723 if ((notify = inotify_init1(IN_CLOEXEC)) < 0) {
1724 r = -errno;
1725 goto fail;
1726 }
1727
1728 if ((wd = inotify_add_watch(notify, name, IN_CLOSE)) < 0) {
1729 r = -errno;
1730 goto fail;
1731 }
1732 }
1733
1734 for (;;) {
e3d1855b
LP
1735 if (notify >= 0)
1736 if ((r = flush_fd(notify)) < 0)
1737 goto fail;
80876c20
LP
1738
1739 /* We pass here O_NOCTTY only so that we can check the return
1740 * value TIOCSCTTY and have a reliable way to figure out if we
1741 * successfully became the controlling process of the tty */
1742 if ((fd = open_terminal(name, O_RDWR|O_NOCTTY)) < 0)
1743 return -errno;
1744
1745 /* First, try to get the tty */
21de3988
LP
1746 r = ioctl(fd, TIOCSCTTY, force);
1747
1748 /* Sometimes it makes sense to ignore TIOCSCTTY
1749 * returning EPERM, i.e. when very likely we already
1750 * are have this controlling terminal. */
1751 if (r < 0 && errno == EPERM && ignore_tiocstty_eperm)
1752 r = 0;
1753
1754 if (r < 0 && (force || fail || errno != EPERM)) {
80876c20
LP
1755 r = -errno;
1756 goto fail;
1757 }
1758
1759 if (r >= 0)
1760 break;
1761
1762 assert(!fail);
1763 assert(!force);
1764 assert(notify >= 0);
1765
1766 for (;;) {
1767 struct inotify_event e;
1768 ssize_t l;
1769
1770 if ((l = read(notify, &e, sizeof(e))) != sizeof(e)) {
1771
1772 if (l < 0) {
1773
1774 if (errno == EINTR)
1775 continue;
1776
1777 r = -errno;
1778 } else
1779 r = -EIO;
1780
1781 goto fail;
1782 }
1783
1784 if (e.wd != wd || !(e.mask & IN_CLOSE)) {
1785 r = -errno;
1786 goto fail;
1787 }
1788
1789 break;
1790 }
1791
1792 /* We close the tty fd here since if the old session
1793 * ended our handle will be dead. It's important that
1794 * we do this after sleeping, so that we don't enter
1795 * an endless loop. */
1796 close_nointr_nofail(fd);
1797 }
1798
1799 if (notify >= 0)
a16e1123 1800 close_nointr_nofail(notify);
80876c20
LP
1801
1802 if ((r = reset_terminal(fd)) < 0)
1803 log_warning("Failed to reset terminal: %s", strerror(-r));
1804
1805 return fd;
1806
1807fail:
1808 if (fd >= 0)
a16e1123 1809 close_nointr_nofail(fd);
80876c20
LP
1810
1811 if (notify >= 0)
a16e1123 1812 close_nointr_nofail(notify);
80876c20
LP
1813
1814 return r;
1815}
1816
1817int release_terminal(void) {
1818 int r = 0, fd;
57cd2192 1819 struct sigaction sa_old, sa_new;
80876c20 1820
57cd2192 1821 if ((fd = open("/dev/tty", O_RDWR|O_NOCTTY|O_NDELAY)) < 0)
80876c20
LP
1822 return -errno;
1823
57cd2192
LP
1824 /* Temporarily ignore SIGHUP, so that we don't get SIGHUP'ed
1825 * by our own TIOCNOTTY */
1826
1827 zero(sa_new);
1828 sa_new.sa_handler = SIG_IGN;
1829 sa_new.sa_flags = SA_RESTART;
1830 assert_se(sigaction(SIGHUP, &sa_new, &sa_old) == 0);
1831
80876c20
LP
1832 if (ioctl(fd, TIOCNOTTY) < 0)
1833 r = -errno;
1834
57cd2192
LP
1835 assert_se(sigaction(SIGHUP, &sa_old, NULL) == 0);
1836
80876c20
LP
1837 close_nointr_nofail(fd);
1838 return r;
1839}
1840
9a34ec5f
LP
1841int sigaction_many(const struct sigaction *sa, ...) {
1842 va_list ap;
1843 int r = 0, sig;
1844
1845 va_start(ap, sa);
1846 while ((sig = va_arg(ap, int)) > 0)
1847 if (sigaction(sig, sa, NULL) < 0)
1848 r = -errno;
1849 va_end(ap);
1850
1851 return r;
1852}
1853
1854int ignore_signals(int sig, ...) {
a337c6fc 1855 struct sigaction sa;
9a34ec5f
LP
1856 va_list ap;
1857 int r = 0;
a337c6fc
LP
1858
1859 zero(sa);
1860 sa.sa_handler = SIG_IGN;
1861 sa.sa_flags = SA_RESTART;
1862
9a34ec5f
LP
1863 if (sigaction(sig, &sa, NULL) < 0)
1864 r = -errno;
1865
1866 va_start(ap, sig);
1867 while ((sig = va_arg(ap, int)) > 0)
1868 if (sigaction(sig, &sa, NULL) < 0)
1869 r = -errno;
1870 va_end(ap);
1871
1872 return r;
1873}
1874
1875int default_signals(int sig, ...) {
1876 struct sigaction sa;
1877 va_list ap;
1878 int r = 0;
1879
1880 zero(sa);
1881 sa.sa_handler = SIG_DFL;
1882 sa.sa_flags = SA_RESTART;
1883
1884 if (sigaction(sig, &sa, NULL) < 0)
1885 r = -errno;
1886
1887 va_start(ap, sig);
1888 while ((sig = va_arg(ap, int)) > 0)
1889 if (sigaction(sig, &sa, NULL) < 0)
1890 r = -errno;
1891 va_end(ap);
1892
1893 return r;
a337c6fc
LP
1894}
1895
8d567588
LP
1896int close_pipe(int p[]) {
1897 int a = 0, b = 0;
1898
1899 assert(p);
1900
1901 if (p[0] >= 0) {
1902 a = close_nointr(p[0]);
1903 p[0] = -1;
1904 }
1905
1906 if (p[1] >= 0) {
1907 b = close_nointr(p[1]);
1908 p[1] = -1;
1909 }
1910
1911 return a < 0 ? a : b;
1912}
1913
1914ssize_t loop_read(int fd, void *buf, size_t nbytes) {
1915 uint8_t *p;
1916 ssize_t n = 0;
1917
1918 assert(fd >= 0);
1919 assert(buf);
1920
1921 p = buf;
1922
1923 while (nbytes > 0) {
1924 ssize_t k;
1925
1926 if ((k = read(fd, p, nbytes)) <= 0) {
1927
1928 if (errno == EINTR)
1929 continue;
1930
1931 if (errno == EAGAIN) {
1932 struct pollfd pollfd;
1933
1934 zero(pollfd);
1935 pollfd.fd = fd;
1936 pollfd.events = POLLIN;
1937
1938 if (poll(&pollfd, 1, -1) < 0) {
1939 if (errno == EINTR)
1940 continue;
1941
1942 return n > 0 ? n : -errno;
1943 }
1944
1945 if (pollfd.revents != POLLIN)
1946 return n > 0 ? n : -EIO;
1947
1948 continue;
1949 }
1950
1951 return n > 0 ? n : (k < 0 ? -errno : 0);
1952 }
1953
1954 p += k;
1955 nbytes -= k;
1956 n += k;
1957 }
1958
1959 return n;
1960}
1961
1962int path_is_mount_point(const char *t) {
1963 struct stat a, b;
1964 char *copy;
1965
1966 if (lstat(t, &a) < 0) {
1967
1968 if (errno == ENOENT)
1969 return 0;
1970
1971 return -errno;
1972 }
1973
1974 if (!(copy = strdup(t)))
1975 return -ENOMEM;
1976
1977 if (lstat(dirname(copy), &b) < 0) {
1978 free(copy);
1979 return -errno;
1980 }
1981
1982 free(copy);
1983
1984 return a.st_dev != b.st_dev;
1985}
1986
24a6e4a4
LP
1987int parse_usec(const char *t, usec_t *usec) {
1988 static const struct {
1989 const char *suffix;
1990 usec_t usec;
1991 } table[] = {
1992 { "sec", USEC_PER_SEC },
1993 { "s", USEC_PER_SEC },
1994 { "min", USEC_PER_MINUTE },
1995 { "hr", USEC_PER_HOUR },
1996 { "h", USEC_PER_HOUR },
1997 { "d", USEC_PER_DAY },
1998 { "w", USEC_PER_WEEK },
1999 { "msec", USEC_PER_MSEC },
2000 { "ms", USEC_PER_MSEC },
2001 { "m", USEC_PER_MINUTE },
2002 { "usec", 1ULL },
2003 { "us", 1ULL },
2004 { "", USEC_PER_SEC },
2005 };
2006
2007 const char *p;
2008 usec_t r = 0;
2009
2010 assert(t);
2011 assert(usec);
2012
2013 p = t;
2014 do {
2015 long long l;
2016 char *e;
2017 unsigned i;
2018
2019 errno = 0;
2020 l = strtoll(p, &e, 10);
2021
2022 if (errno != 0)
2023 return -errno;
2024
2025 if (l < 0)
2026 return -ERANGE;
2027
2028 if (e == p)
2029 return -EINVAL;
2030
2031 e += strspn(e, WHITESPACE);
2032
2033 for (i = 0; i < ELEMENTSOF(table); i++)
2034 if (startswith(e, table[i].suffix)) {
2035 r += (usec_t) l * table[i].usec;
2036 p = e + strlen(table[i].suffix);
2037 break;
2038 }
2039
2040 if (i >= ELEMENTSOF(table))
2041 return -EINVAL;
2042
2043 } while (*p != 0);
2044
2045 *usec = r;
2046
2047 return 0;
2048}
2049
843d2643
LP
2050int make_stdio(int fd) {
2051 int r, s, t;
2052
2053 assert(fd >= 0);
2054
2055 r = dup2(fd, STDIN_FILENO);
2056 s = dup2(fd, STDOUT_FILENO);
2057 t = dup2(fd, STDERR_FILENO);
2058
2059 if (fd >= 3)
2060 close_nointr_nofail(fd);
2061
2062 if (r < 0 || s < 0 || t < 0)
2063 return -errno;
2064
2065 return 0;
2066}
2067
cb8a8f78
LP
2068bool is_clean_exit(int code, int status) {
2069
2070 if (code == CLD_EXITED)
2071 return status == 0;
2072
2073 /* If a daemon does not implement handlers for some of the
2074 * signals that's not considered an unclean shutdown */
2075 if (code == CLD_KILLED)
2076 return
2077 status == SIGHUP ||
2078 status == SIGINT ||
2079 status == SIGTERM ||
2080 status == SIGPIPE;
2081
2082 return false;
2083}
2084
8407a5d0
LP
2085bool is_device_path(const char *path) {
2086
2087 /* Returns true on paths that refer to a device, either in
2088 * sysfs or in /dev */
2089
2090 return
2091 path_startswith(path, "/dev/") ||
2092 path_startswith(path, "/sys/");
2093}
2094
1dccbe19
LP
2095static const char *const ioprio_class_table[] = {
2096 [IOPRIO_CLASS_NONE] = "none",
2097 [IOPRIO_CLASS_RT] = "realtime",
2098 [IOPRIO_CLASS_BE] = "best-effort",
2099 [IOPRIO_CLASS_IDLE] = "idle"
2100};
2101
2102DEFINE_STRING_TABLE_LOOKUP(ioprio_class, int);
2103
2104static const char *const sigchld_code_table[] = {
2105 [CLD_EXITED] = "exited",
2106 [CLD_KILLED] = "killed",
2107 [CLD_DUMPED] = "dumped",
2108 [CLD_TRAPPED] = "trapped",
2109 [CLD_STOPPED] = "stopped",
2110 [CLD_CONTINUED] = "continued",
2111};
2112
2113DEFINE_STRING_TABLE_LOOKUP(sigchld_code, int);
2114
2115static const char *const log_facility_table[LOG_NFACILITIES] = {
2116 [LOG_FAC(LOG_KERN)] = "kern",
2117 [LOG_FAC(LOG_USER)] = "user",
2118 [LOG_FAC(LOG_MAIL)] = "mail",
2119 [LOG_FAC(LOG_DAEMON)] = "daemon",
2120 [LOG_FAC(LOG_AUTH)] = "auth",
2121 [LOG_FAC(LOG_SYSLOG)] = "syslog",
2122 [LOG_FAC(LOG_LPR)] = "lpr",
2123 [LOG_FAC(LOG_NEWS)] = "news",
2124 [LOG_FAC(LOG_UUCP)] = "uucp",
2125 [LOG_FAC(LOG_CRON)] = "cron",
2126 [LOG_FAC(LOG_AUTHPRIV)] = "authpriv",
2127 [LOG_FAC(LOG_FTP)] = "ftp",
2128 [LOG_FAC(LOG_LOCAL0)] = "local0",
2129 [LOG_FAC(LOG_LOCAL1)] = "local1",
2130 [LOG_FAC(LOG_LOCAL2)] = "local2",
2131 [LOG_FAC(LOG_LOCAL3)] = "local3",
2132 [LOG_FAC(LOG_LOCAL4)] = "local4",
2133 [LOG_FAC(LOG_LOCAL5)] = "local5",
2134 [LOG_FAC(LOG_LOCAL6)] = "local6",
2135 [LOG_FAC(LOG_LOCAL7)] = "local7"
2136};
2137
2138DEFINE_STRING_TABLE_LOOKUP(log_facility, int);
2139
2140static const char *const log_level_table[] = {
2141 [LOG_EMERG] = "emerg",
2142 [LOG_ALERT] = "alert",
2143 [LOG_CRIT] = "crit",
2144 [LOG_ERR] = "err",
2145 [LOG_WARNING] = "warning",
2146 [LOG_NOTICE] = "notice",
2147 [LOG_INFO] = "info",
2148 [LOG_DEBUG] = "debug"
2149};
2150
2151DEFINE_STRING_TABLE_LOOKUP(log_level, int);
2152
2153static const char* const sched_policy_table[] = {
2154 [SCHED_OTHER] = "other",
2155 [SCHED_BATCH] = "batch",
2156 [SCHED_IDLE] = "idle",
2157 [SCHED_FIFO] = "fifo",
2158 [SCHED_RR] = "rr"
2159};
2160
2161DEFINE_STRING_TABLE_LOOKUP(sched_policy, int);
2162
2163static const char* const rlimit_table[] = {
2164 [RLIMIT_CPU] = "LimitCPU",
2165 [RLIMIT_FSIZE] = "LimitFSIZE",
2166 [RLIMIT_DATA] = "LimitDATA",
2167 [RLIMIT_STACK] = "LimitSTACK",
2168 [RLIMIT_CORE] = "LimitCORE",
2169 [RLIMIT_RSS] = "LimitRSS",
2170 [RLIMIT_NOFILE] = "LimitNOFILE",
2171 [RLIMIT_AS] = "LimitAS",
2172 [RLIMIT_NPROC] = "LimitNPROC",
2173 [RLIMIT_MEMLOCK] = "LimitMEMLOCK",
2174 [RLIMIT_LOCKS] = "LimitLOCKS",
2175 [RLIMIT_SIGPENDING] = "LimitSIGPENDING",
2176 [RLIMIT_MSGQUEUE] = "LimitMSGQUEUE",
2177 [RLIMIT_NICE] = "LimitNICE",
2178 [RLIMIT_RTPRIO] = "LimitRTPRIO",
2179 [RLIMIT_RTTIME] = "LimitRTTIME"
2180};
2181
2182DEFINE_STRING_TABLE_LOOKUP(rlimit, int);