From: Ari Johnson Date: Wed, 21 Feb 2007 01:35:59 +0000 (+0000) Subject: Setting and resetting multiple attribute flags at once is now more flexible X-Git-Tag: 0.73~148 X-Git-Url: https://git.theari.com/?a=commitdiff_plain;h=e253e5209043da690ebd3be7ce43af33e6227bff;p=cobramush.git Setting and resetting multiple attribute flags at once is now more flexible --- diff --git a/hdrs/attrib.h b/hdrs/attrib.h index 8d4c693..2bb35e4 100644 --- a/hdrs/attrib.h +++ b/hdrs/attrib.h @@ -72,6 +72,8 @@ extern int do_set_atr(dbref thing, char const *RESTRICT atr, 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); +extern int string_to_atrflagsets(dbref player, const char *p, int *setbits, + int *clrbits); extern const char *atrflag_to_string(int mask); extern void init_atr_name_tree(void); diff --git a/hdrs/privtab.h b/hdrs/privtab.h index b068c93..6d0f9af 100644 --- a/hdrs/privtab.h +++ b/hdrs/privtab.h @@ -28,6 +28,8 @@ struct priv_info { #define PrivShowBits(x) ((x)->bits_to_show) extern int string_to_privs(PRIV *table, const char *str, long int origprivs); +extern int string_to_privsets(PRIV *table, const char *str, int *setprivs, + int *clrprivs); extern int letter_to_privs(PRIV *table, const char *str, long int origprivs); extern const char *privs_to_string(PRIV *table, int privs); extern const char *privs_to_letters(PRIV *table, int privs); diff --git a/src/attrib.c b/src/attrib.c index 5ca7050..287538a 100644 --- a/src/attrib.c +++ b/src/attrib.c @@ -295,6 +295,31 @@ string_to_atrflag(dbref player, char const *p) return f; } +/** Convert a string of attribute flags to a pair of bitmasks. + * Given a space-separated string of attribute flags, look them up + * and return bitmasks of those to set or clear + * if player is permitted to use all of those flags. + * \param player the dbref to use for privilege checks. + * \param p a space-separated string of attribute flags. + * \param setbits pointer to address of bitmask to set. + * \param clrbits pointer to address of bitmask to clear. + * \return setbits or -1 on error. + */ +int +string_to_atrflagsets(dbref player, char const *p, int *setbits, int *clrbits) +{ + int f; + *setbits = *clrbits = 0; + f = string_to_privsets(attr_privs, p, setbits, clrbits); + if (f <= 0) + return -1; + if (!Prived(player) && ((*setbits & AF_MDARK) || (*clrbits & AF_MDARK))) + return -1; + if (!See_All(player) && ((*setbits & AF_PRIVILEGE) || (*clrbits & AF_PRIVILEGE))) + return -1; + return *setbits; +} + /** Convert an attribute flag bitmask into a list of the full * names of the flags. * \param mask the bitmask of attribute flags to display. diff --git a/src/privtab.c b/src/privtab.c index c399a5e..5efcd58 100644 --- a/src/privtab.c +++ b/src/privtab.c @@ -68,6 +68,58 @@ string_to_privs(PRIV *table, const char *str, long int origprivs) return ((origprivs | yes) & ~no); } +/** Convert a string to 2 sets of privilege bits, privs to set and + * privs to clear. + * \param table pointer to a privtab. + * \param str a space-separated string of privilege names to apply. + * \param setprivs pointer to address to store privileges to set. + * \param clrprivs pointer to address to store privileges to clear. + * \retval 1 string successfully parsed for bits with no errors. + * \retval 0 string contained no privs + * \retval -1 string at least one name matched no privs. + */ +int +string_to_privsets(PRIV *table, const char *str, int *setprivs, int *clrprivs) +{ + PRIV *c; + char *p, *r; + char tbuf1[BUFFER_LEN]; + int not; + int words = 0; + int err = 0; + int found = 0; + + *setprivs = *clrprivs = 0; + if (!str || !*str) + return 0; + strcpy(tbuf1, str); + r = trim_space_sep(tbuf1, ' '); + while ((p = split_token(&r, ' '))) { + words++; + not = 0; + if (*p == '!') { + not = 1; + if (!*++p) { + err = 1; + continue; + } + } + for (c = table; c->name; c++) { + if (string_prefix(c->name, p)) { + found++; + if (not) + *clrprivs |= c->bits_to_set; + else + *setprivs |= c->bits_to_set; + break; + } + } + } + if (err || (words != found)) + return -1; + return 1; +} + /** Convert a letter string to a set of privilege bits, masked by an original set. * Given a privs table, a letter string, and an original set of privileges, * return a modified set of privileges by applying the privs in the diff --git a/src/set.c b/src/set.c index d06ec83..92119c5 100644 --- a/src/set.c +++ b/src/set.c @@ -450,9 +450,10 @@ do_chzone(dbref player, char const *name, char const *newobj, int noisy) /** Structure for af_helper() data. */ struct af_args { - int f; /**< flag bits */ - int clear; /**< True to remove the flag */ - char *flag; /**< flag name */ + int setf; /**< flag bits to set */ + int clrf; /**< flag bits to clear */ + char *setflags; /**< list of names of flags to set */ + char *clrflags; /**< list of names of flags to clear */ }; static int @@ -467,23 +468,25 @@ af_helper(dbref player, dbref thing, dbref parent __attribute__ ((__unused__)), * There is one special case - the resetting of the SAFE flag. */ if (!(Can_Write_Attr(player, thing, AL_ATTR(atr)) || - (af->clear && (af->f & AF_SAFE) && + ((af->clrf & AF_SAFE) && Can_Write_Attr_Ignore_Safe(player, thing, AL_ATTR(atr))))) { notify_format(player, T("You cannot change that flag on %s/%s"), Name(thing), AL_NAME(atr)); return 0; } - if (af->clear) { - AL_FLAGS(atr) &= ~af->f; + /* Clear flags first, then set flags */ + if (af->clrf) { + AL_FLAGS(atr) &= ~af->clrf; if (!AreQuiet(player, thing)) notify_format(player, T("%s/%s - %s reset."), Name(thing), AL_NAME(atr), - af->flag); - } else { - AL_FLAGS(atr) |= af->f; + af->clrflags); + } + if (af->setf) { + AL_FLAGS(atr) |= af->setf; if (!AreQuiet(player, thing)) notify_format(player, T("%s/%s - %s set."), Name(thing), AL_NAME(atr), - af->flag); + af->setflags); } return 1; @@ -525,21 +528,22 @@ do_attrib_flags(dbref player, const char *obj, const char *atrname, return; } - af.clear = 0; - - /* move past NOT token if there is one */ - for (p = flag; *p && ((*p == NOT_TOKEN) || isspace((unsigned char) *p)); p++) - if (*p == NOT_TOKEN) - af.clear = !af.clear; + p = flag; + /* Skip leading spaces */ + while (*p && isspace((unsigned char) *p)) + p++; - if ((af.f = string_to_atrflag(player, p)) < 0) { + af.setf = af.clrf = 0; + if (string_to_atrflagsets(player, p, &af.setf, &af.clrf) < 0) { notify(player, T("Unrecognized attribute flag.")); return; } - af.flag = mush_strdup(atrflag_to_string(af.f), "af_flag list"); + af.clrflags = mush_strdup(atrflag_to_string(af.clrf), "al_flag list"); + af.setflags = mush_strdup(atrflag_to_string(af.setf), "al_flag list"); if (!atr_iter_get(player, thing, atrname, 0, af_helper, &af)) notify(player, T("No attribute found to change.")); - mush_free((Malloc_t) af.flag, "af_flag list"); + mush_free((Malloc_t) af.clrflags, "af_flag list"); + mush_free((Malloc_t) af.setflags, "af_flag list"); }