aboutsummaryrefslogtreecommitdiff
path: root/toys/posix
diff options
context:
space:
mode:
Diffstat (limited to 'toys/posix')
-rw-r--r--toys/posix/ps.c113
1 files changed, 94 insertions, 19 deletions
diff --git a/toys/posix/ps.c b/toys/posix/ps.c
index d2c9a267..cc07042e 100644
--- a/toys/posix/ps.c
+++ b/toys/posix/ps.c
@@ -155,7 +155,7 @@ config IOTOP
help
usage: iotop [-Aabkoq] [-n NUMBER] [-d SECONDS] [-p PID,] [-u USER,]
- Rank processes by I/O.
+ Rank processes by I/O. Cursor left/right to change sort, Q to exit.
-A All I/O, not just disk
-a Accumulated I/O (not percentage)
@@ -205,7 +205,7 @@ GLOBALS(
void *fields, *kfields;
long long ticks, bits, ioread, iowrite, aioread, aiowrite;
size_t header_len;
- int kcount, ksave, forcek;
+ int kcount, ksave, forcek, sortpos;
int (*match_process)(long long *slot);
)
@@ -846,7 +846,6 @@ static int ksort(void *aa, void *bb)
int ret = 0, slot;
for (field = TT.kfields; field; field = field->next) {
-
slot = typos[field->which].slot;
// Compare as strings?
if (slot&64) {
@@ -884,7 +883,6 @@ static struct carveup **collate(int count, struct dirtree *dt,
dt = temp;
}
-
return tbsort;
}
@@ -1014,21 +1012,45 @@ void ttop_main(void)
#define FOR_iotop
#include "generated/flags.h"
+// select which of the -o fields to sort by
+static void setsort(int pos)
+{
+ struct strawberry *field, *going2;
+ int i = 0;
+
+ if (pos<0) pos = 0;
+
+ for (field = TT.fields; field; field = field->next) {
+ if ((TT.sortpos = i++)<pos) continue;
+ going2 = TT.kfields;
+ going2->which = field->which;
+ going2->len = field->len;
+ break;
+ }
+}
+
void iotop_main(void)
{
+ struct timespec ts;
+ long long timeout = 0, now;
struct proclist {
struct carveup **tb;
int count;
} plist[2], *plold, *plnew, old, new, mix;
struct arg_list al;
- char *d = "D"+!!(toys.optflags&FLAG_A), *header,
+ char *d = "D"+!!(toys.optflags&FLAG_A), *header, scratch[16],
deltas[] = {11,28,29,44,50,51,52,53,54};
unsigned tock = 0;
- int i, lines;
+ int i, lines, done = 0;
if (!TT.iotop.d) TT.iotop.d = 3;
+ TT.iotop.d *= 1000;
if (toys.optflags&FLAG_k) TT.forcek++;
if (toys.optflags&FLAG_b) TT.width = TT.height = 99999;
+ else {
+ xset_terminal(0, 1, 0);
+ sigatexit(tty_sigreset);
+ }
shared_main();
// TODO: usage: iotop [-oq]
@@ -1043,15 +1065,17 @@ void iotop_main(void)
dlist_terminate(TT.fields);
header = strdup(toybuf);
- al.arg = xmprintf("-%sIO,-%sREAD,-%sWRITE,-SWAP,-ETIME,-PID",d,d,d);
+ // Fallback sorts. First (dummy) field gets overwritten by setsort()
+ al.arg = xmprintf("-S,-%sIO,-ETIME,-PID",d);
comma_args(&al, &TT.kfields, 0, parse_ko);
free(al.arg);
dlist_terminate(TT.kfields);
+ setsort(6);
TT.ksave = DIRTREE_SAVE;
TT.match_process = shared_match_process;
memset(plist, 0, sizeof(plist));
- for (;;) {
+ do {
struct dirtree *dt = dirtree_read("/proc", get_ps);
plold = plist+(tock++&1);
@@ -1086,8 +1110,9 @@ void iotop_main(void)
if (!old.count || *otb->slot > *ntb->slot) mix.tb[mix.count] = ntb;
else {
- // If we have both, adjust deltas. Stomping old data is fine because
- // we free it after displaying.
+ // If we have both, adjust slot[deltas[]] to be relative to previous
+ // measurement rather than process start. Stomping old.data is fine
+ // because we free it after displaying.
if (!(toys.optflags&FLAG_a))
for (i = 0; i<ARRAY_LEN(deltas); i++)
otb->slot[deltas[i]] = ntb->slot[deltas[i]] - otb->slot[deltas[i]];
@@ -1102,17 +1127,67 @@ void iotop_main(void)
new.count--;
}
- qsort(mix.tb, mix.count, sizeof(struct carveup *), (void *)ksort);
- if (!(toys.optflags&FLAG_q))
- printf("%s%s\n", (toys.optflags&FLAG_b) ? "" : "\033[H\033[J", header);
- lines = TT.height-2;
+ // Will will re-fetch no data before its time. - Mork calling Orson Welles
+ for (;;) {
+ char was, is, *pos;
+
+ qsort(mix.tb, mix.count, sizeof(struct carveup *), (void *)ksort);
+ if (!(toys.optflags&FLAG_b)) printf("\033[H\033[J");
+ if (!(toys.optflags&FLAG_q)) {
+ i = 0;
+ strcpy(pos = toybuf, header);
+ for (i=0, is = *pos; *pos; pos++) {
+ was = is;
+ is = *pos;
+ if (isspace(was) && !isspace(is) && i++==TT.sortpos) pos[-1] = '[';
+ if (!isspace(was) && isspace(is) && i==TT.sortpos+1) *pos = ']';
+ }
+ printf("\033[7m%s\033[0m\n\r", toybuf);
+
+ if (!(toys.optflags&FLAG_b))
+ terminal_probesize(&TT.width, &TT.height);
+ }
+ lines = TT.height-2;
+
+ for (i=0; i<lines && i<mix.count; i++) {
+ show_ps(mix.tb[i]);
+ xputc('\r');
+ }
+
+ if (TT.iotop.n && !--TT.iotop.n) {
+ done++;
+ break;
+ }
+
+ // Get current time in miliseconds
+ clock_gettime(CLOCK_MONOTONIC, &ts);
+ now = ts.tv_sec*1000+ts.tv_nsec/1000000;
+ if (timeout<=now) timeout += TT.iotop.d;
+ if (timeout<=now) timeout = now+TT.iotop.d;
+
+ i = scan_key_getsize(scratch, timeout-now, &TT.width, &TT.height);
+ if (i==-1 || i==3 || toupper(i)=='Q') {
+ done++;
+ break;
+ }
+ if (i==-2) break;
+
+ // Flush unknown escape sequences.
+ if (i==27) {
+ while (0<scan_key_getsize(scratch, 0, &TT.width, &TT.height));
+ continue;
+ }
+
+ i -= 256;
+ if (i == KEY_LEFT) setsort(TT.sortpos-1);
+ else if (i == KEY_RIGHT) setsort(TT.sortpos+1);
+ else continue;
+ break;
+ }
- for (i=0; i<lines && i<mix.count; i++) show_ps(mix.tb[i]);
free(mix.tb);
for (i=0; i<plold->count; i++) free(plold->tb[i]);
free(plold->tb);
-
- if (TT.iotop.n) if (!--TT.iotop.n) break;
- msleep(1000*TT.iotop.d);
- }
+ } while (!done);
+ if (!(toys.optflags&FLAG_b)) tty_reset();
}