aboutsummaryrefslogtreecommitdiff
path: root/toys/pending/top.c
diff options
context:
space:
mode:
authorRob Landley <rob@landley.net>2016-01-20 16:51:17 -0600
committerRob Landley <rob@landley.net>2016-01-20 16:51:17 -0600
commit941f9d6cc09adaa0155ee71ac34e6f9b773a90f1 (patch)
tree12620e41d1dae88099e84bbf487215cb9c56d902 /toys/pending/top.c
parent59781de0c0512ed3c862bef5735d569b2adcd4a3 (diff)
downloadtoybox-941f9d6cc09adaa0155ee71ac34e6f9b773a90f1.tar.gz
Add basic top support to ps.c, delete toys/pending/top.c.
While I'm there, pack the ps help text, break out TOP_COMMON (todo: update config2help to collate that properly), add -o CPU showing which processor this pid is running on, implement -o C (it's %cpu without the fractional part), add -o %MEM, fix header padding.
Diffstat (limited to 'toys/pending/top.c')
-rw-r--r--toys/pending/top.c848
1 files changed, 0 insertions, 848 deletions
diff --git a/toys/pending/top.c b/toys/pending/top.c
deleted file mode 100644
index fd7e879c..00000000
--- a/toys/pending/top.c
+++ /dev/null
@@ -1,848 +0,0 @@
-/* top.c - Provide a view of process activity in real time.
- *
- * Copyright 2013 Bilal Qureshi <bilal.jmi@gmail.com>
- * Copyright 2013 Ashwini Kumar <ak.ashwini@gmail.com>
- * Copyright 2013 Kyungwan Han <asura321@gmail.com>
- *
- * No Standard
-
-USE_TOP(NEWTOY(top, ">0d#=3n#<1mb", TOYFLAG_USR|TOYFLAG_BIN))
-
-config TOP
- bool "top"
- default n
- help
-
- usage: top [-mb] [ -d seconds ] [ -n iterations ]
-
- Provide a view of process activity in real time.
- Keys
- N/M/P/T show CPU usage, sort by pid/mem/cpu/time
- S show memory
- R reverse sort
- H toggle threads
- C,1 toggle SMP
- Q,^C exit
-
- Options
- -n Iterations before exiting
- -d Delay between updates
- -m Same as 's' key
- -b Batch mode
-*/
-
-#define FOR_top
-#include "toys.h"
-#include <signal.h>
-#include <poll.h>
-
-GLOBALS(
- long iterations;
- long delay;
-
- long cmp_field;
- long reverse;
- long rows;
- long smp;
- long threads;
- long m_flag;
- long num_new_procs;
- long scroll_offset;
- struct termios inf;
-)
-
-#define PROC_NAME_LEN 512 //For long cmdline.
-#define INIT_PROCS 50
-
-struct cpu_info {
- long unsigned utime, ntime, stime, itime;
- long unsigned iowtime, irqtime, sirqtime, steal;
- unsigned long long total;
-};
-
-struct keycode_map_s {
- char *key;
- int code;
-};
-
-struct proc_info {
- struct proc_info *next;
- pid_t pid, ppid;
- uid_t uid;
- char name[PROC_NAME_LEN];
- char tname[PROC_NAME_LEN];
- char state[4];
- int prs;
- unsigned long utime, stime, delta_utime, delta_stime, delta_time;
- unsigned long vss, vssrw, rss, rss_shr, drt, drt_shr, stack;
-};
-
-static struct proc_info *free_procs, **old_procs, **new_procs;
-static struct cpu_info old_cpu[10], new_cpu[10]; //1 total, 8 cores, 1 null
-static int (*proc_cmp)(const void *a, const void *b);
-
-static struct proc_info *find_old_proc(pid_t pid)
-{
- int i;
-
- for (i = 0; old_procs && old_procs[i]; i++)
- if (old_procs[i]->pid == pid) return old_procs[i];
-
- return NULL;
-}
-
-static void read_stat(char *filename, struct proc_info *proc)
-{
- int nice;
- FILE *file;
- char *open_paren, *close_paren;
-
- if (!(file = fopen(filename, "r"))) return;
- fgets(toybuf, sizeof(toybuf), file);
- fclose(file);
-
- // Split at first '(' and last ')' to get process name.
- open_paren = strchr(toybuf, '(');
- close_paren = strrchr(toybuf, ')');
- if (!open_paren || !close_paren) return;
-
- *open_paren = *close_paren = '\0';
- snprintf(proc->tname, PROC_NAME_LEN, "[%s]",open_paren + 1);
-
- // Scan rest of string.
- sscanf(close_paren + 1, " %c %d %*d %*d %*d %*d %*d %*d %*d %*d %*d "
- "%lu %lu %*d %*d %*d %d %*d %*d %*d %lu %ld "
- "%*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %d",
- &proc->state[0], &proc->ppid, &proc->utime, &proc->stime, &nice,
- &proc->vss, &proc->rss, &proc->prs);
- if (!proc->vss && proc->state[0] != 'Z') proc->state[1] = 'W';
- else proc->state[1] = ' ';
- if (nice < 0 ) proc->state[2] = '<';
- else if (nice) proc->state[2] = 'N';
- else proc->state[2] = ' ';
-}
-
-static void read_status(char *filename, struct proc_info *proc)
-{
- FILE *file;
-
- if (!(file = fopen(filename, "r"))) return;
- while (fgets(toybuf, sizeof(toybuf), file))
- if (sscanf(toybuf, "Uid: %u", &(proc->uid)) == 1) break;
-
- fclose(file);
-}
-
-static void read_cmdline(char *filename, struct proc_info *proc)
-{
- int fd, len, rbytes = 0;
- char *ch, *base, tname[PROC_NAME_LEN];
-
- if ((fd = open(filename, O_RDONLY)) == -1) return;
- rbytes = readall(fd, toybuf, sizeof(toybuf));
- close(fd);
- if (rbytes <= 0) {
- strcpy(proc->name, proc->tname);
- return;
- }
- toybuf[rbytes] = '\0';
- while (--rbytes >= 0 && toybuf[rbytes] == '\0') continue;
-
- snprintf(tname, PROC_NAME_LEN, "%s", proc->tname+1);
- tname[strlen(tname) - 1] = '\0';
- ch = strchr(toybuf, ' ');
- if (ch) *ch = '\0';
- base = strrchr(toybuf, '/');
- if (base) base++;
- else base = toybuf;
-
- for (; rbytes >= 0; rbytes--)
- if ((unsigned char)toybuf[rbytes] < ' ') toybuf[rbytes] = ' ';
-
- if (*base == '-') base++;
- len = strlen(tname);
- if (strncmp(base, tname, len)) {
- len +=3; //{,}, \0
- rbytes = strlen(toybuf);
- memmove(toybuf+ len, toybuf, rbytes+1);
- snprintf(toybuf, sizeof(toybuf), "{%s}", tname);
- toybuf[len-1] = ' ';
- }
- snprintf(proc->name, PROC_NAME_LEN, "%s", toybuf);
-}
-
-static void add_proc(int proc_num, struct proc_info *proc)
-{
- int i;
-
- if (proc_num >= TT.num_new_procs-1) {
- new_procs = xrealloc(new_procs, (INIT_PROCS + TT.num_new_procs)
- * sizeof(struct proc_info *));
- for (i = TT.num_new_procs; i < (INIT_PROCS + TT.num_new_procs); i++)
- new_procs[i] = NULL;
- TT.num_new_procs += INIT_PROCS;
- }
- new_procs[proc_num] = proc;
-}
-
-void signal_handler(int sig)
-{
- tcsetattr(STDIN_FILENO, TCSANOW, &TT.inf);
- xputc('\n');
- signal(sig, SIG_DFL);
- raise(sig);
- _exit(sig | 128);
-}
-
-static int get_key_code(char *ch, int i)
-{
- static struct keycode_map_s type2[] = {
- {"OA",KEY_UP}, {"OB",KEY_DOWN}, {"OH",KEY_HOME},
- {"OF",KEY_END}, {"[A",KEY_UP}, {"[B",KEY_DOWN},
- {"[H",KEY_HOME}, {"[F",KEY_END}, {NULL, 0}
- };
-
- static struct keycode_map_s type3[] = {
- {"[1~", KEY_HOME}, {"[4~", KEY_END}, {"[5~", KEY_PGUP},
- {"[6~", KEY_PGDN}, {"[7~", KEY_HOME}, {"[8~", KEY_END},
- {NULL, 0}
- };
- struct keycode_map_s *table, *keytable[3] = {type2, type3, NULL};
- int j;
-
- if ( i > 3 || i < 1) return -1;
-
- for (j=0; (table = keytable[j]); j++) {
- while (table->key) {
- if (!strncmp(ch, table->key, i)) break;
- table++;
- }
- if (table->key) {
- if (i == 1 || (i == 2 && j)) return 1;
- return table->code;
- }
- }
- return -1;
-}
-
-static int read_input(int delay)
-{
- struct pollfd pfd[1];
- int ret, fret = 0, cnt = 0, escproc = 0, timeout = delay * 1000;
- char ch, seq[4] = {0,};
- struct termios newf;
-
- tcgetattr(0, &TT.inf);
- if (toys.optflags & FLAG_b) {
- sleep(delay);
- return 0;
- }
- pfd[0].fd = 0;
- pfd[0].events = POLLIN;
-
- //prepare terminal for input, without Enter of Carriage return
- memcpy(&newf, &TT.inf, sizeof(struct termios));
- newf.c_lflag &= ~(ICANON | ECHO | ECHONL);
- newf.c_cc[VMIN] = 1;
- newf.c_cc[VTIME] = 0;
- tcsetattr(0, TCSANOW, &newf);
-
- while (1) {
- if ((ret = poll(pfd, 1, timeout)) >= 0) break;
- else {
- if (timeout > 0) timeout--;
- if (errno == EINTR) continue;
- perror_exit("poll");
- }
- }
-
- while (ret) {
- if (read(STDIN_FILENO, &ch, 1) != 1) toys.optflags |= FLAG_b;
- else if (ch == '\033' || escproc) {
- int code;
- //process ESC keys
- if (!escproc) {
- if (!poll(pfd, 1, 50)) break; //no more chars
- escproc = 1;
- continue;
- }
- seq[cnt++] = ch;
- code = get_key_code(seq, cnt);
- switch(code) {
- case -1: //no match
- fret = 0;
- break;
- case 1: //read more
- continue;
- default: // got the key
- fret = code;
- break;
- }
- } else if ((ch == TT.inf.c_cc[VINTR])
- || (ch == TT.inf.c_cc[VEOF]))
- fret = 'q';
- else fret = ch | 0x20;
- break;
- }
- tcsetattr(0, TCSANOW, &TT.inf);
- return fret;
-}
-
-// Allocation for Processes
-static struct proc_info *alloc_proc(void)
-{
- struct proc_info *proc;
-
- if (free_procs) {
- proc = free_procs;
- free_procs = free_procs->next;
- memset(proc, 0, sizeof(*proc));
- } else proc = xzalloc(sizeof(*proc));
-
- return proc;
-}
-
-static void free_proc_list(struct proc_info *procs)
-{
- struct proc_info *tmp = procs;
-
- for (;tmp; tmp = procs) {
- procs = procs->next;
- free(tmp);
- }
-}
-
-// Free allocated Processes in order to avoid memory leaks
-static void free_proc(struct proc_info *proc)
-{
- proc->next = free_procs;
- free_procs = proc;
-}
-
-static struct proc_info *add_new_proc(pid_t pid, pid_t tid)
-{
- char filename[64];
- struct proc_info *proc = alloc_proc();
-
- proc->pid = (tid)? tid : pid;
- if (!tid) {
- sprintf(filename, "/proc/%d/stat", pid);
- read_stat(filename, proc);
- sprintf(filename, "/proc/%d/cmdline", pid);
- read_cmdline(filename, proc);
- sprintf(filename, "/proc/%d/status", pid);
- read_status(filename, proc);
- } else{
- sprintf(filename, "/proc/%d/task/%d/stat", pid,tid);
- read_stat(filename, proc);
- sprintf(filename, "/proc/%d/task/%d/cmdline", pid, tid);
- read_cmdline(filename, proc);
- }
- return proc;
-}
-
-static void read_smaps(pid_t pid, struct proc_info *p)
-{
- FILE *fp;
- char *line;
- size_t len;
- long long start, end, val, prvcl, prvdr, shrdr, shrcl;
- int count;
-
- p->vss = p->rss = 0;
- start = end = val = prvcl = prvdr = shrdr = shrcl = 0;
- sprintf(toybuf, "/proc/%u/smaps", pid);
- if (!(fp = fopen(toybuf, "r"))) {
- error_msg("No %ld\n", (long)pid);
- return;
- }
- for (;;) {
- int off;
-
- line = 0;
- if (0 >= getline(&line, &len, fp)) break;
- count = sscanf(line, "%llx-%llx %s %*s %*s %*s %n",
- &start, &end, toybuf, &off);
-
- if (count == 3) {
- end = end - start;
- if (strncmp(line+off, "/dev/", 5) || !strcmp(line+off, "/dev/zero\n")) {
- p->vss += end;
- if (toybuf[1] == 'w') p->vssrw += end;
- }
- if (line[off] && !strncmp(line+off, "[stack]",7)) p->stack += end;
- } else {
- if (0<sscanf(line, "Private_Clean: %lld", &val)) prvcl += val;
- if (0<sscanf(line, "Private_Dirty: %lld", &val)) prvdr += val;
- if (0<sscanf(line, "Shared_Dirty: %lld", &val)) shrdr += val;
- if (0<sscanf(line, "Shared_Clean: %lld", &val)) shrcl += val;
- }
- free(line);
- }
- free(line); //incase it broke out.
- p->rss_shr = shrdr + shrcl;
- p->drt = prvdr + shrdr;
- p->drt_shr = shrdr;
- p->rss = p->rss_shr + prvdr + prvcl;
- fclose(fp);
-}
-
-static void read_procs(void) // Read Processes
-{
- DIR *proc_dir, *thr_dir;
- struct dirent *pid_dir, *t_dir;
- struct proc_info *proc;
- pid_t pid, tid;
- int proc_num = 0;
-
- proc_dir = opendir("/proc");
- if (!proc_dir) perror_exit("Could not open /proc");
-
- new_procs = xzalloc(INIT_PROCS * sizeof(struct proc_info *));
- TT.num_new_procs = INIT_PROCS;
-
- while ((pid_dir = readdir(proc_dir))) {
- if (!isdigit(pid_dir->d_name[0])) continue;
-
- pid = atoi(pid_dir->d_name);
- proc = add_new_proc(pid, 0);
- if (TT.m_flag) {
- read_smaps(pid, proc);
- if (!proc->vss) {
- free(proc);
- continue;
- }
- }
- add_proc(proc_num++, proc);
-
- if (TT.threads) {
- char filename[64];
- uid_t uid = proc->uid;
-
- sprintf(filename,"/proc/%d/task",pid);
- if ((thr_dir = opendir(filename))) {
- while ((t_dir = readdir(thr_dir))) {
- if (!isdigit(t_dir->d_name[0])) continue;
-
- tid = atoi(t_dir->d_name);
- if (pid == tid) continue;
- proc = add_new_proc(pid, tid);
- proc->uid = uid; //child will have same uid as parent.
- add_proc(proc_num++, proc);
- }
- closedir(thr_dir);
- }
- }
- }
-
- closedir(proc_dir);
- TT.num_new_procs = proc_num;
-}
-
-//calculate percentage.
-static char* show_percent(long unsigned num, long unsigned den)
-{
- long res;
- static char ch, buff[12]={'\0'};
-
- if(num > den) num = den;
- res = (num * 100)/den;
- sprintf(buff,"%ld", (num * 100)% den);
- ch = *buff;
- sprintf(buff, "%ld.%c",res, ch);
- return buff;
-}
-
-static int print_header(struct sysinfo *info, unsigned int cols)
-{
- int fd, j, k, rows =0;
- long unsigned total, meminfo_cached, anon, meminfo_mapped,
- meminfo_slab, meminfo_dirty, meminfo_writeback, swapT, swapF;
- char *buff;
-
- fd = xopen("/proc/meminfo", O_RDONLY);
- while ((buff = get_line(fd))) {
- if (!strncmp(buff, "Cached", 6))
- sscanf(buff,"%*s %lu\n",&meminfo_cached);
- else if (!strncmp(buff, "AnonPages", 9))
- sscanf(buff,"%*s %lu\n",&anon);
- else if (!strncmp(buff, "Mapped", 6))
- sscanf(buff,"%*s %lu\n",&meminfo_mapped);
- else if (!strncmp(buff, "Slab", 4))
- sscanf(buff,"%*s %lu\n",&meminfo_slab);
- else if (!strncmp(buff, "Dirty", 5))
- sscanf(buff,"%*s %lu\n",&meminfo_dirty);
- else if (!strncmp(buff, "Writeback", 9))
- sscanf(buff,"%*s %lu\n",&meminfo_writeback);
- else if (!strncmp(buff, "SwapTotal", 9))
- sscanf(buff,"%*s %lu\n",&swapT);
- else if (!strncmp(buff, "SwapFree", 8))
- sscanf(buff,"%*s %lu\n",&swapF);
- free(buff);
- }
- close(fd);
-
- if (!(toys.optflags & FLAG_b)) printf("\033[H\033[J");
-
- if (TT.m_flag){
- sprintf(toybuf, "Mem total:%lu anon:%lu map:%lu free:%lu",
- ((info->totalram) >> 10), anon, meminfo_mapped,
- ((info->freeram) >> 10));
- printf("%.*s\n", cols, toybuf);
-
- sprintf(toybuf, "slab:%lu buf:%lu cache:%lu dirty:%lu write:%lu",
- meminfo_slab, ((info->bufferram) >>10), meminfo_cached,
- meminfo_dirty,meminfo_writeback);
- printf("%.*s\n", cols, toybuf);
-
- sprintf(toybuf, "Swap total:%lu free:%lu",swapT, swapF);
- printf("%.*s\n", cols, toybuf);
- rows += 3;
- } else {
- sprintf(toybuf,"Mem: %luK used, %luK free, %luK shrd, %luK buff, %luK cached",
- (info->totalram-info->freeram) >>10, (info->freeram) >>10,
- (info->sharedram) >>10, (info->bufferram) >>10, meminfo_cached);
- printf("%.*s\n", cols, toybuf);
-
- for (k = 1; new_cpu[k].total; k++) {
- j = 0;
- if (!TT.smp) {
- k = 0;
- j = sprintf(toybuf,"CPU:");
- } else j = sprintf(toybuf,"CPU%d:", k-1);
-
- total = (new_cpu[k].total) - (old_cpu[k].total);
- if (!total) total = 1; //avoid denominator as 0, FPE
- j += sprintf(toybuf + j," %s%% usr",
- show_percent((new_cpu[k].utime - old_cpu[k].utime), total));
- j += sprintf(toybuf+j," %s%% sys",
- show_percent((new_cpu[k].stime - old_cpu[k].stime), total));
- j += sprintf(toybuf+j," %s%% nic",
- show_percent(new_cpu[k].ntime - old_cpu[k].ntime, total));
- j += sprintf(toybuf+j," %s%% idle",
- show_percent(new_cpu[k].itime - old_cpu[k].itime, total));
- j += sprintf(toybuf+j," %s%% io",
- show_percent((new_cpu[k].iowtime - old_cpu[k].iowtime), total));
- j += sprintf(toybuf+j," %s%% irq",
- show_percent(new_cpu[k].irqtime - old_cpu[k].irqtime, total));
- j += sprintf(toybuf+j," %s%% sirq",
- show_percent(new_cpu[k].sirqtime - old_cpu[k].sirqtime, total));
- printf("%.*s\n", cols, toybuf);
- if (!TT.smp) break;
- }
-
- if ((buff = readfile("/proc/loadavg", NULL, 0))) {
- buff[strlen(buff) -1] = '\0'; //removing '\n' at end
- sprintf(toybuf, "Load average: %s", buff);
- printf("%.*s\n", cols, toybuf);
- free(buff);
- }
- rows += 2 + ((TT.smp) ? k-1 : 1);
- }
- return rows;
-}
-
-static void print_procs(void)
-{
- int i, j = 0;
- struct proc_info *old_proc, *proc;
- long unsigned total_delta_time;
- struct passwd *user;
- char *user_str, user_buf[20];
- struct sysinfo info;
- unsigned int cols=0, rows =0;
-
- terminal_size(&cols, &rows);
- if (!rows){
- rows = 24; //on serial consoles setting default
- cols = 79;
- }
- if (toys.optflags & FLAG_b) rows = INT_MAX;
- TT.rows = rows;
-
- for (i = 0; i < TT.num_new_procs; i++) {
- if (new_procs[i]) {
- old_proc = find_old_proc(new_procs[i]->pid);
- if (old_proc) {
- new_procs[i]->delta_utime = new_procs[i]->utime - old_proc->utime;
- new_procs[i]->delta_stime = new_procs[i]->stime - old_proc->stime;
- } else {
- new_procs[i]->delta_utime = 0;
- new_procs[i]->delta_stime = 0;
- }
- new_procs[i]->delta_time = new_procs[i]->delta_utime
- + new_procs[i]->delta_stime;
- }
- }
-
- total_delta_time = new_cpu[0].total - old_cpu[0].total;
- if (!total_delta_time) total_delta_time = 1;
-
- qsort(new_procs, TT.num_new_procs, sizeof(struct proc_info *), proc_cmp);
-
- //Memory details
- sysinfo(&info);
- info.totalram *= info.mem_unit;
- info.freeram *= info.mem_unit;
- info.sharedram *= info.mem_unit;
- info.bufferram *= info.mem_unit;
-
- rows -= print_header(&info, cols);
-
- if (TT.m_flag) {
- sprintf(toybuf, "%5s %5s %5s %5s %5s %5s %5s %5s %s", "PID", "VSZ", "VSZRW",
- "RSS", "(SHR)", "DIRTY", "(SHR)", "STACK", "COMMAND");
- toybuf[11 + TT.cmp_field*6] = (TT.reverse)?'_':'^'; //11 for PID,VSZ fields
- } else sprintf(toybuf, "%5s %5s %-8s %4s %5s %5s %4s %5s %s", "PID", "PPID",
- "USER", "STAT", "VSZ", "%VSZ", "CPU" , "%CPU", "COMMAND");
-
- printf((toys.optflags & FLAG_b)?"%.*s\n":"\033[7m%.*s\033[0m\n",cols, toybuf);
- rows--;
- for (i = TT.scroll_offset; i < TT.num_new_procs; i++) {
- j = 0;
- proc = new_procs[i];
-
- user = getpwuid(proc->uid);
- if (user && user->pw_name) {
- user_str = user->pw_name;
- } else {
- snprintf(user_buf, 20, "%d", proc->uid);
- user_str = user_buf;
- }
-
- if (!TT.m_flag )
- {
- float vss_percentage = (float)(proc->vss)/info.totalram * 100;
-
- j = sprintf(toybuf, "%5d %5d %-8.8s %-4s",proc->pid, proc->ppid, user_str,
- proc->state);
-
- if ((proc->vss >> 10) >= 100000)
- j += sprintf(toybuf + j, " %4lum", ((proc->vss >> 10) >> 10));
- else j += sprintf(toybuf+j, " %5lu", (proc->vss >> 10));
-
- sprintf(toybuf + j," %5.1f %4d %5s %s", vss_percentage, proc->prs,
- show_percent(proc->delta_time, total_delta_time),
- ((proc->name[0])? proc->name : proc->tname));
- printf("%.*s", cols, toybuf);
- } else {
- j = sprintf(toybuf, "%5d",proc->pid);
-
- if ((proc->vss >> 10) >= 100000)
- j += sprintf(toybuf + j, " %4lum", ((proc->vss >> 10) >> 10));
- else j += sprintf(toybuf+j, " %5lu", (proc->vss >> 10));
- if ((proc->vssrw >>10) >= 100000)
- j += sprintf(toybuf + j, " %4lum", ((proc->vssrw >> 10) >> 10));
- else j += sprintf(toybuf+j, " %5lu", (proc->vssrw >> 10));
- if (proc->rss >= 100000)
- j += sprintf(toybuf + j, " %4lum", ((proc->rss >> 10)));
- else j += sprintf(toybuf+j, " %5lu", proc->rss);
- if (proc->rss_shr >= 100000)
- j += sprintf(toybuf + j, " %4lum", (proc->rss_shr >> 10));
- else j += sprintf(toybuf+j, " %5lu", proc->rss_shr);
- if (proc->drt >= 100000)
- j += sprintf(toybuf + j, " %4lum", (proc->drt >> 10));
- else j += sprintf(toybuf+j, " %5lu", proc->drt);
- if (proc->drt_shr >= 100000)
- j += sprintf(toybuf + j, " %4lum", (proc->drt_shr >> 10));
- else j += sprintf(toybuf+j, " %5lu", proc->drt_shr);
- if ((proc->stack >>10) >= 100000)
- j += sprintf(toybuf + j, " %4lum", ((proc->stack >> 10) >> 10));
- else j += sprintf(toybuf+j, " %5lu", (proc->stack >> 10));
-
- sprintf(toybuf + j," %s",((proc->name[0])? proc->name : proc->tname));
- printf("%.*s", cols, toybuf);
- }
- rows--;
- if (!rows) {
- xputc('\r');
- break; //don't print any more process details.
- } else xputc('\n');
- }
-}
-
-/*
- * Free old processes(displayed in old iteration) in order to
- * avoid memory leaks
- */
-static void free_procs_arr(struct proc_info **procs)
-{
- int i;
- for (i = 0; procs && procs[i]; i++)
- free_proc(procs[i]);
-
- free(procs);
-}
-
-static int numcmp(long long a, long long b)
-{
- if (a < b) return (TT.reverse)?-1 : 1;
- if (a > b) return (TT.reverse)?1 : -1;
- return 0;
-}
-
-static int top_mem_cmp(const void *a, const void *b)
-{
- char *pa, *pb;
-
- int n = offsetof(struct proc_info, vss) + TT.cmp_field * sizeof(unsigned long);
- pa = *((char **)a); pb = *((char **)b);
- return numcmp(*(unsigned long*)(pa+n), *(unsigned long*)(pb+n));
-}
-
-static int proc_time_cmp(const void *a, const void *b)
-{
- struct proc_info *pa, *pb;
-
- pa = *((struct proc_info **)a); pb = *((struct proc_info **)b);
- return numcmp(pa->utime + pa->stime, pb->utime+pa->stime);
-}
-
-/*
- * Function to compare CPU usgae % while displaying processes
- * according to CPU usage
- */
-static int proc_cpu_cmp(const void *a, const void *b)
-{
- struct proc_info *pa, *pb;
-
- pa = *((struct proc_info **)a); pb = *((struct proc_info **)b);
- return numcmp(pa->delta_time, pb->delta_time);
-}
-
-/*
- * Function to compare memory taking by a process at the time of
- * displaying processes according to Memory usage
- */
-static int proc_vss_cmp(const void *a, const void *b)
-{
- struct proc_info *pa, *pb;
-
- pa = *((struct proc_info **)a); pb = *((struct proc_info **)b);
- return numcmp(pa->vss, pb->vss);
-}
-
-static int proc_pid_cmp(const void *a, const void *b)
-{
- struct proc_info *pa, *pb;
-
- pa = *((struct proc_info **)a); pb = *((struct proc_info **)b);
- return numcmp(pa->pid, pb->pid);
-}
-
-/* Read CPU stats for all the cores, assuming max 8 cores
- * to be present here.
- */
-static void read_cpu_stat()
-{
- int i;
- size_t len;
- char *line = 0, *params = "%lu %lu %lu %lu %lu %lu %lu %lu";
- FILE *fp = xfopen("/proc/stat", "r");
-
- for (i = 0; i<=8 && getline(&line, &len, fp) > 0; i++) {
- if (i) sprintf(toybuf, "cpu%d %s", i-1, params);
- else sprintf(toybuf, "cpu %s", params);
- len = sscanf(line, toybuf, &new_cpu[i].utime, &new_cpu[i].ntime,
- &new_cpu[i].stime, &new_cpu[i].itime, &new_cpu[i].iowtime,
- &new_cpu[i].irqtime, &new_cpu[i].sirqtime, &new_cpu[i].steal);
- if (len == 8)
- new_cpu[i].total = new_cpu[i].utime + new_cpu[i].ntime + new_cpu[i].stime
- + new_cpu[i].itime + new_cpu[i].iowtime + new_cpu[i].irqtime
- + new_cpu[i].sirqtime + new_cpu[i].steal;
-
- free(line);
- line = 0;
- }
- fclose(fp);
-}
-
-void top_main(void )
-{
- int get_key;
-
- proc_cmp = &proc_cpu_cmp;
- if ( TT.delay < 0) TT.delay = 3;
- if (toys.optflags & FLAG_m) {
- proc_cmp = &top_mem_cmp;
- TT.m_flag = 1;
- }
-
- sigatexit(signal_handler);
- read_cpu_stat();
- get_key = read_input(0);
-
- while (!(toys.optflags & FLAG_n) || TT.iterations--) {
- old_procs = new_procs;
- memcpy(old_cpu, new_cpu, sizeof(old_cpu));
- read_procs();
- read_cpu_stat();
- print_procs();
- free_procs_arr(old_procs);
- if ((toys.optflags & FLAG_n) && !TT.iterations) break;
-
- get_key = read_input(TT.delay);
- if (get_key == 'q') break;
-
- switch(get_key) {
- case 'n':
- proc_cmp = &proc_pid_cmp;
- TT.m_flag = 0;
- break;
- case 'h':
- if (!TT.m_flag) TT.threads ^= 1;
- break;
- case 'm':
- proc_cmp = &proc_vss_cmp;
- TT.m_flag = 0;
- break;
- case 'r':
- TT.reverse ^= 1;
- break;
- case 'c':
- case '1':
- TT.smp ^= 1;
- break;
- case 's':
- TT.m_flag = 1;
- TT.cmp_field = (TT.cmp_field + 1) % 7;//7 sort fields, vss,vssrw...
- proc_cmp = &top_mem_cmp;
- break;
- case 'p':
- proc_cmp = &proc_cpu_cmp;
- TT.m_flag = 0;
- break;
- case 't':
- proc_cmp = &proc_time_cmp;
- TT.m_flag = 0;
- break;
- case KEY_UP:
- TT.scroll_offset--;
- break;
- case KEY_DOWN:
- TT.scroll_offset++;
- break;
- case KEY_HOME:
- TT.scroll_offset = 0;
- break;
- case KEY_END:
- TT.scroll_offset = TT.num_new_procs - TT.rows/2;
- break;
- case KEY_PGUP:
- TT.scroll_offset -= TT.rows/2;
- break;
- case KEY_PGDN:
- TT.scroll_offset += TT.rows/2;
- break;
- }
- if (TT.scroll_offset >= TT.num_new_procs) TT.scroll_offset = TT.num_new_procs-1;
- if (TT.scroll_offset < 0) TT.scroll_offset = 0;
- }
- xputc('\n');
- if (CFG_TOYBOX_FREE) {
- free_proc_list(free_procs);
- free_procs = NULL;
- free_procs_arr(new_procs);
- free_proc_list(free_procs);
- }
-}