]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/basic/process-util.c
Merge pull request #3546 from keszybz/systemctl-fixes
[thirdparty/systemd.git] / src / basic / process-util.c
CommitLineData
0b452006
RC
1/***
2 This file is part of systemd.
3
4 Copyright 2010 Lennart Poettering
5
6 systemd is free software; you can redistribute it and/or modify it
7 under the terms of the GNU Lesser General Public License as published by
8 the Free Software Foundation; either version 2.1 of the License, or
9 (at your option) any later version.
10
11 systemd is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
15
16 You should have received a copy of the GNU Lesser General Public License
17 along with systemd; If not, see <http://www.gnu.org/licenses/>.
18***/
19
4f5dd394 20#include <ctype.h>
0b452006 21#include <errno.h>
11c3a366
TA
22#include <limits.h>
23#include <linux/oom.h>
7b3e062c 24#include <sched.h>
0b452006 25#include <signal.h>
4f5dd394
LP
26#include <stdbool.h>
27#include <stdio.h>
11c3a366 28#include <stdlib.h>
4f5dd394 29#include <string.h>
7b3e062c 30#include <sys/personality.h>
405f8907 31#include <sys/prctl.h>
4f5dd394
LP
32#include <sys/types.h>
33#include <sys/wait.h>
11c3a366 34#include <syslog.h>
4f5dd394 35#include <unistd.h>
dcadc967
EV
36#ifdef HAVE_VALGRIND_VALGRIND_H
37#include <valgrind/valgrind.h>
38#endif
0b452006 39
b5efdb8a 40#include "alloc-util.h"
6e5f1b57 41#include "architecture.h"
4f5dd394 42#include "escape.h"
3ffd4af2 43#include "fd-util.h"
0b452006 44#include "fileio.h"
f4f15635 45#include "fs-util.h"
7b3e062c 46#include "ioprio.h"
0b452006 47#include "log.h"
11c3a366
TA
48#include "macro.h"
49#include "missing.h"
93cc7779 50#include "process-util.h"
8869a0b4 51#include "raw-clone.h"
93cc7779 52#include "signal-util.h"
1359fffa 53#include "stat-util.h"
7b3e062c 54#include "string-table.h"
07630cea 55#include "string-util.h"
b1d4f8e1 56#include "user-util.h"
4f5dd394 57#include "util.h"
0b452006
RC
58
59int get_process_state(pid_t pid) {
60 const char *p;
61 char state;
62 int r;
63 _cleanup_free_ char *line = NULL;
64
65 assert(pid >= 0);
66
67 p = procfs_file_alloca(pid, "stat");
a644184a 68
0b452006 69 r = read_one_line_file(p, &line);
a644184a
LP
70 if (r == -ENOENT)
71 return -ESRCH;
0b452006
RC
72 if (r < 0)
73 return r;
74
75 p = strrchr(line, ')');
76 if (!p)
77 return -EIO;
78
79 p++;
80
81 if (sscanf(p, " %c", &state) != 1)
82 return -EIO;
83
84 return (unsigned char) state;
85}
86
87int get_process_comm(pid_t pid, char **name) {
88 const char *p;
89 int r;
90
91 assert(name);
92 assert(pid >= 0);
93
94 p = procfs_file_alloca(pid, "comm");
95
96 r = read_one_line_file(p, name);
97 if (r == -ENOENT)
98 return -ESRCH;
99
100 return r;
101}
102
103int get_process_cmdline(pid_t pid, size_t max_length, bool comm_fallback, char **line) {
104 _cleanup_fclose_ FILE *f = NULL;
ba4cd7e2 105 bool space = false;
0b452006
RC
106 char *r = NULL, *k;
107 const char *p;
108 int c;
109
110 assert(line);
111 assert(pid >= 0);
112
69281c49
LP
113 /* Retrieves a process' command line. Replaces unprintable characters while doing so by whitespace (coalescing
114 * multiple sequential ones into one). If max_length is != 0 will return a string of the specified size at most
115 * (the trailing NUL byte does count towards the length here!), abbreviated with a "..." ellipsis. If
116 * comm_fallback is true and the process has no command line set (the case for kernel threads), or has a
117 * command line that resolves to the empty string will return the "comm" name of the process instead.
118 *
119 * Returns -ESRCH if the process doesn't exist, and -ENOENT if the process has no command line (and
120 * comm_fallback is false). */
121
0b452006
RC
122 p = procfs_file_alloca(pid, "cmdline");
123
124 f = fopen(p, "re");
a644184a
LP
125 if (!f) {
126 if (errno == ENOENT)
127 return -ESRCH;
0b452006 128 return -errno;
a644184a 129 }
0b452006 130
69281c49
LP
131 if (max_length == 1) {
132
133 /* If there's only room for one byte, return the empty string */
134 r = new0(char, 1);
135 if (!r)
136 return -ENOMEM;
137
138 *line = r;
139 return 0;
140
141 } else if (max_length == 0) {
0b452006
RC
142 size_t len = 0, allocated = 0;
143
144 while ((c = getc(f)) != EOF) {
145
69281c49 146 if (!GREEDY_REALLOC(r, allocated, len+3)) {
0b452006
RC
147 free(r);
148 return -ENOMEM;
149 }
150
ba4cd7e2
MP
151 if (isprint(c)) {
152 if (space) {
153 r[len++] = ' ';
154 space = false;
155 }
156
157 r[len++] = c;
69281c49 158 } else if (len > 0)
ba4cd7e2
MP
159 space = true;
160 }
0b452006
RC
161
162 if (len > 0)
ba4cd7e2 163 r[len] = 0;
0b452006
RC
164
165 } else {
69281c49 166 bool dotdotdot = false;
0b452006
RC
167 size_t left;
168
169 r = new(char, max_length);
170 if (!r)
171 return -ENOMEM;
172
173 k = r;
174 left = max_length;
175 while ((c = getc(f)) != EOF) {
176
177 if (isprint(c)) {
69281c49 178
0b452006 179 if (space) {
69281c49
LP
180 if (left <= 2) {
181 dotdotdot = true;
0b452006 182 break;
69281c49 183 }
0b452006
RC
184
185 *(k++) = ' ';
186 left--;
187 space = false;
188 }
189
69281c49
LP
190 if (left <= 1) {
191 dotdotdot = true;
0b452006 192 break;
69281c49 193 }
0b452006
RC
194
195 *(k++) = (char) c;
196 left--;
69281c49 197 } else if (k > r)
0b452006
RC
198 space = true;
199 }
200
69281c49
LP
201 if (dotdotdot) {
202 if (max_length <= 4) {
203 k = r;
204 left = max_length;
205 } else {
206 k = r + max_length - 4;
207 left = 4;
208
209 /* Eat up final spaces */
210 while (k > r && isspace(k[-1])) {
211 k--;
212 left++;
213 }
214 }
215
216 strncpy(k, "...", left-1);
217 k[left] = 0;
0b452006
RC
218 } else
219 *k = 0;
220 }
221
222 /* Kernel threads have no argv[] */
223 if (isempty(r)) {
224 _cleanup_free_ char *t = NULL;
225 int h;
226
227 free(r);
228
229 if (!comm_fallback)
230 return -ENOENT;
231
232 h = get_process_comm(pid, &t);
233 if (h < 0)
234 return h;
235
69281c49
LP
236 if (max_length == 0)
237 r = strjoin("[", t, "]", NULL);
238 else {
239 size_t l;
240
241 l = strlen(t);
242
243 if (l + 3 <= max_length)
244 r = strjoin("[", t, "]", NULL);
245 else if (max_length <= 6) {
246
247 r = new(char, max_length);
248 if (!r)
249 return -ENOMEM;
250
251 memcpy(r, "[...]", max_length-1);
252 r[max_length-1] = 0;
253 } else {
254 char *e;
255
256 t[max_length - 6] = 0;
257
258 /* Chop off final spaces */
259 e = strchr(t, 0);
260 while (e > t && isspace(e[-1]))
261 e--;
262 *e = 0;
263
264 r = strjoin("[", t, "...]", NULL);
265 }
266 }
0b452006
RC
267 if (!r)
268 return -ENOMEM;
269 }
270
271 *line = r;
272 return 0;
273}
274
405f8907
LP
275void rename_process(const char name[8]) {
276 assert(name);
277
278 /* This is a like a poor man's setproctitle(). It changes the
279 * comm field, argv[0], and also the glibc's internally used
280 * name of the process. For the first one a limit of 16 chars
281 * applies, to the second one usually one of 10 (i.e. length
282 * of "/sbin/init"), to the third one one of 7 (i.e. length of
283 * "systemd"). If you pass a longer string it will be
284 * truncated */
285
79d62972 286 (void) prctl(PR_SET_NAME, name);
405f8907
LP
287
288 if (program_invocation_name)
289 strncpy(program_invocation_name, name, strlen(program_invocation_name));
290
291 if (saved_argc > 0) {
292 int i;
293
294 if (saved_argv[0])
295 strncpy(saved_argv[0], name, strlen(saved_argv[0]));
296
297 for (i = 1; i < saved_argc; i++) {
298 if (!saved_argv[i])
299 break;
300
301 memzero(saved_argv[i], strlen(saved_argv[i]));
302 }
303 }
304}
305
0b452006
RC
306int is_kernel_thread(pid_t pid) {
307 const char *p;
308 size_t count;
309 char c;
310 bool eof;
311 FILE *f;
312
a6149b93 313 if (pid == 0 || pid == 1) /* pid 1, and we ourselves certainly aren't a kernel thread */
0b452006
RC
314 return 0;
315
a6149b93 316 assert(pid > 1);
0b452006
RC
317
318 p = procfs_file_alloca(pid, "cmdline");
319 f = fopen(p, "re");
a644184a
LP
320 if (!f) {
321 if (errno == ENOENT)
322 return -ESRCH;
0b452006 323 return -errno;
a644184a 324 }
0b452006
RC
325
326 count = fread(&c, 1, 1, f);
327 eof = feof(f);
328 fclose(f);
329
330 /* Kernel threads have an empty cmdline */
331
332 if (count <= 0)
333 return eof ? 1 : -errno;
334
335 return 0;
336}
337
338int get_process_capeff(pid_t pid, char **capeff) {
339 const char *p;
a644184a 340 int r;
0b452006
RC
341
342 assert(capeff);
343 assert(pid >= 0);
344
345 p = procfs_file_alloca(pid, "status");
346
c4cd1d4d 347 r = get_proc_field(p, "CapEff", WHITESPACE, capeff);
a644184a
LP
348 if (r == -ENOENT)
349 return -ESRCH;
350
351 return r;
0b452006
RC
352}
353
354static int get_process_link_contents(const char *proc_file, char **name) {
355 int r;
356
357 assert(proc_file);
358 assert(name);
359
360 r = readlink_malloc(proc_file, name);
a644184a
LP
361 if (r == -ENOENT)
362 return -ESRCH;
0b452006 363 if (r < 0)
a644184a 364 return r;
0b452006
RC
365
366 return 0;
367}
368
369int get_process_exe(pid_t pid, char **name) {
370 const char *p;
371 char *d;
372 int r;
373
374 assert(pid >= 0);
375
376 p = procfs_file_alloca(pid, "exe");
377 r = get_process_link_contents(p, name);
378 if (r < 0)
379 return r;
380
381 d = endswith(*name, " (deleted)");
382 if (d)
383 *d = '\0';
384
385 return 0;
386}
387
388static int get_process_id(pid_t pid, const char *field, uid_t *uid) {
389 _cleanup_fclose_ FILE *f = NULL;
390 char line[LINE_MAX];
391 const char *p;
392
393 assert(field);
394 assert(uid);
395
0b452006
RC
396 p = procfs_file_alloca(pid, "status");
397 f = fopen(p, "re");
a644184a
LP
398 if (!f) {
399 if (errno == ENOENT)
400 return -ESRCH;
0b452006 401 return -errno;
a644184a 402 }
0b452006
RC
403
404 FOREACH_LINE(line, f, return -errno) {
405 char *l;
406
407 l = strstrip(line);
408
409 if (startswith(l, field)) {
410 l += strlen(field);
411 l += strspn(l, WHITESPACE);
412
413 l[strcspn(l, WHITESPACE)] = 0;
414
415 return parse_uid(l, uid);
416 }
417 }
418
419 return -EIO;
420}
421
422int get_process_uid(pid_t pid, uid_t *uid) {
423 return get_process_id(pid, "Uid:", uid);
424}
425
426int get_process_gid(pid_t pid, gid_t *gid) {
427 assert_cc(sizeof(uid_t) == sizeof(gid_t));
428 return get_process_id(pid, "Gid:", gid);
429}
430
431int get_process_cwd(pid_t pid, char **cwd) {
432 const char *p;
433
434 assert(pid >= 0);
435
436 p = procfs_file_alloca(pid, "cwd");
437
438 return get_process_link_contents(p, cwd);
439}
440
441int get_process_root(pid_t pid, char **root) {
442 const char *p;
443
444 assert(pid >= 0);
445
446 p = procfs_file_alloca(pid, "root");
447
448 return get_process_link_contents(p, root);
449}
450
451int get_process_environ(pid_t pid, char **env) {
452 _cleanup_fclose_ FILE *f = NULL;
453 _cleanup_free_ char *outcome = NULL;
454 int c;
455 const char *p;
456 size_t allocated = 0, sz = 0;
457
458 assert(pid >= 0);
459 assert(env);
460
461 p = procfs_file_alloca(pid, "environ");
462
463 f = fopen(p, "re");
a644184a
LP
464 if (!f) {
465 if (errno == ENOENT)
466 return -ESRCH;
0b452006 467 return -errno;
a644184a 468 }
0b452006
RC
469
470 while ((c = fgetc(f)) != EOF) {
471 if (!GREEDY_REALLOC(outcome, allocated, sz + 5))
472 return -ENOMEM;
473
474 if (c == '\0')
475 outcome[sz++] = '\n';
476 else
477 sz += cescape_char(c, outcome + sz);
478 }
479
03c55bc0
LP
480 if (!outcome) {
481 outcome = strdup("");
482 if (!outcome)
483 return -ENOMEM;
484 } else
485 outcome[sz] = '\0';
de8763b6 486
0b452006
RC
487 *env = outcome;
488 outcome = NULL;
489
490 return 0;
491}
492
6bc73acb 493int get_process_ppid(pid_t pid, pid_t *_ppid) {
0b452006
RC
494 int r;
495 _cleanup_free_ char *line = NULL;
496 long unsigned ppid;
497 const char *p;
498
499 assert(pid >= 0);
500 assert(_ppid);
501
502 if (pid == 0) {
503 *_ppid = getppid();
504 return 0;
505 }
506
507 p = procfs_file_alloca(pid, "stat");
508 r = read_one_line_file(p, &line);
a644184a
LP
509 if (r == -ENOENT)
510 return -ESRCH;
0b452006
RC
511 if (r < 0)
512 return r;
513
514 /* Let's skip the pid and comm fields. The latter is enclosed
515 * in () but does not escape any () in its value, so let's
516 * skip over it manually */
517
518 p = strrchr(line, ')');
519 if (!p)
520 return -EIO;
521
522 p++;
523
524 if (sscanf(p, " "
525 "%*c " /* state */
526 "%lu ", /* ppid */
527 &ppid) != 1)
528 return -EIO;
529
530 if ((long unsigned) (pid_t) ppid != ppid)
531 return -ERANGE;
532
533 *_ppid = (pid_t) ppid;
534
535 return 0;
536}
537
538int wait_for_terminate(pid_t pid, siginfo_t *status) {
539 siginfo_t dummy;
540
541 assert(pid >= 1);
542
543 if (!status)
544 status = &dummy;
545
546 for (;;) {
547 zero(*status);
548
549 if (waitid(P_PID, pid, status, WEXITED) < 0) {
550
551 if (errno == EINTR)
552 continue;
553
554 return -errno;
555 }
556
557 return 0;
558 }
559}
560
561/*
562 * Return values:
563 * < 0 : wait_for_terminate() failed to get the state of the
564 * process, the process was terminated by a signal, or
565 * failed for an unknown reason.
566 * >=0 : The process terminated normally, and its exit code is
567 * returned.
568 *
569 * That is, success is indicated by a return value of zero, and an
570 * error is indicated by a non-zero value.
571 *
572 * A warning is emitted if the process terminates abnormally,
573 * and also if it returns non-zero unless check_exit_code is true.
574 */
575int wait_for_terminate_and_warn(const char *name, pid_t pid, bool check_exit_code) {
576 int r;
577 siginfo_t status;
578
579 assert(name);
580 assert(pid > 1);
581
582 r = wait_for_terminate(pid, &status);
583 if (r < 0)
584 return log_warning_errno(r, "Failed to wait for %s: %m", name);
585
586 if (status.si_code == CLD_EXITED) {
587 if (status.si_status != 0)
588 log_full(check_exit_code ? LOG_WARNING : LOG_DEBUG,
589 "%s failed with error code %i.", name, status.si_status);
590 else
591 log_debug("%s succeeded.", name);
592
593 return status.si_status;
594 } else if (status.si_code == CLD_KILLED ||
595 status.si_code == CLD_DUMPED) {
596
597 log_warning("%s terminated by signal %s.", name, signal_to_string(status.si_status));
598 return -EPROTO;
599 }
600
601 log_warning("%s failed due to unknown reason.", name);
602 return -EPROTO;
603}
604
89c9030d
LP
605void sigkill_wait(pid_t pid) {
606 assert(pid > 1);
607
608 if (kill(pid, SIGKILL) > 0)
609 (void) wait_for_terminate(pid, NULL);
610}
611
612void sigkill_waitp(pid_t *pid) {
4d0d3d41
LP
613 if (!pid)
614 return;
615 if (*pid <= 1)
616 return;
617
89c9030d 618 sigkill_wait(*pid);
4d0d3d41
LP
619}
620
0b452006
RC
621int kill_and_sigcont(pid_t pid, int sig) {
622 int r;
623
624 r = kill(pid, sig) < 0 ? -errno : 0;
625
626 if (r >= 0)
627 kill(pid, SIGCONT);
628
629 return r;
630}
631
632int getenv_for_pid(pid_t pid, const char *field, char **_value) {
633 _cleanup_fclose_ FILE *f = NULL;
634 char *value = NULL;
635 int r;
636 bool done = false;
637 size_t l;
638 const char *path;
639
640 assert(pid >= 0);
641 assert(field);
642 assert(_value);
643
644 path = procfs_file_alloca(pid, "environ");
645
646 f = fopen(path, "re");
a644184a
LP
647 if (!f) {
648 if (errno == ENOENT)
649 return -ESRCH;
0b452006 650 return -errno;
a644184a 651 }
0b452006
RC
652
653 l = strlen(field);
654 r = 0;
655
656 do {
657 char line[LINE_MAX];
658 unsigned i;
659
660 for (i = 0; i < sizeof(line)-1; i++) {
661 int c;
662
663 c = getc(f);
664 if (_unlikely_(c == EOF)) {
665 done = true;
666 break;
667 } else if (c == 0)
668 break;
669
670 line[i] = c;
671 }
672 line[i] = 0;
673
674 if (memcmp(line, field, l) == 0 && line[l] == '=') {
675 value = strdup(line + l + 1);
676 if (!value)
677 return -ENOMEM;
678
679 r = 1;
680 break;
681 }
682
683 } while (!done);
684
685 *_value = value;
686 return r;
687}
688
689bool pid_is_unwaited(pid_t pid) {
690 /* Checks whether a PID is still valid at all, including a zombie */
691
5fd9b2c5 692 if (pid < 0)
0b452006
RC
693 return false;
694
5fd9b2c5
LP
695 if (pid <= 1) /* If we or PID 1 would be dead and have been waited for, this code would not be running */
696 return true;
697
0b452006
RC
698 if (kill(pid, 0) >= 0)
699 return true;
700
701 return errno != ESRCH;
702}
703
704bool pid_is_alive(pid_t pid) {
705 int r;
706
707 /* Checks whether a PID is still valid and not a zombie */
708
5fd9b2c5 709 if (pid < 0)
0b452006
RC
710 return false;
711
5fd9b2c5
LP
712 if (pid <= 1) /* If we or PID 1 would be a zombie, this code would not be running */
713 return true;
714
0b452006 715 r = get_process_state(pid);
a644184a 716 if (r == -ESRCH || r == 'Z')
0b452006
RC
717 return false;
718
719 return true;
720}
d4510856 721
1359fffa
MS
722int pid_from_same_root_fs(pid_t pid) {
723 const char *root;
724
725 if (pid < 0)
726 return 0;
727
728 root = procfs_file_alloca(pid, "root");
729
730 return files_same(root, "/proc/1/root");
731}
732
d4510856
LP
733bool is_main_thread(void) {
734 static thread_local int cached = 0;
735
736 if (_unlikely_(cached == 0))
737 cached = getpid() == gettid() ? 1 : -1;
738
739 return cached > 0;
740}
7b3e062c
LP
741
742noreturn void freeze(void) {
743
3da48d7a
EV
744 log_close();
745
7b3e062c
LP
746 /* Make sure nobody waits for us on a socket anymore */
747 close_all_fds(NULL, 0);
748
749 sync();
750
751 for (;;)
752 pause();
753}
754
755bool oom_score_adjust_is_valid(int oa) {
756 return oa >= OOM_SCORE_ADJ_MIN && oa <= OOM_SCORE_ADJ_MAX;
757}
758
759unsigned long personality_from_string(const char *p) {
6e5f1b57 760 int architecture;
7b3e062c 761
0c0fea07
LP
762 if (!p)
763 return PERSONALITY_INVALID;
764
6e5f1b57
LP
765 /* Parse a personality specifier. We use our own identifiers that indicate specific ABIs, rather than just
766 * hints regarding the register size, since we want to keep things open for multiple locally supported ABIs for
767 * the same register size. */
768
769 architecture = architecture_from_string(p);
770 if (architecture < 0)
771 return PERSONALITY_INVALID;
7b3e062c 772
0c0fea07 773 if (architecture == native_architecture())
7b3e062c 774 return PER_LINUX;
0c0fea07
LP
775#ifdef SECONDARY_ARCHITECTURE
776 if (architecture == SECONDARY_ARCHITECTURE)
f2d1736c 777 return PER_LINUX32;
7b3e062c
LP
778#endif
779
780 return PERSONALITY_INVALID;
781}
782
783const char* personality_to_string(unsigned long p) {
6e5f1b57 784 int architecture = _ARCHITECTURE_INVALID;
7b3e062c 785
7b3e062c 786 if (p == PER_LINUX)
0c0fea07
LP
787 architecture = native_architecture();
788#ifdef SECONDARY_ARCHITECTURE
6e5f1b57 789 else if (p == PER_LINUX32)
0c0fea07 790 architecture = SECONDARY_ARCHITECTURE;
7b3e062c
LP
791#endif
792
6e5f1b57
LP
793 if (architecture < 0)
794 return NULL;
795
796 return architecture_to_string(architecture);
7b3e062c
LP
797}
798
dcadc967
EV
799void valgrind_summary_hack(void) {
800#ifdef HAVE_VALGRIND_VALGRIND_H
801 if (getpid() == 1 && RUNNING_ON_VALGRIND) {
802 pid_t pid;
8869a0b4 803 pid = raw_clone(SIGCHLD);
dcadc967
EV
804 if (pid < 0)
805 log_emergency_errno(errno, "Failed to fork off valgrind helper: %m");
806 else if (pid == 0)
807 exit(EXIT_SUCCESS);
808 else {
809 log_info("Spawned valgrind helper as PID "PID_FMT".", pid);
810 (void) wait_for_terminate(pid, NULL);
811 }
812 }
813#endif
814}
815
291d565a
LP
816int pid_compare_func(const void *a, const void *b) {
817 const pid_t *p = a, *q = b;
818
819 /* Suitable for usage in qsort() */
820
821 if (*p < *q)
822 return -1;
823 if (*p > *q)
824 return 1;
825 return 0;
826}
827
7b3e062c
LP
828static const char *const ioprio_class_table[] = {
829 [IOPRIO_CLASS_NONE] = "none",
830 [IOPRIO_CLASS_RT] = "realtime",
831 [IOPRIO_CLASS_BE] = "best-effort",
832 [IOPRIO_CLASS_IDLE] = "idle"
833};
834
835DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(ioprio_class, int, INT_MAX);
836
837static const char *const sigchld_code_table[] = {
838 [CLD_EXITED] = "exited",
839 [CLD_KILLED] = "killed",
840 [CLD_DUMPED] = "dumped",
841 [CLD_TRAPPED] = "trapped",
842 [CLD_STOPPED] = "stopped",
843 [CLD_CONTINUED] = "continued",
844};
845
846DEFINE_STRING_TABLE_LOOKUP(sigchld_code, int);
847
848static const char* const sched_policy_table[] = {
849 [SCHED_OTHER] = "other",
850 [SCHED_BATCH] = "batch",
851 [SCHED_IDLE] = "idle",
852 [SCHED_FIFO] = "fifo",
853 [SCHED_RR] = "rr"
854};
855
856DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(sched_policy, int, INT_MAX);