filter.c
changeset 0 7f37716d4f1e
child 1 5af08d964c9e
equal deleted inserted replaced
-1:000000000000 0:7f37716d4f1e
       
     1 #include <stdio.h>
       
     2 #include <stdlib.h>
       
     3 #include <sys/select.h>
       
     4 #include <sys/types.h>
       
     5 #include <sys/wait.h>
       
     6 #include <unistd.h>
       
     7 
       
     8 #include "dictre.h"
       
     9 
       
    10 extern struct Def defs[];
       
    11 extern int ndefs;
       
    12 extern int dont_touch[];
       
    13 extern int ndont_touch;
       
    14 
       
    15 static void more_memory(void **ptr, int size)
       
    16 {
       
    17     void *new;
       
    18 
       
    19     new = realloc(*ptr, size);
       
    20     *ptr = new;
       
    21 }
       
    22 
       
    23 static
       
    24 char * manage_filter(const char *def, int deflen, int writeto, int readfrom,
       
    25         int *outlen)
       
    26 {
       
    27     int maxfd;
       
    28     int defptr;
       
    29     int outptr;
       
    30     char *out;
       
    31     int outsize;
       
    32     int outrest;
       
    33 
       
    34     out = 0;
       
    35     outsize = 1000;
       
    36     outptr = 0;
       
    37     more_memory((void **) &out, outsize);
       
    38     outrest = 1000;
       
    39 
       
    40     maxfd = writeto;
       
    41     if (readfrom > maxfd)
       
    42         maxfd = readfrom;
       
    43 
       
    44     defptr = 0;
       
    45     do
       
    46     {
       
    47         fd_set writeset, readset;
       
    48         FD_ZERO(&writeset);
       
    49         FD_ZERO(&readset);
       
    50         if (defptr < deflen)
       
    51             FD_SET(writeto, &writeset);
       
    52         FD_SET(readfrom, &readset);
       
    53 
       
    54         select(maxfd+1, &readset, &writeset, 0, 0);
       
    55 
       
    56         if (FD_ISSET(readfrom, &readset))
       
    57         {
       
    58             int res;
       
    59             res = read(readfrom, out + outptr, outrest);
       
    60             if (res == 0)
       
    61             {
       
    62                 close(readfrom);
       
    63                 break;
       
    64             }
       
    65             outrest -= res;
       
    66             outptr += res;
       
    67             if (outrest == 0)
       
    68             {
       
    69                 outrest = 1000;
       
    70                 outsize += 1000;
       
    71                 more_memory((void **) &out, outsize);
       
    72             }
       
    73         }
       
    74 
       
    75         if (FD_ISSET(writeto, &writeset))
       
    76         {
       
    77             int res;
       
    78             res = write(writeto, def+defptr, 1);
       
    79             defptr++;
       
    80             if (defptr >= deflen)
       
    81                 close(writeto);
       
    82         }
       
    83     } while(1);
       
    84 
       
    85     if (defptr < deflen)
       
    86     {
       
    87         fprintf(stderr, "Error in filter! not all written.\n");
       
    88         exit(-1);
       
    89     }
       
    90 
       
    91     *outlen = outptr;
       
    92     return out;
       
    93 }
       
    94 
       
    95 static char * filter(char *def, int deflen, const char *filter_par, int *outlen)
       
    96 {
       
    97     int write_pipe[2];
       
    98     int read_pipe[2];
       
    99     int pid;
       
   100     int res;
       
   101     int status;
       
   102     char *out;
       
   103 
       
   104     pipe(write_pipe);
       
   105     pipe(read_pipe);
       
   106 
       
   107 
       
   108     pid = fork();
       
   109     switch(pid)
       
   110     {
       
   111         case 0:  /* child */
       
   112             close(0);
       
   113             dup(write_pipe[0]);
       
   114             close(write_pipe[0]);
       
   115             close(write_pipe[1]);
       
   116             close(1);
       
   117             dup(read_pipe[1]);
       
   118             close(read_pipe[1]);
       
   119             close(read_pipe[0]);
       
   120             execlp("bash", "bash", "-c", filter_par, 0);
       
   121             perror("execlp");
       
   122             exit(-1);
       
   123             break;
       
   124         case -1:
       
   125             perror("fork");
       
   126             exit(-1);
       
   127             break;
       
   128         default:  /* parent */
       
   129             close(write_pipe[0]);
       
   130             close(read_pipe[1]);
       
   131             break;
       
   132     }
       
   133 
       
   134     /* parent */
       
   135     out = manage_filter(def, deflen, write_pipe[1], read_pipe[0], outlen);
       
   136 
       
   137     res = wait(&status);
       
   138     if (res != pid || WEXITSTATUS(status) != 0)
       
   139     {
       
   140         fprintf(stderr, "Error filtering: pid=%i status=%i",
       
   141                 pid, WEXITSTATUS(status));
       
   142         exit(-1);
       
   143     }
       
   144 
       
   145     return out;
       
   146 }
       
   147 
       
   148 static int in_dont_touch(int n)
       
   149 {
       
   150     int i;
       
   151     for(i =0; i < ndont_touch; ++i)
       
   152     {
       
   153         if (n == dont_touch[i])
       
   154         {
       
   155             return 1;
       
   156         }
       
   157     }
       
   158     return 0;
       
   159 }
       
   160 
       
   161 void filter_all(const char *filter_par)
       
   162 {
       
   163     int i;
       
   164 
       
   165     for(i=0; i < ndefs; ++i)
       
   166     {
       
   167         char *newdef;
       
   168         int newdeflen;
       
   169         if (!in_dont_touch(i))
       
   170         {
       
   171             newdef = filter(defs[i].d, defs[i].length,
       
   172                     filter_par, &newdeflen);
       
   173             defs[i].length = newdeflen;
       
   174             defs[i].d = newdef;
       
   175         }
       
   176     }
       
   177 }