1f1abbce7SDavid van Moolenbroek /* ProcFS - pid.c - generators for PID-specific files */
2433d6423SLionel Sambuc
3433d6423SLionel Sambuc #include "inc.h"
4433d6423SLionel Sambuc
5433d6423SLionel Sambuc #include <sys/mman.h>
6433d6423SLionel Sambuc #include <minix/vm.h>
7433d6423SLionel Sambuc
8433d6423SLionel Sambuc static void pid_psinfo(int slot);
9433d6423SLionel Sambuc static void pid_cmdline(int slot);
10433d6423SLionel Sambuc static void pid_environ(int slot);
11433d6423SLionel Sambuc static void pid_map(int slot);
12433d6423SLionel Sambuc
13f1abbce7SDavid van Moolenbroek /*
14f1abbce7SDavid van Moolenbroek * The files that are dynamically created in each PID directory. The data
15f1abbce7SDavid van Moolenbroek * field contains each file's read function. Subdirectories are not yet
16f1abbce7SDavid van Moolenbroek * supported.
17433d6423SLionel Sambuc */
18433d6423SLionel Sambuc struct file pid_files[] = {
19433d6423SLionel Sambuc { "psinfo", REG_ALL_MODE, (data_t) pid_psinfo },
20433d6423SLionel Sambuc { "cmdline", REG_ALL_MODE, (data_t) pid_cmdline },
21433d6423SLionel Sambuc { "environ", REG_ALL_MODE, (data_t) pid_environ },
22433d6423SLionel Sambuc { "map", REG_ALL_MODE, (data_t) pid_map },
23433d6423SLionel Sambuc { NULL, 0, (data_t) NULL }
24433d6423SLionel Sambuc };
25433d6423SLionel Sambuc
26f1abbce7SDavid van Moolenbroek /*
27f1abbce7SDavid van Moolenbroek * Is the given slot a zombie process?
28433d6423SLionel Sambuc */
29f1abbce7SDavid van Moolenbroek static int
is_zombie(int slot)30f1abbce7SDavid van Moolenbroek is_zombie(int slot)
31f1abbce7SDavid van Moolenbroek {
32433d6423SLionel Sambuc
33433d6423SLionel Sambuc return (slot >= NR_TASKS &&
34*305e366fSDavid van Moolenbroek (proc_list[slot - NR_TASKS].mpl_flags & MPLF_ZOMBIE));
35433d6423SLionel Sambuc }
36433d6423SLionel Sambuc
37f1abbce7SDavid van Moolenbroek /*
38*305e366fSDavid van Moolenbroek * Get MINIX3-specific process data for the process identified by the given
39*305e366fSDavid van Moolenbroek * kernel slot. Return OK or a negative error code.
40*305e366fSDavid van Moolenbroek */
41*305e366fSDavid van Moolenbroek int
get_proc_data(pid_t pid,struct minix_proc_data * mpd)42*305e366fSDavid van Moolenbroek get_proc_data(pid_t pid, struct minix_proc_data * mpd)
43*305e366fSDavid van Moolenbroek {
44*305e366fSDavid van Moolenbroek int mib[4] = { CTL_MINIX, MINIX_PROC, PROC_DATA, pid };
45*305e366fSDavid van Moolenbroek size_t oldlen;
46*305e366fSDavid van Moolenbroek
47*305e366fSDavid van Moolenbroek oldlen = sizeof(*mpd);
48*305e366fSDavid van Moolenbroek if (__sysctl(mib, __arraycount(mib), mpd, &oldlen, NULL, 0) != 0)
49*305e366fSDavid van Moolenbroek return -errno;
50*305e366fSDavid van Moolenbroek
51*305e366fSDavid van Moolenbroek return OK;
52*305e366fSDavid van Moolenbroek }
53*305e366fSDavid van Moolenbroek
54*305e366fSDavid van Moolenbroek /*
55*305e366fSDavid van Moolenbroek * Print process information. This feature is now used only by mtop(1), and as
56*305e366fSDavid van Moolenbroek * a result, we only provide information that mtop(1) actually uses. In the
57*305e366fSDavid van Moolenbroek * future, this file may be extended with additional fields again.
58433d6423SLionel Sambuc */
59f1abbce7SDavid van Moolenbroek static void
pid_psinfo(int slot)60*305e366fSDavid van Moolenbroek pid_psinfo(int slot)
61f1abbce7SDavid van Moolenbroek {
62*305e366fSDavid van Moolenbroek struct minix_proc_data mpd;
63433d6423SLionel Sambuc struct vm_usage_info vui;
64*305e366fSDavid van Moolenbroek pid_t pid;
65*305e366fSDavid van Moolenbroek uid_t uid;
66*305e366fSDavid van Moolenbroek char *p;
67*305e366fSDavid van Moolenbroek int task, type, state;
68433d6423SLionel Sambuc
69*305e366fSDavid van Moolenbroek if ((pid = pid_from_slot(slot)) == 0)
70*305e366fSDavid van Moolenbroek return;
71433d6423SLionel Sambuc
72*305e366fSDavid van Moolenbroek if (get_proc_data(pid, &mpd) != OK)
73*305e366fSDavid van Moolenbroek return;
74*305e366fSDavid van Moolenbroek
75*305e366fSDavid van Moolenbroek task = (slot < NR_TASKS);
76433d6423SLionel Sambuc
77433d6423SLionel Sambuc /* Get the type of the process. */
78433d6423SLionel Sambuc if (task)
79433d6423SLionel Sambuc type = TYPE_TASK;
80*305e366fSDavid van Moolenbroek else if (mpd.mpd_flags & MPDF_SYSTEM)
81433d6423SLionel Sambuc type = TYPE_SYSTEM;
82433d6423SLionel Sambuc else
83433d6423SLionel Sambuc type = TYPE_USER;
84433d6423SLionel Sambuc
85*305e366fSDavid van Moolenbroek /*
86*305e366fSDavid van Moolenbroek * Get the (rudimentary) state of the process. The zombie flag is also
87*305e366fSDavid van Moolenbroek * in the proc_list entry but it just may be set since we obtained that
88*305e366fSDavid van Moolenbroek * entry, in which case we'd end up with the wrong state here.
89433d6423SLionel Sambuc */
90*305e366fSDavid van Moolenbroek if (mpd.mpd_flags & MPDF_ZOMBIE)
91*305e366fSDavid van Moolenbroek state = STATE_ZOMBIE;
92*305e366fSDavid van Moolenbroek else if (mpd.mpd_flags & MPDF_RUNNABLE)
93*305e366fSDavid van Moolenbroek state = STATE_RUN;
94*305e366fSDavid van Moolenbroek else if (mpd.mpd_flags & MPDF_STOPPED)
95*305e366fSDavid van Moolenbroek state = STATE_STOP;
96*305e366fSDavid van Moolenbroek else
97*305e366fSDavid van Moolenbroek state = STATE_SLEEP;
98*305e366fSDavid van Moolenbroek
99*305e366fSDavid van Moolenbroek /* Get the process's effective user ID. */
100*305e366fSDavid van Moolenbroek if (!task)
101*305e366fSDavid van Moolenbroek uid = proc_list[slot - NR_TASKS].mpl_uid;
102*305e366fSDavid van Moolenbroek else
103*305e366fSDavid van Moolenbroek uid = 0;
104*305e366fSDavid van Moolenbroek
105*305e366fSDavid van Moolenbroek /* Get memory usage. We do not care if this fails. */
106*305e366fSDavid van Moolenbroek memset(&vui, 0, sizeof(vui));
107*305e366fSDavid van Moolenbroek if (!(mpd.mpd_flags & MPDF_ZOMBIE))
108*305e366fSDavid van Moolenbroek (void)vm_info_usage(mpd.mpd_endpoint, &vui);
109*305e366fSDavid van Moolenbroek
110*305e366fSDavid van Moolenbroek /* Spaces in the process name would mess up the output format. */
111*305e366fSDavid van Moolenbroek if ((p = strchr(mpd.mpd_name, ' ')) != NULL)
112*305e366fSDavid van Moolenbroek *p = '\0';
113*305e366fSDavid van Moolenbroek
114*305e366fSDavid van Moolenbroek /* Print all the information. */
115*305e366fSDavid van Moolenbroek buf_printf("%d %c %d %s %c %d %d %u %u "
116*305e366fSDavid van Moolenbroek "%"PRIu64" %"PRIu64" %"PRIu64" %lu %d %u\n",
117433d6423SLionel Sambuc PSINFO_VERSION, /* information version */
118433d6423SLionel Sambuc type, /* process type */
119*305e366fSDavid van Moolenbroek mpd.mpd_endpoint, /* process endpoint */
120*305e366fSDavid van Moolenbroek mpd.mpd_name, /* process name */
121433d6423SLionel Sambuc state, /* process state letter */
122*305e366fSDavid van Moolenbroek mpd.mpd_blocked_on, /* endpt blocked on, or NONE */
123*305e366fSDavid van Moolenbroek mpd.mpd_priority, /* process priority */
124*305e366fSDavid van Moolenbroek mpd.mpd_user_time, /* user time */
125*305e366fSDavid van Moolenbroek mpd.mpd_sys_time, /* system time */
126*305e366fSDavid van Moolenbroek mpd.mpd_cycles, /* execution cycles */
127*305e366fSDavid van Moolenbroek mpd.mpd_kipc_cycles, /* kernel IPC cycles */
128*305e366fSDavid van Moolenbroek mpd.mpd_kcall_cycles, /* kernel call cycles */
129433d6423SLionel Sambuc vui.vui_total, /* total memory */
130*305e366fSDavid van Moolenbroek mpd.mpd_nice, /* nice value */
131*305e366fSDavid van Moolenbroek uid /* effective user ID */
132433d6423SLionel Sambuc );
133433d6423SLionel Sambuc }
134433d6423SLionel Sambuc
135f1abbce7SDavid van Moolenbroek /*
136f1abbce7SDavid van Moolenbroek * Dump the process's command line as it is contained in the process itself.
137f1abbce7SDavid van Moolenbroek * Each argument is terminated with a null character.
138433d6423SLionel Sambuc */
139f1abbce7SDavid van Moolenbroek static void
pid_cmdline(int slot)140f1abbce7SDavid van Moolenbroek pid_cmdline(int slot)
141f1abbce7SDavid van Moolenbroek {
142*305e366fSDavid van Moolenbroek char buf[BUF_SIZE];
143*305e366fSDavid van Moolenbroek int mib[] = { CTL_KERN, KERN_PROC_ARGS, 0, KERN_PROC_ARGV };
144*305e366fSDavid van Moolenbroek size_t oldlen;
145*305e366fSDavid van Moolenbroek pid_t pid;
146433d6423SLionel Sambuc
147*305e366fSDavid van Moolenbroek /* Kernel tasks and zombies have no memory. */
148*305e366fSDavid van Moolenbroek if ((pid = pid_from_slot(slot)) <= 0 || is_zombie(slot))
149433d6423SLionel Sambuc return;
150433d6423SLionel Sambuc
151*305e366fSDavid van Moolenbroek mib[2] = proc_list[slot - NR_TASKS].mpl_pid;
152433d6423SLionel Sambuc
153*305e366fSDavid van Moolenbroek /* TODO: zero-copy into the main output buffer */
154*305e366fSDavid van Moolenbroek oldlen = sizeof(buf);
155433d6423SLionel Sambuc
156*305e366fSDavid van Moolenbroek if (__sysctl(mib, __arraycount(mib), buf, &oldlen, NULL, 0) != 0)
157*305e366fSDavid van Moolenbroek return;
158433d6423SLionel Sambuc
159*305e366fSDavid van Moolenbroek buf_append(buf, oldlen);
160433d6423SLionel Sambuc }
161433d6423SLionel Sambuc
162f1abbce7SDavid van Moolenbroek /*
163f1abbce7SDavid van Moolenbroek * Dump the process's initial environment as it is contained in the process
164f1abbce7SDavid van Moolenbroek * itself. Each entry is terminated with a null character.
165433d6423SLionel Sambuc */
166f1abbce7SDavid van Moolenbroek static void
pid_environ(int slot)167f1abbce7SDavid van Moolenbroek pid_environ(int slot)
168f1abbce7SDavid van Moolenbroek {
169*305e366fSDavid van Moolenbroek char buf[BUF_SIZE];
170*305e366fSDavid van Moolenbroek int mib[] = { CTL_KERN, KERN_PROC_ARGS, 0, KERN_PROC_ENV };
171*305e366fSDavid van Moolenbroek size_t oldlen;
172*305e366fSDavid van Moolenbroek pid_t pid;
173433d6423SLionel Sambuc
174*305e366fSDavid van Moolenbroek /* Kernel tasks and zombies have no memory. */
175*305e366fSDavid van Moolenbroek if ((pid = pid_from_slot(slot)) <= 0 || is_zombie(slot))
176433d6423SLionel Sambuc return;
177433d6423SLionel Sambuc
178*305e366fSDavid van Moolenbroek mib[2] = proc_list[slot - NR_TASKS].mpl_pid;
179433d6423SLionel Sambuc
180*305e366fSDavid van Moolenbroek /* TODO: zero-copy into the main output buffer */
181*305e366fSDavid van Moolenbroek oldlen = sizeof(buf);
182433d6423SLionel Sambuc
183*305e366fSDavid van Moolenbroek if (__sysctl(mib, __arraycount(mib), buf, &oldlen, NULL, 0) != 0)
184*305e366fSDavid van Moolenbroek return;
185433d6423SLionel Sambuc
186*305e366fSDavid van Moolenbroek buf_append(buf, oldlen);
187433d6423SLionel Sambuc }
188433d6423SLionel Sambuc
189f1abbce7SDavid van Moolenbroek /*
190f1abbce7SDavid van Moolenbroek * Print the virtual memory regions of a process.
191433d6423SLionel Sambuc */
192f1abbce7SDavid van Moolenbroek static void
pid_map(int slot)193*305e366fSDavid van Moolenbroek pid_map(int slot)
194f1abbce7SDavid van Moolenbroek {
195*305e366fSDavid van Moolenbroek struct minix_proc_data mpd;
196433d6423SLionel Sambuc struct vm_region_info vri[MAX_VRI_COUNT];
197433d6423SLionel Sambuc vir_bytes next;
198*305e366fSDavid van Moolenbroek pid_t pid;
199433d6423SLionel Sambuc int i, r, count;
200433d6423SLionel Sambuc
201*305e366fSDavid van Moolenbroek /* Kernel tasks and zombies have no memory. */
202*305e366fSDavid van Moolenbroek if ((pid = pid_from_slot(slot)) <= 0 || is_zombie(slot))
203*305e366fSDavid van Moolenbroek return;
204*305e366fSDavid van Moolenbroek
205*305e366fSDavid van Moolenbroek /* Get the process endpoint. */
206*305e366fSDavid van Moolenbroek if (get_proc_data(pid, &mpd) != OK)
207*305e366fSDavid van Moolenbroek return;
208*305e366fSDavid van Moolenbroek
209433d6423SLionel Sambuc count = 0;
210433d6423SLionel Sambuc next = 0;
211433d6423SLionel Sambuc
212433d6423SLionel Sambuc do {
213*305e366fSDavid van Moolenbroek r = vm_info_region(mpd.mpd_endpoint, vri, MAX_VRI_COUNT,
214433d6423SLionel Sambuc &next);
215433d6423SLionel Sambuc
216f1abbce7SDavid van Moolenbroek if (r <= 0)
217433d6423SLionel Sambuc break;
218433d6423SLionel Sambuc
219433d6423SLionel Sambuc for (i = 0; i < r; i++) {
220433d6423SLionel Sambuc buf_printf("%08lx-%08lx %c%c%c\n",
221f1abbce7SDavid van Moolenbroek vri[i].vri_addr,
222f1abbce7SDavid van Moolenbroek vri[i].vri_addr + vri[i].vri_length,
223433d6423SLionel Sambuc (vri[i].vri_prot & PROT_READ) ? 'r' : '-',
224433d6423SLionel Sambuc (vri[i].vri_prot & PROT_WRITE) ? 'w' : '-',
225433d6423SLionel Sambuc (vri[i].vri_prot & PROT_EXEC) ? 'x' : '-');
226433d6423SLionel Sambuc
227433d6423SLionel Sambuc count++;
228433d6423SLionel Sambuc }
229433d6423SLionel Sambuc } while (r == MAX_VRI_COUNT);
230433d6423SLionel Sambuc }
231