root/op/1.28/lex.l

Revision 216, 8.9 kB (checked in by athomas, 4 years ago)

Missed this in the last commit.

Line 
1 %{
2 /* +-------------------------------------------------------------------+ */
3 /* | Copyright 1991, David Koblas.                                     | */
4 /* |   Permission to use, copy, modify, and distribute this software   | */
5 /* |   and its documentation for any purpose and without fee is hereby | */
6 /* |   granted, provided that the above copyright notice appear in all | */
7 /* |   copies and that both that copyright notice and this permission  | */
8 /* |   notice appear in supporting documentation.  This software is    | */
9 /* |   provided "as is" without express or implied warranty.           | */
10 /* +-------------------------------------------------------------------+ */
11
12 #include <stdio.h>
13 #include <string.h>
14 #include <stdarg.h>
15 #include <ctype.h>
16 #include <syslog.h>
17 #include "defs.h"
18
19 static cmd_t    *newcmd();
20 char    *savestr();
21 void addvar(const char *str);
22 void preproc(const char *str);
23 void preprocerror(const char *str);
24 static void addquotedarg(int state, cmd_t *cmd, const char *instr);
25 static void addarg(int state, cmd_t *cmd, const char *instr);
26
27 #ifndef _AIX
28 extern char     *strchr();
29 #endif
30 int     yyline = 1;
31
32 %}
33
34 WS              [ \t]*
35 NWS             [^ \n\t;]+
36
37 %s ARGS
38
39 %%
40         int     state = 0;
41         cmd_t   *cmd;
42
43 #[^\n]*                 ;
44 ^%(((if|elsif)[ \t]+.*)|(else|endif))           { preproc(yytext); }
45 ^%.*                    { preprocerror(yytext); }
46 \n                      { yyline++; BEGIN 0; }
47 ^[A-Z_][A-Z_0-9]*=[^\n\r]*      { addvar(yytext); }
48 ^[^ \n\t]+              { cmd = newcmd(yytext);
49                                 state = (strcmp(yytext,"DEFAULT")==0) ? 1 : 0;
50                                 BEGIN ARGS; }
51 ^{WS}                   BEGIN ARGS;
52 <ARGS>";"               state++;
53 <ARGS>'(\\.|[^'])*'     addquotedarg(state, cmd, yytext);
54 <ARGS>\"(\\.|[^\"])*\"  addquotedarg(state, cmd, yytext);
55 <ARGS>{NWS}             addarg(state, cmd, yytext);
56 <ARGS>{WS}              ;
57 %%
58 #include <sys/types.h>
59 #include <sys/stat.h>
60 #include <string.h>
61
62 void msg(const char *format, ...)
63 {
64 #if 0
65         va_list ap;
66         char    *s;
67
68         va_start(ap);
69         s = va_arg(ap, char *);
70         fprintf(stderr,"line %d: ",yyline);
71         vfprintf(stderr, s, ap);
72         fputc('\n', stderr);
73         va_end(ap);
74 #endif
75 }
76
77 char *expandvars(const char *instr) {
78 char *str = (char*)malloc(VAR_EXPAND_LEN);
79 int i = 0;
80
81         if (str == NULL)
82                 fatal(1, "Unable to allocate variable expansion buffer");
83
84         while (*instr)
85                 if (isupper(*instr) || *instr == '_') {
86                 const char *mark = instr;
87                 var_t *var;
88
89                         while (*instr && (isupper(*instr) || isdigit(*instr) || *instr == '_'))
90                                 ++instr;
91                         for (var = Variables; var != 0; var = var->next) {
92                         int l = strlen(var->name);
93
94                                 if (instr - mark > l) l = instr - mark;
95                                 if (!strncmp(mark, var->name, l)) {
96                                         str[i] = 0;
97                                         strcat(str, var->value);
98                                         i += strlen(var->value);
99                                         break;
100                                 }
101                         }
102                         if (!var) {
103                                 instr = mark + 1;
104                                 str[i++] = *mark;
105                         }
106                 } else
107                         str[i++] = *instr++;
108         str[i] = 0;
109         return str;
110 }
111
112 void preprocerror(const char *str) {
113         fprintf(stderr, "Invalid preprocessor command '%s'\n", str);
114         exit(1);
115 }
116
117 void preproc(const char *str) {
118         if (!strncmp(str, "%if", 3)) {
119         } else
120         if (!strncmp(str, "%elseif", 7)) {
121         } else
122         if (!strcmp(str, "%else")) {
123         } else
124         if (!strcmp(str, "%endif")) {
125         } else
126                 preprocerror(str);
127 }
128
129 void addvar(const char *str) {
130 char name[VAR_NAME_LEN], value[VAR_EXPAND_LEN];
131 const char *eq = strchr(str, '=');
132
133         if (eq && str - eq < VAR_NAME_LEN) {
134         int i, o;
135         var_t *var;
136
137                 strncpy(name, str, eq - str);
138                 name[eq - str] = 0;
139
140                 for (o = 0, i = eq - str + 1; o < VAR_EXPAND_LEN - 1 && str[i]; ++i)
141                         if (str[i] == '\\') {
142                                 switch (str[++i]) {
143                                         case 'n' : value[o++] = '\n'; break;
144                                         case 'r' : value[o++] = '\r'; break;
145                                         case 't' : value[o++] = '\t'; break;
146                                         case 'a' : value[o++] = '\a'; break;
147                                         case 'b' : value[o++] = '\b'; break;
148                                         default : value[o++] = str[i]; break;
149                                 }
150                         } else
151                         if (str[i] == '"')
152                                 break;
153                         else
154                                 value[o++] = str[i];
155                 value[o++] = 0;
156
157                 if ((var = (var_t*)malloc(sizeof(var_t))) == NULL)
158                         fatal(1, "Unable to allocate var_t");
159                 if ((var->name = malloc(strlen(name) + 1)) == NULL)
160                         fatal(1, "Unable to allocate variable name");
161                 strcpy(var->name, name);
162                 var->value = expandvars(value);
163                 var->next = 0;
164
165                 if (Variables) {
166                 var_t *i;
167
168                         for (i = Variables; i->next; i = i->next) ;
169                         i->next = var;
170                 } else
171                         Variables = var;
172         } else
173                 fatal(1, "Invalid alias");
174 }
175
176 static void addquotedarg(int state, cmd_t *cmd, const char *instr) {
177 char buffer[MAXSTRLEN];
178 int i, o;
179
180         if (strlen(instr) + 2 > MAXSTRLEN) {
181                 fatal(1, "Quoted argument too long\n");
182                 exit(1);
183         }
184         for (o = 0, i = 1; instr[i] != instr[0]; ++i, ++o) {
185                 if (instr[i] == '\\') {
186                 int c = instr[++i];
187
188                         if (strchr("'\"", c)) {
189                                 buffer[o] = c;
190                         } else {
191                                 buffer[o++] = '\\';
192                                 buffer[o] = c;
193                         }
194                 } else
195                         buffer[o] = instr[i];
196         }
197         buffer[o] = 0;
198         addarg(state, cmd, buffer);
199 }
200
201 static void addarg(int state, cmd_t *cmd, const char *instr) {
202 char *str = expandvars(instr);
203
204         if (state == 0) {
205                 msg("cmd='%s' add arg '%s'",cmd->name,str);
206                 if (cmd->margs == cmd->nargs)  {
207                         cmd->margs += cmd->margs;
208                         cmd->args = (char **)realloc(cmd->args,
209                                         sizeof(char *) * cmd->margs);
210                         if (cmd->args == NULL)
211                                 fatal(1, "Unable to groupw args");
212                 }
213                 cmd->args[cmd->nargs++] = savestr(str);
214         } else if (state == 1) {
215                 msg("cmd='%s' add opt '%s'",cmd->name,str);
216                 if (cmd->mopts == cmd->nopts) {
217                         cmd->mopts += cmd->mopts;
218                         cmd->opts = (char **)realloc(cmd->opts,
219                                         sizeof(char *) * cmd->mopts);
220                         if (cmd->opts == NULL)
221                                 fatal(1, "Unable to groupw opts");
222                 }
223                 cmd->opts[cmd->nopts++] = savestr(str);
224         } else {
225                 fatal(1, "bad state (%d) received\n",state);
226         }
227         free(str);
228 }
229
230 char    *savestr(str)
231 char    *str;
232 {
233         char    *s = (char *)malloc(strlen(str)+1);
234
235         if (s == NULL)
236                 fatal(1, "No string space");
237
238         strcpy(s, str);
239         return s;
240 }
241
242 static cmd_t    *newcmd(name)
243 char    *name;
244 {
245         cmd_t   *cmd = (cmd_t *)malloc(sizeof(cmd_t));
246
247         if (cmd == NULL)
248                 fatal(1, "Unable to alloc space for new command");
249
250         cmd->next = First;
251         First = cmd;
252
253         cmd->name = savestr(name);
254         cmd->nargs = 0;         cmd->margs = 16;
255         cmd->nopts = 0;         cmd->mopts = 16;
256         cmd->args = (char **)malloc(sizeof(char *)*cmd->margs);
257         cmd->opts = (char **)malloc(sizeof(char *)*cmd->mopts);
258
259         if (cmd->args == NULL || cmd->opts == NULL)
260                 fatal(1, "Unable to alloc args/opts");
261
262         return cmd;
263 }
264
265 int ReadFile(file)
266 char    *file;
267 {
268         struct stat     statbuf;
269         FILE            *fd;
270        
271         if ((stat(file, &statbuf) < 0))
272                 return 0;
273         if ((statbuf.st_uid != 0) || /* Owned by root */
274                         ((statbuf.st_mode & 0077) != 0)) { /* SD - no perm */
275                 logger(LOG_ERR, "Permission problems on %s", file);
276                 return 0;
277         }
278         if ((fd = fopen(file,"r")) == NULL)
279                 return 0;
280
281         yyin = fd;
282         yylex();
283
284         return 1;
285 }
286
287 int CountArgs(cmd)
288 cmd_t   *cmd;
289 {
290         int     i, val;
291         int     wild = 0, max = 0;
292         char    *cp, *np, str[MAXSTRLEN];
293
294         for (i = 0; i < cmd->nargs; i++) {
295                 np = cmd->args[i];
296
297                 while ((cp = strchr(np, '$')) != NULL) {
298                         if ((cp != cmd->args[i]) && (*(cp-1) == '\\'))
299                                 np = cp + 1;
300                         else {
301                                 if (*(cp+1) == '*') {
302                                         wild = 1;
303                                         ++cp;
304                                         np = cp;
305                                         continue;
306                                 }
307                                 cp++;
308                                 np = cp;
309                                
310                                 while (isdigit(*cp))
311                                         cp++;
312                                 if ((cp - np) == 0)
313                                         continue;
314                                 strncpy(str, np, cp - np);
315                                 str[cp - np] = '\0';
316                                 val = atoi(str);
317                                 if (val > max)
318                                         max = val;
319                         }
320                 }
321         }
322
323         if (wild)
324                 return -max;
325         return max;
326 }
327
328 static int      cmpopts(a, b)
329 char    *a, *b;
330 {
331         char    *cp_a, *cp_b;
332         int     val_a, val_b;
333         char    str_a[MAXSTRLEN], str_b[MAXSTRLEN];
334
335         if (*a != '$' && *b != '$')
336                 return 0;
337         if (*a == '$' && *b != '$')
338                 return -1;
339         if (*a != '$' && *b == '$')
340                 return  1;
341
342         cp_a = ++a;
343         cp_b = ++b;
344         while ((*cp_a != '\0') && (*cp_a != '='))
345                 if (! isdigit(*cp_a))
346                         break;
347         while ((*cp_b != '\0') && (*cp_b != '='))
348                 if (! isdigit(*cp_b))
349                         break;
350        
351         if (*cp_a != '=' && *cp_b != '=')
352                 return 0;
353         if (*cp_a == '=' && *cp_b != '=')
354                 return -1;
355         if (*cp_a != '=' && *cp_b == '=')
356                 return  1;
357
358         strncpy(str_a, a, cp_a - a);
359         str_a[cp_a - a] = '\0';
360         val_a = atoi(str_a);
361         strncpy(str_b, b, cp_b - a);
362         str_a[cp_b - b] = '\0';
363         val_b = atoi(str_b);
364
365         if (val_a < val_b)
366                 return -1;
367         if (val_a > val_b)
368                 return  1;
369         return 0;
370 }
371
372 void sortopts(cmd)
373 cmd_t   *cmd;
374 {
375         qsort(cmd->opts, cmd->nopts, sizeof(char *), cmpopts);
376 }
377
378 cmd_t   *Build(def, cmd)
379 cmd_t   *def, *cmd;
380 {
381         cmd_t           *new = newcmd("");
382         char            defname[MAXSTRLEN], optname[MAXSTRLEN], *cp;
383         int             i, j;
384 #ifndef _AIX
385         extern char     *strchr();
386 #endif
387         if (cmd == NULL)
388                 return def;
389         if (def == NULL)
390                 return cmd;
391
392         for (i = 0; i < cmd->nargs; i++)
393                 addarg(0, new, cmd->args[i]);
394
395         for (i = 0; i < def->nopts; i++) {
396                 if ((cp = strchr(def->opts[i], '=')) == NULL)
397                         strcpy(defname, def->opts[i]);
398                 else {
399                         int     l = cp - def->opts[i];
400                         strncpy(defname, def->opts[i], l);
401                         defname[l] = '\0';
402                 }
403                 for (j = 0; j < cmd->nopts; j++) {
404                         if ((cp = strchr(cmd->opts[j], '=')) == NULL)
405                                 strcpy(optname, cmd->opts[j]);
406                         else {
407                                 int     l = cp - cmd->opts[j];
408                                 strncpy(optname, cmd->opts[j], l);
409                                 optname[l] = '\0';
410                         }
411                         if (strcmp(defname, optname) == 0)
412                                 def->opts[i][0] = '\0';
413                 }
414                 if (def->opts[i][0] != '\0')
415                         addarg(1, new, def->opts[i]);
416         }
417         for (j = 0; j < cmd->nopts; j++)
418                 addarg(1, new, cmd->opts[j]);
419
420         /* sortopts(new); */
421
422         return new;
423 }
Note: See TracBrowser for help on using the browser.