/** * \file funufun.c * * \brief Evaluation and user-function functions for mushcode. * * */ #include "copyrite.h" #include "config.h" #include "conf.h" #include "externs.h" #include "match.h" #include "parse.h" #include "mymalloc.h" #include "attrib.h" #include "mushdb.h" #include "dbdefs.h" #include "flags.h" #include "lock.h" #include "confmagic.h" void do_userfn(char *buff, char **bp, dbref obj, ATTR *attrib, int nargs, char **args, dbref executor, dbref caller, dbref enactor, PE_Info * pe_info); /* ARGSUSED */ FUNCTION(fun_s) { char const *p; p = args[0]; process_expression(buff, bp, &p, executor, caller, enactor, PE_DEFAULT, PT_DEFAULT, pe_info); } /* ARGSUSED */ FUNCTION(fun_localize) { char const *p; char *saver[NUMQ]; save_global_regs("localize", saver); p = args[0]; process_expression(buff, bp, &p, executor, caller, enactor, PE_DEFAULT, PT_DEFAULT, pe_info); restore_global_regs("localize", saver); } /* ARGSUSED */ FUNCTION(fun_objeval) { char name[BUFFER_LEN]; char *s; char const *p; dbref obj; /* First, we evaluate our first argument so people can use * functions on it. */ s = name; p = args[0]; process_expression(name, &s, &p, executor, caller, enactor, PE_DEFAULT, PT_DEFAULT, pe_info); *s = '\0'; if (FUNCTION_SIDE_EFFECTS) { /* The security hole created by function side effects is too great * to allow a see_all player to evaluate functions from someone else's * standpoint. We require control. */ if (((obj = match_thing(executor, name)) == NOTHING) || !controls(executor, obj)) obj = executor; } else { /* In order to evaluate from something else's viewpoint, you * must control it, or be able to see_all. */ if (((obj = match_thing(executor, name)) == NOTHING) || (!controls(executor, obj) && !See_All(executor))) obj = executor; } p = args[1]; process_expression(buff, bp, &p, obj, executor, enactor, PE_DEFAULT, PT_DEFAULT, pe_info); } /** Helper function for ufun and family. * \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. */ void do_userfn(char *buff, char **bp, dbref obj, ATTR *attrib, int nargs, char **args, dbref executor, dbref caller __attribute__ ((__unused__)), dbref enactor, PE_Info * pe_info) { int j; char *tptr[10]; char *tbuf; char const *tp; int pe_flags = PE_DEFAULT; /* save our stack */ for (j = 0; j < 10; j++) tptr[j] = global_eval_context.wenv[j]; /* copy the appropriate args into the stack */ if (nargs > 10) nargs = 10; /* maximum ten args */ for (j = 0; j < nargs; j++) global_eval_context.wenv[j] = args[j]; for (; j < 10; j++) global_eval_context.wenv[j] = NULL; tp = tbuf = safe_atr_value(attrib); if (attrib->flags & AF_DEBUG) pe_flags |= PE_DEBUG; process_expression(buff, bp, &tp, obj, executor, enactor, pe_flags, PT_DEFAULT, pe_info); free(tbuf); /* restore the stack */ for (j = 0; j < 10; j++) global_eval_context.wenv[j] = tptr[j]; } /* ARGSUSED */ FUNCTION(fun_ufun) { ATTR *attrib; dbref obj; /* find the user function attribute */ parse_attrib(executor, args[0], &obj, &attrib); if (!GoodObject(obj)) { safe_str(T("#-1 INVALID OBJECT"), buff, bp); return; } if (attrib && Can_Read_Attr(executor, obj, attrib)) { if (!CanEvalAttr(executor, obj, attrib)) { safe_str(T(e_perm), buff, bp); return; } do_userfn(buff, bp, obj, attrib, nargs - 1, args + 1, executor, caller, enactor, pe_info); return; } else if (attrib || !Can_Examine(executor, obj)) { safe_str(T(e_atrperm), buff, bp); return; } return; } /* ARGSUSED */ FUNCTION(fun_ulocal) { /* Like fun_ufun, but saves the state of the q0-q9 registers * when called */ ATTR *attrib; dbref obj; char *preserve[NUMQ]; /* find the user function attribute */ parse_attrib(executor, args[0], &obj, &attrib); if (!GoodObject(obj)) { safe_str(T("#-1 INVALID OBJECT"), buff, bp); return; } if (attrib && Can_Read_Attr(executor, obj, attrib)) { if (!CanEvalAttr(executor, obj, attrib)) { safe_str(T(e_perm), buff, bp); return; } save_global_regs("ulocal.save", preserve); do_userfn(buff, bp, obj, attrib, nargs - 1, args + 1, executor, caller, enactor, pe_info); restore_global_regs("ulocal.save", preserve); return; } else if (attrib || !Can_Examine(executor, obj)) { safe_str(T(e_atrperm), buff, bp); return; } return; } /* Like fun_ufun, but takes as second argument a default message * to use if the attribute isn't there. If called as uldefault, * then preserve registers, too. */ /* ARGSUSED */ FUNCTION(fun_uldefault) { dbref thing; ATTR *attrib; char *dp; char const *sp; char mstr[BUFFER_LEN]; char **xargs; int i; char *preserve[NUMQ]; /* find our object and attribute */ dp = mstr; sp = args[0]; process_expression(mstr, &dp, &sp, executor, caller, enactor, PE_DEFAULT, PT_DEFAULT, pe_info); *dp = '\0'; parse_attrib(executor, mstr, &thing, &attrib); if (GoodObject(thing) && attrib && CanEvalAttr(executor, thing, attrib) && Can_Read_Attr(executor, thing, attrib)) { /* Ok, we've got it */ /* We must now evaluate all the arguments from args[2] on and * pass them to the function */ xargs = NULL; if (nargs > 2) { xargs = (char **) mush_malloc((nargs - 2) * sizeof(char *), "udefault.xargs"); for (i = 0; i < nargs - 2; i++) { xargs[i] = (char *) mush_malloc(BUFFER_LEN, "udefault"); dp = xargs[i]; sp = args[i + 2]; process_expression(xargs[i], &dp, &sp, executor, caller, enactor, PE_DEFAULT, PT_DEFAULT, pe_info); *dp = '\0'; } } if (called_as[1] == 'L') save_global_regs("uldefault.save", preserve); do_userfn(buff, bp, thing, attrib, nargs - 2, xargs, executor, caller, enactor, pe_info); if (called_as[1] == 'L') restore_global_regs("uldefault.save", preserve); /* Free the xargs */ if (nargs > 2) { for (i = 0; i < nargs - 2; i++) mush_free(xargs[i], "udefault"); mush_free(xargs, "udefault.xargs"); } return; } /* We couldn't get it. Evaluate args[1] and return it */ sp = args[1]; if (called_as[1] == 'L') save_global_regs("uldefault.save", preserve); process_expression(buff, bp, &sp, executor, caller, enactor, PE_DEFAULT, PT_DEFAULT, pe_info); if (called_as[1] == 'L') restore_global_regs("uldefault.save", preserve); return; } /* ARGSUSED */ FUNCTION(fun_zfun) { ATTR *attrib; dbref zone; zone = Zone(executor); if (zone == NOTHING) { safe_str(T("#-1 INVALID ZONE"), buff, bp); return; } /* find the user function attribute */ attrib = atr_get(zone, upcasestr(args[0])); if (attrib && Can_Read_Attr(executor, zone, attrib)) { if (!CanEvalAttr(executor, zone, attrib)) { safe_str(T(e_perm), buff, bp); return; } do_userfn(buff, bp, zone, attrib, nargs - 1, args + 1, executor, caller, enactor, pe_info); return; } else if (attrib || !Can_Examine(executor, zone)) { safe_str(T(e_atrperm), buff, bp); return; } safe_str(T("#-1 NO SUCH USER FUNCTION"), buff, bp); return; }