/* misc.c */
#include "copyright.h"
#include "config.h"
#include <stdio.h>
#include <sys/types.h>
#include <ctype.h>
#include <sys/time.h>
#ifdef STRING_H
#include <string.h>
#else
#include <strings.h>
#endif /* STRING_H */
#include "teeny.h"
#include "io.h"
#include "case.h"
char poll[36]; /* Poll for the @doing command */
/* The WHO list. Surprise. */
Iob *wholist = (Iob *) 0;
/* Time last time timers() was called. */
static struct timeval last;
/* Last time we did a dump */
static long lastdump;
/* The time that the mud went up. */
static long startingtimeofmud;
static void set_output_str();
static void log_create();
static void log_badconnect();
void
init_timers()
{
(void) gettimeofday(&last, (struct timezone *) 0);
lastdump = last.tv_sec;
startingtimeofmud = last.tv_sec;
}
/*
* This checks the current time and resets quotas if the current timeslice
* has elapsed, and does a dump if the current dump interval has elapsed.
*
*/
void
timers()
{
struct timeval now;
int delta;
Iob *curr;
(void) gettimeofday(&now, (struct timezone *) 0);
/* How many tenths of seconds have elapsed since last time */
delta = (now.tv_sec - last.tv_sec) * 10
+ (now.tv_usec - last.tv_usec) / 100000;
if (delta >= TIME_SLICE)
{
/* Update all the quotas */
curr = wholist;
if (curr != (Iob *) 0)
{
do
{
curr->quota = SLICE_QUOTA;
curr = curr->whofwd;
} while (curr != wholist);
}
last.tv_sec = now.tv_sec;
last.tv_usec = now.tv_usec;
}
if (now.tv_sec - lastdump > DUMP_INTERVAL)
{
lastdump = now.tv_sec;
/* Dump the DB */
dump_db();
}
}
/*
* The network code calls this with Iob's with pending goo to process.
* Process it.
*
*/
void
dispatch(bp)
Iob *bp;
{
char *buff, *cmd, *p;
int count;
int player;
int fullbuff;
int z;
bp->lastcmd = last.tv_sec;
if (bp->quota < 0)
{
bp->inputcnt = 0;
if (bp->typ == INPUT_NEWCONN)
{
iobflush(bp);
iobdrop(bp);
log_disconnect(bp);
}
return;
}
buff = bp->inputbuf;
count = bp->inputcnt;
/* Slide along, chopping it up into commands. */
fullbuff = (count == (MUDBUFSIZ - 1)); /* One for terminating \0 */
while (1)
{
cmd = buff;
while (*buff != '\n' && count > 0 && *buff != '\r')
{
buff++;
count--;
}
if (count <= 0 && !fullbuff)
break;
if ((bp->typ != INPUT_NEWCONN && !istemple(bp->player)) ||
bp->typ == INPUT_NEWCONN)
(bp->quota)--;
if (bp->quota < 0)
{ /* Fuck this guy */
(bp->blown)++;
buff = cmd; /* Fake an empty buffer */
break;
}
fullbuff = 0;
*buff++ = '\0';
count--;
/* change all non-printing characters to whitespace */
for (z = 0; cmd[z]; z++)
{
if (!isprint(cmd[z]))
cmd[z] = ' ';
}
/* strip leading and trailing whitespace */
for (z--; isspace(cmd[z]); z--);
cmd[z + 1] = '\0';
for (; isspace(cmd[0]); cmd++);
if (!cmd[0])
continue;
/* Check special commands. */
#ifdef WHO_CI
if (!strncasecmp(cmd, WHO_COMMAND, strlen(WHO_COMMAND)))
{
#else
if (!strncmp(cmd, WHO_COMMAND, strlen(WHO_COMMAND)))
{
#endif /* WHO_CI */
if ((bp->typ != INPUT_NEWCONN) && bp->outputprefix)
{
iobput(bp, bp->outputprefix);
iobput(bp, "\r\n");
}
do_wholist(bp, cmd + strlen(WHO_COMMAND));
if ((bp->typ != INPUT_NEWCONN) && bp->outputsuffix)
{
iobput(bp, bp->outputsuffix);
iobput(bp, "\r\n");
}
continue;
} else
if (!strncasecmp(cmd, "@doing", strlen("@doing")))
{
if ((bp->typ != INPUT_NEWCONN) && bp->outputprefix)
{
iobput(bp, bp->outputprefix);
iobput(bp, "\r\n");
}
do_doing(bp, cmd + strlen(FINGER_COMMAND));
if ((bp->typ != INPUT_NEWCONN) && bp->outputsuffix)
{
iobput(bp, bp->outputsuffix);
iobput(bp, "\r\n");
}
continue;
} else
#ifdef QUIT_CI
if (!strcasecmp(cmd, QUIT_COMMAND))
#else
if (!strcmp(cmd, QUIT_COMMAND))
#endif /* QUIT_CI */
{
if ((bp->typ != INPUT_NEWCONN) && bp->outputprefix)
{
iobput(bp, bp->outputprefix);
iobput(bp, "\r\n");
}
if (bp->typ != INPUT_NEWCONN)
iobput(bp, GOODBYE_MSG);
if ((bp->typ != INPUT_NEWCONN) && bp->outputsuffix)
{
iobput(bp, bp->outputsuffix);
iobput(bp, "\r\n");
}
iobflush(bp);
iobdrop(bp);
log_disconnect(bp);
if (bp->typ != INPUT_NEWCONN)
{
disconnect_player(bp->player);
autotoadcheck(bp->player);
}
continue;
} else
if (!strncmp(cmd, PREFIX_COMMAND, strlen(PREFIX_COMMAND)))
{
#ifndef RESTRICT_BOT
set_output_str(bp, cmd + strlen(PREFIX_COMMAND),
PREFIX_CODE);
#else /* RESTRICT_BOT */
if (!istemple(bp->player))
{
iobput(bp, RESTRICT_BOT_MSG);
} else
{
set_output_str(bp, cmd + strlen(PREFIX_COMMAND),
PREFIX_CODE);
}
#endif /* RESTRICT_BOT */
continue;
} else
if (!strncmp(cmd, SUFFIX_COMMAND, strlen(SUFFIX_COMMAND)))
{
#ifndef RESTRICT_BOT
set_output_str(bp, cmd + strlen(SUFFIX_COMMAND),
SUFFIX_CODE);
#else /* RESTRICT_BOT */
if (!istemple(bp->player))
{
iobput(bp, RESTRICT_BOT_MSG);
} else
{
set_output_str(bp, cmd + strlen(SUFFIX_COMMAND),
SUFFIX_CODE);
}
#endif /* RESTRICT_BOT */
continue;
}
switch (bp->typ)
{
case INPUT_NEWCONN:
/* We grok two commands, create and connect. */
for (p = cmd; !isspace(*p) && *p; p++);
if (*p == '\0')
{
greet(bp);
break;
}
*p++ = '\0';
if (stringprefix(cmd, "connect"))
{
player = connect_player(p);
if (player == -1)
{
iobput(bp, BAD_CONNECT);
log_badconnect(p, bp);
} else
{
bp->typ = INPUT_PLAY;
bp->player = player;
if (set_int_elt(player, SITE, bp->site) == -1)
{
iobput(bp, "Couldn't set SITE, something horrid has truly happened.\r\n");
warning("dispatch", "could not set SITE elt");
}
log_connect(bp);
iob_spit_file(bp, MOTD_FILE);
if (iswiz(player))
iob_spit_file(bp, WIZN_FILE);
#ifdef RESTRICT_BOT
if (!istemple(player) &&
(bp->outputprefix || bp->outputsuffix))
{
iobput(bp, "Your OUTPUTPREFIX and OUTPUTSUFFIX strings have been cleared.\r\n");
if (bp->outputprefix)
{
ty_free(bp->outputprefix);
bp->outputprefix = (char *) 0;
}
if (bp->outputsuffix)
{
ty_free(bp->outputsuffix);
bp->outputsuffix = (char *) 0;
}
}
#endif /* RESTRICT_BOT */
do_look(player, (char *) 0);
newwho(bp);
}
} else
if (stringprefix(cmd, "create"))
{
#ifndef REGISTRATION
#ifdef SITE_REGISTRATION
if (check_lockout_list('R',bp->site))
{
if (iob_spit_file(bp, SITELOCKOUT_FILE) == -1)
{
iobput(bp, SITE_REGISTER_MSG);
}
iobflush(bp);
iobdrop(bp);
log_disconnect(bp);
} else
{
#endif /* SITE_REGISTRATION */
player = create_player(p, -1);
if (player == -1)
{
iobput(bp, BAD_CREATE);
} else
{
bp->typ = INPUT_PLAY;
bp->player = player;
if (set_int_elt(player, SITE, bp->site) == -1)
{
iobput(bp, "Couldn't set SITE, something horrid has truly happened.\r\n");
warning("dispatch", "could not set SITE elt");
}
log_create(bp);
iob_spit_file(bp, MOTD_FILE);
#ifdef RESTRICT_BOT
if (!istemple(player) &&
(bp->outputprefix || bp->outputsuffix))
{
iobput(bp, "Your OUTPUTPREFIX and OUTPUTSUFFIX strings have been cleared.\r\n");
if (bp->outputprefix)
{
ty_free(bp->outputprefix);
bp->outputprefix = (char *) 0;
}
if (bp->outputsuffix)
{
ty_free(bp->outputsuffix);
bp->outputsuffix = (char *) 0;
}
}
#endif /* RESTRICT_BOT */
do_look(player, (char *) 0);
newwho(bp);
}
#ifdef SITE_REGISTRATION
}
#endif /* SITE_REGISTRATION */
#else /* REGISTRATION */
if (iob_spit_file(bp, REGISTER_FILE) == -1)
{
iobput(bp, REGISTER_MSG);
}
#endif /* REGISTRATION */
} else
{
/* Re-greet this idiot. */
greet(bp);
}
break;
case INPUT_PLAY:
if (bp->outputprefix)
{
iobput(bp, bp->outputprefix);
iobput(bp, "\r\n");
}
handle_cmd(bp->player, cmd);
if (bp->outputsuffix)
{
iobput(bp, bp->outputsuffix);
iobput(bp, "\r\n");
}
break;
}
}
/* OK We banged into the end of the buffer. */
if (cmd != buff)
{ /* Is there anything left in the buffer? */
bp->inputcnt = buff - cmd;
bcopy(cmd, bp->inputbuf, bp->inputcnt);
} else
{
bp->inputcnt = 0;
}
}
static void
set_output_str(bp, string, code)
Iob *bp;
char *string;
int code;
{
while (*string && isspace(*string) && isascii(*string))
string++;
if (code == PREFIX_CODE)
{
if (!string || !*string)
{
ty_free(bp->outputprefix);
bp->outputprefix = 0;
} else
{
ty_free(bp->outputprefix);
bp->outputprefix = (char *) ty_malloc(strlen(string) + 1, "set_output_str");
if (bp->outputprefix)
strcpy(bp->outputprefix, string);
}
}
if (code == SUFFIX_CODE)
{
if (!string || !*string)
{
ty_free(bp->outputsuffix);
bp->outputsuffix = 0;
} else
{
ty_free(bp->outputsuffix);
bp->outputsuffix = (char *) ty_malloc(strlen(string) + 1, "set_output_str");
if (bp->outputsuffix)
strcpy(bp->outputsuffix, string);
}
}
}
void
newwho(bp)
Iob *bp;
{
if (wholist == (Iob *) 0)
{
wholist = bp->whofwd = bp->whoback = bp;
} else
{
bp->whoback = wholist;
bp->whofwd = wholist->whofwd;
(wholist->whofwd)->whoback = bp;
wholist->whofwd = bp;
}
}
void
dropwho(bp)
Iob *bp;
{
if (bp->whofwd == bp)
{
wholist = (Iob *) 0;
} else
{
if (wholist == bp)
{
wholist = bp->whoback;
}
(bp->whoback)->whofwd = bp->whofwd;
(bp->whofwd)->whoback = bp->whoback;
}
}
void
greet(bp)
Iob *bp;
{
if (iob_spit_file(bp, GREET_FILE) == -1)
{
iobput(bp, DEFAULT_GREET);
}
}
int
iob_spit_file(bp, filename)
Iob *bp;
char *filename;
{
FILE *in;
char filebuff[130];
int i;
if ((in = fopen(filename, "r")) == NULL)
{
return (-1);
}
while (fgets(filebuff, 128, in) != NULL)
{
/* Replace the \n\0 with a \r\n\0, if present. */
i = strlen(filebuff);
if(filebuff[i-1] == '\n')
{
filebuff[i-1] = '\r';
filebuff[i] = '\n';
filebuff[i+1] = '\0';
}
iobput(bp, filebuff);
}
(void) fclose(in);
return (1);
}
/*
* Matches against the list of active players.
*
* returns -1 if no match, -2 if ambiguous, or the object number.
*
* This lives here, 'cause it needs to screw around with the network's notion of
* the who list.
*
*/
int
match_who(name)
char *name;
{
Iob *curr;
char *player_name, *p;
int matched;
matched = -1;
curr = wholist;
do
{
if (get_str_elt(curr->player, NAME, &player_name) == -1)
{
warning("match_who", "bad name reference on WHO list");
return (-1);
}
if (player_name == (char *) 0)
{
warning("match_who", "active player with NULL name");
curr = curr->whofwd;
continue;
}
for (p = name; DOWNCASE(*p) == DOWNCASE(*player_name) && *p && !isspace(*player_name) && *player_name; p++)
player_name++;
if (isspace(*player_name))
{
return (curr->player);
}
curr = curr->whofwd;
} while (curr != wholist);
return (matched);
}
/*
* Display the WHO list to a bp.
*/
void
do_wholist(bp, arg)
Iob *bp;
char *arg;
{
Iob *who;
char *whonm, *p, idletype;
char work2[82];
char work3[14];
char line[82];
int g, h, i, j, k, total = 0;
int where, wizard = 0;
#ifdef REVERSED_WHO
Iob *first;
#endif /* REVERSED_WHO */
if(arg != NULL)
while (arg[0] == ' ')
arg++;
if ((bp->typ != INPUT_NEWCONN) && iswiz(bp->player))
wizard = 1;
iobput(bp, "Player Name On For Idle ");
iobput(bp, poll);
iobput(bp, "\r\n");
if ((who = wholist) == (Iob *) 0)
{
iobput(bp, "No users are connected. ");
goto uptime;
}
#ifdef REVERSED_WHO
first = who = who->whofwd;
#endif /* REVERSED_WHO */
do
{
total++;
p = work2;
if (get_str_elt(who->player, NAME, &whonm) != -1)
{
while (*whonm && !isspace(*whonm))
*p++ = *whonm++;
*p = '\0';
} else
(void) strcpy(work2, "???");
if ((arg != NULL) && !stringprefix(arg, work2))
goto skipthisline;
if (wizard)
{
sprintf(work3, "(#%d)", who->player);
strcat(work2, work3);
}
g = (int) (last.tv_sec - who->connect);
h = g / 86400;
g %= 86400;
i = g / 3600;
j = g / 60 % 60;
k = (int) (last.tv_sec - who->lastcmd);
idletype = 's';
if (k > 59)
{
idletype = 'm';
k /= 60;
if (k > 59)
{
idletype = 'h';
k /= 60;
if (k > 23)
{
idletype = 'd';
k /= 24;
}
}
}
if (h)
sprintf(line,
"%-19s %dd %02d:%02d %2d%c ", work2, h, i, j, k,
idletype);
else
sprintf(line,
"%-22s %02d:%02d %2d%c ", work2, i, j, k, idletype);
strcat(line, who->doing);
strcat(line, "\r\n");
iobput(bp, line);
skipthisline:
#ifdef REVERSED_WHO
who = who->whofwd;
} while (who != first);
#else /* REVERSED_WHO */
who = who->whoback;
} while (who != wholist);
#endif /* REVERSED_WHO */
sprintf(line, "%d user%s %s connected. ", total,
(total == 1) ? "" : "s", (total == 1) ? "is" : "are");
iobput(bp, line);
uptime:
h = last.tv_sec - startingtimeofmud;
j = h / 3600 % 24;
k = h / 60 % 60;
i = h / 86400;
sprintf(work3,"%dd, ",i);
sprintf(line, "Uptime: %s%02d:%02d. %s\r\n", i ? work3 : "", j, k,
total < 3 ? "Kinda lonely here." : total < 4 ? "Have a fish." :
total < 5 ? "Who is John Galt?" : total < 6 ? "Yay." :
total < 7 ? "TinySex is Not Allowed." :
total < 8 ? "Let's have a party!" :
total < 12 ? "Want a cookie?" : total < 16 ? "Reminder: AIX sux" :
total < 20 ? "Thanks, it was delicious." :
total < 25 ? "Space Madness down, or what?" :
total < 33 ? "(EVIL!)Mud rocks, d00d!" : "fuckin'-A! A new record.");
iobput(bp, line);
}
void
do_doing(bp, arg)
Iob *bp;
char *arg;
{
int len;
if(arg == NULL)
{
iobput(bp, "Set. Have fun doing it.\r\n");
strcpy(bp->doing,"");
return;
}
while(arg[0] == ' ')
arg++;
len = strlen(arg);
if(len > 35)
{
arg[35] = '\0';
iobput(bp, "Too long -- Clipped.\r\n");
} else
{
iobput(bp, "Set. Have fun doing it.\r\n");
}
strcpy(bp->doing,arg);
} /* do_doing */
void
log_disconnect(bp)
Iob *bp;
{
char *name, *p, ch;
if (bp->typ != INPUT_NEWCONN)
{
if (get_str_elt(bp->player, NAME, &name) != -1)
{
for (p = name; p && *p && *p != ' '; p++);
ch = *p;
*p = '\0';
log_status("DISCONNECT: %s(#%d) on fd %d.\n", name, bp->player, bp->fd);
*p = ch;
} else
log_status("DISCONNECT: ???(#%d) on fd %d.\n", bp->player, bp->fd);
} else
log_status("DISCONNECT: fd %d never connected.\n", bp->fd);
}
void
log_connect(bp)
Iob *bp;
{
char *name, *p, ch;
if (bp->typ != INPUT_NEWCONN)
{
if (get_str_elt(bp->player, NAME, &name) != -1)
{
for (p = name; p && *p && *p != ' '; p++);
ch = *p;
*p = '\0';
log_status("CONNECTED: %s(#%d) on fd %d.\n", name, bp->player, bp->fd);
*p = ch;
} else
log_status("CONNECTED: ???(#%d) on fd %d.\n", bp->player, bp->fd);
} else
log_status("CONNECTION: fd %d connected from [%s].\n",
bp->fd, bp->hostname);
}
static void
log_create(bp)
Iob *bp;
{
char *name, *p, ch;
if (get_str_elt(bp->player, NAME, &name) != -1)
{
for (p = name; *p && p && *p != ' '; p++);
ch = *p;
*p = '\0';
log_status("CREATED: %s(#%d) on fd %d.\n", name, bp->player, bp->fd);
*p = ch;
} else
log_status("CREATED: ???(#%d) on fd %d.\n", bp->player, bp->fd);
}
static void
log_badconnect(s, bp)
char *s;
Iob *bp;
{
char buf[65];
char *p, *q;
for (p = s, q = buf; p && *p && *p != ' ' && (q - buf) < 64; *q++ = *p++);
*q = '\0';
log_status("FAILED CONNECT: fd %d failed connection to \"%s\".\n",
bp->fd, buf);
}
int
match_active_player(arg)
char *arg;
{
Iob *who;
Iob *first;
int number = 0;
int player;
char *name, work[40], *p;
who = wholist;
first = who = who->whofwd;
do
{
p = work;
if (get_str_elt(who->player, NAME, &name) != -1)
{
while (*name && !isspace(*name))
*p++ = *name++;
*p = '\0';
} else
{
warning("match_active_player", "bad player name");
return(-1);
}
if ((arg != NULL) && stringprefix(arg, work))
{
if (strlen(arg) == strlen(work))
return (who->player);
number++;
if(number == 1)
{
player = who->player;
} else
{
if (who->player != player)
return (-2);
else
number = 1;
}
}
who = who->whofwd;
} while (who != first);
if (number)
return (player);
else
return (-1);
}
void
do_finger(player, arg)
int player;
char *arg;
{
Iob *who;
char *whonm, *p, idletype;
char work2[82];
char work3[14];
char line[82];
int where, wizard = 0;
#ifdef REVERSED_WHO
Iob *first;
#endif /* REVERSED_WHO */
if(arg != NULL)
while (arg[0] == ' ')
arg++;
#ifdef WIZWHOALL
wizard = 1;
#else /* WIZWHOALL */
if (iswiz(player))
wizard = 1;
#endif /* WIZWHOALL */
notify_player(player, "Player Name Location ");
notify_player(player, wizard ? "Site\r\n" : "\r\n");
if ((who = wholist) == (Iob *) 0)
{
notify_player(player, "No users are connected.\r\n");
return;
}
#ifdef REVERSED_WHO
first = who = who->whofwd;
#endif /* REVERSED_WHO */
do
{
p = work2;
if (get_str_elt(who->player, NAME, &whonm) != -1)
{
while (*whonm && !isspace(*whonm))
*p++ = *whonm++;
*p = '\0';
} else
(void) strcpy(work2, "???");
if ((arg != NULL) && !stringprefix(arg, work2))
goto skipthisline2;
if (wizard)
{
sprintf(work3, "(#%d)", who->player);
strcat(work2, work3);
}
if (wizard)
{
if (get_int_elt(who->player, LOC, &where) == -1)
where = -1;
if(iswiz(player) || isjumpok(where))
sprintf(line, "%-19s (#%d)", work2, where);
else
sprintf(line, "%-19s private", work2);
sprintf(work2, "%-30s %-30s", line, who->hostname);
}
strcat(work2, "\r\n");
notify_player(player, work2);
skipthisline2:
#ifdef REVERSED_WHO
who = who->whofwd;
} while (who != first);
#else /* REVERSED_WHO */
who = who->whoback;
} while (who != wholist);
#endif /* REVERSED_WHO */
}
int check_lockout_list(type,site)
char type;
long site;
{
FILE *file;
int a,b,c,d;
long lockedsite;
char locktype;
int lockedout = FALSE;
char buf[200];
char *p;
if ((file = fopen(LOCKOUT_FILE, "r")) == NULL)
{
warning ("check_lockout_list", "LOCKOUT_FILE does not exist");
return (lockedout);
}
while (!lockedout && fgets(buf, 200, file) != NULL)
{
a = b = c = d = 0;
p = buf;
while (*p && *p != '#') p++;
*p = '\0';
p = buf;
locktype = toupper(*p); /* We currently use 'L' and 'R' */
p+=2;
a = atoi(p);
while (*p != '.') p++;
p++;
b = atoi(p);
while (*p != '.') p++;
p++;
c = atoi(p);
while (*p != '.') p++;
p++;
d = atoi(p);
lockedsite = ((a & 0xff) << 24) + ((b & 0xff) << 16)
+ ((c & 0xff) << 8) + (d & 0xff);
if (lockedsite == site && locktype == type) lockedout = TRUE;
}
fclose(file);
return (lockedout);
}