/*
* functions.c - MUX function handlers
*/
/*
* $Id: functions.c,v 1.11 2005/07/01 14:01:02 av1-op Exp $
*/
#include "copyright.h"
#include "config.h"
#include <limits.h>
#include <math.h>
#include "mudconf.h"
#include "db.h"
#include "flags.h"
#include "powers.h"
#include "attrs.h"
#include "externs.h"
#include "match.h"
#include "command.h"
#include "functions.h"
#include "misc.h"
#include "alloc.h"
#include "ansi.h"
#include "comsys.h"
#include "interface.h"
UFUN *ufun_head;
extern NAMETAB indiv_attraccess_nametab[];
extern int game_lag(void);
extern void cf_log_notfound(dbref player, char *cmd,
const char *thingname, char *thing);
/*
* Function definitions from funceval.c
*/
extern void fun_btdesignex();
extern void fun_btgetcharvalue();
extern void fun_btmakemechs();
extern void fun_btmapelev();
extern void fun_btmapterr();
extern void fun_btsetcharvalue();
extern void fun_btgetxcodevalue();
extern void fun_btmakepilotroll();
extern void fun_btsetxcodevalue();
extern void fun_btstores();
extern void fun_btunderrepair();
extern void fun_btdamages();
extern void fun_btcritstatus();
extern void fun_btarmorstatus();
extern void fun_btsetarmorstatus();
extern void fun_btweaponstatus();
extern void fun_btthreshold();
extern void fun_btdamagemech();
extern void fun_bttechstatus();
extern void fun_btpartmatch();
extern void fun_btpartname();
extern void fun_btloadmap();
extern void fun_btloadmech();
extern void fun_btmechfreqs();
extern void fun_btmapunits();
extern void fun_btgetxcodevalue_ref();
extern void fun_btarmorstatus_ref();
extern void fun_btcritstatus_ref();
extern void fun_btweaponstatus_ref();
extern void fun_btid2db();
extern void fun_bthexlos();
extern void fun_btlosm2m();
extern void fun_bthexemit();
extern void fun_btgetweight();
extern void fun_btpartweight();
extern void fun_btaddstores();
extern void fun_btremovestores();
extern void fun_bttechtime();
extern void fun_btcritslot();
extern void fun_btcritslot_ref();
extern void fun_btgetrange();
extern void fun_btsetmaxspeed();
extern void fun_btgetrealmaxspeed();
extern void fun_btgetbv();
extern void fun_btgetbv_ref();
extern void fun_bttechlist();
extern void fun_bttechlist_ref();
extern void fun_btpayload_ref();
extern void fun_btshowstatus_ref();
extern void fun_btshowwspecs_ref();
extern void fun_btshowcritstatus_ref();
extern void fun_btengrate();
extern void fun_btengrate_ref();
extern void fun_btweapstat();
extern void fun_btnumrepjobs();
extern void fun_btsetxy();
extern void fun_btmapemit();
extern void fun_btparttype();
#ifdef BT_ADVANCED_ECON
extern void fun_btgetpartcost();
extern void fun_btsetpartcost();
extern void fun_btfasabasecost_ref();
#endif
extern void fun_btunitfixable();
extern void fun_btlistblz();
extern void fun_bthexinblz();
extern void fun_btcharlist();
extern void fun_cobj();
extern void fun_config();
extern void fun_cwho();
extern void fun_clist();
extern void fun_cemit();
extern void fun_beep();
extern void fun_ansi();
extern void fun_zone();
extern void fun_frank2num();
extern void fun_fnum2rank();
#ifdef SIDE_EFFECT_FUNCTIONS
extern void fun_link();
extern void fun_tel();
extern void fun_pemit();
extern void fun_create();
extern void fun_set();
extern void fun_setlock();
#endif
extern void fun_last();
extern void fun_matchall();
extern void fun_ports();
extern void fun_mix();
extern void fun_foreach();
extern void fun_munge();
extern void fun_visible();
extern void fun_elements();
extern void fun_grab();
extern void fun_scramble();
extern void fun_shuffle();
extern void fun_sortby();
extern void fun_default();
extern void fun_edefault();
extern void fun_udefault();
extern void fun_findable();
extern void fun_isword();
extern void fun_hasattr();
extern void fun_hasattrp();
extern void fun_zwho();
extern void fun_zplayers();
extern void fun_inzone();
extern void fun_children();
extern void fun_encrypt();
extern void fun_decrypt();
extern void fun_objeval();
extern void fun_squish();
extern void fun_stripansi();
extern void fun_zfun();
extern void fun_columns();
extern void fun_playmem();
#ifdef USE_PYTHON
extern void fun_python();
extern void fun_pythoncall();
#endif
extern void fun_objmem();
extern void fun_orflags();
extern void fun_andflags();
extern void fun_strtrunc();
extern void fun_ifelse();
extern void fun_inc();
extern void fun_dec();
extern void fun_mail();
extern void fun_mailfrom();
extern void fun_die();
extern void fun_lit();
extern void fun_shl();
extern void fun_shr();
extern void fun_vadd();
extern void fun_vsub();
extern void fun_vmul();
extern void fun_vmag();
extern void fun_vunit();
extern void fun_vdim();
extern void fun_strcat();
extern void fun_grep();
extern void fun_grepi();
extern void fun_art();
extern void fun_alphamax();
extern void fun_alphamin();
extern void fun_valid();
extern void fun_hastype();
extern void fun_lparent();
extern void fun_empty();
extern void fun_push();
extern void fun_peek();
extern void fun_pop();
extern void fun_items();
extern void fun_lstack();
extern void fun_regmatch();
extern void fun_translate();
/*
* This is for functions that take an optional delimiter character
*/
#define varargs_preamble(xname,xnargs) \
if (!fn_range_check(xname, nfargs, xnargs-1, xnargs, buff, bufc)) \
return; \
if (!delim_check(fargs, nfargs, xnargs, &sep, buff, bufc, 0, \
player, cause, cargs, ncargs)) \
return;
#define evarargs_preamble(xname,xnargs) \
if (!fn_range_check(xname, nfargs, xnargs-1, xnargs, buff, bufc)) \
return; \
if (!delim_check(fargs, nfargs, xnargs, &sep, buff, bufc, 1, \
player, cause, cargs, ncargs)) \
return;
#define mvarargs_preamble(xname,xminargs,xnargs) \
if (!fn_range_check(xname, nfargs, xminargs, xnargs, buff, bufc)) \
return; \
if (!delim_check(fargs, nfargs, xnargs, &sep, buff, bufc, 0, \
player, cause, cargs, ncargs)) \
return;
/*
* Trim off leading and trailing spaces if the separator char is a space
*/
char *trim_space_sep(str, sep)
char *str, sep;
{
char *p;
if (sep != ' ')
return str;
while (*str && (*str == ' '))
str++;
for (p = str; *p; p++);
for (p--; *p == ' ' && p > str; p--);
p++;
*p = '\0';
return str;
}
/*
* next_token: Point at start of next token in string
*/
char *next_token(str, sep)
char *str, sep;
{
while (*str && (*str != sep))
str++;
if (!*str)
return NULL;
str++;
if (sep == ' ') {
while (*str == sep)
str++;
}
return str;
}
/*
* split_token: Get next token from string as null-term string. String is
* * destructively modified.
*/
char *split_token(sp, sep)
char **sp, sep;
{
char *str, *save;
save = str = *sp;
if (!str) {
*sp = NULL;
return NULL;
}
while (*str && (*str != sep))
str++;
if (*str) {
*str++ = '\0';
if (sep == ' ') {
while (*str == sep)
str++;
}
} else {
str = NULL;
}
*sp = str;
return save;
}
dbref match_thing(player, name)
dbref player;
char *name;
{
init_match(player, name, NOTYPE);
match_everything(MAT_EXIT_PARENTS);
return (noisy_match_result());
}
/*
* ---------------------------------------------------------------------------
* * List management utilities.
*/
#define ALPHANUM_LIST 1
#define NUMERIC_LIST 2
#define DBREF_LIST 3
#define FLOAT_LIST 4
static int autodetect_list(ptrs, nitems)
char *ptrs[];
int nitems;
{
int sort_type, i;
char *p;
sort_type = NUMERIC_LIST;
for (i = 0; i < nitems; i++) {
switch (sort_type) {
case NUMERIC_LIST:
if (!is_number(ptrs[i])) {
/*
* If non-numeric, switch to alphanum sort. *
*
* * * * * * Exception: if this is the
* first * element * * and * it is a good
* dbref, * switch to a * * dbref sort. *
* We're a * little looser than * * the
* normal * 'good * dbref' rules, any * *
* number following # * the #-sign is
* accepted.
*/
if (i == 0) {
p = ptrs[i];
if (*p++ != NUMBER_TOKEN) {
return ALPHANUM_LIST;
} else if (is_integer(p)) {
sort_type = DBREF_LIST;
} else {
return ALPHANUM_LIST;
}
} else {
return ALPHANUM_LIST;
}
} else if (index(ptrs[i], '.')) {
sort_type = FLOAT_LIST;
}
break;
case FLOAT_LIST:
if (!is_number(ptrs[i])) {
sort_type = ALPHANUM_LIST;
return ALPHANUM_LIST;
}
break;
case DBREF_LIST:
p = ptrs[i];
if (*p++ != NUMBER_TOKEN)
return ALPHANUM_LIST;
if (!is_integer(p))
return ALPHANUM_LIST;
break;
default:
return ALPHANUM_LIST;
}
}
return sort_type;
}
static int get_list_type(fargs, nfargs, type_pos, ptrs, nitems)
char *fargs[], *ptrs[];
int nfargs, nitems, type_pos;
{
if (nfargs >= type_pos) {
switch (ToLower(*fargs[type_pos - 1])) {
case 'd':
return DBREF_LIST;
case 'n':
return NUMERIC_LIST;
case 'f':
return FLOAT_LIST;
case '\0':
return autodetect_list(ptrs, nitems);
default:
return ALPHANUM_LIST;
}
}
return autodetect_list(ptrs, nitems);
}
int list2arr(arr, maxlen, list, sep)
char *arr[], *list, sep;
int maxlen;
{
char *p;
int i;
list = trim_space_sep(list, sep);
p = split_token(&list, sep);
for (i = 0; p && i < maxlen; i++, p = split_token(&list, sep)) {
arr[i] = p;
}
return i;
}
void arr2list(arr, alen, list, bufc, sep)
char *arr[], **bufc, *list, sep;
int alen;
{
int i;
for (i = 0; i < alen; i++) {
safe_str(arr[i], list, bufc);
safe_chr(sep, list, bufc);
}
if (*bufc != list)
(*bufc)--;
}
static int dbnum(dbr)
char *dbr;
{
if ((strlen(dbr) < 2) && (*dbr != '#'))
return 0;
else
return atoi(dbr + 1);
}
/*
* ---------------------------------------------------------------------------
* * nearby_or_control: Check if player is near or controls thing
*/
int nearby_or_control(player, thing)
dbref player, thing;
{
if (!Good_obj(player) || !Good_obj(thing))
return 0;
if (Controls(player, thing))
return 1;
if (!nearby(player, thing))
return 0;
return 1;
}
/*
* ---------------------------------------------------------------------------
* * fval: copy the floating point value into a buffer and make it presentable
*/
static void fval(buff, bufc, result)
char *buff, **bufc;
double result;
{
char *p, *buf1;
buf1 = *bufc;
safe_tprintf_str(buff, bufc, "%.6f", result); /*
* get double val * *
* into buffer
*/
**bufc = '\0';
p = (char *) rindex(buf1, '0');
if (p == NULL) { /*
* remove useless trailing 0's
*/
return;
} else if (*(p + 1) == '\0') {
while (*p == '0') {
*p-- = '\0';
}
*bufc = p + 1;
}
p = (char *) rindex(buf1, '.'); /*
* take care of dangling '.'
*/
if ((p != NULL) && (*(p + 1) == '\0')) {
*p = '\0';
*bufc = p;
}
}
/*
* ---------------------------------------------------------------------------
* * fn_range_check: Check # of args to a function with an optional argument
* * for validity.
*/
int fn_range_check(fname, nfargs, minargs, maxargs, result, bufc)
const char *fname;
char *result, **bufc;
int nfargs, minargs, maxargs;
{
if ((nfargs >= minargs) && (nfargs <= maxargs))
return 1;
if (maxargs == (minargs + 1))
safe_tprintf_str(result, bufc,
"#-1 FUNCTION (%s) EXPECTS %d OR %d ARGUMENTS", fname, minargs,
maxargs);
else
safe_tprintf_str(result, bufc,
"#-1 FUNCTION (%s) EXPECTS BETWEEN %d AND %d ARGUMENTS", fname,
minargs, maxargs);
return 0;
}
/*
* ---------------------------------------------------------------------------
* * delim_check: obtain delimiter
*/
int delim_check(fargs, nfargs, sep_arg, sep, buff, bufc, eval, player,
cause, cargs, ncargs)
char *fargs[], *cargs[], *sep, *buff, **bufc;
int nfargs, ncargs, sep_arg, eval;
dbref player, cause;
{
char *tstr, *bp, *str;
int tlen;
if (nfargs >= sep_arg) {
tlen = strlen(fargs[sep_arg - 1]);
if (tlen <= 1)
eval = 0;
if (eval) {
tstr = bp = alloc_lbuf("delim_check");
str = fargs[sep_arg - 1];
exec(tstr, &bp, 0, player, cause, EV_EVAL | EV_FCHECK, &str,
cargs, ncargs);
*bp = '\0';
tlen = strlen(tstr);
*sep = *tstr;
free_lbuf(tstr);
}
if (tlen == 0) {
*sep = ' ';
} else if (tlen != 1) {
safe_str("#-1 SEPARATOR MUST BE ONE CHARACTER", buff, bufc);
return 0;
} else if (!eval) {
*sep = *fargs[sep_arg - 1];
}
} else {
*sep = ' ';
}
return 1;
}
/*
* ---------------------------------------------------------------------------
* * fun_words: Returns number of words in a string.
* * Added 1/28/91 Philip D. Wasson
*/
int countwords(str, sep)
char *str, sep;
{
int n;
str = trim_space_sep(str, sep);
if (!*str)
return 0;
for (n = 0; str; str = next_token(str, sep), n++);
return n;
}
static void fun_words(char *buff, char **bufc, dbref player, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs)
{
char sep;
if (nfargs == 0) {
safe_str("0", buff, bufc);
return;
}
varargs_preamble("WORDS", 2);
safe_tprintf_str(buff, bufc, "%d", countwords(fargs[0], sep));
}
/*
* fun_flags: Returns the flags on an object.
* Because @switch is case-insensitive, not quite as useful as it could be.
*/
static void fun_flags(char *buff, char **bufc, dbref player, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs)
{
dbref it;
char *buff2;
it = match_thing(player, fargs[0]);
if ((it != NOTHING) && (mudconf.pub_flags || Examinable(player, it) ||
(it == cause))) {
buff2 = unparse_flags(player, it);
safe_str(buff2, buff, bufc);
free_sbuf(buff2);
} else
safe_str("#-1", buff, bufc);
return;
}
/*
* ---------------------------------------------------------------------------
* * fun_rand: Return a random number from 0 to arg1-1
*/
static void fun_rand(char *buff, char **bufc, dbref player, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs)
{
int num;
num = atoi(fargs[0]);
if (num < 1)
safe_str("0", buff, bufc);
else
safe_tprintf_str(buff, bufc, "%ld", (random() % num));
}
/*
* ---------------------------------------------------------------------------
* * fun_abs: Returns the absolute value of its argument.
*/
static void fun_abs(char *buff, char **bufc, dbref player, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs)
{
double num;
num = atof(fargs[0]);
if (num == 0.0) {
safe_str("0", buff, bufc);
} else if (num < 0.0) {
fval(buff, bufc, -num);
} else {
fval(buff, bufc, num);
}
}
/*
* ---------------------------------------------------------------------------
* * fun_sign: Returns -1, 0, or 1 based on the the sign of its argument.
*/
static void fun_sign(char *buff, char **bufc, dbref player, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs)
{
double num;
num = atof(fargs[0]);
if (num < 0)
safe_str("-1", buff, bufc);
else if (num > 0)
safe_str("1", buff, bufc);
else
safe_str("0", buff, bufc);
}
extern char *silly_atr_get(dbref, int);
time_t mytime(dbref player)
{
struct timeval tv;
struct timezone tz;
char *tzstr;
int hours, dst;
tzstr = silly_atr_get(player, A_TZ);
if (sscanf(tzstr, "%d:%d", &hours, &dst) < 2)
return mudstate.now;
tz.tz_minuteswest = (0 - hours) * 60;
tz.tz_dsttime = dst;
gettimeofday(&tv, &tz);
return tv.tv_sec;
}
/*
* ---------------------------------------------------------------------------
* * fun_time: Returns nicely-formatted time.
*/
static void fun_time(char *buff, char **bufc, dbref player, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs)
{
char *temp;
temp = (char *) ctime(&mudstate.now);
temp[strlen(temp) - 1] = '\0';
safe_str(temp, buff, bufc);
}
/*
* ---------------------------------------------------------------------------
* * fun_time: Seconds since 0:00 1/1/70
*/
static void fun_secs(char *buff, char **bufc, dbref player, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs)
{
safe_tprintf_str(buff, bufc, "%d", mudstate.now);
}
/*
* ---------------------------------------------------------------------------
* * fun_convsecs: converts seconds to time string, based off 0:00 1/1/70
*/
static void fun_convsecs(char *buff, char **bufc, dbref player, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs)
{
char *temp;
time_t tt;
tt = atol(fargs[0]);
temp = (char *) ctime(&tt);
temp[strlen(temp) - 1] = '\0';
safe_str(temp, buff, bufc);
}
/*
* ---------------------------------------------------------------------------
* * fun_convtime: converts time string to seconds, based off 0:00 1/1/70
* * additional auxiliary function and table used to parse time string,
* * since no ANSI standard function are available to do this.
*/
static const char *monthtab[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
};
static const char daystab[] = { 31, 29, 31, 30, 31, 30,
31, 31, 30, 31, 30, 31
};
/*
* converts time string to a struct tm. Returns 1 on success, 0 on fail.
* * Time string format is always 24 characters long, in format
* * Ddd Mmm DD HH:MM:SS YYYY
*/
#define get_substr(buf, p) { \
p = (char *)index(buf, ' '); \
if (p) { \
*p++ = '\0'; \
while (*p == ' ') p++; \
} \
}
int do_convtime(str, ttm)
char *str;
struct tm *ttm;
{
char *buf, *p, *q;
int i;
if (!str || !ttm)
return 0;
while (*str == ' ')
str++;
buf = p = alloc_sbuf("do_convtime"); /*
* make a temp copy of arg
*/
safe_sb_str(str, buf, &p);
*p = '\0';
get_substr(buf, p); /*
* day-of-week or month
*/
if (!p || strlen(buf) != 3) {
free_sbuf(buf);
return 0;
}
for (i = 0; (i < 12) && string_compare(monthtab[i], p); i++);
if (i == 12) {
get_substr(p, q); /*
* month
*/
if (!q || strlen(p) != 3) {
free_sbuf(buf);
return 0;
}
for (i = 0; (i < 12) && string_compare(monthtab[i], p); i++);
if (i == 12) {
free_sbuf(buf);
return 0;
}
p = q;
}
ttm->tm_mon = i;
get_substr(p, q); /*
* day of month
*/
if (!q || (ttm->tm_mday = atoi(p)) < 1 || ttm->tm_mday > daystab[i]) {
free_sbuf(buf);
return 0;
}
p = (char *) index(q, ':'); /*
* hours
*/
if (!p) {
free_sbuf(buf);
return 0;
}
*p++ = '\0';
if ((ttm->tm_hour = atoi(q)) > 23 || ttm->tm_hour < 0) {
free_sbuf(buf);
return 0;
}
if (ttm->tm_hour == 0) {
while (isspace(*q))
q++;
if (*q != '0') {
free_sbuf(buf);
return 0;
}
}
q = (char *) index(p, ':'); /*
* minutes
*/
if (!q) {
free_sbuf(buf);
return 0;
}
*q++ = '\0';
if ((ttm->tm_min = atoi(p)) > 59 || ttm->tm_min < 0) {
free_sbuf(buf);
return 0;
}
if (ttm->tm_min == 0) {
while (isspace(*p))
p++;
if (*p != '0') {
free_sbuf(buf);
return 0;
}
}
get_substr(q, p); /*
* seconds
*/
if (!p || (ttm->tm_sec = atoi(q)) > 59 || ttm->tm_sec < 0) {
free_sbuf(buf);
return 0;
}
if (ttm->tm_sec == 0) {
while (isspace(*q))
q++;
if (*q != '0') {
free_sbuf(buf);
return 0;
}
}
get_substr(p, q); /*
* year
*/
if ((ttm->tm_year = atoi(p)) == 0) {
while (isspace(*p))
p++;
if (*p != '0') {
free_sbuf(buf);
return 0;
}
}
free_sbuf(buf);
if (ttm->tm_year > 100)
ttm->tm_year -= 1900;
if (ttm->tm_year < 0) {
return 0;
}
#define LEAPYEAR_1900(yr) ((yr)%400==100||((yr)%100!=0&&(yr)%4==0))
return (ttm->tm_mday != 29 || i != 1 || LEAPYEAR_1900(ttm->tm_year));
#undef LEAPYEAR_1900
}
static void fun_convtime(char *buff, char **bufc, dbref player, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs)
{
struct tm *ttm;
ttm = localtime(&mudstate.now);
if (do_convtime(fargs[0], ttm))
safe_tprintf_str(buff, bufc, "%d", timelocal(ttm));
else
safe_str("-1", buff, bufc);
}
/*
* ---------------------------------------------------------------------------
* * fun_convuptime: Converts number to minutes/secs/days
*/
#define UPTIME_UNITS 6
struct {
int multip;
char *name;
char *sname;
} uptime_unit_table[UPTIME_UNITS] = {
{
60 *60 * 24 * 30 * 12, "year", "y"}, {
60 *60 * 24 * 30, "month", "m"}, {
60 *60 * 24, "day", "d"}, {
60 *60, "hour", "h"}, {
60, "minute", "m"}, {
1, "second", "s"}
};
char *get_uptime_to_string(int uptime)
{
char *buf = alloc_sbuf("get_uptime_to_string");
int units[UPTIME_UNITS];
int taim = uptime;
int ut = 0, uc = 0, foofaa;
if (uptime <= 0) {
strcpy(buf, "#-1 INVALID VALUE");
return buf;
}
for (ut = 0; ut < UPTIME_UNITS; ut++)
units[ut] = 0;
ut = 0;
buf[0] = 0;
while (taim > 0) {
if ((foofaa = (taim / uptime_unit_table[ut].multip)) > 0) {
uc++;
units[ut] = foofaa;
taim -= uptime_unit_table[ut].multip * foofaa;
}
ut++;
}
/*
* Now, we got it..
*/
for (ut = 0; ut < UPTIME_UNITS; ut++) {
if (units[ut]) {
uc--;
if (units[ut] > 1)
sprintf(buf + strlen(buf), "%d %ss", units[ut],
uptime_unit_table[ut].name);
else
sprintf(buf + strlen(buf), "%d %s", units[ut],
uptime_unit_table[ut].name);
if (uc > 1)
strcat(buf, ", ");
else if (uc > 0)
strcat(buf, " and ");
}
}
return buf;
}
char *get_uptime_to_short_string(int uptime)
{
char *buf = alloc_sbuf("get_uptime_to_string");
int units[UPTIME_UNITS];
int taim = uptime;
int ut = 0, uc = 0, foofaa;
if (uptime <= 0) {
strcpy(buf, "#-1 INVALID VALUE");
return buf;
}
for (ut = 0; ut < UPTIME_UNITS; ut++)
units[ut] = 0;
ut = 0;
buf[0] = 0;
while (taim > 0) {
if ((foofaa = (taim / uptime_unit_table[ut].multip)) > 0) {
uc++;
units[ut] = foofaa;
taim -= uptime_unit_table[ut].multip * foofaa;
}
ut++;
}
/*
* Now, we got it..
*/
for (ut = 0; ut < UPTIME_UNITS; ut++) {
if (units[ut]) {
uc--;
if (units[ut] > 1)
sprintf(buf + strlen(buf), "%d%s", units[ut],
uptime_unit_table[ut].sname);
else
sprintf(buf + strlen(buf), "%d%s", units[ut],
uptime_unit_table[ut].sname);
if (uc > 0)
strcat(buf, " ");
}
}
return buf;
}
static void fun_convuptime(char *buff, char **bufc, dbref player, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs)
{
char *uptimestring = get_uptime_to_string(atoi(fargs[0]));
safe_str(uptimestring, buff, bufc);
free_sbuf(uptimestring);
}
#ifdef BT_ENABLED
static void fun_lag(char *buff, char **bufc, dbref player, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs)
{
char buf[256];
sprintf(buf, "%d", game_lag());
safe_str(buf, buff, bufc);
}
#endif
/*
* ---------------------------------------------------------------------------
* * fun_starttime: What time did this system last reboot?
*/
static void fun_starttime(char *buff, char **bufc, dbref player, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs)
{
char *temp;
temp = (char *) ctime(&mudstate.start_time);
temp[strlen(temp) - 1] = '\0';
safe_str(temp, buff, bufc);
}
/*
* ---------------------------------------------------------------------------
* * fun_get, fun_get_eval: Get attribute from object.
*/
int check_read_perms(player, thing, attr, aowner, aflags, buff, bufc)
dbref player, thing;
ATTR *attr;
int aowner, aflags;
char *buff, **bufc;
{
int see_it;
/*
* If we have explicit read permission to the attr, return it
*/
if (See_attr_explicit(player, thing, attr, aowner, aflags))
return 1;
/*
* If we are nearby or have examine privs to the attr and it is * * *
*
* * visible to us, return it.
*/
see_it = See_attr(player, thing, attr, aowner, aflags);
if ((Examinable(player, thing) || nearby(player, thing) ||
See_All(player)) && see_it)
return 1;
/*
* For any object, we can read its visible attributes, EXCEPT * for *
*
* * * * descs, which are only visible if read_rem_desc is on.
*/
if (see_it) {
if (!mudconf.read_rem_desc && (attr->number == A_DESC)) {
safe_str("#-1 TOO FAR AWAY TO SEE", buff, bufc);
return 0;
} else {
return 1;
}
}
safe_str("#-1 PERMISSION DENIED", buff, bufc);
return 0;
}
static void fun_get(char *buff, char **bufc, dbref player, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs)
{
dbref thing, aowner;
int attrib, free_buffer, aflags;
ATTR *attr;
char *atr_gotten;
struct boolexp *bool;
if (!parse_attrib(player, fargs[0], &thing, &attrib)) {
safe_str("#-1 NO MATCH", buff, bufc);
return;
}
if (attrib == NOTHING) {
return;
}
free_buffer = 1;
attr = atr_num(attrib); /*
* We need the attr's flags for this:
*/
if (!attr) {
return;
}
if (attr->flags & AF_IS_LOCK) {
atr_gotten = atr_get(thing, attrib, &aowner, &aflags);
if (Read_attr(player, thing, attr, aowner, aflags)) {
bool = parse_boolexp(player, atr_gotten, 1);
free_lbuf(atr_gotten);
atr_gotten = unparse_boolexp(player, bool);
free_boolexp(bool);
} else {
free_lbuf(atr_gotten);
atr_gotten = (char *) "#-1 PERMISSION DENIED";
}
free_buffer = 0;
} else {
atr_gotten = atr_pget(thing, attrib, &aowner, &aflags);
}
/*
* Perform access checks. c_r_p fills buff with an error message * *
*
* * * * if needed.
*/
if (check_read_perms(player, thing, attr, aowner, aflags, buff, bufc))
safe_str(atr_gotten, buff, bufc);
if (free_buffer)
free_lbuf(atr_gotten);
return;
}
static void fun_xget(char *buff, char **bufc, dbref player, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs)
{
dbref thing, aowner;
int attrib, free_buffer, aflags;
ATTR *attr;
char *atr_gotten;
struct boolexp *bool;
if (!*fargs[0] || !*fargs[1])
return;
if (!parse_attrib(player, tprintf("%s/%s", fargs[0], fargs[1]), &thing,
&attrib)) {
safe_str("#-1 NO MATCH", buff, bufc);
return;
}
if (attrib == NOTHING) {
return;
}
free_buffer = 1;
attr = atr_num(attrib); /*
* We need the attr's flags for this:
*/
if (!attr) {
return;
}
if (attr->flags & AF_IS_LOCK) {
atr_gotten = atr_get(thing, attrib, &aowner, &aflags);
if (Read_attr(player, thing, attr, aowner, aflags)) {
bool = parse_boolexp(player, atr_gotten, 1);
free_lbuf(atr_gotten);
atr_gotten = unparse_boolexp(player, bool);
free_boolexp(bool);
} else {
free_lbuf(atr_gotten);
atr_gotten = (char *) "#-1 PERMISSION DENIED";
}
free_buffer = 0;
} else {
atr_gotten = atr_pget(thing, attrib, &aowner, &aflags);
}
/*
* Perform access checks. c_r_p fills buff with an error message * *
*
* * * * if needed.
*/
if (check_read_perms(player, thing, attr, aowner, aflags, buff, bufc))
safe_str(atr_gotten, buff, bufc);
if (free_buffer)
free_lbuf(atr_gotten);
return;
}
static void fun_get_eval(char *buff, char **bufc, dbref player, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs)
{
dbref thing, aowner;
int attrib, free_buffer, aflags, eval_it;
ATTR *attr;
char *atr_gotten, *str;
struct boolexp *bool;
if (!parse_attrib(player, fargs[0], &thing, &attrib)) {
safe_str("#-1 NO MATCH", buff, bufc);
return;
}
if (attrib == NOTHING) {
return;
}
free_buffer = 1;
eval_it = 1;
attr = atr_num(attrib); /*
* We need the attr's flags for this:
*/
if (!attr) {
return;
}
if (attr->flags & AF_IS_LOCK) {
atr_gotten = atr_get(thing, attrib, &aowner, &aflags);
if (Read_attr(player, thing, attr, aowner, aflags)) {
bool = parse_boolexp(player, atr_gotten, 1);
free_lbuf(atr_gotten);
atr_gotten = unparse_boolexp(player, bool);
free_boolexp(bool);
} else {
free_lbuf(atr_gotten);
atr_gotten = (char *) "#-1 PERMISSION DENIED";
}
free_buffer = 0;
eval_it = 0;
} else {
atr_gotten = atr_pget(thing, attrib, &aowner, &aflags);
}
if (!check_read_perms(player, thing, attr, aowner, aflags, buff, bufc)) {
if (free_buffer)
free_lbuf(atr_gotten);
return;
}
if (eval_it) {
str = atr_gotten;
exec(buff, bufc, 0, thing, player, EV_FIGNORE | EV_EVAL, &str,
(char **) NULL, 0);
} else {
safe_str(atr_gotten, buff, bufc);
}
if (free_buffer)
free_lbuf(atr_gotten);
return;
}
static void fun_subeval(char *buff, char **bufc, dbref player, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs)
{
char *str;
if (nfargs != 1) {
safe_str("#-1 FUNCTION (EVALNOCOMP) EXPECTS 1 OR 2 ARGUMENTS",
buff, bufc);
return;
}
str = fargs[0];
exec(buff, bufc, 0, player, cause,
EV_NO_LOCATION | EV_NOFCHECK | EV_FIGNORE | EV_NO_COMPRESS, &str,
(char **) NULL, 0);
}
static void fun_eval(char *buff, char **bufc, dbref player, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs)
{
dbref thing, aowner;
int attrib, free_buffer, aflags, eval_it;
ATTR *attr;
char *atr_gotten, *str;
struct boolexp *bool;
if ((nfargs != 1) && (nfargs != 2)) {
safe_str("#-1 FUNCTION (EVAL) EXPECTS 1 OR 2 ARGUMENTS", buff,
bufc);
return;
}
if (nfargs == 1) {
str = fargs[0];
exec(buff, bufc, 0, player, cause, EV_EVAL, &str, (char **) NULL,
0);
return;
}
if (!*fargs[0] || !*fargs[1])
return;
if (!parse_attrib(player, tprintf("%s/%s", fargs[0], fargs[1]), &thing,
&attrib)) {
safe_str("#-1 NO MATCH", buff, bufc);
return;
}
if (attrib == NOTHING) {
return;
}
free_buffer = 1;
eval_it = 1;
attr = atr_num(attrib);
if (!attr) {
return;
}
if (attr->flags & AF_IS_LOCK) {
atr_gotten = atr_get(thing, attrib, &aowner, &aflags);
if (Read_attr(player, thing, attr, aowner, aflags)) {
bool = parse_boolexp(player, atr_gotten, 1);
free_lbuf(atr_gotten);
atr_gotten = unparse_boolexp(player, bool);
free_boolexp(bool);
} else {
free_lbuf(atr_gotten);
atr_gotten = (char *) "#-1 PERMISSION DENIED";
}
free_buffer = 0;
eval_it = 0;
} else {
atr_gotten = atr_pget(thing, attrib, &aowner, &aflags);
}
if (!check_read_perms(player, thing, attr, aowner, aflags, buff, bufc)) {
if (free_buffer)
free_lbuf(atr_gotten);
return;
}
if (eval_it) {
str = atr_gotten;
exec(buff, bufc, 0, thing, player, EV_FIGNORE | EV_EVAL, &str,
(char **) NULL, 0);
} else {
safe_str(atr_gotten, buff, bufc);
}
if (free_buffer)
free_lbuf(atr_gotten);
return;
}
/*
* ---------------------------------------------------------------------------
* * fun_u and fun_ulocal: Call a user-defined function.
*/
static void do_ufun(buff, bufc, player, cause, fargs, nfargs, cargs,
ncargs, is_local)
char *buff, **bufc;
dbref player, cause;
char *fargs[], *cargs[];
int nfargs, ncargs, is_local;
{
dbref aowner, thing;
int aflags, anum, i;
ATTR *ap;
char *atext, *preserve[MAX_GLOBAL_REGS], *str;
/*
* We need at least one argument
*/
if (nfargs < 1) {
safe_str("#-1 TOO FEW ARGUMENTS", buff, bufc);
return;
}
/*
* Two possibilities for the first arg: <obj>/<attr> and <attr>.
*/
if (parse_attrib(player, fargs[0], &thing, &anum)) {
if ((anum == NOTHING) || (!Good_obj(thing)))
ap = NULL;
else
ap = atr_num(anum);
} else {
thing = player;
ap = atr_str(fargs[0]);
}
/*
* Make sure we got a good attribute
*/
if (!ap) {
return;
}
/*
* Use it if we can access it, otherwise return an error.
*/
atext = atr_pget(thing, ap->number, &aowner, &aflags);
if (!atext) {
free_lbuf(atext);
return;
}
if (!*atext) {
free_lbuf(atext);
return;
}
if (!check_read_perms(player, thing, ap, aowner, aflags, buff, bufc)) {
free_lbuf(atext);
return;
}
/*
* If we're evaluating locally, preserve the global registers.
*/
if (is_local) {
for (i = 0; i < MAX_GLOBAL_REGS; i++) {
if (!mudstate.global_regs[i])
preserve[i] = NULL;
else {
preserve[i] = alloc_lbuf("u_regs");
StringCopy(preserve[i], mudstate.global_regs[i]);
}
}
}
/*
* Evaluate it using the rest of the passed function args
*/
str = atext;
exec(buff, bufc, 0, thing, cause, EV_FCHECK | EV_EVAL, &str,
&(fargs[1]), nfargs - 1);
free_lbuf(atext);
/*
* If we're evaluating locally, restore the preserved registers.
*/
if (is_local) {
for (i = 0; i < MAX_GLOBAL_REGS; i++) {
if (preserve[i]) {
if (!mudstate.global_regs[i])
mudstate.global_regs[i] = alloc_lbuf("u_reg");
StringCopy(mudstate.global_regs[i], preserve[i]);
free_lbuf(preserve[i]);
} else {
if (mudstate.global_regs[i])
*(mudstate.global_regs[i]) = '\0';
}
}
}
}
static void fun_u(char *buff, char **bufc, dbref player, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs)
{
do_ufun(buff, bufc, player, cause, fargs, nfargs, cargs, ncargs, 0);
}
static void fun_ulocal(char *buff, char **bufc, dbref player, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs)
{
do_ufun(buff, bufc, player, cause, fargs, nfargs, cargs, ncargs, 1);
}
/*
* ---------------------------------------------------------------------------
* * fun_parent: Get parent of object.
*/
static void fun_parent(char *buff, char **bufc, dbref player, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs)
{
dbref it;
it = match_thing(player, fargs[0]);
if (Good_obj(it) && (Examinable(player, it) || (it == cause))) {
safe_tprintf_str(buff, bufc, "#%d", Parent(it));
} else {
safe_str("#-1", buff, bufc);
}
return;
}
/*
* ---------------------------------------------------------------------------
* * fun_parse: Make list from evaluating arg3 with each member of arg2.
* * arg1 specifies a delimiter character to use in the parsing of arg2.
* * NOTE: This function expects that its arguments have not been evaluated.
*/
static void fun_parse(char *buff, char **bufc, dbref player, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs)
{
char *curr, *objstring, *buff2, *buff3, *cp, sep;
char *dp, *str;
int first, number = 0;
evarargs_preamble("PARSE", 3);
cp = curr = dp = alloc_lbuf("fun_parse");
str = fargs[0];
exec(curr, &dp, 0, player, cause, EV_STRIP | EV_FCHECK | EV_EVAL, &str,
cargs, ncargs);
*dp = '\0';
cp = trim_space_sep(cp, sep);
if (!*cp) {
free_lbuf(curr);
return;
}
first = 1;
while (cp) {
if (!first)
safe_chr(' ', buff, bufc);
first = 0;
number++;
objstring = split_token(&cp, sep);
buff2 = replace_string(BOUND_VAR, objstring, fargs[1]);
buff3 =
replace_string(LISTPLACE_VAR, tprintf("%d", number), buff2);
str = buff3;
exec(buff, bufc, 0, player, cause, EV_STRIP | EV_FCHECK | EV_EVAL,
&str, cargs, ncargs);
free_lbuf(buff2);
free_lbuf(buff3);
}
free_lbuf(curr);
}
/*
* ---------------------------------------------------------------------------
* * fun_mid: mid(foobar,2,3) returns oba
*/
static void fun_mid(char *buff, char **bufc, dbref player, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs)
{
int l, len;
char *oldp;
oldp = *bufc;
l = atoi(fargs[1]);
len = atoi(fargs[2]);
if ((l < 0) || (len < 0) || ((len + l) > LBUF_SIZE) || ((len + 1) < 0)) {
safe_str("#-1 OUT OF RANGE", buff, bufc);
return;
}
if (l < strlen(strip_ansi(fargs[0])))
safe_str(strip_ansi(fargs[0]) + l, buff, bufc);
oldp[len] = 0;
if ((oldp + len) < *bufc) {
*bufc = oldp + len;
}
}
/*
* ---------------------------------------------------------------------------
* * fun_first: Returns first word in a string
*/
static void fun_first(char *buff, char **bufc, dbref player, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs)
{
char *s, *first, sep;
/*
* If we are passed an empty arglist return a null string
*/
if (nfargs == 0) {
return;
}
varargs_preamble("FIRST", 2);
s = trim_space_sep(fargs[0], sep); /*
* leading spaces ...
*/
first = split_token(&s, sep);
if (first) {
safe_str(first, buff, bufc);
}
}
/*
* ---------------------------------------------------------------------------
* * fun_rest: Returns all but the first word in a string
*/
static void fun_rest(char *buff, char **bufc, dbref player, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs)
{
char *s, *first, sep;
/*
* If we are passed an empty arglist return a null string
*/
if (nfargs == 0) {
return;
}
varargs_preamble("REST", 2);
s = trim_space_sep(fargs[0], sep); /*
* leading spaces ...
*/
first = split_token(&s, sep);
if (s) {
safe_str(s, buff, bufc);
}
}
/*
* ---------------------------------------------------------------------------
* * fun_v: Function form of %-substitution
*/
static void fun_v(char *buff, char **bufc, dbref player, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs)
{
dbref aowner;
int aflags;
char *sbuf, *sbufc, *tbuf, *str;
ATTR *ap;
tbuf = fargs[0];
if (isalpha(tbuf[0]) && tbuf[1]) {
/*
* Fetch an attribute from me. First see if it exists, * * *
*
* * returning a null string if it does not.
*/
ap = atr_str(fargs[0]);
if (!ap) {
return;
}
/*
* If we can access it, return it, otherwise return a * null
* * * * string
*/
atr_pget_info(player, ap->number, &aowner, &aflags);
if (See_attr(player, player, ap, aowner, aflags)) {
tbuf = atr_pget(player, ap->number, &aowner, &aflags);
safe_str(tbuf, buff, bufc);
free_lbuf(tbuf);
}
return;
}
/*
* Not an attribute, process as %<arg>
*/
sbuf = alloc_sbuf("fun_v");
sbufc = sbuf;
safe_sb_chr('%', sbuf, &sbufc);
safe_sb_str(fargs[0], sbuf, &sbufc);
*sbufc = '\0';
str = sbuf;
exec(buff, bufc, 0, player, cause, EV_FIGNORE, &str, cargs, ncargs);
free_sbuf(sbuf);
}
/*
* ---------------------------------------------------------------------------
* * fun_s: Force substitution to occur.
*/
static void fun_s(char *buff, char **bufc, dbref player, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs)
{
char *str;
str = fargs[0];
exec(buff, bufc, 0, player, cause, EV_FIGNORE | EV_EVAL, &str, cargs,
ncargs);
}
/*
* ---------------------------------------------------------------------------
* * fun_con: Returns first item in contents list of object/room
*/
static void fun_con(char *buff, char **bufc, dbref player, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs)
{
dbref it;
it = match_thing(player, fargs[0]);
if ((it != NOTHING) && (Has_contents(it)) && (Examinable(player, it) ||
(where_is(player) == it) || (it == cause))) {
safe_tprintf_str(buff, bufc, "#%d", Contents(it));
return;
}
safe_str("#-1", buff, bufc);
return;
}
/*
* ---------------------------------------------------------------------------
* * fun_exit: Returns first exit in exits list of room.
*/
static void fun_exit(char *buff, char **bufc, dbref player, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs)
{
dbref it, exit;
int key;
it = match_thing(player, fargs[0]);
if (Good_obj(it) && Has_exits(it) && Good_obj(Exits(it))) {
key = 0;
if (Examinable(player, it))
key |= VE_LOC_XAM;
if (Dark(it))
key |= VE_LOC_DARK;
DOLIST(exit, Exits(it)) {
if (exit_visible(exit, player, key)) {
safe_tprintf_str(buff, bufc, "#%d", exit);
return;
}
}
}
safe_str("#-1", buff, bufc);
return;
}
/*
* ---------------------------------------------------------------------------
* * fun_next: return next thing in contents or exits chain
*/
static void fun_next(char *buff, char **bufc, dbref player, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs)
{
dbref it, loc, exit, ex_here;
int key;
it = match_thing(player, fargs[0]);
if (Good_obj(it) && Has_siblings(it)) {
loc = where_is(it);
ex_here = Good_obj(loc) ? Examinable(player, loc) : 0;
if (ex_here || (loc == player) || (loc == where_is(player))) {
if (!isExit(it)) {
safe_tprintf_str(buff, bufc, "#%d", Next(it));
return;
} else {
key = 0;
if (ex_here)
key |= VE_LOC_XAM;
if (Dark(loc))
key |= VE_LOC_DARK;
DOLIST(exit, it) {
if ((exit != it) && exit_visible(exit, player, key)) {
safe_tprintf_str(buff, bufc, "#%d", exit);
return;
}
}
}
}
}
safe_str("#-1", buff, bufc);
return;
}
/*
* ---------------------------------------------------------------------------
* * fun_loc: Returns the location of something
*/
static void fun_loc(char *buff, char **bufc, dbref player, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs)
{
dbref it;
it = match_thing(player, fargs[0]);
if (locatable(player, it, cause))
safe_tprintf_str(buff, bufc, "#%d", Location(it));
else
safe_str("#-1", buff, bufc);
return;
}
/*
* ---------------------------------------------------------------------------
* * fun_where: Returns the "true" location of something
*/
static void fun_where(char *buff, char **bufc, dbref player, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs)
{
dbref it;
it = match_thing(player, fargs[0]);
if (locatable(player, it, cause))
safe_tprintf_str(buff, bufc, "#%d", where_is(it));
else
safe_str("#-1", buff, bufc);
return;
}
/*
* ---------------------------------------------------------------------------
* * fun_rloc: Returns the recursed location of something (specifying #levels)
*/
static void fun_rloc(char *buff, char **bufc, dbref player, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs)
{
int i, levels;
dbref it;
levels = atoi(fargs[1]);
if (levels > mudconf.ntfy_nest_lim)
levels = mudconf.ntfy_nest_lim;
it = match_thing(player, fargs[0]);
if (locatable(player, it, cause)) {
for (i = 0; i < levels; i++) {
if (!Good_obj(it) || !Has_location(it))
break;
it = Location(it);
}
safe_tprintf_str(buff, bufc, "#%d", it);
return;
}
safe_str("#-1", buff, bufc);
}
/*
* ---------------------------------------------------------------------------
* * fun_room: Find the room an object is ultimately in.
*/
static void fun_room(char *buff, char **bufc, dbref player, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs)
{
dbref it;
int count;
it = match_thing(player, fargs[0]);
if (locatable(player, it, cause)) {
for (count = mudconf.ntfy_nest_lim; count > 0; count--) {
it = Location(it);
if (!Good_obj(it))
break;
if (isRoom(it)) {
safe_tprintf_str(buff, bufc, "#%d", it);
return;
}
}
safe_str("#-1", buff, bufc);
} else if (isRoom(it)) {
safe_tprintf_str(buff, bufc, "#%d", it);
} else {
safe_str("#-1", buff, bufc);
}
return;
}
/*
* ---------------------------------------------------------------------------
* * fun_owner: Return the owner of an object.
*/
static void fun_owner(char *buff, char **bufc, dbref player, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs)
{
dbref it, aowner;
int atr, aflags;
if (parse_attrib(player, fargs[0], &it, &atr)) {
if (atr == NOTHING) {
it = NOTHING;
} else {
atr_pget_info(it, atr, &aowner, &aflags);
it = aowner;
}
} else {
it = match_thing(player, fargs[0]);
if (it != NOTHING)
it = Owner(it);
}
safe_tprintf_str(buff, bufc, "#%d", it);
}
/*
* ---------------------------------------------------------------------------
* * fun_controls: Does x control y?
*/
static void fun_controls(char *buff, char **bufc, dbref player, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs)
{
dbref x, y;
x = match_thing(player, fargs[0]);
if (x == NOTHING) {
safe_tprintf_str(buff, bufc, "%s", "#-1 ARG1 NOT FOUND");
return;
}
y = match_thing(player, fargs[1]);
if (y == NOTHING) {
safe_tprintf_str(buff, bufc, "%s", "#-1 ARG2 NOT FOUND");
return;
}
safe_tprintf_str(buff, bufc, "%d", Controls(x, y));
}
/*
* ---------------------------------------------------------------------------
* * fun_fullname: Return the fullname of an object (good for exits)
*/
static void fun_fullname(char *buff, char **bufc, dbref player, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs)
{
dbref it;
it = match_thing(player, fargs[0]);
if (it == NOTHING) {
return;
}
if (!mudconf.read_rem_name) {
if (!nearby_or_control(player, it) && (!isPlayer(it))) {
safe_str("#-1 TOO FAR AWAY TO SEE", buff, bufc);
return;
}
}
safe_str(Name(it), buff, bufc);
}
/*
* ---------------------------------------------------------------------------
* * fun_name: Return the name of an object
*/
static void fun_name(char *buff, char **bufc, dbref player, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs)
{
dbref it;
char *s, *temp;
it = match_thing(player, fargs[0]);
if (it == NOTHING) {
return;
}
if (!mudconf.read_rem_name) {
if (!nearby_or_control(player, it) && !isPlayer(it) &&
!Long_Fingers(player)) {
safe_str("#-1 TOO FAR AWAY TO SEE", buff, bufc);
return;
}
}
temp = *bufc;
safe_str(Name(it), buff, bufc);
if (isExit(it)) {
for (s = temp; (s != *bufc) && (*s != ';'); s++);
if (*s == ';')
*bufc = s;
}
}
/*
* ---------------------------------------------------------------------------
* * fun_match, fun_strmatch: Match arg2 against each word of arg1 returning
* * index of first match, or against the whole string.
*/
static void fun_match(char *buff, char **bufc, dbref player, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs)
{
int wcount;
char *r, *s, sep;
varargs_preamble("MATCH", 3);
/*
* Check each word individually, returning the word number of the * *
*
* * * * first one that matches. If none match, return 0.
*/
wcount = 1;
s = trim_space_sep(fargs[0], sep);
do {
r = split_token(&s, sep);
if (quick_wild(fargs[1], r)) {
safe_tprintf_str(buff, bufc, "%d", wcount);
return;
}
wcount++;
} while (s);
safe_str("0", buff, bufc);
}
static void fun_strmatch(char *buff, char **bufc, dbref player, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs)
{
/*
* Check if we match the whole string. If so, return 1
*/
if (quick_wild(fargs[1], fargs[0]))
safe_str("1", buff, bufc);
else
safe_str("0", buff, bufc);
return;
}
/*
* ---------------------------------------------------------------------------
* * fun_extract: extract words from string:
* * extract(foo bar baz,1,2) returns 'foo bar'
* * extract(foo bar baz,2,1) returns 'bar'
* * extract(foo bar baz,2,2) returns 'bar baz'
* *
* * Now takes optional separator extract(foo-bar-baz,1,2,-) returns 'foo-bar'
*/
static void fun_extract(char *buff, char **bufc, dbref player, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs)
{
int start, len;
char *r, *s, *t, sep;
varargs_preamble("EXTRACT", 4);
s = fargs[0];
start = atoi(fargs[1]);
len = atoi(fargs[2]);
if ((start < 1) || (len < 1)) {
return;
}
/*
* Skip to the start of the string to save
*/
start--;
s = trim_space_sep(s, sep);
while (start && s) {
s = next_token(s, sep);
start--;
}
/*
* If we ran of the end of the string, return nothing
*/
if (!s || !*s) {
return;
}
/*
* Count off the words in the string to save
*/
r = s;
len--;
while (len && s) {
s = next_token(s, sep);
len--;
}
/*
* Chop off the rest of the string, if needed
*/
if (s && *s)
t = split_token(&s, sep);
safe_str(r, buff, bufc);
}
int xlate(arg)
char *arg;
{
int temp;
char *temp2;
if (arg[0] == '#') {
arg++;
if (is_integer(arg)) {
temp = atoi(arg);
if (temp == -1)
temp = 0;
return temp;
}
return 0;
}
temp2 = trim_space_sep(arg, ' ');
if (!*temp2)
return 0;
if (is_integer(temp2))
return atoi(temp2);
return 1;
}
/*
* ---------------------------------------------------------------------------
* * fun_index: like extract(), but it works with an arbitrary separator.
* * index(a b | c d e | f gh | ij k, |, 2, 1) => c d e
* * index(a b | c d e | f gh | ij k, |, 2, 2) => c d e | f g h
*/
static void fun_index(char *buff, char **bufc, dbref player, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs)
{
int start, end;
char c, *s, *p;
s = fargs[0];
c = *fargs[1];
start = atoi(fargs[2]);
end = atoi(fargs[3]);
if ((start < 1) || (end < 1) || (*s == '\0'))
return;
if (c == '\0')
c = ' ';
/*
* move s to point to the start of the item we want
*/
start--;
while (start && s && *s) {
if ((s = (char *) index(s, c)) != NULL)
s++;
start--;
}
/*
* skip over just spaces
*/
while (s && (*s == ' '))
s++;
if (!s || !*s)
return;
/*
* figure out where to end the string
*/
p = s;
while (end && p && *p) {
if ((p = (char *) index(p, c)) != NULL) {
if (--end == 0) {
do {
p--;
} while ((*p == ' ') && (p > s));
*(++p) = '\0';
safe_str(s, buff, bufc);
return;
} else {
p++;
}
}
}
/*
* if we've gotten this far, we've run off the end of the string
*/
safe_str(s, buff, bufc);
}
static void fun_cat(char *buff, char **bufc, dbref player, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs)
{
int i;
safe_str(fargs[0], buff, bufc);
for (i = 1; i < nfargs; i++) {
safe_chr(' ', buff, bufc);
safe_str(fargs[i], buff, bufc);
}
}
static void fun_version(char *buff, char **bufc, dbref player, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs)
{
safe_str(mudstate.version, buff, bufc);
}
static void fun_strlen(char *buff, char **bufc, dbref player, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs)
{
safe_tprintf_str(buff, bufc, "%d",
(int) strlen((char *) strip_ansi(fargs[0])));
}
static void fun_num(char *buff, char **bufc, dbref player, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs)
{
safe_tprintf_str(buff, bufc, "#%d", match_thing(player, fargs[0]));
}
static void fun_pmatch(char *buff, char **bufc, dbref player, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs)
{
dbref thing;
if (*fargs[0] == '#') {
safe_tprintf_str(buff, bufc, "#%d", match_thing(player, fargs[0]));
return;
}
if (!((thing = lookup_player(player, fargs[0], 1)) == NOTHING)) {
safe_tprintf_str(buff, bufc, "#%d", thing);
return;
} else
safe_str("#-1 NO MATCH", buff, bufc);
}
static void fun_gt(char *buff, char **bufc, dbref player, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs)
{
safe_tprintf_str(buff, bufc, "%d", (atof(fargs[0]) > atof(fargs[1])));
}
static void fun_gte(char *buff, char **bufc, dbref player, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs)
{
safe_tprintf_str(buff, bufc, "%d", (atof(fargs[0]) >= atof(fargs[1])));
}
static void fun_lt(char *buff, char **bufc, dbref player, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs)
{
safe_tprintf_str(buff, bufc, "%d", (atof(fargs[0]) < atof(fargs[1])));
}
static void fun_lte(char *buff, char **bufc, dbref player, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs)
{
safe_tprintf_str(buff, bufc, "%d", (atof(fargs[0]) <= atof(fargs[1])));
}
static void fun_eq(char *buff, char **bufc, dbref player, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs)
{
safe_tprintf_str(buff, bufc, "%d", (atof(fargs[0]) == atof(fargs[1])));
}
static void fun_neq(char *buff, char **bufc, dbref player, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs)
{
safe_tprintf_str(buff, bufc, "%d", (atof(fargs[0]) != atof(fargs[1])));
}
static void fun_and(char *buff, char **bufc, dbref player, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs)
{
int i, val;
if (nfargs < 2) {
safe_str("#-1 TOO FEW ARGUMENTS", buff, bufc);
return;
}
val = atoi(fargs[0]);
for (i = 1; val && i < nfargs; i++)
val = val && atoi(fargs[i]);
safe_tprintf_str(buff, bufc, "%d", val);
}
static void fun_or(char *buff, char **bufc, dbref player, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs)
{
int i, val;
if (nfargs < 2) {
safe_str("#-1 TOO FEW ARGUMENTS", buff, bufc);
return;
}
val = atoi(fargs[0]);
for (i = 1; !val && i < nfargs; i++)
val = val || atoi(fargs[i]);
safe_tprintf_str(buff, bufc, "%d", val);
}
static void fun_xor(char *buff, char **bufc, dbref player, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs)
{
int i, val;
if (nfargs < 2) {
safe_str("#-1 TOO FEW ARGUMENTS", buff, bufc);
return;
}
val = atoi(fargs[0]);
for (i = 1; i < nfargs; i++) {
int tval = atoi(fargs[i]);
val = (val && !tval) || (!val && tval);
}
safe_tprintf_str(buff, bufc, "%d", val);
}
static void fun_not(char *buff, char **bufc, dbref player, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs)
{
safe_tprintf_str(buff, bufc, "%d", !xlate(fargs[0]));
}
static void fun_sqrt(char *buff, char **bufc, dbref player, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs)
{
double val;
val = atof(fargs[0]);
if (val < 0) {
safe_str("#-1 SQUARE ROOT OF NEGATIVE", buff, bufc);
} else if (val == 0) {
safe_str("0", buff, bufc);
} else {
fval(buff, bufc, sqrt(val));
}
}
static void fun_add(char *buff, char **bufc, dbref player, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs)
{
double sum = 0;
int i;
if (!nfargs) {
safe_str("#-1 TOO FEW ARGUMENTS", buff, bufc);
return;
}
for (i = 0; i < nfargs; i++)
sum += atof(fargs[i]);
fval(buff, bufc, sum);
}
static void fun_sub(char *buff, char **bufc, dbref player, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs)
{
fval(buff, bufc, atof(fargs[0]) - atof(fargs[1]));
}
static void fun_mul(char *buff, char **bufc, dbref player, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs)
{
int i;
double prod;
if (!nfargs) {
safe_str("#-1 TOO FEW ARGUMENTS", buff, bufc);
return;
}
prod = atof(fargs[0]);
for (i = 1; i < nfargs; i++)
prod *= atof(fargs[i]);
fval(buff, bufc, prod);
}
static void fun_floor(char *buff, char **bufc, dbref player, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs)
{
safe_tprintf_str(buff, bufc, "%.0f", floor(atof(fargs[0])));
}
static void fun_ceil(char *buff, char **bufc, dbref player, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs)
{
safe_tprintf_str(buff, bufc, "%.0f", ceil(atof(fargs[0])));
}
static void fun_round(char *buff, char **bufc, dbref player, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs)
{
const char *fstr;
char *oldp;
oldp = *bufc;
switch (atoi(fargs[1])) {
case 1:
fstr = "%.1f";
break;
case 2:
fstr = "%.2f";
break;
case 3:
fstr = "%.3f";
break;
case 4:
fstr = "%.4f";
break;
case 5:
fstr = "%.5f";
break;
case 6:
fstr = "%.6f";
break;
default:
fstr = "%.0f";
break;
}
safe_tprintf_str(buff, bufc, (char *) fstr, atof(fargs[0]));
/* Handle bogus result of "-0" from sprintf. Yay, cclib. */
if (!strcmp(oldp, "-0")) {
*oldp = '0';
*bufc = oldp + 1;
}
}
static void fun_trunc(char *buff, char **bufc, dbref player, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs)
{
safe_tprintf_str(buff, bufc, "%.0f", atof(fargs[0]));
}
static void fun_div(char *buff, char **bufc, dbref player, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs)
{
int bot;
bot = atoi(fargs[1]);
if (bot == 0) {
safe_str("#-1 DIVIDE BY ZERO", buff, bufc);
} else {
safe_tprintf_str(buff, bufc, "%d", (atoi(fargs[0]) / bot));
}
}
static void fun_fdiv(char *buff, char **bufc, dbref player, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs)
{
double bot;
bot = atof(fargs[1]);
if (bot == 0) {
safe_str("#-1 DIVIDE BY ZERO", buff, bufc);
} else {
fval(buff, bufc, (atof(fargs[0]) / bot));
}
}
static void fun_mod(char *buff, char **bufc, dbref player, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs)
{
int bot;
bot = atoi(fargs[1]);
if (bot == 0)
bot = 1;
safe_tprintf_str(buff, bufc, "%d", atoi(fargs[0]) % bot);
}
static void fun_pi(char *buff, char **bufc, dbref player, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs)
{
safe_str("3.141592654", buff, bufc);
}
static void fun_e(char *buff, char **bufc, dbref player, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs)
{
safe_str("2.718281828", buff, bufc);
}
static void fun_sin(char *buff, char **bufc, dbref player, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs)
{
fval(buff, bufc, sin(atof(fargs[0])));
}
static void fun_cos(char *buff, char **bufc, dbref player, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs)
{
fval(buff, bufc, cos(atof(fargs[0])));
}
static void fun_tan(char *buff, char **bufc, dbref player, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs)
{
fval(buff, bufc, tan(atof(fargs[0])));
}
static void fun_exp(char *buff, char **bufc, dbref player, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs)
{
fval(buff, bufc, exp(atof(fargs[0])));
}
static void fun_power(char *buff, char **bufc, dbref player, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs)
{
double val1, val2;
val1 = atof(fargs[0]);
val2 = atof(fargs[1]);
if (val1 < 0) {
safe_str("#-1 POWER OF NEGATIVE", buff, bufc);
} else {
fval(buff, bufc, pow(val1, val2));
}
}
static void fun_ln(char *buff, char **bufc, dbref player, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs)
{
double val;
val = atof(fargs[0]);
if (val > 0)
fval(buff, bufc, log(val));
else
safe_str("#-1 LN OF NEGATIVE OR ZERO", buff, bufc);
}
static void fun_log(char *buff, char **bufc, dbref player, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs)
{
double val;
val = atof(fargs[0]);
if (val > 0) {
fval(buff, bufc, log10(val));
} else {
safe_str("#-1 LOG OF NEGATIVE OR ZERO", buff, bufc);
}
}
static void fun_asin(char *buff, char **bufc, dbref player, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs)
{
double val;
val = atof(fargs[0]);
if ((val < -1) || (val > 1)) {
safe_str("#-1 ASIN ARGUMENT OUT OF RANGE", buff, bufc);
} else {
fval(buff, bufc, asin(val));
}
}
static void fun_acos(char *buff, char **bufc, dbref player, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs)
{
double val;
val = atof(fargs[0]);
if ((val < -1) || (val > 1)) {
safe_str("#-1 ACOS ARGUMENT OUT OF RANGE", buff, bufc);
} else {
fval(buff, bufc, acos(val));
}
}
static void fun_atan(char *buff, char **bufc, dbref player, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs)
{
fval(buff, bufc, atan(atof(fargs[0])));
}
static void fun_dist2d(char *buff, char **bufc, dbref player, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs)
{
int d;
double r;
d = atoi(fargs[0]) - atoi(fargs[2]);
r = (double) (d * d);
d = atoi(fargs[1]) - atoi(fargs[3]);
r += (double) (d * d);
d = (int) (sqrt(r) + 0.5);
safe_tprintf_str(buff, bufc, "%d", d);
}
static void fun_dist3d(char *buff, char **bufc, dbref player, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs)
{
int d;
double r;
d = atoi(fargs[0]) - atoi(fargs[3]);
r = (double) (d * d);
d = atoi(fargs[1]) - atoi(fargs[4]);
r += (double) (d * d);
d = atoi(fargs[2]) - atoi(fargs[5]);
r += (double) (d * d);
d = (int) (sqrt(r) + 0.5);
safe_tprintf_str(buff, bufc, "%d", d);
}
/*
* ---------------------------------------------------------------------------
* * fun_comp: string compare.
*/
static void fun_comp(char *buff, char **bufc, dbref player, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs)
{
int x;
x = strcmp(fargs[0], fargs[1]);
if (x > 0)
safe_str("1", buff, bufc);
else if (x < 0)
safe_str("-1", buff, bufc);
else
safe_str("0", buff, bufc);
}
/*
* ---------------------------------------------------------------------------
* * fun_lcon: Return a list of contents.
*/
static void fun_lcon(char *buff, char **bufc, dbref player, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs)
{
dbref thing, it;
char *tbuf;
int first = 1;
it = match_thing(player, fargs[0]);
if ((it != NOTHING) && (Has_contents(it)) && (Examinable(player, it) ||
(Location(player) == it) || (it == cause))) {
tbuf = alloc_sbuf("fun_lcon");
DOLIST(thing, Contents(it)) {
if (!first)
sprintf(tbuf, " #%d", thing);
else {
sprintf(tbuf, "#%d", thing);
first = 0;
}
safe_str(tbuf, buff, bufc);
}
free_sbuf(tbuf);
} else
safe_str("#-1", buff, bufc);
}
/*
* ---------------------------------------------------------------------------
* * fun_lexits: Return a list of exits.
*/
static void fun_lexits(char *buff, char **bufc, dbref player, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs)
{
dbref thing, it, parent;
char *tbuf;
int exam, lev, key;
int first = 1;
it = match_thing(player, fargs[0]);
if (!Good_obj(it) || !Has_exits(it)) {
safe_str("#-1", buff, bufc);
return;
}
exam = Examinable(player, it);
if (!exam && (where_is(player) != it) && (it != cause)) {
safe_str("#-1", buff, bufc);
return;
}
tbuf = alloc_sbuf("fun_lexits");
/*
* Return info for all parent levels
*/
ITER_PARENTS(it, parent, lev) {
/*
* Look for exits at each level
*/
if (!Has_exits(parent))
continue;
key = 0;
if (Examinable(player, parent))
key |= VE_LOC_XAM;
if (Dark(parent))
key |= VE_LOC_DARK;
if (Dark(it))
key |= VE_BASE_DARK;
DOLIST(thing, Exits(parent)) {
if (exit_visible(thing, player, key)) {
if (!first)
sprintf(tbuf, " #%d", thing);
else {
sprintf(tbuf, "#%d", thing);
first = 0;
}
safe_str(tbuf, buff, bufc);
}
}
}
free_sbuf(tbuf);
return;
}
/*
* --------------------------------------------------------------------------
* * fun_home: Return an object's home
*/
static void fun_home(char *buff, char **bufc, dbref player, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs)
{
dbref it;
it = match_thing(player, fargs[0]);
if (!Good_obj(it) || !Examinable(player, it))
safe_str("#-1", buff, bufc);
else if (Has_home(it))
safe_tprintf_str(buff, bufc, "#%d", Home(it));
else if (Has_dropto(it))
safe_tprintf_str(buff, bufc, "#%d", Dropto(it));
else if (isExit(it))
safe_tprintf_str(buff, bufc, "#%d", where_is(it));
else
safe_str("#-1", buff, bufc);
return;
}
/*
* ---------------------------------------------------------------------------
* * fun_money: Return an object's value
*/
static void fun_money(char *buff, char **bufc, dbref player, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs)
{
dbref it;
it = match_thing(player, fargs[0]);
if ((it == NOTHING) || !Examinable(player, it))
safe_str("#-1", buff, bufc);
else
safe_tprintf_str(buff, bufc, "%d", Pennies(it));
}
/*
* ---------------------------------------------------------------------------
* * fun_pos: Find a word in a string
*/
static void fun_pos(char *buff, char **bufc, dbref player, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs)
{
int i = 1;
char *s, *t, *u;
i = 1;
s = fargs[1];
while (*s) {
u = s;
t = fargs[0];
while (*t && *t == *u)
++t, ++u;
if (*t == '\0') {
safe_tprintf_str(buff, bufc, "%d", i);
return;
}
++i, ++s;
}
safe_str("#-1", buff, bufc);
return;
}
/*
* ---------------------------------------------------------------------------
* * ldelete: Remove a word from a string by place
* * ldelete(<list>,<position>[,<separator>])
* *
* * insert: insert a word into a string by place
* * insert(<list>,<position>,<new item> [,<separator>])
* *
* * replace: replace a word into a string by place
* * replace(<list>,<position>,<new item>[,<separator>])
*/
#define IF_DELETE 0
#define IF_REPLACE 1
#define IF_INSERT 2
static void do_itemfuns(buff, bufc, str, el, word, sep, flag)
char *buff, **bufc, *str, *word, sep;
int el, flag;
{
int ct, overrun;
char *sptr, *iptr, *eptr;
char nullb;
/*
* If passed a null string return an empty string, except that we * *
*
* * * * are allowed to append to a null string.
*/
if ((!str || !*str) && ((flag != IF_INSERT) || (el != 1))) {
return;
}
/*
* we can't fiddle with anything before the first position
*/
if (el < 1) {
safe_str(str, buff, bufc);
return;
}
/*
* Split the list up into 'before', 'target', and 'after' chunks * *
* * * pointed to by sptr, iptr, and eptr respectively.
*/
nullb = '\0';
if (el == 1) {
/*
* No 'before' portion, just split off element 1
*/
sptr = NULL;
if (!str || !*str) {
eptr = NULL;
iptr = NULL;
} else {
eptr = trim_space_sep(str, sep);
iptr = split_token(&eptr, sep);
}
} else {
/*
* Break off 'before' portion
*/
sptr = eptr = trim_space_sep(str, sep);
overrun = 1;
for (ct = el; ct > 2 && eptr; eptr = next_token(eptr, sep), ct--);
if (eptr) {
overrun = 0;
iptr = split_token(&eptr, sep);
}
/*
* If we didn't make it to the target element, just return *
* * * * the string. Insert is allowed to continue if we are
* * * * * exactly at the end of the string, but replace
* and * delete * * * * are not.
*/
if (!(eptr || ((flag == IF_INSERT) && !overrun))) {
safe_str(str, buff, bufc);
return;
}
/*
* Split the 'target' word from the 'after' portion.
*/
if (eptr)
iptr = split_token(&eptr, sep);
else
iptr = NULL;
}
switch (flag) {
case IF_DELETE: /*
* deletion
*/
if (sptr) {
safe_str(sptr, buff, bufc);
if (eptr)
safe_chr(sep, buff, bufc);
}
if (eptr) {
safe_str(eptr, buff, bufc);
}
break;
case IF_REPLACE: /*
* replacing
*/
if (sptr) {
safe_str(sptr, buff, bufc);
safe_chr(sep, buff, bufc);
}
safe_str(word, buff, bufc);
if (eptr) {
safe_chr(sep, buff, bufc);
safe_str(eptr, buff, bufc);
}
break;
case IF_INSERT: /*
* insertion
*/
if (sptr) {
safe_str(sptr, buff, bufc);
safe_chr(sep, buff, bufc);
}
safe_str(word, buff, bufc);
if (iptr) {
safe_chr(sep, buff, bufc);
safe_str(iptr, buff, bufc);
}
if (eptr) {
safe_chr(sep, buff, bufc);
safe_str(eptr, buff, bufc);
}
break;
}
}
static void fun_ldelete(char *buff, char **bufc, dbref player, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs)
{ /*
* delete a word at position X of a list
*/
char sep;
varargs_preamble("LDELETE", 3);
do_itemfuns(buff, bufc, fargs[0], atoi(fargs[1]), NULL, sep,
IF_DELETE);
}
static void fun_replace(char *buff, char **bufc, dbref player, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs)
{ /*
* replace a word at position X of a list
*/
char sep;
varargs_preamble("REPLACE", 4);
do_itemfuns(buff, bufc, fargs[0], atoi(fargs[1]), fargs[2], sep,
IF_REPLACE);
}
static void fun_insert(char *buff, char **bufc, dbref player, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs)
{ /*
* insert a word at position X of a list
*/
char sep;
varargs_preamble("INSERT", 4);
do_itemfuns(buff, bufc, fargs[0], atoi(fargs[1]), fargs[2], sep,
IF_INSERT);
}
/*
* ---------------------------------------------------------------------------
* * fun_remove: Remove a word from a string
*/
static void fun_remove(char *buff, char **bufc, dbref player, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs)
{
char *s, *sp, *word;
char sep;
int first, found;
varargs_preamble("REMOVE", 3);
if (index(fargs[1], sep)) {
safe_str("#-1 CAN ONLY DELETE ONE ELEMENT", buff, bufc);
return;
}
s = fargs[0];
word = fargs[1];
/*
* Walk through the string copying words until (if ever) we get to *
* * * * one that matches the target word.
*/
sp = s;
found = 0;
first = 1;
while (s) {
sp = split_token(&s, sep);
if (found || strcmp(sp, word)) {
if (!first)
safe_chr(sep, buff, bufc);
safe_str(sp, buff, bufc);
first = 0;
} else {
found = 1;
}
}
}
/*
* ---------------------------------------------------------------------------
* * fun_member: Is a word in a string
*/
static void fun_member(char *buff, char **bufc, dbref player, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs)
{
int wcount;
char *r, *s, sep;
varargs_preamble("MEMBER", 3);
wcount = 1;
s = trim_space_sep(fargs[0], sep);
do {
r = split_token(&s, sep);
if (!strcmp(fargs[1], r)) {
safe_tprintf_str(buff, bufc, "%d", wcount);
return;
}
wcount++;
} while (s);
safe_str("0", buff, bufc);
}
/*
* ---------------------------------------------------------------------------
* * fun_secure, fun_escape: escape [, ], %, \, and the beginning of the string.
*/
static void fun_secure(char *buff, char **bufc, dbref player, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs)
{
char *s;
s = fargs[0];
while (*s) {
switch (*s) {
case '%':
case '$':
case '\\':
case '[':
case ']':
case '(':
case ')':
case '{':
case '}':
case ',':
case ';':
safe_chr(' ', buff, bufc);
break;
default:
safe_chr(*s, buff, bufc);
}
s++;
}
}
static void fun_ansi_secure(char *buff, char **bufc, dbref player, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs)
{
char *s;
s = fargs[0];
while (*s) {
switch (*s) {
case '\033':
safe_chr(*s++, buff, bufc);
if (*s == '[') {
safe_chr(*s, buff, bufc);
break;
} /* FALLTHRU */
case '%':
case '[':
case '$':
case '\\':
case ']':
case '(':
case ')':
case '{':
case '}':
case ',':
case ';':
safe_chr(' ', buff, bufc);
break;
default:
safe_chr(*s, buff, bufc);
}
s++;
}
}
static void fun_escape(char *buff, char **bufc, dbref player, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs)
{
char *s, *d;
d = *bufc;
s = fargs[0];
while (*s) {
switch (*s) {
case '%':
case '\\':
case '[':
case ']':
case '{':
case '}':
case ';':
safe_chr('\\', buff, bufc);
default:
if (*bufc == d)
safe_chr('\\', buff, bufc);
safe_chr(*s, buff, bufc);
}
s++;
}
}
/*
* Take a character position and return which word that char is in.
* wordpos(<string>, <charpos>)
*/
static void fun_wordpos(char *buff, char **bufc, dbref player, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs)
{
int charpos, i;
char *cp, *tp, *xp, sep;
varargs_preamble("WORDPOS", 3);
charpos = atoi(fargs[1]);
cp = fargs[0];
if ((charpos > 0) && (charpos <= strlen(cp))) {
tp = &(cp[charpos - 1]);
cp = trim_space_sep(cp, sep);
xp = split_token(&cp, sep);
for (i = 1; xp; i++) {
if (tp < (xp + strlen(xp)))
break;
xp = split_token(&cp, sep);
}
safe_tprintf_str(buff, bufc, "%d", i);
return;
}
safe_str("#-1", buff, bufc);
return;
}
static void fun_type(char *buff, char **bufc, dbref player, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs)
{
dbref it;
it = match_thing(player, fargs[0]);
if (!Good_obj(it)) {
safe_str("#-1 NOT FOUND", buff, bufc);
return;
}
switch (Typeof(it)) {
case TYPE_ROOM:
safe_str("ROOM", buff, bufc);
break;
case TYPE_EXIT:
safe_str("EXIT", buff, bufc);
break;
case TYPE_PLAYER:
safe_str("PLAYER", buff, bufc);
break;
case TYPE_THING:
safe_str("THING", buff, bufc);
break;
default:
safe_str("#-1 ILLEGAL TYPE", buff, bufc);
}
return;
}
static void fun_hasflag(char *buff, char **bufc, dbref player, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs)
{
dbref it;
it = match_thing(player, fargs[0]);
if (!Good_obj(it)) {
safe_str("#-1 NOT FOUND", buff, bufc);
return;
}
if (mudconf.pub_flags || Examinable(player, it) || (it == cause)) {
if (has_flag(player, it, fargs[1]))
safe_str("1", buff, bufc);
else
safe_str("0", buff, bufc);
} else {
safe_str("#-1 PERMISSION DENIED", buff, bufc);
}
}
static void fun_haspower(char *buff, char **bufc, dbref player, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs)
{
dbref it;
it = match_thing(player, fargs[0]);
if (!Good_obj(it)) {
safe_str("#-1 NOT FOUND", buff, bufc);
return;
}
if (mudconf.pub_flags || Examinable(player, it) || (it == cause)) {
if (has_power(player, it, fargs[1]))
safe_str("1", buff, bufc);
else
safe_str("0", buff, bufc);
} else {
safe_str("#-1 PERMISSION DENIED", buff, bufc);
}
}
static void fun_delete(char *buff, char **bufc, dbref player, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs)
{
char *s, *temp, *bp;
int i, start, nchars, len;
s = fargs[0];
start = atoi(fargs[1]);
nchars = atoi(fargs[2]);
len = strlen(s);
if ((start >= len) || (nchars <= 0)) {
safe_str(s, buff, bufc);
return;
}
bp = temp = alloc_lbuf("fun_delete");
for (i = 0; i < start; i++)
*bp++ = (*s++);
if ((i + nchars) < len && (i + nchars) > 0) {
s += nchars;
while ((*bp++ = *s++));
} else
*bp = '\0';
safe_str(temp, buff, bufc);
free_lbuf(temp);
}
static void fun_lock(char *buff, char **bufc, dbref player, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs)
{
dbref it, aowner;
int aflags;
char *tbuf;
ATTR *attr;
struct boolexp *bool;
/*
* Parse the argument into obj + lock
*/
if (!get_obj_and_lock(player, fargs[0], &it, &attr, buff, bufc))
return;
/*
* Get the attribute and decode it if we can read it
*/
tbuf = atr_get(it, attr->number, &aowner, &aflags);
if (Read_attr(player, it, attr, aowner, aflags)) {
bool = parse_boolexp(player, tbuf, 1);
free_lbuf(tbuf);
tbuf = (char *) unparse_boolexp_function(player, bool);
free_boolexp(bool);
safe_str(tbuf, buff, bufc);
} else
free_lbuf(tbuf);
}
static void fun_elock(char *buff, char **bufc, dbref player, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs)
{
dbref it, victim, aowner;
int aflags;
char *tbuf;
ATTR *attr;
struct boolexp *bool;
/*
* Parse lock supplier into obj + lock
*/
if (!get_obj_and_lock(player, fargs[0], &it, &attr, buff, bufc))
return;
/*
* Get the victim and ensure we can do it
*/
victim = match_thing(player, fargs[1]);
if (!Good_obj(victim)) {
safe_str("#-1 NOT FOUND", buff, bufc);
} else if (!nearby_or_control(player, victim) &&
!nearby_or_control(player, it)) {
safe_str("#-1 TOO FAR AWAY", buff, bufc);
} else {
tbuf = atr_get(it, attr->number, &aowner, &aflags);
if ((attr->number == A_LOCK) ||
Read_attr(player, it, attr, aowner, aflags)) {
bool = parse_boolexp(player, tbuf, 1);
safe_tprintf_str(buff, bufc, "%d", eval_boolexp(victim, it, it,
bool));
free_boolexp(bool);
} else {
safe_str("0", buff, bufc);
}
free_lbuf(tbuf);
}
}
/*
* ---------------------------------------------------------------------------
* * fun_lwho: Return list of connected users.
*/
static void fun_lwho(char *buff, char **bufc, dbref player, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs)
{
make_ulist(player, buff, bufc);
}
/*
* ---------------------------------------------------------------------------
* * fun_nearby: Return whether or not obj1 is near obj2.
*/
static void fun_nearby(char *buff, char **bufc, dbref player, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs)
{
dbref obj1, obj2;
obj1 = match_thing(player, fargs[0]);
obj2 = match_thing(player, fargs[1]);
if (!(nearby_or_control(player, obj1) ||
nearby_or_control(player, obj2)))
safe_str("0", buff, bufc);
else if (nearby(obj1, obj2))
safe_str("1", buff, bufc);
else
safe_str("0", buff, bufc);
}
/*
* ---------------------------------------------------------------------------
* * fun_obj, fun_poss, and fun_subj: perform pronoun sub for object.
*/
static void process_sex(player, what, token, buff, bufc)
dbref player;
char *what, *buff, **bufc;
const char *token;
{
dbref it;
char *str;
it = match_thing(player, what);
if (!Good_obj(it) || (!isPlayer(it) && !nearby_or_control(player, it))) {
safe_str("#-1 NO MATCH", buff, bufc);
} else {
str = (char *) token;
exec(buff, bufc, 0, it, it, 0, &str, (char **) NULL, 0);
}
}
static void fun_obj(char *buff, char **bufc, dbref player, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs)
{
process_sex(player, fargs[0], "%o", buff, bufc);
}
static void fun_poss(char *buff, char **bufc, dbref player, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs)
{
process_sex(player, fargs[0], "%p", buff, bufc);
}
static void fun_subj(char *buff, char **bufc, dbref player, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs)
{
process_sex(player, fargs[0], "%s", buff, bufc);
}
static void fun_aposs(char *buff, char **bufc, dbref player, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs)
{
process_sex(player, fargs[0], "%a", buff, bufc);
}
/*
* ---------------------------------------------------------------------------
* * fun_mudname: Return the name of the mud.
*/
static void fun_mudname(char *buff, char **bufc, dbref player, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs)
{
safe_str(mudconf.mud_name, buff, bufc);
}
/*
* ---------------------------------------------------------------------------
* * fun_lcstr, fun_ucstr, fun_capstr: Lowercase, uppercase, or capitalize str.
*/
static void fun_lcstr(char *buff, char **bufc, dbref player, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs)
{
char *ap;
ap = fargs[0];
while (*ap) {
**bufc = ToLower(*ap);
ap++;
(*bufc)++;
}
}
static void fun_ucstr(char *buff, char **bufc, dbref player, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs)
{
char *ap;
ap = fargs[0];
while (*ap) {
**bufc = ToUpper(*ap);
ap++;
(*bufc)++;
}
}
static void fun_capstr(char *buff, char **bufc, dbref player, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs)
{
char *s;
s = *bufc;
safe_str(fargs[0], buff, bufc);
*s = ToUpper(*s);
}
/*
* ---------------------------------------------------------------------------
* * fun_lnum: Return a list of numbers.
*/
static void fun_lnum(char *buff, char **bufc, dbref player, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs)
{
char tbuff[10];
int ctr, limit, llimit = 0, over;
if (nfargs > 2 || nfargs < 1) {
safe_str("#-1 TOO FEW ARGUMENTS", buff, bufc);
return;
}
over = 0;
limit = atoi(fargs[0]);
if (nfargs == 2) {
llimit = atoi(fargs[0]);
limit = atoi(fargs[1]) + 1;
} else
limit = atoi(fargs[0]);
if (limit > 0 && llimit >= 0 && llimit < limit) {
for (ctr = llimit; ctr < limit && !over; ctr++) {
{
sprintf(tbuff, "%s%d", ctr != llimit ? " " : "", ctr);
over = safe_str(tbuff, buff, bufc);
}
}
}
}
/*
* ---------------------------------------------------------------------------
* * fun_lattr: Return list of attributes I can see on the object.
*/
static void fun_lattr(char *buff, char **bufc, dbref player, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs)
{
dbref thing;
int ca, first;
ATTR *attr;
/*
* Check for wildcard matching. parse_attrib_wild checks for read
* permission, so we don't have to. Have p_a_w assume the slash-star if
* it is missing.
*/
first = 1;
olist_push();
if (parse_attrib_wild(player, fargs[0], &thing, 0, 0, 1)) {
for (ca = olist_first(); ca != NOTHING; ca = olist_next()) {
attr = atr_num(ca);
if (attr) {
if (!first)
safe_chr(' ', buff, bufc);
first = 0;
safe_str((char *) attr->name, buff, bufc);
}
}
} else {
safe_str("#-1 NO MATCH", buff, bufc);
}
olist_pop();
return;
}
/*
* ---------------------------------------------------------------------------
* * do_reverse, fun_reverse, fun_revwords: Reverse things.
*/
static void do_reverse(from, to)
char *from, *to;
{
char *tp;
tp = to + strlen(from);
*tp-- = '\0';
while (*from) {
*tp-- = *from++;
}
}
static void fun_reverse(char *buff, char **bufc, dbref player, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs)
{
do_reverse(fargs[0], *bufc);
*bufc += strlen(fargs[0]);
}
static void fun_revwords(char *buff, char **bufc, dbref player, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs)
{
char *temp, *tp, *t1, sep;
int first;
/*
* If we are passed an empty arglist return a null string
*/
if (nfargs == 0) {
return;
}
varargs_preamble("REVWORDS", 2);
temp = alloc_lbuf("fun_revwords");
/*
* Reverse the whole string
*/
do_reverse(fargs[0], temp);
/*
* Now individually reverse each word in the string. This will
* undo the reversing of the words (so the words themselves are
* forwards again.
*/
tp = temp;
first = 1;
while (tp) {
if (!first)
safe_chr(sep, buff, bufc);
t1 = split_token(&tp, sep);
do_reverse(t1, *bufc);
*bufc += strlen(t1);
first = 0;
}
free_lbuf(temp);
}
/*
* ---------------------------------------------------------------------------
* * fun_after, fun_before: Return substring after or before a specified string.
*/
static void fun_after(char *buff, char **bufc, dbref player, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs)
{
char *bp, *cp, *mp;
int mlen;
if (nfargs == 0) {
return;
}
if (!fn_range_check("AFTER", nfargs, 1, 2, buff, bufc))
return;
bp = fargs[0];
mp = fargs[1];
/*
* Sanity-check arg1 and arg2
*/
if (bp == NULL)
bp = "";
if (mp == NULL)
mp = " ";
if (!mp || !*mp)
mp = (char *) " ";
mlen = strlen(mp);
if ((mlen == 1) && (*mp == ' '))
bp = trim_space_sep(bp, ' ');
/*
* Look for the target string
*/
while (*bp) {
/*
* Search for the first character in the target string
*/
cp = (char *) index(bp, *mp);
if (cp == NULL) {
/*
* Not found, return empty string
*/
return;
}
/*
* See if what follows is what we are looking for
*/
if (!strncmp(cp, mp, mlen)) {
/*
* Yup, return what follows
*/
bp = cp + mlen;
safe_str(bp, buff, bufc);
return;
}
/*
* Continue search after found first character
*/
bp = cp + 1;
}
/*
* Ran off the end without finding it
*/
return;
}
static void fun_before(char *buff, char **bufc, dbref player, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs)
{
char *bp, *cp, *mp, *ip;
int mlen;
if (nfargs == 0) {
return;
}
if (!fn_range_check("BEFORE", nfargs, 1, 2, buff, bufc))
return;
bp = fargs[0];
mp = fargs[1];
/*
* Sanity-check arg1 and arg2
*/
if (bp == NULL)
bp = "";
if (mp == NULL)
mp = " ";
if (!mp || !*mp)
mp = (char *) " ";
mlen = strlen(mp);
if ((mlen == 1) && (*mp == ' '))
bp = trim_space_sep(bp, ' ');
ip = bp;
/*
* Look for the target string
*/
while (*bp) {
/*
* Search for the first character in the target string
*/
cp = (char *) index(bp, *mp);
if (cp == NULL) {
/*
* Not found, return entire string
*/
safe_str(ip, buff, bufc);
return;
}
/*
* See if what follows is what we are looking for
*/
if (!strncmp(cp, mp, mlen)) {
/*
* Yup, return what follows
*/
*cp = '\0';
safe_str(ip, buff, bufc);
return;
}
/*
* Continue search after found first character
*/
bp = cp + 1;
}
/*
* Ran off the end without finding it
*/
safe_str(ip, buff, bufc);
return;
}
/*
* ---------------------------------------------------------------------------
* * fun_max, fun_min: Return maximum (minimum) value.
*/
static void fun_max(char *buff, char **bufc, dbref player, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs)
{
int i, j, got_one;
double max;
max = 0;
for (i = 0, got_one = 0; i < nfargs; i++) {
if (fargs[i]) {
j = atof(fargs[i]);
if (!got_one || (j > max)) {
got_one = 1;
max = j;
}
}
}
if (!got_one)
safe_str("#-1 TOO FEW ARGUMENTS", buff, bufc);
else
fval(buff, bufc, max);
return;
}
static void fun_min(char *buff, char **bufc, dbref player, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs)
{
int i, j, got_one;
double min;
min = 0;
for (i = 0, got_one = 0; i < nfargs; i++) {
if (fargs[i]) {
j = atof(fargs[i]);
if (!got_one || (j < min)) {
got_one = 1;
min = j;
}
}
}
if (!got_one) {
safe_str("#-1 TOO FEW ARGUMENTS", buff, bufc);
} else {
fval(buff, bufc, min);
}
return;
}
/*
* ---------------------------------------------------------------------------
* * fun_search: Search the db for things, returning a list of what matches
*/
static void fun_search(char *buff, char **bufc, dbref player, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs)
{
dbref thing;
char *bp, *nbuf;
SEARCH searchparm;
/*
* Set up for the search. If any errors, abort.
*/
if (!search_setup(player, fargs[0], &searchparm)) {
safe_str("#-1 ERROR DURING SEARCH", buff, bufc);
return;
}
/*
* Do the search and report the results
*/
olist_push();
search_perform(player, cause, &searchparm);
bp = *bufc;
nbuf = alloc_sbuf("fun_search");
for (thing = olist_first(); thing != NOTHING; thing = olist_next()) {
if (bp == *bufc)
sprintf(nbuf, "#%d", thing);
else
sprintf(nbuf, " #%d", thing);
safe_str(nbuf, buff, bufc);
}
free_sbuf(nbuf);
olist_pop();
}
/*
* ---------------------------------------------------------------------------
* * fun_stats: Get database size statistics.
*/
static void fun_stats(char *buff, char **bufc, dbref player, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs)
{
dbref who;
STATS statinfo;
if ((!fargs[0]) || !*fargs[0] || !string_compare(fargs[0], "all")) {
who = NOTHING;
} else {
who = lookup_player(player, fargs[0], 1);
if (who == NOTHING) {
safe_str("#-1 NOT FOUND", buff, bufc);
return;
}
}
if (!get_stats(player, who, &statinfo)) {
safe_str("#-1 ERROR GETTING STATS", buff, bufc);
return;
}
safe_tprintf_str(buff, bufc, "%d %d %d %d %d %d", statinfo.s_total,
statinfo.s_rooms, statinfo.s_exits, statinfo.s_things,
statinfo.s_players, statinfo.s_garbage);
}
/*
* ---------------------------------------------------------------------------
* * fun_merge: given two strings and a character, merge the two strings
* * by replacing characters in string1 that are the same as the given
* * character by the corresponding character in string2 (by position).
* * The strings must be of the same length.
*/
static void fun_merge(char *buff, char **bufc, dbref player, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs)
{
char *str, *rep;
char c;
/*
* do length checks first
*/
if (strlen(fargs[0]) != strlen(fargs[1])) {
safe_str("#-1 STRING LENGTHS MUST BE EQUAL", buff, bufc);
return;
}
if (strlen(fargs[2]) > 1) {
safe_str("#-1 TOO MANY CHARACTERS", buff, bufc);
return;
}
/*
* find the character to look for. null character is considered * a *
*
* * * * space
*/
if (!*fargs[2])
c = ' ';
else
c = *fargs[2];
/*
* walk strings, copy from the appropriate string
*/
for (str = fargs[0], rep = fargs[1];
*str && *rep && ((*bufc - buff) < LBUF_SIZE);
str++, rep++, (*bufc)++) {
if (*str == c)
**bufc = *rep;
else
**bufc = *str;
}
/*
* There is no need to check for overflowing the buffer since * both
* * * * strings are LBUF_SIZE or less and the new string cannot be *
* * any * * longer.
*/
return;
}
/*
* ---------------------------------------------------------------------------
* * fun_splice: similar to MERGE(), eplaces by word instead of by character.
*/
static void fun_splice(char *buff, char **bufc, dbref player, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs)
{
char *p1, *p2, *q1, *q2, sep;
int words, i, first;
varargs_preamble("SPLICE", 4);
/*
* length checks
*/
if (countwords(fargs[2], sep) > 1) {
safe_str("#-1 TOO MANY WORDS", buff, bufc);
return;
}
words = countwords(fargs[0], sep);
if (words != countwords(fargs[1], sep)) {
safe_str("#-1 NUMBER OF WORDS MUST BE EQUAL", buff, bufc);
return;
}
/*
* loop through the two lists
*/
p1 = fargs[0];
q1 = fargs[1];
first = 1;
for (i = 0; i < words; i++) {
p2 = split_token(&p1, sep);
q2 = split_token(&q1, sep);
if (!first)
safe_chr(sep, buff, bufc);
if (!strcmp(p2, fargs[2]))
safe_str(q2, buff, bufc); /*
* replace
*/
else
safe_str(p2, buff, bufc); /*
* copy
*/
first = 0;
}
}
/*
* ---------------------------------------------------------------------------
* * fun_repeat: repeats a string
*/
static void fun_repeat(char *buff, char **bufc, dbref player, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs)
{
int times, i;
times = atoi(fargs[1]);
if ((times < 1) || (fargs[0] == NULL) || (!*fargs[0])) {
return;
} else if (times == 1) {
safe_str(fargs[0], buff, bufc);
} else if (strlen(fargs[0]) * times >= (LBUF_SIZE - 1)) {
safe_str("#-1 STRING TOO LONG", buff, bufc);
} else {
for (i = 0; i < times; i++)
safe_str(fargs[0], buff, bufc);
}
}
/*
* ---------------------------------------------------------------------------
* * fun_iter: Make list from evaluating arg2 with each member of arg1.
* * NOTE: This function expects that its arguments have not been evaluated.
*/
static void fun_iter(char *buff, char **bufc, dbref player, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs)
{
char *curr, *objstring, *buff2, *buff3, *cp, *dp, sep, *str;
int first, number = 0;
evarargs_preamble("ITER", 3);
dp = cp = curr = alloc_lbuf("fun_iter");
str = fargs[0];
exec(curr, &dp, 0, player, cause, EV_STRIP | EV_FCHECK | EV_EVAL, &str,
cargs, ncargs);
*dp = '\0';
cp = trim_space_sep(cp, sep);
if (!*cp) {
free_lbuf(curr);
return;
}
first = 1;
while (cp) {
if (!first)
safe_chr(' ', buff, bufc);
first = 0;
number++;
objstring = split_token(&cp, sep);
buff2 = replace_string(BOUND_VAR, objstring, fargs[1]);
buff3 =
replace_string(LISTPLACE_VAR, tprintf("%d", number), buff2);
str = buff3;
exec(buff, bufc, 0, player, cause, EV_STRIP | EV_FCHECK | EV_EVAL,
&str, cargs, ncargs);
free_lbuf(buff2);
free_lbuf(buff3);
}
free_lbuf(curr);
}
static void fun_list(char *buff, char **bufc, dbref player, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs)
{
char *curr, *objstring, *buff2, *buff3, *result, *cp, *dp, *str, sep;
int number = 0;
evarargs_preamble("LIST", 3);
cp = curr = dp = alloc_lbuf("fun_list");
str = fargs[0];
exec(curr, &dp, 0, player, cause, EV_STRIP | EV_FCHECK | EV_EVAL, &str,
cargs, ncargs);
cp = trim_space_sep(cp, sep);
if (!*cp) {
free_lbuf(curr);
return;
}
while (cp) {
number++;
objstring = split_token(&cp, sep);
buff2 = replace_string(BOUND_VAR, objstring, fargs[1]);
buff3 =
replace_string(LISTPLACE_VAR, tprintf("%d", number), buff2);
dp = result = alloc_lbuf("fun_list.2");
str = buff3;
exec(result, &dp, 0, player, cause, EV_STRIP | EV_FCHECK | EV_EVAL,
&str, cargs, ncargs);
*dp = '\0';
free_lbuf(buff2);
free_lbuf(buff3);
notify(cause, result);
free_lbuf(result);
}
free_lbuf(curr);
}
/*
* ---------------------------------------------------------------------------
* * fun_fold: iteratively eval an attrib with a list of arguments
* * and an optional base case. With no base case, the first list element
* * is passed as %0 and the second is %1. The attrib is then evaluated
* * with these args, the result is then used as %0 and the next arg is
* * %1 and so it goes as there are elements left in the list. The
* * optinal base case gives the user a nice starting point.
* *
* * > &REP_NUM object=[%0][repeat(%1,%1)]
* * > say fold(OBJECT/REP_NUM,1 2 3 4 5,->)
* * You say "->122333444455555"
* *
* * NOTE: To use added list separator, you must use base case!
*/
static void fun_fold(char *buff, char **bufc, dbref player, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs)
{
dbref aowner, thing;
int aflags, anum;
ATTR *ap;
char *atext, *result, *curr, *bp, *str, *cp, *atextbuf, *clist[2],
*rstore, sep;
/*
* We need two to four arguements only
*/
mvarargs_preamble("FOLD", 2, 4);
/*
* Two possibilities for the first arg: <obj>/<attr> and <attr>.
*/
if (parse_attrib(player, fargs[0], &thing, &anum)) {
if ((anum == NOTHING) || (!Good_obj(thing)))
ap = NULL;
else
ap = atr_num(anum);
} else {
thing = player;
ap = atr_str(fargs[0]);
}
/*
* Make sure we got a good attribute
*/
if (!ap) {
return;
}
/*
* Use it if we can access it, otherwise return an error.
*/
atext = atr_pget(thing, ap->number, &aowner, &aflags);
if (!atext) {
return;
} else if (!*atext || !See_attr(player, thing, ap, aowner, aflags)) {
free_lbuf(atext);
return;
}
/*
* Evaluate it using the rest of the passed function args
*/
cp = curr = fargs[1];
atextbuf = alloc_lbuf("fun_fold");
StringCopy(atextbuf, atext);
/*
* may as well handle first case now
*/
if ((nfargs >= 3) && (fargs[2])) {
clist[0] = fargs[2];
clist[1] = split_token(&cp, sep);
result = bp = alloc_lbuf("fun_fold");
str = atextbuf;
exec(result, &bp, 0, player, cause, EV_STRIP | EV_FCHECK | EV_EVAL,
&str, clist, 2);
*bp = '\0';
} else {
clist[0] = split_token(&cp, sep);
clist[1] = split_token(&cp, sep);
result = bp = alloc_lbuf("fun_fold");
str = atextbuf;
exec(result, &bp, 0, player, cause, EV_STRIP | EV_FCHECK | EV_EVAL,
&str, clist, 2);
*bp = '\0';
}
rstore = result;
result = NULL;
while (cp) {
clist[0] = rstore;
clist[1] = split_token(&cp, sep);
StringCopy(atextbuf, atext);
result = bp = alloc_lbuf("fun_fold");
str = atextbuf;
exec(result, &bp, 0, player, cause, EV_STRIP | EV_FCHECK | EV_EVAL,
&str, clist, 2);
*bp = '\0';
StringCopy(rstore, result);
free_lbuf(result);
}
safe_str(rstore, buff, bufc);
free_lbuf(rstore);
free_lbuf(atext);
free_lbuf(atextbuf);
}
/*
* ---------------------------------------------------------------------------
* * fun_filter: iteratively perform a function with a list of arguments
* * and return the arg, if the function evaluates to TRUE using the
* * arg.
* *
* * > &IS_ODD object=mod(%0,2)
* * > say filter(object/is_odd,1 2 3 4 5)
* * You say "1 3 5"
* * > say filter(object/is_odd,1-2-3-4-5,-)
* * You say "1-3-5"
* *
* * NOTE: If you specify a separator it is used to delimit returned list
*/
static void fun_filter(char *buff, char **bufc, dbref player, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs)
{
dbref aowner, thing;
int aflags, anum, first;
ATTR *ap;
char *atext, *result, *curr, *objstring, *bp, *str, *cp, *atextbuf,
sep;
varargs_preamble("FILTER", 3);
/*
* Two possibilities for the first arg: <obj>/<attr> and <attr>.
*/
if (parse_attrib(player, fargs[0], &thing, &anum)) {
if ((anum == NOTHING) || (!Good_obj(thing)))
ap = NULL;
else
ap = atr_num(anum);
} else {
thing = player;
ap = atr_str(fargs[0]);
}
/*
* Make sure we got a good attribute
*/
if (!ap) {
return;
}
/*
* Use it if we can access it, otherwise return an error.
*/
atext = atr_pget(thing, ap->number, &aowner, &aflags);
if (!atext) {
return;
} else if (!*atext || !See_attr(player, thing, ap, aowner, aflags)) {
free_lbuf(atext);
return;
}
/*
* Now iteratively eval the attrib with the argument list
*/
cp = curr = trim_space_sep(fargs[1], sep);
atextbuf = alloc_lbuf("fun_filter");
first = 1;
while (cp) {
objstring = split_token(&cp, sep);
StringCopy(atextbuf, atext);
result = bp = alloc_lbuf("fun_filter");
str = atextbuf;
exec(result, &bp, 0, player, cause, EV_STRIP | EV_FCHECK | EV_EVAL,
&str, &objstring, 1);
*bp = '\0';
if (!first && *result == '1')
safe_chr(sep, buff, bufc);
if (*result == '1') {
safe_str(objstring, buff, bufc);
first = 0;
}
free_lbuf(result);
}
free_lbuf(atext);
free_lbuf(atextbuf);
}
/*
* ---------------------------------------------------------------------------
* * fun_map: iteratively evaluate an attribute with a list of arguments.
* *
* * > &DIV_TWO object=fdiv(%0,2)
* * > say map(1 2 3 4 5,object/div_two)
* * You say "0.5 1 1.5 2 2.5"
* * > say map(object/div_two,1-2-3-4-5,-)
* * You say "0.5-1-1.5-2-2.5"
* *
*/
static void fun_map(char *buff, char **bufc, dbref player, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs)
{
dbref aowner, thing;
int aflags, anum, first;
ATTR *ap;
char *atext, *objstring, *str, *cp, *atextbuf, sep;
varargs_preamble("MAP", 3);
/*
* Two possibilities for the second arg: <obj>/<attr> and <attr>.
*/
if (parse_attrib(player, fargs[0], &thing, &anum)) {
if ((anum == NOTHING) || (!Good_obj(thing)))
ap = NULL;
else
ap = atr_num(anum);
} else {
thing = player;
ap = atr_str(fargs[0]);
}
/*
* Make sure we got a good attribute
*/
if (!ap) {
return;
}
/*
* Use it if we can access it, otherwise return an error.
*/
atext = atr_pget(thing, ap->number, &aowner, &aflags);
if (!atext) {
return;
} else if (!*atext || !See_attr(player, thing, ap, aowner, aflags)) {
free_lbuf(atext);
return;
}
/*
* now process the list one element at a time
*/
cp = trim_space_sep(fargs[1], sep);
atextbuf = alloc_lbuf("fun_map");
first = 1;
while (cp) {
if (!first)
safe_chr(sep, buff, bufc);
first = 0;
objstring = split_token(&cp, sep);
StringCopy(atextbuf, atext);
str = atextbuf;
exec(buff, bufc, 0, player, cause, EV_STRIP | EV_FCHECK | EV_EVAL,
&str, &objstring, 1);
}
free_lbuf(atext);
free_lbuf(atextbuf);
}
/*
* ---------------------------------------------------------------------------
* * fun_edit: Edit text.
*/
static void fun_edit(char *buff, char **bufc, dbref player, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs)
{
char *tstr;
edit_string((char *) strip_ansi(fargs[0]), &tstr, fargs[1], fargs[2]);
safe_str(tstr, buff, bufc);
free_lbuf(tstr);
}
/*
* ---------------------------------------------------------------------------
* * fun_locate: Search for things with the perspective of another obj.
*/
static void fun_locate(char *buff, char **bufc, dbref player, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs)
{
int pref_type, check_locks, verbose, multiple;
dbref thing, what;
char *cp;
pref_type = NOTYPE;
check_locks = verbose = multiple = 0;
/*
* Find the thing to do the looking, make sure we control it.
*/
if (See_All(player))
thing = match_thing(player, fargs[0]);
else
thing = match_controlled(player, fargs[0]);
if (!Good_obj(thing)) {
safe_str("#-1 PERMISSION DENIED", buff, bufc);
return;
}
/*
* Get pre- and post-conditions and modifiers
*/
for (cp = fargs[2]; *cp; cp++) {
switch (*cp) {
case 'E':
pref_type = TYPE_EXIT;
break;
case 'L':
check_locks = 1;
break;
case 'P':
pref_type = TYPE_PLAYER;
break;
case 'R':
pref_type = TYPE_ROOM;
break;
case 'T':
pref_type = TYPE_THING;
break;
case 'V':
verbose = 1;
break;
case 'X':
multiple = 1;
break;
}
}
/*
* Set up for the search
*/
if (check_locks)
init_match_check_keys(thing, fargs[1], pref_type);
else
init_match(thing, fargs[1], pref_type);
/*
* Search for each requested thing
*/
for (cp = fargs[2]; *cp; cp++) {
switch (*cp) {
case 'a':
match_absolute();
break;
case 'c':
match_carried_exit_with_parents();
break;
case 'e':
match_exit_with_parents();
break;
case 'h':
match_here();
break;
case 'i':
match_possession();
break;
case 'm':
match_me();
break;
case 'n':
match_neighbor();
break;
case 'p':
match_player();
break;
case '*':
match_everything(MAT_EXIT_PARENTS);
break;
}
}
/*
* Get the result and return it to the caller
*/
if (multiple)
what = last_match_result();
else
what = match_result();
if (verbose)
(void) match_status(player, what);
safe_tprintf_str(buff, bufc, "#%d", what);
}
/*
* ---------------------------------------------------------------------------
* * fun_switch: Return value based on pattern matching (ala @switch)
* * NOTE: This function expects that its arguments have not been evaluated.
*/
static void fun_switch(char *buff, char **bufc, dbref player, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs)
{
int i;
char *mbuff, *tbuff, *buf, *bp, *str;
/*
* If we don't have at least 2 args, return nothing
*/
if (nfargs < 2) {
return;
}
/*
* Evaluate the target in fargs[0]
*/
mbuff = bp = alloc_lbuf("fun_switch");
str = fargs[0];
exec(mbuff, &bp, 0, player, cause, EV_STRIP | EV_FCHECK | EV_EVAL,
&str, cargs, ncargs);
*bp = '\0';
/*
* Loop through the patterns looking for a match
*/
for (i = 1; (i < nfargs - 1) && fargs[i] && fargs[i + 1]; i += 2) {
tbuff = bp = alloc_lbuf("fun_switch.2");
str = fargs[i];
exec(tbuff, &bp, 0, player, cause, EV_STRIP | EV_FCHECK | EV_EVAL,
&str, cargs, ncargs);
*bp = '\0';
if (quick_wild(tbuff, mbuff)) {
free_lbuf(tbuff);
buf = alloc_lbuf("fun_switch");
StringCopy(buf, fargs[i + 1]);
str = buf;
exec(buff, bufc, 0, player, cause,
EV_STRIP | EV_FCHECK | EV_EVAL, &str, cargs, ncargs);
free_lbuf(buf);
free_lbuf(mbuff);
return;
}
free_lbuf(tbuff);
}
free_lbuf(mbuff);
/*
* Nope, return the default if there is one
*/
if ((i < nfargs) && fargs[i]) {
buf = alloc_lbuf("fun_switch");
StringCopy(buf, fargs[i]);
str = buf;
exec(buff, bufc, 0, player, cause, EV_STRIP | EV_FCHECK | EV_EVAL,
&str, cargs, ncargs);
free_lbuf(buf);
}
return;
}
static void fun_case(char *buff, char **bufc, dbref player, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs)
{
int i;
char *mbuff, *buf, *bp, *str;
/*
* If we don't have at least 2 args, return nothing
*/
if (nfargs < 2) {
return;
}
/*
* Evaluate the target in fargs[0]
*/
mbuff = bp = alloc_lbuf("fun_switch");
str = fargs[0];
exec(mbuff, &bp, 0, player, cause, EV_STRIP | EV_FCHECK | EV_EVAL,
&str, cargs, ncargs);
*bp = '\0';
/*
* Loop through the patterns looking for a match
*/
for (i = 1; (i < nfargs - 1) && fargs[i] && fargs[i + 1]; i += 2) {
if (*fargs[i] == *mbuff) {
buf = alloc_lbuf("fun_switch");
StringCopy(buf, fargs[i + 1]);
str = buf;
exec(buff, bufc, 0, player, cause,
EV_STRIP | EV_FCHECK | EV_EVAL, &str, cargs, ncargs);
free_lbuf(buf);
free_lbuf(mbuff);
return;
}
}
free_lbuf(mbuff);
/*
* Nope, return the default if there is one
*/
if ((i < nfargs) && fargs[i]) {
buf = alloc_lbuf("fun_switch");
StringCopy(buf, fargs[i]);
str = buf;
exec(buff, bufc, 0, player, cause, EV_STRIP | EV_FCHECK | EV_EVAL,
&str, cargs, ncargs);
free_lbuf(buf);
}
return;
}
/*
* ---------------------------------------------------------------------------
* * fun_space: Make spaces.
*/
static void fun_space(char *buff, char **bufc, dbref player, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs)
{
int num;
char *cp;
if (!fargs[0] || !(*fargs[0])) {
num = 1;
} else {
num = atoi(fargs[0]);
}
if (num < 1) {
/*
* If negative or zero spaces return a single space, * * * *
* -except- allow 'space(0)' to return "" for calculated * *
* * * padding
*/
if (!is_integer(fargs[0]) || (num != 0)) {
num = 1;
}
} else if (num >= LBUF_SIZE) {
num = LBUF_SIZE - 1;
}
for (cp = *bufc; num > 0; num--)
*cp++ = ' ';
*bufc = cp;
return;
}
/*
* ---------------------------------------------------------------------------
* * fun_idle, fun_conn: return seconds idle or connected.
*/
static void fun_idle(char *buff, char **bufc, dbref player, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs)
{
dbref target;
target = lookup_player(player, fargs[0], 1);
if (Good_obj(target) && Dark(target) && !Wizard(player))
target = NOTHING;
safe_tprintf_str(buff, bufc, "%d", fetch_idle(target));
}
static void fun_conn(char *buff, char **bufc, dbref player, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs)
{
dbref target;
target = lookup_player(player, fargs[0], 1);
if (Good_obj(target) && Dark(target) && !Wizard(player))
target = NOTHING;
safe_tprintf_str(buff, bufc, "%d", fetch_connect(target));
}
/*
* ---------------------------------------------------------------------------
* * fun_sort: Sort lists.
*/
typedef struct f_record f_rec;
typedef struct i_record i_rec;
struct f_record {
double data;
char *str;
};
struct i_record {
long data;
char *str;
};
static int a_comp(s1, s2)
const void *s1, *s2;
{
return strcmp(*(char **) s1, *(char **) s2);
}
static int f_comp(s1, s2)
const void *s1, *s2;
{
if (((f_rec *) s1)->data > ((f_rec *) s2)->data)
return 1;
if (((f_rec *) s1)->data < ((f_rec *) s2)->data)
return -1;
return 0;
}
static int i_comp(s1, s2)
const void *s1, *s2;
{
if (((i_rec *) s1)->data > ((i_rec *) s2)->data)
return 1;
if (((i_rec *) s1)->data < ((i_rec *) s2)->data)
return -1;
return 0;
}
static void do_asort(s, n, sort_type)
char *s[];
int n, sort_type;
{
int i;
f_rec *fp;
i_rec *ip;
switch (sort_type) {
case ALPHANUM_LIST:
qsort((void *) s, n, sizeof(char *), a_comp);
break;
case NUMERIC_LIST:
ip = (i_rec *) malloc(n * sizeof(i_rec));
for (i = 0; i < n; i++) {
ip[i].str = s[i];
ip[i].data = atoi(s[i]);
}
qsort((void *) ip, n, sizeof(i_rec), i_comp);
for (i = 0; i < n; i++) {
s[i] = ip[i].str;
}
free(ip);
break;
case DBREF_LIST:
ip = (i_rec *) malloc(n * sizeof(i_rec));
for (i = 0; i < n; i++) {
ip[i].str = s[i];
ip[i].data = dbnum(s[i]);
}
qsort((void *) ip, n, sizeof(i_rec), i_comp);
for (i = 0; i < n; i++) {
s[i] = ip[i].str;
}
free(ip);
break;
case FLOAT_LIST:
fp = (f_rec *) malloc(n * sizeof(f_rec));
for (i = 0; i < n; i++) {
fp[i].str = s[i];
fp[i].data = atof(s[i]);
}
qsort((void *) fp, n, sizeof(f_rec), f_comp);
for (i = 0; i < n; i++) {
s[i] = fp[i].str;
}
free(fp);
break;
}
}
static void fun_sort(char *buff, char **bufc, dbref player, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs)
{
int nitems, sort_type;
char *list, sep;
char *ptrs[LBUF_SIZE / 2];
/*
* If we are passed an empty arglist return a null string
*/
if (nfargs == 0) {
return;
}
mvarargs_preamble("SORT", 1, 3);
/*
* Convert the list to an array
*/
list = alloc_lbuf("fun_sort");
StringCopy(list, fargs[0]);
nitems = list2arr(ptrs, LBUF_SIZE / 2, list, sep);
sort_type = get_list_type(fargs, nfargs, 2, ptrs, nitems);
do_asort(ptrs, nitems, sort_type);
arr2list(ptrs, nitems, buff, bufc, sep);
free_lbuf(list);
}
/*
* ---------------------------------------------------------------------------
* * fun_setunion, fun_setdiff, fun_setinter: Set management.
*/
#define SET_UNION 1
#define SET_INTERSECT 2
#define SET_DIFF 3
static void handle_sets(fargs, buff, bufc, oper, sep)
char *fargs[], *buff, **bufc, sep;
int oper;
{
char *list1, *list2, *oldp;
char *ptrs1[LBUF_SIZE], *ptrs2[LBUF_SIZE];
int i1, i2, n1, n2, val, first;
list1 = alloc_lbuf("fun_setunion.1");
StringCopy(list1, fargs[0]);
n1 = list2arr(ptrs1, LBUF_SIZE, list1, sep);
do_asort(ptrs1, n1, ALPHANUM_LIST);
list2 = alloc_lbuf("fun_setunion.2");
StringCopy(list2, fargs[1]);
n2 = list2arr(ptrs2, LBUF_SIZE, list2, sep);
do_asort(ptrs2, n2, ALPHANUM_LIST);
i1 = i2 = 0;
first = 1;
oldp = *bufc;
**bufc = '\0';
switch (oper) {
case SET_UNION: /*
* Copy elements common to both lists
*/
/*
* Handle case of two identical single-element lists
*/
if ((n1 == 1) && (n2 == 1) && (!strcmp(ptrs1[0], ptrs2[0]))) {
safe_str(ptrs1[0], buff, bufc);
break;
}
/*
* Process until one list is empty
*/
while ((i1 < n1) && (i2 < n2)) {
/*
* Skip over duplicates
*/
if ((i1 > 0) || (i2 > 0)) {
while ((i1 < n1) && !strcmp(ptrs1[i1], oldp))
i1++;
while ((i2 < n2) && !strcmp(ptrs2[i2], oldp))
i2++;
}
/*
* Compare and copy
*/
if ((i1 < n1) && (i2 < n2)) {
if (!first)
safe_chr(sep, buff, bufc);
first = 0;
oldp = *bufc;
if (strcmp(ptrs1[i1], ptrs2[i2]) < 0) {
safe_str(ptrs1[i1], buff, bufc);
i1++;
} else {
safe_str(ptrs2[i2], buff, bufc);
i2++;
}
**bufc = '\0';
}
}
/*
* Copy rest of remaining list, stripping duplicates
*/
for (; i1 < n1; i1++) {
if (strcmp(oldp, ptrs1[i1])) {
if (!first)
safe_chr(sep, buff, bufc);
first = 0;
oldp = *bufc;
safe_str(ptrs1[i1], buff, bufc);
**bufc = '\0';
}
}
for (; i2 < n2; i2++) {
if (strcmp(oldp, ptrs2[i2])) {
if (!first)
safe_chr(sep, buff, bufc);
first = 0;
oldp = *bufc;
safe_str(ptrs2[i2], buff, bufc);
**bufc = '\0';
}
}
break;
case SET_INTERSECT: /*
* Copy elements not in both lists
*/
while ((i1 < n1) && (i2 < n2)) {
val = strcmp(ptrs1[i1], ptrs2[i2]);
if (!val) {
/*
* Got a match, copy it
*/
if (!first)
safe_chr(sep, buff, bufc);
first = 0;
oldp = *bufc;
safe_str(ptrs1[i1], buff, bufc);
i1++;
i2++;
while ((i1 < n1) && !strcmp(ptrs1[i1], oldp))
i1++;
while ((i2 < n2) && !strcmp(ptrs2[i2], oldp))
i2++;
} else if (val < 0) {
i1++;
} else {
i2++;
}
}
break;
case SET_DIFF: /*
* Copy elements unique to list1
*/
while ((i1 < n1) && (i2 < n2)) {
val = strcmp(ptrs1[i1], ptrs2[i2]);
if (!val) {
/*
* Got a match, increment pointers
*/
oldp = ptrs1[i1];
while ((i1 < n1) && !strcmp(ptrs1[i1], oldp))
i1++;
while ((i2 < n2) && !strcmp(ptrs2[i2], oldp))
i2++;
} else if (val < 0) {
/*
* Item in list1 not in list2, copy
*/
if (!first)
safe_chr(sep, buff, bufc);
first = 0;
safe_str(ptrs1[i1], buff, bufc);
oldp = ptrs1[i1];
i1++;
while ((i1 < n1) && !strcmp(ptrs1[i1], oldp))
i1++;
} else {
/*
* Item in list2 but not in list1, discard
*/
oldp = ptrs2[i2];
i2++;
while ((i2 < n2) && !strcmp(ptrs2[i2], oldp))
i2++;
}
}
/*
* Copy remainder of list1
*/
while (i1 < n1) {
if (!first)
safe_chr(sep, buff, bufc);
first = 0;
safe_str(ptrs1[i1], buff, bufc);
oldp = ptrs1[i1];
i1++;
while ((i1 < n1) && !strcmp(ptrs1[i1], oldp))
i1++;
}
}
free_lbuf(list1);
free_lbuf(list2);
return;
}
static void fun_setunion(char *buff, char **bufc, dbref player, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs)
{
char sep;
varargs_preamble("SETUNION", 3);
handle_sets(fargs, buff, bufc, SET_UNION, sep);
return;
}
static void fun_setdiff(char *buff, char **bufc, dbref player, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs)
{
char sep;
varargs_preamble("SETDIFF", 3);
handle_sets(fargs, buff, bufc, SET_DIFF, sep);
return;
}
static void fun_setinter(char *buff, char **bufc, dbref player, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs)
{
char sep;
varargs_preamble("SETINTER", 3);
handle_sets(fargs, buff, bufc, SET_INTERSECT, sep);
return;
}
/*
* ---------------------------------------------------------------------------
* * rjust, ljust, center: Justify or center text, specifying fill character
*/
static void fun_ljust(char *buff, char **bufc, dbref player, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs)
{
int spaces, i;
char sep;
varargs_preamble("LJUST", 3);
spaces = atoi(fargs[1]) - strlen((char *) strip_ansi(fargs[0]));
/*
* Sanitize number of spaces
*/
if (spaces <= 0) {
/*
* no padding needed, just return string
*/
safe_str(fargs[0], buff, bufc);
return;
} else if (spaces > LBUF_SIZE) {
spaces = LBUF_SIZE;
}
safe_str(fargs[0], buff, bufc);
for (i = 0; i < spaces; i++)
safe_chr(sep, buff, bufc);
}
static void fun_rjust(char *buff, char **bufc, dbref player, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs)
{
int spaces, i;
char sep;
varargs_preamble("RJUST", 3);
spaces = atoi(fargs[1]) - strlen((char *) strip_ansi(fargs[0]));
/*
* Sanitize number of spaces
*/
if (spaces <= 0) {
/*
* no padding needed, just return string
*/
safe_str(fargs[0], buff, bufc);
return;
} else if (spaces > LBUF_SIZE) {
spaces = LBUF_SIZE;
}
for (i = 0; i < spaces; i++)
safe_chr(sep, buff, bufc);
safe_str(fargs[0], buff, bufc);
}
static void fun_center(char *buff, char **bufc, dbref player, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs)
{
char sep;
int i, len, lead_chrs, trail_chrs, width;
varargs_preamble("CENTER", 3);
width = atoi(fargs[1]);
len = strlen((char *) strip_ansi(fargs[0]));
if (width > LBUF_SIZE) {
safe_str("#-1 OUT OF RANGE", buff, bufc);
return;
}
if (len >= width) {
safe_str(fargs[0], buff, bufc);
return;
}
lead_chrs = (width / 2) - (len / 2) + .5;
for (i = 0; i < lead_chrs; i++)
safe_chr(sep, buff, bufc);
safe_str(fargs[0], buff, bufc);
trail_chrs = width - lead_chrs - len;
for (i = 0; i < trail_chrs; i++)
safe_chr(sep, buff, bufc);
}
/*
* ---------------------------------------------------------------------------
* * setq, setr, r: set and read global registers.
*/
static void fun_setq(char *buff, char **bufc, dbref player, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs)
{
int regnum;
regnum = atoi(fargs[0]);
if ((regnum < 0) || (regnum >= MAX_GLOBAL_REGS)) {
safe_str("#-1 INVALID GLOBAL REGISTER", buff, bufc);
} else {
if (!mudstate.global_regs[regnum])
mudstate.global_regs[regnum] = alloc_lbuf("fun_setq");
StringCopy(mudstate.global_regs[regnum], fargs[1]);
}
}
static void fun_setr(char *buff, char **bufc, dbref player, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs)
{
int regnum;
regnum = atoi(fargs[0]);
if ((regnum < 0) || (regnum >= MAX_GLOBAL_REGS)) {
safe_str("#-1 INVALID GLOBAL REGISTER", buff, bufc);
return;
} else {
if (!mudstate.global_regs[regnum])
mudstate.global_regs[regnum] = alloc_lbuf("fun_setq");
StringCopy(mudstate.global_regs[regnum], fargs[1]);
}
safe_str(fargs[1], buff, bufc);
}
static void fun_r(char *buff, char **bufc, dbref player, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs)
{
int regnum;
regnum = atoi(fargs[0]);
if ((regnum < 0) || (regnum >= MAX_GLOBAL_REGS)) {
safe_str("#-1 INVALID GLOBAL REGISTER", buff, bufc);
} else if (mudstate.global_regs[regnum]) {
safe_str(mudstate.global_regs[regnum], buff, bufc);
}
}
/*
* ---------------------------------------------------------------------------
* * isnum: is the argument a number?
*/
static void fun_isnum(char *buff, char **bufc, dbref player, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs)
{
safe_str((is_number(fargs[0]) ? "1" : "0"), buff, bufc);
}
/*
* ---------------------------------------------------------------------------
* * isdbref: is the argument a valid dbref?
*/
static void fun_isdbref(char *buff, char **bufc, dbref player, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs)
{
char *p;
dbref dbitem;
p = fargs[0];
if (*p++ == NUMBER_TOKEN) {
dbitem = parse_dbref(p);
if (Good_obj(dbitem)) {
safe_str("1", buff, bufc);
return;
}
}
safe_str("0", buff, bufc);
}
/*
* ---------------------------------------------------------------------------
* * trim: trim off unwanted white space.
*/
static void fun_trim(char *buff, char **bufc, dbref player, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs)
{
char *p, *lastchar, *q, sep;
int trim;
if (nfargs == 0) {
return;
}
mvarargs_preamble("TRIM", 1, 3);
if (nfargs >= 2) {
switch (ToLower(*fargs[1])) {
case 'l':
trim = 1;
break;
case 'r':
trim = 2;
break;
default:
trim = 3;
break;
}
} else {
trim = 3;
}
if (trim == 2 || trim == 3) {
p = lastchar = fargs[0];
while (*p != '\0') {
if (*p != sep)
lastchar = p;
p++;
}
*(lastchar + 1) = '\0';
}
q = fargs[0];
if (trim == 1 || trim == 3) {
while (*q != '\0') {
if (*q == sep)
q++;
else
break;
}
}
safe_str(q, buff, bufc);
}
#ifdef ARBITRARY_LOGFILES
static void fun_logf(char *buff, char **bufc, dbref player, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs)
{
if (!fargs[0] || !fargs[1]) {
safe_str("#-1 INVALID ARGUMENTS", buff, bufc);
}
if (log_to_file(player, fargs[0], fargs[1]))
return;
safe_str("#-1 INVALID LOGFILE", buff, bufc);
return;
}
#endif
/* ----------------------------------------------------------------------
** fun_doing: return @doing string for arg.
** arg is either socket or player (Code adopted from Mux2.3)
*/
static void fun_doing(char *buff, char **bufc, dbref player, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs)
{
if ( is_number( fargs[0] ) )
{
int s = atoi( fargs[0] );
unsigned short bFound = 0;
DESC *d;
DESC_ITER_CONN(d)
{
if (d->descriptor == s)
{
bFound = 1;
break;
}
}
if ( bFound
&& ( d->player == player
|| Wizard_Who(player)))
{
safe_str(d->doing, buff, bufc);
}
else
{
/* [cad] Mux2.3 returns empty string here, not sure what
convention is used here. Just return #-1 for now */
safe_str("#-1", buff, bufc);
}
}
else
{
dbref victim = lookup_player(player, fargs[0], 1);
if (victim == NOTHING)
{
safe_str("#-1 PLAYER DOES NOT EXIST", buff, bufc);
return;
}
if ( Wizard_Who(player)
|| !Hidden(victim))
{
DESC *d;
DESC_ITER_CONN(d)
{
if (d->player == victim)
{
safe_str(d->doing, buff, bufc);
return;
}
}
}
safe_str("#-1 NOT A CONNECTED PLAYER", buff, bufc);
}
}
/* ----------------------------------------------------------------------
** fun_poll: return @doing header
** (Code adopted from Mux2.3)
*/
static void fun_poll(char *buff, char **bufc, dbref player, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs)
{
safe_str(mudstate.doing_hdr, buff, bufc);
}
/* ----------------------------------------------------------------------
** fun_pairs: take an attr off an object and count the # of
** {[()]} in that attribute and return it as a list
** Modified from fun_get
** Dany - 06/2005
*/
static void fun_pairs(char *buff, char **bufc, dbref player, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs)
{
dbref thing, aowner;
int attrib, free_buffer, aflags;
ATTR *attr;
char *atr_gotten;
struct boolexp *bool;
char *tmp_char;
int right_brace = 0, left_brace = 0, right_square_bracket = 0,
left_square_bracket = 0, right_parenthesis = 0,
left_parenthesis = 0;
if (!parse_attrib(player, fargs[0], &thing, &attrib)) {
safe_str("#-1 NO MATCH", buff, bufc);
return;
}
if (attrib == NOTHING) {
return;
}
free_buffer = 1;
attr = atr_num(attrib); /*
* We need the attr's flags for this:
*/
if (!attr) {
return;
}
if (attr->flags & AF_IS_LOCK) {
atr_gotten = atr_get(thing, attrib, &aowner, &aflags);
if (Read_attr(player, thing, attr, aowner, aflags)) {
bool = parse_boolexp(player, atr_gotten, 1);
free_lbuf(atr_gotten);
atr_gotten = unparse_boolexp(player, bool);
free_boolexp(bool);
} else {
free_lbuf(atr_gotten);
atr_gotten = (char *) "#-1 PERMISSION DENIED";
}
free_buffer = 0;
} else {
atr_gotten = atr_pget(thing, attrib, &aowner, &aflags);
}
/*
* Perform access checks. c_r_p fills buff with an error message * *
*
* * * * if needed.
*/
if (check_read_perms(player, thing, attr, aowner, aflags, buff, bufc)) {
/* Scan through the attribute and count the various brackets */
for(tmp_char = atr_gotten; *tmp_char; tmp_char++) {
switch(*tmp_char) {
case '{':
left_brace++;
break;
case '[':
left_square_bracket++;
break;
case '(':
left_parenthesis++;
break;
case '}':
right_brace++;
break;
case ']':
right_square_bracket++;
break;
case ')':
right_parenthesis++;
break;
default:
break;
}
}
snprintf(atr_gotten, LBUF_SIZE, "%d %d %d %d %d %d",
left_brace,
left_square_bracket,
left_parenthesis,
right_parenthesis,
right_square_bracket,
right_brace);
safe_str(atr_gotten, buff, bufc);
}
if (free_buffer)
free_lbuf(atr_gotten);
return;
}
/* ----------------------------------------------------------------------
** fun_colorpairs: take an attr off an object and color the
** {[()]} in that attribute and return it.
** Modified from fun_get
** Dany - 09/2005
*/
static void fun_colorpairs(char *buff, char **bufc, dbref player, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs)
{
dbref thing, aowner;
int attrib, free_buffer, aflags;
ATTR *attr;
char *atr_gotten;
struct boolexp *bool;
char *tmp_char;
char tmp_string[LBUF_SIZE];
char tmp_piece[2];
if (!parse_attrib(player, fargs[0], &thing, &attrib)) {
safe_str("#-1 NO MATCH", buff, bufc);
return;
}
if (attrib == NOTHING) {
return;
}
free_buffer = 1;
attr = atr_num(attrib); /*
* We need the attr's flags for this:
*/
if (!attr) {
return;
}
if (attr->flags & AF_IS_LOCK) {
atr_gotten = atr_get(thing, attrib, &aowner, &aflags);
if (Read_attr(player, thing, attr, aowner, aflags)) {
bool = parse_boolexp(player, atr_gotten, 1);
free_lbuf(atr_gotten);
atr_gotten = unparse_boolexp(player, bool);
free_boolexp(bool);
} else {
free_lbuf(atr_gotten);
atr_gotten = (char *) "#-1 PERMISSION DENIED";
}
free_buffer = 0;
} else {
atr_gotten = atr_pget(thing, attrib, &aowner, &aflags);
}
/*
* Perform access checks. c_r_p fills buff with an error message * *
*
* * * * if needed.
*/
if (check_read_perms(player, thing, attr, aowner, aflags, buff, bufc)) {
/* zero temporary string */
memset(tmp_string, 0, sizeof(tmp_string));
/* Scan through the attribute, colorize what we want */
for(tmp_char = atr_gotten; *tmp_char; tmp_char++) {
switch(*tmp_char) {
case '{':
strncat(tmp_string, ANSI_RED, LBUF_SIZE);
strncat(tmp_string, "{", LBUF_SIZE);
strncat(tmp_string, ANSI_NORMAL, LBUF_SIZE);
break;
case '[':
strncat(tmp_string, ANSI_YELLOW, LBUF_SIZE);
strncat(tmp_string, "[", LBUF_SIZE);
strncat(tmp_string, ANSI_NORMAL, LBUF_SIZE);
break;
case '(':
strncat(tmp_string, ANSI_GREEN, LBUF_SIZE);
strncat(tmp_string, "(", LBUF_SIZE);
strncat(tmp_string, ANSI_NORMAL, LBUF_SIZE);
break;
case '}':
strncat(tmp_string, ANSI_RED, LBUF_SIZE);
strncat(tmp_string, "}", LBUF_SIZE);
strncat(tmp_string, ANSI_NORMAL, LBUF_SIZE);
break;
case ']':
strncat(tmp_string, ANSI_YELLOW, LBUF_SIZE);
strncat(tmp_string, "]", LBUF_SIZE);
strncat(tmp_string, ANSI_NORMAL, LBUF_SIZE);
break;
case ')':
strncat(tmp_string, ANSI_GREEN, LBUF_SIZE);
strncat(tmp_string, ")", LBUF_SIZE);
strncat(tmp_string, ANSI_NORMAL, LBUF_SIZE);
break;
default:
sprintf(tmp_piece, "%c", *tmp_char);
strncat(tmp_string, tmp_piece, LBUF_SIZE);
break;
}
}
safe_str(tmp_string, buff, bufc);
}
if (free_buffer)
free_lbuf(atr_gotten);
return;
}
/* *INDENT-OFF* */
/* ---------------------------------------------------------------------------
* flist: List of existing functions in alphabetical order.
*/
FUN flist[] = {
{"ABS", fun_abs, 1, 0, CA_PUBLIC},
{"ACOS", fun_acos, 1, 0, CA_PUBLIC},
{"ADD", fun_add, 0, FN_VARARGS, CA_PUBLIC},
{"AFTER", fun_after, 0, FN_VARARGS, CA_PUBLIC},
{"ALPHAMAX", fun_alphamax, 0, FN_VARARGS, CA_PUBLIC},
{"ALPHAMIN", fun_alphamin, 0, FN_VARARGS, CA_PUBLIC},
{"AND", fun_and, 0, FN_VARARGS, CA_PUBLIC},
{"ANDFLAGS", fun_andflags, 2, 0, CA_PUBLIC},
{"ANSI", fun_ansi, 2, 0, CA_PUBLIC},
{"ANSISECURE", fun_ansi_secure, -1, 0, CA_PUBLIC},
{"APOSS", fun_aposs, 1, 0, CA_PUBLIC},
{"ART", fun_art, 1, 0, CA_PUBLIC},
{"ASIN", fun_asin, 1, 0, CA_PUBLIC},
{"ATAN", fun_atan, 1, 0, CA_PUBLIC},
{"BEEP", fun_beep, 0, 0, CA_BUILDER},
{"BEFORE", fun_before, 0, FN_VARARGS, CA_PUBLIC},
#ifdef BT_ENABLED
{"BTARMORSTATUS",fun_btarmorstatus,2,0, CA_WIZARD},
{"BTCRITSTATUS",fun_btcritstatus,2,0, CA_WIZARD},
{"BTDAMAGEMECH",fun_btdamagemech,7, 0, CA_WIZARD},
{"BTDAMAGES", fun_btdamages, 1, 0, CA_WIZARD},
{"BTDESIGNEX", fun_btdesignex, 1, 0, CA_PUBLIC},
{"BTGETCHARVALUE", fun_btgetcharvalue, 3, 0, CA_WIZARD},
{"BTGETXCODEVALUE", fun_btgetxcodevalue, 2, 0, CA_WIZARD},
{"BTLAG", fun_lag, 0, 0, CA_WIZARD},
{"BTLOADMAP", fun_btloadmap, 2, FN_VARARGS, CA_WIZARD},
{"BTLOADMECH", fun_btloadmech, 2, 0, CA_WIZARD},
{"BTMAKEMECHS", fun_btmakemechs,0, FN_VARARGS, CA_WIZARD},
{"BTMAKEPILOTROLL", fun_btmakepilotroll, 3, 0, CA_WIZARD},
{"BTMAPELEV", fun_btmapelev, 3, 0, CA_WIZARD},
{"BTMAPTERR", fun_btmapterr, 3, 0, CA_WIZARD},
{"BTMAPUNITS", fun_btmapunits, 0, FN_VARARGS, CA_WIZARD},
{"BTMECHFREQS", fun_btmechfreqs, 1, 0, CA_WIZARD},
{"BTPARTMATCH", fun_btpartmatch, 1, 0, CA_WIZARD},
{"BTPARTNAME", fun_btpartname, 2, 0, CA_WIZARD},
{"BTSETARMORSTATUS",fun_btsetarmorstatus,4,0, CA_WIZARD},
{"BTSETCHARVALUE", fun_btsetcharvalue, 4, 0, CA_WIZARD},
{"BTSETXCODEVALUE", fun_btsetxcodevalue, 3, 0, CA_WIZARD},
{"BTSTORES", fun_btstores, 0, FN_VARARGS, CA_WIZARD},
{"BTTECHSTATUS",fun_bttechstatus,1, 0, CA_WIZARD},
{"BTTHRESHOLD", fun_btthreshold, 1, 0, CA_WIZARD},
{"BTUNDERREPAIR", fun_btunderrepair, 1, 0, CA_BUILDER},
{"BTWEAPONSTATUS",fun_btweaponstatus,0,FN_VARARGS, CA_WIZARD},
{"BTADDSTORES", fun_btaddstores, 3, 0, CA_WIZARD},
{"BTARMORSTATUS_REF", fun_btarmorstatus_ref, 2, 0, CA_WIZARD},
{"BTCHARLIST", fun_btcharlist, 1, FN_VARARGS, CA_WIZARD},
{"BTCRITSLOT", fun_btcritslot, 0, FN_VARARGS, CA_WIZARD},
{"BTCRITSLOT_REF", fun_btcritslot_ref, 0, FN_VARARGS, CA_WIZARD},
{"BTCRITSTATUS_REF", fun_btcritstatus_ref, 2, 0, CA_WIZARD},
{"BTENGRATE", fun_btengrate, 1, 0, CA_WIZARD},
{"BTENGRATE_REF", fun_btengrate_ref, 1, 0, CA_WIZARD},
#ifdef BT_ADVANCED_ECON
{"BTFASABASECOST_REF", fun_btfasabasecost_ref, 1, 0, CA_WIZARD},
#endif
{"BTGETBV", fun_btgetbv, 1, 0, CA_WIZARD},
{"BTGETBV_REF", fun_btgetbv_ref, 1, 0, CA_WIZARD},
#ifdef BT_ADVANCED_ECON
{"BTGETPARTCOST", fun_btgetpartcost, 1, 0, CA_WIZARD},
#endif
{"BTGETRANGE", fun_btgetrange, 0, FN_VARARGS, CA_WIZARD},
{"BTGETREALMAXSPEED", fun_btgetrealmaxspeed, 1, 0, CA_WIZARD},
{"BTGETWEIGHT", fun_btgetweight, 1, 0, CA_WIZARD},
{"BTGETXCODEVALUE_REF", fun_btgetxcodevalue_ref, 2, 0, CA_WIZARD},
{"BTHEXEMIT", fun_bthexemit, 4, 0, CA_WIZARD},
{"BTHEXINBLZ", fun_bthexinblz, 3, 0, CA_WIZARD},
{"BTHEXLOS", fun_bthexlos, 3, 0, CA_WIZARD},
{"BTID2DB", fun_btid2db, 2, 0, CA_WIZARD},
{"BTLISTBLZ", fun_btlistblz, 1, 0, CA_WIZARD},
{"BTLOSM2M", fun_btlosm2m, 2, 0, CA_WIZARD},
{"BTMAPEMIT", fun_btmapemit, 0, FN_VARARGS, CA_WIZARD},
{"BTNUMREPJOBS", fun_btnumrepjobs, 1, 0, CA_WIZARD},
{"BTPARTTYPE", fun_btparttype, 1, 0, CA_WIZARD},
{"BTPARTWEIGHT", fun_btgetweight, 1, 0, CA_WIZARD},
{"BTPAYLOAD_REF", fun_btpayload_ref, 1, 0, CA_WIZARD},
{"BTREMOVESTORES", fun_btremovestores, 3, 0, CA_WIZARD},
{"BTSETMAXSPEED", fun_btsetmaxspeed, 2, 0, CA_WIZARD},
#ifdef BT_ADVANCED_ECON
{"BTSETPARTCOST", fun_btsetpartcost, 2, 0, CA_WIZARD},
#endif
{"BTSETXY", fun_btsetxy, 0, FN_VARARGS, CA_WIZARD},
{"BTSHOWCRITSTATUS_REF", fun_btshowcritstatus_ref, 3, 0, CA_WIZARD},
{"BTSHOWSTATUS_REF", fun_btshowstatus_ref, 2, 0, CA_WIZARD},
{"BTSHOWWSPECS_REF", fun_btshowwspecs_ref, 2, 0, CA_WIZARD},
{"BTTECHLIST", fun_bttechlist, 1, 0, CA_WIZARD},
{"BTTECHLIST_REF", fun_bttechlist_ref, 1, 0, CA_WIZARD},
{"BTTECHTIME", fun_bttechtime, 0, 0, CA_WIZARD},
{"BTUNITFIXABLE", fun_btunitfixable, 1, 0, CA_WIZARD},
{"BTWEAPONSTATUS_REF", fun_btweaponstatus_ref, 0, FN_VARARGS, CA_WIZARD},
{"BTWEAPSTAT", fun_btweapstat, 2, 0, CA_WIZARD},
#endif
{"CAPSTR", fun_capstr, -1, 0, CA_PUBLIC},
{"CASE", fun_case, 0, FN_VARARGS|FN_NO_EVAL,
CA_PUBLIC},
{"CAT", fun_cat, 0, FN_VARARGS, CA_PUBLIC},
{"CEIL", fun_ceil, 1, 0, CA_PUBLIC},
{"CENTER", fun_center, 0, FN_VARARGS, CA_PUBLIC},
{"CHILDREN", fun_children, 1, 0, CA_PUBLIC},
{"COBJ", fun_cobj, 1, 0, CA_PUBLIC},
{"COLORPAIRS", fun_colorpairs, 1, 0, CA_PUBLIC},
{"COLUMNS", fun_columns, 0, FN_VARARGS, CA_PUBLIC},
{"COMP", fun_comp, 2, 0, CA_PUBLIC},
{"CON", fun_con, 1, 0, CA_PUBLIC},
{"CONFIG", fun_config, 1, 0, CA_WIZARD},
{"CONN", fun_conn, 1, 0, CA_PUBLIC},
{"CONTROLS", fun_controls, 2, 0, CA_PUBLIC},
{"CONVSECS", fun_convsecs, 1, 0, CA_PUBLIC},
{"CONVTIME", fun_convtime, 1, 0, CA_PUBLIC},
{"CONVUPTIME", fun_convuptime, 1, 0, CA_PUBLIC},
{"COS", fun_cos, 1, 0, CA_PUBLIC},
{"CREATE", fun_create, 0, FN_VARARGS, CA_PUBLIC},
{"CWHO", fun_cwho, 1, 0, CA_PUBLIC},
{"CLIST", fun_clist, 1, 0, CA_PUBLIC},
{"CEMIT", fun_cemit, 2, 0, CA_PUBLIC},
{"DEC", fun_dec, 1, 0, CA_PUBLIC},
{"DECRYPT", fun_decrypt, 2, 0, CA_PUBLIC},
{"DEFAULT", fun_default, 2, FN_NO_EVAL, CA_PUBLIC},
{"DELETE", fun_delete, 3, 0, CA_PUBLIC},
{"DIE", fun_die, 2, 0, CA_PUBLIC},
{"DIST2D", fun_dist2d, 4, 0, CA_PUBLIC},
{"DIST3D", fun_dist3d, 6, 0, CA_PUBLIC},
{"DIV", fun_div, 2, 0, CA_PUBLIC},
{"DOING", fun_doing, 1, 0, CA_WIZARD},
{"E", fun_e, 0, 0, CA_PUBLIC},
{"EDEFAULT", fun_edefault, 2, FN_NO_EVAL, CA_PUBLIC},
{"EDIT", fun_edit, 3, 0, CA_PUBLIC},
{"ELEMENTS", fun_elements, 0, FN_VARARGS, CA_PUBLIC},
{"ELOCK", fun_elock, 2, 0, CA_PUBLIC},
{"EMPTY", fun_empty, 0, FN_VARARGS, CA_PUBLIC},
{"ENCRYPT", fun_encrypt, 2, 0, CA_PUBLIC},
{"EQ", fun_eq, 2, 0, CA_PUBLIC},
{"ESCAPE", fun_escape, -1, 0, CA_PUBLIC},
{"EXIT", fun_exit, 1, 0, CA_PUBLIC},
{"EXP", fun_exp, 1, 0, CA_PUBLIC},
{"EXTRACT", fun_extract, 0, FN_VARARGS, CA_PUBLIC},
{"EVAL", fun_eval, 0, FN_VARARGS, CA_PUBLIC},
{"FDIV", fun_fdiv, 2, 0, CA_PUBLIC},
{"FILTER", fun_filter, 0, FN_VARARGS, CA_PUBLIC},
{"FINDABLE", fun_findable, 2, 0, CA_PUBLIC},
{"FIRST", fun_first, 0, FN_VARARGS, CA_PUBLIC},
{"FLAGS", fun_flags, 1, 0, CA_PUBLIC},
{"FLOOR", fun_floor, 1, 0, CA_PUBLIC},
#if 0
{"FNUM2RANK", fun_fnum2rank, 2, 0, CA_PUBLIC},
{"FRANK2NUM", fun_frank2num, 2, 0, CA_PUBLIC},
#endif
{"FOLD", fun_fold, 0, FN_VARARGS, CA_PUBLIC},
{"FOREACH", fun_foreach, 0, FN_VARARGS, CA_PUBLIC},
{"FULLNAME", fun_fullname, 1, 0, CA_PUBLIC},
{"GET", fun_get, 1, 0, CA_PUBLIC},
{"GET_EVAL", fun_get_eval, 1, 0, CA_PUBLIC},
{"GRAB", fun_grab, 0, FN_VARARGS, CA_PUBLIC},
{"GREP", fun_grep, 3, 0, CA_PUBLIC},
{"GREPI", fun_grepi, 3, 0, CA_PUBLIC},
{"GT", fun_gt, 2, 0, CA_PUBLIC},
{"GTE", fun_gte, 2, 0, CA_PUBLIC},
{"HASATTR", fun_hasattr, 2, 0, CA_PUBLIC},
{"HASATTRP", fun_hasattrp, 2, 0, CA_PUBLIC},
{"HASFLAG", fun_hasflag, 2, 0, CA_PUBLIC},
{"HASPOWER", fun_haspower, 2, 0, CA_PUBLIC},
{"HASTYPE", fun_hastype, 2, 0, CA_PUBLIC},
{"HOME", fun_home, 1, 0, CA_PUBLIC},
{"IDLE", fun_idle, 1, 0, CA_PUBLIC},
{"IFELSE", fun_ifelse, 3, FN_NO_EVAL, CA_PUBLIC},
{"INC", fun_inc, 1, 0, CA_PUBLIC},
{"INDEX", fun_index, 4, 0, CA_PUBLIC},
{"INSERT", fun_insert, 0, FN_VARARGS, CA_PUBLIC},
{"INZONE", fun_inzone, 1, 0, CA_PUBLIC},
{"ISDBREF", fun_isdbref, 1, 0, CA_PUBLIC},
{"ISNUM", fun_isnum, 1, 0, CA_PUBLIC},
{"ISWORD", fun_isword, 1, 0, CA_PUBLIC},
{"ITEMS", fun_items, 0, FN_VARARGS, CA_PUBLIC},
{"ITER", fun_iter, 0, FN_VARARGS|FN_NO_EVAL,
CA_PUBLIC},
{"LAST", fun_last, 0, FN_VARARGS, CA_PUBLIC},
{"LATTR", fun_lattr, 1, 0, CA_PUBLIC},
{"LCON", fun_lcon, 1, 0, CA_PUBLIC},
{"LCSTR", fun_lcstr, -1, 0, CA_PUBLIC},
{"LDELETE", fun_ldelete, 0, FN_VARARGS, CA_PUBLIC},
{"LEXITS", fun_lexits, 1, 0, CA_PUBLIC},
{"LPARENT", fun_lparent, 1, 0, CA_PUBLIC},
{"LIST", fun_list, 0, FN_VARARGS|FN_NO_EVAL,
CA_PUBLIC},
{"LIT", fun_lit, 1, FN_NO_EVAL, CA_PUBLIC},
{"LJUST", fun_ljust, 0, FN_VARARGS, CA_PUBLIC},
{"LINK", fun_link, 2, 0, CA_PUBLIC},
{"LN", fun_ln, 1, 0, CA_PUBLIC},
{"LNUM", fun_lnum, 0, FN_VARARGS, CA_PUBLIC},
{"LOC", fun_loc, 1, 0, CA_BUILDER},
{"LOCATE", fun_locate, 3, 0, CA_BUILDER},
{"LOCK", fun_lock, 1, 0, CA_PUBLIC},
{"LOG", fun_log, 1, 0, CA_PUBLIC},
#ifdef ARBITRARY_LOGFILES
{"LOGF", fun_logf, 2, 0, CA_WIZARD},
#endif
{"LSTACK", fun_lstack, 0, FN_VARARGS, CA_PUBLIC},
{"LT", fun_lt, 2, 0, CA_PUBLIC},
{"LTE", fun_lte, 2, 0, CA_PUBLIC},
{"LWHO", fun_lwho, 0, 0, CA_BUILDER},
{"MAIL", fun_mail, 0, FN_VARARGS, CA_PUBLIC},
{"MAILFROM", fun_mailfrom, 0, FN_VARARGS, CA_PUBLIC},
{"MAP", fun_map, 0, FN_VARARGS, CA_PUBLIC},
{"MATCH", fun_match, 0, FN_VARARGS, CA_PUBLIC},
{"MATCHALL", fun_matchall, 0, FN_VARARGS, CA_PUBLIC},
{"MAX", fun_max, 0, FN_VARARGS, CA_PUBLIC},
{"MEMBER", fun_member, 0, FN_VARARGS, CA_PUBLIC},
{"MERGE", fun_merge, 3, 0, CA_PUBLIC},
{"MID", fun_mid, 3, 0, CA_PUBLIC},
{"MIN", fun_min, 0, FN_VARARGS, CA_PUBLIC},
{"MIX", fun_mix, 0, FN_VARARGS, CA_PUBLIC},
{"MOD", fun_mod, 2, 0, CA_PUBLIC},
{"MONEY", fun_money, 1, 0, CA_PUBLIC},
{"MUDNAME", fun_mudname, 0, 0, CA_PUBLIC},
{"MUL", fun_mul, 0, FN_VARARGS, CA_PUBLIC},
{"MUNGE", fun_munge, 0, FN_VARARGS, CA_PUBLIC},
{"NAME", fun_name, 1, 0, CA_PUBLIC},
{"NEARBY", fun_nearby, 2, 0, CA_PUBLIC},
{"NEQ", fun_neq, 2, 0, CA_PUBLIC},
{"NEXT", fun_next, 1, 0, CA_PUBLIC},
{"NOT", fun_not, 1, 0, CA_PUBLIC},
{"NUM", fun_num, 1, 0, CA_PUBLIC},
{"OBJ", fun_obj, 1, 0, CA_PUBLIC},
{"OBJEVAL", fun_objeval, 2, FN_NO_EVAL, CA_PUBLIC},
{"OBJMEM", fun_objmem, 1, 0, CA_PUBLIC},
{"OR", fun_or, 0, FN_VARARGS, CA_PUBLIC},
{"ORFLAGS", fun_orflags, 2, 0, CA_PUBLIC},
{"OWNER", fun_owner, 1, 0, CA_PUBLIC},
{"PAIRS", fun_pairs, 1, 0, CA_PUBLIC},
{"PARENT", fun_parent, 1, 0, CA_PUBLIC},
{"PARSE", fun_parse, 0, FN_VARARGS|FN_NO_EVAL,
CA_PUBLIC},
{"PEEK", fun_peek, 0, FN_VARARGS, CA_PUBLIC},
{"PEMIT", fun_pemit, 2, 0, CA_PUBLIC},
{"PI", fun_pi, 0, 0, CA_PUBLIC},
{"PLAYMEM", fun_playmem, 1, 0, CA_PUBLIC},
{"PMATCH", fun_pmatch, 1, 0, CA_PUBLIC},
{"POLL", fun_poll, 0, 0, CA_WIZARD},
{"POP", fun_pop, 0, FN_VARARGS, CA_PUBLIC},
{"PORTS", fun_ports, 1, 0, CA_PUBLIC},
{"POS", fun_pos, 2, 0, CA_PUBLIC},
{"POSS", fun_poss, 1, 0, CA_PUBLIC},
{"POWER", fun_power, 2, 0, CA_PUBLIC},
{"PUSH", fun_push, 0, FN_VARARGS, CA_PUBLIC},
#ifdef USE_PYTHON
{"PYTHON", fun_python, 1, FN_NO_EVAL, CA_WIZARD},
{"PYTHONCALL", fun_pythoncall, 0, FN_VARARGS, CA_WIZARD},
#endif
{"R", fun_r, 1, 0, CA_PUBLIC},
{"RAND", fun_rand, 1, 0, CA_PUBLIC},
{"REGMATCH", fun_regmatch, 0, FN_VARARGS, CA_PUBLIC},
{"REMOVE", fun_remove, 0, FN_VARARGS, CA_PUBLIC},
{"REPEAT", fun_repeat, 2, 0, CA_PUBLIC},
{"REPLACE", fun_replace, 0, FN_VARARGS, CA_PUBLIC},
{"REST", fun_rest, 0, FN_VARARGS, CA_PUBLIC},
{"REVERSE", fun_reverse, -1, 0, CA_PUBLIC},
{"REVWORDS", fun_revwords, 0, FN_VARARGS, CA_PUBLIC},
{"RJUST", fun_rjust, 0, FN_VARARGS, CA_PUBLIC},
{"RLOC", fun_rloc, 2, 0, CA_PUBLIC},
{"ROOM", fun_room, 1, 0, CA_PUBLIC},
{"ROUND", fun_round, 2, 0, CA_PUBLIC},
{"S", fun_s, -1, 0, CA_PUBLIC},
{"SCRAMBLE", fun_scramble, 1, 0, CA_PUBLIC},
{"SEARCH", fun_search, -1, 0, CA_PUBLIC},
{"SECS", fun_secs, 0, 0, CA_PUBLIC},
{"SECURE", fun_secure, -1, 0, CA_PUBLIC},
{"SET", fun_set, 2, 0, CA_PUBLIC},
{"SETDIFF", fun_setdiff, 0, FN_VARARGS, CA_PUBLIC},
{"SETINTER", fun_setinter, 0, FN_VARARGS, CA_PUBLIC},
{"SETLOCK", fun_setlock, 3, 0, CA_WIZARD},
{"SETQ", fun_setq, 2, 0, CA_PUBLIC},
{"SETR", fun_setr, 2, 0, CA_PUBLIC},
{"SETUNION", fun_setunion, 0, FN_VARARGS, CA_PUBLIC},
{"SHL", fun_shl, 2, 0, CA_PUBLIC},
{"SHR", fun_shr, 2, 0, CA_PUBLIC},
{"SHUFFLE", fun_shuffle, 0, FN_VARARGS, CA_PUBLIC},
{"SIGN", fun_sign, 1, 0, CA_PUBLIC},
{"SIN", fun_sin, 1, 0, CA_PUBLIC},
{"SORT", fun_sort, 0, FN_VARARGS, CA_PUBLIC},
{"SORTBY", fun_sortby, 0, FN_VARARGS, CA_PUBLIC},
{"SPACE", fun_space, 1, 0, CA_PUBLIC},
{"SPLICE", fun_splice, 0, FN_VARARGS, CA_PUBLIC},
{"SQRT", fun_sqrt, 1, 0, CA_PUBLIC},
{"SQUISH", fun_squish, 1, 0, CA_PUBLIC},
{"STARTTIME", fun_starttime, 0, 0, CA_PUBLIC},
{"STATS", fun_stats, 1, 0, CA_PUBLIC},
{"STRCAT", fun_strcat, 0, FN_VARARGS, CA_PUBLIC},
{"STRIPANSI", fun_stripansi, 1, 0, CA_PUBLIC},
{"STRLEN", fun_strlen, -1, 0, CA_PUBLIC},
{"STRMATCH", fun_strmatch, 2, 0, CA_PUBLIC},
{"STRTRUNC", fun_strtrunc, 2, 0, CA_PUBLIC},
{"SUB", fun_sub, 2, 0, CA_PUBLIC},
{"SUBEVAL", fun_subeval, 1, 0, CA_PUBLIC},
{"SUBJ", fun_subj, 1, 0, CA_PUBLIC},
{"SWITCH", fun_switch, 0, FN_VARARGS|FN_NO_EVAL,
CA_PUBLIC},
{"TAN", fun_tan, 1, 0, CA_PUBLIC},
{"TEL", fun_tel, 2, 0, CA_PUBLIC},
{"TIME", fun_time, 0, 0, CA_PUBLIC},
{"TRANSLATE", fun_translate, 2, 0, CA_PUBLIC},
{"TRIM", fun_trim, 0, FN_VARARGS, CA_PUBLIC},
{"TRUNC", fun_trunc, 1, 0, CA_PUBLIC},
{"TYPE", fun_type, 1, 0, CA_PUBLIC},
{"U", fun_u, 0, FN_VARARGS, CA_PUBLIC},
{"UCSTR", fun_ucstr, -1, 0, CA_PUBLIC},
{"UDEFAULT", fun_udefault, 0, FN_VARARGS|FN_NO_EVAL,
CA_PUBLIC},
{"ULOCAL", fun_ulocal, 0, FN_VARARGS, CA_PUBLIC},
{"V", fun_v, 1, 0, CA_PUBLIC},
{"VADD", fun_vadd, 0, FN_VARARGS, CA_PUBLIC},
{"VALID", fun_valid, 2, FN_VARARGS, CA_PUBLIC},
{"VDIM", fun_vdim, 0, FN_VARARGS, CA_PUBLIC},
{"VERSION", fun_version, 0, 0, CA_PUBLIC},
{"VISIBLE", fun_visible, 2, 0, CA_PUBLIC},
{"VMAG", fun_vmag, 0, FN_VARARGS, CA_PUBLIC},
{"VMUL", fun_vmul, 0, FN_VARARGS, CA_PUBLIC},
{"VSUB", fun_vsub, 0, FN_VARARGS, CA_PUBLIC},
{"VUNIT", fun_vunit, 0, FN_VARARGS, CA_PUBLIC},
{"WHERE", fun_where, 1, 0, CA_PUBLIC},
{"WORDPOS", fun_wordpos, 0, FN_VARARGS, CA_PUBLIC},
{"WORDS", fun_words, 0, FN_VARARGS, CA_PUBLIC},
{"XGET", fun_xget, 2, 0, CA_PUBLIC},
{"XOR", fun_xor, 0, FN_VARARGS, CA_PUBLIC},
{"ZFUN", fun_zfun, 0, FN_VARARGS, CA_PUBLIC},
{"ZONE", fun_zone, 1, 0, CA_PUBLIC},
{"ZPLAYERS", fun_zplayers, 1, 0, CA_PUBLIC},
{"ZWHO", fun_zwho, 1, 0, CA_PUBLIC},
{NULL, NULL, 0, 0, 0}};
/* *INDENT-ON* */
void init_functab() {
FUN *fp;
char *buff, *cp, *dp;
buff = alloc_sbuf("init_functab");
hashinit(&mudstate.func_htab, 100 * HASH_FACTOR);
for (fp = flist; fp->name; fp++) {
cp = (char *) fp->name;
dp = buff;
while (*cp) {
*dp = ToLower(*cp);
cp++;
dp++;
}
*dp = '\0';
hashadd(buff, (int *) fp, &mudstate.func_htab);
}
free_sbuf(buff);
ufun_head = NULL;
hashinit(&mudstate.ufunc_htab, 11);
}
void do_function(player, cause, key, fname, target)
dbref player, cause;
int key;
char *fname, *target;
{
UFUN *ufp, *ufp2;
ATTR *ap;
char *np, *bp;
int atr, aflags;
dbref obj, aowner;
/*
* Make a local uppercase copy of the function name
*/
bp = np = alloc_sbuf("add_user_func");
safe_sb_str(fname, np, &bp);
*bp = '\0';
for (bp = np; *bp; bp++)
*bp = ToLower(*bp);
/*
* Verify that the function doesn't exist in the builtin table
*/
if (hashfind(np, &mudstate.func_htab) != NULL) {
notify_quiet(player,
"Function already defined in builtin function table.");
free_sbuf(np);
return;
}
/*
* Make sure the target object exists
*/
if (!parse_attrib(player, target, &obj, &atr)) {
notify_quiet(player, "I don't see that here.");
free_sbuf(np);
return;
}
/*
* Make sure the attribute exists
*/
if (atr == NOTHING) {
notify_quiet(player, "No such attribute.");
free_sbuf(np);
return;
}
/*
* Make sure attribute is readably by me
*/
ap = atr_num(atr);
if (!ap) {
notify_quiet(player, "No such attribute.");
free_sbuf(np);
return;
}
atr_get_info(obj, atr, &aowner, &aflags);
if (!See_attr(player, obj, ap, aowner, aflags)) {
notify_quiet(player, "Permission denied.");
free_sbuf(np);
return;
}
/*
* Privileged functions require you control the obj.
*/
if ((key & FN_PRIV) && !Controls(player, obj)) {
notify_quiet(player, "Permission denied.");
free_sbuf(np);
return;
}
/*
* See if function already exists. If so, redefine it
*/
ufp = (UFUN *) hashfind(np, &mudstate.ufunc_htab);
if (!ufp) {
ufp = (UFUN *) malloc(sizeof(UFUN));
ufp->name = strsave(np);
for (bp = (char *) ufp->name; *bp; bp++)
*bp = ToUpper(*bp);
ufp->obj = obj;
ufp->atr = atr;
ufp->perms = CA_PUBLIC;
ufp->next = NULL;
if (!ufun_head) {
ufun_head = ufp;
} else {
for (ufp2 = ufun_head; ufp2->next; ufp2 = ufp2->next);
ufp2->next = ufp;
}
hashadd(np, (int *) ufp, &mudstate.ufunc_htab);
}
ufp->obj = obj;
ufp->atr = atr;
ufp->flags = key;
free_sbuf(np);
if (!Quiet(player))
notify_quiet(player, tprintf("Function %s defined.", fname));
}
/*
* ---------------------------------------------------------------------------
* * list_functable: List available functions.
*/
void list_functable(player)
dbref player;
{
FUN *fp;
UFUN *ufp;
char *buf, *bp, *cp;
buf = alloc_lbuf("list_functable");
bp = buf;
for (cp = (char *) "Functions:"; *cp; cp++)
*bp++ = *cp;
for (fp = flist; fp->name; fp++) {
if (check_access(player, fp->perms)) {
*bp++ = ' ';
for (cp = (char *) (fp->name); *cp; cp++)
*bp++ = *cp;
}
}
for (ufp = ufun_head; ufp; ufp = ufp->next) {
if (check_access(player, ufp->perms)) {
*bp++ = ' ';
for (cp = (char *) (ufp->name); *cp; cp++)
*bp++ = *cp;
}
}
*bp = '\0';
notify(player, buf);
free_lbuf(buf);
}
/*
* ---------------------------------------------------------------------------
* * cf_func_access: set access on functions
*/
int cf_func_access(int *vp, char *str, long extra, dbref player, char *cmd)
{
FUN *fp;
UFUN *ufp;
char *ap;
for (ap = str; *ap && !isspace(*ap); ap++);
if (*ap)
*ap++ = '\0';
for (fp = flist; fp->name; fp++) {
if (!string_compare(fp->name, str)) {
return (cf_modify_bits(&fp->perms, ap, extra, player, cmd));
}
}
for (ufp = ufun_head; ufp; ufp = ufp->next) {
if (!string_compare(ufp->name, str)) {
return (cf_modify_bits(&ufp->perms, ap, extra, player, cmd));
}
}
cf_log_notfound(player, cmd, "Function", str);
return -1;
}