#include "socket.h"
#include <errno.h>
#define LUSER 0
#define RUSER 1
#define HOST 2
#define CONTINUED 3
mapping sockets;
void callback(int fd, int act, mixed a, mixed b);
status main(string str)
{
string user, host;
int sock;
if (!sockets) sockets = allocate_mapping(0, 4);
if (!adminp(this_player())) return 0;
if (!str) str="";
host = __HOST_NAME__;
user = str;
sscanf(str, "%s@%s", user, host);
sock = SOCKETD->socket_connect(host, 79, #'callback);
sockets[sock, LUSER] = this_player();
sockets[sock, RUSER] = user;
sockets[sock, HOST] = host;
printf("[finger to: %s@%s]\n", user, host);
call_out("time_out", 90, sock);
return 1;
}
void callback(int sock, int act, mixed a, mixed b)
{
if (!sockets[sock, LUSER] && act != SOCKET_CLOSE) {
SOCKETD->socket_close(sock);
return;
}
switch(act) {
case SOCKET_READY:
SOCKETD->socket_write(sock, sprintf("%s\r\n", sockets[sock, RUSER]));
break;
case SOCKET_READ:
if (!sockets[sock, CONTINUED]) {
tell_object(sockets[sock, LUSER], sprintf("[%s@%s]\n",
sockets[sock, RUSER],
sockets[sock, HOST]));
sockets[sock, CONTINUED] = 1;
}
tell_object(sockets[sock, LUSER], a);
break;
case SOCKET_CLOSE:
m_delete(sockets, sock);
break;
case SOCKET_ERROR: {
string err;
switch(a) {
case ECONNREFUSED:
err = "Connection Refused";
break;
case EHOSTUNREACH:
err = "Host Unreachable";
break;
case ENETUNREACH:
err = "Net Unreachable";
break;
default:
err = sprintf("Code %d", a);
break;
}
tell_object(sockets[sock, LUSER],
sprintf("ifinger: Error in connection to %s: %s.\n",
sockets[sock, HOST],
err));
m_delete(sockets, sock);
}
break;
}
return;
}
void help()
{
write("Usage: ifinger [[<user>]@<host>]\n"
"Send an internet finger request.\n");
return;
}
void time_out(int sock)
{
if (sockets[sock, LUSER])
tell_object(sockets[sock, LUSER],
sprintf("Finger to %s@%s timed out.\n",
sockets[sock, RUSER],
sockets[sock, HOST]));
m_delete(sockets, sock);
return;
}
mapping query_sockets() { return copy_mapping(sockets); }