X-Git-Url: https://vcs.maemo.org/git/?a=blobdiff_plain;f=src%2Ftailhead.c;h=f0488cbc184f9de878b383b35017a184a09248d6;hb=7a8c1e45c8d53a3b84a712c09c1fbdf9eaaa3e5a;hp=81ec8e4729d0e22077cab9feccc9b6d8f54e8219;hpb=b9a28c37a879ba9ef09201001cb4e0b0f4362a3e;p=monky diff --git a/src/tailhead.c b/src/tailhead.c index 81ec8e4..f0488cb 100644 --- a/src/tailhead.c +++ b/src/tailhead.c @@ -10,7 +10,7 @@ * Please see COPYING for details * * Copyright (c) 2004, Hannu Saransaari and Lauri Hakkarainen - * Copyright (c) 2005-2009 Brenden Matthews, Philip Kovacs, et. al. + * Copyright (c) 2005-2010 Brenden Matthews, Philip Kovacs, et. al. * (see AUTHORS) * All rights reserved. * @@ -28,16 +28,29 @@ * */ +#define _GNU_SOURCE +#include "common.h" #include "text_object.h" #include "logging.h" #include +#include #include +#include #include #define MAX_HEADTAIL_LINES 30 #define DEFAULT_MAX_HEADTAIL_USES 2 -void tailstring(char *string, int endofstring, int wantedlines) { +struct headtail { + int wantedlines; + char *logfile; + char *buffer; + int current_use; + int max_uses; + int reported; +}; + +static void tailstring(char *string, int endofstring, int wantedlines) { int i, linescounted = 0; string[endofstring] = 0; @@ -56,53 +69,77 @@ void tailstring(char *string, int endofstring, int wantedlines) { } } +void free_tailhead(struct text_object *obj) +{ + struct headtail *ht = obj->data.opaque; + if (!ht) + return; + if (ht->logfile) + free(ht->logfile); + if (ht->buffer) + free(ht->buffer); + free(obj->data.opaque); + obj->data.opaque = NULL; +} + void init_tailhead(const char* type, const char* arg, struct text_object *obj, void* free_at_crash) { unsigned int args; + struct headtail *ht; - obj->data.headtail.logfile=malloc(DEFAULT_TEXT_BUFFER_SIZE); - obj->data.headtail.max_uses = DEFAULT_MAX_HEADTAIL_USES; - args = sscanf(arg, "%s %d %d", obj->data.headtail.logfile, &obj->data.headtail.wantedlines, &obj->data.headtail.max_uses); - if(args == 2 || args == 3) { - if(obj->data.headtail.max_uses < 1) { - free(obj->data.headtail.logfile); - CRIT_ERR(obj, free_at_crash, "invalid arg for %s, next_check must be larger than 0", type); - } - if (obj->data.headtail.wantedlines > 0 && obj->data.headtail.wantedlines <= MAX_HEADTAIL_LINES) { - to_real_path(obj->data.headtail.logfile, obj->data.headtail.logfile); - obj->data.headtail.buffer = NULL; - obj->data.headtail.current_use = 0; - }else{ - free(obj->data.headtail.logfile); - CRIT_ERR(obj, free_at_crash, "invalid arg for %s, number of lines must be between 1 and %d", type, MAX_HEADTAIL_LINES); - } - } else { - free(obj->data.headtail.logfile); + ht = malloc(sizeof(struct headtail)); + memset(ht, 0, sizeof(struct headtail)); + + ht->logfile = malloc(DEFAULT_TEXT_BUFFER_SIZE); + memset(ht->logfile, 0, DEFAULT_TEXT_BUFFER_SIZE); + + ht->max_uses = DEFAULT_MAX_HEADTAIL_USES; + + args = sscanf(arg, "%s %d %d", ht->logfile, &ht->wantedlines, &ht->max_uses); + if (args < 2 || args > 3) { + free_tailhead(obj); CRIT_ERR(obj, free_at_crash, "%s needs a file as 1st and a number of lines as 2nd argument", type); } + if (ht->max_uses < 1) { + free_tailhead(obj); + CRIT_ERR(obj, free_at_crash, "invalid arg for %s, next_check must be larger than 0", type); + } + if (ht->wantedlines > 0 && ht->wantedlines <= MAX_HEADTAIL_LINES) { + to_real_path(ht->logfile, ht->logfile); + ht->buffer = NULL; + ht->current_use = 0; + } else { + free_tailhead(obj); + CRIT_ERR(obj, free_at_crash, "invalid arg for %s, number of lines must be between 1 and %d", type, MAX_HEADTAIL_LINES); + } + obj->data.opaque = ht; } void print_tailhead(const char* type, struct text_object *obj, char *p, int p_max_size) { int fd, i, endofstring = 0, linescounted = 0; FILE *fp; struct stat st; + struct headtail *ht = obj->data.opaque; + + if (!ht) + return; //empty the buffer and reset the counter if we used it the max number of times - if(obj->data.headtail.buffer && obj->data.headtail.current_use >= obj->data.headtail.max_uses - 1) { - free(obj->data.headtail.buffer); - obj->data.headtail.buffer = NULL; - obj->data.headtail.current_use = 0; + if(ht->buffer && ht->current_use >= ht->max_uses - 1) { + free(ht->buffer); + ht->buffer = NULL; + ht->current_use = 0; } //use the buffer if possible - if(obj->data.headtail.buffer) { - strcpy(p, obj->data.headtail.buffer); - obj->data.headtail.current_use++; + if(ht->buffer) { + strcpy(p, ht->buffer); + ht->current_use++; }else{ //otherwise find the needed data - if(stat(obj->data.headtail.logfile, &st) == 0) { + if(stat(ht->logfile, &st) == 0) { if (S_ISFIFO(st.st_mode)) { - fd = open_fifo(obj->data.headtail.logfile, &obj->a); + fd = open_fifo(ht->logfile, &ht->reported); if(fd != -1) { if(strcmp(type, "head") == 0) { - for(i = 0; linescounted < obj->data.headtail.wantedlines; i++) { + for(i = 0; linescounted < ht->wantedlines; i++) { read(fd, p + i, 1); if(p[i] == '\n') { linescounted++; @@ -111,34 +148,91 @@ void print_tailhead(const char* type, struct text_object *obj, char *p, int p_ma p[i] = 0; } else if(strcmp(type, "tail") == 0) { i = read(fd, p, p_max_size - 1); - tailstring(p, i, obj->data.headtail.wantedlines); + tailstring(p, i, ht->wantedlines); } else { CRIT_ERR(NULL, NULL, "If you are seeing this then there is a bug in the code, report it !"); } } close(fd); } else { - fp = open_file(obj->data.headtail.logfile, &obj->a); + fp = open_file(ht->logfile, &ht->reported); if(fp != NULL) { if(strcmp(type, "head") == 0) { - for(i = 0; i < obj->data.headtail.wantedlines; i++) { + for(i = 0; i < ht->wantedlines; i++) { fgets(p + endofstring, p_max_size - endofstring, fp); endofstring = strlen(p); } } else if(strcmp(type, "tail") == 0) { fseek(fp, - p_max_size, SEEK_END); i = fread(p, 1, p_max_size - 1, fp); - tailstring(p, i, obj->data.headtail.wantedlines); + tailstring(p, i, ht->wantedlines); } else { CRIT_ERR(NULL, NULL, "If you are seeing this then there is a bug in the code, report it !"); } fclose(fp); } } - obj->data.headtail.buffer = strdup(p); + ht->buffer = strdup(p); } else { - CRIT_ERR(NULL, NULL, "$%s can't find information about %s", type, obj->data.headtail.logfile); + CRIT_ERR(NULL, NULL, "$%s can't find information about %s", type, ht->logfile); } } return; } + +/* FIXME: use something more general (see also tail.c, head.c */ +#define BUFSZ 0x1000 + +void print_lines(struct text_object *obj, char *p, int p_max_size) +{ + static int rep = 0; + FILE *fp = open_file(obj->data.s, &rep); + char buf[BUFSZ]; + int j, lines; + + if (!fp) { + snprintf(p, p_max_size, "File Unreadable"); + return; + } + + lines = 0; + while(fgets(buf, BUFSZ, fp) != NULL){ + for(j = 0; buf[j] != 0; j++) { + if(buf[j] == '\n') { + lines++; + } + } + } + snprintf(p, p_max_size, "%d", lines); + fclose(fp); +} + +void print_words(struct text_object *obj, char *p, int p_max_size) +{ + static int rep = 0; + FILE *fp = open_file(obj->data.s, &rep); + char buf[BUFSZ]; + int j, words; + char inword = 0; + + if(!fp) { + snprintf(p, p_max_size, "File Unreadable"); + return; + } + + words = 0; + while(fgets(buf, BUFSZ, fp) != NULL){ + for(j = 0; buf[j] != 0; j++) { + if(!isspace(buf[j])) { + if(!inword) { + words++; + inword = 1; + } + } else { + inword = 0; + } + } + } + snprintf(p, p_max_size, "%d", words); + fclose(fp); +}