From 4a13ca98e18cea4acc8d605653d0ee8425e34f59 Mon Sep 17 00:00:00 2001 From: Rob Landley Date: Thu, 28 Jan 2016 22:10:06 -0600 Subject: Add SIGWINCH support to top, and implement -o and -n in pgrep/pkill. --- lib/interestingtimes.c | 15 +++++--- lib/net.c | 1 + toys/posix/ps.c | 94 ++++++++++++++++++++++++++++++-------------------- 3 files changed, 68 insertions(+), 42 deletions(-) diff --git a/lib/interestingtimes.c b/lib/interestingtimes.c index 93e2ec52..c4ea2c27 100644 --- a/lib/interestingtimes.c +++ b/lib/interestingtimes.c @@ -67,10 +67,14 @@ int scan_key_getsize(char *scratch, int miliwait, unsigned *xx, unsigned *yy) { int key; - while (512&(key = scan_key(scratch, miliwait))) { - if (key<0) break; - if (xx) *xx = (key>>10)&1023; - if (yy) *yy = (key>>20)&1023; + if (512&(key = scan_key(scratch, miliwait))) { + if (key>0) { + if (xx) *xx = (key>>10)&1023; + if (yy) *yy = (key>>20)&1023; + toys.signal = SIGWINCH; + + return -3; + } } return key; @@ -195,7 +199,8 @@ int scan_key(char *scratch, int miliwait) // Read 1 byte so we don't overshoot sequence match. (We can deviate // and fail to match, but match consumes entire buffer.) - if (1 != read(0, scratch+1+*scratch, 1)) return -1; + if (toys.signal || 1 != read(0, scratch+1+*scratch, 1)) + return toys.signal ? -3 : -1; ++*scratch; } diff --git a/lib/net.c b/lib/net.c index facb0968..2e72b268 100644 --- a/lib/net.c +++ b/lib/net.c @@ -49,6 +49,7 @@ int xpoll(struct pollfd *fds, int nfds, int timeout) for (;;) { if (0>(i = poll(fds, nfds, timeout))) { + if (toys.signal) return i; if (errno != EINTR && errno != ENOMEM) perror_exit("xpoll"); else if (timeout>0) timeout--; } else return i; diff --git a/toys/posix/ps.c b/toys/posix/ps.c index c95f73f5..f99a2168 100644 --- a/toys/posix/ps.c +++ b/toys/posix/ps.c @@ -41,13 +41,14 @@ * TODO: iotop: Window size change: respond immediately. Why not padding * at right edge? (Not adjusting to screen size at all? Header wraps?) * TODO: top: thread support and SMP + * TODO: pgrep -f only searches the amount of cmdline that fits in toybuf. USE_PS(NEWTOY(ps, "k(sort)*P(ppid)*aAdeflMno*O*p(pid)*s*t*u*U*g*G*wZ[!ol][+Ae]", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_LOCALE)) // stayroot because iotop needs root to read other process' proc/$$/io USE_TOP(NEWTOY(top, ">0m" "k*o*p*u*s#<1=9d#=3<1n#<1bq", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_LOCALE)) USE_IOTOP(NEWTOY(iotop, ">0AaKO" "k*o*p*u*s#<1=7d#=3<1n#<1bq", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_STAYROOT|TOYFLAG_LOCALE)) -USE_PGREP(NEWTOY(pgrep, "?cld:u*U*t*s*P*g*G*fnovxL:", TOYFLAG_USR|TOYFLAG_BIN)) -USE_PKILL(NEWTOY(pkill, "Vu*U*t*s*P*g*G*fnovxl:", TOYFLAG_USR|TOYFLAG_BIN)) +USE_PGREP(NEWTOY(pgrep, "?cld:u*U*t*s*P*g*G*fnovxL:[-no]", TOYFLAG_USR|TOYFLAG_BIN)) +USE_PKILL(NEWTOY(pkill, "Vu*U*t*s*P*g*G*fnovxl:[-no]", TOYFLAG_USR|TOYFLAG_BIN)) config PS bool "ps" @@ -232,8 +233,6 @@ GLOBALS( struct arg_list *p; struct arg_list *o; struct arg_list *k; - - long long milistart; } top; struct{ char *L; @@ -246,9 +245,9 @@ GLOBALS( struct arg_list *u; char *d; - void *regexes; + void *regexes, *snapshot; int signal; - pid_t self; + pid_t self, match; } pgrep; }; @@ -257,7 +256,7 @@ GLOBALS( unsigned width, height; dev_t tty; void *fields, *kfields; - long long ticks, bits; + long long ticks, bits, time; int kcount, forcek, sortpos; int (*match_process)(long long *slot); void (*show_process)(void *tb); @@ -542,6 +541,7 @@ static void show_ps(struct carveup *tb) else width -= printf("%*.*s", pad, len, out); if (!width) break; } + xputc(TT.time ? '\r' : '\n'); } // dirtree callback: read data about process to display, store, or discard it. @@ -756,7 +756,6 @@ static int get_ps(struct dirtree *new) TT.kcount++; if (TT.show_process) { TT.show_process(tb); - xputc('\n'); return 0; } @@ -1057,7 +1056,7 @@ void ps_main(void) // Calculate seen fields bit array, and if we aren't deferring printing // print headers now (for low memory/nommu systems). TT.bits = get_headers(TT.fields, toybuf, sizeof(toybuf)); - if (!(toys.optflags&FLAG_M)) printf("%s\n", toybuf); + if (!(toys.optflags&FLAG_M)) printf("%.*s\n", TT.width, toybuf); if (!(toys.optflags&(FLAG_k|FLAG_M))) TT.show_process = (void *)show_ps; TT.match_process = ps_match_process; dt = dirtree_read("/proc", get_ps); @@ -1078,7 +1077,7 @@ void ps_main(void) // Now that we've recalculated field widths, re-pad headers again get_headers(TT.fields, toybuf, sizeof(toybuf)); - printf("%s\n", toybuf); + printf("%.*s\n", TT.width, toybuf); } if (toys.optflags&FLAG_k) @@ -1086,7 +1085,6 @@ void ps_main(void) for (i = 0; iname == 't') { @@ -1332,15 +1337,12 @@ static void top_common( } *pos = 0; lines = header_line(lines, 1); - - if (!(toys.optflags&FLAG_b)) - terminal_probesize(&TT.width, &TT.height); } if (!recalc) printf("\033[%dH\033[J", 1+TT.height-lines); recalc = 1; for (i = 0; islot, TT.pgrep.signal)) { + char *s = num_to_sig(TT.pgrep.signal); + + if (!s) sprintf(s = toybuf, "%d", TT.pgrep.signal); + perror_msg("%s->%lld", s, *tb->slot); + } + } + if (!(toys.optflags&FLAG_c) && (!TT.pgrep.signal || TT.tty)) { + printf("%lld", *tb->slot); + if (toys.optflags&FLAG_l) + printf(" %s", tb->str+tb->offset[4]*!!(toys.optflags&FLAG_f)); + + printf("%s", TT.pgrep.d ? TT.pgrep.d : "\n"); + } +} + +static void match_pgrep(struct carveup *tb) { regmatch_t match; struct regex_list *reg; - char *name = tb->str; + char *name = tb->str+tb->offset[4]*!!(toys.optflags&FLAG_f);; // Never match ourselves. if (TT.pgrep.self == *tb->slot) return; - if (toys.optflags&FLAG_f) name += tb->offset[4]; - if (TT.pgrep.regexes) { for (reg = TT.pgrep.regexes; reg; reg = reg->next) { if (regexec(®->reg, name, 1, &match, 0)) continue; @@ -1495,20 +1516,15 @@ static void show_pgrep(struct carveup *tb) // Repurpose a field for -c count TT.sortpos++; - if (TT.pgrep.signal) { - if (kill(*tb->slot, TT.pgrep.signal)) { - char *s = num_to_sig(TT.pgrep.signal); - - if (!s) sprintf(s = toybuf, "%d", TT.pgrep.signal); - perror_msg("%s->%lld", s, *tb->slot); - } - } - if (!(toys.optflags&FLAG_c) && (!TT.pgrep.signal || TT.tty)) { - printf("%lld", *tb->slot); - if (toys.optflags&FLAG_l) printf(" %s", name); - - printf("%s", TT.pgrep.d ? TT.pgrep.d : "\n"); - } + if (toys.optflags&(FLAG_n|FLAG_o)) { + long long ll = tb->slot[SLOT_starttime]; + + if (toys.optflags&FLAG_o) ll *= -1; + if (TT.time && TT.time>ll) return; + TT.time = ll; + free(TT.pgrep.snapshot); + TT.pgrep.snapshot = xmemdup(toybuf, (name+strlen(name)+1)-toybuf); + } else do_pgk(tb); } static int pgrep_match_process(long long *slot) @@ -1549,10 +1565,14 @@ void pgrep_main(void) TT.pgrep.regexes = reg; } TT.match_process = pgrep_match_process; - TT.show_process = (void *)show_pgrep; + TT.show_process = (void *)match_pgrep; dirtree_read("/proc", get_ps); if (toys.optflags&FLAG_c) printf("%d\n", TT.sortpos); + if (TT.pgrep.snapshot) { + do_pgk(TT.pgrep.snapshot); + if (CFG_TOYBOX_FREE) free(TT.pgrep.snapshot); + } if (TT.pgrep.d) xputc('\n'); } -- cgit v1.2.3