/** Add new help command. This function is * the basis for the help_command directive in mush.cnf. It creates * a new help entry for the hash table, builds a help index, * and adds the new command to the command table. * \param command_name name of help command to add. * \param filename name of the help file to use for this command. * \param admin if 1, this command reads admin topics, rather than standard. */ void add_help_file(const char *command_name, const char *filename, int admin) { help_file *h; if (help_init == 0) init_help_files(); if (!command_name || !filename || !*command_name || !*filename) return; /* If there's already an entry for it, complain */ h = hashfind(strupper(command_name), &help_files); if (h) { do_rawlog(LT_ERR, "Duplicate help_command %s ignored.", command_name); return; } h = mush_malloc(sizeof *h, "help_file.entry"); h->command = mush_strdup(strupper(command_name), "help_file.command"); h->file = mush_strdup(filename, "help_file.filename"); h->entries = 0; h->indx = NULL; h->admin = admin; help_build_index(h, h->admin); if (!h->indx) { mush_free(h->command, "help_file.command"); mush_free(h->file, "help_file.filename"); mush_free(h, "help_file.entry"); return; } (void) command_add(h->command, CMD_T_ANY | CMD_T_NOPARSE, NULL, 0, NULL, cmd_helpcmd); hashadd(h->command, h, &help_files); }
static void end_log(struct log_stream *log, bool keep_buffer) { FILE *fp; if (!log->filename || !*log->filename || !log->fp) return; if ((fp = hashfind(strupper(log->filename), &htab_logfiles))) { int n; lock_file(fp); fputs("END OF LOG.\n", fp); fflush(fp); for (n = 0; n < NLOGS; n++) { if (logs[n].fp == fp) logs[n].fp = NULL; } fclose(fp); /* Implicit lock removal */ if (!keep_buffer) { free_bufferq(log->buffer); log->buffer = NULL; } hashdelete(strupper(log->filename), &htab_logfiles); } }
static void start_log(struct log_stream *log) { static int ht_initialized = 0; FILE *f; if (!log->filename || !*log->filename) { log->fp = stderr; } else { if (!ht_initialized) { hashinit(&htab_logfiles, 8); ht_initialized = 1; } if ((f = hashfind(strupper(log->filename), &htab_logfiles))) { /* We've already opened this file for another log, so just use that pointer */ log->fp = f; } else { log->fp = fopen(log->filename, "a+"); if (log->fp == NULL) { fprintf(stderr, "WARNING: cannot open log %s: %s\n", log->filename, strerror(errno)); log->fp = stderr; } else { hashadd(strupper(log->filename), log->fp, &htab_logfiles); fputs("START OF LOG.\n", log->fp); fflush(log->fp); } } } if (!log->buffer) log->buffer = allocate_bufferq(LOG_BUFFER_SIZE); }
int HandledCommand_sub(dbref player, dbref location, char *command) { XCODE *xcode_obj = NULL; struct SpecialObjectStruct *typeOfObject; int type; CommandsStruct *cmd; HASHTAB *damnedhash; char *tmpc, *tmpchar; int ishelp; type = WhichSpecial(location); if (type < 0 || (SpecialObjects[type].datasize > 0 && !(xcode_obj = rb_find(xcode_tree, (void *)location)))) { if(type >= 0 || !Hardcode(location) || Zombie(location)) return 0; if((type = WhichSpecialS(location)) >= 0) { if(SpecialObjects[type].datasize > 0) return 0; } else return 0; } #ifdef FAST_WHICHSPECIAL if(type > NUM_SPECIAL_OBJECTS) return 0; #endif typeOfObject = &SpecialObjects[type]; damnedhash = &SpecialCommandHash[type]; tmpc = strstr(command, " "); if(tmpc) *tmpc = 0; ishelp = !strcmp(command, "HELP"); for(tmpchar = command; *tmpchar; tmpchar++) *tmpchar = ToLower(*tmpchar); cmd = (CommandsStruct *) hashfind(command, &SpecialCommandHash[type]); if(tmpc) *tmpc = ' '; if(cmd && (type != GTYPE_MECH || (type == GTYPE_MECH && Can_Use_Command(((MECH *) xcode_obj), cmd->flag)))) { #define SKIPSTUFF(a) while (*a && *a != ' ') a++;while (*a == ' ') a++ if(cmd->helpmsg[0] != '@' || Have_MechPower(Owner(player), typeOfObject->power_needed)) { SKIPSTUFF(command); cmd->func(player, xcode_obj, command); } else notify(player, "Sorry, that command is restricted!"); return 1; } else if(ishelp) { SKIPSTUFF(command); DoSpecialObjectHelp(player, typeOfObject->type, type, location, typeOfObject->power_needed, location, command); return 1; } return 0; }
/** Determine if a lock type is one of the standard types or not. * \param type type of lock to check. * \return canonical lock type or NULL */ lock_type match_lock(lock_type type) { lock_list *ll; ll = hashfind(strupper(type), &htab_locks); if (ll) return ll->type; else return NULL; }
FLAGENT *find_flag( dbref thing, char *flagname ) { char *cp; /* * Make sure the flag name is valid */ for( cp = flagname; *cp; cp++ ) { *cp = toupper( *cp ); } return ( FLAGENT * ) hashfind( flagname, &mudstate.flags_htab ); }
/** Look up a player in the player list htab only. * \param name name of player to find. * \return dbref of player, or NOTHING. */ dbref lookup_player_name(const char *name) { dbref *p; if (hft_initialized) { p = hashfind(strupper(name), &htab_player_list); if (!p) return NOTHING; return *p; } return NOTHING; }
POWERENT *find_power(dbref thing, char *powername) { char *cp; /* * Make sure the power name is valid */ for (cp = powername; *cp; cp++) { *cp = tolower(*cp); } return (POWERENT *) hashfind(powername, &mudstate.powers_htab); }
dbref absolute_nref(char *str) { char *p, *q, *buf, *bp; dbref *np, nref; /* * Global or local reference? Global references are automatically * * prepended with an additional underscore. i.e., #__foo_ is a global * * reference, and #_foo_ is a local reference. * * Our beginning and end underscores have already been stripped, so * * we would see only _foo or foo. * * * * We are not allowed to nibble our buffer, because we've got a * * pointer into the match string. Therefore we must copy it. * * If we're matching locally we copy the dbref of the owner first, * * which means that we then need to worry about buffer size. */ buf = alloc_lbuf("absolute_nref"); if (*str == '_') { for (p = buf, q = str; *q; p++, q++) { *p = tolower(*q); } *p = '\0'; } else { bp = buf; safe_ltos(buf, &bp, Owner(md.player), LBUF_SIZE); safe_chr('.', buf, &bp); for (q = str; *q; q++) { safe_chr(tolower(*q), buf, &bp); } *bp = '\0'; } np = (int *) hashfind(buf, &mudstate.nref_htab); if (np && Good_obj(*np)) { nref = *np; } else { nref = NOTHING; } free_lbuf(buf); return nref; }
int decode_power(dbref player, char *powername, POWERSET * pset) { POWERENT *pent; pset->word1 = 0; pset->word2 = 0; pent = (POWERENT *) hashfind(powername, &mudstate.powers_htab); if (!pent) { notify_check(player, player, MSG_PUP_ALWAYS | MSG_ME_ALL | MSG_F_DOWN, "%s: Power not found.", powername); return 0; } if (pent->powerpower & POWER_EXT) { pset->word2 = pent->powervalue; } else { pset->word1 = pent->powervalue; } return 1; }
/** Add new help command. This function is * the basis for the help_command directive in mush.cnf. It creates * a new help entry for the hash table, builds a help index, * and adds the new command to the command table. * \param command_name name of help command to add. * \param filename name of the help file to use for this command. * \param admin if 1, this command reads admin topics, rather than standard. */ void add_help_file(const char *command_name, const char *filename, int admin) { help_file *h; char newfilename[256] = "\0"; /* Must use a buffer for MacOS file path conversion */ strncpy(newfilename, filename, 256); if (help_init == 0) init_help_files(); if (!command_name || !filename || !*command_name || !*newfilename) return; /* If there's already an entry for it, complain */ h = hashfind(strupper(command_name), &help_files); if (h) { do_rawlog(LT_ERR, T("Duplicate help_command %s ignored."), command_name); return; } h = mush_malloc(sizeof *h, "help_file.entry"); h->command = mush_strdup(strupper(command_name), "help_file.command"); h->file = mush_strdup(newfilename, "help_file.filename"); h->entries = 0; h->indx = NULL; h->admin = admin; help_build_index(h, h->admin); if (!h->indx) { mush_free(h->command, "help_file.command"); mush_free(h->file, "help_file.filename"); mush_free(h, "help_file.entry"); return; } (void) command_add(h->command, CMD_T_ANY | CMD_T_NOPARSE, NULL, cmd_helpcmd, NULL); hashadd(h->command, h, &help_files); }
void vattr_delete( char *name ) { VATTR *vp; int number; fixcase( name ); if( !ok_attr_name( name ) ) { return; } number = 0; vp = ( VATTR * ) hashfind( name, &mudstate.vattr_name_htab ); if( vp ) { number = vp->number; anum_set( number, NULL ); hashdelete( name, &mudstate.vattr_name_htab ); XFREE( vp, "vattr_delete" ); } return; }
VATTR *vattr_rename( char *name, char *newname ) { VATTR *vp; fixcase( name ); if( !ok_attr_name( name ) ) { return ( NULL ); } /* * Be ruthless. */ if( strlen( newname ) >= VNAME_SIZE ) { newname[VNAME_SIZE - 1] = '\0'; } fixcase( newname ); if( !ok_attr_name( newname ) ) { return ( NULL ); } /* * We must explicitly delete and add the name to the hashtable, * * since we are changing the data. */ vp = ( VATTR * ) hashfind( name, &mudstate.vattr_name_htab ); if( vp ) { vp->name = store_string( newname ); hashdelete( name, &mudstate.vattr_name_htab ); hashadd( newname, ( int * ) vp, &mudstate.vattr_name_htab, 0 ); } return ( vp ); }
void exec(char *buff, char **bufc, int tflags, dbref player, dbref cause, int eval, char **dstr, char *cargs[], int ncargs) { #define NFARGS 30 char *fargs[NFARGS]; char *preserve[MAX_GLOBAL_REGS]; char *tstr, *tbuf, *tbufc, *savepos, *atr_gotten, *start, *oldp, *savestr; char savec, ch, *str; char *realbuff = NULL, *realbp = NULL; dbref aowner; int at_space, nfargs, gender, i, j, alldone, feval; long aflags; int is_trace, is_top, save_count; int ansi; FUN *fp; UFUN *ufp; static const char *subj[5] = { "", "it", "she", "he", "they" }; static const char *poss[5] = { "", "its", "her", "his", "their" }; static const char *obj[5] = { "", "it", "her", "him", "them" }; static const char *absp[5] = { "", "its", "hers", "his", "theirs" }; if(*dstr == NULL) return; // dprintk("%d/%s", player, *dstr); at_space = 1; gender = -1; alldone = 0; ansi = 0; is_trace = Trace(player) && !(eval & EV_NOTRACE); is_top = 0; /* Extend the buffer if we need to. */ if(((*bufc) - buff) > (LBUF_SIZE - SBUF_SIZE)) { realbuff = buff; realbp = *bufc; buff = (char *) malloc(LBUF_SIZE); *bufc = buff; } oldp = start = *bufc; /* * If we are tracing, save a copy of the starting buffer */ savestr = NULL; if(is_trace) { is_top = tcache_empty(); savestr = alloc_lbuf("exec.save"); StringCopy(savestr, *dstr); } while (**dstr && !alldone) { switch (**dstr) { case ' ': /* * A space. Add a space if not compressing or if * * * * * * * previous char was not a space */ if(!(mudconf.space_compress && at_space) || (eval & EV_NO_COMPRESS)) { safe_chr(' ', buff, bufc); at_space = 1; } break; case '\\': /* * General escape. Add the following char without * * * * * special processing */ at_space = 0; (*dstr)++; if(**dstr) safe_chr(**dstr, buff, bufc); else (*dstr)--; break; case '[': /* * Function start. Evaluate the contents of the * * * * * square brackets as a function. If no closing * * * * * bracket, insert the [ and continue. */ at_space = 0; tstr = (*dstr)++; if(eval & EV_NOFCHECK) { safe_chr('[', buff, bufc); *dstr = tstr; break; } tbuf = parse_to(dstr, ']', 0); if(*dstr == NULL) { safe_chr('[', buff, bufc); *dstr = tstr; } else { str = tbuf; exec(buff, bufc, 0, player, cause, (eval | EV_FCHECK | EV_FMAND), &str, cargs, ncargs); (*dstr)--; } break; case '{': /* * Literal start. Insert everything up to the * * * * * terminating } without parsing. If no closing * * * * * brace, insert the { and continue. */ at_space = 0; tstr = (*dstr)++; tbuf = parse_to(dstr, '}', 0); if(*dstr == NULL) { safe_chr('{', buff, bufc); *dstr = tstr; } else { if(!(eval & EV_STRIP)) { safe_chr('{', buff, bufc); } /* * Preserve leading spaces (Felan) */ if(*tbuf == ' ') { safe_chr(' ', buff, bufc); tbuf++; } str = tbuf; exec(buff, bufc, 0, player, cause, (eval & ~(EV_STRIP | EV_FCHECK)), &str, cargs, ncargs); if(!(eval & EV_STRIP)) { safe_chr('}', buff, bufc); } (*dstr)--; } break; case '%': /* * Percent-replace start. Evaluate the chars * * * * following * and perform the appropriate * * * * substitution. */ at_space = 0; (*dstr)++; savec = **dstr; savepos = *bufc; switch (savec) { case '\0': /* * Null - all done */ (*dstr)--; break; case '|': /* piped command output */ safe_str(mudstate.pout, buff, bufc); break; case '%': /* * Percent - a literal % */ safe_chr('%', buff, bufc); break; case 'c': case 'C': (*dstr)++; if(!**dstr) (*dstr)--; ansi = 1; switch (**dstr) { case 'h': /* * hilite */ safe_str(ANSI_HILITE, buff, bufc); break; case 'i': /* * inverse */ safe_str(ANSI_INVERSE, buff, bufc); break; case 'f': /* * flash */ safe_str(ANSI_BLINK, buff, bufc); break; case 'u': /* underline */ safe_str(ANSI_UNDER, buff, bufc); break; case 'n': /* * normal */ safe_str(ANSI_NORMAL, buff, bufc); ansi = 0; break; case 'x': /* * black fg */ safe_str(ANSI_BLACK, buff, bufc); break; case 'r': /* * red fg */ safe_str(ANSI_RED, buff, bufc); break; case 'g': /* * green fg */ safe_str(ANSI_GREEN, buff, bufc); break; case 'y': /* * yellow fg */ safe_str(ANSI_YELLOW, buff, bufc); break; case 'b': /* * blue fg */ safe_str(ANSI_BLUE, buff, bufc); break; case 'm': /* * magenta fg */ safe_str(ANSI_MAGENTA, buff, bufc); break; case 'c': /* * cyan fg */ safe_str(ANSI_CYAN, buff, bufc); break; case 'w': /* * white fg */ safe_str(ANSI_WHITE, buff, bufc); break; case 'X': /* * black bg */ safe_str(ANSI_BBLACK, buff, bufc); break; case 'R': /* * red bg */ safe_str(ANSI_BRED, buff, bufc); break; case 'G': /* * green bg */ safe_str(ANSI_BGREEN, buff, bufc); break; case 'Y': /* * yellow bg */ safe_str(ANSI_BYELLOW, buff, bufc); break; case 'B': /* * blue bg */ safe_str(ANSI_BBLUE, buff, bufc); break; case 'M': /* * magenta bg */ safe_str(ANSI_BMAGENTA, buff, bufc); break; case 'C': /* * cyan bg */ safe_str(ANSI_BCYAN, buff, bufc); break; case 'W': /* * white bg */ safe_str(ANSI_BWHITE, buff, bufc); break; default: safe_chr(**dstr, buff, bufc); } break; case 'r': /* * Carriage return */ case 'R': safe_str((char *) "\r\n", buff, bufc); break; case 't': /* * Tab */ case 'T': safe_chr('\t', buff, bufc); break; case 'B': /* * Blank */ case 'b': safe_chr(' ', buff, bufc); break; case '0': /* * Command argument number N */ case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': i = (**dstr - '0'); if((i < ncargs) && (cargs[i] != NULL)) safe_str(cargs[i], buff, bufc); break; case 'V': /* * Variable attribute */ case 'v': (*dstr)++; ch = ToUpper(**dstr); if(!**dstr) (*dstr)--; if((ch < 'A') || (ch > 'Z')) break; i = 100 + ch - 'A'; atr_gotten = atr_pget(player, i, &aowner, &aflags); safe_str(atr_gotten, buff, bufc); free_lbuf(atr_gotten); break; case 'Q': case 'q': (*dstr)++; i = (**dstr - '0'); if((i >= 0) && (i <= 9) && mudstate.global_regs[i]) { safe_str(mudstate.global_regs[i], buff, bufc); } if(!**dstr) (*dstr)--; break; case 'O': /* * Objective pronoun */ case 'o': if(gender < 0) gender = get_gender(cause); if(!gender) tbuf = Name(cause); else tbuf = (char *) obj[gender]; safe_str(tbuf, buff, bufc); break; case 'P': /* * Personal pronoun */ case 'p': if(gender < 0) gender = get_gender(cause); if(!gender) { safe_str(Name(cause), buff, bufc); safe_chr('s', buff, bufc); } else { safe_str((char *) poss[gender], buff, bufc); } break; case 'S': /* * Subjective pronoun */ case 's': if(gender < 0) gender = get_gender(cause); if(!gender) tbuf = Name(cause); else tbuf = (char *) subj[gender]; safe_str(tbuf, buff, bufc); break; case 'A': /* * Absolute posessive */ case 'a': /* * idea from Empedocles */ if(gender < 0) gender = get_gender(cause); if(!gender) { safe_str(Name(cause), buff, bufc); safe_chr('s', buff, bufc); } else { safe_str((char *) absp[gender], buff, bufc); } break; case '#': /* * Invoker DB number */ tbuf = alloc_sbuf("exec.invoker"); sprintf(tbuf, "#%ld", cause); safe_str(tbuf, buff, bufc); free_sbuf(tbuf); break; case '!': /* * Executor DB number */ tbuf = alloc_sbuf("exec.executor"); sprintf(tbuf, "#%ld", player); safe_str(tbuf, buff, bufc); free_sbuf(tbuf); break; case 'N': /* * Invoker name */ case 'n': safe_str(Name(cause), buff, bufc); break; case 'L': /* * Invoker location db# */ case 'l': if(!(eval & EV_NO_LOCATION)) { tbuf = alloc_sbuf("exec.exloc"); sprintf(tbuf, "#%ld", where_is(cause)); safe_str(tbuf, buff, bufc); free_sbuf(tbuf); } break; default: /* * Just copy */ safe_chr(**dstr, buff, bufc); } if(isupper(savec)) *savepos = ToUpper(*savepos); break; case '(': /* * Arglist start. See if what precedes is a function. If so, * execute it if we should. */ at_space = 0; if(!(eval & EV_FCHECK)) { safe_chr('(', buff, bufc); break; } /* * Load an sbuf with an uppercase version of the func name, and * see if the func exists. Trim trailing spaces from the name * if configured. */ **bufc = '\0'; tbufc = tbuf = alloc_sbuf("exec.tbuf"); safe_sb_str(oldp, tbuf, &tbufc); *tbufc = '\0'; if(mudconf.space_compress) { while ((--tbufc >= tbuf) && isspace(*tbufc)); tbufc++; *tbufc = '\0'; } for(tbufc = tbuf; *tbufc; tbufc++) *tbufc = ToLower(*tbufc); fp = (FUN *) hashfind(tbuf, &mudstate.func_htab); /* * If not a builtin func, check for global func */ ufp = NULL; if(fp == NULL) { ufp = (UFUN *) hashfind(tbuf, &mudstate.ufunc_htab); } /* * Do the right thing if it doesn't exist */ if(!fp && !ufp) { if(eval & EV_FMAND) { *bufc = oldp; safe_str((char *) "#-1 FUNCTION (", buff, bufc); safe_str(tbuf, buff, bufc); safe_str((char *) ") NOT FOUND", buff, bufc); alldone = 1; } else { safe_chr('(', buff, bufc); } free_sbuf(tbuf); eval &= ~EV_FCHECK; break; } free_sbuf(tbuf); /* * Get the arglist and count the number of args * Neg * * * * * * * # of args means catenate subsequent * args */ if(ufp) nfargs = NFARGS; else if(fp->nargs < 0) nfargs = -fp->nargs; else nfargs = NFARGS; tstr = *dstr; if(fp && (fp->flags & FN_NO_EVAL)) feval = (eval & ~EV_EVAL) | EV_STRIP_ESC; else feval = eval; *dstr = parse_arglist(player, cause, *dstr + 1, ')', feval, fargs, nfargs, cargs, ncargs); /* * If no closing delim, just insert the '(' and * * * * * * continue normally */ if(!*dstr) { *dstr = tstr; safe_chr(**dstr, buff, bufc); for(i = 0; i < nfargs; i++) if(fargs[i] != NULL) free_lbuf(fargs[i]); eval &= ~EV_FCHECK; break; } /* * Count number of args returned */ (*dstr)--; j = 0; for(i = 0; i < nfargs; i++) if(fargs[i] != NULL) j = i + 1; nfargs = j; /* * If it's a user-defined function, perform it now. */ if(ufp) { mudstate.func_nest_lev++; if(!check_access(player, ufp->perms)) { safe_str("#-1 PERMISSION DENIED", buff, &oldp); *bufc = oldp; } else { tstr = atr_get(ufp->obj, ufp->atr, &aowner, &aflags); if(ufp->flags & FN_PRIV) i = ufp->obj; else i = player; str = tstr; if(ufp->flags & FN_PRES) { for(j = 0; j < MAX_GLOBAL_REGS; j++) { if(!mudstate.global_regs[j]) preserve[j] = NULL; else { preserve[j] = alloc_lbuf("eval_regs"); StringCopy(preserve[j], mudstate.global_regs[j]); } } } exec(buff, &oldp, 0, i, cause, feval, &str, fargs, nfargs); *bufc = oldp; if(ufp->flags & FN_PRES) { for(j = 0; j < MAX_GLOBAL_REGS; j++) { if(preserve[j]) { if(!mudstate.global_regs[j]) mudstate.global_regs[j] = alloc_lbuf("eval_regs"); StringCopy(mudstate.global_regs[j], preserve[j]); free_lbuf(preserve[j]); } else { if(mudstate.global_regs[j]) *(mudstate.global_regs[i]) = '\0'; } } } free_lbuf(tstr); } /* * Return the space allocated for the args */ mudstate.func_nest_lev--; for(i = 0; i < nfargs; i++) if(fargs[i] != NULL) free_lbuf(fargs[i]); eval &= ~EV_FCHECK; break; } /* * If the number of args is right, perform the func. * Otherwise return an error message. Note * that parse_arglist returns zero args as one * null arg, so we have to handle that case * specially. */ if((fp->nargs == 0) && (nfargs == 1)) { if(!*fargs[0]) { free_lbuf(fargs[0]); fargs[0] = NULL; nfargs = 0; } } if((nfargs == fp->nargs) || (nfargs == -fp->nargs) || (fp->flags & FN_VARARGS)) { /* * Check recursion limit */ mudstate.func_nest_lev++; mudstate.func_invk_ctr++; if(mudstate.func_nest_lev >= mudconf.func_nest_lim) { safe_str("#-1 FUNCTION RECURSION LIMIT EXCEEDED", buff, bufc); } else if(mudstate.func_invk_ctr == mudconf.func_invk_lim) { safe_str("#-1 FUNCTION INVOCATION LIMIT EXCEEDED", buff, bufc); } else if(!check_access(player, fp->perms)) { safe_str("#-1 PERMISSION DENIED", buff, &oldp); *bufc = oldp; } else if(mudstate.func_invk_ctr < mudconf.func_invk_lim) { fp->fun(buff, &oldp, player, cause, fargs, nfargs, cargs, ncargs); *bufc = oldp; } else { **bufc = '\0'; } mudstate.func_nest_lev--; } else { *bufc = oldp; tstr = alloc_sbuf("exec.funcargs"); sprintf(tstr, "%d", fp->nargs); safe_str((char *) "#-1 FUNCTION (", buff, bufc); safe_str((char *) fp->name, buff, bufc); safe_str((char *) ") EXPECTS ", buff, bufc); safe_str(tstr, buff, bufc); safe_str((char *) " ARGUMENTS", buff, bufc); free_sbuf(tstr); } /* * Return the space allocated for the arguments */ for(i = 0; i < nfargs; i++) if(fargs[i] != NULL) free_lbuf(fargs[i]); eval &= ~EV_FCHECK; break; default: /* * A mundane character. Just copy it */ at_space = 0; safe_chr(**dstr, buff, bufc); } (*dstr)++; } /* * If we're eating spaces, and the last thing was a space, eat it * up. Complicated by the fact that at_space is initially * true. So check to see if we actually put something in the * buffer, too. */ if(mudconf.space_compress && at_space && !(eval & EV_NO_COMPRESS) && (start != *bufc)) (*bufc)--; /* * The ansi() function knows how to take care of itself. However, * if the player used a %c sub in the string, and hasn't yet * terminated the color with a %cn yet, we'll have to do it for * them. */ if(ansi == 1) safe_str(ANSI_NORMAL, buff, bufc); **bufc = '\0'; /* * Report trace information */ if(realbuff) { **bufc = '\0'; *bufc = realbp; safe_str(buff, realbuff, bufc); free(buff); buff = realbuff; } if(is_trace) { tcache_add(savestr, start); save_count = tcache_count - mudconf.trace_limit;; if(is_top || !mudconf.trace_topdown) tcache_finish(player); if(is_top && (save_count > 0)) { tbuf = alloc_mbuf("exec.trace_diag"); sprintf(tbuf, "%d lines of trace output discarded.", save_count); notify(player, tbuf); free_mbuf(tbuf); } } }
int cf_flag_name( int *vp, char *str, long extra, dbref player, char *cmd ) { char *numstr, *namestr, *tokst; FLAGENT *fp; int flagnum = -1; char *flagstr, *cp; numstr = strtok_r( str, " \t=,", &tokst ); namestr = strtok_r( NULL, " \t=,", &tokst ); if( numstr && ( strlen( numstr ) == 1 ) ) { flagnum = ( int ) strtol( numstr, ( char ** ) NULL, 10 ); } if( ( flagnum < 0 ) || ( flagnum > 9 ) ) { cf_log_notfound( player, cmd, "Not a marker flag", numstr ); return -1; } if( ( fp = letter_to_flag( *numstr ) ) == NULL ) { cf_log_notfound( player, cmd, "Marker flag", numstr ); return -1; } /* * Our conditions: The flag name MUST start with an underscore. It * must not conflict with the name of any existing flag. There is a * KNOWN MEMORY LEAK here -- if you name the flag and rename it * later, the old bit of memory for the name won't get freed. This * should pretty much never happen, since you're not going to run * around arbitrarily giving your flags new names all the time. */ flagstr = xstrprintf( "cf_flag_name", "_%s", namestr ); if( strlen( flagstr ) > 31 ) { cf_log_syntax( player, cmd, "Marker flag name too long: %s", namestr ); XFREE( flagstr, "cf_flag_name" ); } for( cp = flagstr; cp && *cp; cp++ ) { if( !isalnum( *cp ) && ( *cp != '_' ) ) { cf_log_syntax( player, cmd, "Illegal marker flag name: %s", namestr ); XFREE( flagstr, "cf_flag_name" ); return -1; } *cp = tolower( *cp ); } if( hashfind( flagstr, &mudstate.flags_htab ) ) { XFREE( flagstr, "cf_flag_name" ); cf_log_syntax( player, cmd, "Marker flag name in use: %s", namestr ); return -1; } for( cp = flagstr; cp && *cp; cp++ ) { *cp = toupper( *cp ); } fp->flagname = ( const char * ) flagstr; hashadd( ( char * ) fp->flagname, ( int * ) fp, &mudstate.flags_htab, 0 ); return 0; }
VATTR *vattr_find( char *name ) { return ( VATTR * ) hashfind( name, &mudstate.vattr_name_htab ); }
void process_data(Logfile *logfilep, Hashtable **hash, Arraydata **arraydata, choice *count, choice *code2type, choice datacols[ITEM_NUMBER][OUTCOME_NUMBER][DATACOLS_NUMBER][2], choice data2cols[ITEM_NUMBER][DATA_NUMBER], unsigned int *no_cols, Include **wanthead, Include *ispagehead, Alias **aliashead, Include *argshead, Include *refargshead, Dateman *dman, Tree **tree, Derv **derv, choice *alltrees, choice *alldervs, choice *lowmem, logical case_insensitive, logical usercase_insensitive, unsigned char convfloor, logical multibyte, char *dirsuffix, unsigned int dirsufflength, unsigned int granularity) { extern unsigned int year, month, date, hour, minute, code; extern unsigned long unixtime, proctime; extern char am; extern double bytes; extern Memman mm[], mmq, mms, *amemman; extern choice *rep2type; extern Hashentry *unwanted_entry, *blank_entry; extern Hashindex *dummy_item; static Hashindex *gp[ITEM_NUMBER]; unsigned long data[DATA2_NUMBER]; Hashentry *item[ITEM_NUMBER]; logical wanttree[ITEM_NUMBER]; logical isitpage, last7; choice ispage = UNSET; choice wanted = TRUE, rc, outcome; timecode_t timecode = FIRST_TIME; char *name, *namestart, *nameend; size_t len; choice i, j, k; /*** check whether this line is wanted ***/ if (count[INP_CODE] != 0) { if (code == IGNORE_CODE) { for (j = 0; j < ITEM_NUMBER; j++) { /* reset strings */ if (count[j] != 0) mm[j].next_pos = mm[j].curr_pos; } mmq.next_pos = mmq.curr_pos; mms.next_pos = mms.curr_pos; logfilep->data[LOGDATA_UNKNOWN]++; return; } else if (code2type[code] == UNWANTED) wanted = FALSE; } if (wanted && count[INP_DATE] > 0) { if (count[INP_UNIXTIME]) wanted = wantunixtime(&timecode, dman, unixtime, logfilep->tz); else { if (count[INP_AM]) { if (hour > 12) { corrupt_line(logfilep, "Hour greater than 12", -1); return; } else if (hour == 12) hour = 0; if (am == 'p') hour += 12; } wanted = wantdate(&timecode, dman, hour, minute, date, month, year, logfilep->tz); } if (wanted == ERR) { /* corrupt date */ corrupt_line(logfilep, "Corrupt date or time", -1); return; } } /* end count[INP_DATE] > 0 */ for (i = 0; i < ITEM_NUMBER; i++) { wanttree[i] = FALSE; if (!wanted) { for (j = i; j < ITEM_NUMBER; j++) { /* reset not-yet-hashed strings */ if (count[j] != 0) /* NB i is now (unwanted i) + 1 */ mm[j].next_pos = mm[j].curr_pos; } mmq.next_pos = mmq.curr_pos; mms.next_pos = mms.curr_pos; logfilep->data[LOGDATA_UNWANTED]++; return; } if (i == ITEM_HOST) prealiasS(&(mm[ITEM_HOST]), &mms); name = (char *)(mm[i].curr_pos); if (count[i] == 0 || IS_EMPTY_STRING(name) || (name[0] == '-' && name[1] == '\0')) { item[i] = blank_entry; /* or unwanted_; but we get wanted right anyway */ wanted = (wanthead[i] == NULL || included("", FALSE, wanthead[i])); /* wanthead[i] == NULL is tested again in included() but it often saves a call to that function, because blankness is common. */ } else { if (i == ITEM_FILE || i == ITEM_REFERRER) { if ((j = prealias(&(mm[i]), &(mm[ITEM_VHOST]), item[ITEM_VHOST], &mmq, (logical)((i == ITEM_FILE)?case_insensitive:FALSE), (i == ITEM_FILE)?(logfilep->prefix):NULL, logfilep->prefixlen, logfilep->pvpos, (i == ITEM_FILE)?argshead:refargshead)) < 0) { if (j == -1) corrupt_line(logfilep, "%v in file prefix but no VHOST in line", -1); else corrupt_line(logfilep, "Filename too long", -1); return; } } if (lowmem[i] == 0) { if (gp[i] == NULL || !STREQ(name, gp[i]->name)) { gp[i] = hashfind(&mm[i], &(hash[i]), no_cols[i], wanthead[i], UNSET, ispagehead, aliashead[i], dirsuffix, dirsufflength, usercase_insensitive, 0, FALSE, i, FALSE); } /* if name the same as last time, don't need */ else /* to hashfind again, or save the name */ mm[i].next_pos = mm[i].curr_pos; item[i] = (Hashentry *)(gp[i]->other); wanted = (choice)(ENTRY_WANTED(item[i])); } else if (lowmem[i] == 1) { if ((rc = do_alias(name, amemman, aliashead[i], dirsuffix, dirsufflength, usercase_insensitive, 0, FALSE, i)) == FALSE) { item[i] = hashfind(&mm[i], &(hash[i]), no_cols[i], wanthead[i], UNSET, ispagehead, NULL, dirsuffix, dirsufflength, usercase_insensitive, 0, FALSE, i, TRUE)->own; } else if (rc == TRUE) { mm[i].next_pos = mm[i].curr_pos; /* don't save string */ item[i] = hashfind(amemman, &(hash[i]), no_cols[i], wanthead[i], UNSET, ispagehead, NULL, dirsuffix, dirsufflength, usercase_insensitive, 0, FALSE, i, TRUE)->own; } else { /* rc == ERR */ mm[i].next_pos = mm[i].curr_pos; if (included("", FALSE, wanthead[i])) item[i] = blank_entry; else item[i] = unwanted_entry; } wanted = (choice)(ENTRY_WANTED(item[i])); } else { /* lowmem[i] >= 2 */ if ((rc = do_alias(name, amemman, aliashead[i], dirsuffix, dirsufflength, usercase_insensitive, 0, FALSE, i)) == TRUE) { mm[i].next_pos = mm[i].curr_pos; /* don't save old string */ len = strlen((char *)(amemman->curr_pos)); memcpy(submalloc(&(mm[i]), len + 1), amemman->curr_pos, len + 1); name = (char *)(mm[i].curr_pos); /* which might have changed */ amemman->next_pos = amemman->curr_pos; } if (rc == ERR) { if (included("", FALSE, wanthead[i])) { item[i] = blank_entry; if (i == ITEM_FILE) ispage = FALSE; } else wanted = FALSE; mm[i].next_pos = mm[i].curr_pos; } else { isitpage = pageq(name, ispagehead, i); if (i == ITEM_FILE) ispage = (choice)isitpage; if (included(name, isitpage, wanthead[i])) { if (lowmem[i] == 2) { item[i] = hashfind(&(mm[i]), &(hash[i]), no_cols[i], wanthead[i], isitpage, ispagehead, NULL, dirsuffix, dirsufflength, usercase_insensitive, 0, FALSE, i, TRUE)->own; } else { item[i] = blank_entry; wanttree[i] = TRUE; mm[i].next_pos = mm[i].curr_pos; } } else { wanted = FALSE; mm[i].next_pos = mm[i].curr_pos; } } } /* end lowmem[i] >= 2 */ } } /* end for i */ if (!wanted) { logfilep->data[LOGDATA_UNWANTED]++; return; } /*** now add it to the hash tables ***/ /* add to logfile from and to if wanted, whatever status code */ if (timecode != FIRST_TIME) logfilep->from = MIN(logfilep->from, timecode); logfilep->to = MAX(logfilep->to, timecode); last7 = (timecode > dman->last7from && timecode <= dman->last7to); if (ispage == UNSET) /* NB blank_entry has ispage FALSE */ ispage = (choice)(item[ITEM_FILE]->ispage); if (count[INP_BYTES] == 0) bytes = 0; if (count[INP_CODE] == 0) { outcome = SUCCESS; if (count[ITEM_FILE] == 2) { logfilep->data[LOGDATA_SUCC]++; logfilep->data[LOGDATA_SUCC7] += (unsigned long)last7; logfilep->data[LOGDATA_PAGES] += (unsigned long)ispage; logfilep->data[LOGDATA_PAGES7] += (unsigned long)((logical)ispage && last7); } else { logfilep->data[LOGDATA_UNKNOWN]++; logfilep->data[LOGDATA_UNKNOWN7] += (unsigned long)last7; } } else if (code <= 199) { outcome = INFO; logfilep->data[LOGDATA_INFO]++; logfilep->data[LOGDATA_INFO7] += (unsigned long)last7; } else switch (outcome = code2type[code]) { case SUCCESS: logfilep->data[LOGDATA_SUCC]++; logfilep->data[LOGDATA_SUCC7] += (unsigned long)last7; logfilep->data[LOGDATA_PAGES] += (unsigned long)ispage; logfilep->data[LOGDATA_PAGES7] += (unsigned long)((logical)ispage && last7); break; case FAILURE: logfilep->data[LOGDATA_FAIL]++; logfilep->data[LOGDATA_FAIL7] += (unsigned long)last7; break; case REDIRECT: logfilep->data[LOGDATA_REDIR]++; logfilep->data[LOGDATA_REDIR7] += (unsigned long)last7; break; case INFO: logfilep->data[LOGDATA_INFO]++; logfilep->data[LOGDATA_INFO7] += (unsigned long)last7; break; } /* NB any change in what to count when will require corresponding change to end of strtoinfmt() and to fmt munching in correct() */ if (count[INP_CODE] == 2) arrayscore(arraydata[REP_CODE - FIRST_ARRAYREP], code, 1, (unsigned long)last7, 0, 0, 0., 0., timecode); if (outcome != INFO) { if (outcome == SUCCESS) { if (count[INP_DATE] == 2) /* only if file present: see strtoinfmt() */ datehash(timecode, dman, 1, (unsigned long)ispage, bytes, granularity); if (count[INP_BYTES] == 2) { arrayscore(arraydata[REP_SIZE - FIRST_ARRAYREP], bytes, 1, (unsigned long)last7, (unsigned long)ispage, (unsigned long)((logical)ispage && last7), bytes, last7?bytes:0., timecode); logfilep->bytes += bytes; if (last7) logfilep->bytes7 += bytes; } if (count[INP_PROCTIME] == 2) arrayscore(arraydata[REP_PROCTIME - FIRST_ARRAYREP], proctime, 1, (unsigned long)last7, (unsigned long)ispage, (unsigned long)((logical)ispage && last7), bytes, last7?bytes:0., timecode); if (alltrees[0] != REP_NUMBER || alldervs[0] != REP_NUMBER) { /* for LOWMEM 3, run through alltrees then alldervs */ /* NB these (POSSTREE/POSSDERV in init.c) only count successes */ for (k = 0; k <= 1; k++) { for (i = 0; (k?(alldervs[i]):(alltrees[i])) != REP_NUMBER; i++) { j = rep2type[k?(alldervs[i]):(alltrees[i])]; if (wanttree[j]) { dummy_item->name = mm[j].curr_pos; /* mm.curr_pos is marked for deletion, but still intact at present */ dummy_item->own->data[data2cols[j][REQUESTS]] = 1; if (data2cols[j][REQUESTS7] >= 0) /* see comment in genrep() */ dummy_item->own->data[data2cols[j][REQUESTS7]] = (unsigned long)last7; if (data2cols[j][PAGES] >= 0) dummy_item->own->data[data2cols[j][PAGES]] = (unsigned long)ispage; if (data2cols[j][PAGES7] >= 0) dummy_item->own->data[data2cols[j][PAGES7]] = (unsigned long)((logical)ispage && last7); if (data2cols[j][SUCCDATE] >= 0) dummy_item->own->data[data2cols[j][SUCCDATE]] = timecode; if (data2cols[j][SUCCFIRSTD] >= 0) dummy_item->own->data[data2cols[j][SUCCFIRSTD]] = timecode; dummy_item->own->bytes = bytes; dummy_item->own->bytes7 = last7?bytes:0.; if (k) makederived(derv[alldervs[i] - FIRST_DERVREP], dummy_item, NULL, convfloor, multibyte, alldervs[i], datacols[j], no_cols[j]); else { namestart = NULL; tree[G(alltrees[i])]->cutfn(&namestart, &nameend, dummy_item->name, FALSE); (void)treefind(namestart, nameend, &(tree[G(alltrees[i])]->tree), dummy_item, tree[G(alltrees[i])]->cutfn, FALSE, TRUE, FALSE, tree[G(alltrees[i])]->space, datacols[j], no_cols[j]); } } } } } /* there are trees or dervs */ } /* outcome == SUCCESS */ data[REQUESTS2] = 1; data[REQUESTS72] = (unsigned long)last7; data[PAGES2] = (unsigned long)ispage; data[PAGES72] = (unsigned long)((logical)ispage && last7); data[DATE2] = timecode; data[FIRSTD2] = timecode; for (i = 0; i < ITEM_NUMBER; i++) { if (count[i] == 2 && !ENTRY_BLANK(item[i])) hashscore(item[i], data, datacols[i][outcome], outcome, bytes); } } /* end if outcome != INFO */ }
/** Return the proper entry from lock_types, or NULL. * \param type of lock to look up. * \return lock_types entry for lock. */ const lock_list * get_lockproto(lock_type type) { return hashfind(strupper(type), &htab_locks); }