/** Delete an attribute from the attribute table. * \verbatim * Top-level function for @attrib/delete. * \endverbatim * \param player the enactor. * \param name the name of the attribute to delete. */ void do_attribute_delete(dbref player, char *name) { ATTR *ap; if (!name || !*name) { notify(player, T("Which attribute do you mean?")); return; } /* Is this attribute in the table? */ ap = (ATTR *) ptab_find_exact(&ptab_attrib, name); if (!ap) { notify(player, T("That attribute isn't in the attribute table")); return; } /* Free everything it uses. */ if (ap->data != NULL_CHUNK_REFERENCE) { chunk_delete(ap->data); } /* Ok, take it out of the hash table */ ptab_delete(&ptab_attrib, name); notify_format(player, T("Removed %s from attribute table."), name); return; }
static PyObject * hashsplit_read_chunk(PyObject *self, PyObject *args) { PyObject *source_file = NULL; //gcc complains if these aren't initialized PyObject *max_chunk_size = NULL; long MAX_CHUNK_SIZE; PyObject *result = NULL; Chunk *chunk; FILE *source; if (!PyArg_UnpackTuple(args, "read_chunk", 1, 2, &source_file, &max_chunk_size)) return NULL; if (!(source = PyFile_AsFile(source_file))) { PyErr_SetString(PyExc_TypeError, "Expected file or file descriptor"); return NULL; } if (!max_chunk_size || max_chunk_size == Py_None) { MAX_CHUNK_SIZE = DEFAULT_MAX_CHUNK_SIZE; } else if ((MAX_CHUNK_SIZE = PyInt_AsLong(max_chunk_size))==-1 && PyErr_Occurred()) { PyErr_SetString(PyExc_TypeError, "max_chunk_size should be an integer"); return NULL; } if (MAX_CHUNK_SIZE < MIN_CHUNK_SIZE) { PyErr_SetString(PyExc_ValueError, "max_chunk_size must be larger than MIN_CHUNK_SIZE"); return NULL; } if (!(chunk = chunk_new(MAX_CHUNK_SIZE))) return PyErr_NoMemory(); if (!read_chunk(source, chunk, MAX_CHUNK_SIZE)) { PyErr_SetString(PyExc_EOFError, ""); } else { result = PyString_FromStringAndSize((char*)chunk->data, chunk->length); } chunk_delete(chunk); return result; }
/** Free all memory used by a standard attribute, and remove it from the hash * table if necessary. * \param a attr to remove * \param inserted has the attr been inserted into the hash table already? * \retval number of entries (including aliases) removed from the hash table */ static int free_standard_attr(ATTR *a, bool inserted) { int count = 0; if (!a) { return count; } /* If the attr has no name, there's no way it can be in the hash table */ if (AL_NAME(a)) { if (inserted) { count = free_standard_attr_aliases(a) + 1; ptab_delete(&ptab_attrib, AL_NAME(a)); } free((char *) AL_NAME(a)); } if (a->data != NULL_CHUNK_REFERENCE) { chunk_delete(a->data); } mush_free(a, "ATTR"); return count; }
/** Limit an attribute's possible values, using either an enum or a * regexp /limit. * \verbatim * Given a name, restriction type and string for an attribute, * set its data value to said data and set a flag for limit or * enum. * * For an enum, the attr's data will be set to * <delim><pattern><delim>, so a simple strstr() can be used when * matching the pattern. * * An optional delimiter can be provided on the left hand side by using * @attr/enum <delim> <attrname>=<enum list> * \endverbatim * \param player the enactor. * \param name the attribute name. * \param type AF_RLIMIT for regexp, AF_ENUM for enum. * \param pattern The allowed pattern for the attribute. */ void do_attribute_limit(dbref player, char *name, int type, char *pattern) { ATTR *ap; char buff[BUFFER_LEN]; char *ptr, *bp; char delim = ' '; pcre *re; const char *errptr; int erroffset; int unset = 0; if (pattern && *pattern) { if (type == AF_RLIMIT) { /* Compile to regexp. */ re = pcre_compile(remove_markup(pattern, NULL), PCRE_CASELESS, &errptr, &erroffset, tables); if (!re) { notify(player, T("Invalid Regular Expression.")); return; } /* We only care if it's valid, we're not using it. */ free(re); /* Copy it to buff to be placed into ap->data. */ snprintf(buff, BUFFER_LEN, "%s", pattern); } else if (type == AF_ENUM) { ptr = name; /* Check for a delimiter: @attr/enum | attrname=foo */ if ((name = strchr(ptr, ' ')) != NULL) { *(name++) = '\0'; if (strlen(ptr) > 1) { notify(player, T("Delimiter must be one character.")); return; } delim = *ptr; } else { name = ptr; delim = ' '; } /* For speed purposes, we require the pattern to begin and end with * a delimiter. */ snprintf(buff, BUFFER_LEN, "%c%s%c", delim, pattern, delim); buff[BUFFER_LEN - 1] = '\0'; /* For sanity's sake, we'll enforce a properly delimited enum * with a quick and dirty squish(). * We already know we start with a delim, hence the +1 =). */ for (ptr = buff + 1, bp = buff + 1; *ptr; ptr++) { if (!(*ptr == delim && *(ptr - 1) == delim)) { *(bp++) = *ptr; } } *bp = '\0'; } else { /* Err, we got called with the wrong limit type? */ notify(player, T("Unknown limit type?")); return; } } else { unset = 1; } /* Parse name and perms */ if (!name || !*name) { notify(player, T("Which attribute do you mean?")); return; } upcasestr(name); if (*name == '@') name++; /* Is this attribute already in the table? */ ap = (ATTR *) ptab_find_exact(&ptab_attrib, name); if (!ap) { notify(player, T ("I don't know that attribute. Please use @attribute/access to create it, first.")); return; } if (AF_Internal(ap)) { /* Don't muck with internal attributes */ notify(player, T("That attribute's permissions cannot be changed.")); return; } /* All's good, set the data and the AF_RLIMIT or AF_ENUM flag. */ if (ap->data != NULL_CHUNK_REFERENCE) { chunk_delete(ap->data); } /* Clear any extant rlimit or enum flags */ ap->flags &= ~(AF_RLIMIT | AF_ENUM); if (unset) { if (ap->data != NULL_CHUNK_REFERENCE) { ap->data = NULL_CHUNK_REFERENCE; notify_format(player, T("%s -- Attribute limit or enum unset."), name); } else { notify_format(player, T("%s -- Attribute limit or enum already unset."), name); } } else { unsigned char *t = compress(buff); ap->data = chunk_create(t, u_strlen(t), 0); free(t); ap->flags |= type; notify_format(player, T("%s -- Attribute %s set to: %s"), name, type == AF_RLIMIT ? "limit" : "enum", display_attr_limit(ap)); } }