--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/filter.c Sun Aug 05 23:06:42 2007 +0200
@@ -0,0 +1,177 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/select.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+#include "dictre.h"
+
+extern struct Def defs[];
+extern int ndefs;
+extern int dont_touch[];
+extern int ndont_touch;
+
+static void more_memory(void **ptr, int size)
+{
+ void *new;
+
+ new = realloc(*ptr, size);
+ *ptr = new;
+}
+
+static
+char * manage_filter(const char *def, int deflen, int writeto, int readfrom,
+ int *outlen)
+{
+ int maxfd;
+ int defptr;
+ int outptr;
+ char *out;
+ int outsize;
+ int outrest;
+
+ out = 0;
+ outsize = 1000;
+ outptr = 0;
+ more_memory((void **) &out, outsize);
+ outrest = 1000;
+
+ maxfd = writeto;
+ if (readfrom > maxfd)
+ maxfd = readfrom;
+
+ defptr = 0;
+ do
+ {
+ fd_set writeset, readset;
+ FD_ZERO(&writeset);
+ FD_ZERO(&readset);
+ if (defptr < deflen)
+ FD_SET(writeto, &writeset);
+ FD_SET(readfrom, &readset);
+
+ select(maxfd+1, &readset, &writeset, 0, 0);
+
+ if (FD_ISSET(readfrom, &readset))
+ {
+ int res;
+ res = read(readfrom, out + outptr, outrest);
+ if (res == 0)
+ {
+ close(readfrom);
+ break;
+ }
+ outrest -= res;
+ outptr += res;
+ if (outrest == 0)
+ {
+ outrest = 1000;
+ outsize += 1000;
+ more_memory((void **) &out, outsize);
+ }
+ }
+
+ if (FD_ISSET(writeto, &writeset))
+ {
+ int res;
+ res = write(writeto, def+defptr, 1);
+ defptr++;
+ if (defptr >= deflen)
+ close(writeto);
+ }
+ } while(1);
+
+ if (defptr < deflen)
+ {
+ fprintf(stderr, "Error in filter! not all written.\n");
+ exit(-1);
+ }
+
+ *outlen = outptr;
+ return out;
+}
+
+static char * filter(char *def, int deflen, const char *filter_par, int *outlen)
+{
+ int write_pipe[2];
+ int read_pipe[2];
+ int pid;
+ int res;
+ int status;
+ char *out;
+
+ pipe(write_pipe);
+ pipe(read_pipe);
+
+
+ pid = fork();
+ switch(pid)
+ {
+ case 0: /* child */
+ close(0);
+ dup(write_pipe[0]);
+ close(write_pipe[0]);
+ close(write_pipe[1]);
+ close(1);
+ dup(read_pipe[1]);
+ close(read_pipe[1]);
+ close(read_pipe[0]);
+ execlp("bash", "bash", "-c", filter_par, 0);
+ perror("execlp");
+ exit(-1);
+ break;
+ case -1:
+ perror("fork");
+ exit(-1);
+ break;
+ default: /* parent */
+ close(write_pipe[0]);
+ close(read_pipe[1]);
+ break;
+ }
+
+ /* parent */
+ out = manage_filter(def, deflen, write_pipe[1], read_pipe[0], outlen);
+
+ res = wait(&status);
+ if (res != pid || WEXITSTATUS(status) != 0)
+ {
+ fprintf(stderr, "Error filtering: pid=%i status=%i",
+ pid, WEXITSTATUS(status));
+ exit(-1);
+ }
+
+ return out;
+}
+
+static int in_dont_touch(int n)
+{
+ int i;
+ for(i =0; i < ndont_touch; ++i)
+ {
+ if (n == dont_touch[i])
+ {
+ return 1;
+ }
+ }
+ return 0;
+}
+
+void filter_all(const char *filter_par)
+{
+ int i;
+
+ for(i=0; i < ndefs; ++i)
+ {
+ char *newdef;
+ int newdeflen;
+ if (!in_dont_touch(i))
+ {
+ newdef = filter(defs[i].d, defs[i].length,
+ filter_par, &newdeflen);
+ defs[i].length = newdeflen;
+ defs[i].d = newdef;
+ }
+ }
+}