xref: /third_party/eudev/src/shared/process-util.c (revision 99ca880a)
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 <stdbool.h>
21#include <sys/types.h>
22#include <string.h>
23#include <stdio.h>
24#include <assert.h>
25#include <errno.h>
26#include <unistd.h>
27#include <sys/wait.h>
28#include <signal.h>
29#include <ctype.h>
30
31#include "process-util.h"
32#include "fileio.h"
33#include "util.h"
34#include "log.h"
35
36int get_process_comm(pid_t pid, char **name) {
37        const char *p;
38        int r;
39
40        assert(name);
41        assert(pid >= 0);
42
43        p = procfs_file_alloca(pid, "comm");
44
45        r = read_one_line_file(p, name);
46        if (r == -ENOENT)
47                return -ESRCH;
48
49        return r;
50}
51
52int get_process_cmdline(pid_t pid, size_t max_length, bool comm_fallback, char **line) {
53        _cleanup_fclose_ FILE *f = NULL;
54        char *r = NULL, *k;
55        const char *p;
56        int c;
57
58        assert(line);
59        assert(pid >= 0);
60
61        p = procfs_file_alloca(pid, "cmdline");
62
63        f = fopen(p, "re");
64        if (!f)
65                return -errno;
66
67        if (max_length == 0) {
68                size_t len = 0, allocated = 0;
69
70                while ((c = getc(f)) != EOF) {
71
72                        if (!GREEDY_REALLOC(r, allocated, len+2)) {
73                                free(r);
74                                return -ENOMEM;
75                        }
76
77                        r[len++] = isprint(c) ? c : ' ';
78                }
79
80                if (len > 0)
81                        r[len-1] = 0;
82
83        } else {
84                bool space = false;
85                size_t left;
86
87                r = new(char, max_length);
88                if (!r)
89                        return -ENOMEM;
90
91                k = r;
92                left = max_length;
93                while ((c = getc(f)) != EOF) {
94
95                        if (isprint(c)) {
96                                if (space) {
97                                        if (left <= 4)
98                                                break;
99
100                                        *(k++) = ' ';
101                                        left--;
102                                        space = false;
103                                }
104
105                                if (left <= 4)
106                                        break;
107
108                                *(k++) = (char) c;
109                                left--;
110                        }  else
111                                space = true;
112                }
113
114                if (left <= 4) {
115                        size_t n = MIN(left-1, 3U);
116                        memcpy(k, "...", n);
117                        k[n] = 0;
118                } else
119                        *k = 0;
120        }
121
122        /* Kernel threads have no argv[] */
123        if (isempty(r)) {
124                _cleanup_free_ char *t = NULL;
125                int h;
126
127                free(r);
128
129                if (!comm_fallback)
130                        return -ENOENT;
131
132                h = get_process_comm(pid, &t);
133                if (h < 0)
134                        return h;
135
136                r = strjoin("[", t, "]", NULL);
137                if (!r)
138                        return -ENOMEM;
139        }
140
141        *line = r;
142        return 0;
143}
144
145int get_process_environ(pid_t pid, char **env) {
146        _cleanup_fclose_ FILE *f = NULL;
147        _cleanup_free_ char *outcome = NULL;
148        int c;
149        const char *p;
150        size_t allocated = 0, sz = 0;
151
152        assert(pid >= 0);
153        assert(env);
154
155        p = procfs_file_alloca(pid, "environ");
156
157        f = fopen(p, "re");
158        if (!f)
159                return -errno;
160
161        while ((c = fgetc(f)) != EOF) {
162                if (!GREEDY_REALLOC(outcome, allocated, sz + 5))
163                        return -ENOMEM;
164
165                if (c == '\0')
166                        outcome[sz++] = '\n';
167                else
168                        sz += cescape_char(c, outcome + sz);
169        }
170
171        outcome[sz] = '\0';
172        *env = outcome;
173        outcome = NULL;
174
175        return 0;
176}
177