/* Copyright (C) 1991, Marcus J. Ranum. All rights reserved. */ #ifndef lint static char RCSid[] = "$Header: /home/mjr/hacks/umud/RCS/vars.c,v 1.15 91/10/28 21:35:15 mjr Exp $"; #endif /* configure all options BEFORE including system stuff. */ #include "config.h" #include <ctype.h> #include "mud.h" #include "sbuf.h" #include "match.h" /* variable flags */ #define VAR_PRIV 001 /* wiz-only can set */ #define VAR_MTYP 002 /* can be more than one type */ #define VAR_PRIVPLY 004 /* only wizzes can set this for players */ #define VAR_PUBLIC 010 /* can be seen with $thing.attrib */ #define VAR_LOC_PUBLIC 020 /* can be seen with $thing.attrib, if it's nearby */ #define LOC_PUB_COOKIE '+' /* Attributes starting with this char are automagically LOC_PUBLIC */ /* WARNING - globals will robinson, globals! */ char typ_str[] = "str"; char typ_int[] = "int"; char typ_cmd[] = "cmd"; char typ_list[] = "lst"; char typ_bool[] = "boo"; char typ_obj[] = "obj"; char typ_flag[] = "flg"; char var_loc[] = "loc"; char var_cont[] = "con"; char var_xit[] = "xit"; char var_dest[] = "dst"; char var_dropto[] = "drpto"; char var_lock[] = "lok"; char var_link[] = "lnk"; char var_ply[] = "ply"; char var_owner[] = "own"; char var_nam[] = "nam"; char var_desc[] = "desc"; char var_text[] = "txt"; char var_pass[] = "pass"; char var_using[] = "use"; char var_wiz[] = "_wz"; char var_fail[] = "fail"; char var_ofail[] = "ofail"; char var_succ[] = "succ"; char var_osucc[] = "osucc"; char var_drop[] = "drop"; char var_odrop[] = "odrop"; char var_isplay[] = "_pl"; char var_isdark[] = "dark"; char var_isroom[] = "_rm"; char var_islocal[] = "lcl"; char var_newsart[] = "newsarticle"; char var_subive[] = "subv"; char var_Subve[] = "Subv"; char var_objive[] = "objv"; char var_Objve[] = "Objv"; char var_posive[] = "posv"; char var_Posve[] = "Posv"; char var_home[] = "home"; char var_linkmsg[] = "linkmsg"; #ifdef COMBAT char var_strength[] = "_stren"; char var_Strength[] = "_Stren"; char var_endurance[] = "_endur"; char var_Endurance[] = "_Endur"; char var_willpowr[] = "_willp"; char var_Willpowr[] = "_Willp"; char var_agility[] = "_dextr"; char var_Agility[] = "_Dextr"; char var_magic[] = "_magic"; char var_Magic[] = "_Magic"; char var_action[] = "_actup"; char var_Action[] = "_Actup"; char var_power[] = "_power"; char var_Power[] = "_Power"; char var_lastupd[] = "_lupd"; char var_lasthit[] = "_lhit"; char var_lastatt[] = "_latt"; char var_armor[] = "_armor"; char var_defend[] = "_defend"; char var_attack[] = "_attack"; #endif /* system object related stuff. */ char system_object[] = "sysobj"; char var_objcnt[] = "_objcnt"; char var_syslimbo[] = "_syslimbo"; char var_wizs[] = "_wizards"; char var_bsequence[] = "_backupseq"; /* variable type table */ static struct typtab { char *tnam; } ttab[] = { typ_str, typ_int, typ_cmd, typ_list, typ_bool, typ_obj, typ_flag, 0 }; /* variable permissions and other whatnots table. these should be roughly in order of preference, since "set" chooses based on first match */ static struct vartab { char *vnam; /* actual attribute name */ char *vlong; /* long "readable" name */ char *deftyp; /* default type (unless specified) */ int flg; /* various flags */ char *desc; /* description of attribute */ } vtab[] = { var_desc, "description", typ_str, VAR_LOC_PUBLIC, "description", var_text, "text", typ_str, VAR_LOC_PUBLIC, "text inscription", var_fail, "failure", typ_str, VAR_MTYP, "failure message/command", var_ofail, "ofailure", typ_str, VAR_MTYP, "other player failure message/command", var_succ, "success", typ_str, VAR_MTYP, "success message/command", var_osucc, "osuccess", typ_str, VAR_MTYP, "other player success message/command", var_drop, "drop", typ_str, VAR_MTYP, "drop message/command", var_odrop, "odrop", typ_str, VAR_MTYP, "other player drop message/command", var_subive, "subjective", typ_str, VAR_LOC_PUBLIC, "subjective pronoun", var_Subve, "Subjective", typ_str, VAR_LOC_PUBLIC, "subjective pronoun (capitalized)", var_objive, "objective", typ_str, VAR_LOC_PUBLIC, "objective pronoun", var_Objve, "Objective", typ_str, VAR_LOC_PUBLIC, "objective pronoun (capitalized)", var_posive, "possessive", typ_str, VAR_LOC_PUBLIC, "possessive pronoun", var_Posve, "Possessive", typ_str, VAR_LOC_PUBLIC, "possessive pronoun (capitalized)", #ifdef PLAYER_NAMECHANGING var_nam, "name", typ_str, VAR_PUBLIC, "name", #else var_nam, "name", typ_str, VAR_PRIVPLY|VAR_PUBLIC, "name", #endif var_pass, "password", typ_str, VAR_PRIV, "object's password", var_owner, "owners", typ_list, 0, "object owner list", var_ply, "players", typ_list, VAR_PRIV, "room player list", var_cont, "contents", typ_list, VAR_PRIV, "contents list", var_xit, "exits", typ_list, VAR_PRIV, "room exit list", var_wizs, "wizardlist", typ_list, VAR_PRIV, "valid wizards", var_loc, "location", typ_obj, VAR_PRIV, "location of an object", var_dest, "destination", typ_obj, VAR_PRIV, "exit destination", var_dropto, "dropto", typ_obj, 0, "dropto destination", var_using, "holding", typ_obj, VAR_PRIV, "object being held by player", var_using, "using", typ_obj, VAR_PRIV, "object being used by player", var_home, "home", typ_obj, 0, "object's home location", var_lock, "lock", typ_bool, 0, "object access lock", var_link, "linkok", typ_bool, 0, "link permissions", var_isdark, "isdark", typ_flag, 0, "object is dark", var_islocal, "local", typ_flag, 0, "object is local", var_wiz, "wizard", typ_flag, VAR_PRIV, "object is a wizard", var_isplay, "isplayer", typ_flag, VAR_PRIV, "object is a player", var_isroom, "isroom", typ_flag, VAR_PRIV, "object is a room", var_newsart, "newsarticle", typ_int, 0, "last read news article", var_linkmsg, "linkmessage", typ_str, VAR_PRIV, "portal player moved through", 0, 0, 0, 0, 0 }; /* return nonzero if the variable is writeable only by The Big Guy */ int var_ispriv(vn) char *vn; { struct vartab *vp = vtab; /* any/all variable starting with underscore are reserved */ if(*vn == '_') return(1); while(vp->vnam != (char *)0) { if(!strcmp(vp->vnam,vn)) return((vp->flg & VAR_PRIV)); vp++; } return(0); } /* return nonzero if the variable is public */ int var_ispublic(vn,who,aswho,what) char *vn; char *who; char *aswho; char *what; { struct vartab *vp = vtab; if(*vn == LOC_PUB_COOKIE){ /* Order the checks in the 'best' way? */ return(!strcmp(ut_loc(who),ut_loc(what)) || !strcmp(who,ut_loc(what)) || !strcmp(ut_loc(who),what)); } while(vp->vnam != (char *)0) { if(!strcmp(vp->vnam,vn)){ if(vp->flg & VAR_PUBLIC) return(1); if(vp->flg & VAR_LOC_PUBLIC){ /* Order the checks in the 'best' way? */ return(!strcmp(ut_loc(who),ut_loc(what)) || !strcmp(who,ut_loc(what)) || !strcmp(ut_loc(who),what)); } } vp++; } return(0); } static int set_help(who) char *who; { struct vartab *vp = vtab; struct typtab *tp = ttab; char line[60]; /* TODO - prettier format ? */ say(who,"\nData types known to this MUD:\n",(char *)0); while(tp->tnam != (char *)0) { say(who,tp->tnam," ",(char *)0); tp++; } say(who,"\n\n",(char *)0); say(who,"Attributes known to this MUD:\n",(char *)0); say(who,"-long name- -(type : shortname)- -description-\n",(char *)0); while(vp->vnam != (char *)0) { sprintf(line,"%-13.13s(%-5.5s:%11.11s) %23.23s", vp->vlong, vp->deftyp, vp->vnam, vp->desc); say(who,line,(char *)0); if(vp->flg & VAR_PUBLIC) say(who," (public)",(char *)0); if(vp->flg & VAR_PRIV) say(who," (wiz-only)",(char *)0); if(vp->flg & VAR_MTYP) say(who," (multi-type)",(char *)0); if(vp->flg & VAR_PRIVPLY) say(who," (wiz-only on players)",(char *)0); say(who,"\n",(char *)0); vp++; } say(who,"\n",(char *)0); return(0); } /* resolve a possible long-form name to short form */ char * var_namatch(nam) char *nam; { struct vartab *vp = vtab; while(vp->vnam != (char *)0) { if(!strcmp(vp->vnam,nam)) return(nam); if(!strcmp(vp->vlong,nam)) return(vp->vnam); vp++; } return((char *)0); } /* ARGSUSED */ cmd_set(argc,argv,who,aswho) int argc; char *argv[]; char *who; char *aswho; { char *typp; char *atpp; char *vapp; struct vartab *vp = vtab; char ob[MAXOID]; int izlist = 0; int wiz; if(argc == 2 && !strcmp(argv[1],"help")) return(set_help(who)); if(argc < 3 || argc > 5) { say(who,"usage: set thing [type] attribute value\n",(char *)0); say(who,"or \"set help\" for help using \"set\"\n",(char *)0); return(1); } if(argc > 4) { typp = argv[2]; atpp = argv[3]; vapp = argv[4]; } else { typp = (char *)0; atpp = argv[2]; vapp = argv[3]; } /* can we find a match in the variable table? */ while(vp->vnam != (char *)0) { if(!strcmp(vp->vnam,atpp)) { if(typp == (char *)0) typp = vp->deftyp; break; } if(!strcmp(vp->vlong,atpp)) { if(typp == (char *)0) typp = vp->deftyp; atpp = vp->vnam; break; } vp++; } /* if it's not one of the known attributes, we need its type */ if(typp == (char *)0) { say(who,"\"",atpp,"\" data type unknown. You must provide its type.\n",(char *)0); return(1); } if (strlen(typp) == 0 || strlen(atpp) == 0 || index(typp, '=') != (char *) 0 || index(atpp, '=') != (char *)0) { say(who, "Attributes and types must be non-blank and contain no = characters.\n", (char *)0); return (1); } /* is this a priv'd attribute? */ wiz = ut_flagged(aswho,var_wiz); /* stamp out type clash - usually - only wizards may typeclash */ if(vp->vnam != (char *)0 && !wiz && !(vp->flg & VAR_MTYP) && strcmp(typp,vp->deftyp)) { say(who,vp->vlong," is only a ",vp->deftyp, ". You cannot set it to be a ",typp,".\n",(char *)0); return(1); } if(vp->vnam != (char *)0 && (vp->flg & VAR_PRIV) && !wiz) { say(who,"You must be a wizard to set ",vp->vlong,".\n",(char *)0); return(1); } /* next step: what should we be setting this attribute in? */ if(matchlocal(who,argv[1],ut_loc(who),MTCH_UNIQ|MTCH_NONLOC|MTCH_MEOK,ob)) return(1); /* check for wiz-only on player */ if((vp->flg & VAR_PRIVPLY) && !wiz && ut_flagged(ob,var_isplay)) { say(who,"You must be a wizard to set ",vp->vlong," for a player.\n",(char *)0); return(1); } /* next: do we own the thang?? */ if(!wiz && !ut_isobjown(aswho,ob)) { say(who,"You don't own ",ut_name(ob),".\n",(char *)0); return(1); } /* if the type is a flag, trap it here */ if(!strcmp(typp,typ_flag)) { /* Special case for DARK */ if(!wiz && !strcmp(atpp,var_isdark) && !ut_flagged(ob,var_isroom)){ say(who,"You can't set a non-room dark!\n",(char *)0); return(1); } if(ut_set(who,ob,typp,atpp,"")) return(1); if(run_level() == 0) say(who,"Set flag ",atpp,"\n",(char *)0); return(0); } /* at this point, we need another arg at least */ if(argc < 4) { say(who,"Set ",typp," ",atpp," to what?\n",(char *)0); return(1); } /* do not allow strings starting with '#' */ if(!wiz && !strcmp(typp,typ_str) && vapp[0] == '#') { say(who,"You cannot start a string with '#'.\n",(char *)0); return(1); } /* do re-writing and syntax checks on booleans */ if(!strcmp(typp,typ_bool)){ Sbuf suf; sbuf_initstatic(&suf); if(bool_rewrite(who,vapp,&suf)){ say(who,"Bad Boolean expression.\n",(char *)0); sbuf_freestatic(&suf); return(1); } vapp = sbuf_buf(&suf); if(bool_syntax(who,vapp)) { sbuf_freestatic(&suf); return(1); } if(ut_set(who,ob,typp,atpp,vapp)) { sbuf_freestatic(&suf); return(1); } if(run_level() == 0) say(who,"Set ",atpp,".\n",(char *)0); sbuf_freestatic(&suf); return(0); } /* special case for lists and objects being set to NULL */ izlist = !strcmp(typp,typ_list); if((izlist || !strcmp(typp,typ_obj)) && vapp[0] == '\0') { if(ut_unset(who,ob,atpp)) return(1); say(who,"Nulled out ",atpp,"\n",(char *)0); return(0); } /* special case for lists +thing and -thing */ if(izlist && (vapp[0] == '+' || vapp[0] == '-')) { char *thang; if(!strcmp("me",&vapp[1])) thang = aswho; else if(!strcmp("here",&vapp[1])) thang = ut_loc(who); else thang = &vapp[1]; if(vapp[0] == '-') { if(ut_listdel(who,ob,atpp,thang)) return(1); if(run_level() == 0) say(who,"Dropped ",thang," from ",atpp,"\n",(char *)0); return(0); } /* Must be adding it. Special case owners list. Xtra chex.*/ if(!strcmp(atpp,var_owner) && (!ut_isgoodid(thang) || !cache_check(thang))){ if(run_level() == 0) say(who,"Cannot add ",thang," to owners list.\n",(char *)0); return(1); } /* add away */ if(ut_listadd(who,ob,atpp,thang)) return(1); if(run_level() == 0) say(who,"Added ",thang," to ",atpp,"\n",(char *)0); return(0); } if(!wiz && izlist && (run_level() == 0)){ say(who, "Use + or - to manipulate lists, please.\n",(char *)0); return(0); } /* special case for droptos */ if(!strcmp(atpp,var_dropto)){ /* We setting this on a room? */ if(!wiz && !ut_flagged(ob,var_isroom)){ say(who,"Can't set a dropto on a non-room.\n",(char *)0); return(1); } /* Can we link to that? */ if(!wiz && strcmp(vapp,"home") && !ut_flagged(vapp,var_isroom)){ say(who,"Can't set a dropto to a non-room.\n",(char *)0); return(1); } if(!wiz && strcmp(vapp,"home") && !ut_isobjown(aswho,vapp) && bool_locked(aswho,vapp,ut_loc(aswho),var_link,1)){ say(who,"You can't link a dropto to ",vapp,".\n",(char *)0); return(1); } } /* special case for homes */ if(!strcmp(atpp,var_home)){ char hm[MAXOID]; if(matchlocal(who,vapp,ut_loc(who),MTCH_UNIQ|MTCH_NONLOC|MTCH_MEOK,hm)){ say(who,"I can't find ",vapp,".\n",(char *)0); return(1); } /* Can we set the home to it? */ if(!wiz &&!ut_isobjown(aswho,hm) && bool_locked(aswho,hm,ut_loc(aswho),var_link,1)){ say(who,"You can't set home to ",vapp,".\n",(char *)0); return(1); } if(!wiz && ut_flagged(ob,var_isplay)){ if(!ut_flagged(hm,var_isroom)){ say(who,vapp," isn't a room!\n",(char *)0); return(1); } } else if (!wiz) { if(!ut_flagged(hm,var_isroom) && !ut_flagged(hm,var_isplay)){ say(who,"You can't set home to ",vapp,".\n",(char *)0); return(1); } } if(index(hm,'@') == (char *)0){ /* Flesh the object ID out fully */ /* Be anal retentive about it */ if(strlen(hm) + strlen(mud_getname()) + 1 > MAXOID){ say(who,"You can't set home to ",vapp,".\n",(char *)0); return(1); } strcat(hm,"@"); strcat(hm,mud_getname()); } if(ut_set(who,ob,typp,atpp,hm)) return(1); if(run_level() == 0) say(who,"Set ",atpp,"\n",(char *)0); return(0); } if(ut_set(who,ob,typp,atpp,vapp)) return(1); if(run_level() == 0) say(who,"Set ",atpp,"\n",(char *)0); return(0); } /* ARGSUSED */ cmd_unset(argc,argv,who,aswho) int argc; char *argv[]; char *who; char *aswho; { char *atpp; struct vartab *vp = vtab; char ob[MAXOID]; int wiz; atpp = argv[2]; if (strlen(atpp) == 0 || index(atpp, '=') != (char *)0) { say(who, "Attributes must be non-blank and contain no = characters.\n", (char *)0); return (1); } while(vp->vnam != (char *)0) { if(!strcmp(vp->vnam,atpp)) break; if(!strcmp(vp->vlong,atpp)) { atpp = vp->vnam; break; } vp++; } wiz = ut_flagged(aswho,var_wiz); if(vp->vnam != (char *)0 && (vp->flg & VAR_PRIV) && !wiz) { say(who,"You must be a wizard to unset ",vp->vlong,".\n",(char *)0); return(1); } if(matchlocal(who,argv[1],ut_loc(who),MTCH_UNIQ|MTCH_NONLOC|MTCH_MEOK,ob)) return(1); if((vp->flg & VAR_PRIVPLY) && !wiz && ut_flagged(ob,var_isplay)) { say(who,"You must be a wizard to unset ",vp->vlong," for a player.\n",(char *)0); return(1); } if(!wiz && !ut_isobjown(aswho,ob)) { say(who,"You don't own ",ut_name(ob),".\n",(char *)0); return(1); } if(ut_unset(who,ob,atpp)) return(1); if(run_level() == 0) say(who,"Unset ",atpp,"\n",(char *)0); return(0); } /* check if this is a known attribute and possibly */ /* get the long name (to use as a title) */ fndvnam(vt,buf) char *vt; /* the attribute */ char *buf; /* long name? */ { struct vartab *vp; /* can we find a match in the variable table? */ for(vp = vtab; vp->vnam != (char *)0; ++vp) { if(!strcmp(vp->vnam,vt)) { if(buf != (char *)0) { strncpy(buf,vp->vlong,MAXOID - 1); } return(1); } } if(buf != (char *)0) strncpy(buf,vt,MAXOID - 1); /* gotta tell'em something... */ return(0); }