From ccd51857c11eea272a9bb8014fbdac71d43771f8 Mon Sep 17 00:00:00 2001 From: Nikolas Garofil Date: Wed, 22 Jul 2009 22:08:31 +0200 Subject: [PATCH] Let $tail and $head work with FIFOs again (was disabled by commit 41a7cffbe7c4a4a4f04aa0a414901f01f0d7d198 ), and fix memory bug when to_real_path is used in init_tailhead --- src/common.c | 24 ++++++++++++++- src/common.h | 3 +- src/tailhead.c | 89 ++++++++++++++++++++++++++++++++++++++++---------------- 3 files changed, 89 insertions(+), 27 deletions(-) diff --git a/src/common.c b/src/common.c index 697716c..4700be1 100644 --- a/src/common.c +++ b/src/common.c @@ -38,6 +38,7 @@ #include #include #include "diskio.h" +#include /* check for OS and include appropriate headers */ #if defined(__linux__) @@ -111,6 +112,27 @@ void to_real_path(char *dest, const char *source) } } +int open_fifo(const char *file, int *reported) +{ + char path[DEFAULT_TEXT_BUFFER_SIZE]; + int fd = 0; + + to_real_path(path, file); + fd = open(file, O_RDONLY | O_NONBLOCK); + + if (fd == -1) { + if (!reported || *reported == 0) { + ERR("can't open %s: %s", file, strerror(errno)); + if (reported) { + *reported = 1; + } + } + return -1; + } + + return fd; +} + FILE *open_file(const char *file, int *reported) { char path[DEFAULT_TEXT_BUFFER_SIZE]; @@ -126,7 +148,7 @@ FILE *open_file(const char *file, int *reported) *reported = 1; } } - return 0; + return NULL; } return fp; diff --git a/src/common.h b/src/common.h index d094c9d..d191406 100644 --- a/src/common.h +++ b/src/common.h @@ -32,7 +32,8 @@ double get_time(void); * DEFAULT_TEXT_BUFFER_SIZE. It's similar to variable_substitute, except only * cheques for $HOME and ~/ in path */ void to_real_path(char *dest, const char *source); -FILE *open_file(const char *, int *); +FILE *open_file(const char *file, int *reported); +int open_fifo(const char *file, int *reported); void variable_substitute(const char *s, char *dest, unsigned int n); void format_seconds(char *buf, unsigned int n, long t); diff --git a/src/tailhead.c b/src/tailhead.c index 6645800..2e7b206 100644 --- a/src/tailhead.c +++ b/src/tailhead.c @@ -27,15 +27,37 @@ #include "text_object.h" #include "logging.h" +#include +#include +#include #define MAX_HEADTAIL_LINES 30 #define DEFAULT_MAX_HEADTAIL_USES 2 +void tailstring(char *string, int endofstring, int wantedlines) { + int i, linescounted = 0; + + string[endofstring] = 0; + if(endofstring > 0) { + if(string[endofstring-1] == '\n') { //work with or without \n at end of file + string[endofstring-1] = 0; + } + for(i = endofstring - 1; i >= 0 && linescounted < wantedlines; i--) { + if(string[i] == '\n') { + linescounted++; + } + } + if(i > 0) { + strfold(string, i+2); + } + } +} + void init_tailhead(const char* type, const char* arg, struct text_object *obj, void* free_at_crash) { unsigned int args; if(arg) { - obj->data.headtail.logfile=malloc(strlen(arg)); + 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) { @@ -61,45 +83,62 @@ void init_tailhead(const char* type, const char* arg, struct text_object *obj, v } void print_tailhead(const char* type, struct text_object *obj, char *p, int p_max_size) { - int i, endofstring = 0, linescounted = 0; + int fd, i, endofstring = 0, linescounted = 0; FILE *fp; + struct stat st; + //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; } + //use the buffer if possible if(obj->data.headtail.buffer) { strcpy(p, obj->data.headtail.buffer); obj->data.headtail.current_use++; - }else{ - fp = open_file(obj->data.headtail.logfile, &obj->a); - if(fp != NULL) { - if(strcmp(type,"head") == 0) { - for(i = 0; i < obj->data.headtail.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); - fread(p, 1, p_max_size, fp); - p[p_max_size - 1] = 0; - if(p[strlen(p)-1] == '\n') { //work with or without \n at end of file - p[strlen(p)-1] = 0; - } - for(i = strlen(p); i >= 0 && linescounted < obj->data.headtail.wantedlines; i--) { - if(p[i] == '\n') { - linescounted++; + }else{ //otherwise find the needed data + if(stat(obj->data.headtail.logfile, &st) == 0) { + if (S_ISFIFO(st.st_mode)) { + fd = open_fifo(obj->data.headtail.logfile, &obj->a); + if(fd != -1) { + if(strcmp(type, "head") == 0) { + for(i = 0; linescounted < obj->data.headtail.wantedlines; i++) { + read(fd, p + i, 1); + if(p[i] == '\n') { + linescounted++; + } + } + p[i] = 0; + } else if(strcmp(type, "tail") == 0) { + i = read(fd, p, p_max_size - 1); + tailstring(p, i, obj->data.headtail.wantedlines); + } else { + CRIT_ERR(NULL, NULL, "If you are seeing this then there is a bug in the code, report it !"); } } - if(i > 0) { - strfold(p, i+2); - } + close(fd); } else { - CRIT_ERR(NULL, NULL, "If you are seeing this then there is a bug in the code, report it !"); + fp = open_file(obj->data.headtail.logfile, &obj->a); + if(fp != NULL) { + if(strcmp(type, "head") == 0) { + for(i = 0; i < obj->data.headtail.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); + } else { + CRIT_ERR(NULL, NULL, "If you are seeing this then there is a bug in the code, report it !"); + } + fclose(fp); + } } - fclose(fp); obj->data.headtail.buffer = strdup(p); + } else { + CRIT_ERR(NULL, NULL, "$%s can't find information about %s", type, obj->data.headtail.logfile); } } return; -- 1.7.9.5