consolidate ESC sequences
[oweals/busybox.git] / procps / nmeter.c
index 205cb8251760946c55c5ef755907a4f2f2a7e264..bb1e819a6fb77d49b2e800fd079afad862e20423 100644 (file)
 //  totalram=2107416576, freeram=211525632, sharedram=0, bufferram=157204480}
 //  totalswap=134209536, freeswap=134209536, procs=157})
 
-#include <time.h>
 #include "libbb.h"
 
 typedef unsigned long long ullong;
 
-enum { PROC_FILE_SIZE = 4096 };
+enum {  /* Preferably use powers of 2 */
+       PROC_MIN_FILE_SIZE = 256,
+       PROC_MAX_FILE_SIZE = 16 * 1024,
+};
 
 typedef struct proc_file {
        char *file;
-       //const char *name;
+       int file_sz;
        smallint last_gen;
 } proc_file;
 
@@ -124,35 +126,47 @@ static void put_question_marks(int count)
                put_c('?');
 }
 
-static void readfile_z(char *buf, int sz, const char* fname)
+static void readfile_z(proc_file *pf, const char* fname)
 {
 // open_read_close() will do two reads in order to be sure we are at EOF,
 // and we don't need/want that.
-//     sz = open_read_close(fname, buf, sz-1);
-
-       int fd = xopen(fname, O_RDONLY);
+       int fd;
+       int sz, rdsz;
+       char *buf;
+
+       sz = pf->file_sz;
+       buf = pf->file;
+       if (!buf) {
+               buf = xmalloc(PROC_MIN_FILE_SIZE);
+               sz = PROC_MIN_FILE_SIZE;
+       }
+ again:
+       fd = xopen(fname, O_RDONLY);
        buf[0] = '\0';
-       sz = read(fd, buf, sz - 1);
-       if (sz > 0)
-               buf[sz] = '\0';
+       rdsz = read(fd, buf, sz-1);
        close(fd);
+       if (rdsz > 0) {
+               if (rdsz == sz-1 && sz < PROC_MAX_FILE_SIZE) {
+                       sz *= 2;
+                       buf = xrealloc(buf, sz);
+                       goto again;
+               }
+               buf[rdsz] = '\0';
+       }
+       pf->file_sz = sz;
+       pf->file = buf;
 }
 
 static const char* get_file(proc_file *pf)
 {
        if (pf->last_gen != gen) {
                pf->last_gen = gen;
-               // We allocate PROC_FILE_SIZE bytes. This wastes memory,
-               // but allows us to allocate only once (at first sample)
-               // per proc file, and reuse buffer for each sample
-               if (!pf->file)
-                       pf->file = xmalloc(PROC_FILE_SIZE);
-               readfile_z(pf->file, PROC_FILE_SIZE, proc_name[pf - &first_proc_file]);
+               readfile_z(pf, proc_name[pf - &first_proc_file]);
        }
        return pf->file;
 }
 
-static inline ullong read_after_slash(const char *p)
+static ullong read_after_slash(const char *p)
 {
        p = strchr(p, '/');
        if (!p) return 0;
@@ -267,14 +281,14 @@ static void scale(ullong ul)
 #define S_STAT(a) \
 typedef struct a { \
        struct s_stat *next; \
-       void (*collect)(struct a *s); \
+       void (*collect)(struct a *s) FAST_FUNC; \
        const char *label;
 #define S_STAT_END(a) } a;
 
 S_STAT(s_stat)
 S_STAT_END(s_stat)
 
-static void collect_literal(s_stat *s ATTRIBUTE_UNUSED)
+static void FAST_FUNC collect_literal(s_stat *s UNUSED_PARAM)
 {
 }
 
@@ -293,7 +307,7 @@ static s_stat* init_delay(const char *param)
        return NULL;
 }
 
-static s_stat* init_cr(const char *param ATTRIBUTE_UNUSED)
+static s_stat* init_cr(const char *param UNUSED_PARAM)
 {
        final_str = "\r";
        return (s_stat*)0;
@@ -311,7 +325,7 @@ S_STAT(cpu_stat)
 S_STAT_END(cpu_stat)
 
 
-static void collect_cpu(cpu_stat *s)
+static void FAST_FUNC collect_cpu(cpu_stat *s)
 {
        ullong data[CPU_FIELDCNT] = { 0, 0, 0, 0, 0, 0, 0 };
        unsigned frac[CPU_FIELDCNT] = { 0, 0, 0, 0, 0, 0, 0 };
@@ -385,7 +399,7 @@ S_STAT(int_stat)
        int no;
 S_STAT_END(int_stat)
 
-static void collect_int(int_stat *s)
+static void FAST_FUNC collect_int(int_stat *s)
 {
        ullong data[1];
        ullong old;
@@ -419,7 +433,7 @@ S_STAT(ctx_stat)
        ullong old;
 S_STAT_END(ctx_stat)
 
-static void collect_ctx(ctx_stat *s)
+static void FAST_FUNC collect_ctx(ctx_stat *s)
 {
        ullong data[1];
        ullong old;
@@ -435,7 +449,7 @@ static void collect_ctx(ctx_stat *s)
        scale(data[0] - old);
 }
 
-static s_stat* init_ctx(const char *param ATTRIBUTE_UNUSED)
+static s_stat* init_ctx(const char *param UNUSED_PARAM)
 {
        ctx_stat *s = xzalloc(sizeof(*s));
        s->collect = collect_ctx;
@@ -448,7 +462,7 @@ S_STAT(blk_stat)
        ullong old[2];
 S_STAT_END(blk_stat)
 
-static void collect_blk(blk_stat *s)
+static void FAST_FUNC collect_blk(blk_stat *s)
 {
        ullong data[2];
        int i;
@@ -477,7 +491,7 @@ static void collect_blk(blk_stat *s)
        scale(data[1]*512);
 }
 
-static s_stat* init_blk(const char *param ATTRIBUTE_UNUSED)
+static s_stat* init_blk(const char *param UNUSED_PARAM)
 {
        blk_stat *s = xzalloc(sizeof(*s));
        s->collect = collect_blk;
@@ -490,7 +504,7 @@ S_STAT(fork_stat)
        ullong old;
 S_STAT_END(fork_stat)
 
-static void collect_thread_nr(fork_stat *s ATTRIBUTE_UNUSED)
+static void FAST_FUNC collect_thread_nr(fork_stat *s UNUSED_PARAM)
 {
        ullong data[1];
 
@@ -501,7 +515,7 @@ static void collect_thread_nr(fork_stat *s ATTRIBUTE_UNUSED)
        scale(data[0]);
 }
 
-static void collect_fork(fork_stat *s)
+static void FAST_FUNC collect_fork(fork_stat *s)
 {
        ullong data[1];
        ullong old;
@@ -535,7 +549,7 @@ S_STAT(if_stat)
        char *device_colon;
 S_STAT_END(if_stat)
 
-static void collect_if(if_stat *s)
+static void FAST_FUNC collect_if(if_stat *s)
 {
        ullong data[4];
        int i;
@@ -610,7 +624,7 @@ S_STAT_END(mem_stat)
 //HugePages_Total:     0
 //HugePages_Free:      0
 //Hugepagesize:     4096 kB
-static void collect_mem(mem_stat *s)
+static void FAST_FUNC collect_mem(mem_stat *s)
 {
        ullong m_total = 0;
        ullong m_free = 0;
@@ -657,7 +671,7 @@ static s_stat* init_mem(const char *param)
 S_STAT(swp_stat)
 S_STAT_END(swp_stat)
 
-static void collect_swp(swp_stat *s ATTRIBUTE_UNUSED)
+static void FAST_FUNC collect_swp(swp_stat *s UNUSED_PARAM)
 {
        ullong s_total[1];
        ullong s_free[1];
@@ -670,7 +684,7 @@ static void collect_swp(swp_stat *s ATTRIBUTE_UNUSED)
        scale((s_total[0]-s_free[0]) << 10);
 }
 
-static s_stat* init_swp(const char *param ATTRIBUTE_UNUSED)
+static s_stat* init_swp(const char *param UNUSED_PARAM)
 {
        swp_stat *s = xzalloc(sizeof(*s));
        s->collect = collect_swp;
@@ -681,7 +695,7 @@ static s_stat* init_swp(const char *param ATTRIBUTE_UNUSED)
 S_STAT(fd_stat)
 S_STAT_END(fd_stat)
 
-static void collect_fd(fd_stat *s ATTRIBUTE_UNUSED)
+static void FAST_FUNC collect_fd(fd_stat *s UNUSED_PARAM)
 {
        ullong data[2];
 
@@ -693,7 +707,7 @@ static void collect_fd(fd_stat *s ATTRIBUTE_UNUSED)
        scale(data[0] - data[1]);
 }
 
-static s_stat* init_fd(const char *param ATTRIBUTE_UNUSED)
+static s_stat* init_fd(const char *param UNUSED_PARAM)
 {
        fd_stat *s = xzalloc(sizeof(*s));
        s->collect = collect_fd;
@@ -706,7 +720,7 @@ S_STAT(time_stat)
        int scale;
 S_STAT_END(time_stat)
 
-static void collect_time(time_stat *s)
+static void FAST_FUNC collect_time(time_stat *s)
 {
        char buf[sizeof("12:34:56.123456")];
        struct tm* tm;
@@ -741,7 +755,7 @@ static s_stat* init_time(const char *param)
        return (s_stat*)s;
 }
 
-static void collect_info(s_stat *s)
+static void FAST_FUNC collect_info(s_stat *s)
 {
        gen ^= 1;
        while (s) {
@@ -771,7 +785,7 @@ static init_func *const init_functions[] = {
 };
 
 int nmeter_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
-int nmeter_main(int argc, char **argv)
+int nmeter_main(int argc UNUSED_PARAM, char **argv)
 {
        char buf[32];
        s_stat *first = NULL;
@@ -783,11 +797,13 @@ int nmeter_main(int argc, char **argv)
 
        xchdir("/proc");
 
-       if (argc != 2)
+       if (!argv[1])
                bb_show_usage();
 
-       if (open_read_close("version", buf, sizeof(buf)) > 0)
-               is26 = (strstr(buf, " 2.4.")==NULL);
+       if (open_read_close("version", buf, sizeof(buf)-1) > 0) {
+               buf[sizeof(buf)-1] = '\0';
+               is26 = (strstr(buf, " 2.4.") == NULL);
+       }
 
        // Can use argv[1] directly, but this will mess up
        // parameters as seen by e.g. ps. Making a copy...
@@ -800,7 +816,7 @@ int nmeter_main(int argc, char **argv)
                if (!cur)
                        break;
                if (cur[1] == '%') {    // %%
-                       strcpy(cur, cur+1);
+                       overlapping_strcpy(cur, cur + 1);
                        cur++;
                        goto again;
                }