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. */

/*
** This file is part of the Lima distribution mudlib.
** Do not remove this header.  Please see /USAGE for more
** information on using this code.
**
** FILE: /trans/obj/telnet_ob.c
** AUTHOR: John Viega (rust@virginia.edu)
** CREATED: Jul 22 1995
**
** OVERVIEW
** ========
** This object allows people with permissions to open sockets
** the ability to telnet.  It allows for multiple sessions, and
** knows the addresses of muds on the intermud already.
**
** TODO
** =====
** Add telnet negotiations.
**
** REVISIONS
** =========
** Rust. Jul 25 1995 - / isn't the command character if you have the
**                     telnet_char environment variable set.  Suggested
**                     by Satan@ArcadiaF.
**                   - Added a /close to close the current connection.
**                   - Added /hide to hide all input from any telnet session.
**                     (it toggles.)  Suggested by Zifnab.
*/

#include <mudlib.h>
#include <socket.h>

inherit M_ACCESS;
inherit M_REGEX;
inherit M_INPUT;
//#define TELNET_HELP_FILE "/help/admin/telnet"
#define TELNET_HELP_FILE "/help/admin/command/telnet"
#define IAC  255

string *iac_regex = ({sprintf("%c..",IAC)});
string iac = sprintf("%c",IAC);



class connection
{
    string address;
    object socket;
    string output_buffer;
    string session_name;
    string session_base_name;
}


private nosave class connection *sessions = ({});
private nosave int 		active_session = -1;
private nosave string	 	active_session_name;
private nosave int 		actively_elsewhere;
private nosave int 		notify_on_activity = 1;
private nosave object           owner;
private nosave string           control_char;
private nosave int              hide_all_output;


private nomask string get_address(string);
private nomask string get_unique_session_name(string);
private nomask void open_socket(class connection);
private nomask void recv_input_from(string, object, string);
private nomask void close_session(string, object);
private nomask void handle_command(string);
nomask void remove();


private nomask void init_session(string session_name, string address)
{
    class connection new_connection;
    int i;

    new_connection = new(class connection);
    for(i=0;i<sizeof(sessions);i++){
	if (!sessions[i] || !sessions[i]->socket)
	    break;
    }

    if(i != sizeof(sessions))
	sessions[i] = new_connection;
    else
	sessions += ({ new_connection });

    printf ("Opening connection #%i...\n", i+1);
    new_connection->address = get_address(address);
    new_connection->session_name = get_unique_session_name(session_name);
    new_connection->session_base_name = session_name;
    new_connection->output_buffer = "";

    if(catch(open_socket(new_connection)))
    {
	write("Session could not be opened.\n");
	return;
    }
    active_session = i;
    active_session_name = new_connection->session_name;
}


private nomask string get_address(string potential_mudname)
{
    mapping mudlist;
    string* matches;
    mudlist = IMUD_D->query_mudlist();

    matches = insensitive_regexp(keys(mudlist), potential_mudname);

    if(sizeof(matches) != 1)
	return potential_mudname;

    return sprintf("%s %i", mudlist[matches[0]][1], mudlist[matches[0]][2]);
}

private nomask string get_unique_session_name(string session_name)
{
    int i = 1;
    class connection con;

    foreach(con in sessions){
	if(!con || !stringp(con->session_name))
	    continue;
	if(con->session_base_name == session_name)
	    i++;
    }

    if(i == 1)
	return session_name;

    return sprintf("%s<%i>", session_name, i);
}

private nomask void open_socket(class connection this_con)
{
    string session = this_con->session_name;

    this_con->socket = new(SOCKET, SKT_STYLE_CONNECT,
      this_con->address,
      (: recv_input_from, session :),
      (: close_session, session :));
}


private nomask void recv_input_from(string session, object sock, string input)
{
    string	*info;
    int		i;
    int           session_num = -1;

    for(i=0;i<sizeof(sessions);i++)
    {
	if(sessions[i]->session_name == session)
	{
	    session_num = i;
	}
    }

    //  BBUG(catch(info = reg_assoc(input,iac_regex, ({0}))[0]));
    // tmp hack cause my reg_assoc errors where it shouldn't.
    info = ({input});
    for(i=0;i<sizeof(info);i++)
    {
	if(i%2) {
	    //	handle_negotiation(info[i]);
	    continue;
	}
	if(!hide_all_output && active_session_name == session)
	{
	    foreach (string line in explode(info[i],"\n")) {
		tell(owner, "~ " + line + "\n");
	    }
	    continue;
	}
	else
	{
	    if(notify_on_activity && sessions[session_num]->output_buffer == "")
	    {
		tell(owner, sprintf("%%There is activity in %s\n",
		    session));
	    }
	    sessions[session_num]->output_buffer += input;
	}
    }
}


private nomask void handle_input(mixed input)
{
    if(input == -1)
    {
	remove();
    }
    if(strlen(input) > 1 && (input[0] == control_char[0]))
    {
	handle_command(input[1..]);
	return;
    }

    if(actively_elsewhere)
    {
	class connection con;

	con = sessions[active_session];
	con->socket->send(input + "\n");
	return;
    }
    else
	modal_pass(input);
}

void init_telnet()
{
    if(owner) 
	return;
    owner = this_body();
    control_char = get_user_variable("telnet_char") ||
    "/";
    modal_push((: handle_input :), "# ");
}

nomask void remove() {
    class connection con;

    foreach(con in sessions)
    {
	if(!con) continue;
	if(!con->socket) continue;
	catch(con->socket->remove());
    }
    destruct();
}


private nomask void handle_command(string cmd)
{
    string arg;
    class connection con;
    int i;

    sscanf(cmd,"%s %s", cmd, arg);
    switch(cmd)
    {
    case "hide" :
	if(!hide_all_output)
	{
	    hide_all_output = 1;
	    write("Hiding all telnet output.\n");
	}
	else
	{
	    hide_all_output = 0;
	    map(explode(sessions[active_session]->output_buffer, "\n"),
	      (: printf("~ %s\n", $1) :));
	    sessions[active_session]->output_buffer = "";
	}
	return;
    case "send" :
	if(active_session == -1)
	{
	    write("Perhaps you should open a session first.\n");
	    return;
	}
	con = sessions[active_session];
	con->socket->send(arg + "\n");
	return;

    case "open" :
	if (!arg) { write("Open <host>\n"); return; }
	init_session(arg, arg);
	return;

    case "goto" :
	i = to_int(arg);
	if(i<1 || i > sizeof(sessions) || !sessions[i-1])
	{
	    write("Invalid session.\n");
	    return;
	}
	active_session = i-1;
	active_session_name = sessions[active_session]->session_name;
	write("Switching.\n");
	map(explode(sessions[active_session]->output_buffer, "\n"),
	  (: printf("~ %s\n", $1) :));
	sessions[active_session]->output_buffer = "";
	return;

    case "jobs" :
	if(!sizeof(filter(sessions, (: typeof($1) == "class" :)))){
	    write("You currently have no sessions open.\n");
	    return;
	}
	write("Active sessions:\n================\n");
	for(i=0;i<sizeof(sessions);i++){
	    if(typeof(sessions[i]) != "class")
		continue;
	    printf("%i:  %s\n", i+1, sessions[i]->session_name);
	}
	return;
    case "exit" :
	modal_pop();
	remove();
	return;
    case "tog" :
	if(!actively_elsewhere && active_session == -1)
	{
	    write("But you have no active sessions....\n");
	    return;
	}
	if(actively_elsewhere)
	    actively_elsewhere = 0;
	else
	    actively_elsewhere = 1;
	write("Ok.\n");
	return;

    case "help" :
    case "?" :
	more_file(TELNET_HELP_FILE);
	return;

    case "close" :
	if(!active_session_name || active_session == -1)
	{
	    write("Nothing to close.\n");
	    return;
	}
	close_session(active_session_name, sessions[active_session]->socket);
	return;

    default:
	write("Unknown telnet command.\n");
	return;
    }
}

private nomask void close_session(string ses, object sock)
{
    int i;
    int new_session = -1;

    ZBUG(owner);
    tell(owner, sprintf("%%Session '%s' is closed.\n", ses));

    for(i=0; i<sizeof(sessions); i++)
    {
	if(!sessions[i])
	    continue;
	if(sessions[i]->session_name == ses)
	{
	    sessions[i] = 0;
	}
	else if(new_session == -1 && sessions[i])
	{
	    new_session = i;
	}
    }
    active_session = new_session;
    write( active_session );
    write( "     " + active_session_name + "\n");
    if(active_session == -1)
    {
	write("No more active sessions.\n");
	if(actively_elsewhere)
	{
	    write("Doing a /tog for you.\n");
	    actively_elsewhere = 0;
	}
	else active_session_name = 0;
    }
    else
    {
	write("Use /goto to return to another session.\n");
	active_session_name = sessions[active_session]->session_name;
    }
    catch(sock->remove());
}

private void create() {
    set_privilege(1);
}