// /global/cmd/cmd_handler.c -- Object based command handler /* Removed the #ifdefs (don't ask me why. * Added verb * Baldrick, dec '97 */ #include <standard.h> #include <cmd.h> #define SOUL_OBJECT "/obj/handlers/soul" int cmd_make_hash(int i); int soul_com(string str, object me); static mapping cmd_dirs = ([ "/cmds/player/": ({0, "Player"}), "/cmds/creator/": ({BUILDER_CMD, "Builder"}), "/cmds/patron/": ({PATRON_CMD, "Patron"}), "/cmds/thane/": ({THANE_CMD, "Thane"}), "/cmds/demi/": ({DEMI_CMD,"Demi-God"}), "/cmds/god/": ({GOD_CMD,"God"}), "/net/intermud3/cmds/": ({0, "InterMUD network"}) "/cmds/handlers/cmds/": ({0, "Command handler"}), ]); static mapping cmd_hash = ([ ]); // For commands and their objects static mapping cmd_aliases = ([ ]); // For command aliases static string last_dir = ""; // Last directory a command was found static string current_verb; // Used by query_verb() efun void create() { seteuid(getuid()); current_verb = 0; cmd_make_hash(0); } void dest_me() { destruct(TO); } int clean_up() { return 0; } // The simul for query_verb() queries this if efun::query_verb() == 0 string query_current_verb() { return current_verb; } // The real code :) string find_cmd(string verb) { // Try to find the command for 'verb', or return 0 // if not found. Remember it's location.. string s, *dirs; int i; if(cmd_hash[verb]) { last_dir = cmd_hash[verb]["dir"]; return cmd_hash[verb]["file"]; } dirs = m_indices(cmd_dirs); for(i=0; i<sizeof(dirs); i++) { s = dirs[i] + verb; if(file_size(s+".c") > 0) { last_dir = dirs[i]; cmd_hash[verb] = ([ "file" : s, "count" : 0 ]); cmd_hash[verb]["dir"] = last_dir; return s; } } return 0; } int cmd(string verb, string tail, object thisob) { object ob; string s, euid; int ret; string orig_verb = verb; seteuid("Root"); euid = geteuid(thisob); s = cmd_aliases[verb]; if(stringp(s) && s!=0) verb = s; s = find_cmd(verb); if(!s) return 0; // Check their position now... switch(cmd_dirs[last_dir][0]) { case GOD_CMD: if(!MASTER->high_programmer(euid)) return 0; break; case DEMI_CMD: if(!MASTER->query_lord(euid)) return 0; break; case THANE_CMD: if(!thisob->query_thane()) return 0; break; case PATRON_CMD: if(!thisob->query_patron()) return 0; break; case BUILDER_CMD: if(!thisob->query_creator()) return 0; break; } cmd_hash[verb]["count"]++; if(!(ob = find_object(s))) { catch(s->FORCE_LOAD()); ob = find_object(s); } if(!ob) { notify_fail("Error loading command.\n"); return 0; } if(ob->_query_doclone()) ob = clone_object(s); seteuid("CMD"); current_verb = verb; ret = (int)ob->_cmd(tail, thisob, orig_verb); current_verb = 0; if(ob->_query_dodest() || ob->_query_doclone()) ob->dest_me(); return ret; } int cmd_make_hash(int verbose) { /* This goes and finds _all_ the valid commands in the listed * paths, and also works out the command aliases from the * _CMD_ALIASES file in each directory. */ string *paths, *files, s, *a; int i, j, k, l, count; seteuid("Root"); cmd_hash = ([ ]); cmd_aliases = ([ ]); count = 0; paths = keys(cmd_dirs); for(i=0; i<sizeof(paths); i++) { if(verbose) write("Scanning directory: "+paths[i]+"\n"); files = get_dir(paths[i]+"/*.c"); for(j=0; j<sizeof(files); j++) { a = explode(files[j], "."); s=implode(a[0..sizeof(a)-1], "."); if(verbose) write(" Command: "+s+"\n"); cmd_hash[s] = ([ "file": paths[i]+s, "count": 0, "dir": paths[i], ]); count++; } s = read_file(paths[i]+"/_CMD_ALIASES"); if(stringp(s) && s!=0 && s!="") { a = explode(s, "\n"); for(j=0; j<sizeof(a); j++) { k = 0; files = explode(replace(a[j],"\t", " "), " "); if(sizeof(files) && files[0] == "alias") k++; if(sizeof(files) > k) { for(l=k+1; l<sizeof(files); l++) if(files[l] != files[k]) { if(verbose) write(" Alias "+ files[l]+" to "+ files[k]+"\n"); cmd_aliases[files[l]]= files[k]; } } } } } seteuid("CMD"); return count; } //// mapping query_cmds() { return cmd_dirs; } mapping query_hash() { return cmd_hash; } string query_last_dir() { return last_dir; } mapping query_aliases() { return cmd_aliases; } string query_alias(string verb) { return cmd_aliases[verb]; } /* Added by Baldrick. */ int soul_com(string str, object me) { string str1, str2; int i; if (sscanf(str,"%s %s", str1, str2) != 2) str1 = str; if (!me->query_property("nosoul")) { if ( !load_object(SOUL_OBJECT) ) { write("Soul errors! Notify an immortal.\n"); write("Use nosoul to turn the soul back on when it is fixed.\n"); me->add_property("nosoul",1); return 0; } i = SOUL_OBJECT->soul_command(str1, str2, me); /* souls are trivial */ if ( i ) me->set_trivial_action(); return i; } return 0; } /* soul_com() */