/*
* Playground+ - parse.c
* Command parsing code, timer code and more
* ---------------------------------------------------------------------------
*/
#include <ctype.h>
#include <sys/time.h>
#include <signal.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <string.h>
#include <memory.h>
#ifndef BSDISH
#include <malloc.h>
#endif
#include <stdlib.h>
#include <stdio.h>
#include "include/config.h"
#include "include/player.h"
#include "include/fix.h"
#include "include/clist.h"
#include "include/proto.h"
/* varibles */
struct command *last_com;
char *stack_check;
int nsync = 0, synct = 0, sync_counter = 0, note_sync = NOTE_SYNC_TIME;
int account_wobble = 1;
int performance_timer = 0;
struct command *help_list = 0;
file help_file =
{0, 0};
int shutdown_count = -1;
int comm_match = 0;
int news_sync = NEWS_SYNC_INTERVAL;
int reload_count = 5;
int backup_hour;
/* interns */
void spam_warning(player *);
void show_clock(player *);
extern char *sys_time_prompt(int diff);
/* returns the first char of the input buffer */
char *first_char(player * p)
{
char *scan;
scan = p->ibuffer;
while (*scan && isspace(*scan))
scan++;
return scan;
}
/* what happens if bad stack detected */
void bad_stack(void)
{
int missing;
missing = (int) stack - (int) stack_check;
if (last_com)
sprintf(stack_check, "Bad stack in function %s, missing %d bytes",
last_com->text, missing);
else
sprintf(stack_check, "Bad stack somewhere, missing %d bytes", missing);
stack = end_string(stack_check);
log("stack", stack_check);
stack = stack_check;
}
/* flag changing routines */
/* returns the value of a flag from the flag list */
int get_flag(flag_list * list, char *str)
{
for (; list->text; list++)
if (!strcmp(list->text, str))
return list->change;
return 0;
}
int get_case_flag(flag_list * list, char *str)
{
for (; list->text; list++)
if (!strcasecmp(list->text, str))
return list->change;
return 0;
}
char *get_flag_name(flag_list * list, char *str)
{
for (; list->text; list++)
if (!strcasecmp(list->text, str))
return list->text;
return 0;
}
/* routine to get the next part of an arg */
char *next_space(char *str)
{
while (*str && *str != ' ')
str++;
if (*str == ' ')
{
while (*str == ' ')
str++;
str--;
}
return str;
}
/* view command lists */
int command_prescan(player * p, char *str)
{
char *oldstack = stack;
if (!*str || !strcasecmp(str, "?") || !strcasecmp(str, "help"))
{
oldstack = stack;
sprintf(stack, " Format: commands [a-z|all|comm|move|desc|info]\n"
" [item|sys|");
stack = strchr(stack, 0);
if (social_index >= 0)
stack += sprintf(stack, "soc|");
stack = strchr(stack, 0);
if (p->residency & LIST)
{
strcpy(stack, "list|");
stack = strchr(stack, 0);
}
if (p->residency & BUILD)
{
strcpy(stack, "room|");
stack = strchr(stack, 0);
}
if (p->residency & (PSU | SU))
{
strcpy(stack, "su|");
stack = strchr(stack, 0);
}
if (p->residency & (ADC | LOWER_ADMIN | ADMIN))
{
strcpy(stack, "ad|");
stack = strchr(stack, 0);
}
strcpy(stack, "misc]\n");
stack = end_string(stack);
tell_player(p, oldstack);
stack = oldstack;
return -1;
}
/* ok check for what area was inputted, and return appropriate value. */
if (!strcasecmp(str, "all"))
return 0; /* do all commands =) */
if (!strcasecmp(str, "comm") || !strcasecmp(str, "talk"))
return COMMc;
if (p->residency & LIST && (!strcasecmp(str, "list")))
return LISTc;
if (p->residency & BUILD && (!strcasecmp(str, "room")))
return ROOMc;
if (!strcasecmp(str, "go") || !strcasecmp(str, "move"))
return MOVEc;
if (!strcasecmp(str, "item"))
return ITEMc;
if (!strcasecmp(str, "info"))
return INFOc;
if (!strcasecmp(str, "sys") || !strcasecmp(str, "toggles"))
return SYSc;
if (!strcasecmp(str, "desc") || !strcasecmp(str, "personalize") || !strcasecmp(str, "personalise"))
return DESCc;
if ((!strcasecmp(str, "soc") || !strcasecmp(str, "social")) &&
social_index >= 0)
return SOCIALc;
if (!strcasecmp(str, "misc"))
return MISCc;
if (p->residency & PSU &&
(!strcasecmp(str, "su") || !strcasecmp(str, "super")))
return SUPERc;
if (p->residency & (LOWER_ADMIN | ADMIN | ADC) &&
(!strcasecmp(str, "ad") || !strcasecmp(str, "admin")))
return ADMINc;
if (config_flags & cfNOSPAM)
{
if (p->residency & (LOWER_ADMIN | ADMIN | ADC) &&
(!strcasecmp(str, "spam")))
return SPAMc;
}
return THE_EVIL_Q; /* a stupid return yes */
}
void view_commands(player * p, char *str)
{
struct command *comlist;
char *oldstack, middle[80];
char *plyr;
int s;
int noc = 0, len = 0, l;
int choice;
player *p2 = 0;
plyr = next_space(str);
*plyr++ = 0;
if (*plyr && p->residency & ADMIN)
{
p2 = find_player_absolute_quiet(plyr);
if (!p2)
{
tell_player(p, " That player is not logged in right now ...\n");
return;
}
}
if (strlen(str) == 1) /* all commands beginning with ... */
{
lower_case(str);
if (!isalpha(*str))
{
(void) command_prescan(p, "help");
return;
}
l = *str - 'a';
if (l < 0 || l > 25)
{
(void) command_prescan(p, "help");
return;
}
l++;
oldstack = stack;
sprintf(middle, "Commands beginning with '%c'", toupper(*str));
pstack_mid(middle);
sprintf(stack, "\n ");
stack = strchr(stack, 0);
for (comlist = coms[l]; comlist->text; comlist++)
{
if ((!comlist->level || (p->residency & comlist->level)) &&
(!comlist->andlevel || (p->residency & comlist->andlevel)) && !(comlist->section & INVISc))
{
if (len + strlen(comlist->text) > 70)
{
sprintf(stack, "\n ");
stack = strchr(stack, 0);
len = 2;
}
sprintf(stack, "%s ", comlist->text);
stack = strchr(stack, 0);
len += (strlen(comlist->text) + 1); /* +1 for the space */
noc++;
}
}
sprintf(stack, "\n\n");
stack = strchr(stack, 0);
sprintf(middle, "There are %d commands available to you", noc);
pstack_mid(middle);
*stack++ = 0;
pager(p, oldstack);
stack = oldstack;
return;
}
choice = command_prescan(p, str);
oldstack = stack;
switch (choice)
{
case -1:
return;
break;
case THE_EVIL_Q:
tell_player(p, " That area not found. Type commands ? to list valid areas.\n");
return;
break;
case 0:
pstack_mid("Complete set of commands");
break;
case LISTc:
pstack_mid("List commands");
break;
case COMMc:
pstack_mid("Communication commands");
break;
case ROOMc:
pstack_mid("Room commands");
break;
case MOVEc:
pstack_mid("Movement commands");
break;
case ITEMc:
pstack_mid("Item commands");
break;
case INFOc:
pstack_mid("Info commands");
break;
case SYSc:
pstack_mid("System toggle commands");
break;
case DESCc:
pstack_mid("Personalisation commands");
break;
case SOCIALc:
pstack_mid("Social commands");
break;
case MISCc:
pstack_mid("Misc commands");
break;
case SUPERc:
sprintf(middle, "%s commands", get_config_msg("staff_name"));
pstack_mid(middle);
break;
case ADMINc:
sprintf(middle, "%s commands", get_config_msg("admin_name"));
pstack_mid(middle);
break;
case SPAMc: /* leave un cased, i mean how do we get HERE if its not on? */
pstack_mid("Commands which trigger spam code");
break;
}
if (*plyr && p->residency & ADMIN)
ADDSTACK("\n [for %s]\n\n", p2->name);
else
{
ADDSTACK("\n");
p2 = p;
}
ADDSTACK(" ");
for (s = 0; s < 27; s++)
{
for (comlist = coms[s]; comlist->text; comlist++)
{
if ((!comlist->level || ((p2->residency) & comlist->level)) &&
(!comlist->andlevel || ((p2->residency) & comlist->andlevel))
&& ((!choice || comlist->section & choice) && !(comlist->section & INVISc)))
{
if (len + strlen(comlist->text) > 70)
{
ADDSTACK("\n ");
stack = strchr(stack, 0);
len = 2;
}
ADDSTACK("%s ", comlist->text);
len += (strlen(comlist->text) + 1); /* +1 for the space */
noc++;
}
}
}
if (choice == SOCIALc)
noc += list_socials(p);
ADDSTACK("\n\n");
if (*plyr && p->residency & ADMIN)
sprintf(middle, "There are %d commands listed here available to %s", noc, p2->name);
else
sprintf(middle, "There are %d commands listed here available to you", noc);
pstack_mid(middle);
*stack++ = 0;
pager(p, oldstack);
stack = oldstack;
}
void view_sub_commands(player * p, struct command *comlist)
{
char *oldstack, middle[80];
int noc = 0, len = 0;
oldstack = stack;
pstack_mid("Available sub commands");
sprintf(stack, "\n");
stack = strchr(stack, 0);
for (; comlist->text; comlist++)
if (((!comlist->level) || ((p->residency) & (comlist->level))) &&
((!comlist->andlevel) || ((p->residency) & (comlist->andlevel))))
{
sprintf(stack, "%s ", comlist->text);
stack = strchr(stack, 0);
len += strlen(comlist->text);
len++;
if (len > 60)
{
sprintf(stack, "\n ");
len = 0;
}
noc++;
}
ADDSTACK("\n\n");
sprintf(middle, "There are %d commands listed here", noc);
pstack_mid(middle);
*stack++ = 0;
tell_player(p, oldstack);
stack = oldstack;
}
/* initialise the hash array */
void init_parser()
{
int i;
struct command *scan;
scan = complete_list;
for (i = 0; i < 27; i++)
{
coms[i] = scan;
while (scan->text)
scan++;
scan++;
}
}
/* see if any commands fit the bill */
#ifndef COM_MATCH
char *do_match(char *str, struct command *com_entry)
{
char *t;
for (t = com_entry->text; *t; t++, str++)
if (tolower(*str) != *t)
return 0;
if ((com_entry->space) && (*str) && (!isspace(*str)))
return 0;
while (*str && isspace(*str))
str++;
return str;
}
#else
char *do_match_old(char *str, struct command *com_entry)
{
char *t;
for (t = com_entry->text; *t; t++, str++)
if (tolower(*str) != *t)
return 0;
if ((com_entry->space) && (*str) && (!isspace(*str)))
return 0;
while (*str && isspace(*str))
str++;
return str;
}
char *do_match(char *str, struct command *com_entry)
{
char *scan;
for (scan = com_entry->text; *scan && *str && !isspace(*str); scan++, str++)
if (tolower(*str) != *scan)
return 0;
if ((com_entry->space) && (*str) && (!isspace(*str)))
return 0;
if (*scan)
{
if (com_entry->section & (NOMATCHc | INVISc))
return 0;
com_entry->section |= TAGGEDc;
comm_match++;
return 0;
}
/* while we are on spaces */
while (*str && isspace(*str))
str++;
return str;
}
#endif
void clear_comlist_tags(struct command *comlist)
{
if (!comm_match)
return;
while (comlist->text)
{
comlist->section &= ~TAGGEDc;
comlist++;
}
comm_match = 0;
}
void execute_command(player * p, struct command *com, char *str)
{
void (*fn) (player *, char *);
if (str[strlen(str) - 1] != '^')
{
last_com = com;
stack_check = stack;
sys_flags &= ~(FAILED_COMMAND | PIPE | ROOM_TAG | FRIEND_TAG | OFRIEND_TAG | EVERYONE_TAG);
command_type &= ~ROOM;
fn = com->function;
(*fn) (p, str);
if (stack != stack_check)
bad_stack();
}
else
TELLPLAYER(p, " '%s' command cancelled.\n", p->command_used->text);
sys_flags &= ~(FAILED_COMMAND | PIPE | ROOM_TAG | FRIEND_TAG | OFRIEND_TAG | EVERYONE_TAG);
command_type = 0;
}
/* execute a function from a sub command list */
void sub_command(player * p, char *str, struct command *comlist)
{
struct command *comliststart;
char *oldstack = stack, *rol, *space;
/* Lowercase string here, line in case the person was rm_capped */
if (p->system_flags & DECAPPED)
lower_case(str);
comliststart = comlist;
while (comlist->text)
{
if (((!comlist->level) || ((p->residency) & (comlist->level))) &&
((!comlist->andlevel) || ((p->residency) & (comlist->andlevel))))
{
rol = do_match(str, comlist);
if (rol)
{
execute_command(p, comlist, rol);
clear_comlist_tags(comliststart);
return;
}
}
comlist++;
}
if (comm_match)
{
if (comm_match == 1) /* single match */
{
for (comlist = comliststart; comlist->text && !(comlist->section & TAGGEDc); comlist++)
;
for (space = comlist->text, rol = str; *space && *rol && !isspace(*rol); rol++)
;
while (*rol && isspace(*rol))
rol++;
comlist->section &= ~TAGGEDc;
comm_match = 0;
execute_command(p, comlist, rol);
}
else
{
strcpy(oldstack, " Multiple sub command matches: ");
stack = strchr(stack, 0);
for (comlist = comliststart; comlist->text; comlist++)
if (comlist->section & TAGGEDc)
{
comlist->section &= ~TAGGEDc;
sprintf(stack, "%s ", comlist->text);
stack = strchr(stack, 0);
}
stack--;
strcpy(stack, ".\n");
stack = end_string(stack);
tell_player(p, oldstack);
stack = oldstack;
comm_match = 0;
}
return;
}
rol = str;
while (*rol && !isspace(*rol))
rol++;
*rol = 0;
if (p->location == prison)
sprintf(oldstack, " They don't let you do that kinda thing down here.\n");
else
#ifndef COM_MATCH
sprintf(oldstack, " Cannot find sub command '%s'\n", str);
#else
sprintf(oldstack, " Cannot match sub command '%s'\n", str);
#endif
stack = end_string(oldstack);
tell_player(p, oldstack);
stack = oldstack;
}
/* match commands to the main command lists */
void old_match_commands(player * p, char *str)
{
struct command *comlist, *comliststart;
char *rol, *oldstack, *space;
oldstack = stack;
while (*str && *str == ' ')
str++;
space = strchr(str, 0);
space--;
while (*space == ' ')
*space-- = 0;
if (!*str)
return;
/* Lowercase string here, line in case the person was rm_capped */
if (p->system_flags & DECAPPED)
lower_case(str);
if (isalpha(*str))
comlist = coms[((int) (tolower(*str)) - (int) 'a' + 1)];
else
comlist = coms[0];
comliststart = comlist;
while (comlist->text)
{
if (((!comlist->level) || ((p->residency) & (comlist->level))) &&
((!comlist->andlevel) || ((p->residency) & (comlist->andlevel))))
{
rol = do_match(str, comlist);
if (rol)
{
#ifdef COMMAND_STATS
if (!(comlist->section & (SUPERc | ADMINc)))
#ifdef ROBOTS
if (!(comlist->section & (SUPERc | ADMINc)) && !(p->residency & ROBOT_PRIV))
#endif /* robots */
commandUsed(comlist->text);
#endif /* command_stats */
if (config_flags & cfNOSPAM)
if (comlist->section & SPAMc)
{
if (last_com == comlist)
p->antispam += atoi(get_config_msg("spam_repeat"));
else
p->antispam += atoi(get_config_msg("spam_different"));
}
p->command_used = comlist;
if (!strncasecmp(rol, "/?", 2) || !strncasecmp(rol, "-h", 2))
help(p, p->command_used->text);
else if (config_flags & cfNOSWEAR)
{
if ((comlist->section & F_SWEARc) ||
((comlist->section & M_SWEARc) &&
(!strcmp(p->location->owner->lower_name, SYS_ROOM_OWNER) ||
!strcmp(p->location->owner->lower_name, "intercom"))))
execute_command(p, comlist, filter_rude_words(rol));
else
execute_command(p, comlist, rol);
}
else
execute_command(p, comlist, rol);
clear_comlist_tags(comliststart);
return;
}
}
comlist++;
}
/* check for taggings */
if (comm_match)
{
if (comm_match == 1)
{
for (comlist = comliststart; comlist->text && !(comlist->section & TAGGEDc); comlist++)
;
for (space = comlist->text, rol = str; *space && *rol && !isspace(*rol); rol++)
;
while (*rol && isspace(*rol))
rol++;
comlist->section &= ~TAGGEDc;
comm_match = 0;
#ifdef COMMAND_STATS
if (!(comlist->section & (SUPERc | ADMINc)))
#ifdef ROBOTS
if (!(comlist->section & (SUPERc | ADMINc)) && !(p->residency & ROBOT_PRIV))
#endif /* robots */
commandUsed(comlist->text);
#endif /* command_stats */
if (config_flags & cfNOSPAM)
if (comlist->section & SPAMc)
{
if (last_com == comlist)
p->antispam += atoi(get_config_msg("spam_repeat"));
else
p->antispam += atoi(get_config_msg("spam_different"));
}
p->command_used = comlist;
if (!strncasecmp(rol, "/?", 2) || !strncasecmp(rol, "-h", 2))
help(p, p->command_used->text);
else
execute_command(p, comlist, rol);
}
else
{
strcpy(oldstack, " Multiple command matches: ");
stack = strchr(stack, 0);
for (comlist = comliststart; comlist->text; comlist++)
if (comlist->section & TAGGEDc)
{
comlist->section &= ~TAGGEDc;
sprintf(stack, "%s ", comlist->text);
stack = strchr(stack, 0);
}
stack--;
strcpy(stack, ".\n");
stack = end_string(stack);
tell_player(p, oldstack);
stack = oldstack;
comm_match = 0;
}
return;
}
rol = str;
while (*rol && !isspace(*rol))
rol++;
*rol = 0;
#ifndef COM_MATCH
sprintf(oldstack, " Cannot find command '%s'\n", str);
#else
sprintf(oldstack, " Cannot match command '%s'\n", str);
#endif
stack = end_string(oldstack);
tell_player(p, oldstack);
stack = oldstack;
}
void match_commands(player * p, char *str)
{
char *rol, holder[1000];
alias *al;
if (!(p->saved))
{
old_match_commands(p, str);
return;
}
/* lets try an alias match first */
rol = do_alias_match(p, str);
if (strcmp(rol, "\n"))
{
al = get_alias(p, str);
if (!al)
{
tell_player(p, " Alias matching error\n");
return;
}
/* NEED TO LOOP THROUGH HERE */
strcpy(holder, splice_argument(p, al->sub, rol, 0));
while (holder[0])
{
if (p->system_flags & DECAPPED)
lower_case(holder);
old_match_commands(p, holder);
strcpy(holder, splice_argument(p, al->sub, rol, 1));
}
}
else
old_match_commands(p, str);
}
/* handle input from one player */
void input_for_one(player * p)
{
char *pick;
masks_reset();
this_rand = (player *) NULL; /* dynatext random player reset */
if (p->input_to_fn)
{
p->idle = 0;
p->idle_index = 0;
p->idle_msg[0] = 0;
last_com = &input_to;
stack_check = stack;
sys_flags &= ~(FAILED_COMMAND | PIPE | ROOM_TAG | FRIEND_TAG | OFRIEND_TAG | EVERYONE_TAG);
command_type &= ~ROOM;
(*p->input_to_fn) (p, p->ibuffer);
if (stack != stack_check)
bad_stack();
sys_flags &= ~(FAILED_COMMAND | PIPE | ROOM_TAG | FRIEND_TAG | OFRIEND_TAG | EVERYONE_TAG);
command_type = 0;
return;
}
if (!p->ibuffer[0])
return;
p->idle = 0;
p->idle_index = 0;
p->idle_msg[0] = 0;
action = "doing command";
if (p->ibuffer[0] != '#')
{
if (p->custom_flags & CONVERSE)
{
pick = p->ibuffer;
while (*pick && isspace(*pick))
pick++;
if (*pick)
{
if (*pick == '/' || *pick == '.')
if (current_room == prison && !(p->residency & (ADMIN | SU)))
sub_command(p, pick + 1, restricted_list);
else
{
if (!match_social(p, pick + 1))
match_commands(p, pick + 1);
}
else if (!isalpha(*pick))
if (current_room == prison && !(p->residency & (ADMIN | SU)))
sub_command(p, pick, restricted_list);
else
{
if (!match_social(p, pick))
match_commands(p, pick);
}
else
{
if (config_flags & cfNOSWEAR &&
(!strcmp(p->location->owner->lower_name, SYS_ROOM_OWNER) ||
!strcmp(p->location->owner->lower_name, "intercom")))
pick = filter_rude_words(pick);
say(p, pick);
}
}
}
else if (current_room == prison && !(p->residency & (ADMIN | SU)))
sub_command(p, p->ibuffer, restricted_list);
else
{
if (!match_social(p, p->ibuffer))
match_commands(p, p->ibuffer);
}
}
}
void su_quit_log(player * p)
{
char *oldstack;
int csu;
csu = true_count_su();
oldstack = stack;
sprintf(stack, "%s leaves -- %d sus left", p->name, csu - 1);
stack = end_string(stack);
log("su", oldstack);
stack = oldstack;
}
/* scan through the players and see if anything needs doing */
void process_players()
{
player *scan, *sparky;
char *oldstack, *hasta, thetime[10];
FILE *fp;
if (current_players > max_ppl_on_so_far)
{
max_ppl_on_so_far = current_players;
max_ppl_on_so_far_time = time(0);
if (max_ppl_on_so_far > max_ppl_ever_so_far)
{
oldstack = stack;
max_ppl_ever_so_far = max_ppl_on_so_far;
max_ppl_ever_so_far_time = max_ppl_on_so_far_time;
ADDSTACK("max_ppl: %d\nmax_ppl_time: %d",
max_ppl_ever_so_far, (int) max_ppl_ever_so_far_time);
ENDSTACK("\n");
fp = fopen("files/stats_info", "w");
if (!fp)
LOGF("error", "Couldn't open stats_info file in process_players");
else
{
fprintf(fp, oldstack);
fclose(fp);
}
stack = oldstack;
}
}
for (scan = flatlist_start; scan; scan = sparky)
{
sparky = scan->flat_next;
if (scan->flat_next)
if (((player *) scan->flat_next)->flat_previous != scan)
{
raw_wall("\n\n -=> Non-terminated flatlist <=-\n\n");
raw_wall("\n\n -=> Dumping end off of list <=-\n\n");
scan->flat_next = NULL;
}
#ifdef ROBOTS
if ((scan->fd < 0 && !(scan->flags & ROBOT)) || (scan->flags & PANIC) || (scan->flags & CHUCKOUT))
#else
if ((scan->fd < 0) || (scan->flags & PANIC) || (scan->flags & CHUCKOUT))
#endif
{
oldstack = stack;
current_player = scan;
if (scan->location && scan->name[0] && !(scan->flags & RECONNECTION))
{
#ifdef LAST
stampLogout(scan->name);
#endif
if (scan->residency & SU && true_count_su() <= 1)
su_quit_log(scan);
hasta = do_alias_match(scan, "_logoff");
if (strcmp(hasta, "\n"))
{
match_commands(scan, "_logoff");
}
if (scan == p_sess)
{
session_reset = 0;
}
if (strlen(scan->logoffmsg) < 1)
{
stack += sprintf(stack, "%s %s ",
get_config_msg("logoff_prefix"), scan->name);
stack += sprintf(stack, "%s ", get_config_msg("def_logout"));
stack += sprintf(stack, "^N%s\n", get_config_msg("logoff_suffix"));
}
else
{
if (emote_no_break(*scan->logoffmsg))
{
stack += sprintf(stack, "%s %s%s ", get_config_msg("logoff_prefix"),
scan->name, scan->logoffmsg);
stack += sprintf(stack, "^N%s\n", get_config_msg("logoff_suffix"));
}
else
{
stack += sprintf(stack, "%s %s %s ", get_config_msg("logoff_prefix"),
scan->name, scan->logoffmsg);
stack += sprintf(stack, "^N%s\n", get_config_msg("logoff_suffix"));
}
}
stack = end_string(stack);
command_type |= LOGOUT_TAG;
tell_room(scan->location, oldstack);
command_type &= ~LOGOUT_TAG;
stack = oldstack;
save_player(scan);
command_type = 0;
do_inform(scan, get_plists_msg("inform_logout"));
if (scan->saved && !(scan->flags & NO_SAVE_LAST_ON))
scan->saved->last_on = time(0);
}
if (sys_flags & VERBOSE || scan->residency == 0)
{
/* Ignore "advanced" talker listings which spam the newconn log */
if (!unlogged_site(scan->inet_addr) && !unlogged_site(scan->num_addr))
{
if (scan->name[0])
{
if (scan->newbieinform)
SUWALL(" -=*> '%s' has disconnected (non-resident)\n", scan->name);
LOGF("newconn", "%s disconnects from %s", scan->name,
get_address(scan, NULL));
}
else
LOGF("nonconn", "%s disconnects from login", scan->inet_addr);
}
}
destroy_player(scan);
current_player = 0;
stack = oldstack;
}
else if (scan->flags & INPUT_READY)
{
if (!(scan->lagged) && !(scan->system_flags & SAVE_LAGGED))
{
current_player = scan;
current_room = scan->location;
input_for_one(scan);
action = "processing players";
current_player = 0;
current_room = 0;
sys_color_atm = SYSsc;
}
if (scan->flags & PROMPT)
{
if (scan->custom_flags & CONVERSE)
do_prompt(scan, scan->converse_prompt);
else if ((scan->system_flags & TIMEPROMPT) && !(scan->custom_flags & CONVERSE))
{
sprintf(thetime, "[%s]> ", sys_time_prompt(scan->jetlag));
do_prompt(scan, thetime);
}
else if (!(scan->system_flags & TIMEPROMPT))
do_prompt(scan, scan->prompt);
}
memset(scan->ibuffer, 0, IBUFFER_LENGTH);
scan->flags &= ~INPUT_READY;
}
}
}
/* timer things */
/* automessages */
void do_automessage(room * r)
{
int count = 0, type;
char *scan, *oldstack;
oldstack = stack;
scan = r->automessage.where;
if (!scan)
{
r->flags &= ~AUTO_MESSAGE;
return;
}
for (; *scan; scan++)
if (*scan == '\n')
count++;
if (!count)
{
FREE(r->automessage.where);
r->automessage.where = 0;
r->automessage.length = 0;
r->flags &= ~AUTO_MESSAGE;
stack = oldstack;
return;
}
count = rand() % count;
for (scan = r->automessage.where; count; count--, scan++)
while (*scan != '\n')
scan++;
while (*scan != '\n')
*stack++ = *scan++;
*stack++ = '\n';
*stack++ = 0;
type = command_type;
command_type = AUTO;
tell_room(r, oldstack);
command_type = type;
r->auto_count = r->auto_base + (rand() & 63);
stack = oldstack;
}
/* file syncing */
void do_sync(void)
{
int origin;
action = "doing sync";
sync_counter = SYNC_TIME;
origin = synct;
while (!update[synct])
{
synct = (synct + 1) % 26;
if (synct == origin)
break;
}
if (update[synct])
{
sync_to_file(synct + 'a', 0);
synct = (synct + 1) % 26;
}
}
/* this is the actual timer pling */
void actual_timer(int c)
{
static int pling = TIMER_CLICK;
player *scan;
time_t t;
int timeon;
if (sys_flags & PANIC)
return;
#if !defined(hpux) && !defined(linux)
if ((int) signal(SIGALRM, actual_timer) < 0)
handle_error("Can't set timer signal.");
#endif /* hpux */
t = time(0);
if ((splat_timeout - t) <= 0)
splat1 = splat2 = 0;
pling--;
if (pling)
return;
pling = TIMER_CLICK;
sys_flags |= DO_TIMER;
/* if (mem_use_log_count > 0)
mem_use_log_count--; */
if (shutdown_count > 0)
shutdown_count--;
#ifdef ROBOTS
process_robot_counters();
#endif
#ifdef ALLOW_MULTIS
update_multis();
#endif
this_rand = (player *) NULL; /* dynatext random player reset, here too,
in case dynatext is not run from a command */
for (scan = flatlist_start; scan; scan = scan->flat_next)
if (!(scan->flags & PANIC))
{
if (scan->next_ping == 0)
{
scan->next_ping = -1;
ping_timed(scan);
}
if (scan->next_ping > 0)
scan->next_ping--;
scan->idle++;
scan->idle_index++;
scan->total_login++;
if (scan->total_login % ONE_HOUR == 0)
scan->pennies += 10;
if (scan->pennies > 100000)
scan->pennies = 100000;
if (scan->residency && !(scan->residency & NO_SYNC) && scan->total_login % 1200 == 800)
save_player(scan);
if (scan->location && !strcmp(scan->location->owner->lower_name, SYS_ROOM_OWNER))
scan->time_in_main++;
if (scan->script && scan->script > 1)
scan->script--;
if (scan->timer_fn && scan->timer_count > 0)
scan->timer_count--;
if (scan->no_shout > 0)
scan->no_shout--;
if (scan->no_move > 0 && !(scan->system_flags & SAVED_RM_MOVE))
scan->no_move--;
if (scan->lagged > 0)
scan->lagged--;
if (scan->shout_index > 0)
scan->shout_index--;
if (scan->social_index)
scan->social_index--;
/* for sing */
if (scan->no_sing > 0)
scan->no_sing--;
/* for clock */
if (time(0) % ONE_HOUR == 0 && !(scan->custom_flags & NO_CLOCK))
show_clock(scan);
/* For max login time */
timeon = time(0) - scan->on_since;
#ifdef ROBOTS
if (scan->location && timeon > longest_time && !(scan->residency & ROBOT_PRIV))
#else
if (scan->location && timeon > longest_time)
#endif
{
longest_time = timeon;
strncpy(longest_player, scan->name, 20);
}
/* For slots */
if (pot <= 150)
pot = atoi(get_config_msg("initial_pot"));
/* For residency things */
if (scan->awaiting_residency == 1)
make_resident(scan);
else if (scan->awaiting_residency > 0)
{
scan->awaiting_residency--;
if (scan->awaiting_residency == 31 || scan->awaiting_residency == 16)
{
TELLPLAYER(scan, " -=*> You have %d seconds left before you become a resident.\n", scan->awaiting_residency - 1);
SUWALL(" -=*> %s will be granted residency in %d seconds ...\n", scan->name, scan->awaiting_residency - 1);
}
}
/* for asty's idle thang */
if (scan->idle_index > 300 && !(scan->residency & ADMIN))
{
scan->total_idle_time += (290 + (rand() % 40));
scan->idle_index = 0;
}
if (scan->jail_timeout > 0)
scan->jail_timeout--;
/* unidle admins */
if (config_flags & cfADMINIDLE)
if (scan->idle > 3000 && scan->residency & ADMIN)
scan->idle = 0;
if (config_flags & cfNOSPAM)
{
/* Anti-spam code */
scan->antispam -= 7;
if (scan->antispam < 0)
scan->antispam = 0;
if (scan->antispam > 50)
spam_warning(scan);
}
/* Channel stuff */
if (strlen(scan->zchannel) > 0)
{
scan->zcidle++;
if (scan->zcidle > ONE_HOUR)
{
if (scan->misc_flags & CHAN_HI)
command_type |= HIGHLIGHT;
sys_color_atm = UCEsc;
TELLPLAYER(scan, " <(%s)> -- This channel is too idle and has been destroyed\n", scan->zchannel);
sys_color_atm = SYSsc;
if (scan->misc_flags & CHAN_HI)
command_type &= ~HIGHLIGHT;
strcpy(scan->zchannel, "");
scan->zcidle = 0;
}
}
/* timing out REALLY idle gits... */
if (config_flags & cfIDLEBAD)
{
if (scan->idle == 3000 || scan->idle == 3300 ||
(!(scan->residency) && (scan->idle == 1500 || scan->idle == 1620)))
{
TELLPLAYER(scan, " -=*> Warning - you are now %d minutes idle.\007\n",
scan->idle / ONE_MINUTE);
}
if (scan->idle == 3540 || (!(scan->residency) && scan->idle == 1740))
{
TELLPLAYER(scan, " -=*> You're %d minutes idle. 1 minute till auto-disconnect.\007\n",
scan->idle / ONE_MINUTE);
}
if (scan->idle >= ONE_HOUR || (!(scan->residency) && scan->idle >= (ONE_HOUR / 2)))
{
TELLPLAYER(scan, "\n\n"
LINE
"\nThank you for visiting %s.\n\n"
"Next time though, when you decide to leave, you ought to quit for yourself.\n\n"
LINE
"\n\n", scan->name);
scan->idled_out_count++;
log("idle", scan->lower_name);
quit(scan, 0);
}
}
}
net_count--;
if (!net_count)
{
net_count = 10;
in_total += in_current;
out_total += out_current;
in_pack_total += in_pack_current;
out_pack_total += out_pack_current;
in_bps = in_current / 10;
out_bps = out_current / 10;
in_pps = in_pack_current / 10;
out_pps = out_pack_current / 10;
in_average = (in_average + in_bps) >> 1;
out_average = (out_average + out_bps) >> 1;
in_pack_average = (in_pack_average + in_pps) >> 1;
out_pack_average = (out_pack_average + out_pps) >> 1;
in_current = 0;
out_current = 0;
in_pack_current = 0;
out_pack_current = 0;
}
}
/* If they've been naughty - then they get kicked off. Heh heh heh --Silver */
void spam_warning(player * p)
{
int no1, no2, no3, no4, gon;
gon = atoi(get_config_msg("spam_eject"));
TELLPLAYER(p, "\n\n"
LINE
"\nYou have triggered the anti-spam code. As well as being pointless and\n"
"irritating, spamming is also unnecessary and annoys other residents.\n\n"
"You have been prevented from logging in for the next %d minute(s).\n\n"
LINE
"\n\n\007", gon);
LOGF("spam", "%s is ejected for %d min(s) for spamming", p->name, gon);
SW_BUT(p, " -=*> %s is ejected for %d min(s) for spamming\n", p->name, gon);
p->sneezed = time(0) + (gon * 60);
soft_timeout = time(0) + (gon * 60);
sscanf(p->num_addr, "%d.%d.%d.%d", &no1, &no2, &no3, &no4);
soft_splat1 = no1;
soft_splat2 = no2;
quit(p, "");
}
/* the timer function */
void timer_function()
{
player *scan, *old_current;
room *r, **list;
char *oldstack;
int count = 0, pcount = 0;
char *action_cpy;
struct tm *ts;
time_t t;
#if !defined(linux)
#ifndef BSDISH
struct mallinfo minfo;
#endif
#else
/* struct mstats memstats; */
#endif /* LINUX */
#ifdef AUTOSHUTDOWN
int nump = 0;
#endif
if (!(sys_flags & DO_TIMER))
return;
sys_flags &= ~DO_TIMER;
waitpid((pid_t) - 1, (int *) 0, WNOHANG);
/* wait3(0,WNOHANG,0); */
old_current = current_player;
action_cpy = action;
oldstack = stack;
if (shutdown_count > -1)
{
command_type |= HIGHLIGHT;
switch (shutdown_count)
{
case ONE_YEAR:
raw_wall("\n\n -=*> Your attention please. <*=-\n"
" -=*> We'll be rebooting in exactly one year <*=-\n"
" -=*> Anyone still here at that time needs help! <*=-\n\n");
break;
case ONE_DAY:
sprintf(stack, "\n %s\n\n", get_shutdowns_msg("1day"));
stack = end_string(stack);
raw_wall(oldstack);
stack = oldstack;
break;
case (15 * ONE_MINUTE):
sprintf(stack, "\n %s\n\n", get_shutdowns_msg("15mins"));
stack = end_string(stack);
raw_wall(oldstack);
stack = oldstack;
break;
case (10 * ONE_MINUTE):
sprintf(stack, "\n %s\n\n", get_shutdowns_msg("10mins"));
stack = end_string(stack);
raw_wall(oldstack);
stack = oldstack;
break;
case (5 * ONE_MINUTE):
sprintf(stack, "\n %s\n\n", get_shutdowns_msg("5mins"));
stack = end_string(stack);
raw_wall(oldstack);
stack = oldstack;
break;
case (3 * ONE_MINUTE):
sprintf(stack, "\n %s\n\n", get_shutdowns_msg("3mins"));
stack = end_string(stack);
raw_wall(oldstack);
stack = oldstack;
break;
case (2 * ONE_MINUTE):
sprintf(stack, "\n %s\n\n", get_shutdowns_msg("2mins"));
stack = end_string(stack);
raw_wall(oldstack);
stack = oldstack;
break;
case ONE_MINUTE:
sprintf(stack, "\n %s\n\n", get_shutdowns_msg("1min"));
stack = end_string(stack);
raw_wall(oldstack);
stack = oldstack;
break;
case 45:
sprintf(stack, "\n %s\n\n", get_shutdowns_msg("45secs"));
stack = end_string(stack);
raw_wall(oldstack);
stack = oldstack;
break;
case 30:
sprintf(stack, "\n %s\n\n", get_shutdowns_msg("30secs"));
stack = end_string(stack);
raw_wall(oldstack);
stack = oldstack;
break;
case 15:
sprintf(stack, "\n %s\n\n", get_shutdowns_msg("15secs"));
stack = end_string(stack);
raw_wall(oldstack);
stack = oldstack;
break;
case 10:
sprintf(stack, "\n %s\n\n", get_shutdowns_msg("10secs"));
stack = end_string(stack);
raw_wall(oldstack);
stack = oldstack;
break;
case 9:
sprintf(stack, "\n %s\n", get_shutdowns_msg("9secs"));
stack = end_string(stack);
raw_wall(oldstack);
stack = oldstack;
break;
case 8:
sprintf(stack, "\n %s\n", get_shutdowns_msg("8secs"));
stack = end_string(stack);
raw_wall(oldstack);
stack = oldstack;
break;
case 7:
sprintf(stack, "\n %s\n", get_shutdowns_msg("7secs"));
stack = end_string(stack);
raw_wall(oldstack);
stack = oldstack;
break;
case 6:
sprintf(stack, "\n %s\n", get_shutdowns_msg("6secs"));
stack = end_string(stack);
raw_wall(oldstack);
stack = oldstack;
break;
case 5:
sprintf(stack, "\n %s\n", get_shutdowns_msg("5secs"));
stack = end_string(stack);
raw_wall(oldstack);
stack = oldstack;
break;
case 4:
sprintf(stack, "\n %s\n", get_shutdowns_msg("4secs"));
stack = end_string(stack);
raw_wall(oldstack);
stack = oldstack;
break;
case 3:
sprintf(stack, "\n %s\n", get_shutdowns_msg("3secs"));
stack = end_string(stack);
raw_wall(oldstack);
stack = oldstack;
break;
case 2:
sprintf(stack, "\n %s\n", get_shutdowns_msg("2secs"));
stack = end_string(stack);
raw_wall(oldstack);
stack = oldstack;
break;
case 1:
sprintf(stack, "\n %s\n", get_shutdowns_msg("1sec"));
stack = end_string(stack);
raw_wall(oldstack);
stack = oldstack;
break;
case 0:
log("shutdown", shutdown_reason);
sys_flags |= SHUTDOWN;
stack = oldstack;
return;
}
command_type &= ~HIGHLIGHT;
}
if (sync_counter)
sync_counter--;
else
do_sync();
if (note_sync)
note_sync--;
else
{
note_sync = NOTE_SYNC_TIME;
sync_notes(1);
}
scan_news();
if (news_sync)
news_sync--;
else
{
news_sync = NEWS_SYNC_INTERVAL;
sync_all_news_headers();
}
if (reload_count)
reload_count--;
else
{
reload_count = 5;
init_messages();
}
align(stack);
list = (room **) stack;
for (scan = flatlist_start; scan; scan = scan->flat_next)
{
if (!(scan->flags & PANIC))
{
if (scan->script && scan->script == 1)
end_emergency(scan);
if (scan->timer_fn && !scan->timer_count)
{
current_player = scan;
sys_flags &= ~(FAILED_COMMAND | PIPE | ROOM_TAG | FRIEND_TAG | OFRIEND_TAG | EVERYONE_TAG);
command_type &= ~ROOM;
(*scan->timer_fn) (scan);
scan->timer_fn = 0;
scan->timer_count = -1;
}
current_player = old_current;
action = "processing autos";
r = scan->location;
if (r)
{
pcount++;
if (r->flags & AUTO_MESSAGE && !(r->flags & AUTOS_TAG))
{
if (!r->auto_count)
do_automessage(r);
else
r->auto_count--;
*(room **) stack = r;
stack += sizeof(room *);
count++;
r->flags |= AUTOS_TAG;
}
}
/* Jail timeout thang */
if (scan->jail_timeout == 0 && scan->location == prison)
{
command_type |= HIGHLIGHT;
tell_player(scan, " After serving your sentence you are flung out"
" to society again.\n");
command_type &= ~HIGHLIGHT;
move_to(scan, sys_room_id(ENTRANCE_ROOM), 0);
}
}
}
for (; count; count--, list++)
(*list)->flags &= ~AUTOS_TAG;
stack = oldstack;
action = action_cpy;
current_players = pcount;
t = time(0);
ts = localtime(&t);
if ((backup_hour != -1) && (ts->tm_hour == backup_hour) &&
!(ts->tm_min) && !(ts->tm_sec))
do_backup(0, 0);
#ifdef AUTOSHUTDOWN
if (auto_sd == 1)
{
nump = 0;
for (scan = flatlist_start; scan; scan = scan->flat_next)
#ifdef ROBOTS
if (!(scan->residency & ROBOT_PRIV))
#endif
nump++;
if (nump == 0)
{
LOGF("shutdown", "Auto-Shutdown sequence started");
close_down();
}
}
#endif
#ifdef SEAMLESS_REBOOT
if (awaiting_reboot)
{
awaiting_reboot = 0;
for (scan = flatlist_start; scan; scan = scan->flat_next)
if (scan->location && (scan->flags & IN_EDITOR || scan->mode & (MAILEDIT | ROOMEDIT | NEWSEDIT)))
awaiting_reboot = 1;
if (!awaiting_reboot)
do_reboot();
}
#endif
}
/* the help system (aargh argh argh) */
/* look through all possible places to find a bit of help */
struct command *find_help(char *str)
{
struct command *comlist;
if (isalpha(*str))
comlist = coms[((int) (tolower(*str)) - (int) 'a' + 1)];
else
comlist = coms[0];
for (; comlist->text; comlist++)
#ifdef COM_MATCH
if (do_match_old(str, comlist))
#else
if (do_match(str, comlist))
#endif
return comlist;
comlist = help_list;
if (!comlist)
return 0;
for (; comlist->text; comlist++)
#ifdef COM_MATCH
if (do_match_old(str, comlist))
#else
if (do_match(str, comlist))
#endif
return comlist;
return 0;
}
void next_line(file * hf)
{
while (hf->length > 0 && *(hf->where) != '\n')
{
hf->where++;
hf->length--;
}
if (hf->length > 0)
{
hf->where++;
hf->length--;
}
}
void init_help()
{
file hf;
struct command *found, *hstart;
char *oldstack, *start, *scan;
int length;
oldstack = stack;
if (sys_flags & VERBOSE)
log("boot", "Loading help pages");
if (help_list)
FREE(help_list);
help_list = 0;
if (help_file.where)
FREE(help_file.where);
help_file = load_file("doc/help");
hf = help_file;
align(stack);
hstart = (struct command *) stack;
while (hf.length > 0)
{
while (hf.length > 0 && *(hf.where) != ':')
next_line(&hf);
if (hf.length > 0)
{
scan = hf.where;
next_line(&hf);
*scan++ = 0;
while (scan != hf.where)
{
start = scan;
while (*scan != ',' && *scan != '\n')
scan++;
*scan++ = 0;
found = find_help(start);
if (!found)
{
found = (struct command *) stack;
stack += sizeof(struct command);
found->text = start;
found->function = 0;
found->level = 0;
found->andlevel = 0;
found->space = 1;
found->section = 0;
}
found->help = hf.where;
}
}
}
*(hf.where - 1) = 0;
found = (struct command *) stack;
stack += sizeof(struct command);
found->text = 0;
found->function = 0;
found->level = 0;
found->andlevel = 0;
found->space = 0;
found->help = 0;
found->section = 0;
length = (int) stack - (int) hstart;
help_list = (struct command *) MALLOC(length);
memcpy(help_list, hstart, length);
stack = oldstack;
}
/* load that help file in */
int get_help(player * p, char *str)
{
int fail = 0;
file text;
char *oldstack = stack;
char header[75];
if (*str == '.')
{
stack = oldstack;
return 0;
}
sprintf(stack, "doc/%s.help", str);
stack = end_string(stack);
text = load_file_verbose(oldstack, 0);
if (text.where)
{
if (*(text.where))
{
stack = oldstack;
snprintf(header, 70, "%s Online Help: %s",
get_config_msg("talker_name"), str);
pstack_mid(header);
sprintf(stack, "\n%s"
LINE, text.where);
stack = end_string(stack);
pager(p, oldstack);
fail = 1;
}
else
fail = 0;
FREE(text.where);
}
stack = oldstack;
return fail;
}
int get_victim(player * p, char *text)
{
return 0;
}
/* the help command */
void help(player * p, char *str)
{
char *oldstack, header[75];
struct command *fn, *comlist;
char command[100] = "";
int i = 0;
oldstack = stack;
if (!*str)
{
if (p->residency)
str = "general";
else
str = "newbie";
}
/* so ressies can see "help su" */
if (!strcasecmp(str, "su"))
{
str = "superuser";
}
if (isalpha(*str))
comlist = coms[((int) (tolower(*str)) - (int) 'a' + 1)];
else
comlist = coms[0];
/* check they aren't exploiting a pg96 bug to get su/admin help files */
for (i = 0; i < strlen(str); i++)
{
if (str[i] == ' ')
{
str[i] = 0;
break;
}
}
strncpy(command, str, 95);
/* Here it is - check person's privs before helping them =) */
for (; comlist->text; comlist++)
if (!strcmp(comlist->text, str))
if ((!(p->residency & comlist->level)) && comlist->level != 0)
str = " ";
fn = find_help(str);
if (!fn || !(fn->help))
{
if (get_help(p, str))
return;
stack = oldstack;
TELLPLAYER(p, " Cannot find any help on '%s'. \n", command);
LOGF("help", "%s requested help on '%s'", p->name, command);
return;
}
if (!strcasecmp(str, "newbie"))
if (get_victim(p, fn->help))
{
stack = oldstack;
return;
}
snprintf(header, 70, "%s Online Help: %s",
get_config_msg("talker_name"), command);
pstack_mid(header);
sprintf(stack, "%s"
LINE, fn->help);
stack = end_string(stack);
pager(p, oldstack);
stack = oldstack;
}
void forcehelp(player * p, char *str)
{
player *p2;
char *temp;
temp = next_space(str);
*temp++ = 0;
if (!*str)
{
tell_player(p, " Format: forcehelp <player> <help file>\n");
return;
}
p2 = find_player_global(str);
if (!p2)
return;
if (p2 == p)
{
tell_player(p, " You don't need to forcehelp yourself something!\n");
return;
}
tell_player(p2, " -=> I think you need to read this ... \n");
help(p2, temp);
SUWALL(" -=*> %s shows help '%s' to %s\n", p->name, temp, p2->name);
LOGF("forcehelp", "%s forcehelpped '%s' to %s.", p->name, temp, p2->name);
}
/* Credit goes to Renegade for spotting a bug with this code. The original
PG one didn't check to see if the SU/Minister/etc was actually a person
on the talker (indeed a person at all). Must amusement came from typing the
command "push <name> a large cliff" or "push <name> a fluffy sheep" */
void redtape(player * p, char *str)
{
player *p2, *p3;
char *temp, *oldstack;
temp = next_space(str);
*temp++ = 0;
oldstack = stack;
if ((!*str) || (!*temp))
{
tell_player(p, " Format: redtape <git> <SuperUser/Minister/etc>\n");
return;
}
p2 = find_player_global(str);
if (!p2)
return;
p3 = find_player_global(temp);
if (!p3)
return;
if (p2 == p3)
{
tell_player(p, "Are you sure about that??\n");
return;
}
sprintf(stack, "\n -=*> %s may be able to help you better. \n\n", p3->name);
stack = end_string(oldstack);
command_type |= HIGHLIGHT;
tell_player(p2, oldstack);
command_type &= ~HIGHLIGHT;
stack = oldstack;
sprintf(stack, " -=*> %s pushes %s towards %s\n", p->name, p2->name, p3->name);
stack = end_string(oldstack);
su_wall(oldstack);
stack = oldstack;
}
/* Show the clock - okay so this is one poxy little procedure but I
like it this way, so there. --Silver
(function seperation is a good thing, it leads to easily
readable and modifiable code *grin* ~phy) */
void show_clock(player * p)
{
char *oldstack = stack;
time_t t;
static char buf[80];
if (p->jetlag)
t = time(0) + (ONE_HOUR * p->jetlag);
else
t = time(0);
strftime(buf, 79, "%I:%M %p", localtime(&t));
sprintf(stack, get_config_msg("hourly_clock"), buf);
stack = end_string(stack);
TELLPLAYER(p, " %s\007\n", oldstack);
stack = oldstack;
}
/* Specilised match code becuase strnomatch is no good */
int swear_match(char *str1, char *str2)
{
char *s1p, *s2p;
s1p = str1;
s2p = str2;
for (; *s1p; s1p++, s2p++)
{
if (tolower(*s1p) != tolower(*s2p))
return 1;
}
return 0;
}
/* Swear words removal code :o)
A list of rude words can be found in admin.h - gasp! */
char rand_curse_char(void)
{
srand(rand());
return (char) (rand() % 6 + 33);
}
char *filter_rude_words(char *str)
{
char *ptr = str, *rude;
while ((rude = strcaseline(ptr, rude_msg.where)))
while (*rude && isalpha(*rude))
*rude++ = rand_curse_char();
return str;
}
void swear_version(void)
{
sprintf(stack, " -=*> Swear filtering v1.0 (by Silver) enabled.\n");
stack = strchr(stack, 0);
}