~ubuntu-branches/ubuntu/lucid/vde2/lucid-proposed

« back to all changes in this revision

Viewing changes to utils/cmdparse.c

  • Committer: Bazaar Package Importer
  • Author(s): Filippo Giunchedi
  • Date: 2008-06-17 15:36:32 UTC
  • mfrom: (1.1.3 upstream)
  • Revision ID: james.westby@ubuntu.com-20080617153632-5318x7iv0zwmu3zu
Tags: 2.2.1-1
* New upstream release
  - fix vlan commands on amd64 (Closes: #484295)
  - fix mac addresses switch between ports (Closes: #469098)
* Suggest: qemu and kvm as requested in #461514
* Expand and spell-check README.Debian, add manual method example
  (Closes: #466363)
* Do not assume MAKEDEV presence in postinst
* Remove /usr/bin/daemon usage from ifupdown scripts (and Recommends)
* Add manpage for vde_tunctl
* Upgrade to S-V 3.8.0 (add Homepage field) 

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * Copyright (C) 2007 - Renzo Davoli, Luca Bigliardi
3
 
 * This program is free software; you can redistribute it and/or
4
 
 * modify it under the terms of the GNU General Public License
5
 
 * as published by the Free Software Foundation; either version 2
6
 
 * of the License, or (at your option) any later version.
7
 
 *
8
 
 * This program is distributed in the hope that it will be useful,
9
 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
 
 * GNU General Public License for more details.
12
 
 *
13
 
 * You should have received a copy of the GNU General Public License
14
 
 * along with this program; if not, write to the Free Software
15
 
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
16
 
 */
17
 
 
18
 
#define _GNU_SOURCE
19
 
#include <stdio.h>
20
 
#include <stdlib.h>
21
 
#include <string.h>
22
 
#include <unistd.h>
23
 
#include <sys/poll.h>
24
 
#include <errno.h>
25
 
 
26
 
#ifndef HAVE_OPEN_MEMSTREAM
27
 
#include <utils/open_memstream.h>
28
 
#endif
29
 
 
30
 
#include <utils/cmdparse.h>
31
 
 
32
 
#define BUFSIZE 256
33
 
#define TIMEOUT 10000
34
 
 
35
 
enum command {ERR, IN, THROW, SEND, SHIFT, IF, GOTO, COPY, EXIT, EXITRV, SKIP, IFARG, RVATOI, OUTSHIFT, OUTTAG};
36
 
 
37
 
char *commandname[]= {
38
 
        "",
39
 
        "IN", 
40
 
        "THROW", 
41
 
        "SEND", 
42
 
        "SHIFT", 
43
 
        "IF", 
44
 
        "GOTO", 
45
 
        "COPY", 
46
 
        "EXIT", 
47
 
        "EXITRV",
48
 
        "SKIP",
49
 
        "IFARG",
50
 
        "RVATOI",
51
 
        "OUTSHIFT",
52
 
        "OUTTAG"
53
 
};
54
 
 
55
 
#define NUMCOMMANDS (sizeof(commandname)/sizeof(char *))
56
 
 
57
 
static const char *nullstring="";
58
 
 
59
 
struct utmstate {
60
 
        int num;
61
 
        enum command command;
62
 
        const char *string;
63
 
#define value nextnum;
64
 
        int nextnum;
65
 
        struct utmstate *next;
66
 
};
67
 
 
68
 
static struct utmstate *utmsadd(struct utmstate *head, struct utmstate *this)
69
 
{
70
 
        if (!head || head->num > this->num) {
71
 
                this->next=head;
72
 
                return this;
73
 
        } else {
74
 
                head->next=utmsadd(head->next,this);
75
 
                return head;
76
 
        }
77
 
}
78
 
 
79
 
static enum command searchcommand(char *name)
80
 
{
81
 
                int i;
82
 
                for (i=0; i<NUMCOMMANDS && strcmp(name,commandname[i]) != 0; i++)
83
 
                        ;
84
 
                if (i<NUMCOMMANDS) 
85
 
                        return i;
86
 
                else
87
 
                        return ERR;
88
 
}
89
 
 
90
 
static inline char *blankskip(char *s)
91
 
{
92
 
        while (*s && (*s==' ' || *s=='\t'))
93
 
                s++;
94
 
        return s;
95
 
}
96
 
 
97
 
static inline char *fieldskip(char *s)
98
 
{
99
 
        while (*s && *s!=' ' && *s!='\t' && *s!='\n') 
100
 
                s++;
101
 
        return s;
102
 
}
103
 
 
104
 
static int readchar(int fd, struct utm_buf *inbuf, char *out, int timeout)
105
 
{
106
 
        if (!inbuf->buf) {
107
 
                inbuf->buf=(char *)malloc(sizeof(char)*BUFSIZE);
108
 
                if(!inbuf->buf) { perror("readchar"); exit(-1); }
109
 
                inbuf->len=inbuf->pos=0;
110
 
        }
111
 
        if (inbuf->len <= inbuf->pos)
112
 
        {
113
 
                struct pollfd pfd={fd, POLLIN, 0};
114
 
                if (poll(&pfd,1,timeout) <= 0) {
115
 
                        return -1;
116
 
                }
117
 
                inbuf->len=read(fd,inbuf->buf,BUFSIZE);
118
 
                if (inbuf->len==0)
119
 
                        return -1;
120
 
                else
121
 
                        inbuf->pos=0;
122
 
        }
123
 
        *out = (inbuf->buf[(inbuf->pos)++]);
124
 
        return 0;
125
 
}
126
 
 
127
 
struct utmstate *sgoto(struct utmstate *head,int nextnum)
128
 
{
129
 
        if (head) {
130
 
                if (nextnum == head->num)
131
 
                        return head;
132
 
                else
133
 
                        return sgoto(head->next,nextnum);
134
 
        } else {
135
 
                //fprintf(stderr,"Error Label not found: %d\n",nextnum);
136
 
                return NULL;
137
 
        }
138
 
}
139
 
 
140
 
void utm_freestate(struct utmstate *head)
141
 
{
142
 
        struct utmstate* rest = head->next;
143
 
        free(head);
144
 
        utm_freestate(rest);
145
 
}
146
 
 
147
 
struct utm *utm_alloc(char *conf)
148
 
{
149
 
        FILE *f;
150
 
        struct utm *utm=NULL;
151
 
        int line=0;
152
 
        char buf[BUFSIZE];
153
 
        if ((f=fopen(conf,"r")) == NULL) {
154
 
                //fprintf(stderr,"Configuration file error %s\n",conf);
155
 
                errno=ENOENT;
156
 
                return NULL;
157
 
        }
158
 
        utm=(struct utm*)malloc(sizeof(struct utm));
159
 
        if(!utm) {perror("utm_alloc"); exit(-1); }
160
 
        utm->timeout=TIMEOUT ; utm->head = NULL;
161
 
        while (fgets(buf,BUFSIZE,f) != NULL) {
162
 
                char *s=buf;
163
 
                int num;
164
 
                line++;
165
 
                s=blankskip(s);
166
 
                num=atoi(s);
167
 
                if (num>0) {
168
 
                        /* create new automata state */
169
 
                        enum command cmd;
170
 
                        char *currfield;
171
 
                        char c;
172
 
                        s=fieldskip(s);
173
 
                        s=blankskip(s);
174
 
                        currfield=s;
175
 
                        s=fieldskip(s);
176
 
                        c=*s;*s=0;
177
 
                        if ((cmd=searchcommand(currfield)) != ERR) {
178
 
                                struct utmstate *new=malloc(sizeof(struct utmstate));
179
 
                                if(!new) {perror("utm_alloc"); exit(-1); }
180
 
                                new->num = num;
181
 
                                new->command = cmd;
182
 
                                *s=c;
183
 
                                s=blankskip(s);
184
 
                                currfield=s;
185
 
                                if (*currfield=='\'') { /* first argument is a string */
186
 
                                        char *t;
187
 
                                        char skip=0; /*not escaped*/
188
 
                                        t=currfield=++s; /* skip ' */
189
 
                                        while (*s && (skip || *s != '\'')) {
190
 
                                                if (*s == '\\' && *(s+1) != 0) {
191
 
                                                        s++; /* skip \ */
192
 
                                                        switch (*s) {
193
 
                                                                case 'n': *s='\n'; break;
194
 
                                                                case 't': *s='\t'; break;
195
 
                                                                case 'f': *s='\f'; break;
196
 
                                                        }
197
 
                                                }
198
 
                                                *t++ = *s++;
199
 
                                        }
200
 
                                        c=*s;*t=0;
201
 
                                        new->string=strdup(currfield);
202
 
                                        if (c) s++;
203
 
                                        s=blankskip(s);
204
 
                                        currfield=s;
205
 
                                } else {
206
 
                                        new->string=nullstring;
207
 
                                }
208
 
                                new->nextnum=atoi(currfield);
209
 
                                utm->head=utmsadd(utm->head,new);
210
 
                        }
211
 
                } else {
212
 
                        /* add constant definition */
213
 
                        if (strncmp("TIMEOUT",s,7)==0)
214
 
                                utm->timeout=atoi(s+8);
215
 
                }
216
 
        }
217
 
        fclose(f);
218
 
        return(utm);
219
 
}
220
 
 
221
 
void utm_free(struct utm *utm)
222
 
{
223
 
        if(utm){
224
 
                if(utm->head) utm_freestate(utm->head);
225
 
                free(utm);
226
 
        }
227
 
}
228
 
 
229
 
int utm_run(struct utm *utm, struct utm_buf *buf, int fd, int argc, char **argv, struct utm_out *out, int debug)
230
 
{
231
 
        struct utmstate *status = utm->head;
232
 
        int len=0, curr=0, linebufsize=0, rv=-1;
233
 
        char *linebuf=NULL;
234
 
 
235
 
        if(debug) {int i; printf("c: %d\n", argc); for(i=0; i <=argc ; i++) printf("a[%d]: %s\n", i, argv[i]); }
236
 
 
237
 
        while (1) {
238
 
                int patlen=strlen(status->string);
239
 
                if (debug) printf("NOW %d parsing %s\n",status->num,linebuf?(linebuf+curr):NULL);
240
 
                switch (status -> command) {
241
 
                        case ERR: /* error, return */
242
 
                                if(linebuf) free(linebuf);
243
 
                                return -1;
244
 
                                break;
245
 
                        case IN: /* eat from inbuf while timeout or pattern found */
246
 
                                {
247
 
                                        int ltimeout=0;
248
 
                                        do {
249
 
                                                if (len==linebufsize) {
250
 
                                                        linebufsize += BUFSIZE;
251
 
                                                        linebuf=realloc(linebuf,sizeof(char)*(linebufsize+1));
252
 
                                                        if(!linebuf){ perror("utm_run"); exit(-1); }
253
 
                                                }
254
 
                                                if (readchar(fd, buf, &linebuf[len], utm->timeout) < 0)
255
 
                                                        ltimeout=1;
256
 
                                                else
257
 
                                                        len++;
258
 
                                        } while (!ltimeout && (len < patlen || strncmp(status->string,linebuf+(len-patlen),patlen) != 0));
259
 
                                        linebuf[len]=0;
260
 
                                        if(ltimeout)
261
 
                                                status=sgoto(utm->head,status->nextnum);
262
 
                                        else
263
 
                                                status=status->next;
264
 
                                }
265
 
                                break;
266
 
                        case THROW: /* drop current linebuf */
267
 
                                curr=0;
268
 
                                if(linebuf) *linebuf=0;
269
 
                                len=0;
270
 
                                status=status->next;
271
 
                                break;
272
 
                        case SEND: /* write command to fd */
273
 
                                {
274
 
                                        const char *t=status->string;
275
 
                                        char *ptr;
276
 
                                        size_t size;
277
 
                                        FILE *mf=open_memstream(&ptr,&size);
278
 
                                        while (*t) { /* create the string */
279
 
                                                if (*t == '$' && (t==status->string || *(t-1) != '\\')) {
280
 
                                                        t++;
281
 
                                                        if (*t == '*' || *t == '0') { /*all parms*/
282
 
                                                                int i;
283
 
                                                                for (i=0;i<argc;i++) {
284
 
                                                                        if (i) fprintf(mf," ");
285
 
                                                                        fprintf(mf,argv[i]);
286
 
                                                                }
287
 
                                                        } else {
288
 
                                                                int num=atoi(t);
289
 
                                                                while (*t >='0' && *t <= '9') t++;
290
 
                                                                if (num < argc) 
291
 
                                                                        fprintf(mf,argv[num]);
292
 
                                                        }
293
 
                                                } else
294
 
                                                        fprintf(mf,"%c",*t);
295
 
                                                t++;
296
 
                                        }
297
 
                                        fclose(mf);
298
 
                                        write (fd,ptr,size);
299
 
                                        free(ptr);
300
 
                                }
301
 
                                status=status->next;
302
 
                                break;
303
 
                        case SHIFT: /* eat first argument */
304
 
                                argc--; argv++;
305
 
                                status=status->next;
306
 
                                break;
307
 
                        case IF: /* goto nextnum if pattern match */
308
 
                                if (linebuf && (strncmp(linebuf+curr,status->string,patlen) == 0) )
309
 
                                        status=sgoto(utm->head,status->nextnum);
310
 
                                else
311
 
                                        status=status->next;
312
 
                                break;
313
 
                        case GOTO: /* simple goto */
314
 
                                status=sgoto(utm->head,status->nextnum);
315
 
                                break;
316
 
                        case COPY: /* copy current linebuf to current outbuf */
317
 
                                if(linebuf){
318
 
                                        int tocpy=strlen(linebuf+curr)+1;
319
 
                                        out->buf=realloc(out->buf, out->sz+tocpy);
320
 
                                        if(!out->buf){ perror("utm_run"); exit(-1); }
321
 
                                        memcpy(out->buf+out->sz, linebuf+curr, tocpy);
322
 
                                        out->sz+=tocpy;
323
 
                                }
324
 
                                status=status->next;
325
 
                                break;
326
 
                        case EXIT: /* exit with value */
327
 
                                rv = status->nextnum;
328
 
                        case EXITRV: /* exit with retval */
329
 
                                if(linebuf) free(linebuf);
330
 
                                return rv;
331
 
                                break;
332
 
                        case SKIP: /* skip after the first occurence of string or N chars */
333
 
                                if(linebuf){
334
 
                                        char *skip=NULL;
335
 
                                        if(strlen(status->string)) skip=strstr(linebuf, status->string);
336
 
                                        if(skip) curr=(status->string+strlen(status->string))-linebuf;
337
 
                                        else curr+=status->nextnum;
338
 
                                        if(curr>len) curr=len; /* normalize */
339
 
                                }
340
 
                                status=status->next;
341
 
                                break;
342
 
                        case IFARG: /* goto if there are still arguments */
343
 
                                if (argc>=0)
344
 
                                        status=sgoto(utm->head,status->nextnum);
345
 
                                else
346
 
                                        status=status->next;
347
 
                                break;
348
 
                        case RVATOI: /* remember current number as return value the
349
 
                                                optional argument is the base to convert from*/
350
 
                                if(!linebuf){
351
 
                                        rv = -1;
352
 
                                }else if( status->nextnum <= 0 ){
353
 
                                        rv = strtol(linebuf+curr, NULL, 10);
354
 
                                }else if( status->nextnum >= 2 && status->nextnum <= 36 ){
355
 
                                        rv = strtol(linebuf+curr, NULL, status->nextnum);
356
 
                                }else{
357
 
                                        rv = -1;
358
 
                                }
359
 
                                status=status->next;
360
 
                                break;
361
 
                        case OUTSHIFT: /* alloc another output buffer and use it */
362
 
                                out->next=utmout_alloc();
363
 
                                out=out->next;
364
 
                                status=status->next;
365
 
                                break;
366
 
                        case OUTTAG: /* set tag of current output buffer */
367
 
                                out->tag=status->nextnum;
368
 
                                status=status->next;
369
 
                                break;
370
 
                        default:
371
 
                                if(linebuf) free(linebuf);
372
 
                                return -1;
373
 
                                break;
374
 
                }
375
 
        }
376
 
}
377
 
 
378
 
struct utm_out *utmout_alloc(void)
379
 
{
380
 
        struct utm_out *out = NULL;
381
 
        out = (struct utm_out*)malloc(sizeof(struct utm_out));
382
 
        if(!out) { perror(__func__); exit(-1);}
383
 
        memset(out, 0, sizeof(struct utm_out));
384
 
        return out;
385
 
}
386
 
 
387
 
void utmout_free(struct utm_out *out)
388
 
{
389
 
        while(out) {
390
 
                if(out->buf) free(out->buf);
391
 
                out = out->next;
392
 
        }
393
 
}
394
 
 
395