#include "ttail.h" ttail_t *ttail_init(int argc, char **argv) { ttail_t *res; int c, opt_i, ret; char *dates[2] = { NULL, NULL }; char *date; res = malloc(sizeof(ttail_t)); if(!res) { perror("Unable to allocate memory"); goto ttail_init_alloc_err; } opterr = 0; optind = 0; res->verbose = 0; res->fmt = NULL; res->flag = 0; res->logfile = NULL; res->logfile_name = NULL; res->logfile_sz = 0; memset(&(res->date_min), 0, sizeof(struct tm)); memset(&(res->date_max), 0, sizeof(struct tm)); while(1) { static struct option long_options[] = { {"verbose", no_argument, 0, 'v'}, {"re-prefix", required_argument, 0, 'p'}, {"date-format", required_argument, 0, 'f'}, {"date-min", required_argument, 0, 'd'}, {"date-max", required_argument, 0, 'm'}, {"logfile", required_argument, 0, 'l'}, {0, 0, 0, 0 } }; opt_i = 0; c = getopt_long(argc, argv, "p:f:d:l:m:", long_options, &opt_i); if(c == -1) break; switch(c) { case 'v': res->verbose++; break; case 'p': if(ttail_set_prefix(res, optarg)) { goto ttail_init_err; } break; case 'f': if(res->flag & TTAIL_FLAG_FORMAT) { fprintf(stderr,"Multiple date format \ given\n"); goto ttail_init_err; } res->fmt = malloc( sizeof(char)*(strlen(optarg)+1)); if(!res->fmt) { perror("Unable to allocate memory\ for date format"); goto ttail_init_err; } strcpy(res->fmt, optarg); res->flag |= TTAIL_FLAG_FORMAT; break; case 'l': fprintf(stderr,"-l with %s\n", optarg); ret = ttail_add_logfile(res, optarg); if(ret < 0) { goto ttail_init_err; } break; case 'd': case 'm': date = malloc(sizeof(char)*(strlen(optarg)+1)); if(!date) { goto ttail_init_err; } strcpy(date, optarg); dates[c=='d'?0:1] = date; break; case '?': optind--; goto init_badarg; break; default: fprintf(stderr, "Bad argument\n"); goto init_badarg; } } if(optind < argc) { init_badarg: fprintf(stderr, "bad option :"); while(optind < argc) { fprintf(stderr, argv[optind++]); } fprintf(stderr, "\n"); goto ttail_init_err; } /* date min/max processing */ for(c=0;cflag & TTAIL_FLAG_PREFIX)) { /* no format specified */ ret = ttail_format_guess(res, dates[c], c==0?&(res->date_min):&(res->date_max)); if(res < 0) { fprintf(stderr, "Unable to guess format for \ date '%s'\n", dates[c]); goto ttail_init_err; } continue; } date = strptime(dates[c], res->fmt, c==0?&(res->date_min):&(res->date_max)); if(!date) { fprintf(stderr, "Unable to parse date-%s '%s' with \ format '%s'\n", c==0?"min":"max", dates[c], res->fmt); goto ttail_init_err; } else if(*date != '\0') { fprintf(stderr, "Leading caracters for date-%s : %s\n",\ c==0?"min":"max", date); } free(dates[c]); } return res; ttail_init_err: if(dates[0]) { free(dates[0]); } if(dates[1]) { free(dates[1]); } ttail_free(res); ttail_init_alloc_err: return NULL; } int ttail_add_logfile(ttail_t* res, const char* filename) { void *tmp; FILE *fp; char *fname; int ret, i; for(i=0; ilogfile_sz; i++) { if(strcmp(filename, res->logfile_name[i]) == 0) { fprintf(stderr, "File '%s' allready added\n", filename); return -1; } } res->logfile_sz++; tmp = res->logfile; res->logfile = realloc(res->logfile, sizeof(FILE*)*res->logfile_sz); ret = 0; if(!res->logfile) { perror("Unable to allocate memory for logfiles"); res->logfile = tmp; goto ttail_add_logfile_fpalloc_err; } fp = fopen(filename, "r"); if(!fp) { fprintf(stderr, "Unable to open file : %s\n", filename); ret = 1; } res->logfile[res->logfile_sz-1] = fp; tmp = res->logfile_name; res->logfile_name = realloc(res->logfile_name, sizeof(char*)*res->logfile_sz); if(!res->logfile_name) { perror("Unable to allocate memory for logfiles"); res->logfile_name = tmp; goto ttail_add_logfile_fnalloc_err; } fname = malloc(sizeof(char)*(strlen(filename)+1)); if(!fname) { perror("Unable to allocate memory for logfiles"); goto ttail_add_logfile_fnalloc_err; } strcpy(fname, filename); res->logfile_name[res->logfile_sz-1] = fname; return ret; ttail_add_logfile_fnalloc_err: fclose(res->logfile[res->logfile_sz-2]); ttail_add_logfile_fpalloc_err: res->logfile_sz--; return -1; } int ttail_set_prefix(ttail_t* res, const char* regex) { int ret; char *re_errbuff; size_t re_errbuff_sz; if(res->flag & TTAIL_FLAG_PREFIX) { fprintf(stderr, "Regex prefix allready set"); return 1; } res->flag |= TTAIL_FLAG_PREFIX; ret = regcomp(&res->date_prefix, regex, 0); if(!ret) { return 0; } /*compilation error */ res->flag ^= TTAIL_FLAG_PREFIX; re_errbuff_sz = regerror(ret, &res->date_prefix, NULL, 0); re_errbuff = malloc( sizeof(char)*re_errbuff_sz); if(!re_errbuff) { perror("Failed to allocate memory for regex compilation \ error message"); goto ttail_set_prefix_err; } regerror(ret, &res->date_prefix, re_errbuff, sizeof(char)*re_errbuff_sz); fprintf(stderr, "Regex compilation fails : %s", re_errbuff); free(re_errbuff); ttail_set_prefix_err: return -1; } int ttail_format_guess(ttail_t* t, const char* date_str, struct tm* tm) { int i, res; char *res_ret, *ret; char *fmt[] = TTAIL_DEFAULT_FORMATS; struct tm dte; memset(&dte, 0, sizeof(struct tm)); if(t->flag & TTAIL_FLAG_FORMAT) { fprintf(stderr, "Format allready set\n"); return -2; } res = -1; res_ret = NULL; i=0; while(fmt[i]) { ret = strptime(date_str, fmt[i], &dte); if(ret) { if(!res_ret || strlen(res_ret) > strlen(ret)) { res_ret = ret; res = i; if(tm) { memcpy(tm, &dte, sizeof(struct tm)); } if(t->fmt) { free(t->fmt); } t->fmt = malloc( sizeof(char)*(strlen(fmt[i])+1)); if(!t->fmt) { perror("Unable to allocate memory\ for date format"); t->flag ^= TTAIL_FLAG_FORMAT; return -1; } strcpy(t->fmt, fmt[i]); t->flag |= TTAIL_FLAG_FORMAT; } } i++; } if(!res_ret) { if(tm) { memset(tm, 0, sizeof(struct tm)); } return -1; } return res; } void ttail_free(ttail_t* t) { size_t i; for(i=0; ilogfile_sz; i++) { if(t->logfile[i]) { fclose(t->logfile[i]); } if(t->logfile_name[i]) { free(t->logfile_name[i]); } } t->logfile_sz = 0; if(t->fmt != NULL) { free(t->fmt); } free(t); optind=0; }