Blame


1 b8c14089 2003-11-23 devnull #include <u.h>
2 b8c14089 2003-11-23 devnull #include <libc.h>
3 b8c14089 2003-11-23 devnull #include <bio.h>
4 b8c14089 2003-11-23 devnull #include <regexp.h>
5 b8c14089 2003-11-23 devnull #include <thread.h>
6 b8c14089 2003-11-23 devnull #include <ctype.h>
7 b8c14089 2003-11-23 devnull #include <plumb.h>
8 b8c14089 2003-11-23 devnull #include "plumber.h"
9 b8c14089 2003-11-23 devnull
10 b8c14089 2003-11-23 devnull typedef struct Input Input;
11 b8c14089 2003-11-23 devnull typedef struct Var Var;
12 b8c14089 2003-11-23 devnull
13 b8c14089 2003-11-23 devnull struct Input
14 b8c14089 2003-11-23 devnull {
15 b8c14089 2003-11-23 devnull char *file; /* name of file */
16 b8c14089 2003-11-23 devnull Biobuf *fd; /* input buffer, if from real file */
17 b8c14089 2003-11-23 devnull uchar *s; /* input string, if from /mnt/plumb/rules */
18 b8c14089 2003-11-23 devnull uchar *end; /* end of input string */
19 b8c14089 2003-11-23 devnull int lineno;
20 b8c14089 2003-11-23 devnull Input *next; /* file to read after EOF on this one */
21 b8c14089 2003-11-23 devnull };
22 b8c14089 2003-11-23 devnull
23 b8c14089 2003-11-23 devnull struct Var
24 b8c14089 2003-11-23 devnull {
25 b8c14089 2003-11-23 devnull char *name;
26 b8c14089 2003-11-23 devnull char *value;
27 b8c14089 2003-11-23 devnull char *qvalue;
28 b8c14089 2003-11-23 devnull };
29 b8c14089 2003-11-23 devnull
30 b8c14089 2003-11-23 devnull static int parsing;
31 b8c14089 2003-11-23 devnull static int nvars;
32 b8c14089 2003-11-23 devnull static Var *vars;
33 b8c14089 2003-11-23 devnull static Input *input;
34 b8c14089 2003-11-23 devnull
35 b8c14089 2003-11-23 devnull static char ebuf[4096];
36 b8c14089 2003-11-23 devnull
37 b8c14089 2003-11-23 devnull char *badports[] =
38 b8c14089 2003-11-23 devnull {
39 b8c14089 2003-11-23 devnull ".",
40 b8c14089 2003-11-23 devnull "..",
41 b8c14089 2003-11-23 devnull "send",
42 b8c14089 2003-11-23 devnull nil
43 b8c14089 2003-11-23 devnull };
44 b8c14089 2003-11-23 devnull
45 b8c14089 2003-11-23 devnull char *objects[] =
46 b8c14089 2003-11-23 devnull {
47 b8c14089 2003-11-23 devnull "arg",
48 b8c14089 2003-11-23 devnull "attr",
49 b8c14089 2003-11-23 devnull "data",
50 b8c14089 2003-11-23 devnull "dst",
51 b8c14089 2003-11-23 devnull "plumb",
52 b8c14089 2003-11-23 devnull "src",
53 b8c14089 2003-11-23 devnull "type",
54 b8c14089 2003-11-23 devnull "wdir",
55 b8c14089 2003-11-23 devnull nil
56 b8c14089 2003-11-23 devnull };
57 b8c14089 2003-11-23 devnull
58 b8c14089 2003-11-23 devnull char *verbs[] =
59 b8c14089 2003-11-23 devnull {
60 b8c14089 2003-11-23 devnull "add",
61 b8c14089 2003-11-23 devnull "client",
62 b8c14089 2003-11-23 devnull "delete",
63 b8c14089 2003-11-23 devnull "is",
64 b8c14089 2003-11-23 devnull "isdir",
65 b8c14089 2003-11-23 devnull "isfile",
66 b8c14089 2003-11-23 devnull "matches",
67 b8c14089 2003-11-23 devnull "set",
68 b8c14089 2003-11-23 devnull "start",
69 b8c14089 2003-11-23 devnull "to",
70 b8c14089 2003-11-23 devnull nil
71 b8c14089 2003-11-23 devnull };
72 b8c14089 2003-11-23 devnull
73 b8c14089 2003-11-23 devnull static void
74 b8c14089 2003-11-23 devnull printinputstackrev(Input *in)
75 b8c14089 2003-11-23 devnull {
76 b8c14089 2003-11-23 devnull if(in == nil)
77 b8c14089 2003-11-23 devnull return;
78 b8c14089 2003-11-23 devnull printinputstackrev(in->next);
79 b8c14089 2003-11-23 devnull fprint(2, "%s:%d: ", in->file, in->lineno);
80 b8c14089 2003-11-23 devnull }
81 b8c14089 2003-11-23 devnull
82 b8c14089 2003-11-23 devnull void
83 b8c14089 2003-11-23 devnull printinputstack(void)
84 b8c14089 2003-11-23 devnull {
85 b8c14089 2003-11-23 devnull printinputstackrev(input);
86 b8c14089 2003-11-23 devnull }
87 b8c14089 2003-11-23 devnull
88 b8c14089 2003-11-23 devnull static void
89 b8c14089 2003-11-23 devnull pushinput(char *name, int fd, uchar *str)
90 b8c14089 2003-11-23 devnull {
91 b8c14089 2003-11-23 devnull Input *in;
92 b8c14089 2003-11-23 devnull int depth;
93 b8c14089 2003-11-23 devnull
94 b8c14089 2003-11-23 devnull depth = 0;
95 b8c14089 2003-11-23 devnull for(in=input; in; in=in->next)
96 b8c14089 2003-11-23 devnull if(depth++ >= 10) /* prevent deep C stack in plumber and bad include structure */
97 b8c14089 2003-11-23 devnull parseerror("include stack too deep; max 10");
98 b8c14089 2003-11-23 devnull
99 b8c14089 2003-11-23 devnull in = emalloc(sizeof(Input));
100 b8c14089 2003-11-23 devnull in->file = estrdup(name);
101 b8c14089 2003-11-23 devnull in->next = input;
102 b8c14089 2003-11-23 devnull input = in;
103 b8c14089 2003-11-23 devnull if(str)
104 b8c14089 2003-11-23 devnull in->s = str;
105 b8c14089 2003-11-23 devnull else{
106 b8c14089 2003-11-23 devnull in->fd = emalloc(sizeof(Biobuf));
107 b8c14089 2003-11-23 devnull if(Binit(in->fd, fd, OREAD) < 0)
108 b8c14089 2003-11-23 devnull parseerror("can't initialize Bio for rules file: %r");
109 b8c14089 2003-11-23 devnull }
110 b8c14089 2003-11-23 devnull
111 b8c14089 2003-11-23 devnull }
112 b8c14089 2003-11-23 devnull
113 b8c14089 2003-11-23 devnull int
114 b8c14089 2003-11-23 devnull popinput(void)
115 b8c14089 2003-11-23 devnull {
116 b8c14089 2003-11-23 devnull Input *in;
117 b8c14089 2003-11-23 devnull
118 b8c14089 2003-11-23 devnull in = input;
119 b8c14089 2003-11-23 devnull if(in == nil)
120 b8c14089 2003-11-23 devnull return 0;
121 b8c14089 2003-11-23 devnull input = in->next;
122 b8c14089 2003-11-23 devnull if(in->fd){
123 b8c14089 2003-11-23 devnull Bterm(in->fd);
124 b8c14089 2003-11-23 devnull free(in->fd);
125 b8c14089 2003-11-23 devnull }
126 b8c14089 2003-11-23 devnull free(in);
127 b8c14089 2003-11-23 devnull return 1;
128 b8c14089 2003-11-23 devnull }
129 b8c14089 2003-11-23 devnull
130 c91bd328 2004-03-05 devnull static int
131 b8c14089 2003-11-23 devnull getc(void)
132 b8c14089 2003-11-23 devnull {
133 b8c14089 2003-11-23 devnull if(input == nil)
134 b8c14089 2003-11-23 devnull return Beof;
135 b8c14089 2003-11-23 devnull if(input->fd)
136 b8c14089 2003-11-23 devnull return Bgetc(input->fd);
137 b8c14089 2003-11-23 devnull if(input->s < input->end)
138 b8c14089 2003-11-23 devnull return *(input->s)++;
139 b8c14089 2003-11-23 devnull return -1;
140 b8c14089 2003-11-23 devnull }
141 b8c14089 2003-11-23 devnull
142 b8c14089 2003-11-23 devnull char*
143 b8c14089 2003-11-23 devnull getline(void)
144 b8c14089 2003-11-23 devnull {
145 b8c14089 2003-11-23 devnull static int n = 0;
146 32f69c36 2003-12-11 devnull static char *s /*, *incl*/;
147 b8c14089 2003-11-23 devnull int c, i;
148 b8c14089 2003-11-23 devnull
149 b8c14089 2003-11-23 devnull i = 0;
150 b8c14089 2003-11-23 devnull for(;;){
151 b8c14089 2003-11-23 devnull c = getc();
152 b8c14089 2003-11-23 devnull if(c < 0)
153 b8c14089 2003-11-23 devnull return nil;
154 b8c14089 2003-11-23 devnull if(i == n){
155 b8c14089 2003-11-23 devnull n += 100;
156 b8c14089 2003-11-23 devnull s = erealloc(s, n);
157 b8c14089 2003-11-23 devnull }
158 b8c14089 2003-11-23 devnull if(c<0 || c=='\0' || c=='\n')
159 b8c14089 2003-11-23 devnull break;
160 b8c14089 2003-11-23 devnull s[i++] = c;
161 b8c14089 2003-11-23 devnull }
162 b8c14089 2003-11-23 devnull s[i] = '\0';
163 b8c14089 2003-11-23 devnull return s;
164 b8c14089 2003-11-23 devnull }
165 b8c14089 2003-11-23 devnull
166 b8c14089 2003-11-23 devnull int
167 b8c14089 2003-11-23 devnull lookup(char *s, char *tab[])
168 b8c14089 2003-11-23 devnull {
169 b8c14089 2003-11-23 devnull int i;
170 b8c14089 2003-11-23 devnull
171 b8c14089 2003-11-23 devnull for(i=0; tab[i]!=nil; i++)
172 b8c14089 2003-11-23 devnull if(strcmp(s, tab[i])==0)
173 b8c14089 2003-11-23 devnull return i;
174 b8c14089 2003-11-23 devnull return -1;
175 b8c14089 2003-11-23 devnull }
176 b8c14089 2003-11-23 devnull
177 b8c14089 2003-11-23 devnull Var*
178 b8c14089 2003-11-23 devnull lookupvariable(char *s, int n)
179 b8c14089 2003-11-23 devnull {
180 b8c14089 2003-11-23 devnull int i;
181 b8c14089 2003-11-23 devnull
182 b8c14089 2003-11-23 devnull for(i=0; i<nvars; i++)
183 b8c14089 2003-11-23 devnull if(n==strlen(vars[i].name) && memcmp(s, vars[i].name, n)==0)
184 b8c14089 2003-11-23 devnull return vars+i;
185 b8c14089 2003-11-23 devnull return nil;
186 b8c14089 2003-11-23 devnull }
187 b8c14089 2003-11-23 devnull
188 b8c14089 2003-11-23 devnull char*
189 b8c14089 2003-11-23 devnull variable(char *s, int n)
190 b8c14089 2003-11-23 devnull {
191 b8c14089 2003-11-23 devnull Var *var;
192 b8c14089 2003-11-23 devnull
193 b8c14089 2003-11-23 devnull var = lookupvariable(s, n);
194 b8c14089 2003-11-23 devnull if(var)
195 b8c14089 2003-11-23 devnull return var->qvalue;
196 b8c14089 2003-11-23 devnull return nil;
197 b8c14089 2003-11-23 devnull }
198 b8c14089 2003-11-23 devnull
199 b8c14089 2003-11-23 devnull void
200 b8c14089 2003-11-23 devnull setvariable(char *s, int n, char *val, char *qval)
201 b8c14089 2003-11-23 devnull {
202 b8c14089 2003-11-23 devnull Var *var;
203 b8c14089 2003-11-23 devnull
204 b8c14089 2003-11-23 devnull var = lookupvariable(s, n);
205 b8c14089 2003-11-23 devnull if(var){
206 b8c14089 2003-11-23 devnull free(var->value);
207 b8c14089 2003-11-23 devnull free(var->qvalue);
208 b8c14089 2003-11-23 devnull }else{
209 b8c14089 2003-11-23 devnull vars = erealloc(vars, (nvars+1)*sizeof(Var));
210 b8c14089 2003-11-23 devnull var = vars+nvars++;
211 b8c14089 2003-11-23 devnull var->name = emalloc(n+1);
212 b8c14089 2003-11-23 devnull memmove(var->name, s, n);
213 b8c14089 2003-11-23 devnull }
214 b8c14089 2003-11-23 devnull var->value = estrdup(val);
215 b8c14089 2003-11-23 devnull var->qvalue = estrdup(qval);
216 b8c14089 2003-11-23 devnull }
217 b8c14089 2003-11-23 devnull
218 b8c14089 2003-11-23 devnull static char*
219 b8c14089 2003-11-23 devnull nonnil(char *s)
220 b8c14089 2003-11-23 devnull {
221 b8c14089 2003-11-23 devnull if(s == nil)
222 b8c14089 2003-11-23 devnull return "";
223 b8c14089 2003-11-23 devnull return s;
224 b8c14089 2003-11-23 devnull }
225 b8c14089 2003-11-23 devnull
226 b8c14089 2003-11-23 devnull static char*
227 b8c14089 2003-11-23 devnull filename(Exec *e, char *name)
228 b8c14089 2003-11-23 devnull {
229 b8c14089 2003-11-23 devnull static char *buf; /* rock to hold value so we don't leak the strings */
230 b8c14089 2003-11-23 devnull
231 b8c14089 2003-11-23 devnull free(buf);
232 b8c14089 2003-11-23 devnull /* if name is defined, used it */
233 b8c14089 2003-11-23 devnull if(name!=nil && name[0]!='\0'){
234 b8c14089 2003-11-23 devnull buf = estrdup(name);
235 b8c14089 2003-11-23 devnull return cleanname(buf);
236 b8c14089 2003-11-23 devnull }
237 b8c14089 2003-11-23 devnull /* if data is an absolute file name, or wdir is empty, use it */
238 b8c14089 2003-11-23 devnull if(e->msg->data[0]=='/' || e->msg->wdir==nil || e->msg->wdir[0]=='\0'){
239 b8c14089 2003-11-23 devnull buf = estrdup(e->msg->data);
240 b8c14089 2003-11-23 devnull return cleanname(buf);
241 b8c14089 2003-11-23 devnull }
242 b8c14089 2003-11-23 devnull buf = emalloc(strlen(e->msg->wdir)+1+strlen(e->msg->data)+1);
243 b8c14089 2003-11-23 devnull sprint(buf, "%s/%s", e->msg->wdir, e->msg->data);
244 b8c14089 2003-11-23 devnull return cleanname(buf);
245 b8c14089 2003-11-23 devnull }
246 b8c14089 2003-11-23 devnull
247 b8c14089 2003-11-23 devnull char*
248 b8c14089 2003-11-23 devnull dollar(Exec *e, char *s, int *namelen)
249 b8c14089 2003-11-23 devnull {
250 b8c14089 2003-11-23 devnull int n;
251 b8c14089 2003-11-23 devnull static char *abuf;
252 b8c14089 2003-11-23 devnull char *t;
253 b8c14089 2003-11-23 devnull
254 b8c14089 2003-11-23 devnull *namelen = 1;
255 b8c14089 2003-11-23 devnull if(e!=nil && '0'<=s[0] && s[0]<='9')
256 b8c14089 2003-11-23 devnull return nonnil(e->match[s[0]-'0']);
257 b8c14089 2003-11-23 devnull
258 3bd56b04 2005-09-09 devnull for(t=s; isalnum((uchar)*t); t++)
259 b8c14089 2003-11-23 devnull ;
260 b8c14089 2003-11-23 devnull n = t-s;
261 b8c14089 2003-11-23 devnull *namelen = n;
262 b8c14089 2003-11-23 devnull
263 b8c14089 2003-11-23 devnull if(e != nil){
264 b8c14089 2003-11-23 devnull if(n == 3){
265 b8c14089 2003-11-23 devnull if(memcmp(s, "src", 3) == 0)
266 b8c14089 2003-11-23 devnull return nonnil(e->msg->src);
267 b8c14089 2003-11-23 devnull if(memcmp(s, "dst", 3) == 0)
268 b8c14089 2003-11-23 devnull return nonnil(e->msg->dst);
269 b8c14089 2003-11-23 devnull if(memcmp(s, "dir", 3) == 0)
270 b8c14089 2003-11-23 devnull return filename(e, e->dir);
271 b8c14089 2003-11-23 devnull }
272 b8c14089 2003-11-23 devnull if(n == 4){
273 b8c14089 2003-11-23 devnull if(memcmp(s, "attr", 4) == 0){
274 b8c14089 2003-11-23 devnull free(abuf);
275 b8c14089 2003-11-23 devnull abuf = plumbpackattr(e->msg->attr);
276 b8c14089 2003-11-23 devnull return nonnil(abuf);
277 b8c14089 2003-11-23 devnull }
278 b8c14089 2003-11-23 devnull if(memcmp(s, "data", 4) == 0)
279 b8c14089 2003-11-23 devnull return nonnil(e->msg->data);
280 b8c14089 2003-11-23 devnull if(memcmp(s, "file", 4) == 0)
281 b8c14089 2003-11-23 devnull return filename(e, e->file);
282 b8c14089 2003-11-23 devnull if(memcmp(s, "type", 4) == 0)
283 b8c14089 2003-11-23 devnull return nonnil(e->msg->type);
284 b8c14089 2003-11-23 devnull if(memcmp(s, "wdir", 3) == 0)
285 b8c14089 2003-11-23 devnull return nonnil(e->msg->wdir);
286 b8c14089 2003-11-23 devnull }
287 b8c14089 2003-11-23 devnull }
288 b8c14089 2003-11-23 devnull
289 b8c14089 2003-11-23 devnull return variable(s, n);
290 b8c14089 2003-11-23 devnull }
291 b8c14089 2003-11-23 devnull
292 b8c14089 2003-11-23 devnull /* expand one blank-terminated string, processing quotes and $ signs */
293 b8c14089 2003-11-23 devnull char*
294 b8c14089 2003-11-23 devnull expand(Exec *e, char *s, char **ends)
295 b8c14089 2003-11-23 devnull {
296 b8c14089 2003-11-23 devnull char *p, *ep, *val;
297 b8c14089 2003-11-23 devnull int namelen, quoting;
298 b8c14089 2003-11-23 devnull
299 b8c14089 2003-11-23 devnull p = ebuf;
300 b8c14089 2003-11-23 devnull ep = ebuf+sizeof ebuf-1;
301 b8c14089 2003-11-23 devnull quoting = 0;
302 b8c14089 2003-11-23 devnull while(p<ep && *s!='\0' && (quoting || (*s!=' ' && *s!='\t'))){
303 b8c14089 2003-11-23 devnull if(*s == '\''){
304 b8c14089 2003-11-23 devnull s++;
305 b8c14089 2003-11-23 devnull if(!quoting)
306 b8c14089 2003-11-23 devnull quoting = 1;
307 b8c14089 2003-11-23 devnull else if(*s == '\''){
308 b8c14089 2003-11-23 devnull *p++ = '\'';
309 b8c14089 2003-11-23 devnull s++;
310 b8c14089 2003-11-23 devnull }else
311 b8c14089 2003-11-23 devnull quoting = 0;
312 b8c14089 2003-11-23 devnull continue;
313 b8c14089 2003-11-23 devnull }
314 b8c14089 2003-11-23 devnull if(quoting || *s!='$'){
315 b8c14089 2003-11-23 devnull *p++ = *s++;
316 b8c14089 2003-11-23 devnull continue;
317 b8c14089 2003-11-23 devnull }
318 b8c14089 2003-11-23 devnull s++;
319 b8c14089 2003-11-23 devnull val = dollar(e, s, &namelen);
320 b8c14089 2003-11-23 devnull if(val == nil){
321 b8c14089 2003-11-23 devnull *p++ = '$';
322 b8c14089 2003-11-23 devnull continue;
323 b8c14089 2003-11-23 devnull }
324 b8c14089 2003-11-23 devnull if(ep-p < strlen(val))
325 b8c14089 2003-11-23 devnull return "string-too-long";
326 b8c14089 2003-11-23 devnull strcpy(p, val);
327 b8c14089 2003-11-23 devnull p += strlen(val);
328 b8c14089 2003-11-23 devnull s += namelen;
329 b8c14089 2003-11-23 devnull }
330 b8c14089 2003-11-23 devnull if(ends)
331 b8c14089 2003-11-23 devnull *ends = s;
332 b8c14089 2003-11-23 devnull *p = '\0';
333 b8c14089 2003-11-23 devnull return ebuf;
334 b8c14089 2003-11-23 devnull }
335 b8c14089 2003-11-23 devnull
336 b8c14089 2003-11-23 devnull void
337 b8c14089 2003-11-23 devnull regerror(char *msg)
338 b8c14089 2003-11-23 devnull {
339 b8c14089 2003-11-23 devnull if(parsing){
340 b8c14089 2003-11-23 devnull parsing = 0;
341 b8c14089 2003-11-23 devnull parseerror("%s", msg);
342 b8c14089 2003-11-23 devnull }
343 b8c14089 2003-11-23 devnull error("%s", msg);
344 b8c14089 2003-11-23 devnull }
345 b8c14089 2003-11-23 devnull
346 b8c14089 2003-11-23 devnull void
347 b8c14089 2003-11-23 devnull parserule(Rule *r)
348 b8c14089 2003-11-23 devnull {
349 b8c14089 2003-11-23 devnull r->qarg = estrdup(expand(nil, r->arg, nil));
350 b8c14089 2003-11-23 devnull switch(r->obj){
351 b8c14089 2003-11-23 devnull case OArg:
352 b8c14089 2003-11-23 devnull case OAttr:
353 b8c14089 2003-11-23 devnull case OData:
354 b8c14089 2003-11-23 devnull case ODst:
355 b8c14089 2003-11-23 devnull case OType:
356 b8c14089 2003-11-23 devnull case OWdir:
357 b8c14089 2003-11-23 devnull case OSrc:
358 b8c14089 2003-11-23 devnull if(r->verb==VClient || r->verb==VStart || r->verb==VTo)
359 b8c14089 2003-11-23 devnull parseerror("%s not valid verb for object %s", verbs[r->verb], objects[r->obj]);
360 b8c14089 2003-11-23 devnull if(r->obj!=OAttr && (r->verb==VAdd || r->verb==VDelete))
361 b8c14089 2003-11-23 devnull parseerror("%s not valid verb for object %s", verbs[r->verb], objects[r->obj]);
362 b8c14089 2003-11-23 devnull if(r->verb == VMatches){
363 b8c14089 2003-11-23 devnull r->regex = regcomp(r->qarg);
364 b8c14089 2003-11-23 devnull return;
365 b8c14089 2003-11-23 devnull }
366 b8c14089 2003-11-23 devnull break;
367 b8c14089 2003-11-23 devnull case OPlumb:
368 b8c14089 2003-11-23 devnull if(r->verb!=VClient && r->verb!=VStart && r->verb!=VTo)
369 b8c14089 2003-11-23 devnull parseerror("%s not valid verb for object %s", verbs[r->verb], objects[r->obj]);
370 b8c14089 2003-11-23 devnull break;
371 b8c14089 2003-11-23 devnull }
372 b8c14089 2003-11-23 devnull }
373 b8c14089 2003-11-23 devnull
374 b8c14089 2003-11-23 devnull int
375 b8c14089 2003-11-23 devnull assignment(char *p)
376 b8c14089 2003-11-23 devnull {
377 b8c14089 2003-11-23 devnull char *var, *qval;
378 b8c14089 2003-11-23 devnull int n;
379 b8c14089 2003-11-23 devnull
380 3bd56b04 2005-09-09 devnull if(!isalpha((uchar)p[0]))
381 b8c14089 2003-11-23 devnull return 0;
382 3bd56b04 2005-09-09 devnull for(var=p; isalnum((uchar)*p); p++)
383 b8c14089 2003-11-23 devnull ;
384 b8c14089 2003-11-23 devnull n = p-var;
385 b8c14089 2003-11-23 devnull while(*p==' ' || *p=='\t')
386 b8c14089 2003-11-23 devnull p++;
387 b8c14089 2003-11-23 devnull if(*p++ != '=')
388 b8c14089 2003-11-23 devnull return 0;
389 b8c14089 2003-11-23 devnull while(*p==' ' || *p=='\t')
390 b8c14089 2003-11-23 devnull p++;
391 b8c14089 2003-11-23 devnull qval = expand(nil, p, nil);
392 b8c14089 2003-11-23 devnull setvariable(var, n, p, qval);
393 b8c14089 2003-11-23 devnull return 1;
394 b8c14089 2003-11-23 devnull }
395 b8c14089 2003-11-23 devnull
396 b8c14089 2003-11-23 devnull int
397 b8c14089 2003-11-23 devnull include(char *s)
398 b8c14089 2003-11-23 devnull {
399 b8c14089 2003-11-23 devnull char *t, *args[3], buf[128];
400 b8c14089 2003-11-23 devnull int n, fd;
401 b8c14089 2003-11-23 devnull
402 b8c14089 2003-11-23 devnull if(strncmp(s, "include", 7) != 0)
403 b8c14089 2003-11-23 devnull return 0;
404 b8c14089 2003-11-23 devnull /* either an include or an error */
405 b8c14089 2003-11-23 devnull n = tokenize(s, args, nelem(args));
406 b8c14089 2003-11-23 devnull if(n < 2)
407 b8c14089 2003-11-23 devnull goto Err;
408 b8c14089 2003-11-23 devnull if(strcmp(args[0], "include") != 0)
409 b8c14089 2003-11-23 devnull goto Err;
410 b8c14089 2003-11-23 devnull if(args[1][0] == '#')
411 b8c14089 2003-11-23 devnull goto Err;
412 b8c14089 2003-11-23 devnull if(n>2 && args[2][0] != '#')
413 b8c14089 2003-11-23 devnull goto Err;
414 b8c14089 2003-11-23 devnull t = args[1];
415 b8c14089 2003-11-23 devnull fd = open(t, OREAD);
416 b8c14089 2003-11-23 devnull if(fd<0 && t[0]!='/' && strncmp(t, "./", 2)!=0 && strncmp(t, "../", 3)!=0){
417 32f69c36 2003-12-11 devnull snprint(buf, sizeof buf, "#9/plumb/%s", t);
418 8ad51794 2004-03-25 devnull t = unsharp(buf);
419 b8c14089 2003-11-23 devnull fd = open(t, OREAD);
420 b8c14089 2003-11-23 devnull }
421 b8c14089 2003-11-23 devnull if(fd < 0)
422 b8c14089 2003-11-23 devnull parseerror("can't open %s for inclusion", t);
423 b8c14089 2003-11-23 devnull pushinput(t, fd, nil);
424 b8c14089 2003-11-23 devnull return 1;
425 b8c14089 2003-11-23 devnull
426 b8c14089 2003-11-23 devnull Err:
427 b8c14089 2003-11-23 devnull parseerror("malformed include statement");
428 b8c14089 2003-11-23 devnull return 0;
429 b8c14089 2003-11-23 devnull }
430 b8c14089 2003-11-23 devnull
431 b8c14089 2003-11-23 devnull Rule*
432 b8c14089 2003-11-23 devnull readrule(int *eof)
433 b8c14089 2003-11-23 devnull {
434 b8c14089 2003-11-23 devnull Rule *rp;
435 b8c14089 2003-11-23 devnull char *line, *p;
436 b8c14089 2003-11-23 devnull char *word;
437 b8c14089 2003-11-23 devnull
438 b8c14089 2003-11-23 devnull Top:
439 b8c14089 2003-11-23 devnull line = getline();
440 b8c14089 2003-11-23 devnull if(line == nil){
441 b8c14089 2003-11-23 devnull /*
442 b8c14089 2003-11-23 devnull * if input is from string, and bytes remain (input->end is within string),
443 b8c14089 2003-11-23 devnull * morerules() will pop input and save remaining data. otherwise pop
444 b8c14089 2003-11-23 devnull * the stack here, and if there's more input, keep reading.
445 b8c14089 2003-11-23 devnull */
446 b8c14089 2003-11-23 devnull if((input!=nil && input->end==nil) && popinput())
447 b8c14089 2003-11-23 devnull goto Top;
448 b8c14089 2003-11-23 devnull *eof = 1;
449 b8c14089 2003-11-23 devnull return nil;
450 b8c14089 2003-11-23 devnull }
451 b8c14089 2003-11-23 devnull input->lineno++;
452 b8c14089 2003-11-23 devnull
453 b8c14089 2003-11-23 devnull for(p=line; *p==' ' || *p=='\t'; p++)
454 b8c14089 2003-11-23 devnull ;
455 b8c14089 2003-11-23 devnull if(*p=='\0' || *p=='#') /* empty or comment line */
456 b8c14089 2003-11-23 devnull return nil;
457 b8c14089 2003-11-23 devnull
458 b8c14089 2003-11-23 devnull if(include(p))
459 b8c14089 2003-11-23 devnull goto Top;
460 b8c14089 2003-11-23 devnull
461 b8c14089 2003-11-23 devnull if(assignment(p))
462 b8c14089 2003-11-23 devnull return nil;
463 b8c14089 2003-11-23 devnull
464 b8c14089 2003-11-23 devnull rp = emalloc(sizeof(Rule));
465 b8c14089 2003-11-23 devnull
466 b8c14089 2003-11-23 devnull /* object */
467 b8c14089 2003-11-23 devnull for(word=p; *p!=' ' && *p!='\t'; p++)
468 b8c14089 2003-11-23 devnull if(*p == '\0')
469 b8c14089 2003-11-23 devnull parseerror("malformed rule");
470 b8c14089 2003-11-23 devnull *p++ = '\0';
471 b8c14089 2003-11-23 devnull rp->obj = lookup(word, objects);
472 b8c14089 2003-11-23 devnull if(rp->obj < 0){
473 b8c14089 2003-11-23 devnull if(strcmp(word, "kind") == 0) /* backwards compatibility */
474 b8c14089 2003-11-23 devnull rp->obj = OType;
475 b8c14089 2003-11-23 devnull else
476 b8c14089 2003-11-23 devnull parseerror("unknown object %s", word);
477 b8c14089 2003-11-23 devnull }
478 b8c14089 2003-11-23 devnull
479 b8c14089 2003-11-23 devnull /* verb */
480 b8c14089 2003-11-23 devnull while(*p==' ' || *p=='\t')
481 b8c14089 2003-11-23 devnull p++;
482 b8c14089 2003-11-23 devnull for(word=p; *p!=' ' && *p!='\t'; p++)
483 b8c14089 2003-11-23 devnull if(*p == '\0')
484 b8c14089 2003-11-23 devnull parseerror("malformed rule");
485 b8c14089 2003-11-23 devnull *p++ = '\0';
486 b8c14089 2003-11-23 devnull rp->verb = lookup(word, verbs);
487 b8c14089 2003-11-23 devnull if(rp->verb < 0)
488 b8c14089 2003-11-23 devnull parseerror("unknown verb %s", word);
489 b8c14089 2003-11-23 devnull
490 b8c14089 2003-11-23 devnull /* argument */
491 b8c14089 2003-11-23 devnull while(*p==' ' || *p=='\t')
492 b8c14089 2003-11-23 devnull p++;
493 b8c14089 2003-11-23 devnull if(*p == '\0')
494 b8c14089 2003-11-23 devnull parseerror("malformed rule");
495 b8c14089 2003-11-23 devnull rp->arg = estrdup(p);
496 b8c14089 2003-11-23 devnull
497 b8c14089 2003-11-23 devnull parserule(rp);
498 b8c14089 2003-11-23 devnull
499 b8c14089 2003-11-23 devnull return rp;
500 b8c14089 2003-11-23 devnull }
501 b8c14089 2003-11-23 devnull
502 b8c14089 2003-11-23 devnull void
503 b8c14089 2003-11-23 devnull freerule(Rule *r)
504 b8c14089 2003-11-23 devnull {
505 b8c14089 2003-11-23 devnull free(r->arg);
506 b8c14089 2003-11-23 devnull free(r->qarg);
507 b8c14089 2003-11-23 devnull free(r->regex);
508 b8c14089 2003-11-23 devnull }
509 b8c14089 2003-11-23 devnull
510 b8c14089 2003-11-23 devnull void
511 b8c14089 2003-11-23 devnull freerules(Rule **r)
512 b8c14089 2003-11-23 devnull {
513 b8c14089 2003-11-23 devnull while(*r)
514 b8c14089 2003-11-23 devnull freerule(*r++);
515 b8c14089 2003-11-23 devnull }
516 b8c14089 2003-11-23 devnull
517 b8c14089 2003-11-23 devnull void
518 b8c14089 2003-11-23 devnull freeruleset(Ruleset *rs)
519 b8c14089 2003-11-23 devnull {
520 b8c14089 2003-11-23 devnull freerules(rs->pat);
521 b8c14089 2003-11-23 devnull free(rs->pat);
522 b8c14089 2003-11-23 devnull freerules(rs->act);
523 b8c14089 2003-11-23 devnull free(rs->act);
524 b8c14089 2003-11-23 devnull free(rs->port);
525 b8c14089 2003-11-23 devnull free(rs);
526 b8c14089 2003-11-23 devnull }
527 b8c14089 2003-11-23 devnull
528 b8c14089 2003-11-23 devnull Ruleset*
529 b8c14089 2003-11-23 devnull readruleset(void)
530 b8c14089 2003-11-23 devnull {
531 b8c14089 2003-11-23 devnull Ruleset *rs;
532 b8c14089 2003-11-23 devnull Rule *r;
533 b8c14089 2003-11-23 devnull int eof, inrule, i, ncmd;
534 4de03b54 2005-01-11 devnull char *plan9root;
535 b8c14089 2003-11-23 devnull
536 4de03b54 2005-01-11 devnull plan9root = get9root();
537 4de03b54 2005-01-11 devnull if(plan9root)
538 4de03b54 2005-01-11 devnull setvariable("plan9", 5, plan9root, plan9root);
539 4de03b54 2005-01-11 devnull
540 b8c14089 2003-11-23 devnull Again:
541 b8c14089 2003-11-23 devnull eof = 0;
542 b8c14089 2003-11-23 devnull rs = emalloc(sizeof(Ruleset));
543 b8c14089 2003-11-23 devnull rs->pat = emalloc(sizeof(Rule*));
544 b8c14089 2003-11-23 devnull rs->act = emalloc(sizeof(Rule*));
545 b8c14089 2003-11-23 devnull inrule = 0;
546 b8c14089 2003-11-23 devnull ncmd = 0;
547 b8c14089 2003-11-23 devnull for(;;){
548 b8c14089 2003-11-23 devnull r = readrule(&eof);
549 b8c14089 2003-11-23 devnull if(eof)
550 b8c14089 2003-11-23 devnull break;
551 b8c14089 2003-11-23 devnull if(r==nil){
552 b8c14089 2003-11-23 devnull if(inrule)
553 b8c14089 2003-11-23 devnull break;
554 b8c14089 2003-11-23 devnull continue;
555 b8c14089 2003-11-23 devnull }
556 b8c14089 2003-11-23 devnull inrule = 1;
557 b8c14089 2003-11-23 devnull switch(r->obj){
558 b8c14089 2003-11-23 devnull case OArg:
559 b8c14089 2003-11-23 devnull case OAttr:
560 b8c14089 2003-11-23 devnull case OData:
561 b8c14089 2003-11-23 devnull case ODst:
562 b8c14089 2003-11-23 devnull case OType:
563 b8c14089 2003-11-23 devnull case OWdir:
564 b8c14089 2003-11-23 devnull case OSrc:
565 b8c14089 2003-11-23 devnull rs->npat++;
566 b8c14089 2003-11-23 devnull rs->pat = erealloc(rs->pat, (rs->npat+1)*sizeof(Rule*));
567 b8c14089 2003-11-23 devnull rs->pat[rs->npat-1] = r;
568 b8c14089 2003-11-23 devnull rs->pat[rs->npat] = nil;
569 b8c14089 2003-11-23 devnull break;
570 b8c14089 2003-11-23 devnull case OPlumb:
571 b8c14089 2003-11-23 devnull rs->nact++;
572 b8c14089 2003-11-23 devnull rs->act = erealloc(rs->act, (rs->nact+1)*sizeof(Rule*));
573 b8c14089 2003-11-23 devnull rs->act[rs->nact-1] = r;
574 b8c14089 2003-11-23 devnull rs->act[rs->nact] = nil;
575 b8c14089 2003-11-23 devnull if(r->verb == VTo){
576 b8c14089 2003-11-23 devnull if(rs->npat>0 && rs->port != nil) /* npat==0 implies port declaration */
577 b8c14089 2003-11-23 devnull parseerror("too many ports");
578 b8c14089 2003-11-23 devnull if(lookup(r->qarg, badports) >= 0)
579 b8c14089 2003-11-23 devnull parseerror("illegal port name %s", r->qarg);
580 b8c14089 2003-11-23 devnull rs->port = estrdup(r->qarg);
581 b8c14089 2003-11-23 devnull }else
582 b8c14089 2003-11-23 devnull ncmd++; /* start or client rule */
583 b8c14089 2003-11-23 devnull break;
584 b8c14089 2003-11-23 devnull }
585 b8c14089 2003-11-23 devnull }
586 b8c14089 2003-11-23 devnull if(ncmd > 1){
587 b8c14089 2003-11-23 devnull freeruleset(rs);
588 b8c14089 2003-11-23 devnull parseerror("ruleset has more than one client or start action");
589 b8c14089 2003-11-23 devnull }
590 b8c14089 2003-11-23 devnull if(rs->npat>0 && rs->nact>0)
591 b8c14089 2003-11-23 devnull return rs;
592 b8c14089 2003-11-23 devnull if(rs->npat==0 && rs->nact==0){
593 b8c14089 2003-11-23 devnull freeruleset(rs);
594 b8c14089 2003-11-23 devnull return nil;
595 b8c14089 2003-11-23 devnull }
596 b8c14089 2003-11-23 devnull if(rs->nact==0 || rs->port==nil){
597 b8c14089 2003-11-23 devnull freeruleset(rs);
598 b8c14089 2003-11-23 devnull parseerror("ruleset must have patterns and actions");
599 b8c14089 2003-11-23 devnull return nil;
600 b8c14089 2003-11-23 devnull }
601 b8c14089 2003-11-23 devnull
602 b8c14089 2003-11-23 devnull /* declare ports */
603 b8c14089 2003-11-23 devnull for(i=0; i<rs->nact; i++)
604 b8c14089 2003-11-23 devnull if(rs->act[i]->verb != VTo){
605 b8c14089 2003-11-23 devnull freeruleset(rs);
606 b8c14089 2003-11-23 devnull parseerror("ruleset must have actions");
607 b8c14089 2003-11-23 devnull return nil;
608 b8c14089 2003-11-23 devnull }
609 b8c14089 2003-11-23 devnull for(i=0; i<rs->nact; i++)
610 b8c14089 2003-11-23 devnull addport(rs->act[i]->qarg);
611 b8c14089 2003-11-23 devnull freeruleset(rs);
612 b8c14089 2003-11-23 devnull goto Again;
613 b8c14089 2003-11-23 devnull }
614 b8c14089 2003-11-23 devnull
615 b8c14089 2003-11-23 devnull Ruleset**
616 b8c14089 2003-11-23 devnull readrules(char *name, int fd)
617 b8c14089 2003-11-23 devnull {
618 b8c14089 2003-11-23 devnull Ruleset *rs, **rules;
619 b8c14089 2003-11-23 devnull int n;
620 b8c14089 2003-11-23 devnull
621 b8c14089 2003-11-23 devnull parsing = 1;
622 b8c14089 2003-11-23 devnull pushinput(name, fd, nil);
623 b8c14089 2003-11-23 devnull rules = emalloc(sizeof(Ruleset*));
624 b8c14089 2003-11-23 devnull for(n=0; (rs=readruleset())!=nil; n++){
625 b8c14089 2003-11-23 devnull rules = erealloc(rules, (n+2)*sizeof(Ruleset*));
626 b8c14089 2003-11-23 devnull rules[n] = rs;
627 b8c14089 2003-11-23 devnull rules[n+1] = nil;
628 b8c14089 2003-11-23 devnull }
629 b8c14089 2003-11-23 devnull popinput();
630 b8c14089 2003-11-23 devnull parsing = 0;
631 b8c14089 2003-11-23 devnull return rules;
632 b8c14089 2003-11-23 devnull }
633 b8c14089 2003-11-23 devnull
634 b8c14089 2003-11-23 devnull char*
635 b8c14089 2003-11-23 devnull concat(char *s, char *t)
636 b8c14089 2003-11-23 devnull {
637 b8c14089 2003-11-23 devnull if(t == nil)
638 b8c14089 2003-11-23 devnull return s;
639 b8c14089 2003-11-23 devnull if(s == nil)
640 b8c14089 2003-11-23 devnull s = estrdup(t);
641 b8c14089 2003-11-23 devnull else{
642 b8c14089 2003-11-23 devnull s = erealloc(s, strlen(s)+strlen(t)+1);
643 b8c14089 2003-11-23 devnull strcat(s, t);
644 b8c14089 2003-11-23 devnull }
645 b8c14089 2003-11-23 devnull return s;
646 b8c14089 2003-11-23 devnull }
647 b8c14089 2003-11-23 devnull
648 b8c14089 2003-11-23 devnull char*
649 b8c14089 2003-11-23 devnull printpat(Rule *r)
650 b8c14089 2003-11-23 devnull {
651 b8c14089 2003-11-23 devnull char *s;
652 b8c14089 2003-11-23 devnull
653 b8c14089 2003-11-23 devnull s = emalloc(strlen(objects[r->obj])+1+strlen(verbs[r->verb])+1+strlen(r->arg)+1+1);
654 b8c14089 2003-11-23 devnull sprint(s, "%s\t%s\t%s\n", objects[r->obj], verbs[r->verb], r->arg);
655 b8c14089 2003-11-23 devnull return s;
656 b8c14089 2003-11-23 devnull }
657 b8c14089 2003-11-23 devnull
658 b8c14089 2003-11-23 devnull char*
659 b8c14089 2003-11-23 devnull printvar(Var *v)
660 b8c14089 2003-11-23 devnull {
661 b8c14089 2003-11-23 devnull char *s;
662 b8c14089 2003-11-23 devnull
663 b8c14089 2003-11-23 devnull s = emalloc(strlen(v->name)+1+strlen(v->value)+2+1);
664 b8c14089 2003-11-23 devnull sprint(s, "%s=%s\n\n", v->name, v->value);
665 b8c14089 2003-11-23 devnull return s;
666 b8c14089 2003-11-23 devnull }
667 b8c14089 2003-11-23 devnull
668 b8c14089 2003-11-23 devnull char*
669 b8c14089 2003-11-23 devnull printrule(Ruleset *r)
670 b8c14089 2003-11-23 devnull {
671 b8c14089 2003-11-23 devnull int i;
672 b8c14089 2003-11-23 devnull char *s;
673 b8c14089 2003-11-23 devnull
674 b8c14089 2003-11-23 devnull s = nil;
675 b8c14089 2003-11-23 devnull for(i=0; i<r->npat; i++)
676 b8c14089 2003-11-23 devnull s = concat(s, printpat(r->pat[i]));
677 b8c14089 2003-11-23 devnull for(i=0; i<r->nact; i++)
678 b8c14089 2003-11-23 devnull s = concat(s, printpat(r->act[i]));
679 b8c14089 2003-11-23 devnull s = concat(s, "\n");
680 b8c14089 2003-11-23 devnull return s;
681 b8c14089 2003-11-23 devnull }
682 b8c14089 2003-11-23 devnull
683 b8c14089 2003-11-23 devnull char*
684 b8c14089 2003-11-23 devnull printport(char *port)
685 b8c14089 2003-11-23 devnull {
686 b8c14089 2003-11-23 devnull char *s;
687 b8c14089 2003-11-23 devnull
688 b8c14089 2003-11-23 devnull s = nil;
689 b8c14089 2003-11-23 devnull s = concat(s, "plumb to ");
690 b8c14089 2003-11-23 devnull s = concat(s, port);
691 b8c14089 2003-11-23 devnull s = concat(s, "\n");
692 b8c14089 2003-11-23 devnull return s;
693 b8c14089 2003-11-23 devnull }
694 b8c14089 2003-11-23 devnull
695 b8c14089 2003-11-23 devnull char*
696 b8c14089 2003-11-23 devnull printrules(void)
697 b8c14089 2003-11-23 devnull {
698 b8c14089 2003-11-23 devnull int i;
699 b8c14089 2003-11-23 devnull char *s;
700 b8c14089 2003-11-23 devnull
701 b8c14089 2003-11-23 devnull s = nil;
702 b8c14089 2003-11-23 devnull for(i=0; i<nvars; i++)
703 b8c14089 2003-11-23 devnull s = concat(s, printvar(&vars[i]));
704 b8c14089 2003-11-23 devnull for(i=0; i<nports; i++)
705 b8c14089 2003-11-23 devnull s = concat(s, printport(ports[i]));
706 b8c14089 2003-11-23 devnull s = concat(s, "\n");
707 b8c14089 2003-11-23 devnull for(i=0; rules[i]; i++)
708 b8c14089 2003-11-23 devnull s = concat(s, printrule(rules[i]));
709 b8c14089 2003-11-23 devnull return s;
710 b8c14089 2003-11-23 devnull }
711 b8c14089 2003-11-23 devnull
712 b8c14089 2003-11-23 devnull char*
713 b8c14089 2003-11-23 devnull stringof(char *s, int n)
714 b8c14089 2003-11-23 devnull {
715 b8c14089 2003-11-23 devnull char *t;
716 b8c14089 2003-11-23 devnull
717 b8c14089 2003-11-23 devnull t = emalloc(n+1);
718 b8c14089 2003-11-23 devnull memmove(t, s, n);
719 b8c14089 2003-11-23 devnull return t;
720 b8c14089 2003-11-23 devnull }
721 b8c14089 2003-11-23 devnull
722 b8c14089 2003-11-23 devnull uchar*
723 b8c14089 2003-11-23 devnull morerules(uchar *text, int done)
724 b8c14089 2003-11-23 devnull {
725 b8c14089 2003-11-23 devnull int n;
726 b8c14089 2003-11-23 devnull Ruleset *rs;
727 b8c14089 2003-11-23 devnull uchar *otext, *s, *endofrule;
728 b8c14089 2003-11-23 devnull
729 b8c14089 2003-11-23 devnull pushinput("<rules input>", -1, text);
730 b8c14089 2003-11-23 devnull if(done)
731 b8c14089 2003-11-23 devnull input->end = text+strlen((char*)text);
732 b8c14089 2003-11-23 devnull else{
733 b8c14089 2003-11-23 devnull /*
734 b8c14089 2003-11-23 devnull * Help user by sending any full rules to parser so any parse errors will
735 b8c14089 2003-11-23 devnull * occur on write rather than close. A heuristic will do: blank line ends rule.
736 b8c14089 2003-11-23 devnull */
737 b8c14089 2003-11-23 devnull endofrule = nil;
738 b8c14089 2003-11-23 devnull for(s=text; *s!='\0'; s++)
739 b9424f64 2019-09-19 crossd if(*s=='\n' && *(s+1)=='\n')
740 b9424f64 2019-09-19 crossd endofrule = s+2;
741 b8c14089 2003-11-23 devnull if(endofrule == nil)
742 b8c14089 2003-11-23 devnull return text;
743 b8c14089 2003-11-23 devnull input->end = endofrule;
744 b8c14089 2003-11-23 devnull }
745 b8c14089 2003-11-23 devnull for(n=0; rules[n]; n++)
746 b8c14089 2003-11-23 devnull ;
747 b8c14089 2003-11-23 devnull while((rs=readruleset()) != nil){
748 b8c14089 2003-11-23 devnull rules = erealloc(rules, (n+2)*sizeof(Ruleset*));
749 b8c14089 2003-11-23 devnull rules[n++] = rs;
750 b8c14089 2003-11-23 devnull rules[n] = nil;
751 b8c14089 2003-11-23 devnull }
752 b8c14089 2003-11-23 devnull otext =text;
753 b8c14089 2003-11-23 devnull if(input == nil)
754 b8c14089 2003-11-23 devnull text = (uchar*)estrdup("");
755 b8c14089 2003-11-23 devnull else
756 b8c14089 2003-11-23 devnull text = (uchar*)estrdup((char*)input->end);
757 b8c14089 2003-11-23 devnull popinput();
758 b8c14089 2003-11-23 devnull free(otext);
759 b8c14089 2003-11-23 devnull return text;
760 b8c14089 2003-11-23 devnull }
761 b8c14089 2003-11-23 devnull
762 b8c14089 2003-11-23 devnull char*
763 b8c14089 2003-11-23 devnull writerules(char *s, int n)
764 b8c14089 2003-11-23 devnull {
765 b8c14089 2003-11-23 devnull static uchar *text;
766 b8c14089 2003-11-23 devnull char *tmp;
767 b8c14089 2003-11-23 devnull
768 b8c14089 2003-11-23 devnull free(lasterror);
769 b8c14089 2003-11-23 devnull lasterror = nil;
770 b8c14089 2003-11-23 devnull parsing = 1;
771 b8c14089 2003-11-23 devnull if(setjmp(parsejmp) == 0){
772 b8c14089 2003-11-23 devnull tmp = stringof(s, n);
773 b8c14089 2003-11-23 devnull text = (uchar*)concat((char*)text, tmp);
774 b8c14089 2003-11-23 devnull free(tmp);
775 b9424f64 2019-09-19 crossd text = morerules(text, n==0);
776 b8c14089 2003-11-23 devnull }
777 b8c14089 2003-11-23 devnull if(s == nil){
778 b8c14089 2003-11-23 devnull free(text);
779 b8c14089 2003-11-23 devnull text = nil;
780 b8c14089 2003-11-23 devnull }
781 b8c14089 2003-11-23 devnull parsing = 0;
782 b8c14089 2003-11-23 devnull makeports(rules);
783 b8c14089 2003-11-23 devnull return lasterror;
784 b8c14089 2003-11-23 devnull }