xref: /minix3/minix/fs/procfs/pid.c (revision 433d6423c39e34ec4b79c950597bb2d236f886be)
1*433d6423SLionel Sambuc /* ProcFS - pid.c - by Alen Stojanov and David van Moolenbroek */
2*433d6423SLionel Sambuc 
3*433d6423SLionel Sambuc #include "inc.h"
4*433d6423SLionel Sambuc 
5*433d6423SLionel Sambuc #include <sys/mman.h>
6*433d6423SLionel Sambuc #include <minix/vm.h>
7*433d6423SLionel Sambuc 
8*433d6423SLionel Sambuc #define S_FRAME_SIZE	4096		/* use malloc if larger than this */
9*433d6423SLionel Sambuc static char s_frame[S_FRAME_SIZE];	/* static storage for process frame */
10*433d6423SLionel Sambuc static char *frame;			/* pointer to process frame buffer */
11*433d6423SLionel Sambuc 
12*433d6423SLionel Sambuc static void pid_psinfo(int slot);
13*433d6423SLionel Sambuc static void pid_cmdline(int slot);
14*433d6423SLionel Sambuc static void pid_environ(int slot);
15*433d6423SLionel Sambuc static void pid_map(int slot);
16*433d6423SLionel Sambuc 
17*433d6423SLionel Sambuc /* The files that are dynamically created in each PID directory. The data field
18*433d6423SLionel Sambuc  * contains each file's read function. Subdirectories are not yet supported.
19*433d6423SLionel Sambuc  */
20*433d6423SLionel Sambuc struct file pid_files[] = {
21*433d6423SLionel Sambuc 	{ "psinfo",	REG_ALL_MODE,	(data_t) pid_psinfo	},
22*433d6423SLionel Sambuc 	{ "cmdline",	REG_ALL_MODE,	(data_t) pid_cmdline	},
23*433d6423SLionel Sambuc 	{ "environ",	REG_ALL_MODE,	(data_t) pid_environ	},
24*433d6423SLionel Sambuc 	{ "map",	REG_ALL_MODE,	(data_t) pid_map	},
25*433d6423SLionel Sambuc 	{ NULL,		0,		(data_t) NULL		}
26*433d6423SLionel Sambuc };
27*433d6423SLionel Sambuc 
28*433d6423SLionel Sambuc /*===========================================================================*
29*433d6423SLionel Sambuc  *				is_zombie				     *
30*433d6423SLionel Sambuc  *===========================================================================*/
31*433d6423SLionel Sambuc static int is_zombie(int slot)
32*433d6423SLionel Sambuc {
33*433d6423SLionel Sambuc 	/* Is the given slot a zombie process?
34*433d6423SLionel Sambuc 	 */
35*433d6423SLionel Sambuc 
36*433d6423SLionel Sambuc 	return (slot >= NR_TASKS &&
37*433d6423SLionel Sambuc 		(mproc[slot - NR_TASKS].mp_flags & (TRACE_ZOMBIE | ZOMBIE)));
38*433d6423SLionel Sambuc }
39*433d6423SLionel Sambuc 
40*433d6423SLionel Sambuc /*===========================================================================*
41*433d6423SLionel Sambuc  *				pid_psinfo				     *
42*433d6423SLionel Sambuc  *===========================================================================*/
43*433d6423SLionel Sambuc static void pid_psinfo(int i)
44*433d6423SLionel Sambuc {
45*433d6423SLionel Sambuc 	/* Print information used by ps(1) and top(1).
46*433d6423SLionel Sambuc 	 */
47*433d6423SLionel Sambuc 	int pi, task, state, type, p_state, f_state;
48*433d6423SLionel Sambuc 	char name[PROC_NAME_LEN+1], *p;
49*433d6423SLionel Sambuc 	struct vm_usage_info vui;
50*433d6423SLionel Sambuc 	pid_t ppid;
51*433d6423SLionel Sambuc 
52*433d6423SLionel Sambuc 	pi = i - NR_TASKS;
53*433d6423SLionel Sambuc 	task = proc[i].p_nr < 0;
54*433d6423SLionel Sambuc 
55*433d6423SLionel Sambuc 	/* Get the name of the process. Spaces would mess up the format.. */
56*433d6423SLionel Sambuc 	if (task || mproc[i].mp_name[0] == 0)
57*433d6423SLionel Sambuc 		strncpy(name, proc[i].p_name, sizeof(name) - 1);
58*433d6423SLionel Sambuc 	else
59*433d6423SLionel Sambuc 		strncpy(name, mproc[pi].mp_name, sizeof(name) - 1);
60*433d6423SLionel Sambuc 	name[sizeof(name) - 1] = 0;
61*433d6423SLionel Sambuc 	if ((p = strchr(name, ' ')) != NULL)
62*433d6423SLionel Sambuc 		p[0] = 0;
63*433d6423SLionel Sambuc 
64*433d6423SLionel Sambuc 	/* Get the type of the process. */
65*433d6423SLionel Sambuc 	if (task)
66*433d6423SLionel Sambuc 		type = TYPE_TASK;
67*433d6423SLionel Sambuc 	else if (mproc[i].mp_flags & PRIV_PROC)
68*433d6423SLionel Sambuc 		type = TYPE_SYSTEM;
69*433d6423SLionel Sambuc 	else
70*433d6423SLionel Sambuc 		type = TYPE_USER;
71*433d6423SLionel Sambuc 
72*433d6423SLionel Sambuc 	/* Get the state of the process. */
73*433d6423SLionel Sambuc 	if (!task) {
74*433d6423SLionel Sambuc 		if (is_zombie(i))
75*433d6423SLionel Sambuc 			state = STATE_ZOMBIE;	/* zombie */
76*433d6423SLionel Sambuc 		else if (mproc[pi].mp_flags & TRACE_STOPPED)
77*433d6423SLionel Sambuc 			state = STATE_STOP;	/* stopped (traced) */
78*433d6423SLionel Sambuc 		else if (proc[i].p_rts_flags == 0)
79*433d6423SLionel Sambuc 			state = STATE_RUN;	/* in run-queue */
80*433d6423SLionel Sambuc 		else if (fp_is_blocked(&fproc[pi]) ||
81*433d6423SLionel Sambuc 		(mproc[pi].mp_flags & (WAITING | SIGSUSPENDED)))
82*433d6423SLionel Sambuc 			state = STATE_SLEEP;	/* sleeping */
83*433d6423SLionel Sambuc 		else
84*433d6423SLionel Sambuc 			state = STATE_WAIT;	/* waiting */
85*433d6423SLionel Sambuc 	} else {
86*433d6423SLionel Sambuc 		if (proc[i].p_rts_flags == 0)
87*433d6423SLionel Sambuc 			state = STATE_RUN;	/* in run-queue */
88*433d6423SLionel Sambuc 		else
89*433d6423SLionel Sambuc 			state = STATE_WAIT;	/* other i.e. waiting */
90*433d6423SLionel Sambuc 	}
91*433d6423SLionel Sambuc 
92*433d6423SLionel Sambuc 	/* We assume that even if a process has become a zombie, its kernel
93*433d6423SLionel Sambuc 	 * proc entry still contains the old (but valid) information. Currently
94*433d6423SLionel Sambuc 	 * this is true, but in the future we may have to filter some fields.
95*433d6423SLionel Sambuc 	 */
96*433d6423SLionel Sambuc 	buf_printf("%d %c %d %s %c %d %d %lu %lu %lu %lu",
97*433d6423SLionel Sambuc 		PSINFO_VERSION,			/* information version */
98*433d6423SLionel Sambuc 		type,				/* process type */
99*433d6423SLionel Sambuc 		(int) proc[i].p_endpoint,	/* process endpoint */
100*433d6423SLionel Sambuc 		name,				/* process name */
101*433d6423SLionel Sambuc 		state,				/* process state letter */
102*433d6423SLionel Sambuc 		(int) P_BLOCKEDON(&proc[i]),	/* endpt blocked on, or NONE */
103*433d6423SLionel Sambuc 		(int) proc[i].p_priority,	/* process priority */
104*433d6423SLionel Sambuc 		(long) proc[i].p_user_time,	/* user time */
105*433d6423SLionel Sambuc 		(long) proc[i].p_sys_time,	/* system time */
106*433d6423SLionel Sambuc 		ex64hi(proc[i].p_cycles),	/* execution cycles */
107*433d6423SLionel Sambuc 		ex64lo(proc[i].p_cycles)
108*433d6423SLionel Sambuc 	);
109*433d6423SLionel Sambuc 
110*433d6423SLionel Sambuc 	memset(&vui, 0, sizeof(vui));
111*433d6423SLionel Sambuc 
112*433d6423SLionel Sambuc 	if (!is_zombie(i)) {
113*433d6423SLionel Sambuc 		/* We don't care if this fails.  */
114*433d6423SLionel Sambuc 		(void) vm_info_usage(proc[i].p_endpoint, &vui);
115*433d6423SLionel Sambuc 	}
116*433d6423SLionel Sambuc 
117*433d6423SLionel Sambuc 	/* If the process is not a kernel task, we add some extra info. */
118*433d6423SLionel Sambuc 	if (!task) {
119*433d6423SLionel Sambuc 		if (mproc[pi].mp_flags & WAITING)
120*433d6423SLionel Sambuc 			p_state = PSTATE_WAITING;
121*433d6423SLionel Sambuc 		else if (mproc[pi].mp_flags & SIGSUSPENDED)
122*433d6423SLionel Sambuc 			p_state = PSTATE_SIGSUSP;
123*433d6423SLionel Sambuc 		else
124*433d6423SLionel Sambuc 			p_state = '-';
125*433d6423SLionel Sambuc 
126*433d6423SLionel Sambuc 		if (mproc[pi].mp_parent == pi)
127*433d6423SLionel Sambuc 			ppid = NO_PID;
128*433d6423SLionel Sambuc 		else
129*433d6423SLionel Sambuc 			ppid = mproc[mproc[pi].mp_parent].mp_pid;
130*433d6423SLionel Sambuc 
131*433d6423SLionel Sambuc 		switch (fproc[pi].fp_blocked_on) {
132*433d6423SLionel Sambuc 		case FP_BLOCKED_ON_NONE:	f_state = FSTATE_NONE; break;
133*433d6423SLionel Sambuc 		case FP_BLOCKED_ON_PIPE:	f_state = FSTATE_PIPE; break;
134*433d6423SLionel Sambuc 		case FP_BLOCKED_ON_LOCK:	f_state = FSTATE_LOCK; break;
135*433d6423SLionel Sambuc 		case FP_BLOCKED_ON_POPEN:	f_state = FSTATE_POPEN; break;
136*433d6423SLionel Sambuc 		case FP_BLOCKED_ON_SELECT:	f_state = FSTATE_SELECT; break;
137*433d6423SLionel Sambuc 		case FP_BLOCKED_ON_OTHER:	f_state = FSTATE_TASK; break;
138*433d6423SLionel Sambuc 		default:			f_state = FSTATE_UNKNOWN;
139*433d6423SLionel Sambuc 		}
140*433d6423SLionel Sambuc 
141*433d6423SLionel Sambuc 		buf_printf(" %lu %lu %lu %c %d %u %u %u %d %c %d %u",
142*433d6423SLionel Sambuc 			vui.vui_total,			/* total memory */
143*433d6423SLionel Sambuc 			vui.vui_common,			/* common memory */
144*433d6423SLionel Sambuc 			vui.vui_shared,			/* shared memory */
145*433d6423SLionel Sambuc 			p_state,			/* sleep state */
146*433d6423SLionel Sambuc 			ppid,				/* parent PID */
147*433d6423SLionel Sambuc 			mproc[pi].mp_realuid,		/* real UID */
148*433d6423SLionel Sambuc 			mproc[pi].mp_effuid,		/* effective UID */
149*433d6423SLionel Sambuc 			mproc[pi].mp_procgrp,		/* process group */
150*433d6423SLionel Sambuc 			mproc[pi].mp_nice,		/* nice value */
151*433d6423SLionel Sambuc 			f_state,			/* VFS block state */
152*433d6423SLionel Sambuc 			(int) (fproc[pi].fp_blocked_on == FP_BLOCKED_ON_OTHER)
153*433d6423SLionel Sambuc 				? fproc[pi].fp_task : NONE, /* block proc */
154*433d6423SLionel Sambuc 			fproc[pi].fp_tty		/* controlling tty */
155*433d6423SLionel Sambuc 		);
156*433d6423SLionel Sambuc 	}
157*433d6423SLionel Sambuc 
158*433d6423SLionel Sambuc 	/* always add kernel cycles */
159*433d6423SLionel Sambuc 	buf_printf(" %lu %lu %lu %lu",
160*433d6423SLionel Sambuc 		ex64hi(proc[i].p_kipc_cycles),
161*433d6423SLionel Sambuc 		ex64lo(proc[i].p_kipc_cycles),
162*433d6423SLionel Sambuc 		ex64hi(proc[i].p_kcall_cycles),
163*433d6423SLionel Sambuc 		ex64lo(proc[i].p_kcall_cycles));
164*433d6423SLionel Sambuc 
165*433d6423SLionel Sambuc 	/* add total memory for tasks at the end */
166*433d6423SLionel Sambuc 	if(task) buf_printf(" %lu", vui.vui_total);
167*433d6423SLionel Sambuc 
168*433d6423SLionel Sambuc 	/* Newline at the end of the file. */
169*433d6423SLionel Sambuc 	buf_printf("\n");
170*433d6423SLionel Sambuc }
171*433d6423SLionel Sambuc 
172*433d6423SLionel Sambuc /*===========================================================================*
173*433d6423SLionel Sambuc  *				put_frame				     *
174*433d6423SLionel Sambuc  *===========================================================================*/
175*433d6423SLionel Sambuc static void put_frame(void)
176*433d6423SLionel Sambuc {
177*433d6423SLionel Sambuc 	/* If we allocated memory dynamically during a call to get_frame(),
178*433d6423SLionel Sambuc 	 * free it up here.
179*433d6423SLionel Sambuc 	 */
180*433d6423SLionel Sambuc 
181*433d6423SLionel Sambuc 	if (frame != s_frame)
182*433d6423SLionel Sambuc 		free(frame);
183*433d6423SLionel Sambuc }
184*433d6423SLionel Sambuc 
185*433d6423SLionel Sambuc /*===========================================================================*
186*433d6423SLionel Sambuc  *				get_frame				     *
187*433d6423SLionel Sambuc  *===========================================================================*/
188*433d6423SLionel Sambuc static int get_frame(int slot, vir_bytes *basep, vir_bytes *sizep,
189*433d6423SLionel Sambuc 	size_t *nargsp)
190*433d6423SLionel Sambuc {
191*433d6423SLionel Sambuc 	/* Get the execution frame from the top of the given process's stack.
192*433d6423SLionel Sambuc 	 * It may be very large, in which case we temporarily allocate memory
193*433d6423SLionel Sambuc 	 * for it (up to a certain size).
194*433d6423SLionel Sambuc 	 */
195*433d6423SLionel Sambuc 	vir_bytes base, size;
196*433d6423SLionel Sambuc 	size_t nargs;
197*433d6423SLionel Sambuc 
198*433d6423SLionel Sambuc 	if (proc[slot].p_nr < 0 || is_zombie(slot))
199*433d6423SLionel Sambuc 		return FALSE;
200*433d6423SLionel Sambuc 
201*433d6423SLionel Sambuc 	/* Get the frame base address and size. Limit the size to whatever we
202*433d6423SLionel Sambuc 	 * can handle. If our static buffer is not sufficiently large to store
203*433d6423SLionel Sambuc 	 * the entire frame, allocate memory dynamically. It is then later
204*433d6423SLionel Sambuc 	 * freed by put_frame().
205*433d6423SLionel Sambuc 	 */
206*433d6423SLionel Sambuc 	base = mproc[slot - NR_TASKS].mp_frame_addr;
207*433d6423SLionel Sambuc 	size = mproc[slot - NR_TASKS].mp_frame_len;
208*433d6423SLionel Sambuc 
209*433d6423SLionel Sambuc 	if (size < sizeof(size_t)) return FALSE;
210*433d6423SLionel Sambuc 
211*433d6423SLionel Sambuc 	if (size > ARG_MAX) size = ARG_MAX;
212*433d6423SLionel Sambuc 
213*433d6423SLionel Sambuc 	if (size > sizeof(s_frame)) {
214*433d6423SLionel Sambuc 		frame = malloc(size);
215*433d6423SLionel Sambuc 
216*433d6423SLionel Sambuc 		if (frame == NULL)
217*433d6423SLionel Sambuc 			return FALSE;
218*433d6423SLionel Sambuc 	}
219*433d6423SLionel Sambuc 	else frame = s_frame;
220*433d6423SLionel Sambuc 
221*433d6423SLionel Sambuc 	/* Copy in the complete process frame. */
222*433d6423SLionel Sambuc 	if (sys_datacopy(proc[slot].p_endpoint, base,
223*433d6423SLionel Sambuc 			SELF, (vir_bytes) frame, (phys_bytes) size) != OK) {
224*433d6423SLionel Sambuc 		put_frame();
225*433d6423SLionel Sambuc 
226*433d6423SLionel Sambuc 		return FALSE;
227*433d6423SLionel Sambuc 	}
228*433d6423SLionel Sambuc 
229*433d6423SLionel Sambuc 	frame[size] = 0; /* terminate any last string */
230*433d6423SLionel Sambuc 
231*433d6423SLionel Sambuc 	nargs = * (size_t *) frame;
232*433d6423SLionel Sambuc 	if (nargs < 1 || sizeof(size_t) + sizeof(char *) * (nargs + 1) > size) {
233*433d6423SLionel Sambuc 		put_frame();
234*433d6423SLionel Sambuc 
235*433d6423SLionel Sambuc 		return FALSE;
236*433d6423SLionel Sambuc 	}
237*433d6423SLionel Sambuc 
238*433d6423SLionel Sambuc 	*basep = base;
239*433d6423SLionel Sambuc 	*sizep = size;
240*433d6423SLionel Sambuc 	*nargsp = nargs;
241*433d6423SLionel Sambuc 
242*433d6423SLionel Sambuc 	/* The caller now has to called put_frame() to clean up. */
243*433d6423SLionel Sambuc 	return TRUE;
244*433d6423SLionel Sambuc }
245*433d6423SLionel Sambuc 
246*433d6423SLionel Sambuc /*===========================================================================*
247*433d6423SLionel Sambuc  *				pid_cmdline				     *
248*433d6423SLionel Sambuc  *===========================================================================*/
249*433d6423SLionel Sambuc static void pid_cmdline(int slot)
250*433d6423SLionel Sambuc {
251*433d6423SLionel Sambuc 	/* Dump the process's command line as it is contained in the process
252*433d6423SLionel Sambuc 	 * itself. Each argument is terminated with a null character.
253*433d6423SLionel Sambuc 	 */
254*433d6423SLionel Sambuc 	vir_bytes base, size, ptr;
255*433d6423SLionel Sambuc 	size_t i, len, nargs;
256*433d6423SLionel Sambuc 	char **argv;
257*433d6423SLionel Sambuc 
258*433d6423SLionel Sambuc 	if (!get_frame(slot, &base, &size, &nargs))
259*433d6423SLionel Sambuc 		return;
260*433d6423SLionel Sambuc 
261*433d6423SLionel Sambuc 	argv = (char **) &frame[sizeof(size_t)];
262*433d6423SLionel Sambuc 
263*433d6423SLionel Sambuc 	for (i = 0; i < nargs; i++) {
264*433d6423SLionel Sambuc 		ptr = (vir_bytes) argv[i] - base;
265*433d6423SLionel Sambuc 
266*433d6423SLionel Sambuc 		/* Check for bad pointers. */
267*433d6423SLionel Sambuc 		if ((long) ptr < 0L || ptr >= size)
268*433d6423SLionel Sambuc 			break;
269*433d6423SLionel Sambuc 
270*433d6423SLionel Sambuc 		len = strlen(&frame[ptr]) + 1;
271*433d6423SLionel Sambuc 
272*433d6423SLionel Sambuc 		buf_append(&frame[ptr], len);
273*433d6423SLionel Sambuc 	}
274*433d6423SLionel Sambuc 
275*433d6423SLionel Sambuc 	put_frame();
276*433d6423SLionel Sambuc }
277*433d6423SLionel Sambuc 
278*433d6423SLionel Sambuc /*===========================================================================*
279*433d6423SLionel Sambuc  *				pid_environ				     *
280*433d6423SLionel Sambuc  *===========================================================================*/
281*433d6423SLionel Sambuc static void pid_environ(int slot)
282*433d6423SLionel Sambuc {
283*433d6423SLionel Sambuc 	/* Dump the process's initial environment as it is contained in the
284*433d6423SLionel Sambuc 	 * process itself. Each entry is terminated with a null character.
285*433d6423SLionel Sambuc 	 */
286*433d6423SLionel Sambuc 	vir_bytes base, size, ptr;
287*433d6423SLionel Sambuc 	size_t nargs, off, len;
288*433d6423SLionel Sambuc 	char **envp;
289*433d6423SLionel Sambuc 
290*433d6423SLionel Sambuc 	if (!get_frame(slot, &base, &size, &nargs))
291*433d6423SLionel Sambuc 		return;
292*433d6423SLionel Sambuc 
293*433d6423SLionel Sambuc 	off = sizeof(size_t) + sizeof(char *) * (nargs + 1);
294*433d6423SLionel Sambuc 	envp = (char **) &frame[off];
295*433d6423SLionel Sambuc 
296*433d6423SLionel Sambuc 	for (;;) {
297*433d6423SLionel Sambuc 		/* Make sure there is no buffer overrun. */
298*433d6423SLionel Sambuc 		if (off + sizeof(char *) > size)
299*433d6423SLionel Sambuc 			break;
300*433d6423SLionel Sambuc 
301*433d6423SLionel Sambuc 		ptr = (vir_bytes) *envp;
302*433d6423SLionel Sambuc 
303*433d6423SLionel Sambuc 		/* Stop at the terminating NULL pointer. */
304*433d6423SLionel Sambuc 		if (ptr == 0L)
305*433d6423SLionel Sambuc 			break;
306*433d6423SLionel Sambuc 
307*433d6423SLionel Sambuc 		ptr -= base;
308*433d6423SLionel Sambuc 
309*433d6423SLionel Sambuc 		/* Check for bad pointers. */
310*433d6423SLionel Sambuc 		if ((long) ptr < 0L || ptr >= size)
311*433d6423SLionel Sambuc 			break;
312*433d6423SLionel Sambuc 
313*433d6423SLionel Sambuc 		len = strlen(&frame[ptr]) + 1;
314*433d6423SLionel Sambuc 
315*433d6423SLionel Sambuc 		buf_append(&frame[ptr], len);
316*433d6423SLionel Sambuc 
317*433d6423SLionel Sambuc 		off += sizeof(char *);
318*433d6423SLionel Sambuc 		envp++;
319*433d6423SLionel Sambuc 	}
320*433d6423SLionel Sambuc 
321*433d6423SLionel Sambuc 	put_frame();
322*433d6423SLionel Sambuc }
323*433d6423SLionel Sambuc 
324*433d6423SLionel Sambuc /*===========================================================================*
325*433d6423SLionel Sambuc  *				dump_regions				     *
326*433d6423SLionel Sambuc  *===========================================================================*/
327*433d6423SLionel Sambuc static int dump_regions(int slot)
328*433d6423SLionel Sambuc {
329*433d6423SLionel Sambuc 	/* Print the virtual memory regions of a process.
330*433d6423SLionel Sambuc 	 */
331*433d6423SLionel Sambuc 	struct vm_region_info vri[MAX_VRI_COUNT];
332*433d6423SLionel Sambuc 	vir_bytes next;
333*433d6423SLionel Sambuc 	int i, r, count;
334*433d6423SLionel Sambuc 
335*433d6423SLionel Sambuc 	count = 0;
336*433d6423SLionel Sambuc 	next = 0;
337*433d6423SLionel Sambuc 
338*433d6423SLionel Sambuc 	do {
339*433d6423SLionel Sambuc 		r = vm_info_region(proc[slot].p_endpoint, vri, MAX_VRI_COUNT,
340*433d6423SLionel Sambuc 			&next);
341*433d6423SLionel Sambuc 
342*433d6423SLionel Sambuc 		if (r < 0)
343*433d6423SLionel Sambuc 			return r;
344*433d6423SLionel Sambuc 
345*433d6423SLionel Sambuc 		if (r == 0)
346*433d6423SLionel Sambuc 			break;
347*433d6423SLionel Sambuc 
348*433d6423SLionel Sambuc 		for (i = 0; i < r; i++) {
349*433d6423SLionel Sambuc 			buf_printf("%08lx-%08lx %c%c%c\n",
350*433d6423SLionel Sambuc 				vri[i].vri_addr, vri[i].vri_addr + vri[i].vri_length,
351*433d6423SLionel Sambuc 				(vri[i].vri_prot & PROT_READ) ? 'r' : '-',
352*433d6423SLionel Sambuc 				(vri[i].vri_prot & PROT_WRITE) ? 'w' : '-',
353*433d6423SLionel Sambuc 				(vri[i].vri_prot & PROT_EXEC) ? 'x' : '-');
354*433d6423SLionel Sambuc 
355*433d6423SLionel Sambuc 			count++;
356*433d6423SLionel Sambuc 		}
357*433d6423SLionel Sambuc 	} while (r == MAX_VRI_COUNT);
358*433d6423SLionel Sambuc 
359*433d6423SLionel Sambuc 	return count;
360*433d6423SLionel Sambuc }
361*433d6423SLionel Sambuc 
362*433d6423SLionel Sambuc /*===========================================================================*
363*433d6423SLionel Sambuc  *				pid_map					     *
364*433d6423SLionel Sambuc  *===========================================================================*/
365*433d6423SLionel Sambuc static void pid_map(int slot)
366*433d6423SLionel Sambuc {
367*433d6423SLionel Sambuc 	/* Print a memory map of the process. Obtain the information from VM if
368*433d6423SLionel Sambuc 	 * possible; otherwise fall back on segments from the kernel.
369*433d6423SLionel Sambuc 	 */
370*433d6423SLionel Sambuc 
371*433d6423SLionel Sambuc 	/* Zombies have no memory. */
372*433d6423SLionel Sambuc 	if (is_zombie(slot))
373*433d6423SLionel Sambuc 		return;
374*433d6423SLionel Sambuc 
375*433d6423SLionel Sambuc 	/* Kernel tasks also have no memory. */
376*433d6423SLionel Sambuc 	if (proc[slot].p_nr >= 0) {
377*433d6423SLionel Sambuc 		if (dump_regions(slot) != 0)
378*433d6423SLionel Sambuc 			return;
379*433d6423SLionel Sambuc 	}
380*433d6423SLionel Sambuc }
381