]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/util.c
execute: setup namespace after doing NSS calls
[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
2c7108c4
LP
585int readlink_and_make_absolute(const char *p, char **r) {
586 char *target, *k;
587 int j;
588
589 assert(p);
590 assert(r);
591
592 if ((j = readlink_malloc(p, &target)) < 0)
593 return j;
594
595 k = file_in_same_dir(p, target);
596 free(target);
597
598 if (!k)
599 return -ENOMEM;
600
601 *r = k;
602 return 0;
603}
604
87f0e418
LP
605char *file_name_from_path(const char *p) {
606 char *r;
607
608 assert(p);
609
610 if ((r = strrchr(p, '/')))
611 return r + 1;
612
613 return (char*) p;
614}
0301abf4
LP
615
616bool path_is_absolute(const char *p) {
617 assert(p);
618
619 return p[0] == '/';
620}
621
622bool is_path(const char *p) {
623
624 return !!strchr(p, '/');
625}
626
627char *path_make_absolute(const char *p, const char *prefix) {
628 char *r;
629
630 assert(p);
631
65d2ebdc
LP
632 /* Makes every item in the list an absolute path by prepending
633 * the prefix, if specified and necessary */
634
0301abf4
LP
635 if (path_is_absolute(p) || !prefix)
636 return strdup(p);
637
638 if (asprintf(&r, "%s/%s", prefix, p) < 0)
639 return NULL;
640
641 return r;
642}
2a987ee8 643
65d2ebdc
LP
644char *path_make_absolute_cwd(const char *p) {
645 char *cwd, *r;
646
647 assert(p);
648
649 /* Similar to path_make_absolute(), but prefixes with the
650 * current working directory. */
651
652 if (path_is_absolute(p))
653 return strdup(p);
654
655 if (!(cwd = get_current_dir_name()))
656 return NULL;
657
658 r = path_make_absolute(p, cwd);
659 free(cwd);
660
661 return r;
662}
663
664char **strv_path_make_absolute_cwd(char **l) {
665 char **s;
666
667 /* Goes through every item in the string list and makes it
668 * absolute. This works in place and won't rollback any
669 * changes on failure. */
670
671 STRV_FOREACH(s, l) {
672 char *t;
673
674 if (!(t = path_make_absolute_cwd(*s)))
675 return NULL;
676
677 free(*s);
678 *s = t;
679 }
680
681 return l;
682}
683
c3f6d675
LP
684char **strv_path_canonicalize(char **l) {
685 char **s;
686 unsigned k = 0;
687 bool enomem = false;
688
689 if (strv_isempty(l))
690 return l;
691
692 /* Goes through every item in the string list and canonicalize
693 * the path. This works in place and won't rollback any
694 * changes on failure. */
695
696 STRV_FOREACH(s, l) {
697 char *t, *u;
698
699 t = path_make_absolute_cwd(*s);
700 free(*s);
701
702 if (!t) {
703 enomem = true;
704 continue;
705 }
706
707 errno = 0;
708 u = canonicalize_file_name(t);
709 free(t);
710
711 if (!u) {
712 if (errno == ENOMEM || !errno)
713 enomem = true;
714
715 continue;
716 }
717
718 l[k++] = u;
719 }
720
721 l[k] = NULL;
722
723 if (enomem)
724 return NULL;
725
726 return l;
727}
728
2a987ee8
LP
729int reset_all_signal_handlers(void) {
730 int sig;
731
732 for (sig = 1; sig < _NSIG; sig++) {
733 struct sigaction sa;
734
735 if (sig == SIGKILL || sig == SIGSTOP)
736 continue;
737
738 zero(sa);
739 sa.sa_handler = SIG_DFL;
431c32bf 740 sa.sa_flags = SA_RESTART;
2a987ee8
LP
741
742 /* On Linux the first two RT signals are reserved by
743 * glibc, and sigaction() will return EINVAL for them. */
744 if ((sigaction(sig, &sa, NULL) < 0))
745 if (errno != EINVAL)
746 return -errno;
747 }
748
8e274523 749 return 0;
2a987ee8 750}
4a72ff34
LP
751
752char *strstrip(char *s) {
753 char *e, *l = NULL;
754
755 /* Drops trailing whitespace. Modifies the string in
756 * place. Returns pointer to first non-space character */
757
758 s += strspn(s, WHITESPACE);
759
760 for (e = s; *e; e++)
761 if (!strchr(WHITESPACE, *e))
762 l = e;
763
764 if (l)
765 *(l+1) = 0;
766 else
767 *s = 0;
768
769 return s;
4a72ff34
LP
770}
771
ee9b5e01
LP
772char *delete_chars(char *s, const char *bad) {
773 char *f, *t;
774
775 /* Drops all whitespace, regardless where in the string */
776
777 for (f = s, t = s; *f; f++) {
778 if (strchr(bad, *f))
779 continue;
780
781 *(t++) = *f;
782 }
783
784 *t = 0;
785
786 return s;
787}
788
4a72ff34
LP
789char *file_in_same_dir(const char *path, const char *filename) {
790 char *e, *r;
791 size_t k;
792
793 assert(path);
794 assert(filename);
795
796 /* This removes the last component of path and appends
797 * filename, unless the latter is absolute anyway or the
798 * former isn't */
799
800 if (path_is_absolute(filename))
801 return strdup(filename);
802
803 if (!(e = strrchr(path, '/')))
804 return strdup(filename);
805
806 k = strlen(filename);
807 if (!(r = new(char, e-path+1+k+1)))
808 return NULL;
809
810 memcpy(r, path, e-path+1);
811 memcpy(r+(e-path)+1, filename, k+1);
812
813 return r;
814}
fb624d04 815
a9f5d454
LP
816int mkdir_parents(const char *path, mode_t mode) {
817 const char *p, *e;
818
819 assert(path);
820
821 /* Creates every parent directory in the path except the last
822 * component. */
823
824 p = path + strspn(path, "/");
825 for (;;) {
826 int r;
827 char *t;
828
829 e = p + strcspn(p, "/");
830 p = e + strspn(e, "/");
831
832 /* Is this the last component? If so, then we're
833 * done */
834 if (*p == 0)
835 return 0;
836
837 if (!(t = strndup(path, e - path)))
838 return -ENOMEM;
839
840 r = mkdir(t, mode);
841
842 free(t);
843
844 if (r < 0 && errno != EEXIST)
845 return -errno;
846 }
847}
848
bbd67135
LP
849int mkdir_p(const char *path, mode_t mode) {
850 int r;
851
852 /* Like mkdir -p */
853
854 if ((r = mkdir_parents(path, mode)) < 0)
855 return r;
856
857 if (mkdir(path, mode) < 0)
858 return -errno;
859
860 return 0;
861}
862
fb624d04
LP
863char hexchar(int x) {
864 static const char table[16] = "0123456789abcdef";
865
866 return table[x & 15];
867}
4fe88d28
LP
868
869int unhexchar(char c) {
870
871 if (c >= '0' && c <= '9')
872 return c - '0';
873
874 if (c >= 'a' && c <= 'f')
ea430986 875 return c - 'a' + 10;
4fe88d28
LP
876
877 if (c >= 'A' && c <= 'F')
ea430986 878 return c - 'A' + 10;
4fe88d28
LP
879
880 return -1;
881}
882
883char octchar(int x) {
884 return '0' + (x & 7);
885}
886
887int unoctchar(char c) {
888
889 if (c >= '0' && c <= '7')
890 return c - '0';
891
892 return -1;
893}
894
5af98f82
LP
895char decchar(int x) {
896 return '0' + (x % 10);
897}
898
899int undecchar(char c) {
900
901 if (c >= '0' && c <= '9')
902 return c - '0';
903
904 return -1;
905}
906
4fe88d28
LP
907char *cescape(const char *s) {
908 char *r, *t;
909 const char *f;
910
911 assert(s);
912
913 /* Does C style string escaping. */
914
915 if (!(r = new(char, strlen(s)*4 + 1)))
916 return NULL;
917
918 for (f = s, t = r; *f; f++)
919
920 switch (*f) {
921
922 case '\a':
923 *(t++) = '\\';
924 *(t++) = 'a';
925 break;
926 case '\b':
927 *(t++) = '\\';
928 *(t++) = 'b';
929 break;
930 case '\f':
931 *(t++) = '\\';
932 *(t++) = 'f';
933 break;
934 case '\n':
935 *(t++) = '\\';
936 *(t++) = 'n';
937 break;
938 case '\r':
939 *(t++) = '\\';
940 *(t++) = 'r';
941 break;
942 case '\t':
943 *(t++) = '\\';
944 *(t++) = 't';
945 break;
946 case '\v':
947 *(t++) = '\\';
948 *(t++) = 'v';
949 break;
950 case '\\':
951 *(t++) = '\\';
952 *(t++) = '\\';
953 break;
954 case '"':
955 *(t++) = '\\';
956 *(t++) = '"';
957 break;
958 case '\'':
959 *(t++) = '\\';
960 *(t++) = '\'';
961 break;
962
963 default:
964 /* For special chars we prefer octal over
965 * hexadecimal encoding, simply because glib's
966 * g_strescape() does the same */
967 if ((*f < ' ') || (*f >= 127)) {
968 *(t++) = '\\';
969 *(t++) = octchar((unsigned char) *f >> 6);
970 *(t++) = octchar((unsigned char) *f >> 3);
971 *(t++) = octchar((unsigned char) *f);
972 } else
973 *(t++) = *f;
974 break;
975 }
976
977 *t = 0;
978
979 return r;
980}
981
982char *cunescape(const char *s) {
983 char *r, *t;
984 const char *f;
985
986 assert(s);
987
988 /* Undoes C style string escaping */
989
990 if (!(r = new(char, strlen(s)+1)))
991 return r;
992
993 for (f = s, t = r; *f; f++) {
994
995 if (*f != '\\') {
996 *(t++) = *f;
997 continue;
998 }
999
1000 f++;
1001
1002 switch (*f) {
1003
1004 case 'a':
1005 *(t++) = '\a';
1006 break;
1007 case 'b':
1008 *(t++) = '\b';
1009 break;
1010 case 'f':
1011 *(t++) = '\f';
1012 break;
1013 case 'n':
1014 *(t++) = '\n';
1015 break;
1016 case 'r':
1017 *(t++) = '\r';
1018 break;
1019 case 't':
1020 *(t++) = '\t';
1021 break;
1022 case 'v':
1023 *(t++) = '\v';
1024 break;
1025 case '\\':
1026 *(t++) = '\\';
1027 break;
1028 case '"':
1029 *(t++) = '"';
1030 break;
1031 case '\'':
1032 *(t++) = '\'';
1033 break;
1034
1035 case 'x': {
1036 /* hexadecimal encoding */
1037 int a, b;
1038
1039 if ((a = unhexchar(f[1])) < 0 ||
1040 (b = unhexchar(f[2])) < 0) {
1041 /* Invalid escape code, let's take it literal then */
1042 *(t++) = '\\';
1043 *(t++) = 'x';
1044 } else {
1045 *(t++) = (char) ((a << 4) | b);
1046 f += 2;
1047 }
1048
1049 break;
1050 }
1051
1052 case '0':
1053 case '1':
1054 case '2':
1055 case '3':
1056 case '4':
1057 case '5':
1058 case '6':
1059 case '7': {
1060 /* octal encoding */
1061 int a, b, c;
1062
1063 if ((a = unoctchar(f[0])) < 0 ||
1064 (b = unoctchar(f[1])) < 0 ||
1065 (c = unoctchar(f[2])) < 0) {
1066 /* Invalid escape code, let's take it literal then */
1067 *(t++) = '\\';
1068 *(t++) = f[0];
1069 } else {
1070 *(t++) = (char) ((a << 6) | (b << 3) | c);
1071 f += 2;
1072 }
1073
1074 break;
1075 }
1076
1077 case 0:
1078 /* premature end of string.*/
1079 *(t++) = '\\';
1080 goto finish;
1081
1082 default:
1083 /* Invalid escape code, let's take it literal then */
1084 *(t++) = '\\';
1085 *(t++) = 'f';
1086 break;
1087 }
1088 }
1089
1090finish:
1091 *t = 0;
1092 return r;
1093}
1094
1095
1096char *xescape(const char *s, const char *bad) {
1097 char *r, *t;
1098 const char *f;
1099
1100 /* Escapes all chars in bad, in addition to \ and all special
1101 * chars, in \xFF style escaping. May be reversed with
1102 * cunescape. */
1103
1104 if (!(r = new(char, strlen(s)*4+1)))
1105 return NULL;
1106
1107 for (f = s, t = r; *f; f++) {
1108
b866264a
LP
1109 if ((*f < ' ') || (*f >= 127) ||
1110 (*f == '\\') || strchr(bad, *f)) {
4fe88d28
LP
1111 *(t++) = '\\';
1112 *(t++) = 'x';
1113 *(t++) = hexchar(*f >> 4);
1114 *(t++) = hexchar(*f);
1115 } else
1116 *(t++) = *f;
1117 }
1118
1119 *t = 0;
1120
1121 return r;
1122}
1123
ea430986 1124char *bus_path_escape(const char *s) {
ea430986
LP
1125 char *r, *t;
1126 const char *f;
1127
47be870b
LP
1128 assert(s);
1129
ea430986
LP
1130 /* Escapes all chars that D-Bus' object path cannot deal
1131 * with. Can be reverse with bus_path_unescape() */
1132
1133 if (!(r = new(char, strlen(s)*3+1)))
1134 return NULL;
1135
1136 for (f = s, t = r; *f; f++) {
1137
1138 if (!(*f >= 'A' && *f <= 'Z') &&
1139 !(*f >= 'a' && *f <= 'z') &&
1140 !(*f >= '0' && *f <= '9')) {
1141 *(t++) = '_';
1142 *(t++) = hexchar(*f >> 4);
1143 *(t++) = hexchar(*f);
1144 } else
1145 *(t++) = *f;
1146 }
1147
1148 *t = 0;
1149
1150 return r;
1151}
1152
9e2f7c11 1153char *bus_path_unescape(const char *f) {
ea430986 1154 char *r, *t;
ea430986 1155
9e2f7c11 1156 assert(f);
47be870b 1157
9e2f7c11 1158 if (!(r = strdup(f)))
ea430986
LP
1159 return NULL;
1160
9e2f7c11 1161 for (t = r; *f; f++) {
ea430986
LP
1162
1163 if (*f == '_') {
1164 int a, b;
1165
1166 if ((a = unhexchar(f[1])) < 0 ||
1167 (b = unhexchar(f[2])) < 0) {
1168 /* Invalid escape code, let's take it literal then */
1169 *(t++) = '_';
1170 } else {
1171 *(t++) = (char) ((a << 4) | b);
1172 f += 2;
1173 }
1174 } else
1175 *(t++) = *f;
1176 }
1177
1178 *t = 0;
1179
1180 return r;
1181}
1182
4fe88d28
LP
1183char *path_kill_slashes(char *path) {
1184 char *f, *t;
1185 bool slash = false;
1186
1187 /* Removes redundant inner and trailing slashes. Modifies the
1188 * passed string in-place.
1189 *
1190 * ///foo///bar/ becomes /foo/bar
1191 */
1192
1193 for (f = path, t = path; *f; f++) {
1194
1195 if (*f == '/') {
1196 slash = true;
1197 continue;
1198 }
1199
1200 if (slash) {
1201 slash = false;
1202 *(t++) = '/';
1203 }
1204
1205 *(t++) = *f;
1206 }
1207
1208 /* Special rule, if we are talking of the root directory, a
1209 trailing slash is good */
1210
1211 if (t == path && slash)
1212 *(t++) = '/';
1213
1214 *t = 0;
1215 return path;
1216}
1217
1218bool path_startswith(const char *path, const char *prefix) {
1219 assert(path);
1220 assert(prefix);
1221
1222 if ((path[0] == '/') != (prefix[0] == '/'))
1223 return false;
1224
1225 for (;;) {
1226 size_t a, b;
1227
1228 path += strspn(path, "/");
1229 prefix += strspn(prefix, "/");
1230
1231 if (*prefix == 0)
1232 return true;
1233
1234 if (*path == 0)
1235 return false;
1236
1237 a = strcspn(path, "/");
1238 b = strcspn(prefix, "/");
1239
1240 if (a != b)
1241 return false;
1242
1243 if (memcmp(path, prefix, a) != 0)
1244 return false;
1245
1246 path += a;
1247 prefix += b;
1248 }
1249}
1250
15ae422b
LP
1251bool path_equal(const char *a, const char *b) {
1252 assert(a);
1253 assert(b);
1254
1255 if ((a[0] == '/') != (b[0] == '/'))
1256 return false;
1257
1258 for (;;) {
1259 size_t j, k;
1260
1261 a += strspn(a, "/");
1262 b += strspn(b, "/");
1263
1264 if (*a == 0 && *b == 0)
1265 return true;
1266
1267 if (*a == 0 || *b == 0)
1268 return false;
1269
1270 j = strcspn(a, "/");
1271 k = strcspn(b, "/");
1272
1273 if (j != k)
1274 return false;
1275
1276 if (memcmp(a, b, j) != 0)
1277 return false;
1278
1279 a += j;
1280 b += k;
1281 }
1282}
1283
67d51650 1284char *ascii_strlower(char *t) {
4fe88d28
LP
1285 char *p;
1286
67d51650 1287 assert(t);
4fe88d28 1288
67d51650 1289 for (p = t; *p; p++)
4fe88d28
LP
1290 if (*p >= 'A' && *p <= 'Z')
1291 *p = *p - 'A' + 'a';
1292
67d51650 1293 return t;
4fe88d28 1294}
1dccbe19 1295
c85dc17b
LP
1296bool ignore_file(const char *filename) {
1297 assert(filename);
1298
1299 return
1300 filename[0] == '.' ||
6c78be3c 1301 streq(filename, "lost+found") ||
c85dc17b
LP
1302 endswith(filename, "~") ||
1303 endswith(filename, ".rpmnew") ||
1304 endswith(filename, ".rpmsave") ||
1305 endswith(filename, ".rpmorig") ||
1306 endswith(filename, ".dpkg-old") ||
1307 endswith(filename, ".dpkg-new") ||
1308 endswith(filename, ".swp");
1309}
1310
3a0ecb08
LP
1311int fd_nonblock(int fd, bool nonblock) {
1312 int flags;
1313
1314 assert(fd >= 0);
1315
1316 if ((flags = fcntl(fd, F_GETFL, 0)) < 0)
1317 return -errno;
1318
1319 if (nonblock)
1320 flags |= O_NONBLOCK;
1321 else
1322 flags &= ~O_NONBLOCK;
1323
1324 if (fcntl(fd, F_SETFL, flags) < 0)
1325 return -errno;
1326
1327 return 0;
1328}
1329
1330int fd_cloexec(int fd, bool cloexec) {
1331 int flags;
1332
1333 assert(fd >= 0);
1334
1335 if ((flags = fcntl(fd, F_GETFD, 0)) < 0)
1336 return -errno;
1337
1338 if (cloexec)
1339 flags |= FD_CLOEXEC;
1340 else
1341 flags &= ~FD_CLOEXEC;
1342
1343 if (fcntl(fd, F_SETFD, flags) < 0)
1344 return -errno;
1345
1346 return 0;
1347}
1348
a0d40ac5
LP
1349int close_all_fds(const int except[], unsigned n_except) {
1350 DIR *d;
1351 struct dirent *de;
1352 int r = 0;
1353
1354 if (!(d = opendir("/proc/self/fd")))
1355 return -errno;
1356
1357 while ((de = readdir(d))) {
a7610064 1358 int fd = -1;
a0d40ac5 1359
a16e1123 1360 if (ignore_file(de->d_name))
a0d40ac5
LP
1361 continue;
1362
1363 if ((r = safe_atoi(de->d_name, &fd)) < 0)
1364 goto finish;
1365
1366 if (fd < 3)
1367 continue;
1368
1369 if (fd == dirfd(d))
1370 continue;
1371
1372 if (except) {
1373 bool found;
1374 unsigned i;
1375
1376 found = false;
1377 for (i = 0; i < n_except; i++)
1378 if (except[i] == fd) {
1379 found = true;
1380 break;
1381 }
1382
1383 if (found)
1384 continue;
1385 }
1386
2f357920
LP
1387 if ((r = close_nointr(fd)) < 0) {
1388 /* Valgrind has its own FD and doesn't want to have it closed */
1389 if (errno != EBADF)
1390 goto finish;
1391 }
a0d40ac5
LP
1392 }
1393
2f357920
LP
1394 r = 0;
1395
a0d40ac5
LP
1396finish:
1397 closedir(d);
1398 return r;
1399}
1400
db12775d
LP
1401bool chars_intersect(const char *a, const char *b) {
1402 const char *p;
1403
1404 /* Returns true if any of the chars in a are in b. */
1405 for (p = a; *p; p++)
1406 if (strchr(b, *p))
1407 return true;
1408
1409 return false;
1410}
1411
8b6c7120
LP
1412char *format_timestamp(char *buf, size_t l, usec_t t) {
1413 struct tm tm;
1414 time_t sec;
1415
1416 assert(buf);
1417 assert(l > 0);
1418
1419 if (t <= 0)
1420 return NULL;
1421
1422 sec = (time_t) t / USEC_PER_SEC;
1423
1424 if (strftime(buf, l, "%a, %d %b %Y %H:%M:%S %z", localtime_r(&sec, &tm)) <= 0)
1425 return NULL;
1426
1427 return buf;
1428}
1429
871d7de4
LP
1430char *format_timespan(char *buf, size_t l, usec_t t) {
1431 static const struct {
1432 const char *suffix;
1433 usec_t usec;
1434 } table[] = {
1435 { "w", USEC_PER_WEEK },
1436 { "d", USEC_PER_DAY },
1437 { "h", USEC_PER_HOUR },
1438 { "min", USEC_PER_MINUTE },
1439 { "s", USEC_PER_SEC },
1440 { "ms", USEC_PER_MSEC },
1441 { "us", 1 },
1442 };
1443
1444 unsigned i;
1445 char *p = buf;
1446
1447 assert(buf);
1448 assert(l > 0);
1449
1450 if (t == (usec_t) -1)
1451 return NULL;
1452
1453 /* The result of this function can be parsed with parse_usec */
1454
1455 for (i = 0; i < ELEMENTSOF(table); i++) {
1456 int k;
1457 size_t n;
1458
1459 if (t < table[i].usec)
1460 continue;
1461
1462 if (l <= 1)
1463 break;
1464
1465 k = snprintf(p, l, "%s%llu%s", p > buf ? " " : "", (unsigned long long) (t / table[i].usec), table[i].suffix);
1466 n = MIN((size_t) k, l);
1467
1468 l -= n;
1469 p += n;
1470
1471 t %= table[i].usec;
1472 }
1473
1474 *p = 0;
1475
1476 return buf;
1477}
1478
42856c10
LP
1479bool fstype_is_network(const char *fstype) {
1480 static const char * const table[] = {
1481 "cifs",
1482 "smbfs",
1483 "ncpfs",
1484 "nfs",
ca139f94
LP
1485 "nfs4",
1486 "gfs",
1487 "gfs2"
42856c10
LP
1488 };
1489
1490 unsigned i;
1491
1492 for (i = 0; i < ELEMENTSOF(table); i++)
1493 if (streq(table[i], fstype))
1494 return true;
1495
1496 return false;
1497}
1498
601f6a1e
LP
1499int chvt(int vt) {
1500 int fd, r = 0;
1501
1502 if ((fd = open("/dev/tty0", O_RDWR|O_NOCTTY|O_CLOEXEC)) < 0)
1503 return -errno;
1504
1505 if (vt < 0) {
1506 int tiocl[2] = {
1507 TIOCL_GETKMSGREDIRECT,
1508 0
1509 };
1510
1511 if (ioctl(fd, TIOCLINUX, tiocl) < 0)
1512 return -errno;
1513
1514 vt = tiocl[0] <= 0 ? 1 : tiocl[0];
1515 }
1516
1517 if (ioctl(fd, VT_ACTIVATE, vt) < 0)
1518 r = -errno;
1519
a16e1123 1520 close_nointr_nofail(r);
601f6a1e
LP
1521 return r;
1522}
1523
80876c20
LP
1524int read_one_char(FILE *f, char *ret, bool *need_nl) {
1525 struct termios old_termios, new_termios;
1526 char c;
1527 char line[1024];
1528
1529 assert(f);
1530 assert(ret);
1531
1532 if (tcgetattr(fileno(f), &old_termios) >= 0) {
1533 new_termios = old_termios;
1534
1535 new_termios.c_lflag &= ~ICANON;
1536 new_termios.c_cc[VMIN] = 1;
1537 new_termios.c_cc[VTIME] = 0;
1538
1539 if (tcsetattr(fileno(f), TCSADRAIN, &new_termios) >= 0) {
1540 size_t k;
1541
1542 k = fread(&c, 1, 1, f);
1543
1544 tcsetattr(fileno(f), TCSADRAIN, &old_termios);
1545
1546 if (k <= 0)
1547 return -EIO;
1548
1549 if (need_nl)
1550 *need_nl = c != '\n';
1551
1552 *ret = c;
1553 return 0;
1554 }
1555 }
1556
1557 if (!(fgets(line, sizeof(line), f)))
1558 return -EIO;
1559
1560 truncate_nl(line);
1561
1562 if (strlen(line) != 1)
1563 return -EBADMSG;
1564
1565 if (need_nl)
1566 *need_nl = false;
1567
1568 *ret = line[0];
1569 return 0;
1570}
1571
1572int ask(char *ret, const char *replies, const char *text, ...) {
1573 assert(ret);
1574 assert(replies);
1575 assert(text);
1576
1577 for (;;) {
1578 va_list ap;
1579 char c;
1580 int r;
1581 bool need_nl = true;
1582
b1b2dc0c
LP
1583 fputs("\x1B[1m", stdout);
1584
80876c20
LP
1585 va_start(ap, text);
1586 vprintf(text, ap);
1587 va_end(ap);
1588
b1b2dc0c
LP
1589 fputs("\x1B[0m", stdout);
1590
80876c20
LP
1591 fflush(stdout);
1592
1593 if ((r = read_one_char(stdin, &c, &need_nl)) < 0) {
1594
1595 if (r == -EBADMSG) {
1596 puts("Bad input, please try again.");
1597 continue;
1598 }
1599
1600 putchar('\n');
1601 return r;
1602 }
1603
1604 if (need_nl)
1605 putchar('\n');
1606
1607 if (strchr(replies, c)) {
1608 *ret = c;
1609 return 0;
1610 }
1611
1612 puts("Read unexpected character, please try again.");
1613 }
1614}
1615
1616int reset_terminal(int fd) {
1617 struct termios termios;
1618 int r = 0;
1619
1620 assert(fd >= 0);
1621
aaf694ca 1622 /* Set terminal to some sane defaults */
80876c20
LP
1623
1624 if (tcgetattr(fd, &termios) < 0) {
1625 r = -errno;
1626 goto finish;
1627 }
1628
aaf694ca
LP
1629 /* We only reset the stuff that matters to the software. How
1630 * hardware is set up we don't touch assuming that somebody
1631 * else will do that for us */
1632
1633 termios.c_iflag &= ~(IGNBRK | BRKINT | ISTRIP | INLCR | IGNCR | IUCLC);
80876c20
LP
1634 termios.c_iflag |= ICRNL | IMAXBEL | IUTF8;
1635 termios.c_oflag |= ONLCR;
1636 termios.c_cflag |= CREAD;
1637 termios.c_lflag = ISIG | ICANON | IEXTEN | ECHO | ECHOE | ECHOK | ECHOCTL | ECHOPRT | ECHOKE;
1638
1639 termios.c_cc[VINTR] = 03; /* ^C */
1640 termios.c_cc[VQUIT] = 034; /* ^\ */
1641 termios.c_cc[VERASE] = 0177;
1642 termios.c_cc[VKILL] = 025; /* ^X */
1643 termios.c_cc[VEOF] = 04; /* ^D */
1644 termios.c_cc[VSTART] = 021; /* ^Q */
1645 termios.c_cc[VSTOP] = 023; /* ^S */
1646 termios.c_cc[VSUSP] = 032; /* ^Z */
1647 termios.c_cc[VLNEXT] = 026; /* ^V */
1648 termios.c_cc[VWERASE] = 027; /* ^W */
1649 termios.c_cc[VREPRINT] = 022; /* ^R */
aaf694ca
LP
1650 termios.c_cc[VEOL] = 0;
1651 termios.c_cc[VEOL2] = 0;
80876c20
LP
1652
1653 termios.c_cc[VTIME] = 0;
1654 termios.c_cc[VMIN] = 1;
1655
1656 if (tcsetattr(fd, TCSANOW, &termios) < 0)
1657 r = -errno;
1658
1659finish:
1660 /* Just in case, flush all crap out */
1661 tcflush(fd, TCIOFLUSH);
1662
1663 return r;
1664}
1665
1666int open_terminal(const char *name, int mode) {
1667 int fd, r;
1668
1669 if ((fd = open(name, mode)) < 0)
1670 return -errno;
1671
1672 if ((r = isatty(fd)) < 0) {
1673 close_nointr_nofail(fd);
1674 return -errno;
1675 }
1676
1677 if (!r) {
1678 close_nointr_nofail(fd);
1679 return -ENOTTY;
1680 }
1681
1682 return fd;
1683}
1684
1685int flush_fd(int fd) {
1686 struct pollfd pollfd;
1687
1688 zero(pollfd);
1689 pollfd.fd = fd;
1690 pollfd.events = POLLIN;
1691
1692 for (;;) {
1693 char buf[1024];
1694 ssize_t l;
1695 int r;
1696
1697 if ((r = poll(&pollfd, 1, 0)) < 0) {
1698
1699 if (errno == EINTR)
1700 continue;
1701
1702 return -errno;
1703 }
1704
1705 if (r == 0)
1706 return 0;
1707
1708 if ((l = read(fd, buf, sizeof(buf))) < 0) {
1709
1710 if (errno == EINTR)
1711 continue;
1712
1713 if (errno == EAGAIN)
1714 return 0;
1715
1716 return -errno;
1717 }
1718
1719 if (l <= 0)
1720 return 0;
1721 }
1722}
1723
21de3988 1724int acquire_terminal(const char *name, bool fail, bool force, bool ignore_tiocstty_eperm) {
bab45044 1725 int fd = -1, notify = -1, r, wd = -1;
80876c20
LP
1726
1727 assert(name);
1728
1729 /* We use inotify to be notified when the tty is closed. We
1730 * create the watch before checking if we can actually acquire
1731 * it, so that we don't lose any event.
1732 *
1733 * Note: strictly speaking this actually watches for the
1734 * device being closed, it does *not* really watch whether a
1735 * tty loses its controlling process. However, unless some
1736 * rogue process uses TIOCNOTTY on /dev/tty *after* closing
1737 * its tty otherwise this will not become a problem. As long
1738 * as the administrator makes sure not configure any service
1739 * on the same tty as an untrusted user this should not be a
1740 * problem. (Which he probably should not do anyway.) */
1741
1742 if (!fail && !force) {
1743 if ((notify = inotify_init1(IN_CLOEXEC)) < 0) {
1744 r = -errno;
1745 goto fail;
1746 }
1747
1748 if ((wd = inotify_add_watch(notify, name, IN_CLOSE)) < 0) {
1749 r = -errno;
1750 goto fail;
1751 }
1752 }
1753
1754 for (;;) {
e3d1855b
LP
1755 if (notify >= 0)
1756 if ((r = flush_fd(notify)) < 0)
1757 goto fail;
80876c20
LP
1758
1759 /* We pass here O_NOCTTY only so that we can check the return
1760 * value TIOCSCTTY and have a reliable way to figure out if we
1761 * successfully became the controlling process of the tty */
1762 if ((fd = open_terminal(name, O_RDWR|O_NOCTTY)) < 0)
1763 return -errno;
1764
1765 /* First, try to get the tty */
21de3988
LP
1766 r = ioctl(fd, TIOCSCTTY, force);
1767
1768 /* Sometimes it makes sense to ignore TIOCSCTTY
1769 * returning EPERM, i.e. when very likely we already
1770 * are have this controlling terminal. */
1771 if (r < 0 && errno == EPERM && ignore_tiocstty_eperm)
1772 r = 0;
1773
1774 if (r < 0 && (force || fail || errno != EPERM)) {
80876c20
LP
1775 r = -errno;
1776 goto fail;
1777 }
1778
1779 if (r >= 0)
1780 break;
1781
1782 assert(!fail);
1783 assert(!force);
1784 assert(notify >= 0);
1785
1786 for (;;) {
1787 struct inotify_event e;
1788 ssize_t l;
1789
1790 if ((l = read(notify, &e, sizeof(e))) != sizeof(e)) {
1791
1792 if (l < 0) {
1793
1794 if (errno == EINTR)
1795 continue;
1796
1797 r = -errno;
1798 } else
1799 r = -EIO;
1800
1801 goto fail;
1802 }
1803
1804 if (e.wd != wd || !(e.mask & IN_CLOSE)) {
1805 r = -errno;
1806 goto fail;
1807 }
1808
1809 break;
1810 }
1811
1812 /* We close the tty fd here since if the old session
1813 * ended our handle will be dead. It's important that
1814 * we do this after sleeping, so that we don't enter
1815 * an endless loop. */
1816 close_nointr_nofail(fd);
1817 }
1818
1819 if (notify >= 0)
a16e1123 1820 close_nointr_nofail(notify);
80876c20
LP
1821
1822 if ((r = reset_terminal(fd)) < 0)
1823 log_warning("Failed to reset terminal: %s", strerror(-r));
1824
1825 return fd;
1826
1827fail:
1828 if (fd >= 0)
a16e1123 1829 close_nointr_nofail(fd);
80876c20
LP
1830
1831 if (notify >= 0)
a16e1123 1832 close_nointr_nofail(notify);
80876c20
LP
1833
1834 return r;
1835}
1836
1837int release_terminal(void) {
1838 int r = 0, fd;
57cd2192 1839 struct sigaction sa_old, sa_new;
80876c20 1840
57cd2192 1841 if ((fd = open("/dev/tty", O_RDWR|O_NOCTTY|O_NDELAY)) < 0)
80876c20
LP
1842 return -errno;
1843
57cd2192
LP
1844 /* Temporarily ignore SIGHUP, so that we don't get SIGHUP'ed
1845 * by our own TIOCNOTTY */
1846
1847 zero(sa_new);
1848 sa_new.sa_handler = SIG_IGN;
1849 sa_new.sa_flags = SA_RESTART;
1850 assert_se(sigaction(SIGHUP, &sa_new, &sa_old) == 0);
1851
80876c20
LP
1852 if (ioctl(fd, TIOCNOTTY) < 0)
1853 r = -errno;
1854
57cd2192
LP
1855 assert_se(sigaction(SIGHUP, &sa_old, NULL) == 0);
1856
80876c20
LP
1857 close_nointr_nofail(fd);
1858 return r;
1859}
1860
9a34ec5f
LP
1861int sigaction_many(const struct sigaction *sa, ...) {
1862 va_list ap;
1863 int r = 0, sig;
1864
1865 va_start(ap, sa);
1866 while ((sig = va_arg(ap, int)) > 0)
1867 if (sigaction(sig, sa, NULL) < 0)
1868 r = -errno;
1869 va_end(ap);
1870
1871 return r;
1872}
1873
1874int ignore_signals(int sig, ...) {
a337c6fc 1875 struct sigaction sa;
9a34ec5f
LP
1876 va_list ap;
1877 int r = 0;
a337c6fc
LP
1878
1879 zero(sa);
1880 sa.sa_handler = SIG_IGN;
1881 sa.sa_flags = SA_RESTART;
1882
9a34ec5f
LP
1883 if (sigaction(sig, &sa, NULL) < 0)
1884 r = -errno;
1885
1886 va_start(ap, sig);
1887 while ((sig = va_arg(ap, int)) > 0)
1888 if (sigaction(sig, &sa, NULL) < 0)
1889 r = -errno;
1890 va_end(ap);
1891
1892 return r;
1893}
1894
1895int default_signals(int sig, ...) {
1896 struct sigaction sa;
1897 va_list ap;
1898 int r = 0;
1899
1900 zero(sa);
1901 sa.sa_handler = SIG_DFL;
1902 sa.sa_flags = SA_RESTART;
1903
1904 if (sigaction(sig, &sa, NULL) < 0)
1905 r = -errno;
1906
1907 va_start(ap, sig);
1908 while ((sig = va_arg(ap, int)) > 0)
1909 if (sigaction(sig, &sa, NULL) < 0)
1910 r = -errno;
1911 va_end(ap);
1912
1913 return r;
a337c6fc
LP
1914}
1915
8d567588
LP
1916int close_pipe(int p[]) {
1917 int a = 0, b = 0;
1918
1919 assert(p);
1920
1921 if (p[0] >= 0) {
1922 a = close_nointr(p[0]);
1923 p[0] = -1;
1924 }
1925
1926 if (p[1] >= 0) {
1927 b = close_nointr(p[1]);
1928 p[1] = -1;
1929 }
1930
1931 return a < 0 ? a : b;
1932}
1933
1934ssize_t loop_read(int fd, void *buf, size_t nbytes) {
1935 uint8_t *p;
1936 ssize_t n = 0;
1937
1938 assert(fd >= 0);
1939 assert(buf);
1940
1941 p = buf;
1942
1943 while (nbytes > 0) {
1944 ssize_t k;
1945
1946 if ((k = read(fd, p, nbytes)) <= 0) {
1947
1948 if (errno == EINTR)
1949 continue;
1950
1951 if (errno == EAGAIN) {
1952 struct pollfd pollfd;
1953
1954 zero(pollfd);
1955 pollfd.fd = fd;
1956 pollfd.events = POLLIN;
1957
1958 if (poll(&pollfd, 1, -1) < 0) {
1959 if (errno == EINTR)
1960 continue;
1961
1962 return n > 0 ? n : -errno;
1963 }
1964
1965 if (pollfd.revents != POLLIN)
1966 return n > 0 ? n : -EIO;
1967
1968 continue;
1969 }
1970
1971 return n > 0 ? n : (k < 0 ? -errno : 0);
1972 }
1973
1974 p += k;
1975 nbytes -= k;
1976 n += k;
1977 }
1978
1979 return n;
1980}
1981
1982int path_is_mount_point(const char *t) {
1983 struct stat a, b;
1984 char *copy;
1985
1986 if (lstat(t, &a) < 0) {
1987
1988 if (errno == ENOENT)
1989 return 0;
1990
1991 return -errno;
1992 }
1993
1994 if (!(copy = strdup(t)))
1995 return -ENOMEM;
1996
1997 if (lstat(dirname(copy), &b) < 0) {
1998 free(copy);
1999 return -errno;
2000 }
2001
2002 free(copy);
2003
2004 return a.st_dev != b.st_dev;
2005}
2006
24a6e4a4
LP
2007int parse_usec(const char *t, usec_t *usec) {
2008 static const struct {
2009 const char *suffix;
2010 usec_t usec;
2011 } table[] = {
2012 { "sec", USEC_PER_SEC },
2013 { "s", USEC_PER_SEC },
2014 { "min", USEC_PER_MINUTE },
2015 { "hr", USEC_PER_HOUR },
2016 { "h", USEC_PER_HOUR },
2017 { "d", USEC_PER_DAY },
2018 { "w", USEC_PER_WEEK },
2019 { "msec", USEC_PER_MSEC },
2020 { "ms", USEC_PER_MSEC },
2021 { "m", USEC_PER_MINUTE },
2022 { "usec", 1ULL },
2023 { "us", 1ULL },
2024 { "", USEC_PER_SEC },
2025 };
2026
2027 const char *p;
2028 usec_t r = 0;
2029
2030 assert(t);
2031 assert(usec);
2032
2033 p = t;
2034 do {
2035 long long l;
2036 char *e;
2037 unsigned i;
2038
2039 errno = 0;
2040 l = strtoll(p, &e, 10);
2041
2042 if (errno != 0)
2043 return -errno;
2044
2045 if (l < 0)
2046 return -ERANGE;
2047
2048 if (e == p)
2049 return -EINVAL;
2050
2051 e += strspn(e, WHITESPACE);
2052
2053 for (i = 0; i < ELEMENTSOF(table); i++)
2054 if (startswith(e, table[i].suffix)) {
2055 r += (usec_t) l * table[i].usec;
2056 p = e + strlen(table[i].suffix);
2057 break;
2058 }
2059
2060 if (i >= ELEMENTSOF(table))
2061 return -EINVAL;
2062
2063 } while (*p != 0);
2064
2065 *usec = r;
2066
2067 return 0;
2068}
2069
843d2643
LP
2070int make_stdio(int fd) {
2071 int r, s, t;
2072
2073 assert(fd >= 0);
2074
2075 r = dup2(fd, STDIN_FILENO);
2076 s = dup2(fd, STDOUT_FILENO);
2077 t = dup2(fd, STDERR_FILENO);
2078
2079 if (fd >= 3)
2080 close_nointr_nofail(fd);
2081
2082 if (r < 0 || s < 0 || t < 0)
2083 return -errno;
2084
2085 return 0;
2086}
2087
cb8a8f78
LP
2088bool is_clean_exit(int code, int status) {
2089
2090 if (code == CLD_EXITED)
2091 return status == 0;
2092
2093 /* If a daemon does not implement handlers for some of the
2094 * signals that's not considered an unclean shutdown */
2095 if (code == CLD_KILLED)
2096 return
2097 status == SIGHUP ||
2098 status == SIGINT ||
2099 status == SIGTERM ||
2100 status == SIGPIPE;
2101
2102 return false;
2103}
2104
8407a5d0
LP
2105bool is_device_path(const char *path) {
2106
2107 /* Returns true on paths that refer to a device, either in
2108 * sysfs or in /dev */
2109
2110 return
2111 path_startswith(path, "/dev/") ||
2112 path_startswith(path, "/sys/");
2113}
2114
01f78473
LP
2115int dir_is_empty(const char *path) {
2116 DIR *d;
2117 int r;
2118 struct dirent buf, *de;
2119
2120 if (!(d = opendir(path)))
2121 return -errno;
2122
2123 for (;;) {
2124 if ((r = readdir_r(d, &buf, &de)) > 0) {
2125 r = -r;
2126 break;
2127 }
2128
2129 if (!de) {
2130 r = 1;
2131 break;
2132 }
2133
2134 if (!ignore_file(de->d_name)) {
2135 r = 0;
2136 break;
2137 }
2138 }
2139
2140 closedir(d);
2141 return r;
2142}
2143
d3782d60
LP
2144unsigned long long random_ull(void) {
2145 int fd;
2146 uint64_t ull;
2147 ssize_t r;
2148
2149 if ((fd = open("/dev/urandom", O_RDONLY|O_CLOEXEC|O_NOCTTY)) < 0)
2150 goto fallback;
2151
2152 r = loop_read(fd, &ull, sizeof(ull));
2153 close_nointr_nofail(fd);
2154
2155 if (r != sizeof(ull))
2156 goto fallback;
2157
2158 return ull;
2159
2160fallback:
2161 return random() * RAND_MAX + random();
2162}
2163
1dccbe19
LP
2164static const char *const ioprio_class_table[] = {
2165 [IOPRIO_CLASS_NONE] = "none",
2166 [IOPRIO_CLASS_RT] = "realtime",
2167 [IOPRIO_CLASS_BE] = "best-effort",
2168 [IOPRIO_CLASS_IDLE] = "idle"
2169};
2170
2171DEFINE_STRING_TABLE_LOOKUP(ioprio_class, int);
2172
2173static const char *const sigchld_code_table[] = {
2174 [CLD_EXITED] = "exited",
2175 [CLD_KILLED] = "killed",
2176 [CLD_DUMPED] = "dumped",
2177 [CLD_TRAPPED] = "trapped",
2178 [CLD_STOPPED] = "stopped",
2179 [CLD_CONTINUED] = "continued",
2180};
2181
2182DEFINE_STRING_TABLE_LOOKUP(sigchld_code, int);
2183
2184static const char *const log_facility_table[LOG_NFACILITIES] = {
2185 [LOG_FAC(LOG_KERN)] = "kern",
2186 [LOG_FAC(LOG_USER)] = "user",
2187 [LOG_FAC(LOG_MAIL)] = "mail",
2188 [LOG_FAC(LOG_DAEMON)] = "daemon",
2189 [LOG_FAC(LOG_AUTH)] = "auth",
2190 [LOG_FAC(LOG_SYSLOG)] = "syslog",
2191 [LOG_FAC(LOG_LPR)] = "lpr",
2192 [LOG_FAC(LOG_NEWS)] = "news",
2193 [LOG_FAC(LOG_UUCP)] = "uucp",
2194 [LOG_FAC(LOG_CRON)] = "cron",
2195 [LOG_FAC(LOG_AUTHPRIV)] = "authpriv",
2196 [LOG_FAC(LOG_FTP)] = "ftp",
2197 [LOG_FAC(LOG_LOCAL0)] = "local0",
2198 [LOG_FAC(LOG_LOCAL1)] = "local1",
2199 [LOG_FAC(LOG_LOCAL2)] = "local2",
2200 [LOG_FAC(LOG_LOCAL3)] = "local3",
2201 [LOG_FAC(LOG_LOCAL4)] = "local4",
2202 [LOG_FAC(LOG_LOCAL5)] = "local5",
2203 [LOG_FAC(LOG_LOCAL6)] = "local6",
2204 [LOG_FAC(LOG_LOCAL7)] = "local7"
2205};
2206
2207DEFINE_STRING_TABLE_LOOKUP(log_facility, int);
2208
2209static const char *const log_level_table[] = {
2210 [LOG_EMERG] = "emerg",
2211 [LOG_ALERT] = "alert",
2212 [LOG_CRIT] = "crit",
2213 [LOG_ERR] = "err",
2214 [LOG_WARNING] = "warning",
2215 [LOG_NOTICE] = "notice",
2216 [LOG_INFO] = "info",
2217 [LOG_DEBUG] = "debug"
2218};
2219
2220DEFINE_STRING_TABLE_LOOKUP(log_level, int);
2221
2222static const char* const sched_policy_table[] = {
2223 [SCHED_OTHER] = "other",
2224 [SCHED_BATCH] = "batch",
2225 [SCHED_IDLE] = "idle",
2226 [SCHED_FIFO] = "fifo",
2227 [SCHED_RR] = "rr"
2228};
2229
2230DEFINE_STRING_TABLE_LOOKUP(sched_policy, int);
2231
2232static const char* const rlimit_table[] = {
2233 [RLIMIT_CPU] = "LimitCPU",
2234 [RLIMIT_FSIZE] = "LimitFSIZE",
2235 [RLIMIT_DATA] = "LimitDATA",
2236 [RLIMIT_STACK] = "LimitSTACK",
2237 [RLIMIT_CORE] = "LimitCORE",
2238 [RLIMIT_RSS] = "LimitRSS",
2239 [RLIMIT_NOFILE] = "LimitNOFILE",
2240 [RLIMIT_AS] = "LimitAS",
2241 [RLIMIT_NPROC] = "LimitNPROC",
2242 [RLIMIT_MEMLOCK] = "LimitMEMLOCK",
2243 [RLIMIT_LOCKS] = "LimitLOCKS",
2244 [RLIMIT_SIGPENDING] = "LimitSIGPENDING",
2245 [RLIMIT_MSGQUEUE] = "LimitMSGQUEUE",
2246 [RLIMIT_NICE] = "LimitNICE",
2247 [RLIMIT_RTPRIO] = "LimitRTPRIO",
2248 [RLIMIT_RTTIME] = "LimitRTTIME"
2249};
2250
2251DEFINE_STRING_TABLE_LOOKUP(rlimit, int);