top: use poll instead of select for waiting on one descriptor smart_ulltoa5: make it more cryptic. -50 bytes.
No binary (build failed)
—
(log yok)
| @@ -27,6 +27,7 @@ | |
| #include <stddef.h> | |
| #include <string.h> | |
| /* #include <strings.h> - said to be obsolete */ | |
| + | #include <sys/poll.h> |
| #include <sys/ioctl.h> | |
| #include <sys/mman.h> | |
| #include <sys/socket.h> | |
| @@ -284,35 +284,44 @@ void smart_ulltoa5(unsigned long long ul, char buf[5]) | |
| { | |
| const char *fmt; | |
| char c; | |
| - | unsigned v,idx = 0; |
| - | ul *= 10; |
| - | if (ul > 9999*10) { // do not scale if 9999 or less |
| - | while (ul >= 10000) { |
| + | unsigned v, u, idx = 0; |
| + | |
| + | if (ul > 9999) { // do not scale if 9999 or less |
| + | ul *= 10; |
| + | do { |
| ul /= 1024; | |
| idx++; | |
| - | } |
| + | } while (ul >= 10000); |
| } | |
| v = ul; // ullong divisions are expensive, avoid them | |
| fmt = " 123456789"; | |
| - | if (!idx) { // 9999 or less: use 1234 format |
| - | c = buf[0] = " 123456789"[v/10000]; |
| + | u = v / 10; |
| + | v = v % 10; |
| + | if (!idx) { |
| + | // 9999 or less: use "1234" format |
| + | // u is value/10, v is last digit |
| + | c = buf[0] = " 123456789"[u/100]; |
| if (c != ' ') fmt = "0123456789"; | |
| - | c = buf[1] = fmt[v/1000%10]; |
| + | c = buf[1] = fmt[u/10%10]; |
| if (c != ' ') fmt = "0123456789"; | |
| - | buf[2] = fmt[v/100%10]; |
| - | buf[3] = "0123456789"[v/10%10]; |
| + | buf[2] = fmt[u%10]; |
| + | buf[3] = "0123456789"[v]; |
| } else { | |
| - | if (v >= 10*10) { // scaled value is >=10: use 123M format |
| - | c = buf[0] = " 123456789"[v/1000]; |
| + | // u is value, v is 1/10ths (allows for 9.2M format) |
| + | if (u >= 10) { |
| + | // value is >= 10: use "123M', " 12M" formats |
| + | c = buf[0] = " 123456789"[u/100]; |
| if (c != ' ') fmt = "0123456789"; | |
| - | buf[1] = fmt[v/100%10]; |
| - | buf[2] = "0123456789"[v/10%10]; |
| - | } else { // scaled value is <10: use 1.2M format |
| - | buf[0] = "0123456789"[v/10]; |
| + | v = u % 10; |
| + | u = u / 10; |
| + | buf[1] = fmt[u%10]; |
| + | } else { |
| + | // value is < 10: use "9.2M" format |
| + | buf[0] = "0123456789"[u]; |
| buf[1] = '.'; | |
| - | buf[2] = "0123456789"[v%10]; |
| } | |
| + | buf[2] = "0123456789"[v]; |
| // see http://en.wikipedia.org/wiki/Tera | |
| buf[3] = " kMGTPEZY"[idx]; | |
| } | |
| @@ -470,7 +479,8 @@ char *xasprintf(const char *format, ...) | |
| va_end(p); | |
| #endif | |
| - | if (r < 0) bb_error_msg_and_die(bb_msg_memory_exhausted); |
| + | if (r < 0) |
| + | bb_error_msg_and_die(bb_msg_memory_exhausted); |
| return string_ptr; | |
| } | |
| @@ -448,7 +448,7 @@ static void display_status(int count, int scr_width) | |
| #endif | |
| if (s->vsz >= 100*1024) | |
| - | sprintf(vsz_str_buf, "%6ldM", s->vsz/1024); |
| + | sprintf(vsz_str_buf, "%6ldm", s->vsz/1024); |
| else | |
| sprintf(vsz_str_buf, "%7ld", s->vsz); | |
| // PID PPID USER STAT VSZ %MEM [%CPU] COMMAND | |
| @@ -519,23 +519,29 @@ int top_main(int argc, char **argv); | |
| int top_main(int argc, char **argv) | |
| { | |
| int count, lines, col; | |
| - | unsigned interval = 5; /* default update rate is 5 seconds */ |
| - | unsigned iterations = UINT_MAX; /* 2^32 iterations by default :) */ |
| + | unsigned interval; |
| + | int iterations = -1; /* infinite */ |
| char *sinterval, *siterations; | |
| #if ENABLE_FEATURE_USE_TERMIOS | |
| struct termios new_settings; | |
| - | struct timeval tv; |
| - | fd_set readfds; |
| + | struct pollfd pfd[1]; |
| unsigned char c; | |
| + | |
| + | pfd[0].fd = 0; |
| + | pfd[0].events = POLLIN; |
| #endif /* FEATURE_USE_TERMIOS */ | |
| - | interval = 5; |
| + | interval = 5; /* default update rate is 5 seconds */ |
| /* do normal option parsing */ | |
| opt_complementary = "-"; | |
| getopt32(argv, "d:n:b", &sinterval, &siterations); | |
| - | if (option_mask32 & 0x1) interval = xatou(sinterval); // -d |
| - | if (option_mask32 & 0x2) iterations = xatou(siterations); // -n |
| + | if (option_mask32 & 0x1) { |
| + | /* Need to limit it to not overflow poll timeout */ |
| + | interval = xatou16(sinterval); // -d |
| + | } |
| + | if (option_mask32 & 0x2) |
| + | iterations = xatoi_u(siterations); // -n |
| //if (option_mask32 & 0x4) // -b | |
| /* change to /proc */ | |
| @@ -584,9 +590,8 @@ int top_main(int argc, char **argv) | |
| | PSSCAN_UTIME | |
| | PSSCAN_STATE | |
| | PSSCAN_COMM | |
| - | | PSSCAN_SID |
| | PSSCAN_UIDGID | |
| - | ))) { |
| + | )) != NULL) { |
| int n = ntop; | |
| top = xrealloc(top, (++ntop) * sizeof(*top)); | |
| top[n].pid = p->pid; | |
| @@ -622,15 +627,9 @@ int top_main(int argc, char **argv) | |
| /* show status for each of the processes */ | |
| display_status(count, col); | |
| #if ENABLE_FEATURE_USE_TERMIOS | |
| - | tv.tv_sec = interval; |
| - | tv.tv_usec = 0; |
| - | FD_ZERO(&readfds); |
| - | FD_SET(0, &readfds); |
| - | select(1, &readfds, NULL, NULL, &tv); |
| - | if (FD_ISSET(0, &readfds)) { |
| - | if (read(0, &c, 1) <= 0) { /* signal */ |
| - | return EXIT_FAILURE; |
| - | } |
| + | if (poll(pfd, 1, interval * 1000) != 0) { |
| + | if (read(0, &c, 1) != 1) /* signal */ |
| + | break; |
| if (c == 'q' || c == initial_settings.c_cc[VINTR]) | |
| break; | |
| if (c == 'M') { | |
| @@ -662,7 +661,7 @@ int top_main(int argc, char **argv) | |
| #endif | |
| } | |
| } | |
| - | if (!--iterations) |
| + | if (iterations >= 0 && !--iterations) |
| break; | |
| #else | |
| sleep(interval); | |