/* // tsh.c: TMI-shell or Tru-shell -- written by Truilkan@TMI 92/02/05 // meant to be inherited by player.c // // Brutally hacked up and destroyed by Buddha to install something "better" // on 3-7-92 // // 1992/03/08 - hacked again by Truilkan@TMI to fix pushd and popd // // 1993/02/06 - Multiple command repeat capability by Watcher@TMI // // 1993/02/22 - Allowing silent queries to write_prompt() by Watcher@TMI // // 1993/03/30 - Uses STACK not CSTACK (makes `dirs' cmd easier) // Uses tilde_path in prompt. // Cleaned up a bit. (Zak@tmi-2) // 1993/08/05 Grendel@tmi-2 - Added test for files in ~/tsh/ // 94-11-09 - Leto added an int typecast */ #include <adt_defs.h> #include <commands.h> #include <tsh.h> #include <uid.h> #define DEFAULT_PROMPT "> " #define MAX_HIST_SIZE 50 #define MIN_HIST_SIZE 20 #define MIN_PUSHD_SIZE 5 #define MAX_PUSHD_SIZE 50 /* STACK_ADT should be inherited from here so that this object can have its own private stack */ private inherit STACK_ADT; /* for pushd and popd */ private static string tsh_prompt; private static int cur, hist_size, pushd_size, custom_prompt; string do_nicknames(string arg); string do_alias(string arg); string do_substitution(string arg) ; string handle_history(string arg); nomask mixed query( string label ); /* do_new: called by the "new" command */ int do_new() { string d1, d2; tsh_prompt = (string)this_object()->getenv("prompt"); tsh_prompt = !tsh_prompt ? DEFAULT_PROMPT : tsh_prompt + " "; custom_prompt = (tsh_prompt != DEFAULT_PROMPT); d1 = (string)this_object()->getenv("pushd"); pushd_size = 0; if (d1) sscanf(d1,"%d",pushd_size); if (pushd_size > MAX_PUSHD_SIZE) pushd_size = MAX_PUSHD_SIZE; if (!pushd_size) pushd_size = MIN_PUSHD_SIZE; d1 = (string)this_object()->getenv("history"); hist_size = 0; if (stringp(d1)) sscanf(d1,"%d",hist_size); else if (intp(d1)) hist_size = (int)d1; // Leto if (hist_size > MAX_HIST_SIZE) hist_size = MAX_HIST_SIZE; if (!intp(hist_size) || hist_size <= 0) hist_size = MIN_HIST_SIZE; return 1; } // do_new /* push current directory onto the stack and cd to dir named "arg" */ int pushd(string arg) { string path; if (!arg && (string)this_object()->getenv("pushdtohome")) arg = "~"; path = (string)this_object()->query("cwd"); if (((int)CMD_CD->cmd_cd(arg))) { if (push(path) == -1) write("dirstack full - try popd-ing some elements first\n"); } return 1; } // pushd int popd() { mixed dir; dir = pop(); if ((int)dir == -1) write("Directory stack is empty.\n"); else CMD_CD->cmd_cd((string)dir); return 1; } // popd mixed *dirs() { return query_stack(); } void initialize_tsh() { string rcfile; do_new(); if (pushd_size) alloc(pushd_size); // According to Beek, the next 2 lines shoulf go, but that // kills history completely..... Leto 942711 if (hist_size) history::hist_alloc(hist_size); rcfile = user_path((string)this_object()->query("name")) + ".login"; if( file_size(rcfile) > 0 ) this_object()->tsh(rcfile); } // initialize_tsh string write_prompt(int silent) { string path, prompt, tmp; if (custom_prompt) { prompt = tsh_prompt; prompt = replace_string(prompt,"$D", tilde_path((string)this_object()->query("cwd"), 0)); prompt = replace_string(prompt,"\\n","\n"); prompt = replace_string(prompt,"$N",lower_case(mud_name())); prompt = replace_string(prompt,"$T",ctime(time())) ; prompt = replace_string(prompt,"$C",""+(query_cmd_num() + 1)); } else prompt = DEFAULT_PROMPT; if(!silent) message("prompt", prompt, this_player()); return prompt; } // write_prompt static nomask string process_input(string arg) { int loop, num, macro; if (arg && arg != "") { if(sscanf(arg, "%d %s", num, arg) == 2) macro = 1; arg = do_substitution(arg) ; arg = do_nicknames(arg); arg = do_alias(arg); arg = handle_history(arg); // Allow multiple repeat actions like '5 north' as well as // alias commands. - Watcher (02/05/93) if(macro && num && arg && arg != "" && !previous_object()) { if(num > 10) { write("Command macro increment too high.\n"); return ""; } for(loop=0; this_player() && loop < num; loop++) if(!command(arg)) { write("Could not complete action. Command macro halted.\n"); break; } return ""; } } if( strlen( arg ) > 5 && arg[0..5] == "passwd" ) { CMD_PASSWD -> cmd_passwd( (strlen( arg ) > 6 ? arg[7..<1] : 0) ); return ""; } return arg; } // process_input nomask int tsh(string file) { string contents, euid, *lines; int j, len; euid = geteuid( previous_object() ); // 93-02-12 pallando (_tsh wasn't working) if ( ( euid != geteuid( this_object() ) ) && ( euid != ROOT_UID ) && !adminp(euid) ) return 0; if (!file) { notify_fail("usage: tsh filename\n"); return 0; } contents = read_file( resolv_path( "cwd", file ) ); if (!contents) { contents = read_file( resolv_path( "cwd", "~/tsh/"+file ) ); if (!contents) { notify_fail("tsh: couldn't read " + file + "\n"); return 0; } } lines = explode(contents,"\n"); len = sizeof(lines); for (j = 0; this_player() && j < len; j++) { if (lines[j][0] != '#' && !command(lines[j])) { write(file + ": terminated abnormally on line #" + (j+1) + "\n"); write("while doing: " + lines[j] + "\n"); break; } } return 1; } // tsh // This function allows for ^foo^bar substitutions. nomask string do_substitution (string arg) { string pre,post,old,New,lastcom ; if (arg == "^^") { write ((lastcom = query_last_command()) + "\n"); return lastcom; } if (sscanf(arg,"^%s^%s",old,New)!=2) { return arg ; } lastcom = query_last_command() ; if (!lastcom || lastcom=="") { write ("No previous command.\n") ; return "" ; } if (old == "") { // allow you to prepend last string write (New + lastcom + "\n"); return New + lastcom ; } if (sscanf(lastcom, "%s" + old + "%s", pre,post) != 2) { write ("Failed substitution.\n") ; return "" ; } write (pre+New+post+"\n") ; return pre+New+post ; }