last_patch95 from vodz:
[oweals/busybox.git] / procps / top.c
index 06ae77119c84a9bb684834eaf03a7aeff2cd7051..2e1bd3286d38d324a874f0c10f668c249809a876 100644 (file)
 #include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
-#include <dirent.h>
 #include <string.h>
 #include <sys/ioctl.h>
-#include <sys/stat.h>
 /* get page info */
 #include <asm/page.h>
 #include "busybox.h"
 #endif
 
 
-typedef struct {
-       int pid;
-       char user[9];
-       char state[4];
-       unsigned long rss;
-       int ppid;
-#ifdef FEATURE_CPU_USAGE_PERCENTAGE
-       unsigned pcpu;
-       unsigned long stime, utime;
-#endif
-       char *cmd;
-
-       /* basename of executable file in call to exec(2),
-               size from kernel headers */
-       char short_cmd[16];
-} status_t;
-
-typedef int (*cmp_t)(status_t *P, status_t *Q);
+typedef int (*cmp_t)(procps_status_t *P, procps_status_t *Q);
 
-static status_t *top;   /* Hehe */
+static procps_status_t *top;   /* Hehe */
 static int ntop;
 
 
-static int pid_sort (status_t *P, status_t *Q)
+static int pid_sort (procps_status_t *P, procps_status_t *Q)
 {
     int p = P->pid;
     int q = Q->pid;
@@ -82,7 +63,7 @@ static int pid_sort (status_t *P, status_t *Q)
     return 0;
 }
 
-static int mem_sort (status_t *P, status_t *Q)
+static int mem_sort (procps_status_t *P, procps_status_t *Q)
 {
     long p = P->rss;
     long q = Q->rss;
@@ -97,7 +78,7 @@ static int mem_sort (status_t *P, status_t *Q)
 #define sort_depth 3
 static cmp_t sort_function[sort_depth];
 
-static int pcpu_sort (status_t *P, status_t *Q)
+static int pcpu_sort (procps_status_t *P, procps_status_t *Q)
 {
     int p = P->pcpu;
     int q = Q->pcpu;
@@ -107,7 +88,7 @@ static int pcpu_sort (status_t *P, status_t *Q)
     return 0;
 }
 
-static int time_sort (status_t *P, status_t *Q)
+static int time_sort (procps_status_t *P, procps_status_t *Q)
 {
     long p = P->stime;
     long q = Q->stime;
@@ -174,11 +155,11 @@ static unsigned long Hertz;
 
 #define FILE_TO_BUF(filename, fd) do{                           \
     if (fd == -1 && (fd = open(filename, O_RDONLY)) == -1) {    \
-       perror_msg_and_die("/proc not be mounted?");            \
+       bb_perror_msg_and_die("/proc not be mounted?");            \
     }                                                           \
     lseek(fd, 0L, SEEK_SET);                                    \
     if ((local_n = read(fd, buf, sizeof buf - 1)) < 0) {        \
-       perror_msg_and_die("%s", filename);                     \
+       bb_perror_msg_and_die("%s", filename);                     \
     }                                                           \
     buf[local_n] = '\0';                                        \
 }while(0)
@@ -186,7 +167,7 @@ static unsigned long Hertz;
 #define FILE_TO_BUF2(filename, fd) do{                          \
     lseek(fd, 0L, SEEK_SET);                                    \
     if ((local_n = read(fd, buf, sizeof buf - 1)) < 0) {        \
-       perror_msg_and_die("%s", filename);                     \
+       bb_perror_msg_and_die("%s", filename);                     \
     }                                                           \
     buf[local_n] = '\0';                                        \
 }while(0)
@@ -253,7 +234,7 @@ static void do_stats(void)
     struct timezone timez;
     float elapsed_time;
 
-    status_t *cur;
+    procps_status_t *cur;
     int total_time, i, n;
     static int prev_count;
     int systime, usrtime, pid;
@@ -317,7 +298,7 @@ static void do_stats(void)
     save_history = memcpy(xmalloc(sizeof(struct save_hist)*n), New_save_hist,
                                                sizeof(struct save_hist)*n);
     prev_count = n;
-    qsort(top, n, sizeof(status_t), (void*)mult_lvl_cmp);
+    qsort(top, n, sizeof(procps_status_t), (void*)mult_lvl_cmp);
 }
 #else
 static cmp_t sort_function;
@@ -332,19 +313,19 @@ static unsigned long display_generic(void)
        unsigned long total, used, mfree, shared, buffers, cached;
 
        /* read memory info */
-       fp = xfopen("meminfo", "r");
+       fp = bb_xfopen("meminfo", "r");
        fgets(buf, sizeof(buf), fp);    /* skip first line */
 
        if (fscanf(fp, "Mem: %lu %lu %lu %lu %lu %lu",
                   &total, &used, &mfree, &shared, &buffers, &cached) != 6) {
-               error_msg_and_die("failed to read '%s'", "meminfo");
+               bb_error_msg_and_die("failed to read '%s'", "meminfo");
        }
        fclose(fp);
        
        /* read load average */
-       fp = xfopen("loadavg", "r");
+       fp = bb_xfopen("loadavg", "r");
        if (fscanf(fp, "%f %f %f", &avg1, &avg2, &avg3) != 3) {
-               error_msg_and_die("failed to read '%s'", "loadavg");
+               bb_error_msg_and_die("failed to read '%s'", "loadavg");
        }
        fclose(fp);
 
@@ -370,7 +351,7 @@ static unsigned long display_generic(void)
 /* display process statuses */
 static void display_status(int count, int col)
 {
-       status_t *s = top;
+       procps_status_t *s = top;
        char rss_str_buf[8];
        unsigned long total_memory = display_generic();
        
@@ -382,7 +363,7 @@ static void display_status(int count, int col)
 #endif
 
        while (count--) {
-               char *namecmd = s->cmd;
+               char *namecmd = s->short_cmd;
                int pmem;
 
                pmem = 1000.0 * s->rss / total_memory;
@@ -402,130 +383,17 @@ static void display_status(int count, int col)
                        s->pcpu/10, s->pcpu%10,
 #endif
                        pmem/10, pmem%10);
-               if(namecmd != 0 && namecmd[0] != 0) {
                        if(strlen(namecmd) > col)
                                namecmd[col] = 0;
                        printf("%s\n", namecmd);
-                       } else {
-                       namecmd = s->short_cmd;
-                       if(strlen(namecmd) > (col-2))
-                               namecmd[col-2] = 0;
-                       printf("[%s]\n", namecmd);
-                       }
                s++;
-               }
+       }
 }
 
-/* returns true for file names which are PID dirs
- * (i.e. start with number)
- */
-static int filter_pids(const struct dirent *dir)
+static void clearmems(void)
 {
-       char *name = dir->d_name;
-       int n;
-       char status[20];
-       char buf[1024];
-       FILE *fp;
-       status_t curstatus;
-       int pid;
-       long tasknice;
-       struct stat sb;
-
-       if (!(*name >= '0' && *name <= '9'))
-               return 0;
-       if(stat(name, &sb))
-               return 0;
-
-       memset(&curstatus, 0, sizeof(status_t));
-       pid = atoi(name);
-       curstatus.pid = pid;
-       
-       my_getpwuid(curstatus.user, sb.st_uid);
-
-       sprintf(status, "%d/stat", pid);
-       if((fp = fopen(status, "r")) == NULL)
-               return 0;
-       name = fgets(buf, sizeof(buf), fp);
-                       fclose(fp);
-       if(name == NULL)
-               return 0;
-       name = strrchr(buf, ')'); /* split into "PID (cmd" and "<rest>" */
-       if(name == 0 || name[1] != ' ')
-               return 0;
-       *name = 0;
-       sscanf(buf, "%*s (%15c", curstatus.short_cmd);
-       n = sscanf(name+2,
-        "%c %d "
-        "%*s %*s %*s %*s "     /* pgrp, session, tty, tpgid */
-        "%*s %*s %*s %*s %*s " /* flags, min_flt, cmin_flt, maj_flt, cmaj_flt */
-#ifdef FEATURE_CPU_USAGE_PERCENTAGE
-        "%lu %lu "
-#else
-        "%*s %*s "
-#endif
-        "%*s %*s %*s "         /* cutime, cstime, priority */
-        "%ld "
-        "%*s %*s %*s "         /* timeout, it_real_value, start_time */
-        "%*s "                 /* vsize */
-        "%ld",
-        curstatus.state, &curstatus.ppid,
-#ifdef FEATURE_CPU_USAGE_PERCENTAGE
-       &curstatus.utime, &curstatus.stime,
-#endif
-       &tasknice,
-       &curstatus.rss);
-#ifdef FEATURE_CPU_USAGE_PERCENTAGE
-       if(n != 6)
-#else
-       if(n != 4)
-#endif
-               return 0;
-
-       if (curstatus.rss == 0 && curstatus.state[0] != 'Z')
-               curstatus.state[1] = 'W';
-        else
-               curstatus.state[1] = ' ';
-       if (tasknice < 0)
-               curstatus.state[2] = '<';
-        else if (tasknice > 0)
-               curstatus.state[2] = 'N';
-        else
-               curstatus.state[2] = ' ';
-
-       curstatus.rss <<= (PAGE_SHIFT - 10);     /* 2**10 = 1kb */
-
-       sprintf(status, "%d/cmdline", pid);
-       if((fp = fopen(status, "r")) == NULL)
-               return 0;
-       if(fgets(buf, sizeof(buf), fp) != NULL) {
-            name = strchr(buf, '\n');
-            if(name != NULL)
-               *name = 0;
-            if(buf[0])
-               curstatus.cmd = strdup(buf); /* if NULL it work true also */
-               }
-               fclose(fp);
-               
-       n = ntop;
-       top = xrealloc(top, (++ntop)*sizeof(status_t));
-       memcpy(top + n, &curstatus, sizeof(status_t));
-       return 1;
-}
-
-
-static struct dirent **namelist;
-
-static void clearmems(void) {
-       int i;
-
-       for(i = 0; i < ntop; i++) {
-               free(top[i].cmd);
-               free(namelist[i]);
-       }
        free(top);
-       free(namelist);
        top = 0;
-       namelist = 0;
        ntop = 0;
 }
 
@@ -579,7 +447,7 @@ int top_main(int argc, char **argv)
                    interval = atoi(optarg);
                    break;
                default:
-                   show_usage();
+                   bb_show_usage();
            }
        }
 
@@ -591,9 +459,9 @@ int top_main(int argc, char **argv)
 #else
        col = 35;
 #endif
-       /* change to proc */
+       /* change to /proc */
        if (chdir("/proc") < 0) {
-               perror_msg_and_die("chdir('/proc')");
+               bb_perror_msg_and_die("chdir('/proc')");
        }
 #if defined CONFIG_FEATURE_USE_TERMIOS
        tcgetattr(0, (void *) &initial_settings);
@@ -631,8 +499,20 @@ int top_main(int argc, char **argv)
 #endif
        while (1) {
                /* read process IDs & status for all the processes */
-               if (scandir(".", &namelist, filter_pids, 0) < 0) {
-               perror_msg_and_die("scandir('/proc')");
+               procps_status_t * p;
+
+#ifdef CONFIG_SELINUX
+               while ((p = procps_scan(0, 0, NULL) ) != 0) {
+#else
+               while ((p = procps_scan(0)) != 0) {
+#endif
+                       int n = ntop;
+
+                       top = xrealloc(top, (++ntop)*sizeof(procps_status_t));
+                       memcpy(top + n, p, sizeof(procps_status_t));
+               }
+               if (ntop == 0) {
+               bb_perror_msg_and_die("scandir('/proc')");
        }
 #ifdef FEATURE_CPU_USAGE_PERCENTAGE
                if(!Hertz) {
@@ -644,7 +524,7 @@ int top_main(int argc, char **argv)
        }
                do_stats();
 #else
-               qsort(top, ntop, sizeof(status_t), (void*)sort_function);
+               qsort(top, ntop, sizeof(procps_status_t), (void*)sort_function);
 #endif
                opt = lines;
                if (opt > ntop) {