/**************************************************************************
** Dirt IV System functions
** 1996 - Marty
** Original code by various other Coders
**************************************************************************/
#define SYSTEM_C
/**************************************************************************
** IMPORT
**************************************************************************/
#include <strings.h>
#include <unistd.h>
#include <stdio.h>
#include <signal.h>
#include "kernel.h"
#include "bprintf.h"
#include "main.h"
#include "sendsys.h"
#include "mudmacros.h"
#include "pflags.h"
#include "oflags.h"
#include "lflags.h"
#include "cflags.h"
#include "sflags.h"
#include "bprintf.h"
#include "parse.h"
#include "colors.h"
#include "zones.h"
#include "objsys.h"
#include "mobile.h"
#include "rooms.h"
#include "log.h"
#include "main.h"
#include "calendar.h"
#include "special.h"
#include "atsys.h"
#include "actions.h"
#include "wizard.h"
#ifdef INTERMUD
#include "InterMud/intermud.h"
#endif
#ifdef ABERCHAT
extern int aberfd;
extern Boolean auto_restart;
#endif
/**************************************************************************
** PROTOTYPES
**************************************************************************/
PUBLIC A_COMMAND(delaycom); /* Set the MUD in a delayed reboot */
PUBLIC A_COMMAND(rebootcom); /* Do a direct Reboot of the MUD */
PUBLIC A_COMMAND(updatecom); /* Do a direct Update of the MUD */
PUBLIC A_COMMAND(workloadcom); /* Get the machine's workload and CPU usage */
PUBLIC A_COMMAND(globalcom); /* The the global MUD status */
PUBLIC A_COMMAND(opengamecom); /* Open the game after a shutdown */
PUBLIC A_COMMAND(tournamentcom); /* Open a Tournament on the MUD */
PUBLIC A_COMMAND(startcom); /* Start the mobiles who move */
PUBLIC A_COMMAND(stopcom); /* Stop the mobiles from moving */
PUBLIC A_COMMAND(eventscom); /* Start/Stop events */
PUBLIC A_COMMAND(acctcom); /* Accounting system */
PRIVATE int dopc (int max, int exist);
PRIVATE void countmobiles (int zone);
PRIVATE void countobjects (int zone);
PRIVATE void countrooms (int zone);
PUBLIC void objectscom (void);
PUBLIC void mstatcom (void);
PUBLIC void signalcom (void);
/*************************************************************************
** IMPLEMENTATION
*************************************************************************/
PUBLIC A_COMMAND(eventscom)
{ Boolean on;
if (brkword() == -1)
{ bprintf("Usage: events on/off\n");
}
else
{ if (EQ(wordbuf,"on"))
{ (void)setfunctions();
on = True;
}
else if (EQ(wordbuf,"off"))
{ clearfunctions();
on = False;
}
else
{
bprintf("Usages: events on/off\n");
return;
}
send_msg(DEST_ALL,MODE_BRACKET|MODE_QUIET,LVL_DEMI,LVL_MAX,NOBODY,NOBODY,
"Game events are %s", on ? "On" : "Off");
#ifdef LOG_EVENTS
mudlog("GAME: events %s by %s\n",on ? "ON" : "OFF", pname(mynum));
#endif
}
}
PUBLIC A_COMMAND(delaycom)
{
if (!ptstflg(mynum,PFL_REBOOT))
{ bprintf("You can't do that now.\n");
}
else {
if (the_world->w_delayed == 0)
the_world->w_delayed = 1;
else
the_world->w_delayed = 0;
send_msg (DEST_ALL, MODE_BRACKET|MODE_QUIET, LVL_DEMI, LVL_MAX, NOBODY, NOBODY,
"&+wDelayed Reboot now %s",
the_world->w_delayed ? "Enabled" : "Disabled" );
mudlog("Delayed Reboot: %s by %s", the_world->w_delayed ?
"ENABLED" : "DISABLED", pname(mynum));
}
}
PUBLIC A_COMMAND(rebootcom)
{ if (!ptstflg(mynum,PFL_REBOOT))
{ erreval();
return;
}
send_msg(DEST_ALL,MODE_BRACKET,LVL_ARCHWIZARD,LVL_MAX,NOBODY,NOBODY,
"World reboot initiated");
numreboots++;
#ifdef INTERMUD
imShutdown(1);
#endif
sysreboot(False,False);
}
PUBLIC A_COMMAND(updatecom)
{ if (!ptstflg(mynum,PFL_REBOOT))
{ erreval();
return;
}
send_msg(DEST_ALL,MODE_BRACKET,LVL_ARCHWIZARD,LVL_MAX,NOBODY,NOBODY,
"World update initiated");
numreboots++;
#ifdef INTERMUD
imShutdown(1);
#endif
sysreboot(False,True);
}
PUBLIC A_COMMAND(workloadcom)
{ char work[100];
char ps1[100];
char ps2[100];
FILE *fp;
char command[50];
char *wlerror = "Unable to get system work load statistics.\n";
if (!ptstflg(mynum,PFL_SYSSTAT))
{ erreval();
return;
}
#ifndef LINUX
bprintf ("Disabled for now.\n");
return;
#endif
sprintf(command,"ps u %d|grep aberd",getpid());
if ((fp = popen ("uptime; ps -u","r")) == NULL )
{ bprintf("%s\n",wlerror);
return;
}
fgets (work, sizeof(work),fp);
fgets (ps1, sizeof(ps1),fp);
pclose (fp);
if ((fp = popen(command,"r")) == NULL )
{ bprintf("%s",wlerror);
return;
}
fgets(ps2,sizeof(ps2),fp);
pclose(fp);
bprintf("&+wSystem statistics for server &+w%s&*\n&+w%s&*\n",my_hostname,
DOUBLELINE);
bprintf("%s\n",work);
bprintf("&+w%s Daemon statistics\n",MUDNAME);
bprintf("&+w%s&*\n",DOUBLELINE);
bprintf("&+w%s",ps1);
bprintf("%-79.79s\n",ps2);
}
PUBLIC A_COMMAND(globalcom)
{ extern int dnsfd;
char buff[80];
bprintf ("&+wGlobal Settings:&*\n&+w%s&*\n"
"&+wWeather &+w: &+w%s&*\n", DOUBLELINE, wthr_type (the_world->w_weather));
bprintf ("&+wLock-status &+w: &+w%slocked&*\n", lev2s (buff, the_world->w_lock, 0));
if (the_world->w_start_loc == 0)
bprintf ("&+wGame Running &+w: &+wAllowed&*\n");
else
bprintf ("&+wGame Running &+w: &+wBlocked &+w(Start Location: &+w%s&+w)&*\n",
showname(the_world->w_start_loc));
bprintf ("&+wMUD DNS Status &+w: %s\n",
(dnsfd != -1) ? "&+wActivated" : "&+wDown");
#ifdef INTERMUD
bprintf ("&+wInterMUD Status &+w: %s&*\n",
(imfd == -1) ? "&+wConnection closed" : "&+wConnection Established");
#endif
#ifdef ABERCHAT
bprintf ("&+wAberChat Status &+w: %s &+w(%s&+w)&*\n",
(aberfd == -1) ? "&+wConnection closed" : "&+wConnection Established",
auto_restart ? "&+wAutomatic Reconnect" : "&+wManual Connect");
#endif
bprintf ("&+wMobiles &+w: %s&*\n",
(the_world->w_mob_stop) ? "&+wStopped" : "&+wStarted&*");
bprintf ("&+wWar/Peace &+w: %s&*\n", (the_world->w_peace) ? "&+wPeace" : "&+wWar");
bprintf ("&+wTournament-Mode &+w: %s&*\n",
(the_world->w_tournament) ? "&+wActivated" : "&+wDeactivated");
bprintf ("&+wDelayed Reboot &+w: %s&*\n", the_world->w_delayed ? "&+wEnabled" : "&+wDisabled" );
bprintf ("&+wMax. Users &+w: &+w%d&*\n", max_players);
bprintf ("&+wNumber of Rooms &+w: "
"&+w%4d &+wpermanent +&+w%4d &+wwiz-made = &+w%4d&+w (max %d)&*\n",
num_const_locs, numloc - num_const_locs, numloc, GLOBAL_MAX_LOCS);
bprintf ("&+wNumber of Mobiles &+w: "
"&+w%4d &+wpermanent +&+w%4d&+w wiz-made = &+w%4d&+w (max %d)&*\n",
num_const_chars - max_players, numchars - num_const_chars,
numchars - max_players, GLOBAL_MAX_MOBS);
bprintf ("&+wNumber of Objects &+w: "
"&+w%4d&+w permanent +&+w%4d&+w wiz-made = &+w%4d&+w (max %d)&+w\n",
num_const_obs, numobs - num_const_obs, numobs, GLOBAL_MAX_OBJS);
bprintf("&+w%s&*\n",DOUBLELINE);
}
PUBLIC void shutdowncom (char crash)
{
FILE *nologin_file;
char s[MAX_COM_LEN];
int i;
char *t = MUDNAME" is closed for debugging. Please try again later.";
if (crash != 100)
{ if (!ptstflg (mynum, PFL_SHUTDOWN))
{ erreval ();
return;
}
}
getreinput (s);
if (!EMPTY (s))
t = s;
if (!crash)
{ if ((nologin_file = fopen (NOLOGIN, "w")) == NULL)
{ bprintf ("(Unable to write NOLOGIN file.)");
}
else
{ fprintf (nologin_file, "%s\n", t);
fclose (nologin_file);
}
bprintf ("&+w%s is now closed.&*\n",MUDNAME);
send_msg(DEST_ALL,MODE_BRACKET|MODE_QUIET,LVL_MIN,LVL_MAX,mynum,NOBODY,
"%s has been closed for the public",MUDNAME);
}
else
{ bprintf ("&+w[&+w%s is going down &+wHARD&+w]&*\n",MUDNAME);
mudlog ("CRASH Called by %s.",pname(mynum));
rm_pid_file ();
}
mudlog ("SYSTEM: SHUTDOWN%s by %s", crash ? " >CRASH<" : "",
crash == 100 ? "Due to FATAL error" : pname (mynum));
send_msg (DEST_ALL, MODE_BRACKET, LVL_APPREN, LVL_MAX, NOBODY, NOBODY,
"%s %s %s",
crash ? "CRASH" : "SHUTDOWN",
crash == 100 ? "" : "by",
crash == 100 ? "DUE TO FATAL ERROR" : pname (mynum));
saveallcom();
/* kick people off here */
for (i = 0; i < max_players; i++)
{ if (is_in_game (i) && (plev(i) < LVL_GOD && !crash))
{ p_crapup (i, t, CRAP_SAVE);
}
}
if (crash)
{ exit (0);
}
}
PUBLIC A_COMMAND(opengamecom)
{ if (!ptstflg(mynum, PFL_SHUTDOWN))
{ erreval();
return;
}
if (unlink(NOLOGIN) < 0)
{ bprintf("The game is already open.\n");
}
else
{ mudlog("SYSTEM: OPENGAME by %s", pname(mynum));
send_msg(DEST_ALL,MODE_QUIET|MODE_BRACKET,LVL_MIN,LVL_MAX,NOBODY,NOBODY,
"%s is now open",MUDNAME);
}
}
PUBLIC A_COMMAND(tournamentcom)
{
bprintf("&+w[&+wTournament mode is now %s&+w]&*\n",
(the_world->w_tournament = !the_world->w_tournament) ?
"ON" : "OFF");
}
PUBLIC A_COMMAND(stopcom)
{
the_world->w_mob_stop = 1;
send_msg (DEST_ALL, MODE_BRACKET|MODE_QUIET, LVL_APPREN, LVL_MAX, NOBODY, NOBODY,
"Mobiles STOPped");
mudlog("GAME: mobiles STOPped by %s",pname(mynum));
}
PUBLIC A_COMMAND(startcom)
{
the_world->w_mob_stop = 0;
send_msg (DEST_ALL, MODE_BRACKET|MODE_QUIET, LVL_APPREN, LVL_MAX, NOBODY, NOBODY,
"Mobiles STARTed");
mudlog("GAME: mobiles STARTed by %s",pname(mynum));
}
/**
** The Accounting System - By Illusion
**/
PUBLIC A_COMMAND(acctcom)
{ char text[80];
int zone = -1;
int i;
if (brkword () != -1)
{ if ((zone = get_zone_by_name (wordbuf)) == -1)
{ bprintf ("No Such Zone: %s\n", wordbuf);
return;
}
}
if (zone == -1)
sprintf (text, "Current System Accounting");
else
sprintf (text, "Current System Accounting (Zone: %s)", zname (zone));
for (i = 0; i < (60 - strlen (text)) / 2; ++i)
bprintf (" ");
bprintf ("&+w%s\n", text);
bprintf ("&+w%s\n", DASHLINE);
countrooms (zone);
bprintf ("\n");
countmobiles (zone);
bprintf ("\n");
countobjects (zone);
}
/* Show percentage: max is maximum, exist is how many of max are left */
PRIVATE int dopc (int max, int exist)
{ int proc;
int t;
if (exist > max) /* Someone passed them backwards */
{ t = max; /* so we fix that here. */
max = exist;
exist = t;
}
if (!(max))
proc = 0;
else
proc = (exist * 100) / max;
return (proc);
}
PRIVATE void countmobiles (int zone)
{ int bas, j = 0, i;
int a;
int NoHassle, Possessed, DeadMobs;
int proc;
NoHassle = Possessed = DeadMobs = 0;
a = max_players;
if (zone == -1)
bas = numchars;
else
{ a = 0;
bas = znumchars (zone);
}
for (; a < bas; a++)
{ i = (zone == -1) ? a : zmob_nr (a, zone);
if (EMPTY (pname (i)))
continue;
if (ptstflg (i, PFL_NOHASSLE))
NoHassle++;
if (ptstflg (i, SFL_OCCUPIED))
Possessed++;
if (alive (i) != -1)
j++;
if (zone == -1)
DeadMobs = ((numchars - max_players) - j);
else
DeadMobs = (znumchars (zone) - j);
}
if (zone == -1)
proc = dopc (numchars - max_players, j);
else
proc = dopc (znumchars (zone), j);
if (zone == -1)
bprintf ("&+w%-18s: %8d\t%-18s: %8d\n", "Total Mobiles", numchars - max_players, "Living Mobiles", j);
else
bprintf ("&+w%-18s: %8d\t%-18s: %8d\n", "Total Mobiles", znumchars (zone), "Living Mobiles", j);
bprintf ("&+w%-18s: %8d\t%-18s: %8d\n",
"Dead Mobiles", DeadMobs, "Percent Living", proc);
bprintf ("&+w%-18s: %8d\t%-18s: %8d\n",
"Possessed", Possessed, "NoHassle", NoHassle);
}
PRIVATE void countobjects (int zone)
{ int proc;
long totalval = 0;
int aa, oc = 0;
int destroyed, weapons, armor, food;
int lightable, container, key, noget;
int destweap, destarm, destfood, destlight, destcont, destkey;
int objnum;
destroyed = weapons = armor = food = lightable
= container = key = noget = destweap = destarm = destfood =
destlight = destcont = destkey = 0;
if (zone == -1)
objnum = numobs;
else
{ aa = zfirst_obj (zone);
objnum = znumobs (zone);
}
for (aa = 0; aa < objnum; aa++)
{ if (zone != -1)
oc = zobj_nr (aa, zone);
if (!otstbit (oc, OFL_NOGET) && !otstbit (oc, OFL_DESTROYED))
totalval += ovalue (oc);
if (otstbit (oc, OFL_NOGET))
noget++;
if (otstbit (oc, OFL_DESTROYED))
destroyed++;
if (otstbit (oc, OFL_WEAPON))
{ weapons++;
if (otstbit (oc, OFL_DESTROYED))
destweap++;
}
if (otstbit (oc, OFL_ARMOR))
{ armor++;
if (otstbit (oc, OFL_DESTROYED))
destarm++;
}
if (otstbit (oc, OFL_FOOD))
{ food++;
if (otstbit (oc, OFL_DESTROYED))
destfood++;
}
if (otstbit (oc, OFL_CONTAINER) &&
!otstbit (oc, OFL_NOGET))
{ container++;
if (otstbit (oc, OFL_DESTROYED))
destcont++;
}
if (otstbit (oc, OFL_KEY))
{ key++;
if (otstbit (oc, OFL_DESTROYED))
destkey++;
}
if (otstbit (oc, OFL_LIGHTABLE))
{ lightable++;
if (otstbit (oc, OFL_DESTROYED))
destlight++;
}
if (zone == -1)
oc++;
}
if (zone == -1)
proc = dopc (oc - destroyed, oc);
else
proc = dopc (znumobs (zone) - destroyed, znumobs (zone));
if (zone == -1)
bprintf ("&+w%-18s: %8d\t%-18s: %8d\n", "Total Objects", oc, "Remaining", oc - destroyed);
else
bprintf ("&+w%-18s: %8d\t%-18s: %8d\n", "Total Objects", znumobs (zone), "Remaining", znumobs (zone) - destroyed);
bprintf ("&+w%-18s: %8d\t%-18s: %8d\n", "Destroyed", destroyed, "Percent Left", proc);
bprintf ("&+w%-18s: %8d\t%-18s: %8d\n\n", "NoGet", noget, "Value of Objects", totalval);
bprintf ("&+w Detail List of Objects Available to Mortals\n");
bprintf ("&+w%s\n", DASHLINE);
bprintf ("&+w%-18s: %8d\t%-18s: %8d\n", "Weapons", weapons, "Destroyed", destweap);
bprintf ("&+w%-18s: %8d\t%-18s: %8d\n", "Armor", armor, "Destroyed", destarm);
bprintf ("&+w%-18s: %8d\t%-18s: %8d\n", "Food", food, "Destroyed", destfood);
bprintf ("&+w%-18s: %8d\t%-18s: %8d\n", "Containers", container, "Destroyed", destcont);
bprintf ("&+w%-18s: %8d\t%-18s: %8d\n", "Lightable", lightable, "Destroyed", destlight);
bprintf ("&+w%-18s: %8d\t%-18s: %8d\n", "Keys", key, "Destroyed", destkey);
bprintf ("&+w%s\n", DASHLINE);
}
PRIVATE void countrooms (int zone)
{ int roomct,atcount;
if (zone == -1)
roomct = num_const_locs;
else
roomct = znumloc (zone);
atcount = countATs();
bprintf ("&+w%-18s: %8d\t%-18s: %8d\n", "Total Rooms", roomct, "Automated Trans.",atcount);
}
/* objectscom()
* 1995 by Illusion
* Pager-ized by Marty
*/
PUBLIC A_COMMAND(objectscom)
{ int zone = -1;
int i, c, oc = 0;
char b[60], d[60];
FILE *fp;
char fn[512];
if (brkword () != -1)
{ if ((zone = get_zone_by_name (wordbuf)) == -1)
{ bprintf ("No Such Zone: %s\n", wordbuf);
return;
}
}
sprintf(fn,"%sobjectscom.%s",TEMP_DIR,pname(mynum));
if ((fp = fopen(fn,"w")) == NULL)
{ fwerror(fn);
return;
}
if (zone == -1)
{ for (i = 0; i < numobs; ++i)
{ oc++;
c = findzone (oloc (i), b);
sprintf (d, "%s%d", b, c);
if (ocarrf (i) >= CARRIED_BY)
strcpy (d, "Carried");
else if (ocarrf (i) == IN_CONTAINER)
strcpy (d, "In Container");
fprintf (fp,"&+w%-12s&+w%-13s", oname (i), d);
if (oc % 3 == 0)
fprintf (fp,"\n");
}
if (oc % 3 != 0)
fprintf (fp,"\n");
fprintf (fp,"\n&+wTotal of &+w%d &+wobjects.\n", oc);
}
else
{
fprintf (fp,"&+wObject List For Zone: &+w%s\n", zname (zone));
for (i = zfirst_obj (zone); i != SET_END; i = znext_obj (zone))
{ oc++;
c = findzone (oloc (i), b);
sprintf (d, "%s%d", b, c);
if (ocarrf (i) >= CARRIED_BY)
strcpy (d, "Carried");
else if (ocarrf (i) == IN_CONTAINER)
strcpy (d, "In Container");
fprintf (fp,"&+w%-12s&+w%-14s", oname (i), d);
if (oc % 3 == 0)
fprintf (fp,"\n");
}
if (oc % 3 != 0)
fprintf (fp,"\n");
fprintf (fp,"\n&+wTotal of &+w%d &+wobjects.\n", oc);
}
fclose(fp);
read_file(fn,NULL,True,NULL);
unlink(fn);
}
/* mstatcom()
* Status for mortals
* 1995 by Illusion
*/
PUBLIC A_COMMAND(mstatcom)
{ int i, j = 0;
char cond[50];
char buff[100];
bprintf ("&+wLvl Name Score Str/Max DP AC Cnd Who/Where\n");
bprintf ("&+w--------------------------------------------------------------------------------\n");
for (i = 0; i < max_players; ++i)
{ if (is_in_game (i) && plev (i) < LVL_APPREN)
{ ++j;
if (pfighting (i) >= 0)
sprintf (cond, "&+wFgt &+w%s: %d (%s)", pname (pfighting (i)), pstr (pfighting (i)), xshowname (buff, ploc (i)));
else if (phelping (i) >= 0)
sprintf (cond, "&+wHlp &+w%s (%s)", pname (phelping (i)), xshowname (buff, ploc (i)));
else if (psitting (i)==1)
sprintf (cond, "&+wSit &+w(%s)", xshowname (buff, ploc (i)));
else if (psitting(i) == 2)
sprintf(cond, "&+wSlp &+w(%s)", xshowname(buff,ploc(i)));
else if (psitting(i) == 3)
sprintf(cond, "&+wTrn &+w(%s)", xshowname(buff,ploc(i)));
else
sprintf (cond, "&+wStd &+w(%s)", xshowname (buff, ploc (i)));
bprintf ("&+w%3d &+w%-13.13s &+w%-6d %s%3d&+w/&+w%-3d &+w%2d %2d &+w%-32.32s\n",
plev (i), pname (i), pscore (i),
pstr (i) == maxstrength (i) ?
"&+w" : pstr (i) < 20 ? "&+w" : "&+w",
pstr (i), maxstrength (i),
player_damage (i),
player_armor (i), cond);
}
}
if (!j)
bprintf ("&+w No Mortals On-Line\n");
bprintf ("&+w--------------------------------------------------------------------------------\n");
}
PUBLIC A_COMMAND(signalcom)
{ static char *SigTable[] =
{"list", "sigsegv", "sigterm", "sigbus",
"sigint", "sigusr1", "sigusr2", TABLE_END};
int sig = -1, x;
if (!ptstflg (mynum, PFL_SIGNAL))
{ erreval ();
return;
}
if (brkword () == -1)
{ bprintf ("Send what signal?\n");
return;
}
if ((x = tlookup (wordbuf, SigTable)) < 0)
{ bprintf ("Invalid signal.\n");
return;
}
switch (x) {
case 0:
sig = -1;
break;
case 1:
sig = SIGSEGV;
break;
case 2:
sig = SIGTERM;
break;
case 3:
sig = SIGBUS;
break;
case 4:
sig = SIGINT;
break;
case 5:
sig = SIGUSR1;
break;
case 6:
sig = SIGUSR2;
break;
}
if (sig == -1)
{ bprintf ("Signals: SIGSEGV, SIGTERM, SIGBUS, SIGINT, SIGUSR1, SIGUSR2.\n");
return;
}
send_msg (DEST_ALL, MODE_BRACKET, LVL_ARCHWIZARD, LVL_MAX, mynum, NOBODY,
"&+wSignal &*has been called: &+w%s",
SigTable[x]);
mudlog ("SIGNAL: %s has called signal %s", pname (mynum), SigTable[x]);
kill (getpid (), sig);
}
A_COMMAND(reboot_actions)
{ char fn[100];
FILE *fp;
if (plev(mynum) < LVL_DEMI)
{ bprintf("Maybe in another time and space.\n");
return;
}
sprintf(fn,"%s/actions",data_dir);
if ((fp = fopen(fn,"r")) == NULL)
{ bprintf("Unable to locate actions file, reload aborted.\n");
mudlog("FILE: Error opening actions file.\n");
return;
}
bprintf("Rebooting Action File..\n");
clear_all_ext();
boot_extern(fp,fn);
fclose(fp);
mudlog("SYSTEM: Actions reloaded by %s",pname(mynum));
send_msg(DEST_ALL,MODE_BRACKET|MODE_QUIET,LVL_ARCHWIZARD,LVL_MAX,mynum,NOBODY,
"Actions reloaded by %s",pname(mynum));
bprintf("Actions file has been reloaded.\n");
}