aboutsummaryrefslogtreecommitdiff
path: root/procps
diff options
context:
space:
mode:
Diffstat (limited to 'procps')
-rw-r--r--procps/kill.c6
-rw-r--r--procps/ps.c28
-rw-r--r--procps/top.c144
3 files changed, 115 insertions, 63 deletions
diff --git a/procps/kill.c b/procps/kill.c
index 9b96b4c1a..18121f06f 100644
--- a/procps/kill.c
+++ b/procps/kill.c
@@ -82,7 +82,7 @@ do_it_now:
82 82
83 if (killall5) { 83 if (killall5) {
84 pid_t sid; 84 pid_t sid;
85 procps_status_t* p; 85 procps_status_t* p = NULL;
86 86
87// Cannot happen anyway? We don't TERM ourself, we STOP 87// Cannot happen anyway? We don't TERM ourself, we STOP
88// /* kill(-1, sig) on Linux (at least 2.1.x) 88// /* kill(-1, sig) on Linux (at least 2.1.x)
@@ -94,8 +94,8 @@ do_it_now:
94 pid = getpid(); 94 pid = getpid();
95 sid = getsid(pid); 95 sid = getsid(pid);
96 /* Now kill all processes except our session */ 96 /* Now kill all processes except our session */
97 while ((p = procps_scan(0))!=0) { 97 while ((p = procps_scan(p, PSSCAN_PID|PSSCAN_SID))) {
98 if (getsid(p->pid)!=sid && p->pid!=pid && p->pid!=1) 98 if (p->sid != sid && p->pid != pid && p->pid != 1)
99 kill(p->pid, signo); 99 kill(p->pid, signo);
100 } 100 }
101 /* And let them continue */ 101 /* And let them continue */
diff --git a/procps/ps.c b/procps/ps.c
index 9d6e42d79..2ff6e77d4 100644
--- a/procps/ps.c
+++ b/procps/ps.c
@@ -11,7 +11,7 @@
11 11
12int ps_main(int argc, char **argv) 12int ps_main(int argc, char **argv)
13{ 13{
14 procps_status_t * p; 14 procps_status_t *p = NULL;
15 int i, len; 15 int i, len;
16 SKIP_SELINUX(const) int use_selinux = 0; 16 SKIP_SELINUX(const) int use_selinux = 0;
17 USE_SELINUX(security_context_t sid = NULL;) 17 USE_SELINUX(security_context_t sid = NULL;)
@@ -50,7 +50,13 @@ int ps_main(int argc, char **argv)
50 else 50 else
51 puts(" PID Uid VmSize Stat Command"); 51 puts(" PID Uid VmSize Stat Command");
52 52
53 while ((p = procps_scan(1)) != 0) { 53 while ((p = procps_scan(p, 0
54 | PSSCAN_PID
55 | PSSCAN_UIDGID
56 | PSSCAN_STATE
57 | PSSCAN_RSS
58 | PSSCAN_CMD
59 ))) {
54 char *namecmd = p->cmd; 60 char *namecmd = p->cmd;
55#if ENABLE_SELINUX 61#if ENABLE_SELINUX
56 if (use_selinux) { 62 if (use_selinux) {
@@ -71,13 +77,18 @@ int ps_main(int argc, char **argv)
71 } else { 77 } else {
72 safe_strncpy(sbuf, "unknown", 7); 78 safe_strncpy(sbuf, "unknown", 7);
73 } 79 }
74 len = printf("%5u %-32s %s ", (unsigned)p->pid, sbuf, p->state); 80 len = printf("%5u %-32s %s ", p->pid, sbuf, p->state);
75 } else 81 } else
76#endif 82#endif
83 {
84 const char *user = get_cached_username(p->uid);
77 if (p->rss == 0) 85 if (p->rss == 0)
78 len = printf("%5u %-8s %s ", (unsigned)p->pid, p->user, p->state); 86 len = printf("%5u %-8s %s ",
87 p->pid, user, p->state);
79 else 88 else
80 len = printf("%5u %-8s %6ld %s ", (unsigned)p->pid, p->user, p->rss, p->state); 89 len = printf("%5u %-8s %6ld %s ",
90 p->pid, user, p->rss, p->state);
91 }
81 92
82 i = terminal_width-len; 93 i = terminal_width-len;
83 94
@@ -88,16 +99,15 @@ int ps_main(int argc, char **argv)
88 namecmd[i] = 0; 99 namecmd[i] = 0;
89 puts(namecmd); 100 puts(namecmd);
90 } else { 101 } else {
91 namecmd = p->short_cmd; 102 namecmd = p->comm;
92 if (i < 2) 103 if (i < 2)
93 i = 2; 104 i = 2;
94 if (strlen(namecmd) > ((size_t)i-2)) 105 if (strlen(namecmd) > ((size_t)i-2))
95 namecmd[i-2] = 0; 106 namecmd[i-2] = 0;
96 printf("[%s]\n", namecmd); 107 printf("[%s]\n", namecmd);
97 } 108 }
98 /* no check needed, but to make valgrind happy.. */
99 if (ENABLE_FEATURE_CLEAN_UP && p->cmd)
100 free(p->cmd);
101 } 109 }
110 if (ENABLE_FEATURE_CLEAN_UP)
111 clear_username_cache();
102 return EXIT_SUCCESS; 112 return EXIT_SUCCESS;
103} 113}
diff --git a/procps/top.c b/procps/top.c
index c76fdc312..8d732d4b2 100644
--- a/procps/top.c
+++ b/procps/top.c
@@ -30,37 +30,76 @@
30 30
31#include "busybox.h" 31#include "busybox.h"
32 32
33typedef int (*cmp_t)(procps_status_t *P, procps_status_t *Q);
34 33
35static procps_status_t *top; /* Hehe */ 34typedef struct {
35 unsigned long rss;
36#if ENABLE_FEATURE_TOP_CPU_USAGE_PERCENTAGE
37 unsigned long ticks;
38 unsigned pcpu; /* delta of ticks */
39#endif
40 unsigned pid, ppid;
41 unsigned uid;
42 char state[4];
43 char comm[COMM_LEN];
44} top_status_t;
45static top_status_t *top;
36static int ntop; 46static int ntop;
47/* This structure stores some critical information from one frame to
48 the next. Used for finding deltas. */
49struct save_hist {
50 unsigned long ticks;
51 unsigned pid;
52};
53static struct save_hist *prev_hist;
54static int prev_hist_count;
55/* static int hist_iterations; */
56static unsigned total_pcpu;
57/* static unsigned long total_rss; */
58
59
37#define OPT_BATCH_MODE (option_mask32 & 0x4) 60#define OPT_BATCH_MODE (option_mask32 & 0x4)
38 61
39#if ENABLE_FEATURE_USE_TERMIOS 62#if ENABLE_FEATURE_USE_TERMIOS
40static int pid_sort(procps_status_t *P, procps_status_t *Q) 63static int pid_sort(top_status_t *P, top_status_t *Q)
41{ 64{
65 /* Buggy wrt pids with high bit set */
66 /* (linux pids are in [1..2^15-1]) */
42 return (Q->pid - P->pid); 67 return (Q->pid - P->pid);
43} 68}
44#endif 69#endif
45 70
46static int mem_sort(procps_status_t *P, procps_status_t *Q) 71static int mem_sort(top_status_t *P, top_status_t *Q)
47{ 72{
48 return (int)(Q->rss - P->rss); 73 /* We want to avoid unsigned->signed and truncation errors */
74 if (Q->rss < P->rss) return -1;
75 return Q->rss != P->rss; /* 0 if ==, 1 if > */
49} 76}
50 77
51#if ENABLE_FEATURE_TOP_CPU_USAGE_PERCENTAGE 78
79typedef int (*cmp_funcp)(top_status_t *P, top_status_t *Q);
80
81#if !ENABLE_FEATURE_TOP_CPU_USAGE_PERCENTAGE
82
83static cmp_funcp sort_function;
84
85#else
52 86
53enum { SORT_DEPTH = 3 }; 87enum { SORT_DEPTH = 3 };
54static cmp_t sort_function[SORT_DEPTH];
55 88
56static int pcpu_sort(procps_status_t *P, procps_status_t *Q) 89static cmp_funcp sort_function[SORT_DEPTH];
90
91static int pcpu_sort(top_status_t *P, top_status_t *Q)
57{ 92{
58 return (Q->pcpu - P->pcpu); 93 /* Buggy wrt ticks with high bit set */
94 /* Affects only processes for which ticks overflow */
95 return (int)Q->pcpu - (int)P->pcpu;
59} 96}
60 97
61static int time_sort(procps_status_t *P, procps_status_t *Q) 98static int time_sort(top_status_t *P, top_status_t *Q)
62{ 99{
63 return (int)((Q->stime + Q->utime) - (P->stime + P->utime)); 100 /* We want to avoid unsigned->signed and truncation errors */
101 if (Q->ticks < P->ticks) return -1;
102 return Q->ticks != P->ticks; /* 0 if ==, 1 if > */
64} 103}
65 104
66static int mult_lvl_cmp(void* a, void* b) { 105static int mult_lvl_cmp(void* a, void* b) {
@@ -74,24 +113,6 @@ static int mult_lvl_cmp(void* a, void* b) {
74 return 0; 113 return 0;
75} 114}
76 115
77/* This structure stores some critical information from one frame to
78 the next. Mostly used for sorting. */
79struct save_hist {
80 int ticks;
81 pid_t pid;
82};
83
84/*
85 * Calculates percent cpu usage for each task.
86 */
87
88static struct save_hist *prev_hist;
89static int prev_hist_count;
90/* static int hist_iterations; */
91
92
93static unsigned total_pcpu;
94/* static unsigned long total_rss; */
95 116
96typedef struct { 117typedef struct {
97 unsigned long long usr,nic,sys,idle,iowait,irq,softirq,steal; 118 unsigned long long usr,nic,sys,idle,iowait,irq,softirq,steal;
@@ -115,11 +136,12 @@ static void get_jiffy_counts(void)
115 jif.busy = jif.total - jif.idle - jif.iowait; 136 jif.busy = jif.total - jif.idle - jif.iowait;
116} 137}
117 138
139
118static void do_stats(void) 140static void do_stats(void)
119{ 141{
120 procps_status_t *cur; 142 top_status_t *cur;
121 pid_t pid; 143 pid_t pid;
122 int total_time, i, last_i, n; 144 int i, last_i, n;
123 struct save_hist *new_hist; 145 struct save_hist *new_hist;
124 146
125 get_jiffy_counts(); 147 get_jiffy_counts();
@@ -139,8 +161,7 @@ static void do_stats(void)
139 * and system time 161 * and system time
140 */ 162 */
141 pid = cur->pid; 163 pid = cur->pid;
142 total_time = cur->stime + cur->utime; 164 new_hist[n].ticks = cur->ticks;
143 new_hist[n].ticks = total_time;
144 new_hist[n].pid = pid; 165 new_hist[n].pid = pid;
145 166
146 /* find matching entry from previous pass */ 167 /* find matching entry from previous pass */
@@ -150,13 +171,13 @@ static void do_stats(void)
150 last_i = i; 171 last_i = i;
151 if (prev_hist_count) do { 172 if (prev_hist_count) do {
152 if (prev_hist[i].pid == pid) { 173 if (prev_hist[i].pid == pid) {
153 cur->pcpu = total_time - prev_hist[i].ticks; 174 cur->pcpu = cur->ticks - prev_hist[i].ticks;
175 total_pcpu += cur->pcpu;
154 break; 176 break;
155 } 177 }
156 i = (i+1) % prev_hist_count; 178 i = (i+1) % prev_hist_count;
157 /* hist_iterations++; */ 179 /* hist_iterations++; */
158 } while (i != last_i); 180 } while (i != last_i);
159 total_pcpu += cur->pcpu;
160 /* total_rss += cur->rss; */ 181 /* total_rss += cur->rss; */
161 } 182 }
162 183
@@ -167,10 +188,9 @@ static void do_stats(void)
167 prev_hist = new_hist; 188 prev_hist = new_hist;
168 prev_hist_count = ntop; 189 prev_hist_count = ntop;
169} 190}
170#else
171static cmp_t sort_function;
172#endif /* FEATURE_TOP_CPU_USAGE_PERCENTAGE */ 191#endif /* FEATURE_TOP_CPU_USAGE_PERCENTAGE */
173 192
193
174/* display generic info (meminfo / loadavg) */ 194/* display generic info (meminfo / loadavg) */
175static unsigned long display_generic(int scr_width) 195static unsigned long display_generic(int scr_width)
176{ 196{
@@ -265,7 +285,7 @@ static void display_status(int count, int scr_width)
265 bits_per_int = sizeof(int)*8 285 bits_per_int = sizeof(int)*8
266 }; 286 };
267 287
268 procps_status_t *s = top; 288 top_status_t *s = top;
269 char rss_str_buf[8]; 289 char rss_str_buf[8];
270 unsigned long total_memory = display_generic(scr_width); /* or use total_rss? */ 290 unsigned long total_memory = display_generic(scr_width); /* or use total_rss? */
271 unsigned pmem_shift, pmem_scale; 291 unsigned pmem_shift, pmem_scale;
@@ -333,14 +353,19 @@ static void display_status(int count, int scr_width)
333 sprintf(rss_str_buf, "%6ldM", s->rss/1024); 353 sprintf(rss_str_buf, "%6ldM", s->rss/1024);
334 else 354 else
335 sprintf(rss_str_buf, "%7ld", s->rss); 355 sprintf(rss_str_buf, "%7ld", s->rss);
336 USE_FEATURE_TOP_CPU_USAGE_PERCENTAGE(pcpu = div((s->pcpu*pcpu_scale) >> pcpu_shift, 10);) 356 USE_FEATURE_TOP_CPU_USAGE_PERCENTAGE(
337 col -= printf("\n%5u %-8s %s %s%6u%3u.%c" \ 357 pcpu = div((s->pcpu*pcpu_scale) >> pcpu_shift, 10);
338 USE_FEATURE_TOP_CPU_USAGE_PERCENTAGE("%3u.%c") " ", 358 )
339 (unsigned)s->pid, s->user, s->state, rss_str_buf, (unsigned)s->ppid, 359 col -= printf("\n%5u %-8s %s "
360 "%s%6u"
361 USE_FEATURE_TOP_CPU_USAGE_PERCENTAGE("%3u.%c")
362 "%3u.%c ",
363 s->pid, get_cached_username(s->uid), s->state,
364 rss_str_buf, s->ppid,
340 USE_FEATURE_TOP_CPU_USAGE_PERCENTAGE(pcpu.quot, '0'+pcpu.rem,) 365 USE_FEATURE_TOP_CPU_USAGE_PERCENTAGE(pcpu.quot, '0'+pcpu.rem,)
341 pmem.quot, '0'+pmem.rem); 366 pmem.quot, '0'+pmem.rem);
342 if (col > 0) 367 if (col > 0)
343 printf("%.*s", col, s->short_cmd); 368 printf("%.*s", col, s->comm);
344 /* printf(" %d/%d %lld/%lld", s->pcpu, total_pcpu, 369 /* printf(" %d/%d %lld/%lld", s->pcpu, total_pcpu,
345 jif.busy - prev_jif.busy, jif.total - prev_jif.total); */ 370 jif.busy - prev_jif.busy, jif.total - prev_jif.total); */
346 s++; 371 s++;
@@ -350,18 +375,20 @@ static void display_status(int count, int scr_width)
350 fflush(stdout); 375 fflush(stdout);
351} 376}
352 377
378
353static void clearmems(void) 379static void clearmems(void)
354{ 380{
381 clear_username_cache();
355 free(top); 382 free(top);
356 top = 0; 383 top = 0;
357 ntop = 0; 384 ntop = 0;
358} 385}
359 386
387
360#if ENABLE_FEATURE_USE_TERMIOS 388#if ENABLE_FEATURE_USE_TERMIOS
361#include <termios.h> 389#include <termios.h>
362#include <signal.h> 390#include <signal.h>
363 391
364
365static struct termios initial_settings; 392static struct termios initial_settings;
366 393
367static void reset_term(void) 394static void reset_term(void)
@@ -427,7 +454,7 @@ int top_main(int argc, char **argv)
427#endif /* FEATURE_TOP_CPU_USAGE_PERCENTAGE */ 454#endif /* FEATURE_TOP_CPU_USAGE_PERCENTAGE */
428 455
429 while (1) { 456 while (1) {
430 procps_status_t *p; 457 procps_status_t *p = NULL;
431 458
432 /* Default to 25 lines - 5 lines for status */ 459 /* Default to 25 lines - 5 lines for status */
433 lines = 24 - 3; 460 lines = 24 - 3;
@@ -442,11 +469,26 @@ int top_main(int argc, char **argv)
442#endif /* FEATURE_USE_TERMIOS */ 469#endif /* FEATURE_USE_TERMIOS */
443 470
444 /* read process IDs & status for all the processes */ 471 /* read process IDs & status for all the processes */
445 while ((p = procps_scan(0)) != 0) { 472 while ((p = procps_scan(p, 0
473 | PSSCAN_PID
474 | PSSCAN_PPID
475 | PSSCAN_RSS
476 | PSSCAN_STIME
477 | PSSCAN_UTIME
478 | PSSCAN_STATE
479 | PSSCAN_COMM
480 | PSSCAN_SID
481 | PSSCAN_UIDGID
482 ))) {
446 int n = ntop; 483 int n = ntop;
447 484 top = xrealloc(top, (++ntop)*sizeof(top_status_t));
448 top = xrealloc(top, (++ntop)*sizeof(procps_status_t)); 485 top[n].pid = p->pid;
449 memcpy(top + n, p, sizeof(procps_status_t)); 486 top[n].ppid = p->ppid;
487 top[n].rss = p->rss;
488 top[n].ticks = p->stime + p->utime;
489 top[n].uid = p->uid;
490 strcpy(top[n].state, p->state);
491 strcpy(top[n].comm, p->comm);
450 } 492 }
451 if (ntop == 0) { 493 if (ntop == 0) {
452 bb_error_msg_and_die("can't find process info in /proc"); 494 bb_error_msg_and_die("can't find process info in /proc");
@@ -459,9 +501,9 @@ int top_main(int argc, char **argv)
459 continue; 501 continue;
460 } 502 }
461 do_stats(); 503 do_stats();
462 qsort(top, ntop, sizeof(procps_status_t), (void*)mult_lvl_cmp); 504 qsort(top, ntop, sizeof(top_status_t), (void*)mult_lvl_cmp);
463#else 505#else
464 qsort(top, ntop, sizeof(procps_status_t), (void*)sort_function); 506 qsort(top, ntop, sizeof(top_status_t), (void*)sort_function);
465#endif /* FEATURE_TOP_CPU_USAGE_PERCENTAGE */ 507#endif /* FEATURE_TOP_CPU_USAGE_PERCENTAGE */
466 count = lines; 508 count = lines;
467 if (OPT_BATCH_MODE || count > ntop) { 509 if (OPT_BATCH_MODE || count > ntop) {