Skip to content

Commit fc65fd7

Browse files
committed
use libgetargv
1 parent cdf02e0 commit fc65fd7

File tree

1 file changed

+13
-153
lines changed

1 file changed

+13
-153
lines changed

ps/print.c

Lines changed: 13 additions & 153 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,6 @@ static const char rcsid[] =
4848

4949
#include <sys/ucred.h>
5050
#include <sys/user.h>
51-
#include <sys/sysctl.h>
5251
#include <sys/cdefs.h>
5352

5453
#ifdef __APPLE__
@@ -71,6 +70,8 @@ static const char rcsid[] =
7170
#include <vis.h>
7271
#include <pwd.h>
7372

73+
#include <libgetargv.h>
74+
7475
#include "ps.h"
7576

7677
extern int mflg, print_all_thread, print_thread_num;
@@ -115,9 +116,6 @@ static void
115116
getproclline(KINFO *k, char **command_name, int *argvlen, int *argv0len,
116117
int show_args)
117118
{
118-
int mib[3], argmax, nargs, c = 0;
119-
size_t size;
120-
char *procargs, *sp, *np, *cp;
121119
extern int eflg;
122120

123121
/*
@@ -129,126 +127,16 @@ getproclline(KINFO *k, char **command_name, int *argvlen, int *argv0len,
129127
return;
130128
}
131129

132-
/* Get the maximum process arguments size. */
133-
mib[0] = CTL_KERN;
134-
mib[1] = KERN_ARGMAX;
135-
136-
size = sizeof(argmax);
137-
if (sysctl(mib, 2, &argmax, &size, NULL, 0) == -1) {
138-
goto ERROR_A;
139-
}
140-
141-
/* Allocate space for the arguments. */
142-
procargs = (char *)malloc(argmax);
143-
if (procargs == NULL) {
130+
struct ArgvEnvpResult result;
131+
if (!get_argv_and_envp_of_pid(KI_PROC(k)->p_pid, &result)) {
144132
goto ERROR_A;
145133
}
146134

147-
/*
148-
* Make a sysctl() call to get the raw argument space of the process.
149-
* The layout is documented in start.s, which is part of the Csu
150-
* project. In summary, it looks like:
151-
*
152-
* /---------------\ 0x00000000
153-
* : :
154-
* : :
155-
* |---------------|
156-
* | argc |
157-
* |---------------|
158-
* | arg[0] |
159-
* |---------------|
160-
* : :
161-
* : :
162-
* |---------------|
163-
* | arg[argc - 1] |
164-
* |---------------|
165-
* | 0 |
166-
* |---------------|
167-
* | env[0] |
168-
* |---------------|
169-
* : :
170-
* : :
171-
* |---------------|
172-
* | env[n] |
173-
* |---------------|
174-
* | 0 |
175-
* |---------------| <-- Beginning of data returned by sysctl() is here.
176-
* | argc |
177-
* |---------------|
178-
* | exec_path |
179-
* |:::::::::::::::|
180-
* | |
181-
* | String area. |
182-
* | |
183-
* |---------------| <-- Top of stack.
184-
* : :
185-
* : :
186-
* \---------------/ 0xffffffff
187-
*/
188-
mib[0] = CTL_KERN;
189-
mib[1] = KERN_PROCARGS2;
190-
mib[2] = KI_PROC(k)->p_pid;
191-
192-
size = (size_t)argmax;
193-
if (sysctl(mib, 3, procargs, &size, NULL, 0) == -1) {
194-
goto ERROR_B;
195-
}
196-
197-
memcpy(&nargs, procargs, sizeof(nargs));
198-
cp = procargs + sizeof(nargs);
199-
200-
/* Skip the saved exec_path. */
201-
for (; cp < &procargs[size]; cp++) {
202-
if (*cp == '\0') {
203-
/* End of exec_path reached. */
204-
break;
205-
}
206-
}
207-
if (cp == &procargs[size]) {
208-
goto ERROR_B;
209-
}
210-
211-
/* Skip trailing '\0' characters. */
212-
for (; cp < &procargs[size]; cp++) {
213-
if (*cp != '\0') {
214-
/* Beginning of first argument reached. */
215-
break;
216-
}
217-
}
218-
if (cp == &procargs[size]) {
219-
goto ERROR_B;
220-
}
221-
/* Save where the argv[0] string starts. */
222-
sp = cp;
223-
224-
/*
225-
* Iterate through the '\0'-terminated strings and convert '\0' to ' '
226-
* until a string is found that has a '=' character in it (or there are
227-
* no more strings in procargs). There is no way to deterministically
228-
* know where the command arguments end and the environment strings
229-
* start, which is why the '=' character is searched for as a heuristic.
230-
*/
231-
for (np = NULL; c < nargs && cp < &procargs[size]; cp++) {
232-
if (*cp == '\0') {
233-
c++;
234-
if (np != NULL) {
235-
/* Convert previous '\0'. */
236-
*np = ' ';
237-
} else {
238-
*argv0len = cp - sp;
239-
}
240-
/* Note location of current '\0'. */
241-
np = cp;
242-
243-
if (!show_args) {
244-
/*
245-
* Don't convert '\0' characters to ' '.
246-
* However, we needed to know that the
247-
* command name was terminated, which we
248-
* now know.
249-
*/
250-
break;
251-
}
135+
*argv0len = (result.argv[1] - result.argv[0]) - 1;
136+
if (show_args) {
137+
//for every arg except the last one, convert the terminating NUL into a space
138+
for (int c = 0; c < result.argc - 1; c++) {
139+
*(result.argv[c+1] - 1) = ' ';
252140
}
253141
}
254142

@@ -258,46 +146,18 @@ getproclline(KINFO *k, char **command_name, int *argvlen, int *argv0len,
258146
* follow.
259147
*/
260148
if ( show_args && (eflg != 0) && ( (getuid() == 0) || (KI_EPROC(k)->e_pcred.p_ruid == getuid()) ) ) {
261-
for (; cp < &procargs[size]; cp++) {
262-
if (*cp == '\0') {
263-
if (np != NULL) {
264-
if (&np[1] == cp) {
265-
/*
266-
* Two '\0' characters in a row.
267-
* This should normally only
268-
* happen after all the strings
269-
* have been seen, but in any
270-
* case, stop parsing.
271-
*/
272-
break;
273-
}
274-
/* Convert previous '\0'. */
275-
*np = ' ';
276-
}
277-
/* Note location of current '\0'. */
278-
np = cp;
279-
}
149+
for (int c = 0; c < result.envc - 1; c++) {
150+
*(result.envp[c+1] - 1) = ' ';
280151
}
281152
}
282153

283-
/*
284-
* sp points to the beginning of the arguments/environment string, and
285-
* np should point to the '\0' terminator for the string.
286-
*/
287-
if (np == NULL || np == sp) {
288-
/* Empty or unterminated string. */
289-
goto ERROR_B;
290-
}
291-
292154
/* Make a copy of the string. */
293-
*argvlen = asprintf(command_name, "%s", sp);
155+
*argvlen = asprintf(command_name, "%s", result.argv[0]);
294156

295157
/* Clean up. */
296-
free(procargs);
158+
free_ArgvEnvpResult(&result);
297159
return;
298160

299-
ERROR_B:
300-
free(procargs);
301161
ERROR_A:
302162
*argv0len = *argvlen
303163
= asprintf(command_name, "(%s)", KI_PROC(k)->p_comm);

0 commit comments

Comments
 (0)