/* Add a new, or restrict an existing, standard attribute from cnf file */ int cnf_attribute_access(char *attrname, char *opts) { ATTR *a; privbits flags = 0; upcasestr(attrname); if (!good_atr_name(attrname)) return 0; if (strcasecmp(opts, "none")) { flags = list_to_privs(attr_privs_set, opts, 0); if (!flags) return 0; } a = (ATTR *) ptab_find_exact(&ptab_attrib, attrname); if (a) { if (AF_Internal(a)) return 0; } else { a = (ATTR *) mush_malloc(sizeof(ATTR), "ATTR"); if (!a) return 0; AL_NAME(a) = strdup(attrname); a->data = NULL_CHUNK_REFERENCE; ptab_insert_one(&ptab_attrib, attrname, a); } AL_FLAGS(a) = flags; AL_CREATOR(a) = GOD; return 1; }
/** Associate a new alias with an existing attribute. */ int alias_attribute(const char *atr, const char *alias) { ATTR *ap; /* Make sure the alias doesn't exist already */ if (aname_find_exact(alias)) return 0; /* Look up the original */ ap = aname_find_exact(atr); if (!ap) return 0; ptab_insert_one(&ptab_attrib, strupper(alias), ap); return 1; }
/** Add a new attribute. Called from db.c to add new attributes * to older databases which have their own attr table. * \param name name of attr to add * \param flags attribute flags (AF_*) */ void add_new_attr(char *name, uint32_t flags) { ATTR *ap; ap = (ATTR *) ptab_find_exact(&ptab_attrib, name); if (ap || !good_atr_name(name)) return; ap = (ATTR *) mush_malloc(sizeof(ATTR), "ATTR"); if (!ap) { do_log(LT_ERR, 0, 0, "add_new_attr: unable to malloc ATTR"); return; } AL_NAME(ap) = strdup(name); ap->data = NULL_CHUNK_REFERENCE; AL_FLAGS(ap) = flags; AL_CREATOR(ap) = 0; ptab_insert_one(&ptab_attrib, name, ap); }
/** 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; }
/** Add new standard attributes, or change permissions on them. * \verbatim * Given the name and permission string for an attribute, add it to * the attribute table (or modify the permissions if it's already * there). Permissions may be changed retroactively, which modifies * permissions on any copies of that attribute set on objects in the * database. This is the top-level code for @attribute/access. * \endverbatim * \param player the enactor. * \param name the attribute name. * \param perms a string of attribute permissions, space-separated. * \param retroactive if true, apply the permissions retroactively. */ void do_attribute_access(dbref player, char *name, char *perms, int retroactive) { ATTR *ap, *ap2; privbits flags = 0; int i; int insert = 0; /* Parse name and perms */ if (!name || !*name) { notify(player, T("Which attribute do you mean?")); return; } if (strcasecmp(perms, "none")) { flags = list_to_privs(attr_privs_set, perms, 0); if (!flags) { notify(player, T("I don't understand those permissions.")); return; } } upcasestr(name); /* Is this attribute already in the table? */ ap = (ATTR *) ptab_find_exact(&ptab_attrib, name); if (ap) { if (AF_Internal(ap)) { /* Don't muck with internal attributes */ notify(player, T("That attribute's permissions can not be changed.")); return; } } else { /* Create fresh if the name is ok */ if (!good_atr_name(name)) { notify(player, T("Invalid attribute name.")); return; } insert = 1; ap = (ATTR *) mush_malloc(sizeof(ATTR), "ATTR"); if (!ap) { notify(player, T("Critical memory failure - Alert God!")); do_log(LT_ERR, 0, 0, "do_attribute_access: unable to malloc ATTR"); return; } AL_NAME(ap) = strdup(name); ap->data = NULL_CHUNK_REFERENCE; } AL_FLAGS(ap) = flags; AL_CREATOR(ap) = player; /* Only insert when it's not already in the table */ if (insert) { ptab_insert_one(&ptab_attrib, name, ap); } /* Ok, now we need to see if there are any attributes of this name * set on objects in the db. If so, and if we're retroactive, set * perms/creator */ if (retroactive) { for (i = 0; i < db_top; i++) { if ((ap2 = atr_get_noparent(i, name))) { if (AL_FLAGS(ap2) & AF_ROOT) AL_FLAGS(ap2) = flags | AF_ROOT; else AL_FLAGS(ap2) = flags; AL_CREATOR(ap2) = player; } } } notify_format(player, T("%s -- Attribute permissions now: %s"), name, privs_to_string(attr_privs_view, flags)); }