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
get_process_comm(pid_t pid,char ** name)36 int 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
get_process_cmdline(pid_t pid,size_t max_length,bool comm_fallback,char ** line)52 int 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
get_process_environ(pid_t pid,char ** env)145 int 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