lima-1.0b5/
lima-1.0b5/driver/
lima-1.0b5/driver/ChangeLog.old/
lima-1.0b5/driver/Win32/
lima-1.0b5/driver/compat/
lima-1.0b5/driver/include/
lima-1.0b5/driver/testsuite/
lima-1.0b5/driver/testsuite/clone/
lima-1.0b5/driver/testsuite/command/
lima-1.0b5/driver/testsuite/data/
lima-1.0b5/driver/testsuite/etc/
lima-1.0b5/driver/testsuite/include/
lima-1.0b5/driver/testsuite/inherit/
lima-1.0b5/driver/testsuite/inherit/master/
lima-1.0b5/driver/testsuite/log/
lima-1.0b5/driver/testsuite/single/
lima-1.0b5/driver/testsuite/single/tests/compiler/
lima-1.0b5/driver/testsuite/single/tests/efuns/
lima-1.0b5/driver/testsuite/single/tests/operators/
lima-1.0b5/driver/testsuite/u/
lima-1.0b5/driver/tmp/
lima-1.0b5/etc/
lima-1.0b5/lib/WWW/help/
lima-1.0b5/lib/cmds/
lima-1.0b5/lib/cmds/create/
lima-1.0b5/lib/cmds/player/attic/
lima-1.0b5/lib/contrib/bboard/
lima-1.0b5/lib/contrib/boards/
lima-1.0b5/lib/contrib/marriage/
lima-1.0b5/lib/contrib/roommaker/
lima-1.0b5/lib/contrib/transient_effect/
lima-1.0b5/lib/daemons/channel/
lima-1.0b5/lib/daemons/imud/
lima-1.0b5/lib/data/
lima-1.0b5/lib/data/config/
lima-1.0b5/lib/data/links/
lima-1.0b5/lib/data/news/
lima-1.0b5/lib/data/players/
lima-1.0b5/lib/data/secure/
lima-1.0b5/lib/domains/
lima-1.0b5/lib/domains/std/2.4.5/maze1/
lima-1.0b5/lib/domains/std/2.4.5/npc/
lima-1.0b5/lib/domains/std/2.4.5/post_dir/
lima-1.0b5/lib/domains/std/2.4.5/sub/
lima-1.0b5/lib/domains/std/camera/
lima-1.0b5/lib/domains/std/config/
lima-1.0b5/lib/domains/std/cult/
lima-1.0b5/lib/domains/std/effects/
lima-1.0b5/lib/domains/std/misc/
lima-1.0b5/lib/domains/std/monsters/
lima-1.0b5/lib/domains/std/recorder/
lima-1.0b5/lib/domains/std/rooms/
lima-1.0b5/lib/domains/std/rooms/beach/
lima-1.0b5/lib/domains/std/rooms/labyrinth/
lima-1.0b5/lib/domains/std/school/
lima-1.0b5/lib/domains/std/school/O/
lima-1.0b5/lib/domains/std/spells/
lima-1.0b5/lib/domains/std/spells/stock-mage/
lima-1.0b5/lib/domains/std/spells/stock-priest/
lima-1.0b5/lib/help/
lima-1.0b5/lib/help/admin/
lima-1.0b5/lib/help/hints/General_Questions/
lima-1.0b5/lib/help/hints/Pirate_Quest/
lima-1.0b5/lib/help/player/
lima-1.0b5/lib/help/player/bin/
lima-1.0b5/lib/help/player/quests/
lima-1.0b5/lib/help/wizard/
lima-1.0b5/lib/help/wizard/coding/guilds/
lima-1.0b5/lib/help/wizard/coding/rooms/
lima-1.0b5/lib/help/wizard/lib/daemons/
lima-1.0b5/lib/help/wizard/lib/lfun/
lima-1.0b5/lib/help/wizard/lib/std/
lima-1.0b5/lib/help/wizard/mudos_doc/
lima-1.0b5/lib/help/wizard/mudos_doc/applies/
lima-1.0b5/lib/help/wizard/mudos_doc/applies/interactive/
lima-1.0b5/lib/help/wizard/mudos_doc/applies/parsing/
lima-1.0b5/lib/help/wizard/mudos_doc/concepts/
lima-1.0b5/lib/help/wizard/mudos_doc/driver/
lima-1.0b5/lib/help/wizard/mudos_doc/efuns/
lima-1.0b5/lib/help/wizard/mudos_doc/efuns/arrays/
lima-1.0b5/lib/help/wizard/mudos_doc/efuns/buffers/
lima-1.0b5/lib/help/wizard/mudos_doc/efuns/compile/
lima-1.0b5/lib/help/wizard/mudos_doc/efuns/filesystem/
lima-1.0b5/lib/help/wizard/mudos_doc/efuns/floats/
lima-1.0b5/lib/help/wizard/mudos_doc/efuns/functions/
lima-1.0b5/lib/help/wizard/mudos_doc/efuns/general/
lima-1.0b5/lib/help/wizard/mudos_doc/efuns/mappings/
lima-1.0b5/lib/help/wizard/mudos_doc/efuns/mixed/
lima-1.0b5/lib/help/wizard/mudos_doc/efuns/numbers/
lima-1.0b5/lib/help/wizard/mudos_doc/efuns/parsing/
lima-1.0b5/lib/help/wizard/mudos_doc/lpc/constructs/
lima-1.0b5/lib/help/wizard/mudos_doc/lpc/types/
lima-1.0b5/lib/include/driver/
lima-1.0b5/lib/log/
lima-1.0b5/lib/obj/admtool/
lima-1.0b5/lib/obj/admtool/internal/
lima-1.0b5/lib/obj/admtool/mudinfo/
lima-1.0b5/lib/obj/admtool/secure/
lima-1.0b5/lib/obj/secure/
lima-1.0b5/lib/obj/secure/cmd/
lima-1.0b5/lib/obj/secure/mailers/
lima-1.0b5/lib/obj/secure/shell/
lima-1.0b5/lib/obj/secure/shell/classes/
lima-1.0b5/lib/obj/tasktool/
lima-1.0b5/lib/obj/tasktool/internal/
lima-1.0b5/lib/open/
lima-1.0b5/lib/secure/
lima-1.0b5/lib/secure/cgi/
lima-1.0b5/lib/secure/modules/
lima-1.0b5/lib/secure/simul_efun/
lima-1.0b5/lib/std/adversary/
lima-1.0b5/lib/std/adversary/advancement/
lima-1.0b5/lib/std/adversary/armor/
lima-1.0b5/lib/std/adversary/blows/
lima-1.0b5/lib/std/adversary/death/
lima-1.0b5/lib/std/adversary/formula/
lima-1.0b5/lib/std/adversary/health/
lima-1.0b5/lib/std/adversary/pulse/
lima-1.0b5/lib/std/adversary/wield/
lima-1.0b5/lib/std/classes/event_info/
lima-1.0b5/lib/std/container/
lima-1.0b5/lib/std/living/
lima-1.0b5/lib/std/modules/contrib/
lima-1.0b5/lib/std/patterns/
lima-1.0b5/lib/std/race/
lima-1.0b5/lib/std/race/restricted/
lima-1.0b5/lib/std/room/
lima-1.0b5/lib/tmp/
lima-1.0b5/lib/trans/
lima-1.0b5/lib/trans/admincmds/
lima-1.0b5/lib/trans/obj/
lima-1.0b5/lib/wiz/
/* Do not remove the headers from this file! see /USAGE for more info. */

#include <mudlib.h>
#include <commands.h>

inherit SHELL;
inherit M_SHELLVARS;
inherit M_PROMPT;
inherit M_COMPLETE;
inherit M_GETOPT;
inherit M_REGEX;

#define WIZ_CMD_DIRS ({CMD_DIR_NO_RESTRICT "/", CMD_DIR_RESTRICT "/",\
	CMD_DIR_CREATE "/", CMD_DIR_PLAYER "/"})

#define ADMIN_CMD_DIRS ({CMD_DIR_NO_RESTRICT "/", CMD_DIR_RESTRICT "/",\
	CMD_DIR_CREATE "/", CMD_DIR_PLAYER "/", CMD_DIR_ADMIN "/" })

private nosave string path;
int	expand_vars;

void set_expand_vars(int i)
{
    expand_vars = i;
}

int is_variable(string name);
private mixed check_for_nuggets(string array args);

private void cmd_rehash()
{
    CMD_D->cache(map(path,(:evaluate_path:)));
    write("Okay.\n");
}

private mixed evaluate_code(mixed code)
{
    string dir;

    code = reg_assoc(code,({"\\$[a-zA-Z0-9]+"}),({0}))[0];

    code =
    map(code, (: (strlen($1) > 1 && $1[0] == '$' && is_variable($1[1..]))  ?
	"(get_user_variable(\""+$1[1..]+"\"))" :
	$1 :));
    code = implode(code, "");

    // don't chop access
    if (check_privilege(1))
	dir = "/trans/tmp";
    else if (file_size(dir = wiz_dir(this_user())) != -2)
	dir = "/tmp";

    if(is_file(wiz_dir(this_user())+"/eval.h"))
	return exec_code(code, dir, wiz_dir(this_user())+"/eval.h");
    else
	return exec_code(code, dir);
}

private nomask string * expand_arguments(string* argv)
{
    int i, n;

    if ( this_user() != query_owner() )
	error("get your own shell, asswipe!\n");

    n = sizeof(argv);
    for( i = 0; i < n; i++)
    {

	if(strlen(argv[i])>2 && argv[i][0] == '`' && argv[i][<1] == '`')
	{
	    if(catch(argv[i] = evaluate_code(argv[i][1..<2])))
		return 0;
	}
    }
    return argv;
}


// called when the value of the "path" variable changes
private void set_path(string arg) {
    if (!arrayp(arg))
	return;
    arg = filter(arg, (: stringp :));
    path = map(arg, (: evaluate_path :));
}

string query_path() {
    // New shells need to query this to get the saved value
    if (!path) set_path(get_variable("path"));
    return path;
}

private void fix_path()
{
    set_variable("path", WIZ_CMD_DIRS);
    if(query_owner() && adminp(query_owner()))
      set_variable("path", ADMIN_CMD_DIRS);
    printf("Ok, your path is fixed.\n");
}


private void show_shell_help()
{
    more_file("/help/wizard/shell");
}

private void create()
{
    if ( !clonep() )
	return;

    ::create();
    prompt::create();

    set_privilege(1);

    /* set up to save variables through the M_SAVE api */
    setup_for_save();

    arg_to_words_func = (: argument_explode :);
}

protected void prepare_shell()
{
    ::prepare_shell();

    set_if_undefined("path", WIZ_CMD_DIRS);

    if(query_owner() && adminp(query_owner()))
      set_if_undefined("path", ADMIN_CMD_DIRS);

    set_if_undefined("pwd", "/");
    set_if_undefined("cwf", 0);

    shell_bind_if_undefined("resetpath", (: fix_path :));
    shell_bind_if_undefined("?",	(: show_shell_help :));
    shell_bind_if_undefined("set",	(: cmd_set :));
    shell_bind_if_undefined("unset",	(: cmd_unset :));
    shell_bind_if_undefined("rehash",   (: cmd_rehash :));

    add_variable_hook("path", (: set_path :));
}

string query_shellname()
{
    return "wish (Lima wizard shell) v. 0.9";
}

varargs protected void execute_command(string original_input)
{
    string * argv = explode(original_input, " ");
    mixed	tmp;
    string	path = query_path();
    mixed 	cmd_info;
    string	channel_name;
    mixed	orig_argv;
    mixed	stdin_info;
    mixed	extra_args;
    mixed       nugget_info;
    mixed	remaining_implode_info;
    string	virgin_input;
    string      array implode_info;

    /* BEGINNING OF EXPANSION */
    tmp = evaluate(arg_to_words_func, implode(argv," "));
    argv = tmp[0];
    implode_info = tmp[1];

    if(sizeof(argv) == 1 && argv[0][0] == '$' && strlen(argv[0]) > 1)
    {
	print_variable(argv[0][1..]);
	return;
    }
    if(sizeof(argv) > 1)
	argv = argv[0..0] + map(argv[1..], (: expand_if_variable($1,1) :));


    // In some shells, this is the hook for doing username completion,
    // globbing, flag pre-parsing, etc...  In others, it's used to execute
    // code encased in ` `'s.
    argv = expand_arguments( argv - ({ "" }) - ({}));

    if(!argv)
	return;

    if(wizardp(this_user()))
	argv = map(argv, 
	  (: (stringp($1)) ? replace_string($1,"\\`","`") :  $1 :));

    // check for if this is a variable setting.
    if(sizeof(argv) > 2 && argv[1] == "=" && strlen(argv[0]) > 1 &&
      argv[0][0] == '$')
    {
	if(sizeof(argv) == 3)
	    set_variable(argv[0][1..],expand_if_variable(argv[2]));
	else
	    set_variable(argv[0][1..], implode_by_arr(map(argv[2..], 
		  (: expand_if_variable :)),
		implode_info[2..]));
	return;
    }

    // Expand variables
    if(expand_vars)
	argv = map(argv, (: expand_if_variable :));

    // ### wtf is this?
    // Hmm, I might undo this one...  the only reason this is here is to 
    // allow \\$ to work right.  \$ can work right in other ways....
    argv = map(argv, (: stringp($1) ? replace_string($1, "\\$","$") : $1 :));

    // If there is a local shell command that matches our input, try to
    // execute it.
    if (!sizeof(argv)) return;
    evaluate(tmp=dispatch[argv[0]], argv, implode_info);
    if(tmp)
	return;

    /* END OF EXPANSION */

    orig_argv = argv;
    virgin_input = implode_by_arr(map(orig_argv[1..], 
	(:stringp($1)?$1:sprintf("%O",$1):)), implode_info[1..])[1..];

    nugget_info = check_for_nuggets(argv);
    argv = nugget_info[0];
    stdin_info = nugget_info[1];
    extra_args = nugget_info[2];
    remaining_implode_info = implode_info[sizeof(argv)..];
    implode_info = implode_info[1..(sizeof(argv)-1)]+({""});
    if(sizeof(implode_info) && (implode_info[0][0..0] == " "))
	implode_info[0] = implode_info[0][1..];


    /* find and execute the given command */
    cmd_info = CMD_D->smart_arg_parsing(argv, path, implode_info);
    if ( !intp(cmd_info) )
    {
	if(strlen(virgin_input) == strlen(original_input))
	    virgin_input = "";
	while(1)
	{
	    mixed tmp2;
	    cmd_info = cmd_info[0]->call_main(cmd_info[2], cmd_info[1], 
	      stdin_info, extra_args,
	      implode_info, 
	      remaining_implode_info,
	      virgin_input);
	    if(!cmd_info)
		return;
	    stdin_info = cmd_info[1];
	    implode_info = cmd_info[2];
	    nugget_info = check_for_nuggets(cmd_info[0]);
	    argv = nugget_info[0];
	    extra_args = nugget_info[2];
	    tmp2 = argv;
	    if(arrayp(extra_args))
		tmp2 += extra_args;
	    if(!sizeof(tmp2))
	    {
		write("error: pipe to nothing.\n");
		return;
	    }
	    virgin_input = implode_by_arr(tmp2[1..],  
	      implode_info[(sizeof(implode_info)-sizeof(tmp2))..]);
	    if(virgin_input[0] == ' ')
		virgin_input = virgin_input[1..];
	    remaining_implode_info = implode_info[sizeof(argv)..];
	    implode_info = implode_info[1..(sizeof(argv)-1)]+({""});
	    if(sizeof(implode_info) && (implode_info[0][0..0] == " "))
		implode_info[0] = implode_info[0][1..];
	    cmd_info = CMD_D->smart_arg_parsing(argv,path,implode_info);
	    if(intp(cmd_info))
	    {
		if (sizeof(argv))
		    printf("error: pipe to %s failed.\n", argv[0]);
		else
		    write("error: pipe to nothing.\n");
		return;
	    }
	}
    }
    if ( cmd_info > 0 )
    {
	if ( cmd_info != 1 )
	    printf("Found command is uncallable.\n");
	return;
    }
    if( cmd_info == -2)
    {
	printf("Unable to finish command.\n");
	return;
    }

    if (!sizeof(argv)) {
	printf("Nothing before pipe.\n");
	return;
    }

    if (this_body()) {
	/* use the parser to try the command */
	if ( this_body()->do_game_command(original_input) )
	    return;

	/* try a channel */
	channel_name = CHANNEL_D->is_valid_channel(orig_argv[0], this_user()->query_channel_list());
	if ( channel_name ) {
	    int chan_type = channel_name[0..4] == "imud_";
	    CHANNEL_D->cmd_channel(channel_name,
	      virgin_input,
	      chan_type);
	    return;
	}

	if(is_file(CMD_DIR_VERBS "/" + argv[0] + ".c"))
	    write(this_body()->nonsense());
	else
	    printf("I don't know the verb '%s'.\n", argv[0]);
    } else {
	if (is_file(CMD_DIR_VERBS "/" + argv[0] + ".c"))
	    write("Can't use verb with no body.\n");
	else
	    printf("I don't know the verb '%s'.\n", argv[0]);
    }
}

void set_pwd(string fname)
{
    set_variable("lastpwd", get_variable("pwd"));
    set_variable("pwd", fname);
}

void swap_pwd() {
    set_pwd(get_variable("lastpwd"));
}

void set_cwf(string fname)
{
    set_variable("cwf", fname);
}

void setup_for_save()
{
    ::setup_for_save();

    shellvars::setup_for_save();
}

protected mixed what_prompt()
{
    return (: get_prompt :);
}

protected nomask string query_save_path(string userid)
{
    return WSHELL_PATH(userid);
}

// Support for IO redirection
private mixed check_for_nuggets(string array args)
{
    int		i,j;
    string array	stdinstuff = 0;

    i = member_array("<",args);
    if(i != -1)
    {
	j = i+1;
	while((j < sizeof(args)) && (args[j] != ">") && (args[j] != ">>")
	  && (args[j] != "|") && (args[j] != "<")) j++;
	stdinstuff = args[i+1..(j-1)];
	args = args[0..(i-1)] + args[j..];
    }

    for(i=0;i<sizeof(args);i++)
    {
	if(stringp(args[i]))
	    switch(args[i])
	{
	case "|":
	case ">":
	case ">>":
	    return ({args[0..(i-1)], stdinstuff, args[i..]});
	default:
	    break;
	}
    }
    return ({args, stdinstuff, 0});
}