#include "socket.h"
#include <errno.h>
#define DEFAULT_PORT 23
object user;
string buff="",
host,
log_file;
int sock,
port;
status attached,
connected;
static void callback(int fd, int act, mixed a, mixed b);
static void timeout();
void start(string h, int p)
{
if (!adminp(this_player())) return 0;
sock=(int)SOCKETD->socket_connect(h, p, #'callback);
connected=0;
printf("Connecting to %s port %d\n", h, p);
user=this_player();
host=h;
port=p;
attached=1;
call_out(#'timeout, 15);
input_to("input");
return;
}
void reattach()
{
printf("[telnet: Reattaching to %s%c%s]\n",
host,
port == DEFAULT_PORT ? 0 :' ',
port == DEFAULT_PORT ? "":to_string(port));
attached=1;
write(buff);
buff="";
input_to("input");
return;
}
void tell_user(string msg)
{
if (attached)
tell_object(user, msg);
else
buff=sprintf("%s%s", buff, msg);
if (!attached && member(msg, '') != -1)
tell_object(user, sprintf("[telnet: Beep from %s%c%s]\n",
host,
port == DEFAULT_PORT ? 0 :' ',
port == DEFAULT_PORT ? "":to_string(port)));
if (log_file)
write_file(log_file, msg);
return;
}
static void timeout()
{
if (connected) return;
tell_user("telnet: connection timed out.\n");
if (!attached)
tell_object(user, buff);
sock=-1;
user=0;
destruct(this_object());
}
void callback(int fd, int act, mixed a, mixed b)
{
switch(act) {
case SOCKET_READY:
tell_user("telnet: connected.\n");
remove_call_out(#'timeout);
connected=1;
break;
case SOCKET_READ:
tell_user(a);
break;
case SOCKET_CLOSE:
tell_user("telnet: connection closed.\n");
if (!attached)
tell_object(user, buff);
sock=-1;
user=0;
connected=0;
destruct(this_object());
break;
case SOCKET_ERROR: {
string err;
if (a == ERQ_E_NOTFOUND) err="Unknown host";
else switch(b) {
case ECONNREFUSED:
err="Connection Refused";
break;
case EHOSTUNREACH:
err="Host Unreachable";
break;
case ENETUNREACH:
err="Net Unreachable";
break;
default:
err=sprintf("Error %d", b);
break;
}
tell_user(sprintf("telnet: %s\nclosing connection.\n", err));
if (!attached)
tell_object(user, buff);
sock=-1;
user=0;
destruct(this_object());
}
break;
}
return;
}
void input(string str)
{
if (sock<0) return;
if (str[0]=='') {
switch(str[1]) {
case 'c': {
if (!log_file)
write("telnet: Not logging session.\n");
else {
printf("telnet: Stopped logging session to: %s.\n", log_file);
log_file=0;
}
input_to("input");
return;
}
case 'd': {
tell_object(user, "Detached. Type 'telnet' to resume.\n");
attached=0;
return;
}
case 'l': {
if (!str[2]) {
if (log_file)
printf("telnet: Logging session to: %s.\n", log_file);
else
write("telnet: Not logging session.\n");
} else {
str=eval_path(trimstr(str[2..]));
if (file_size(str) == -2)
str=sprintf("%s/telnet_log", str);
printf("telnet: Logging session to: %s.\n", str);
log_file=str;
}
input_to("input");
return;
}
case 'q': {
SOCKETD->socket_close(sock);
tell_user("telnet: connection closed.\n");
if (!attached)
tell_object(user, buff);
user=0;
sock=-1;
destruct(this_object());
return;
}
case 's': {
str=eval_path(trimstr(str[2..]));
if (file_size(str) < 0)
printf("telnet: Could not find file: %s.\n", str);
else if (connected) {
string *lines;
lines=explode(read_file(str), "\n");
tell_user(sprintf("telnet: Sending file: %s.\n", str));
for(; sizeof(lines); lines=lines[1..])
SOCKETD->socket_write(sock, sprintf("%s\n", lines[0]));
tell_user("telnet: File sent.\n");
}
input_to("input");
return;
}
case '!': {
str=str[1..];
}
case '?': {
write("telnet: Escape commands:\n"
"All commands are preceeded by the escape (^[) character.\n"
"\n"
"c Close session log.\n"
"d Detach telnet session.\n"
"l<file> Open session log into <file>.\n"
"q Forcefully close telnet session.\n"
"s<file> Send a file to telnet session.\n"
"!<arg> Send '!<arg>' to remote host.\n"
"? This help page.\n");
input_to("input");
return;
}
}
}
if (connected) {
SOCKETD->socket_write(sock, str=sprintf("%s\n", str));
if (log_file)
write_file(log_file, str);
}
input_to("input");
return;
}
status clean_up(status arg)
{
if (!user)
destruct(this_object());
return 1;
}