/* 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); }