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