/* Copyright (C) 1991, Marcus J. Ranum. All rights reserved. */ #ifndef lint static char RCSid[] = "$Header: /home/mjr/hacks/umud/RCS/vars.c,v 1.12 92/05/17 23:32:46 mjr Exp $"; #endif /* configure all options BEFORE including system stuff. */ #include "config.h" #include <ctype.h> #include "mud.h" #include "vars.h" #include "sbuf.h" #include "match.h" /* 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 typ_u[] = "U"; 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_jump[] = "jmp"; 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"; char var_wearing[] = "_wear"; #ifdef COMBAT char var_strength[] = "_stren"; char var_Strength[] = "_Stren"; char var_endurance[] = "_endur"; char var_Endurance[] = "_Endur"; char var_willpower[] = "_willp"; char var_Willpower[] = "_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_counters[] = "counter"; char var_lastupd[] = "_lupd"; char var_lasthit[] = "_lhit"; char var_lastatt[] = "_latt"; char var_isdead[] = "_dead"; char var_weapon[] = "_weapon"; /* flags */ char var_isweapon[] = "_isweap"; char var_isarmor[] = "_isarm"; #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 */ TypTab ttab[] = { typ_str, typ_int, typ_cmd, typ_list, typ_bool, typ_obj, typ_flag, typ_u, 0 }; /* Newusers allowed flag? */ char newusers = 0; /* variable permissions and other whatnots table. these should be roughly in order of preference, since "set" chooses based on first match */ VarTab 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_LOC_PUBLIC|VAR_PRIV, "room player list", var_cont, "contents", typ_list, VAR_LOC_PUBLIC|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_jump, "jump", typ_bool, VAR_MTYP, "object access lock", var_lock, "lock", typ_bool, VAR_MTYP, "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", var_wearing, "wearing", typ_list, VAR_PRIV, "player garments", #ifdef COMBAT var_strength, "strength", typ_int, VAR_PRIV, "player current strength", var_Strength, "Strength", typ_int, VAR_PRIV, "player maximum strength", var_endurance, "endurance", typ_int, VAR_PRIV, "player current endurance", var_Endurance, "Endurance", typ_int, VAR_PRIV, "player maximum endurance", var_willpower, "willpower", typ_int, VAR_PRIV, "player current willpower", var_Willpower, "Willpower", typ_int, VAR_PRIV, "player maximum willpower", var_agility, "agility", typ_int, VAR_PRIV, "player current agility", var_Agility, "Agility", typ_int, VAR_PRIV, "player maximum agility", var_magic, "magic", typ_int, VAR_PRIV, "player current magic level", var_Magic, "Magic", typ_int, VAR_PRIV, "player maximum magic level", var_action, "action", typ_int, VAR_PRIV, "player current action points", var_Action, "Action", typ_int, VAR_PRIV, "player maximum action points", var_counters, "counters", typ_list, 0, "player counterattack list", var_power, "power", typ_int, VAR_PRIV, "player current power level", var_lastupd, "lastupd", typ_str, VAR_PRIV, "player last combat stats update time", var_lasthit, "lasthit", typ_obj, VAR_PRIV, "player last attacker that hit", var_lastatt, "lastatt", typ_obj, VAR_PRIV, "player last attacker", var_isdead, "isdead", typ_flag, VAR_PRIV, "player killed by something", var_weapon, "weapon", typ_obj, VAR_PRIV, "player weapon in use", var_isweapon, "isweapon", typ_flag, VAR_PRIV, "object is weapon flag", var_isarmor, "isarmor", typ_flag, VAR_PRIV, "object is armor flag", #endif 0, 0, 0, 0, 0 }; /* return nonzero if the variable is public */ int var_ispublic(vn,who,aswho,what) char *vn; char *who; char *aswho; char *what; { char *dst; int exitsees = 0; VarTab *vp = vtab; /* If we're an exit, we can see also local_public at our dst */ if(dst = ut_getatt(aswho,0,typ_obj,var_dest,(char *)0)) exitsees = (!strcmp(ut_loc(what), dst)); if(*vn == LOC_PUB_COOKIE) { return(!strcmp(ut_loc(who),ut_loc(what)) || !strcmp(who,ut_loc(what)) || !strcmp(ut_loc(who),what) || exitsees); } while(vp->vnam != (char *)0) { if(!strcmp(vp->vnam,vn)) { if(vp->flg & VAR_PUBLIC) return(1); if(vp->flg & VAR_LOC_PUBLIC) { if(ut_flagged(what,var_isdark)) return(0); return(!strcmp(ut_loc(who),ut_loc(what)) || !strcmp(who,ut_loc(what)) || !strcmp(ut_loc(who),what) || exitsees); } } vp++; } return(0); } static int set_help(who) char *who; { VarTab *vp = vtab; 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(UERR_NONE); } VarTab * var_tabfind(nam) char *nam; { VarTab *vp = vtab; while(vp->vnam != (char *)0) { if(!strcmp(vp->vnam,nam) || !strcmp(vp->vlong,nam)) return(vp); vp++; } return((VarTab *)0); } /* resolve a possible long-form name to short form */ char * var_namatch(nam) char *nam; { VarTab *vp; if((vp = var_tabfind(nam)) == (VarTab *)0) return((char *)0); return(vp->vnam); } /* ARGSUSED */ cmd_set(argc,argv,who,aswho) int argc; char *argv[]; char *who; char *aswho; { char ob[MAXOID]; char *typp; char *atpp; char *vapp; 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(UERR_ARGCNT); } if(matchlocal(who,argv[1],ut_loc(who),MTCH_UNIQ|MTCH_NONLOC|MTCH_MEOK,ob)) return(UERR_NOMATCH); typp = (char *)0; atpp = argv[2]; vapp = argv[3]; /* type spec given ? */ if(argc > 4) { typp = argv[2]; atpp = argv[3]; vapp = argv[4]; } return(var_set_internal(who,aswho,ob,typp,atpp,vapp,1)); } /* internal set routine - very gross!! but all this gook has to fit someplace called also from U-interpreter code. */ var_set_internal(who,aswho,ob,typp,atpp,vapp,vbose) char *who; char *aswho; char *ob; char *typp; char *atpp; char *vapp; int vbose; { VarTab *vp; int izlist = 0; int wiz; /* can we find a match in the variable table? */ if((vp = var_tabfind(atpp)) != (VarTab *)0) { if(typp == (char *)0) typp = vp->deftyp; atpp = vp->vnam; } /* if it's not one of the known attributes, we need its type */ if(typp == (char *)0) { if(vbose) say(who,"\"",atpp,"\" type unknown. Provide its type.\n",(char *)0); return(UERR_ILLASGN); } if (strlen(typp) == 0 || strlen(atpp) == 0 || index(typp, '=') != (char *) 0 || index(atpp, '=') != (char *)0) { if(vbose) say(who, "Attributes and types must be non-blank and contain no = characters.\n", (char *)0); return(UERR_ILLASGN); } /* is this a priv'd attribute? */ wiz = ut_flagged(aswho,var_wiz); /* stamp out type clash - usually - only wizards may typeclash */ if(vp != (VarTab *)0 && !wiz && !(vp->flg & VAR_MTYP) && strcmp(typp,vp->deftyp)) { if(vbose) say(who,vp->vlong," is only a ",vp->deftyp, ". You cannot set it to be a ",typp,".\n",(char *)0); return(UERR_ILLASGN); } /* priv'd attribute */ if(vp != (VarTab *)0 && (vp->flg & VAR_PRIV) && !wiz) { if(vbose) say(who,"You must be a wizard to set ",vp->vlong,".\n",(char *)0); return(UERR_PERM); } /* check for wiz-only on player */ if(vp != (VarTab *)0 && (vp->flg & VAR_PRIVPLY) && !wiz && ut_flagged(ob,var_isplay)) { if(vbose) say(who,"You must be a wizard to set ",vp->vlong," for a player.\n",(char *)0); return(UERR_PERM); } /* next: do we own the thang?? */ if(!wiz && !ut_isobjown(aswho,ob)) { if(vbose) say(who,"You don't own ",ut_name(ob),".\n",(char *)0); return(UERR_PERM); } /* 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)){ if(vbose) say(who,"You can't set a non-room dark!\n",(char *)0); return(UERR_ILLASGN); } if(ut_set(who,ob,typp,atpp,"")) return(UERR_FATAL); if(vbose && run_level() == 0) say(who,"Set flag ",atpp,"\n",(char *)0); return(UERR_NONE); } /* at this point, we need another arg at least */ if(vapp == (char *)0) { if(vbose) say(who,"Set ",typp," ",atpp," to what?\n",(char *)0); return(UERR_ARGCNT); } /* do not allow strings starting with '#' */ if(!wiz && !strcmp(typp,typ_str) && vapp[0] == '#') { if(vbose) say(who,"You cannot start a string with '#'.\n",(char *)0); return(UERR_ILLASGN); } /* do re-writing and syntax checks on booleans */ if(!strcmp(typp,typ_bool)) { Sbuf suf; sbuf_initstatic(&suf); if(bool_rewrite(who,vapp,&suf)) { if(vbose) say(who,"Bad Boolean expression.\n",(char *)0); sbuf_freestatic(&suf); return(UERR_SYNTAX); } vapp = sbuf_buf(&suf); if(bool_syntax(who,vapp)) { sbuf_freestatic(&suf); return(UERR_SYNTAX); } if(ut_set(who,ob,typp,atpp,vapp)) { sbuf_freestatic(&suf); return(UERR_FATAL); } if(vbose && run_level() == 0) say(who,"Set ",atpp,".\n",(char *)0); sbuf_freestatic(&suf); return(UERR_NONE); } /* 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(UERR_FATAL); if(vbose) say(who,"Nulled out ",atpp,"\n",(char *)0); return(UERR_NONE); } /* 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(UERR_FATAL); if(vbose && run_level() == 0) say(who,"Dropped ",thang," from ",atpp,"\n",(char *)0); return(UERR_NONE); } /* Must be adding it. Special case owners list. Xtra chex.*/ if(!strcmp(atpp,var_owner) && (!ut_isgoodid(thang) || !cache_check(thang))){ if(vbose && run_level() == 0) say(who,"Cannot add ",thang," to owners list.\n",(char *)0); return(UERR_BADOID); } /* add away */ if(ut_listadd(who,ob,atpp,thang)) return(UERR_FATAL); if(vbose && run_level() == 0) say(who,"Added ",thang," to ",atpp,"\n",(char *)0); return(UERR_NONE); } if(!wiz && izlist && vbose && run_level() == 0){ say(who, "Use + or - to manipulate lists, please.\n",(char *)0); return(UERR_ILLASGN); } /* special case for droptos */ if(!strcmp(atpp,var_dropto)){ /* We setting this on a room? */ if(!wiz && !ut_flagged(ob,var_isroom)){ if(vbose) say(who,"Can't set a dropto on a non-room.\n",(char *)0); return(UERR_ILLASGN); } /* Can we link to that? */ if(!wiz && strcmp(vapp,"home") && !ut_flagged(vapp,var_isroom)) { if(vbose) say(who,"Can't set a dropto to a non-room.\n",(char *)0); return(UERR_ILLASGN); } if(!wiz && strcmp(vapp,"home") && !ut_isobjown(aswho,vapp) && bool_locked(aswho,vapp,ut_loc(aswho),var_link,1)) { if(vbose) say(who,"You can't link a dropto to ",vapp,".\n",(char *)0); return(UERR_ILLASGN); } } /* 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)){ if(vbose) say(who,"I can't find ",vapp,".\n",(char *)0); return(UERR_NOMATCH); } /* Can we set the home to it? */ if(!wiz &&!ut_isobjown(aswho,hm) && bool_locked(aswho,hm,ut_loc(aswho),var_link,1)) { if(vbose) say(who,"You can't set home to ",vapp,".\n",(char *)0); return(UERR_PERM); } if(!wiz && ut_flagged(ob,var_isplay)) { if(!ut_flagged(hm,var_isroom)) { if(vbose) say(who,vapp," isn't a room!\n",(char *)0); return(UERR_ILLASGN); } } else if (!wiz) { if(!ut_flagged(hm,var_isroom) && !ut_flagged(hm,var_isplay)) { if(vbose) say(who,"You can't set home to ",vapp,".\n",(char *)0); return(UERR_ILLASGN); } } if(index(hm,'@') == (char *)0){ /* Flesh the object ID out fully */ /* Be anal retentive about it */ if(strlen(hm) + strlen(mud_getname()) + 1 > MAXOID){ if(vbose) say(who,"You can't set home to ",vapp,".\n",(char *)0); return(UERR_ILLASGN); } strcat(hm,"@"); strcat(hm,mud_getname()); } if(ut_set(who,ob,typp,atpp,hm)) return(UERR_FATAL); if(vbose && run_level() == 0) say(who,"Set ",atpp,"\n",(char *)0); return(UERR_NONE); } #ifdef PLAYER_NAMECHANGING /* log name changes - why not ? */ if(!wiz && !strcmp(atpp,var_nam) && ut_flagged(ob,var_isplay)) { if(index(vapp,'\'')||index(vapp,'\"')||index(vapp,';')) { if(vbose) say(who,"Illegal character in name.\n",(char *)0); return(UERR_ILLASGN); } plogf("%s changed %s name to %s\n",who,ob,vapp); } #endif if(ut_set(who,ob,typp,atpp,vapp)) return(UERR_FATAL); if(vbose && run_level() == 0) say(who,"Set ",atpp,"\n",(char *)0); return(UERR_NONE); } /* ARGSUSED */ cmd_unset(argc,argv,who,aswho) int argc; char *argv[]; char *who; char *aswho; { char ob[MAXOID]; if(matchlocal(who,argv[1],ut_loc(who),MTCH_UNIQ|MTCH_NONLOC|MTCH_MEOK,ob)) return(UERR_NOMATCH); return(var_unset_internal(who,aswho,ob,argv[2],1)); } var_unset_internal(who,aswho,ob,atpp,vbose) char *who; char *aswho; char *ob; char *atpp; int vbose; { int wiz; VarTab *vp = vtab; 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) { if(vbose) say(who,"You must be a wizard to unset ",vp->vlong,".\n",(char *)0); return(UERR_PERM); } if((vp->flg & VAR_PRIVPLY) && !wiz && ut_flagged(ob,var_isplay)) { if(vbose) say(who,"You must be a wizard to unset ",vp->vlong," for a player.\n",(char *)0); return(UERR_PERM); } if(!wiz && !ut_isobjown(aswho,ob)) { if(vbose) say(who,"You don't own ",ut_name(ob),".\n",(char *)0); return(UERR_PERM); } if(ut_unset(who,ob,atpp)) return(UERR_FATAL); if(vbose && run_level() == 0) say(who,"Unset ",atpp,"\n",(char *)0); return(UERR_NONE); } /* check if this is a known attribute and possibly */ /* get the long name (to use as a title) */ void fndvnam(vt,buf,siz) char *vt; /* the attribute */ char *buf; /* long name? */ int siz; { 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,siz - 2); return; } } if(buf != (char *)0) strncpy(buf,vt,siz - 2); /* gotta tell'em something... */ buf[siz - 1] = '\0'; } fndtyp(vt) char *vt; { TypTab *tp; for(tp = ttab; tp->tnam != (char *)0; tp++) if(!strcmp(vt,tp->tnam)) return(1); return(0); }