コード例 #1
0
ファイル: atr_tab.c プロジェクト: Syntroth/redpill_mush
/* 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;
}
コード例 #2
0
ファイル: utils.c プロジェクト: kymoon/pennmush
/** Populate a ufun_attrib struct from an obj/attr pair.
 * \verbatim Given an attribute [<object>/]<name> pair (which may include #lambda),
 * fetch its value, owner (thing), and pe_flags, and store in the struct
 * pointed to by ufun
 * \endverbatim
 * \param attrstring The obj/name of attribute.
 * \param executor Dbref of the executing object.
 * \param ufun Pointer to an allocated ufun_attrib struct to fill in.
 * \param flags A bitwise or of desired UFUN_* flags.
 * \return 0 on failure, true on success.
 */
bool
fetch_ufun_attrib(const char *attrstring, dbref executor, ufun_attrib * ufun,
                  int flags)
{
  char *thingname, *attrname;
  char astring[BUFFER_LEN];
  ATTR *attrib;

  if (!ufun)
    return 0;

  ufun->contents[0] = '\0';
  ufun->errmess = (char *) "";
  ufun->thing = executor;
  ufun->pe_flags = PE_UDEFAULT;
  ufun->ufun_flags = flags;

  ufun->thing = executor;
  thingname = NULL;

  if (!attrstring)
    return 0;
  strncpy(astring, attrstring, BUFFER_LEN);

  /* Split obj/attr */
  if ((flags & UFUN_OBJECT) && ((attrname = strchr(astring, '/')) != NULL)) {
    thingname = astring;
    *(attrname++) = '\0';
  } else {
    attrname = astring;
  }

  if (thingname && (flags & UFUN_LAMBDA)
      && (strcasecmp(thingname, "#lambda") == 0
          || strncasecmp(thingname, "#apply", 6) == 0)) {
    /* It's a lambda. */

    ufun->ufun_flags &= ~UFUN_NAME;
    ufun->thing = executor;
    if (strcasecmp(thingname, "#lambda") == 0)
      mush_strncpy(ufun->contents, attrname, BUFFER_LEN);
    else {                      /* #apply */
      char *ucb = ufun->contents;
      unsigned nargs = 1, n;

      thingname += 6;

      if (*thingname)
        nargs = parse_uinteger(thingname);

      /* Limit between 1 and 10 arguments (%0-%9) */
      if (nargs == 0)
        nargs = 1;
      if (nargs > 10)
        nargs = 10;

      safe_str(attrname, ufun->contents, &ucb);
      safe_chr('(', ufun->contents, &ucb);
      for (n = 0; n < nargs; n++) {
        if (n > 0)
          safe_chr(',', ufun->contents, &ucb);
        safe_format(ufun->contents, &ucb, "%%%u", n);
      }
      safe_chr(')', ufun->contents, &ucb);
      *ucb = '\0';
    }

    ufun->attrname[0] = '\0';
    return 1;
  }

  if (thingname) {
    /* Attribute is on something else. */
    ufun->thing =
      noisy_match_result(executor, thingname, NOTYPE, MAT_EVERYTHING);
    if (!GoodObject(ufun->thing)) {
      ufun->errmess = (char *) "#-1 INVALID OBJECT";
      return 0;
    }
  }

  attrib = (ATTR *) atr_get(ufun->thing, upcasestr(attrname));
  if (attrib && AF_Internal(attrib)) {
    /* Regardless of whether we're doing permission checks, we should
     * never be showing internal attributes here */
    attrib = NULL;
  }

  /* An empty attrib is the same as no attrib. */
  if (attrib == NULL) {
    if (flags & UFUN_REQUIRE_ATTR) {
      if (!(flags & UFUN_IGNORE_PERMS) && !Can_Examine(executor, ufun->thing))
        ufun->errmess = e_atrperm;
      return 0;
    } else {
      mush_strncpy(ufun->attrname, attrname, ATTRIBUTE_NAME_LIMIT + 1);
      return 1;
    }
  }
  if (!(flags & UFUN_IGNORE_PERMS)
      && !Can_Read_Attr(executor, ufun->thing, attrib)) {
    ufun->errmess = e_atrperm;
    return 0;
  }
  if (!(flags & UFUN_IGNORE_PERMS)
      && !CanEvalAttr(executor, ufun->thing, attrib)) {
    ufun->errmess = e_perm;
    return 0;
  }

  /* DEBUG attributes */
  if (AF_NoDebug(attrib))
    ufun->pe_flags |= PE_NODEBUG;       /* No_Debug overrides Debug */
  else if (AF_Debug(attrib))
    ufun->pe_flags |= PE_DEBUG;

  if (flags & UFUN_NAME) {
    if (attrib->flags & AF_NONAME)
      ufun->ufun_flags &= ~UFUN_NAME;
    else if (attrib->flags & AF_NOSPACE)
      ufun->ufun_flags |= UFUN_NAME_NOSPACE;
  }

  /* Populate the ufun object */
  mush_strncpy(ufun->contents, atr_value(attrib), BUFFER_LEN);
  mush_strncpy(ufun->attrname, AL_NAME(attrib), ATTRIBUTE_NAME_LIMIT + 1);

  /* We're good */
  return 1;
}
コード例 #3
0
ファイル: atr_tab.c プロジェクト: Syntroth/redpill_mush
/** 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));
}
コード例 #4
0
ファイル: atr_tab.c プロジェクト: Syntroth/redpill_mush
/** 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));
  }
}