Ejemplo n.º 1
0
/* Show the 'Obvious Exits' list for a room. Used in 'look' and 'examine'.
 * \param player The player looking
 * \param loc room whose exits we're showing
 * \param exit_name "Obvious Exits" string
 * \param pe_info the pe_info to use for evaluating EXITFORMAT and interact locks
 */
static void
look_exits(dbref player, dbref loc, const char *exit_name, NEW_PE_INFO *pe_info)
{
  dbref thing;
  char *tbuf1, *tbuf2, *nbuf;
  char *s1, *s2;
  char *p;
  int exit_count, this_exit, total_count;
  int texits;
  ufun_attrib ufun;
  PUEBLOBUFF;

  /* make sure location is a room */
  if (!IsRoom(loc))
    return;

  tbuf1 = (char *) mush_malloc(BUFFER_LEN, "string");
  tbuf2 = (char *) mush_malloc(BUFFER_LEN, "string");
  nbuf = (char *) mush_malloc(BUFFER_LEN, "string");
  if (!tbuf1 || !tbuf2 || !nbuf)
    mush_panic("Unable to allocate memory in look_exits");
  s1 = tbuf1;
  s2 = tbuf2;
  texits = exit_count = total_count = 0;
  this_exit = 1;

  if (fetch_ufun_attrib
      ("EXITFORMAT", loc, &ufun, UFUN_IGNORE_PERMS | UFUN_REQUIRE_ATTR)) {
    char *arg, *buff, *bp;
    PE_REGS *pe_regs = pe_regs_create(PE_REGS_ARG, "look_exits");

    arg = (char *) mush_malloc(BUFFER_LEN, "string");
    buff = (char *) mush_malloc(BUFFER_LEN, "string");
    if (!arg || !buff)
      mush_panic("Unable to allocate memory in look_exits");

    bp = arg;
    DOLIST(thing, Exits(loc)) {
      if (((Light(loc) || Light(thing)) || !(Dark(loc) || Dark(thing)))
          && can_interact(thing, player, INTERACT_SEE, pe_info)) {
        if (bp != arg)
          safe_chr(' ', arg, &bp);
        safe_dbref(thing, arg, &bp);
      }
    }
    *bp = '\0';
    pe_regs_setenv_nocopy(pe_regs, 0, arg);

    call_ufun(&ufun, buff, player, player, pe_info, pe_regs);

    pe_regs_free(pe_regs);
    notify_by(loc, player, buff);
    mush_free(tbuf1, "string");
    mush_free(tbuf2, "string");
    mush_free(nbuf, "string");
    mush_free(arg, "string");
    mush_free(buff, "string");
    return;
  }
Ejemplo n.º 2
0
/** Helper function for calling \@functioned funs.
 * \param buff string to store result of evaluation.
 * \param bp pointer into end of buff.
 * \param obj object on which the ufun is stored.
 * \param attrib pointer to attribute on which the ufun is stored.
 * \param nargs number of arguments passed to the ufun.
 * \param args array of arguments passed to the ufun.
 * \param executor executor.
 * \param caller caller (unused).
 * \param enactor enactor.
 * \param pe_info pointer to structure for process_expression data.
 * \param extra_flags extra PE_ flags to pass in (PE_USERFN or 0).
 */
void
do_userfn(char *buff, char **bp, dbref obj, ATTR *attrib, int nargs,
          char **args, dbref executor, dbref caller
          __attribute__ ((__unused__)), dbref enactor, NEW_PE_INFO *pe_info,
          int extra_flags)
{
  int j;
  int made_pe_info = 0;
  char *tbuf;
  char const *tp;
  int pe_flags = PE_DEFAULT | extra_flags;
  PE_REGS *pe_regs;

  if (nargs > 10)
    nargs = 10;                 /* maximum ten args */

  /* save our stack */
  if (!pe_info) {
    made_pe_info = 1;
    pe_info = make_pe_info("pe_info-do_userfn");
  }

  /* copy the appropriate args into pe_regs */
  pe_regs = pe_regs_localize(pe_info, PE_REGS_ARG, "do_userfn");
  for (j = 0; j < nargs; j++) {
    pe_regs_setenv_nocopy(pe_regs, j, args[j]);
  }

  tp = tbuf = safe_atr_value(attrib);
  if (AF_NoDebug(attrib))
    pe_flags |= PE_NODEBUG;     /* no_debug overrides debug */
  else if (AF_Debug(attrib))
    pe_flags |= PE_DEBUG;

  process_expression(buff, bp, &tp, obj, executor, enactor, pe_flags,
                     PT_DEFAULT, pe_info);

  free(tbuf);

  pe_regs_restore(pe_info, pe_regs);
  pe_regs_free(pe_regs);

  if (made_pe_info) {
    free_pe_info(pe_info);
  }
}
Ejemplo n.º 3
0
/** A wrapper for real_did_it that can set %0 and %1 to dbrefs.
 * \param player the enactor.
 * \param thing object being triggered.
 * \param what message attribute for enactor.
 * \param def default message to enactor.
 * \param owhat message attribute for others.
 * \param odef default message to others.
 * \param awhat action attribute to trigger.
 * \param loc location in which action is taking place.
 * \param env0 dbref to pass as %0, or NOTHING.
 * \param env1 dbref to pass as %1, or NOTHING.
 * \param flags interaction flags to pass to real_did_it.
 * \retval 0 no attributes were present, only defaults were used if given.
 * \retval 1 some attributes were evaluated and used.
 */
int
did_it_with(dbref player, dbref thing, const char *what, const char *def,
            const char *owhat, const char *odef, const char *awhat,
            dbref loc, dbref env0, dbref env1, int flags, int an_flags)
{
  PE_REGS *pe_regs = pe_regs_create(PE_REGS_ARG, "did_it_with");
  int retval;

  if (env0 != NOTHING) {
    pe_regs_setenv(pe_regs, 0, unparse_dbref(env0));
  }
  if (env1 != NOTHING) {
    pe_regs_setenv(pe_regs, 1, unparse_dbref(env1));
  }
  retval = real_did_it(player, thing, what, def, owhat, odef, awhat, loc,
                       pe_regs, flags, an_flags);

  pe_regs_free(pe_regs);
  return retval;
}
Ejemplo n.º 4
0
/** Evaluate a lock, saving/clearing the env (%0-%9) and qreg (%q*) first,
 ** and restoring them after.
 */
int
eval_lock_clear(dbref player, dbref thing, lock_type ltype,
                NEW_PE_INFO *pe_info)
{
  if (!pe_info)
    return eval_lock_with(player, thing, ltype, NULL);
  else {
    PE_REGS *pe_regs;
    int result;

    pe_regs = pe_regs_localize(pe_info, PE_REGS_ISOLATE, "eval_lock_clear");

    /* Run the lock */
    result = eval_lock_with(player, thing, ltype, pe_info);

    /* Restore q-regs */
    pe_regs_restore(pe_info, pe_regs);
    pe_regs_free(pe_regs);
    return result;
  }
}
Ejemplo n.º 5
0
/** The say command.
 * \param player the enactor.
 * \param message the message to say.
 * \param pe_info pe_info to eval speechmod with
 */
void
do_say(dbref player, const char *message, NEW_PE_INFO *pe_info)
{
  dbref loc;
  PE_REGS *pe_regs;
  char modmsg[BUFFER_LEN];
  char says[BUFFER_LEN];
  char *sp;
  int mod = 0;
  loc = speech_loc(player);
  if (!GoodObject(loc))
    return;

  if (!Loud(player) && !eval_lock_with(player, loc, Speech_Lock, pe_info)) {
    fail_lock(player, loc, Speech_Lock, T("You may not speak here!"), NOTHING);
    return;
  }

  if (*message == SAY_TOKEN && CHAT_STRIP_QUOTE)
    message++;

  pe_regs = pe_regs_create(PE_REGS_ARG, "do_say");
  pe_regs_setenv_nocopy(pe_regs, 0, message);
  pe_regs_setenv_nocopy(pe_regs, 1, "\"");
  modmsg[0] = '\0';

  if (call_attrib(player, "SPEECHMOD", modmsg, player, pe_info, pe_regs)
      && *modmsg != '\0')
    mod = 1;
  pe_regs_free(pe_regs);

  /* notify everybody */
  notify_format(player, T("You say, \"%s\""), (mod ? modmsg : message));
  sp = says;
  safe_format(says, &sp, T("%s says, \"%s\""), spname(player),
              (mod ? modmsg : message));
  *sp = '\0';
  notify_except(player, loc, player, says, NA_INTER_HEAR);
}
Ejemplo n.º 6
0
/** Given a ufun, executor, enactor, PE_Info, and arguments for %0-%9,
 *  call the ufun with appropriate permissions on values given for
 *  wenv_args. The value returned is stored in the buffer pointed to
 *  by ret, if given.
 * \param ufun The ufun_attrib that was initialized by fetch_ufun_attrib
 * \param ret If desired, a pointer to a buffer in which the results
 *            of the process_expression are stored in.
 * \param caller The caller (%@).
 * \param enactor The enactor. (%#)
 * \param pe_info The pe_info passed to the FUNCTION
 * \param user_regs Other arguments that may want to be added. This nests BELOW
 *                the pe_regs created by call_ufun. (It is checked first)
 * \param data a void pointer to extra data. Currently only used to pass the
 *             name to use, when UFUN_NAME is given.
 * \retval 0 success
 * \retval 1 process_expression failed. (CPU time limit)
 */
bool
call_ufun_int(ufun_attrib * ufun, char *ret, dbref caller, dbref enactor,
              NEW_PE_INFO *pe_info, PE_REGS *user_regs, void *data)
{
  char rbuff[BUFFER_LEN];
  char *rp, *np = NULL;
  int pe_ret;
  char const *ap;
  char old_attr[BUFFER_LEN];
  int made_pe_info = 0;
  PE_REGS *pe_regs;
  PE_REGS *pe_regs_old;
  int pe_reg_flags = 0;

  /* Make sure we have a ufun first */
  if (!ufun)
    return 1;
  if (!pe_info) {
    pe_info = make_pe_info("pe_info.call_ufun");
    made_pe_info = 1;
  } else {
    strcpy(old_attr, pe_info->attrname);
  }

  pe_regs_old = pe_info->regvals;

  if (ufun->ufun_flags & UFUN_LOCALIZE)
    pe_reg_flags |= PE_REGS_Q;
  else {
    pe_reg_flags |= PE_REGS_NEWATTR;
    if (ufun->ufun_flags & UFUN_SHARE_STACK)
      pe_reg_flags |= PE_REGS_ARGPASS;
  }

  pe_regs = pe_regs_localize(pe_info, pe_reg_flags, "call_ufun");

  rp = pe_info->attrname;
  if (*ufun->attrname == '\0') {
    safe_str("#LAMBDA", pe_info->attrname, &rp);
    safe_chr('/', pe_info->attrname, &rp);
    safe_str(ufun->contents, pe_info->attrname, &rp);
  } else {
    safe_dbref(ufun->thing, pe_info->attrname, &rp);
    safe_chr('/', pe_info->attrname, &rp);
    safe_str(ufun->attrname, pe_info->attrname, &rp);
  }
  *rp = '\0';

  /* If the user doesn't care about the return of the expression,
   * then use our own rbuff.  */
  if (!ret)
    ret = rbuff;
  rp = ret;

  /* Anything the caller wants available goes on the bottom of the stack */
  if (user_regs) {
    user_regs->prev = pe_info->regvals;
    pe_info->regvals = user_regs;
  }

  if (ufun->ufun_flags & UFUN_NAME) {
    char *name = (char *) data;
    if (!name || !*name)
      name = (char *) Name(enactor);
    safe_str(name, ret, &rp);
    if (!(ufun->ufun_flags & UFUN_NAME_NOSPACE))
      safe_chr(' ', ret, &rp);
    np = rp;
  }


  /* And now, make the call! =) */
  ap = ufun->contents;
  pe_ret = process_expression(ret, &rp, &ap, ufun->thing, caller,
                              enactor, ufun->pe_flags, PT_DEFAULT, pe_info);
  *rp = '\0';

  if ((ufun->ufun_flags & UFUN_NAME) && np == rp) {
    /* Attr was empty, so we take off the name again */
    *ret = '\0';
  }

  /* Restore call_ufun's pe_regs */
  if (user_regs) {
    pe_info->regvals = user_regs->prev;
  }

  /* Restore the pe_regs stack. */
  pe_regs_restore(pe_info, pe_regs);
  pe_regs_free(pe_regs);

  pe_info->regvals = pe_regs_old;

  if (!made_pe_info) {
    /* Restore the old attrname. */
    strcpy(pe_info->attrname, old_attr);
  } else {
    free_pe_info(pe_info);
  }

  return pe_ret;
}
Ejemplo n.º 7
0
/** Rename something.
 * \verbatim
 * This implements @name.
 * \endverbatim
 * \param player the enactor.
 * \param name current name of object to rename.
 * \param newname_ new name for object.
 */
void
do_name(dbref player, const char *name, char *newname_)
{
  dbref thing;
  char oldname[BUFFER_LEN];
  char *newname = NULL;
  char *alias = NULL;
  PE_REGS *pe_regs;

  if ((thing = match_controlled(player, name)) == NOTHING)
    return;

  /* check for bad name */
  if ((*newname_ == '\0') || strchr(newname_, '[')) {
    notify(player, T("Give it what new name?"));
    return;
  }
  switch (Typeof(thing)) {
  case TYPE_PLAYER:
    switch (ok_object_name
            (newname_, player, thing, TYPE_PLAYER, &newname, &alias)) {
    case OPAE_INVALID:
    case OPAE_NULL:
      notify(player, T("You can't give a player that name or alias."));
      if (newname)
        mush_free(newname, "name.newname");
      if (alias)
        mush_free(alias, "name.newname");
      return;
    case OPAE_TOOMANY:
      notify(player, T("Too many aliases."));
      mush_free(newname, "name.newname");
      return;
    case OPAE_SUCCESS:
      break;
    }
    break;
  case TYPE_EXIT:
    if (ok_object_name(newname_, player, thing, TYPE_EXIT, &newname, &alias) !=
        OPAE_SUCCESS) {
      notify(player, T("That is not a reasonable name."));
      if (newname)
        mush_free(newname, "name.newname");
      if (alias)
        mush_free(alias, "name.newname");
      return;
    }
    break;
  case TYPE_THING:
  case TYPE_ROOM:
    if (!ok_name(newname_, 0)) {
      notify(player, T("That is not a reasonable name."));
      return;
    }
    newname = mush_strdup(trim_space_sep(newname_, ' '), "name.newname");
    break;
  default:
    /* Should never occur */
    notify(player, T("I don't see that here."));
    return;
  }

  /* Actually change it */
  mush_strncpy(oldname, Name(thing), BUFFER_LEN);

  if (IsPlayer(thing)) {
    do_log(LT_CONN, 0, 0, "Name change by %s(#%d) to %s",
           Name(thing), thing, newname);
    if (Suspect(thing) && strcmp(Name(thing), newname) != 0)
      flag_broadcast("WIZARD", 0,
                     T("Broadcast: Suspect %s changed name to %s."),
                     Name(thing), newname);
    reset_player_list(thing, Name(thing), NULL, newname, NULL);
  }
  set_name(thing, newname);
  if (alias) {
    if (*alias == ALIAS_DELIMITER) {
      do_set_atr(thing, "ALIAS", NULL, player, 0);
    } else {
      /* New alias to set */
      do_set_atr(thing, "ALIAS", alias, player, 0);
    }
    mush_free(alias, "name.newname");
  }

  queue_event(player, "OBJECT`RENAME", "%s,%s,%s",
              unparse_objid(thing), newname, oldname);

  if (!AreQuiet(player, thing))
    notify(player, T("Name set."));
  pe_regs = pe_regs_create(PE_REGS_ARG, "do_name");
  pe_regs_setenv_nocopy(pe_regs, 0, oldname);
  pe_regs_setenv_nocopy(pe_regs, 1, newname);
  real_did_it(player, thing, NULL, NULL, "ONAME", NULL, "ANAME", NOTHING,
              pe_regs, NA_INTER_PRESENCE, AN_SYS);
  pe_regs_free(pe_regs);
  mush_free(newname, "name.newname");
}
Ejemplo n.º 8
0
/** User-defined verbs.
 * \verbatim
 * This implements the @verb command.
 * \endverbatim
 * \param executor the executor.
 * \param enactor the object causing this command to run.
 * \param arg1 the object to read verb attributes from.
 * \param argv the array of remaining arguments to the verb command.
 * \param queue_entry The queue entry \@verb is running in
 */
void
do_verb(dbref executor, dbref enactor, char *arg1, char **argv,
        MQUE *queue_entry)
{
  dbref victim;
  dbref actor;
  int i;
  PE_REGS *pe_regs = NULL;

  /* find the object that we want to read the attributes off
   * (the object that was the victim of the command)
   */

  /* our victim object can be anything */
  victim = match_result(executor, arg1, NOTYPE, MAT_EVERYTHING);

  if (!GoodObject(victim)) {
    notify(executor, T("What was the victim of the verb?"));
    return;
  }
  /* find the object that executes the action */

  if (!argv || !argv[1] || !*argv[1]) {
    notify(executor, T("What do you want to do with the verb?"));
    return;
  }
  actor = match_result(executor, argv[1], NOTYPE, MAT_EVERYTHING);

  if (!GoodObject(actor)) {
    notify(executor, T("What do you want to do the verb?"));
    return;
  }
  /* Control check is fascist.
   * First check: we don't want <actor> to do something involuntarily.
   *   Both victim and actor have to be controlled by the thing which did
   *   the @verb (for speed we do a WIZARD check first), or: cause controls
   *   actor plus the second check is passed.
   * Second check: we need read access to the attributes.
   *   Either the player controls victim or the player
   *   must be priviledged, or the victim has to be VISUAL.
   */

  if (!(Wizard(executor) ||
        (controls(executor, victim) && controls(executor, actor)) ||
        ((controls(enactor, actor) && Can_Examine(executor, victim))))) {
    notify(executor, T("Permission denied."));
    return;
  }
  /* We're okay.  Send out messages. */

  pe_regs = pe_regs_create(PE_REGS_ARG | PE_REGS_Q, "do_verb");
  for (i = 0; i < MAX_STACK_ARGS; i++) {
    if (argv[i + 7]) {
      pe_regs_setenv_nocopy(pe_regs, i, argv[i + 7]);
    }
  }
  pe_regs_qcopy(pe_regs, queue_entry->pe_info->regvals);

  real_did_it(actor, victim,
              upcasestr(argv[2]), argv[3], upcasestr(argv[4]), argv[5],
              NULL, Location(actor), pe_regs, NA_INTER_HEAR, AN_SYS);

  /* Now we copy our args into the stack, and do the command. */

  if (argv[6] && *argv[6])
    queue_attribute_base(victim, upcasestr(argv[6]), actor, 0, pe_regs,
                         (queue_entry->queue_type & QUEUE_EVENT));

  pe_regs_free(pe_regs);
}
Ejemplo n.º 9
0
/** The switch command.
 * \verbatim
 * For lack of better place the @switch code is here.
 * @switch expression=args
 * \endverbatim
 * \param executor the executor.
 * \param expression the expression to test against cases.
 * \param argv array of cases and actions.
 * \param enactor the object that caused this code to run.
 * \param first if 1, run only first matching case; if 0, run all matching cases.
 * \param notifyme if 1, perform a notify after executing matched cases.
 * \param regexp if 1, do regular expression matching; if 0, wildcard globbing.
 * \param queue_type the type of queue to run any new commands as
 * \param queue_entry the queue entry \@switch is being run in
 */
void
do_switch(dbref executor, char *expression, char **argv, dbref enactor,
          int first, int notifyme, int regexp, int queue_type,
          MQUE *queue_entry)
{
  int any = 0, a;
  char buff[BUFFER_LEN], *bp;
  char const *ap;
  char *tbuf1;
  PE_REGS *pe_regs;

  if (!argv[1])
    return;

  pe_regs = pe_regs_create(PE_REGS_SWITCH | PE_REGS_CAPTURE, "do_switch");
  pe_regs_clear(pe_regs);
  pe_regs_set(pe_regs, PE_REGS_SWITCH, "t0", expression);

  /* now try a wild card match of buff with stuff in coms */
  for (a = 1;
       !(first && any) && (a < (MAX_ARG - 1)) && argv[a] && argv[a + 1];
       a += 2) {
    /* eval expression */
    ap = argv[a];
    bp = buff;
    if (process_expression(buff, &bp, &ap, executor, enactor, enactor,
                           PE_DEFAULT, PT_DEFAULT, queue_entry->pe_info)) {
      pe_regs_free(pe_regs);
      return;
    }
    *bp = '\0';
    /* check for a match */
    pe_regs_clear_type(pe_regs, PE_REGS_CAPTURE);
    if (regexp ? regexp_match_case_r(buff, expression, 0,
                                     NULL, 0, NULL, 0, pe_regs, 0)
        : local_wild_match(buff, expression, pe_regs)) {
      tbuf1 = replace_string("#$", expression, argv[a + 1]);
      if (!any) {
        /* Add the new switch context to the parent queue... */
        any = 1;
      }
      if (queue_type != QUEUE_DEFAULT) {
        new_queue_actionlist(executor, enactor, enactor, tbuf1, queue_entry,
                             PE_INFO_SHARE, queue_type, pe_regs);
      } else {
        new_queue_actionlist(executor, enactor, enactor, tbuf1, queue_entry,
                             PE_INFO_CLONE, QUEUE_DEFAULT, pe_regs);
      }
      mush_free(tbuf1, "replace_string.buff");
    }
  }
  /* do default if nothing has been matched */
  if ((a < MAX_ARG) && !any && argv[a]) {
    tbuf1 = replace_string("#$", expression, argv[a]);
    if (queue_type != QUEUE_DEFAULT) {
      new_queue_actionlist(executor, enactor, enactor, tbuf1, queue_entry,
                           PE_INFO_SHARE, queue_type, pe_regs);
    } else {
      new_queue_actionlist(executor, enactor, enactor, tbuf1, queue_entry,
                           PE_INFO_CLONE, QUEUE_DEFAULT, pe_regs);
    }
    mush_free(tbuf1, "replace_string.buff");
  }
  pe_regs_free(pe_regs);
  if (queue_type == QUEUE_DEFAULT) {
    if (notifyme)
      parse_que(executor, enactor, "@notify me", NULL);
  }
}