/*
* Playground+ - aliases.c
* Aliases editing, creating and matching code
* ---------------------------------------------------------------------------
*/
#include <ctype.h>
#include <string.h>
#ifndef BSDISH
#include <malloc.h>
#endif
#include <fcntl.h>
#include <memory.h>
#include <stdio.h>
#include <stdlib.h>
#include "include/config.h"
#include "include/player.h"
#include "include/fix.h"
#include "include/aliases.h"
#include "include/proto.h"
/* delete and entry from someones list */
void delete_entry_alias(saved_player * sp, alias * l)
{
alias *scan;
if (!sp)
return;
scan = sp->alias_top;
if (scan == l)
{
sp->alias_top = l->next;
FREE(l);
return;
}
while (scan)
if (scan->next == l)
{
scan->next = l->next;
FREE(l);
return;
}
else
scan = scan->next;
log("error", "Tried to delete alias that wasn't there.");
}
/* compress list */
void tmp_comp_alias(saved_player * sp)
{
char *oldstack;
alias *l, *next;
l = sp->alias_top;
oldstack = stack;
stack = store_int(stack, 0);
while (l)
{
next = l->next;
if (!l->cmd[0])
{
log("error", "Bad alias entry on compress .. auto deleted.");
delete_entry_alias(sp, l);
}
else
{
stack = store_string(stack, l->cmd);
stack = store_string(stack, l->sub);
}
l = next;
}
store_int(oldstack, ((int) stack - (int) oldstack));
}
/* */
void compress_alias(saved_player * sp)
{
char *oldstack;
int length;
alias *new, *l, *next;
if (sp->system_flags & COMPRESSED_ALIAS)
return;
sp->system_flags |= COMPRESSED_ALIAS;
oldstack = stack;
tmp_comp_alias(sp);
length = (int) stack - (int) oldstack;
if (length == 4)
{
sp->alias_top = 0;
stack = oldstack;
return;
}
new = (alias *) MALLOC(length);
memcpy(new, oldstack, length);
l = sp->alias_top;
while (l)
{
next = l->next;
FREE(l);
l = next;
}
sp->alias_top = new;
stack = oldstack;
}
/* decompress list */
void decompress_alias(saved_player * sp)
{
alias *l;
char *old, *end, *start;
int length;
if (!(sp->system_flags & COMPRESSED_ALIAS))
return;
sp->system_flags &= ~COMPRESSED_ALIAS;
old = (char *) sp->alias_top;
start = old;
if (!old)
return;
old = get_int(&length, old);
end = old + length - 4;
sp->alias_top = 0;
while (old < end)
{
l = (alias *) MALLOC(sizeof(alias));
old = get_string(stack, old);
strncpy(l->cmd, stack, MAX_NAME - 3);
old = get_string(stack, old);
strncpy(l->sub, stack, MAX_DESC - 3);
l->next = sp->alias_top;
sp->alias_top = l;
}
FREE(start);
}
/* save list */
void construct_alias_save(saved_player * sp)
{
int length;
char *where;
if (!(sp->system_flags & COMPRESSED_ALIAS) &&
(!find_player_absolute_quiet(sp->lower_name)))
compress_alias(sp);
if (sp->system_flags & COMPRESSED_ALIAS)
{
if (sp->alias_top)
{
where = (char *) sp->alias_top;
(void) get_int(&length, where);
memcpy(stack, where, length);
stack += length;
}
else
stack = store_int(stack, 4);
}
else
tmp_comp_alias(sp);
}
/* retrieve list */
char *retrieve_alias_data(saved_player * sp, char *where)
{
int length;
(void) get_int(&length, where);
if (length == 4)
sp->alias_top = 0;
else
{
sp->system_flags |= COMPRESSED_ALIAS;
sp->alias_top = (alias *) MALLOC(length);
memcpy(sp->alias_top, where, length);
}
where += length;
return where;
}
/* count list entries */
int count_alias(player * p)
{
alias *l;
int count = 0;
if (!p->saved)
return 0;
if (!p->saved->alias_top)
return 0;
for (l = p->saved->alias_top; l; l = l->next)
count++;
return count;
}
/* find list entry for a person */
alias *find_alias_entry(player * p, char *name)
{
alias *l;
if (!p->saved)
return 0;
decompress_alias(p->saved);
l = p->saved->alias_top;
while (l)
if (!strcasecmp(l->cmd, name))
return l;
else
l = l->next;
return 0;
}
/* create a list entry */
alias *create_entry_alias(player * p, char *name)
{
alias *l;
if (!p->saved)
return 0;
if ((count_alias(p)) >= (p->max_alias))
{
tell_player(p, " Can't create new alias, "
"because your alias list is full.\n");
return 0;
}
l = (alias *) MALLOC(sizeof(alias));
strncpy(l->cmd, name, MAX_NAME - 3);
l->cmd[MAX_NAME - 3] = 0;
strncpy(l->sub, "", MAX_DESC - 3);
l->sub[MAX_DESC - 3] = 0;
l->next = p->saved->alias_top;
p->saved->alias_top = l;
return l;
}
/* view alias list */
void view_alias(player * p, char *str)
{
char *oldstack, li[] = "Logon Script", lo[] = "Logoff Script", re[] = "Reconnect Script";
alias *l, *logon = 0, *logoff = 0, *recon = 0;
int count;
char top[70];
oldstack = stack;
if (!p->saved)
{
tell_player(p, " You have no alias list to view.\n");
return;
}
count = count_alias(p);
if (!count)
{
TELLPLAYER(p, "You are using none of your maximum %d aliases.\n", p->max_alias);
return;
}
sprintf(top, "You are using %d of your maximum %d aliases",
count, p->max_alias);
pstack_mid(top);
for (l = p->saved->alias_top; l; l = l->next)
{
if (!strcmp(l->cmd, "_logon"))
logon = l;
else if (!strcmp(l->cmd, "_logoff"))
logoff = l;
else if (!strcmp(l->cmd, "_recon"))
recon = l;
else
{
sprintf(stack, "^B%-20s^N = %s", l->cmd, l->sub);
stack = strchr(stack, 0);
*stack++ = '\n';
}
}
if (logon || logoff || recon)
{
sprintf(stack, LINE);
stack = strchr(stack, 0);
if (logon)
{
sprintf(stack, "^B%-20s^N = %s", li, logon->sub);
stack = strchr(stack, 0);
*stack++ = '\n';
}
if (logoff)
{
sprintf(stack, "^B%-20s^N = %s", lo, logoff->sub);
stack = strchr(stack, 0);
*stack++ = '\n';
}
if (recon)
{
sprintf(stack, "^B%-20s^N = %s", re, recon->sub);
stack = strchr(stack, 0);
*stack++ = '\n';
}
}
sprintf(stack, LINE);
stack = end_string(stack);
pager(p, oldstack);
stack = oldstack;
}
/* undefine a macro? */
void undefine_alias(player * p, char *str)
{
char *oldstack, *text, msg[50];
int count = 0;
alias *l;
oldstack = stack;
if (!p->saved)
{
tell_player(p, " You do not have an alias list to alter, "
"since you are not saved\n");
return;
}
if (!*str)
{
tell_player(p, " Format: undefine <alias to undefine>\n");
return;
}
{
l = find_alias_entry(p, str);
if (!l)
{
text = stack;
sprintf(stack, " Can't find any alias list entry for '%s'.\n", str);
stack = end_string(stack);
tell_player(p, text);
}
else
{
count++;
sprintf(msg, " Entry removed for '%s'\n", l->cmd);
tell_player(p, msg);
delete_entry_alias(p->saved, l);
}
}
stack = oldstack;
if (!count)
tell_player(p, " No entries removed.\n");
else
{
sprintf(stack, " Deleted alias.\n");
stack = end_string(stack);
tell_player(p, oldstack);
}
stack = oldstack;
}
/* check for people aliasing _logon / _logoff / _recon to something which uses the
* quit command -- blimey
*/
int alias_contains_quit_command(char * str)
{
char * current;
for (current = str; current; current = strstr(current, "%;")) {
/* skip to the start of a commandline */
if ((current[0] == '%') && (current[1] == ';'))
current += 2;
while (current[0] == ' ')
current++;
/* see if the commandline is prefixed by "quit",
and has the suffix of a command delimiter */
if ((strlen(current) >= 4) &&
(strncasecmp(current, "quit", 4) == 0) &&
((current[4] == '\0') || (current[4] == ' ') ||
(current[4] == '\n') || ((current[4] == '%') && (current[5] == ';'))))
return 1;
}
return 0;
}
/* define an alias -- woowoo */
void define_alias(player * p, char *str)
{
char *doh, *oldstack, *scanned;
int count = 0;
alias *l;
if (!p->saved)
{
tell_player(p, " You can't alias because you have no save file.\n");
return;
}
oldstack = stack;
doh = next_space(str);
if (!*doh)
{
tell_player(p, " Format: define <alias> <command to do instead>\n");
return;
}
*doh++ = 0;
/* strip extra spaces from str */
scanned = str;
while (*str && !(isspace(*str)))
str++;
*str++ = 0;
str = scanned;
/* check for stupid people */
if ((!strcasecmp(str, "_logon") || !strcasecmp(str, "_logoff") || !strcasecmp(str, "_recon")) &&
alias_contains_quit_command(doh))
{
tell_player(p, " You can't use the 'quit' command in such an alias.\n");
return;
}
l = find_alias_entry(p, str);
if (!l)
l = create_entry_alias(p, str);
if (l)
{
count++;
strncpy(l->sub, doh, MAX_DESC - 3);
l->sub[MAX_DESC - 3] = 0;
}
if (count)
tell_player(p, " Alias defined.\n");
else
tell_player(p, " Error - could not create alias.\n");
}
char *do_alias_match(player * p, char *str)
{
alias *scan;
int g;
if (!p->saved)
return "\n";
scan = p->saved->alias_top;
while (scan)
{
g = 1;
if (strnomatch(scan->cmd, str, 0))
g = 0;
if (g)
{
while (*str && *str != ' ')
str++;
while (*str && isspace(*str))
str++;
return str;
}
scan = scan->next;
}
return "\n";
}
alias *get_alias(player * p, char *str)
{
alias *scan;
int g;
if (!p->saved)
return 0;
scan = p->saved->alias_top;
while (scan)
{
g = 1;
if (strnomatch(scan->cmd, str, 0))
g = 0;
if (g)
{
return scan;
}
scan = scan->next;
}
return 0;
}
/* New (spooned) splice_argument to prevent buffer overflows by Phypor */
char *splice_argument(player * p, char *str, char *arg, int conti)
{
static char BUFFER[10000];
char arghold[1000], strhold[1000], num[2], RARG[10][100];
int b, no, word, r1, r2;
static int a, s;
memset(BUFFER, 0, 10000);
memset(arghold, 0, 1000);
if (*arg)
strncpy(arghold, arg, 999);
else
strcpy(arghold, "");
strncpy(strhold, str, 999);
num[0] = 0;
num[1] = 0;
b = 0;
if (!(conti))
{ /* reset variables */
s = 0;
a = 0;
}
/*
buffer was getting overloaded, was 1000 bytes, now is 10000,
no longer have break-to-stop loop, will end when way past
length for writing out, but before buffer can be written past
*/
while (b < 1000)
{
if (!strhold[s])
{
BUFFER[b++] = 0;
return BUFFER;
}
else if (strhold[s] != '%')
{
BUFFER[b++] = strhold[s++];
}
else
{
if (strhold[s + 1] == ';')
{
BUFFER[b++] = 0;
s += 2;
return BUFFER;
}
else if (strhold[s + 1] == '%')
{
BUFFER[b++] = '%';
s += 2;
}
else if (strhold[s + 1] == '0')
{
s += 2;
a = 0;
while (arghold[a])
BUFFER[b++] = arghold[a++];
}
else if (strhold[s + 1] == '-')
{
s += 3;
num[0] = strhold[s - 1];
num[1] = 0;
no = atoi(num);
a = 0;
for (word = 0; word != no; a++)
{
if (!arghold[a])
{
word = no;
}
else if (isspace(arghold[a]))
word++;
}
while (arghold[a])
BUFFER[b++] = arghold[a++];
}
else if (isdigit(strhold[s + 1]))
{
s += 2;
num[0] = strhold[s - 1];
num[1] = 0;
no = atoi(num);
a = 0;
for (word = 1; word != no; a++)
{
if (!arghold[a])
{
word = no;
}
else if (isspace(arghold[a]))
word++;
}
while (arghold[a] && !(isspace(arghold[a])))
BUFFER[b++] = arghold[a++];
}
else if (strhold[s + 1] == '{')
{
/* first, clear all the old rargs */
for (r1 = 0; r1 < 10; r1++)
for (r2 = 0; r2 < 100; r2++)
RARG[r1][r2] = 0;
/* now, fill in the data into RARG */
r1 = 0;
r2 = 0;
s += 2;
/* while (strhold[s] != '}') */
while (strhold[s] && strhold[s] != '}')
{
if (r1 < 10 && r2 < 99)
{
if (strhold[s] == '@')
{
RARG[r1++][r2] = 0;
r2 = 0;
}
else
RARG[r1][r2++] = strhold[s];
}
else if (r1 < 10)
{
RARG[r1++][r2] = 0;
r2 = 0;
}
s++;
}
/* this *should* be non wibblesd */
RARG[r1][r2] = 0;
/* cose a random arg */
s++; /* get the s to the space after the %{...} */
r2 = (rand() % (r1 + 1));
r1 = 0;
while (RARG[r2][r1])
{
BUFFER[b++] = RARG[r2][r1++];
}
}
else
s += 2;
}
}
return "";
}
int strnomatch(char *str1, char *str2, int unanal)
{
char *s1p, *s2p;
s1p = str1;
s2p = str2;
for (; *s1p; s1p++, s2p++)
{
if (unanal && *s1p != *s2p)
return 1;
else if (tolower(*s1p) != tolower(*s2p))
return 1;
}
if (!unanal && *s2p && (!isspace(*s2p)))
return 1;
return 0;
}
/* view someone else's alias list, if you are Admin */
void view_others_aliases(player * p, char *str)
{
char *oldstack, li[] = "Login", lo[] = "Logout", re[] = "Reconnect";
int count;
player *p2, dummy;
alias *l, *logon = 0, *logoff = 0, *recon = 0;
char top[70];
oldstack = stack;
memset(&dummy, 0, sizeof(player));
if (!*str)
{
tell_player(p, " Format: val <player>\n");
return;
}
lower_case(str);
p2 = find_player_global_quiet(str);
if (!p2)
{
strcpy(dummy.lower_name, str);
dummy.fd = p->fd;
if (!load_player(&dummy))
{
tell_player(p, " That person does not exist!\n");
return;
}
p2 = &dummy;
}
if (!p2->saved)
{
tell_player(p, " That person has no alias list to view.\n");
return;
}
count = count_alias(p2);
stack = oldstack;
sprintf(top, "%s is using %d of %s %d alias list entries",
p2->name, count, their_player(p2), p2->max_alias);
pstack_mid(top);
if (count)
{
for (l = p2->saved->alias_top; l; l = l->next)
{
if (!strcmp(l->cmd, "_logon"))
logon = l;
else if (!strcmp(l->cmd, "_logoff"))
logoff = l;
else if (!strcmp(l->cmd, "_recon"))
recon = l;
else
{
sprintf(stack, "^B%-20s^N = %s", l->cmd, l->sub);
stack = strchr(stack, 0);
*stack++ = '\n';
}
}
if (logon || logoff || recon)
{
strcpy(stack, LINE "\n");
stack = strchr(stack, 0);
if (logon)
{
sprintf(stack, "^B%-20s^N = %s", li, logon->sub);
stack = strchr(stack, 0);
*stack++ = '\n';
}
if (logoff)
{
sprintf(stack, "^B%-20s^N = %s", lo, logoff->sub);
stack = strchr(stack, 0);
*stack++ = '\n';
}
if (recon)
{
sprintf(stack, "^B%-20s^N = %s", re, recon->sub);
stack = strchr(stack, 0);
*stack++ = '\n';
}
}
}
sprintf(stack, LINE);
stack = end_string(stack);
pager(p, oldstack);
stack = oldstack;
}
void define_logon_macro(player * p, char *str)
{
char *oldstack;
if (!*str)
{
undefine_alias(p, "_logon");
return;
}
oldstack = stack;
sprintf(stack, "_logon %s", str);
stack = end_string(stack);
define_alias(p, oldstack);
stack = oldstack;
}
void define_logoff_macro(player * p, char *str)
{
char *oldstack;
if (!*str)
{
undefine_alias(p, "_logoff");
return;
}
oldstack = stack;
sprintf(stack, "_logoff %s", str);
stack = end_string(stack);
define_alias(p, oldstack);
stack = oldstack;
}
void define_recon_macro(player * p, char *str)
{
char *oldstack;
if (!*str)
{
undefine_alias(p, "_recon");
return;
}
oldstack = stack;
sprintf(stack, "_recon %s", str);
stack = end_string(stack);
define_alias(p, oldstack);
stack = oldstack;
}
void library_list(player * p, char *str)
{
char temp[80];
char *oldstack;
int i = 0;
oldstack = stack;
sprintf(temp, "%s alias library", get_config_msg("talker_name"));
pstack_mid(temp);
while (library[i].command)
{
if (!(library[i].privs) || p->residency & PSU)
{
sprintf(stack, "%-18s", library[i].command);
stack = strchr(stack, 0);
}
i++;
if (i % 4 == 0)
stack += sprintf(stack, "\n");
}
if (i % 4 != 0)
stack += sprintf(stack, "\n");
sprintf(temp, "Please send any alias submissions to %s",
get_config_msg("talker_email"));
pstack_mid(temp);
*stack++ = 0;
tell_player(p, oldstack);
stack = oldstack;
}
alias_library get_lib_alias(char *str)
{
int i = 0;
while (library[i].command)
{
if (!strcasecmp(str, library[i].command))
return library[i];
i++;
}
return no_library_here;
}
void library_copy(player * p, char *str)
{
char *oldstack, *new_alias_name;
alias_library to_be_copied;
if (!*str)
{
tell_player(p, " Format: libcopy <library alias> [<Your name for alias>]\n");
return;
}
new_alias_name = next_space(str);
if (*new_alias_name)
*new_alias_name++ = 0;
to_be_copied = get_lib_alias(str);
if (!to_be_copied.command || (to_be_copied.privs && !(p->residency & PSU)))
{
tell_player(p, " That alias not found in the library.\n");
return;
}
else
{
oldstack = stack;
if (*new_alias_name)
sprintf(stack, "%s %s", new_alias_name, to_be_copied.alias_string);
else
sprintf(stack, "%s %s", to_be_copied.command, to_be_copied.alias_string);
stack = end_string(stack);
define_alias(p, oldstack);
stack = oldstack;
}
}
void library_examine(player * p, char *str)
{
alias_library see_this;
char *oldstack;
if (!*str)
{
tell_player(p, " Format: Libexam <library alias to examine>\n");
return;
}
see_this = get_lib_alias(str);
if (!see_this.command || (see_this.privs && !(p->residency & PSU)))
{
tell_player(p, " Couldn't find that alias in the library.\n");
return;
}
oldstack = stack;
sprintf(stack, "Command: %s\nDoes : %s\nUsage : %s\nAuthor : %s\n",
see_this.command, see_this.alias_string, see_this.description, see_this.author);
stack = end_string(stack);
tell_player(p, oldstack);
stack = oldstack;
}
/* well, we learned that aliases ain't perfect neither */
void blank_all_aliases(player * p, char *str)
{
player *p2 = 0, d;
if (*str && p->residency & ADMIN)
{
if (!(p2 = find_player_absolute_quiet(str)))
{
strncpy(d.lower_name, str, MAX_NAME - 1);
/* we dont really have to load_player here, as the aliases
are part of the saved_player, but i find it easier to
demonstrate we are working on either a player thats logged
in or out like this
~phy
*/
if (!load_player(&d))
{
tell_player(p, " Noone to blank aliases ...\n");
return;
}
p2 = &d;
}
}
else
p2 = p;
if (!p2->saved)
{
if (p == p2)
tell_player(p, " You don't seem to have a place for an alias list.\n");
else
TELLPLAYER(p, " '%s' doesn't have a saved_player ...\n", p2->name);
return;
}
if (p != p2 && !check_privs(p->residency, p2->residency))
{
tell_player(p, " You can't do that!!!\n");
if (p2 != &d)
TELLPLAYER(p2, " -=*> %s tried to blank all your aliases!\n", p->name);
else
SW_BUT(p, " -=*> %s tried to blank all of %s's aliases!\n", p->name, p2->name);
return;
}
if (p != p2 && !p2->saved->alias_top)
{
TELLPLAYER(p, " '%s' has no aliases defined presently.\n", p2->name);
return;
}
p2->saved->alias_top = 0;
if (p == p2)
{
tell_player(p, "Aliases deleted.\n");
return;
}
TELLPLAYER(p, " '%s' aliases have been deleted ...\n", p2->name);
SW_BUT(p, " -=*> %s deletes all of %s's aliases ...\n", p->name, p2->name);
LOGF("blanks", "%s blanks ALL of %s's aliases.", p->name, p2->name);
}