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