|
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 } |