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