This source file includes following definitions.
- read_core
- get_loadavg
- get_uptime
- get_meminfo
- get_version
- get_task
- get_phys_addr
- get_array
- get_env
- get_arg
- get_wchan
- get_stat
- get_statm
- get_maps
- array_read
1
2
3
4
5
6
7
8
9
10 #include <linux/types.h>
11 #include <linux/errno.h>
12 #include <linux/sched.h>
13 #include <linux/kernel.h>
14 #include <linux/tty.h>
15 #include <linux/user.h>
16 #include <linux/a.out.h>
17 #include <linux/string.h>
18 #include <linux/mman.h>
19
20 #include <asm/segment.h>
21 #include <asm/io.h>
22
23 #define LOAD_INT(x) ((x) >> FSHIFT)
24 #define LOAD_FRAC(x) LOAD_INT(((x) & (FIXED_1-1)) * 100)
25
26 #ifdef CONFIG_DEBUG_MALLOC
27 int get_malloc(char * buffer);
28 #endif
29
30 static int read_core(struct inode * inode, struct file * file,char * buf, int count)
31 {
32 unsigned long p = file->f_pos;
33 int read;
34 int count1;
35 char * pnt;
36 struct user dump;
37
38 memset(&dump, 0, sizeof(struct user));
39 dump.magic = CMAGIC;
40 dump.u_dsize = high_memory >> 12;
41
42 if (count < 0)
43 return -EINVAL;
44 if (p >= high_memory)
45 return 0;
46 if (count > high_memory - p)
47 count = high_memory - p;
48 read = 0;
49
50 if (p < sizeof(struct user) && count > 0) {
51 count1 = count;
52 if (p + count1 > sizeof(struct user))
53 count1 = sizeof(struct user)-p;
54 pnt = (char *) &dump + p;
55 memcpy_tofs(buf,(void *) pnt, count1);
56 buf += count1;
57 p += count1;
58 count -= count1;
59 read += count1;
60 }
61
62 while (p < 2*PAGE_SIZE && count > 0) {
63 put_fs_byte(0,buf);
64 buf++;
65 p++;
66 count--;
67 read++;
68 }
69 memcpy_tofs(buf,(void *) (p - PAGE_SIZE),count);
70 read += count;
71 file->f_pos += read;
72 return read;
73 }
74
75 static int get_loadavg(char * buffer)
76 {
77 int a, b, c;
78
79 a = avenrun[0] + (FIXED_1/200);
80 b = avenrun[1] + (FIXED_1/200);
81 c = avenrun[2] + (FIXED_1/200);
82 return sprintf(buffer,"%d.%02d %d.%02d %d.%02d\n",
83 LOAD_INT(a), LOAD_FRAC(a),
84 LOAD_INT(b), LOAD_FRAC(b),
85 LOAD_INT(c), LOAD_FRAC(c));
86 }
87
88 static int get_uptime(char * buffer)
89 {
90 unsigned long uptime;
91 unsigned long idle;
92
93 uptime = jiffies;
94 idle = task[0]->utime + task[0]->stime;
95 return sprintf(buffer,"%lu.%02lu %lu.%02lu\n",
96 uptime / HZ,
97 uptime % HZ,
98 idle / HZ,
99 idle % HZ);
100 }
101
102 static int get_meminfo(char * buffer)
103 {
104 struct sysinfo i;
105
106 si_meminfo(&i);
107 si_swapinfo(&i);
108 return sprintf(buffer, " total: used: free: shared: buffers:\n"
109 "Mem: %8lu %8lu %8lu %8lu %8lu\n"
110 "Swap: %8lu %8lu %8lu\n",
111 i.totalram, i.totalram-i.freeram, i.freeram, i.sharedram, i.bufferram,
112 i.totalswap, i.totalswap-i.freeswap, i.freeswap);
113 }
114
115 static int get_version(char * buffer)
116 {
117 extern char *linux_banner;
118
119 strcpy(buffer, linux_banner);
120 return strlen(buffer);
121 }
122
123 static struct task_struct ** get_task(pid_t pid)
124 {
125 struct task_struct ** p;
126
127 p = task;
128 while (++p < task+NR_TASKS) {
129 if (*p && (*p)->pid == pid)
130 return p;
131 }
132 return NULL;
133 }
134
135 static unsigned long get_phys_addr(struct task_struct ** p, unsigned long ptr)
136 {
137 unsigned long page;
138
139 if (!p || !*p || ptr >= TASK_SIZE)
140 return 0;
141 page = *PAGE_DIR_OFFSET((*p)->tss.cr3,ptr);
142 if (!(page & 1))
143 return 0;
144 page &= PAGE_MASK;
145 page += PAGE_PTR(ptr);
146 page = *(unsigned long *) page;
147 if (!(page & 1))
148 return 0;
149 page &= PAGE_MASK;
150 page += ptr & ~PAGE_MASK;
151 return page;
152 }
153
154 static int get_array(struct task_struct ** p, unsigned long start, unsigned long end, char * buffer)
155 {
156 unsigned long addr;
157 int size = 0, result = 0;
158 char c;
159
160 if (start >= end)
161 return result;
162 for (;;) {
163 addr = get_phys_addr(p, start);
164 if (!addr)
165 return result;
166 do {
167 c = *(char *) addr;
168 if (!c)
169 result = size;
170 if (size < PAGE_SIZE)
171 buffer[size++] = c;
172 else
173 return result;
174 addr++;
175 start++;
176 if (start >= end)
177 return result;
178 } while (!(addr & ~PAGE_MASK));
179 }
180 }
181
182 static int get_env(int pid, char * buffer)
183 {
184 struct task_struct ** p = get_task(pid);
185
186 if (!p || !*p)
187 return 0;
188 return get_array(p, (*p)->env_start, (*p)->env_end, buffer);
189 }
190
191 static int get_arg(int pid, char * buffer)
192 {
193 struct task_struct ** p = get_task(pid);
194
195 if (!p || !*p)
196 return 0;
197 return get_array(p, (*p)->arg_start, (*p)->arg_end, buffer);
198 }
199
200 static unsigned long get_wchan(struct task_struct *p)
201 {
202 unsigned long ebp, eip;
203 unsigned long stack_page;
204 int count = 0;
205
206 if (!p || p == current || p->state == TASK_RUNNING)
207 return 0;
208 stack_page = p->kernel_stack_page;
209 if (!stack_page)
210 return 0;
211 ebp = p->tss.ebp;
212 do {
213 if (ebp < stack_page || ebp >= 4092+stack_page)
214 return 0;
215 eip = *(unsigned long *) (ebp+4);
216 if ((void *)eip != sleep_on &&
217 (void *)eip != interruptible_sleep_on)
218 return eip;
219 ebp = *(unsigned long *) ebp;
220 } while (count++ < 16);
221 return 0;
222 }
223
224 #define KSTK_EIP(stack) (((unsigned long *)stack)[1019])
225 #define KSTK_ESP(stack) (((unsigned long *)stack)[1022])
226
227 static int get_stat(int pid, char * buffer)
228 {
229 struct task_struct ** p = get_task(pid);
230 unsigned long sigignore=0, sigcatch=0, bit=1, wchan;
231 unsigned long vsize, eip, esp;
232 int i,tty_pgrp;
233 char state;
234
235 if (!p || !*p)
236 return 0;
237 if ((*p)->state < 0 || (*p)->state > 5)
238 state = '.';
239 else
240 state = "RSDZTD"[(*p)->state];
241 eip = esp = 0;
242 vsize = (*p)->kernel_stack_page;
243 if (vsize) {
244 eip = KSTK_EIP(vsize);
245 esp = KSTK_ESP(vsize);
246 vsize = (*p)->brk - (*p)->start_code + PAGE_SIZE-1;
247 if (esp)
248 vsize += TASK_SIZE - esp;
249 }
250 wchan = get_wchan(*p);
251 for(i=0; i<32; ++i) {
252 switch((int) (*p)->sigaction[i].sa_handler) {
253 case 1: sigignore |= bit; break;
254 case 0: break;
255 default: sigcatch |= bit;
256 } bit <<= 1;
257 }
258 tty_pgrp = (*p)->tty;
259 if (tty_pgrp > 0 && tty_table[tty_pgrp])
260 tty_pgrp = tty_table[tty_pgrp]->pgrp;
261 else
262 tty_pgrp = -1;
263 return sprintf(buffer,"%d (%s) %c %d %d %d %d %d %lu %lu \
264 %lu %lu %lu %ld %ld %ld %ld %ld %ld %lu %lu %ld %lu %u %u %lu %lu %lu %lu %lu %lu \
265 %lu %lu %lu %lu\n",
266 pid,
267 (*p)->comm,
268 state,
269 (*p)->p_pptr->pid,
270 (*p)->pgrp,
271 (*p)->session,
272 (*p)->tty,
273 tty_pgrp,
274 (*p)->flags,
275 (*p)->min_flt,
276 (*p)->cmin_flt,
277 (*p)->maj_flt,
278 (*p)->cmaj_flt,
279 (*p)->utime,
280 (*p)->stime,
281 (*p)->cutime,
282 (*p)->cstime,
283 (*p)->counter,
284
285 (*p)->priority,
286
287 (*p)->timeout,
288 (*p)->it_real_value,
289 (*p)->start_time,
290 vsize,
291 (*p)->rss,
292 (*p)->rlim[RLIMIT_RSS].rlim_cur,
293 (*p)->start_code,
294 (*p)->end_code,
295 (*p)->start_stack,
296 esp,
297 eip,
298 (*p)->signal,
299 (*p)->blocked,
300 sigignore,
301 sigcatch,
302 wchan);
303 }
304
305 static int get_statm(int pid, char * buffer)
306 {
307 struct task_struct ** p = get_task(pid);
308 int i, tpag;
309 int size=0, resident=0, share=0, trs=0, lrs=0, drs=0, dt=0;
310 unsigned long ptbl, *buf, *pte, *pagedir, map_nr;
311
312 if (!p || !*p)
313 return 0;
314 tpag = (*p)->end_code / PAGE_SIZE;
315 if ((*p)->state != TASK_ZOMBIE) {
316 pagedir = (unsigned long *) (*p)->tss.cr3;
317 for (i = 0; i < 0x300; ++i) {
318 if ((ptbl = pagedir[i]) == 0) {
319 tpag -= PTRS_PER_PAGE;
320 continue;
321 }
322 buf = (unsigned long *)(ptbl & PAGE_MASK);
323 for (pte = buf; pte < (buf + PTRS_PER_PAGE); ++pte) {
324 if (*pte != 0) {
325 ++size;
326 if (*pte & 1) {
327 ++resident;
328 if (tpag > 0)
329 ++trs;
330 else
331 ++drs;
332 if (i >= 15 && i < 0x2f0) {
333 ++lrs;
334 if (*pte & 0x40)
335 ++dt;
336 else
337 --drs;
338 }
339 map_nr = MAP_NR(*pte);
340 if (map_nr < (high_memory / PAGE_SIZE) && mem_map[map_nr] > 1)
341 ++share;
342 }
343 }
344 --tpag;
345 }
346 }
347 }
348 return sprintf(buffer,"%d %d %d %d %d %d %d\n",
349 size, resident, share, trs, lrs, drs, dt);
350 }
351
352 static int get_maps(int pid, char *buf)
353 {
354 int sz = 0;
355 struct task_struct **p = get_task(pid);
356 struct vm_area_struct *map;
357
358 if (!p || !*p)
359 return 0;
360
361 for(map = (*p)->mmap; map != NULL; map = map->vm_next) {
362 char str[7], *cp = str;
363 int prot = map->vm_page_prot;
364 int perms, flags;
365 int end = sz + 80;
366 dev_t dev;
367 unsigned long ino;
368
369
370
371
372
373
374
375 flags = perms = 0;
376
377 if ((prot & PAGE_READONLY) == PAGE_READONLY)
378 perms |= PROT_READ | PROT_EXEC;
379 if (prot & (PAGE_COW|PAGE_RW)) {
380 perms |= PROT_WRITE | PROT_READ;
381 flags = prot & PAGE_COW ? MAP_PRIVATE : MAP_SHARED;
382 }
383
384 *cp++ = perms & PROT_READ ? 'r' : '-';
385 *cp++ = perms & PROT_WRITE ? 'w' : '-';
386 *cp++ = perms & PROT_EXEC ? 'x' : '-';
387 *cp++ = flags & MAP_SHARED ? 's' : '-';
388 *cp++ = flags & MAP_PRIVATE ? 'p' : '-';
389 *cp++ = 0;
390
391 if (end >= PAGE_SIZE) {
392 sprintf(buf+sz, "...\n");
393 break;
394 }
395
396 if (map->vm_inode != NULL) {
397 dev = map->vm_inode->i_dev;
398 ino = map->vm_inode->i_ino;
399 } else {
400 dev = 0;
401 ino = 0;
402 }
403
404 sz += sprintf(buf+sz, "%08lx-%08lx %s %08lx %02x:%02x %lu\n",
405 map->vm_start, map->vm_end, str, map->vm_offset,
406 MAJOR(dev),MINOR(dev), ino);
407 if (sz > end) {
408 printk("get_maps: end(%d) < sz(%d)\n", end, sz);
409 break;
410 }
411 }
412
413 return sz;
414 }
415
416 asmlinkage int get_module_list( char *);
417
418 static int array_read(struct inode * inode, struct file * file,char * buf, int count)
419 {
420 char * page;
421 int length;
422 int end;
423 unsigned int type, pid;
424
425 if (count < 0)
426 return -EINVAL;
427 if (!(page = (char*) __get_free_page(GFP_KERNEL)))
428 return -ENOMEM;
429 type = inode->i_ino;
430 pid = type >> 16;
431 type &= 0x0000ffff;
432 switch (type) {
433 case 2:
434 length = get_loadavg(page);
435 break;
436 case 3:
437 length = get_uptime(page);
438 break;
439 case 4:
440 length = get_meminfo(page);
441 break;
442 case 6:
443 length = get_version(page);
444 break;
445 case 9:
446 length = get_env(pid, page);
447 break;
448 case 10:
449 length = get_arg(pid, page);
450 break;
451 case 11:
452 length = get_stat(pid, page);
453 break;
454 case 12:
455 length = get_statm(pid, page);
456 break;
457 #ifdef CONFIG_DEBUG_MALLOC
458 case 13:
459 length = get_malloc(page);
460 break;
461 #endif
462 case 14:
463 free_page((unsigned long) page);
464 return read_core(inode, file, buf, count);
465 case 15:
466 length = get_maps(pid, page);
467 break;
468 case 16:
469 length = get_module_list(page);
470 break;
471 default:
472 free_page((unsigned long) page);
473 return -EBADF;
474 }
475 if (file->f_pos >= length) {
476 free_page((unsigned long) page);
477 return 0;
478 }
479 if (count + file->f_pos > length)
480 count = length - file->f_pos;
481 end = count + file->f_pos;
482 memcpy_tofs(buf, page + file->f_pos, count);
483 free_page((unsigned long) page);
484 file->f_pos = end;
485 return count;
486 }
487
488 static struct file_operations proc_array_operations = {
489 NULL,
490 array_read,
491 NULL,
492 NULL,
493 NULL,
494 NULL,
495 NULL,
496 NULL,
497 NULL,
498 NULL
499 };
500
501 struct inode_operations proc_array_inode_operations = {
502 &proc_array_operations,
503 NULL,
504 NULL,
505 NULL,
506 NULL,
507 NULL,
508 NULL,
509 NULL,
510 NULL,
511 NULL,
512 NULL,
513 NULL,
514 NULL,
515 NULL,
516 NULL
517 };