blob: cee1b52c18e492d66725d65ec1042dbbf51323b4 [file] [log] [blame]
Eric Andersen420b2082002-09-17 22:14:58 +00001/*
2 * A tiny 'top' utility.
3 *
Eric Andersen08a72202002-09-30 20:52:10 +00004 * This is written specifically for the linux /proc/<PID>/stat(m)
5 * files format.
6
7 * This reads the PIDs of all processes and their status and shows
8 * the status of processes (first ones that fit to screen) at given
9 * intervals.
Eric Andersen420b2082002-09-17 22:14:58 +000010 *
11 * NOTES:
12 * - At startup this changes to /proc, all the reads are then
13 * relative to that.
Eric Andersen420b2082002-09-17 22:14:58 +000014 *
15 * (C) Eero Tamminen <oak at welho dot com>
Eric Andersen08a72202002-09-30 20:52:10 +000016 *
17 * Rewroted by Vladimir Oleynik (C) 2002 <dzo@simtreas.ru>
Eric Andersen420b2082002-09-17 22:14:58 +000018 */
Eric Andersen08a72202002-09-30 20:52:10 +000019
20/* Original code Copyrights */
21/*
22 * Copyright (c) 1992 Branko Lankester
23 * Copyright (c) 1992 Roger Binns
24 * Copyright (C) 1994-1996 Charles L. Blake.
25 * Copyright (C) 1992-1998 Michael K. Johnson
26 * May be distributed under the conditions of the
27 * GNU Library General Public License
28 */
29
30#include <sys/types.h>
Eric Andersen420b2082002-09-17 22:14:58 +000031#include <stdio.h>
32#include <stdlib.h>
33#include <unistd.h>
Eric Andersen420b2082002-09-17 22:14:58 +000034#include <string.h>
35#include <sys/ioctl.h>
Eric Andersen08a72202002-09-30 20:52:10 +000036/* get page info */
37#include <asm/page.h>
Eric Andersen420b2082002-09-17 22:14:58 +000038#include "busybox.h"
39
Eric Andersen08a72202002-09-30 20:52:10 +000040//#define FEATURE_CPU_USAGE_PERCENTAGE /* + 2k */
Eric Andersen420b2082002-09-17 22:14:58 +000041
Eric Andersen08a72202002-09-30 20:52:10 +000042#ifdef FEATURE_CPU_USAGE_PERCENTAGE
43#include <time.h>
44#include <sys/time.h>
45#include <fcntl.h>
46#include <netinet/in.h> /* htons */
47#endif
48
49
Eric Andersen44608e92002-10-22 12:21:15 +000050typedef int (*cmp_t)(procps_status_t *P, procps_status_t *Q);
Eric Andersen08a72202002-09-30 20:52:10 +000051
Eric Andersen44608e92002-10-22 12:21:15 +000052static procps_status_t *top; /* Hehe */
Eric Andersen08a72202002-09-30 20:52:10 +000053static int ntop;
54
55
Eric Andersen44608e92002-10-22 12:21:15 +000056static int pid_sort (procps_status_t *P, procps_status_t *Q)
Eric Andersen08a72202002-09-30 20:52:10 +000057{
58 int p = P->pid;
59 int q = Q->pid;
60
61 if( p < q ) return -1;
62 if( p > q ) return 1;
63 return 0;
64}
65
Eric Andersen44608e92002-10-22 12:21:15 +000066static int mem_sort (procps_status_t *P, procps_status_t *Q)
Eric Andersen08a72202002-09-30 20:52:10 +000067{
68 long p = P->rss;
69 long q = Q->rss;
70
71 if( p > q ) return -1;
72 if( p < q ) return 1;
73 return 0;
74}
75
76#ifdef FEATURE_CPU_USAGE_PERCENTAGE
77
78#define sort_depth 3
79static cmp_t sort_function[sort_depth];
80
Eric Andersen44608e92002-10-22 12:21:15 +000081static int pcpu_sort (procps_status_t *P, procps_status_t *Q)
Eric Andersen08a72202002-09-30 20:52:10 +000082{
83 int p = P->pcpu;
84 int q = Q->pcpu;
85
86 if( p > q ) return -1;
87 if( p < q ) return 1;
88 return 0;
89}
90
Eric Andersen44608e92002-10-22 12:21:15 +000091static int time_sort (procps_status_t *P, procps_status_t *Q)
Eric Andersen08a72202002-09-30 20:52:10 +000092{
93 long p = P->stime;
94 long q = Q->stime;
95
96 p += P->utime;
97 q += Q->utime;
98 if( p > q ) return -1;
99 if( p < q ) return 1;
100 return 0;
101}
102
103int mult_lvl_cmp(void* a, void* b) {
104 int i, cmp_val;
105
106 for(i = 0; i < sort_depth; i++) {
107 cmp_val = (*sort_function[i])(a, b);
108 if (cmp_val != 0)
109 return cmp_val;
110 }
111 return 0;
112}
113
114/* This structure stores some critical information from one frame to
115 the next. mostly used for sorting. Added cumulative and resident fields. */
116struct save_hist {
117 int ticks;
118 int pid;
119 int utime;
120 int stime;
121};
122
123/*
124 * Calculates percent cpu usage for each task.
125 */
126
127static struct save_hist *save_history;
128
129static unsigned long Hertz;
130
131/***********************************************************************
132 * Some values in /proc are expressed in units of 1/HZ seconds, where HZ
133 * is the kernel clock tick rate. One of these units is called a jiffy.
134 * The HZ value used in the kernel may vary according to hacker desire.
135 * According to Linus Torvalds, this is not true. He considers the values
136 * in /proc as being in architecture-dependant units that have no relation
137 * to the kernel clock tick rate. Examination of the kernel source code
138 * reveals that opinion as wishful thinking.
139 *
140 * In any case, we need the HZ constant as used in /proc. (the real HZ value
141 * may differ, but we don't care) There are several ways we could get HZ:
142 *
143 * 1. Include the kernel header file. If it changes, recompile this library.
144 * 2. Use the sysconf() function. When HZ changes, recompile the C library!
145 * 3. Ask the kernel. This is obviously correct...
146 *
147 * Linus Torvalds won't let us ask the kernel, because he thinks we should
148 * not know the HZ value. Oh well, we don't have to listen to him.
149 * Someone smuggled out the HZ value. :-)
150 *
151 * This code should work fine, even if Linus fixes the kernel to match his
152 * stated behavior. The code only fails in case of a partial conversion.
153 *
154 */
155
156#define FILE_TO_BUF(filename, fd) do{ \
157 if (fd == -1 && (fd = open(filename, O_RDONLY)) == -1) { \
Manuel Novoa III cad53642003-03-19 09:13:01 +0000158 bb_perror_msg_and_die("/proc not be mounted?"); \
Eric Andersen08a72202002-09-30 20:52:10 +0000159 } \
160 lseek(fd, 0L, SEEK_SET); \
161 if ((local_n = read(fd, buf, sizeof buf - 1)) < 0) { \
Manuel Novoa III cad53642003-03-19 09:13:01 +0000162 bb_perror_msg_and_die("%s", filename); \
Eric Andersen08a72202002-09-30 20:52:10 +0000163 } \
164 buf[local_n] = '\0'; \
165}while(0)
166
167#define FILE_TO_BUF2(filename, fd) do{ \
168 lseek(fd, 0L, SEEK_SET); \
169 if ((local_n = read(fd, buf, sizeof buf - 1)) < 0) { \
Manuel Novoa III cad53642003-03-19 09:13:01 +0000170 bb_perror_msg_and_die("%s", filename); \
Eric Andersen08a72202002-09-30 20:52:10 +0000171 } \
172 buf[local_n] = '\0'; \
173}while(0)
174
175static void init_Hertz_value(void) {
176 unsigned long user_j, nice_j, sys_j, other_j; /* jiffies (clock ticks) */
177 double up_1, up_2, seconds;
178 unsigned long jiffies, h;
179 char buf[80];
180 int uptime_fd = -1;
181 int stat_fd = -1;
182
183 long smp_num_cpus = sysconf(_SC_NPROCESSORS_CONF);
184
185 if(smp_num_cpus<1) smp_num_cpus=1;
186 do {
187 int local_n;
188
189 FILE_TO_BUF("uptime", uptime_fd);
190 up_1 = strtod(buf, 0);
191 FILE_TO_BUF("stat", stat_fd);
192 sscanf(buf, "cpu %lu %lu %lu %lu", &user_j, &nice_j, &sys_j, &other_j);
193 FILE_TO_BUF2("uptime", uptime_fd);
194 up_2 = strtod(buf, 0);
195 } while((long)( (up_2-up_1)*1000.0/up_1 )); /* want under 0.1% error */
196
197 close(uptime_fd);
198 close(stat_fd);
199
200 jiffies = user_j + nice_j + sys_j + other_j;
201 seconds = (up_1 + up_2) / 2;
202 h = (unsigned long)( (double)jiffies/seconds/smp_num_cpus );
203 /* actual values used by 2.4 kernels: 32 64 100 128 1000 1024 1200 */
204 switch(h){
205 case 30 ... 34 : Hertz = 32; break; /* ia64 emulator */
206 case 48 ... 52 : Hertz = 50; break;
207 case 58 ... 62 : Hertz = 60; break;
208 case 63 ... 65 : Hertz = 64; break; /* StrongARM /Shark */
209 case 95 ... 105 : Hertz = 100; break; /* normal Linux */
210 case 124 ... 132 : Hertz = 128; break; /* MIPS, ARM */
211 case 195 ... 204 : Hertz = 200; break; /* normal << 1 */
212 case 253 ... 260 : Hertz = 256; break;
213 case 295 ... 304 : Hertz = 300; break; /* 3 cpus */
214 case 393 ... 408 : Hertz = 400; break; /* normal << 2 */
215 case 495 ... 504 : Hertz = 500; break; /* 5 cpus */
216 case 595 ... 604 : Hertz = 600; break; /* 6 cpus */
217 case 695 ... 704 : Hertz = 700; break; /* 7 cpus */
218 case 790 ... 808 : Hertz = 800; break; /* normal << 3 */
219 case 895 ... 904 : Hertz = 900; break; /* 9 cpus */
220 case 990 ... 1010 : Hertz = 1000; break; /* ARM */
221 case 1015 ... 1035 : Hertz = 1024; break; /* Alpha, ia64 */
222 case 1095 ... 1104 : Hertz = 1100; break; /* 11 cpus */
223 case 1180 ... 1220 : Hertz = 1200; break; /* Alpha */
224 default:
225 /* If 32-bit or big-endian (not Alpha or ia64), assume HZ is 100. */
226 Hertz = (sizeof(long)==sizeof(int) || htons(999)==999) ? 100UL : 1024UL;
227 }
228}
229
230static void do_stats(void)
231{
232 struct timeval t;
233 static struct timeval oldtime;
234 struct timezone timez;
235 float elapsed_time;
236
Eric Andersen44608e92002-10-22 12:21:15 +0000237 procps_status_t *cur;
Eric Andersen08a72202002-09-30 20:52:10 +0000238 int total_time, i, n;
239 static int prev_count;
240 int systime, usrtime, pid;
241
242 struct save_hist *New_save_hist;
243
244 /*
245 * Finds the current time (in microseconds) and calculates the time
246 * elapsed since the last update.
247 */
248 gettimeofday(&t, &timez);
249 elapsed_time = (t.tv_sec - oldtime.tv_sec)
250 + (float) (t.tv_usec - oldtime.tv_usec) / 1000000.0;
251 oldtime.tv_sec = t.tv_sec;
252 oldtime.tv_usec = t.tv_usec;
253
254 New_save_hist = alloca(sizeof(struct save_hist)*ntop);
255 /*
256 * Make a pass through the data to get stats.
257 */
258 for(n = 0; n < ntop; n++) {
259 cur = top + n;
260
261 /*
262 * Calculate time in cur process. Time is sum of user time
263 * (usrtime) plus system time (systime).
264 */
265 systime = cur->stime;
266 usrtime = cur->utime;
267 pid = cur->pid;
268 total_time = systime + usrtime;
269 New_save_hist[n].ticks = total_time;
270 New_save_hist[n].pid = pid;
271 New_save_hist[n].stime = systime;
272 New_save_hist[n].utime = usrtime;
273
274 /* find matching entry from previous pass */
275 for (i = 0; i < prev_count; i++) {
276 if (save_history[i].pid == pid) {
277 total_time -= save_history[i].ticks;
278 systime -= save_history[i].stime;
279 usrtime -= save_history[i].utime;
280 break;
281 }
282 }
283
284 /*
285 * Calculate percent cpu time for cur task.
286 */
287 i = (total_time * 10 * 100/Hertz) / elapsed_time;
288 if (i > 999)
289 i = 999;
290 cur->pcpu = i;
291
292 }
293
294 /*
295 * Save cur frame's information.
296 */
297 free(save_history);
298 save_history = memcpy(xmalloc(sizeof(struct save_hist)*n), New_save_hist,
299 sizeof(struct save_hist)*n);
300 prev_count = n;
Eric Andersen44608e92002-10-22 12:21:15 +0000301 qsort(top, n, sizeof(procps_status_t), (void*)mult_lvl_cmp);
Eric Andersen08a72202002-09-30 20:52:10 +0000302}
303#else
304static cmp_t sort_function;
305#endif /* FEATURE_CPU_USAGE_PERCENTAGE */
306
Eric Andersen420b2082002-09-17 22:14:58 +0000307/* display generic info (meminfo / loadavg) */
Eric Andersen08a72202002-09-30 20:52:10 +0000308static unsigned long display_generic(void)
Eric Andersen420b2082002-09-17 22:14:58 +0000309{
310 FILE *fp;
311 char buf[80];
312 float avg1, avg2, avg3;
313 unsigned long total, used, mfree, shared, buffers, cached;
314
315 /* read memory info */
Manuel Novoa III cad53642003-03-19 09:13:01 +0000316 fp = bb_xfopen("meminfo", "r");
Eric Andersen420b2082002-09-17 22:14:58 +0000317 fgets(buf, sizeof(buf), fp); /* skip first line */
318
319 if (fscanf(fp, "Mem: %lu %lu %lu %lu %lu %lu",
320 &total, &used, &mfree, &shared, &buffers, &cached) != 6) {
Manuel Novoa III cad53642003-03-19 09:13:01 +0000321 bb_error_msg_and_die("failed to read '%s'", "meminfo");
Eric Andersen420b2082002-09-17 22:14:58 +0000322 }
323 fclose(fp);
324
325 /* read load average */
Manuel Novoa III cad53642003-03-19 09:13:01 +0000326 fp = bb_xfopen("loadavg", "r");
Eric Andersen420b2082002-09-17 22:14:58 +0000327 if (fscanf(fp, "%f %f %f", &avg1, &avg2, &avg3) != 3) {
Manuel Novoa III cad53642003-03-19 09:13:01 +0000328 bb_error_msg_and_die("failed to read '%s'", "loadavg");
Eric Andersen420b2082002-09-17 22:14:58 +0000329 }
330 fclose(fp);
331
332 /* convert to kilobytes */
Eric Andersen08a72202002-09-30 20:52:10 +0000333 used /= 1024;
334 mfree /= 1024;
335 shared /= 1024;
336 buffers /= 1024;
337 cached /= 1024;
Eric Andersen420b2082002-09-17 22:14:58 +0000338
339 /* output memory info and load average */
Eric Andersen08a72202002-09-30 20:52:10 +0000340 /* clear screen & go to top */
341 printf("\e[H\e[J" "Mem: "
342 "%ldK used, %ldK free, %ldK shrd, %ldK buff, %ldK cached\n",
343 used, mfree, shared, buffers, cached);
344 printf("Load average: %.2f, %.2f, %.2f "
345 "(State: S=sleeping R=running, W=waiting)\n",
Eric Andersen420b2082002-09-17 22:14:58 +0000346 avg1, avg2, avg3);
Eric Andersen08a72202002-09-30 20:52:10 +0000347 return total / 1024;
Eric Andersen420b2082002-09-17 22:14:58 +0000348}
349
350
351/* display process statuses */
Eric Andersen08a72202002-09-30 20:52:10 +0000352static void display_status(int count, int col)
Eric Andersen420b2082002-09-17 22:14:58 +0000353{
Eric Andersen44608e92002-10-22 12:21:15 +0000354 procps_status_t *s = top;
Eric Andersen08a72202002-09-30 20:52:10 +0000355 char rss_str_buf[8];
356 unsigned long total_memory = display_generic();
Eric Andersen420b2082002-09-17 22:14:58 +0000357
Eric Andersen08a72202002-09-30 20:52:10 +0000358#ifdef FEATURE_CPU_USAGE_PERCENTAGE
Eric Andersen420b2082002-09-17 22:14:58 +0000359 /* what info of the processes is shown */
Eric Andersen08a72202002-09-30 20:52:10 +0000360 printf("\n\e[7m PID USER STATUS RSS PPID %%CPU %%MEM COMMAND\e[0m\n");
361#else
362 printf("\n\e[7m PID USER STATUS RSS PPID %%MEM COMMAND\e[0m\n");
363#endif
Eric Andersen420b2082002-09-17 22:14:58 +0000364
365 while (count--) {
Eric Andersen44608e92002-10-22 12:21:15 +0000366 char *namecmd = s->short_cmd;
Eric Andersen08a72202002-09-30 20:52:10 +0000367 int pmem;
Eric Andersen420b2082002-09-17 22:14:58 +0000368
Eric Andersen08a72202002-09-30 20:52:10 +0000369 pmem = 1000.0 * s->rss / total_memory;
370 if (pmem > 999) pmem = 999;
Eric Andersen420b2082002-09-17 22:14:58 +0000371
Eric Andersen08a72202002-09-30 20:52:10 +0000372 if(s->rss > 10*1024)
373 sprintf(rss_str_buf, "%6ldM", s->rss/1024);
Manuel Novoa III d4993302002-09-18 19:27:10 +0000374 else
Eric Andersen08a72202002-09-30 20:52:10 +0000375 sprintf(rss_str_buf, "%7ld", s->rss);
Eric Andersen8efe9672003-09-15 08:33:45 +0000376 printf(
Eric Andersen08a72202002-09-30 20:52:10 +0000377#ifdef FEATURE_CPU_USAGE_PERCENTAGE
Eric Andersen8efe9672003-09-15 08:33:45 +0000378 "%5d %-8s %s %s %5d %2d.%d %2u.%u ",
Eric Andersen08a72202002-09-30 20:52:10 +0000379#else
Eric Andersen8efe9672003-09-15 08:33:45 +0000380 "%5d %-8s %s %s %5d %2u.%u ",
Eric Andersen08a72202002-09-30 20:52:10 +0000381#endif
382 s->pid, s->user, s->state, rss_str_buf, s->ppid,
383#ifdef FEATURE_CPU_USAGE_PERCENTAGE
384 s->pcpu/10, s->pcpu%10,
385#endif
386 pmem/10, pmem%10);
Eric Andersen08a72202002-09-30 20:52:10 +0000387 if(strlen(namecmd) > col)
388 namecmd[col] = 0;
389 printf("%s\n", namecmd);
Eric Andersen420b2082002-09-17 22:14:58 +0000390 s++;
Eric Andersen08a72202002-09-30 20:52:10 +0000391 }
Eric Andersen44608e92002-10-22 12:21:15 +0000392}
393
394static void clearmems(void)
395{
Eric Andersen08a72202002-09-30 20:52:10 +0000396 free(top);
Eric Andersen08a72202002-09-30 20:52:10 +0000397 top = 0;
Eric Andersen08a72202002-09-30 20:52:10 +0000398 ntop = 0;
399}
400
401#if defined CONFIG_FEATURE_USE_TERMIOS
402#include <termios.h>
403#include <sys/time.h>
404#include <signal.h>
405
406
407static struct termios initial_settings;
408
409static void reset_term(void)
410{
411 tcsetattr(0, TCSANOW, (void *) &initial_settings);
412#ifdef CONFIG_FEATURE_CLEAN_UP
413 clearmems();
414#ifdef FEATURE_CPU_USAGE_PERCENTAGE
415 free(save_history);
416#endif
417#endif /* CONFIG_FEATURE_CLEAN_UP */
418}
419
420static void sig_catcher (int sig)
421{
422 reset_term();
423}
424#endif /* CONFIG_FEATURE_USE_TERMIOS */
425
426
Eric Andersen420b2082002-09-17 22:14:58 +0000427int top_main(int argc, char **argv)
428{
Eric Andersen08a72202002-09-30 20:52:10 +0000429 int opt, interval, lines, col;
430#if defined CONFIG_FEATURE_USE_TERMIOS
431 struct termios new_settings;
432 struct timeval tv;
433 fd_set readfds;
434 unsigned char c;
435 struct sigaction sa;
Eric Andersen08a72202002-09-30 20:52:10 +0000436#endif /* CONFIG_FEATURE_USE_TERMIOS */
437
Eric Andersen420b2082002-09-17 22:14:58 +0000438 /* Default update rate is 5 seconds */
439 interval = 5;
Eric Andersen420b2082002-09-17 22:14:58 +0000440
441 /* do normal option parsing */
442 while ((opt = getopt(argc, argv, "d:")) > 0) {
443 switch (opt) {
444 case 'd':
445 interval = atoi(optarg);
446 break;
447 default:
Manuel Novoa III cad53642003-03-19 09:13:01 +0000448 bb_show_usage();
Eric Andersen420b2082002-09-17 22:14:58 +0000449 }
450 }
451
Eric Andersen08a72202002-09-30 20:52:10 +0000452 /* Default to 25 lines - 5 lines for status */
453 lines = 25 - 5;
454 /* Default CMD format size */
455#ifdef FEATURE_CPU_USAGE_PERCENTAGE
456 col = 35 - 6;
457#else
458 col = 35;
Eric Andersen420b2082002-09-17 22:14:58 +0000459#endif
Eric Andersen44608e92002-10-22 12:21:15 +0000460 /* change to /proc */
Eric Andersen420b2082002-09-17 22:14:58 +0000461 if (chdir("/proc") < 0) {
Manuel Novoa III cad53642003-03-19 09:13:01 +0000462 bb_perror_msg_and_die("chdir('/proc')");
Eric Andersen420b2082002-09-17 22:14:58 +0000463 }
Eric Andersen08a72202002-09-30 20:52:10 +0000464#if defined CONFIG_FEATURE_USE_TERMIOS
465 tcgetattr(0, (void *) &initial_settings);
466 memcpy(&new_settings, &initial_settings, sizeof(struct termios));
467 new_settings.c_lflag &= ~(ISIG | ICANON); /* unbuffered input */
468 /* Turn off echoing */
469 new_settings.c_lflag &= ~(ECHO | ECHONL);
470
471 signal (SIGTERM, sig_catcher);
472 sigaction (SIGTERM, (struct sigaction *) 0, &sa);
473 sa.sa_flags |= SA_RESTART;
474 sa.sa_flags &= ~SA_INTERRUPT;
475 sigaction (SIGTERM, &sa, (struct sigaction *) 0);
476 sigaction (SIGINT, &sa, (struct sigaction *) 0);
477 tcsetattr(0, TCSANOW, (void *) &new_settings);
478 atexit(reset_term);
Eric Andersen8efe9672003-09-15 08:33:45 +0000479
480 get_terminal_width_height(0, &col, &lines);
481 if (lines > 4) {
482 lines -= 5;
Eric Andersen08a72202002-09-30 20:52:10 +0000483#ifdef FEATURE_CPU_USAGE_PERCENTAGE
Eric Andersen8efe9672003-09-15 08:33:45 +0000484 col = col - 80 + 35 - 6;
Eric Andersen08a72202002-09-30 20:52:10 +0000485#else
Eric Andersen8efe9672003-09-15 08:33:45 +0000486 col = col - 80 + 35;
Eric Andersen08a72202002-09-30 20:52:10 +0000487#endif
488 }
Eric Andersen08a72202002-09-30 20:52:10 +0000489#endif /* CONFIG_FEATURE_USE_TERMIOS */
490#ifdef FEATURE_CPU_USAGE_PERCENTAGE
491 sort_function[0] = pcpu_sort;
492 sort_function[1] = mem_sort;
493 sort_function[2] = time_sort;
494#else
495 sort_function = mem_sort;
496#endif
497 while (1) {
498 /* read process IDs & status for all the processes */
Eric Andersen44608e92002-10-22 12:21:15 +0000499 procps_status_t * p;
500
Eric Andersen9e480452003-07-03 10:07:04 +0000501#ifdef CONFIG_SELINUX
502 while ((p = procps_scan(0, 0, NULL) ) != 0) {
503#else
Eric Andersen44608e92002-10-22 12:21:15 +0000504 while ((p = procps_scan(0)) != 0) {
Eric Andersen9e480452003-07-03 10:07:04 +0000505#endif
Eric Andersen44608e92002-10-22 12:21:15 +0000506 int n = ntop;
507
508 top = xrealloc(top, (++ntop)*sizeof(procps_status_t));
509 memcpy(top + n, p, sizeof(procps_status_t));
510 }
511 if (ntop == 0) {
Manuel Novoa III cad53642003-03-19 09:13:01 +0000512 bb_perror_msg_and_die("scandir('/proc')");
Eric Andersen420b2082002-09-17 22:14:58 +0000513 }
Eric Andersen08a72202002-09-30 20:52:10 +0000514#ifdef FEATURE_CPU_USAGE_PERCENTAGE
515 if(!Hertz) {
516 init_Hertz_value();
517 do_stats();
518 sleep(1);
519 clearmems();
520 continue;
Eric Andersen420b2082002-09-17 22:14:58 +0000521 }
Eric Andersen08a72202002-09-30 20:52:10 +0000522 do_stats();
523#else
Eric Andersen44608e92002-10-22 12:21:15 +0000524 qsort(top, ntop, sizeof(procps_status_t), (void*)sort_function);
Eric Andersen08a72202002-09-30 20:52:10 +0000525#endif
526 opt = lines;
527 if (opt > ntop) {
528 opt = ntop;
529 }
530 /* show status for each of the processes */
531 display_status(opt, col);
532#if defined CONFIG_FEATURE_USE_TERMIOS
533 tv.tv_sec = interval;
534 tv.tv_usec = 0;
535 FD_ZERO (&readfds);
536 FD_SET (0, &readfds);
537 select (1, &readfds, NULL, NULL, &tv);
538 if (FD_ISSET (0, &readfds)) {
539 if (read (0, &c, 1) <= 0) { /* signal */
Eric Andersen420b2082002-09-17 22:14:58 +0000540 return EXIT_FAILURE;
541 }
Eric Andersen08a72202002-09-30 20:52:10 +0000542 if(c == 'q' || c == initial_settings.c_cc[VINTR])
543 return EXIT_SUCCESS;
544 if(c == 'M') {
545#ifdef FEATURE_CPU_USAGE_PERCENTAGE
546 sort_function[0] = mem_sort;
547 sort_function[1] = pcpu_sort;
548 sort_function[2] = time_sort;
549#else
550 sort_function = mem_sort;
551#endif
552 }
553#ifdef FEATURE_CPU_USAGE_PERCENTAGE
554 if(c == 'P') {
555 sort_function[0] = pcpu_sort;
556 sort_function[1] = mem_sort;
557 sort_function[2] = time_sort;
558 }
559 if(c == 'T') {
560 sort_function[0] = time_sort;
561 sort_function[1] = mem_sort;
562 sort_function[2] = pcpu_sort;
563 }
564#endif
565 if(c == 'N') {
566#ifdef FEATURE_CPU_USAGE_PERCENTAGE
567 sort_function[0] = pid_sort;
568#else
569 sort_function = pid_sort;
570#endif
571 }
572 }
573#else
Eric Andersen420b2082002-09-17 22:14:58 +0000574 sleep(interval);
Eric Andersen08a72202002-09-30 20:52:10 +0000575#endif /* CONFIG_FEATURE_USE_TERMIOS */
576 clearmems();
Eric Andersen420b2082002-09-17 22:14:58 +0000577 }
578
Eric Andersen420b2082002-09-17 22:14:58 +0000579 return EXIT_SUCCESS;
580}