/** Display information on an attribute from the table. * \verbatim * Top-level function for @attribute. * \endverbatim * \param player the enactor. * \param name the name of the attribute. */ void do_attribute_info(dbref player, char *name) { ATTR *ap; if (!name || !*name) { notify(player, T("Which attribute do you mean?")); return; } /* Is this attribute in the table? */ if (*name == '@') name++; ap = aname_hash_lookup(name); if (!ap) { notify(player, T("That attribute isn't in the attribute table")); return; } notify_format(player, "%9s: %s", T("Attribute"), AL_NAME(ap)); if (ap->flags & AF_RLIMIT) { notify_format(player, "%9s: %s", T("Limit"), display_attr_limit(ap)); } else if (ap->flags & AF_ENUM) { notify_format(player, "%9s: %s", T("Enum"), display_attr_limit(ap)); } notify_format(player, "%9s: %s", T("Flags"), privs_to_string(attr_privs_view, AL_FLAGS(ap))); notify_format(player, "%9s: %s", T("Creator"), unparse_dbref(AL_CREATOR(ap))); return; }
/** Debit a player's pennies, if they can afford it. * \param who player to debit. * \param cost number of pennies to debit. * \retval 1 player successfully debited. * \retval 0 player can't afford the cost. */ int payfor(dbref who, int cost) { /* subtract cost from who's pennies */ int tmp; dbref owner; if ((cost == 0) || NoPay(who)) return 1; owner = Owner(who); if ((tmp = Pennies(owner)) >= cost) { if (Track_Money(owner)) { notify_format(owner, T("GAME: %s(%s) spent %d %s."), AName(who, AN_SYS, NULL), unparse_dbref(who), cost, (cost == 1) ? MONEY : MONIES); } s_Pennies(owner, tmp - cost); return 1; } else { if (Track_Money(owner)) { notify_format(owner, T("GAME: %s(%s) tried to spend %d %s."), AName(who, AN_SYS, NULL), unparse_dbref(who), cost, (cost == 1) ? MONEY : MONIES); } return 0; } }
/** Check to see if an object has a good zone lock set. * If it doesn't have a lock at all, set one of '=Zone'. * \param player The object responsible for having the lock checked. * \param zone the object whose lock needs to be checked. * \param noisy if 1, notify player of automatic locking */ void check_zone_lock(dbref player, dbref zone, int noisy) { boolexp key = getlock(zone, Zone_Lock); if (key == TRUE_BOOLEXP) { add_lock(GOD, zone, Zone_Lock, parse_boolexp(zone, "=me", Zone_Lock), -1); if (noisy) notify_format(player, T ("Unlocked zone %s - automatically zone-locking to itself"), unparse_object(player, zone)); } else if (eval_lock(Location(player), zone, Zone_Lock)) { /* Does #0 and #2 pass it? If so, probably trivial elock */ if (eval_lock(PLAYER_START, zone, Zone_Lock) && eval_lock(MASTER_ROOM, zone, Zone_Lock)) { if (noisy) notify_format(player, T("Zone %s really should have a more secure zone-lock."), unparse_object(player, zone)); } else /* Probably inexact zone lock */ notify_format(player, T ("Warning: Zone %s may have loose zone lock. Lock zones to =player, not player"), unparse_object(player, zone)); } }
/** Decompile the standard attribute table, as per \@attribute/decompile * \param player The enactor * \param pattern Wildcard pattern of attrnames to decompile * \param retroactive Include the /retroactive switch? */ void do_decompile_attribs(dbref player, char *pattern, int retroactive) { ATTR *ap; const char *name; notify(player, T("@@ Standard Attributes:")); for (ap = ptab_firstentry_new(&ptab_attrib, &name); ap; ap = ptab_nextentry_new(&ptab_attrib, &name)) { if (strcmp(name, AL_NAME(ap))) continue; if (pattern && *pattern && !quick_wild(pattern, AL_NAME(ap))) continue; notify_format(player, "@attribute/access%s %s=%s", (retroactive ? "/retroactive" : ""), AL_NAME(ap), privs_to_string(attr_privs_view, AL_FLAGS(ap))); if (ap->flags & AF_RLIMIT) { notify_format(player, "@attribute/limit %s=%s", AL_NAME(ap), display_attr_limit(ap)); } else if (ap->flags & AF_ENUM) { notify_format(player, "@attribute/enum %s=%s", AL_NAME(ap), display_attr_limit(ap)); } } }
/** Unlock a lock (user interface). * \verbatim * This implements @unlock. * \endverbatim * \param player the enactor. * \param name name of object to unlock. * \param type type of lock to unlock. */ void do_unlock(dbref player, const char *name, lock_type type) { dbref thing; char *sp; lock_type real_type; /* check for '@unlock <object>/<atr>' */ sp = strchr(name, '/'); if (sp) { notify(player, "Use @atrlock."); return; } if ((thing = match_controlled(player, name)) != NOTHING) { if ((real_type = check_lock_type(player, thing, type)) != NULL) { if (getlock(thing, real_type) == TRUE_BOOLEXP) { if (!AreQuiet(player, thing)) notify_format(player, T("%s(%s) - %s (already) unlocked."), Name(thing), unparse_dbref(thing), real_type); } else if (delete_lock(player, thing, real_type)) { if (!AreQuiet(player, thing)) notify_format(player, T("%s(%s) - %s unlocked."), Name(thing), unparse_dbref(thing), real_type); if (!IsPlayer(thing)) { char lmbuf[1024]; ModTime(thing) = mudtime; snprintf(lmbuf, 1023, "%s lock[#%d]", real_type, player); lmbuf[strlen(lmbuf)+1] = '\0'; set_lmod(thing, lmbuf); } } else notify(player, T("Permission denied.")); } } }
/** Unlock a lock (user interface). * \verbatim * This implements @unlock. * \endverbatim * \param player the enactor. * \param name name of object to unlock. * \param type type of lock to unlock. */ void do_unlock(dbref player, const char *name, lock_type type) { dbref thing; lock_type real_type; /* check for '@unlock <object>/<atr>' */ if (strchr(name, '/')) { do_atrlock(player, name, "off"); return; } if ((thing = match_controlled(player, name)) != NOTHING) { if ((real_type = check_lock_type(player, thing, type)) != NULL) { if (getlock(thing, real_type) == TRUE_BOOLEXP) { if (!AreQuiet(player, thing)) notify_format(player, T("%s(%s) - %s (already) unlocked."), AName(thing, AN_SYS, NULL), unparse_dbref(thing), real_type); } else if (delete_lock(player, thing, real_type)) { if (!AreQuiet(player, thing)) notify_format(player, T("%s(%s) - %s unlocked."), AName(thing, AN_SYS, NULL), unparse_dbref(thing), real_type); if (!IsPlayer(thing)) ModTime(thing) = mudtime; } else notify(player, T("Permission denied.")); } } }
/** Actually change the ownership of something, and fix bits. * \param player the enactor. * \param thing object to change ownership of. * \param newowner new owner for thing. * \param preserve if 1, preserve privileges and don't halt. */ void chown_object(dbref player, dbref thing, dbref newowner, int preserve) { (void) undestroy(player, thing); if (God(player)) { Owner(thing) = newowner; } else { Owner(thing) = Owner(newowner); } /* Don't allow circular zones */ Zone(thing) = NOTHING; if (GoodObject(Zone(newowner))) { dbref tmp; int ok_to_zone = 1; int zone_depth = MAX_ZONES; for (tmp = Zone(Zone(newowner)); GoodObject(tmp); tmp = Zone(tmp)) { if (tmp == thing) { notify(player, T("Circular zone broken.")); ok_to_zone = 0; break; } if (tmp == Zone(tmp)) /* Ran into an object zoned to itself */ break; zone_depth--; if (!zone_depth) { ok_to_zone = 0; notify(player, T("Overly deep zone chain broken.")); break; } } if (ok_to_zone) Zone(thing) = Zone(newowner); } clear_flag_internal(thing, "CHOWN_OK"); if (!preserve || !Wizard(player)) { clear_flag_internal(thing, "WIZARD"); clear_flag_internal(thing, "ROYALTY"); clear_flag_internal(thing, "TRUST"); set_flag_internal(thing, "HALT"); destroy_flag_bitmask("POWER", Powers(thing)); Powers(thing) = new_flag_bitmask("POWER"); do_halt(thing, "", thing); } else { if (preserve == 1 && (newowner != player) && Wizard(thing) && !Wizard(newowner)) { notify_format(player, T("Warning: WIZ flag reset on #%d because " "@CHOWN/PRESERVE is to a non-WIZ flagged third-party."), thing); clear_flag_internal(thing, "WIZARD"); } if (!null_flagmask("POWER", Powers(thing)) || Wizard(thing) || Royalty(thing) || Inherit(thing)) notify_format(player, T("Warning: @CHOWN/PRESERVE on an object (#%d) " "with WIZ, ROY, INHERIT, or @power privileges."), thing); } }
/** Can someone pay for something (in cash and quota)? * Does who have enough pennies to pay for something, and if something * is being built, does who have enough quota? Wizards, roys * aren't subject to either. This function not only checks that they * can afford it, but actually charges them. * \param who player attempting to pay. * \param pennies cost in pennies. * \retval 1 who can pay. * \retval 0 who can't pay. */ int can_pay_fees(dbref who, int pennies) { if (Guest(who)) { notify(who, T("Sorry, you aren't allowed to build.")); return 0; } /* check database size -- EVERYONE is subject to this! */ if (DBTOP_MAX && (db_top >= DBTOP_MAX + 1) && (first_free == NOTHING)) { notify(who, T("Sorry, there is no more room in the database.")); return 0; } /* Can they afford it? */ if (!NoPay(who) && (Pennies(Owner(who)) < pennies)) { notify_format(who, T("Sorry, you don't have enough %s."), MONIES); return 0; } /* check building quota */ if (!pay_quota(who, QUOTA_COST)) { notify(who, T("Sorry, your building quota has run out.")); return 0; } /* charge */ payfor(who, pennies); return 1; }
/** Delete an attribute from the attribute table. * \verbatim * Top-level function for @attrib/delete. * \endverbatim * \param player the enactor. * \param name the name of the attribute to delete. */ void do_attribute_delete(dbref player, char *name) { ATTR *ap; if (!name || !*name) { notify(player, T("Which attribute do you mean?")); return; } /* Is this attribute in the table? */ ap = (ATTR *) ptab_find_exact(&ptab_attrib, name); if (!ap) { notify(player, T("That attribute isn't in the attribute table")); return; } /* Free everything it uses. */ if (ap->data != NULL_CHUNK_REFERENCE) { chunk_delete(ap->data); } /* Ok, take it out of the hash table */ ptab_delete(&ptab_attrib, name); notify_format(player, T("Removed %s from attribute table."), name); return; }
/* spawn a single drone */ void hs_spawn(dbref player, char *which) { dbref obj; hship *ship; obj = match_result(player, which, TYPE_THING, MAT_NEAR_THINGS); if (!RealGoodObject(obj)) { notify(player, "HSPACE: Unable to find that drone template."); return; } if (!IsDrone(obj)) { notify(player, "HSPACE: That is not a valid drone template."); return; } ship = create_drone(obj); if (!ship) { notify(player, "HSPACE: Failed to create the drone."); return; } notify_format(player, "HSPACE: Drone created at %s(#%d) %.0f %.0f %.0f.", Name(ship->uid->objnum), ship->uid->objnum, ship->x, ship->y, ship->z); return; }
static void display_attr_info(dbref player, ATTR *ap) { notify_format(player, "%9s: %s", T("Attribute"), AL_NAME(ap)); if (ap->flags & AF_RLIMIT) { notify_format(player, "%9s: %s", T("Limit"), display_attr_limit(ap)); } else if (ap->flags & AF_ENUM) { notify_format(player, "%9s: %s", T("Enum"), display_attr_limit(ap)); } notify_format(player, "%9s: %s", T("Flags"), privs_to_string(attr_privs_view, AL_FLAGS(ap))); notify_format(player, "%9s: %s", T("Creator"), unparse_dbref(AL_CREATOR(ap))); return; }
/** Issue a warning about an object. * \param player player to receive the warning notification. * \param i object the warning is about. * \param name name of the warnings. * \param desc a formatting string for the warning message. */ void complain(dbref player, dbref i, const char *name, const char *desc, ...) { #ifdef HAS_VSNPRINTF char buff[BUFFER_LEN]; #else char buff[BUFFER_LEN * 3]; /* safety margin */ #endif va_list args; va_start(args, desc); #ifdef HAS_VSNPRINTF vsnprintf(buff, sizeof buff, desc, args); #else vsprintf(buff, desc, args); #endif buff[BUFFER_LEN - 1] = '\0'; va_end(args); notify_format(player, T("Warning '%s' for %s:"), name, unparse_object(player, i)); notify(player, buff); }
/** Set/lock a lock (user interface). * \verbatim * This implements @lock. * \endverbatim * \param player the enactor. * \param name name of object to lock. * \param keyname key to lock the lock to, as a string. * \param type type of lock to lock. */ void do_lock(dbref player, const char *name, const char *keyname, lock_type type) { lock_type real_type; dbref thing; boolexp key; /* check for '@lock <object>/<atr>' */ if (strchr(name, '/')) { do_atrlock(player, name, "on"); return; } if (!keyname || !*keyname) { do_unlock(player, name, type); return; } switch (thing = match_result(player, name, NOTYPE, MAT_EVERYTHING)) { case NOTHING: notify(player, T("I don't see what you want to lock!")); return; case AMBIGUOUS: notify(player, T("I don't know which one you want to lock!")); return; default: if (!controls(player, thing)) { notify(player, T("You can't lock that!")); return; } if (IsGarbage(thing)) { notify(player, T("Why would you want to lock garbage?")); return; } break; } key = parse_boolexp(player, keyname, type); /* do the lock */ if (key == TRUE_BOOLEXP) { notify(player, T("I don't understand that key.")); } else { if ((real_type = check_lock_type(player, thing, type)) != NULL) { /* everything ok, do it */ if (add_lock(player, thing, real_type, key, LF_DEFAULT)) { if (!AreQuiet(player, thing)) notify_format(player, T("%s(%s) - %s locked."), AName(thing, AN_SYS, NULL), unparse_dbref(thing), real_type); if (!IsPlayer(thing)) ModTime(thing) = mudtime; } else { notify(player, T("Permission denied.")); /* Done by a failed add_lock() // free_boolexp(key); */ } } else free_boolexp(key); } }
/** Add an access rule to the linked list. * \param player enactor. * \param host host pattern to add. * \param who player to which rule applies, or AMBIGUOUS. * \param can flags of allowed actions. * \param cant flags of disallowed actions. * \retval 1 success. * \retval 0 failure. * \verbatim * This function adds an access rule after the @sitelock entry. * If there is no @sitelock entry, add one to the end of the list * and then add the entry. * Build an appropriate comment based on the player and date * \endverbatim */ bool add_access_sitelock(dbref player, const char *host, dbref who, uint32_t can, uint32_t cant) { struct access *end; struct access *tmp; const char *errptr = NULL; tmp = sitelock_alloc(host, who, can, cant, "", &errptr); if (!tmp) { notify_format(player, T("Unable to add sitelock entry: %s"), errptr); return false; } if (!access_top) { /* Add to the beginning, but first add a sitelock marker */ if (!add_access_node("@sitelock", AMBIGUOUS, ACS_SITELOCK, 0, "", &errptr)) { notify_format(player, T("Unable to add @sitelock separator: %s"), errptr); return 0; } access_top->next = tmp; } else { end = access_top; while (end->next && end->can != ACS_SITELOCK) end = end->next; /* Now, either we're at the sitelock or the end */ if (end->can != ACS_SITELOCK) { /* We're at the end and there's no sitelock marker. Add one */ if (!add_access_node("@sitelock", AMBIGUOUS, ACS_SITELOCK, 0, "", &errptr)) { notify_format(player, T("Unable to add @sitelock separator: %s"), errptr); return 0; } end = end->next; } else { /* We're in the middle, so be sure we keep the list linked */ tmp->next = end->next; } end->next = tmp; } return 1; }
/** User interface to list locks. * \verbatim * This function implements @list/locks. * \endverbatim * \param player the enactor. * \param arg wildcard pattern of flag names to list, or NULL for all. * \param lc if 1, list flags in lowercase. * \param label label to prefix to list. */ void do_list_locks(dbref player, const char *arg, int lc, const char *label) { char buff[BUFFER_LEN]; char *bp = buff; list_locks(buff, &bp, arg); *bp = '\0'; notify_format(player, "%s: %s", label, lc ? strlower(buff) : buff); }
/** Processing related to players' last connections. * Here we check to see if a player gets a paycheck, tell them their * last connection site, and update all their LAST* attributes. * \param player dbref of player. * \param host hostname of player's current connection. * \param ip ip address of player's current connection. */ void check_last(dbref player, const char *host, const char *ip) { char *s; ATTR *a; ATTR *h; char last_time[MAX_COMMAND_LEN / 8]; char last_place[MAX_COMMAND_LEN]; /* compare to last connect see if player gets salary */ s = show_time(mudtime, 0); a = atr_get_noparent(player, "LAST"); if (a && (strncmp(atr_value(a), s, 10) != 0)) giveto(player, Paycheck(player)); /* tell the player where he last connected from */ if (!Guest(player)) { h = atr_get_noparent(player, "LASTSITE"); if (h && a) { strcpy(last_place, atr_value(h)); strcpy(last_time, atr_value(a)); notify_format(player, T("Last connect was from %s on %s."), last_place, last_time); } /* How about last failed connection */ h = atr_get_noparent(player, "LASTFAILED"); if (h && a) { strcpy(last_place, atr_value(h)); if (strlen(last_place) > 2) notify_format(player, T("Last FAILED connect was from %s."), last_place); } } /* if there is no Lastsite, then the player is newly created. * the extra variables are a kludge to work around some weird * behavior involving uncompress. */ /* set the new attributes */ (void) atr_add(player, "LAST", s, GOD, 0); (void) atr_add(player, "LASTSITE", host, GOD, 0); (void) atr_add(player, "LASTIP", ip, GOD, 0); (void) atr_add(player, "LASTFAILED", " ", GOD, 0); }
/** Set flags on a lock (user interface). * \verbatim * This implements @lset. * \endverbatim * \param player the enactor. * \param what string in the form obj/lock. * \param flags list of flags to set. */ void do_lset(dbref player, char *what, char *flags) { dbref thing; lock_list *l; char *lname; int flag; int unset = 0; if ((lname = strchr(what, '/')) == NULL) { notify(player, T("No lock name given.")); return; } *lname++ = '\0'; if ((thing = match_controlled(player, what)) == NOTHING) return; if (*flags == '!') { unset = 1; flags++; } if ((flag = string_to_lockflag(flags)) < 0) { notify(player, T("Unrecognized lock flag.")); return; } l = getlockstruct_noparent(thing, lname); if (!l || !Can_Read_Lock(player, thing, L_TYPE(l))) { notify(player, T("No such lock.")); return; } if (!can_write_lock(player, thing, l)) { notify(player, T("Permission denied.")); return; } if (unset) L_FLAGS(l) &= ~flag; else L_FLAGS(l) |= flag; if (!Quiet(player) && !(Quiet(thing) && (Owner(thing) == player))) notify_format(player, "%s/%s - %s.", Name(thing), L_TYPE(l), unset ? T("lock flags unset") : T("lock flags set")); if (!IsPlayer(thing)) { char lmbuf[1024]; ModTime(thing) = mudtime; snprintf(lmbuf, 1023, "lflags - %s[#%d]", flags, player); lmbuf[strlen(lmbuf)+1] = '\0'; set_lmod(thing, lmbuf); } }
/** Display the access list. * \param player enactor. * Sends the complete access list to the player. */ void do_list_access(dbref player) { struct access *ap; acsflag *c; char flaglist[BUFFER_LEN]; int rulenum = 0; char *bp; for (ap = access_top; ap; ap = ap->next) { rulenum++; if (ap->can != ACS_SITELOCK) { bp = flaglist; for (c = acslist; c->name; c++) { if (c->flag == ACS_DEFAULT) continue; if (ap->can & c->flag) { safe_chr(' ', flaglist, &bp); safe_str(c->name, flaglist, &bp); } if (c->toggle && (ap->cant & c->flag)) { safe_chr(' ', flaglist, &bp); safe_chr('!', flaglist, &bp); safe_str(c->name, flaglist, &bp); } } *bp = '\0'; notify_format(player, T("%3d SITE: %-20s DBREF: %-6s FLAGS:%s"), rulenum, ap->host, unparse_dbref(ap->who), flaglist); notify_format(player, T(" COMMENT: %s"), ap->comment ? ap->comment : ""); } else { notify(player, T ("---- @sitelock will add sites immediately below this line ----")); } } if (rulenum == 0) { notify(player, T("There are no access rules.")); } }
/** List allocations in use. * \param player the enactor. */ void list_mem_check(dbref player) { MEM *chk; if (!options.mem_check) return; for (chk = memcheck_head->links[0]; chk; chk = chk->links[0]) { if (chk->ref_count != 0) notify_format(player, "%s : %d", chk->ref_name, chk->ref_count); } }
/** Delete an attribute from the attribute table. * \verbatim * Top-level function for @attrib/delete. * \endverbatim * \param player the enactor. * \param name the name of the attribute to delete. */ void do_attribute_delete(dbref player, char *name) { ATTR *ap; int count; if (!name || !*name) { notify(player, T("Which attribute do you mean?")); return; } /* Is this attribute in the table? */ ap = (ATTR *) ptab_find_exact(&ptab_attrib, name); if (!ap) { notify(player, T("That attribute isn't in the attribute table")); return; } /* Display current attr info, for backup/safety reasons */ display_attr_info(player, ap); /* Free all data, remove any aliases, and remove from the hash table */ count = free_standard_attr(ap, 1); switch (count) { case 0: notify_format(player, T("Failed to remove %s from attribute table."), name); break; case 1: notify_format(player, T("Removed %s from attribute table."), name); break; default: notify_format(player, T("Removed %s and %d alias(es) from attribute table."), name, count - 1); break; } return; }
/** Rename an attribute in the attribute table. * \verbatim * Top-level function for @attrib/rename. * \endverbatim * \param player the enactor. * \param old the name of the attribute to rename. * \param newname the new name (surprise!) */ void do_attribute_rename(dbref player, char *old, char *newname) { ATTR *ap; if (!old || !*old || !newname || !*newname) { notify(player, T("Which attributes do you mean?")); return; } upcasestr(old); upcasestr(newname); /* Is the new name valid? */ if (!good_atr_name(newname)) { notify(player, T("Invalid attribute name.")); return; } /* Is the new name already in use? */ ap = (ATTR *) ptab_find_exact(&ptab_attrib, newname); if (ap) { notify_format(player, T("The name %s is already used in the attribute table."), newname); return; } /* Is the old name a real attribute? */ ap = (ATTR *) ptab_find_exact(&ptab_attrib, old); if (!ap) { notify(player, T("That attribute isn't in the attribute table")); return; } /* Ok, take it out and put it back under the new name */ ptab_delete(&ptab_attrib, old); /* This causes a slight memory leak if you rename an attribute added via /access. But that doesn't happen often. Will fix someday. */ AL_NAME(ap) = strdup(newname); ptab_insert_one(&ptab_attrib, newname, ap); notify_format(player, T("Renamed %s to %s in attribute table."), old, newname); return; }
/** Autoreply messages for pages (HAVEN, IDLE, AWAY). * \param player the paging player. * \param target the paged player. * \param type type of message to return. * \param message name of attribute containing the message. * \param def default message to return. */ void page_return(dbref player, dbref target, const char *type, const char *message, const char *def) { char buff[BUFFER_LEN]; struct tm *ptr; if (message && *message) { if (call_attrib(target, message, buff, player, NULL, NULL)) { if (*buff) { ptr = (struct tm *) localtime(&mudtime); notify_format(player, T("%s message from %s: %s"), type, AName(target, AN_SYS, NULL), buff); if (!Haven(target)) notify_format(target, T("[%d:%02d] %s message sent to %s."), ptr->tm_hour, ptr->tm_min, type, AName(player, AN_SYS, NULL)); } } else if (def && *def) notify(player, def); } }
/** Set flags on a lock (user interface). * \verbatim * This implements @lset. * \endverbatim * \param player the enactor. * \param what string in the form obj/lock. * \param flags list of flags to set. */ void do_lset(dbref player, char *what, char *flags) { dbref thing; lock_list *l; char *lname; privbits flag; bool unset = 0; if ((lname = strchr(what, '/')) == NULL) { notify(player, T("No lock name given.")); return; } *lname++ = '\0'; if ((thing = match_controlled(player, what)) == NOTHING) return; if (*flags == '!') { unset = 1; flags++; } if (string_to_lockflag(player, flags, &flag) < 0) { notify(player, T("Unrecognized lock flag.")); return; } l = getlockstruct_noparent(thing, lname); if (!l || !Can_Read_Lock(player, thing, L_TYPE(l))) { notify(player, T("No such lock.")); return; } if (!can_write_lock(player, thing, l)) { notify(player, T("Permission denied.")); return; } if (unset) L_FLAGS(l) &= ~flag; else L_FLAGS(l) |= flag; if (!Quiet(player) && !(Quiet(thing) && (Owner(thing) == player))) notify_format(player, "%s/%s - %s.", AName(thing, AN_SYS, NULL), L_TYPE(l), unset ? T("lock flags unset") : T("lock flags set")); if (!IsPlayer(thing)) ModTime(thing) = mudtime; }
/** Issue a warning about an object. * \param player player to receive the warning notification. * \param i object the warning is about. * \param name name of the warnings. * \param desc a formatting string for the warning message. */ void complain(dbref player, dbref i, const char *name, const char *desc, ...) { char buff[BUFFER_LEN]; va_list args; va_start(args, desc); mush_vsnprintf(buff, sizeof buff, desc, args); va_end(args); notify_format(player, T("Warning '%s' for %s:"), name, unparse_object(player, i)); notify(player, buff); }
/** Statistics about the tree. * \param player player to notify with header. * \param root pointer to root of string tree. * \param name name of string tree, for row header. */ void st_stats(dbref player, StrTree *root, const char *name) { unsigned long bytes; int maxdepth = 0, mindepth = 0, avgdepth = 0, leaves = 0; if (!root) return; bytes = (sizeof(StrNode) - BUFFER_LEN) * root->count + root->mem; st_traverse_stats(root->root, &maxdepth, &mindepth, &avgdepth, &leaves); notify_format(player, "%-10s %7d %7d %6d %4d %4d %7lu", name, (int) root->count, leaves, mindepth, maxdepth, avgdepth, bytes); }
/** Display stats on a hashtable. * \param player player to notify with stats. * \param htab pointer to the hash table. * \param hname name of the hash table. */ void hash_stats(dbref player, HASHTAB *htab, const char *hname) { int n, entries = 0; size_t bytes; unsigned int compares[3] = { 0, 0, 0 }; if (!htab || !hname) return; bytes = sizeof *htab; bytes += sizeof(struct hash_bucket) * htab->hashsize; for (n = 0; n < htab->hashsize; n++) if (htab->buckets[n].key) { int i; int len = strlen(htab->buckets[n].key); bytes += len + 1; entries += 1; for (i = 0; i < 3; i++) { hash_func hash = hash_functions[(i + htab->hashfunc_offset) % NHASH_MOD]; if ((hash(htab->buckets[n].key, len) % htab->hashsize) == (uint32_t) n) { compares[i] += 1; break; } } } notify_format(player, "%-11s %7d %7d %7u %7u %7u %7u", hname, htab->hashsize, htab->entries, compares[0], compares[1], compares[2], (unsigned int) bytes); if (entries != htab->entries) notify_format(player, "Mismatch in size: %d expected, %d found!", htab->entries, entries); }
/** Statistics about the tree. * \param player player to notify with header. * \param root pointer to root of string tree. * \param name name of string tree, for row header. */ void st_stats(dbref player, StrTree *root, const char *name) { unsigned long bytes; int maxdepth = 0, mindepth = 0, avgdepth = 0, leaves = 0; unsigned long perms = 0, nperms = 0; bytes = (sizeof(StrNode) - BUFFER_LEN) * root->count + root->mem; st_traverse_stats(root->root, &maxdepth, &mindepth, &avgdepth, &leaves, &perms, &nperms); notify_format(player, "%-10s %7d %7d %6d %4d %4d %9lu %11.3f %7lu", name, (int) root->count, leaves, mindepth, maxdepth, avgdepth, perms, ((double) nperms / (double) (root->count - perms)), bytes); }
/** Given a list of warnings, return the bitmask that represents it. * \param player dbref to report errors to, or NOTHING. * \param warnings the string of warning names * \return a warning bitmask */ warn_type parse_warnings(dbref player, const char *warnings) { int found = 0; warn_type flags, negate_flags; char tbuf1[BUFFER_LEN]; char *w, *s; tcheck *c; flags = W_NONE; negate_flags = W_NONE; if (warnings && *warnings) { strcpy(tbuf1, warnings); /* Loop through whatever's listed and add on those warnings */ s = trim_space_sep(tbuf1, ' '); w = split_token(&s, ' '); while (w && *w) { found = 0; if (*w == '!') { /* Found a negated warning */ w++; for (c = checklist; c->name; c++) { if (!strcasecmp(w, c->name)) { negate_flags |= c->flag; found++; } } } else { for (c = checklist; c->name; c++) { if (!strcasecmp(w, c->name)) { flags |= c->flag; found++; } } } /* At this point, we haven't matched any warnings. */ if (!found && player != NOTHING) { notify_format(player, T("Unknown warning: %s"), w); } w = split_token(&s, ' '); } /* If we haven't matched anything, don't change the player's stuff */ if (!found) return -1; return flags & ~negate_flags; } else return 0; }
static void grep_add_attr(char *buff, char **bp, dbref player, int count, ATTR *attr, char *atrval) { if (buff) { if (count) safe_chr(' ', buff, bp); safe_str(AL_NAME(attr), buff, bp); } else { notify_format(player, "%s%s [#%d%s]:%s %s", ANSI_HILITE, AL_NAME(attr), Owner(AL_CREATOR(attr)), privs_to_letters(attr_privs_view, AL_FLAGS(attr)), ANSI_END, atrval); } }
void hs_print_config(dbref player, const char *which) { hconfigitem *conf; int i; if (!which || !*which) { notify(player, "HSPACE: Listing configuration options..."); i = 0; conf = &hs_conflist[i]; do { if (conf && conf->name && conf->value) { if (conf->type == HS_INTEGER) notify_format(player, "%-30s %-15s %d", conf->name, "INTEGER", *(int*)(conf->value)); else if (conf->type == HS_DOUBLE) notify_format(player, "%-30s %-15s %g", conf->name, "DOUBLE", *(double*)(conf->value)); else if (conf->type == HS_STRING) notify_format(player, "%-30s %-15s %s", conf->name, "STRING", (char*) conf->value); } i++; conf = &hs_conflist[i]; } while (conf && conf->name); } else { i = 0; conf = &hs_conflist[i]; do { if (conf && conf->name && conf->value) { if (!strcasecmp(conf->name, which)) { if (conf->type == HS_INTEGER) notify_format(player, "%-30s %-15s %d", conf->name, "INTEGER", *(int*)(conf->value)); else if (conf->type == HS_DOUBLE) notify_format(player, "%-30s %-15s %g", conf->name, "DOUBLE", *(double*)(conf->value)); else if (conf->type == HS_STRING) notify_format(player, "%-30s %-15s %s", conf->name, "STRING", (char*) conf->value); return; } } i++; conf = &hs_conflist[i]; } while (conf && conf->name); notify(player, "HSPACE: Invalid configuration option."); } }