logtop-0.4.3/0000755000175000017500000000000011763466721012653 5ustar mandarkmandarklogtop-0.4.3/COPYRIGHT0000644000175000017500000000246311467530164014145 0ustar mandarkmandarklogtop is distributed under the following terms: Copyright (c) 2010 Palard Julien. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. logtop-0.4.3/doc/0000755000175000017500000000000011756246237013420 5ustar mandarkmandarklogtop-0.4.3/doc/logtop.10000644000175000017500000000432111756246237015006 0ustar mandarkmandark.\" Hey, EMACS: -*- nroff -*- .\" First parameter, NAME, should be all caps .\" Second parameter, SECTION, should be 1-8, maybe w/ subsection .\" other parameters are allowed: see man(7), man(1) .TH LOGTOP 1 "April 16, 2011" .\" Please adjust this date whenever revising the manpage. .SH "NAME" logtop \- Realtime log line rate analyser .SH "SYNOPSIS" .B logtop .RI [ OPTIONS ] .SH "DESCRIPTION" \fBlogtop\fP is a System Administrator tool analyzing line rate on stdin. It reads on stdin and print a constantly updated result displaying, in columns: Line number, count, frequency, and the actual line. $ tail \-f FILE | \fBlogtop\fP is the friendly version of: $ watch 'tail FILE | sort | uniq \-c | sort \-gr' .PP .SH "OPTIONS" .TP .B \-s, \-\-size=K Only keep K lines in memory, instead of 10000. .TP .B \-q, \-\-quiet Do not display a live view of the data, only display a top at exit. .TP .B \-l, \-\-line-by-line=K Print result line by line, in a machine friendly format, K is the number of result to print per line. Line by line format is : [%d %f %s\\t]*\\n %d : Number of occurences %f : Frequency of apparition %s : String (Control chars replaced by dots. .TP .B \-i, \-\-interval=K Interval between graphical updates, in seconds. Defaults to 1. .TP .B \-h, \-\-help Show summary of options. .TP .B \-v, \-\-version Show version of program. .SH "EXAMPLES" .PP Here are some \fBlogtop\fP usage examples. .PP .PP \fBtail \-f cache.log | grep \-o "HIT\\|MISS" | logtop\fR .PP Realtime hit / miss ratio on some caching software log file. .PP \fBtail \-f access.log | cut \-d' ' \-f1 | logtop \-s 10000\fR .PP Realtime most querying IPs on your server, as long as log lines in access.log starts with the client IP. .PP \fBtail \-f access.log | cut \-d' ' \-f7 | logtop \-s 10000\fR .PP Realtime most requested web pages in a NCSA like log file. .PP \fBcat auth.log | grep \-v "CRON" | grep \-o ": .*" | logtop \-q \-s 100000\fR .PP Display a one\-shot simple analyse of your auth.log. .SH "SEE ALSO" .BR watch (1) .br .SH "AUTHOR" logtop was written by Julien Palard. .PP This manual page was written by Julien Palard , for the Debian project (and may be used by others). logtop-0.4.3/src/0000755000175000017500000000000011763466721013442 5ustar mandarkmandarklogtop-0.4.3/src/curses.c0000644000175000017500000001043711756226100015102 0ustar mandarkmandark/* * Copyright (c) 2010 Julien Palard. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include "logtop.h" #include "history.h" static WINDOW *window; static void curses_update_winsize(void) { struct winsize ws; if (ioctl(1, TIOCGWINSZ, &ws) == -1) { gl_env.display_height = 24; gl_env.display_width = 80; } else { gl_env.display_height = ws.ws_row; gl_env.display_width = ws.ws_col; } } static void curses_on_sigwinch(int sig) { (void) sig; curses_update_winsize(); endwin(); delwin(window); window = newwin(gl_env.display_height, gl_env.display_width, 0, 0); curses_update(); } void curses_setup() { curses_update_winsize(); setup_sighandler(SIGWINCH, SA_RESTART, curses_on_sigwinch); initscr(); window = newwin(gl_env.display_height, gl_env.display_width, 0, 0); } void curses_release() { delwin(window); endwin(); } struct line_metadata { double duration; }; static void display_line_with_freq(void *data, int index, void *metadata) { log_line_t *line; double duration; line = (log_line_t *)data; duration = ((struct line_metadata *)metadata)->duration; mvwprintw(window, index, 0, "%4d %4d %8.2f/s %-*s", index, line->count, line->count / duration, gl_env.display_width - 21, line->repr); } static void display_line_without_freq(void *data, int index, void *metadata) { log_line_t *line; (void) metadata; line = (log_line_t *)data; mvwprintw(window, index, 0, "%4d %4d %s", index, line->count, line->repr); } void curses_update() { struct line_metadata line_data; history_element_t *oldest_element; history_element_t *newest_element; unsigned int qte_of_elements; line_data.duration = 0; oldest_element = oldest_element_in_history(); newest_element = newest_element_in_history(); if (oldest_element != NULL && newest_element != NULL) line_data.duration = difftime(newest_element->time, oldest_element->time); qte_of_elements = qte_of_elements_in_history(); clear(); if (line_data.duration > 0) mvwprintw(window, 0, 0, "%d elements in %d seconds (%.2f elements/s)", qte_of_elements, (unsigned int)line_data.duration, qte_of_elements / (double)line_data.duration, gl_env.display_height); else mvwprintw(window, 0, 0, "%d elements in %d seconds", qte_of_elements, (unsigned int)line_data.duration); if (line_data.duration > 0) traverse_log_lines(gl_env.top, gl_env.display_height - 1, display_line_with_freq, &line_data); else traverse_log_lines(gl_env.top, gl_env.display_height - 1, display_line_without_freq, &line_data); wrefresh(window); } logtop-0.4.3/src/logtop.h0000644000175000017500000000430511756241171015111 0ustar mandarkmandark/* * Copyright (c) 2010 Julien Palard. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef __LOGTOP_H__ #define __LOGTOP_H__ #include #include "avl.h" #include "history.h" #ifndef STRINGIFY # define __LOGTOP_STRINGIFY(x) #x # define STRINGIFY(x) __LOGTOP_STRINGIFY(x) #endif #define DEFAULT_HISTORY_SIZE 10000 typedef struct s_env { log_line_t *strings; int quiet; int line_by_line; struct avl_table *top; history_element_t *history; unsigned int history_start; unsigned int history_size; unsigned int display_width; unsigned int display_height; time_t last_update_time; time_t interval; } env_t; extern env_t gl_env; void curses_setup(void); void curses_release(void); void curses_update(void); void stdout_update(int nb_lines, int line_by_line); void setup_sighandler(int signum, int flags, void (*act)(int)); #endif logtop-0.4.3/src/avl.c0000644000175000017500000001056311756211754014371 0ustar mandarkmandark/* * Copyright (c) 2010 Julien Palard. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include "logtop.h" static int compare_log_lines_count(const void *log_line1, const void *log_line2, void *avl_param) { (void) avl_param; if (((log_line_t*)log_line1)->count != ((log_line_t*)log_line2)->count) { if (((log_line_t*)log_line2)->count > ((log_line_t*)log_line1)->count) return 1; else return -1; } return (strcmp(((log_line_t*)log_line1)->string, ((log_line_t*)log_line2)->string)); } static void die(void) { fputs("Ran out of memory, commit suicide for important tasks to live !", stderr); exit(EXIT_FAILURE); } static char *repr(const char *str) { char *clean; int i; clean = strdup(str); if (clean == NULL) return NULL; for (i = 0; clean[i] != '\0'; ++i) if (clean[i] < ' ' || clean[i] > '~') clean[i] = '.'; return clean; } static log_line_t *create_log_entry(char *string) { log_line_t *entry; entry = (log_line_t*)malloc(sizeof(*entry)); if (entry == NULL) die(); entry->count = 0; entry->string = strdup(string); if (entry->string == NULL) die(); entry->repr = repr(string); if (entry->repr == NULL) die(); HASH_ADD_KEYPTR(hh, gl_env.strings, entry->string, strlen(entry->string), entry); avl_insert(gl_env.top, entry); return entry; } static void delete_log_entry(log_line_t *log_entry) { HASH_DEL(gl_env.strings, log_entry); free(log_entry->string); free(log_entry->repr); free(log_entry); } void init_avl() { gl_env.history_start = 0; gl_env.last_update_time = time(NULL); gl_env.strings = NULL; gl_env.top = avl_create(compare_log_lines_count, NULL, NULL); if (gl_env.top == NULL) { fputs("Not enough memory to create storage", stderr); exit(EXIT_FAILURE); } } log_line_t *get_log_entry(char *string) { log_line_t *node; HASH_FIND_STR(gl_env.strings, string, node); if (node != NULL) return node; else return create_log_entry(string); } void increment_log_entry_count(log_line_t *log_entry) { avl_delete(gl_env.top, log_entry); log_entry->count += 1; avl_insert(gl_env.top, log_entry); } void decrement_log_entry_count(log_line_t *log_entry) { avl_delete(gl_env.top, log_entry); log_entry->count -= 1; if (log_entry->count != 0) avl_insert(gl_env.top, log_entry); else delete_log_entry(log_entry); } void traverse_log_lines(struct avl_table *tree, unsigned int length, void (*visitor)(void *data, int index, void *user_data), void *user_data) { struct avl_traverser trav; void *node; unsigned int last; last = length; node = avl_t_first(&trav, tree); while (length-- > 0 && node != NULL) { visitor(node, last - length, user_data); node = avl_t_next(&trav); } } logtop-0.4.3/src/history.c0000644000175000017500000000570011756211747015307 0ustar mandarkmandark/* * Copyright (c) 2010 Julien Palard. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include "logtop.h" /* ** If the element under history_start is null ** then the history is not full. */ unsigned int qte_of_elements_in_history() { if (gl_env.history[gl_env.history_start].log_entry == NULL) return gl_env.history_start; else return gl_env.history_size; } history_element_t *oldest_element_in_history() { if (gl_env.history[gl_env.history_start].log_entry != NULL) { return &(gl_env.history[gl_env.history_start]); } else { if (gl_env.history_start == 0) return NULL; return &(gl_env.history[0]); } } history_element_t *newest_element_in_history() { int newest_item_index; newest_item_index = gl_env.history_start == 0 ? gl_env.history_size - 1 : gl_env.history_start - 1; if (gl_env.history[newest_item_index].log_entry == NULL) return NULL; else return &(gl_env.history[newest_item_index]); } void update_history(log_line_t *element) { history_element_t *history_element; log_line_t *log_entry; history_element = &(gl_env.history[gl_env.history_start]); log_entry = history_element->log_entry; if (log_entry != NULL) decrement_log_entry_count(log_entry); gl_env.history[gl_env.history_start].log_entry = element; gl_env.history[gl_env.history_start].time = time(NULL); gl_env.history_start += 1; if (gl_env.history_start >= gl_env.history_size) gl_env.history_start = 0; } void init_history() { gl_env.history = (history_element_t*)calloc(sizeof(history_element_t), gl_env.history_size); } logtop-0.4.3/src/stdout.c0000644000175000017500000001021711756231370015121 0ustar mandarkmandark/* * Copyright (c) 2010 Julien Palard. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include "logtop.h" #include "history.h" struct line_metadata { double duration; }; typedef void (*result_printer)(void *data, int index, void *metadata); static void display_line_with_freq(void *data, int index, void *metadata) { log_line_t *line; double duration; line = (log_line_t *)data; duration = ((struct line_metadata *)metadata)->duration; printf("%4d %4d %4.2f/s %s\n", index, line->count, line->count / duration, line->repr); } static void display_line_without_freq(void *data, int index, void *metadata) { log_line_t *line; (void) metadata; line = (log_line_t *)data; printf("%4d %4d %s\n", index, line->count, line->repr); } static void display_result_with_freq(void *data, int index, void *metadata) { log_line_t *line; double duration; (void) index; line = (log_line_t *)data; duration = ((struct line_metadata *)metadata)->duration; printf("%d %.2f %s\t", line->count, line->count / duration, line->repr); } static void display_result_without_freq(void *data, int index, void *metadata) { log_line_t *line; (void) index; (void) metadata; line = (log_line_t *)data; printf("{%d, 0, %s}", line->count, line->repr); } static const result_printer printers[2][2] = {{display_line_without_freq, display_line_with_freq}, {display_result_without_freq, display_result_with_freq}}; void stdout_update(int nb_results, int line_by_line) { history_element_t *oldest_element; history_element_t *newest_element; struct line_metadata line_metadata; unsigned int qte_of_elements; line_metadata.duration = 0; oldest_element = oldest_element_in_history(); newest_element = newest_element_in_history(); if (oldest_element != NULL && newest_element != NULL) line_metadata.duration = difftime(newest_element->time, oldest_element->time); qte_of_elements = qte_of_elements_in_history(); if (!line_by_line) { if (line_metadata.duration > 0) printf("%d elements in %d seconds (%.2f elements/s)\n", qte_of_elements, (unsigned int)line_metadata.duration, qte_of_elements / (double)line_metadata.duration); else printf("%d elements\n", qte_of_elements); } traverse_log_lines(gl_env.top, nb_results, printers[line_by_line ? 1 : 0][line_metadata.duration > 0], &line_metadata); if (line_by_line) printf("\n"); } logtop-0.4.3/src/logtop.c0000644000175000017500000001410511760676535015116 0ustar mandarkmandark/* * Copyright (c) 2010 Julien Palard. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include "logtop.h" #include "history.h" #include "avl.h" env_t gl_env; /** * Basic sig handling using sigaction. * Reset action to SIG_DFL if act is NULL. */ void setup_sighandler(int signum, int flags, void (*act)(int)) { struct sigaction sa; sigemptyset(&sa.sa_mask); if (act != NULL) sa.sa_handler = act; else sa.sa_handler = SIG_DFL; sa.sa_flags = flags; sigaction(signum, &sa, NULL); } static void got_a_new_string(char *string) { log_line_t *element; time_t current_time; element = get_log_entry(string); increment_log_entry_count(element); update_history(element); if (gl_env.quiet) return ; current_time = time(NULL); if (current_time < gl_env.last_update_time + gl_env.interval) return ; gl_env.last_update_time = current_time; if (gl_env.line_by_line) stdout_update(gl_env.line_by_line, 1); else curses_update(); } static void run(void) { char *string; size_t size; ssize_t str_length; string = NULL; size = 0; while ((str_length = getline(&string, &size, stdin)) != -1) { while (str_length > 0 && (string[str_length - 1] == '\n' || string[str_length - 1] == '\r')) { string[str_length - 1] = '\0'; str_length -= 1; } got_a_new_string(string); } if (string != NULL) free(string); } static void usage_and_exit(int exit_code) { fprintf(exit_code == EXIT_SUCCESS ? stdout : stderr, "Usage: tail something | logtop [OPTIONS]\n" " -s, --size=NUM Number of log line to keep in memory\n" " Defaults to : " STRINGIFY(DEFAULT_HISTORY_SIZE) "\n" " -q, --quiet Quiet, only display a top 10 at exit.\n" " -l, --line-by-line=NUM Print result line by line\n" " in a machine friendly format,\n" " NUM: quantity of result by line.\n"); fprintf(exit_code == EXIT_SUCCESS ? stdout : stderr, " -i, --interval=NUM Interval between graphical updates,\n" " in seconds. Defaults to 1.\n" "\n" " Line by line format is : [%%d %%f %%s\\t]*\\n\n" " %%d : Number of occurences\n" " %%f : Frequency of apparition\n" " %%s : String (Control chars replaced by dots.\n" "\n"); exit(exit_code); } static void version_and_exit(void) { fprintf(stdout, "logtop v0.2.2\n"); exit(EXIT_SUCCESS); } static void parse_args(int ac, char **av) { int c; gl_env.history_size = 0; gl_env.quiet = 0; gl_env.last_update_time = 0; gl_env.line_by_line = 0; gl_env.interval = 1; while (1) { int option_index = 0; static struct option long_options[] = { {"size", 1, 0, 's'}, {"quiet", 0, 0, 'q'}, {"help", 0, 0, 'h'}, {"version", 0, 0, 'v'}, {"line-by-line", 1, 0, 'l'}, {"interval", 1, 0, 'i'}, {0, 0, 0, 0} }; c = getopt_long(ac, av, "qhvl:s:i:", long_options, &option_index); if (c == -1) break; switch (c) { case 'l': gl_env.line_by_line = atoi(optarg); break; case 'q': gl_env.quiet = 1; break; case 's': gl_env.history_size = atoi(optarg); break; case 'i': gl_env.interval = atoi(optarg); break; case 'v': version_and_exit(); case 'h': usage_and_exit(EXIT_SUCCESS); default: usage_and_exit(EXIT_FAILURE); } } if (isatty(fileno(stdin))) usage_and_exit(EXIT_FAILURE); if (gl_env.history_size == 0) gl_env.history_size = DEFAULT_HISTORY_SIZE; } static void at_exit(void) { if (!gl_env.quiet && !gl_env.line_by_line) curses_release(); if (gl_env.line_by_line) stdout_update(gl_env.line_by_line, 1); else stdout_update(10, 0); fflush(NULL); } static void on_sigint(int sig) { setup_sighandler(SIGINT, 0, NULL); at_exit(); kill(getpid(), sig); } int main(int ac, char **av) { parse_args(ac, av); setup_sighandler(SIGINT, 0, on_sigint); init_history(); init_avl(); if (!gl_env.quiet && !gl_env.line_by_line) curses_setup(); run(); at_exit(); return EXIT_SUCCESS; } logtop-0.4.3/src/avl.h0000644000175000017500000000355011756211256014371 0ustar mandarkmandark/* * Copyright (c) 2010 Julien Palard. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef __AVL_H__ #define __AVL_H__ #include "libavl/avl.h" #include typedef struct s_log_line { char *string; char *repr; unsigned int count; UT_hash_handle hh; } log_line_t; void init_avl(void); log_line_t *get_log_entry(char *); void increment_log_entry_count(log_line_t *); void decrement_log_entry_count(log_line_t *); void traverse_log_lines(struct avl_table *tree, unsigned int length, void (*visitor)(void *data, int index, void *user_data), void *user_data); #endif logtop-0.4.3/src/history.h0000644000175000017500000000327211756211213015302 0ustar mandarkmandark/* * Copyright (c) 2010 Julien Palard. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef __HISTORY__ #define __HISTORY__ #include "avl.h" typedef struct s_history_element { log_line_t *log_entry; time_t time; } history_element_t; void init_history(void); history_element_t *oldest_element_in_history(void); history_element_t *newest_element_in_history(void); unsigned int qte_of_elements_in_history(void); void update_history(log_line_t *element); #endif logtop-0.4.3/src/libavl/0000755000175000017500000000000011763466721014713 5ustar mandarkmandarklogtop-0.4.3/src/libavl/avl.c0000644000175000017500000006025111552265163015636 0ustar mandarkmandark/* Produced by texiweb from libavl.w. */ /* libavl - library for manipulation of binary trees. Copyright (C) 1998-2002, 2004 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. The author may be contacted at on the Internet, or write to Ben Pfaff, Stanford University, Computer Science Dept., 353 Serra Mall, Stanford CA 94305, USA. */ #include #include #include #include #include "avl.h" /* Creates and returns a new table with comparison function |compare| using parameter |param| and memory allocator |allocator|. Returns |NULL| if memory allocation failed. */ struct avl_table * avl_create (avl_comparison_func *compare, void *param, struct libavl_allocator *allocator) { struct avl_table *tree; assert (compare != NULL); if (allocator == NULL) allocator = &avl_allocator_default; tree = allocator->libavl_malloc (allocator, sizeof *tree); if (tree == NULL) return NULL; tree->avl_root = NULL; tree->avl_compare = compare; tree->avl_param = param; tree->avl_alloc = allocator; tree->avl_count = 0; tree->avl_generation = 0; return tree; } /* Search |tree| for an item matching |item|, and return it if found. Otherwise return |NULL|. */ void * avl_find (const struct avl_table *tree, const void *item) { const struct avl_node *p; assert (tree != NULL && item != NULL); for (p = tree->avl_root; p != NULL; ) { int cmp = tree->avl_compare (item, p->avl_data, tree->avl_param); if (cmp < 0) p = p->avl_link[0]; else if (cmp > 0) p = p->avl_link[1]; else /* |cmp == 0| */ return p->avl_data; } return NULL; } /* Inserts |item| into |tree| and returns a pointer to |item|'s address. If a duplicate item is found in the tree, returns a pointer to the duplicate without inserting |item|. Returns |NULL| in case of memory allocation failure. */ void ** avl_probe (struct avl_table *tree, void *item) { struct avl_node *y, *z; /* Top node to update balance factor, and parent. */ struct avl_node *p, *q; /* Iterator, and parent. */ struct avl_node *n; /* Newly inserted node. */ struct avl_node *w; /* New root of rebalanced subtree. */ int dir; /* Direction to descend. */ unsigned char da[AVL_MAX_HEIGHT]; /* Cached comparison results. */ int k = 0; /* Number of cached results. */ assert (tree != NULL && item != NULL); z = (struct avl_node *) &tree->avl_root; y = tree->avl_root; dir = 0; for (q = z, p = y; p != NULL; q = p, p = p->avl_link[dir]) { int cmp = tree->avl_compare (item, p->avl_data, tree->avl_param); if (cmp == 0) return &p->avl_data; if (p->avl_balance != 0) z = q, y = p, k = 0; da[k++] = dir = cmp > 0; } n = q->avl_link[dir] = tree->avl_alloc->libavl_malloc (tree->avl_alloc, sizeof *n); if (n == NULL) return NULL; tree->avl_count++; n->avl_data = item; n->avl_link[0] = n->avl_link[1] = NULL; n->avl_balance = 0; if (y == NULL) return &n->avl_data; for (p = y, k = 0; p != n; p = p->avl_link[da[k]], k++) if (da[k] == 0) p->avl_balance--; else p->avl_balance++; if (y->avl_balance == -2) { struct avl_node *x = y->avl_link[0]; if (x->avl_balance == -1) { w = x; y->avl_link[0] = x->avl_link[1]; x->avl_link[1] = y; x->avl_balance = y->avl_balance = 0; } else { assert (x->avl_balance == +1); w = x->avl_link[1]; x->avl_link[1] = w->avl_link[0]; w->avl_link[0] = x; y->avl_link[0] = w->avl_link[1]; w->avl_link[1] = y; if (w->avl_balance == -1) x->avl_balance = 0, y->avl_balance = +1; else if (w->avl_balance == 0) x->avl_balance = y->avl_balance = 0; else /* |w->avl_balance == +1| */ x->avl_balance = -1, y->avl_balance = 0; w->avl_balance = 0; } } else if (y->avl_balance == +2) { struct avl_node *x = y->avl_link[1]; if (x->avl_balance == +1) { w = x; y->avl_link[1] = x->avl_link[0]; x->avl_link[0] = y; x->avl_balance = y->avl_balance = 0; } else { assert (x->avl_balance == -1); w = x->avl_link[0]; x->avl_link[0] = w->avl_link[1]; w->avl_link[1] = x; y->avl_link[1] = w->avl_link[0]; w->avl_link[0] = y; if (w->avl_balance == +1) x->avl_balance = 0, y->avl_balance = -1; else if (w->avl_balance == 0) x->avl_balance = y->avl_balance = 0; else /* |w->avl_balance == -1| */ x->avl_balance = +1, y->avl_balance = 0; w->avl_balance = 0; } } else return &n->avl_data; z->avl_link[y != z->avl_link[0]] = w; tree->avl_generation++; return &n->avl_data; } /* Inserts |item| into |table|. Returns |NULL| if |item| was successfully inserted or if a memory allocation error occurred. Otherwise, returns the duplicate item. */ void * avl_insert (struct avl_table *table, void *item) { void **p = avl_probe (table, item); return p == NULL || *p == item ? NULL : *p; } /* Inserts |item| into |table|, replacing any duplicate item. Returns |NULL| if |item| was inserted without replacing a duplicate, or if a memory allocation error occurred. Otherwise, returns the item that was replaced. */ void * avl_replace (struct avl_table *table, void *item) { void **p = avl_probe (table, item); if (p == NULL || *p == item) return NULL; else { void *r = *p; *p = item; return r; } } /* Deletes from |tree| and returns an item matching |item|. Returns a null pointer if no matching item found. */ void * avl_delete (struct avl_table *tree, const void *item) { /* Stack of nodes. */ struct avl_node *pa[AVL_MAX_HEIGHT]; /* Nodes. */ unsigned char da[AVL_MAX_HEIGHT]; /* |avl_link[]| indexes. */ int k; /* Stack pointer. */ struct avl_node *p; /* Traverses tree to find node to delete. */ int cmp; /* Result of comparison between |item| and |p|. */ assert (tree != NULL && item != NULL); k = 0; p = (struct avl_node *) &tree->avl_root; for (cmp = -1; cmp != 0; cmp = tree->avl_compare (item, p->avl_data, tree->avl_param)) { int dir = cmp > 0; pa[k] = p; da[k++] = dir; p = p->avl_link[dir]; if (p == NULL) return NULL; } item = p->avl_data; if (p->avl_link[1] == NULL) pa[k - 1]->avl_link[da[k - 1]] = p->avl_link[0]; else { struct avl_node *r = p->avl_link[1]; if (r->avl_link[0] == NULL) { r->avl_link[0] = p->avl_link[0]; r->avl_balance = p->avl_balance; pa[k - 1]->avl_link[da[k - 1]] = r; da[k] = 1; pa[k++] = r; } else { struct avl_node *s; int j = k++; for (;;) { da[k] = 0; pa[k++] = r; s = r->avl_link[0]; if (s->avl_link[0] == NULL) break; r = s; } s->avl_link[0] = p->avl_link[0]; r->avl_link[0] = s->avl_link[1]; s->avl_link[1] = p->avl_link[1]; s->avl_balance = p->avl_balance; pa[j - 1]->avl_link[da[j - 1]] = s; da[j] = 1; pa[j] = s; } } tree->avl_alloc->libavl_free (tree->avl_alloc, p); assert (k > 0); while (--k > 0) { struct avl_node *y = pa[k]; if (da[k] == 0) { y->avl_balance++; if (y->avl_balance == +1) break; else if (y->avl_balance == +2) { struct avl_node *x = y->avl_link[1]; if (x->avl_balance == -1) { struct avl_node *w; assert (x->avl_balance == -1); w = x->avl_link[0]; x->avl_link[0] = w->avl_link[1]; w->avl_link[1] = x; y->avl_link[1] = w->avl_link[0]; w->avl_link[0] = y; if (w->avl_balance == +1) x->avl_balance = 0, y->avl_balance = -1; else if (w->avl_balance == 0) x->avl_balance = y->avl_balance = 0; else /* |w->avl_balance == -1| */ x->avl_balance = +1, y->avl_balance = 0; w->avl_balance = 0; pa[k - 1]->avl_link[da[k - 1]] = w; } else { y->avl_link[1] = x->avl_link[0]; x->avl_link[0] = y; pa[k - 1]->avl_link[da[k - 1]] = x; if (x->avl_balance == 0) { x->avl_balance = -1; y->avl_balance = +1; break; } else x->avl_balance = y->avl_balance = 0; } } } else { y->avl_balance--; if (y->avl_balance == -1) break; else if (y->avl_balance == -2) { struct avl_node *x = y->avl_link[0]; if (x->avl_balance == +1) { struct avl_node *w; assert (x->avl_balance == +1); w = x->avl_link[1]; x->avl_link[1] = w->avl_link[0]; w->avl_link[0] = x; y->avl_link[0] = w->avl_link[1]; w->avl_link[1] = y; if (w->avl_balance == -1) x->avl_balance = 0, y->avl_balance = +1; else if (w->avl_balance == 0) x->avl_balance = y->avl_balance = 0; else /* |w->avl_balance == +1| */ x->avl_balance = -1, y->avl_balance = 0; w->avl_balance = 0; pa[k - 1]->avl_link[da[k - 1]] = w; } else { y->avl_link[0] = x->avl_link[1]; x->avl_link[1] = y; pa[k - 1]->avl_link[da[k - 1]] = x; if (x->avl_balance == 0) { x->avl_balance = +1; y->avl_balance = -1; break; } else x->avl_balance = y->avl_balance = 0; } } } } tree->avl_count--; tree->avl_generation++; return (void *) item; } /* Refreshes the stack of parent pointers in |trav| and updates its generation number. */ static void trav_refresh (struct avl_traverser *trav) { assert (trav != NULL); trav->avl_generation = trav->avl_table->avl_generation; if (trav->avl_node != NULL) { avl_comparison_func *cmp = trav->avl_table->avl_compare; void *param = trav->avl_table->avl_param; struct avl_node *node = trav->avl_node; struct avl_node *i; trav->avl_height = 0; for (i = trav->avl_table->avl_root; i != node; ) { assert (trav->avl_height < AVL_MAX_HEIGHT); assert (i != NULL); trav->avl_stack[trav->avl_height++] = i; i = i->avl_link[cmp (node->avl_data, i->avl_data, param) > 0]; } } } /* Initializes |trav| for use with |tree| and selects the null node. */ void avl_t_init (struct avl_traverser *trav, struct avl_table *tree) { trav->avl_table = tree; trav->avl_node = NULL; trav->avl_height = 0; trav->avl_generation = tree->avl_generation; } /* Initializes |trav| for |tree| and selects and returns a pointer to its least-valued item. Returns |NULL| if |tree| contains no nodes. */ void * avl_t_first (struct avl_traverser *trav, struct avl_table *tree) { struct avl_node *x; assert (tree != NULL && trav != NULL); trav->avl_table = tree; trav->avl_height = 0; trav->avl_generation = tree->avl_generation; x = tree->avl_root; if (x != NULL) while (x->avl_link[0] != NULL) { assert (trav->avl_height < AVL_MAX_HEIGHT); trav->avl_stack[trav->avl_height++] = x; x = x->avl_link[0]; } trav->avl_node = x; return x != NULL ? x->avl_data : NULL; } /* Initializes |trav| for |tree| and selects and returns a pointer to its greatest-valued item. Returns |NULL| if |tree| contains no nodes. */ void * avl_t_last (struct avl_traverser *trav, struct avl_table *tree) { struct avl_node *x; assert (tree != NULL && trav != NULL); trav->avl_table = tree; trav->avl_height = 0; trav->avl_generation = tree->avl_generation; x = tree->avl_root; if (x != NULL) while (x->avl_link[1] != NULL) { assert (trav->avl_height < AVL_MAX_HEIGHT); trav->avl_stack[trav->avl_height++] = x; x = x->avl_link[1]; } trav->avl_node = x; return x != NULL ? x->avl_data : NULL; } /* Searches for |item| in |tree|. If found, initializes |trav| to the item found and returns the item as well. If there is no matching item, initializes |trav| to the null item and returns |NULL|. */ void * avl_t_find (struct avl_traverser *trav, struct avl_table *tree, void *item) { struct avl_node *p, *q; assert (trav != NULL && tree != NULL && item != NULL); trav->avl_table = tree; trav->avl_height = 0; trav->avl_generation = tree->avl_generation; for (p = tree->avl_root; p != NULL; p = q) { int cmp = tree->avl_compare (item, p->avl_data, tree->avl_param); if (cmp < 0) q = p->avl_link[0]; else if (cmp > 0) q = p->avl_link[1]; else /* |cmp == 0| */ { trav->avl_node = p; return p->avl_data; } assert (trav->avl_height < AVL_MAX_HEIGHT); trav->avl_stack[trav->avl_height++] = p; } trav->avl_height = 0; trav->avl_node = NULL; return NULL; } /* Attempts to insert |item| into |tree|. If |item| is inserted successfully, it is returned and |trav| is initialized to its location. If a duplicate is found, it is returned and |trav| is initialized to its location. No replacement of the item occurs. If a memory allocation failure occurs, |NULL| is returned and |trav| is initialized to the null item. */ void * avl_t_insert (struct avl_traverser *trav, struct avl_table *tree, void *item) { void **p; assert (trav != NULL && tree != NULL && item != NULL); p = avl_probe (tree, item); if (p != NULL) { trav->avl_table = tree; trav->avl_node = ((struct avl_node *) ((char *) p - offsetof (struct avl_node, avl_data))); trav->avl_generation = tree->avl_generation - 1; return *p; } else { avl_t_init (trav, tree); return NULL; } } /* Initializes |trav| to have the same current node as |src|. */ void * avl_t_copy (struct avl_traverser *trav, const struct avl_traverser *src) { assert (trav != NULL && src != NULL); if (trav != src) { trav->avl_table = src->avl_table; trav->avl_node = src->avl_node; trav->avl_generation = src->avl_generation; if (trav->avl_generation == trav->avl_table->avl_generation) { trav->avl_height = src->avl_height; memcpy (trav->avl_stack, (const void *) src->avl_stack, sizeof *trav->avl_stack * trav->avl_height); } } return trav->avl_node != NULL ? trav->avl_node->avl_data : NULL; } /* Returns the next data item in inorder within the tree being traversed with |trav|, or if there are no more data items returns |NULL|. */ void * avl_t_next (struct avl_traverser *trav) { struct avl_node *x; assert (trav != NULL); if (trav->avl_generation != trav->avl_table->avl_generation) trav_refresh (trav); x = trav->avl_node; if (x == NULL) { return avl_t_first (trav, trav->avl_table); } else if (x->avl_link[1] != NULL) { assert (trav->avl_height < AVL_MAX_HEIGHT); trav->avl_stack[trav->avl_height++] = x; x = x->avl_link[1]; while (x->avl_link[0] != NULL) { assert (trav->avl_height < AVL_MAX_HEIGHT); trav->avl_stack[trav->avl_height++] = x; x = x->avl_link[0]; } } else { struct avl_node *y; do { if (trav->avl_height == 0) { trav->avl_node = NULL; return NULL; } y = x; x = trav->avl_stack[--trav->avl_height]; } while (y == x->avl_link[1]); } trav->avl_node = x; return x->avl_data; } /* Returns the previous data item in inorder within the tree being traversed with |trav|, or if there are no more data items returns |NULL|. */ void * avl_t_prev (struct avl_traverser *trav) { struct avl_node *x; assert (trav != NULL); if (trav->avl_generation != trav->avl_table->avl_generation) trav_refresh (trav); x = trav->avl_node; if (x == NULL) { return avl_t_last (trav, trav->avl_table); } else if (x->avl_link[0] != NULL) { assert (trav->avl_height < AVL_MAX_HEIGHT); trav->avl_stack[trav->avl_height++] = x; x = x->avl_link[0]; while (x->avl_link[1] != NULL) { assert (trav->avl_height < AVL_MAX_HEIGHT); trav->avl_stack[trav->avl_height++] = x; x = x->avl_link[1]; } } else { struct avl_node *y; do { if (trav->avl_height == 0) { trav->avl_node = NULL; return NULL; } y = x; x = trav->avl_stack[--trav->avl_height]; } while (y == x->avl_link[0]); } trav->avl_node = x; return x->avl_data; } /* Returns |trav|'s current item. */ void * avl_t_cur (struct avl_traverser *trav) { assert (trav != NULL); return trav->avl_node != NULL ? trav->avl_node->avl_data : NULL; } /* Replaces the current item in |trav| by |new| and returns the item replaced. |trav| must not have the null item selected. The new item must not upset the ordering of the tree. */ void * avl_t_replace (struct avl_traverser *trav, void *new) { void *old; assert (trav != NULL && trav->avl_node != NULL && new != NULL); old = trav->avl_node->avl_data; trav->avl_node->avl_data = new; return old; } /* Destroys |new| with |avl_destroy (new, destroy)|, first setting right links of nodes in |stack| within |new| to null pointers to avoid touching uninitialized data. */ static void copy_error_recovery (struct avl_node **stack, int height, struct avl_table *new, avl_item_func *destroy) { assert (stack != NULL && height >= 0 && new != NULL); for (; height > 2; height -= 2) stack[height - 1]->avl_link[1] = NULL; avl_destroy (new, destroy); } /* Copies |org| to a newly created tree, which is returned. If |copy != NULL|, each data item in |org| is first passed to |copy|, and the return values are inserted into the tree, with |NULL| return values taken as indications of failure. On failure, destroys the partially created new tree, applying |destroy|, if non-null, to each item in the new tree so far, and returns |NULL|. If |allocator != NULL|, it is used for allocation in the new tree. Otherwise, the same allocator used for |org| is used. */ struct avl_table * avl_copy (const struct avl_table *org, avl_copy_func *copy, avl_item_func *destroy, struct libavl_allocator *allocator) { struct avl_node *stack[2 * (AVL_MAX_HEIGHT + 1)]; int height = 0; struct avl_table *new; const struct avl_node *x; struct avl_node *y; assert (org != NULL); new = avl_create (org->avl_compare, org->avl_param, allocator != NULL ? allocator : org->avl_alloc); if (new == NULL) return NULL; new->avl_count = org->avl_count; if (new->avl_count == 0) return new; x = (const struct avl_node *) &org->avl_root; y = (struct avl_node *) &new->avl_root; for (;;) { while (x->avl_link[0] != NULL) { assert (height < 2 * (AVL_MAX_HEIGHT + 1)); y->avl_link[0] = new->avl_alloc->libavl_malloc (new->avl_alloc, sizeof *y->avl_link[0]); if (y->avl_link[0] == NULL) { if (y != (struct avl_node *) &new->avl_root) { y->avl_data = NULL; y->avl_link[1] = NULL; } copy_error_recovery (stack, height, new, destroy); return NULL; } stack[height++] = (struct avl_node *) x; stack[height++] = y; x = x->avl_link[0]; y = y->avl_link[0]; } y->avl_link[0] = NULL; for (;;) { y->avl_balance = x->avl_balance; if (copy == NULL) y->avl_data = x->avl_data; else { y->avl_data = copy (x->avl_data, org->avl_param); if (y->avl_data == NULL) { y->avl_link[1] = NULL; copy_error_recovery (stack, height, new, destroy); return NULL; } } if (x->avl_link[1] != NULL) { y->avl_link[1] = new->avl_alloc->libavl_malloc (new->avl_alloc, sizeof *y->avl_link[1]); if (y->avl_link[1] == NULL) { copy_error_recovery (stack, height, new, destroy); return NULL; } x = x->avl_link[1]; y = y->avl_link[1]; break; } else y->avl_link[1] = NULL; if (height <= 2) return new; y = stack[--height]; x = stack[--height]; } } } /* Frees storage allocated for |tree|. If |destroy != NULL|, applies it to each data item in inorder. */ void avl_destroy (struct avl_table *tree, avl_item_func *destroy) { struct avl_node *p, *q; assert (tree != NULL); for (p = tree->avl_root; p != NULL; p = q) if (p->avl_link[0] == NULL) { q = p->avl_link[1]; if (destroy != NULL && p->avl_data != NULL) destroy (p->avl_data, tree->avl_param); tree->avl_alloc->libavl_free (tree->avl_alloc, p); } else { q = p->avl_link[0]; p->avl_link[0] = q->avl_link[1]; q->avl_link[1] = p; } tree->avl_alloc->libavl_free (tree->avl_alloc, tree); } /* Allocates |size| bytes of space using |malloc()|. Returns a null pointer if allocation fails. */ void * avl_malloc (struct libavl_allocator *allocator, size_t size) { assert (allocator != NULL && size > 0); return malloc (size); } /* Frees |block|. */ void avl_free (struct libavl_allocator *allocator, void *block) { assert (allocator != NULL && block != NULL); free (block); } /* Default memory allocator that uses |malloc()| and |free()|. */ struct libavl_allocator avl_allocator_default = { avl_malloc, avl_free }; #undef NDEBUG #include /* Asserts that |avl_insert()| succeeds at inserting |item| into |table|. */ void (avl_assert_insert) (struct avl_table *table, void *item) { void **p = avl_probe (table, item); assert (p != NULL && *p == item); } /* Asserts that |avl_delete()| really removes |item| from |table|, and returns the removed item. */ void * (avl_assert_delete) (struct avl_table *table, void *item) { void *p = avl_delete (table, item); assert (p != NULL); return p; } logtop-0.4.3/src/libavl/avl.h0000644000175000017500000001055411552265163015644 0ustar mandarkmandark/* Produced by texiweb from libavl.w. */ /* libavl - library for manipulation of binary trees. Copyright (C) 1998-2002, 2004 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. The author may be contacted at on the Internet, or write to Ben Pfaff, Stanford University, Computer Science Dept., 353 Serra Mall, Stanford CA 94305, USA. */ #ifndef AVL_H #define AVL_H 1 #include /* Function types. */ typedef int avl_comparison_func (const void *avl_a, const void *avl_b, void *avl_param); typedef void avl_item_func (void *avl_item, void *avl_param); typedef void *avl_copy_func (void *avl_item, void *avl_param); #ifndef LIBAVL_ALLOCATOR #define LIBAVL_ALLOCATOR /* Memory allocator. */ struct libavl_allocator { void *(*libavl_malloc) (struct libavl_allocator *, size_t libavl_size); void (*libavl_free) (struct libavl_allocator *, void *libavl_block); }; #endif /* Default memory allocator. */ extern struct libavl_allocator avl_allocator_default; void *avl_malloc (struct libavl_allocator *, size_t); void avl_free (struct libavl_allocator *, void *); /* Maximum AVL height. */ #ifndef AVL_MAX_HEIGHT #define AVL_MAX_HEIGHT 32 #endif /* Tree data structure. */ struct avl_table { struct avl_node *avl_root; /* Tree's root. */ avl_comparison_func *avl_compare; /* Comparison function. */ void *avl_param; /* Extra argument to |avl_compare|. */ struct libavl_allocator *avl_alloc; /* Memory allocator. */ size_t avl_count; /* Number of items in tree. */ unsigned long avl_generation; /* Generation number. */ }; /* An AVL tree node. */ struct avl_node { struct avl_node *avl_link[2]; /* Subtrees. */ void *avl_data; /* Pointer to data. */ signed char avl_balance; /* Balance factor. */ }; /* AVL traverser structure. */ struct avl_traverser { struct avl_table *avl_table; /* Tree being traversed. */ struct avl_node *avl_node; /* Current node in tree. */ struct avl_node *avl_stack[AVL_MAX_HEIGHT]; /* All the nodes above |avl_node|. */ size_t avl_height; /* Number of nodes in |avl_parent|. */ unsigned long avl_generation; /* Generation number. */ }; /* Table functions. */ struct avl_table *avl_create (avl_comparison_func *, void *, struct libavl_allocator *); struct avl_table *avl_copy (const struct avl_table *, avl_copy_func *, avl_item_func *, struct libavl_allocator *); void avl_destroy (struct avl_table *, avl_item_func *); void **avl_probe (struct avl_table *, void *); void *avl_insert (struct avl_table *, void *); void *avl_replace (struct avl_table *, void *); void *avl_delete (struct avl_table *, const void *); void *avl_find (const struct avl_table *, const void *); void avl_assert_insert (struct avl_table *, void *); void *avl_assert_delete (struct avl_table *, void *); #define avl_count(table) ((size_t) (table)->avl_count) /* Table traverser functions. */ void avl_t_init (struct avl_traverser *, struct avl_table *); void *avl_t_first (struct avl_traverser *, struct avl_table *); void *avl_t_last (struct avl_traverser *, struct avl_table *); void *avl_t_find (struct avl_traverser *, struct avl_table *, void *); void *avl_t_insert (struct avl_traverser *, struct avl_table *, void *); void *avl_t_copy (struct avl_traverser *, const struct avl_traverser *); void *avl_t_next (struct avl_traverser *); void *avl_t_prev (struct avl_traverser *); void *avl_t_cur (struct avl_traverser *); void *avl_t_replace (struct avl_traverser *, void *); #endif /* avl.h */ logtop-0.4.3/CHANGELOG0000644000175000017500000002564711760676636014110 0ustar mandarkmandarkcommit 43411226105af5f0b8ebb437df0fb5cfbe16a2a7 Author: Julien Palard Date: Mon May 28 15:26:45 2012 +0200 FIX: Support LDFLAGS in Makefile commit 5d00e5423bdff5e3b86e26c3be151e182b9db7b0 Author: Julien Palard Date: Mon May 21 15:01:50 2012 +0200 FIX: Forgot a debug. commit d7ac287638cd86615b4724d80874f86309101422 Author: Julien Palard Date: Sun May 20 21:58:59 2012 +0200 Upgrading documentation and manpage. Version is now 0.2. commit 430fa9273f1ea88379cff466a84ae926822bd8b7 Author: Julien Palard Date: Sun May 20 21:25:57 2012 +0200 Prit usage if stdin is a TTY. commit 4db20d36ad795940dfe94b4f4ef21de146e4cc3d Author: Julien Palard Date: Sun May 20 21:22:16 2012 +0200 Renaming without_curses in quiet. That's more expressive in the actual context. commit d77459913595a83e5f91ecd1137e8ff6118bec98 Author: Julien Palard Date: Sun May 20 21:09:23 2012 +0200 NEW: Line by line reporting. Line by line reporting is for programs that want to parse logtop output, a report is printed, entierly in one line, once per second, in a machine friendly format. Option parsing has been rewritted using getopt_long, and a new option has appeard : --interval, permitting to change the default interface update interval, for line-by-line and for curses. commit 18785a8ba180a4b8337ee2aec5c4e076d59330a1 Author: Julien Palard Date: Sun May 20 19:40:49 2012 +0200 NEW: -q option to disable curses As the top 10 is print at exit, updating in real time with curses become optional. commit 60f61bd32a137f3dd27c8069ae020f03a9426d20 Author: Julien Palard Date: Sun May 20 19:28:11 2012 +0200 Enhancing ccurses view. Handling SIGWINCH, permitting resize or terminals. Only repaint what was actually modified at each repaint. commit c2ec00a3c070abd306a4a8332055994f07fa2259 Author: Julien Palard Date: Sun May 20 17:56:02 2012 +0200 Code uniformisation and -Wstrict-prototypes commit 6198e912c23f5f93b14895204edd3dcebc66de9f Author: Julien Palard Date: Sun May 20 17:51:38 2012 +0200 NEW: Only print the top 10 elements at exit. Also print the top 10 elements when SIGINT is catched. commit ff777e8ebae0f304e6e4e227ebfddd9b9181f241 Author: Julien Palard Date: Sun May 20 16:33:48 2012 +0200 NEW: Handling SIGINT. commit 66aea8dba65b34ab5a552b2b1e163df35fd869d8 Author: Julien Date: Tue May 31 18:43:43 2011 +0200 Adding a missing build dependency in the README file (uthash-dev) commit ed1e9befb8414d1c5fb4db77368b4bec85c3eaa9 Author: Julien Date: Tue May 31 18:31:07 2011 +0200 Addin an 'About libavl' in the README file commit 9173816f68403eed3e736c5f7629fcfb39da08f1 Author: Julien Date: Tue May 31 18:24:29 2011 +0200 Updating README to reflect the actual implementation, and fixing a typo commit 14ec7f22988ebbd17a8a067dad1d97725bdeb753 Author: Julien Date: Tue May 3 23:47:50 2011 +0200 Replacing strings storage, from an AVL tree to an hashtable, little gain in performance (~20%) But keeping an AVL tree for the rank (as it needs to be sorted) commit 88c217e50fa8593afa57fa92c6501926735dc53a Author: Julien Date: Sat Apr 16 12:30:42 2011 +0200 FIX: If a line does not end with \n (the last?) it was reported as an empty string. NEW: Compatibility with lines ending with CR+LF, LF+CR, LF, or CR (and any other combinations !) commit 0a613e0b38ae2444ba16db7ad9e304138c245d01 Author: Julien Date: Sat Apr 16 12:17:22 2011 +0200 Some corretion to the manpage commit fd4f01ce719327bf6a408e3303fb4abf2956623d Merge: 7dd641b e1297af Author: Julien Date: Sat Apr 16 12:07:46 2011 +0200 Merge branch 'master' of github.com:JulienPalard/logtop commit 7dd641b0f8c55a4d6066b7cbf86ba058fae1cc23 Author: Julien Date: Sat Apr 16 12:06:25 2011 +0200 Rewriting the README to remove livavl dependencies commit e1297afe02efbf283b7097a2b9be18e95ae0c211 Author: Julien Palard Date: Wed Mar 16 22:47:48 2011 +0100 FIX: Forgotten .o in libavl folder while make clean commit 48ba928d91c57f08469540d7a9c11784eb8d8f6d Author: Julien Palard Date: Wed Mar 16 08:51:45 2011 +0100 Fixed a bug that makes some entry to appear more than once in the result. commit b80e8ac8a51e3fed021b63e7e8061d2a0650752c Author: Julien Palard Date: Tue Mar 15 23:07:01 2011 +0100 Fixing display bug commit a36398cc512cd4e83be330ddab98bdc36062f1ab Author: Julien Palard Date: Tue Mar 15 23:06:24 2011 +0100 Removing a useless strlen commit bb88531f819a3d32cfe8ff09228f2e3bf023f1be Author: Julien Palard Date: Tue Mar 15 23:01:58 2011 +0100 traverse_log_lines can yield NULL, so we have to check it commit d578251e91d8ef0cc863f7c9add9f36b9d7eddd2 Author: Julien Palard Date: Tue Mar 15 22:51:07 2011 +0100 Simple refactoring of writers commit 99130d175dadbd46d7759c0a8e899a44e0ec9f37 Author: Julien Palard Date: Tue Mar 15 20:41:29 2011 +0100 Removing one line in the stdout output module to keep the first line of result, previously dropped due to the appearing shell line of the user commit b4e7ce5133d5537f38ce1824a33475c1a7a2476a Author: Julien Palard Date: Tue Mar 15 20:39:29 2011 +0100 Removing the unused UNUSED define and protecting STRINGIFY commit 1e19ee9d10ec2c621de087c257e1f93513fa4344 Author: Julien Palard Date: Tue Mar 15 20:35:26 2011 +0100 Dropping dependency to Debian's libavl in favor of the pfaff's one, statically build commit a68ce57035b92f02086c62e7b7f5d4b008f2f2a9 Author: Julien Date: Sun Jan 16 20:32:26 2011 +0100 Adding Debian changelog commit 3baa3447757da760a10eb417f58a6c92ed239c65 Author: mandark Date: Tue Dec 28 10:15:17 2010 +0100 Refactorig for readeability commit b597c950277555d15191ace04b9c1ba252f35c8f Author: mandark Date: Tue Dec 28 09:46:32 2010 +0100 Moving history structure to history.h commit 1a7dca7680a8bc52b0e4d2a8ecea4f85b995bd29 Author: mandark Date: Tue Dec 28 09:42:26 2010 +0100 Updating licences commit 05fb3773ced37f5e3328d5ecae752e01f5c0fd69 Author: mandark Date: Tue Dec 28 09:20:37 2010 +0100 Refactoring for readeability commit 4d4e20ddd51a301b809fb70c9e27d5a9767461d7 Author: mandark Date: Tue Dec 28 08:51:29 2010 +0100 Splitting history managment in history.c commit afbee48ee250e83bdbcebae0ff929c0e02d56938 Author: Julien Date: Mon Dec 27 08:41:17 2010 +0100 Fixing manpage commit 7d02ea927e14beeb32322edfb939c6a616c03013 Author: mandark Date: Sun Dec 12 20:57:50 2010 +0100 FIX: More verbose help statement FIX: Removing deprecated initialisation of value while parsing arguments commit 376223e482df8472da2d6b06e833e2e66a1e8ef5 Author: mandark Date: Sun Dec 12 20:52:37 2010 +0100 FIX: Fixing help to remove deprecated -c parameter commit 0d1d7d82611648ff3154bd197ff988a76dc3f0d1 Author: mandark Date: Sun Dec 12 20:51:31 2010 +0100 ADD: Compile dependencies in README file commit 284f3af56138e4e6adf506535dc693682d7620af Author: Julien Date: Sun Dec 12 00:18:40 2010 +0100 NEW: Use ioctl to determine display height. commit 58f564d6d68f5228c148a844b4d03ab503216710 Author: Julien Date: Sun Dec 5 20:13:58 2010 +0100 Adding make install and a man commit aba37c9245bbf5ce28dbbfcaf0c6c6aac85cd0ca Author: Julien Date: Sun Dec 5 20:13:02 2010 +0100 Adding -v to get version and -h to get some help commit 970f620b73e40f94e5f6245534d3b0e7180be697 Author: Julien Date: Sun Dec 5 19:25:56 2010 +0100 Fine tuning visualisation commit 95db9a66c4549788ba2e9d64f4d7ee70b9742349 Author: Julien Date: Fri Dec 3 09:57:41 2010 +0100 FIX: Replace specials chars like \r to dots to ensure graphical concistency commit a0fd59d126de96d04d5851aa5ff10171c03d0ee5 Author: Julien Date: Sun Nov 14 22:22:03 2010 +0100 FIX: display_height was non used in stdout display commit 88cc21b818e845bba96d96c89327ac9a049dbe1b Author: Julien Date: Sun Nov 14 15:30:46 2010 +0100 Style improvment and renaming commit edd3d8f524398ebb0bd429f0eef1b5dd00c8bc64 Author: Julien Date: Sat Nov 13 21:45:03 2010 +0100 Improving a bit the UI adding the number of log lines read by second ... On my box, a $ strings /dev/urandom | ./logtop -s 100000 gaves me : 80% CPU for strings 20% CPU for logtop 12000 lines/seconds, no memory leak. commit 92c00f7b1111715250e40c11d13df4569ed30f25 Author: Julien Date: Sat Nov 13 21:27:32 2010 +0100 Oops just forgotten -lefence in da Makefile :p commit d3e2bf9c440466b2561232234aa45bb4c9a3f96b Author: Julien Date: Sat Nov 13 21:24:51 2010 +0100 Fix a bug in "get_newest_element_in_history" commit 2a536c2f7731f7730892048f3cf2ecb504bd2fc6 Author: Julien Date: Sat Nov 13 21:09:49 2010 +0100 Fixing headers commit abc4cef173494d5c3894c67aacaafcd39d0b2d94 Author: Julien Date: Sat Nov 13 17:32:20 2010 +0100 NEW: Now displaying loglines by seconds as : 917 25/s foobar commit d1079f610a3854aaf6febabd04b80410e8012413 Author: Julien Date: Sat Nov 13 15:33:54 2010 +0100 ADD: Each history entity is now dated, i'll can add some feature like a rotation by duration. commit c1961bbb78e34b09f9920be07097da8dc02ab1df Author: Julien Date: Sat Nov 13 15:06:13 2010 +0100 FIX: Bug during optparse commit c028e4e87447f82f9aebba12b1b90490418b24b1 Author: Julien Date: Sat Nov 13 15:00:27 2010 +0100 Adding two new files after splitting source commit 1dee8e7856af88895bbb8ff33073e3a0c88c6af9 Author: Julien Date: Sat Nov 13 14:59:28 2010 +0100 ADD: Dump last view on stdout leaving FIX: Restore curses leaving commit a7f64ba9a94926e191812a1f4100fa2ecc18f55e Author: Julien Date: Thu Jul 1 19:17:10 2010 +0200 Add usage sample to the README commit 7a8820bd67927891183ecfd1219d1194df201bec Author: Julien Date: Thu Jul 1 19:09:12 2010 +0200 Updating README : Adding dependencies commit ba0a8d9b310f8aeefbd226aaca33076d7696a3fa Author: Julien Date: Thu Jul 1 19:05:05 2010 +0200 EHLO World logtop-0.4.3/README0000644000175000017500000000255111756243425013532 0ustar mandarkmandarkFor copyright information, please see the file COPYRIGHT in this directory or in the files of the source tree. This project was initiated on 2010-06-29 by Palard Julien See http://julien.palard.fr or ask me questions at : julien at palard in fr Compile dependencies : You will need : Package: libncurses5-dev Version: 5.7+20100313-1 $ aptitude install libncurses5-dev uthash-dev Then, to compile just type : $ make Run : You will need : $ aptitude install libncurses5 $ ./logtop Usage : logtop displays real-time count of strings recieved in standard input. I's useful for some cases, like getting the IP flooding your server : $ tail -f /var/log/apache2/access.log | cut -d' ' -f1 | logtop Or the top buzzing article of your blog : $ tail -f /var/log/apache2/access.log | cut -d' ' -f7 | grep article | logtop Development : I use a hashtable to store strings and an AVL tree to store frequencies, so I can fetch by string or fetch ordered by frequency to display the top-strings. About libavl: The libavl used here is the Ben Pfaff's one, statically build with logtop, as Ben want it to be (see INSTALL file and here : http://lists.debian.org/debian-devel/2001/07/msg01303.html) So this libavl is NOT packaged as a library for Debian, the libavl you'll found in Debian repositories is the Wessel Dankers's one. logtop-0.4.3/NCURSES_COPYRIGHT0000644000175000017500000000620511467530164015345 0ustar mandarkmandarkThis is the Debian prepackaged version of the ncurses library and terminfo utilities. ncurses/terminfo was originally written by Pavel Curtis and Zeyd M. Ben-Halim , and is currently held by the Free Software Foundation. This package was put together by Vaidhyanathan G Mayilrangam and Joel Klecker , using sources obtained from ftp://ftp.gnu.org/gnu/ncurses/ncurses-5.0.tar.gz. It is based somewhat on work done by Bruce Perens , David Engel . Michael Alan Dorman , Richard Braakman , James Troup , J.H.M. Dassen (Ray) , and Galen Hazelwood over various years. Changes: * added Debian package maintenance system files * changed Makefile.in's to compile with -D_REENTRANT * changed configure.in to support proper compilation of debugging libraries * Fixed tget{flag,num,str} in lib_termcap ("long" strings work now) Changes to terminfo.src: * Removed ich(1) from linux, screen, vt320 /**************************************************************************** * Copyright (c) 1998 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * * "Software"), to deal in the Software without restriction, including * * without limitation the rights to use, copy, modify, merge, publish, * * distribute, distribute with modifications, sublicense, and/or sell * * copies of the Software, and to permit persons to whom the Software is * * furnished to do so, subject to the following conditions: * * * * The above copyright notice and this permission notice shall be included * * in all copies or substantial portions of the Software. * * * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * * THE USE OR OTHER DEALINGS IN THE SOFTWARE. * * * * Except as contained in this notice, the name(s) of the above copyright * * holders shall not be used in advertising or otherwise to promote the * * sale, use or other dealings in this Software without prior written * * authorization. * ****************************************************************************/ logtop-0.4.3/Makefile0000644000175000017500000000136711760676321014316 0ustar mandarkmandark## ## Makefile for logtop ## ## Made by julien palard ## Login ## NAME = logtop DSRC = src SRC = $(DSRC)/logtop.c $(DSRC)/avl.c $(DSRC)/history.c $(DSRC)/curses.c \ $(DSRC)/stdout.c $(DSRC)/libavl/avl.c OBJ = $(SRC:.c=.o) CC = gcc INCLUDE = . DEFINE = _GNU_SOURCE LIB = -lncurses #-lefence CFLAGS = -O3 -W -Wall -ansi -pedantic -Wstrict-prototypes -I$(INCLUDE) RM = rm -f LDFLAGS = $(NAME): $(OBJ) $(CC) $(CFLAGS) -o $(NAME) $(OBJ) $(LIB) $(LDFLAGS) install: $(NAME) mkdir -p $(DESTDIR)/usr/bin/ cp $(NAME) $(DESTDIR)/usr/bin/ all: @make $(NAME) .c.o: $(CC) -D $(DEFINE) -c $(CFLAGS) $< -o $(<:.c=.o) clean: $(RM) $(NAME) $(DSRC)/*~ $(DSRC)/#*# $(DSRC)/*.o $(DSRC)/*.core \ $(DSRC)/libavl/*.o re: clean all