aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/interestingtimes.c6
-rw-r--r--lib/lib.h1
-rwxr-xr-xscripts/make.sh2
-rw-r--r--toys/example/test_scankey.c2
-rw-r--r--toys/other/hexedit.c2
-rw-r--r--toys/posix/ps.c113
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();
diff --git a/lib/lib.h b/lib/lib.h
index ade7c59b..a6998a86 100644
--- a/lib/lib.h
+++ b/lib/lib.h
@@ -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();
}