"Fossies" - the Fresh Open Source Software Archive

Member "ffe-0.3.9/src/ffe.c" (12 Feb 2017, 32584 Bytes) of package /linux/privat/ffe-0.3.9.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "ffe.c" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 0.3.7_vs_0.3.7-1.

    1 /*
    2  *    ffe - Flat File Extractor
    3  *
    4  *    Copyright (C) 2006 Timo Savinen
    5  *    This file is part of ffe.
    6  * 
    7  *    ffe is free software; you can redistribute it and/or modify
    8  *    it under the terms of the GNU General Public License as published by
    9  *    the Free Software Foundation; either version 2 of the License, or
   10  *    (at your option) any later version.
   11  *
   12  *    ffe is distributed in the hope that it will be useful,
   13  *    but WITHOUT ANY WARRANTY; without even the implied warranty of
   14  *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   15  *    GNU General Public License for more details.
   16  *
   17  *    You should have received a copy of the GNU General Public License
   18  *    along with ffe; if not, write to the Free Software
   19  *    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
   20  *    F607480034
   21  *    HJ9004-2
   22  *
   23  */
   24 
   25 /* $Id: ffe.c,v 1.88 2011-04-10 10:12:10 timo Exp $ */
   26 
   27 #include "ffe.h"
   28 #include <ctype.h>
   29 #include <stdlib.h>
   30 
   31 #ifdef HAVE_GETOPT_H
   32 #include <getopt.h>
   33 #endif
   34 
   35 #ifdef HAVE_STRING_H
   36 #include <string.h>
   37 #endif
   38 
   39 #ifdef HAVE_SIGNAL_H
   40 #include <signal.h>
   41 #endif
   42 
   43 #ifdef PACKAGE
   44 static char *program = PACKAGE;
   45 #else
   46 static char *program = "ffe";
   47 #endif
   48 
   49 #ifdef PACKAGE_VERSION
   50 static char *version = PACKAGE_VERSION;
   51 #else
   52 static char *version = "0.2.5";
   53 #endif
   54 
   55 #ifdef HOST
   56 static char *host = HOST;
   57 #else
   58 static char *host = "";
   59 #endif
   60 
   61 #ifdef PACKAGE_BUGREPORT
   62 static char *email_address = PACKAGE_BUGREPORT;
   63 #else
   64 static char *email_address = "tjsa@iki.fi";
   65 #endif
   66 
   67 static char short_opts[] = "c:s:o:p:f:e:r:A:l?VavdIX";
   68 
   69 #ifdef HAVE_GETOPT_LONG
   70 static struct option long_opts[] = {
   71     {"configuration",1,NULL,'c'},
   72     {"structure",1,NULL,'s'},
   73     {"output",1,NULL,'o'},
   74     {"print",1,NULL,'p'},
   75     {"field-list",1,NULL,'f'},
   76     {"loose",0,NULL,'l'},
   77     {"expression",1,NULL,'e'},
   78     {"help",0,NULL,'?'},
   79     {"version",0,NULL,'V'},
   80     {"and",0,NULL,'a'},
   81     {"invert-match",0,NULL,'v'},
   82     {"replace",1,NULL,'r'},
   83     {"debug",0,NULL,'d'},
   84     {"info",0,NULL,'I'},
   85     {"casecmp",0,NULL,'X'},
   86     {"anonymize",1,NULL,'A'},
   87     {NULL,0,NULL,0}
   88 };
   89 #endif
   90 
   91 extern void print_info();
   92 extern void init_libgcrypt();
   93 
   94 
   95 extern struct input_file *files;
   96 
   97 int system_endianess = F_UNKNOWN_ENDIAN;
   98 int max_binary_record_length = 0;
   99 char *ffe_open = NULL;
  100 
  101 
  102 
  103 /* global rc-data */
  104 struct structure *structure = NULL;
  105 struct output *output = NULL;
  106 struct expression *expression = NULL;
  107 struct lookup *lookup = NULL;
  108 struct replace *replace = NULL;
  109 struct field *const_field = NULL;
  110 struct pipe *pipes = NULL;
  111 struct anon_field *anonymize = NULL;
  112 
  113 /* output no marker */
  114 struct output dummy_no;
  115 struct output *no_output = &dummy_no;
  116 struct output dummy_raw;
  117 struct output *raw = &dummy_raw;
  118 
  119 void
  120 panic(char *msg,char *info,char *syserror)
  121 {
  122     if (info == NULL && syserror == NULL)
  123     {
  124         fprintf(stderr,"%s: %s\n",program,msg);
  125     } else if(info != NULL && syserror == NULL)
  126     {
  127         fprintf(stderr,"%s: %s: %s\n",program,msg,info);
  128     } else if(info != NULL && syserror != NULL)
  129     {
  130         fprintf(stderr,"%s: %s: %s; %s\n",program,msg,info,syserror);
  131     } else if(info == NULL && syserror != NULL)
  132     {
  133         fprintf(stderr,"%s: %s; %s\n",program,msg,syserror);
  134     }
  135     exit(EXIT_FAILURE);
  136 }
  137 
  138 void
  139 problem(char *msg,char *info,char *syserror)
  140 {
  141     if (info == NULL && syserror == NULL)
  142     {
  143         fprintf(stderr,"%s: %s\n",program,msg);
  144     } else if(info != NULL && syserror == NULL)
  145     {
  146         fprintf(stderr,"%s: %s: %s\n",program,msg,info);
  147     } else if(info != NULL && syserror != NULL)
  148     {
  149         fprintf(stderr,"%s: %s: %s; %s\n",program,msg,info,syserror);
  150     } else if(info == NULL && syserror != NULL)
  151     {
  152         fprintf(stderr,"%s: %s; %s\n",program,msg,syserror);
  153     }
  154 }
  155 
  156 
  157 char *
  158 get_default_rc_name()
  159 {
  160     char *home;
  161     char *result;
  162 #ifdef WIN32
  163     char *file = "ffe.rc";
  164 #else
  165     char *file = ".fferc";
  166 #endif
  167 
  168     result = NULL;
  169     home = getenv("HOME");
  170 #ifdef WIN32
  171     if(home == NULL)
  172     {
  173         home = getenv("FFE_HOME");
  174         if(home == NULL)
  175         {
  176             home = getenv("USERPROFILE");
  177         }
  178     }
  179 #endif
  180     if(home != NULL)
  181     {
  182             result = xmalloc(strlen(home) + strlen(file) + strlen(PATH_SEPARATOR_STRING) + 2);
  183             strcpy(result,home);
  184             strcat(result,PATH_SEPARATOR_STRING);
  185             strcat(result,file);
  186     } else
  187     {
  188         result = file;
  189     }
  190     return result;
  191 }
  192         
  193 void
  194 help(FILE *stream)
  195 {
  196     char *rc=get_default_rc_name();
  197     fprintf(stream,"Usage: %s [OPTION]...\n\n",program);
  198 #ifdef HAVE_GETOPT_LONG
  199     fprintf(stream,"-c, --configuration=FILE\n");
  200     fprintf(stream,"\t\tRead configuration from FILE, default is \'%s\'.\n",rc);
  201     fprintf(stream,"-s, --structure=STRUCTURE\n");
  202     fprintf(stream,"\t\tUse structure STRUCTURE for input file, suppresses guessing.\n");
  203     fprintf(stream,"-p, --print=FORMAT\n");
  204     fprintf(stream,"\t\tUse output format FORMAT for printing.\n");
  205     fprintf(stream,"-o, --output=NAME\n");
  206     fprintf(stream,"\t\tWrite output to NAME instead of standard output.\n");
  207     fprintf(stream,"-f, --field-list=LIST\n");
  208     fprintf(stream,"\t\tPrint only fields and constants listed in comma separated list LIST.\n");
  209     fprintf(stream,"-e, --expression=EXPRESSION\n");
  210     fprintf(stream,"\t\tPrint only those records for which the EXPRESSION evaluates to true.\n");
  211     fprintf(stream,"-a, --and\n");
  212     fprintf(stream,"\t\tExpressions are combined with logical and, default is logical or.\n");
  213     fprintf(stream,"-X, --casecmp\n");
  214     fprintf(stream,"\t\tExpressions are evaluated case insensitive.\n");
  215     fprintf(stream,"-v, --invert-match\n");
  216     fprintf(stream,"\t\tPrint only those records which don't match the expression.\n");
  217     fprintf(stream,"-l, --loose\n");
  218     fprintf(stream,"\t\tAn invalid input line does not cause %s to abort.\n",program);
  219     fprintf(stream,"-r, --replace=FIELD=VALUE\n");
  220     fprintf(stream,"\t\tReplace FIELDs contents with VALUE in output.\n");
  221     fprintf(stream,"-d, --debug\n");
  222     fprintf(stream,"\t\tWrite invalid input lines to error log.\n");
  223     fprintf(stream,"-I, --info\n");
  224     fprintf(stream,"\t\tShow the structure information and exit.\n");
  225     fprintf(stream,"-A, --anonymize=ANONYMIZE\n");
  226     fprintf(stream,"\t\tUse anonymization ANONYMIZE to anomymize certain input fields.\n");
  227     fprintf(stream,"-?, --help\n");
  228     fprintf(stream,"\t\tDisplay this help and exit.\n");
  229     fprintf(stream,"-V, --version\n");
  230 #else
  231     fprintf(stream,"-c FILE\n");
  232     fprintf(stream,"\t\tRead configuration from FILE, default is \'%s\'.\n",rc);
  233     fprintf(stream,"-s STRUCTURE\n");
  234     fprintf(stream,"\t\tUse structure STRUCTURE for input file, suppresses guessing.\n");
  235     fprintf(stream,"-p FORMAT\n");
  236     fprintf(stream,"\t\tUse output format FORMAT for printing.\n");
  237     fprintf(stream,"-o NAME\n");
  238     fprintf(stream,"\t\tWrite output to NAME instead of standard output.\n");
  239     fprintf(stream,"-f LIST\n");
  240     fprintf(stream,"\t\tPrint only fields and constants listed in comma separated list LIST.\n");
  241     fprintf(stream,"-e EXPRESSION\n");
  242     fprintf(stream,"\t\tPrint only those records for which the EXPRESSION evaluates to true.\n");
  243     fprintf(stream,"-a\n");
  244     fprintf(stream,"\t\tExpressions are combined with logical and, default is logical or.\n");
  245     fprintf(stream,"-X\n");
  246     fprintf(stream,"\t\tExpressions are evaluated case insensitive.\n");
  247     fprintf(stream,"-v\n");
  248     fprintf(stream,"\t\tPrint only those records which don't match the expression.\n");
  249     fprintf(stream,"-l\n");
  250     fprintf(stream,"\t\tAn invalid input line does not cause %s to abort.\n",program);
  251     fprintf(stream,"-r FIELD=VALUE\n");
  252     fprintf(stream,"\t\tReplace FIELDs contents with VALUE in output.\n");
  253     fprintf(stream,"-d\n");
  254     fprintf(stream,"\t\tWrite invalid input lines to error log.\n");
  255     fprintf(stream,"-I\n");
  256     fprintf(stream,"\t\tShow the structure information and exit.\n");
  257     fprintf(stream,"-A ANONYMIZE\n");
  258     fprintf(stream,"\t\tUse anonymization ANONYMIZE to anomymize certain input fields.\n");
  259     fprintf(stream,"-?\n");
  260     fprintf(stream,"\t\tDisplay this help and exit.\n");
  261     fprintf(stream,"-V\n");
  262 #endif
  263     fprintf(stream,"\t\tShow version and exit.\n");
  264     fprintf(stream,"\nAll remaining arguments are names of input files;\n");
  265     fprintf(stream,"if no input files are specified, then the standard input is read.\n");
  266     fprintf(stream,"\nSend bug reports to %s.\n",email_address);
  267     free(rc);
  268 }
  269 
  270 void
  271 usage(int opt)
  272 {
  273         fprintf(stderr,"Unknown option '-%c'\n",(char) opt);
  274         help(stderr);
  275 }
  276 
  277 void
  278 print_version()
  279 {
  280     printf("%s version %s\n%s\n",program,version,host);
  281     printf("Copyright (c) 2007 Timo Savinen\n\n");
  282     printf("This is free software; see the source for copying conditions.\n");
  283     printf("There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n");
  284 }
  285 
  286 size_t
  287 hash(char *str,size_t len)
  288 {
  289     register unsigned long h = 5381;
  290     int c;
  291 
  292     if(len > 0)
  293     {
  294         while ((c = *str++) != 0 && len > 0)
  295         {
  296             h = ((h << 5) + h) + c;
  297             len--;
  298         }
  299     }else
  300     {
  301         while ((c = *str++) != 0)
  302         {
  303             h = ((h << 5) + h) + c;
  304         }
  305     }
  306     return (size_t) (h % MAX_EXPR_HASH);
  307 }
  308 
  309 /* update anonymization pointers to fields which should be anonymized
  310  * return the number of found fields
  311  */
  312 int update_anon_info(struct structure *s,char *anon)
  313 {
  314      struct record *r = s->r;
  315      struct field *f;
  316      struct anon_field *a;
  317      int retval = 0;
  318      int found = 0;
  319 
  320      if(anon == NULL) return 0;
  321 
  322      while(r != NULL)
  323      {
  324          f = r->f;
  325          while(f != NULL)
  326          {
  327              a = anonymize;
  328              while(f->a == NULL && a != NULL)
  329              {
  330                  if(strcasecmp(a->anon_name,anon) == 0 && strcasecmp(f->name,a->field_name) == 0)
  331                  {
  332                      if(!found) found = 1;
  333                      if(strcasecmp(f->name,a->field_name) == 0)
  334                      {
  335                          f->a = a;
  336                          retval++;
  337                      }
  338                  }
  339                  a = a->next;
  340              }
  341              f = f->next;
  342          }
  343          r = r->next;
  344      }
  345      if(!found) panic("Unknown anonymization",anon,NULL);
  346      return retval;
  347 }
  348 
  349 
  350 
  351 
  352 struct output *
  353 search_output(char *name)
  354 {
  355     struct output *o = output;
  356 
  357     if(strcmp(name,"no") == 0) return no_output;
  358     if(strcmp(name,"raw") == 0) return raw;
  359 
  360     while(o != NULL)
  361     {
  362         if(strcmp(name,o->name) == 0) return o;
  363         o = o->next;
  364     }
  365     fprintf(stderr,"%s: Unknown output \'%s\'\n",program,name);
  366     return NULL;
  367 }
  368 
  369 struct pipe *
  370 search_pipe(char *name)
  371 {
  372     struct pipe *p = pipes;
  373 
  374     while(p != NULL)
  375     {
  376         if(strcmp(name,p->name) == 0) return p;
  377         p = p->next;
  378     }
  379     return NULL;
  380 }
  381 
  382 /* returns a record after name */
  383 struct record *
  384 find_record(struct structure *s,char *name)
  385 {
  386     struct record *ret = s->r;
  387 
  388     while(ret != NULL)
  389     {
  390         if(strcmp(ret->name,name) == 0) return ret;
  391         ret = ret->next;
  392     }
  393     return NULL;
  394 }
  395 
  396 /* find a structure after a name */
  397 struct structure *
  398 find_structure(char *name)
  399 {
  400     struct structure *s = structure;
  401 
  402     while(s != NULL)
  403     {
  404         if(strcmp(s->name,name) == 0) return s;
  405         s = s->next;
  406     }
  407     return NULL;
  408 }
  409 
  410 /* check structure and output integrity */
  411 /* and initialize some things */
  412 void 
  413 check_rc(char *use_output)
  414 {
  415     struct structure *s;
  416     struct output *o;
  417     struct record *r,*fr;
  418     struct field *f;
  419     struct lookup *l;
  420     int several_records = 0;
  421     int errors = 0;
  422     int ordinal;
  423     int field_count_first;
  424     int var_field_found;
  425     char num[64];
  426 
  427     s = structure;
  428     o = output;
  429 
  430     if(s == NULL)
  431     {
  432         errors++;
  433         fprintf(stderr,"%s: No structure definitions in rc-file\n",program);
  434     }
  435 
  436     while(s != NULL)
  437     {
  438         if(use_output != NULL)
  439         {
  440             free(s->output_name);
  441             s->output_name = xstrdup(use_output);
  442         }
  443 
  444         if(s->output_name == NULL)
  445         {
  446             s->output_name = DEFAULT_OUTPUT;
  447         }
  448 
  449         s->o = search_output(s->output_name);
  450         s->max_record_len = 0;
  451         if(s->o == NULL) errors++;
  452         r = s->r;
  453         if(r == NULL) 
  454         {
  455             errors++;
  456             fprintf(stderr,"%s: No records in structure \'%s\'\n",program,s->name);
  457         } else
  458         {
  459             several_records = r->next != NULL ? 1 : 0;
  460         }
  461         if(s->quote && s->type[0] == SEPARATED)
  462         {
  463             if(s->quote == s->type[1])
  464             {
  465                 errors++;
  466                 fprintf(stderr,"%s: Quotation and separator cannot be the same character, structure \'%s\'\n",program,s->name);
  467             }
  468         }
  469         if(s->header && s->type[0] != SEPARATED)
  470         {
  471             errors++;
  472             fprintf(stderr,"%s: Headers are valid only in separated input, structure \'%s\'\n",program,s->name);
  473         }
  474 
  475         field_count_first = 0;
  476 
  477         while(r != NULL)
  478         {
  479             if(r->output_name == NULL || use_output != NULL) 
  480             {
  481                 if(r->output_name != NULL) free(r->output_name);
  482                 r->output_name = s->output_name;
  483                 r->o = s->o;
  484             } else
  485             {
  486                 r->o = search_output(r->output_name);
  487                 if(r->o == NULL) errors++;
  488             }
  489 
  490             if(several_records && s->type[0] == BINARY && r->i == NULL)
  491             {
  492                 errors++;
  493                 fprintf(stderr,"%s: Every record in a binary multi-record structure must have an id, structure \'%s\', record \'%s\'\n",program,s->name,r->name);
  494             }
  495 
  496             if(r->fields_from != NULL)
  497             {
  498                 if(r->f != NULL)
  499                 {
  500                     errors++;
  501                     fprintf(stderr,"%s: field and fields-from are mutually exclusive, structure \'%s\', record \'%s\'\n",program,s->name,r->name);
  502                 }
  503                 fr = find_record(s,r->fields_from);
  504                 if(fr != NULL)
  505                 {
  506                     r->f = fr->f;
  507                 } else
  508                 {
  509                     errors++;
  510                     fprintf(stderr,"%s: No record named as '\%s\' in structure \'%s\'\n",program,r->fields_from,s->name);
  511                 }
  512             }
  513 
  514             f = r->f;
  515             if(f == NULL)
  516             {
  517                 errors++;
  518                 fprintf(stderr,"%s: No fields in record \'%s\'\n",program,r->name);
  519             }
  520             r->length = 0;
  521             ordinal = 1;
  522             var_field_found = 0;
  523             while(f != NULL) 
  524             {
  525                 if(s->type[0] == FIXED_LENGTH || s->type[0] == BINARY)
  526                 {
  527                     if (r->length_field_name != NULL && strcmp(r->length_field_name,f->name) == 0) r->length_field = f;
  528                     if (r->var_field_name != NULL && strcmp(r->var_field_name,f->name) == 0) 
  529                     {
  530                          f->length = 0;  
  531                          f->var_length = 1;  
  532                     }
  533                     f->position = r->length;
  534                     f->bposition = r->length;
  535                     r->length += f->length;
  536                 } else
  537                 {
  538                     f->position = ordinal;
  539                     r->length++;
  540                     if(s->header)
  541                     {
  542                         if(r == s->r) 
  543                         {
  544                             field_count_first++;
  545                         } 
  546                     }
  547                 }
  548 
  549                 if(!s->header && f->name == NULL)
  550                 {
  551                     sprintf(num,"%d",ordinal);
  552                     f->name = xstrdup(num);
  553                 }
  554 
  555                 if(s->type[0] == BINARY && f->length < 1)
  556                 {
  557                     if((r->length_field != NULL && var_field_found) || !r->length_field_name)
  558                     {
  559                         errors++;
  560                         fprintf(stderr,"%s: The field \'%s\' must have length in binary structure \'%s\' record \'%s\'\n",program ,f->name,s->name,r->name);
  561                     }
  562                     var_field_found = 1;
  563                 }
  564 
  565                 if(s->type[0] == FIXED_LENGTH && f->length < 1)
  566                 {
  567                     if(f->next) /* last field can have length 0 */
  568                     {
  569                         if(r->length_field != NULL && var_field_found)
  570                         {
  571                             errors++;
  572                             fprintf(stderr,"%s: The field \'%s\' must have length in fixed length structure \'%s\' record \'%s\'\n",program,f->name,s->name,r->name);
  573                         }
  574                         var_field_found = 1;
  575                     } else
  576                     {
  577                         if(r->length_field == NULL) r->arb_length = 1;
  578                     }
  579                 }
  580 
  581                 if(f->lookup_table_name != NULL)
  582                 {
  583                     l = lookup;
  584 
  585                     while(l != NULL && f->lookup == NULL)
  586                     {
  587                         if(strcmp(l->name,f->lookup_table_name) == 0)
  588                         {
  589                             f->lookup = l;
  590                         }
  591                         l = l->next;
  592                     }
  593 
  594                     if(f->lookup == NULL)
  595                     {
  596                         errors++;
  597                         fprintf(stderr,"%s: No lookup table named as '%s'\n",program,f->lookup_table_name);
  598                     }
  599                 }
  600 
  601                 if(f->output_name != NULL && use_output == NULL)
  602                 {
  603                     f->o = search_output(f->output_name);
  604                     if(f->o == NULL) errors++;
  605                     if(f->o == raw) {
  606                         errors++;
  607                         fprintf(stderr,"%s: Field cannot have output \'raw\', field \'%s\'\n",program,f->name);
  608                     }
  609                 }
  610 
  611                 if(f->pipe_name != NULL)
  612                 {
  613                     f->p = search_pipe(f->pipe_name);
  614                     if(f->p == NULL) {
  615                         errors++;
  616                         fprintf(stderr,"%s: No filter named as '%s'\n",program,f->pipe_name);
  617                     }
  618                 }
  619 
  620                 f = f->next;
  621                 ordinal++;
  622             }
  623 
  624             if (r->length_field_name != NULL && !r->length_field) {
  625                 errors++;
  626                 fprintf(stderr,"%s: Record \'%s\' does not contain length field '\%s\'\n",program,r->name,r->length_field_name);
  627             }
  628 
  629             if(r->length < 1 && s->type[0] == BINARY) {
  630                 errors++;
  631                 fprintf(stderr,"%s: Record \'%s\' in structure \'%s\' must have length\n",program,r->name,s->name);
  632             }
  633 
  634             if(r->length > s->max_record_len) s->max_record_len = r->length;
  635             if(s->type[0] == BINARY && s->max_record_len > max_binary_record_length) max_binary_record_length = s->max_record_len;
  636 
  637             if(s->header && r->length != field_count_first)
  638             {
  639                 errors++;
  640                 fprintf(stderr,"%s: All records in separated structure with header must have equal count of fields, structure \'%s\'\n",program,s->name);
  641             }
  642             r = r->next;
  643         }
  644         s = s->next;
  645     }
  646     
  647     if(o == NULL)
  648     {
  649         errors++;
  650         fprintf(stderr,"%s: No output definitions in rc-file\n",program);
  651     }
  652 
  653     while(o != NULL)
  654     {
  655         if(o->lookup == NULL) o->lookup = o->data;
  656         if(o->output_file != NULL)
  657         {
  658             if(o->output_file[0] == '-' && o->output_file[1] == 0)
  659             {
  660                 o->ofp = stdout;
  661                 free(o->output_file);
  662                 o->output_file = "(stdout)";
  663             } else
  664             {
  665                 o->ofp = xfopen(o->output_file,"w");
  666             }
  667         }
  668         o = o->next;
  669     }
  670 
  671     if(errors)
  672     {
  673         panic("Errors in rc-file",NULL,NULL);
  674     }
  675 }
  676 
  677 void
  678 add_replace(char *optarg)
  679 {
  680     char *op_pos;
  681     struct replace *r;
  682 
  683     if((op_pos = strchr(optarg,'=')) == NULL)
  684     {
  685         panic("Replace expression must contain =-character",optarg,NULL);
  686     }
  687 
  688     *op_pos = 0;
  689 
  690     r = replace;
  691 
  692     if(r == NULL)
  693     {
  694         replace = xmalloc(sizeof(struct replace));
  695         replace->next =  NULL;
  696         r = replace;
  697     } else
  698     {
  699         while(r->next != NULL) r = r->next;
  700         r->next = xmalloc(sizeof(struct replace));
  701         r = r->next;
  702         r->next = NULL;
  703     }
  704 
  705     r->field = xstrdup(optarg);
  706     op_pos++;
  707     r->value = (uint8_t *) xstrdup(op_pos);
  708     r->found = 0;
  709 }
  710 
  711 
  712 /* adds an item to expression hash list 
  713     */
  714 static void
  715 add_expression_to_list(struct expr_list **list, char *value)
  716 {
  717     size_t h = hash(value,0);
  718     register struct expr_list *e = list[h];
  719 
  720     if(e == NULL)
  721     {
  722         e = xmalloc(sizeof(struct expr_list));
  723         list[h] = e;
  724     } else
  725     {
  726         while(e->next != NULL) e = e->next;
  727         e->next = xmalloc(sizeof(struct expr_list));
  728         e = e->next;
  729     }
  730     e->value = xstrdup(value);
  731     e->value_len = strlen(e->value);
  732     e->next = NULL;
  733 }
  734 
  735 
  736 static void
  737 read_expression_file(struct expr_list **list, char *file)
  738 {
  739     FILE *fp;
  740     register int ccount;
  741     size_t line_len = 1024;
  742     char *line = xmalloc(line_len);
  743 
  744     fp = xfopen(file,"r");
  745 
  746     do
  747     {
  748 #ifdef HAVE_GETLINE
  749         ccount = getline(&line,&line_len,fp);
  750 #else
  751         if(fgets(line,line_len,fp) != NULL)
  752         {
  753             ccount = strlen(line);
  754         } else
  755         {
  756             ccount = -1;
  757         }
  758 #endif
  759         if (ccount > 1)
  760         {
  761             line[ccount - 1] = 0;
  762             add_expression_to_list(list,line);
  763         }
  764     }
  765     while(ccount != -1);
  766     fclose(fp);
  767     free(line);
  768 }
  769 
  770 static void
  771 init_expr_hash(struct expr_list **list)
  772 {
  773     register int i = 0;
  774 
  775     while(i < MAX_EXPR_HASH) list[i++] = NULL;
  776 }
  777 
  778 
  779 void
  780 add_expression(char *optarg)
  781 {
  782     char *op_pos;
  783     char op = 0;
  784     struct expression *e,*last;
  785     int found = 0;
  786     char *value_file;
  787 
  788     if((op_pos = strchr(optarg,OP_REQEXP)) != NULL)
  789     {
  790 #ifdef HAVE_REGEX
  791         op = OP_REQEXP;    
  792 #else
  793         panic("Regular expressions are not supported in this system",optarg,NULL);
  794 #endif
  795     } else if((op_pos = strchr(optarg,OP_EQUAL)) != NULL)
  796     {
  797         op = OP_EQUAL;
  798     } else if((op_pos = strchr(optarg,OP_START)) != NULL)
  799     {
  800         op = OP_START;
  801     } else if((op_pos = strchr(optarg,OP_CONTAINS)) != NULL)
  802     {
  803         op = OP_CONTAINS;
  804     } else if((op_pos = strchr(optarg,OP_NOT_EQUAL)) != NULL)
  805     {
  806         op = OP_NOT_EQUAL;
  807     } else
  808     {
  809         panic("Expression must contain an operator: =,^,~,? or !",optarg,NULL);
  810     }
  811 
  812     *op_pos = 0;
  813 
  814     e = expression;
  815 
  816     if(e == NULL)
  817     {
  818         expression = xmalloc(sizeof(struct expression));
  819         expression->next =  NULL;
  820         e = expression;
  821         e->field = xstrdup(optarg);
  822         e->exp_min_len = 0;
  823         e->exp_max_len = 0;
  824         e->fast_entries = 0;
  825         init_expr_hash(e->expr_hash); 
  826     } else
  827     {
  828         do
  829         {
  830             if(strcasecmp(optarg,e->field) == 0 && e->op == op) 
  831             {
  832                 found = 1;
  833             } else
  834             {
  835                 last = e;
  836                 e = e->next;
  837             }
  838         }
  839         while(e != NULL && !found);
  840 
  841         if(!found)
  842         {
  843             last->next = xmalloc(sizeof(struct expression));
  844             e = last->next;
  845             e->next = NULL;
  846             e->field = xstrdup(optarg);
  847             e->exp_min_len = 0;
  848             e->exp_max_len = 0;
  849             e->fast_entries = 0;
  850             init_expr_hash(e->expr_hash);
  851         }
  852     }
  853 
  854     op_pos++;
  855     if(strstr(op_pos,"file:") == op_pos)
  856     {
  857         value_file = expand_home(&op_pos[5]);
  858         read_expression_file(e->expr_hash,value_file);
  859         free(value_file);
  860     } else
  861     {
  862         add_expression_to_list(e->expr_hash,op_pos);
  863     }
  864     e->found = 0;
  865     e->op = op;
  866 }
  867 
  868 static void
  869 init_expression()
  870 {
  871     struct expression *e = expression;
  872     register struct expr_list *l;
  873     register int i;
  874     int rc,min_init;
  875     size_t buflen;
  876     char *errbuf;
  877 
  878     while(e != NULL)
  879     {
  880         i = 0;
  881         min_init = 0;
  882         while(i < MAX_EXPR_HASH)
  883         {
  884             l = e->expr_hash[i];
  885 
  886             if (l != NULL && e->fast_entries <= MAX_EXPR_FAST_LIST) e->fast_expr_hash[e->fast_entries++] = i; 
  887 
  888             while(l != NULL)
  889             {
  890                 if(!min_init) {min_init = 1;e->exp_min_len = l->value_len;}
  891                 if(l->value_len < e->exp_min_len) e->exp_min_len = l->value_len;
  892                 if(l->value_len > e->exp_max_len) e->exp_max_len = l->value_len;
  893 
  894 #ifdef HAVE_REGEX
  895                 if(e->op == OP_REQEXP)
  896                 {
  897                     rc = regcomp(&l->reg,l->value,REG_EXTENDED | REG_NOSUB);
  898                     if(rc)
  899                     {
  900                         buflen = regerror(rc,&l->reg,NULL,0);
  901                         errbuf = xmalloc(buflen + 1);
  902                         regerror(rc,&l->reg,errbuf,buflen);
  903                         panic("Error in regular expression",l->value,errbuf);
  904                     }
  905                 }
  906 #endif
  907                 l = l->next;
  908             }
  909             i++;
  910         }
  911         if(e->fast_entries > MAX_EXPR_FAST_LIST) e->fast_entries = 0; 
  912         e = e->next;
  913     }
  914 }
  915 
  916 /* if variable is set it will not be overwritten */
  917 void
  918 set_env(char *name, char *value)
  919 {
  920         if(name == NULL || value == NULL) return;
  921 #ifdef HAVE_SETENV
  922         if(setenv(name,value,0) != 0) problem("Cannot set environment",name,strerror(errno));
  923 #elif HAVE_PUTENV
  924         if(getenv(name) == NULL)
  925         {
  926              char *s = xmalloc(strlen(name)+strlen(value)+2);
  927              strcpy(s,name);
  928              strcat(s,"=");
  929              strcat(s,value);
  930              if(putenv(s) != 0) problem("Cannot set environment",s,strerror(errno));
  931         }
  932 #else
  933         problem("Cannot set environment",NULL,NULL);
  934 #endif
  935 }
  936 
  937 
  938 
  939 /* set FFE_STRUCTURE,FFE_FORMAT,FFE_OUTPUT,FFE_FIRST_FILE,FFE_FILES,*/
  940 /* returns 0 in case of error */
  941 /* if variable is set it will not be overwritten */
  942 void
  943 environment(char *structure, char *format,char *ofile)
  944 {
  945     struct input_file *f=files;
  946     char *file_names;
  947     size_t files_len = 1024,used = 0;
  948     
  949     set_env("FFE_STRUCTURE",structure);
  950     set_env("FFE_OUTPUT",ofile);
  951     set_env("FFE_FORMAT",format);
  952     set_env("FFE_FIRST_FILE",f->name);
  953     file_names = xmalloc(files_len);
  954     file_names[0] = 0;
  955     while(f != NULL)
  956     {
  957         used += strlen(f->name) + 1;
  958         if(used > files_len) 
  959         {
  960             files_len *= 2;
  961             file_names = xrealloc(file_names,files_len);
  962         }
  963         strcat(file_names,f->name);
  964         if(f->next != NULL) strcat(file_names," ");
  965         f = f->next;
  966     }
  967     set_env("FFE_FILES",file_names);
  968     free(file_names);
  969 }
  970 
  971 
  972 
  973 int
  974 main(int argc, char **argv)
  975 {
  976     int opt;
  977     int strict = 1;
  978     int debug = 0;
  979     int info = 0;
  980     int expression_and = 0;
  981     int expression_invert = 0;
  982     int expression_casecmp = 0;
  983     struct structure *s = NULL;
  984     char *structure_to_use = NULL;
  985     char *output_to_use = NULL;
  986     char *config_to_use = NULL;
  987     char *ofile_to_use = NULL;
  988     char *anon_to_use = NULL;
  989     char *field_list = NULL;
  990 
  991 #ifdef HAVE_SIGACTION
  992 #ifndef SA_NOCLDWAIT
  993 #define SA_NOCLDWAIT 0
  994 #endif
  995     struct sigaction act;
  996     sigemptyset(&act.sa_mask);
  997     act.sa_handler = SIG_IGN;
  998     act.sa_flags = SA_NOCLDWAIT;
  999     sigaction (SIGCHLD, &act, NULL);
 1000 #endif
 1001 
 1002 #ifdef HAVE_GETOPT_LONG
 1003     while ((opt = getopt_long(argc,argv,short_opts,long_opts,NULL)) != -1)
 1004 #else
 1005     while ((opt = getopt(argc,argv,short_opts)) != -1)
 1006 #endif
 1007         {
 1008             switch(opt)
 1009             {
 1010                 case 'c':
 1011                     if(config_to_use == NULL)
 1012                     {
 1013                         config_to_use = xstrdup(optarg);
 1014                     } else
 1015                     {
 1016                         panic("Only one -c option allowed",NULL,NULL);
 1017                     }
 1018                     break;
 1019                 case 's':
 1020                     if(structure_to_use == NULL)
 1021                     {
 1022                         structure_to_use = xstrdup(optarg);
 1023                     } else
 1024                     {
 1025                         panic("Only one -s option allowed",NULL,NULL);
 1026                     }
 1027                     break;
 1028                 case 'p':
 1029                     if(output_to_use == NULL)
 1030                     {
 1031                         output_to_use = xstrdup(optarg);
 1032                     } else
 1033                     {
 1034                         panic("Only one -p option allowed",NULL,NULL);
 1035                     }
 1036                     break;
 1037                 case 'f':
 1038                     if(field_list == NULL)
 1039                     {
 1040                         field_list = xstrdup(optarg);
 1041                     } else
 1042                     {
 1043                         panic("Only one -f option allowed",NULL,NULL);
 1044                     }
 1045                     break;
 1046                  case 'o':
 1047                     if(ofile_to_use == NULL)
 1048                     {
 1049                         ofile_to_use = xstrdup(optarg);
 1050                     } else
 1051                     {
 1052                         panic("Only one -o option allowed",NULL,NULL);
 1053                     }
 1054                     break; 
 1055                 case 'e':
 1056                     add_expression(optarg);
 1057                     break;
 1058                 case 'r':
 1059                     add_replace(optarg);
 1060                     break;
 1061                 case 'a':
 1062                     expression_and = 1;
 1063                     break;
 1064                 case 'X':
 1065                     expression_casecmp = 1;
 1066                     break;
 1067                 case 'd':
 1068                     debug = 1;
 1069                     break;
 1070                 case 'v':
 1071                     expression_invert = !expression_invert;
 1072                     break;
 1073                 case 'l':
 1074                     strict = 0;
 1075                     break;
 1076                 case '?':
 1077                     help(stdout);
 1078                     exit(EXIT_SUCCESS);
 1079                     break;
 1080                 case 'V':
 1081                     print_version();
 1082                     exit(EXIT_SUCCESS);
 1083                     break;
 1084                 case 'I':
 1085                     info = 1;
 1086                     break;
 1087                 case 'A':
 1088                     if(anon_to_use == NULL)
 1089                     {
 1090                         anon_to_use = xstrdup(optarg);
 1091                     } else
 1092                     {
 1093                         panic("Only one -A option allowed",NULL,NULL);
 1094                     }
 1095                     break;
 1096                 default:
 1097                     usage(opt);
 1098                     exit(EXIT_FAILURE);
 1099                     break;
 1100             }
 1101         }
 1102 
 1103 
 1104     if(optind < argc)
 1105     {
 1106         while(optind < argc) set_input_file(argv[optind++]);
 1107     } else
 1108     {
 1109         set_input_file("-");
 1110     }
 1111     
 1112     if(config_to_use == NULL) config_to_use = get_default_rc_name();
 1113 
 1114     environment(structure_to_use,output_to_use,ofile_to_use);
 1115     
 1116     system_endianess = check_system_endianess();
 1117                 
 1118     parserc(config_to_use,field_list);
 1119 
 1120     check_rc(output_to_use);
 1121      
 1122     init_expression();
 1123 
 1124     if(info)
 1125     {
 1126         print_info();
 1127         exit(EXIT_SUCCESS);
 1128     }
 1129     
 1130     ffe_open = getenv("FFEOPEN");
 1131 
 1132     if(structure_to_use == NULL)
 1133     {
 1134         open_input_file(BINARY);  // guess binary first
 1135         structure_to_use = guess_binary_structure();
 1136         if(structure_to_use == NULL)
 1137         {
 1138             structure_to_use = guess_structure();
 1139         }
 1140         if(structure_to_use == NULL) panic("Structure cannot be guessed, use -s option",NULL,NULL);
 1141         s = find_structure(structure_to_use);
 1142     } else
 1143     {
 1144         s = find_structure(structure_to_use);
 1145         if(s != NULL)
 1146         {
 1147             open_input_file(s->type[0]);
 1148         } else
 1149         {
 1150             panic("No structure named as",structure_to_use,NULL);
 1151         }
 1152     }
 1153  
 1154 
 1155     free(config_to_use); /* to avoid strange valgrind memory lost */
 1156 
 1157     set_output_file(ofile_to_use);
 1158 
 1159     execute(s,strict,expression_and,expression_invert,expression_casecmp,debug,anon_to_use);
 1160 
 1161     close_output_file();
 1162 
 1163     if(output_to_use != NULL) free(output_to_use);
 1164 
 1165     exit(EXIT_SUCCESS);
 1166 }
 1167