Setting and resetting multiple attribute flags at once is now more flexible
authorAri Johnson <ari@cobramush.org>
Wed, 21 Feb 2007 01:35:59 +0000 (01:35 +0000)
committerAri Johnson <ari@cobramush.org>
Wed, 21 Feb 2007 01:35:59 +0000 (01:35 +0000)
hdrs/attrib.h
hdrs/privtab.h
src/attrib.c
src/privtab.c
src/set.c

index 8d4c6937d64a4b5fd53f791e40fad2a33de14f5b..2bb35e4f26d1640f08e8c36916140efca4bb5682 100644 (file)
@@ -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);
 
index b068c939db38b1b18344753475a20ead8819fee6..6d0f9af6f18154d4d7a5e02c921e35ac22bc883c 100644 (file)
@@ -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);
index 5ca70503b378191c32b9669dde8c7b19d1e205c1..287538aab6f42786882bcde546fceb8cb2e4ee2c 100644 (file)
@@ -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.
index c399a5eb70ca62c760a9b51ea59dc66b282890ec..5efcd5892d19a4cb43cf77d3a59f95ebb4b61303 100644 (file)
@@ -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
index d06ec838ccf2f45f4c884fcd39eaf6e3947e3a17..92119c508d1cf7efb947d0409670ae74b6994951 100644 (file)
--- 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");
 }