Skip to content
Commits on Source (4)
......@@ -45,7 +45,6 @@
#define RUNAWAY 1200
#define MAXRUNAWAY 5000
#define FLOODLIMIT 15
#define RIGHTS_BBS 0
#define RIGHTS_TALK 1
......
......@@ -150,37 +150,6 @@ struct alarm *alarm_at(const struct timeval *when, void *what, void (*how)(void
return temp;
}
static void set_flag(void *flag)
{
if (flag != NULL) *(int *)flag = 1;
}
void alarm_sleep(struct timeval *delay, int resume)
{
volatile int flag;
struct alarm *alrm;
struct timeval finish;
flag = 0;
do {
alrm = alarm_after(delay->tv_sec, delay->tv_usec, (void *)&flag, &set_flag);
select(0, NULL, NULL, NULL, delay);
if (flag)
timerclear(delay);
else
{
gettimeofday(&finish, NULL);
alrm->how = NULL;
timersub(&alrm->when, &finish, delay);
if (timercmp(delay, &zero_time, <=))
{
delay->tv_sec = 0;
delay->tv_usec = 1;
}
}
} while (!flag && resume);
}
int alarm_select(int maxfd, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout)
{
int nfds;
......
......@@ -21,7 +21,6 @@ void alarm_cleanup(void);
void alarm_handler(int sig);
struct alarm *alarm_at(const struct timeval *when, void *what, void (*how)(void *));
struct alarm *alarm_after(long secs, long usecs, void *what, void (*how)(void *));
void alarm_sleep(struct timeval *delay, int resume);
int alarm_select(int maxfd, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);
#endif /* ALARM_H */
......@@ -167,7 +167,7 @@ char *list_bind(const char *text, int state)
name = bind->from;
bind = bind->next;
if ((len == 0) || !strncasecmp(name, text, len))
return dupstr(name, "");
return strdup(name);
}
return NULL;
}
......
......@@ -61,7 +61,6 @@ CommandList chattable[]={
{"sa" ,0x0000 ,2, "Usage: sayto <user> <message>", "Talk normally but only to a single user", t_sayto, 1},
{"say" ,0x0000 ,2, "Usage: say <user> <message>", "Talk normally but only to a single user (deprecated)", t_sayto_warn, 0},
{"sayto" ,0x0000 ,2, "Usage: sayto <user> <message>", "Talk normally but only to a single user", t_sayto, 1},
{"scrhelp" ,0x0200 ,0, "Usage: scrhelp [command]", "List available script commands, or help on [command]", t_scrhelp, 1},
{"script" ,0x0200 ,0, "Usage: script [function]", "List script functions, or source code for [function]", t_script, 1},
{"shout" ,0x0000 ,1, "Usage: shout <message>", "Send message to all rooms", t_shout, 1},
{"spy" ,0x0100 ,1, "Usage: spy <on|off>", "Spy mode - see who said what", t_spy, 1},
......@@ -78,7 +77,6 @@ CommandList chattable[]={
{"unprotect" ,0x0020 ,1, "Usage: unprotect <user>", "Remove protection from user", t_unprotect, 1},
{"uptime" ,0x0000 ,0, "Usage: uptime", "Show server uptime", t_uptime, 1},
{"uri" ,0x0000 ,0, "Usage: uri [list [*|username] [n] | delete <id> | nsfw <id> | membersonly <id> | anonymous <id> | displaymode <full|short>]", "View/Edit the uris in the mwuri database", t_uri, 1},
{"variables" ,0x0200 ,0, "Usage: variables [mask]", "List script variables + contents [or starting with mask]", t_showvars, 1},
{"what" ,0x0000 ,0, "Usage: what", "See peoples status", t_what, 1},
{"whisper" ,0x0000 ,2, "Usage: whisper <user> <message>", "Send a message to a single user", t_whisper, 1},
{"who" ,0x0000 ,0, "Usage: who", "See who's about", t_who, 1},
......
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include "expand.h"
/* New arg expansion code */
#define EA_BRACE 1
#define EA_BRACKET 2
#define EA_PAREN 4
#define EA_COLON 8
/* Debug macros / vars */
#define SHOWSTATE() /* printf("%-20s%20s\n", exp_buf.start, in) */
static struct expand_buf exp_buf = {NULL,NULL,0};
static var_op_t exp_var;
static char *var_key = NULL;
static void expand_init(void);
static void ensure_capacity(int cap);
static void append_chars(const char *str, int len);
static void append_string(const char *str);
static const char *expand_arg(const char *in, int flags);
static const char *expand_variable(const char *in);
static const char *expand_identifier(const char *in);
static const char *expand_name_string(const char *in);
static const char *expand_index(const char *in, var_list_t *vars);
static void do_lookup(const char *start, const char *end);
static const char *expand_infix(const char *in);
static const char *eval_expr(const char *in);
static void argv_squish(int offset);
static void expand_init(void)
{
exp_buf.pos = exp_buf.start;
ensure_capacity(0);
*exp_buf.start = '\0';
}
void expand_close(void)
{
if (var_key) free(var_key);
if (exp_buf.start) free(exp_buf.start);
}
const char *eval_str(char *arg)
{
expand_init();
if (expand_arg(arg, EA_BRACE|EA_BRACKET|EA_PAREN))
return exp_buf.start;
else
return NULL;
}
int eval_var(const char *name, var_op_t *op)
{
expand_init();
if (expand_variable(name))
{
*op = exp_var;
var_key_dup(op);
return 1;
} else
return 0;
}
static void append_chars(const char *str, int len)
{
ensure_capacity(len);
memcpy(exp_buf.pos, str, len * sizeof(char));
*(exp_buf.pos += len) = '\0';
}
static void append_string(const char *str)
{
static int len;
len = strlen(str);
ensure_capacity(len);
strcpy(exp_buf.pos, str);
exp_buf.pos += len;
}
static void ensure_capacity(int cap)
{
static int offset;
offset = exp_buf.start? exp_buf.pos - exp_buf.start: 0;
cap += offset + 1;
if (!exp_buf.start || exp_buf.capacity < cap)
{
exp_buf.capacity = ((cap-1) | 0xfff) + 1; /* Round up to 4Kb */
exp_buf.start = realloc(exp_buf.start, exp_buf.capacity);
exp_buf.pos = exp_buf.start + offset;
}
}
static const char *expand_arg(const char *in, int flags)
{
static int length;
SHOWSTATE();
/*
printf("Entering expand_arg()\n");
ensure_capacity(2+strlen(in));
*/
while (*in)
{
switch(*in)
{
/* Brackets within bracketed expressions eg "$(2*(1+3))" must be
* balanced, for obvious reasons.
*/
case '{':
if (!(flags & EA_BRACE))
{
append_chars(in++, 1);
in = expand_arg(in, flags | ~EA_BRACE);
if (in && *in) append_chars(in++, 1);
break;
case '[':
if (!(flags & EA_BRACKET))
{
append_chars(in++, 1);
in = expand_arg(in, flags | ~EA_BRACKET);
if (in && *in) append_chars(in++, 1);
break;
case '(':
if (!(flags & EA_PAREN))
{
append_chars(in++, 1);
in = expand_arg(in, flags | ~EA_PAREN);
if (in && *in) append_chars(in++, 1);
break;
}
}
}
append_chars(in++, 1);
break;
/* Return on the last closing bracket */
case '}':
if (!(flags & EA_BRACE))
{
/*printf("Encountered brace; leaving expand_arg()\n");*/
return in;
case ']':
if (!(flags & EA_BRACKET))
{
/*printf("Encountered bracket; leaving expand_arg()\n");*/
return in;
case ')':
if (!(flags & EA_PAREN))
{
/*printf("Encountered parenthesis; leaving expand_arg()\n");*/
return in;
}
}
}
append_chars(in++, 1);
break;
default:
length = strcspn(in, "$[]{}()");
append_chars(in, length);
in += length;
break;
case '$':
switch (*++in)
{
case '$':
append_chars(in++, 1);
break;
case '*':
argv_squish(0);
SHOWSTATE();
++in;
break;
case '%':
argv_squish(1);
SHOWSTATE();
++in;
break;
case '^':
append_chars("$^", 2); /* Preserve for argv_shift() */
++in;
break;
case '[':
/*printf("Encountered '['; Expanding arithmetic expression\n");*/
in = expand_infix(++in); /* Quoted variable name */
if (!in) return NULL; /* Parse error */
if (*in) /* Allow omitting ']' at the end of an expression */
{
if (*in == ']') ++in; /* Skip over ']' */
else
{
SHOWSTATE();
/*printf("ERROR: ']' expected\n");*/
return NULL; /* Parse error */
}
}
break;
case '|': /* Shortcut for 'strlen' or array size */
ensure_capacity(30); /* Make room for the number */
in = expand_variable(++in);
if (!in) return(NULL);
if (VAR_TYPE_STR(&exp_var) || VAR_TYPE_INT(&exp_var))
{
/*printf("Inserting string length\n");*/
exp_buf.pos += snprintf(exp_buf.pos, 29, "%zu", strlen(var_str_val(&exp_var)));
} else if (VAR_TYPE_ARRAY(&exp_var))
{
static int count;
var_list_t *array = VAR_ARRAY_VAL(&exp_var);
count = 0;
VAR_LIST_ITERATE(&exp_var, array);
while (VAR_FOUND(&exp_var))
{
++count;
VAR_LIST_NEXT(&exp_var);
}
/*printf("Inserting array size\n");*/
exp_buf.pos += snprintf(exp_buf.pos, 29, "%d", count);
} else
append_string("");
SHOWSTATE();
break;
default:
in = expand_variable(in);
if (!in) return NULL;
/* We should have a string now */
if (VAR_TYPE_STR(&exp_var) || VAR_TYPE_INT(&exp_var))
append_string(var_str_val(&exp_var));
else
append_string("");
/* TODO: add sane expansions for arrays etc */
/*printf("Inserting variable value\n");*/
SHOWSTATE();
break;
}
break;
}
}
return in;
}
static const char *expand_variable(const char *in)
{
SHOWSTATE();
/*printf("Entering expand_variable()\n");*/
switch(*in)
{
default:
/* Start of an ordinary variable name */
in = expand_identifier(in);
break;
case '#':
/* Number of args passed to function */
do_lookup(in, in+1);
++in;
break;
case '{':
/*printf("Encountered '{'; Expanding name\n");*/
in = expand_name_string(++in); /* Quoted variable name */
if (in && *in) /* Allow omitting '}' at the end of an arg */
{
if (*in == '}') ++in; /* Skip over '}' */
else
{
SHOWSTATE();
/*printf("ERROR: '}' expected\n");*/
return NULL; /* Parse error */
}
}
break;
}
if (!in) return in;
/* Now check for array reference(s) */
while (1 == 2 && *in == '[') /* disabled for now */
{
/*printf("Encountered '['; ");*/
/* Find the array to search */
if (VAR_TYPE_ARRAY(&exp_var))
{
/*printf("Parsing array index\n");*/
/* Search for and expand the array element */
in = expand_index(++in, VAR_ARRAY_VAL(&exp_var));
SHOWSTATE();
} else
{
/* Leave strings alone for now. i.e. if $s == "fish" then */
/* $s[wibble] == "fish". */
/* Maybe we could add string slicing i.e. $s[2:3] == "is"? */
char *garbage_start = exp_buf.pos;
/*printf("Not an array - will ignore index\n");*/
in = expand_arg(++in, EA_BRACE|EA_PAREN);
*(exp_buf.pos = garbage_start) = '\0';
}
if (*in) /* Allow omitting ']' at the end of an arg */
{
if (*in == ']') ++in; /* Skip over '}' */
else
{
SHOWSTATE();
/*printf("ERROR: ']' expected\n");*/
return NULL; /* Parse error */
}
}
}
SHOWSTATE();
/*printf("Leaving expand_variable().\n");*/
return in;
}
/* Expand a simple identifier (alphanumerics and '_' only)
* IN: (none)
* OUT: name_start: Pointer to the expanded name within exp_buf
* var_key: Copy of the expanded name
* ARGS: in: The starting parse position in the input string
* RETURN: The end parse position
*/
static const char *expand_identifier(const char *in)
{
static const char *name_start;
static char c;
SHOWSTATE();
/*printf("Entering expand_identifier()\n");*/
name_start = in;
/* Optimisation - isalnum() is *slow* */
while (c = *in | 0x20,
(c >= 'a' && c <= 'z') ||
(c >= '0' && c <= '9') ||
*in == '_' ||
*in == '/')
++in;
/*while (isalnum(*in) || *in == '_') ++in;*/
SHOWSTATE();
/* We have an identifier; look it up in the variable list */
/*printf("Leaving expand_identifier()\n");*/
if (in <= name_start)
{
int len = strlen(in);
if (len>10) len=10;
snprintf(parse_error, 79, "Expected identifer, found \"%*s\"", len, in);
return NULL;
} else
{
/*printf("Looking up key: %s.\n", name_start);*/
do_lookup(name_start, in);
/*printf("Looked up key: %s.\n", name_start);*/
return in;
}
}
static const char *expand_name_string(const char *in)
{
char *name_start;
var_op_t saved_op;
char *saved_key;
SHOWSTATE();
/*printf("Entering expand_name_string()\n");*/
/* Recursively expand the quoted name */
saved_op = exp_var;
saved_key = var_key;
name_start = exp_buf.pos;
var_key = NULL;
in = expand_arg(in, EA_BRACKET|EA_PAREN);
if (var_key) free(var_key);
var_key = saved_key;
exp_var = saved_op;
if (!in) return NULL; /* Propagate parse errors */
/* We have an identifier; look it up in the variable list */
do_lookup(name_start, exp_buf.pos);
SHOWSTATE();
/*printf("Lookup complete; popping name\n");*/
*(exp_buf.pos = name_start) = 0; /* 'pop' the variable name */
SHOWSTATE();
/*printf("Leaving expand_name_string()\n");*/
return in;
}
/* Expand a key and search an array for it
* IN: (none)
* OUT: var_key: Copy of the key
* exp_var: Pointer to an array element if found
* name_start: Pointer to the key in the output string
* ARGS: in: The starting parse position in the input string
* array: The array to be searched
* RETURN: The end parse position
*/
static const char *expand_index(const char *in, var_list_t *array)
{
char *name_start;
var_op_t saved_op;
char *saved_key;
SHOWSTATE();
/*printf("Entering expand_index()\n");*/
/* Recursively expand the quoted name */
saved_op = exp_var;
saved_key = var_key;
name_start = exp_buf.pos;
var_key = NULL;
in = expand_arg(in, EA_BRACE|EA_PAREN);
if (var_key) free(var_key);
var_key = saved_key;
exp_var = saved_op;
if (!in) return NULL; /* Propagate parse errors */
/* We have a key; look it up in the array */
if (var_key) free(var_key);
var_key = calloc(exp_buf.pos + 1 - name_start, sizeof(char));
/*printf("expand_index: searching for key '%*s'\n", exp_buf.pos - name_start, name_start);*/
strncpy(var_key, name_start, exp_buf.pos - name_start);
VAR_OP_INIT(&exp_var, array);
VAR_SEARCH(&exp_var, var_key);
SHOWSTATE();
/*printf("Lookup complete; popping name\n");*/
*(exp_buf.pos = name_start) = 0; /* 'pop' the array index */
SHOWSTATE();
/*printf("Leaving expand_index()\n");*/
return in;
}
/* Look up the variable name pointed to by `name_start'
* OUT: var_key: Copy of the variable name
* exp_var: Pointer to a local/global variable if found
*/
static void do_lookup(const char *start, const char *end)
{
if (var_key) free(var_key);
var_key = calloc(end + 1 - start, sizeof(char));
strncpy(var_key, start, end - start);
/*printf("do_lookup: searching for variable '%s'\n", var_key);*/
VAR_OP_INIT(&exp_var, local_vars);
VAR_SEARCH(&exp_var, var_key);
if (!VAR_FOUND(&exp_var))
{
VAR_OP_INIT(&exp_var, &var_list);
VAR_SEARCH(&exp_var, var_key);
}
}
static void argv_squish(int offset)
{
int i;
int argc;
static char number[10];
static var_op_t op;
argc = arg_count(local_vars);
for (i=1;i<(argc-offset);i++)
{
snprintf(number, 9, "%d", i+offset);
VAR_OP_INIT(&op, local_vars);
VAR_SEARCH(&op, number);
if (VAR_FOUND(&op))
{
if (i>1) append_chars(" ", 1);
append_string(var_str_val(&op));
}
}
}
typedef enum
{
op_nop = 0,
op_notb = 0x10, op_uminus = 0x11, op_uplus = 0x12,
op_times = 0x20, op_div = 0x21, op_mod = 0x22,
op_plus = 0x30, op_minus = 0x31,
op_shl = 0x40, op_shr = 0x41, op_ushr = 0x42,
op_andb = 0x70, op_xorb = 0x71, op_orb = 0x72,
op_paren = 0x200, op_end = 0x210
} operator_t;
static long numstack[1024];
static operator_t opstack[1024];
static int stack_limit = 0;
static int numcount = 0, opcount = 0;
static int complete = 0;
char parse_error[80] = {0};
static int push_op(operator_t op)
{
if ((op < 0x20 && complete) ||
(op >= 0x20 && !complete))
{
snprintf(parse_error, 79, "Invalid operator #%d: complete=%d", op, complete);
return 0; /* Parse error */
}
/*printf("Pushing operator #%d.\n", op);*/
/*printf("Op stack size: %d; top: %d; new: %d.\n", opcount, (opstack[opcount-1] & ~0xf), (op & ~0xf));*/
while (opcount > stack_limit &&
(opstack[opcount-1] & ~0xf) <= (op & ~0xf))
{
--opcount;
if (opstack[opcount] >= op_paren &&
opstack[opcount] >= op)
{
break;
} else switch(opstack[opcount])
{
case op_uplus:
break; /* No calculation necessary */
case op_notb:
numstack[numcount-1] = ~numstack[numcount-1];
break;
case op_uminus:
numstack[numcount-1] = -numstack[numcount-1];
break;
case op_times:
numstack[numcount-2] *= numstack[numcount-1];
--numcount;
break;
case op_div:
numstack[numcount-2] /= numstack[numcount-1];
--numcount;
break;
case op_mod:
numstack[numcount-2] %= numstack[numcount-1];
--numcount;
break;
case op_plus:
numstack[numcount-2] += numstack[numcount-1];
--numcount;
break;
case op_minus:
numstack[numcount-2] -= numstack[numcount-1];
--numcount;
break;
case op_shl:
numstack[numcount-2] <<= numstack[numcount-1];
--numcount;
break;
case op_shr:
numstack[numcount-2] >>= numstack[numcount-1];
--numcount;
break;
case op_ushr:
numstack[numcount-2] = (unsigned long)numstack[numcount-2]
>> numstack[numcount-1];
--numcount;
break;
case op_andb:
numstack[numcount-2] &= numstack[numcount-1];
--numcount;
break;
case op_xorb:
numstack[numcount-2] ^= numstack[numcount-1];
--numcount;
break;
case op_orb:
numstack[numcount-2] |= numstack[numcount-1];
--numcount;
break;
default:
/* All remaining operators are no-ops */
break;
}
/*printf("Reducing to value: %d\n", numstack[numcount-1]);*/
/*printf("Op stack size: %d; top: %d.\n", opcount, (opstack[opcount-1] & ~0xf));*/
}
/*printf("Leaving push_op(); complete=%d.\n", complete);*/
complete = (op >= op_paren); /* There are no postfix operators */
if (!complete) /* Don't keep '(' after evaluating contents */
opstack[opcount++] = op;
return 1; /* Errors caught earlier */
}
static int push_num(int num)
{
if (complete)
{
snprintf(parse_error, 79, "Operator expected");
/*printf("Operator expected.\n");*/
return 0; /* Parse error */
} else
{
/*printf("Pushing value: %d.\n", num);*/
numstack[numcount++] = num;
complete = 1;
return 1;
}
}
static int push_paren(void)
{
if (complete)
{
/*printf("Error pushing '('.\n");*/
return 0; /* Parse error */
} else
{
opstack[opcount++] = op_paren;
return 1;
}
}
static const char *expand_infix(const char *in)
{
char *expr_start;
var_op_t saved_op;
char *saved_key;
char *expr_text;
int saved_limit;
SHOWSTATE();
/*printf("Entering expand_infix()\n");*/
/* Recursively expand the expression text */
expr_start = exp_buf.pos;
saved_op = exp_var;
saved_key = var_key;
var_key = NULL;
saved_limit = stack_limit;
stack_limit = opcount;
in = expand_arg(in, EA_PAREN|EA_BRACE);
complete = 0; /* Prepare for next expansion */
stack_limit = saved_limit;
if (var_key) free(var_key);
var_key = saved_key;
exp_var = saved_op;
if (!in) return NULL; /* Propagate parse errors */
/* We have an expression; Copy and evaluate it */
SHOWSTATE();
expr_text = calloc(exp_buf.pos + 1 - expr_start, sizeof(char));
strncpy(expr_text, expr_start, exp_buf.pos - expr_start);
/*printf("Expression copied; removing from buffer\n");*/
*(exp_buf.pos = expr_start) = 0; /* 'pop' the original expression */
if (!eval_expr(expr_text))
{ /* Error in expression */
free(expr_text);
return NULL;
}
SHOWSTATE();
/*printf("Leaving expand_infix()\n");*/
free(expr_text);
return in;
}
static const char *eval_expr(const char *in)
{
static int num;
SHOWSTATE();
/*printf("Entering eval_expr()\n");*/
while (*in)
{
if (isdigit(*in))
{
/* Parse & push a number */
if (!push_num(strtol(in, (char **)&in, 0)))
return NULL; /* Parse error */
} else if (isalpha(*in) || *in == '{')
{
/* Parse & push a variable. */
if ((in = expand_variable(in)) != NULL)
{
/*printf("Checking variable '%s'.\n", VAR_STR_KEY(&exp_var));*/
if (var_isanum(&exp_var, &num, 0))
{
if (!push_num(num))
{
snprintf(parse_error, 79, "Expected operator, found \"%8s\"", in);
}
} else
{
if (VAR_FOUND(&exp_var))
snprintf(parse_error, 79, "Value '%s' of variable '%s' is not a number", var_str_val(&exp_var), VAR_STR_KEY(&exp_var));
else
snprintf(parse_error, 79, "Variable '%s' not found", var_key);
return NULL; /* Not a number */
}
} else
{
snprintf(parse_error, 79, "expand_variable() failed");
return NULL; /* Parse error */
}
} else if (isspace(*in))
{
++in;
} else switch (*in++)
{
case '(':
if (push_paren()) break; else return NULL;
case ')':
if (push_op(op_paren))
{
/*printf("Remaining input: \"%s\"\n", in);*/
break;
} else
{
/*printf("Push of ')' failed!\n");*/
return NULL;
}
case '~': /* ~ is always unary */
if (push_op(op_notb)) break; else return NULL;
case '+': /* + and - have unary and binary variants */
if (complete)
{
if (!push_op(op_plus))
return NULL;
} else
if (!push_op(op_uplus))
return NULL;
break;
case '-':
if (complete)
{
if (!push_op(op_minus))
return NULL;
} else
if (!push_op(op_uminus))
return NULL;
break;
case '*': /* Others are always binary */
if (push_op(op_times)) break; else return NULL;
case '/':
if (push_op(op_div)) break; else return NULL;
case '%':
if (push_op(op_mod)) break; else return NULL;
case '^':
if (push_op(op_xorb)) break; else return NULL;
case '&':
if (push_op(op_andb)) break; else return NULL;
case '|':
if (push_op(op_orb)) break; else return NULL;
default:
snprintf(parse_error, 79, "Unexpected char in expression: \"%-12s...\"", --in);
return NULL; /* Parse error */
}
}
/*printf("Op stack size: %d; top: %d.\n", opcount, (opstack[opcount-1] & ~0xf));*/
if (push_op(op_end))
{
ensure_capacity(30);
exp_buf.pos += snprintf(exp_buf.pos, 29, "%ld", numstack[--numcount]);
return in;
} else
{
/* Stop errors affecting later expansions */
opcount = numcount = stack_limit = 0;
snprintf(parse_error, 79, "Unexpected end of expression");
return NULL;
}
}
#ifndef EXPAND_H
#define EXPAND_H
#include "script.h"
struct expand_buf
{
char *start, *pos;
int capacity;
};
/*typedef int var_func_t(var_op_t *op, void *arg);*/
extern char parse_error[];
const char *eval_str(char *arg);
/*int call_with_var_op(char *varname, var_func_t *func, void *arg);*/
int eval_var(const char *name, var_op_t *op);
void expand_close(void);
#endif /* EXPAND_H */
......@@ -24,21 +24,6 @@ static struct hashrec *hash_enter(const hash_op_t *op);
/*static struct hashrec *freerecs = 0;*/
static union fieldrec *freefields = NULL;
void hash_setup(void)
{
maxfields = INITIALFIELDS;
fields = calloc(maxfields , sizeof(*fields));
nextfield = 0;
capacity = INITIALBUCKETS;
buckets = calloc(capacity, sizeof(*buckets));
}
void hash_shutdown(void)
{
free(buckets);
free(fields);
}
int hash_alloc(void)
{
int newfield;
......
......@@ -50,8 +50,6 @@ typedef struct {
extern union fieldrec *fields;
extern int code;
extern void hash_setup(void);
extern void hash_shutdown(void);
extern int hash_alloc(void);
void hash_free(int field);
void hash_iterate(struct hashrec ***iter, int field);
......
......@@ -602,7 +602,7 @@ static void display_content(ipc_message_t *msg)
static void accept_pipe_cmd(ipc_message_t *msg, struct user *mesg_user)
{
enum ipc_types state = msg->head.type;
char *newbuff = msg->body;
char *newbuff = (char *)(msg + 1);
/*printf("\n<message type is %d>\n", state);*/
switch (state) {
......
......@@ -28,6 +28,8 @@
extern struct user * const user;
struct alarm *timeout_event = NULL;
int interrupt = 1;
int js_flood;
int js_flood_limit = JS_FLOOD_LIMIT_DEFAULT;
duk_context *ctx;
......@@ -403,8 +405,8 @@ static duk_ret_t js_say(duk_context *cx)
fprintf(stderr, "mwjs error: say() requires an argument\n");
return DUK_RET_SYNTAX_ERROR;
}
flood++;
if (flood > flood_limit) {
js_flood++;
if (js_flood > js_flood_limit) {
fprintf(stderr, "mwjs error: Script exceeded flood limit\n");
return DUK_RET_ERROR;
}
......
......@@ -26,4 +26,8 @@ enum bindtype {
const char *js_command_name_get(int x);
extern int js_flood;
#define JS_FLOOD_LIMIT_DEFAULT 15
extern int js_flood_limit;
#endif /* JS_H */
......@@ -673,8 +673,6 @@ int main(int argc, char **argv)
* we run the autoexec functions, so wholist etc can arrive */
idle( -1, 1);
/* initialise script variables */
script_init();
setup_js();
/* clear transient talker flags */
......@@ -896,8 +894,6 @@ void close_down(int logofftype, char *sourceuser, char *reason)
DestroyAllLinks(&ipc_list);
DestroyAllLinks(&shutdown_list);
ScriptCleanup();
RoomDestroy(&user->room);
ClearStack();
stop_js();
......@@ -1234,16 +1230,6 @@ void reset_timeout(int secs)
/* start of Readline Commands */
char *dupstr(const char *text, const char *prepend)
{
char *c;
c=(char *)malloc(strlen(text)+1+strlen(prepend));
strcpy(c,prepend);
strcat(c,text);
return(c);
}
static char *strip_commandname(char *line)
{
char *l2 = strdup(line);
......@@ -1565,9 +1551,13 @@ char *list_commands(const char *text, int state)
if (!strncasecmp(name, rtext, len) &&
( table[i].Rights==0 || ((rights&table[i].Rights)==table[i].Rights)))
{
const char *pre = cm_test(user, CM_ONCHAT) ? CMD_BOARD_STR : "";
char *ret;
free(rtext);
i++;
return (dupstr(name, cm_test(user, CM_ONCHAT) ? CMD_BOARD_STR : ""));
asprintf(&ret, "%s%s", pre, name);
return ret;
}
i++;
}
......@@ -1596,8 +1586,12 @@ char *list_chat_commands(const char *text, int state)
(chattable[i].Rights==0 || ((rights&chattable[i].Rights)==chattable[i].Rights)) &&
(chattable[i].Show == 1))
{
const char *pre = cm_test(user, CM_ONCHAT) ? CMD_TALK_STR : "";
char *ret;
i++;
return (dupstr(name, cm_test(user, CM_ONCHAT) ? CMD_TALK_STR:""));
asprintf(&ret, "%s%s", pre, name);
return ret;
}
i++;
}
......@@ -1626,7 +1620,7 @@ char *find_folder(const char *text, int state)
&& (allowed_r(fol,user)
|| allowed_w(fol,user))) /*allowed*/
if (len==0 || !strncasecmp(text,fol->name,len))
return (dupstr(fol->name, ""));
return strdup(fol->name);
}
close(file);
......@@ -1658,7 +1652,7 @@ char *part_user(const char *text, int status)
{
const char *name = usr.record.name;
if (len==0 || !strncasecmp(name, text, len))
return (dupstr(name, ""));
return strdup(name);
}
}
close(file);
......@@ -1682,7 +1676,7 @@ char *part_comm_user(const char *text, int status)
{
if (len==0 || !strncasecmp(partlist_user[ptr], text, len))
{
c=dupstr(partlist_user[ptr],"");
c = strdup(partlist_user[ptr]);
ptr++;
return(c);
}
......@@ -1708,7 +1702,7 @@ char *part_comm_search(const char *text, int status)
{
if (len==0 || !strncasecmp(partlist_search[ptr], text, len))
{
c=dupstr(partlist_search[ptr],"");
c = strdup(partlist_search[ptr]);
ptr++;
return(c);
}
......@@ -1734,7 +1728,7 @@ char *part_comm_folder(const char *text, int status)
{
if (len==0 || !strncasecmp(partlist_folder[ptr], text, len))
{
c=dupstr(partlist_folder[ptr],"");
c = strdup(partlist_folder[ptr]);
ptr++;
return(c);
}
......@@ -1760,7 +1754,7 @@ char *part_comm_mesg(const char *text, int status)
{
if (len==0 || !strncasecmp(partlist_mesg[ptr], text, len))
{
c=dupstr(partlist_mesg[ptr],"");
c = strdup(partlist_mesg[ptr]);
ptr++;
return(c);
}
......
......@@ -8,7 +8,6 @@ void printfile(const char *filename);
void reset_timeout(int secs);
int idle(int fd, int millis);
void set_rights(void);
char *dupstr(const char *text, const char *prepend);
char *part_user(const char *text, int status);
char *part_comm_search(const char *text, int status);
......
......@@ -94,7 +94,7 @@ void broadcast(int state, const char *fmt, ...)
json_t * j = json_init(NULL);
json_addstring(j, "text", buff);
json_addstring(j, "type", "status");
ipcmsg_json_encode(msg, j);
ipcmsg_json_encode(&msg, j);
json_decref(j);
ipcmsg_transmit(msg);
......
......@@ -23,7 +23,7 @@ int announce_logon(const char *usr, int type, int quiet)
msg = ipcmsg_create(IPC_CHECKONOFF, user->posn);
ipcmsg_destination(msg, SYSTEM_USER);
ipcmsg_json_encode(msg, j);
ipcmsg_json_encode(&msg, j);
json_decref(j);
ipcmsg_transmit(msg);
return 0;
......@@ -46,7 +46,7 @@ int announce_logoff(const char *usr, int type, const char *agent, const char *re
msg = ipcmsg_create(IPC_CHECKONOFF, user->posn);
ipcmsg_destination(msg, SYSTEM_USER);
ipcmsg_json_encode(msg, j);
ipcmsg_json_encode(&msg, j);
json_decref(j);
ipcmsg_transmit(msg);
return 0;
......@@ -68,7 +68,7 @@ int announce_join(const char *usr, int channel, int type, const char *agent, int
msg = ipcmsg_create(IPC_CHECKONOFF, user->posn);
ipcmsg_destination(msg, SYSTEM_USER);
ipcmsg_json_encode(msg, j);
ipcmsg_json_encode(&msg, j);
json_decref(j);
ipcmsg_transmit(msg);
return 0;
......@@ -92,7 +92,7 @@ int announce_leave(const char *usr, int channel, int type, const char *agent, co
msg = ipcmsg_create(IPC_CHECKONOFF, user->posn);
ipcmsg_destination(msg, SYSTEM_USER);
ipcmsg_json_encode(msg, j);
ipcmsg_json_encode(&msg, j);
json_decref(j);
ipcmsg_transmit(msg);
return 0;
......
......@@ -12,11 +12,9 @@
#include "talker_privs.h"
#include "strings.h"
#include "str_util.h"
#include "expand.h"
#include "talker.h"
#include "init.h"
#include "alias.h"
#include "script_inst.h"
#include "main.h"
#include "frl.h"
#include "js.h"
......@@ -24,6 +22,7 @@
#include "userio.h"
#include "who.h"
#include "gaglist.h"
#include "script.h"
#include <util.h>
#define MAX_ARGC 128
......@@ -45,9 +44,6 @@ char *event_body_text=NULL;
/* set runaway variable */
unsigned long run_away = RUNAWAY;
/* set flood limit */
int flood_limit = FLOODLIMIT;
/* how many script threads are currently running */
int script_running=0;
......@@ -64,45 +60,6 @@ int talker_logontype = 0;
static char *homedir = NULL;
static size_t homelen = 0;
void script_init(void)
{
hash_setup();
VAR_NEWLIST(&var_list);
}
char ** makeargs(int argc, const char **argv, int offset)
{
int num;
char **new;
int i;
num=argc-offset;
new=(char **)calloc(num+1, sizeof(char *));
for (i=0; i<num; i++)
{
new[i]=strdup(argv[offset+i]);
}
new[num]=NULL;
return (new);
}
static char *debug_info(const char *filename, int lineno)
{
char buff[512];
snprintf(buff, 511, "%s:%d", filename, lineno);
return ( strdup(buff) );
}
static int endchar(const char *haystack, char needle)
{
int len;
len=strlen(haystack);
if (haystack[len-1] == needle) return (1);
else return(0);
}
/* autoexecs any new initialisation functions */
void RunInitFuncs(int talkinit)
{
......@@ -135,250 +92,6 @@ void RunInitFuncs(int talkinit)
}
}
FuncNames scrtc[]={
{"talkname" ,part_who_talk},
{"whoname" ,part_who},
{"username" ,part_user},
{"gag" ,gaglist_tc_filter},
{"bind" ,list_bind},
{"boardexec" ,list_commands},
{"exec" ,list_chat_commands},
{"script" ,list_script},
{"null" ,NULL},
{NULL ,NULL}
};
void LoadFunction(char *funcname, char *header, FILE *file, int *lineno, const char *filename, int flags)
{
struct function *new;
char *buff = NULL;
char *line = NULL;
const char *bits[MAX_ARGC];
int num;
struct label *label=NULL;
struct code *codeend=NULL, *newcode;
Instruction *inst;
/* new vars for tab-completion */
const char *argv[MAX_ARGC];
int argc;
int lp;
FuncNames *fn = NULL;
int found;
new=function_list;
while (new!=NULL && strcasecmp(funcname, new->name)) new=new->next;
if (new!=NULL)
{
printf("Function %s already exists. Redefined at line %d in %s.\n", funcname, *lineno, filename);
buff = NULL;
while (!feof(file))
{
if ((buff = frl_line_nspace(file, "#")) == NULL) break;
*lineno+=num_lines_read();
if (!strcasecmp(buff, "endfunc")) break;
free(buff);
buff = NULL;
}
if (buff) free(buff);
return;
}
/* insert new function into the list */
new=(struct function *)malloc(sizeof(struct function));
new->name=strdup(funcname);
new->new=true;
new->code=NULL;
new->jump=NULL;
new->flags = flags;
/* add current function to function list */
/* new ordered insert - so tab-completion for script names works */
{
struct function *prev, *cur;
cur = function_list;
prev = NULL;
while (cur!=NULL && strcmp(cur->name,new->name) < 0)
{
prev=cur;
cur=cur->next;
}
/* start of list */
if (prev == NULL)
{
new->next = function_list;
function_list = new;
}
/* end of list */
else if (cur == NULL)
{
prev->next = new;
new->next = NULL;
}
/* middle of list */
else
{
new->next = cur;
prev->next = new;
}
}
/* work out tab-completion status information */
new->numcomp = 0;
new->complist = NULL;
argc = ParseLine(header, argv);
if (argc <= 2)
{
new->numcomp = 1;
new->complist = malloc(sizeof(CompletionList));
new->complist[0].Command = "";
new->complist[0].Mode = 2;
new->complist[0].FArg = 1;
new->complist[0].LArg = -1;
new->complist[0].CPFunction = part_who;
}
else
{
for (lp=2; lp<argc; lp++)
{
/* go through tab complete list */
fn = scrtc;
found = 0;
while(fn->name)
{
if (!strcasecmp(fn->name, argv[lp]))
{
found = 1;
break;
}
fn++;
}
/* handle special 'ad infinitum' sequence */
if (!strcasecmp("...", argv[lp])) found = 2;
/* if not found, skip arguments */
if (!found)
{
printf("Invalid argument type '%s' for function %s, on line %d in %s\n", argv[lp], funcname, *lineno, filename);
break;
}
else
{
/* completion function */
new->numcomp++;
new->complist = realloc(new->complist, sizeof(CompletionList) * new->numcomp);
new->complist[new->numcomp - 1].Command = "";
new->complist[new->numcomp - 1].Mode = 2;
new->complist[new->numcomp - 1].FArg = lp-1;
new->complist[new->numcomp - 1].LArg = (found==2)?-1:lp-1;
new->complist[new->numcomp - 1].CPFunction = fn->function;
/* if ad infinitum, skip rest of arguments */
if (found == 2) break;
}
}
}
while (!feof(file) && (line = frl_line(file)))
{
(*lineno)++;
if (strchr("#\n\r", line[0])!=NULL) { free(line); continue; }
num=ParseLine(line, bits);
if (num==0) { free(line); continue; }
if (bits[0][0]=='#') { free(line); continue; }
if (!strcasecmp(bits[0], "endfunc")) break;
if (endchar(bits[0], ':'))
{
char *p;
if ((p=strrchr(bits[0],':'))!=NULL) *p=0;
label=new->jump;
while (label!=NULL && strcasecmp(bits[0], label->name))
label=label->next;
if (label!=NULL)
{
printf("Label %s referenced at %s:%d already in use at %s\n", label->name, filename, *lineno, label->debug);
label=NULL;
free(line);
continue;
}
label=(struct label *)malloc(sizeof(struct label));
label->name=strdup(bits[0]);
label->debug=debug_info(filename, *lineno);
label->next=new->jump;
label->where=NULL; /* fill in later */
new->jump=label;
}else
{
inst=inst_table;
while (inst->name != NULL && strcasecmp(inst->name, bits[0])) {
inst++;
}
if (inst->name==NULL)
{
printf("Invalid instruction '%s' at line %d of file %s\n", bits[0], *lineno, filename);
free(line);
continue;
}
newcode=(struct code *)malloc(sizeof(struct code));
newcode->inst=inst;
newcode->argc=num-1;
newcode->argv=makeargs(num, bits, 1);
newcode->debug=debug_info(filename, *lineno);
newcode->parent=new;
newcode->next=NULL;
if (new->code==NULL)
{
new->code=newcode;
codeend=newcode;
}else
{
codeend->next=newcode;
codeend=newcode;
}
/* fill in the labels */
if (label!=NULL)
{
label=new->jump;
while (label!=NULL) {
if (label->where==NULL)
label->where=newcode;
label=label->next;
}
label=NULL;
}
}
free(line);
}
if (line) free(line);
/* automatic return at the end of a function if theres a label hanging open. */
if (new->code!=NULL && label!=NULL) {
inst=inst_table;
while (inst->name != NULL && strcasecmp(inst->name, "return")) {
inst++;
}
newcode=(struct code *)malloc(sizeof(struct code));
newcode->inst=inst;
newcode->argc=0;
newcode->argv=NULL;
newcode->debug=debug_info(filename, *lineno);
newcode->parent=new;
newcode->next=NULL;
codeend->next=newcode;
label=new->jump;
while (label!=NULL) {
if (label->where==NULL)
label->where=newcode;
label=label->next;
}
label=NULL;
}
}
void DestroyFunction(const char *funcname)
{
struct function *func, *funcold;
......@@ -472,121 +185,6 @@ void DestroyAllFunctions(int debug)
}
}
/***************
*** HELP
***************/
void scr_helpfile(const char *args)
{
Instruction *inst;
if (args!=NULL &&(strchr(args,'.')!=NULL || strchr(args,'/')!=NULL))
{
printf("Sorry, no help available on that subject. *:-)\n");
return;
}
if (args==NULL)
{
const char *x = SCRIPTHELP"/general";
if (!access(x,00))
printfile(x);
else
printf("No general help available on scripts.\n");
}else
{
_autofree char *x = NULL;
inst=inst_table;
while (inst->name != NULL && strcasecmp(inst->name, args)) {
inst++;
}
if (inst->name!=NULL)
{
if ((rights&inst->Rights) != inst->Rights)
{
printf("Sorry, no help available on that subject. *:-)\n");
return;
}
}
asprintf(&x, SCRIPTHELP"/%s", args);
if (x != NULL && !access(x,00))
printfile(x);
else
printf("No help available on that subject.\n");
}
}
void scr_helplist(void)
{
int count;
char buff[10];
Instruction *c = inst_table;
int screen_height = screen_h();
count=0;
printf("Available commands:-\n");
while (c->name)
{
if ((rights&c->Rights) == c->Rights) {
printf("%20s - %s\n",c->name,c->help);
count++;
}
c++;
if (count>=(screen_height-2))
{
printf("---more---\r");
get_str(buff, 5);
printf(" \r");
if (*buff=='q' || *buff=='Q') return;
count=0;
}
}
}
void ListVars(const char *srch)
{
var_op_t op;
int count=0;
int screen_height = screen_h();
char buff[MAXTEXTLENGTH];
if (local_vars)
VAR_LIST_ITERATE(&op, local_vars);
else
VAR_LIST_ITERATE(&op, &var_list);
while (VAR_FOUND(&op))
{
if (srch == NULL || !strncasecmp(srch, VAR_STR_KEY(&op), strlen(srch)))
{
snprintf(buff, MAXTEXTLENGTH-1, "Variable '%s'", VAR_STR_KEY(&op));
if (var_str_val(&op)==NULL)
strncat(buff, " is set but invalid\n", MAXTEXTLENGTH - strlen(buff) - 1);
else
{
strncat(buff, " contains value '", MAXTEXTLENGTH - strlen(buff) - 1);
strncat(buff, var_str_val(&op), MAXTEXTLENGTH - strlen(buff) - 1);
strncat(buff, "'\n", MAXTEXTLENGTH - strlen(buff) - 1);
}
/*display_message(buff, 0, 1);*/
escprintf("%s", buff);
count++;
}
if (count>=(screen_height-2))
{
printf("---more---\r");
get_str(buff, 5);
printf(" \r");
if (*buff=='q' || *buff=='Q') return;
count=0;
}
VAR_LIST_NEXT(&op);
}
}
/***************
** Runtime...
***************/
......@@ -598,66 +196,14 @@ int script_offset=0; /* how far have we 'shift'ed the args */
struct code *script_jump;
unsigned long runaway=0; /* count how many instructions executed to stop infinite loops */
int flood=0; /* stop room flooding by a script */
int script_debug=0; /* print verbose debug info */
int script_terminate;
int ExecInst(char *line)
{
const char *bits[MAX_ARGC];
int num;
Instruction *inst;
struct code *pc;
num=ParseLine(line, bits);
if (num==0)
{
printf("- WARNING (ExecInst): No Instruction to Execute\n");
return 0;
}
inst=inst_table;
while (inst->name != NULL && strcasecmp(inst->name, bits[0])) {
inst++;
}
if (inst->name==NULL)
{
printf("- WARNING (ExecInst): Invalid Instruction (%s)\n", bits[0]);
return 0;
}
pc=(struct code *)malloc(sizeof(struct code));
pc->inst=inst;
pc->argc=num-1;
pc->argv=makeargs(num, bits, 1);
pc->debug=strdup("ExecInst");
pc->parent=NULL;
pc->next=NULL;
if ((rights&pc->inst->Rights) == pc->inst->Rights)
{
pc->inst->Function(pc, 0, 0);
}
free(pc->debug);
for (num=0; num < pc->argc; num++)
{
free(pc->argv[num]);
}
free(pc->argv);
free(pc);
return 1;
}
void DoScript(char *line)
{
const char *bits[MAX_ARGC];
var_list_t args;
int num;
int i;
char *function_name;
flood=0;
int num;
if ((num=ParseLine(line, bits))<1) return;
......@@ -667,166 +213,14 @@ void DoScript(char *line)
printf("Script bind '%s' not found.\n", bits[0]);
return;
}
if (is_js(function_name)) {
if (is_js(function_name))
js_exec(function_name, num, bits);
free(function_name);
return;
}
free(function_name);
runaway=0;
script_terminate=0;
script_jump=NULL;
compare_count=0;
compare_match=0;
script_offset=0;
script_running=1;
if (event_user!=NULL) free(event_user);
event_user=NULL;
busy++;
VAR_NEWLIST(&args);
ARG_RANGE(&args, 0, num-1);
for (i=0; i<num; ++i)
ARG_STR_FORCE(&args, i, bits[i]);
switch (ExecScript(bits[0], &args, 1))
{
case 1:
printf("Script function for bind '%s' not found.\n", bits[0]);
break;
case 2:
printf("Script bind '%s' not found.\n", bits[0]);
break;
default:
break;
}
VAR_FREELIST(&args);
script_running=0;
busy--;
}
static void Push_Comparisons(int cc, int cm)
{
CompStack *temp;
temp=malloc(sizeof(CompStack));
temp->compare = cc;
temp->match = cm;
temp->next = comparison_stack;
comparison_stack = temp;
}
static void Pop_Comparisons(int *cc, int *cm)
{
CompStack *temp;
if ((temp = comparison_stack) == NULL)
{
*cm = 0;
*cc = 0;
}
else
{
*cc = temp->compare;
*cm = temp->match;
comparison_stack = comparison_stack->next;
free(temp);
}
}
int ExecScript(const char *name, var_list_t *vars, int bound)
{
struct function *script;
struct code *pc;
char *function_name=NULL;
int old_rights;
/* publically named scripts */
if (bound)
{
if ((function_name = FindLinks(bind_list, name)) == NULL)
{
return(2);
}
}
/* otherwise use the name were given */
if (function_name==NULL) function_name=strdup(name);
/* look for a defined function by that name */
script=function_list;
while (script!=NULL && strcasecmp(function_name, script->name)) script=script->next;
if (script==NULL)
{
/* okay, so its not a mwscript function */
free(function_name);
return(1);
}
/* backup old rights, and set talker rights */
old_rights = current_rights;
set_talk_rights();
/* push current comparison counters onto the stack. */
/* first time this happens, values are ignored, as we use current values, not those on stack. */
/* this is horrible, but cant be bothered to change _everything_ */
Push_Comparisons(compare_count, compare_match);
compare_count = 0;
compare_match = 0;
/*found script and now runing */
pc=script->code;
local_vars = vars;
while (pc!=NULL && !script_terminate)
{
runaway++;
if ((run_away > 0) && (runaway > run_away))
{
printf("Runaway script got to %lu instructions at %s\n", runaway, pc->debug);
break;
}
if (script_debug)
{
int i;
escprintf("%s: %s ", pc->debug, pc->inst->name);
for (i=0;i<pc->argc;i++) escprintf("'%s' ",pc->argv[i]);
printf("\n");
}
if ((rights&pc->inst->Rights) == pc->inst->Rights)
{
pc->inst->Function( pc, 0, 0);
local_vars = vars;
}
pc=pc->next;
if (script_jump!=NULL)
{ /* execute a goto */
pc=script_jump;
script_jump=NULL;
}
}
/* pop old comparison counters off the stack */
Pop_Comparisons(&compare_count, &compare_match);
if (script_terminate==1) script_terminate=0;
free(function_name);
local_vars = NULL;
/* restore old rights */
if (old_rights == RIGHTS_BBS) set_rights();
return(0);
}
int ExecEvent(char *script, const char *text, const char *event, const char *who, int pre)
{
int retval;
var_list_t args;
if (is_js(script)) {
const char *argv[4];
......@@ -839,44 +233,11 @@ int ExecEvent(char *script, const char *text, const char *event, const char *who
busy--;
return retval;
}
runaway=0;
if (!script_running) { flood=0;}
script_terminate=0;
script_jump=NULL;
compare_count=0;
compare_match=0;
script_offset=0;
if (event_user!=NULL) free(event_user);
VAR_NEWLIST(&args);
ARG_RANGE(&args, 0, 3);
ARG_STR_FORCE(&args, 0, event);
ARG_STR_FORCE(&args, 1, text);
if (who!=NULL)
{
event_user=strdup(who);
/*ARG_STR_FORCE(&args, 2, strdup(who)); */
}else
{
event_user=NULL;
/*ARG_STR_FORCE(&args, 2, strdup("")); */
}
if (event_body_text!=NULL) free(event_body_text);
event_body_text = strdup(text+pre);
/*ARG_STR_FORCE(&args, 3, strdup(event_body_text)); */
busy++;
retval = ExecScript(script, &args, 0);
VAR_FREELIST(&args);
busy--;
return(retval);
return 0;
}
int ExecEvent2(char *script, const char *event, const char *who, int pre, int numargs, char *aargs[])
{
var_list_t args;
int retval, i;
if (is_js(script)) {
......@@ -890,46 +251,7 @@ int ExecEvent2(char *script, const char *event, const char *who, int pre, int nu
free(argv);
return retval;
}
runaway=0;
if (!script_running) { flood=0;}
script_terminate=0;
script_jump=NULL;
compare_count=0;
compare_match=0;
script_offset=0;
script_output=1;
if (event_user!=NULL) free(event_user);
VAR_NEWLIST(&args);
ARG_RANGE(&args, 0, numargs+1);
ARG_STR_FORCE(&args, 0, event);
for (i = 0; i < numargs; i++)
{
ARG_STR_FORCE(&args, i + 1, aargs[i]);
}
if (who!=NULL)
{
event_user=strdup(who);
}else
{
event_user=NULL;
}
if (event_body_text!=NULL) free(event_body_text);
if (numargs == 0)
event_body_text = strdup("");
else
event_body_text = strdup(aargs[0] + pre);
busy++;
retval = ExecScript(script, &args, 0);
VAR_FREELIST(&args);
busy--;
return(retval);
return 0;
}
void ListScript(const char *name)
......@@ -958,117 +280,6 @@ void ListScript(const char *name)
}
}
char *eval_arg(char *arg, int argc, char **argv)
{
const char *value = eval_str(arg);
if (value)
return strdup(value);
else
{
printf("Parse error in expansion of \"%s\": %s.\n", arg, parse_error);
return strdup("{error}");
}
}
char ** argv_shift(int argc, char **argv, int offset, int *newsize)
{
char **new;
char buff[13];
int i, idx, num;
char *text;
int fargc;
char **fargv = 0;
num=argc-offset;
fargc = arg_count(local_vars);
*newsize=0;
for (i=0; i<num; i++)
{
text = eval_arg(argv[offset+i], fargc, fargv);
if (!strncasecmp(text, "$^", 2))
{
int start=2;
if (strlen(text)>2)
{
int ts;
ts = atoi(&text[2]);
if (ts > start) start = ts;
}
(*newsize)+=fargc-start;
}
else (*newsize)++;
free(text);
}
/* fixed problem if there arent enough arguments to cope with $^n */
if (*newsize < 0) *newsize = 0;
new=(char **)calloc((*newsize)+1, sizeof(char *));
idx=0;
for (i=0; i<num; i++)
{
text = eval_arg(argv[offset+i], fargc, fargv);
if (!strncasecmp(text, "$^", 2))
{
int j;
int start=2;
if (strlen(text)>2)
{
int ts;
ts = atoi(&text[2]);
if (ts > start) start = ts;
}
for (j=0; j<fargc-start; j++)
{
snprintf(buff, 12, "$%d", j+start);
new[idx]=eval_arg(buff, fargc, fargv);
idx++;
}
}
else
{
new[idx]=eval_arg(argv[offset+i], fargc, fargv);
idx++;
}
free(text);
}
new[idx]=NULL;
return (new);
}
void DestroyVariables(int debug)
{
VAR_FREELIST(&var_list);
}
void ScriptCleanup(void)
{
DestroyAllFunctions(0);
DestroyVariables(0);
expand_close();
hash_shutdown();
if (homedir) free (homedir);
}
void scr_devel_msg(struct code *pc, const char *fmt, ...)
{
va_list va;
char text[MAXTEXTLENGTH];
va_start(va, fmt);
vsnprintf(text, MAXTEXTLENGTH-1, fmt, va);
va_end(va);
if (cp_test(user, CP_DEVEL))
printf("- WARNING (%s): %s, in %s\n", pc->inst->name, text, pc->debug);
}
/* script function autocompletion for readline */
char *list_script(const char *text, int state)
{
......@@ -1093,7 +304,7 @@ char *list_script(const char *text, int state)
/* only if an interface function (default) */
if (hidden == false)
{
return dupstr(name, "");
return strdup(name);
}
}
}
......
......@@ -218,8 +218,6 @@ struct function {
struct function *next;
};
extern int flood;
extern int flood_limit;
extern int script_terminate;
extern int script_debug;
extern var_list_t var_list;
......@@ -234,14 +232,8 @@ extern int script_offset;
extern volatile int script_output;
extern char *event_user;
char *eval_arg(char *arg, int argc, char **argv);
char ** makeargs(int argc, const char **argv, int offset);
char ** argv_shift(int argc, char **argv, int offset, int *newsize);
void CallFunction(struct code *code, int argc, char **argv);
int ExecInst(char *line);
void scr_devel_msg(struct code *pc, const char *fmt, ...) __attribute__((format(printf,2,3)));
void RunInitFuncs(int talkinit);
extern void LoadFunction(char *, char *, FILE *, int *, const char *, int);
int arg_count(var_list_t *list);
int var_isanum(var_op_t *op, int *result, int onlydecimal);
......@@ -251,25 +243,16 @@ char *list_script(const char *text, int state);
char *list_mwsfile(const char *text, int state);
int expand_script_dir(char **dir);
void var_str_force_2(const char *name, const char *val);
char *var_str_val(var_op_t *op);
void var_key_dup(var_op_t *op);
extern void DoScript(char *line);
int ExecScript(const char *name, var_list_t *args, int bound);
int ExecEvent(char *script, const char *text, const char *event, const char *who, int pre);
int ExecEvent2(char *script, const char *event, const char *who, int pre, int numargs, char *aargs[]);
void ListScript(const char *name);
void ListVars(const char *srch);
void ScriptCleanup(void);
void DestroyAllFunctions(int debug);
void DestroyFunction(const char *funcname);
void DestroyVariables(int debug);
void script_init(void);
void scr_helpfile(const char *args);
void scr_helplist(void);
#endif /* SCRIPT_H */
This diff is collapsed.
#ifndef SCRIPT_INST_H
#define SCRIPT_INST_H
#include "script.h"
/*** Instruction set for the scripting language */
void scr_base( struct code *, int, char **);
void scr_beep( struct code *, int, char **);
void scr_boolopt( struct code *, int, char **);
void scr_case( struct code *, int, char **);
void scr_clearvars( struct code *, int, char **);
void scr_compare( struct code *, int, char **);
void scr_end( struct code *, int, char **);
void scr_exec( struct code *, int, char **);
void scr_getvar( struct code *, int, char **);
void scr_inlist( struct code *, int, char **);
void scr_input( struct code *, int, char **);
void scr_isanum( struct code *, int, char **);
void scr_ison( struct code *, int, char **);
void scr_jump( struct code *, int, char **);
void scr_listvars( struct code *, int, char **);
void scr_local( struct code *, int, char **);
void scr_logoninfo( struct code *, int, char **);
void scr_makestr( struct code *, int, char **);
void scr_math( struct code *, int, char **);
void scr_math2( struct code *, int, char **);
void scr_output( struct code *, int, char **);
void scr_print( struct code *, int, char **);
void scr_quit( struct code *, int, char **);
void scr_rand( struct code *, int, char **);
void scr_range( struct code *, int, char **);
void scr_regex( struct code *, int, char **);
void scr_return( struct code *, int, char **);
void scr_room( struct code *, int, char **);
void scr_roomnum( struct code *, int, char **);
void scr_say( struct code *, int, char **);
void scr_sayto( struct code *, int, char **);
void scr_sendipc( struct code *, int, char **);
void scr_sendrpc( struct code *, int, char **);
void scr_set( struct code *, int, char **);
void scr_showrunaway( struct code *, int, char **);
void scr_sleep( struct code *, int, char **);
void scr_split( struct code *, int, char **);
void scr_strcat( struct code *, int, char **);
void scr_string( struct code *, int, char **);
void scr_talkpriv( struct code *, int, char **);
void scr_time( struct code *, int, char **);
void scr_unset( struct code *, int, char **);
void scr_user( struct code *, int, char **);
void scr_version( struct code *, int, char **);
void scr_wholist( struct code *, int, char **);
int isanumul(const char *a, unsigned long *result, int onlydecimal);
int isanum(const char *a, int *result, int onlydecimal);
extern Instruction inst_table[];
#endif /* SCRIPT_INST_H */