diff -Nru eventstat-0.03.00/debian/changelog eventstat-0.03.01/debian/changelog --- eventstat-0.03.00/debian/changelog 2016-02-11 01:13:39.000000000 +0000 +++ eventstat-0.03.01/debian/changelog 2016-02-11 11:15:56.000000000 +0000 @@ -1,3 +1,23 @@ +eventstat (0.03.01-1) unstable; urgency=medium + + * Makefile: bump version + * Update manual to reflect -l -s mode on tty output + * Show long or short command line info in tty output and not just in CSV + * Add smart column resizing based on variable tty width + * Add some small ncurses helpers for top only mode + * Clean up -h info, make it 80 column friendly + * Remove a few empty lines in source + * Re-align global vars so there is less wasted padding + * Make source 80 column friendly + * es_printf: emit curses output if curses_init is true + * Reformat overly long function declarations + * Minor code improvement in set_timer_stat + * check for failed sigaction on SIGWINCH + * Improve error handling with some error message and clean up helpers + * Call endwin() only in top mode + + -- Colin King Thu, 11 Feb 2016 11:09:11 +0000 + eventstat (0.03.00-1) unstable; urgency=medium * Makefile: bump version diff -Nru eventstat-0.03.00/eventstat.8 eventstat-0.03.01/eventstat.8 --- eventstat-0.03.00/eventstat.8 2016-02-11 01:13:39.000000000 +0000 +++ eventstat-0.03.01/eventstat.8 2016-02-11 11:15:56.000000000 +0000 @@ -52,7 +52,7 @@ report just kernel threads. .TP .B \-l -report long process name from /proc/pid/cmdline in CSV output. This reports +report long process name from /proc/pid/cmdline. This reports the process name and all the command line arguments. .TP .B \-n event_count @@ -67,7 +67,7 @@ source spread sheet. .TP .B \-s -report short process name from /proc/pid/cmdline in CSV output. This reports +report short process name from /proc/pid/cmdline. This reports just the process name. .TP .B \-S diff -Nru eventstat-0.03.00/eventstat.c eventstat-0.03.01/eventstat.c --- eventstat-0.03.00/eventstat.c 2016-02-11 01:13:39.000000000 +0000 +++ eventstat-0.03.01/eventstat.c 2016-02-11 11:15:56.000000000 +0000 @@ -52,13 +52,15 @@ #define OPT_BRIEF (0x00000080) #define OPT_KERNEL (0x00000100) #define OPT_USER (0x00000200) -#define OPT_CMD (OPT_CMD_SHORT | OPT_CMD_LONG) #define OPT_SHOW_WHENCE (0x00000400) #define OPT_TOP (0x00000800) +#define OPT_CMD (OPT_CMD_SHORT | OPT_CMD_LONG) #define EVENT_BUF_SIZE (8192) -#define TIMER_REAP_AGE (600) /* How old a timer is before we reap it */ +#define TIMER_REAP_AGE (600) /* Age of timer before it is reaped */ #define TIMER_REAP_THRESHOLD (30) +#define TASK_WIDTH (15) +#define FUNC_WIDTH (25) #define _VER_(major, minor, patchlevel) \ ((major * 10000) + (minor * 100) + patchlevel) @@ -66,7 +68,8 @@ #if defined(__GNUC__) && defined(__GNUC_MINOR__) #if defined(__GNUC_PATCHLEVEL__) #define NEED_GNUC(major, minor, patchlevel) \ - _VER_(major, minor, patchlevel) <= _VER_(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__) + _VER_(major, minor, patchlevel) <= \ + _VER_(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__) #else #define NEED_GNUC(major, minor, patchlevel) \ _VER_(major, minor, patchlevel) <= _VER_(__GNUC__, __GNUC_MINOR__, 0) @@ -92,7 +95,7 @@ struct timer_info *hash_next; /* Next in hash list */ pid_t pid; char *task; /* Name of process/kernel task */ - char *task_mangled; /* Modified name of process/kernel task */ + char *task_mangled; /* Modified name of process/kernel */ char *cmdline; /* From /proc/$pid/cmdline */ char *func; /* Kernel waiting func */ char *callback; /* Kernel timer callback func */ @@ -141,16 +144,19 @@ static timer_stat_t *timer_stat_free_list; /* free list of timer stats */ static timer_info_t *timer_info_list; /* cache list of timer_info */ -static uint32_t timer_info_list_length; /* length of timer_info_list */ static timer_info_t *timer_info_hash[TABLE_SIZE]; /* hash of timer_info */ static sample_delta_list_t *sample_delta_list; /* list of samples, sorted in sample time order */ static char *csv_results; /* results in comma separated values */ -static volatile bool stop_eventstat = false; /* set by sighandler */ +static char *get_events_buf; /* buffer to glob events into */ static double opt_threshold; /* ignore samples with event delta less than this */ +static uint32_t timer_info_list_length; /* length of timer_info_list */ static uint32_t opt_flags; /* option flags */ +static volatile bool stop_eventstat = false; /* set by sighandler */ static bool sane_procs; /* false if we are in a container */ -static char *get_events_buf; /* buffer to glob events into */ static bool resized; /* window resized */ +static bool curses_init; /* curses initialised */ +static int rows = 25; /* tty size, rows */ +static int cols = 80; /* tty size, columns */ /* * Attempt to catch a range of signals so @@ -222,6 +228,81 @@ } /* + * eventstat_winsize() + * get tty size + */ +static void eventstat_winsize() +{ + struct winsize ws; + + if (ioctl(fileno(stdin), TIOCGWINSZ, &ws) != -1) { + rows = ws.ws_row; + cols = ws.ws_col; + } +} + + +/* + * eventstat_clear() + * clear screen if in top mode + */ +static inline void eventstat_clear(void) +{ + if (curses_init) + clear(); +} + +/* + * eventstat_refresh() + * refresh screen if in top mode + */ +static inline void eventstat_refresh() +{ + if (curses_init) + refresh(); +} + +/* + * eventstat_move() + * move cursor if in top mode + */ +static inline void eventstat_move( + const int y, + const int x) +{ + if (curses_init) + move(y, x); +} + +/* + * eventstat_endwin() + * call endwin if in top mode + */ +static void eventstat_endwin(void) +{ + if (curses_init) { + clear(); + endwin(); + } +} + +/* + * err_abort() + * print an error and exit + */ +static void __attribute__ ((noreturn)) err_abort(const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + eventstat_endwin(); + vfprintf(stderr,fmt, ap); + va_end(ap); + + exit(EXIT_FAILURE); +} + +/* * set_timer_stat() * enable/disable timer stat */ @@ -232,27 +313,22 @@ if ((fd = open(proc_timer_stats, O_WRONLY, S_IRUSR | S_IWUSR)) < 0) { if (carp) { - fprintf(stderr, "Cannot open %s, errno=%d (%s)\n", + err_abort("Cannot open %s, errno=%d (%s)\n", proc_timer_stats, errno, strerror(errno)); - exit(EXIT_FAILURE); - } else { - return; } + return; } if (write(fd, str, len) != len) { close(fd); if (carp) { - fprintf(stderr, "Cannot write to %s, errno=%d (%s)\n", + err_abort("Cannot write to %s, errno=%d (%s)\n", proc_timer_stats, errno, strerror(errno)); - exit(EXIT_FAILURE); - } else { - return; } + return; } (void)close(fd); } - /* * eventstat_exit() * exit and set timer stat to 0 @@ -294,11 +370,9 @@ { struct timeval tv; - if (gettimeofday(&tv, NULL) < 0) { - fprintf(stderr, "gettimeofday failed: errno=%d (%s)\n", + if (gettimeofday(&tv, NULL) < 0) + err_abort("gettimeofday failed: errno=%d (%s)\n", errno, strerror(errno)); - eventstat_exit(EXIT_FAILURE); - } return timeval_to_double(&tv); } @@ -378,7 +452,8 @@ /* * sample_add() - * add a timer_stat's delta and info field to a list at time position whence + * add a timer_stat's delta and info field to a + * list at time position whence */ static void sample_add( timer_stat_t *timer_stat, @@ -403,33 +478,31 @@ * list since time is assumed to be increasing */ if (!found) { - if ((sdl = calloc(1, sizeof(sample_delta_list_t))) == NULL) { - fprintf(stderr, "Cannot allocate sample delta list\n"); - eventstat_exit(EXIT_FAILURE); - } + if ((sdl = calloc(1, sizeof(sample_delta_list_t))) == NULL) + err_abort("Cannot allocate sample delta list\n"); sdl->whence = whence; sdl->next = sample_delta_list; sample_delta_list = sdl; } /* Now append the sdi onto the list */ - if ((sdi = calloc(1, sizeof(sample_delta_item_t))) == NULL) { - fprintf(stderr, "Cannot allocate sample delta item\n"); - eventstat_exit(EXIT_FAILURE); - } + if ((sdi = calloc(1, sizeof(sample_delta_item_t))) == NULL) + err_abort("Cannot allocate sample delta item\n"); sdi->delta = timer_stat->delta; sdi->time_delta = timer_stat->time_delta; - sdi->info = timer_stat->info; - + sdi->info = timer_stat->info; sdi->next = sdl->list; sdl->list = sdi; } /* * sample_find() - * scan through a sample_delta_list for timer info, return NULL if not found + * scan through a sample_delta_list for timer info, + * return NULL if not found */ -inline HOT static sample_delta_item_t *sample_find(sample_delta_list_t *sdl, const timer_info_t *info) +inline HOT static sample_delta_item_t *sample_find( + sample_delta_list_t *sdl, + const timer_info_t *info) { sample_delta_item_t *sdi; @@ -491,7 +564,7 @@ size_t i; for (i = 0; kernel_tasks[i].task != NULL; i++) { - if (strncmp(task, kernel_tasks[i].task, kernel_tasks[i].len) == 0) + if (!strncmp(task, kernel_tasks[i].task, kernel_tasks[i].len)) return true; } return false; @@ -501,7 +574,10 @@ * pid_a_kernel_thread * */ -static bool pid_a_kernel_thread(const char *cmdline, const char *task, const pid_t id) +static bool pid_a_kernel_thread( + const char *cmdline, + const char *task, + const pid_t id) { pid_t pgid; @@ -597,10 +673,8 @@ return; } - if ((sorted_timer_infos = calloc(timer_info_list_length, sizeof(timer_info_t*))) == NULL) { - fprintf(stderr, "Cannot allocate buffer for sorting timer_infos\n"); - eventstat_exit(EXIT_FAILURE); - } + if ((sorted_timer_infos = calloc(timer_info_list_length, sizeof(timer_info_t*))) == NULL) + err_abort("Cannot allocate buffer for sorting timer_infos\n"); /* Just want the timers with some non-zero total */ for (n = 0, info = timer_info_list; info; info = info->next) { @@ -653,11 +727,12 @@ /* Scan in timer info order to be consistent for all sdl rows */ for (i = 0; i < n; i++) { - sample_delta_item_t *sdi = sample_find(sdl, sorted_timer_infos[i]); + sample_delta_item_t *sdi = + sample_find(sdl, sorted_timer_infos[i]); /* - * duration - if -C option is used then don't scale by the - * per sample duration time, instead give the raw sample count - * by scaling by 1.0 (i.e. no scaling). + * duration - if -C option is used then don't scale + * by the per sample duration time, instead give the + * raw sample count by scaling by 1.0 (i.e. no scaling) */ if (sdi) { duration = duration_round((opt_flags & OPT_SAMPLE_COUNT) ? 1.0 : sdi->time_delta); @@ -679,11 +754,13 @@ sample_delta_list_t *sdl; for (sdl = sample_delta_list; sdl; sdl = sdl->next) { - sample_delta_item_t *sdi = sample_find(sdl, sorted_timer_infos[i]); + sample_delta_item_t *sdi = + sample_find(sdl, sorted_timer_infos[i]); if (sdi) { double duration = duration_round((opt_flags & OPT_SAMPLE_COUNT) ? 1.0 : sdi->time_delta); - double val = (duration == 0.0) ? 0.0: sdi->delta / duration; + double val = (duration == 0.0) ? + 0.0 : sdi->delta / duration; if (min > val) min = val; } @@ -698,11 +775,13 @@ sample_delta_list_t *sdl; for (sdl = sample_delta_list; sdl; sdl= sdl->next) { - sample_delta_item_t *sdi = sample_find(sdl, sorted_timer_infos[i]); + sample_delta_item_t *sdi = + sample_find(sdl, sorted_timer_infos[i]); if (sdi) { double duration = duration_round((opt_flags & OPT_SAMPLE_COUNT) ? 1.0 : sdi->time_delta); - double val = (duration == 0.0) ? 0.0: sdi->delta / duration; + double val = (duration == 0.0) ? + 0.0 : sdi->delta / duration; if (max < val) max = val; } @@ -722,12 +801,14 @@ */ fprintf(fp, ",Std.Dev.:"); for (i = 0; i < n; i++) { - double average = (double)sorted_timer_infos[i]->total / (double)count; + double average = (double) + sorted_timer_infos[i]->total / (double)count; double sum = 0.0; sample_delta_list_t *sdl; for (sdl = sample_delta_list; sdl; sdl = sdl->next) { - sample_delta_item_t *sdi = sample_find(sdl, sorted_timer_infos[i]); + sample_delta_item_t *sdi = + sample_find(sdl, sorted_timer_infos[i]); if (sdi) { double duration = duration_round((opt_flags & OPT_SAMPLE_COUNT) ? 1.0 : sdi->time_delta); double diff = duration == 0.0 ? 0.0 : @@ -765,10 +846,8 @@ return info; } } - if ((info = calloc(1, sizeof(timer_info_t))) == NULL) { - fprintf(stderr, "Cannot allocate timer info\n"); - eventstat_exit(EXIT_FAILURE); - } + if ((info = calloc(1, sizeof(timer_info_t))) == NULL) + err_abort("Cannot allocate timer info\n"); info->pid = new_info->pid; info->task = strdup(new_info->task); @@ -789,16 +868,13 @@ info->func == NULL || info->callback == NULL || info->ident == NULL) { - fprintf(stderr, "Out of memory allocating a timer stat fields\n"); - eventstat_exit(EXIT_FAILURE); + err_abort("Out of memory allocating a timer stat fields\n"); } /* Does not exist in list, append it */ - info->next = timer_info_list; timer_info_list = info; timer_info_list_length++; - info->hash_next = timer_info_hash[h]; timer_info_hash[h] = info; @@ -1007,10 +1083,8 @@ timer_stat_free_list = timer_stat_free_list->next; } else { /* Get one from heap */ - if ((ts_new = malloc(sizeof(timer_stat_t))) == NULL) { - fprintf(stderr, "Out of memory allocating a timer stat\n"); - eventstat_exit(EXIT_FAILURE); - } + if ((ts_new = malloc(sizeof(timer_stat_t))) == NULL) + err_abort("Out of memory allocating a timer stat\n"); } ts_new->count = info->total; @@ -1019,7 +1093,6 @@ ts_new->next = timer_stats[h]; ts_new->time = time_now; ts_new->sorted_freq_next = NULL; - timer_stats[h] = ts_new; } @@ -1077,7 +1150,7 @@ va_list ap; va_start(ap, fmt); - if (opt_flags & OPT_TOP) { + if (curses_init) { char buf[256]; vsnprintf(buf, sizeof(buf), fmt, ap); @@ -1136,34 +1209,61 @@ if (!(opt_flags & OPT_QUIET)) { uint64_t total = 0UL, kt_total = 0UL; int32_t j = 0; + int sz, ta_size, if_size, cb_size; - es_printf("%8s %-5s %-15s", - (opt_flags & OPT_CUMULATIVE) ? "Events" : "Event/s", "PID", "Task"); + eventstat_winsize(); + if (resized && curses_init) { + resizeterm(rows, cols); + refresh(); + resized = false; + } + + sz = (cols - 80) / 6; + if (sz < 0) + sz = 0; + + ta_size = TASK_WIDTH + sz; + if_size = FUNC_WIDTH + (3 * sz); + cb_size = cols - (8 + 1 + 5 + 1 + ta_size + 1 + if_size + 2); + if (cb_size < 0) + cb_size = 20; + + es_printf("%8s %-5s %-*.*s", + (opt_flags & OPT_CUMULATIVE) ? + "Events" : "Event/s", "PID", + ta_size, ta_size, "Task"); if (!(opt_flags & OPT_BRIEF)) - es_printf(" %-25s %-s\n", - "Init Function", "Callback"); + es_printf(" %-*.*s %-*.*s\n", + if_size, if_size, "Init Function", + cb_size, cb_size, "Callback"); else es_printf("\n"); while (sorted) { - if (((n_lines == -1) || (j < n_lines)) && (sorted->delta != 0)) { + if (((n_lines == -1) || (j < n_lines)) && + (sorted->delta != 0)) { + char *task = (opt_flags & OPT_CMD) ? + sorted->info->cmdline : sorted->info->task_mangled; + if (!*task) + task = sorted->info->task_mangled; + j++; if (opt_flags & OPT_CUMULATIVE) - es_printf("%8" PRIu64 " ", sorted->count); + es_printf("%8" PRIu64 " ", + sorted->count); else es_printf("%8.2f ", (double)sorted->delta / duration); if (opt_flags & OPT_BRIEF) { - char *cmd = sorted->info->cmdline; es_printf("%5d %s\n", - sorted->info->pid, - (opt_flags & OPT_CMD) ? - cmd : sorted->info->task_mangled); + sorted->info->pid, task); } else { - es_printf("%5d %-15s %-25s %-s\n", - sorted->info->pid, sorted->info->task_mangled, - sorted->info->func, sorted->info->callback); + es_printf("%5d %-*.*s %-*.*s %-*.*s\n", + sorted->info->pid, + ta_size, ta_size, task, + if_size, if_size, sorted->info->func, + cb_size, cb_size, sorted->info->callback); } } total += sorted->delta; @@ -1172,26 +1272,26 @@ sorted = sorted->sorted_freq_next; } - if (opt_flags & OPT_TOP) - move(LINES - 1, 0); + eventstat_move(LINES - 1, 0); es_printf("%" PRIu64 " Total events, %5.2f events/sec " "(kernel: %5.2f, userspace: %5.2f)\n", total, (double)total / duration, (double)kt_total / duration, (double)(total - kt_total) / duration); - if ((opt_flags & OPT_SHOW_WHENCE) && - (!(opt_flags & OPT_TOP))) { + if ((opt_flags & OPT_SHOW_WHENCE) && !curses_init) { time_t t = (time_t)whence; char *timestr = ctime(&t); char *pos = strchr(timestr, '\n'); if (*pos) *pos = '\0'; - es_printf("Timestamp: %s, Total Run Duration: %.1f secs\n", timestr, time_delta); + es_printf("Timestamp: %s, Total Run Duration: " + "%.1f secs\n", timestr, time_delta); } if (!sane_procs) - es_printf("Note: this was run inside a container, kernel tasks were guessed.\n"); + es_printf("Note: this was run inside a container, " + "kernel tasks were guessed.\n"); es_printf("\n"); } } @@ -1210,17 +1310,15 @@ size_t size; if (get_events_buf == NULL) { - if ((get_events_buf = malloc(EVENT_BUF_SIZE << 1)) == NULL) { - fprintf(stderr, "Cannot read %s, out of memory\n", proc_timer_stats); - return NULL; - } + if ((get_events_buf = malloc(EVENT_BUF_SIZE << 1)) == NULL) + err_abort("Cannot read %s, out of memory\n", + proc_timer_stats); + get_events_size = (EVENT_BUF_SIZE << 1); } - if ((fd = open(proc_timer_stats, O_RDONLY)) < 0) { - fprintf(stderr, "Cannot open %s\n", proc_timer_stats); - return NULL; - } + if ((fd = open(proc_timer_stats, O_RDONLY)) < 0) + err_abort("Cannot open %s\n", proc_timer_stats); size = 0; for (;;) { @@ -1245,8 +1343,8 @@ tmpptr = realloc(get_events_buf, get_events_size + 1); if (!tmpptr) { (void)close(fd); - fprintf(stderr, "Cannot read %s, out of memory\n", proc_timer_stats); - return NULL; + err_abort("Cannot read %s, out of memory\n", + proc_timer_stats); } get_events_buf = tmpptr; } @@ -1316,7 +1414,8 @@ memset(func, 0, sizeof(func)); memset(callback, 0, sizeof(callback)); info.pid = -1; - if (sscanf(ptr, "%10d %63s %63s (%63[^)])", &info.pid, task, func, callback) != 4) + if (sscanf(ptr, "%10d %63s %63s (%63[^)])", + &info.pid, task, func, callback) != 4) goto next; /* Processes without a command line are kernel threads */ @@ -1373,20 +1472,22 @@ { printf("%s, version %s\n\n", app_name, VERSION); printf("Usage: %s [options] [duration] [count]\n", app_name); - printf("Options are:\n"); - printf(" -c\t\treport cumulative events rather than events per second.\n"); - printf(" -C\t\treport event count rather than event per second in CSV output.\n"); - printf(" -d\t\tremove pathname from long process name in CSV output.\n"); - printf(" -h\t\tprint this help.\n"); - printf(" -l\t\tuse long cmdline text from /proc/pid/cmdline in CSV output.\n"); - printf(" -n events\tspecifies number of events to display.\n"); - printf(" -q\t\trun quietly, useful with option -r.\n"); - printf(" -r filename\tspecifies a comma separated values (CSV) output file to dump samples into.\n"); - printf(" -s\t\tuse short process name from /proc/pid/cmdline in CSV output.\n"); - printf(" -S\t\tcalculate min, max, average and standard deviation in CSV output.\n"); - printf(" -t threshold\tsamples less than the specified threshold are ignored.\n"); - printf(" -T\t\tenable \'top\' mode rather than a scrolling output.\n"); - printf(" -w\t\tadd time stamp (when events occurred) to output.\n"); + printf("Options are:\n" + " -c\t\treport cumulative events rather than events per second.\n" + " -C\t\treport event count rather than event per second in CSV output.\n" + " -d\t\tremove pathname from long process name in CSV output.\n" + " -h\t\tprint this help.\n" + " -l\t\tuse long cmdline text from /proc/pid/cmdline for process name.\n" + " -n events\tspecifies number of events to display.\n" + " -q\t\trun quietly, useful with option -r.\n" + " -r filename\tspecifies a comma separated values (CSV) output file\n" + "\t\tto dump samples into.\n" + " -s\t\tuse short process name from /proc/pid/cmdline for process name.\n" + " -S\t\tcalculate min, max, average and standard deviation in CSV\n" + "\t\toutput.\n" + " -t threshold\tsamples less than the specified threshold are ignored.\n" + " -T\t\tenable \'top\' mode rather than a scrolling output.\n" + " -w\t\tadd time stamp (when events occurred) to output.\n"); } /* @@ -1397,6 +1498,8 @@ { (void)sig; + eventstat_winsize(); + resized = true; } @@ -1434,21 +1537,16 @@ case 'n': errno = 0; n_lines = (int32_t)strtol(optarg, NULL, 10); - if (errno) { - fprintf(stderr, "Invalid value for number of events to display\n"); - eventstat_exit(EXIT_FAILURE); - } - if (n_lines < 1) { - fprintf(stderr, "-n option must be greater than 0\n"); - eventstat_exit(EXIT_FAILURE); - } + if (errno) + err_abort("Invalid value for number " + "of events to display\n"); + if (n_lines < 1) + err_abort("-n option must be greater than 0\n"); break; case 't': opt_threshold = strtoull(optarg, NULL, 10); - if (opt_threshold < 1) { - fprintf(stderr, "-t threshold must be 1 or more.\n"); - eventstat_exit(EXIT_FAILURE); - } + if (opt_threshold < 1) + err_abort("-t threshold must be 1 or more.\n"); break; case 'T': opt_flags |= OPT_TOP; @@ -1488,33 +1586,25 @@ if (optind < argc) { duration_secs = atof(argv[optind++]); - if (duration_secs < 0.5) { - fprintf(stderr, "Duration must 0.5 or more.\n"); - eventstat_exit(EXIT_FAILURE); - } + if (duration_secs < 0.5) + err_abort("Duration must 0.5 or more.\n"); } if (optind < argc) { forever = false; errno = 0; count = (int64_t)strtoll(argv[optind++], NULL, 10); - if (errno) { - fprintf(stderr, "Invalid count value\n"); - eventstat_exit(EXIT_FAILURE); - } - if (count < 1) { - fprintf(stderr, "Count must be > 0\n"); - eventstat_exit(EXIT_FAILURE); - } + if (errno) + err_abort("Invalid count value\n"); + if (count < 1) + err_abort("Count must be > 0\n"); } opt_threshold *= duration_secs; - if (geteuid() != 0) { - fprintf(stderr, "%s requires root privileges to write to %s\n", + if (geteuid() != 0) + err_abort("%s requires root privileges to write to %s\n", app_name, proc_timer_stats); - eventstat_exit(EXIT_FAILURE); - } sane_procs = sane_proc_pid_info(); if (!sane_procs) @@ -1526,21 +1616,15 @@ sigemptyset(&new_action.sa_mask); new_action.sa_flags = 0; - if (sigaction(signals[i], &new_action, NULL) < 0) { - fprintf(stderr, "sigaction failed: errno=%d (%s)\n", + if (sigaction(signals[i], &new_action, NULL) < 0) + err_abort("sigaction failed: errno=%d (%s)\n", errno, strerror(errno)); - eventstat_exit(EXIT_FAILURE); - } } - if ((timer_stats_old = calloc(TABLE_SIZE, sizeof(timer_stat_t*))) == NULL) { - fprintf(stderr, "Cannot allocate old timer stats table\n"); - eventstat_exit(EXIT_FAILURE); - } - if ((timer_stats_new = calloc(TABLE_SIZE, sizeof(timer_stat_t*))) == NULL) { - fprintf(stderr, "Cannot allocate old timer stats table\n"); - eventstat_exit(EXIT_FAILURE); - } + if ((timer_stats_old = calloc(TABLE_SIZE, sizeof(timer_stat_t*))) == NULL) + err_abort("Cannot allocate old timer stats table\n"); + if ((timer_stats_new = calloc(TABLE_SIZE, sizeof(timer_stat_t*))) == NULL) + err_abort("Cannot allocate old timer stats table\n"); /* Should really catch signals and set back to zero before we die */ set_timer_stat("1\n", true); @@ -1553,14 +1637,16 @@ memset(&sa, 0, sizeof(sa)); sa.sa_handler = handle_sigwinch; - sigaction(SIGWINCH, &sa, NULL); - + if (sigaction(SIGWINCH, &sa, NULL) < 0) + err_abort("sigaction failed: errno=%d (%s)\n", + errno, strerror(errno)); initscr(); cbreak(); noecho(); nodelay(stdscr, 1); keypad(stdscr, 1); curs_set(0); + curses_init = true; } while (!stop_eventstat && (forever || count--)) { @@ -1584,7 +1670,7 @@ redo = false; tv = double_to_timeval(secs); - if (opt_flags & OPT_TOP) { + if (curses_init) { fd_set rfds; int ch; @@ -1595,14 +1681,6 @@ ch = getch(); if ((ch == 27) || (ch == 'q')) break; - if (resized) { - struct winsize ws; - if (ioctl(fileno(stdin), TIOCGWINSZ, &ws) != -1) { - resizeterm(ws.ws_row, ws.ws_col); - refresh(); - } - resized = false; - } if (ret > 0) redo = true; } else { @@ -1611,10 +1689,10 @@ if (ret < 0) { if (errno != EINTR) { - if (opt_flags & OPT_TOP) - endwin(); + eventstat_endwin(); - fprintf(stderr, "select() failed: errno=%d (%s)\n", + fprintf(stderr, "select() failed: " + "errno=%d (%s)\n", errno, strerror(errno)); goto abort; } @@ -1627,13 +1705,10 @@ time_delta = time_now - time_start; get_events(timer_stats_new, time_now); - if (opt_flags & OPT_TOP) { - clear(); - } + eventstat_clear(); timer_stat_diff(duration, time_delta, n_lines, time_now, timer_stats_old, timer_stats_new); - if (opt_flags & OPT_TOP) - refresh(); + eventstat_refresh(); timer_stat_free_contents(timer_stats_old); tmp = timer_stats_old; @@ -1642,7 +1717,7 @@ timer_info_purge_old(time_now); } - endwin(); + eventstat_endwin(); abort: samples_dump(csv_results); diff -Nru eventstat-0.03.00/Makefile eventstat-0.03.01/Makefile --- eventstat-0.03.00/Makefile 2016-02-11 01:13:39.000000000 +0000 +++ eventstat-0.03.01/Makefile 2016-02-11 11:15:56.000000000 +0000 @@ -16,7 +16,7 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # -VERSION=0.03.00 +VERSION=0.03.01 CFLAGS += -Wall -Wextra -DVERSION='"$(VERSION)"' -O2