diff options
-rw-r--r-- | lib/interestingtimes.c | 6 | ||||
-rw-r--r-- | lib/lib.h | 1 | ||||
-rwxr-xr-x | scripts/make.sh | 2 | ||||
-rw-r--r-- | toys/example/test_scankey.c | 2 | ||||
-rw-r--r-- | toys/other/hexedit.c | 2 | ||||
-rw-r--r-- | toys/posix/ps.c | 113 |
6 files changed, 104 insertions, 22 deletions
diff --git a/lib/interestingtimes.c b/lib/interestingtimes.c index 70fd4f9b..93e2ec52 100644 --- a/lib/interestingtimes.c +++ b/lib/interestingtimes.c @@ -110,6 +110,11 @@ int set_terminal(int fd, int raw, struct termios *old) return tcsetattr(fd, TCSANOW, &termio); } +void xset_terminal(int fd, int raw, struct termios *old) +{ + if (-1 == set_terminal(fd, raw, old)) perror_exit("bad tty fd#%d", fd); +} + struct scan_key_list { char *name, *seq; } static const scan_key_list[] = TAGGED_ARRAY(KEY, @@ -225,6 +230,7 @@ void tty_reset(void) fflush(0); } +// If you call set_terminal(), use sigatexit(tty_sigreset); void tty_sigreset(int i) { tty_reset(); @@ -224,6 +224,7 @@ int terminal_size(unsigned *xx, unsigned *yy); int terminal_probesize(unsigned *xx, unsigned *yy); int scan_key_getsize(char *scratch, int miliwait, unsigned *xx, unsigned *yy); int set_terminal(int fd, int raw, struct termios *old); +void xset_terminal(int fd, int raw, struct termios *old); int scan_key(char *scratch, int miliwait); void tty_esc(char *s); void tty_jump(int x, int y); diff --git a/scripts/make.sh b/scripts/make.sh index efa70904..e827a5c9 100755 --- a/scripts/make.sh +++ b/scripts/make.sh @@ -93,7 +93,7 @@ then # for it. > generated/optlibs.dat - for i in util crypt m resolv selinux smack attr + for i in util crypt m resolv selinux smack attr rt do echo "int main(int argc, char *argv[]) {return 0;}" | \ ${CROSS_COMPILE}${CC} $CFLAGS -xc - -o generated/libprobe -Wl,--as-needed -l$i > /dev/null 2>/dev/null && diff --git a/toys/example/test_scankey.c b/toys/example/test_scankey.c index 57177416..17eb0cfd 100644 --- a/toys/example/test_scankey.c +++ b/toys/example/test_scankey.c @@ -33,7 +33,7 @@ void test_scankey_main(void) tty_esc("?25l"); // hide cursor tty_esc("0m"); // reset color to default tty_esc("2J"); // Clear screen - set_terminal(1, 1, 0); // Raw mode + xset_terminal(1, 1, 0); // Raw mode for (;;) { tty_jump(x, y); diff --git a/toys/other/hexedit.c b/toys/other/hexedit.c index 3c362dbd..c86d75e8 100644 --- a/toys/other/hexedit.c +++ b/toys/other/hexedit.c @@ -125,7 +125,7 @@ void hexedit_main(void) tty_esc("0m"); tty_esc("?25l"); fflush(0); - set_terminal(1, 1, 0); + xset_terminal(1, 1, 0); if ((TT.len = fdlength(fd))<0) error_exit("bad length"); if (sizeof(long)==32 && TT.len>SIZE_MAX) TT.len = SIZE_MAX; 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(); } |