chiark / gitweb /
update fixme
[elogind.git] / util.c
1 /*-*- Mode: C; c-basic-offset: 8 -*-*/
2
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
22 #include <assert.h>
23 #include <string.h>
24 #include <unistd.h>
25 #include <errno.h>
26 #include <stdlib.h>
27 #include <signal.h>
28 #include <stdio.h>
29 #include <syslog.h>
30 #include <sched.h>
31 #include <sys/resource.h>
32 #include <linux/sched.h>
33
34 #include "macro.h"
35 #include "util.h"
36 #include "ioprio.h"
37 #include "missing.h"
38
39 usec_t now(clockid_t clock_id) {
40         struct timespec ts;
41
42         assert_se(clock_gettime(clock_id, &ts) == 0);
43
44         return timespec_load(&ts);
45 }
46
47 usec_t timespec_load(const struct timespec *ts) {
48         assert(ts);
49
50         return
51                 (usec_t) ts->tv_sec * USEC_PER_SEC +
52                 (usec_t) ts->tv_nsec / NSEC_PER_USEC;
53 }
54
55 struct timespec *timespec_store(struct timespec *ts, usec_t u)  {
56         assert(ts);
57
58         ts->tv_sec = (time_t) (u / USEC_PER_SEC);
59         ts->tv_nsec = (long int) ((u % USEC_PER_SEC) * NSEC_PER_USEC);
60
61         return ts;
62 }
63
64 usec_t timeval_load(const struct timeval *tv) {
65         assert(tv);
66
67         return
68                 (usec_t) tv->tv_sec * USEC_PER_SEC +
69                 (usec_t) tv->tv_usec;
70 }
71
72 struct timeval *timeval_store(struct timeval *tv, usec_t u) {
73         assert(tv);
74
75         tv->tv_sec = (time_t) (u / USEC_PER_SEC);
76         tv->tv_usec = (suseconds_t) (u % USEC_PER_SEC);
77
78         return tv;
79 }
80
81 bool endswith(const char *s, const char *postfix) {
82         size_t sl, pl;
83
84         assert(s);
85         assert(postfix);
86
87         sl = strlen(s);
88         pl = strlen(postfix);
89
90         if (sl < pl)
91                 return false;
92
93         return memcmp(s + sl - pl, postfix, pl) == 0;
94 }
95
96 bool startswith(const char *s, const char *prefix) {
97         size_t sl, pl;
98
99         assert(s);
100         assert(prefix);
101
102         sl = strlen(s);
103         pl = strlen(prefix);
104
105         if (sl < pl)
106                 return false;
107
108         return memcmp(s, prefix, pl) == 0;
109 }
110
111 bool first_word(const char *s, const char *word) {
112         size_t sl, wl;
113
114         assert(s);
115         assert(word);
116
117         sl = strlen(s);
118         wl = strlen(word);
119
120         if (sl < wl)
121                 return false;
122
123         if (memcmp(s, word, wl) != 0)
124                 return false;
125
126         return (s[wl] == 0 ||
127                 strchr(WHITESPACE, s[wl]));
128 }
129
130 int close_nointr(int fd) {
131         assert(fd >= 0);
132
133         for (;;) {
134                 int r;
135
136                 if ((r = close(fd)) >= 0)
137                         return r;
138
139                 if (errno != EINTR)
140                         return r;
141         }
142 }
143
144 void close_nointr_nofail(int fd) {
145
146         /* like close_nointr() but cannot fail, and guarantees errno
147          * is unchanged */
148
149         assert_se(close_nointr(fd) == 0);
150 }
151
152 int parse_boolean(const char *v) {
153         assert(v);
154
155         if (streq(v, "1") || v[0] == 'y' || v[0] == 'Y' || v[0] == 't' || v[0] == 'T' || !strcasecmp(v, "on"))
156                 return 1;
157         else if (streq(v, "0") || v[0] == 'n' || v[0] == 'N' || v[0] == 'f' || v[0] == 'F' || !strcasecmp(v, "off"))
158                 return 0;
159
160         return -EINVAL;
161 }
162
163 int safe_atou(const char *s, unsigned *ret_u) {
164         char *x = NULL;
165         unsigned long l;
166
167         assert(s);
168         assert(ret_u);
169
170         errno = 0;
171         l = strtoul(s, &x, 0);
172
173         if (!x || *x || errno)
174                 return errno ? -errno : -EINVAL;
175
176         if ((unsigned long) (unsigned) l != l)
177                 return -ERANGE;
178
179         *ret_u = (unsigned) l;
180         return 0;
181 }
182
183 int safe_atoi(const char *s, int *ret_i) {
184         char *x = NULL;
185         long l;
186
187         assert(s);
188         assert(ret_i);
189
190         errno = 0;
191         l = strtol(s, &x, 0);
192
193         if (!x || *x || errno)
194                 return errno ? -errno : -EINVAL;
195
196         if ((long) (int) l != l)
197                 return -ERANGE;
198
199         *ret_i = (int) l;
200         return 0;
201 }
202
203 int safe_atolu(const char *s, long unsigned *ret_lu) {
204         char *x = NULL;
205         unsigned long l;
206
207         assert(s);
208         assert(ret_lu);
209
210         errno = 0;
211         l = strtoul(s, &x, 0);
212
213         if (!x || *x || errno)
214                 return errno ? -errno : -EINVAL;
215
216         *ret_lu = l;
217         return 0;
218 }
219
220 int safe_atoli(const char *s, long int *ret_li) {
221         char *x = NULL;
222         long l;
223
224         assert(s);
225         assert(ret_li);
226
227         errno = 0;
228         l = strtol(s, &x, 0);
229
230         if (!x || *x || errno)
231                 return errno ? -errno : -EINVAL;
232
233         *ret_li = l;
234         return 0;
235 }
236
237 int safe_atollu(const char *s, long long unsigned *ret_llu) {
238         char *x = NULL;
239         unsigned long long l;
240
241         assert(s);
242         assert(ret_llu);
243
244         errno = 0;
245         l = strtoull(s, &x, 0);
246
247         if (!x || *x || errno)
248                 return errno ? -errno : -EINVAL;
249
250         *ret_llu = l;
251         return 0;
252 }
253
254 int safe_atolli(const char *s, long long int *ret_lli) {
255         char *x = NULL;
256         long long l;
257
258         assert(s);
259         assert(ret_lli);
260
261         errno = 0;
262         l = strtoll(s, &x, 0);
263
264         if (!x || *x || errno)
265                 return errno ? -errno : -EINVAL;
266
267         *ret_lli = l;
268         return 0;
269 }
270
271 /* Split a string into words. */
272 char *split_spaces(const char *c, size_t *l, char **state) {
273         char *current;
274
275         current = *state ? *state : (char*) c;
276
277         if (!*current || *c == 0)
278                 return NULL;
279
280         current += strspn(current, WHITESPACE);
281         *l = strcspn(current, WHITESPACE);
282         *state = current+*l;
283
284         return (char*) current;
285 }
286
287 /* Split a string into words, but consider strings enclosed in '' and
288  * "" as words even if they include spaces. */
289 char *split_quoted(const char *c, size_t *l, char **state) {
290         char *current;
291
292         current = *state ? *state : (char*) c;
293
294         if (!*current || *c == 0)
295                 return NULL;
296
297         current += strspn(current, WHITESPACE);
298
299         if (*current == '\'') {
300                 current ++;
301                 *l = strcspn(current, "'");
302                 *state = current+*l;
303
304                 if (**state == '\'')
305                         (*state)++;
306         } else if (*current == '\"') {
307                 current ++;
308                 *l = strcspn(current, "\"");
309                 *state = current+*l;
310
311                 if (**state == '\"')
312                         (*state)++;
313         } else {
314                 *l = strcspn(current, WHITESPACE);
315                 *state = current+*l;
316         }
317
318         /* FIXME: Cannot deal with strings that have spaces AND ticks
319          * in them */
320
321         return (char*) current;
322 }
323
324 int get_parent_of_pid(pid_t pid, pid_t *_ppid) {
325         int r;
326         FILE *f;
327         char fn[132], line[256], *p;
328         long long unsigned ppid;
329
330         assert(pid >= 0);
331         assert(_ppid);
332
333         assert_se(snprintf(fn, sizeof(fn)-1, "/proc/%llu/stat", (unsigned long long) pid) < (int) (sizeof(fn)-1));
334         fn[sizeof(fn)-1] = 0;
335
336         if (!(f = fopen(fn, "r")))
337                 return -errno;
338
339         if (!(fgets(line, sizeof(line), f))) {
340                 r = -errno;
341                 fclose(f);
342                 return r;
343         }
344
345         fclose(f);
346
347         /* Let's skip the pid and comm fields. The latter is enclosed
348          * in () but does not escape any () in its value, so let's
349          * skip over it manually */
350
351         if (!(p = strrchr(line, ')')))
352                 return -EIO;
353
354         p++;
355
356         if (sscanf(p, " "
357                    "%*c "  /* state */
358                    "%llu ", /* ppid */
359                    &ppid) != 1)
360                 return -EIO;
361
362         if ((long long unsigned) (pid_t) ppid != ppid)
363                 return -ERANGE;
364
365         *_ppid = (pid_t) ppid;
366
367         return 0;
368 }
369
370 int write_one_line_file(const char *fn, const char *line) {
371         FILE *f;
372         int r;
373
374         assert(fn);
375         assert(line);
376
377         if (!(f = fopen(fn, "we")))
378                 return -errno;
379
380         if (fputs(line, f) < 0) {
381                 r = -errno;
382                 goto finish;
383         }
384
385         r = 0;
386 finish:
387         fclose(f);
388         return r;
389 }
390
391 int read_one_line_file(const char *fn, char **line) {
392         FILE *f;
393         int r;
394         char t[64], *c;
395
396         assert(fn);
397         assert(line);
398
399         if (!(f = fopen(fn, "re")))
400                 return -errno;
401
402         if (!(fgets(t, sizeof(t), f))) {
403                 r = -errno;
404                 goto finish;
405         }
406
407         if (!(c = strdup(t))) {
408                 r = -ENOMEM;
409                 goto finish;
410         }
411
412         *line = c;
413         r = 0;
414
415 finish:
416         fclose(f);
417         return r;
418 }
419
420 char *strappend(const char *s, const char *suffix) {
421         size_t a, b;
422         char *r;
423
424         assert(s);
425         assert(suffix);
426
427         a = strlen(s);
428         b = strlen(suffix);
429
430         if (!(r = new(char, a+b+1)))
431                 return NULL;
432
433         memcpy(r, s, a);
434         memcpy(r+a, suffix, b);
435         r[a+b] = 0;
436
437         return r;
438 }
439
440 int readlink_malloc(const char *p, char **r) {
441         size_t l = 100;
442
443         assert(p);
444         assert(r);
445
446         for (;;) {
447                 char *c;
448                 ssize_t n;
449
450                 if (!(c = new(char, l)))
451                         return -ENOMEM;
452
453                 if ((n = readlink(p, c, l-1)) < 0) {
454                         int ret = -errno;
455                         free(c);
456                         return ret;
457                 }
458
459                 if ((size_t) n < l-1) {
460                         c[n] = 0;
461                         *r = c;
462                         return 0;
463                 }
464
465                 free(c);
466                 l *= 2;
467         }
468 }
469
470 char *file_name_from_path(const char *p) {
471         char *r;
472
473         assert(p);
474
475         if ((r = strrchr(p, '/')))
476                 return r + 1;
477
478         return (char*) p;
479 }
480
481 bool path_is_absolute(const char *p) {
482         assert(p);
483
484         return p[0] == '/';
485 }
486
487 bool is_path(const char *p) {
488
489         return !!strchr(p, '/');
490 }
491
492 char *path_make_absolute(const char *p, const char *prefix) {
493         char *r;
494
495         assert(p);
496
497         if (path_is_absolute(p) || !prefix)
498                 return strdup(p);
499
500         if (asprintf(&r, "%s/%s", prefix, p) < 0)
501                 return NULL;
502
503         return r;
504 }
505
506 int reset_all_signal_handlers(void) {
507         int sig;
508
509         for (sig = 1; sig < _NSIG; sig++) {
510                 struct sigaction sa;
511
512                 if (sig == SIGKILL || sig == SIGSTOP)
513                         continue;
514
515                 zero(sa);
516                 sa.sa_handler = SIG_DFL;
517                 sa.sa_flags = SA_RESTART;
518
519                 /* On Linux the first two RT signals are reserved by
520                  * glibc, and sigaction() will return EINVAL for them. */
521                 if ((sigaction(sig, &sa, NULL) < 0))
522                         if (errno != EINVAL)
523                                 return -errno;
524         }
525
526     return 0;
527 }
528
529 char *strstrip(char *s) {
530         char *e, *l = NULL;
531
532         /* Drops trailing whitespace. Modifies the string in
533          * place. Returns pointer to first non-space character */
534
535         s += strspn(s, WHITESPACE);
536
537         for (e = s; *e; e++)
538                 if (!strchr(WHITESPACE, *e))
539                         l = e;
540
541         if (l)
542                 *(l+1) = 0;
543         else
544                 *s = 0;
545
546         return s;
547
548 }
549
550 char *file_in_same_dir(const char *path, const char *filename) {
551         char *e, *r;
552         size_t k;
553
554         assert(path);
555         assert(filename);
556
557         /* This removes the last component of path and appends
558          * filename, unless the latter is absolute anyway or the
559          * former isn't */
560
561         if (path_is_absolute(filename))
562                 return strdup(filename);
563
564         if (!(e = strrchr(path, '/')))
565                 return strdup(filename);
566
567         k = strlen(filename);
568         if (!(r = new(char, e-path+1+k+1)))
569                 return NULL;
570
571         memcpy(r, path, e-path+1);
572         memcpy(r+(e-path)+1, filename, k+1);
573
574         return r;
575 }
576
577 char hexchar(int x) {
578         static const char table[16] = "0123456789abcdef";
579
580         return table[x & 15];
581 }
582
583 int unhexchar(char c) {
584
585         if (c >= '0' && c <= '9')
586                 return c - '0';
587
588         if (c >= 'a' && c <= 'f')
589                 return c - 'a' + 10;
590
591         if (c >= 'A' && c <= 'F')
592                 return c - 'A' + 10;
593
594         return -1;
595 }
596
597 char octchar(int x) {
598         return '0' + (x & 7);
599 }
600
601 int unoctchar(char c) {
602
603         if (c >= '0' && c <= '7')
604                 return c - '0';
605
606         return -1;
607 }
608
609 char *cescape(const char *s) {
610         char *r, *t;
611         const char *f;
612
613         assert(s);
614
615         /* Does C style string escaping. */
616
617         if (!(r = new(char, strlen(s)*4 + 1)))
618                 return NULL;
619
620         for (f = s, t = r; *f; f++)
621
622                 switch (*f) {
623
624                 case '\a':
625                         *(t++) = '\\';
626                         *(t++) = 'a';
627                         break;
628                 case '\b':
629                         *(t++) = '\\';
630                         *(t++) = 'b';
631                         break;
632                 case '\f':
633                         *(t++) = '\\';
634                         *(t++) = 'f';
635                         break;
636                 case '\n':
637                         *(t++) = '\\';
638                         *(t++) = 'n';
639                         break;
640                 case '\r':
641                         *(t++) = '\\';
642                         *(t++) = 'r';
643                         break;
644                 case '\t':
645                         *(t++) = '\\';
646                         *(t++) = 't';
647                         break;
648                 case '\v':
649                         *(t++) = '\\';
650                         *(t++) = 'v';
651                         break;
652                 case '\\':
653                         *(t++) = '\\';
654                         *(t++) = '\\';
655                         break;
656                 case '"':
657                         *(t++) = '\\';
658                         *(t++) = '"';
659                         break;
660                 case '\'':
661                         *(t++) = '\\';
662                         *(t++) = '\'';
663                         break;
664
665                 default:
666                         /* For special chars we prefer octal over
667                          * hexadecimal encoding, simply because glib's
668                          * g_strescape() does the same */
669                         if ((*f < ' ') || (*f >= 127)) {
670                                 *(t++) = '\\';
671                                 *(t++) = octchar((unsigned char) *f >> 6);
672                                 *(t++) = octchar((unsigned char) *f >> 3);
673                                 *(t++) = octchar((unsigned char) *f);
674                         } else
675                                 *(t++) = *f;
676                         break;
677                 }
678
679         *t = 0;
680
681         return r;
682 }
683
684 char *cunescape(const char *s) {
685         char *r, *t;
686         const char *f;
687
688         assert(s);
689
690         /* Undoes C style string escaping */
691
692         if (!(r = new(char, strlen(s)+1)))
693                 return r;
694
695         for (f = s, t = r; *f; f++) {
696
697                 if (*f != '\\') {
698                         *(t++) = *f;
699                         continue;
700                 }
701
702                 f++;
703
704                 switch (*f) {
705
706                 case 'a':
707                         *(t++) = '\a';
708                         break;
709                 case 'b':
710                         *(t++) = '\b';
711                         break;
712                 case 'f':
713                         *(t++) = '\f';
714                         break;
715                 case 'n':
716                         *(t++) = '\n';
717                         break;
718                 case 'r':
719                         *(t++) = '\r';
720                         break;
721                 case 't':
722                         *(t++) = '\t';
723                         break;
724                 case 'v':
725                         *(t++) = '\v';
726                         break;
727                 case '\\':
728                         *(t++) = '\\';
729                         break;
730                 case '"':
731                         *(t++) = '"';
732                         break;
733                 case '\'':
734                         *(t++) = '\'';
735                         break;
736
737                 case 'x': {
738                         /* hexadecimal encoding */
739                         int a, b;
740
741                         if ((a = unhexchar(f[1])) < 0 ||
742                             (b = unhexchar(f[2])) < 0) {
743                                 /* Invalid escape code, let's take it literal then */
744                                 *(t++) = '\\';
745                                 *(t++) = 'x';
746                         } else {
747                                 *(t++) = (char) ((a << 4) | b);
748                                 f += 2;
749                         }
750
751                         break;
752                 }
753
754                 case '0':
755                 case '1':
756                 case '2':
757                 case '3':
758                 case '4':
759                 case '5':
760                 case '6':
761                 case '7': {
762                         /* octal encoding */
763                         int a, b, c;
764
765                         if ((a = unoctchar(f[0])) < 0 ||
766                             (b = unoctchar(f[1])) < 0 ||
767                             (c = unoctchar(f[2])) < 0) {
768                                 /* Invalid escape code, let's take it literal then */
769                                 *(t++) = '\\';
770                                 *(t++) = f[0];
771                         } else {
772                                 *(t++) = (char) ((a << 6) | (b << 3) | c);
773                                 f += 2;
774                         }
775
776                         break;
777                 }
778
779                 case 0:
780                         /* premature end of string.*/
781                         *(t++) = '\\';
782                         goto finish;
783
784                 default:
785                         /* Invalid escape code, let's take it literal then */
786                         *(t++) = '\\';
787                         *(t++) = 'f';
788                         break;
789                 }
790         }
791
792 finish:
793         *t = 0;
794         return r;
795 }
796
797
798 char *xescape(const char *s, const char *bad) {
799         char *r, *t;
800         const char *f;
801
802         /* Escapes all chars in bad, in addition to \ and all special
803          * chars, in \xFF style escaping. May be reversed with
804          * cunescape. */
805
806         if (!(r = new(char, strlen(s)*4+1)))
807                 return NULL;
808
809         for (f = s, t = r; *f; f++) {
810
811                 if (*f < ' ' || *f >= 127 ||
812                     *f == '\\' || strchr(bad, *f)) {
813                         *(t++) = '\\';
814                         *(t++) = 'x';
815                         *(t++) = hexchar(*f >> 4);
816                         *(t++) = hexchar(*f);
817                 } else
818                         *(t++) = *f;
819         }
820
821         *t = 0;
822
823         return r;
824 }
825
826 char *bus_path_escape(const char *s) {
827         char *r, *t;
828         const char *f;
829
830         assert(s);
831
832         /* Escapes all chars that D-Bus' object path cannot deal
833          * with. Can be reverse with bus_path_unescape() */
834
835         if (!(r = new(char, strlen(s)*3+1)))
836                 return NULL;
837
838         for (f = s, t = r; *f; f++) {
839
840                 if (!(*f >= 'A' && *f <= 'Z') &&
841                     !(*f >= 'a' && *f <= 'z') &&
842                     !(*f >= '0' && *f <= '9')) {
843                         *(t++) = '_';
844                         *(t++) = hexchar(*f >> 4);
845                         *(t++) = hexchar(*f);
846                 } else
847                         *(t++) = *f;
848         }
849
850         *t = 0;
851
852         return r;
853 }
854
855 char *bus_path_unescape(const char *s) {
856         char *r, *t;
857         const char *f;
858
859         assert(s);
860
861         if (!(r = new(char, strlen(s)+1)))
862                 return NULL;
863
864         for (f = s, t = r; *f; f++) {
865
866                 if (*f == '_') {
867                         int a, b;
868
869                         if ((a = unhexchar(f[1])) < 0 ||
870                             (b = unhexchar(f[2])) < 0) {
871                                 /* Invalid escape code, let's take it literal then */
872                                 *(t++) = '_';
873                         } else {
874                                 *(t++) = (char) ((a << 4) | b);
875                                 f += 2;
876                         }
877                 } else
878                         *(t++) = *f;
879         }
880
881         *t = 0;
882
883         return r;
884 }
885
886 char *path_kill_slashes(char *path) {
887         char *f, *t;
888         bool slash = false;
889
890         /* Removes redundant inner and trailing slashes. Modifies the
891          * passed string in-place.
892          *
893          * ///foo///bar/ becomes /foo/bar
894          */
895
896         for (f = path, t = path; *f; f++) {
897
898                 if (*f == '/') {
899                         slash = true;
900                         continue;
901                 }
902
903                 if (slash) {
904                         slash = false;
905                         *(t++) = '/';
906                 }
907
908                 *(t++) = *f;
909         }
910
911         /* Special rule, if we are talking of the root directory, a
912         trailing slash is good */
913
914         if (t == path && slash)
915                 *(t++) = '/';
916
917         *t = 0;
918         return path;
919 }
920
921 bool path_startswith(const char *path, const char *prefix) {
922         assert(path);
923         assert(prefix);
924
925         if ((path[0] == '/') != (prefix[0] == '/'))
926                 return false;
927
928         for (;;) {
929                 size_t a, b;
930
931                 path += strspn(path, "/");
932                 prefix += strspn(prefix, "/");
933
934                 if (*prefix == 0)
935                         return true;
936
937                 if (*path == 0)
938                         return false;
939
940                 a = strcspn(path, "/");
941                 b = strcspn(prefix, "/");
942
943                 if (a != b)
944                         return false;
945
946                 if (memcmp(path, prefix, a) != 0)
947                         return false;
948
949                 path += a;
950                 prefix += b;
951         }
952 }
953
954 char *ascii_strlower(char *path) {
955         char *p;
956
957         assert(path);
958
959         for (p = path; *p; p++)
960                 if (*p >= 'A' && *p <= 'Z')
961                         *p = *p - 'A' + 'a';
962
963         return p;
964 }
965
966 static const char *const ioprio_class_table[] = {
967         [IOPRIO_CLASS_NONE] = "none",
968         [IOPRIO_CLASS_RT] = "realtime",
969         [IOPRIO_CLASS_BE] = "best-effort",
970         [IOPRIO_CLASS_IDLE] = "idle"
971 };
972
973 DEFINE_STRING_TABLE_LOOKUP(ioprio_class, int);
974
975 static const char *const sigchld_code_table[] = {
976         [CLD_EXITED] = "exited",
977         [CLD_KILLED] = "killed",
978         [CLD_DUMPED] = "dumped",
979         [CLD_TRAPPED] = "trapped",
980         [CLD_STOPPED] = "stopped",
981         [CLD_CONTINUED] = "continued",
982 };
983
984 DEFINE_STRING_TABLE_LOOKUP(sigchld_code, int);
985
986 static const char *const log_facility_table[LOG_NFACILITIES] = {
987         [LOG_FAC(LOG_KERN)] = "kern",
988         [LOG_FAC(LOG_USER)] = "user",
989         [LOG_FAC(LOG_MAIL)] = "mail",
990         [LOG_FAC(LOG_DAEMON)] = "daemon",
991         [LOG_FAC(LOG_AUTH)] = "auth",
992         [LOG_FAC(LOG_SYSLOG)] = "syslog",
993         [LOG_FAC(LOG_LPR)] = "lpr",
994         [LOG_FAC(LOG_NEWS)] = "news",
995         [LOG_FAC(LOG_UUCP)] = "uucp",
996         [LOG_FAC(LOG_CRON)] = "cron",
997         [LOG_FAC(LOG_AUTHPRIV)] = "authpriv",
998         [LOG_FAC(LOG_FTP)] = "ftp",
999         [LOG_FAC(LOG_LOCAL0)] = "local0",
1000         [LOG_FAC(LOG_LOCAL1)] = "local1",
1001         [LOG_FAC(LOG_LOCAL2)] = "local2",
1002         [LOG_FAC(LOG_LOCAL3)] = "local3",
1003         [LOG_FAC(LOG_LOCAL4)] = "local4",
1004         [LOG_FAC(LOG_LOCAL5)] = "local5",
1005         [LOG_FAC(LOG_LOCAL6)] = "local6",
1006         [LOG_FAC(LOG_LOCAL7)] = "local7"
1007 };
1008
1009 DEFINE_STRING_TABLE_LOOKUP(log_facility, int);
1010
1011 static const char *const log_level_table[] = {
1012         [LOG_EMERG] = "emerg",
1013         [LOG_ALERT] = "alert",
1014         [LOG_CRIT] = "crit",
1015         [LOG_ERR] = "err",
1016         [LOG_WARNING] = "warning",
1017         [LOG_NOTICE] = "notice",
1018         [LOG_INFO] = "info",
1019         [LOG_DEBUG] = "debug"
1020 };
1021
1022 DEFINE_STRING_TABLE_LOOKUP(log_level, int);
1023
1024 static const char* const sched_policy_table[] = {
1025         [SCHED_OTHER] = "other",
1026         [SCHED_BATCH] = "batch",
1027         [SCHED_IDLE] = "idle",
1028         [SCHED_FIFO] = "fifo",
1029         [SCHED_RR] = "rr"
1030 };
1031
1032 DEFINE_STRING_TABLE_LOOKUP(sched_policy, int);
1033
1034 static const char* const rlimit_table[] = {
1035         [RLIMIT_CPU] = "LimitCPU",
1036         [RLIMIT_FSIZE] = "LimitFSIZE",
1037         [RLIMIT_DATA] = "LimitDATA",
1038         [RLIMIT_STACK] = "LimitSTACK",
1039         [RLIMIT_CORE] = "LimitCORE",
1040         [RLIMIT_RSS] = "LimitRSS",
1041         [RLIMIT_NOFILE] = "LimitNOFILE",
1042         [RLIMIT_AS] = "LimitAS",
1043         [RLIMIT_NPROC] = "LimitNPROC",
1044         [RLIMIT_MEMLOCK] = "LimitMEMLOCK",
1045         [RLIMIT_LOCKS] = "LimitLOCKS",
1046         [RLIMIT_SIGPENDING] = "LimitSIGPENDING",
1047         [RLIMIT_MSGQUEUE] = "LimitMSGQUEUE",
1048         [RLIMIT_NICE] = "LimitNICE",
1049         [RLIMIT_RTPRIO] = "LimitRTPRIO",
1050         [RLIMIT_RTTIME] = "LimitRTTIME"
1051 };
1052
1053 DEFINE_STRING_TABLE_LOOKUP(rlimit, int);