/*
Copyright (C) 1991, Marcus J. Ranum. All rights reserved.
*/
/* configure all options BEFORE including system stuff. */
#include "config.h"
#include "mud.h"
#include "sym.h"
#include "sbuf.h"
#include "vars.h"
#include "RWHO/rwho.h"
/* GLOBAL !*/
int cron_quantum = 3600; /* one hour */
static int mud_running = 1;
static char *mud_myname = (char *) 0;
time_t cronlast;
time_t currtime;
static int usage (void)
{
fprintf (stderr, "usage: mud -c configfile -s startupfile\n");
return (1);
}
/* choke down a file full of commands */
static int boot_file (char *path)
{
FILE *bfp;
char ibuf[BUFSIZ];
if ((bfp = fopen (path, "rb")) == (FILE *) 0) {
log_printf ("can't open ", path, ": ", (char *) -1, "\n", (char *) 0);
return (1);
}
while (fgets (ibuf, sizeof (ibuf), bfp) != (char *) 0)
if (ibuf[0] != '#' && ibuf[0] != '\n')
(void) run_boot (ibuf);
fclose (bfp);
return (0);
}
/* initiate shutdown (used in signal handlers) */
static void shutdown_mud (void)
{
log_printf ("mud is down.\n", (char *) 0);
mud_running = 0;
}
/* as simple as possible */
int main (int ac, char **av)
{
int x;
char *config = (char *) 0;
char *startup = (char *) 0;
for (x = 1; x < ac; x++) {
if (av[x][0] == '-') {
switch (av[x][1]) {
case 'c':
config = av[++x];
break;
case 's':
startup = av[++x];
break;
default:
return (usage ());
}
} else {
return (usage ());
}
}
/* if there is a configuration file, run it */
if (config != (char *) 0 && boot_file (config))
fatal ("configure failed.\n", (char *) 0);
syminit ();
WIN32STARTUP
if (io_init ()) {
fatal ("network init failed\n", (char *) 0);
return (1);
}
if (cache_init ()) {
fatal ("cache init failed\n", (char *) 0);
return (1);
}
if (DB_INIT ()) {
fatal ("database init failed\n", (char *) 0);
return (1);
}
/* all I/O layers are initialized, now run startup file if one */
if (startup != (char *) 0 && boot_file (startup))
fatal ("startup failed.\n", (char *) 0);
/* MUD name must be set */
if (mud_myname == (char *) 0)
fatal ("mud server name is unset\n", (char *) 0);
#ifdef DAEMON
(void) signal (SIGINT, shutdown_mud);
(void) signal (SIGTERM, shutdown_mud);
(void) signal (SIGQUIT, shutdown_mud);
#endif
while (mud_running) {
if (io_loop () != 0)
break;
/* flush I/O buffers */
io_sync ();
/* reset cache pointers */
cache_reset ();
/* maintenance/cron routines ? */
(void) time (&currtime);
if (currtime - cronlast > cron_quantum) {
cron_run (currtime);
cronlast = currtime;
}
/* free any temporarily allocated memory */
tmp_sync ();
}
/* orderly shutdown */
(void) cache_sync ();
DB_CLOSE ();
#ifdef USE_RWHO
rwhocli_shutdown ();
#endif
return (0);
}
/* return our protected name */
char *mud_getname (void)
{
return (mud_myname);
}
/* ARGSUSED */
int cmd__mudconfig (int ac, char *av[], char *who, char *aswho)
{
if (!strcmp (av[1], "shutdown")) {
log_printf ("shutdown by ", who, "\n", (char *) 0);
shutdown_mud ();
return (UERR_NONE);
}
if (!strcmp (av[1], "log")) {
if (ac != 3)
return (UERR_ARGCNT);
if (logf_open (av[2]))
return (UERR_FATAL);
log_printf ("log is now ", av[2], "\n", (char *) 0);
return (UERR_NONE);
}
if (!strcmp (av[1], "chdir")) {
if (ac != 3) {
log_printf ("chdir: must provide directory.\n", (char *) 0);
return (UERR_ARGCNT);
}
if (chdir (av[2])) {
log_printf ("cannot cd to ", av[2], " ", (char *) -1, "\n", (char *) 0);
return (UERR_FATAL);
}
log_printf ("working directory is now ", av[2], "\n", (char *) 0);
return (UERR_NONE);
}
if (!strcmp (av[1], "name")) {
if (ac != 3 || av[2][0] == '\0') {
log_printf ("must provide mud name.\n", (char *) 0);
return (UERR_ARGCNT);
}
if (mud_myname != (char *) 0) {
log_printf ("mud name is already set!\n", (char *) 0);
return (UERR_FATAL);
}
mud_myname = (char *) malloc ((unsigned) strlen (av[2]) + 1);
if (mud_myname == (char *) 0)
fatal ("cannot allocate mud name buffer!\n", (char *) 0);
(void) strcpy (mud_myname, av[2]);
log_printf ("mud name is ", mud_myname, "\n", (char *) 0);
return (UERR_NONE);
}
if (!strcmp (av[1], "newusers")) {
if (ac != 3 || av[2][0] == '\0') {
log_printf ("can only turn on or off newusers!\n", (char *) 0);
} else if (!strcmp (av[2], "on")) {
log_printf ("new user logons enabled.\n", (char *) 0);
newusers = 1;
} else if (!strcmp (av[2], "off")) {
log_printf ("new user logons disabled.\n", (char *) 0);
newusers = 0;
} else {
log_printf ("can only turn on or off newusers!\n", (char *) 0);
}
return (UERR_NONE);
}
#ifdef DAEMON
/* daemonize ourself */
if (!strcmp (av[1], "daemonize")) {
(void) signal (SIGHUP, SIG_IGN);
(void) signal (SIGCHLD, SIG_IGN);
(void) signal (SIGALRM, SIG_IGN);
if (fork ())
exit (0);
#ifdef SETSID
(void) setsid ();
#endif
log_printf ("daemonized.\n", (char *) 0);
return (UERR_NONE);
}
#endif
/* define a known remote MUD */
if (!strcmp (av[1], "defmud")) {
char *timp = (char *) 0;
if (ac < 9 || ac > 10) {
log_printf
("usage: defmud name host symbolichost remotepassword localpassword port playerport [timeout]\n",
(char *) 0);
return (UERR_ARGCNT);
}
if (ac == 10)
timp = av[9];
if (xmit_def_mudent (av[2], av[3], av[4], av[5], av[6], av[7], av[8],
timp)) {
log_printf ("mud entry ", av[2], " NOT defined\n", (char *) 0);
return (UERR_FATAL);
}
log_printf ("added mud entry ", av[2], "\n", (char *) 0);
return (UERR_NONE);
}
if (!strcmp (av[1], "defknownmud")) {
if (ac != 3) {
log_printf ("usage: defknownmud name\n", (char *) 0);
return (UERR_ARGCNT);
}
if (xmit_def_knownmud (av[2])) {
log_printf ("known-mud entry ", av[2], " NOT defined\n", (char *) 0);
return (UERR_FATAL);
}
log_printf ("added known mud ", av[2], "\n", (char *) 0);
return (UERR_NONE);
}
/* list all global macros */
if (!strcmp (av[1], "listmac")) {
if (ac == 2)
symlist (who, (char *) 0);
else {
int junk;
for (junk = 2; junk < ac; junk++)
symlist (who, av[junk]);
}
return (UERR_NONE);
}
/* define a global macro */
if (!strcmp (av[1], "defmac")) {
if (ac != 4) {
log_printf ("usage: defmac name macro\n", (char *) 0);
return (UERR_ARGCNT);
}
if (symdef (av[2], av[3], SFLG_CMD)) {
log_printf ("macro defn failed\n", (char *) 0);
return (UERR_FATAL);
}
log_printf ("defn macro ", av[2], "\n", (char *) 0);
return (UERR_NONE);
}
if (!strcmp (av[1], "defUmac")) {
if (ac != 4) {
log_printf ("usage: defmac name macro\n", (char *) 0);
return (UERR_ARGCNT);
}
if (symdef (av[2], av[3], SFLG_UCMD)) {
log_printf ("macro defn failed\n", (char *) 0);
return (UERR_FATAL);
}
log_printf ("defn U-code ", av[2], "\n", (char *) 0);
return (UERR_NONE);
}
/* mark a macro as priv'd */
if (!strcmp (av[1], "privmac")) {
if (ac != 4) {
log_printf ("usage: privmac macroname owner\n", (char *) 0);
return (UERR_ARGCNT);
}
if (sympriv (av[2], av[3])) {
log_printf ("macro setpriv failed\n", (char *) 0);
return (UERR_FATAL);
}
log_printf ("setpriv macro ", av[2], " as ", av[3], "\n", (char *) 0);
return (UERR_NONE);
}
/* UNdefine a global macro */
if (!strcmp (av[1], "undefmac")) {
if (ac != 3) {
log_printf ("usage: undefmac name\n", (char *) 0);
return (UERR_ARGCNT);
}
if (symundef (av[2])) {
log_printf ("macro undefined: ", av[2], "\n", (char *) 0);
return (UERR_FATAL);
}
log_printf ("undefn macro ", av[2], "\n", (char *) 0);
return (UERR_NONE);
}
#ifdef USE_RWHO
if (!strcmp (av[1], "rwhoserver")) {
char *info;
if (ac < 4) {
log_printf ("usage: rwhoserver hostname password\n", (char *) 0);
return (UERR_ARGCNT);
}
info = ac > 4 ? av[4] : version;
if (mud_myname == (char *) 0) {
log_printf ("must set MUD name first\n", (char *) 0);
return (UERR_FATAL);
}
if (rwhocli_setup (av[2], av[3], mud_myname, info)) {
log_printf ("could not establish RWHO server\n", (char *) 0);
return (UERR_FATAL);
}
return (UERR_NONE);
}
if (!strcmp (av[1], "rwhodown")) {
rwhocli_shutdown ();
log_printf ("rwho service shut down\n", (char *) 0);
return (UERR_NONE);
}
if (!strcmp (av[1], "rwhoupdate")) {
update_rwho ();
return (UERR_NONE);
}
#endif
/* backup */
if (!strcmp (av[1], "backup")) {
int sequence;
int modulus = 0;
char nxbuf[MAXOID];
char filename[MAXPATHLEN];
if (ac != 3 && ac != 4) {
log_printf ("usage: backup <filename> [modulus]\n", (char *) 0);
return (UERR_ARGCNT);
}
/* check for modulus */
if (ac == 4)
modulus = atoi (av[3]);
/* get the backup sequence number */
if (ut_getnum (system_object, var_bsequence, &sequence))
sequence = 0;
sequence++;
if (modulus > 0)
sequence %= modulus;
/* assume this works */
(void) ut_setnum (who, system_object, var_bsequence, sequence);
(void) itoa (sequence, nxbuf, 10);
if (cache_sync ()) {
log_printf ("couldn't sync cache for backup #",
nxbuf, "\n", (char *) 0);
return (UERR_FATAL);
}
snprintf (filename, sizeof (filename), "%s.%s", av[2], nxbuf);
if (DB_BACKUP (filename)) {
log_printf ("couldn't write backup file ", filename, "\n", (char *) 0);
return (UERR_FATAL);
}
log_printf ("wrote backup file ", filename, "\n", (char *) 0);
return (UERR_NONE);
}
if (!strcmp (av[1], "help")) {
say (who, av[0], " shutdown\n", (char *) 0);
say (who, av[0], " log file-name\n", (char *) 0);
say (who, av[0], " chdir directory-name\n", (char *) 0);
say (who, av[0], " name mud-name\n", (char *) 0);
#ifdef DAEMON
say (who, av[0], " daemonize\n", (char *) 0);
#endif
say (who, av[0], " newusers [on|off]\n", (char *) 0);
say (who, av[0],
" defmud MUDname hostIP-addr hostname remotepassword localpassword serverport playerport [timeout]\n",
(char *) 0);
say (who, av[0], " defknownmud MUDname\n", (char *) 0);
say (who, av[0], " defmac mac-name macro\n", (char *) 0);
say (who, av[0], " defUmac mac-name U-code\n", (char *) 0);
say (who, av[0], " undefmac mac-name\n", (char *) 0);
say (who, av[0], " privmac mac-name object-id\n", (char *) 0);
#ifdef USE_RWHO
say (who, av[0], " rwhoserver hostname password [comment]\n", (char *) 0);
say (who, av[0], " rwhodown\n", (char *) 0);
#endif
say (who, av[0], " backup file-name [modulus]\n", (char *) 0);
return (UERR_NONE);
}
log_printf ("_mudconfig: I don't understand ", av[1], "\n", (char *) 0);
return (UERR_NONE);
}