/** Display information on an attribute from the table. * \verbatim * Top-level function for @attribute. * \endverbatim * \param player the enactor. * \param name the name of the attribute. */ void do_attribute_info(dbref player, char *name) { ATTR *ap; if (!name || !*name) { notify(player, T("Which attribute do you mean?")); return; } /* Is this attribute in the table? */ if (*name == '@') name++; ap = aname_hash_lookup(name); if (!ap) { notify(player, T("That attribute isn't in the attribute table")); return; } notify_format(player, "%9s: %s", T("Attribute"), AL_NAME(ap)); if (ap->flags & AF_RLIMIT) { notify_format(player, "%9s: %s", T("Limit"), display_attr_limit(ap)); } else if (ap->flags & AF_ENUM) { notify_format(player, "%9s: %s", T("Enum"), display_attr_limit(ap)); } notify_format(player, "%9s: %s", T("Flags"), privs_to_string(attr_privs_view, AL_FLAGS(ap))); notify_format(player, "%9s: %s", T("Creator"), unparse_dbref(AL_CREATOR(ap))); return; }
/* 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; }
/** Decompile the standard attribute table, as per \@attribute/decompile * \param player The enactor * \param pattern Wildcard pattern of attrnames to decompile * \param retroactive Include the /retroactive switch? */ void do_decompile_attribs(dbref player, char *pattern, int retroactive) { ATTR *ap; const char *name; notify(player, T("@@ Standard Attributes:")); for (ap = ptab_firstentry_new(&ptab_attrib, &name); ap; ap = ptab_nextentry_new(&ptab_attrib, &name)) { if (strcmp(name, AL_NAME(ap))) continue; if (pattern && *pattern && !quick_wild(pattern, AL_NAME(ap))) continue; notify_format(player, "@attribute/access%s %s=%s", (retroactive ? "/retroactive" : ""), AL_NAME(ap), privs_to_string(attr_privs_view, AL_FLAGS(ap))); if (ap->flags & AF_RLIMIT) { notify_format(player, "@attribute/limit %s=%s", AL_NAME(ap), display_attr_limit(ap)); } else if (ap->flags & AF_ENUM) { notify_format(player, "@attribute/enum %s=%s", AL_NAME(ap), display_attr_limit(ap)); } } }
static void display_attr_info(dbref player, ATTR *ap) { notify_format(player, "%9s: %s", T("Attribute"), AL_NAME(ap)); if (ap->flags & AF_RLIMIT) { notify_format(player, "%9s: %s", T("Limit"), display_attr_limit(ap)); } else if (ap->flags & AF_ENUM) { notify_format(player, "%9s: %s", T("Enum"), display_attr_limit(ap)); } notify_format(player, "%9s: %s", T("Flags"), privs_to_string(attr_privs_view, AL_FLAGS(ap))); notify_format(player, "%9s: %s", T("Creator"), unparse_dbref(AL_CREATOR(ap))); return; }
static void grep_add_attr(char *buff, char **bp, dbref player, int count, ATTR *attr, char *atrval) { if (buff) { if (count) safe_chr(' ', buff, bp); safe_str(AL_NAME(attr), buff, bp); } else { notify_format(player, "%s%s [#%d%s]:%s %s", ANSI_HILITE, AL_NAME(attr), Owner(AL_CREATOR(attr)), privs_to_letters(attr_privs_view, AL_FLAGS(attr)), ANSI_END, atrval); } }
/** 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); }
void attr_write_all(PENNFILE *f) { int attrcount = 0, aliascount = 0; ATTR *a; const char *attrname; char *data; for (a = ptab_firstentry_new(&ptab_attrib, &attrname); a; a = ptab_nextentry_new(&ptab_attrib, &attrname)) { if (!strcmp(attrname, AL_NAME(a))) attrcount++; else aliascount++; } db_write_labeled_int(f, "attrcount", attrcount); for (a = ptab_firstentry_new(&ptab_attrib, &attrname); a; a = ptab_nextentry_new(&ptab_attrib, &attrname)) { if (strcmp(attrname, AL_NAME(a))) continue; /* skip aliases */ db_write_labeled_string(f, " name", AL_NAME(a)); db_write_labeled_string(f, " flags", privs_to_string(attr_privs_db, AL_FLAGS(a))); db_write_labeled_dbref(f, " creator", AL_CREATOR(a)); data = atr_value(a); db_write_labeled_string(f, " data", data); } db_write_labeled_int(f, "attraliascount", aliascount); for (a = ptab_firstentry_new(&ptab_attrib, &attrname); a; a = ptab_nextentry_new(&ptab_attrib, &attrname)) { if (!strcmp(attrname, AL_NAME(a))) continue; /* skip non-aliases */ db_write_labeled_string(f, " name", AL_NAME(a)); db_write_labeled_string(f, " alias", attrname); } }
/** 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)); }
static ATTR * attr_read(PENNFILE *f) { ATTR *a; char *tmp; dbref d = GOD; privbits flags = 0; a = (ATTR *) mush_malloc(sizeof(ATTR), "ATTR"); if (!a) { mush_panic("Not enough memory to add attribute in attr_read()!"); return NULL; } AL_NAME(a) = NULL; a->data = NULL_CHUNK_REFERENCE; AL_FLAGS(a) = 0; AL_CREATOR(a) = GOD; a->next = NULL; db_read_this_labeled_string(f, "name", &tmp); if (!good_atr_name(tmp)) { do_rawlog(LT_ERR, "Invalid attribute name '%s' in db.", tmp); (void) getstring_noalloc(f); /* flags */ (void) getstring_noalloc(f); /* creator */ (void) getstring_noalloc(f); /* data */ free_standard_attr(a, 0); return NULL; } AL_NAME(a) = strdup(tmp); db_read_this_labeled_string(f, "flags", &tmp); if (tmp && *tmp && strcasecmp(tmp, "none")) { flags = list_to_privs(attr_privs_db, tmp, 0); if (!flags) { do_rawlog(LT_ERR, "Invalid attribute flags for '%s' in db.", AL_NAME(a)); free((char *) AL_NAME(a)); (void) getstring_noalloc(f); /* creator */ (void) getstring_noalloc(f); /* data */ free_standard_attr(a, 0); return NULL; } } AL_FLAGS(a) = flags; db_read_this_labeled_dbref(f, "creator", &d); AL_CREATOR(a) = d; db_read_this_labeled_string(f, "data", &tmp); if (!tmp || !*tmp || !(AL_FLAGS(a) & (AF_ENUM | AF_RLIMIT))) { a->data = NULL_CHUNK_REFERENCE; } else if (AL_FLAGS(a) & AF_ENUM) { /* Store string as it is */ char *t = compress(tmp); a->data = chunk_create(t, strlen(t), 0); free(t); } else if (AL_FLAGS(a) & AF_RLIMIT) { /* Need to validate regexp */ char *t; pcre *re; const char *errptr; int erroffset; re = pcre_compile(tmp, PCRE_CASELESS, &errptr, &erroffset, tables); if (!re) { do_rawlog(LT_ERR, "Invalid regexp in limit for attribute '%s' in db.", AL_NAME(a)); free_standard_attr(a, 0); return NULL; } pcre_free(re); /* don't need it, just needed to check it */ t = compress(tmp); a->data = chunk_create(t, strlen(t), 0); free(t); } return a; }