/* walkdb.c */ #include "copyright.h" /* Support for commands which trudge up 'n down the database like @find, @fnd and @stat. */ #ifdef WANT_ANSI #ifdef __STDC__ #include <stddef.h> #endif /* __STDC__ */ #endif /* WANT_ANSI */ #include <ctype.h> #include "mudconf.h" #include "config.h" #include "db.h" #include "interface.h" #include "match.h" #include "externs.h" #include "command.h" #include "flags.h" #include "misc.h" /* Bind occurances of the universal var in ACTION to ARG, then run ACTION. Cmds run in low-prio Q after a 1 sec delay for the first one. */ static void bind_and_queue (dbref player, dbref cause, char *action, char *argstr, char *cargs[], int ncargs) { char *command; /* allocated by replace_string */ command = replace_string (BOUND_VAR, argstr, action), wait_que (player, cause, RU_ARG1_TAKE, 0, NOTHING, command, cargs, ncargs); } #ifdef notdef /*************************************************************************/ /* Option-ish Schtuff */ /*************************************************************************/ #define FND_HELPFILE "@fnd_helpfile" /* These two statements define the operator tokens. They MUST be sorted longest first, so the longer ops will still match if they contain a shorter op in their beginning. */ typedef enum { WILDNEQ, WILDEQ, STRNEQ, STREQ, ERR } op_t; static const char *Ops[] = { "!==", "==", "!=", "=", NULL }; /* union of all op chars, above */ #define OP_CHARS "=!" /*************************************************************************/ /* End of Option-ish Schtuff */ /*************************************************************************/ /* struct used to remember each word in query after parsing */ typedef struct { char *left, *right; op_t op; } findit; extern void abort (); extern int atoi (); extern dbref match_thing (dbref player, const char *name); extern char **string2list (char *str, const char sep); static void fnd_parse_word (char *word, findit * out) { int where, len, wherelen, i; if (!word || *word == '\0' || ((len = strlen (word)) == (where = strcspn (word, OP_CHARS)))) out->op = ERR; else { wherelen = strspn (word + where, OP_CHARS); for (i = 0; Ops[i]; i++) if (!strncmp (Ops[i], word + where, strlen (Ops[i]))) break; out->op = i; if (i != ERR) { out->left = word; *(word + where) = '\0'; out->right = word + where + wherelen; } } } /* * Returns number of non-null ptrs in array thereof */ static int count_ptrs (const void **p) { int out = 0; if (p) while (*p++) out++; return out; } #define FNDUSAGE(x) if(1) { notify(player,x);\ spit_file(player, FND_HELPFILE);\ goto byebye; } #define MALLOCTST(x) if(!x) { perror("Bad malloc in do_fnd. No mem?");\ return; } #define FNDMALLOC(x,y,z) if(!((x) = XMALLOC (y, z)))\ { perror("Bad malloc in do_fnd. No mem?");\ return; } #define HELP " " #define ATTRIB "Bad @fnd attribute/value syntax." #define OPTION "Bad @fnd `-' option syntax." #define CONFUSED "I don't think this does what you think it does." /*#define FND_DEBUG*/ /* Command: @fnd - More like the unix find. * Created: Tue Dec 18 20:33:20 1990 mitch@alpha.ces.cwru.edu * Usage: @fnd */ /**** Trial new version (old one below) ****/ void do_fnd (dbref player, const char *in_cmd) { extern char *optarg; extern int optind, opterr, getopt (int, char **, const char *); int c, argc, nquery; /* argc:how many words */ char *command; /* my copy of in_cmd */ char **argv; /* pntrs to words in cmd */ char *buff; /* temporary buffer */ dbref i; /* for walking dbase */ findit *queries = NULL; /* array of attribute/operation structs */ /* Option vars and their defaults:: Set according to user input. */ int debug = 0; /* no debug mode by default */ int quiet = 0; /* print output by default */ char *execstr = NULL; /* execute this string on each hit */ opterr = 0; /* tell getopt: no error message */ optind = 1; /* tell getopt: start on second arg */ if (!in_cmd || *in_cmd == '\0') { notify (player, "Sorry, internal error."); return; } if (!payfor (player, mudconf.searchcost)) { notify (player, tprintf("You don't have enough %s.", mudconf.many_coins)); return; } /* * Copy because s2l will modify it. This may not really be needed. */ FNDMALLOC (command, sizeof (char *) * strlen (in_cmd) +1, "do_fnd"); argv = string2list (strcpy (command, in_cmd), ' '); argc = count_ptrs ((const void **) argv); if (argc <= 1) FNDUSAGE (CONFUSED); #ifdef FND_DEBUG for (i = 0; i < argc; i++) { buff=alloc_lbuf("do_fnd.debug.1"); sprintf (buff, "FND-DEBUG:arg %d=`%s'", i, argv[i]); fputs (buff, stderr); notify (player, buff); free_lbuf(buff); } #endif while ((c = getopt (argc, argv, "qhdx:")) != EOF) switch (c) { case 'x': execstr = optarg; break; case 'h': /* help */ FNDUSAGE (HELP); case 'q': /* quiet */ quiet = 1; break; case 'd': /* debug */ debug = 1; break; case '?': /* huh? */ FNDUSAGE (OPTION); } /* Check the non-option parameters. If any have no '=' in them, complain. Otherwise, treat as an ATTR=VALUE pair to look for */ FNDMALLOC (buff, sizeof (findit) * (argc - optind + 1), "do_fnd.2"); queries = (findit *)buff; for (nquery = 0; optind < argc; optind++, nquery++) { fnd_parse_word (argv[optind], &queries[nquery]); if (queries[nquery].op == ERR) FNDUSAGE (ATTRIB); } if (debug) { buff=alloc_lbuf("do_fnd.debug.2"); sprintf (buff, "fnd debug:quiet=%d execstr=`%s' nquery=%d", quiet, execstr, nquery); notify (player, buff); for (i = 0; i < nquery; i++) { sprintf (buff, "op=%d left=`%s' right=`%s'", queries[i].op, queries[i].left, queries[i].right); notify (player, buff); } free_lbuf(buff); } else { #if 0 /* We know the options, let's do the db walk */ DO_WHOLE_DB(i) { if (!controls (player, i)) continue; if (!quiet) { buff = unparse_object (player, i); notify (player, buff); free_lbuf(buff); } if (execstr && !(Flags (i) & GOING)) /* bind_and_queue (player, player, execstr, i, NULL, 0); */ /*2nd player==cause */ } #endif if (!quiet) notify (player, "*** @fnd: End of List ***"); } byebye: XFREE (command, "do_fnd"); XFREE (queries, "do_fnd.2"); /* TO DO: walk this, to free each one. */ } /* end of do_fnd */ #endif /* notdef */ /* New @dolist. i.e.: * @dolist #12 #34 #45 #123 #34644=@emit [name(##)] */ void do_dolist (dbref player, dbref cause, int key, char *list, char *command, char *cargs[], int ncargs) { char *curr, *objstring; if (!list || *list == '\0') { notify (player, "That's terrific, but what should I do with the list?"); return; } curr = list; while (curr && *curr) { while (*curr==' ') curr++; if (*curr) { objstring = parse_to(&curr, ' ', EV_STRIP); bind_and_queue (player, cause, command, objstring, cargs, ncargs); } } } /* Regular @find command */ void do_find (dbref player, dbref cause, int key, char *name) { dbref i; char *buff; if (!payfor (player, mudconf.searchcost)) { notify (player, tprintf("You don't have enough %s.",mudconf.many_coins)); } else { DO_WHOLE_DB(i) { if ((i % 100) == 0) { tmp_sync(); cache_reset(); } if (Typeof (i) != TYPE_EXIT && controls (player, i) && (!*name || string_match (Name (i), name))) { buff = unparse_object (player, i); notify (player, buff); free_lbuf(buff); } } notify (player, "***End of List***"); } } /* --------------------------------------------------------------------------- * get_stats, do_stats: Get counts of items in the db. */ int get_stats (dbref player, dbref who, STATS *info) { dbref i; info->s_total = 0; info->s_rooms = 0; info->s_exits = 0; info->s_things = 0; info->s_players = 0; info->s_garbage = 0; /* Do we have permission? */ if (Good_obj(who) && !Controls(player, who)) { notify(player, "Permission denied."); return 0; } /* Can we afford it? */ if (!payfor (player, mudconf.searchcost)) { notify (player, tprintf("You don't have enough %s.", mudconf.many_coins)); return 0; } DO_WHOLE_DB(i) { if ((who == NOTHING) || (who == Owner (i))) { info->s_total++; if ((Flags (i) & GOING) && (Typeof(i) != TYPE_ROOM)) { info->s_garbage++; continue; } switch (Typeof (i)) { case TYPE_ROOM: info->s_rooms++; break; case TYPE_EXIT: info->s_exits++; break; case TYPE_THING: info->s_things++; break; case TYPE_PLAYER: info->s_players++; break; default: info->s_garbage++; } } } return 1; } void do_stats (dbref player, dbref cause, int key, char *name) /* reworked by R'nice */ { dbref owner; STATS statinfo; switch (key) { case STAT_ALL: owner = NOTHING; break; case STAT_ME: owner = Owner(player); break; case STAT_PLAYER: if (!(name && *name)) { notify(player, tprintf("The universe contains %d objects.", mudstate.db_top)); return; } owner = lookup_player (player, name, 1); if (owner == NOTHING) { notify(player, "Not found."); return; } break; default: notify(player, "Illegal combination of switches."); return; } if (!get_stats(player, owner, &statinfo)) return; notify (player, tprintf ("%d objects = %d rooms, %d exits, %d things, %d players. (%d garbage)", statinfo.s_total, statinfo.s_rooms, statinfo.s_exits, statinfo.s_things, statinfo.s_players, statinfo.s_garbage)); #ifdef TEST_MALLOC if (Wizard (player)) notify (player, tprintf ("Malloc count = %d.", malloc_count)); #endif /* TEST_MALLOC */ #ifdef MSTATS if(Wizard(player)) { struct mstats_value mval; int i; extern unsigned int malloc_sbrk_used, malloc_sbrk_unused; extern int nmal, nfre; extern struct mstats_value malloc_stats(); extern int malloc_mem_used(), malloc_mem_free(); notify(player, tprintf("Sbrk Unused: %d -- Sbrk Used: %d", malloc_sbrk_unused, malloc_sbrk_used)); notify(player, tprintf("Raw malloc cnt: %d -- Raw free cnt: %d", nmal, nfre)); for(i = 0; i < 15; i++) { mval = malloc_stats(i); notify(player, tprintf("Blocksz: %d -- Free: %d -- Used: %d", mval.blocksize, mval.nfree, mval.nused)); } notify(player, tprintf("Mem used: %d -- Mem free: %d", malloc_mem_used(), malloc_mem_free())); } #endif /* MSTATS */ } int chown_all (dbref from_player, dbref to_player) { int i, count; if (Typeof(from_player) != TYPE_PLAYER) from_player = Owner(from_player); if (Typeof(to_player) != TYPE_PLAYER) to_player = Owner(to_player); count = 0; DO_WHOLE_DB(i) { if ((Owner(i) == from_player) && (Owner(i) != i)) { if (Typeof(i) == TYPE_PLAYER) s_Owner(i, i); else s_Owner (i, to_player); s_Flags(i, (Flags(i) & ~(CHOWN_OK|INHERIT)) | HALT); count++; } } return count; } void do_chownall (dbref player, dbref cause, int key, char *from, char *to) { int count; dbref victim, recipient; init_match (player, from, TYPE_PLAYER); match_neighbor (); match_absolute (); match_player (); if ((victim = noisy_match_result ()) == NOTHING) return; if ((to != NULL) && *to) { init_match (player, to, TYPE_PLAYER); match_neighbor (); match_absolute (); match_player (); if ((recipient = noisy_match_result ()) == NOTHING) return; } else { recipient = player; } count = chown_all(victim, recipient); if (!Quiet(player)) { notify(player, tprintf("%d objects @chowned.", count)); } } #define ANY_OWNER -2 /* --------------------------------------------------------------------------- * convert_flags: convert a list of flag letters into its bit pattern. * Also set the type qualifier if specified and not already set. */ FLAG convert_flags (dbref player, char *flaglist, FLAGSEL *selection, FLAG *p_type) { int i, handled, handled_any, handled_real_flag; char *s; FLAG masks[8], type; FLAGENT *fp; for(i=0; i<8; i++) masks[i] = 0; handled_real_flag = 0; type = *p_type; for (s=flaglist; *s; s++) { handled = 0; /* Check for object type */ for (i=0; (i<=7) && !handled; i++) { if ((object_types[i].lett == *s) && !(((object_types[i].perm & CA_WIZARD) && !Wizard(player)) || ((object_types[i].perm & CA_GOD) && !God(player)))) { if ((type != NOTYPE) && (type != i)) { notify(player, tprintf("%c: Conflicting type specifications.", *s)); return 0; } type = i; handled = 1; } } /* Check generic flags */ if (handled) continue; for (fp=gen_flags; (fp->flagname) && !handled; fp++) { if ((fp->flaglett == *s) && !(((fp->listperm & CA_WIZARD) && !Wizard(player)) || ((fp->listperm & CA_GOD) && !God(player)))) { for (i=0; i<8; i++) masks[i] |= fp->flagvalue; handled = 1; handled_real_flag = 1; } } /* Check type-specific flags */ if (handled) continue; handled_any = 0; for (i=0; i<=7; i++) { handled = 0; if ((type != NOTYPE) && (type != i)) continue; if (!(fp = object_types[i].flaglist)) continue; for (; (fp->flagname) && !handled; fp++) { if ((fp->flaglett == *s) && !(((fp->listperm & CA_WIZARD) && !Wizard(player)) || ((fp->listperm & CA_GOD) && !God(player)))) { masks[i] |= fp->flagvalue; handled = 1; handled_any = 1; handled_real_flag = 1; } } if (!handled) masks[i] = -1; } if (handled_any) handled = 1; if (!handled) { notify(player, tprintf("%c: Flag unknown or not valid for specified object type", *s)); return 0; } } /* Exclude classes that match nothing by setting their mask to -1 */ if (handled_real_flag) { for (i=0; i<8; i++) { if (!masks[i]) masks[i] = -1; } } /* return new mask and type */ selection->player_flags = masks[TYPE_PLAYER]; selection->room_flags = masks[TYPE_ROOM]; selection->thing_flags = masks[TYPE_THING]; selection->exit_flags = masks[TYPE_EXIT]; selection->player_eflags = 0; *p_type = type; return 1; } void er_mark_disabled (dbref player) { notify(player, "The mark commands are not allowed while DB cleaning is enabled."); notify(player, "Use the '@disable cleaning' command to disable automatic cleaning."); notify(player, "Remember to '@unmark_all' before re-enabling automatic cleaning."); } /* --------------------------------------------------------------------------- * do_search: Walk the db reporting various things (or setting/clearing * mark bits) */ int search_setup (dbref player, char *searchfor, SEARCH *parm) { char *pname, *searchtype; int err; /* Crack arg into <pname> <type>=<targ> */ pname = parse_to(&searchfor, '=', EV_STRIP_TS); if (!pname || !*pname) pname = (char *) "me"; searchtype = strchr(pname, ' '); if (searchtype) { *searchtype++ = '\0'; } else { if (!searchfor || !*searchfor) { searchtype = (char *) ""; } else { searchtype = pname; pname = (char *) ""; } } parm->s_owner = Owner(player); parm->s_wizard = Wizard(player); /* set limits on who we search */ parm->s_rst_owner = NOTHING; if (!*pname) { parm->s_rst_owner = parm->s_wizard ? ANY_OWNER : player; } else if (pname[0] == '#') { parm->s_rst_owner = atoi (&pname[1]); if (!Good_obj(parm->s_rst_owner)) parm->s_rst_owner = NOTHING; else if (Typeof(parm->s_rst_owner) != TYPE_PLAYER) parm->s_rst_owner = NOTHING; } else if (strcmp (pname, "me") == 0) { parm->s_rst_owner = player; } else { parm->s_rst_owner = lookup_player (player, pname, 1); } if (parm->s_rst_owner == NOTHING) { notify (player, tprintf ("%s: No such player", pname)); return 0; } /* set limits on what we search for */ err = 0; parm->s_rst_name = NULL; parm->s_rst_eval = NULL; parm->s_rst_type = NOTYPE; parm->s_flagmasks.player_flags = 0; parm->s_flagmasks.room_flags = 0; parm->s_flagmasks.thing_flags = 0; parm->s_flagmasks.exit_flags = 0; parm->s_flagmasks.player_eflags = 0; switch (searchtype[0]) { case '\0': /* the no class requested class :) */ break; case 'e': if (string_prefix ("exits", searchtype)) { parm->s_rst_name = searchfor; parm->s_rst_type = TYPE_EXIT; } else if (string_prefix ("evaluate", searchtype)) { parm->s_rst_eval = searchfor; } else if (string_prefix ("eplayer", searchtype)) { parm->s_rst_type = TYPE_PLAYER; parm->s_rst_eval = searchfor; } else if (string_prefix ("eroom", searchtype)) { parm->s_rst_type = TYPE_ROOM; parm->s_rst_eval = searchfor; } else if (string_prefix ("eobject", searchtype)) { parm->s_rst_type = TYPE_THING; parm->s_rst_eval = searchfor; } else if (string_prefix ("eexit", searchtype)) { parm->s_rst_type = TYPE_EXIT; parm->s_rst_eval = searchfor; } else { err = 1; } break; case 'f': if (string_prefix ("flags", searchtype)) { /* convert_flags ignores previous values of flag_mask * and s_rst_type while setting them */ if (!convert_flags (player, searchfor, &parm->s_flagmasks, &parm->s_rst_type)) return 0; } else { err = 1; } break; case 'n': if (string_prefix ("name", searchtype)) { parm->s_rst_name = searchfor; } else { err = 1; } break; case 'o': if (string_prefix ("objects", searchtype)) { parm->s_rst_name = searchfor; parm->s_rst_type = TYPE_THING; } else { err = 1; } break; case 'p': if (string_prefix ("players", searchtype)) { parm->s_rst_name = searchfor; parm->s_rst_type = TYPE_PLAYER; if (!*pname) parm->s_rst_owner = ANY_OWNER; } else { err = 1; } break; case 'r': if (string_prefix ("rooms", searchtype)) { parm->s_rst_name = searchfor; parm->s_rst_type = TYPE_ROOM; } else { err = 1; } break; case 't': if (string_prefix ("type", searchtype)) { if (searchfor[0] == '\0') break; if (string_prefix ("room", searchfor)) parm->s_rst_type = TYPE_ROOM; else if (string_prefix ("exit", searchfor)) parm->s_rst_type = TYPE_EXIT; else if (string_prefix ("object", searchfor)) parm->s_rst_type = TYPE_THING; else if (string_prefix ("player", searchfor)) { parm->s_rst_type = TYPE_PLAYER; if (!*pname) parm->s_rst_owner = ANY_OWNER; } else { notify(player, tprintf("%s: unknown type", searchfor)); return 0; } } else { err = 1; } break; default: err = 1; } if (err) { notify (player, tprintf ("%s: unknown class", searchtype)); return 0; } /* Make sure player is authorized to do the search */ if (!parm->s_wizard && (parm->s_rst_type != TYPE_PLAYER) && (parm->s_rst_owner != player)) { notify (player, "You need a search warrant to do that!"); return 0; } /* make sure player has money to do the search */ if (!payfor(player, mudconf.searchcost)) { notify(player, tprintf("You don't have enough %s to search. (You need %d)", mudconf.many_coins, mudconf.searchcost)); return 0; } return 1; } void search_perform (dbref player, dbref cause, SEARCH *parm) { FLAG thingflags, mask; dbref thing; char *buff, *buff2, *result; int save_invk_ctr; buff = alloc_sbuf("search_perform.num"); olist_init(); save_invk_ctr = mudstate.func_invk_ctr; DO_WHOLE_DB(thing) { if ((thing % 100) == 0) { tmp_sync(); cache_reset(); } mudstate.func_invk_ctr = save_invk_ctr; /* Check for matching type */ if ((parm->s_rst_type != NOTYPE) && (parm->s_rst_type != Typeof(thing))) continue; /* Check for matching owner */ if ((parm->s_rst_owner != ANY_OWNER) && (parm->s_rst_owner != Owner(thing))) continue; /* Toss out destroyed things */ thingflags = Flags(thing); if ((Typeof(thing) == TYPE_THING) && (thingflags & GOING)) continue; /* Check for matching flags */ switch (Typeof(thing)) { case TYPE_PLAYER: mask = parm->s_flagmasks.player_flags; break; case TYPE_ROOM: mask = parm->s_flagmasks.room_flags; break; case TYPE_THING: mask = parm->s_flagmasks.thing_flags; break; case TYPE_EXIT: mask = parm->s_flagmasks.exit_flags; break; default: mask = 0; } if ((thingflags & mask) != mask) continue; /* Check for matching name */ if (parm->s_rst_name != NULL) { if (!string_prefix(Name(thing), parm->s_rst_name)) continue; } /* Check for successful evaluation */ if (parm->s_rst_eval != NULL) { sprintf(buff, "#%d", thing); buff2 = replace_string(BOUND_VAR, buff, parm->s_rst_eval); result = exec(player, cause, EV_FCHECK, buff2, (char **)NULL, 0); free_lbuf(buff2); if (!*result || !xlate(result)) { free_lbuf(result); continue; } free_lbuf(result); } /* It passed everything. Amazing. */ olist_add(thing); } free_sbuf(buff); mudstate.func_invk_ctr = save_invk_ctr; } static void search_mark (dbref player, int key) { dbref thing; int nchanged, is_marked; nchanged = 0; for (thing=olist_first(); thing!=NOTHING; thing=olist_next()) { is_marked = Marked(thing); /* Don't bother checking if marking and already marked * (or if unmarking and not marked) */ if (((key == SRCH_MARK) && is_marked) || ((key == SRCH_UNMARK) && !is_marked)) continue; /* Toggle the mark bit and update the counters */ if (key == SRCH_MARK) { Mark(thing); nchanged++; } else { Unmark(thing); nchanged++; } } notify(player, tprintf("%d objects %smarked", nchanged, ((key==SRCH_MARK) ? "" : "un"))); return; } void do_search (dbref player, dbref cause, int key, char *arg) { int flag, destitute; char *buff, *outbuf, *bp; dbref thing, from, to; SEARCH searchparm; if ((key != SRCH_SEARCH) && (mudconf.control_flags & CF_DBCHECK)) { er_mark_disabled(player); return; } if (!search_setup (player, arg, &searchparm)) return; search_perform (player, cause, &searchparm); destitute = 1; /* If we are doing a @mark command, handle that here. */ if (key != SRCH_SEARCH) { search_mark(player, key); return; } outbuf = alloc_lbuf("do_search.outbuf"); /* room search */ if (searchparm.s_rst_type == TYPE_ROOM || searchparm.s_rst_type == NOTYPE) { flag = 1; for (thing=olist_first(); thing!=NOTHING; thing=olist_next()) { if (Typeof(thing) != TYPE_ROOM) continue; if (flag) { flag = 0; destitute = 0; notify (player, "\nROOMS:"); } buff = unparse_object (player, thing); notify (player, buff); free_lbuf(buff); } } /* exit search */ if (searchparm.s_rst_type == TYPE_EXIT || searchparm.s_rst_type == NOTYPE) { flag = 1; for (thing=olist_first(); thing!=NOTHING; thing=olist_next()) { if (Typeof(thing) != TYPE_EXIT) continue; if (flag) { flag = 0; destitute = 0; notify (player, "\nEXITS:"); } from = Exits (thing); to = Location (thing); bp = outbuf; buff = unparse_object (player, thing); safe_str(buff, outbuf, &bp); free_lbuf(buff); safe_str((char *)" [from ", outbuf, &bp); buff = unparse_object (player, from); safe_str(((from==NOTHING) ? "NOWHERE" : buff), outbuf, &bp); free_lbuf(buff); safe_str((char *)" to ", outbuf, &bp); buff = unparse_object (player, to); safe_str(((to==NOTHING) ? "NOWHERE" : buff), outbuf, &bp); free_lbuf(buff); safe_chr(']', outbuf, &bp); *bp = '\0'; notify (player, outbuf); } } /* object search */ if (searchparm.s_rst_type == TYPE_THING || searchparm.s_rst_type == NOTYPE) { flag = 1; for (thing=olist_first(); thing!=NOTHING; thing=olist_next()) { if (Typeof(thing) != TYPE_THING) continue; if (flag) { flag = 0; destitute = 0; notify (player, "\nOBJECTS:"); } bp = outbuf; buff = unparse_object (player, thing); safe_str(buff, outbuf, &bp); free_lbuf(buff); safe_str((char *)" [owner: ", outbuf, &bp); buff = unparse_object (player, Owner (thing)); safe_str(buff, outbuf, &bp); free_lbuf(buff); safe_chr(']', outbuf, &bp); *bp = '\0'; notify (player, outbuf); } } /* player search */ if (searchparm.s_rst_type == TYPE_PLAYER || searchparm.s_rst_type == NOTYPE) { flag = 1; for (thing=olist_first(); thing!=NOTHING; thing=olist_next()) { if (Typeof(thing) != TYPE_PLAYER) continue; if (flag) { flag = 0; destitute = 0; notify (player, "\nPLAYERS:"); } bp = outbuf; buff = unparse_object (player, thing); safe_str(buff, outbuf, &bp); free_lbuf(buff); if (searchparm.s_wizard) { safe_str((char *)" [location: ", outbuf, &bp); buff = unparse_object (player, Location (thing)); safe_str(buff, outbuf, &bp); free_lbuf(buff); safe_chr(']', outbuf, &bp); } *bp = '\0'; notify (player, outbuf); } } /* if nothing found matching search criteria */ if (destitute) { notify (player, "Nothing found."); } free_lbuf(outbuf); olist_init(); } /* --------------------------------------------------------------------------- * do_markall: set or clear the mark bits of all objects in the db. */ void do_markall (dbref player, dbref cause, int key) { int i; if (mudconf.control_flags & CF_DBCHECK) { er_mark_disabled(player); return; } if (key == MARK_SET) Mark_all(i); else if (key == MARK_CLEAR) Unmark_all(i); if (!Quiet(player)) notify(player, "Done."); } /* --------------------------------------------------------------------------- * do_apply_marked: Perform a command for each marked obj in the db. */ void do_apply_marked (dbref player, dbref cause, int key, char *command, char *cargs[], int ncargs) { char *buff; int i; if (mudconf.control_flags & CF_DBCHECK) { er_mark_disabled(player); return; } buff = alloc_sbuf("do_apply_marked"); DO_WHOLE_DB(i) { if (Marked(i)) { sprintf(buff, "#%d", i); bind_and_queue (player, cause, command, buff, cargs, ncargs); } } free_sbuf(buff); if (!Quiet(player)) notify(player, "Done."); } /* --------------------------------------------------------------------------- * olist_init, olist_add, olist_first, olist_next: Object list management * routines. */ /* olist_init: Clear and initialize the object list */ void olist_init (void) { OBLOCK *op, *onext; for (op=mudstate.olist_head; op!=NULL; op=onext) { onext = op->next; free_lbuf(op); } mudstate.olist_head = NULL; mudstate.olist_tail = NULL; mudstate.olist_cblock = NULL; mudstate.olist_count = 0; mudstate.olist_citm = 0; } /* olist_add: Add an entry to the object list */ void olist_add (dbref item) { OBLOCK *op; if (!mudstate.olist_head) { op = (OBLOCK *)alloc_lbuf("olist_add.first"); mudstate.olist_head = mudstate.olist_tail = op; mudstate.olist_count = 0; op->next = NULL; } else if (mudstate.olist_count >= OBLOCK_SIZE) { op = (OBLOCK *)alloc_lbuf("olist_add.next"); mudstate.olist_tail->next = op; mudstate.olist_tail = op; mudstate.olist_count = 0; op->next = NULL; } else { op = mudstate.olist_tail; } op->data[mudstate.olist_count++] = item; } /* olist_first: Return the first entry in the object list */ dbref olist_first (void) { if (!mudstate.olist_head) return NOTHING; if ((mudstate.olist_head == mudstate.olist_tail) && (mudstate.olist_count == 0)) return NOTHING; mudstate.olist_cblock = mudstate.olist_head; mudstate.olist_citm = 0; return mudstate.olist_cblock -> data[mudstate.olist_citm++]; } dbref olist_next (void) { dbref thing; if (!mudstate.olist_cblock) return NOTHING; if ((mudstate.olist_cblock == mudstate.olist_tail) && (mudstate.olist_citm >= mudstate.olist_count)) return NOTHING; thing = mudstate.olist_cblock->data[mudstate.olist_citm++]; if (mudstate.olist_citm >= OBLOCK_SIZE) { mudstate.olist_cblock = mudstate.olist_cblock->next; mudstate.olist_citm = 0; } return thing; }