1303 files changed, 32187 insertions, 57138 deletions
diff --git a/procps/nmeter.c b/procps/nmeter.c index 5d5b83b..3eac2d3 100644 --- a/procps/nmeter.c +++ b/procps/nmeter.c @@ -21,7 +21,7 @@ //usage:#define nmeter_full_usage "\n\n" //usage: "Monitor system in real time" //usage: "\n" -//usage: "\n -d MSEC Milliseconds between updates (default:1000)" +//usage: "\n -d MSEC Milliseconds between updates, default:1000, none:-1" //usage: "\n" //usage: "\nFormat specifiers:" //usage: "\n %Nc or %[cN] CPU. N - bar size (default:10)" @@ -53,6 +53,7 @@ // totalswap=134209536, freeswap=134209536, procs=157}) #include "libbb.h" +#include "common_bufsiz.h" typedef unsigned long long ullong; @@ -83,10 +84,10 @@ struct globals { smallint is26; // 1 if sample delay is not an integer fraction of a second smallint need_seconds; + char final_char; char *cur_outbuf; - const char *final_str; int delta; - int deltanz; + unsigned deltanz; struct timeval tv; #define first_proc_file proc_stat proc_file proc_stat; // Must match the order of proc_name's! @@ -101,9 +102,6 @@ struct globals { #define is26 (G.is26 ) #define need_seconds (G.need_seconds ) #define cur_outbuf (G.cur_outbuf ) -#define final_str (G.final_str ) -#define delta (G.delta ) -#define deltanz (G.deltanz ) #define tv (G.tv ) #define proc_stat (G.proc_stat ) #define proc_loadavg (G.proc_loadavg ) @@ -111,16 +109,15 @@ struct globals { #define proc_meminfo (G.proc_meminfo ) #define proc_diskstats (G.proc_diskstats ) #define proc_sys_fs_filenr (G.proc_sys_fs_filenr) +#define outbuf bb_common_bufsiz1 #define INIT_G() do { \ + setup_common_bufsiz(); \ SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \ cur_outbuf = outbuf; \ - final_str = "\n"; \ - deltanz = delta = 1000000; \ + G.final_char = '\n'; \ + G.deltanz = G.delta = 1000000; \ } while (0) -// We depend on this being a char[], not char* - we take sizeof() of it -#define outbuf bb_common_bufsiz1 - static inline void reset_outbuf(void) { cur_outbuf = outbuf; @@ -142,16 +139,16 @@ static void print_outbuf(void) static void put(const char *s) { - int sz = strlen(s); - if (sz > outbuf + sizeof(outbuf) - cur_outbuf) - sz = outbuf + sizeof(outbuf) - cur_outbuf; - memcpy(cur_outbuf, s, sz); - cur_outbuf += sz; + char *p = cur_outbuf; + int sz = outbuf + COMMON_BUFSIZE - p; + while (*s && --sz >= 0) + *p++ = *s++; + cur_outbuf = p; } static void put_c(char c) { - if (cur_outbuf < outbuf + sizeof(outbuf)) + if (cur_outbuf < outbuf + COMMON_BUFSIZE) *cur_outbuf++ = c; } @@ -208,65 +205,50 @@ static ullong read_after_slash(const char *p) return strtoull(p+1, NULL, 10); } -enum conv_type { conv_decimal, conv_slash }; +enum conv_type { + conv_decimal = 0, + conv_slash = 1 +}; // Reads decimal values from line. Values start after key, for example: // "cpu 649369 0 341297 4336769..." - key is "cpu" here. -// Values are stored in vec[]. arg_ptr has list of positions -// we are interested in: for example: 1,2,5 - we want 1st, 2nd and 5th value. -static int vrdval(const char* p, const char* key, - enum conv_type conv, ullong *vec, va_list arg_ptr) +// Values are stored in vec[]. +// posbits is a bit lit of positions we are interested in. +// for example: 00100110 - we want 1st, 2nd and 5th value. +// posbits.bit0 encodes conversion type. +static int rdval(const char* p, const char* key, ullong *vec, long posbits) { - int indexline; - int indexnext; + unsigned curpos; p = strstr(p, key); if (!p) return 1; p += strlen(key); - indexline = 1; - indexnext = va_arg(arg_ptr, int); + curpos = 1 << 1; while (1) { while (*p == ' ' || *p == '\t') p++; if (*p == '\n' || *p == '\0') break; - if (indexline == indexnext) { // read this value - *vec++ = conv==conv_decimal ? + if (curpos & posbits) { // read this value + *vec++ = (posbits & 1) == conv_decimal ? strtoull(p, NULL, 10) : read_after_slash(p); - indexnext = va_arg(arg_ptr, int); + posbits -= curpos; + if (posbits <= 1) + return 0; } - while (*p > ' ') p++; // skip over value - indexline++; + while (*p > ' ') // skip over the value + p++; + curpos <<= 1; } return 0; } -// Parses files with lines like "cpu0 21727 0 15718 1813856 9461 10485 0 0": -// rdval(file_contents, "string_to_find", result_vector, value#, value#...) -// value# start with 1 -static int rdval(const char* p, const char* key, ullong *vec, ...) -{ - va_list arg_ptr; - int result; - - va_start(arg_ptr, vec); - result = vrdval(p, key, conv_decimal, vec, arg_ptr); - va_end(arg_ptr); - - return result; -} - // Parses files with lines like "... ... ... 3/148 ...." -static int rdval_loadavg(const char* p, ullong *vec, ...) +static int rdval_loadavg(const char* p, ullong *vec, long posbits) { - va_list arg_ptr; int result; - - va_start(arg_ptr, vec); - result = vrdval(p, "", conv_slash, vec, arg_ptr); - va_end(arg_ptr); - + result = rdval(p, "", vec, posbits | conv_slash); return result; } @@ -337,7 +319,6 @@ static void scale(ullong ul) put(buf); } - #define S_STAT(a) \ typedef struct a { \ struct s_stat *next; \ @@ -359,21 +340,12 @@ static s_stat* init_literal(void) return (s_stat*)s; } -static s_stat* init_delay(const char *param) -{ - delta = strtoul(param, NULL, 0) * 1000; /* param can be "" */ - deltanz = delta > 0 ? delta : 1; - need_seconds = (1000000%deltanz) != 0; - return NULL; -} - static s_stat* init_cr(const char *param UNUSED_PARAM) { - final_str = "\r"; - return (s_stat*)0; + G.final_char = '\r'; + return NULL; } - // user nice system idle iowait irq softirq (last 3 only in 2.6) //cpu 649369 0 341297 4336769 11640 7122 1183 //cpuN 649369 0 341297 4336769 11640 7122 1183 @@ -381,10 +353,9 @@ enum { CPU_FIELDCNT = 7 }; S_STAT(cpu_stat) ullong old[CPU_FIELDCNT]; int bar_sz; - char *bar; + char bar[1]; S_STAT_END(cpu_stat) - static void FAST_FUNC collect_cpu(cpu_stat *s) { ullong data[CPU_FIELDCNT] = { 0, 0, 0, 0, 0, 0, 0 }; @@ -395,7 +366,15 @@ static void FAST_FUNC collect_cpu(cpu_stat *s) char *bar = s->bar; int i; - if (rdval(get_file(&proc_stat), "cpu ", data, 1, 2, 3, 4, 5, 6, 7)) { + if (rdval(get_file(&proc_stat), "cpu ", data, 0 + | (1 << 1) + | (1 << 2) + | (1 << 3) + | (1 << 4) + | (1 << 5) + | (1 << 6) + | (1 << 7)) + ) { put_question_marks(bar_sz); return; } @@ -438,22 +417,20 @@ static void FAST_FUNC collect_cpu(cpu_stat *s) put(s->bar); } - static s_stat* init_cpu(const char *param) { int sz; - cpu_stat *s = xzalloc(sizeof(*s)); - s->collect = collect_cpu; + cpu_stat *s; sz = strtoul(param, NULL, 0); /* param can be "" */ if (sz < 10) sz = 10; if (sz > 1000) sz = 1000; - s->bar = xzalloc(sz+1); + s = xzalloc(sizeof(*s) + sz); /*s->bar[sz] = '\0'; - xzalloc did it */ s->bar_sz = sz; + s->collect = collect_cpu; return (s_stat*)s; } - S_STAT(int_stat) ullong old; int no; @@ -464,7 +441,7 @@ static void FAST_FUNC collect_int(int_stat *s) ullong data[1]; ullong old; - if (rdval(get_file(&proc_stat), "intr", data, s->no)) { + if (rdval(get_file(&proc_stat), "intr", data, 1 << s->no)) { put_question_marks(4); return; } @@ -488,7 +465,6 @@ static s_stat* init_int(const char *param) return (s_stat*)s; } - S_STAT(ctx_stat) ullong old; S_STAT_END(ctx_stat) @@ -498,7 +474,7 @@ static void FAST_FUNC collect_ctx(ctx_stat *s) ullong data[1]; ullong old; - if (rdval(get_file(&proc_stat), "ctxt", data, 1)) { + if (rdval(get_file(&proc_stat), "ctxt", data, 1 << 1)) { put_question_marks(4); return; } @@ -516,7 +492,6 @@ static s_stat* init_ctx(const char *param UNUSED_PARAM) return (s_stat*)s; } - S_STAT(blk_stat) const char* lookfor; ullong old[2]; @@ -530,7 +505,10 @@ static void FAST_FUNC collect_blk(blk_stat *s) if (is26) { i = rdval_diskstats(get_file(&proc_diskstats), data); } else { - i = rdval(get_file(&proc_stat), s->lookfor, data, 1, 2); + i = rdval(get_file(&proc_stat), s->lookfor, data, 0 + | (1 << 1) + | (1 << 2) + ); // Linux 2.4 reports bio in Kbytes, convert to sectors: data[0] *= 2; data[1] *= 2; @@ -559,7 +537,6 @@ static s_stat* init_blk(const char *param UNUSED_PARAM) return (s_stat*)s; } - S_STAT(fork_stat) ullong old; S_STAT_END(fork_stat) @@ -568,7 +545,7 @@ static void FAST_FUNC collect_thread_nr(fork_stat *s UNUSED_PARAM) { ullong data[1]; - if (rdval_loadavg(get_file(&proc_loadavg), data, 4)) { + if (rdval_loadavg(get_file(&proc_loadavg), data, 1 << 4)) { put_question_marks(4); return; } @@ -580,7 +557,7 @@ static void FAST_FUNC collect_fork(fork_stat *s) ullong data[1]; ullong old; - if (rdval(get_file(&proc_stat), "processes", data, 1)) { + if (rdval(get_file(&proc_stat), "processes", data, 1 << 1)) { put_question_marks(4); return; } @@ -602,7 +579,6 @@ static s_stat* init_fork(const char *param) return (s_stat*)s; } - S_STAT(if_stat) ullong old[4]; const char *device; @@ -614,7 +590,12 @@ static void FAST_FUNC collect_if(if_stat *s) ullong data[4]; int i; - if (rdval(get_file(&proc_net_dev), s->device_colon, data, 1, 3, 9, 11)) { + if (rdval(get_file(&proc_net_dev), s->device_colon, data, 0 + | (1 << 1) + | (1 << 3) + | (1 << 9) + | (1 << 11)) + ) { put_question_marks(10); return; } @@ -644,7 +625,6 @@ static s_stat* init_if(const char *device) return (s_stat*)s; } - S_STAT(mem_stat) char opt; S_STAT_END(mem_stat) @@ -692,7 +672,7 @@ static void FAST_FUNC collect_mem(mem_stat *s) ullong m_cached = 0; ullong m_slab = 0; - if (rdval(get_file(&proc_meminfo), "MemTotal:", &m_total, 1)) { + if (rdval(get_file(&proc_meminfo), "MemTotal:", &m_total, 1 << 1)) { put_question_marks(4); return; } @@ -701,10 +681,10 @@ static void FAST_FUNC collect_mem(mem_stat *s) return; } - if (rdval(proc_meminfo.file, "MemFree:", &m_free , 1) - || rdval(proc_meminfo.file, "Buffers:", &m_bufs , 1) - || rdval(proc_meminfo.file, "Cached:", &m_cached, 1) - || rdval(proc_meminfo.file, "Slab:", &m_slab , 1) + if (rdval(proc_meminfo.file, "MemFree:", &m_free , 1 << 1) + || rdval(proc_meminfo.file, "Buffers:", &m_bufs , 1 << 1) + || rdval(proc_meminfo.file, "Cached:", &m_cached, 1 << 1) + || rdval(proc_meminfo.file, "Slab:", &m_slab , 1 << 1) ) { put_question_marks(4); return; @@ -727,7 +707,6 @@ static s_stat* init_mem(const char *param) return (s_stat*)s; } - S_STAT(swp_stat) S_STAT_END(swp_stat) @@ -735,8 +714,8 @@ static void FAST_FUNC collect_swp(swp_stat *s UNUSED_PARAM) { ullong s_total[1]; ullong s_free[1]; - if (rdval(get_file(&proc_meminfo), "SwapTotal:", s_total, 1) - || rdval(proc_meminfo.file, "SwapFree:" , s_free, 1) + if (rdval(get_file(&proc_meminfo), "SwapTotal:", s_total, 1 << 1) + || rdval(proc_meminfo.file, "SwapFree:" , s_free, 1 << 1) ) { put_question_marks(4); return; @@ -751,7 +730,6 @@ static s_stat* init_swp(const char *param UNUSED_PARAM) return (s_stat*)s; } - S_STAT(fd_stat) S_STAT_END(fd_stat) @@ -759,7 +737,10 @@ static void FAST_FUNC collect_fd(fd_stat *s UNUSED_PARAM) { ullong data[2]; - if (rdval(get_file(&proc_sys_fs_filenr), "", data, 1, 2)) { + if (rdval(get_file(&proc_sys_fs_filenr), "", data, 0 + | (1 << 1) + | (1 << 2)) + ) { put_question_marks(4); return; } @@ -774,17 +755,16 @@ static s_stat* init_fd(const char *param UNUSED_PARAM) return (s_stat*)s; } - S_STAT(time_stat) - int prec; - int scale; + unsigned prec; + unsigned scale; S_STAT_END(time_stat) static void FAST_FUNC collect_time(time_stat *s) { char buf[sizeof("12:34:56.123456")]; struct tm* tm; - int us = tv.tv_usec + s->scale/2; + unsigned us = tv.tv_usec + s->scale/2; time_t t = tv.tv_sec; if (us >= 1000000) { @@ -825,11 +805,9 @@ static void FAST_FUNC collect_info(s_stat *s) } } - typedef s_stat* init_func(const char *param); -// Deprecated %NNNd is to be removed, -d MSEC supersedes it -static const char options[] ALIGN1 = "ncmsfixptbdr"; +static const char options[] ALIGN1 = "ncmsfixptbr"; static init_func *const init_functions[] = { init_if, init_cpu, @@ -841,7 +819,6 @@ static init_func *const init_functions[] = { init_fork, init_time, init_blk, - init_delay, init_cr }; @@ -864,8 +841,11 @@ int nmeter_main(int argc UNUSED_PARAM, char **argv) is26 = (strstr(buf, " 2.4.") == NULL); } - if (getopt32(argv, "d:", &opt_d)) - init_delay(opt_d); + if (getopt32(argv, "d:", &opt_d)) { + G.delta = xatoi(opt_d) * 1000; + G.deltanz = G.delta > 0 ? G.delta : 1; + need_seconds = (1000000 % G.deltanz) != 0; + } argv += optind; if (!argv[0]) @@ -920,8 +900,8 @@ int nmeter_main(int argc UNUSED_PARAM, char **argv) last->next = s; last = s; } else { - // %NNNNd or %r option. remove it from string - strcpy(prev + strlen(prev), cur); + // %r option. remove it from string + overlapping_strcpy(prev + strlen(prev), cur); cur = prev; } } @@ -939,15 +919,15 @@ int nmeter_main(int argc UNUSED_PARAM, char **argv) // Generate first samples but do not print them, they're bogus collect_info(first); reset_outbuf(); - if (delta >= 0) { + if (G.delta >= 0) { gettimeofday(&tv, NULL); - usleep(delta > 1000000 ? 1000000 : delta - tv.tv_usec%deltanz); + usleep(G.delta > 1000000 ? 1000000 : G.delta - tv.tv_usec % G.deltanz); } while (1) { gettimeofday(&tv, NULL); collect_info(first); - put(final_str); + put_c(G.final_char); print_outbuf(); // Negative delta -> no usleep at all @@ -955,18 +935,18 @@ int nmeter_main(int argc UNUSED_PARAM, char **argv) // time resolution ;) // TODO: detect and avoid useless updates // (like: nothing happens except time) - if (delta >= 0) { + if (G.delta >= 0) { int rem; // can be commented out, will sacrifice sleep time precision a bit gettimeofday(&tv, NULL); if (need_seconds) - rem = delta - ((ullong)tv.tv_sec*1000000 + tv.tv_usec) % deltanz; + rem = G.delta - ((ullong)tv.tv_sec*1000000 + tv.tv_usec) % G.deltanz; else - rem = delta - tv.tv_usec%deltanz; + rem = G.delta - (unsigned)tv.tv_usec % G.deltanz; // Sometimes kernel wakes us up just a tiny bit earlier than asked // Do not go to very short sleep in this case - if (rem < delta/128) { - rem += delta; + if (rem < (unsigned)G.delta / 128) { + rem += G.delta; } usleep(rem); } |