From: Rick Bird Date: Fri, 25 Mar 2011 21:09:24 +0000 (-0400) Subject: PennMUSH Incorp 182p4.. X-Git-Url: https://git.theari.com/?a=commitdiff_plain;h=efacc4e0b3dcf13ef81fe24c1213118faf084d54;p=cobramush.git PennMUSH Incorp 182p4.. * Loading a db with empty attributes used as the roots of attribute trees didn't work if empty_attrs is set to no. Reported by Kevin. [SW] * Bugs in wiping attribute trees with attributes the wiper doesn't have permission to delete fixed. [SW] * @wipe reports the number of attributes deleted. [183] * speak() uses accented names. Sketch. --- diff --git a/hdrs/attrib.h b/hdrs/attrib.h index 82168a2..a76bb83 100644 --- a/hdrs/attrib.h +++ b/hdrs/attrib.h @@ -1,3 +1,9 @@ +/** + * \file attrib.h + * + * \brief Attribute-related prototypes and constants. + */ + #ifndef _ATTRIB_H #define _ATTRIB_H @@ -13,7 +19,7 @@ struct attr { char const *name; /**< Name of attribute */ - int flags; /**< Attribute flags */ + unsigned int flags; /**< Attribute flags */ chunk_reference_t data; /**< The attribute's value, compressed */ dbref creator; /**< The attribute's creator's dbref */ boolexp write_lock; /**< Attribute lock set */ @@ -42,23 +48,36 @@ extern void attr_init_postconfig(void); extern void do_attribute_lock(dbref player, char *name, char *lock, switch_mask swi); /* From attrib.c */ + +/** atr_add(), atr_clr() error codes */ +typedef enum { + AE_OKAY = 0, /**< Success */ + AE_ERROR = -1, /**< general failure */ + AE_SAFE = -2, /**< attempt to overwrite a safe attribute */ + AE_BADNAME = -3, /**< invalid name */ + AE_TOOMANY = -4, /**< too many attribs */ + AE_TREE = -5, /**< unable to delete/create entire tree */ + AE_NOTFOUND = -6 /** No such attribute */ +} atr_err; + extern int good_atr_name(char const *s); extern ATTR *atr_match(char const *string); extern ATTR *atr_sub_branch(ATTR *branch); extern void atr_new_add(dbref thing, char const *RESTRICT atr, - char const *RESTRICT s, dbref player, int flags, + char const *RESTRICT s, dbref player, unsigned int flags, unsigned char derefs, boolexp wlock, boolexp rlock, time_t modtime); -extern int atr_add(dbref thing, char const *RESTRICT atr, - char const *RESTRICT s, dbref player, int flags); -extern int atr_clr(dbref thing, char const *atr, dbref player); +extern atr_err atr_add(dbref thing, char const *RESTRICT atr, + char const *RESTRICT s, dbref player, unsigned int flags); +extern atr_err atr_clr(dbref thing, char const *atr, dbref player); +extern atr_err wipe_atr(dbref thing, char const *atr, dbref player); extern ATTR *atr_get(dbref thing, char const *atr); extern ATTR *atr_get_noparent(dbref thing, char const *atr); typedef int (*aig_func) (dbref, dbref, dbref, const char *, ATTR *, void *); extern int atr_iter_get(dbref player, dbref thing, char const *name, int mortal, aig_func func, void *args); extern ATTR *atr_complete_match(dbref player, char const *atr, dbref privs); -extern void atr_free(dbref thing); +extern void atr_free_all(dbref thing); extern void atr_cpy(dbref dest, dbref source); extern char const *convert_atr(int oldatr); extern int atr_comm_match(dbref thing, dbref player, int type, int end, @@ -70,7 +89,7 @@ extern int atr_comm_divmatch(dbref thing, dbref player, int type, int end, extern int one_comm_match(dbref thing, dbref player, const char *atr, const char *str); extern int do_set_atr(dbref thing, char const *RESTRICT atr, - char const *RESTRICT s, dbref player, int flags); + char const *RESTRICT s, dbref player, unsigned int flags); extern void do_atrlock(dbref player, char const *arg1, char const *arg2, char write_lock); extern void do_atrchown(dbref player, char const *arg1, char const *arg2); extern int string_to_atrflag(dbref player, const char *p); @@ -90,6 +109,7 @@ safe_atr_value(ATTR *atr) /* possible attribute flags */ +#define AF_EMPTY_FLAGS 0x0 /**< No flag at all */ #define AF_ODARK 0x1 /* OBSOLETE! Leave here but don't use */ #define AF_INTERNAL 0x2 /* no one can see it or set it */ #define AF_PRIVILEGE 0x4 /* Only privileged players can change it */ @@ -103,7 +123,7 @@ safe_atr_value(ATTR *atr) #define AF_REGEXP 0x400 /* Match $/^ patterns using regexps */ #define AF_CASE 0x800 /* Match $/^ patterns case-sensitive */ #define AF_SAFE 0x1000 /* This attribute may not be modified */ -#define AF_STATIC 0x10000 /* OBSOLETE! Leave here but don't use */ +#define AF_ROOT 0x10000 /* Root of an attribute tree */ #define AF_COMMAND 0x20000 /* INTERNAL: value starts with $ */ #define AF_LISTEN 0x40000 /* INTERNAL: value starts with ^ */ #define AF_NODUMP 0x80000 /* INTERNAL: attribute is not saved */ @@ -115,8 +135,16 @@ safe_atr_value(ATTR *atr) #define AF_PUBLIC 0x2000000 /* Override SAFER_UFUN */ #define AF_ANON 0x4000000 /* INTERNAL: Attribute doesn't exist in the database */ #define AF_POWINHERIT 0x8000000 /* Execute with powers of object it's on */ +#define AF_NONAME 0x10000000 /**< No name in did_it */ #define AF_MHEAR 0x20000000 /* ^-listens can be triggered by %! */ #define AF_AHEAR 0x40000000 /* ^-listens can be triggered by anyone */ +#define AF_NOSPACE 0x80000000 /**< No space in did_it */ + +#define AF_MAXVAL 0x100000000 /**< Largest attribute flag value. */ + +/*** external predefined attributes. */ + extern ATTR attr[]; + /* external predefined attributes. */ extern ATTR attr[]; @@ -135,10 +163,14 @@ safe_atr_value(ATTR *atr) #define AL_RLock(alist) ((alist)->read_lock) #define AL_MODTIME(alist) ((alist)->last_modified) -/* Errors from ok_player_alias */ -#define OPAE_SUCCESS 1 -#define OPAE_INVALID -1 -#define OPAE_TOOMANY -2 -#define OPAE_NULL -3 +/** Errors from ok_player_alias */ +/** Success */ +#define OPAE_SUCCESS 1 +/** Invalid alias */ +#define OPAE_INVALID -1 +/** Too many aliases already set */ +#define OPAE_TOOMANY -2 +/** Null alias */ +#define OPAE_NULL -3 #endif /* __ATTRIB_H */ diff --git a/hdrs/chunk.h b/hdrs/chunk.h index 25fa8cf..9eb38e8 100644 --- a/hdrs/chunk.h +++ b/hdrs/chunk.h @@ -1,5 +1,4 @@ -/* This must be first, otherwise dbref will be undefined */ -#include "mushtype.h" +/* Must be included after mushtype.h to get dbref typedef */ #ifndef _CHUNK_H_ #define _CHUNK_H_ diff --git a/src/atr_tab.c b/src/atr_tab.c index dbc9076..72c915e 100644 --- a/src/atr_tab.c +++ b/src/atr_tab.c @@ -86,6 +86,7 @@ PRIV attr_privs_view[] = { {"nearby", 'n', AF_NEARBY, AF_NEARBY}, {"amhear", 'M', AF_MHEAR, AF_MHEAR}, {"aahear", 'A', AF_AHEAR, AF_AHEAR}, + {"root", '`', AF_ROOT, AF_ROOT}, {NULL, '\0', 0, 0} }; diff --git a/src/attrib.c b/src/attrib.c index 1906b6b..e261366 100644 --- a/src/attrib.c +++ b/src/attrib.c @@ -31,15 +31,6 @@ #pragma warning( disable : 4761) /* disable warning re conversion */ #endif -/** Attribute error - too many attribs */ -#define AE_TOOMANY -4 -/** Attribute error - invalid name */ -#define AE_BADNAME -3 -/** Attribute error - attempt to overwrite a safe attribute */ -#define AE_SAFE -2 -/** Attribute error - general failure */ -#define AE_ERROR -1 - /* Catchall Attribute any non-standard attributes will conform to this */ ATTR *catchall; @@ -52,13 +43,9 @@ extern PRIV attr_privs_set[]; extern PRIV attr_privs_view[]; dbref atr_on_obj = NOTHING; -/** A flag to show if we're in the middle of a @wipe (this changes - * behaviour for atr_clr()). Yes, this is gross and ugly, but it - * seemed like a better idea than propogating signature changes - * for atr_clr() and do_set_atr() through the entire codebase. If - * you come up with a better way, PLEASE fix this... - */ -int we_are_wiping; +static int real_atr_clr(dbref thinking, char const *atr, dbref player, + int we_are_wiping); + dbref global_parent_depth[] = { 0, 0 }; @@ -81,11 +68,17 @@ typedef struct atrpage { ATTR atrs[ATTRS_PER_PAGE]; /**< Array of attribute structures */ } ATTRPAGE; -static ATTR *atr_free_list; -static ATTR *get_atr_free_list(void); +static int atr_clear_children(dbref player, dbref thing, ATTR *root); +static ATTR *atr_free_list = NULL; +static ATTR *alloc_atr(void); +static ATTR *pop_free_list(void); +static void push_free_list(ATTR *); +static void atr_free_one(ATTR *); static ATTR *find_atr_pos_in_list(ATTR *** pos, char const *name); +static atr_err can_create_attr(dbref player, dbref obj, char const *atr_name, + unsigned int flags); static int can_create_attr(dbref player, dbref obj, char const *atr_name, - int flags); + unsigned int flags); static ATTR *find_atr_in_list(ATTR * atr, char const *name); /** Utility define for can_write_attr_internal and can_create_attr. @@ -264,7 +257,7 @@ find_atr_in_list(ATTR * atr, char const *name) return NULL; } -/** Find the place to insert/delete an attribute with the specified name. +/** Find the place to insert an attribute with the specified name. * \param pos a pointer to the ATTR ** holding the list position * \param name the attribute name to look for * \return the matching attribute, or NULL if no matching attribute @@ -358,8 +351,7 @@ atrflag_to_string(int mask) lock_owner = AL_CREATOR(std); \ ns_chk = 0; \ } else { \ - if (flags != NOTHING) \ - AL_FLAGS(atr) |= flags; \ + AL_FLAGS(atr) = flags; \ AL_WLock(atr) = AL_RLock(atr) = TRUE_BOOLEXP; \ lock_owner = NOTHING; \ ns_chk = 1; \ @@ -377,12 +369,14 @@ atrflag_to_string(int mask) * \param player the player trying to do the write. * \param obj the object targetted for the write. * \param atr the attribute being interrogated. - * \param flags the default flags to add to the attribute. + * \param flags the default flags to add to the attribute. + * 0 for default flags if it's a builtin attribute. * \retval 0 if the player cannot write the attribute. * \retval 1 if the player can write the attribute. */ static int -can_create_attr(dbref player, dbref obj, char const *atr_name, int flags) +can_create_attr(dbref player, dbref obj, char const *atr_name, + unsigned int flags) { char *p; ATTR tmpatr, *atr; @@ -447,7 +441,7 @@ can_create_attr(dbref player, dbref obj, char const *atr_name, int flags) return AE_TOOMANY; } - return 1; + return AE_OKAY; } /*======================================================================*/ @@ -469,8 +463,11 @@ create_atr(dbref thing, char const *atr_name) return NULL; /* allocate a new page, if needed */ - ptr = get_atr_free_list(); - atr_free_list = AL_NEXT(ptr); + ptr = pop_free_list(); + if (ptr == NULL) { + st_delete(name, &atr_names); + return NULL; + } /* initialize atr */ AL_WLock(ptr) = TRUE_BOOLEXP; @@ -503,11 +500,14 @@ create_atr(dbref thing, char const *atr_name) */ void atr_new_add(dbref thing, const char *RESTRICT atr, const char *RESTRICT s, - dbref player, int flags, unsigned char derefs, boolexp wlock, + dbref player, unsigned int flags, unsigned char derefs, boolexp wlock, boolexp rlock, time_t modtime) { ATTR *ptr; boolexp lock; + dbref lock_owner; + int ns_chk; + char *p, root_name[ATTRIBUTE_NAME_LIMIT + 1]; if (!EMPTY_ATTRS && !*s) return; @@ -527,7 +527,35 @@ atr_new_add(dbref thing, const char *RESTRICT atr, const char *RESTRICT s, if((lock = dup_bool(rlock))) AL_RLock(ptr) = lock; - AL_FLAGS(ptr) = (flags != NOTHING) ? flags : 0; + strcpy(root_name, atr); + if ((p = strrchr(root_name, '`'))) { + ATTR *root = NULL; + *p = '\0'; + root = find_atr_in_list(List(thing), root_name); + if (!root) { + do_rawlog(LT_ERR, T("Missing root attribute '%s' on object #%d!\n"), + root_name, thing); + root = create_atr(thing, root_name); + set_default_flags(root, 0, lock_owner, ns_chk); + if(lock_owner == NOTHING) + lock_owner = player; + AL_FLAGS(root) |= AF_ROOT; + AL_CREATOR(root) = player; + if (!EMPTY_ATTRS) { + unsigned char *t = compress(" "); + if (!t) { + mush_panic(T("Unable to allocate memory in atr_new_add()!")); + } + root->data = chunk_create(t, u_strlen(t), 0); + free(t); + } + } else { + if (!AL_FLAGS(root) & AF_ROOT) /* Upgrading old database */ + AL_FLAGS(root) |= AF_ROOT; + } + } + + AL_FLAGS(ptr) = flags; AL_FLAGS(ptr) &= ~AF_COMMAND & ~AF_LISTEN; AL_CREATOR(ptr) = ooref != NOTHING ? ooref : player; @@ -540,6 +568,7 @@ atr_new_add(dbref thing, const char *RESTRICT atr, const char *RESTRICT s, unsigned char *t = compress(s); if (!t) return; + ptr->data = chunk_create(t, u_strlen(t), derefs); free(t); @@ -560,17 +589,16 @@ atr_new_add(dbref thing, const char *RESTRICT atr, const char *RESTRICT s, * \param atr name of the attribute to set. * \param s value of the attribute to set. * \param player the attribute creator. - * \param flags bitmask of attribute flags for this attribute. - * \retval AE_BADNAME invalid attribute name. - * \retval AE_SAFE attempt to overwrite a SAFE attribute. - * \retval AE_ERROR general failure. - * \retval 1 success. + * \param flags bitmask of attribute flags for this attribute. 0 will use + * default. + * \return AE_OKAY or an AE_* error code. */ -int + +atr_err atr_add(dbref thing, const char *RESTRICT atr, const char *RESTRICT s, - dbref player, int flags) + dbref player, unsigned int flags) { - ATTR *ptr; + ATTR *ptr, *root = NULL; dbref lock_owner; /* Not used.. but set in set_default_flags */ int ns_chk; char *p; @@ -604,8 +632,8 @@ atr_add(dbref thing, const char *RESTRICT atr, const char *RESTRICT s, /* make a new atr, if needed */ if (!ptr) { - int res = can_create_attr(player, thing, atr, flags); - if (res < 0) { + atr_err res = can_create_attr(player, thing, atr, flags); + if (res != AE_OKAY) { ooref = tooref; return res; } @@ -615,13 +643,13 @@ atr_add(dbref thing, const char *RESTRICT atr, const char *RESTRICT s, for (p = strchr(missing_name, '`'); p; p = strchr(p + 1, '`')) { *p = '\0'; - ptr = find_atr_in_list(ptr, missing_name); + root = find_atr_in_list(ptr, missing_name); - if (!ptr) { - ptr = create_atr(thing, missing_name); - if (!ptr) { + if (!root) { + root = create_atr(thing, missing_name); + if (!root) { ooref = tooref; - return AE_ERROR; + return AE_TREE; } /* update modification time here, because from now on, @@ -634,20 +662,21 @@ atr_add(dbref thing, const char *RESTRICT atr, const char *RESTRICT s, set_lmod(thing, lmbuf); } - set_default_flags(ptr, flags, lock_owner, ns_chk); - AL_FLAGS(ptr) &= ~AF_COMMAND & ~AF_LISTEN; - AL_CREATOR(ptr) = ooref != NOTHING ? Owner(ooref) : Owner(player); - AL_MODTIME(ptr) = mudtime; + set_default_flags(root, flags, lock_owner, ns_chk); + AL_FLAGS(root) &= ~AF_COMMAND & ~AF_LISTEN; + AL_FLAGS(root) |= AF_ROOT; + AL_CREATOR(root) = ooref != NOTHING ? Owner(ooref) : Owner(player); + AL_MODTIME(root) = mudtime; if (!EMPTY_ATTRS) { unsigned char *t = compress(" "); if (!t) { + mush_panic(T("Unable to allocate memory in atr_add()!")); ooref = tooref; - return AE_ERROR; } - ptr->data = chunk_create(t, u_strlen(t), 0); + root->data = chunk_create(t, u_strlen(t), 0); free(t); } - } + } else AL_FLAGS(root) |= AF_ROOT; *p = '`'; } @@ -707,15 +736,14 @@ atr_add(dbref thing, const char *RESTRICT atr, const char *RESTRICT s, * \param thing object to clear attribute from. * \param atr name of attribute to remove. * \param player enactor attempting to remove attribute. - * \retval 0 no attribute found to reset - * \retval AE_SAFE attribute is safe - * \retval AE_ERROR other failure + * \param we_are_wiping true if called by \@wipe. + * \return AE_OKAY or AE_* error code. */ -int -atr_clr(dbref thing, char const *atr, dbref player) +static atr_err +real_atr_clr(dbref thing, char const *atr, dbref player, int we_are_wiping) { - ATTR *ptr, **prev, *sub; - size_t len; + ATTR *ptr, **prev; + int can_clear = 1; tooref = ooref; if (player == GOD) @@ -726,7 +754,7 @@ atr_clr(dbref thing, char const *atr, dbref player) if (!ptr) { ooref = tooref; - return 0; + return AE_NOTFOUND; } if (ptr && AF_Safe(ptr)) { @@ -738,59 +766,79 @@ atr_clr(dbref thing, char const *atr, dbref player) return AE_ERROR; } - sub = atr_sub_branch(ptr); - if (!we_are_wiping && sub) { + if ((AL_FLAGS(ptr) & AF_ROOT) && !we_are_wiping) { ooref = tooref; - return AE_ERROR; - } - - if (!IsPlayer(thing) && !AF_Nodump(ptr)) { - char lmbuf[1024]; - ModTime(thing) = mudtime; - snprintf(lmbuf, 1023, "%s[#%d]", ptr->name, player); - lmbuf[strlen(lmbuf) + 1] = '\0'; - set_lmod(thing, lmbuf); + return AE_TREE; } - *prev = AL_NEXT(ptr); + /* We only hit this if wiping. */ + if (AL_FLAGS(ptr) & AF_ROOT) + can_clear = atr_clear_children(player, thing, ptr); - if (ptr->data) - chunk_delete(ptr->data); + if (can_clear) { + char *p; + char root_name[ATTRIBUTE_NAME_LIMIT + 1]; - len = strlen(AL_NAME(ptr)); - st_delete(AL_NAME(ptr), &atr_names); + strcpy(root_name, AL_NAME(ptr)); - free_atr_locks(ptr); - - AL_NEXT(ptr) = atr_free_list; - AL_FLAGS(ptr) = 0; - atr_free_list = ptr; - AttrCount(thing)--; - - if (we_are_wiping && sub) { - while (*prev != sub) - prev = &AL_NEXT(*prev); - ptr = *prev; - while (ptr && strlen(AL_NAME(ptr)) > len && AL_NAME(ptr)[len] == '`') { - *prev = AL_NEXT(ptr); - - if (ptr->data) - chunk_delete(ptr->data); - st_delete(AL_NAME(ptr), &atr_names); - - AL_NEXT(ptr) = atr_free_list; - AL_FLAGS(ptr) = 0; - atr_free_list = ptr; - AttrCount(thing)--; - - ptr = *prev; - } - } - ooref = tooref; - return 1; + if (!IsPlayer(thing) && !AF_Nodump(ptr)) + ModTime(thing) = mudtime; + *prev = AL_NEXT(ptr); + atr_free_one(ptr); + AttrCount(thing)--; + + /* If this was the only leaf of a tree, clear the AF_ROOT flag from + * the parent. */ + if ((p = strrchr(root_name, '`'))) { + ATTR *root; + *p = '\0'; + + root = find_atr_in_list(List(thing), root_name); + *p = '`'; + + if (!root) { + do_rawlog(LT_ERR, T("Attribute %s on object #%d lacks a parent!"), + root_name, thing); + } else { + if (!atr_sub_branch(root)) + AL_FLAGS(root) &= ~AF_ROOT; + } + } + + return AE_OKAY; + } else + return AE_TREE; } -/** Retrieve an attribute from an object or its ancestors. +/* Remove an attribute from an object. + * This function clears an attribute from an object. + * Permission is denied if the attribute is a branch, not a leaf. + * \param thing object to clear attribute from. + * \param atr name of attribute to remove. + * \param player enactor attempting to remove attribute. + * \return AE_OKAY or an AE_* error code + */ +atr_err +atr_clr(dbref thing, char const *atr, dbref player) +{ + return real_atr_clr(thing, atr, player, 0); +} + + +/* \@wipe an attribute (And any leaves) from an object. + * This function clears an attribute from an object. + * \param thing object to clear attribute from. + * \param atr name of attribute to remove. + * \param player enactor attempting to remove attribute. + * \return AE_OKAY or an AE_* error code. + */ +atr_err +wipe_atr(dbref thing, char const *atr, dbref player) +{ + return real_atr_clr(thing, atr, player, 1); +} + + /** Retrieve an attribute from an object or its ancestors. * This function retrieves an attribute from an object, or from its * parent chain, returning a pointer to the first attribute that * matches or NULL. This is a pointer to an attribute structure, not @@ -965,7 +1013,7 @@ atr_iter_get(dbref player, dbref thing, const char *name, int mortal, * \param thing dbref of object */ void -atr_free(dbref thing) +atr_free_all(dbref thing) { ATTR *ptr; @@ -982,17 +1030,7 @@ atr_free(dbref thing) while ((ptr = List(thing))) { List(thing) = AL_NEXT(ptr); - if (AL_WLock(ptr) != TRUE_BOOLEXP) - free_boolexp(AL_WLock(ptr)); - if (AL_RLock(ptr) != TRUE_BOOLEXP) - free_boolexp(AL_RLock(ptr)); - - if (ptr->data) - chunk_delete(ptr->data); - st_delete(AL_NAME(ptr), &atr_names); - - AL_NEXT(ptr) = atr_free_list; - atr_free_list = ptr; + atr_free_one(ptr); } } @@ -1740,12 +1778,12 @@ one_comm_match(dbref thing, dbref player, const char *atr, const char *str) */ int do_set_atr(dbref thing, const char *RESTRICT atr, const char *RESTRICT s, - dbref player, int flags) + dbref player, unsigned int flags) { ATTR *old; char name[BUFFER_LEN]; char tbuf1[BUFFER_LEN]; - int res; + atr_err res; int was_hearer; int was_listener; dbref contents; @@ -1850,14 +1888,26 @@ do_set_atr(dbref thing, const char *RESTRICT atr, const char *RESTRICT s, s ? atr_add(thing, name, s, player, (flags & 0x02) ? AF_NOPROG : NOTHING) : atr_clr(thing, name, player); - if (res == AE_SAFE) { + switch (res) { + case AE_SAFE: notify_format(player, T("Attribute %s is SAFE. Set it !SAFE to modify it."), name); return 0; - } else if (res == AE_BADNAME) { - notify(player, T("That's not a very good name for an attribute.")); + case AE_TREE: + if (!s) { + notify_format(player, + T("Unable to remove '%s' because of a protected tree attribute."), + name); + return 0; + } else { + notify_format(player, + T("Unable to set '%s' because of a failure to create a needed parent attribute."), name); + return 0; + } + case AE_BADNAME: + notify_format(player, T("That's not a very good name for an attribute.")); return 0; - } else if (res == AE_ERROR) { + case AE_ERROR: if (*missing_name) { if (s && (EMPTY_ATTRS || *s)) notify_format(player, T("You must set %s first."), missing_name); @@ -1869,12 +1919,15 @@ do_set_atr(dbref thing, const char *RESTRICT atr, const char *RESTRICT s, } else notify(player, T("That attribute cannot be changed by you.")); return 0; - } else if (res == AE_TOOMANY) { + case AE_TOOMANY: notify(player, T("Too many attributes on that object to add another.")); return 0; - } else if (!res) { + case AE_NOTFOUND: notify(player, T("No such attribute to reset.")); return 0; + case AE_OKAY: + /* Success */ + break; } if (!strcmp(name, "ALIAS") && IsPlayer(thing)) { reset_player_list(thing, NULL, tbuf1, NULL, s); @@ -2075,14 +2128,14 @@ do_atrchown(dbref player, const char *arg1, const char *arg2) * \return the pointer to the head of the attribute free list. */ static ATTR * -get_atr_free_list(void) +alloc_atr(void) { if (!atr_free_list) { ATTRPAGE *page; int j; page = (ATTRPAGE *) mush_malloc(sizeof(ATTRPAGE), "ATTRPAGE"); if (!page) - mush_panic("Couldn't allocate memory in get_atr_free_list"); + mush_panic("Couldn't allocate memory in alloc_attr"); for (j = 0; j < ATTRS_PER_PAGE - 1; j++) AL_NEXT(page->atrs + j) = page->atrs + j + 1; AL_NEXT(page->atrs + ATTRS_PER_PAGE - 1) = NULL; @@ -2272,7 +2325,105 @@ can_write_attr_internal(dbref player, dbref obj, ATTR * atr, int safe) *p = '`'; } - return 1; + return AE_OKAY; +} + + +/** Remove all child attributes from root attribute that can be. + * \param player object doing a @wipe. + * \param thing object being @wiped. + * \param root root of attribute tree. + * \return 1 if all children were deleted, 0 if some were left. + */ +static int +atr_clear_children(dbref player, dbref thing, ATTR *root) +{ + ATTR *sub, *next = NULL, *prev; + int skipped = 0; + + prev = root; + + for (sub = atr_sub_branch(root); + sub && string_prefix(AL_NAME(sub), AL_NAME(root)); sub = next) { + if (AL_FLAGS(sub) & AF_ROOT) { + if (!atr_clear_children(player, thing, sub)) { + skipped++; + next = AL_NEXT(sub); + prev = sub; + continue; + } + } + + next = AL_NEXT(sub); + + if (!Can_Write_Attr(player, thing, sub)) { + skipped++; + prev = sub; + continue; + } + + /* Can safely delete attribute. */ + AL_NEXT(prev) = next; + atr_free_one(sub); + AttrCount(thing)--; + + } + + return !skipped; + +} + +/** Pop an empty attribute off of the free list for use on + * an object. + * \return the pointer to an attribute, or NULL on error. + */ +static ATTR * +pop_free_list(void) +{ + ATTR *ptr; + ptr = alloc_atr(); + if (!ptr) + return NULL; + atr_free_list = AL_NEXT(ptr); + AL_NEXT(ptr) = NULL; + return ptr; +} + +/** Push a now-unused attribute onto the free list + * \param An attribute that's been deleted from an object and + * had its chunk reference deleted. + */ +static void +push_free_list(ATTR *a) +{ + memset(a, 0, sizeof(*a)); + AL_NEXT(a) = atr_free_list; + atr_free_list = a; +} + +/** Delete one attribute, deallocating its name and data. + * Does not update the owning object's attribute list or + * attribute count. That is the caller's responsibility. + * + * \param a the attribute to free + */ +static void +atr_free_one(ATTR *a) +{ + if (!a) + return; + + if (AL_WLock(a) != TRUE_BOOLEXP) + free_boolexp(AL_WLock(a)); + if (AL_RLock(a) != TRUE_BOOLEXP) + free_boolexp(AL_RLock(a)); + + st_delete(AL_NAME(a), &atr_names); + + if (a->data) + chunk_delete(a->data); + + push_free_list(a); } /** Return the compressed data for an attribute. diff --git a/src/bsd.c b/src/bsd.c index f2efb8b..085fa01 100644 --- a/src/bsd.c +++ b/src/bsd.c @@ -1468,7 +1468,7 @@ logout_sock(DESC *d) snprintf(tbuf1, BUFFER_LEN-1, "%ld %ld %d %d", (mudtime - d->connected_at), d->idle_total, d->unidle_times, d->cmds); tbuf1[strlen(tbuf1)+1] = '\0'; - (void) atr_add(d->player, "LASTACTIVITY", tbuf1, GOD, NOTHING); + (void) atr_add(d->player, "LASTACTIVITY", tbuf1, GOD, 0); announce_disconnect(d->player); #ifdef USE_MAILER do_mail_purge(d->player); @@ -1552,7 +1552,7 @@ shutdownsock(DESC *d) snprintf(tbuf1, BUFFER_LEN-1, "%ld %ld %d %d", (mudtime - d->connected_at), d->idle_total , d->unidle_times, d->cmds); tbuf1[strlen(tbuf1)+1] = '\0'; - (void) atr_add(d->player, "LASTACTIVITY", tbuf1, GOD, NOTHING); + (void) atr_add(d->player, "LASTACTIVITY", tbuf1, GOD, 0); announce_disconnect(d->player); #ifdef USE_MAILER do_mail_purge(d->player); @@ -3887,7 +3887,7 @@ announce_disconnect(dbref player) (void) queue_attribute(obj, "ADISCONNECT", player); } clear_flag_internal(player, "CONNECTED"); - (void) atr_add(player, "LASTLOGOUT", show_time(mudtime, 0), GOD, NOTHING); + (void) atr_add(player, "LASTLOGOUT", show_time(mudtime, 0), GOD, 0); } else { /* note: when you partially disconnect, ADISCONNECTS are not executed */ sprintf(tbuf1, T("%s has partially disconnected."), Name(player)); @@ -5323,7 +5323,7 @@ load_reboot_db(void) snprintf(tbuf1, BUFFER_LEN-1, "%ld %ld %d %d", (mudtime - closed->connected_at), closed->idle_total , closed->unidle_times, closed->cmds); tbuf1[strlen(tbuf1)+1] = '\0'; - (void) atr_add(closed->player, "LASTACTIVITY", tbuf1, GOD, NOTHING); + (void) atr_add(closed->player, "LASTACTIVITY", tbuf1, GOD, 0); announce_disconnect(closed->player); mush_free(closed, "descriptor"); closed = nextclosed; @@ -5646,7 +5646,7 @@ COMMAND(cmd_su) { sep[1] = '\0'; arr2list(p_buf, cnt-1, tbuf, &tbp, sep); /* Add the attribute back */ - (void) atr_add(player, "XYXX_DIVRCD", tbuf, GOD, NOTHING); + (void) atr_add(player, "XYXX_DIVRCD", tbuf, GOD, 0); } } else { notify(player, "Must specify what player you wish to @su into."); diff --git a/src/cque.c b/src/cque.c index 48e5343..c60d193 100644 --- a/src/cque.c +++ b/src/cque.c @@ -182,7 +182,7 @@ add_to_generic(dbref player, int am, const char *name, int flags) static int add_to(dbref player, int am) { - return (add_to_generic(player, am, "QUEUE", NOTHING)); + return (add_to_generic(player, am, "QUEUE", 0)); } static int diff --git a/src/db.c b/src/db.c index b961e26..4be028a 100644 --- a/src/db.c +++ b/src/db.c @@ -1247,7 +1247,7 @@ db_free(void) for (i = 0; i < db_top; i++) { set_name(i, NULL); set_lmod(i, NULL); - atr_free(i); + atr_free_all(i); free_locks(Locks(i)); } @@ -1294,9 +1294,8 @@ get_list(FILE * f, dbref i) } *q++ = '\0'; flags = atoi(q); - /* Remove obsolete AF_NUKED flag and AF_STATIC, just in case */ + /* Remove obsolete AF_NUKED flag just in case */ flags &= ~AF_NUKED; - flags &= ~AF_STATIC; if (!(indb_flags & DBF_AF_VISUAL)) { /* Remove AF_ODARK flag. If it wasn't there, set AF_VISUAL */ if (!(flags & AF_ODARK)) diff --git a/src/destroy.c b/src/destroy.c index 0c23386..67db9a8 100644 --- a/src/destroy.c +++ b/src/destroy.c @@ -704,7 +704,7 @@ free_object(dbref thing) } /* chomp chomp */ - atr_free(thing); + atr_free_all(thing); List(thing) = NULL; /* don't eat name otherwise examine will crash */ diff --git a/src/funstr.c b/src/funstr.c index 52b05b0..c4efed0 100644 --- a/src/funstr.c +++ b/src/funstr.c @@ -2205,9 +2205,10 @@ FUNCTION(fun_speak) else close = args[6]; + switch (*string) { case ':': - safe_str(Name(speaker), buff, bp); + safe_str(accented_name(speaker), buff, bp); string++; if (*string == ' ') { /* semipose it instead */ @@ -2218,7 +2219,7 @@ FUNCTION(fun_speak) break; case ';': string++; - safe_str(Name(speaker), buff, bp); + safe_str(accented_name(speaker), buff, bp); if (*string == ' ') { /* pose it instead */ safe_chr(' ', buff, bp); @@ -2240,7 +2241,8 @@ FUNCTION(fun_speak) if (!transform || (!say && !strstr(string, open))) { /* nice and easy */ if (say) - safe_format(buff, bp, "%s %s \"%s\"", Name(speaker), say_string, string); + safe_format(buff, bp, "%s %s \"%s\"", accented_name(speaker), + say_string, string); else safe_str(string, buff, bp); LEAVE_OOREF; @@ -2258,7 +2260,7 @@ FUNCTION(fun_speak) return; } if (strlen(rbuff) > 0) { - safe_format(buff, bp, "%s %s %s", Name(speaker), say_string, rbuff); + safe_format(buff, bp, "%s %s %s", accented_name(speaker), say_string, rbuff); LEAVE_OOREF; return; } else if (null == 1) { @@ -2280,7 +2282,7 @@ FUNCTION(fun_speak) int delete = 0; if (say) { - safe_str(Name(speaker), buff, bp); + safe_str(accented_name(speaker), buff, bp); safe_chr(' ', buff, bp); safe_str(say_string, buff, bp); safe_chr(' ', buff, bp); diff --git a/src/funtime.c b/src/funtime.c index 518cf62..aa9bec5 100644 --- a/src/funtime.c +++ b/src/funtime.c @@ -20,6 +20,7 @@ #include "externs.h" #include "parse.h" #include "dbdefs.h" +#include "attrib.h" #include "log.h" #include "match.h" #include "attrib.h" diff --git a/src/game.c b/src/game.c index 37d3db2..005a52d 100644 --- a/src/game.c +++ b/src/game.c @@ -1954,7 +1954,7 @@ do_dolist(dbref player, char *list, char *command, dbref cause, *bp = '\0'; if (flags & DOL_MAP) { /* if we're doing a @map, copy the list to an attribute */ - (void) atr_add(player, "MAPLIST", outbuf, GOD, NOTHING); + (void) atr_add(player, "MAPLIST", outbuf, GOD, 0); notify(player, T("Function mapped onto list.")); } if (flags & DOL_NOTIFY) { diff --git a/src/look.c b/src/look.c index d878328..a563d60 100644 --- a/src/look.c +++ b/src/look.c @@ -27,8 +27,10 @@ #include "command.h" #include "parse.h" #include "privtab.h" -#include "confmagic.h" #include "log.h" +#include "case.h" +#include "confmagic.h" + static void look_exits(dbref player, dbref loc, const char *exit_name); static void look_contents(dbref player, dbref loc, const char *contents_name); @@ -344,8 +346,6 @@ look_helper_veiled(dbref player, dbref thing __attribute__ ((__unused__)), !strcmp(AL_NAME(atr), "DESCRIBE") && !strcmp(pattern, "*")) return 0; strcpy(fbuf, privs_to_letters(attr_privs_view, AL_FLAGS(atr))); - if (atr_sub_branch(atr)) - strcat(fbuf, "`"); if (AF_Veiled(atr)) { if (ShowAnsi(player)) notify_format(player, @@ -388,8 +388,6 @@ look_helper(dbref player, dbref thing __attribute__ ((__unused__)), !strcmp(AL_NAME(atr), "DESCRIBE") && !strcmp(pattern, "*")) return 0; strcpy(fbuf, privs_to_letters(attr_privs_view, AL_FLAGS(atr))); - if (atr_sub_branch(atr)) - strcat(fbuf, "`"); r = safe_atr_value(atr); if (ShowAnsi(player)) notify_format(player, @@ -1637,7 +1635,7 @@ decompose_str(char *what) } /* If background color, change the letter to a capital. */ if (*(ptr - 1) == '4') - ansi_letter = toupper(ansi_letter); + ansi_letter = UPCASE(ansi_letter); safe_chr(ansi_letter, value, &s); } /* No "else" here: If a two-digit code @@ -1708,7 +1706,7 @@ decompile_helper(dbref player, dbref thing __attribute__ ((__unused__)), if (dh->skipdef && ptr) { /* Standard attribute. Get the default perms, if any. */ /* Are we different? If so, do as usual */ - int npmflags = AL_FLAGS(ptr) & (~AF_PREFIXMATCH); + unsigned int npmflags = AL_FLAGS(ptr) & (~AF_PREFIXMATCH); if (AL_FLAGS(atr) != AL_FLAGS(ptr) && AL_FLAGS(atr) != npmflags) privs = privs_to_string(attr_privs_view, AL_FLAGS(atr)); } else { diff --git a/src/move.c b/src/move.c index d58e799..65b9aed 100644 --- a/src/move.c +++ b/src/move.c @@ -1127,14 +1127,14 @@ add_follower(dbref leader, dbref follower) char *bp; a = atr_get_noparent(leader, "FOLLOWERS"); if (!a) { - (void) atr_add(leader, "FOLLOWERS", unparse_dbref(follower), GOD, NOTHING); + (void) atr_add(leader, "FOLLOWERS", unparse_dbref(follower), GOD, 0); } else { bp = tbuf1; safe_str(atr_value(a), tbuf1, &bp); safe_chr(' ', tbuf1, &bp); safe_dbref(follower, tbuf1, &bp); *bp = '\0'; - (void) atr_add(leader, "FOLLOWERS", tbuf1, GOD, NOTHING); + (void) atr_add(leader, "FOLLOWERS", tbuf1, GOD, 0); } } @@ -1147,14 +1147,14 @@ add_following(dbref follower, dbref leader) char *bp; a = atr_get_noparent(follower, "FOLLOWING"); if (!a) { - (void) atr_add(follower, "FOLLOWING", unparse_dbref(leader), GOD, NOTHING); + (void) atr_add(follower, "FOLLOWING", unparse_dbref(leader), GOD, 0); } else { bp = tbuf1; safe_str(atr_value(a), tbuf1, &bp); safe_chr(' ', tbuf1, &bp); safe_dbref(leader, tbuf1, &bp); *bp = '\0'; - (void) atr_add(follower, "FOLLOWING", tbuf1, GOD, NOTHING); + (void) atr_add(follower, "FOLLOWING", tbuf1, GOD, 0); } } @@ -1186,8 +1186,7 @@ del_follower(dbref leader, dbref follower) /* Let's take it apart and put it back together w/o follower */ strcpy(flwr, unparse_dbref(follower)); strcpy(tbuf1, atr_value(a)); - (void) atr_add(leader, "FOLLOWERS", - remove_word(tbuf1, flwr, ' '), GOD, NOTHING); + (void) atr_add(leader, "FOLLOWERS", remove_word(tbuf1, flwr, ' '), GOD, 0); } /* Delete someone from a player's FOLLOWING attribute */ @@ -1203,8 +1202,7 @@ del_following(dbref follower, dbref leader) /* Let's take it apart and put it back together w/o leader */ strcpy(ldr, unparse_dbref(leader)); strcpy(tbuf1, atr_value(a)); - (void) atr_add(follower, "FOLLOWING", - remove_word(tbuf1, ldr, ' '), GOD, NOTHING); + (void) atr_add(follower, "FOLLOWING", remove_word(tbuf1, ldr, ' '), GOD, 0); } static void diff --git a/src/player.c b/src/player.c index 112264d..8206c07 100644 --- a/src/player.c +++ b/src/player.c @@ -103,7 +103,7 @@ password_check(dbref player, const char *password) return 0; } /* Something worked. Change password to SHS-encrypted */ - (void) atr_add(player, pword_attr, passwd, GOD, NOTHING); + (void) atr_add(player, pword_attr, passwd, GOD, 0); } free(saved); return 1; @@ -223,7 +223,7 @@ dbref create_guest(const char *host, const char *ip) { copy_flag_bitmask("FLAG", Flags(gst_id), flags); } mush_free((Malloc_t) guest_name, "gst_buf"); - atr_add(gst_id, "DESCRIBE", GUEST_DESCRIBE, gst_id, NOTHING); + atr_add(gst_id, "DESCRIBE", GUEST_DESCRIBE, gst_id, 0); SLEVEL(gst_id) = LEVEL_GUEST; Home(gst_id) = options.guest_start; @@ -391,7 +391,7 @@ email_register_player(const char *name, const char *email, const char *host, reserve_fd(); /* Ok, all's well, make a player */ player = make_player(name, passwd, host, ip); - (void) atr_add(player, "REGISTERED_EMAIL", email, GOD, NOTHING); + (void) atr_add(player, "REGISTERED_EMAIL", email, GOD, 0); SLEVEL(player) = LEVEL_UNREGISTERED; powergroup_db_set(NOTHING, player, PLAYER_DEF_POWERGROUP, 1); return player; @@ -432,14 +432,14 @@ make_player(const char *name, const char *password, const char *host, set_initial_warnings(player); /* Modtime tracks login failures */ ModTime(player) = (time_t) 0; - (void) atr_add(player, "XYXXY", mush_crypt(password), GOD, NOTHING); + (void) atr_add(player, "XYXXY", mush_crypt(password), GOD, 0); giveto(player, START_BONUS); /* starting bonus */ - (void) atr_add(player, "LAST", show_time(mudtime, 0), GOD, NOTHING); - (void) atr_add(player, "LASTSITE", host, GOD, NOTHING); + (void) atr_add(player, "LAST", show_time(mudtime, 0), GOD, 0); + (void) atr_add(player, "LASTSITE", host, GOD, 0); (void) atr_add(player, "LASTIP", ip, GOD, NOTHING); - (void) atr_add(player, "LASTFAILED", " ", GOD, NOTHING); + (void) atr_add(player, "LASTFAILED", " ", GOD, 0); sprintf(temp, "%d", START_QUOTA); - (void) atr_add(player, "RQUOTA", temp, GOD, NOTHING); + (void) atr_add(player, "RQUOTA", temp, GOD, 0); (void) atr_add(player, "ICLOC", EMPTY_ATTRS ? "" : " ", GOD, AF_MDARK | AF_PRIVATE | AF_NOCOPY); #ifdef USE_MAILER @@ -503,7 +503,7 @@ do_password(dbref player, dbref cause, const char *old, const char *newobj) } else if (!ok_password(newobj)) { notify(player, T("Bad new password.")); } else { - (void) atr_add(player, "XYXXY", mush_crypt(newobj), GOD, NOTHING); + (void) atr_add(player, "XYXXY", mush_crypt(newobj), GOD, 0); notify(player, T("You have changed your password.")); } } @@ -554,12 +554,12 @@ check_last(dbref player, const char *host, const char *ip) */ /* set the new attributes */ - (void) atr_add(player, "LAST", s, GOD, NOTHING); + (void) atr_add(player, "LAST", s, GOD, 0); if(!has_flag_by_name(player, "WEIRDSITE", TYPE_PLAYER)) { - (void) atr_add(player, "LASTSITE", host, GOD, NOTHING); - (void) atr_add(player, "LASTIP", ip, GOD, NOTHING); + (void) atr_add(player, "LASTSITE", host, GOD, 0); + (void) atr_add(player, "LASTIP", ip, GOD, 0); } - (void) atr_add(player, "LASTFAILED", " ", GOD, NOTHING); + (void) atr_add(player, "LASTFAILED", " ", GOD, 0); } @@ -575,5 +575,5 @@ check_lastfailed(dbref player, const char *host) bp = last_place; safe_format(last_place, &bp, T("%s on %s"), host, show_time(mudtime, 0)); *bp = '\0'; - (void) atr_add(player, "LASTFAILED", last_place, GOD, NOTHING); + (void) atr_add(player, "LASTFAILED", last_place, GOD, 0); } diff --git a/src/plyrlist.c b/src/plyrlist.c index 2f4b6c2..75377aa 100644 --- a/src/plyrlist.c +++ b/src/plyrlist.c @@ -13,11 +13,11 @@ #include #include "copyrite.h" - #include "conf.h" #include "externs.h" #include "mushdb.h" #include "dbdefs.h" +#include "attrib.h" #include "flags.h" #include "attrib.h" #include "htab.h" diff --git a/src/predicat.c b/src/predicat.c index 73ccee7..a9b4f46 100644 --- a/src/predicat.c +++ b/src/predicat.c @@ -124,11 +124,11 @@ charge_action(dbref player, dbref thing, const char *awhat) int res; if ((res = queue_attribute(thing, awhat, player))) (void) atr_add(thing, "CHARGES", tprintf("%d", num - 1), - Owner(b->creator), NOTHING); + Owner(b->creator), 0); return res; } else { /* no charges left, try to execute runout */ - return queue_attribute(thing, "RUNOUT", player); + return queue_attribute(thing, "RUNOUT", 0); } } } @@ -639,7 +639,7 @@ get_current_quota(dbref who) else limit = owned; - (void) atr_add(IsDivision(who) ? who : Owner(who), "RQUOTA", tprintf("%d", limit), GOD, NOTHING); + (void) atr_add(IsDivision(who) ? who : Owner(who), "RQUOTA", tprintf("%d", limit), GOD, 0); return limit; } @@ -657,13 +657,13 @@ change_quota(dbref who, int payment) return; (void) atr_add(Owner(who), "RQUOTA", - tprintf("%d", get_current_quota(who) + payment), GOD, NOTHING); + tprintf("%d", get_current_quota(who) + payment), GOD, 0); /* Check If Division Quota has to be adjusted now */ if(GoodObject(Division(who)) && !NoQuota(Division(who))) (void) atr_add(Division(who), "RQUOTA", - tprintf("%d", get_current_quota(Division(who)) + payment), GOD, NOTHING); + tprintf("%d", get_current_quota(Division(who)) + payment), GOD, 0); } diff --git a/src/set.c b/src/set.c index 214b2c9..6c89b1d 100644 --- a/src/set.c +++ b/src/set.c @@ -1084,9 +1084,26 @@ wipe_helper(dbref player, dbref thing, dbref parent __attribute__ ((__unused__)) * attributes using this command and wildcards. Wiping a specific * attr still works, though. */ + int saved_count = AttrCount(thing); + if (wildcard(pattern) && (AL_FLAGS(atr) & AF_PRIVILEGE) && !Director(player)) return 0; - return do_set_atr(thing, AL_NAME(atr), NULL, player, 0) == 1; + switch (wipe_atr(thing, AL_NAME(atr), player)) { + case AE_SAFE: + notify_format(player, T("Attribute %s is SAFE. Set it !SAFE to modify it."), + AL_NAME(atr)); + return 0; + case AE_ERROR: + notify_format(player, T("Unable to wipe attribute %s"), AL_NAME(atr)); + return 0; + case AE_TREE: + notify_format(player, + T("Attribute %s cannot be wiped because a child attribute cannot be wiped."), + AL_NAME(atr)); + /* Fall through */ + default: + return saved_count - AttrCount(thing); + } } /** Clear an attribute. @@ -1101,6 +1118,7 @@ do_wipe(dbref player, char *name) { dbref thing; char *pattern; + int wiped; if ((pattern = strchr(name, '/')) != NULL) *pattern++ = '\0'; @@ -1121,12 +1139,14 @@ do_wipe(dbref player, char *name) return; } - we_are_wiping = 1; - - if (!atr_iter_get(player, thing, pattern, 0, wipe_helper, NULL)) + switch ((wiped = atr_iter_get(player, thing, pattern, 0, wipe_helper, NULL))) { + case 0: notify(player, T("No attributes wiped.")); - else - notify(player, T("Attributes wiped.")); - - we_are_wiping = 0; + break; + case 1: + notify(player, T("One attribute wiped.")); + break; + default: + notify_format(player, T("%d attributes wiped."), wiped); + } } diff --git a/src/speech.c b/src/speech.c index a2e9fc0..c24c41a 100644 --- a/src/speech.c +++ b/src/speech.c @@ -849,7 +849,7 @@ do_page(dbref player, const char *arg1, const char *arg2, dbref cause, } *tp = '\0'; *tp2 = '\0'; - (void) atr_add(player, "LASTPAGED", tbuf, GOD, NOTHING); + (void) atr_add(player, "LASTPAGED", tbuf, GOD, 0); /* Reset tbuf to use later */ tp = tbuf; diff --git a/src/timer.c b/src/timer.c index 0d9ed7d..dd2bca8 100644 --- a/src/timer.c +++ b/src/timer.c @@ -39,6 +39,7 @@ #include "game.h" #include "help.h" #include "parse.h" +#include "attrib.h" #include "confmagic.h" diff --git a/src/unparse.c b/src/unparse.c index 59f2d91..62278bb 100644 --- a/src/unparse.c +++ b/src/unparse.c @@ -121,7 +121,6 @@ real_unparse(dbref player, dbref loc, int obey_myopic, int use_nameformat, static char buf[BUFFER_LEN], *bp; static char tbuf1[BUFFER_LEN]; char *p; - int got_nameformat = 0; couldunparse = 0; if (!(GoodObject(loc) || (loc == NOTHING) || (loc == AMBIGUOUS) || @@ -146,14 +145,12 @@ real_unparse(dbref player, dbref loc, int obey_myopic, int use_nameformat, /* Don't let 'em get dbrefs when they're IC */ if ((Can_Examine(player, loc) || can_link_to(player, loc) || JumpOk(loc) || ChownOk(loc) || DestOk(loc)) && - (!Myopic(player) || !obey_myopic) && - !(use_nameformat && got_nameformat) - ) { + (!Myopic(player) || !obey_myopic)) { /* show everything */ if (SUPPORT_PUEBLO) couldunparse = 1; bp = buf; - if (ANSI_NAMES && ShowAnsi(player) && !got_nameformat) + if (ANSI_NAMES && ShowAnsi(player)) safe_format(buf, &bp, "%s%s%s(#%d%s)", ANSI_HILITE, tbuf1, ANSI_NORMAL, loc, unparse_flags(loc, player)); else @@ -162,7 +159,7 @@ real_unparse(dbref player, dbref loc, int obey_myopic, int use_nameformat, *bp = '\0'; } else { /* show only the name */ - if (ANSI_NAMES && ShowAnsi(player) && !got_nameformat) { + if (ANSI_NAMES && ShowAnsi(player)) { bp = buf; safe_format(buf, &bp, "%s%s%s", ANSI_HILITE, tbuf1, ANSI_NORMAL); *bp = '\0'; diff --git a/src/wiz.c b/src/wiz.c index fa19335..5379258 100644 --- a/src/wiz.c +++ b/src/wiz.c @@ -221,7 +221,7 @@ do_quota(dbref player, const char *arg1, const char *arg2, int set_q) limit = dlimit; (void) atr_add(!IsDivision(who) ? Owner(who) : who, "RQUOTA", tprintf("%d", limit - owned), GOD, - NOTHING); + 0); notify_format(player, T("Objects: %d Limit: %d"), owned, limit); } @@ -284,10 +284,10 @@ do_allquota(dbref player, const char *arg1, int quiet) } if (limit != -1) { if (limit <= owned) { - (void) atr_add(who, "RQUOTA", "0", GOD, NOTHING); + (void) atr_add(who, "RQUOTA", "0", GOD, 0); } else { (void) atr_add(who, "RQUOTA", tprintf("%d", limit - owned), GOD, - NOTHING); + 0); } } } @@ -811,7 +811,7 @@ do_newpassword(dbref player, dbref cause, notify(player, T("Bad password.")); } else { /* it's ok, do it */ - (void) atr_add(victim, "XYXXY", mush_crypt(password), GOD, NOTHING); + (void) atr_add(victim, "XYXXY", mush_crypt(password), GOD, 0); notify_format(player, T("Password for %s changed."), Name(victim)); notify_format(victim, T("Your password has been changed by %s."), Name(player)); diff --git a/utils/mkvershlp.pl b/utils/mkvershlp.pl index 9ff7cc9..9326f0c 100755 --- a/utils/mkvershlp.pl +++ b/utils/mkvershlp.pl @@ -1,4 +1,4 @@ -#!/usr/local/bin/perl +#!/usr/bin/env perl # # Generate game/txt/hlp/ files from the CHANGES file(s). # Should be run by Makefile from top-level directory