]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/basic/process-util.c
util-lib: split our string related calls from util.[ch] into its own file string...
[thirdparty/systemd.git] / src / basic / process-util.c
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
20 #include <assert.h>
21 #include <ctype.h>
22 #include <errno.h>
23 #include <signal.h>
24 #include <stdbool.h>
25 #include <stdio.h>
26 #include <string.h>
27 #include <sys/types.h>
28 #include <sys/wait.h>
29 #include <unistd.h>
30
31 #include "escape.h"
32 #include "fileio.h"
33 #include "log.h"
34 #include "signal-util.h"
35 #include "string-util.h"
36 #include "util.h"
37 #include "process-util.h"
38
39 int get_process_state(pid_t pid) {
40 const char *p;
41 char state;
42 int r;
43 _cleanup_free_ char *line = NULL;
44
45 assert(pid >= 0);
46
47 p = procfs_file_alloca(pid, "stat");
48
49 r = read_one_line_file(p, &line);
50 if (r == -ENOENT)
51 return -ESRCH;
52 if (r < 0)
53 return r;
54
55 p = strrchr(line, ')');
56 if (!p)
57 return -EIO;
58
59 p++;
60
61 if (sscanf(p, " %c", &state) != 1)
62 return -EIO;
63
64 return (unsigned char) state;
65 }
66
67 int get_process_comm(pid_t pid, char **name) {
68 const char *p;
69 int r;
70
71 assert(name);
72 assert(pid >= 0);
73
74 p = procfs_file_alloca(pid, "comm");
75
76 r = read_one_line_file(p, name);
77 if (r == -ENOENT)
78 return -ESRCH;
79
80 return r;
81 }
82
83 int get_process_cmdline(pid_t pid, size_t max_length, bool comm_fallback, char **line) {
84 _cleanup_fclose_ FILE *f = NULL;
85 char *r = NULL, *k;
86 const char *p;
87 int c;
88
89 assert(line);
90 assert(pid >= 0);
91
92 p = procfs_file_alloca(pid, "cmdline");
93
94 f = fopen(p, "re");
95 if (!f) {
96 if (errno == ENOENT)
97 return -ESRCH;
98 return -errno;
99 }
100
101 if (max_length == 0) {
102 size_t len = 0, allocated = 0;
103
104 while ((c = getc(f)) != EOF) {
105
106 if (!GREEDY_REALLOC(r, allocated, len+2)) {
107 free(r);
108 return -ENOMEM;
109 }
110
111 r[len++] = isprint(c) ? c : ' ';
112 }
113
114 if (len > 0)
115 r[len-1] = 0;
116
117 } else {
118 bool space = false;
119 size_t left;
120
121 r = new(char, max_length);
122 if (!r)
123 return -ENOMEM;
124
125 k = r;
126 left = max_length;
127 while ((c = getc(f)) != EOF) {
128
129 if (isprint(c)) {
130 if (space) {
131 if (left <= 4)
132 break;
133
134 *(k++) = ' ';
135 left--;
136 space = false;
137 }
138
139 if (left <= 4)
140 break;
141
142 *(k++) = (char) c;
143 left--;
144 } else
145 space = true;
146 }
147
148 if (left <= 4) {
149 size_t n = MIN(left-1, 3U);
150 memcpy(k, "...", n);
151 k[n] = 0;
152 } else
153 *k = 0;
154 }
155
156 /* Kernel threads have no argv[] */
157 if (isempty(r)) {
158 _cleanup_free_ char *t = NULL;
159 int h;
160
161 free(r);
162
163 if (!comm_fallback)
164 return -ENOENT;
165
166 h = get_process_comm(pid, &t);
167 if (h < 0)
168 return h;
169
170 r = strjoin("[", t, "]", NULL);
171 if (!r)
172 return -ENOMEM;
173 }
174
175 *line = r;
176 return 0;
177 }
178
179 int is_kernel_thread(pid_t pid) {
180 const char *p;
181 size_t count;
182 char c;
183 bool eof;
184 FILE *f;
185
186 if (pid == 0 || pid == 1) /* pid 1, and we ourselves certainly aren't a kernel thread */
187 return 0;
188
189 assert(pid > 1);
190
191 p = procfs_file_alloca(pid, "cmdline");
192 f = fopen(p, "re");
193 if (!f) {
194 if (errno == ENOENT)
195 return -ESRCH;
196 return -errno;
197 }
198
199 count = fread(&c, 1, 1, f);
200 eof = feof(f);
201 fclose(f);
202
203 /* Kernel threads have an empty cmdline */
204
205 if (count <= 0)
206 return eof ? 1 : -errno;
207
208 return 0;
209 }
210
211 int get_process_capeff(pid_t pid, char **capeff) {
212 const char *p;
213 int r;
214
215 assert(capeff);
216 assert(pid >= 0);
217
218 p = procfs_file_alloca(pid, "status");
219
220 r = get_proc_field(p, "CapEff", WHITESPACE, capeff);
221 if (r == -ENOENT)
222 return -ESRCH;
223
224 return r;
225 }
226
227 static int get_process_link_contents(const char *proc_file, char **name) {
228 int r;
229
230 assert(proc_file);
231 assert(name);
232
233 r = readlink_malloc(proc_file, name);
234 if (r == -ENOENT)
235 return -ESRCH;
236 if (r < 0)
237 return r;
238
239 return 0;
240 }
241
242 int get_process_exe(pid_t pid, char **name) {
243 const char *p;
244 char *d;
245 int r;
246
247 assert(pid >= 0);
248
249 p = procfs_file_alloca(pid, "exe");
250 r = get_process_link_contents(p, name);
251 if (r < 0)
252 return r;
253
254 d = endswith(*name, " (deleted)");
255 if (d)
256 *d = '\0';
257
258 return 0;
259 }
260
261 static int get_process_id(pid_t pid, const char *field, uid_t *uid) {
262 _cleanup_fclose_ FILE *f = NULL;
263 char line[LINE_MAX];
264 const char *p;
265
266 assert(field);
267 assert(uid);
268
269 if (pid == 0)
270 return getuid();
271
272 p = procfs_file_alloca(pid, "status");
273 f = fopen(p, "re");
274 if (!f) {
275 if (errno == ENOENT)
276 return -ESRCH;
277 return -errno;
278 }
279
280 FOREACH_LINE(line, f, return -errno) {
281 char *l;
282
283 l = strstrip(line);
284
285 if (startswith(l, field)) {
286 l += strlen(field);
287 l += strspn(l, WHITESPACE);
288
289 l[strcspn(l, WHITESPACE)] = 0;
290
291 return parse_uid(l, uid);
292 }
293 }
294
295 return -EIO;
296 }
297
298 int get_process_uid(pid_t pid, uid_t *uid) {
299 return get_process_id(pid, "Uid:", uid);
300 }
301
302 int get_process_gid(pid_t pid, gid_t *gid) {
303 assert_cc(sizeof(uid_t) == sizeof(gid_t));
304 return get_process_id(pid, "Gid:", gid);
305 }
306
307 int get_process_cwd(pid_t pid, char **cwd) {
308 const char *p;
309
310 assert(pid >= 0);
311
312 p = procfs_file_alloca(pid, "cwd");
313
314 return get_process_link_contents(p, cwd);
315 }
316
317 int get_process_root(pid_t pid, char **root) {
318 const char *p;
319
320 assert(pid >= 0);
321
322 p = procfs_file_alloca(pid, "root");
323
324 return get_process_link_contents(p, root);
325 }
326
327 int get_process_environ(pid_t pid, char **env) {
328 _cleanup_fclose_ FILE *f = NULL;
329 _cleanup_free_ char *outcome = NULL;
330 int c;
331 const char *p;
332 size_t allocated = 0, sz = 0;
333
334 assert(pid >= 0);
335 assert(env);
336
337 p = procfs_file_alloca(pid, "environ");
338
339 f = fopen(p, "re");
340 if (!f) {
341 if (errno == ENOENT)
342 return -ESRCH;
343 return -errno;
344 }
345
346 while ((c = fgetc(f)) != EOF) {
347 if (!GREEDY_REALLOC(outcome, allocated, sz + 5))
348 return -ENOMEM;
349
350 if (c == '\0')
351 outcome[sz++] = '\n';
352 else
353 sz += cescape_char(c, outcome + sz);
354 }
355
356 if (!outcome) {
357 outcome = strdup("");
358 if (!outcome)
359 return -ENOMEM;
360 } else
361 outcome[sz] = '\0';
362
363 *env = outcome;
364 outcome = NULL;
365
366 return 0;
367 }
368
369 int get_parent_of_pid(pid_t pid, pid_t *_ppid) {
370 int r;
371 _cleanup_free_ char *line = NULL;
372 long unsigned ppid;
373 const char *p;
374
375 assert(pid >= 0);
376 assert(_ppid);
377
378 if (pid == 0) {
379 *_ppid = getppid();
380 return 0;
381 }
382
383 p = procfs_file_alloca(pid, "stat");
384 r = read_one_line_file(p, &line);
385 if (r == -ENOENT)
386 return -ESRCH;
387 if (r < 0)
388 return r;
389
390 /* Let's skip the pid and comm fields. The latter is enclosed
391 * in () but does not escape any () in its value, so let's
392 * skip over it manually */
393
394 p = strrchr(line, ')');
395 if (!p)
396 return -EIO;
397
398 p++;
399
400 if (sscanf(p, " "
401 "%*c " /* state */
402 "%lu ", /* ppid */
403 &ppid) != 1)
404 return -EIO;
405
406 if ((long unsigned) (pid_t) ppid != ppid)
407 return -ERANGE;
408
409 *_ppid = (pid_t) ppid;
410
411 return 0;
412 }
413
414 int wait_for_terminate(pid_t pid, siginfo_t *status) {
415 siginfo_t dummy;
416
417 assert(pid >= 1);
418
419 if (!status)
420 status = &dummy;
421
422 for (;;) {
423 zero(*status);
424
425 if (waitid(P_PID, pid, status, WEXITED) < 0) {
426
427 if (errno == EINTR)
428 continue;
429
430 return -errno;
431 }
432
433 return 0;
434 }
435 }
436
437 /*
438 * Return values:
439 * < 0 : wait_for_terminate() failed to get the state of the
440 * process, the process was terminated by a signal, or
441 * failed for an unknown reason.
442 * >=0 : The process terminated normally, and its exit code is
443 * returned.
444 *
445 * That is, success is indicated by a return value of zero, and an
446 * error is indicated by a non-zero value.
447 *
448 * A warning is emitted if the process terminates abnormally,
449 * and also if it returns non-zero unless check_exit_code is true.
450 */
451 int wait_for_terminate_and_warn(const char *name, pid_t pid, bool check_exit_code) {
452 int r;
453 siginfo_t status;
454
455 assert(name);
456 assert(pid > 1);
457
458 r = wait_for_terminate(pid, &status);
459 if (r < 0)
460 return log_warning_errno(r, "Failed to wait for %s: %m", name);
461
462 if (status.si_code == CLD_EXITED) {
463 if (status.si_status != 0)
464 log_full(check_exit_code ? LOG_WARNING : LOG_DEBUG,
465 "%s failed with error code %i.", name, status.si_status);
466 else
467 log_debug("%s succeeded.", name);
468
469 return status.si_status;
470 } else if (status.si_code == CLD_KILLED ||
471 status.si_code == CLD_DUMPED) {
472
473 log_warning("%s terminated by signal %s.", name, signal_to_string(status.si_status));
474 return -EPROTO;
475 }
476
477 log_warning("%s failed due to unknown reason.", name);
478 return -EPROTO;
479 }
480
481 int kill_and_sigcont(pid_t pid, int sig) {
482 int r;
483
484 r = kill(pid, sig) < 0 ? -errno : 0;
485
486 if (r >= 0)
487 kill(pid, SIGCONT);
488
489 return r;
490 }
491
492 int getenv_for_pid(pid_t pid, const char *field, char **_value) {
493 _cleanup_fclose_ FILE *f = NULL;
494 char *value = NULL;
495 int r;
496 bool done = false;
497 size_t l;
498 const char *path;
499
500 assert(pid >= 0);
501 assert(field);
502 assert(_value);
503
504 path = procfs_file_alloca(pid, "environ");
505
506 f = fopen(path, "re");
507 if (!f) {
508 if (errno == ENOENT)
509 return -ESRCH;
510 return -errno;
511 }
512
513 l = strlen(field);
514 r = 0;
515
516 do {
517 char line[LINE_MAX];
518 unsigned i;
519
520 for (i = 0; i < sizeof(line)-1; i++) {
521 int c;
522
523 c = getc(f);
524 if (_unlikely_(c == EOF)) {
525 done = true;
526 break;
527 } else if (c == 0)
528 break;
529
530 line[i] = c;
531 }
532 line[i] = 0;
533
534 if (memcmp(line, field, l) == 0 && line[l] == '=') {
535 value = strdup(line + l + 1);
536 if (!value)
537 return -ENOMEM;
538
539 r = 1;
540 break;
541 }
542
543 } while (!done);
544
545 *_value = value;
546 return r;
547 }
548
549 bool pid_is_unwaited(pid_t pid) {
550 /* Checks whether a PID is still valid at all, including a zombie */
551
552 if (pid <= 0)
553 return false;
554
555 if (kill(pid, 0) >= 0)
556 return true;
557
558 return errno != ESRCH;
559 }
560
561 bool pid_is_alive(pid_t pid) {
562 int r;
563
564 /* Checks whether a PID is still valid and not a zombie */
565
566 if (pid <= 0)
567 return false;
568
569 r = get_process_state(pid);
570 if (r == -ESRCH || r == 'Z')
571 return false;
572
573 return true;
574 }