/*
* IMC2 - an inter-mud communications protocol
*
* router.c: a simple router/hub for IMC2
*
* Copyright (C) 1996,1997 Oliver Jowett <oliver@jowett.manawatu.planet.co.nz>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program (see the file COPYING); if not, write to the
* Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
/* This is the code for a standalone hub for IMC2. You do NOT need to
* link this if you're running a normal mud using IMC!
*/
#include <stdlib.h>
#include <stdio.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>
#include <signal.h>
#include "imc.h"
#define USE_ICED
#ifdef USE_ICED
#include "iced.h"
#endif
/* commands:
*
* password connect name
* password disconnect name
* password reboot
* password sockets
* password list
* password (command as in imc_command)
*
*/
char *password;
int logging;
#ifndef CONFIG
#define CONFIG "hub/"
#endif
#ifndef EMAIL
#define EMAIL "moodyg@erols.com"
#endif
#define onearg(x,y) imc_getarg(x,y,IMC_DATA_LENGTH)
int rebooting;
int reloading;
void icec_shutdown(void) /* dummy catch for non muds */
{
}
void *imc_malloc(int size)
{
return malloc(size);
}
void IMC_free(void *block, int size)
{
if(block)
free(block);
}
char *imc_strdup(const char *orig)
{
return strdup(orig);
}
void IMC_strfree(char *str)
{
if(str)
free(str);
}
int imc_readconfighook(const char *type, const char *value)
{
if (!strcasecmp(type, "password"))
{
if (password)
{
imc_strfree(password);
}
password=imc_strdup(value);
return 1;
}
else if (!strcasecmp(type, "logging"))
{
logging=atoi(value);
return 1;
}
return 0;
}
void imc_saveconfighook(FILE *fp)
{
if (password)
fprintf(fp, "Password %s\n", password);
fprintf(fp, "Logging %d\n", logging);
}
void ev_reboot(void *data)
{
rebooting=1;
}
void ev_reload(void *data)
{
reloading=1;
}
const char *docommand(const char *name, const char *arg)
{
char buf[IMC_DATA_LENGTH];
const char *orig;
int r;
orig=arg;
arg=onearg(arg,buf);
if (!password || strcmp(buf, password))
{
imc_logstring("bad password on command from %s: %s", name, orig);
return NULL;
}
imc_logstring("command from %s: %s", name, arg);
orig=arg;
arg=onearg(arg,buf);
if (!strcasecmp(buf, "reboot"))
{
imc_add_event(10, ev_reboot, NULL, 1);
if (logging)
imc_send_chat(NULL, 2, "Rebooting in 10 seconds", "*");
return "'k";
}
if (!strcasecmp(buf, "reload"))
{
imc_add_event(10, ev_reload, NULL, 1);
if (logging)
imc_send_chat(NULL, 2, "Reloading config in 10 seconds", "*");
return "'k";
}
if (!strcasecmp(buf, "logging"))
{
logging=!logging;
return logging ? "Logging now enabled" : "Logging now disabled";
}
if (!strcasecmp(buf, "connect"))
{
arg=onearg(arg,buf);
if (imc_connect_to(buf))
return "'k";
else
return imc_error();
}
if (!strcasecmp(buf, "disconnect"))
{
arg=onearg(arg,buf);
if (imc_disconnect(buf))
return "'k";
else
return imc_error();
}
if (!strcasecmp(buf, "sockets"))
return imc_sockets();
if (!strcasecmp(buf, "list"))
return imc_list(2);
if (!strcasecmp(buf, "config"))
return imc_list(5);
#ifdef USE_ICED
if (!strcasecmp(buf, "iced"))
{
char chan[IMC_DATA_LENGTH], cmd[IMC_DATA_LENGTH];
const char *argument;
argument=imc_getarg(buf, cmd, IMC_DATA_LENGTH);
argument=imc_getarg(argument, chan, IMC_DATA_LENGTH);
iced_recv_command(name, chan, cmd, argument, 1);
return "Command executed.";
}
#endif
if ((r=imc_command(orig))>0)
return "'k";
if (!r)
return "Unknown command";
else
return imc_error();
}
char *getstats(void)
{
char *buf=imc_getsbuf(IMC_DATA_LENGTH);
char buf1[IMC_DATA_LENGTH];
int found=0;
imc_connect *c;
imc_reminfo *i;
sprintf(buf, "Connections to %s (using %s):\n\r", imc_name, IMC_VERSIONID);
for (c=imc_connect_list; c; c=c->next)
{
if (c->state==IMC_CONNECTED)
{
found++;
i=imc_find_reminfo(c->info->name, 0);
if (i && i->ping)
sprintf(buf1, " [%4dms] %s@%s\n\r",
i->ping,
c->info->name,
c->info->host);
else
sprintf(buf1, " [????ms] %s@%s\n\r",
c->info->name,
c->info->host);
strcat(buf, buf1);
}
}
sprintf(buf1, "%d direct connections total.\n\r", found);
strcat(buf, buf1);
imc_shrinksbuf(buf);
return buf;
}
void imc_debug(const imc_connect *c, int out, const char *string)
{
#if 1
char *dir;
dir=out ? "<" : ">";
printf("%s %s %s\n", imc_getconnectname(c), dir, string);
#endif
}
void imc_log(const char *string)
{
char buf[IMC_DATA_LENGTH];
char *msg;
int log=0;
strcpy(buf, ctime(&imc_now));
buf[strlen(buf)-1]=' ';
fprintf(stderr, "%s%s\n", buf, string);
if (!strncmp(string, "connect to", 10))
log=1;
else
{
msg=strchr(string, ':');
if (msg)
{
msg++;
if (!strncmp(string, "connect to", 10) ||
!strcmp(msg, " closing link") ||
!strncmp(msg, " password failure", 17) ||
!strncmp(msg, " connected ", 11))
log=1;
}
}
if (log && logging)
{
sprintf(buf, "%s", string);
imc_send_chat(NULL, 2, buf, "*"); /* log to rinfo */
}
}
void imc_recv_who(const imc_char_data *from, const char *type)
{
char arg[IMC_DATA_LENGTH];
char sendarg[6000];
type=onearg(type, arg);
if (!strcasecmp(arg, "who"))
imc_send_whoreply(from->name, getstats(), -1);
else if (!strcasecmp(arg, "info"))
{
/* use info from config file - shogar*/
sprintf(sendarg,"\n\r%s\n\rInfoHost:%s\n\rAdminstrated by %s\n\remail:%s \n\rimcmail:%s\n\r",
imc_siteinfo.details,
imc_siteinfo.host,
imc_siteinfo.name,
imc_siteinfo.email,
imc_siteinfo.imail);
imc_send_whoreply(from->name,sendarg,-1);
/*
imc_send_whoreply(from->name,
"This is a stand-alone IMC router prototype based on Oliver Jowett's router.c.\n\r"
"It is administered by " EMAIL "\n\r"
"For information on IMC: http://moodyg.erols.com/imc/index.html\n\r", -1);
*/
}
else if (!strcasecmp(arg, "direct"))
imc_send_whoreply(from->name, imc_list(0), -1);
else if (!strcasecmp(arg, "list"))
imc_send_whoreply(from->name, imc_list(3), -1);
else if (!strcasecmp(arg, "config"))
imc_send_whoreply(from->name, imc_list(4), -1);
else if (!strcasecmp(arg, "istats"))
imc_send_whoreply(from->name, imc_getstats(), -1);
else if (!strcasecmp(arg, "help") || !strcasecmp(arg, "services") ||
!strcasecmp(arg, "help"))
imc_send_whoreply(from->name,
"Available rquery types:\n\r"
"help - this list\n\r"
"who - active muds on IMC\n\r"
"info - router information\n\r"
"list - list known muds on IMC\n\r"
"direct - list directly connected muds\n\r"
"config - show local configuration\n\r"
"istats - IMC statistics\n\r", -1);
else
imc_send_whoreply(from->name,
"Sorry, no information of that type is available", -1);
}
void imc_recv_tell(const imc_char_data *from, const char *to, const char *text,
int isreply)
{
const char *response;
if (strcmp(to, "*"))
return;
response=docommand(from->name, text);
if (response)
imc_send_tell(NULL, from->name, response, 1);
}
void imc_recv_chat(const imc_char_data *from, int channel, const char *text)
{
}
void imc_recv_emote(const imc_char_data *from, int channel, const char *text)
{
}
void imc_recv_whois(const imc_char_data *from, const char *to)
{
}
void imc_recv_whoisreply(const char *to, const char *text)
{
}
void imc_recv_whoreply(const char *to, const char *text, int sequence)
{
}
void imc_recv_beep(const imc_char_data *from, const char *to)
{
}
void imc_traceroute(int ping, const char *pathto, const char *pathfrom)
{
}
char *imc_mail_arrived(const char *from, const char *to, const char *date,
const char *subject, const char *text)
{
char *buf=imc_getsbuf(200);
sprintf(buf, "%s is a router only, and does not accept mail.", imc_name);
imc_shrinksbuf(buf);
return buf;
}
static void graceful_exit(int sig)
{
imc_logstring("Killed from shell");
imc_shutdown();
exit(0);
}
int main(void)
{
signal(SIGPIPE, SIG_IGN);
signal(SIGTERM,graceful_exit );
imc_is_router=1;
imc_startup(CONFIG);
if ((imc_active < IA_UP) || (imc_lock_file<0))
{
imc_logstring("router: giving up");
exit(1);
}
#ifdef USE_ICED
iced_init();
#endif
while (!rebooting)
{
imc_idle(imc_get_max_timeout(), 0);
if (reloading)
{
imc_shutdown();
imc_startup(CONFIG);
reloading=0;
}
}
imc_shutdown();
exit(0);
}