void process_options(char *options, struct request_info *request) { char *key; char *value; char *curr_opt; char *next_opt; struct option *op; char bf[BUFSIZ]; for (curr_opt = get_field(options); curr_opt; curr_opt = next_opt) { next_opt = get_field((char *) 0); /* * Separate the option into name and value parts. For backwards * compatibility we ignore exactly one '=' between name and value. */ curr_opt = chop_string(curr_opt); if (*(value = curr_opt + strcspn(curr_opt, whitespace_eq))) { if (*value != '=') { *value++ = 0; value += strspn(value, whitespace); } if (*value == '=') { *value++ = 0; value += strspn(value, whitespace); } } if (*value == 0) value = 0; key = curr_opt; /* * Disallow missing option names (and empty option fields). */ if (*key == 0) tcpd_jump("missing option name"); /* * Lookup the option-specific info and do some common error checks. * Delegate option-specific processing to the specific functions. */ for (op = option_table; op->name && STR_NE(op->name, key); op++) /* VOID */ ; if (op->name == 0) tcpd_jump("bad option name: \"%s\"", key); if (!value && need_arg(op)) tcpd_jump("option \"%s\" requires value", key); if (value && !permit_arg(op)) tcpd_jump("option \"%s\" requires no value", key); if (next_opt && use_last(op)) tcpd_jump("option \"%s\" must be at end", key); if (value && expand_arg(op)) value = chop_string(percent_x(bf, sizeof(bf), value, request)); if (hosts_access_verbose) syslog(LOG_DEBUG, "option: %s %s", key, value ? value : ""); (*(op->func)) (value, request); } }
int add_arg( char* s, char*** arg, size_t* index, size_t* capacity, int level ) /* purpose: sorts a given full argument string, whether to add or extend * This is the high-level interface to previous functions. * paramtr: s (IN): string to append * arg (OUT): list of arguments as vector * index (IO): index where a new data should be inserted into * capacity (IO): capacity (extend) of vector * level (IN): level of recursion, use 1 * returns: 0 means ok, -1 means error, see errno */ { if ( s[0] == '@' && s[1] != 0 ) { if ( s[1] == '@' ) { return append_arg( s+1, arg, index, capacity ); } else { return expand_arg( s+1, arg, index, capacity, level+1 ); } } else { return append_arg( s, arg, index, capacity ); } }
union node* expand_param(struct nargparam* param, union node** nptr, struct vartab* varstack, char* argv[], int exitcode, int flags) { union node* n = *nptr; stralloc value; char* str = NULL; const char *v = NULL; unsigned long argc, vlen = 0; for(argc = 0; argv[argc]; ++argc) ; stralloc_init(&value); /* treat special arguments */ if(param->flag & S_SPECIAL) { switch(param->flag & S_SPECIAL) { /* $# substitution */ case S_ARGC: { stralloc_catulong0(&value, argc, 0); break; } /* $* substitution */ case S_ARGV: { char** s; for(s = argv; *s;) { stralloc_cats(&n->narg.stra, *s); if(*++s) stralloc_catc(&n->narg.stra, ' '); } break; } /* $@ substitution */ case S_ARGVS: { unsigned int i = 0; while(i < argc) { param->flag &= ~S_SPECIAL; param->flag |= S_ARG; param->numb = 1 + i; n = expand_param(param, nptr, varstack, argv, exitcode,flags); if(++i < argc) nptr = &n->list.next; } return n; } /* $? substitution */ case S_EXITCODE: { stralloc_catulong0(&value, exitcode, 0); break; } /* $- substitution */ case S_FLAGS: break; /* $! substitution */ case S_BGEXCODE: break; /* $[0-9] arg subst */ case S_ARG: { if(param->numb == 0) { /* stralloc_cats(&value, sh_argv0); */ } else if(param->numb - 1 < argc) { stralloc_cats(&value, argv[param->numb - 1]); } break; } /* $$ arg subst */ case S_PID: { stralloc_catulong0(&value, getpid(), 0); break; } } /* special parameters are always set */ if(value.len) { stralloc_nul(&value); v = value.s; } vlen = value.len; } /* ..and variable substitutions */ else { size_t offset; /* look for the variable. if the S_NULL flag is set and we have a var which is null set v to NULL */ if((v = var_get(varstack, param->name, &offset))) { if(v[offset] == '\0' && (param->flag & S_NULL)) { v = NULL; vlen = 0; } else { v = &v[offset]; vlen = str_len(v); } } } /* check for S_STRLEN substitution */ if(param->flag & S_STRLEN) { char lstr[FMT_ULONG]; n = expand_cat(lstr, fmt_ulong(lstr, vlen), nptr, varstack, flags); stralloc_free(&value); return n; } str = str_ndup(v, vlen); /* otherwise expand the apropriate variable/word subst */ switch(param->flag & S_VAR) { /* return word if parameter unset (or null) */ case S_DEFAULT: { if(v) n = expand_cat(v, vlen, nptr, varstack, flags); /* unset, substitute */ else n = expand_arg(¶m->word->narg, nptr, varstack, argv, exitcode, flags); break; } /* if parameter unset (or null) then expand word to it and substitute paramter */ case S_ASGNDEF: { if(v) n = expand_cat(v, vlen, nptr, varstack, flags); else { n = expand_arg(¶m->word->narg, nptr, varstack, argv, exitcode, flags | X_NOSPLIT); var_setvsa(param->name, /* BUG */ &n->narg.stra, V_DEFAULT); } break; } /* indicate error if null or unset */ case S_ERRNULL: { if(v) n = expand_cat(v, vlen, nptr, varstack, flags); else { union node* tmpnode = NULL; n = expand_arg(¶m->word->narg, &tmpnode, varstack, argv, exitcode, flags); errmsg_warn((n && n->narg.stra.s) ? n->narg.stra.s : "parameter null or not set", 0); if(tmpnode) tree_free(tmpnode); } break; } /* if parameter unset (or null) then substitute null, otherwise substitute word */ case S_ALTERNAT: { if(v) n = expand_arg(¶m->word->narg, nptr, varstack, argv, exitcode, flags); break; /* remove smallest matching suffix */ case S_RSSFX: { int i; stralloc sa; if(v && vlen) { expand_copysa(param->word, &sa, varstack, argv, exitcode, 0); stralloc_nul(&sa); for(i = vlen - 1; i >= 0; i--) if(fnmatch(sa.s, str + i, FNM_PERIOD) == 0) break; n = expand_cat(v, (i < 0 ? vlen : i), nptr, varstack, flags); } break; } } /* remove largest matching suffix */ case S_RLSFX: { unsigned int i; stralloc sa; if(v && vlen) { expand_copysa(param->word, &sa, varstack, argv, exitcode, 0); stralloc_nul(&sa); for(i = 0; i <= vlen; i++) if(fnmatch(sa.s, str + i, FNM_PERIOD) == 0) break; n = expand_cat(v, (i > vlen ? vlen : i), nptr, varstack, flags); } break; } /* remove smallest matching prefix */ case S_RSPFX: { unsigned int i; stralloc sa; if(v && vlen) { expand_copysa(param->word, &sa, varstack, argv, exitcode, 0); stralloc_nul(&sa); for(i = 1; i <= vlen; i++) { str_copyn(str, v, i); if(fnmatch(sa.s, (char*)v, FNM_PERIOD) == 0) break; } if(i > vlen) i = 0; n = expand_cat(v + i, vlen - i, nptr, varstack, flags); str_copy(str, v); } break; } /* remove largest matching prefix */ case S_RLPFX: { unsigned int i; stralloc sa; if(v && vlen) { expand_copysa(param->word, &sa, varstack, argv, exitcode, 0); stralloc_nul(&sa); for(i = vlen; i > 0; i--) { str_copyn(str, v, i); if(fnmatch(sa.s, (char*)v, FNM_PERIOD) == 0) break; } if(i == 0) i = vlen; n = expand_cat(v + i, vlen - i, nptr, varstack, flags); str_copy(str, v); } break; } } free(str); stralloc_free(&value); return n; }
void program_flow( sh_int pvnum, /* For diagnostic purposes */ char *source, /* the actual MOBprog code */ CHAR_DATA *mob, CHAR_DATA *ch, const void *arg1, const void *arg2 ) { CHAR_DATA *rch = NULL; char *code, *line; char buf[MAX_STRING_LENGTH]; char control[MAX_INPUT_LENGTH], data[MAX_STRING_LENGTH]; static int call_level; /* Keep track of nested "mpcall"s */ int level, eval, check; int state[MAX_NESTED_LEVEL], /* Block state (BEGIN,IN,END) */ cond[MAX_NESTED_LEVEL]; /* Boolean value based on the last if-check */ sh_int mvnum = mob->pIndexData->vnum; if( ++call_level > MAX_CALL_LEVEL ) { bug( "MOBprogs: MAX_CALL_LEVEL exceeded, vnum %d", mob->pIndexData->vnum ); return; } /* * Reset "stack" */ for ( level = 0; level < MAX_NESTED_LEVEL; level++ ) { state[level] = IN_BLOCK; cond[level] = TRUE; } level = 0; code = source; /* * Parse the MOBprog code */ while ( *code ) { bool first_arg = TRUE; char *b = buf, *c = control, *d = data; /* * Get a command line. We sneakily get both the control word * (if/and/or) and the rest of the line in one pass. */ while( isspace( *code ) && *code ) code++; while ( *code ) { if ( *code == '\n' || *code == '\r' ) break; else if ( isspace(*code) ) { if ( first_arg ) first_arg = FALSE; else *d++ = *code; } else { if ( first_arg ) *c++ = *code; else *d++ = *code; } *b++ = *code++; } *b = *c = *d = '\0'; if ( buf[0] == '\0' ) break; if ( buf[0] == '*' ) /* Comment */ continue; line = data; /* * Match control words */ if ( !str_cmp( control, "if" ) ) { if ( state[level] == BEGIN_BLOCK ) { sprintf( buf, "Mobprog: misplaced if statement, mob %d prog %d", mvnum, pvnum ); bug( buf, 0 ); return; } state[level] = BEGIN_BLOCK; if ( ++level >= MAX_NESTED_LEVEL ) { sprintf( buf, "Mobprog: Max nested level exceeded, mob %d prog %d", mvnum, pvnum ); bug( buf, 0 ); return; } if ( level && cond[level-1] == FALSE ) { cond[level] = FALSE; continue; } line = one_argument( line, control ); if ( ( check = keyword_lookup( fn_keyword, control ) ) >= 0 ) { cond[level] = cmd_eval( pvnum, line, check, mob, ch, arg1, arg2, rch ); } else { sprintf( buf, "Mobprog: invalid if_check (if), mob %d prog %d", mvnum, pvnum ); bug( buf, 0 ); return; } state[level] = END_BLOCK; } else if ( !str_cmp( control, "or" ) ) { if ( !level || state[level-1] != BEGIN_BLOCK ) { sprintf( buf, "Mobprog: or without if, mob %d prog %d", mvnum, pvnum ); bug( buf, 0 ); return; } if ( level && cond[level-1] == FALSE ) continue; line = one_argument( line, control ); if ( ( check = keyword_lookup( fn_keyword, control ) ) >= 0 ) { eval = cmd_eval( pvnum, line, check, mob, ch, arg1, arg2, rch ); } else { sprintf( buf, "Mobprog: invalid if_check (or), mob %d prog %d", mvnum, pvnum ); bug( buf, 0 ); return; } cond[level] = (eval == TRUE) ? TRUE : cond[level]; } else if ( !str_cmp( control, "and" ) ) { if ( !level || state[level-1] != BEGIN_BLOCK ) { sprintf( buf, "Mobprog: and without if, mob %d prog %d", mvnum, pvnum ); bug( buf, 0 ); return; } if ( level && cond[level-1] == FALSE ) continue; line = one_argument( line, control ); if ( ( check = keyword_lookup( fn_keyword, control ) ) >= 0 ) { eval = cmd_eval( pvnum, line, check, mob, ch, arg1, arg2, rch ); } else { sprintf( buf, "Mobprog: invalid if_check (and), mob %d prog %d", mvnum, pvnum ); bug( buf, 0 ); return; } cond[level] = (cond[level] == TRUE) && (eval == TRUE) ? TRUE : FALSE; } else if ( !str_cmp( control, "endif" ) ) { if ( !level || state[level-1] != BEGIN_BLOCK ) { sprintf( buf, "Mobprog: endif without if, mob %d prog %d", mvnum, pvnum ); bug( buf, 0 ); return; } cond[level] = TRUE; state[level] = IN_BLOCK; state[--level] = END_BLOCK; } else if ( !str_cmp( control, "else" ) ) { if ( !level || state[level-1] != BEGIN_BLOCK ) { sprintf( buf, "Mobprog: else without if, mob %d prog %d", mvnum, pvnum ); bug( buf, 0 ); return; } if ( level && cond[level-1] == FALSE ) continue; state[level] = IN_BLOCK; cond[level] = (cond[level] == TRUE) ? FALSE : TRUE; } else if ( cond[level] == TRUE && ( !str_cmp( control, "break" ) || !str_cmp( control, "end" ) ) ) { call_level--; return; } else if ( (!level || cond[level] == TRUE) && buf[0] != '\0' ) { state[level] = IN_BLOCK; expand_arg( data, buf, mob, ch, arg1, arg2, rch ); if ( !str_cmp( control, "mob" ) ) { /* * Found a mob restricted command, pass it to mob interpreter */ line = one_argument( data, control ); mob_interpret( mob, line ); } else { /* * Found a normal mud command, pass it to interpreter */ interpret( mob, data ); } } } call_level--; }