blob: 2e1bd3286d38d324a874f0c10f668c249809a876 [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);
376#ifdef FEATURE_CPU_USAGE_PERCENTAGE
377 printf("%5d %-8s %s %s %5d %2d.%d %2u.%u ",
378#else
379 printf("%5d %-8s %s %s %5d %2u.%u ",
380#endif
381 s->pid, s->user, s->state, rss_str_buf, s->ppid,
382#ifdef FEATURE_CPU_USAGE_PERCENTAGE
383 s->pcpu/10, s->pcpu%10,
384#endif
385 pmem/10, pmem%10);
Eric Andersen08a72202002-09-30 20:52:10 +0000386 if(strlen(namecmd) > col)
387 namecmd[col] = 0;
388 printf("%s\n", namecmd);
Eric Andersen420b2082002-09-17 22:14:58 +0000389 s++;
Eric Andersen08a72202002-09-30 20:52:10 +0000390 }
Eric Andersen44608e92002-10-22 12:21:15 +0000391}
392
393static void clearmems(void)
394{
Eric Andersen08a72202002-09-30 20:52:10 +0000395 free(top);
Eric Andersen08a72202002-09-30 20:52:10 +0000396 top = 0;
Eric Andersen08a72202002-09-30 20:52:10 +0000397 ntop = 0;
398}
399
400#if defined CONFIG_FEATURE_USE_TERMIOS
401#include <termios.h>
402#include <sys/time.h>
403#include <signal.h>
404
405
406static struct termios initial_settings;
407
408static void reset_term(void)
409{
410 tcsetattr(0, TCSANOW, (void *) &initial_settings);
411#ifdef CONFIG_FEATURE_CLEAN_UP
412 clearmems();
413#ifdef FEATURE_CPU_USAGE_PERCENTAGE
414 free(save_history);
415#endif
416#endif /* CONFIG_FEATURE_CLEAN_UP */
417}
418
419static void sig_catcher (int sig)
420{
421 reset_term();
422}
423#endif /* CONFIG_FEATURE_USE_TERMIOS */
424
425
Eric Andersen420b2082002-09-17 22:14:58 +0000426int top_main(int argc, char **argv)
427{
Eric Andersen08a72202002-09-30 20:52:10 +0000428 int opt, interval, lines, col;
429#if defined CONFIG_FEATURE_USE_TERMIOS
430 struct termios new_settings;
431 struct timeval tv;
432 fd_set readfds;
433 unsigned char c;
434 struct sigaction sa;
435#if defined CONFIG_FEATURE_AUTOWIDTH
Eric Andersen420b2082002-09-17 22:14:58 +0000436 struct winsize win = { 0, 0, 0, 0 };
437#endif
Eric Andersen08a72202002-09-30 20:52:10 +0000438#endif /* CONFIG_FEATURE_USE_TERMIOS */
439
Eric Andersen420b2082002-09-17 22:14:58 +0000440 /* Default update rate is 5 seconds */
441 interval = 5;
Eric Andersen420b2082002-09-17 22:14:58 +0000442
443 /* do normal option parsing */
444 while ((opt = getopt(argc, argv, "d:")) > 0) {
445 switch (opt) {
446 case 'd':
447 interval = atoi(optarg);
448 break;
449 default:
Manuel Novoa III cad53642003-03-19 09:13:01 +0000450 bb_show_usage();
Eric Andersen420b2082002-09-17 22:14:58 +0000451 }
452 }
453
Eric Andersen08a72202002-09-30 20:52:10 +0000454 /* Default to 25 lines - 5 lines for status */
455 lines = 25 - 5;
456 /* Default CMD format size */
457#ifdef FEATURE_CPU_USAGE_PERCENTAGE
458 col = 35 - 6;
459#else
460 col = 35;
Eric Andersen420b2082002-09-17 22:14:58 +0000461#endif
Eric Andersen44608e92002-10-22 12:21:15 +0000462 /* change to /proc */
Eric Andersen420b2082002-09-17 22:14:58 +0000463 if (chdir("/proc") < 0) {
Manuel Novoa III cad53642003-03-19 09:13:01 +0000464 bb_perror_msg_and_die("chdir('/proc')");
Eric Andersen420b2082002-09-17 22:14:58 +0000465 }
Eric Andersen08a72202002-09-30 20:52:10 +0000466#if defined CONFIG_FEATURE_USE_TERMIOS
467 tcgetattr(0, (void *) &initial_settings);
468 memcpy(&new_settings, &initial_settings, sizeof(struct termios));
469 new_settings.c_lflag &= ~(ISIG | ICANON); /* unbuffered input */
470 /* Turn off echoing */
471 new_settings.c_lflag &= ~(ECHO | ECHONL);
472
473 signal (SIGTERM, sig_catcher);
474 sigaction (SIGTERM, (struct sigaction *) 0, &sa);
475 sa.sa_flags |= SA_RESTART;
476 sa.sa_flags &= ~SA_INTERRUPT;
477 sigaction (SIGTERM, &sa, (struct sigaction *) 0);
478 sigaction (SIGINT, &sa, (struct sigaction *) 0);
479 tcsetattr(0, TCSANOW, (void *) &new_settings);
480 atexit(reset_term);
481#if defined CONFIG_FEATURE_AUTOWIDTH
482 ioctl(0, TIOCGWINSZ, &win);
483 if (win.ws_row > 4) {
484 lines = win.ws_row - 5;
485#ifdef FEATURE_CPU_USAGE_PERCENTAGE
486 col = win.ws_col - 80 + 35 - 6;
487#else
488 col = win.ws_col - 80 + 35;
489#endif
490 }
491#endif
492#endif /* CONFIG_FEATURE_USE_TERMIOS */
493#ifdef FEATURE_CPU_USAGE_PERCENTAGE
494 sort_function[0] = pcpu_sort;
495 sort_function[1] = mem_sort;
496 sort_function[2] = time_sort;
497#else
498 sort_function = mem_sort;
499#endif
500 while (1) {
501 /* read process IDs & status for all the processes */
Eric Andersen44608e92002-10-22 12:21:15 +0000502 procps_status_t * p;
503
Eric Andersen9e480452003-07-03 10:07:04 +0000504#ifdef CONFIG_SELINUX
505 while ((p = procps_scan(0, 0, NULL) ) != 0) {
506#else
Eric Andersen44608e92002-10-22 12:21:15 +0000507 while ((p = procps_scan(0)) != 0) {
Eric Andersen9e480452003-07-03 10:07:04 +0000508#endif
Eric Andersen44608e92002-10-22 12:21:15 +0000509 int n = ntop;
510
511 top = xrealloc(top, (++ntop)*sizeof(procps_status_t));
512 memcpy(top + n, p, sizeof(procps_status_t));
513 }
514 if (ntop == 0) {
Manuel Novoa III cad53642003-03-19 09:13:01 +0000515 bb_perror_msg_and_die("scandir('/proc')");
Eric Andersen420b2082002-09-17 22:14:58 +0000516 }
Eric Andersen08a72202002-09-30 20:52:10 +0000517#ifdef FEATURE_CPU_USAGE_PERCENTAGE
518 if(!Hertz) {
519 init_Hertz_value();
520 do_stats();
521 sleep(1);
522 clearmems();
523 continue;
Eric Andersen420b2082002-09-17 22:14:58 +0000524 }
Eric Andersen08a72202002-09-30 20:52:10 +0000525 do_stats();
526#else
Eric Andersen44608e92002-10-22 12:21:15 +0000527 qsort(top, ntop, sizeof(procps_status_t), (void*)sort_function);
Eric Andersen08a72202002-09-30 20:52:10 +0000528#endif
529 opt = lines;
530 if (opt > ntop) {
531 opt = ntop;
532 }
533 /* show status for each of the processes */
534 display_status(opt, col);
535#if defined CONFIG_FEATURE_USE_TERMIOS
536 tv.tv_sec = interval;
537 tv.tv_usec = 0;
538 FD_ZERO (&readfds);
539 FD_SET (0, &readfds);
540 select (1, &readfds, NULL, NULL, &tv);
541 if (FD_ISSET (0, &readfds)) {
542 if (read (0, &c, 1) <= 0) { /* signal */
Eric Andersen420b2082002-09-17 22:14:58 +0000543 return EXIT_FAILURE;
544 }
Eric Andersen08a72202002-09-30 20:52:10 +0000545 if(c == 'q' || c == initial_settings.c_cc[VINTR])
546 return EXIT_SUCCESS;
547 if(c == 'M') {
548#ifdef FEATURE_CPU_USAGE_PERCENTAGE
549 sort_function[0] = mem_sort;
550 sort_function[1] = pcpu_sort;
551 sort_function[2] = time_sort;
552#else
553 sort_function = mem_sort;
554#endif
555 }
556#ifdef FEATURE_CPU_USAGE_PERCENTAGE
557 if(c == 'P') {
558 sort_function[0] = pcpu_sort;
559 sort_function[1] = mem_sort;
560 sort_function[2] = time_sort;
561 }
562 if(c == 'T') {
563 sort_function[0] = time_sort;
564 sort_function[1] = mem_sort;
565 sort_function[2] = pcpu_sort;
566 }
567#endif
568 if(c == 'N') {
569#ifdef FEATURE_CPU_USAGE_PERCENTAGE
570 sort_function[0] = pid_sort;
571#else
572 sort_function = pid_sort;
573#endif
574 }
575 }
576#else
Eric Andersen420b2082002-09-17 22:14:58 +0000577 sleep(interval);
Eric Andersen08a72202002-09-30 20:52:10 +0000578#endif /* CONFIG_FEATURE_USE_TERMIOS */
579 clearmems();
Eric Andersen420b2082002-09-17 22:14:58 +0000580 }
581
Eric Andersen420b2082002-09-17 22:14:58 +0000582 return EXIT_SUCCESS;
583}