/* Copyright (C) 1991, Marcus J. Ranum. All rights reserved. */ #ifndef lint static char RCSid[] = "$Header: /usr/users/mjr/hacks/umud/RCS/mud.c,v 1.4 91/08/18 21:49:48 mjr Exp $"; #endif /* configure all options BEFORE including system stuff. */ #include "config.h" #include <stdio.h> #ifdef NOSYSTYPES_H #include <types.h> #else #include <sys/types.h> #endif #ifndef VMS #include <sys/param.h> #endif #ifdef DAEMON #include <signal.h> #endif #include "mud.h" #include "sbuf.h" #include "vars.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() { fprintf(stderr,"usage: mud -c configfile -s startupfile\n"); return(1); } /* choke down a file full of commands */ static int boot_file(path) char *path; { FILE *bfp; char ibuf[BUFSIZ]; if((bfp = fopen(path,"r")) == (FILE *)0) { logf("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() { logf("mud is down.\n",(char *)0); mud_running = 0; } /* as simple as possible */ main(ac,av) 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: exit(usage()); } } else { exit(usage()); } } /* if there is a configuration file, run it */ if(config != (char *)0 && boot_file(config)) fatal("configure failed.\n",(char *)0); syminit(); if(io_init()) { fatal("network init failed\n",(char *)0); exit(1); } if(cache_init()) { fatal("cache init failed\n",(char *)0); exit(1); } if(DB_INIT()) { fatal("database init failed\n",(char *)0); exit(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) { (void)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 exit(0); } /* return our protected name */ char * mud_getname() { return(mud_myname); } /* ARGSUSED */ cmd__mudconfig(ac,av,who,aswho) int ac; char *av[]; char *who; char *aswho; { if(!strcmp(av[1],"shutdown")) { logf("shutdown by ",who,"\n",(char *)0); shutdown_mud(); return(0); } if(!strcmp(av[1],"log")) { if(ac != 3) return(1); if(logf_open(av[2])) return(1); logf("log is now ",av[2],"\n",(char *)0); return(0); } if(!strcmp(av[1],"chdir")) { if(ac != 3) { logf("chdir: must provide directory.\n",(char *)0); return(1); } if(chdir(av[2])) { logf("cannot cd to ",av[2]," ",(char *)-1,"\n",(char *)0); return(1); } logf("working directory is now ",av[2],"\n",(char *)0); return(0); } if(!strcmp(av[1],"name")) { if(ac != 3 || av[2][0] == '\0') { logf("must provide mud name.\n",(char *)0); return(1); } if(mud_myname != (char *)0) { logf("mud name is already set!\n",(char *)0); return(1); } 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]); logf("mud name is ",mud_myname,"\n",(char *)0); return(0); } #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 logf("daemonized.\n",(char *)0); return(0); } #endif /* define a known remote MUD */ if(!strcmp(av[1],"defmud")) { char *timp = (char *)0; if(ac < 9 || ac > 10) { logf("usage: defmud name host symbolichost remotepassword localpassword port playerport [timeout]\n",(char *)0); return(1); } 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)) { logf("mud entry ",av[2]," NOT defined\n",(char *)0); return(1); } logf("added mud entry ",av[2],"\n",(char *)0); return(1); } if (!strcmp(av[1], "defknownmud")) { if (ac != 3) { logf("usage: defknownmud name\n", (char *) 0); return 1; } if (xmit_def_knownmud(av[2])) { logf("known-mud entry ", av[2], " NOT defined\n", (char *)0); return 1; } logf("added known mud ", av[2], "\n", (char *) 0); return 1; } /* define a global macro */ if(!strcmp(av[1],"defmac")) { if(ac != 4) { logf("usage: defmac name macro\n",(char *)0); return(1); } if(symdef(av[2],av[3])) { logf("macro defn failed ",(char *)-1,"\n",(char *)0); return(1); } logf("defn macro ",av[2],"\n",(char *)0); return(0); } /* UNdefine a global macro */ if(!strcmp(av[1],"undefmac")) { if(ac != 3) { logf("usage: undefmac name\n",(char *)0); return(1); } if(symundef(av[2])) { logf("macro undefined: ",av[2],"\n",(char *)0); return(1); } logf("undefn macro ",av[2],"\n",(char *)0); return(0); } #ifdef USE_RWHO if(!strcmp(av[1],"rwhoserver")) { char *info; if(ac < 4) { logf("usage: rwhoserver hostname password\n",(char *)0); return(1); } info = ac > 4 ? av[4] : version; if(mud_myname == (char *)0) { logf("must set MUD name first\n",(char *)0); return(1); } if(rwhocli_setup(av[2],av[3],mud_myname,info)) { logf("could not establish RWHO server\n",(char *)0); return(1); } return(0); } if(!strcmp(av[1],"rwhodown")) { rwhocli_shutdown(); logf("rwho service shut down\n",(char *)0); return(0); } if(!strcmp(av[1],"rwhoupdate")) { update_rwho(); return(0); } #endif /* backup */ if(!strcmp(av[1],"backup")) { int sequence; int modulus = 0; char nxbuf[MAXOID]; char filename[MAXPATHLEN]; FILE *fp; if(ac != 3 && ac != 4) { logf("usage: backup <filename> [modulus]\n",(char *)0); return(1); } /* 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 */ ut_setnum(who,system_object,var_bsequence,sequence); itoa(sequence,nxbuf); if(cache_sync()) { logf("couldn't sync cache for backup #", nxbuf,"\n",(char *)0); return(1); } sprintf(filename,"%s.%s",av[2],nxbuf); if(DB_BACKUP(filename)) { logf("couldn't write backup file ",filename,"\n", (char *)0); return(1); } logf("wrote backup file ",filename,"\n",(char *)0); return(0); } 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]," 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 name macro\n",(char *)0); say(who,av[0]," undefmac name\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(0); } logf("_mudconfig: I don't understand ",av[1],"\n",(char *)0); return(0); }