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);
#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);
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.
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
/** 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
* 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;
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");
}