]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/basic/process-util.c
basic: include only what we use
[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>
0b452006 36
b5efdb8a 37#include "alloc-util.h"
4f5dd394 38#include "escape.h"
3ffd4af2 39#include "fd-util.h"
0b452006 40#include "fileio.h"
f4f15635 41#include "fs-util.h"
7b3e062c 42#include "ioprio.h"
0b452006 43#include "log.h"
3ffd4af2 44#include "process-util.h"
24882e06 45#include "signal-util.h"
11c3a366
TA
46#include "macro.h"
47#include "missing.h"
7b3e062c 48#include "string-table.h"
07630cea 49#include "string-util.h"
b1d4f8e1 50#include "user-util.h"
4f5dd394 51#include "util.h"
0b452006
RC
52
53int get_process_state(pid_t pid) {
54 const char *p;
55 char state;
56 int r;
57 _cleanup_free_ char *line = NULL;
58
59 assert(pid >= 0);
60
61 p = procfs_file_alloca(pid, "stat");
a644184a 62
0b452006 63 r = read_one_line_file(p, &line);
a644184a
LP
64 if (r == -ENOENT)
65 return -ESRCH;
0b452006
RC
66 if (r < 0)
67 return r;
68
69 p = strrchr(line, ')');
70 if (!p)
71 return -EIO;
72
73 p++;
74
75 if (sscanf(p, " %c", &state) != 1)
76 return -EIO;
77
78 return (unsigned char) state;
79}
80
81int get_process_comm(pid_t pid, char **name) {
82 const char *p;
83 int r;
84
85 assert(name);
86 assert(pid >= 0);
87
88 p = procfs_file_alloca(pid, "comm");
89
90 r = read_one_line_file(p, name);
91 if (r == -ENOENT)
92 return -ESRCH;
93
94 return r;
95}
96
97int get_process_cmdline(pid_t pid, size_t max_length, bool comm_fallback, char **line) {
98 _cleanup_fclose_ FILE *f = NULL;
99 char *r = NULL, *k;
100 const char *p;
101 int c;
102
103 assert(line);
104 assert(pid >= 0);
105
106 p = procfs_file_alloca(pid, "cmdline");
107
108 f = fopen(p, "re");
a644184a
LP
109 if (!f) {
110 if (errno == ENOENT)
111 return -ESRCH;
0b452006 112 return -errno;
a644184a 113 }
0b452006
RC
114
115 if (max_length == 0) {
116 size_t len = 0, allocated = 0;
117
118 while ((c = getc(f)) != EOF) {
119
120 if (!GREEDY_REALLOC(r, allocated, len+2)) {
121 free(r);
122 return -ENOMEM;
123 }
124
125 r[len++] = isprint(c) ? c : ' ';
126 }
127
128 if (len > 0)
129 r[len-1] = 0;
130
131 } else {
132 bool space = false;
133 size_t left;
134
135 r = new(char, max_length);
136 if (!r)
137 return -ENOMEM;
138
139 k = r;
140 left = max_length;
141 while ((c = getc(f)) != EOF) {
142
143 if (isprint(c)) {
144 if (space) {
145 if (left <= 4)
146 break;
147
148 *(k++) = ' ';
149 left--;
150 space = false;
151 }
152
153 if (left <= 4)
154 break;
155
156 *(k++) = (char) c;
157 left--;
158 } else
159 space = true;
160 }
161
162 if (left <= 4) {
163 size_t n = MIN(left-1, 3U);
164 memcpy(k, "...", n);
165 k[n] = 0;
166 } else
167 *k = 0;
168 }
169
170 /* Kernel threads have no argv[] */
171 if (isempty(r)) {
172 _cleanup_free_ char *t = NULL;
173 int h;
174
175 free(r);
176
177 if (!comm_fallback)
178 return -ENOENT;
179
180 h = get_process_comm(pid, &t);
181 if (h < 0)
182 return h;
183
184 r = strjoin("[", t, "]", NULL);
185 if (!r)
186 return -ENOMEM;
187 }
188
189 *line = r;
190 return 0;
191}
192
405f8907
LP
193void rename_process(const char name[8]) {
194 assert(name);
195
196 /* This is a like a poor man's setproctitle(). It changes the
197 * comm field, argv[0], and also the glibc's internally used
198 * name of the process. For the first one a limit of 16 chars
199 * applies, to the second one usually one of 10 (i.e. length
200 * of "/sbin/init"), to the third one one of 7 (i.e. length of
201 * "systemd"). If you pass a longer string it will be
202 * truncated */
203
204 prctl(PR_SET_NAME, name);
205
206 if (program_invocation_name)
207 strncpy(program_invocation_name, name, strlen(program_invocation_name));
208
209 if (saved_argc > 0) {
210 int i;
211
212 if (saved_argv[0])
213 strncpy(saved_argv[0], name, strlen(saved_argv[0]));
214
215 for (i = 1; i < saved_argc; i++) {
216 if (!saved_argv[i])
217 break;
218
219 memzero(saved_argv[i], strlen(saved_argv[i]));
220 }
221 }
222}
223
0b452006
RC
224int is_kernel_thread(pid_t pid) {
225 const char *p;
226 size_t count;
227 char c;
228 bool eof;
229 FILE *f;
230
a6149b93 231 if (pid == 0 || pid == 1) /* pid 1, and we ourselves certainly aren't a kernel thread */
0b452006
RC
232 return 0;
233
a6149b93 234 assert(pid > 1);
0b452006
RC
235
236 p = procfs_file_alloca(pid, "cmdline");
237 f = fopen(p, "re");
a644184a
LP
238 if (!f) {
239 if (errno == ENOENT)
240 return -ESRCH;
0b452006 241 return -errno;
a644184a 242 }
0b452006
RC
243
244 count = fread(&c, 1, 1, f);
245 eof = feof(f);
246 fclose(f);
247
248 /* Kernel threads have an empty cmdline */
249
250 if (count <= 0)
251 return eof ? 1 : -errno;
252
253 return 0;
254}
255
256int get_process_capeff(pid_t pid, char **capeff) {
257 const char *p;
a644184a 258 int r;
0b452006
RC
259
260 assert(capeff);
261 assert(pid >= 0);
262
263 p = procfs_file_alloca(pid, "status");
264
c4cd1d4d 265 r = get_proc_field(p, "CapEff", WHITESPACE, capeff);
a644184a
LP
266 if (r == -ENOENT)
267 return -ESRCH;
268
269 return r;
0b452006
RC
270}
271
272static int get_process_link_contents(const char *proc_file, char **name) {
273 int r;
274
275 assert(proc_file);
276 assert(name);
277
278 r = readlink_malloc(proc_file, name);
a644184a
LP
279 if (r == -ENOENT)
280 return -ESRCH;
0b452006 281 if (r < 0)
a644184a 282 return r;
0b452006
RC
283
284 return 0;
285}
286
287int get_process_exe(pid_t pid, char **name) {
288 const char *p;
289 char *d;
290 int r;
291
292 assert(pid >= 0);
293
294 p = procfs_file_alloca(pid, "exe");
295 r = get_process_link_contents(p, name);
296 if (r < 0)
297 return r;
298
299 d = endswith(*name, " (deleted)");
300 if (d)
301 *d = '\0';
302
303 return 0;
304}
305
306static int get_process_id(pid_t pid, const char *field, uid_t *uid) {
307 _cleanup_fclose_ FILE *f = NULL;
308 char line[LINE_MAX];
309 const char *p;
310
311 assert(field);
312 assert(uid);
313
314 if (pid == 0)
315 return getuid();
316
317 p = procfs_file_alloca(pid, "status");
318 f = fopen(p, "re");
a644184a
LP
319 if (!f) {
320 if (errno == ENOENT)
321 return -ESRCH;
0b452006 322 return -errno;
a644184a 323 }
0b452006
RC
324
325 FOREACH_LINE(line, f, return -errno) {
326 char *l;
327
328 l = strstrip(line);
329
330 if (startswith(l, field)) {
331 l += strlen(field);
332 l += strspn(l, WHITESPACE);
333
334 l[strcspn(l, WHITESPACE)] = 0;
335
336 return parse_uid(l, uid);
337 }
338 }
339
340 return -EIO;
341}
342
343int get_process_uid(pid_t pid, uid_t *uid) {
344 return get_process_id(pid, "Uid:", uid);
345}
346
347int get_process_gid(pid_t pid, gid_t *gid) {
348 assert_cc(sizeof(uid_t) == sizeof(gid_t));
349 return get_process_id(pid, "Gid:", gid);
350}
351
352int get_process_cwd(pid_t pid, char **cwd) {
353 const char *p;
354
355 assert(pid >= 0);
356
357 p = procfs_file_alloca(pid, "cwd");
358
359 return get_process_link_contents(p, cwd);
360}
361
362int get_process_root(pid_t pid, char **root) {
363 const char *p;
364
365 assert(pid >= 0);
366
367 p = procfs_file_alloca(pid, "root");
368
369 return get_process_link_contents(p, root);
370}
371
372int get_process_environ(pid_t pid, char **env) {
373 _cleanup_fclose_ FILE *f = NULL;
374 _cleanup_free_ char *outcome = NULL;
375 int c;
376 const char *p;
377 size_t allocated = 0, sz = 0;
378
379 assert(pid >= 0);
380 assert(env);
381
382 p = procfs_file_alloca(pid, "environ");
383
384 f = fopen(p, "re");
a644184a
LP
385 if (!f) {
386 if (errno == ENOENT)
387 return -ESRCH;
0b452006 388 return -errno;
a644184a 389 }
0b452006
RC
390
391 while ((c = fgetc(f)) != EOF) {
392 if (!GREEDY_REALLOC(outcome, allocated, sz + 5))
393 return -ENOMEM;
394
395 if (c == '\0')
396 outcome[sz++] = '\n';
397 else
398 sz += cescape_char(c, outcome + sz);
399 }
400
03c55bc0
LP
401 if (!outcome) {
402 outcome = strdup("");
403 if (!outcome)
404 return -ENOMEM;
405 } else
406 outcome[sz] = '\0';
de8763b6 407
0b452006
RC
408 *env = outcome;
409 outcome = NULL;
410
411 return 0;
412}
413
6bc73acb 414int get_process_ppid(pid_t pid, pid_t *_ppid) {
0b452006
RC
415 int r;
416 _cleanup_free_ char *line = NULL;
417 long unsigned ppid;
418 const char *p;
419
420 assert(pid >= 0);
421 assert(_ppid);
422
423 if (pid == 0) {
424 *_ppid = getppid();
425 return 0;
426 }
427
428 p = procfs_file_alloca(pid, "stat");
429 r = read_one_line_file(p, &line);
a644184a
LP
430 if (r == -ENOENT)
431 return -ESRCH;
0b452006
RC
432 if (r < 0)
433 return r;
434
435 /* Let's skip the pid and comm fields. The latter is enclosed
436 * in () but does not escape any () in its value, so let's
437 * skip over it manually */
438
439 p = strrchr(line, ')');
440 if (!p)
441 return -EIO;
442
443 p++;
444
445 if (sscanf(p, " "
446 "%*c " /* state */
447 "%lu ", /* ppid */
448 &ppid) != 1)
449 return -EIO;
450
451 if ((long unsigned) (pid_t) ppid != ppid)
452 return -ERANGE;
453
454 *_ppid = (pid_t) ppid;
455
456 return 0;
457}
458
459int wait_for_terminate(pid_t pid, siginfo_t *status) {
460 siginfo_t dummy;
461
462 assert(pid >= 1);
463
464 if (!status)
465 status = &dummy;
466
467 for (;;) {
468 zero(*status);
469
470 if (waitid(P_PID, pid, status, WEXITED) < 0) {
471
472 if (errno == EINTR)
473 continue;
474
475 return -errno;
476 }
477
478 return 0;
479 }
480}
481
482/*
483 * Return values:
484 * < 0 : wait_for_terminate() failed to get the state of the
485 * process, the process was terminated by a signal, or
486 * failed for an unknown reason.
487 * >=0 : The process terminated normally, and its exit code is
488 * returned.
489 *
490 * That is, success is indicated by a return value of zero, and an
491 * error is indicated by a non-zero value.
492 *
493 * A warning is emitted if the process terminates abnormally,
494 * and also if it returns non-zero unless check_exit_code is true.
495 */
496int wait_for_terminate_and_warn(const char *name, pid_t pid, bool check_exit_code) {
497 int r;
498 siginfo_t status;
499
500 assert(name);
501 assert(pid > 1);
502
503 r = wait_for_terminate(pid, &status);
504 if (r < 0)
505 return log_warning_errno(r, "Failed to wait for %s: %m", name);
506
507 if (status.si_code == CLD_EXITED) {
508 if (status.si_status != 0)
509 log_full(check_exit_code ? LOG_WARNING : LOG_DEBUG,
510 "%s failed with error code %i.", name, status.si_status);
511 else
512 log_debug("%s succeeded.", name);
513
514 return status.si_status;
515 } else if (status.si_code == CLD_KILLED ||
516 status.si_code == CLD_DUMPED) {
517
518 log_warning("%s terminated by signal %s.", name, signal_to_string(status.si_status));
519 return -EPROTO;
520 }
521
522 log_warning("%s failed due to unknown reason.", name);
523 return -EPROTO;
524}
525
4d0d3d41
LP
526void sigkill_wait(pid_t *pid) {
527 if (!pid)
528 return;
529 if (*pid <= 1)
530 return;
531
532 if (kill(*pid, SIGKILL) > 0)
533 (void) wait_for_terminate(*pid, NULL);
534}
535
0b452006
RC
536int kill_and_sigcont(pid_t pid, int sig) {
537 int r;
538
539 r = kill(pid, sig) < 0 ? -errno : 0;
540
541 if (r >= 0)
542 kill(pid, SIGCONT);
543
544 return r;
545}
546
547int getenv_for_pid(pid_t pid, const char *field, char **_value) {
548 _cleanup_fclose_ FILE *f = NULL;
549 char *value = NULL;
550 int r;
551 bool done = false;
552 size_t l;
553 const char *path;
554
555 assert(pid >= 0);
556 assert(field);
557 assert(_value);
558
559 path = procfs_file_alloca(pid, "environ");
560
561 f = fopen(path, "re");
a644184a
LP
562 if (!f) {
563 if (errno == ENOENT)
564 return -ESRCH;
0b452006 565 return -errno;
a644184a 566 }
0b452006
RC
567
568 l = strlen(field);
569 r = 0;
570
571 do {
572 char line[LINE_MAX];
573 unsigned i;
574
575 for (i = 0; i < sizeof(line)-1; i++) {
576 int c;
577
578 c = getc(f);
579 if (_unlikely_(c == EOF)) {
580 done = true;
581 break;
582 } else if (c == 0)
583 break;
584
585 line[i] = c;
586 }
587 line[i] = 0;
588
589 if (memcmp(line, field, l) == 0 && line[l] == '=') {
590 value = strdup(line + l + 1);
591 if (!value)
592 return -ENOMEM;
593
594 r = 1;
595 break;
596 }
597
598 } while (!done);
599
600 *_value = value;
601 return r;
602}
603
604bool pid_is_unwaited(pid_t pid) {
605 /* Checks whether a PID is still valid at all, including a zombie */
606
5fd9b2c5 607 if (pid < 0)
0b452006
RC
608 return false;
609
5fd9b2c5
LP
610 if (pid <= 1) /* If we or PID 1 would be dead and have been waited for, this code would not be running */
611 return true;
612
0b452006
RC
613 if (kill(pid, 0) >= 0)
614 return true;
615
616 return errno != ESRCH;
617}
618
619bool pid_is_alive(pid_t pid) {
620 int r;
621
622 /* Checks whether a PID is still valid and not a zombie */
623
5fd9b2c5 624 if (pid < 0)
0b452006
RC
625 return false;
626
5fd9b2c5
LP
627 if (pid <= 1) /* If we or PID 1 would be a zombie, this code would not be running */
628 return true;
629
0b452006 630 r = get_process_state(pid);
a644184a 631 if (r == -ESRCH || r == 'Z')
0b452006
RC
632 return false;
633
634 return true;
635}
d4510856
LP
636
637bool is_main_thread(void) {
638 static thread_local int cached = 0;
639
640 if (_unlikely_(cached == 0))
641 cached = getpid() == gettid() ? 1 : -1;
642
643 return cached > 0;
644}
7b3e062c
LP
645
646noreturn void freeze(void) {
647
648 /* Make sure nobody waits for us on a socket anymore */
649 close_all_fds(NULL, 0);
650
651 sync();
652
653 for (;;)
654 pause();
655}
656
657bool oom_score_adjust_is_valid(int oa) {
658 return oa >= OOM_SCORE_ADJ_MIN && oa <= OOM_SCORE_ADJ_MAX;
659}
660
661unsigned long personality_from_string(const char *p) {
662
663 /* Parse a personality specifier. We introduce our own
664 * identifiers that indicate specific ABIs, rather than just
665 * hints regarding the register size, since we want to keep
666 * things open for multiple locally supported ABIs for the
667 * same register size. We try to reuse the ABI identifiers
668 * used by libseccomp. */
669
670#if defined(__x86_64__)
671
672 if (streq(p, "x86"))
673 return PER_LINUX32;
674
675 if (streq(p, "x86-64"))
676 return PER_LINUX;
677
678#elif defined(__i386__)
679
680 if (streq(p, "x86"))
681 return PER_LINUX;
682
683#elif defined(__s390x__)
684
685 if (streq(p, "s390"))
686 return PER_LINUX32;
687
688 if (streq(p, "s390x"))
689 return PER_LINUX;
690
691#elif defined(__s390__)
692
693 if (streq(p, "s390"))
694 return PER_LINUX;
695#endif
696
697 return PERSONALITY_INVALID;
698}
699
700const char* personality_to_string(unsigned long p) {
701
702#if defined(__x86_64__)
703
704 if (p == PER_LINUX32)
705 return "x86";
706
707 if (p == PER_LINUX)
708 return "x86-64";
709
710#elif defined(__i386__)
711
712 if (p == PER_LINUX)
713 return "x86";
714
715#elif defined(__s390x__)
716
717 if (p == PER_LINUX)
718 return "s390x";
719
720 if (p == PER_LINUX32)
721 return "s390";
722
723#elif defined(__s390__)
724
725 if (p == PER_LINUX)
726 return "s390";
727
728#endif
729
730 return NULL;
731}
732
733static const char *const ioprio_class_table[] = {
734 [IOPRIO_CLASS_NONE] = "none",
735 [IOPRIO_CLASS_RT] = "realtime",
736 [IOPRIO_CLASS_BE] = "best-effort",
737 [IOPRIO_CLASS_IDLE] = "idle"
738};
739
740DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(ioprio_class, int, INT_MAX);
741
742static const char *const sigchld_code_table[] = {
743 [CLD_EXITED] = "exited",
744 [CLD_KILLED] = "killed",
745 [CLD_DUMPED] = "dumped",
746 [CLD_TRAPPED] = "trapped",
747 [CLD_STOPPED] = "stopped",
748 [CLD_CONTINUED] = "continued",
749};
750
751DEFINE_STRING_TABLE_LOOKUP(sigchld_code, int);
752
753static const char* const sched_policy_table[] = {
754 [SCHED_OTHER] = "other",
755 [SCHED_BATCH] = "batch",
756 [SCHED_IDLE] = "idle",
757 [SCHED_FIFO] = "fifo",
758 [SCHED_RR] = "rr"
759};
760
761DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(sched_policy, int, INT_MAX);