#include "defs.h" #include "prims.h" #include "property.h" #include "unused-arg.h" static PROPATTR prog_prop_perm(dbref player, dbref program, struct frame *fr, dbref obj) #define PROG_PROP_PERM(thing) (prog_prop_perm(player,program,fr,thing)&PPERM_HOW_M) { return(PPERM_PICKWHO(PGOD,PWIZARD,PROYALTY,permissions(UID,obj))); } PRIM(getpropval) { struct inst *vobj; struct inst *vname; struct inst *vdef; char *name; dbref obj; struct propref *pr; PROPATTR mask; NARGS(3); vobj = TOS(2); vname = TOS(1); vdef = TOS(0); if (vname->type != PROG_STRING) ABORT_INTERP("Non-string argument (2)"); name = vname->data.string; if (! name) ABORT_INTERP("Empty string argument (2)"); if (! valid_object(vobj)) ABORT_INTERP("Non-object argument (1)"); obj = vobj->data.objref; pr = lookup_property(obj,name,0); mask = PROG_PROP_PERM(obj); if (pr) { if (propref_get_attr(pr) & mask & PPERM_BIT_R) { switch (propref_get_attr(pr) & PATTR_TYPE) { case PTYPE_NIL: panic("PRIM(getpropval): type == nil"); break; case PTYPE_STRING: POP(3); MPUSH(PROG_STRING,propref_get_string(pr)); break; case PTYPE_DBREF: POP(3); MPUSH(PROG_OBJECT,propref_get_dbref(pr)); break; case PTYPE_ANYVAL: POP(3); MPUSH(PROG_NONE,propref_get_anyval(pr)); break; default: panic("PRIM(getpropval): bad type"); break; } } else if (propref_get_attr(pr) & mask & PPERM_BIT_X) { propref_done(pr); ABORT_INTERP("Permission denied."); } else { struct inst v; copyinst(vdef,&v); POP(3); MPUSH(PROG_NONE,v); } propref_done(pr); } else { struct inst v; copyinst(vdef,&v); POP(3); MPUSH(PROG_NONE,v); } } PRIM(getpropstr) { struct inst *vobj; struct inst *vname; dbref obj; char *name; struct propref *pr; PROPATTR mask; char *val; NARGS(2); vname = TOS(0); vobj = TOS(1); if (vname->type != PROG_STRING) ABORT_INTERP("Non-string argument (2)"); name = vname->data.string; if (! name) ABORT_INTERP("Empty string argument (2)"); if (! valid_object(vobj)) ABORT_INTERP("Non-object argument (1)"); obj = vobj->data.objref; pr = lookup_property(obj,name,0); mask = PROG_PROP_PERM(obj); val = 0; if (pr) { if (propref_get_attr(pr) & mask & PPERM_BIT_R) { switch (propref_get_attr(pr) & PATTR_TYPE) { case PTYPE_NIL: panic("PRIM(getpropstr): type == nil"); break; case PTYPE_STRING: val = propref_get_string(pr); break; case PTYPE_DBREF: val = malloc(64); sprintf(val,"#%d",(int)propref_get_dbref(pr)); break; case PTYPE_ANYVAL: break; default: panic("PRIM(getpropstr): bad type"); break; } } else if (propref_get_attr(pr) & mask & PPERM_BIT_X) { propref_done(pr); ABORT_INTERP("Permission denied."); } propref_done(pr); } POP(2); MPUSH(PROG_STRING,val); } PRIM(remove_prop) { struct inst *vobj; struct inst *vname; dbref obj; char *name; struct propref *pr; PROPATTR mask; NARGS(2); vname = TOS(0); vobj = TOS(1); if (vname->type != PROG_STRING) ABORT_INTERP("Non-string argument (2)"); name = vname->data.string; if (! name) ABORT_INTERP("Empty string argument (2)"); if (! valid_object(vobj)) ABORT_INTERP("Non-object argument (1)"); obj = vobj->data.objref; mask = PROG_PROP_PERM(obj); pr = lookup_property(obj,name,0); if (pr) { if (propref_get_attr(pr) & mask & PPERM_BIT_D) { propref_remove(pr); } else if (propref_get_attr(pr) & mask & PPERM_BIT_X) { propref_done(pr); ABORT_INTERP("Permission denied."); } else { propref_done(pr); } } POP(2); } PRIM(addprop) { struct inst *vobj; struct inst *vname; struct inst *vval; dbref obj; char *name; struct propref *pr; PROPATTR mask; if (*top >= 4) { struct inst *vint; vint = TOS(0); vval = TOS(1); vname = TOS(2); vobj = TOS(3); if ( (vint->type == PROG_INTEGER) && (vval->type == PROG_STRING) && (vname->type == PROG_STRING) && valid_object(vobj) && vname->data.string ) { POP(1); } } NARGS(3); vval = TOS(0); vname = TOS(1); vobj = TOS(2); if (vname->type != PROG_STRING) ABORT_INTERP("Non-string argument (2)"); name = vname->data.string; if (! name) ABORT_INTERP("Empty string argument (2)"); if (! ok_prop_name(name)) ABORT_INTERP("Invalid property name"); if (! valid_object(vobj)) ABORT_INTERP("Non-object argument (1)"); if (vval->type != PROG_STRING) ABORT_INTERP("Non-string argument (3)"); obj = vobj->data.objref; mask = PROG_PROP_PERM(obj); pr = create_property_compat(obj,name); if (propref_get_attr(pr) & mask & PPERM_BIT_W) { propref_set_type_and_value(pr,PTYPE_STRING,vval->data.string); } else { propref_remove_nil_or_done(pr); ABORT_INTERP("Permission denied."); } propref_done(pr); POP(3); } PRIM(prop_existsp) { struct inst *vobj; struct inst *vname; dbref obj; char *name; struct propref *pr; int rv; PROPATTR mask; NARGS(2); vname = TOS(0); vobj = TOS(1); if (vname->type != PROG_STRING) ABORT_INTERP("Non-string argument (2)"); name = vname->data.string; if (! name) ABORT_INTERP("Empty string argument (2)"); if (! valid_object(vobj)) ABORT_INTERP("Non-object argument (1)"); obj = vobj->data.objref; pr = lookup_property(obj,name,0); mask = PROG_PROP_PERM(obj); rv = 0; if (pr) { if (propref_get_attr(pr) & mask & PPERM_BIT_X) rv = 1; propref_done(pr); } POP(2); MPUSH(PROG_INTEGER,rv); } #define PF_F_S 0x00000001 #define PF_F_D 0x00000002 #define PF_F_A 0x00000004 #define PF_F__UFLG 0x00000007 static int propfirst_walk(struct propref *pr, void *vvp) #define flags (*(unsigned int *)(((void **)vvp)[0])) #define head (((void **)vvp)[1]) #define mask (*(PROPATTR *)(((void **)vvp)[2])) { struct plt_prop *pp; unsigned int fbit; if (propref_get_attr(pr) & mask & PPERM_BIT_F) { switch (propref_get_attr(pr) & PATTR_TYPE) { case PTYPE_NIL: panic("propfirst_walk: type==nil"); break; case PTYPE_STRING: fbit = PF_F_S; break; case PTYPE_DBREF: fbit = PF_F_D; break; case PTYPE_ANYVAL: fbit = PF_F_A; break; default: panic("propfirst_walk: bad type"); break; } if (flags & fbit) { pp = malloc(sizeof(struct plt_prop)); pp->link = head; head = pp; pp->name = dup_string(propref_get_name(pr)); } } return(0); } #undef flags #undef head #undef mask static char *plt_pop_name(struct plt *plt) { struct plt_prop *pp; char *rv; pp = plt->props; plt->props = pp->link; rv = pp->name; free(pp); return(rv); } PRIM(propfirst) { struct inst *vobj; dbref obj; unsigned int flags; PROPATTR mask; void *vv[3]; int npop; NARGS(1); vobj = TOS(0); if (valid_object(vobj)) { flags = PF_F_S; npop = 1; } else { struct inst *vflg; NARGS(2); vflg = TOS(0); vobj = TOS(1); if (! valid_object(vobj)) ABORT_INTERP("Non-object argument (1)"); if (vflg->type != PROG_INTEGER) ABORT_INTERP("Non-integer argument (2)"); flags = vflg->data.number & PF_F__UFLG; npop = 2; } obj = vobj->data.objref; mask = PROG_PROP_PERM(obj); vv[0] = &flags; vv[1] = 0; vv[2] = &mask; walk_plist(DBFETCH(obj)->properties,0,propfirst_walk,&vv[0]); if (vv[1]) { struct plt *plt; plt = malloc(sizeof(struct plt)); plt->refcnt = 1; plt->dbr = obj; plt->serial = DBFETCH(obj)->serial; plt->props = vv[1]; STACKROOM(3-npop); POP(npop); MPUSH(PROG_PLT,plt); MPUSH(PROG_STRING,plt_pop_name(plt)); MPUSH(PROG_INTEGER,1); } else { POP(npop); MPUSH(PROG_INTEGER,0); } } PRIM(propnext) { struct inst *vplt; dbref obj; NARGS(1); vplt = TOS(0); if (vplt->type != PROG_PLT) ABORT_INTERP("Argument is not a traversal object"); obj = vplt->data.plt->dbr; if (vplt->data.plt->serial != DBFETCH(obj)->serial) { ABORT_INTERP("Traversal dbref has been recycled"); } if (vplt->data.plt->props) { STACKROOM(2); MPUSH(PROG_STRING,plt_pop_name(vplt->data.plt)); MPUSH(PROG_INTEGER,1); } else { POP(1); MPUSH(PROG_INTEGER,0); } } PRIM(addprop_if) { struct inst *vobj; struct inst *vname; struct inst *vval; dbref obj; char *name; struct propref *pr; PROPATTR mask; int didexist; NARGS(3); vval = TOS(0); vname = TOS(1); vobj = TOS(2); if (vname->type != PROG_STRING) ABORT_INTERP("Non-string argument (2)"); name = vname->data.string; if (! name) ABORT_INTERP("Empty string argument (2)"); if (! ok_prop_name(name)) ABORT_INTERP("Invalid property name"); if (! valid_object(vobj)) ABORT_INTERP("Non-object argument (1)"); if (vval->type != PROG_STRING) ABORT_INTERP("Non-string argument (3)"); obj = vobj->data.objref; mask = PROG_PROP_PERM(obj); pr = create_property_compat(obj,name); didexist = ((propref_get_attr(pr) & PATTR_TYPE) != PTYPE_NIL); mask &= propref_get_attr(pr); if (mask & PPERM_BIT_X) { if (didexist) { if (mask & PPERM_BIT_R) { } else { propref_done(pr); ABORT_INTERP("Permission denied."); } } else { if (mask & PPERM_BIT_W) { propref_set_type_and_value(pr,PTYPE_STRING,vval->data.string); propref_done(pr); pr = 0; } else { propref_remove(pr); pr = 0; } } } else { if (mask & PPERM_BIT_W) { propref_set_type_and_value(pr,PTYPE_STRING,vval->data.string); propref_done(pr); pr = 0; } else { if (didexist) propref_done(pr); else propref_remove(pr); ABORT_INTERP("Permission denied."); } } if (pr) { char *val; val = 0; switch (propref_get_attr(pr) & PATTR_TYPE) { case PTYPE_NIL: panic("PRIM(getpropstr): type == nil"); break; case PTYPE_STRING: val = propref_get_string(pr); break; case PTYPE_DBREF: val = malloc(64); sprintf(val,"#%d",(int)propref_get_dbref(pr)); break; case PTYPE_ANYVAL: break; default: panic("PRIM(getpropstr): bad type"); break; } POP(3); MPUSH(PROG_STRING,val); propref_done(pr); } else { POP(3); MPUSH(PROG_INTEGER,0); } } PRIM(remprop_if) { struct inst *vobj; struct inst *vname; struct inst *vval; dbref obj; char *name; struct propref *pr; PROPATTR mask; int rv; NARGS(2); vval = TOS(0); vname = TOS(1); vobj = TOS(2); if (vname->type != PROG_STRING) ABORT_INTERP("Non-string argument (2)"); name = vname->data.string; if (! name) ABORT_INTERP("Empty string argument (2)"); if (! valid_object(vobj)) ABORT_INTERP("Non-object argument (1)"); if (vval->type != PROG_STRING) ABORT_INTERP("Non-string argument (3)"); obj = vobj->data.objref; pr = lookup_property(obj,name,0); mask = PROG_PROP_PERM(obj); rv = 0; if (pr) { mask &= propref_get_attr(pr); if (mask & PPERM_BIT_X) { if ((mask & PPERM_BIT_R) && (mask & PPERM_BIT_D)) { if ((propref_get_attr(pr) & PATTR_TYPE) == PTYPE_STRING) { char *val; val = propref_get_string(pr); if ( (!val && !vval->data.string) || (val && vval->data.string && !strcmp(val,vval->data.string)) ) { propref_remove(pr); pr = 0; rv = 1; } free(val); } } else { ABORT_INTERP("Permission denied."); } } } if (pr) propref_done(pr); POP(3); MPUSH(PROG_INTEGER,rv); } PRIM(name) { struct inst *v; char *rv; NARGS(1); v = TOS(0); if (! valid_object(v)) ABORT_INTERP("Invalid argument type."); rv = dup_string(NAME(v->data.objref)); POP(1); MPUSH(PROG_STRING,rv); } #define FOO(name,field) \ PRIM(name) { struct inst *v; char *rv; NARGS(1); v = TOS(0); \ if (!valid_object(v)) ABORT_INTERP("Invalid argument type."); \ rv = fetch_str(DBFETCH(v->data.objref)->field); POP(1); \ MPUSH(PROG_STRING,rv); } FOO(desc,description) FOO(succ,succ_message) FOO(fail,fail_message) FOO(drop,drop_message) FOO(osucc,osuccess) FOO(ofail,ofail) FOO(odrop,odrop) #undef FOO #define FOO(name,field) \ PRIM(name) { struct inst *vobj; struct inst *vval; dbref obj; char *val;\ NARGS(2); vval = TOS(0); vobj = TOS(1); if (vval->type != \ PROG_STRING) ABORT_INTERP("Non-string argument (2)"); \ val = vval->data.string; if (! valid_object(vobj)) \ { ABORT_INTERP("Non-object argument (1)"); } \ obj = vobj->data.objref; if (!PWIZARD && !permissions(UID,obj)) \ { ABORT_INTERP("Permission denied."); } \ free_str(DBFETCH(obj)->field); DBSTORE(obj,field, \ store_str(val)); POP(2); } FOO(setdesc,description) FOO(setsucc,succ_message) FOO(setfail,fail_message) FOO(setdrop,drop_message) FOO(setosucc,osuccess) FOO(setofail,ofail) FOO(setodrop,odrop) #undef FOO PRIM(setname) { struct inst *vobj; struct inst *vname; dbref obj; char *name; NARGS(2); vname = TOS(0); vobj = TOS(1); if (vname->type != PROG_STRING) ABORT_INTERP("Non-string argument (2)"); name = vname->data.string; if (! ok_name(name)) ABORT_INTERP("Invalid name."); if (! valid_object(vobj)) ABORT_INTERP("Non-object argument (1)"); obj = vobj->data.objref; if (!PWIZARD && !permissions(UID,obj)) ABORT_INTERP("Permission denied."); if (Typeof(obj) == TYPE_PLAYER) { if (! PWIZARD) ABORT_INTERP("Permission denied."); if (! ok_player_name(name)) ABORT_INTERP("Invalid player name."); delete_player(obj); if (NAME(obj)) free(NAME(obj)); NAME(obj) = dup_string(name); add_player(obj); } else { if (NAME(obj)) free(NAME(obj)); NAME(obj) = dup_string(name); } POP(2); } PRIM(pennies) { struct inst *v; dbref obj; int rv; NARGS(1); v = TOS(0); if (! valid_object(v)) ABORT_INTERP("Invalid argument type."); obj = v->data.objref; switch (Typeof(obj)) { case TYPE_PLAYER: rv = DBFETCH(obj)->sp.player.pennies; break; case TYPE_THING: rv = DBFETCH(obj)->sp.thing.value; break; default: ABORT_INTERP("Invalid object type."); break; } POP(1); MPUSH(PROG_INTEGER,rv); } PRIM(addpennies) { struct inst *vobj; struct inst *vamt; dbref obj; int amt; NARGS(2); vamt = TOS(0); vobj = TOS(1); if (! valid_object(vobj)) ABORT_INTERP("Invalid object argument. (1)"); if (vamt->type != PROG_INTEGER) ABORT_INTERP("Non-integer argument. (2)"); obj = vobj->data.objref; amt = vamt->data.number; if (Typeof(obj) == TYPE_PLAYER) { #ifdef ADDPENNIES_UNRESTRICTED { int p; p = DBFETCH(obj)->sp.player.pennies + amt; if (! PWIZARD) { if (p < 0) ABORT_INTERP("Result would be negative"); #ifdef MAX_PENNIES if ((p > MAX_PENNIES) && !Wizard(obj)) ABORT_INTERP("Result would exceed MAX_PENNIES"); #endif } add_pennies(obj,amt,"#%d",(int)program); } #endif #ifdef ADDPENNIES_CONSERVING { dbref src; src = OWNER(program); if (src != obj) { int pdst; int psrc; pdst = DBFETCH(obj)->sp.player.pennies + amt; psrc = DBFETCH(src)->sp.player.pennies - amt; if (! PWIZARD) { if (pdst < 0) ABORT_INTERP("Result would be negative"); if (psrc < 0) ABORT_INTERP("Money not available"); #ifdef MAX_PENNIES if ((pdst > MAX_PENNIES) && !Wizard(obj)) ABORT_INTERP("Result would exceed MAX_PENNIES"); if ((psrc > MAX_PENNIES) && !Wizard(src)) ABORT_INTERP("Result would exceed MAX_PENNIES"); #endif } add_pennies(obj,amt,"#%d",(int)program); if (! Wizard(src)) add_pennies(src,-amt,"#%d",(int)program); } else if (PWIZARD) { add_pennies(obj,amt,"#%d",(int)program); } } #endif #ifdef ADDPENNIES_WIZ_ONLY { if (! PWIZARD) ABORT_INTERP("Permission denied."); add_pennies(obj,amt,"#%d",(int)program); } #endif } else if (Typeof(obj) == TYPE_THING) { int p; if (! PWIZARD) ABORT_INTERP("Permission denied."); p = DBFETCH(obj)->sp.thing.value + amt; if (p < 1) ABORT_INTERP("Result must be positive."); DBSTORE(obj,sp.thing.value,p); } else { ABORT_INTERP("Invalid object type."); } POP(2); } PRIM(getpropperm) { struct inst *vobj; struct inst *vname; char *name; dbref obj; struct propref *pr; PROPATTR rv; NARGS(2); vname = TOS(0); vobj = TOS(1); if (vname->type != PROG_STRING) ABORT_INTERP("Non-string argument (2)"); name = vname->data.string; if (! name) ABORT_INTERP("Empty string argument (2)"); if (! valid_object(vobj)) ABORT_INTERP("Non-object argument (1)"); obj = vobj->data.objref; pr = lookup_property(obj,name,0); if (pr) { rv = propref_get_attr(pr); propref_done(pr); } else { rv = 0; } if (! (rv & PROG_PROP_PERM(obj) & PPERM_BIT_X)) rv = 0; POP(2); MPUSH(PROG_QUAD,(MUFQUAD)(rv&PATTR_PERM)); } PRIM(setpropperm) { struct inst *vobj; struct inst *vname; struct inst *vperm; char *name; dbref obj; PROPATTR perm; struct propref *pr; PROPATTR who; PROPATTR canchange; PROPATTR attr; NARGS(3); vperm = TOS(0); vname = TOS(1); vobj = TOS(2); if (vperm->type != PROG_QUAD) ABORT_INTERP("Non-quad argument (3)"); if (vname->type != PROG_STRING) ABORT_INTERP("Non-string argument (2)"); name = vname->data.string; if (! name) ABORT_INTERP("Empty string argument (2)"); if (! valid_object(vobj)) ABORT_INTERP("Non-object argument (1)"); obj = vobj->data.objref; who = prog_prop_perm(player,program,fr,obj); switch (who) { case PPERM_WHO_G: canchange = PATTR_PERM; break; case PPERM_WHO_W: canchange = PPERM_WHO_W|PPERM_WHO_R|PPERM_WHO_O|PPERM_WHO_A; break; case PPERM_WHO_R: canchange = PPERM_WHO_R|PPERM_WHO_O|PPERM_WHO_A; break; case PPERM_WHO_O: canchange = PPERM_WHO_O|PPERM_WHO_A; break; case PPERM_WHO_A: canchange = PPERM_WHO_A; break; default: ABORT_INTERP("Impossible who in SETPROPPERM - this is a bug!"); break; } perm = *vperm->data.quad; pr = lookup_property(obj,name,0); if (! pr) { ABORT_INTERP("Property not found."); } else { attr = propref_get_attr(pr); if (attr & who & PPERM_HOW_M & PPERM_BIT_C) { propref_set_perms(pr,(((attr&~canchange)|(perm&canchange))&~PATTR_MBZ)|PATTR_MBO); } else if (attr & who & PPERM_HOW_M & PPERM_BIT_X) { ABORT_INTERP("Permission denied."); } else { ABORT_INTERP("Property not found."); } propref_done(pr); } POP(3); } #define FOO(name,bit) \ PRIM(name) { STACKROOM(1); MPUSH(PROG_QUAD,(MUFQUAD)(bit)); } FOO(propperm_who_o,PPERM_WHO_O) FOO(propperm_who_r,PPERM_WHO_R) FOO(propperm_who_w,PPERM_WHO_W) FOO(propperm_who_a,PPERM_WHO_A) FOO(propperm_bit_r,PPERM_BIT_R) FOO(propperm_bit_x,PPERM_BIT_X) FOO(propperm_bit_w,PPERM_BIT_W) FOO(propperm_bit_d,PPERM_BIT_D) FOO(propperm_bit_f,PPERM_BIT_F) FOO(propperm_bit_c,PPERM_BIT_C) FOO(propperm_how_c,PPERM_HOW_C) FOO(propperm_how_m,PPERM_HOW_M) FOO(propperm_how_l,PPERM_HOW_L) #undef FOO PRIM(getpwhash) { struct inst *vobj; dbref obj; NARGS(1); vobj = TOS(0); if (!valid_object(vobj) || (Typeof(vobj->data.objref) != TYPE_PLAYER)) ABORT_INTERP("Not a player."); if (! PWIZARD) ABORT_INTERP("Permission denied."); obj = vobj->data.objref; POP(1); MPUSH(PROG_STRING,dup_string(DBFETCH(obj)->sp.player.password)); } PRIM(setprop) { struct inst *vobj; struct inst *vname; struct inst *vkey; struct inst *vval; PROPATTR perm; struct propref *pr; PROPATTR mask; PROPATTR type; int npop; NARGS(4); vval = TOS(0); vkey = TOS(1); if ( (vkey->type == PROG_STRING) && (vval->type == PROG_QUAD) && vkey->data.string && !strcmp(vkey->data.string,"perm") ) { perm = *vval->data.quad; NARGS(6); vval = TOS(2); vkey = TOS(3); vname = TOS(4); vobj = TOS(5); npop = 6; } else { perm = 0; vname = TOS(2); vobj = TOS(3); npop = 4; } if (! valid_object(vobj)) ABORT_INTERP("Non-object argument (1)"); if (vname->type != PROG_STRING) ABORT_INTERP("Non-string argument (2)"); if (vkey->type != PROG_STRING) ABORT_INTERP("Non-string argument (3)"); if (! vkey->data.string) ABORT_INTERP("Invalid key argument"); if (! strcmp(vkey->data.string,"string")) { if (vval->type != PROG_STRING) ABORT_INTERP("Non-string argument (4)"); type = PTYPE_STRING; } else if (! strcmp(vkey->data.string,"dbref")) { if ( (vval->type != PROG_OBJECT) || ((vval->data.objref != NOTHING) && !valid_object(vval)) ) { ABORT_INTERP("Non-object argument (4)"); } type = PTYPE_DBREF; } else if (! strcmp(vkey->data.string,"any")) { /* nothing to check here */ type = PTYPE_ANYVAL; } else { ABORT_INTERP("Invalid key argument"); } mask = PROG_PROP_PERM(vobj->data.objref); pr = perm ? lookup_property(vobj->data.objref,vname->data.string,LP_CREATE,perm) : create_property_compat(vobj->data.objref,vname->data.string); if (propref_get_attr(pr) & mask & PPERM_BIT_W) { switch (type) { case PTYPE_STRING: propref_set_type_and_value(pr,PTYPE_STRING,vval->data.string); break; case PTYPE_DBREF: propref_set_type_and_value(pr,PTYPE_DBREF,vval->data.objref); break; case PTYPE_ANYVAL: propref_set_type_and_value(pr,PTYPE_ANYVAL,vval); break; default: panic("PRIM(setprop): impossible type"); break; } } else { propref_remove_nil_or_done(pr); ABORT_INTERP("Permission denied."); } propref_done(pr); POP(npop); } PRIM(changeprop) { struct inst *vobj; struct inst *vname; struct inst *vold; struct inst *vnew; struct propref *pr; PROPATTR mask; int rv; char *ps; NARGS(4); vnew = TOS(0); vold = TOS(1); vname = TOS(2); vobj = TOS(3); if (! valid_object(vobj)) ABORT_INTERP("Non-object argument (1)"); if (vname->type != PROG_STRING) ABORT_INTERP("Non-string argument (2)"); if ( (vold->type != PROG_STRING) && (vold->type != PROG_OBJECT) ) ABORT_INTERP("Wrong type argument (3)"); if ( (vnew->type != PROG_STRING) && (vnew->type != PROG_OBJECT) ) ABORT_INTERP("Wrong type argument (4)"); if ( (vnew->type == PROG_OBJECT) && (vnew->data.objref != NOTHING) && !valid_object(vnew) ) ABORT_INTERP("Invalid dbref argument (4)"); mask = PROG_PROP_PERM(vobj->data.objref); pr = lookup_property(vobj->data.objref,vname->data.string,0); rv = 0; if (pr) { if ( (propref_get_attr(pr) & mask & PPERM_BIT_R) && (propref_get_attr(pr) & mask & PPERM_BIT_W) ) { switch (propref_get_attr(pr) & PATTR_TYPE) { case PTYPE_STRING: if (vold->type == PROG_STRING) { ps = propref_get_string(pr); if ( (!ps && !vold->data.string) || (ps && vold->data.string && !strcmp(ps,vold->data.string)) ) { rv = 1; } free(ps); } break; case PTYPE_DBREF: if ( (vold->type == PROG_OBJECT) && (vold->data.objref == propref_get_dbref(pr)) ) { rv = 1; } break; } if (rv) { switch (vnew->type) { case PROG_STRING: propref_set_type_and_value(pr,PTYPE_STRING,vnew->data.string); break; case PROG_OBJECT: propref_set_type_and_value(pr,PTYPE_DBREF,vnew->data.objref); break; default: panic("PRIM(changeprop): impossible new value type"); break; } } } else if (propref_get_attr(pr) & mask & PPERM_BIT_X) { propref_done(pr); ABORT_INTERP("Permission denied."); } } POP(4); MPUSH(PROG_INTEGER,rv); }