src/functions.c

Go to the documentation of this file.
00001 /*
00002  * functions.c - MUX function handlers 
00003  */
00004 
00005 #include "copyright.h"
00006 #include "config.h"
00007 
00008 #include <limits.h>
00009 #include <math.h>
00010 
00011 #include "mudconf.h"
00012 #include "db.h"
00013 #include "flags.h"
00014 #include "powers.h"
00015 #include "attrs.h"
00016 #include "externs.h"
00017 #include "match.h"
00018 #include "command.h"
00019 #include "functions.h"
00020 #include "misc.h"
00021 #include "alloc.h"
00022 #include "ansi.h"
00023 #include "comsys.h"
00024 #include "interface.h"
00025 
00026 UFUN *ufun_head;
00027 
00028 extern NAMETAB indiv_attraccess_nametab[];
00029 
00030 extern int game_lag(void);
00031 
00032 extern void cf_log_notfound(dbref player, char *cmd,
00033                                                         const char *thingname, char *thing);
00034 
00035 /*
00036  * Function definitions from funceval.c 
00037  */
00038 
00039 extern void fun_btdesignex();
00040 extern void fun_btgetcharvalue();
00041 extern void fun_btmakemechs();
00042 extern void fun_btmapelev();
00043 extern void fun_btmapterr();
00044 extern void fun_btsetcharvalue();
00045 extern void fun_btgetxcodevalue();
00046 extern void fun_btmakepilotroll();
00047 extern void fun_btsetxcodevalue();
00048 extern void fun_btstores();
00049 extern void fun_btunderrepair();
00050 extern void fun_btdamages();
00051 extern void fun_btcritstatus();
00052 extern void fun_btarmorstatus();
00053 extern void fun_btsetarmorstatus();
00054 extern void fun_btweaponstatus();
00055 extern void fun_btthreshold();
00056 extern void fun_btdamagemech();
00057 extern void fun_bttechstatus();
00058 extern void fun_btpartmatch();
00059 extern void fun_btpartname();
00060 extern void fun_btloadmap();
00061 extern void fun_btloadmech();
00062 extern void fun_btmechfreqs();
00063 extern void fun_btmapunits();
00064 extern void fun_btgetxcodevalue_ref();
00065 extern void fun_btarmorstatus_ref();
00066 extern void fun_btcritstatus_ref();
00067 extern void fun_btweaponstatus_ref();
00068 extern void fun_btid2db();
00069 extern void fun_bthexlos();
00070 extern void fun_btlosm2m();
00071 extern void fun_bthexemit();
00072 
00073 extern void fun_btgetweight();
00074 extern void fun_btpartweight();
00075 extern void fun_btaddstores();
00076 extern void fun_btremovestores();
00077 extern void fun_bttechtime();
00078 extern void fun_btcritslot();
00079 extern void fun_btcritslot_ref();
00080 extern void fun_btgetrange();
00081 extern void fun_btsetmaxspeed();
00082 extern void fun_btgetrealmaxspeed();
00083 extern void fun_btgetbv();
00084 extern void fun_btgetbv_ref();
00085 extern void fun_bttechlist();
00086 extern void fun_bttechlist_ref();
00087 extern void fun_btpayload_ref();
00088 extern void fun_btshowstatus_ref();
00089 extern void fun_btshowwspecs_ref();
00090 extern void fun_btshowcritstatus_ref();
00091 extern void fun_btengrate();
00092 extern void fun_btengrate_ref();
00093 extern void fun_btweapstat();
00094 extern void fun_btnumrepjobs();
00095 extern void fun_btsetxy();
00096 extern void fun_btmapemit();
00097 extern void fun_btparttype();
00098 extern void fun_btticweaps();
00099 #ifdef BT_ADVANCED_ECON
00100 extern void fun_btgetpartcost();
00101 extern void fun_btsetpartcost();
00102 extern void fun_btfasabasecost_ref();
00103 #endif
00104 extern void fun_btunitfixable();
00105 extern void fun_btlistblz();
00106 extern void fun_bthexinblz();
00107 extern void fun_btcharlist();
00108 extern void fun_cobj();
00109 extern void fun_config();
00110 
00111 extern void fun_cwho();
00112 extern void fun_clist();
00113 extern void fun_cemit();
00114 extern void fun_beep();
00115 extern void fun_ansi();
00116 extern void fun_zone();
00117 #ifdef SIDE_EFFECT_FUNCTIONS
00118 extern void fun_link();
00119 extern void fun_tel();
00120 extern void fun_pemit();
00121 extern void fun_create();
00122 extern void fun_set();
00123 extern void fun_setlock();
00124 #endif
00125 extern void fun_last();
00126 extern void fun_matchall();
00127 extern void fun_ports();
00128 extern void fun_mix();
00129 extern void fun_foreach();
00130 extern void fun_munge();
00131 extern void fun_visible();
00132 extern void fun_elements();
00133 extern void fun_grab();
00134 extern void fun_graball();
00135 extern void fun_scramble();
00136 extern void fun_shuffle();
00137 extern void fun_sortby();
00138 extern void fun_default();
00139 extern void fun_edefault();
00140 extern void fun_udefault();
00141 extern void fun_findable();
00142 extern void fun_isword();
00143 extern void fun_hasattr();
00144 extern void fun_hasattrp();
00145 extern void fun_zwho();
00146 extern void fun_zplayers();
00147 extern void fun_inzone();
00148 extern void fun_children();
00149 extern void fun_encrypt();
00150 extern void fun_decrypt();
00151 extern void fun_objeval();
00152 extern void fun_squish();
00153 extern void fun_stripansi();
00154 extern void fun_zfun();
00155 extern void fun_columns();
00156 extern void fun_playmem();
00157 #ifdef USE_PYTHON
00158 extern void fun_python();
00159 extern void fun_pythoncall();
00160 #endif
00161 extern void fun_objmem();
00162 extern void fun_orflags();
00163 extern void fun_andflags();
00164 extern void fun_strtrunc();
00165 extern void fun_ifelse();
00166 extern void fun_inc();
00167 extern void fun_dec();
00168 extern void fun_mail();
00169 extern void fun_mailfrom();
00170 extern void fun_die();
00171 extern void fun_lit();
00172 extern void fun_shl();
00173 extern void fun_shr();
00174 extern void fun_vadd();
00175 extern void fun_vsub();
00176 extern void fun_vmul();
00177 extern void fun_vmag();
00178 extern void fun_vunit();
00179 extern void fun_vdim();
00180 extern void fun_strcat();
00181 extern void fun_grep();
00182 extern void fun_grepi();
00183 extern void fun_art();
00184 extern void fun_alphamax();
00185 extern void fun_alphamin();
00186 extern void fun_valid();
00187 extern void fun_hastype();
00188 extern void fun_lparent();
00189 extern void fun_empty();
00190 extern void fun_push();
00191 extern void fun_peek();
00192 extern void fun_pop();
00193 extern void fun_items();
00194 extern void fun_lstack();
00195 extern void fun_regmatch();
00196 extern void fun_translate();
00197 
00198 /*
00199  * This is for functions that take an optional delimiter character 
00200  */
00201 
00202 #define varargs_preamble(xname,xnargs)                                  \
00203         if (!fn_range_check(xname, nfargs, xnargs-1, xnargs, buff, bufc))       \
00204                 return;                                                 \
00205         if (!delim_check(fargs, nfargs, xnargs, &sep, buff, bufc, 0,    \
00206                 player, cause, cargs, ncargs))                          \
00207                 return;
00208 
00209 #define evarargs_preamble(xname,xnargs)                                 \
00210         if (!fn_range_check(xname, nfargs, xnargs-1, xnargs, buff, bufc))       \
00211                 return;                                                 \
00212         if (!delim_check(fargs, nfargs, xnargs, &sep, buff, bufc, 1,    \
00213             player, cause, cargs, ncargs))                              \
00214                 return;
00215 
00216 #define mvarargs_preamble(xname,xminargs,xnargs)                        \
00217         if (!fn_range_check(xname, nfargs, xminargs, xnargs, buff, bufc))       \
00218                 return;                                                 \
00219         if (!delim_check(fargs, nfargs, xnargs, &sep, buff, bufc, 0,            \
00220             player, cause, cargs, ncargs))                              \
00221                 return;
00222 
00226 char *trim_space_sep(char *str, char sep)
00227 {
00228         char *p;
00229 
00230     if(*str == '\0') return str;
00231         if(sep != ' ')
00232                 return str;
00233         while (*str && (*str == ' '))
00234                 str++;
00235         for(p = str; *p; p++);
00236         for(p--; *p == ' ' && p > str; p--);
00237         p++;
00238         *p = '\0';
00239         return str;
00240 }
00241 
00242 /*
00243  * next_token: Point at start of next token in string 
00244  */
00245 
00246 char *next_token(char *str, char sep)
00247 {
00248         while (*str && (*str != sep))
00249                 str++;
00250         if(!*str)
00251                 return NULL;
00252         str++;
00253         if(sep == ' ') {
00254                 while (*str == sep)
00255                         str++;
00256         }
00257         return str;
00258 }
00259 
00260 /*
00261  * split_token: Get next token from string as null-term string.  String is
00262  * * destructively modified.
00263  */
00264 
00265 char *split_token(char **sp, char sep)
00266 {
00267         char *str, *save;
00268 
00269         save = str = *sp;
00270         if(!str) {
00271                 *sp = NULL;
00272                 return NULL;
00273         }
00274         while (*str && (*str != sep))
00275                 str++;
00276         if(*str) {
00277                 *str++ = '\0';
00278                 if(sep == ' ') {
00279                         while (*str == sep)
00280                                 str++;
00281                 }
00282         } else {
00283                 str = NULL;
00284         }
00285         *sp = str;
00286         return save;
00287 }
00288 
00289 dbref match_thing(dbref player, char *name)
00290 {
00291         init_match(player, name, NOTYPE);
00292         match_everything(MAT_EXIT_PARENTS);
00293         return (noisy_match_result());
00294 }
00295 
00296 /*
00297  * ---------------------------------------------------------------------------
00298  * * List management utilities.
00299  */
00300 
00301 #define ALPHANUM_LIST   1
00302 #define NUMERIC_LIST    2
00303 #define DBREF_LIST      3
00304 #define FLOAT_LIST      4
00305 
00306 static int autodetect_list(char *ptrs[], int nitems)
00307 {
00308         int sort_type, i;
00309         char *p;
00310 
00311         sort_type = NUMERIC_LIST;
00312         for(i = 0; i < nitems; i++) {
00313                 switch (sort_type) {
00314                 case NUMERIC_LIST:
00315                         if(!is_number(ptrs[i])) {
00316 
00317                                 /*
00318                                  * If non-numeric, switch to alphanum sort. * 
00319                                  * 
00320                                  * *  * *  * * Exception: if this is the
00321                                  * first * element * * and * it is a good
00322                                  * dbref, * switch to a * * dbref sort. *
00323                                  * We're a * little looser than *  * the
00324                                  * normal * 'good  * dbref' rules, any * *
00325                                  * number following # * the #-sign is
00326                                  * accepted.  
00327                                  */
00328 
00329                                 if(i == 0) {
00330                                         p = ptrs[i];
00331                                         if(*p++ != NUMBER_TOKEN) {
00332                                                 return ALPHANUM_LIST;
00333                                         } else if(is_integer(p)) {
00334                                                 sort_type = DBREF_LIST;
00335                                         } else {
00336                                                 return ALPHANUM_LIST;
00337                                         }
00338                                 } else {
00339                                         return ALPHANUM_LIST;
00340                                 }
00341                         } else if(index(ptrs[i], '.')) {
00342                                 sort_type = FLOAT_LIST;
00343                         }
00344                         break;
00345                 case FLOAT_LIST:
00346                         if(!is_number(ptrs[i])) {
00347                                 sort_type = ALPHANUM_LIST;
00348                                 return ALPHANUM_LIST;
00349                         }
00350                         break;
00351                 case DBREF_LIST:
00352                         p = ptrs[i];
00353                         if(*p++ != NUMBER_TOKEN)
00354                                 return ALPHANUM_LIST;
00355                         if(!is_integer(p))
00356                                 return ALPHANUM_LIST;
00357                         break;
00358                 default:
00359                         return ALPHANUM_LIST;
00360                 }
00361         }
00362         return sort_type;
00363 }
00364 
00365 static int get_list_type(char *fargs[], int nfargs, int type_pos,
00366                                                  char *ptrs[], int nitems)
00367 {
00368         if(nfargs >= type_pos) {
00369                 switch (ToLower(*fargs[type_pos - 1])) {
00370                 case 'd':
00371                         return DBREF_LIST;
00372                 case 'n':
00373                         return NUMERIC_LIST;
00374                 case 'f':
00375                         return FLOAT_LIST;
00376                 case '\0':
00377                         return autodetect_list(ptrs, nitems);
00378                 default:
00379                         return ALPHANUM_LIST;
00380                 }
00381         }
00382         return autodetect_list(ptrs, nitems);
00383 }
00384 
00385 int list2arr(char *arr[], int maxlen, char *list, char sep)
00386 {
00387         char *p;
00388         int i;
00389 
00390         list = trim_space_sep(list, sep);
00391         p = split_token(&list, sep);
00392         for(i = 0; p && i < maxlen; i++, p = split_token(&list, sep)) {
00393                 arr[i] = p;
00394         }
00395         return i;
00396 }
00397 
00398 void arr2list(char *arr[], int alen, char *list, char **bufc, char sep)
00399 {
00400         int i;
00401 
00402         for(i = 0; i < alen; i++) {
00403                 safe_str(arr[i], list, bufc);
00404                 safe_chr(sep, list, bufc);
00405         }
00406         if(*bufc != list)
00407                 (*bufc)--;
00408 }
00409 
00410 static int dbnum(char *dbr)
00411 {
00412         if((strlen(dbr) < 2) && (*dbr != '#'))
00413                 return 0;
00414         else
00415                 return atoi(dbr + 1);
00416 }
00417 
00421 int nearby_or_control(dbref player, dbref thing)
00422 {
00423         if(!Good_obj(player) || !Good_obj(thing))
00424                 return 0;
00425         if(Controls(player, thing))
00426                 return 1;
00427         if(!nearby(player, thing))
00428                 return 0;
00429         return 1;
00430 }
00431 
00435 static void fval(char *buff, char **bufc, double result)
00436 {
00437         char *p, *buf1;
00438 
00439         buf1 = *bufc;
00440         safe_tprintf_str(buff, bufc, "%.6f", result);   /*
00441                                                                                                          * get double val * * 
00442                                                                                                          * into buffer 
00443                                                                                                          */
00444         **bufc = '\0';
00445         p = (char *) rindex(buf1, '0');
00446         if(p == NULL) {                         /*
00447                                                                  * remove useless trailing 0's 
00448                                                                  */
00449                 return;
00450         } else if(*(p + 1) == '\0') {
00451                 while (*p == '0') {
00452                         *p-- = '\0';
00453                 }
00454                 *bufc = p + 1;
00455         }
00456         p = (char *) rindex(buf1, '.'); /*
00457                                                                          * take care of dangling '.' 
00458                                                                          */
00459         if((p != NULL) && (*(p + 1) == '\0')) {
00460                 *p = '\0';
00461                 *bufc = p;
00462         }
00463 }
00464 
00469 int fn_range_check(const char *fname, int nfargs, int minargs, int maxargs,
00470                                    char *result, char **bufc)
00471 {
00472         if((nfargs >= minargs) && (nfargs <= maxargs))
00473                 return 1;
00474 
00475         if(maxargs == (minargs + 1))
00476                 safe_tprintf_str(result, bufc,
00477                                                  "#-1 FUNCTION (%s) EXPECTS %d OR %d ARGUMENTS",
00478                                                  fname, minargs, maxargs);
00479         else
00480                 safe_tprintf_str(result, bufc,
00481                                                  "#-1 FUNCTION (%s) EXPECTS BETWEEN %d AND %d ARGUMENTS",
00482                                                  fname, minargs, maxargs);
00483         return 0;
00484 }
00485 
00489 int delim_check(char *fargs[], int nfargs, int sep_arg, char *sep, char *buff,
00490                                 char **bufc, int eval, dbref player, dbref cause,
00491                                 char *cargs[], int ncargs)
00492 {
00493         char *tstr, *bp, *str;
00494         int tlen;
00495 
00496         if(nfargs >= sep_arg) {
00497                 tlen = strlen(fargs[sep_arg - 1]);
00498                 if(tlen <= 1)
00499                         eval = 0;
00500                 if(eval) {
00501                         tstr = bp = alloc_lbuf("delim_check");
00502                         str = fargs[sep_arg - 1];
00503                         exec(tstr, &bp, 0, player, cause, EV_EVAL | EV_FCHECK, &str,
00504                                  cargs, ncargs);
00505                         *bp = '\0';
00506                         tlen = strlen(tstr);
00507                         *sep = *tstr;
00508                         free_lbuf(tstr);
00509                 }
00510                 if(tlen == 0) {
00511                         *sep = ' ';
00512                 } else if(tlen != 1) {
00513                         safe_str("#-1 SEPARATOR MUST BE ONE CHARACTER", buff, bufc);
00514                         return 0;
00515                 } else if(!eval) {
00516                         *sep = *fargs[sep_arg - 1];
00517                 }
00518         } else {
00519                 *sep = ' ';
00520         }
00521         return 1;
00522 }
00523 
00528 int countwords(char *str, char sep)
00529 {
00530         int n;
00531 
00532         str = trim_space_sep(str, sep);
00533         if(!*str)
00534                 return 0;
00535         for(n = 0; str; str = next_token(str, sep), n++);
00536         return n;
00537 }
00538 
00539 static void fun_words(char *buff, char **bufc, dbref player, dbref cause,
00540                                           char *fargs[], int nfargs, char *cargs[], int ncargs)
00541 {
00542         char sep;
00543 
00544         if(nfargs == 0) {
00545                 safe_str("0", buff, bufc);
00546                 return;
00547         }
00548         varargs_preamble("WORDS", 2);
00549         safe_tprintf_str(buff, bufc, "%d", countwords(fargs[0], sep));
00550 }
00551 
00556 static void fun_flags(char *buff, char **bufc, dbref player, dbref cause,
00557                                           char *fargs[], int nfargs, char *cargs[], int ncargs)
00558 {
00559         dbref it;
00560         char *buff2;
00561 
00562         it = match_thing(player, fargs[0]);
00563         if((it != NOTHING) && (mudconf.pub_flags || Examinable(player, it) ||
00564                                                    (it == cause))) {
00565                 buff2 = unparse_flags(player, it);
00566                 safe_str(buff2, buff, bufc);
00567                 free_sbuf(buff2);
00568         } else
00569                 safe_str("#-1", buff, bufc);
00570         return;
00571 }
00572 
00576 static void fun_rand(char *buff, char **bufc, dbref player, dbref cause,
00577                                          char *fargs[], int nfargs, char *cargs[], int ncargs)
00578 {
00579         int num;
00580 
00581         num = atoi(fargs[0]);
00582         if(num < 1)
00583                 safe_str("0", buff, bufc);
00584         else
00585                 safe_tprintf_str(buff, bufc, "%ld", (random() % num));
00586 }
00587 
00591 static void fun_abs(char *buff, char **bufc, dbref player, dbref cause,
00592                                         char *fargs[], int nfargs, char *cargs[], int ncargs)
00593 {
00594         double num;
00595 
00596         num = atof(fargs[0]);
00597         if(num == 0.0) {
00598                 safe_str("0", buff, bufc);
00599         } else if(num < 0.0) {
00600                 fval(buff, bufc, -num);
00601         } else {
00602                 fval(buff, bufc, num);
00603         }
00604 }
00605 
00609 static void fun_sign(char *buff, char **bufc, dbref player, dbref cause,
00610                                          char *fargs[], int nfargs, char *cargs[], int ncargs)
00611 {
00612         double num;
00613 
00614         num = atof(fargs[0]);
00615         if(num < 0)
00616                 safe_str("-1", buff, bufc);
00617         else if(num > 0)
00618                 safe_str("1", buff, bufc);
00619         else
00620                 safe_str("0", buff, bufc);
00621 }
00622 
00623 extern char *silly_atr_get(dbref, int);
00624 
00625 time_t mytime(dbref player)
00626 {
00627         struct timeval tv;
00628         struct timezone tz;
00629         char *tzstr;
00630         int hours, dst;
00631 
00632         tzstr = silly_atr_get(player, A_TZ);
00633         if(sscanf(tzstr, "%d:%d", &hours, &dst) < 2)
00634                 return mudstate.now;
00635         tz.tz_minuteswest = (0 - hours) * 60;
00636         tz.tz_dsttime = dst;
00637         gettimeofday(&tv, &tz);
00638         return tv.tv_sec;
00639 }
00640 
00641 /* Returns secs converted to digits, just like WHO does for connect time */
00642 
00643 static void fun_digittime(char *buff, char **bufc, dbref player, dbref cause,
00644                                                   char *fargs[], int nfargs, char *cargs[],
00645                                                   int ncargs)
00646 {
00647         register struct tm *delta;
00648         static char buf[64];
00649         time_t dt;
00650 
00651         dt = atol(fargs[0]);
00652 
00653         if(dt < 0)
00654                 dt = 0;
00655 
00656         delta = gmtime(&dt);
00657         if(delta->tm_yday > 0) {
00658                 sprintf(buf, "%dd %02d:%02d", delta->tm_yday, delta->tm_hour,
00659                                 delta->tm_min);
00660         } else {
00661                 sprintf(buf, "%02d:%02d", delta->tm_hour, delta->tm_min);
00662         }
00663 
00664         safe_tprintf_str(buff, bufc, buf);
00665 
00666 }
00667 
00671 static void fun_time(char *buff, char **bufc, dbref player, dbref cause,
00672                                          char *fargs[], int nfargs, char *cargs[], int ncargs)
00673 {
00674         char *temp;
00675 
00676         temp = (char *) ctime(&mudstate.now);
00677         temp[strlen(temp) - 1] = '\0';
00678         safe_str(temp, buff, bufc);
00679 }
00680 
00684 static void fun_secs(char *buff, char **bufc, dbref player, dbref cause,
00685                                          char *fargs[], int nfargs, char *cargs[], int ncargs)
00686 {
00687         safe_tprintf_str(buff, bufc, "%d", mudstate.now);
00688 }
00689 
00693 static void fun_convsecs(char *buff, char **bufc, dbref player, dbref cause,
00694                                                  char *fargs[], int nfargs, char *cargs[], int ncargs)
00695 {
00696         char *temp;
00697         time_t tt;
00698 
00699         tt = atol(fargs[0]);
00700         temp = (char *) ctime(&tt);
00701         temp[strlen(temp) - 1] = '\0';
00702         safe_str(temp, buff, bufc);
00703 }
00704 
00710 static const char *monthtab[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
00711         "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
00712 };
00713 
00714 static const char daystab[] = { 31, 29, 31, 30, 31, 30,
00715         31, 31, 30, 31, 30, 31
00716 };
00717 
00724 #define get_substr(buf, p) { \
00725         p = (char *)index(buf, ' '); \
00726         if (p) { \
00727                 *p++ = '\0'; \
00728                 while (*p == ' ') p++; \
00729         } \
00730 }
00731 
00732 int do_convtime(char *str, struct tm *ttm)
00733 {
00734         char *buf, *p, *q;
00735         int i;
00736 
00737         if(!str || !ttm)
00738                 return 0;
00739         while (*str == ' ')
00740                 str++;
00741         buf = p = alloc_sbuf("do_convtime");    /*
00742                                                                                          * make a temp copy of arg 
00743                                                                                          */
00744         safe_sb_str(str, buf, &p);
00745         *p = '\0';
00746 
00747         get_substr(buf, p);                     /*
00748                                                                  * day-of-week or month 
00749                                                                  */
00750         if(!p || strlen(buf) != 3) {
00751                 free_sbuf(buf);
00752                 return 0;
00753         }
00754         for(i = 0; (i < 12) && string_compare(monthtab[i], p); i++);
00755         if(i == 12) {
00756                 get_substr(p, q);               /*
00757                                                                  * month 
00758                                                                  */
00759                 if(!q || strlen(p) != 3) {
00760                         free_sbuf(buf);
00761                         return 0;
00762                 }
00763                 for(i = 0; (i < 12) && string_compare(monthtab[i], p); i++);
00764                 if(i == 12) {
00765                         free_sbuf(buf);
00766                         return 0;
00767                 }
00768                 p = q;
00769         }
00770         ttm->tm_mon = i;
00771 
00772         get_substr(p, q);                       /*
00773                                                                  * day of month 
00774                                                                  */
00775         if(!q || (ttm->tm_mday = atoi(p)) < 1 || ttm->tm_mday > daystab[i]) {
00776                 free_sbuf(buf);
00777                 return 0;
00778         }
00779         p = (char *) index(q, ':');     /*
00780                                                                  * hours 
00781                                                                  */
00782         if(!p) {
00783                 free_sbuf(buf);
00784                 return 0;
00785         }
00786         *p++ = '\0';
00787         if((ttm->tm_hour = atoi(q)) > 23 || ttm->tm_hour < 0) {
00788                 free_sbuf(buf);
00789                 return 0;
00790         }
00791         if(ttm->tm_hour == 0) {
00792                 while (isspace(*q))
00793                         q++;
00794                 if(*q != '0') {
00795                         free_sbuf(buf);
00796                         return 0;
00797                 }
00798         }
00799         q = (char *) index(p, ':');     /*
00800                                                                  * minutes 
00801                                                                  */
00802         if(!q) {
00803                 free_sbuf(buf);
00804                 return 0;
00805         }
00806         *q++ = '\0';
00807         if((ttm->tm_min = atoi(p)) > 59 || ttm->tm_min < 0) {
00808                 free_sbuf(buf);
00809                 return 0;
00810         }
00811         if(ttm->tm_min == 0) {
00812                 while (isspace(*p))
00813                         p++;
00814                 if(*p != '0') {
00815                         free_sbuf(buf);
00816                         return 0;
00817                 }
00818         }
00819         get_substr(q, p);                       /*
00820                                                                  * seconds 
00821                                                                  */
00822         if(!p || (ttm->tm_sec = atoi(q)) > 59 || ttm->tm_sec < 0) {
00823                 free_sbuf(buf);
00824                 return 0;
00825         }
00826         if(ttm->tm_sec == 0) {
00827                 while (isspace(*q))
00828                         q++;
00829                 if(*q != '0') {
00830                         free_sbuf(buf);
00831                         return 0;
00832                 }
00833         }
00834         get_substr(p, q);                       /*
00835                                                                  * year 
00836                                                                  */
00837         if((ttm->tm_year = atoi(p)) == 0) {
00838                 while (isspace(*p))
00839                         p++;
00840                 if(*p != '0') {
00841                         free_sbuf(buf);
00842                         return 0;
00843                 }
00844         }
00845         free_sbuf(buf);
00846         if(ttm->tm_year > 100)
00847                 ttm->tm_year -= 1900;
00848         if(ttm->tm_year < 0) {
00849                 return 0;
00850         }
00851 #define LEAPYEAR_1900(yr) ((yr)%400==100||((yr)%100!=0&&(yr)%4==0))
00852         return (ttm->tm_mday != 29 || i != 1 || LEAPYEAR_1900(ttm->tm_year));
00853 #undef LEAPYEAR_1900
00854 }
00855 
00856 static void fun_convtime(char *buff, char **bufc, dbref player, dbref cause,
00857                                                  char *fargs[], int nfargs, char *cargs[], int ncargs)
00858 {
00859         struct tm *ttm;
00860 
00861         ttm = localtime(&mudstate.now);
00862         if(do_convtime(fargs[0], ttm))
00863                 safe_tprintf_str(buff, bufc, "%d", timelocal(ttm));
00864         else
00865                 safe_str("-1", buff, bufc);
00866 }
00867 
00872 #define UPTIME_UNITS 6
00873 
00874 struct {
00875         int multip;
00876         char *name;
00877         char *sname;
00878 } uptime_unit_table[UPTIME_UNITS] = {
00879         {
00880         60 *60 * 24 * 30 * 12, "year", "y"}, {
00881         60 *60 * 24 * 30, "month", "m"}, {
00882         60 *60 * 24, "day", "d"}, {
00883         60 *60, "hour", "h"}, {
00884         60, "minute", "m"}, {
00885         1, "second", "s"}
00886 };
00887 
00888 char *get_uptime_to_string(int uptime)
00889 {
00890         char *buf = alloc_sbuf("get_uptime_to_string");
00891         int units[UPTIME_UNITS];
00892         int taim = uptime;
00893         int ut = 0, uc = 0, foofaa;
00894 
00895         if(uptime <= 0) {
00896                 strcpy(buf, "#-1 INVALID VALUE");
00897                 return buf;
00898         }
00899         for(ut = 0; ut < UPTIME_UNITS; ut++)
00900                 units[ut] = 0;
00901         ut = 0;
00902         buf[0] = 0;
00903         while (taim > 0) {
00904                 if((foofaa = (taim / uptime_unit_table[ut].multip)) > 0) {
00905                         uc++;
00906                         units[ut] = foofaa;
00907                         taim -= uptime_unit_table[ut].multip * foofaa;
00908                 }
00909                 ut++;
00910         }
00911         /*
00912          * Now, we got it..
00913          */
00914         for(ut = 0; ut < UPTIME_UNITS; ut++) {
00915                 if(units[ut]) {
00916                         uc--;
00917                         if(units[ut] > 1)
00918                                 sprintf(buf + strlen(buf), "%d %ss", units[ut],
00919                                                 uptime_unit_table[ut].name);
00920                         else
00921                                 sprintf(buf + strlen(buf), "%d %s", units[ut],
00922                                                 uptime_unit_table[ut].name);
00923                         if(uc > 1)
00924                                 strcat(buf, ", ");
00925                         else if(uc > 0)
00926                                 strcat(buf, " and ");
00927                 }
00928         }
00929         return buf;
00930 }
00931 
00932 char *get_uptime_to_short_string(int uptime)
00933 {
00934         char *buf = alloc_sbuf("get_uptime_to_string");
00935         int units[UPTIME_UNITS];
00936         int taim = uptime;
00937         int ut = 0, uc = 0, foofaa;
00938 
00939         if(uptime <= 0) {
00940                 strcpy(buf, "#-1 INVALID VALUE");
00941                 return buf;
00942         }
00943         for(ut = 0; ut < UPTIME_UNITS; ut++)
00944                 units[ut] = 0;
00945         ut = 0;
00946         buf[0] = 0;
00947         while (taim > 0) {
00948                 if((foofaa = (taim / uptime_unit_table[ut].multip)) > 0) {
00949                         uc++;
00950                         units[ut] = foofaa;
00951                         taim -= uptime_unit_table[ut].multip * foofaa;
00952                 }
00953                 ut++;
00954         }
00955         /*
00956          * Now, we got it..
00957          */
00958         for(ut = 0; ut < UPTIME_UNITS; ut++) {
00959                 if(units[ut]) {
00960                         uc--;
00961                         if(units[ut] > 1)
00962                                 sprintf(buf + strlen(buf), "%d%s", units[ut],
00963                                                 uptime_unit_table[ut].sname);
00964                         else
00965                                 sprintf(buf + strlen(buf), "%d%s", units[ut],
00966                                                 uptime_unit_table[ut].sname);
00967                         if(uc > 0)
00968                                 strcat(buf, " ");
00969                 }
00970         }
00971         return buf;
00972 }
00973 
00974 static void fun_convuptime(char *buff, char **bufc, dbref player, dbref cause,
00975                                                    char *fargs[], int nfargs, char *cargs[],
00976                                                    int ncargs)
00977 {
00978         char *uptimestring = get_uptime_to_string(atoi(fargs[0]));
00979 
00980         safe_str(uptimestring, buff, bufc);
00981         free_sbuf(uptimestring);
00982 }
00983 
00984 static void fun_lag(char *buff, char **bufc, dbref player, dbref cause,
00985                                         char *fargs[], int nfargs, char *cargs[], int ncargs)
00986 {
00987         char buf[256];
00988 
00989         sprintf(buf, "%d", game_lag());
00990         safe_str(buf, buff, bufc);
00991 }
00992 
00996 static void fun_starttime(char *buff, char **bufc, dbref player, dbref cause,
00997                                                   char *fargs[], int nfargs, char *cargs[],
00998                                                   int ncargs)
00999 {
01000         char *temp;
01001 
01002         temp = (char *) ctime(&mudstate.start_time);
01003         temp[strlen(temp) - 1] = '\0';
01004         safe_str(temp, buff, bufc);
01005 }
01006 
01010 static void fun_startsecs(char *buff, char **bufc, dbref player, dbref cause,
01011                                                   char *fargs[], int nfargs, char *cargs[],
01012                                                   int ncargs)
01013 {
01014         safe_tprintf_str(buff, bufc, "%d", mudstate.start_time);
01015 }
01016 
01020 static void fun_connrecord(char *buff, char **bufc, dbref player, dbref cause,
01021                                                    char *fargs[], int nfargs, char *cargs[],
01022                                                    int ncargs)
01023 {
01024         safe_tprintf_str(buff, bufc, "%d", mudstate.record_players);
01025 }
01026 
01030 int check_read_perms(dbref player, dbref thing, ATTR * attr, int aowner,
01031                                          int aflags, char *buff, char **bufc)
01032 {
01033         int see_it;
01034 
01035         /*
01036          * If we have explicit read permission to the attr, return it 
01037          */
01038 
01039         if(See_attr_explicit(player, thing, attr, aowner, aflags))
01040                 return 1;
01041 
01042         /*
01043          * If we are nearby or have examine privs to the attr and it is * * * 
01044          * 
01045          * * visible to us, return it. 
01046          */
01047 
01048         see_it = See_attr(player, thing, attr, aowner, aflags);
01049         if((Examinable(player, thing) || nearby(player, thing) ||
01050                 See_All(player)) && see_it)
01051                 return 1;
01052 
01053         /*
01054          * For any object, we can read its visible attributes, EXCEPT * for * 
01055          * 
01056          * *  * * descs, which are only visible if read_rem_desc is on. 
01057          */
01058 
01059         if(see_it) {
01060                 if(!mudconf.read_rem_desc && (attr->number == A_DESC)) {
01061                         safe_str("#-1 TOO FAR AWAY TO SEE", buff, bufc);
01062                         return 0;
01063                 } else {
01064                         return 1;
01065                 }
01066         }
01067         safe_str("#-1 PERMISSION DENIED", buff, bufc);
01068         return 0;
01069 }
01070 
01071 static void fun_get(char *buff, char **bufc, dbref player, dbref cause,
01072                                         char *fargs[], int nfargs, char *cargs[], int ncargs)
01073 {
01074         dbref thing, aowner;
01075         int attrib, free_buffer, aflags;
01076         ATTR *attr;
01077         char *atr_gotten;
01078         struct boolexp *bool;
01079 
01080         if(!parse_attrib(player, fargs[0], &thing, &attrib)) {
01081                 safe_str("#-1 NO MATCH", buff, bufc);
01082                 return;
01083         }
01084         if(attrib == NOTHING) {
01085                 return;
01086         }
01087         free_buffer = 1;
01088         attr = atr_num(attrib);         /*
01089                                                                  * We need the attr's flags for this: 
01090                                                                  */
01091         if(!attr) {
01092                 return;
01093         }
01094         if(attr->flags & AF_IS_LOCK) {
01095                 atr_gotten = atr_get(thing, attrib, &aowner, &aflags);
01096                 if(Read_attr(player, thing, attr, aowner, aflags)) {
01097                         bool = parse_boolexp(player, atr_gotten, 1);
01098                         free_lbuf(atr_gotten);
01099                         atr_gotten = unparse_boolexp(player, bool);
01100                         free_boolexp(bool);
01101                 } else {
01102                         free_lbuf(atr_gotten);
01103                         atr_gotten = (char *) "#-1 PERMISSION DENIED";
01104                 }
01105                 free_buffer = 0;
01106         } else {
01107                 atr_gotten = atr_pget(thing, attrib, &aowner, &aflags);
01108         }
01109 
01110         /*
01111          * Perform access checks.  c_r_p fills buff with an error message * * 
01112          * 
01113          * *  * * if needed. 
01114          */
01115 
01116         if(check_read_perms(player, thing, attr, aowner, aflags, buff, bufc))
01117                 safe_str(atr_gotten, buff, bufc);
01118         if(free_buffer)
01119                 free_lbuf(atr_gotten);
01120         return;
01121 }
01122 
01123 static void fun_xget(char *buff, char **bufc, dbref player, dbref cause,
01124                                          char *fargs[], int nfargs, char *cargs[], int ncargs)
01125 {
01126         dbref thing, aowner;
01127         int attrib, free_buffer, aflags;
01128         ATTR *attr;
01129         char *atr_gotten;
01130         struct boolexp *bool;
01131     char buffer[MBUF_SIZE];
01132 
01133 
01134         if(!*fargs[0] || !*fargs[1])
01135                 return;
01136 
01137     snprintf(buffer, MBUF_SIZE - 1, "%s/%s", fargs[0], fargs[1]);
01138         if(!parse_attrib(player, buffer, &thing, &attrib)) {
01139                 safe_str("#-1 NO MATCH", buff, bufc);
01140                 return;
01141         }
01142         if(attrib == NOTHING) {
01143                 return;
01144         }
01145         free_buffer = 1;
01146         attr = atr_num(attrib);         /*
01147                                                                  * We need the attr's flags for this: 
01148                                                                  */
01149         if(!attr) {
01150                 return;
01151         }
01152         if(attr->flags & AF_IS_LOCK) {
01153                 atr_gotten = atr_get(thing, attrib, &aowner, &aflags);
01154                 if(Read_attr(player, thing, attr, aowner, aflags)) {
01155                         bool = parse_boolexp(player, atr_gotten, 1);
01156                         free_lbuf(atr_gotten);
01157                         atr_gotten = unparse_boolexp(player, bool);
01158                         free_boolexp(bool);
01159                 } else {
01160                         free_lbuf(atr_gotten);
01161                         atr_gotten = (char *) "#-1 PERMISSION DENIED";
01162                 }
01163                 free_buffer = 0;
01164         } else {
01165                 atr_gotten = atr_pget(thing, attrib, &aowner, &aflags);
01166         }
01167 
01168         /*
01169          * Perform access checks.  c_r_p fills buff with an error message * * 
01170          * 
01171          * *  * * if needed. 
01172          */
01173 
01174         if(check_read_perms(player, thing, attr, aowner, aflags, buff, bufc))
01175                 safe_str(atr_gotten, buff, bufc);
01176         if(free_buffer)
01177                 free_lbuf(atr_gotten);
01178         return;
01179 }
01180 
01181 static void fun_get_eval(char *buff, char **bufc, dbref player, dbref cause,
01182                                                  char *fargs[], int nfargs, char *cargs[], int ncargs)
01183 {
01184         dbref thing, aowner;
01185         int attrib, free_buffer, aflags, eval_it;
01186         ATTR *attr;
01187         char *atr_gotten, *str;
01188         struct boolexp *bool;
01189 
01190         if(!parse_attrib(player, fargs[0], &thing, &attrib)) {
01191                 safe_str("#-1 NO MATCH", buff, bufc);
01192                 return;
01193         }
01194         if(attrib == NOTHING) {
01195                 return;
01196         }
01197         free_buffer = 1;
01198         eval_it = 1;
01199         attr = atr_num(attrib);         /*
01200                                                                  * We need the attr's flags for this: 
01201                                                                  */
01202         if(!attr) {
01203                 return;
01204         }
01205         if(attr->flags & AF_IS_LOCK) {
01206                 atr_gotten = atr_get(thing, attrib, &aowner, &aflags);
01207                 if(Read_attr(player, thing, attr, aowner, aflags)) {
01208                         bool = parse_boolexp(player, atr_gotten, 1);
01209                         free_lbuf(atr_gotten);
01210                         atr_gotten = unparse_boolexp(player, bool);
01211                         free_boolexp(bool);
01212                 } else {
01213                         free_lbuf(atr_gotten);
01214                         atr_gotten = (char *) "#-1 PERMISSION DENIED";
01215                 }
01216                 free_buffer = 0;
01217                 eval_it = 0;
01218         } else {
01219                 atr_gotten = atr_pget(thing, attrib, &aowner, &aflags);
01220         }
01221         if(!check_read_perms(player, thing, attr, aowner, aflags, buff, bufc)) {
01222                 if(free_buffer)
01223                         free_lbuf(atr_gotten);
01224                 return;
01225         }
01226         if(eval_it) {
01227                 str = atr_gotten;
01228                 exec(buff, bufc, 0, thing, player, EV_FIGNORE | EV_EVAL, &str,
01229                          (char **) NULL, 0);
01230         } else {
01231                 safe_str(atr_gotten, buff, bufc);
01232         }
01233         if(free_buffer)
01234                 free_lbuf(atr_gotten);
01235         return;
01236 }
01237 
01238 static void fun_subeval(char *buff, char **bufc, dbref player, dbref cause,
01239                                                 char *fargs[], int nfargs, char *cargs[], int ncargs)
01240 {
01241         char *str;
01242 
01243         if(nfargs != 1) {
01244                 safe_str("#-1 FUNCTION (EVALNOCOMP) EXPECTS 1 OR 2 ARGUMENTS",
01245                                  buff, bufc);
01246                 return;
01247         }
01248 
01249         str = fargs[0];
01250         exec(buff, bufc, 0, player, cause,
01251                  EV_NO_LOCATION | EV_NOFCHECK | EV_FIGNORE | EV_NO_COMPRESS, &str,
01252                  (char **) NULL, 0);
01253 }
01254 
01255 static void fun_eval(char *buff, char **bufc, dbref player, dbref cause,
01256                                          char *fargs[], int nfargs, char *cargs[], int ncargs)
01257 {
01258         dbref thing, aowner;
01259         int attrib, free_buffer, aflags, eval_it;
01260         ATTR *attr;
01261         char *atr_gotten, *str;
01262         struct boolexp *bool;
01263     char buffer[MBUF_SIZE];
01264 
01265         if((nfargs != 1) && (nfargs != 2)) {
01266                 safe_str("#-1 FUNCTION (EVAL) EXPECTS 1 OR 2 ARGUMENTS", buff, bufc);
01267                 return;
01268         }
01269         if(nfargs == 1) {
01270                 str = fargs[0];
01271                 exec(buff, bufc, 0, player, cause, EV_EVAL, &str, (char **) NULL, 0);
01272                 return;
01273         }
01274         if(!*fargs[0] || !*fargs[1])
01275                 return;
01276 
01277     snprintf(buffer, MBUF_SIZE-1, "%s/%s", fargs[0], fargs[1]);
01278         if(!parse_attrib(player, buffer, &thing, &attrib)) {
01279                 safe_str("#-1 NO MATCH", buff, bufc);
01280                 return;
01281         }
01282         if(attrib == NOTHING) {
01283                 return;
01284         }
01285         free_buffer = 1;
01286         eval_it = 1;
01287         attr = atr_num(attrib);
01288         if(!attr) {
01289                 return;
01290         }
01291         if(attr->flags & AF_IS_LOCK) {
01292                 atr_gotten = atr_get(thing, attrib, &aowner, &aflags);
01293                 if(Read_attr(player, thing, attr, aowner, aflags)) {
01294                         bool = parse_boolexp(player, atr_gotten, 1);
01295                         free_lbuf(atr_gotten);
01296                         atr_gotten = unparse_boolexp(player, bool);
01297                         free_boolexp(bool);
01298                 } else {
01299                         free_lbuf(atr_gotten);
01300                         atr_gotten = (char *) "#-1 PERMISSION DENIED";
01301                 }
01302                 free_buffer = 0;
01303                 eval_it = 0;
01304         } else {
01305                 atr_gotten = atr_pget(thing, attrib, &aowner, &aflags);
01306         }
01307         if(!check_read_perms(player, thing, attr, aowner, aflags, buff, bufc)) {
01308                 if(free_buffer)
01309                         free_lbuf(atr_gotten);
01310                 return;
01311         }
01312         if(eval_it) {
01313                 str = atr_gotten;
01314                 exec(buff, bufc, 0, thing, player, EV_FIGNORE | EV_EVAL, &str,
01315                          (char **) NULL, 0);
01316         } else {
01317                 safe_str(atr_gotten, buff, bufc);
01318         }
01319         if(free_buffer)
01320                 free_lbuf(atr_gotten);
01321         return;
01322 }
01323 
01327 static void do_ufun(char *buff, char **bufc, dbref player, dbref cause,
01328                                         char *fargs[], int nfargs, char *cargs[], int ncargs,
01329                                         int is_local)
01330 {
01331         dbref aowner, thing;
01332         int aflags, anum, i;
01333         ATTR *ap;
01334         char *atext, *preserve[MAX_GLOBAL_REGS], *str;
01335 
01336         /*
01337          * We need at least one argument 
01338          */
01339 
01340         if(nfargs < 1) {
01341                 safe_str("#-1 TOO FEW ARGUMENTS", buff, bufc);
01342                 return;
01343         }
01344         /*
01345          * Two possibilities for the first arg: <obj>/<attr> and <attr>. 
01346          */
01347 
01348         if(parse_attrib(player, fargs[0], &thing, &anum)) {
01349                 if((anum == NOTHING) || (!Good_obj(thing)))
01350                         ap = NULL;
01351                 else
01352                         ap = atr_num(anum);
01353         } else {
01354                 thing = player;
01355                 ap = atr_str(fargs[0]);
01356         }
01357 
01358         /*
01359          * Make sure we got a good attribute 
01360          */
01361 
01362         if(!ap) {
01363                 return;
01364         }
01365         /*
01366          * Use it if we can access it, otherwise return an error. 
01367          */
01368 
01369         atext = atr_pget(thing, ap->number, &aowner, &aflags);
01370         if(!atext) {
01371                 free_lbuf(atext);
01372                 return;
01373         }
01374         if(!*atext) {
01375                 free_lbuf(atext);
01376                 return;
01377         }
01378         if(!check_read_perms(player, thing, ap, aowner, aflags, buff, bufc)) {
01379                 free_lbuf(atext);
01380                 return;
01381         }
01382         /*
01383          * If we're evaluating locally, preserve the global registers. 
01384          */
01385 
01386         if(is_local) {
01387                 for(i = 0; i < MAX_GLOBAL_REGS; i++) {
01388                         if(!mudstate.global_regs[i])
01389                                 preserve[i] = NULL;
01390                         else {
01391                                 preserve[i] = alloc_lbuf("u_regs");
01392                                 StringCopy(preserve[i], mudstate.global_regs[i]);
01393                         }
01394                 }
01395         }
01396         /*
01397          * Evaluate it using the rest of the passed function args 
01398          */
01399 
01400         str = atext;
01401         exec(buff, bufc, 0, thing, cause, EV_FCHECK | EV_EVAL, &str,
01402                  &(fargs[1]), nfargs - 1);
01403         free_lbuf(atext);
01404 
01405         /*
01406          * If we're evaluating locally, restore the preserved registers. 
01407          */
01408 
01409         if(is_local) {
01410                 for(i = 0; i < MAX_GLOBAL_REGS; i++) {
01411                         if(preserve[i]) {
01412                                 if(!mudstate.global_regs[i])
01413                                         mudstate.global_regs[i] = alloc_lbuf("u_reg");
01414                                 StringCopy(mudstate.global_regs[i], preserve[i]);
01415                                 free_lbuf(preserve[i]);
01416                         } else {
01417                                 if(mudstate.global_regs[i])
01418                                         *(mudstate.global_regs[i]) = '\0';
01419                         }
01420                 }
01421         }
01422 }
01423 
01424 static void fun_u(char *buff, char **bufc, dbref player, dbref cause,
01425                                   char *fargs[], int nfargs, char *cargs[], int ncargs)
01426 {
01427         do_ufun(buff, bufc, player, cause, fargs, nfargs, cargs, ncargs, 0);
01428 }
01429 
01430 static void fun_ulocal(char *buff, char **bufc, dbref player, dbref cause,
01431                                            char *fargs[], int nfargs, char *cargs[], int ncargs)
01432 {
01433         do_ufun(buff, bufc, player, cause, fargs, nfargs, cargs, ncargs, 1);
01434 }
01435 
01439 static void fun_parent(char *buff, char **bufc, dbref player, dbref cause,
01440                                            char *fargs[], int nfargs, char *cargs[], int ncargs)
01441 {
01442         dbref it;
01443 
01444         it = match_thing(player, fargs[0]);
01445         if(Good_obj(it) && (Examinable(player, it) || (it == cause))) {
01446                 safe_tprintf_str(buff, bufc, "#%d", Parent(it));
01447         } else {
01448                 safe_str("#-1", buff, bufc);
01449         }
01450         return;
01451 }
01452 
01458 static void fun_parse(char *buff, char **bufc, dbref player, dbref cause,
01459                                           char *fargs[], int nfargs, char *cargs[], int ncargs)
01460 {
01461         char *curr, *objstring, *buff2, *buff3, *cp, sep;
01462         char *dp, *str;
01463         int first, number = 0;
01464     char buffer[MBUF_SIZE];
01465 
01466         evarargs_preamble("PARSE", 3);
01467         cp = curr = dp = alloc_lbuf("fun_parse");
01468         str = fargs[0];
01469         exec(curr, &dp, 0, player, cause, EV_STRIP | EV_FCHECK | EV_EVAL, &str,
01470                  cargs, ncargs);
01471         *dp = '\0';
01472         cp = trim_space_sep(cp, sep);
01473         if(!*cp) {
01474                 free_lbuf(curr);
01475                 return;
01476         }
01477         first = 1;
01478         while (cp) {
01479                 if(!first)
01480                         safe_chr(' ', buff, bufc);
01481                 first = 0;
01482                 number++;
01483                 objstring = split_token(&cp, sep);
01484                 buff2 = replace_string(BOUND_VAR, objstring, fargs[1]);
01485         snprintf(buffer, MBUF_SIZE-1, "%d", number);
01486                 buff3 = replace_string(LISTPLACE_VAR, buffer, buff2);
01487                 str = buff3;
01488                 exec(buff, bufc, 0, player, cause, EV_STRIP | EV_FCHECK | EV_EVAL,
01489                          &str, cargs, ncargs);
01490                 free_lbuf(buff2);
01491                 free_lbuf(buff3);
01492         }
01493         free_lbuf(curr);
01494 }
01495 
01499 static void fun_mid(char *buff, char **bufc, dbref player, dbref cause,
01500                                         char *fargs[], int nfargs, char *cargs[], int ncargs)
01501 {
01502         int l, len;
01503         char *oldp;
01504         char new[LBUF_SIZE];
01505         
01506         oldp = *bufc;
01507         l = atoi(fargs[1]);
01508         len = atoi(fargs[2]);
01509         if((l < 0) || (len < 0) || ((len + l) > LBUF_SIZE) || ((len + 1) < 0)) {
01510                 safe_str("#-1 OUT OF RANGE", buff, bufc);
01511                 return;
01512         }
01513         strncpy(new, fargs[0], LBUF_SIZE-1);
01514         if(l < strlen(strip_ansi_r(new,fargs[0],strlen(fargs[0]))))
01515                 safe_str(strip_ansi_r(new,fargs[0],strlen(fargs[0])) + l, buff, bufc);
01516         oldp[len] = 0;
01517         if((oldp + len) < *bufc) {
01518                 *bufc = oldp + len;
01519         }
01520 }
01521 
01525 static void fun_first(char *buff, char **bufc, dbref player, dbref cause,
01526                                           char *fargs[], int nfargs, char *cargs[], int ncargs)
01527 {
01528         char *s, *first, sep;
01529 
01530         /*
01531          * If we are passed an empty arglist return a null string 
01532          */
01533 
01534         if(nfargs == 0) {
01535                 return;
01536         }
01537         varargs_preamble("FIRST", 2);
01538         s = trim_space_sep(fargs[0], sep);      /*
01539                                                                                  * leading spaces ... 
01540                                                                                  */
01541         first = split_token(&s, sep);
01542         if(first) {
01543                 safe_str(first, buff, bufc);
01544         }
01545 }
01546 
01550 static void fun_rest(char *buff, char **bufc, dbref player, dbref cause,
01551                                          char *fargs[], int nfargs, char *cargs[], int ncargs)
01552 {
01553         char *s, *first, sep;
01554 
01555         /*
01556          * If we are passed an empty arglist return a null string 
01557          */
01558 
01559         if(nfargs == 0) {
01560                 return;
01561         }
01562         varargs_preamble("REST", 2);
01563         s = trim_space_sep(fargs[0], sep);      /*
01564                                                                                  * leading spaces ... 
01565                                                                                  */
01566         first = split_token(&s, sep);
01567         if(s) {
01568                 safe_str(s, buff, bufc);
01569         }
01570 }
01571 
01575 static void fun_v(char *buff, char **bufc, dbref player, dbref cause,
01576                                   char *fargs[], int nfargs, char *cargs[], int ncargs)
01577 {
01578         dbref aowner;
01579         int aflags;
01580         char *sbuf, *sbufc, *tbuf, *str;
01581         ATTR *ap;
01582 
01583         tbuf = fargs[0];
01584         if(isalpha(tbuf[0]) && tbuf[1]) {
01585 
01586                 /*
01587                  * Fetch an attribute from me.  First see if it exists, * * * 
01588                  * 
01589                  * * returning a null string if it does not. 
01590                  */
01591 
01592                 ap = atr_str(fargs[0]);
01593                 if(!ap) {
01594                         return;
01595                 }
01596                 /*
01597                  * If we can access it, return it, otherwise return a * null
01598                  * * * * string 
01599                  */
01600 
01601                 atr_pget_info(player, ap->number, &aowner, &aflags);
01602                 if(See_attr(player, player, ap, aowner, aflags)) {
01603                         tbuf = atr_pget(player, ap->number, &aowner, &aflags);
01604                         safe_str(tbuf, buff, bufc);
01605                         free_lbuf(tbuf);
01606                 }
01607                 return;
01608         }
01609         /*
01610          * Not an attribute, process as %<arg> 
01611          */
01612 
01613         sbuf = alloc_sbuf("fun_v");
01614         sbufc = sbuf;
01615         safe_sb_chr('%', sbuf, &sbufc);
01616         safe_sb_str(fargs[0], sbuf, &sbufc);
01617         *sbufc = '\0';
01618         str = sbuf;
01619         exec(buff, bufc, 0, player, cause, EV_FIGNORE, &str, cargs, ncargs);
01620         free_sbuf(sbuf);
01621 }
01622 
01626 static void fun_s(char *buff, char **bufc, dbref player, dbref cause,
01627                                   char *fargs[], int nfargs, char *cargs[], int ncargs)
01628 {
01629         char *str;
01630 
01631         str = fargs[0];
01632         exec(buff, bufc, 0, player, cause, EV_FIGNORE | EV_EVAL, &str, cargs,
01633                  ncargs);
01634 }
01635 
01639 static void fun_con(char *buff, char **bufc, dbref player, dbref cause,
01640                                         char *fargs[], int nfargs, char *cargs[], int ncargs)
01641 {
01642         dbref it;
01643 
01644         it = match_thing(player, fargs[0]);
01645 
01646         if((it != NOTHING) && (Has_contents(it)) && (Examinable(player, it) ||
01647                                                                                                  (where_is(player) == it)
01648                                                                                                  || (it == cause))) {
01649                 safe_tprintf_str(buff, bufc, "#%d", Contents(it));
01650                 return;
01651         }
01652         safe_str("#-1", buff, bufc);
01653         return;
01654 }
01655 
01656 /*
01657  * ---------------------------------------------------------------------------
01658  * * fun_exit: Returns first exit in exits list of room.
01659  */
01660 static void fun_exit(char *buff, char **bufc, dbref player, dbref cause,
01661                                          char *fargs[], int nfargs, char *cargs[], int ncargs)
01662 {
01663         dbref it, exit;
01664         int key;
01665 
01666         it = match_thing(player, fargs[0]);
01667         if(Good_obj(it) && Has_exits(it) && Good_obj(Exits(it))) {
01668                 key = 0;
01669                 if(Examinable(player, it))
01670                         key |= VE_LOC_XAM;
01671                 if(Dark(it))
01672                         key |= VE_LOC_DARK;
01673                 DOLIST(exit, Exits(it)) {
01674                         if(exit_visible(exit, player, key)) {
01675                                 safe_tprintf_str(buff, bufc, "#%d", exit);
01676                                 return;
01677                         }
01678                 }
01679         }
01680         safe_str("#-1", buff, bufc);
01681         return;
01682 }
01683 
01684 /*
01685  * ---------------------------------------------------------------------------
01686  * * fun_next: return next thing in contents or exits chain
01687  */
01688 
01689 static void fun_next(char *buff, char **bufc, dbref player, dbref cause,
01690                                          char *fargs[], int nfargs, char *cargs[], int ncargs)
01691 {
01692         dbref it, loc, exit, ex_here;
01693         int key;
01694 
01695         it = match_thing(player, fargs[0]);
01696         if(Good_obj(it) && Has_siblings(it)) {
01697                 loc = where_is(it);
01698                 ex_here = Good_obj(loc) ? Examinable(player, loc) : 0;
01699                 if(ex_here || (loc == player) || (loc == where_is(player))) {
01700                         if(!isExit(it)) {
01701                                 safe_tprintf_str(buff, bufc, "#%d", Next(it));
01702                                 return;
01703                         } else {
01704                                 key = 0;
01705                                 if(ex_here)
01706                                         key |= VE_LOC_XAM;
01707                                 if(Dark(loc))
01708                                         key |= VE_LOC_DARK;
01709                                 DOLIST(exit, it) {
01710                                         if((exit != it) && exit_visible(exit, player, key)) {
01711                                                 safe_tprintf_str(buff, bufc, "#%d", exit);
01712                                                 return;
01713                                         }
01714                                 }
01715                         }
01716                 }
01717         }
01718         safe_str("#-1", buff, bufc);
01719         return;
01720 }
01721 
01722 /*
01723  * ---------------------------------------------------------------------------
01724  * * fun_loc: Returns the location of something
01725  */
01726 
01727 static void fun_loc(char *buff, char **bufc, dbref player, dbref cause,
01728                                         char *fargs[], int nfargs, char *cargs[], int ncargs)
01729 {
01730         dbref it;
01731 
01732         it = match_thing(player, fargs[0]);
01733         if(locatable(player, it, cause))
01734                 safe_tprintf_str(buff, bufc, "#%d", Location(it));
01735         else
01736                 safe_str("#-1", buff, bufc);
01737         return;
01738 }
01739 
01740 /*
01741  * ---------------------------------------------------------------------------
01742  * * fun_where: Returns the "true" location of something
01743  */
01744 
01745 static void fun_where(char *buff, char **bufc, dbref player, dbref cause,
01746                                           char *fargs[], int nfargs, char *cargs[], int ncargs)
01747 {
01748         dbref it;
01749 
01750         it = match_thing(player, fargs[0]);
01751         if(locatable(player, it, cause))
01752                 safe_tprintf_str(buff, bufc, "#%d", where_is(it));
01753         else
01754                 safe_str("#-1", buff, bufc);
01755         return;
01756 }
01757 
01758 /*
01759  * ---------------------------------------------------------------------------
01760  * * fun_rloc: Returns the recursed location of something (specifying #levels)
01761  */
01762 
01763 static void fun_rloc(char *buff, char **bufc, dbref player, dbref cause,
01764                                          char *fargs[], int nfargs, char *cargs[], int ncargs)
01765 {
01766         int i, levels;
01767         dbref it;
01768 
01769         levels = atoi(fargs[1]);
01770         if(levels > mudconf.ntfy_nest_lim)
01771                 levels = mudconf.ntfy_nest_lim;
01772 
01773         it = match_thing(player, fargs[0]);
01774         if(locatable(player, it, cause)) {
01775                 for(i = 0; i < levels; i++) {
01776                         if(!Good_obj(it) || !Has_location(it))
01777                                 break;
01778                         it = Location(it);
01779                 }
01780                 safe_tprintf_str(buff, bufc, "#%d", it);
01781                 return;
01782         }
01783         safe_str("#-1", buff, bufc);
01784 }
01785 
01786 /*
01787  * ---------------------------------------------------------------------------
01788  * * fun_room: Find the room an object is ultimately in.
01789  */
01790 
01791 static void fun_room(char *buff, char **bufc, dbref player, dbref cause,
01792                                          char *fargs[], int nfargs, char *cargs[], int ncargs)
01793 {
01794         dbref it;
01795         int count;
01796 
01797         it = match_thing(player, fargs[0]);
01798         if(locatable(player, it, cause)) {
01799                 for(count = mudconf.ntfy_nest_lim; count > 0; count--) {
01800                         it = Location(it);
01801                         if(!Good_obj(it))
01802                                 break;
01803                         if(isRoom(it)) {
01804                                 safe_tprintf_str(buff, bufc, "#%d", it);
01805                                 return;
01806                         }
01807                 }
01808                 safe_str("#-1", buff, bufc);
01809         } else if(isRoom(it)) {
01810                 safe_tprintf_str(buff, bufc, "#%d", it);
01811         } else {
01812                 safe_str("#-1", buff, bufc);
01813         }
01814         return;
01815 }
01816 
01817 /*
01818  * ---------------------------------------------------------------------------
01819  * * fun_owner: Return the owner of an object.
01820  */
01821 
01822 static void fun_owner(char *buff, char **bufc, dbref player, dbref cause,
01823                                           char *fargs[], int nfargs, char *cargs[], int ncargs)
01824 {
01825         dbref it, aowner;
01826         int atr, aflags;
01827 
01828         if(parse_attrib(player, fargs[0], &it, &atr)) {
01829                 if(atr == NOTHING) {
01830                         it = NOTHING;
01831                 } else {
01832                         atr_pget_info(it, atr, &aowner, &aflags);
01833                         it = aowner;
01834                 }
01835         } else {
01836                 it = match_thing(player, fargs[0]);
01837                 if(it != NOTHING)
01838                         it = Owner(it);
01839         }
01840         safe_tprintf_str(buff, bufc, "#%d", it);
01841 }
01842 
01843 /*
01844  * ---------------------------------------------------------------------------
01845  * * fun_controls: Does x control y?
01846  */
01847 
01848 static void fun_controls(char *buff, char **bufc, dbref player, dbref cause,
01849                                                  char *fargs[], int nfargs, char *cargs[], int ncargs)
01850 {
01851         dbref x, y;
01852 
01853         x = match_thing(player, fargs[0]);
01854         if(x == NOTHING) {
01855                 safe_tprintf_str(buff, bufc, "%s", "#-1 ARG1 NOT FOUND");
01856                 return;
01857         }
01858         y = match_thing(player, fargs[1]);
01859         if(y == NOTHING) {
01860                 safe_tprintf_str(buff, bufc, "%s", "#-1 ARG2 NOT FOUND");
01861                 return;
01862         }
01863         safe_tprintf_str(buff, bufc, "%d", Controls(x, y));
01864 }
01865 
01866 /*
01867  * ---------------------------------------------------------------------------
01868  * * fun_fullname: Return the fullname of an object (good for exits)
01869  */
01870 
01871 static void fun_fullname(char *buff, char **bufc, dbref player, dbref cause,
01872                                                  char *fargs[], int nfargs, char *cargs[], int ncargs)
01873 {
01874         dbref it;
01875 
01876         it = match_thing(player, fargs[0]);
01877         if(it == NOTHING) {
01878                 return;
01879         }
01880         if(!mudconf.read_rem_name) {
01881                 if(!nearby_or_control(player, it) && (!isPlayer(it))) {
01882                         safe_str("#-1 TOO FAR AWAY TO SEE", buff, bufc);
01883                         return;
01884                 }
01885         }
01886         safe_str(Name(it), buff, bufc);
01887 }
01888 
01889 /*
01890  * ---------------------------------------------------------------------------
01891  * * fun_name: Return the name of an object
01892  */
01893 
01894 static void fun_name(char *buff, char **bufc, dbref player, dbref cause,
01895                                          char *fargs[], int nfargs, char *cargs[], int ncargs)
01896 {
01897         dbref it;
01898         char *s, *temp;
01899 
01900         it = match_thing(player, fargs[0]);
01901         if(it == NOTHING) {
01902                 return;
01903         }
01904         if(!mudconf.read_rem_name) {
01905                 if(!nearby_or_control(player, it) && !isPlayer(it) &&
01906                    !Long_Fingers(player)) {
01907                         safe_str("#-1 TOO FAR AWAY TO SEE", buff, bufc);
01908                         return;
01909                 }
01910         }
01911         temp = *bufc;
01912         safe_str(Name(it), buff, bufc);
01913         if(isExit(it)) {
01914                 for(s = temp; (s != *bufc) && (*s != ';'); s++);
01915                 if(*s == ';')
01916                         *bufc = s;
01917         }
01918 }
01919 
01920 /*
01921  * ---------------------------------------------------------------------------
01922  * * fun_match, fun_strmatch: Match arg2 against each word of arg1 returning
01923  * * index of first match, or against the whole string.
01924  */
01925 
01926 static void fun_match(char *buff, char **bufc, dbref player, dbref cause,
01927                                           char *fargs[], int nfargs, char *cargs[], int ncargs)
01928 {
01929         int wcount;
01930         char *r, *s, sep;
01931 
01932         varargs_preamble("MATCH", 3);
01933 
01934         /*
01935          * Check each word individually, returning the word number of the * * 
01936          * 
01937          * *  * * first one that matches.  If none match, return 0. 
01938          */
01939 
01940         wcount = 1;
01941         s = trim_space_sep(fargs[0], sep);
01942         do {
01943                 r = split_token(&s, sep);
01944                 if(quick_wild(fargs[1], r)) {
01945                         safe_tprintf_str(buff, bufc, "%d", wcount);
01946                         return;
01947                 }
01948                 wcount++;
01949         } while (s);
01950         safe_str("0", buff, bufc);
01951 }
01952 
01953 static void fun_strmatch(char *buff, char **bufc, dbref player, dbref cause,
01954                                                  char *fargs[], int nfargs, char *cargs[], int ncargs)
01955 {
01956         /*
01957          * Check if we match the whole string.  If so, return 1 
01958          */
01959 
01960         if(quick_wild(fargs[1], fargs[0]))
01961                 safe_str("1", buff, bufc);
01962         else
01963                 safe_str("0", buff, bufc);
01964         return;
01965 }
01966 
01967 /*
01968  * ---------------------------------------------------------------------------
01969  * * fun_extract: extract words from string:
01970  * * extract(foo bar baz,1,2) returns 'foo bar'
01971  * * extract(foo bar baz,2,1) returns 'bar'
01972  * * extract(foo bar baz,2,2) returns 'bar baz'
01973  * * 
01974  * * Now takes optional separator extract(foo-bar-baz,1,2,-) returns 'foo-bar'
01975  */
01976 
01977 static void fun_extract(char *buff, char **bufc, dbref player, dbref cause,
01978                                                 char *fargs[], int nfargs, char *cargs[], int ncargs)
01979 {
01980         int start, len;
01981         char *r, *s, *t, sep;
01982 
01983         varargs_preamble("EXTRACT", 4);
01984 
01985         s = fargs[0];
01986         start = atoi(fargs[1]);
01987         len = atoi(fargs[2]);
01988 
01989         if((start < 1) || (len < 1)) {
01990                 return;
01991         }
01992         /*
01993          * Skip to the start of the string to save 
01994          */
01995 
01996         start--;
01997         s = trim_space_sep(s, sep);
01998         while (start && s) {
01999                 s = next_token(s, sep);
02000                 start--;
02001         }
02002 
02003         /*
02004          * If we ran of the end of the string, return nothing 
02005          */
02006 
02007         if(!s || !*s) {
02008                 return;
02009         }
02010         /*
02011          * Count off the words in the string to save 
02012          */
02013 
02014         r = s;
02015         len--;
02016         while (len && s) {
02017                 s = next_token(s, sep);
02018                 len--;
02019         }
02020 
02021         /*
02022          * Chop off the rest of the string, if needed 
02023          */
02024 
02025         if(s && *s)
02026                 t = split_token(&s, sep);
02027         safe_str(r, buff, bufc);
02028 }
02029 
02030 int xlate(char *arg)
02031 {
02032         int temp;
02033         char *temp2;
02034 
02035         if(arg[0] == '#') {
02036                 arg++;
02037                 /* #- anything is false */
02038                 if(arg[1] == '-') {
02039                         return 0;
02040                 }
02041                 if(is_integer(arg)) {
02042                         temp = atoi(arg);
02043                         if(temp == -1)
02044                                 temp = 0;
02045                         return temp;
02046                 }
02047                 return 0;
02048         }
02049         temp2 = trim_space_sep(arg, ' ');
02050         if(!*temp2)
02051                 return 0;
02052         if(is_integer(temp2))
02053                 return atoi(temp2);
02054         return 1;
02055 }
02056 
02057 /*
02058  * ---------------------------------------------------------------------------
02059  * * fun_index:  like extract(), but it works with an arbitrary separator.
02060  * * index(a b | c d e | f gh | ij k, |, 2, 1) => c d e
02061  * * index(a b | c d e | f gh | ij k, |, 2, 2) => c d e | f g h
02062  */
02063 
02064 static void fun_index(char *buff, char **bufc, dbref player, dbref cause,
02065                                           char *fargs[], int nfargs, char *cargs[], int ncargs)
02066 {
02067         int start, end;
02068         char c, *s, *p;
02069 
02070         s = fargs[0];
02071         c = *fargs[1];
02072         start = atoi(fargs[2]);
02073         end = atoi(fargs[3]);
02074 
02075         if((start < 1) || (end < 1) || (*s == '\0'))
02076                 return;
02077         if(c == '\0')
02078                 c = ' ';
02079 
02080         /*
02081          * move s to point to the start of the item we want 
02082          */
02083 
02084         start--;
02085         while (start && s && *s) {
02086                 if((s = (char *) index(s, c)) != NULL)
02087                         s++;
02088                 start--;
02089         }
02090 
02091         /*
02092          * skip over just spaces 
02093          */
02094 
02095         while (s && (*s == ' '))
02096                 s++;
02097         if(!s || !*s)
02098                 return;
02099 
02100         /*
02101          * figure out where to end the string 
02102          */
02103 
02104         p = s;
02105         while (end && p && *p) {
02106                 if((p = (char *) index(p, c)) != NULL) {
02107                         if(--end == 0) {
02108                                 do {
02109                                         p--;
02110                                 } while ((*p == ' ') && (p > s));
02111                                 *(++p) = '\0';
02112                                 safe_str(s, buff, bufc);
02113                                 return;
02114                         } else {
02115                                 p++;
02116                         }
02117                 }
02118         }
02119 
02120         /*
02121          * if we've gotten this far, we've run off the end of the string 
02122          */
02123 
02124         safe_str(s, buff, bufc);
02125 }
02126 
02127 static void fun_cat(char *buff, char **bufc, dbref player, dbref cause,
02128                                         char *fargs[], int nfargs, char *cargs[], int ncargs)
02129 {
02130         int i;
02131 
02132         safe_str(fargs[0], buff, bufc);
02133         for(i = 1; i < nfargs; i++) {
02134                 safe_chr(' ', buff, bufc);
02135                 safe_str(fargs[i], buff, bufc);
02136         }
02137 }
02138 
02139 static void fun_version(char *buff, char **bufc, dbref player, dbref cause,
02140                                                 char *fargs[], int nfargs, char *cargs[], int ncargs)
02141 {
02142         safe_str(mudstate.version, buff, bufc);
02143 }
02144 
02145 static void fun_strlen(char *buff, char **bufc, dbref player, dbref cause,
02146                                            char *fargs[], int nfargs, char *cargs[], int ncargs)
02147 {
02148         char new[LBUF_SIZE];
02149         strncpy(new, fargs[0], LBUF_SIZE-1);
02150         safe_tprintf_str(buff, bufc, "%d",
02151                                          (int) strlen((char *) strip_ansi_r(new,fargs[0],strlen(fargs[0]))));
02152 }
02153 
02154 static void fun_num(char *buff, char **bufc, dbref player, dbref cause,
02155                                         char *fargs[], int nfargs, char *cargs[], int ncargs)
02156 {
02157         safe_tprintf_str(buff, bufc, "#%d", match_thing(player, fargs[0]));
02158 }
02159 
02160 static void fun_pmatch(char *buff, char **bufc, dbref player, dbref cause,
02161                                            char *fargs[], int nfargs, char *cargs[], int ncargs)
02162 {
02163         dbref thing;
02164 
02165         if(*fargs[0] == '#') {
02166                 safe_tprintf_str(buff, bufc, "#%d", match_thing(player, fargs[0]));
02167                 return;
02168         }
02169         if(!((thing = lookup_player(player, fargs[0], 1)) == NOTHING)) {
02170                 safe_tprintf_str(buff, bufc, "#%d", thing);
02171                 return;
02172         } else
02173                 safe_str("#-1 NO MATCH", buff, bufc);
02174 }
02175 
02176 static void fun_gt(char *buff, char **bufc, dbref player, dbref cause,
02177                                    char *fargs[], int nfargs, char *cargs[], int ncargs)
02178 {
02179         safe_tprintf_str(buff, bufc, "%d", (atof(fargs[0]) > atof(fargs[1])));
02180 }
02181 
02182 static void fun_gte(char *buff, char **bufc, dbref player, dbref cause,
02183                                         char *fargs[], int nfargs, char *cargs[], int ncargs)
02184 {
02185         safe_tprintf_str(buff, bufc, "%d", (atof(fargs[0]) >= atof(fargs[1])));
02186 }
02187 
02188 static void fun_lt(char *buff, char **bufc, dbref player, dbref cause,
02189                                    char *fargs[], int nfargs, char *cargs[], int ncargs)
02190 {
02191         safe_tprintf_str(buff, bufc, "%d", (atof(fargs[0]) < atof(fargs[1])));
02192 }
02193 
02194 static void fun_lte(char *buff, char **bufc, dbref player, dbref cause,
02195                                         char *fargs[], int nfargs, char *cargs[], int ncargs)
02196 {
02197         safe_tprintf_str(buff, bufc, "%d", (atof(fargs[0]) <= atof(fargs[1])));
02198 }
02199 
02200 static void fun_eq(char *buff, char **bufc, dbref player, dbref cause,
02201                                    char *fargs[], int nfargs, char *cargs[], int ncargs)
02202 {
02203         safe_tprintf_str(buff, bufc, "%d", (atof(fargs[0]) == atof(fargs[1])));
02204 }
02205 
02206 static void fun_neq(char *buff, char **bufc, dbref player, dbref cause,
02207                                         char *fargs[], int nfargs, char *cargs[], int ncargs)
02208 {
02209         safe_tprintf_str(buff, bufc, "%d", (atof(fargs[0]) != atof(fargs[1])));
02210 }
02211 
02212 static void fun_and(char *buff, char **bufc, dbref player, dbref cause,
02213                                         char *fargs[], int nfargs, char *cargs[], int ncargs)
02214 {
02215         int i, val;
02216 
02217         if(nfargs < 2) {
02218                 safe_str("#-1 TOO FEW ARGUMENTS", buff, bufc);
02219                 return;
02220         }
02221 
02222         val = atoi(fargs[0]);
02223         for(i = 1; val && i < nfargs; i++)
02224                 val = val && atoi(fargs[i]);
02225 
02226         safe_tprintf_str(buff, bufc, "%d", val);
02227 }
02228 
02229 static void fun_or(char *buff, char **bufc, dbref player, dbref cause,
02230                                    char *fargs[], int nfargs, char *cargs[], int ncargs)
02231 {
02232         int i, val;
02233 
02234         if(nfargs < 2) {
02235                 safe_str("#-1 TOO FEW ARGUMENTS", buff, bufc);
02236                 return;
02237         }
02238 
02239         val = atoi(fargs[0]);
02240         for(i = 1; !val && i < nfargs; i++)
02241                 val = val || atoi(fargs[i]);
02242 
02243         safe_tprintf_str(buff, bufc, "%d", val);
02244 }
02245 
02246 static void fun_xor(char *buff, char **bufc, dbref player, dbref cause,
02247                                         char *fargs[], int nfargs, char *cargs[], int ncargs)
02248 {
02249         int i, val;
02250 
02251         if(nfargs < 2) {
02252                 safe_str("#-1 TOO FEW ARGUMENTS", buff, bufc);
02253                 return;
02254         }
02255 
02256         val = atoi(fargs[0]);
02257         for(i = 1; i < nfargs; i++) {
02258                 int tval = atoi(fargs[i]);
02259                 val = (val && !tval) || (!val && tval);
02260         }
02261         safe_tprintf_str(buff, bufc, "%d", val);
02262 }
02263 
02264 static void fun_not(char *buff, char **bufc, dbref player, dbref cause,
02265                                         char *fargs[], int nfargs, char *cargs[], int ncargs)
02266 {
02267         safe_tprintf_str(buff, bufc, "%d", !xlate(fargs[0]));
02268 }
02269 
02270 static void fun_t(char *buff, char **bufc, dbref player, dbref cause,
02271                                   char *fargs[], int nfargs, char *cargs[], int ncargs)
02272 {
02273         safe_tprintf_str(buff, bufc, "%d", !(!xlate(fargs[0])));
02274 }
02275 
02276 static void fun_sqrt(char *buff, char **bufc, dbref player, dbref cause,
02277                                          char *fargs[], int nfargs, char *cargs[], int ncargs)
02278 {
02279         double val;
02280 
02281         val = atof(fargs[0]);
02282         if(val < 0) {
02283                 safe_str("#-1 SQUARE ROOT OF NEGATIVE", buff, bufc);
02284         } else if(val == 0) {
02285                 safe_str("0", buff, bufc);
02286         } else {
02287                 fval(buff, bufc, sqrt(val));
02288         }
02289 }
02290 
02291 static void fun_add(char *buff, char **bufc, dbref player, dbref cause,
02292                                         char *fargs[], int nfargs, char *cargs[], int ncargs)
02293 {
02294         double sum = 0;
02295         int i;
02296 
02297         if(!nfargs) {
02298                 safe_str("#-1 TOO FEW ARGUMENTS", buff, bufc);
02299                 return;
02300         }
02301         for(i = 0; i < nfargs; i++)
02302                 sum += atof(fargs[i]);
02303 
02304         fval(buff, bufc, sum);
02305 }
02306 
02307 static void fun_sub(char *buff, char **bufc, dbref player, dbref cause,
02308                                         char *fargs[], int nfargs, char *cargs[], int ncargs)
02309 {
02310         fval(buff, bufc, atof(fargs[0]) - atof(fargs[1]));
02311 }
02312 
02313 static void fun_mul(char *buff, char **bufc, dbref player, dbref cause,
02314                                         char *fargs[], int nfargs, char *cargs[], int ncargs)
02315 {
02316         int i;
02317         double prod;
02318 
02319         if(!nfargs) {
02320                 safe_str("#-1 TOO FEW ARGUMENTS", buff, bufc);
02321                 return;
02322         }
02323 
02324         prod = atof(fargs[0]);
02325         for(i = 1; i < nfargs; i++)
02326                 prod *= atof(fargs[i]);
02327 
02328         fval(buff, bufc, prod);
02329 }
02330 
02331 static void fun_floor(char *buff, char **bufc, dbref player, dbref cause,
02332                                           char *fargs[], int nfargs, char *cargs[], int ncargs)
02333 {
02334         safe_tprintf_str(buff, bufc, "%.0f", floor(atof(fargs[0])));
02335 }
02336 
02337 static void fun_ceil(char *buff, char **bufc, dbref player, dbref cause,
02338                                          char *fargs[], int nfargs, char *cargs[], int ncargs)
02339 {
02340         safe_tprintf_str(buff, bufc, "%.0f", ceil(atof(fargs[0])));
02341 }
02342 
02343 static void fun_round(char *buff, char **bufc, dbref player, dbref cause,
02344                                           char *fargs[], int nfargs, char *cargs[], int ncargs)
02345 {
02346         const char *fstr;
02347         char *oldp;
02348 
02349         oldp = *bufc;
02350 
02351         switch (atoi(fargs[1])) {
02352         case 1:
02353                 fstr = "%.1f";
02354                 break;
02355         case 2:
02356                 fstr = "%.2f";
02357                 break;
02358         case 3:
02359                 fstr = "%.3f";
02360                 break;
02361         case 4:
02362                 fstr = "%.4f";
02363                 break;
02364         case 5:
02365                 fstr = "%.5f";
02366                 break;
02367         case 6:
02368                 fstr = "%.6f";
02369                 break;
02370         default:
02371                 fstr = "%.0f";
02372                 break;
02373         }
02374         safe_tprintf_str(buff, bufc, (char *) fstr, atof(fargs[0]));
02375 
02376         /* Handle bogus result of "-0" from sprintf.  Yay, cclib. */
02377 
02378         if(!strcmp(oldp, "-0")) {
02379                 *oldp = '0';
02380                 *bufc = oldp + 1;
02381         }
02382 }
02383 
02384 static void fun_trunc(char *buff, char **bufc, dbref player, dbref cause,
02385                                           char *fargs[], int nfargs, char *cargs[], int ncargs)
02386 {
02387         safe_tprintf_str(buff, bufc, "%.0f", atof(fargs[0]));
02388 }
02389 
02390 static void fun_div(char *buff, char **bufc, dbref player, dbref cause,
02391                                         char *fargs[], int nfargs, char *cargs[], int ncargs)
02392 {
02393         int bot;
02394 
02395         bot = atoi(fargs[1]);
02396         if(bot == 0) {
02397                 safe_str("#-1 DIVIDE BY ZERO", buff, bufc);
02398         } else {
02399                 safe_tprintf_str(buff, bufc, "%d", (atoi(fargs[0]) / bot));
02400         }
02401 }
02402 
02403 static void fun_fdiv(char *buff, char **bufc, dbref player, dbref cause,
02404                                          char *fargs[], int nfargs, char *cargs[], int ncargs)
02405 {
02406         double bot;
02407 
02408         bot = atof(fargs[1]);
02409         if(bot == 0) {
02410                 safe_str("#-1 DIVIDE BY ZERO", buff, bufc);
02411         } else {
02412                 fval(buff, bufc, (atof(fargs[0]) / bot));
02413         }
02414 }
02415 
02416 static void fun_mod(char *buff, char **bufc, dbref player, dbref cause,
02417                                         char *fargs[], int nfargs, char *cargs[], int ncargs)
02418 {
02419         int bot;
02420 
02421         bot = atoi(fargs[1]);
02422         if(bot == 0)
02423                 bot = 1;
02424         safe_tprintf_str(buff, bufc, "%d", atoi(fargs[0]) % bot);
02425 }
02426 
02427 static void fun_pi(char *buff, char **bufc, dbref player, dbref cause,
02428                                    char *fargs[], int nfargs, char *cargs[], int ncargs)
02429 {
02430         safe_str("3.141592654", buff, bufc);
02431 }
02432 
02433 static void fun_e(char *buff, char **bufc, dbref player, dbref cause,
02434                                   char *fargs[], int nfargs, char *cargs[], int ncargs)
02435 {
02436         safe_str("2.718281828", buff, bufc);
02437 }
02438 
02439 static void fun_sin(char *buff, char **bufc, dbref player, dbref cause,
02440                                         char *fargs[], int nfargs, char *cargs[], int ncargs)
02441 {
02442         fval(buff, bufc, sin(atof(fargs[0])));
02443 }
02444 
02445 static void fun_cos(char *buff, char **bufc, dbref player, dbref cause,
02446                                         char *fargs[], int nfargs, char *cargs[], int ncargs)
02447 {
02448         fval(buff, bufc, cos(atof(fargs[0])));
02449 }
02450 
02451 static void fun_tan(char *buff, char **bufc, dbref player, dbref cause,
02452                                         char *fargs[], int nfargs, char *cargs[], int ncargs)
02453 {
02454         fval(buff, bufc, tan(atof(fargs[0])));
02455 }
02456 
02457 static void fun_exp(char *buff, char **bufc, dbref player, dbref cause,
02458                                         char *fargs[], int nfargs, char *cargs[], int ncargs)
02459 {
02460         fval(buff, bufc, exp(atof(fargs[0])));
02461 }
02462 
02463 static void fun_power(char *buff, char **bufc, dbref player, dbref cause,
02464                                           char *fargs[], int nfargs, char *cargs[], int ncargs)
02465 {
02466         double val1, val2;
02467 
02468         val1 = atof(fargs[0]);
02469         val2 = atof(fargs[1]);
02470         if(val1 < 0) {
02471                 safe_str("#-1 POWER OF NEGATIVE", buff, bufc);
02472         } else {
02473                 fval(buff, bufc, pow(val1, val2));
02474         }
02475 }
02476 
02477 static void fun_ln(char *buff, char **bufc, dbref player, dbref cause,
02478                                    char *fargs[], int nfargs, char *cargs[], int ncargs)
02479 {
02480         double val;
02481 
02482         val = atof(fargs[0]);
02483         if(val > 0)
02484                 fval(buff, bufc, log(val));
02485         else
02486                 safe_str("#-1 LN OF NEGATIVE OR ZERO", buff, bufc);
02487 }
02488 
02489 static void fun_log(char *buff, char **bufc, dbref player, dbref cause,
02490                                         char *fargs[], int nfargs, char *cargs[], int ncargs)
02491 {
02492         double val;
02493 
02494         val = atof(fargs[0]);
02495         if(val > 0) {
02496                 fval(buff, bufc, log10(val));
02497         } else {
02498                 safe_str("#-1 LOG OF NEGATIVE OR ZERO", buff, bufc);
02499         }
02500 }
02501 
02502 static void fun_asin(char *buff, char **bufc, dbref player, dbref cause,
02503                                          char *fargs[], int nfargs, char *cargs[], int ncargs)
02504 {
02505         double val;
02506 
02507         val = atof(fargs[0]);
02508         if((val < -1) || (val > 1)) {
02509                 safe_str("#-1 ASIN ARGUMENT OUT OF RANGE", buff, bufc);
02510         } else {
02511                 fval(buff, bufc, asin(val));
02512         }
02513 }
02514 
02515 static void fun_acos(char *buff, char **bufc, dbref player, dbref cause,
02516                                          char *fargs[], int nfargs, char *cargs[], int ncargs)
02517 {
02518         double val;
02519 
02520         val = atof(fargs[0]);
02521         if((val < -1) || (val > 1)) {
02522                 safe_str("#-1 ACOS ARGUMENT OUT OF RANGE", buff, bufc);
02523         } else {
02524                 fval(buff, bufc, acos(val));
02525         }
02526 }
02527 
02528 static void fun_atan(char *buff, char **bufc, dbref player, dbref cause,
02529                                          char *fargs[], int nfargs, char *cargs[], int ncargs)
02530 {
02531         fval(buff, bufc, atan(atof(fargs[0])));
02532 }
02533 
02534 static void fun_dist2d(char *buff, char **bufc, dbref player, dbref cause,
02535                                            char *fargs[], int nfargs, char *cargs[], int ncargs)
02536 {
02537         int d;
02538         double r;
02539 
02540         d = atoi(fargs[0]) - atoi(fargs[2]);
02541         r = (double) (d * d);
02542         d = atoi(fargs[1]) - atoi(fargs[3]);
02543         r += (double) (d * d);
02544         d = (int) (sqrt(r) + 0.5);
02545         safe_tprintf_str(buff, bufc, "%d", d);
02546 }
02547 
02548 static void fun_dist3d(char *buff, char **bufc, dbref player, dbref cause,
02549                                            char *fargs[], int nfargs, char *cargs[], int ncargs)
02550 {
02551         int d;
02552         double r;
02553 
02554         d = atoi(fargs[0]) - atoi(fargs[3]);
02555         r = (double) (d * d);
02556         d = atoi(fargs[1]) - atoi(fargs[4]);
02557         r += (double) (d * d);
02558         d = atoi(fargs[2]) - atoi(fargs[5]);
02559         r += (double) (d * d);
02560         d = (int) (sqrt(r) + 0.5);
02561         safe_tprintf_str(buff, bufc, "%d", d);
02562 }
02563 
02564 /*
02565  * ---------------------------------------------------------------------------
02566  * * fun_comp: string compare.
02567  */
02568 
02569 static void fun_comp(char *buff, char **bufc, dbref player, dbref cause,
02570                                          char *fargs[], int nfargs, char *cargs[], int ncargs)
02571 {
02572         int x;
02573 
02574         x = strcmp(fargs[0], fargs[1]);
02575         if(x > 0)
02576                 safe_str("1", buff, bufc);
02577         else if(x < 0)
02578                 safe_str("-1", buff, bufc);
02579         else
02580                 safe_str("0", buff, bufc);
02581 }
02582 
02583 /*
02584  * ---------------------------------------------------------------------------
02585  * * fun_lcon: Return a list of contents.
02586  */
02587 
02588 static void fun_lcon(char *buff, char **bufc, dbref player, dbref cause,
02589                                          char *fargs[], int nfargs, char *cargs[], int ncargs)
02590 {
02591         dbref thing, it;
02592         char *tbuf;
02593         int first = 1;
02594 
02595         it = match_thing(player, fargs[0]);
02596         if((it != NOTHING) && (Has_contents(it)) && (Examinable(player, it) ||
02597                                                                                                  (Location(player) == it)
02598                                                                                                  || (it == cause))) {
02599                 tbuf = alloc_sbuf("fun_lcon");
02600                 DOLIST(thing, Contents(it)) {
02601                         if(!first)
02602                                 sprintf(tbuf, " #%d", thing);
02603                         else {
02604                                 sprintf(tbuf, "#%d", thing);
02605                                 first = 0;
02606                         }
02607                         safe_str(tbuf, buff, bufc);
02608                 }
02609                 free_sbuf(tbuf);
02610         } else
02611                 safe_str("#-1", buff, bufc);
02612 }
02613 
02614 /*
02615  * ---------------------------------------------------------------------------
02616  * * fun_lexits: Return a list of exits.
02617  */
02618 
02619 static void fun_lexits(char *buff, char **bufc, dbref player, dbref cause,
02620                                            char *fargs[], int nfargs, char *cargs[], int ncargs)
02621 {
02622         dbref thing, it, parent;
02623         char *tbuf;
02624         int exam, lev, key;
02625         int first = 1;
02626 
02627         it = match_thing(player, fargs[0]);
02628 
02629         if(!Good_obj(it) || !Has_exits(it)) {
02630                 safe_str("#-1", buff, bufc);
02631                 return;
02632         }
02633         exam = Examinable(player, it);
02634         if(!exam && (where_is(player) != it) && (it != cause)) {
02635                 safe_str("#-1", buff, bufc);
02636                 return;
02637         }
02638         tbuf = alloc_sbuf("fun_lexits");
02639 
02640         /*
02641          * Return info for all parent levels 
02642          */
02643 
02644         ITER_PARENTS(it, parent, lev) {
02645 
02646                 /*
02647                  * Look for exits at each level 
02648                  */
02649 
02650                 if(!Has_exits(parent))
02651                         continue;
02652                 key = 0;
02653                 if(Examinable(player, parent))
02654                         key |= VE_LOC_XAM;
02655                 if(Dark(parent))
02656                         key |= VE_LOC_DARK;
02657                 if(Dark(it))
02658                         key |= VE_BASE_DARK;
02659                 DOLIST(thing, Exits(parent)) {
02660                         if(exit_visible(thing, player, key)) {
02661                                 if(!first)
02662                                         sprintf(tbuf, " #%d", thing);
02663                                 else {
02664                                         sprintf(tbuf, "#%d", thing);
02665                                         first = 0;
02666                                 }
02667                                 safe_str(tbuf, buff, bufc);
02668                         }
02669                 }
02670         }
02671         free_sbuf(tbuf);
02672         return;
02673 }
02674 
02675 /*
02676  * --------------------------------------------------------------------------
02677  * * fun_home: Return an object's home 
02678  */
02679 
02680 static void fun_home(char *buff, char **bufc, dbref player, dbref cause,
02681                                          char *fargs[], int nfargs, char *cargs[], int ncargs)
02682 {
02683         dbref it;
02684 
02685         it = match_thing(player, fargs[0]);
02686         if(!Good_obj(it) || !Examinable(player, it))
02687                 safe_str("#-1", buff, bufc);
02688         else if(Has_home(it))
02689                 safe_tprintf_str(buff, bufc, "#%d", Home(it));
02690         else if(Has_dropto(it))
02691                 safe_tprintf_str(buff, bufc, "#%d", Dropto(it));
02692         else if(isExit(it))
02693                 safe_tprintf_str(buff, bufc, "#%d", where_is(it));
02694         else
02695                 safe_str("#-1", buff, bufc);
02696         return;
02697 }
02698 
02699 /*
02700  * ---------------------------------------------------------------------------
02701  * * fun_money: Return an object's value
02702  */
02703 
02704 static void fun_money(char *buff, char **bufc, dbref player, dbref cause,
02705                                           char *fargs[], int nfargs, char *cargs[], int ncargs)
02706 {
02707         dbref it;
02708 
02709         it = match_thing(player, fargs[0]);
02710         if((it == NOTHING) || !Examinable(player, it))
02711                 safe_str("#-1", buff, bufc);
02712         else
02713                 safe_tprintf_str(buff, bufc, "%d", Pennies(it));
02714 }
02715 
02716 /*
02717  * ---------------------------------------------------------------------------
02718  * * fun_pos: Find a word in a string 
02719  */
02720 
02721 static void fun_pos(char *buff, char **bufc, dbref player, dbref cause,
02722                                         char *fargs[], int nfargs, char *cargs[], int ncargs)
02723 {
02724         int i = 1;
02725         char *s, *t, *u;
02726 
02727         i = 1;
02728         s = fargs[1];
02729         while (*s) {
02730                 u = s;
02731                 t = fargs[0];
02732                 while (*t && *t == *u)
02733                         ++t, ++u;
02734                 if(*t == '\0') {
02735                         safe_tprintf_str(buff, bufc, "%d", i);
02736                         return;
02737                 }
02738                 ++i, ++s;
02739         }
02740         safe_str("#-1", buff, bufc);
02741         return;
02742 }
02743 
02744 /*
02745  * ---------------------------------------------------------------------------
02746  * * ldelete: Remove a word from a string by place
02747  * *  ldelete(<list>,<position>[,<separator>])
02748  * *
02749  * * insert: insert a word into a string by place
02750  * *  insert(<list>,<position>,<new item> [,<separator>])
02751  * *
02752  * * replace: replace a word into a string by place
02753  * *  replace(<list>,<position>,<new item>[,<separator>])
02754  */
02755 
02756 #define IF_DELETE       0
02757 #define IF_REPLACE      1
02758 #define IF_INSERT       2
02759 
02760 static void do_itemfuns(char *buff, char **bufc, char *str, int el,
02761                                                 char *word, char sep, int flag)
02762 {
02763         int ct, overrun;
02764         char *sptr, *iptr, *eptr;
02765         char nullb;
02766 
02767         /*
02768          * If passed a null string return an empty string, except that we * * 
02769          * 
02770          * *  * * are allowed to append to a null string. 
02771          */
02772 
02773         if((!str || !*str) && ((flag != IF_INSERT) || (el != 1))) {
02774                 return;
02775         }
02776         /*
02777          * we can't fiddle with anything before the first position 
02778          */
02779 
02780         if(el < 1) {
02781                 safe_str(str, buff, bufc);
02782                 return;
02783         }
02784         /*
02785          * Split the list up into 'before', 'target', and 'after' chunks * *
02786          * * * pointed to by sptr, iptr, and eptr respectively. 
02787          */
02788 
02789         nullb = '\0';
02790         if(el == 1) {
02791                 /*
02792                  * No 'before' portion, just split off element 1 
02793                  */
02794 
02795                 sptr = NULL;
02796                 if(!str || !*str) {
02797                         eptr = NULL;
02798                         iptr = NULL;
02799                 } else {
02800                         eptr = trim_space_sep(str, sep);
02801                         iptr = split_token(&eptr, sep);
02802                 }
02803         } else {
02804                 /*
02805                  * Break off 'before' portion 
02806                  */
02807 
02808                 sptr = eptr = trim_space_sep(str, sep);
02809                 overrun = 1;
02810                 for(ct = el; ct > 2 && eptr; eptr = next_token(eptr, sep), ct--);
02811                 if(eptr) {
02812                         overrun = 0;
02813                         iptr = split_token(&eptr, sep);
02814                 }
02815                 /*
02816                  * If we didn't make it to the target element, just return *
02817                  * * * * the string.  Insert is allowed to continue if we are 
02818                  * *  * *  * exactly at the end of the string, but replace
02819                  * and * delete *  *  * * are not. 
02820                  */
02821 
02822                 if(!(eptr || ((flag == IF_INSERT) && !overrun))) {
02823                         safe_str(str, buff, bufc);
02824                         return;
02825                 }
02826                 /*
02827                  * Split the 'target' word from the 'after' portion. 
02828                  */
02829 
02830                 if(eptr)
02831                         iptr = split_token(&eptr, sep);
02832                 else
02833                         iptr = NULL;
02834         }
02835 
02836         switch (flag) {
02837         case IF_DELETE:                 /*
02838                                                                  * deletion 
02839                                                                  */
02840                 if(sptr) {
02841                         safe_str(sptr, buff, bufc);
02842                         if(eptr)
02843                                 safe_chr(sep, buff, bufc);
02844                 }
02845                 if(eptr) {
02846                         safe_str(eptr, buff, bufc);
02847                 }
02848                 break;
02849         case IF_REPLACE:                        /*
02850                                                                  * replacing 
02851                                                                  */
02852                 if(sptr) {
02853                         safe_str(sptr, buff, bufc);
02854                         safe_chr(sep, buff, bufc);
02855                 }
02856                 safe_str(word, buff, bufc);
02857                 if(eptr) {
02858                         safe_chr(sep, buff, bufc);
02859                         safe_str(eptr, buff, bufc);
02860                 }
02861                 break;
02862         case IF_INSERT:                 /*
02863                                                                  * insertion 
02864                                                                  */
02865                 if(sptr) {
02866                         safe_str(sptr, buff, bufc);
02867                         safe_chr(sep, buff, bufc);
02868                 }
02869                 safe_str(word, buff, bufc);
02870                 if(iptr) {
02871                         safe_chr(sep, buff, bufc);
02872                         safe_str(iptr, buff, bufc);
02873                 }
02874                 if(eptr) {
02875                         safe_chr(sep, buff, bufc);
02876                         safe_str(eptr, buff, bufc);
02877                 }
02878                 break;
02879         }
02880 }
02881 
02882 static void fun_ldelete(char *buff, char **bufc, dbref player, dbref cause,
02883                                                 char *fargs[], int nfargs, char *cargs[], int ncargs)
02884 {                                                               /*
02885                                                                  * delete a word at position X of a list 
02886                                                                  */
02887         char sep;
02888 
02889         varargs_preamble("LDELETE", 3);
02890         do_itemfuns(buff, bufc, fargs[0], atoi(fargs[1]), NULL, sep, IF_DELETE);
02891 }
02892 
02893 static void fun_replace(char *buff, char **bufc, dbref player, dbref cause,
02894                                                 char *fargs[], int nfargs, char *cargs[], int ncargs)
02895 {                                                               /*
02896                                                                  * replace a word at position X of a list 
02897                                                                  */
02898         char sep;
02899 
02900         varargs_preamble("REPLACE", 4);
02901         do_itemfuns(buff, bufc, fargs[0], atoi(fargs[1]), fargs[2], sep,
02902                                 IF_REPLACE);
02903 }
02904 
02905 static void fun_insert(char *buff, char **bufc, dbref player, dbref cause,
02906                                            char *fargs[], int nfargs, char *cargs[], int ncargs)
02907 {                                                               /*
02908                                                                  * insert a word at position X of a list 
02909                                                                  */
02910         char sep;
02911 
02912         varargs_preamble("INSERT", 4);
02913         do_itemfuns(buff, bufc, fargs[0], atoi(fargs[1]), fargs[2], sep,
02914                                 IF_INSERT);
02915 }
02916 
02917 /*
02918  * ---------------------------------------------------------------------------
02919  * * fun_remove: Remove a word from a string
02920  */
02921 
02922 static void fun_remove(char *buff, char **bufc, dbref player, dbref cause,
02923                                            char *fargs[], int nfargs, char *cargs[], int ncargs)
02924 {
02925         char *s, *sp, *word;
02926         char sep;
02927         int first, found;
02928 
02929         varargs_preamble("REMOVE", 3);
02930         if(index(fargs[1], sep)) {
02931                 safe_str("#-1 CAN ONLY DELETE ONE ELEMENT", buff, bufc);
02932                 return;
02933         }
02934         s = fargs[0];
02935         word = fargs[1];
02936 
02937         /*
02938          * Walk through the string copying words until (if ever) we get to *
02939          * * * * one that matches the target word. 
02940          */
02941 
02942         sp = s;
02943         found = 0;
02944         first = 1;
02945         while (s) {
02946                 sp = split_token(&s, sep);
02947                 if(found || strcmp(sp, word)) {
02948                         if(!first)
02949                                 safe_chr(sep, buff, bufc);
02950                         safe_str(sp, buff, bufc);
02951                         first = 0;
02952                 } else {
02953                         found = 1;
02954                 }
02955         }
02956 }
02957 
02958 /*
02959  * ---------------------------------------------------------------------------
02960  * * fun_member: Is a word in a string
02961  */
02962 
02963 static void fun_member(char *buff, char **bufc, dbref player, dbref cause,
02964                                            char *fargs[], int nfargs, char *cargs[], int ncargs)
02965 {
02966         int wcount;
02967         char *r, *s, sep;
02968 
02969         varargs_preamble("MEMBER", 3);
02970         wcount = 1;
02971         s = trim_space_sep(fargs[0], sep);
02972         do {
02973                 r = split_token(&s, sep);
02974                 if(!strcmp(fargs[1], r)) {
02975                         safe_tprintf_str(buff, bufc, "%d", wcount);
02976                         return;
02977                 }
02978                 wcount++;
02979         } while (s);
02980         safe_str("0", buff, bufc);
02981 }
02982 
02983 /*
02984  * ---------------------------------------------------------------------------
02985  * * fun_secure, fun_escape: escape [, ], %, \, and the beginning of the string.
02986  */
02987 
02988 static void fun_secure(char *buff, char **bufc, dbref player, dbref cause,
02989                                            char *fargs[], int nfargs, char *cargs[], int ncargs)
02990 {
02991         char *s;
02992 
02993         s = fargs[0];
02994         while (*s) {
02995                 switch (*s) {
02996                 case '%':
02997                 case '$':
02998                 case '\\':
02999                 case '[':
03000                 case ']':
03001                 case '(':
03002                 case ')':
03003                 case '{':
03004                 case '}':
03005                 case ',':
03006                 case ';':
03007                         safe_chr(' ', buff, bufc);
03008                         break;
03009                 default:
03010                         safe_chr(*s, buff, bufc);
03011                 }
03012                 s++;
03013         }
03014 }
03015 
03016 static void fun_ansi_secure(char *buff, char **bufc, dbref player,
03017                                                         dbref cause, char *fargs[], int nfargs,
03018                                                         char *cargs[], int ncargs)
03019 {
03020         char *s;
03021 
03022         s = fargs[0];
03023         while (*s) {
03024                 switch (*s) {
03025                 case '\033':
03026                         safe_chr(*s++, buff, bufc);
03027                         if(*s == '[') {
03028                                 safe_chr(*s, buff, bufc);
03029                                 break;
03030                         }                                       /* FALLTHRU */
03031                 case '%':
03032                 case '[':
03033                 case '$':
03034                 case '\\':
03035                 case ']':
03036                 case '(':
03037                 case ')':
03038                 case '{':
03039                 case '}':
03040                 case ',':
03041                 case ';':
03042                         safe_chr(' ', buff, bufc);
03043                         break;
03044                 default:
03045                         safe_chr(*s, buff, bufc);
03046                 }
03047                 s++;
03048         }
03049 }
03050 
03051 static void fun_escape(char *buff, char **bufc, dbref player, dbref cause,
03052                                            char *fargs[], int nfargs, char *cargs[], int ncargs)
03053 {
03054         char *s, *d;
03055 
03056         d = *bufc;
03057         s = fargs[0];
03058         while (*s) {
03059                 switch (*s) {
03060                 case '%':
03061                 case '\\':
03062                 case '[':
03063                 case ']':
03064                 case '{':
03065                 case '}':
03066                 case ';':
03067                         safe_chr('\\', buff, bufc);
03068                 default:
03069                         if(*bufc == d)
03070                                 safe_chr('\\', buff, bufc);
03071                         safe_chr(*s, buff, bufc);
03072                 }
03073                 s++;
03074         }
03075 }
03076 
03077 /*
03078  * Take a character position and return which word that char is in. 
03079  * wordpos(<string>, <charpos>)
03080  */
03081 static void fun_wordpos(char *buff, char **bufc, dbref player, dbref cause,
03082                                                 char *fargs[], int nfargs, char *cargs[], int ncargs)
03083 {
03084         int charpos, i;
03085         char *cp, *tp, *xp, sep;
03086 
03087         varargs_preamble("WORDPOS", 3);
03088 
03089         charpos = atoi(fargs[1]);
03090         cp = fargs[0];
03091         if((charpos > 0) && (charpos <= strlen(cp))) {
03092                 tp = &(cp[charpos - 1]);
03093                 cp = trim_space_sep(cp, sep);
03094                 xp = split_token(&cp, sep);
03095                 for(i = 1; xp; i++) {
03096                         if(tp < (xp + strlen(xp)))
03097                                 break;
03098                         xp = split_token(&cp, sep);
03099                 }
03100                 safe_tprintf_str(buff, bufc, "%d", i);
03101                 return;
03102         }
03103         safe_str("#-1", buff, bufc);
03104         return;
03105 }
03106 
03107 static void fun_type(char *buff, char **bufc, dbref player, dbref cause,
03108                                          char *fargs[], int nfargs, char *cargs[], int ncargs)
03109 {
03110         dbref it;
03111 
03112         it = match_thing(player, fargs[0]);
03113         if(!Good_obj(it)) {
03114                 safe_str("#-1 NOT FOUND", buff, bufc);
03115                 return;
03116         }
03117         switch (Typeof(it)) {
03118         case TYPE_ROOM:
03119                 safe_str("ROOM", buff, bufc);
03120                 break;
03121         case TYPE_EXIT:
03122                 safe_str("EXIT", buff, bufc);
03123                 break;
03124         case TYPE_PLAYER:
03125                 safe_str("PLAYER", buff, bufc);
03126                 break;
03127         case TYPE_THING:
03128                 safe_str("THING", buff, bufc);
03129                 break;
03130         default:
03131                 safe_str("#-1 ILLEGAL TYPE", buff, bufc);
03132         }
03133         return;
03134 }
03135 
03136 static void fun_hasflag(char *buff, char **bufc, dbref player, dbref cause,
03137                                                 char *fargs[], int nfargs, char *cargs[], int ncargs)
03138 {
03139         dbref it;
03140 
03141         it = match_thing(player, fargs[0]);
03142         if(!Good_obj(it)) {
03143                 safe_str("#-1 NOT FOUND", buff, bufc);
03144                 return;
03145         }
03146         if(mudconf.pub_flags || Examinable(player, it) || (it == cause)) {
03147                 if(has_flag(player, it, fargs[1]))
03148                         safe_str("1", buff, bufc);
03149                 else
03150                         safe_str("0", buff, bufc);
03151         } else {
03152                 safe_str("#-1 PERMISSION DENIED", buff, bufc);
03153         }
03154 }
03155 
03156 static void fun_haspower(char *buff, char **bufc, dbref player, dbref cause,
03157                                                  char *fargs[], int nfargs, char *cargs[], int ncargs)
03158 {
03159         dbref it;
03160 
03161         it = match_thing(player, fargs[0]);
03162         if(!Good_obj(it)) {
03163                 safe_str("#-1 NOT FOUND", buff, bufc);
03164                 return;
03165         }
03166         if(mudconf.pub_flags || Examinable(player, it) || (it == cause)) {
03167                 if(has_power(player, it, fargs[1]))
03168                         safe_str("1", buff, bufc);
03169                 else
03170                         safe_str("0", buff, bufc);
03171         } else {
03172                 safe_str("#-1 PERMISSION DENIED", buff, bufc);
03173         }
03174 }
03175 
03176 static void fun_delete(char *buff, char **bufc, dbref player, dbref cause,
03177                                            char *fargs[], int nfargs, char *cargs[], int ncargs)
03178 {
03179         char *s, *temp, *bp;
03180         int i, start, nchars, len;
03181 
03182         s = fargs[0];
03183         start = atoi(fargs[1]);
03184         nchars = atoi(fargs[2]);
03185         len = strlen(s);
03186         if((start >= len) || (nchars <= 0)) {
03187                 safe_str(s, buff, bufc);
03188                 return;
03189         }
03190         bp = temp = alloc_lbuf("fun_delete");
03191         for(i = 0; i < start; i++)
03192                 *bp++ = (*s++);
03193         if((i + nchars) < len && (i + nchars) > 0) {
03194                 s += nchars;
03195                 while ((*bp++ = *s++));
03196         } else
03197                 *bp = '\0';
03198 
03199         safe_str(temp, buff, bufc);
03200         free_lbuf(temp);
03201 }
03202 
03203 static void fun_lock(char *buff, char **bufc, dbref player, dbref cause,
03204                                          char *fargs[], int nfargs, char *cargs[], int ncargs)
03205 {
03206         dbref it, aowner;
03207         int aflags;
03208         char *tbuf;
03209         ATTR *attr;
03210         struct boolexp *bool;
03211 
03212         /*
03213          * Parse the argument into obj + lock 
03214          */
03215 
03216         if(!get_obj_and_lock(player, fargs[0], &it, &attr, buff, bufc))
03217                 return;
03218 
03219         /*
03220          * Get the attribute and decode it if we can read it 
03221          */
03222 
03223         tbuf = atr_get(it, attr->number, &aowner, &aflags);
03224         if(Read_attr(player, it, attr, aowner, aflags)) {
03225                 bool = parse_boolexp(player, tbuf, 1);
03226                 free_lbuf(tbuf);
03227                 tbuf = (char *) unparse_boolexp_function(player, bool);
03228                 free_boolexp(bool);
03229                 safe_str(tbuf, buff, bufc);
03230         } else
03231                 free_lbuf(tbuf);
03232 }
03233 
03234 static void fun_elock(char *buff, char **bufc, dbref player, dbref cause,
03235                                           char *fargs[], int nfargs, char *cargs[], int ncargs)
03236 {
03237         dbref it, victim, aowner;
03238         int aflags;
03239         char *tbuf;
03240         ATTR *attr;
03241         struct boolexp *bool;
03242 
03243         /*
03244          * Parse lock supplier into obj + lock 
03245          */
03246 
03247         if(!get_obj_and_lock(player, fargs[0], &it, &attr, buff, bufc))
03248                 return;
03249 
03250         /*
03251          * Get the victim and ensure we can do it 
03252          */
03253 
03254         victim = match_thing(player, fargs[1]);
03255         if(!Good_obj(victim)) {
03256                 safe_str("#-1 NOT FOUND", buff, bufc);
03257         } else if(!nearby_or_control(player, victim) &&
03258                           !nearby_or_control(player, it)) {
03259                 safe_str("#-1 TOO FAR AWAY", buff, bufc);
03260         } else {
03261                 tbuf = atr_get(it, attr->number, &aowner, &aflags);
03262                 if((attr->number == A_LOCK) ||
03263                    Read_attr(player, it, attr, aowner, aflags)) {
03264                         bool = parse_boolexp(player, tbuf, 1);
03265                         safe_tprintf_str(buff, bufc, "%d", eval_boolexp(victim, it, it,
03266                                                                                                                         bool));
03267                         free_boolexp(bool);
03268                 } else {
03269                         safe_str("0", buff, bufc);
03270                 }
03271                 free_lbuf(tbuf);
03272         }
03273 }
03274 
03275 /*
03276  * ---------------------------------------------------------------------------
03277  * * fun_lwho: Return list of connected users.
03278  */
03279 
03280 static void fun_lwho(char *buff, char **bufc, dbref player, dbref cause,
03281                                          char *fargs[], int nfargs, char *cargs[], int ncargs)
03282 {
03283         make_ulist(player, buff, bufc);
03284 }
03285 
03286 /*
03287  * ---------------------------------------------------------------------------
03288  * * fun_nearby: Return whether or not obj1 is near obj2.
03289  */
03290 
03291 static void fun_nearby(char *buff, char **bufc, dbref player, dbref cause,
03292                                            char *fargs[], int nfargs, char *cargs[], int ncargs)
03293 {
03294         dbref obj1, obj2;
03295 
03296         obj1 = match_thing(player, fargs[0]);
03297         obj2 = match_thing(player, fargs[1]);
03298         if(!(nearby_or_control(player, obj1) || nearby_or_control(player, obj2)))
03299                 safe_str("0", buff, bufc);
03300         else if(nearby(obj1, obj2))
03301                 safe_str("1", buff, bufc);
03302         else
03303                 safe_str("0", buff, bufc);
03304 }
03305 
03306 /*
03307  * ---------------------------------------------------------------------------
03308  * * fun_obj, fun_poss, and fun_subj: perform pronoun sub for object.
03309  */
03310 
03311 static void process_sex(dbref player, char *what, const char *token,
03312                                                 char *buff, char **bufc)
03313 {
03314         dbref it;
03315         char *str;
03316 
03317         it = match_thing(player, what);
03318         if(!Good_obj(it) || (!isPlayer(it) && !nearby_or_control(player, it))) {
03319                 safe_str("#-1 NO MATCH", buff, bufc);
03320         } else {
03321                 str = (char *) token;
03322                 exec(buff, bufc, 0, it, it, 0, &str, (char **) NULL, 0);
03323         }
03324 }
03325 
03326 static void fun_obj(char *buff, char **bufc, dbref player, dbref cause,
03327                                         char *fargs[], int nfargs, char *cargs[], int ncargs)
03328 {
03329         process_sex(player, fargs[0], "%o", buff, bufc);
03330 }
03331 
03332 static void fun_poss(char *buff, char **bufc, dbref player, dbref cause,
03333                                          char *fargs[], int nfargs, char *cargs[], int ncargs)
03334 {
03335         process_sex(player, fargs[0], "%p", buff, bufc);
03336 }
03337 
03338 static void fun_subj(char *buff, char **bufc, dbref player, dbref cause,
03339                                          char *fargs[], int nfargs, char *cargs[], int ncargs)
03340 {
03341         process_sex(player, fargs[0], "%s", buff, bufc);
03342 }
03343 
03344 static void fun_aposs(char *buff, char **bufc, dbref player, dbref cause,
03345                                           char *fargs[], int nfargs, char *cargs[], int ncargs)
03346 {
03347         process_sex(player, fargs[0], "%a", buff, bufc);
03348 }
03349 
03350 /*
03351  * ---------------------------------------------------------------------------
03352  * * fun_mudname: Return the name of the mud.
03353  */
03354 
03355 static void fun_mudname(char *buff, char **bufc, dbref player, dbref cause,
03356                                                 char *fargs[], int nfargs, char *cargs[], int ncargs)
03357 {
03358         safe_str(mudconf.mud_name, buff, bufc);
03359 }
03360 
03361 /*
03362  * ---------------------------------------------------------------------------
03363  * * fun_lcstr, fun_ucstr, fun_capstr: Lowercase, uppercase, or capitalize str.
03364  */
03365 
03366 static void fun_lcstr(char *buff, char **bufc, dbref player, dbref cause,
03367                                           char *fargs[], int nfargs, char *cargs[], int ncargs)
03368 {
03369         char *ap;
03370 
03371         ap = fargs[0];
03372         while (*ap) {
03373                 **bufc = ToLower(*ap);
03374                 ap++;
03375                 (*bufc)++;
03376         }
03377 }
03378 
03379 static void fun_ucstr(char *buff, char **bufc, dbref player, dbref cause,
03380                                           char *fargs[], int nfargs, char *cargs[], int ncargs)
03381 {
03382         char *ap;
03383 
03384         ap = fargs[0];
03385         while (*ap) {
03386                 **bufc = ToUpper(*ap);
03387                 ap++;
03388                 (*bufc)++;
03389         }
03390 }
03391 
03392 static void fun_capstr(char *buff, char **bufc, dbref player, dbref cause,
03393                                            char *fargs[], int nfargs, char *cargs[], int ncargs)
03394 {
03395         char *s;
03396 
03397         s = *bufc;
03398 
03399         safe_str(fargs[0], buff, bufc);
03400         *s = ToUpper(*s);
03401 }
03402 
03403 /*
03404  * ---------------------------------------------------------------------------
03405  * * fun_lnum: Return a list of numbers.
03406  */
03407 
03408 static void fun_lnum(char *buff, char **bufc, dbref player, dbref cause,
03409                                          char *fargs[], int nfargs, char *cargs[], int ncargs)
03410 {
03411         char tbuff[10];
03412         int ctr, limit, llimit = 0, over;
03413 
03414         if(nfargs > 2 || nfargs < 1) {
03415                 safe_str("#-1 TOO FEW ARGUMENTS", buff, bufc);
03416                 return;
03417         }
03418         over = 0;
03419         limit = atoi(fargs[0]);
03420         if(nfargs == 2) {
03421                 llimit = atoi(fargs[0]);
03422                 limit = atoi(fargs[1]) + 1;
03423         } else
03424                 limit = atoi(fargs[0]);
03425         if(limit > 0 && llimit >= 0 && llimit < limit) {
03426                 for(ctr = llimit; ctr < limit && !over; ctr++) {
03427                         {
03428                                 sprintf(tbuff, "%s%d", ctr != llimit ? " " : "", ctr);
03429                                 over = safe_str(tbuff, buff, bufc);
03430                         }
03431                 }
03432         }
03433 }
03434 
03435 /*
03436  * ---------------------------------------------------------------------------
03437  * * fun_lattr: Return list of attributes I can see on the object.
03438  */
03439 
03440 static void fun_lattr(char *buff, char **bufc, dbref player, dbref cause,
03441                                           char *fargs[], int nfargs, char *cargs[], int ncargs)
03442 {
03443         dbref thing;
03444         int ca, first;
03445         ATTR *attr;
03446 
03447         /*
03448          * Check for wildcard matching.  parse_attrib_wild checks for read
03449          * permission, so we don't have to.  Have p_a_w assume the slash-star if
03450          * it is missing.
03451          */
03452 
03453         first = 1;
03454         olist_push();
03455         if(parse_attrib_wild(player, fargs[0], &thing, 0, 0, 1)) {
03456                 for(ca = olist_first(); ca != NOTHING; ca = olist_next()) {
03457                         attr = atr_num(ca);
03458                         if(attr) {
03459                                 if(!first)
03460                                         safe_chr(' ', buff, bufc);
03461                                 first = 0;
03462                                 safe_str((char *) attr->name, buff, bufc);
03463                         }
03464                 }
03465         } else {
03466                 safe_str("#-1 NO MATCH", buff, bufc);
03467         }
03468         olist_pop();
03469         return;
03470 }
03471 
03472 /*
03473  * ---------------------------------------------------------------------------
03474  * * do_reverse, fun_reverse, fun_revwords: Reverse things.
03475  */
03476 
03477 static void do_reverse(char *from, char *to)
03478 {
03479         char *tp;
03480 
03481         tp = to + strlen(from);
03482         *tp-- = '\0';
03483         while (*from) {
03484                 *tp-- = *from++;
03485         }
03486 }
03487 
03488 static void fun_reverse(char *buff, char **bufc, dbref player, dbref cause,
03489                                                 char *fargs[], int nfargs, char *cargs[], int ncargs)
03490 {
03491         do_reverse(fargs[0], *bufc);
03492         *bufc += strlen(fargs[0]);
03493 }
03494 
03495 static void fun_revwords(char *buff, char **bufc, dbref player, dbref cause,
03496                                                  char *fargs[], int nfargs, char *cargs[], int ncargs)
03497 {
03498         char *temp, *tp, *t1, sep;
03499         int first;
03500 
03501         /*
03502          * If we are passed an empty arglist return a null string 
03503          */
03504 
03505         if(nfargs == 0) {
03506                 return;
03507         }
03508         varargs_preamble("REVWORDS", 2);
03509         temp = alloc_lbuf("fun_revwords");
03510 
03511         /*
03512          * Reverse the whole string 
03513          */
03514 
03515         do_reverse(fargs[0], temp);
03516 
03517         /*
03518          * Now individually reverse each word in the string.  This will
03519          * undo the reversing of the words (so the words themselves are
03520          * forwards again. 
03521          */
03522 
03523         tp = temp;
03524         first = 1;
03525         while (tp) {
03526                 if(!first)
03527                         safe_chr(sep, buff, bufc);
03528                 t1 = split_token(&tp, sep);
03529                 do_reverse(t1, *bufc);
03530                 *bufc += strlen(t1);
03531                 first = 0;
03532         }
03533         free_lbuf(temp);
03534 }
03535 
03536 /*
03537  * ---------------------------------------------------------------------------
03538  * * fun_after, fun_before: Return substring after or before a specified string.
03539  */
03540 
03541 static void fun_after(char *buff, char **bufc, dbref player, dbref cause,
03542                                           char *fargs[], int nfargs, char *cargs[], int ncargs)
03543 {
03544         char *bp, *cp, *mp;
03545         int mlen;
03546 
03547         if(nfargs == 0) {
03548                 return;
03549         }
03550         if(!fn_range_check("AFTER", nfargs, 1, 2, buff, bufc))
03551                 return;
03552         bp = fargs[0];
03553         mp = fargs[1];
03554 
03555         /*
03556          * Sanity-check arg1 and arg2 
03557          */
03558 
03559         if(bp == NULL)
03560                 bp = "";
03561         if(mp == NULL)
03562                 mp = " ";
03563         if(!mp || !*mp)
03564                 mp = (char *) " ";
03565         mlen = strlen(mp);
03566         if((mlen == 1) && (*mp == ' '))
03567                 bp = trim_space_sep(bp, ' ');
03568 
03569         /*
03570          * Look for the target string 
03571          */
03572 
03573         while (*bp) {
03574 
03575                 /*
03576                  * Search for the first character in the target string 
03577                  */
03578 
03579                 cp = (char *) index(bp, *mp);
03580                 if(cp == NULL) {
03581 
03582                         /*
03583                          * Not found, return empty string 
03584                          */
03585 
03586                         return;
03587                 }
03588                 /*
03589                  * See if what follows is what we are looking for 
03590                  */
03591 
03592                 if(!strncmp(cp, mp, mlen)) {
03593 
03594                         /*
03595                          * Yup, return what follows 
03596                          */
03597 
03598                         bp = cp + mlen;
03599                         safe_str(bp, buff, bufc);
03600                         return;
03601                 }
03602                 /*
03603                  * Continue search after found first character 
03604                  */
03605 
03606                 bp = cp + 1;
03607         }
03608 
03609         /*
03610          * Ran off the end without finding it 
03611          */
03612 
03613         return;
03614 }
03615 
03616 static void fun_before(char *buff, char **bufc, dbref player, dbref cause,
03617                                            char *fargs[], int nfargs, char *cargs[], int ncargs)
03618 {
03619         char *bp, *cp, *mp, *ip;
03620         int mlen;
03621 
03622         if(nfargs == 0) {
03623                 return;
03624         }
03625         if(!fn_range_check("BEFORE", nfargs, 1, 2, buff, bufc))
03626                 return;
03627 
03628         bp = fargs[0];
03629         mp = fargs[1];
03630 
03631         /*
03632          * Sanity-check arg1 and arg2 
03633          */
03634 
03635         if(bp == NULL)
03636                 bp = "";
03637         if(mp == NULL)
03638                 mp = " ";
03639         if(!mp || !*mp)
03640                 mp = (char *) " ";
03641         mlen = strlen(mp);
03642         if((mlen == 1) && (*mp == ' '))
03643                 bp = trim_space_sep(bp, ' ');
03644         ip = bp;
03645 
03646         /*
03647          * Look for the target string 
03648          */
03649 
03650         while (*bp) {
03651 
03652                 /*
03653                  * Search for the first character in the target string 
03654                  */
03655 
03656                 cp = (char *) index(bp, *mp);
03657                 if(cp == NULL) {
03658 
03659                         /*
03660                          * Not found, return entire string 
03661                          */
03662 
03663                         safe_str(ip, buff, bufc);
03664                         return;
03665                 }
03666                 /*
03667                  * See if what follows is what we are looking for 
03668                  */
03669 
03670                 if(!strncmp(cp, mp, mlen)) {
03671 
03672                         /*
03673                          * Yup, return what follows 
03674                          */
03675 
03676                         *cp = '\0';
03677                         safe_str(ip, buff, bufc);
03678                         return;
03679                 }
03680                 /*
03681                  * Continue search after found first character 
03682                  */
03683 
03684                 bp = cp + 1;
03685         }
03686 
03687         /*
03688          * Ran off the end without finding it 
03689          */
03690 
03691         safe_str(ip, buff, bufc);
03692         return;
03693 }
03694 
03695 /*
03696  * ---------------------------------------------------------------------------
03697  * * fun_max, fun_min: Return maximum (minimum) value.
03698  */
03699 
03700 static void fun_max(char *buff, char **bufc, dbref player, dbref cause,
03701                                         char *fargs[], int nfargs, char *cargs[], int ncargs)
03702 {
03703         int i, j, got_one;
03704         double max;
03705 
03706         max = 0;
03707         for(i = 0, got_one = 0; i < nfargs; i++) {
03708                 if(fargs[i]) {
03709                         j = atof(fargs[i]);
03710                         if(!got_one || (j > max)) {
03711                                 got_one = 1;
03712                                 max = j;
03713                         }
03714                 }
03715         }
03716 
03717         if(!got_one)
03718                 safe_str("#-1 TOO FEW ARGUMENTS", buff, bufc);
03719         else
03720                 fval(buff, bufc, max);
03721         return;
03722 }
03723 
03724 static void fun_min(char *buff, char **bufc, dbref player, dbref cause,
03725                                         char *fargs[], int nfargs, char *cargs[], int ncargs)
03726 {
03727         int i, j, got_one;
03728         double min;
03729 
03730         min = 0;
03731         for(i = 0, got_one = 0; i < nfargs; i++) {
03732                 if(fargs[i]) {
03733                         j = atof(fargs[i]);
03734                         if(!got_one || (j < min)) {
03735                                 got_one = 1;
03736                                 min = j;
03737                         }
03738                 }
03739         }
03740 
03741         if(!got_one) {
03742                 safe_str("#-1 TOO FEW ARGUMENTS", buff, bufc);
03743         } else {
03744                 fval(buff, bufc, min);
03745         }
03746         return;
03747 }
03748 
03749 /*
03750  * ---------------------------------------------------------------------------
03751  * * fun_search: Search the db for things, returning a list of what matches
03752  */
03753 
03754 static void fun_search(char *buff, char **bufc, dbref player, dbref cause,
03755                                            char *fargs[], int nfargs, char *cargs[], int ncargs)
03756 {
03757         dbref thing;
03758         char *bp, *nbuf;
03759         SEARCH searchparm;
03760 
03761         /*
03762          * Set up for the search.  If any errors, abort. 
03763          */
03764 
03765         if(!search_setup(player, fargs[0], &searchparm)) {
03766                 safe_str("#-1 ERROR DURING SEARCH", buff, bufc);
03767                 return;
03768         }
03769         /*
03770          * Do the search and report the results 
03771          */
03772 
03773         olist_push();
03774         search_perform(player, cause, &searchparm);
03775         bp = *bufc;
03776         nbuf = alloc_sbuf("fun_search");
03777         for(thing = olist_first(); thing != NOTHING; thing = olist_next()) {
03778                 if(bp == *bufc)
03779                         sprintf(nbuf, "#%d", thing);
03780                 else
03781                         sprintf(nbuf, " #%d", thing);
03782                 safe_str(nbuf, buff, bufc);
03783         }
03784         free_sbuf(nbuf);
03785         olist_pop();
03786 }
03787 
03788 /*
03789  * ---------------------------------------------------------------------------
03790  * * fun_stats: Get database size statistics.
03791  */
03792 
03793 static void fun_stats(char *buff, char **bufc, dbref player, dbref cause,
03794                                           char *fargs[], int nfargs, char *cargs[], int ncargs)
03795 {
03796         dbref who;
03797         STATS statinfo;
03798 
03799         if((!fargs[0]) || !*fargs[0] || !string_compare(fargs[0], "all")) {
03800                 who = NOTHING;
03801         } else {
03802                 who = lookup_player(player, fargs[0], 1);
03803                 if(who == NOTHING) {
03804                         safe_str("#-1 NOT FOUND", buff, bufc);
03805                         return;
03806                 }
03807         }
03808         if(!get_stats(player, who, &statinfo)) {
03809                 safe_str("#-1 ERROR GETTING STATS", buff, bufc);
03810                 return;
03811         }
03812         safe_tprintf_str(buff, bufc, "%d %d %d %d %d %d", statinfo.s_total,
03813                                          statinfo.s_rooms, statinfo.s_exits, statinfo.s_things,
03814                                          statinfo.s_players, statinfo.s_garbage);
03815 }
03816 
03817 /*
03818  * ---------------------------------------------------------------------------
03819  * * fun_merge:  given two strings and a character, merge the two strings
03820  * *   by replacing characters in string1 that are the same as the given 
03821  * *   character by the corresponding character in string2 (by position).
03822  * *   The strings must be of the same length.
03823  */
03824 
03825 static void fun_merge(char *buff, char **bufc, dbref player, dbref cause,
03826                                           char *fargs[], int nfargs, char *cargs[], int ncargs)
03827 {
03828         char *str, *rep;
03829         char c;
03830 
03831         /*
03832          * do length checks first 
03833          */
03834 
03835         if(strlen(fargs[0]) != strlen(fargs[1])) {
03836                 safe_str("#-1 STRING LENGTHS MUST BE EQUAL", buff, bufc);
03837                 return;
03838         }
03839         if(strlen(fargs[2]) > 1) {
03840                 safe_str("#-1 TOO MANY CHARACTERS", buff, bufc);
03841                 return;
03842         }
03843         /*
03844          * find the character to look for. null character is considered * a * 
03845          * 
03846          * *  * * space 
03847          */
03848 
03849         if(!*fargs[2])
03850                 c = ' ';
03851         else
03852                 c = *fargs[2];
03853 
03854         /*
03855          * walk strings, copy from the appropriate string 
03856          */
03857 
03858         for(str = fargs[0], rep = fargs[1];
03859                 *str && *rep && ((*bufc - buff) < LBUF_SIZE);
03860                 str++, rep++, (*bufc)++) {
03861                 if(*str == c)
03862                         **bufc = *rep;
03863                 else
03864                         **bufc = *str;
03865         }
03866 
03867         /*
03868          * There is no need to check for overflowing the buffer since * both
03869          * * * * strings are LBUF_SIZE or less and the new string cannot be *
03870          * * any * * longer. 
03871          */
03872 
03873         return;
03874 }
03875 
03876 /*
03877  * ---------------------------------------------------------------------------
03878  * * fun_splice: similar to MERGE(), eplaces by word instead of by character.
03879  */
03880 
03881 static void fun_splice(char *buff, char **bufc, dbref player, dbref cause,
03882                                            char *fargs[], int nfargs, char *cargs[], int ncargs)
03883 {
03884         char *p1, *p2, *q1, *q2, sep;
03885         int words, i, first;
03886 
03887         varargs_preamble("SPLICE", 4);
03888 
03889         /*
03890          * length checks 
03891          */
03892 
03893         if(countwords(fargs[2], sep) > 1) {
03894                 safe_str("#-1 TOO MANY WORDS", buff, bufc);
03895                 return;
03896         }
03897         words = countwords(fargs[0], sep);
03898         if(words != countwords(fargs[1], sep)) {
03899                 safe_str("#-1 NUMBER OF WORDS MUST BE EQUAL", buff, bufc);
03900                 return;
03901         }
03902         /*
03903          * loop through the two lists 
03904          */
03905 
03906         p1 = fargs[0];
03907         q1 = fargs[1];
03908         first = 1;
03909         for(i = 0; i < words; i++) {
03910                 p2 = split_token(&p1, sep);
03911                 q2 = split_token(&q1, sep);
03912                 if(!first)
03913                         safe_chr(sep, buff, bufc);
03914                 if(!strcmp(p2, fargs[2]))
03915                         safe_str(q2, buff, bufc);       /*
03916                                                                                  * replace 
03917                                                                                  */
03918                 else
03919                         safe_str(p2, buff, bufc);       /*
03920                                                                                  * copy 
03921                                                                                  */
03922                 first = 0;
03923         }
03924 }
03925 
03926 /*
03927  * ---------------------------------------------------------------------------
03928  * * fun_repeat: repeats a string
03929  */
03930 
03931 static void fun_repeat(char *buff, char **bufc, dbref player, dbref cause,
03932                                            char *fargs[], int nfargs, char *cargs[], int ncargs)
03933 {
03934         int times, i;
03935 
03936         times = atoi(fargs[1]);
03937         if((times < 1) || (fargs[0] == NULL) || (!*fargs[0])) {
03938                 return;
03939         } else if(times == 1) {
03940                 safe_str(fargs[0], buff, bufc);
03941         } else if(strlen(fargs[0]) * times >= (LBUF_SIZE - 1)) {
03942                 safe_str("#-1 STRING TOO LONG", buff, bufc);
03943         } else {
03944                 for(i = 0; i < times; i++)
03945                         safe_str(fargs[0], buff, bufc);
03946         }
03947 }
03948 
03949 /*
03950  * ---------------------------------------------------------------------------
03951  * * fun_iter: Make list from evaluating arg2 with each member of arg1.
03952  * * NOTE: This function expects that its arguments have not been evaluated.
03953  */
03954 
03955 static void fun_iter(char *buff, char **bufc, dbref player, dbref cause,
03956                                          char *fargs[], int nfargs, char *cargs[], int ncargs)
03957 {
03958         char *curr, *objstring, *buff2, *buff3, *cp, *dp, sep, *str;
03959         int first, number = 0;
03960 
03961         evarargs_preamble("ITER", 3);
03962         dp = cp = curr = alloc_lbuf("fun_iter");
03963         str = fargs[0];
03964         exec(curr, &dp, 0, player, cause, EV_STRIP | EV_FCHECK | EV_EVAL, &str,
03965                  cargs, ncargs);
03966         *dp = '\0';
03967         cp = trim_space_sep(cp, sep);
03968         if(!*cp) {
03969                 free_lbuf(curr);
03970                 return;
03971         }
03972         first = 1;
03973         while (cp) {
03974                 if(!first)
03975                         safe_chr(' ', buff, bufc);
03976                 first = 0;
03977                 number++;
03978                 objstring = split_token(&cp, sep);
03979                 buff2 = replace_string(BOUND_VAR, objstring, fargs[1]);
03980                 buff3 = replace_string(LISTPLACE_VAR, tprintf("%d", number), buff2);
03981                 str = buff3;
03982                 exec(buff, bufc, 0, player, cause, EV_STRIP | EV_FCHECK | EV_EVAL,
03983                          &str, cargs, ncargs);
03984                 free_lbuf(buff2);
03985                 free_lbuf(buff3);
03986         }
03987         free_lbuf(curr);
03988 }
03989 
03990 static void fun_list(char *buff, char **bufc, dbref player, dbref cause,
03991                                          char *fargs[], int nfargs, char *cargs[], int ncargs)
03992 {
03993         char *curr, *objstring, *buff2, *buff3, *result, *cp, *dp, *str, sep;
03994         int number = 0;
03995 
03996         evarargs_preamble("LIST", 3);
03997         cp = curr = dp = alloc_lbuf("fun_list");
03998         str = fargs[0];
03999         exec(curr, &dp, 0, player, cause, EV_STRIP | EV_FCHECK | EV_EVAL, &str,
04000                  cargs, ncargs);
04001         cp = trim_space_sep(cp, sep);
04002         if(!*cp) {
04003                 free_lbuf(curr);
04004                 return;
04005         }
04006         while (cp) {
04007                 number++;
04008                 objstring = split_token(&cp, sep);
04009                 buff2 = replace_string(BOUND_VAR, objstring, fargs[1]);
04010                 buff3 = replace_string(LISTPLACE_VAR, tprintf("%d", number), buff2);
04011                 dp = result = alloc_lbuf("fun_list.2");
04012                 str = buff3;
04013                 exec(result, &dp, 0, player, cause, EV_STRIP | EV_FCHECK | EV_EVAL,
04014                          &str, cargs, ncargs);
04015                 *dp = '\0';
04016                 free_lbuf(buff2);
04017                 free_lbuf(buff3);
04018                 notify(cause, result);
04019                 free_lbuf(result);
04020         }
04021         free_lbuf(curr);
04022 }
04023 
04024 /*
04025  * ---------------------------------------------------------------------------
04026  * * fun_fold: iteratively eval an attrib with a list of arguments
04027  * *        and an optional base case.  With no base case, the first list element
04028  * *    is passed as %0 and the second is %1.  The attrib is then evaluated
04029  * *    with these args, the result is then used as %0 and the next arg is
04030  * *    %1 and so it goes as there are elements left in the list.  The
04031  * *    optinal base case gives the user a nice starting point.
04032  * *
04033  * *    > &REP_NUM object=[%0][repeat(%1,%1)]
04034  * *    > say fold(OBJECT/REP_NUM,1 2 3 4 5,->)
04035  * *    You say "->122333444455555"
04036  * *
04037  * *      NOTE: To use added list separator, you must use base case!
04038  */
04039 
04040 static void fun_fold(char *buff, char **bufc, dbref player, dbref cause,
04041                                          char *fargs[], int nfargs, char *cargs[], int ncargs)
04042 {
04043         dbref aowner, thing;
04044         int aflags, anum;
04045         ATTR *ap;
04046         char *atext, *result, *curr, *bp, *str, *cp, *atextbuf, *clist[2],
04047                 *rstore, sep;
04048 
04049         /*
04050          * We need two to four arguements only 
04051          */
04052 
04053         mvarargs_preamble("FOLD", 2, 4);
04054 
04055         /*
04056          * Two possibilities for the first arg: <obj>/<attr> and <attr>. 
04057          */
04058 
04059         if(parse_attrib(player, fargs[0], &thing, &anum)) {
04060                 if((anum == NOTHING) || (!Good_obj(thing)))
04061                         ap = NULL;
04062                 else
04063                         ap = atr_num(anum);
04064         } else {
04065                 thing = player;
04066                 ap = atr_str(fargs[0]);
04067         }
04068 
04069         /*
04070          * Make sure we got a good attribute 
04071          */
04072 
04073         if(!ap) {
04074                 return;
04075         }
04076         /*
04077          * Use it if we can access it, otherwise return an error. 
04078          */
04079 
04080         atext = atr_pget(thing, ap->number, &aowner, &aflags);
04081         if(!atext) {
04082                 return;
04083         } else if(!*atext || !See_attr(player, thing, ap, aowner, aflags)) {
04084                 free_lbuf(atext);
04085                 return;
04086         }
04087         /*
04088          * Evaluate it using the rest of the passed function args 
04089          */
04090 
04091         cp = curr = fargs[1];
04092         atextbuf = alloc_lbuf("fun_fold");
04093         StringCopy(atextbuf, atext);
04094 
04095         /*
04096          * may as well handle first case now 
04097          */
04098 
04099         if((nfargs >= 3) && (fargs[2])) {
04100                 clist[0] = fargs[2];
04101                 clist[1] = split_token(&cp, sep);
04102                 result = bp = alloc_lbuf("fun_fold");
04103                 str = atextbuf;
04104                 exec(result, &bp, 0, player, cause, EV_STRIP | EV_FCHECK | EV_EVAL,
04105                          &str, clist, 2);
04106                 *bp = '\0';
04107         } else {
04108                 clist[0] = split_token(&cp, sep);
04109                 clist[1] = split_token(&cp, sep);
04110                 result = bp = alloc_lbuf("fun_fold");
04111                 str = atextbuf;
04112                 exec(result, &bp, 0, player, cause, EV_STRIP | EV_FCHECK | EV_EVAL,
04113                          &str, clist, 2);
04114                 *bp = '\0';
04115         }
04116 
04117         rstore = result;
04118         result = NULL;
04119 
04120         while (cp) {
04121                 clist[0] = rstore;
04122                 clist[1] = split_token(&cp, sep);
04123                 StringCopy(atextbuf, atext);
04124                 result = bp = alloc_lbuf("fun_fold");
04125                 str = atextbuf;
04126                 exec(result, &bp, 0, player, cause, EV_STRIP | EV_FCHECK | EV_EVAL,
04127                          &str, clist, 2);
04128                 *bp = '\0';
04129                 StringCopy(rstore, result);
04130                 free_lbuf(result);
04131         }
04132         safe_str(rstore, buff, bufc);
04133         free_lbuf(rstore);
04134         free_lbuf(atext);
04135         free_lbuf(atextbuf);
04136 }
04137 
04138 /*
04139  * ---------------------------------------------------------------------------
04140  * * fun_filter: iteratively perform a function with a list of arguments
04141  * *              and return the arg, if the function evaluates to TRUE using the 
04142  * *      arg.
04143  * *
04144  * *      > &IS_ODD object=mod(%0,2)
04145  * *      > say filter(object/is_odd,1 2 3 4 5)
04146  * *      You say "1 3 5"
04147  * *      > say filter(object/is_odd,1-2-3-4-5,-)
04148  * *      You say "1-3-5"
04149  * *
04150  * *  NOTE:  If you specify a separator it is used to delimit returned list
04151  */
04152 
04153 static void fun_filter(char *buff, char **bufc, dbref player, dbref cause,
04154                                            char *fargs[], int nfargs, char *cargs[], int ncargs)
04155 {
04156         dbref aowner, thing;
04157         int aflags, anum, first;
04158         ATTR *ap;
04159         char *atext, *result, *curr, *objstring, *bp, *str, *cp, *atextbuf, sep;
04160 
04161         varargs_preamble("FILTER", 3);
04162 
04163         /*
04164          * Two possibilities for the first arg: <obj>/<attr> and <attr>. 
04165          */
04166 
04167         if(parse_attrib(player, fargs[0], &thing, &anum)) {
04168                 if((anum == NOTHING) || (!Good_obj(thing)))
04169                         ap = NULL;
04170                 else
04171                         ap = atr_num(anum);
04172         } else {
04173                 thing = player;
04174                 ap = atr_str(fargs[0]);
04175         }
04176 
04177         /*
04178          * Make sure we got a good attribute 
04179          */
04180 
04181         if(!ap) {
04182                 return;
04183         }
04184         /*
04185          * Use it if we can access it, otherwise return an error. 
04186          */
04187 
04188         atext = atr_pget(thing, ap->number, &aowner, &aflags);
04189         if(!atext) {
04190                 return;
04191         } else if(!*atext || !See_attr(player, thing, ap, aowner, aflags)) {
04192                 free_lbuf(atext);
04193                 return;
04194         }
04195         /*
04196          * Now iteratively eval the attrib with the argument list 
04197          */
04198 
04199         cp = curr = trim_space_sep(fargs[1], sep);
04200         atextbuf = alloc_lbuf("fun_filter");
04201         first = 1;
04202         while (cp) {
04203                 objstring = split_token(&cp, sep);
04204                 StringCopy(atextbuf, atext);
04205                 result = bp = alloc_lbuf("fun_filter");
04206                 str = atextbuf;
04207                 exec(result, &bp, 0, player, cause, EV_STRIP | EV_FCHECK | EV_EVAL,
04208                          &str, &objstring, 1);
04209                 *bp = '\0';
04210                 if(!first && *result == '1')
04211                         safe_chr(sep, buff, bufc);
04212                 if(*result == '1') {
04213                         safe_str(objstring, buff, bufc);
04214                         first = 0;
04215                 }
04216                 free_lbuf(result);
04217         }
04218         free_lbuf(atext);
04219         free_lbuf(atextbuf);
04220 }
04221 
04222 /*
04223  * ---------------------------------------------------------------------------
04224  * * fun_map: iteratively evaluate an attribute with a list of arguments.
04225  * *
04226  * *  > &DIV_TWO object=fdiv(%0,2)
04227  * *  > say map(1 2 3 4 5,object/div_two)
04228  * *  You say "0.5 1 1.5 2 2.5"
04229  * *  > say map(object/div_two,1-2-3-4-5,-)
04230  * *  You say "0.5-1-1.5-2-2.5"
04231  * *
04232  */
04233 
04234 static void fun_map(char *buff, char **bufc, dbref player, dbref cause,
04235                                         char *fargs[], int nfargs, char *cargs[], int ncargs)
04236 {
04237         dbref aowner, thing;
04238         int aflags, anum, first;
04239         ATTR *ap;
04240         char *atext, *objstring, *str, *cp, *atextbuf, sep;
04241 
04242         varargs_preamble("MAP", 3);
04243 
04244         /*
04245          * Two possibilities for the second arg: <obj>/<attr> and <attr>. 
04246          */
04247 
04248         if(parse_attrib(player, fargs[0], &thing, &anum)) {
04249                 if((anum == NOTHING) || (!Good_obj(thing)))
04250                         ap = NULL;
04251                 else
04252                         ap = atr_num(anum);
04253         } else {
04254                 thing = player;
04255                 ap = atr_str(fargs[0]);
04256         }
04257 
04258         /*
04259          * Make sure we got a good attribute 
04260          */
04261 
04262         if(!ap) {
04263                 return;
04264         }
04265         /*
04266          * Use it if we can access it, otherwise return an error. 
04267          */
04268 
04269         atext = atr_pget(thing, ap->number, &aowner, &aflags);
04270         if(!atext) {
04271                 return;
04272         } else if(!*atext || !See_attr(player, thing, ap, aowner, aflags)) {
04273                 free_lbuf(atext);
04274                 return;
04275         }
04276         /*
04277          * now process the list one element at a time 
04278          */
04279 
04280         cp = trim_space_sep(fargs[1], sep);
04281         atextbuf = alloc_lbuf("fun_map");
04282         first = 1;
04283         while (cp) {
04284                 if(!first)
04285                         safe_chr(sep, buff, bufc);
04286                 first = 0;
04287                 objstring = split_token(&cp, sep);
04288                 StringCopy(atextbuf, atext);
04289                 str = atextbuf;
04290                 exec(buff, bufc, 0, player, cause, EV_STRIP | EV_FCHECK | EV_EVAL,
04291                          &str, &objstring, 1);
04292         }
04293         free_lbuf(atext);
04294         free_lbuf(atextbuf);
04295 }
04296 
04297 /*
04298  * ---------------------------------------------------------------------------
04299  * * fun_edit: Edit text.
04300  */
04301 
04302 static void fun_edit(char *buff, char **bufc, dbref player, dbref cause,
04303                                          char *fargs[], int nfargs, char *cargs[], int ncargs)
04304 {
04305         char *tstr;
04306         char new[LBUF_SIZE];
04307         
04308         strncpy(new, fargs[0], LBUF_SIZE-1);
04309         edit_string((char *) strip_ansi_r(new,fargs[0],strlen(fargs[0])), &tstr, fargs[1], fargs[2]);
04310         safe_str(tstr, buff, bufc);
04311         free_lbuf(tstr);
04312 }
04313 
04314 /*
04315  * ---------------------------------------------------------------------------
04316  * * fun_locate: Search for things with the perspective of another obj.
04317  */
04318 
04319 static void fun_locate(char *buff, char **bufc, dbref player, dbref cause,
04320                                            char *fargs[], int nfargs, char *cargs[], int ncargs)
04321 {
04322         int pref_type, check_locks, verbose, multiple;
04323         dbref thing, what;
04324         char *cp;
04325 
04326         pref_type = NOTYPE;
04327         check_locks = verbose = multiple = 0;
04328 
04329         /*
04330          * Find the thing to do the looking, make sure we control it. 
04331          */
04332 
04333         if(See_All(player))
04334                 thing = match_thing(player, fargs[0]);
04335         else
04336                 thing = match_controlled(player, fargs[0]);
04337         if(!Good_obj(thing)) {
04338                 safe_str("#-1 PERMISSION DENIED", buff, bufc);
04339                 return;
04340         }
04341         /*
04342          * Get pre- and post-conditions and modifiers 
04343          */
04344 
04345         for(cp = fargs[2]; *cp; cp++) {
04346                 switch (*cp) {
04347                 case 'E':
04348                         pref_type = TYPE_EXIT;
04349                         break;
04350                 case 'L':
04351                         check_locks = 1;
04352                         break;
04353                 case 'P':
04354                         pref_type = TYPE_PLAYER;
04355                         break;
04356                 case 'R':
04357                         pref_type = TYPE_ROOM;
04358                         break;
04359                 case 'T':
04360                         pref_type = TYPE_THING;
04361                         break;
04362                 case 'V':
04363                         verbose = 1;
04364                         break;
04365                 case 'X':
04366                         multiple = 1;
04367                         break;
04368                 }
04369         }
04370 
04371         /*
04372          * Set up for the search 
04373          */
04374 
04375         if(check_locks)
04376                 init_match_check_keys(thing, fargs[1], pref_type);
04377         else
04378                 init_match(thing, fargs[1], pref_type);
04379 
04380         /*
04381          * Search for each requested thing 
04382          */
04383 
04384         for(cp = fargs[2]; *cp; cp++) {
04385                 switch (*cp) {
04386                 case 'a':
04387                         match_absolute();
04388                         break;
04389                 case 'c':
04390                         match_carried_exit_with_parents();
04391                         break;
04392                 case 'e':
04393                         match_exit_with_parents();
04394                         break;
04395                 case 'h':
04396                         match_here();
04397                         break;
04398                 case 'i':
04399                         match_possession();
04400                         break;
04401                 case 'm':
04402                         match_me();
04403                         break;
04404                 case 'n':
04405                         match_neighbor();
04406                         break;
04407                 case 'p':
04408                         match_player();
04409                         break;
04410                 case '*':
04411                         match_everything(MAT_EXIT_PARENTS);
04412                         break;
04413                 }
04414         }
04415 
04416         /*
04417          * Get the result and return it to the caller 
04418          */
04419 
04420         if(multiple)
04421                 what = last_match_result();
04422         else
04423                 what = match_result();
04424 
04425         if(verbose)
04426                 (void) match_status(player, what);
04427 
04428         safe_tprintf_str(buff, bufc, "#%d", what);
04429 }
04430 
04431 /*
04432  * ---------------------------------------------------------------------------
04433  * * fun_switch: Return value based on pattern matching (ala @switch)
04434  * * NOTE: This function expects that its arguments have not been evaluated.
04435  */
04436 
04437 static void fun_switch(char *buff, char **bufc, dbref player, dbref cause,
04438                                            char *fargs[], int nfargs, char *cargs[], int ncargs)
04439 {
04440         int i;
04441         char *mbuff, *tbuff, *buf, *bp, *str;
04442 
04443         /*
04444          * If we don't have at least 2 args, return nothing 
04445          */
04446 
04447         if(nfargs < 2) {
04448                 return;
04449         }
04450         /*
04451          * Evaluate the target in fargs[0] 
04452          */
04453 
04454         mbuff = bp = alloc_lbuf("fun_switch");
04455         str = fargs[0];
04456         exec(mbuff, &bp, 0, player, cause, EV_STRIP | EV_FCHECK | EV_EVAL,
04457                  &str, cargs, ncargs);
04458         *bp = '\0';
04459 
04460         /*
04461          * Loop through the patterns looking for a match 
04462          */
04463 
04464         for(i = 1; (i < nfargs - 1) && fargs[i] && fargs[i + 1]; i += 2) {
04465                 tbuff = bp = alloc_lbuf("fun_switch.2");
04466                 str = fargs[i];
04467                 exec(tbuff, &bp, 0, player, cause, EV_STRIP | EV_FCHECK | EV_EVAL,
04468                          &str, cargs, ncargs);
04469                 *bp = '\0';
04470                 if(quick_wild(tbuff, mbuff)) {
04471                         free_lbuf(tbuff);
04472                         buf = alloc_lbuf("fun_switch");
04473                         StringCopy(buf, fargs[i + 1]);
04474                         str = buf;
04475                         exec(buff, bufc, 0, player, cause,
04476                                  EV_STRIP | EV_FCHECK | EV_EVAL, &str, cargs, ncargs);
04477                         free_lbuf(buf);
04478                         free_lbuf(mbuff);
04479                         return;
04480                 }
04481                 free_lbuf(tbuff);
04482         }
04483         free_lbuf(mbuff);
04484 
04485         /*
04486          * Nope, return the default if there is one 
04487          */
04488 
04489         if((i < nfargs) && fargs[i]) {
04490                 buf = alloc_lbuf("fun_switch");
04491                 StringCopy(buf, fargs[i]);
04492                 str = buf;
04493                 exec(buff, bufc, 0, player, cause, EV_STRIP | EV_FCHECK | EV_EVAL,
04494                          &str, cargs, ncargs);
04495                 free_lbuf(buf);
04496         }
04497         return;
04498 }
04499 
04500 static void fun_case(char *buff, char **bufc, dbref player, dbref cause,
04501                                          char *fargs[], int nfargs, char *cargs[], int ncargs)
04502 {
04503         int i;
04504         char *mbuff, *buf, *bp, *str;
04505 
04506         /*
04507          * If we don't have at least 2 args, return nothing 
04508          */
04509 
04510         if(nfargs < 2) {
04511                 return;
04512         }
04513         /*
04514          * Evaluate the target in fargs[0] 
04515          */
04516 
04517         mbuff = bp = alloc_lbuf("fun_switch");
04518         str = fargs[0];
04519         exec(mbuff, &bp, 0, player, cause, EV_STRIP | EV_FCHECK | EV_EVAL,
04520                  &str, cargs, ncargs);
04521         *bp = '\0';
04522 
04523         /*
04524          * Loop through the patterns looking for a match 
04525          */
04526 
04527         for(i = 1; (i < nfargs - 1) && fargs[i] && fargs[i + 1]; i += 2) {
04528                 if(*fargs[i] == *mbuff) {
04529                         buf = alloc_lbuf("fun_switch");
04530                         StringCopy(buf, fargs[i + 1]);
04531                         str = buf;
04532                         exec(buff, bufc, 0, player, cause,
04533                                  EV_STRIP | EV_FCHECK | EV_EVAL, &str, cargs, ncargs);
04534                         free_lbuf(buf);
04535                         free_lbuf(mbuff);
04536                         return;
04537                 }
04538         }
04539         free_lbuf(mbuff);
04540 
04541         /*
04542          * Nope, return the default if there is one 
04543          */
04544 
04545         if((i < nfargs) && fargs[i]) {
04546                 buf = alloc_lbuf("fun_switch");
04547                 StringCopy(buf, fargs[i]);
04548                 str = buf;
04549                 exec(buff, bufc, 0, player, cause, EV_STRIP | EV_FCHECK | EV_EVAL,
04550                          &str, cargs, ncargs);
04551                 free_lbuf(buf);
04552         }
04553         return;
04554 }
04555 
04556 /*
04557  * ---------------------------------------------------------------------------
04558  * * fun_space: Make spaces.
04559  */
04560 
04561 static void fun_space(char *buff, char **bufc, dbref player, dbref cause,
04562                                           char *fargs[], int nfargs, char *cargs[], int ncargs)
04563 {
04564         int num;
04565         char *cp;
04566 
04567         if(!fargs[0] || !(*fargs[0])) {
04568                 num = 1;
04569         } else {
04570                 num = atoi(fargs[0]);
04571         }
04572 
04573         if(num < 1) {
04574 
04575                 /*
04576                  * If negative or zero spaces return a single space,  * * * * 
04577                  * -except- allow 'space(0)' to return "" for calculated * *
04578                  * * * padding 
04579                  */
04580 
04581                 if(!is_integer(fargs[0]) || (num != 0)) {
04582                         num = 1;
04583                 }
04584         } else if(num >= LBUF_SIZE) {
04585                 num = LBUF_SIZE - 1;
04586         }
04587         for(cp = *bufc; num > 0; num--)
04588                 *cp++ = ' ';
04589         *bufc = cp;
04590         return;
04591 }
04592 
04593 /*
04594  * ---------------------------------------------------------------------------
04595  * * fun_idle, fun_conn: return seconds idle or connected.
04596  */
04597 
04598 static void fun_idle(char *buff, char **bufc, dbref player, dbref cause,
04599                                          char *fargs[], int nfargs, char *cargs[], int ncargs)
04600 {
04601         dbref target;
04602 
04603         target = lookup_player(player, fargs[0], 1);
04604         if(Good_obj(target) && Dark(target) && !Wizard(player))
04605                 target = NOTHING;
04606         safe_tprintf_str(buff, bufc, "%d", fetch_idle(target));
04607 }
04608 
04609 static void fun_conn(char *buff, char **bufc, dbref player, dbref cause,
04610                                          char *fargs[], int nfargs, char *cargs[], int ncargs)
04611 {
04612         dbref target;
04613 
04614         target = lookup_player(player, fargs[0], 1);
04615         if(Good_obj(target) && Dark(target) && !Wizard(player))
04616                 target = NOTHING;
04617         safe_tprintf_str(buff, bufc, "%d", fetch_connect(target));
04618 }
04619 
04620 /*
04621  * ---------------------------------------------------------------------------
04622  * * fun_sort: Sort lists.
04623  */
04624 
04625 typedef struct f_record f_rec;
04626 typedef struct i_record i_rec;
04627 
04628 struct f_record {
04629         double data;
04630         char *str;
04631 };
04632 
04633 struct i_record {
04634         long data;
04635         char *str;
04636 };
04637 
04638 static int a_comp(const void *s1, const void *s2)
04639 {
04640         return strcmp(*(char **) s1, *(char **) s2);
04641 }
04642 
04643 static int f_comp(const void *s1, const void *s2)
04644 {
04645         if(((f_rec *) s1)->data > ((f_rec *) s2)->data)
04646                 return 1;
04647         if(((f_rec *) s1)->data < ((f_rec *) s2)->data)
04648                 return -1;
04649         return 0;
04650 }
04651 
04652 static int i_comp(const void *s1, const void *s2)
04653 {
04654         if(((i_rec *) s1)->data > ((i_rec *) s2)->data)
04655                 return 1;
04656         if(((i_rec *) s1)->data < ((i_rec *) s2)->data)
04657                 return -1;
04658         return 0;
04659 }
04660 
04661 static void do_asort(char *s[], int n, int sort_type)
04662 {
04663         int i;
04664         f_rec *fp;
04665         i_rec *ip;
04666 
04667         switch (sort_type) {
04668         case ALPHANUM_LIST:
04669                 qsort((void *) s, n, sizeof(char *), a_comp);
04670 
04671                 break;
04672         case NUMERIC_LIST:
04673                 ip = (i_rec *) malloc(n * sizeof(i_rec));
04674                 for(i = 0; i < n; i++) {
04675                         ip[i].str = s[i];
04676                         ip[i].data = atoi(s[i]);
04677                 }
04678                 qsort((void *) ip, n, sizeof(i_rec), i_comp);
04679                 for(i = 0; i < n; i++) {
04680                         s[i] = ip[i].str;
04681                 }
04682                 free(ip);
04683                 break;
04684         case DBREF_LIST:
04685                 ip = (i_rec *) malloc(n * sizeof(i_rec));
04686                 for(i = 0; i < n; i++) {
04687                         ip[i].str = s[i];
04688                         ip[i].data = dbnum(s[i]);
04689                 }
04690                 qsort((void *) ip, n, sizeof(i_rec), i_comp);
04691                 for(i = 0; i < n; i++) {
04692                         s[i] = ip[i].str;
04693                 }
04694                 free(ip);
04695                 break;
04696         case FLOAT_LIST:
04697                 fp = (f_rec *) malloc(n * sizeof(f_rec));
04698                 for(i = 0; i < n; i++) {
04699                         fp[i].str = s[i];
04700                         fp[i].data = atof(s[i]);
04701                 }
04702                 qsort((void *) fp, n, sizeof(f_rec), f_comp);
04703                 for(i = 0; i < n; i++) {
04704                         s[i] = fp[i].str;
04705                 }
04706                 free(fp);
04707                 break;
04708         }
04709 }
04710 
04711 static void fun_sort(char *buff, char **bufc, dbref player, dbref cause,
04712                                          char *fargs[], int nfargs, char *cargs[], int ncargs)
04713 {
04714         int nitems, sort_type;
04715         char *list, sep;
04716         char *ptrs[LBUF_SIZE / 2];
04717 
04718         /*
04719          * If we are passed an empty arglist return a null string 
04720          */
04721 
04722         if(nfargs == 0) {
04723                 return;
04724         }
04725         mvarargs_preamble("SORT", 1, 3);
04726 
04727         /*
04728          * Convert the list to an array 
04729          */
04730 
04731         list = alloc_lbuf("fun_sort");
04732         StringCopy(list, fargs[0]);
04733         nitems = list2arr(ptrs, LBUF_SIZE / 2, list, sep);
04734         sort_type = get_list_type(fargs, nfargs, 2, ptrs, nitems);
04735         do_asort(ptrs, nitems, sort_type);
04736         arr2list(ptrs, nitems, buff, bufc, sep);
04737         free_lbuf(list);
04738 }
04739 
04740 /*
04741  * ---------------------------------------------------------------------------
04742  * * fun_setunion, fun_setdiff, fun_setinter: Set management.
04743  */
04744 
04745 #define SET_UNION       1
04746 #define SET_INTERSECT   2
04747 #define SET_DIFF        3
04748 
04749 static void handle_sets(char *fargs[], char *buff, char **bufc,
04750                                                 int oper, char sep)
04751 {
04752         char *list1, *list2, *oldp;
04753         char *ptrs1[LBUF_SIZE], *ptrs2[LBUF_SIZE];
04754         int i1, i2, n1, n2, val, first;
04755 
04756         list1 = alloc_lbuf("fun_setunion.1");
04757         StringCopy(list1, fargs[0]);
04758         n1 = list2arr(ptrs1, LBUF_SIZE, list1, sep);
04759         do_asort(ptrs1, n1, ALPHANUM_LIST);
04760 
04761         list2 = alloc_lbuf("fun_setunion.2");
04762         StringCopy(list2, fargs[1]);
04763         n2 = list2arr(ptrs2, LBUF_SIZE, list2, sep);
04764         do_asort(ptrs2, n2, ALPHANUM_LIST);
04765 
04766         i1 = i2 = 0;
04767         first = 1;
04768         oldp = *bufc;
04769         **bufc = '\0';
04770 
04771         switch (oper) {
04772         case SET_UNION:                 /*
04773                                                                  * Copy elements common to both lists 
04774                                                                  */
04775 
04776                 /*
04777                  * Handle case of two identical single-element lists 
04778                  */
04779 
04780                 if((n1 == 1) && (n2 == 1) && (!strcmp(ptrs1[0], ptrs2[0]))) {
04781                         safe_str(ptrs1[0], buff, bufc);
04782                         break;
04783                 }
04784                 /*
04785                  * Process until one list is empty 
04786                  */
04787 
04788                 while ((i1 < n1) && (i2 < n2)) {
04789 
04790                         /*
04791                          * Skip over duplicates 
04792                          */
04793 
04794                         if((i1 > 0) || (i2 > 0)) {
04795                                 while ((i1 < n1) && !strcmp(ptrs1[i1], oldp))
04796                                         i1++;
04797                                 while ((i2 < n2) && !strcmp(ptrs2[i2], oldp))
04798                                         i2++;
04799                         }
04800                         /*
04801                          * Compare and copy 
04802                          */
04803 
04804                         if((i1 < n1) && (i2 < n2)) {
04805                                 if(!first)
04806                                         safe_chr(sep, buff, bufc);
04807                                 first = 0;
04808                                 oldp = *bufc;
04809                                 if(strcmp(ptrs1[i1], ptrs2[i2]) < 0) {
04810                                         safe_str(ptrs1[i1], buff, bufc);
04811                                         i1++;
04812                                 } else {
04813                                         safe_str(ptrs2[i2], buff, bufc);
04814                                         i2++;
04815                                 }
04816                                 **bufc = '\0';
04817                         }
04818                 }
04819 
04820                 /*
04821                  * Copy rest of remaining list, stripping duplicates 
04822                  */
04823 
04824                 for(; i1 < n1; i1++) {
04825                         if(strcmp(oldp, ptrs1[i1])) {
04826                                 if(!first)
04827                                         safe_chr(sep, buff, bufc);
04828                                 first = 0;
04829                                 oldp = *bufc;
04830                                 safe_str(ptrs1[i1], buff, bufc);
04831                                 **bufc = '\0';
04832                         }
04833                 }
04834                 for(; i2 < n2; i2++) {
04835                         if(strcmp(oldp, ptrs2[i2])) {
04836                                 if(!first)
04837                                         safe_chr(sep, buff, bufc);
04838                                 first = 0;
04839                                 oldp = *bufc;
04840                                 safe_str(ptrs2[i2], buff, bufc);
04841                                 **bufc = '\0';
04842                         }
04843                 }
04844                 break;
04845         case SET_INTERSECT:             /*
04846                                                                  * Copy elements not in both lists 
04847                                                                  */
04848 
04849                 while ((i1 < n1) && (i2 < n2)) {
04850                         val = strcmp(ptrs1[i1], ptrs2[i2]);
04851                         if(!val) {
04852 
04853                                 /*
04854                                  * Got a match, copy it 
04855                                  */
04856 
04857                                 if(!first)
04858                                         safe_chr(sep, buff, bufc);
04859                                 first = 0;
04860                                 oldp = *bufc;
04861                                 safe_str(ptrs1[i1], buff, bufc);
04862                                 i1++;
04863                                 i2++;
04864                                 while ((i1 < n1) && !strcmp(ptrs1[i1], oldp))
04865                                         i1++;
04866                                 while ((i2 < n2) && !strcmp(ptrs2[i2], oldp))
04867                                         i2++;
04868                         } else if(val < 0) {
04869                                 i1++;
04870                         } else {
04871                                 i2++;
04872                         }
04873                 }
04874                 break;
04875         case SET_DIFF:                          /*
04876                                                                  * Copy elements unique to list1 
04877                                                                  */
04878 
04879                 while ((i1 < n1) && (i2 < n2)) {
04880                         val = strcmp(ptrs1[i1], ptrs2[i2]);
04881                         if(!val) {
04882 
04883                                 /*
04884                                  * Got a match, increment pointers 
04885                                  */
04886 
04887                                 oldp = ptrs1[i1];
04888                                 while ((i1 < n1) && !strcmp(ptrs1[i1], oldp))
04889                                         i1++;
04890                                 while ((i2 < n2) && !strcmp(ptrs2[i2], oldp))
04891                                         i2++;
04892                         } else if(val < 0) {
04893 
04894                                 /*
04895                                  * Item in list1 not in list2, copy 
04896                                  */
04897 
04898                                 if(!first)
04899                                         safe_chr(sep, buff, bufc);
04900                                 first = 0;
04901                                 safe_str(ptrs1[i1], buff, bufc);
04902                                 oldp = ptrs1[i1];
04903                                 i1++;
04904                                 while ((i1 < n1) && !strcmp(ptrs1[i1], oldp))
04905                                         i1++;
04906                         } else {
04907 
04908                                 /*
04909                                  * Item in list2 but not in list1, discard 
04910                                  */
04911 
04912                                 oldp = ptrs2[i2];
04913                                 i2++;
04914                                 while ((i2 < n2) && !strcmp(ptrs2[i2], oldp))
04915                                         i2++;
04916                         }
04917                 }
04918 
04919                 /*
04920                  * Copy remainder of list1 
04921                  */
04922 
04923                 while (i1 < n1) {
04924                         if(!first)
04925                                 safe_chr(sep, buff, bufc);
04926                         first = 0;
04927                         safe_str(ptrs1[i1], buff, bufc);
04928                         oldp = ptrs1[i1];
04929                         i1++;
04930                         while ((i1 < n1) && !strcmp(ptrs1[i1], oldp))
04931                                 i1++;
04932                 }
04933         }
04934         free_lbuf(list1);
04935         free_lbuf(list2);
04936         return;
04937 }
04938 
04939 static void fun_setunion(char *buff, char **bufc, dbref player, dbref cause,
04940                                                  char *fargs[], int nfargs, char *cargs[], int ncargs)
04941 {
04942         char sep;
04943 
04944         varargs_preamble("SETUNION", 3);
04945         handle_sets(fargs, buff, bufc, SET_UNION, sep);
04946         return;
04947 }
04948 
04949 static void fun_setdiff(char *buff, char **bufc, dbref player, dbref cause,
04950                                                 char *fargs[], int nfargs, char *cargs[], int ncargs)
04951 {
04952         char sep;
04953 
04954         varargs_preamble("SETDIFF", 3);
04955         handle_sets(fargs, buff, bufc, SET_DIFF, sep);
04956         return;
04957 }
04958 
04959 static void fun_setinter(char *buff, char **bufc, dbref player, dbref cause,
04960                                                  char *fargs[], int nfargs, char *cargs[], int ncargs)
04961 {
04962         char sep;
04963 
04964         varargs_preamble("SETINTER", 3);
04965         handle_sets(fargs, buff, bufc, SET_INTERSECT, sep);
04966         return;
04967 }
04968 
04969 /*
04970  * ---------------------------------------------------------------------------
04971  * * rjust, ljust, center: Justify or center text, specifying fill character
04972  */
04973 
04974 static void fun_ljust(char *buff, char **bufc, dbref player, dbref cause,
04975                                           char *fargs[], int nfargs, char *cargs[], int ncargs)
04976 {
04977         int spaces, i;
04978         char sep;
04979         char new[LBUF_SIZE];
04980 
04981         varargs_preamble("LJUST", 3);
04982         strncpy(new, fargs[0], LBUF_SIZE-1);
04983         spaces = atoi(fargs[1]) - strlen((char *) strip_ansi_r(new,fargs[0],strlen(fargs[0])));
04984 
04985         /*
04986          * Sanitize number of spaces 
04987          */
04988 
04989         if(spaces <= 0) {
04990                 /*
04991                  * no padding needed, just return string 
04992                  */
04993                 safe_str(fargs[0], buff, bufc);
04994                 return;
04995         } else if(spaces > LBUF_SIZE) {
04996                 spaces = LBUF_SIZE;
04997         }
04998         safe_str(fargs[0], buff, bufc);
04999         for(i = 0; i < spaces; i++)
05000                 safe_chr(sep, buff, bufc);
05001 }
05002 
05003 static void fun_rjust(char *buff, char **bufc, dbref player, dbref cause,
05004                                           char *fargs[], int nfargs, char *cargs[], int ncargs)
05005 {
05006         int spaces, i;
05007         char sep;
05008         char new[LBUF_SIZE];
05009         
05010         varargs_preamble("RJUST", 3);
05011         strncpy(new, fargs[0], LBUF_SIZE-1);
05012         spaces = atoi(fargs[1]) - strlen((char *) strip_ansi_r(new,fargs[0],strlen(fargs[0])));
05013 
05014         /*
05015          * Sanitize number of spaces 
05016          */
05017 
05018         if(spaces <= 0) {
05019                 /*
05020                  * no padding needed, just return string 
05021                  */
05022                 safe_str(fargs[0], buff, bufc);
05023                 return;
05024         } else if(spaces > LBUF_SIZE) {
05025                 spaces = LBUF_SIZE;
05026         }
05027         for(i = 0; i < spaces; i++)
05028                 safe_chr(sep, buff, bufc);
05029         safe_str(fargs[0], buff, bufc);
05030 }
05031 
05032 static void fun_center(char *buff, char **bufc, dbref player, dbref cause,
05033                                            char *fargs[], int nfargs, char *cargs[], int ncargs)
05034 {
05035         char sep;
05036         int i, len, lead_chrs, trail_chrs, width;
05037         char new[LBUF_SIZE];
05038 
05039         varargs_preamble("CENTER", 3);
05040 
05041         width = atoi(fargs[1]);
05042         strncpy(new, fargs[0], LBUF_SIZE-1);
05043         len = strlen((char *) strip_ansi_r(new,fargs[0],strlen(fargs[0])));
05044 
05045         if(width > LBUF_SIZE) {
05046                 safe_str("#-1 OUT OF RANGE", buff, bufc);
05047                 return;
05048         }
05049 
05050         if(len >= width) {
05051                 safe_str(fargs[0], buff, bufc);
05052                 return;
05053         }
05054 
05055         lead_chrs = (width / 2) - (len / 2) + .5;
05056         for(i = 0; i < lead_chrs; i++)
05057                 safe_chr(sep, buff, bufc);
05058         safe_str(fargs[0], buff, bufc);
05059         trail_chrs = width - lead_chrs - len;
05060         for(i = 0; i < trail_chrs; i++)
05061                 safe_chr(sep, buff, bufc);
05062 }
05063 
05064 /*
05065  * ---------------------------------------------------------------------------
05066  * * setq, setr, r: set and read global registers.
05067  */
05068 
05069 static void fun_setq(char *buff, char **bufc, dbref player, dbref cause,
05070                                          char *fargs[], int nfargs, char *cargs[], int ncargs)
05071 {
05072         int regnum;
05073 
05074         regnum = atoi(fargs[0]);
05075         if((regnum < 0) || (regnum >= MAX_GLOBAL_REGS)) {
05076                 safe_str("#-1 INVALID GLOBAL REGISTER", buff, bufc);
05077         } else {
05078                 if(!mudstate.global_regs[regnum])
05079                         mudstate.global_regs[regnum] = alloc_lbuf("fun_setq");
05080                 StringCopy(mudstate.global_regs[regnum], fargs[1]);
05081         }
05082 }
05083 
05084 static void fun_setr(char *buff, char **bufc, dbref player, dbref cause,
05085                                          char *fargs[], int nfargs, char *cargs[], int ncargs)
05086 {
05087         int regnum;
05088 
05089         regnum = atoi(fargs[0]);
05090         if((regnum < 0) || (regnum >= MAX_GLOBAL_REGS)) {
05091                 safe_str("#-1 INVALID GLOBAL REGISTER", buff, bufc);
05092                 return;
05093         } else {
05094                 if(!mudstate.global_regs[regnum])
05095                         mudstate.global_regs[regnum] = alloc_lbuf("fun_setq");
05096                 StringCopy(mudstate.global_regs[regnum], fargs[1]);
05097         }
05098         safe_str(fargs[1], buff, bufc);
05099 }
05100 
05101 static void fun_r(char *buff, char **bufc, dbref player, dbref cause,
05102                                   char *fargs[], int nfargs, char *cargs[], int ncargs)
05103 {
05104         int regnum;
05105 
05106         regnum = atoi(fargs[0]);
05107         if((regnum < 0) || (regnum >= MAX_GLOBAL_REGS)) {
05108                 safe_str("#-1 INVALID GLOBAL REGISTER", buff, bufc);
05109         } else if(mudstate.global_regs[regnum]) {
05110                 safe_str(mudstate.global_regs[regnum], buff, bufc);
05111         }
05112 }
05113 
05114 /*
05115  * ---------------------------------------------------------------------------
05116  * * isnum: is the argument a number?
05117  */
05118 
05119 static void fun_isnum(char *buff, char **bufc, dbref player, dbref cause,
05120                                           char *fargs[], int nfargs, char *cargs[], int ncargs)
05121 {
05122         safe_str((is_number(fargs[0]) ? "1" : "0"), buff, bufc);
05123 }
05124 
05125 /*
05126  * ---------------------------------------------------------------------------
05127  * * isdbref: is the argument a valid dbref?
05128  */
05129 
05130 static void fun_isdbref(char *buff, char **bufc, dbref player, dbref cause,
05131                                                 char *fargs[], int nfargs, char *cargs[], int ncargs)
05132 {
05133         char *p;
05134         dbref dbitem;
05135 
05136         p = fargs[0];
05137         if(*p++ == NUMBER_TOKEN) {
05138                 dbitem = parse_dbref(p);
05139                 if(Good_obj(dbitem)) {
05140                         safe_str("1", buff, bufc);
05141                         return;
05142                 }
05143         }
05144         safe_str("0", buff, bufc);
05145 }
05146 
05147 /*
05148  * ---------------------------------------------------------------------------
05149  * * trim: trim off unwanted white space.
05150  */
05151 
05152 static void fun_trim(char *buff, char **bufc, dbref player, dbref cause,
05153                                          char *fargs[], int nfargs, char *cargs[], int ncargs)
05154 {
05155         char *p, *lastchar, *q, sep;
05156         int trim;
05157 
05158         if(nfargs == 0) {
05159                 return;
05160         }
05161         mvarargs_preamble("TRIM", 1, 3);
05162         if(nfargs >= 2) {
05163                 switch (ToLower(*fargs[1])) {
05164                 case 'l':
05165                         trim = 1;
05166                         break;
05167                 case 'r':
05168                         trim = 2;
05169                         break;
05170                 default:
05171                         trim = 3;
05172                         break;
05173                 }
05174         } else {
05175                 trim = 3;
05176         }
05177 
05178         if(trim == 2 || trim == 3) {
05179                 p = lastchar = fargs[0];
05180                 while (*p != '\0') {
05181                         if(*p != sep)
05182                                 lastchar = p;
05183                         p++;
05184                 }
05185                 *(lastchar + 1) = '\0';
05186         }
05187         q = fargs[0];
05188         if(trim == 1 || trim == 3) {
05189                 while (*q != '\0') {
05190                         if(*q == sep)
05191                                 q++;
05192                         else
05193                                 break;
05194                 }
05195         }
05196         safe_str(q, buff, bufc);
05197 }
05198 
05199 #ifdef ARBITRARY_LOGFILES
05200 static void fun_logf(char *buff, char **bufc, dbref player, dbref cause,
05201                                          char *fargs[], int nfargs, char *cargs[], int ncargs)
05202 {
05203         if(!fargs[0] || !fargs[1]) {
05204                 safe_str("#-1 INVALID ARGUMENTS", buff, bufc);
05205         }
05206         if(log_to_file(player, fargs[0], fargs[1]))
05207                 return;
05208 
05209         safe_str("#-1 INVALID LOGFILE", buff, bufc);
05210         return;
05211 }
05212 #endif
05213 
05214 /* ----------------------------------------------------------------------
05215 ** fun_doing: return @doing string for arg.
05216 ** arg is either socket or player (Code adopted from Mux2.3)
05217 */
05218 static void fun_doing(char *buff, char **bufc, dbref player, dbref cause,
05219                                           char *fargs[], int nfargs, char *cargs[], int ncargs)
05220 {
05221         if(is_number(fargs[0])) {
05222                 int s = atoi(fargs[0]);
05223                 unsigned short bFound = 0;
05224                 DESC *d;
05225                 DESC_ITER_CONN(d) {
05226                         if(d->descriptor == s) {
05227                                 bFound = 1;
05228                                 break;
05229                         }
05230                 }
05231                 if(bFound && (d->player == player || Wizard_Who(player))) {
05232                         safe_str(d->doing, buff, bufc);
05233                 } else {
05234                         /* [cad] Mux2.3 returns empty string here, not sure what
05235                            convention is used here. Just return #-1 for now */
05236                         safe_str("#-1", buff, bufc);
05237                 }
05238         } else {
05239                 dbref victim = lookup_player(player, fargs[0], 1);
05240                 if(victim == NOTHING) {
05241                         safe_str("#-1 PLAYER DOES NOT EXIST", buff, bufc);
05242                         return;
05243                 }
05244 
05245                 if(Wizard_Who(player)
05246                    || !Hidden(victim)) {
05247                         DESC *d;
05248                         DESC_ITER_CONN(d) {
05249                                 if(d->player == victim) {
05250                                         safe_str(d->doing, buff, bufc);
05251                                         return;
05252                                 }
05253                         }
05254                 }
05255                 safe_str("#-1 NOT A CONNECTED PLAYER", buff, bufc);
05256         }
05257 }
05258 
05259 /* ----------------------------------------------------------------------
05260 ** fun_poll: return @doing header
05261 ** (Code adopted from Mux2.3)
05262 */
05263 static void fun_poll(char *buff, char **bufc, dbref player, dbref cause,
05264                                          char *fargs[], int nfargs, char *cargs[], int ncargs)
05265 {
05266         safe_str(mudstate.doing_hdr, buff, bufc);
05267 }
05268 
05269 /* ----------------------------------------------------------------------
05270  ** fun_pairs: take an attr off an object and count the # of
05271  ** {[()]} in that attribute and return it as a list
05272  ** Modified from fun_get
05273  ** Dany - 06/2005
05274  */
05275 static void fun_pairs(char *buff, char **bufc, dbref player, dbref cause,
05276                                           char *fargs[], int nfargs, char *cargs[], int ncargs)
05277 {
05278         dbref thing, aowner;
05279         int attrib, free_buffer, aflags;
05280         ATTR *attr;
05281         char *atr_gotten;
05282         struct boolexp *bool;
05283 
05284         char *tmp_char;
05285         int right_brace = 0, left_brace = 0, right_square_bracket = 0,
05286                 left_square_bracket = 0, right_parenthesis = 0, left_parenthesis = 0;
05287 
05288         if(!parse_attrib(player, fargs[0], &thing, &attrib)) {
05289                 safe_str("#-1 NO MATCH", buff, bufc);
05290                 return;
05291         }
05292         if(attrib == NOTHING) {
05293                 return;
05294         }
05295         free_buffer = 1;
05296         attr = atr_num(attrib);         /*
05297                                                                  * We need the attr's flags for this: 
05298                                                                  */
05299         if(!attr) {
05300                 return;
05301         }
05302         if(attr->flags & AF_IS_LOCK) {
05303                 atr_gotten = atr_get(thing, attrib, &aowner, &aflags);
05304                 if(Read_attr(player, thing, attr, aowner, aflags)) {
05305                         bool = parse_boolexp(player, atr_gotten, 1);
05306                         free_lbuf(atr_gotten);
05307                         atr_gotten = unparse_boolexp(player, bool);
05308                         free_boolexp(bool);
05309                 } else {
05310                         free_lbuf(atr_gotten);
05311                         atr_gotten = (char *) "#-1 PERMISSION DENIED";
05312                 }
05313                 free_buffer = 0;
05314         } else {
05315                 atr_gotten = atr_pget(thing, attrib, &aowner, &aflags);
05316         }
05317 
05318         /*
05319          * Perform access checks.  c_r_p fills buff with an error message * * 
05320          * 
05321          * *  * * if needed. 
05322          */
05323 
05324         if(check_read_perms(player, thing, attr, aowner, aflags, buff, bufc)) {
05325 
05326                 /* Scan through the attribute and count the various brackets */
05327                 for(tmp_char = atr_gotten; *tmp_char; tmp_char++) {
05328 
05329                         switch (*tmp_char) {
05330                         case '{':
05331                                 left_brace++;
05332                                 break;
05333                         case '[':
05334                                 left_square_bracket++;
05335                                 break;
05336                         case '(':
05337                                 left_parenthesis++;
05338                                 break;
05339                         case '}':
05340                                 right_brace++;
05341                                 break;
05342                         case ']':
05343                                 right_square_bracket++;
05344                                 break;
05345                         case ')':
05346                                 right_parenthesis++;
05347                                 break;
05348                         default:
05349                                 break;
05350                         }
05351 
05352                 }
05353 
05354                 snprintf(atr_gotten, LBUF_SIZE, "%d %d %d %d %d %d",
05355                                  left_brace,
05356                                  left_square_bracket,
05357                                  left_parenthesis,
05358                                  right_parenthesis, right_square_bracket, right_brace);
05359                 safe_str(atr_gotten, buff, bufc);
05360         }
05361 
05362         if(free_buffer)
05363                 free_lbuf(atr_gotten);
05364         return;
05365 }
05366 
05367 /* ----------------------------------------------------------------------
05368  ** fun_colorpairs: take an attr off an object and color the
05369  ** {[()]} in that attribute and return it.
05370  ** Modified from fun_get
05371  ** Dany - 09/2005
05372  */
05373 static void fun_colorpairs(char *buff, char **bufc, dbref player, dbref cause,
05374                                                    char *fargs[], int nfargs, char *cargs[],
05375                                                    int ncargs)
05376 {
05377         dbref thing, aowner;
05378         int attrib, free_buffer, aflags;
05379         ATTR *attr;
05380         char *atr_gotten;
05381         struct boolexp *bool;
05382 
05383         char *tmp_char;
05384         char tmp_string[LBUF_SIZE];
05385         char tmp_piece[2];
05386 
05387         if(!parse_attrib(player, fargs[0], &thing, &attrib)) {
05388                 safe_str("#-1 NO MATCH", buff, bufc);
05389                 return;
05390         }
05391         if(attrib == NOTHING) {
05392                 return;
05393         }
05394         free_buffer = 1;
05395         attr = atr_num(attrib);         /*
05396                                                                  * We need the attr's flags for this: 
05397                                                                  */
05398         if(!attr) {
05399                 return;
05400         }
05401         if(attr->flags & AF_IS_LOCK) {
05402                 atr_gotten = atr_get(thing, attrib, &aowner, &aflags);
05403                 if(Read_attr(player, thing, attr, aowner, aflags)) {
05404                         bool = parse_boolexp(player, atr_gotten, 1);
05405                         free_lbuf(atr_gotten);
05406                         atr_gotten = unparse_boolexp(player, bool);
05407                         free_boolexp(bool);
05408                 } else {
05409                         free_lbuf(atr_gotten);
05410                         atr_gotten = (char *) "#-1 PERMISSION DENIED";
05411                 }
05412                 free_buffer = 0;
05413         } else {
05414                 atr_gotten = atr_pget(thing, attrib, &aowner, &aflags);
05415         }
05416 
05417         /*
05418          * Perform access checks.  c_r_p fills buff with an error message * * 
05419          * 
05420          * *  * * if needed. 
05421          */
05422 
05423         if(check_read_perms(player, thing, attr, aowner, aflags, buff, bufc)) {
05424 
05425                 /* zero temporary string */
05426                 memset(tmp_string, 0, sizeof(tmp_string));
05427 
05428                 /* Scan through the attribute, colorize what we want */
05429                 for(tmp_char = atr_gotten; *tmp_char; tmp_char++) {
05430 
05431                         switch (*tmp_char) {
05432                         case '{':
05433                                 strncat(tmp_string, ANSI_RED, LBUF_SIZE);
05434                                 strncat(tmp_string, "{", LBUF_SIZE);
05435                                 strncat(tmp_string, ANSI_NORMAL, LBUF_SIZE);
05436                                 break;
05437                         case '[':
05438                                 strncat(tmp_string, ANSI_YELLOW, LBUF_SIZE);
05439                                 strncat(tmp_string, "[", LBUF_SIZE);
05440                                 strncat(tmp_string, ANSI_NORMAL, LBUF_SIZE);
05441                                 break;
05442                         case '(':
05443                                 strncat(tmp_string, ANSI_GREEN, LBUF_SIZE);
05444                                 strncat(tmp_string, "(", LBUF_SIZE);
05445                                 strncat(tmp_string, ANSI_NORMAL, LBUF_SIZE);
05446                                 break;
05447                         case '}':
05448                                 strncat(tmp_string, ANSI_RED, LBUF_SIZE);
05449                                 strncat(tmp_string, "}", LBUF_SIZE);
05450                                 strncat(tmp_string, ANSI_NORMAL, LBUF_SIZE);
05451                                 break;
05452                         case ']':
05453                                 strncat(tmp_string, ANSI_YELLOW, LBUF_SIZE);
05454                                 strncat(tmp_string, "]", LBUF_SIZE);
05455                                 strncat(tmp_string, ANSI_NORMAL, LBUF_SIZE);
05456                                 break;
05457                         case ')':
05458                                 strncat(tmp_string, ANSI_GREEN, LBUF_SIZE);
05459                                 strncat(tmp_string, ")", LBUF_SIZE);
05460                                 strncat(tmp_string, ANSI_NORMAL, LBUF_SIZE);
05461                                 break;
05462                         default:
05463                                 sprintf(tmp_piece, "%c", *tmp_char);
05464                                 strncat(tmp_string, tmp_piece, LBUF_SIZE);
05465                                 break;
05466                         }
05467 
05468                 }
05469 
05470                 safe_str(tmp_string, buff, bufc);
05471         }
05472 
05473         if(free_buffer)
05474                 free_lbuf(atr_gotten);
05475         return;
05476 }
05477 
05478 /* ---------------------------------------------------------------------------
05479  * flist: List of existing functions in alphabetical order.
05480  */
05481 
05482 FUN flist[] = {
05483         {"ABS", fun_abs, 1, 0, CA_PUBLIC},
05484         {"ACOS", fun_acos, 1, 0, CA_PUBLIC},
05485         {"ADD", fun_add, 0, FN_VARARGS, CA_PUBLIC},
05486         {"AFTER", fun_after, 0, FN_VARARGS, CA_PUBLIC},
05487         {"ALPHAMAX", fun_alphamax, 0, FN_VARARGS, CA_PUBLIC},
05488         {"ALPHAMIN", fun_alphamin, 0, FN_VARARGS, CA_PUBLIC},
05489         {"AND", fun_and, 0, FN_VARARGS, CA_PUBLIC},
05490         {"ANDFLAGS", fun_andflags, 2, 0, CA_PUBLIC},
05491         {"ANSI", fun_ansi, 2, 0, CA_PUBLIC},
05492         {"ANSISECURE", fun_ansi_secure, -1, 0, CA_PUBLIC},
05493         {"APOSS", fun_aposs, 1, 0, CA_PUBLIC},
05494         {"ART", fun_art, 1, 0, CA_PUBLIC},
05495         {"ASIN", fun_asin, 1, 0, CA_PUBLIC},
05496         {"ATAN", fun_atan, 1, 0, CA_PUBLIC},
05497         {"BEEP", fun_beep, 0, 0, CA_BUILDER},
05498         {"BEFORE", fun_before, 0, FN_VARARGS, CA_PUBLIC},
05499         {"BTADDSTORES", fun_btaddstores, 3, 0, CA_WIZARD},
05500         {"BTARMORSTATUS", fun_btarmorstatus, 2, 0, CA_WIZARD},
05501         {"BTARMORSTATUS_REF", fun_btarmorstatus_ref, 2, 0, CA_WIZARD},
05502         {"BTCHARLIST", fun_btcharlist, 1, FN_VARARGS, CA_WIZARD},
05503         {"BTCRITSLOT", fun_btcritslot, 0, FN_VARARGS, CA_WIZARD},
05504         {"BTCRITSLOT_REF", fun_btcritslot_ref, 0, FN_VARARGS, CA_WIZARD},
05505         {"BTCRITSTATUS", fun_btcritstatus, 2, 0, CA_WIZARD},
05506         {"BTCRITSTATUS_REF", fun_btcritstatus_ref, 2, 0, CA_WIZARD},
05507         {"BTDAMAGEMECH", fun_btdamagemech, 7, 0, CA_WIZARD},
05508         {"BTDAMAGES", fun_btdamages, 1, 0, CA_WIZARD},
05509         {"BTDESIGNEX", fun_btdesignex, 1, 0, CA_PUBLIC},
05510         {"BTENGRATE", fun_btengrate, 1, 0, CA_WIZARD},
05511         {"BTENGRATE_REF", fun_btengrate_ref, 1, 0, CA_WIZARD},
05512 #ifdef BT_ADVANCED_ECON
05513         {"BTFASABASECOST_REF", fun_btfasabasecost_ref, 1, 0, CA_WIZARD},
05514 #endif
05515         {"BTGETBV", fun_btgetbv, 1, 0, CA_WIZARD},
05516         {"BTGETBV_REF", fun_btgetbv_ref, 1, 0, CA_WIZARD},
05517         {"BTGETCHARVALUE", fun_btgetcharvalue, 3, 0, CA_WIZARD},
05518 #ifdef BT_ADVANCED_ECON
05519         {"BTGETPARTCOST", fun_btgetpartcost, 1, 0, CA_WIZARD},
05520 #endif
05521         {"BTGETRANGE", fun_btgetrange, 0, FN_VARARGS, CA_WIZARD},
05522         {"BTGETREALMAXSPEED", fun_btgetrealmaxspeed, 1, 0, CA_WIZARD},
05523         {"BTGETWEIGHT", fun_btgetweight, 1, 0, CA_WIZARD},
05524         {"BTGETXCODEVALUE", fun_btgetxcodevalue, 2, 0, CA_WIZARD},
05525         {"BTGETXCODEVALUE_REF", fun_btgetxcodevalue_ref, 2, 0, CA_WIZARD},
05526         {"BTHEXEMIT", fun_bthexemit, 4, 0, CA_WIZARD},
05527         {"BTHEXINBLZ", fun_bthexinblz, 3, 0, CA_WIZARD},
05528         {"BTHEXLOS", fun_bthexlos, 3, 0, CA_WIZARD},
05529         {"BTID2DB", fun_btid2db, 2, 0, CA_WIZARD},
05530         {"BTLAG", fun_lag, 0, 0, CA_WIZARD},
05531         {"BTLISTBLZ", fun_btlistblz, 1, 0, CA_WIZARD},
05532         {"BTLOADMAP", fun_btloadmap, 2, FN_VARARGS, CA_WIZARD},
05533         {"BTLOADMECH", fun_btloadmech, 2, 0, CA_WIZARD},
05534         {"BTLOSM2M", fun_btlosm2m, 2, 0, CA_WIZARD},
05535         {"BTMAKEMECHS", fun_btmakemechs, 0, FN_VARARGS, CA_WIZARD},
05536         {"BTMAKEPILOTROLL", fun_btmakepilotroll, 3, 0, CA_WIZARD},
05537         {"BTMAPELEV", fun_btmapelev, 3, 0, CA_WIZARD},
05538         {"BTMAPEMIT", fun_btmapemit, 0, FN_VARARGS, CA_WIZARD},
05539         {"BTMAPTERR", fun_btmapterr, 3, 0, CA_WIZARD},
05540         {"BTMAPUNITS", fun_btmapunits, 0, FN_VARARGS, CA_WIZARD},
05541         {"BTMECHFREQS", fun_btmechfreqs, 1, 0, CA_WIZARD},
05542         {"BTNUMREPJOBS", fun_btnumrepjobs, 1, 0, CA_WIZARD},
05543         {"BTPARTTYPE", fun_btparttype, 1, 0, CA_WIZARD},
05544         {"BTPARTMATCH", fun_btpartmatch, 1, 0, CA_WIZARD},
05545         {"BTPARTNAME", fun_btpartname, 2, 0, CA_WIZARD},
05546         {"BTPARTWEIGHT", fun_btgetweight, 1, 0, CA_WIZARD},
05547         {"BTPAYLOAD_REF", fun_btpayload_ref, 1, 0, CA_WIZARD},
05548         {"BTREMOVESTORES", fun_btremovestores, 3, 0, CA_WIZARD},
05549         {"BTSETARMORSTATUS", fun_btsetarmorstatus, 4, 0, CA_WIZARD},
05550         {"BTSETCHARVALUE", fun_btsetcharvalue, 4, 0, CA_WIZARD},
05551         {"BTSETMAXSPEED", fun_btsetmaxspeed, 2, 0, CA_WIZARD},
05552 #ifdef BT_ADVANCED_ECON
05553         {"BTSETPARTCOST", fun_btsetpartcost, 2, 0, CA_WIZARD},
05554 #endif
05555         {"BTSETXCODEVALUE", fun_btsetxcodevalue, 3, 0, CA_WIZARD},
05556         {"BTSETXY", fun_btsetxy, 0, FN_VARARGS, CA_WIZARD},
05557         {"BTSHOWCRITSTATUS_REF", fun_btshowcritstatus_ref, 3, 0, CA_WIZARD},
05558         {"BTSHOWSTATUS_REF", fun_btshowstatus_ref, 2, 0, CA_WIZARD},
05559         {"BTSHOWWSPECS_REF", fun_btshowwspecs_ref, 2, 0, CA_WIZARD},
05560         {"BTSTORES", fun_btstores, 0, FN_VARARGS, CA_WIZARD},
05561         {"BTTECHLIST", fun_bttechlist, 1, 0, CA_WIZARD},
05562         {"BTTECHLIST_REF", fun_bttechlist_ref, 1, 0, CA_WIZARD},
05563         {"BTTECHSTATUS", fun_bttechstatus, 1, 0, CA_WIZARD},
05564         {"BTTECHTIME", fun_bttechtime, 0, 0, CA_WIZARD},
05565         {"BTTHRESHOLD", fun_btthreshold, 1, 0, CA_WIZARD},
05566         {"BTTICWEAPS", fun_btticweaps, 2, 0, CA_WIZARD},
05567         {"BTUNDERREPAIR", fun_btunderrepair, 1, 0, CA_BUILDER},
05568         {"BTUNITFIXABLE", fun_btunitfixable, 1, 0, CA_WIZARD},
05569         {"BTWEAPONSTATUS", fun_btweaponstatus, 0, FN_VARARGS, CA_WIZARD},
05570         {"BTWEAPONSTATUS_REF", fun_btweaponstatus_ref, 0, FN_VARARGS, CA_WIZARD},
05571         {"BTWEAPSTAT", fun_btweapstat, 2, 0, CA_WIZARD},
05572         {"CAPSTR", fun_capstr, -1, 0, CA_PUBLIC},
05573         {"CASE", fun_case, 0, FN_VARARGS | FN_NO_EVAL, CA_PUBLIC},
05574         {"CAT", fun_cat, 0, FN_VARARGS, CA_PUBLIC},
05575         {"CEIL", fun_ceil, 1, 0, CA_PUBLIC},
05576         {"CENTER", fun_center, 0, FN_VARARGS, CA_PUBLIC},
05577         {"CHILDREN", fun_children, 1, 0, CA_PUBLIC},
05578         {"COBJ", fun_cobj, 1, 0, CA_PUBLIC},
05579         {"COLORPAIRS", fun_colorpairs, 1, 0, CA_PUBLIC},
05580         {"COLUMNS", fun_columns, 0, FN_VARARGS, CA_PUBLIC},
05581         {"COMP", fun_comp, 2, 0, CA_PUBLIC},
05582         {"CON", fun_con, 1, 0, CA_PUBLIC},
05583         {"CONFIG", fun_config, 1, 0, CA_WIZARD},
05584         {"CONN", fun_conn, 1, 0, CA_PUBLIC},
05585         {"CONNRECORD", fun_connrecord, 0, 0, CA_PUBLIC},
05586         {"CONTROLS", fun_controls, 2, 0, CA_PUBLIC},
05587         {"CONVSECS", fun_convsecs, 1, 0, CA_PUBLIC},
05588         {"CONVTIME", fun_convtime, 1, 0, CA_PUBLIC},
05589         {"CONVUPTIME", fun_convuptime, 1, 0, CA_PUBLIC},
05590         {"COS", fun_cos, 1, 0, CA_PUBLIC},
05591         {"CREATE", fun_create, 0, FN_VARARGS, CA_PUBLIC},
05592         {"CWHO", fun_cwho, 1, 0, CA_PUBLIC},
05593         {"CLIST", fun_clist, 1, 0, CA_PUBLIC},
05594         {"CEMIT", fun_cemit, 2, 0, CA_PUBLIC},
05595         {"DEC", fun_dec, 1, 0, CA_PUBLIC},
05596         {"DECRYPT", fun_decrypt, 2, 0, CA_PUBLIC},
05597         {"DEFAULT", fun_default, 2, FN_NO_EVAL, CA_PUBLIC},
05598         {"DELETE", fun_delete, 3, 0, CA_PUBLIC},
05599         {"DIGITTIME", fun_digittime, 1, 0, CA_PUBLIC},
05600         {"DIE", fun_die, 2, 0, CA_PUBLIC},
05601         {"DIST2D", fun_dist2d, 4, 0, CA_PUBLIC},
05602         {"DIST3D", fun_dist3d, 6, 0, CA_PUBLIC},
05603         {"DIV", fun_div, 2, 0, CA_PUBLIC},
05604         {"DOING", fun_doing, 1, 0, CA_WIZARD},
05605         {"E", fun_e, 0, 0, CA_PUBLIC},
05606         {"EDEFAULT", fun_edefault, 2, FN_NO_EVAL, CA_PUBLIC},
05607         {"EDIT", fun_edit, 3, 0, CA_PUBLIC},
05608         {"ELEMENTS", fun_elements, 0, FN_VARARGS, CA_PUBLIC},
05609         {"ELOCK", fun_elock, 2, 0, CA_PUBLIC},
05610         {"EMPTY", fun_empty, 0, FN_VARARGS, CA_PUBLIC},
05611         {"ENCRYPT", fun_encrypt, 2, 0, CA_PUBLIC},
05612         {"EQ", fun_eq, 2, 0, CA_PUBLIC},
05613         {"ESCAPE", fun_escape, -1, 0, CA_PUBLIC},
05614         {"EXIT", fun_exit, 1, 0, CA_PUBLIC},
05615         {"EXP", fun_exp, 1, 0, CA_PUBLIC},
05616         {"EXTRACT", fun_extract, 0, FN_VARARGS, CA_PUBLIC},
05617         {"EVAL", fun_eval, 0, FN_VARARGS, CA_PUBLIC},
05618         {"FDIV", fun_fdiv, 2, 0, CA_PUBLIC},
05619         {"FILTER", fun_filter, 0, FN_VARARGS, CA_PUBLIC},
05620         {"FINDABLE", fun_findable, 2, 0, CA_PUBLIC},
05621         {"FIRST", fun_first, 0, FN_VARARGS, CA_PUBLIC},
05622         {"FLAGS", fun_flags, 1, 0, CA_PUBLIC},
05623         {"FLOOR", fun_floor, 1, 0, CA_PUBLIC},
05624         {"FOLD", fun_fold, 0, FN_VARARGS, CA_PUBLIC},
05625         {"FOREACH", fun_foreach, 0, FN_VARARGS, CA_PUBLIC},
05626         {"FULLNAME", fun_fullname, 1, 0, CA_PUBLIC},
05627         {"GET", fun_get, 1, 0, CA_PUBLIC},
05628         {"GET_EVAL", fun_get_eval, 1, 0, CA_PUBLIC},
05629         {"GRAB", fun_grab, 0, FN_VARARGS, CA_PUBLIC},
05630         {"GRABALL", fun_graball, 0, FN_VARARGS, CA_PUBLIC},
05631         {"GREP", fun_grep, 3, 0, CA_PUBLIC},
05632         {"GREPI", fun_grepi, 3, 0, CA_PUBLIC},
05633         {"GT", fun_gt, 2, 0, CA_PUBLIC},
05634         {"GTE", fun_gte, 2, 0, CA_PUBLIC},
05635         {"HASATTR", fun_hasattr, 2, 0, CA_PUBLIC},
05636         {"HASATTRP", fun_hasattrp, 2, 0, CA_PUBLIC},
05637         {"HASFLAG", fun_hasflag, 2, 0, CA_PUBLIC},
05638         {"HASPOWER", fun_haspower, 2, 0, CA_PUBLIC},
05639         {"HASTYPE", fun_hastype, 2, 0, CA_PUBLIC},
05640         {"HOME", fun_home, 1, 0, CA_PUBLIC},
05641         {"IDLE", fun_idle, 1, 0, CA_PUBLIC},
05642         {"IFELSE", fun_ifelse, 3, FN_NO_EVAL, CA_PUBLIC},
05643         {"INC", fun_inc, 1, 0, CA_PUBLIC},
05644         {"INDEX", fun_index, 4, 0, CA_PUBLIC},
05645         {"INSERT", fun_insert, 0, FN_VARARGS, CA_PUBLIC},
05646         {"INZONE", fun_inzone, 1, 0, CA_PUBLIC},
05647         {"ISDBREF", fun_isdbref, 1, 0, CA_PUBLIC},
05648         {"ISNUM", fun_isnum, 1, 0, CA_PUBLIC},
05649         {"ISWORD", fun_isword, 1, 0, CA_PUBLIC},
05650         {"ITEMS", fun_items, 0, FN_VARARGS, CA_PUBLIC},
05651         {"ITER", fun_iter, 0, FN_VARARGS | FN_NO_EVAL, CA_PUBLIC},
05652         {"LAST", fun_last, 0, FN_VARARGS, CA_PUBLIC},
05653         {"LATTR", fun_lattr, 1, 0, CA_PUBLIC},
05654         {"LCON", fun_lcon, 1, 0, CA_PUBLIC},
05655         {"LCSTR", fun_lcstr, -1, 0, CA_PUBLIC},
05656         {"LDELETE", fun_ldelete, 0, FN_VARARGS, CA_PUBLIC},
05657         {"LEXITS", fun_lexits, 1, 0, CA_PUBLIC},
05658         {"LPARENT", fun_lparent, 1, 0, CA_PUBLIC},
05659         {"LIST", fun_list, 0, FN_VARARGS | FN_NO_EVAL, CA_PUBLIC},
05660         {"LIT", fun_lit, 1, FN_NO_EVAL, CA_PUBLIC},
05661         {"LJUST", fun_ljust, 0, FN_VARARGS, CA_PUBLIC},
05662         {"LINK", fun_link, 2, 0, CA_PUBLIC},
05663         {"LN", fun_ln, 1, 0, CA_PUBLIC},
05664         {"LNUM", fun_lnum, 0, FN_VARARGS, CA_PUBLIC},
05665         {"LOC", fun_loc, 1, 0, CA_BUILDER},
05666         {"LOCATE", fun_locate, 3, 0, CA_BUILDER},
05667         {"LOCK", fun_lock, 1, 0, CA_PUBLIC},
05668         {"LOG", fun_log, 1, 0, CA_PUBLIC},
05669 #ifdef ARBITRARY_LOGFILES
05670         {"LOGF", fun_logf, 2, 0, CA_WIZARD},
05671 #endif
05672         {"LSTACK", fun_lstack, 0, FN_VARARGS, CA_PUBLIC},
05673         {"LT", fun_lt, 2, 0, CA_PUBLIC},
05674         {"LTE", fun_lte, 2, 0, CA_PUBLIC},
05675         {"LWHO", fun_lwho, 0, 0, CA_BUILDER},
05676         {"MAIL", fun_mail, 0, FN_VARARGS, CA_PUBLIC},
05677         {"MAILFROM", fun_mailfrom, 0, FN_VARARGS, CA_PUBLIC},
05678         {"MAP", fun_map, 0, FN_VARARGS, CA_PUBLIC},
05679         {"MATCH", fun_match, 0, FN_VARARGS, CA_PUBLIC},
05680         {"MATCHALL", fun_matchall, 0, FN_VARARGS, CA_PUBLIC},
05681         {"MAX", fun_max, 0, FN_VARARGS, CA_PUBLIC},
05682         {"MEMBER", fun_member, 0, FN_VARARGS, CA_PUBLIC},
05683         {"MERGE", fun_merge, 3, 0, CA_PUBLIC},
05684         {"MID", fun_mid, 3, 0, CA_PUBLIC},
05685         {"MIN", fun_min, 0, FN_VARARGS, CA_PUBLIC},
05686         {"MIX", fun_mix, 0, FN_VARARGS, CA_PUBLIC},
05687         {"MOD", fun_mod, 2, 0, CA_PUBLIC},
05688         {"MONEY", fun_money, 1, 0, CA_PUBLIC},
05689         {"MUDNAME", fun_mudname, 0, 0, CA_PUBLIC},
05690         {"MUL", fun_mul, 0, FN_VARARGS, CA_PUBLIC},
05691         {"MUNGE", fun_munge, 0, FN_VARARGS, CA_PUBLIC},
05692         {"NAME", fun_name, 1, 0, CA_PUBLIC},
05693         {"NEARBY", fun_nearby, 2, 0, CA_PUBLIC},
05694         {"NEQ", fun_neq, 2, 0, CA_PUBLIC},
05695         {"NEXT", fun_next, 1, 0, CA_PUBLIC},
05696         {"NOT", fun_not, 1, 0, CA_PUBLIC},
05697         {"NUM", fun_num, 1, 0, CA_PUBLIC},
05698         {"OBJ", fun_obj, 1, 0, CA_PUBLIC},
05699         {"OBJEVAL", fun_objeval, 2, FN_NO_EVAL, CA_PUBLIC},
05700         {"OBJMEM", fun_objmem, 1, 0, CA_PUBLIC},
05701         {"OR", fun_or, 0, FN_VARARGS, CA_PUBLIC},
05702         {"ORFLAGS", fun_orflags, 2, 0, CA_PUBLIC},
05703         {"OWNER", fun_owner, 1, 0, CA_PUBLIC},
05704         {"PAIRS", fun_pairs, 1, 0, CA_PUBLIC},
05705         {"PARENT", fun_parent, 1, 0, CA_PUBLIC},
05706         {"PARSE", fun_parse, 0, FN_VARARGS | FN_NO_EVAL, CA_PUBLIC},
05707         {"PEEK", fun_peek, 0, FN_VARARGS, CA_PUBLIC},
05708         {"PEMIT", fun_pemit, 2, 0, CA_PUBLIC},
05709         {"PI", fun_pi, 0, 0, CA_PUBLIC},
05710         {"PLAYMEM", fun_playmem, 1, 0, CA_PUBLIC},
05711         {"PMATCH", fun_pmatch, 1, 0, CA_PUBLIC},
05712         {"POLL", fun_poll, 0, 0, CA_WIZARD},
05713         {"POP", fun_pop, 0, FN_VARARGS, CA_PUBLIC},
05714         {"PORTS", fun_ports, 1, 0, CA_PUBLIC},
05715         {"POS", fun_pos, 2, 0, CA_PUBLIC},
05716         {"POSS", fun_poss, 1, 0, CA_PUBLIC},
05717         {"POWER", fun_power, 2, 0, CA_PUBLIC},
05718         {"PUSH", fun_push, 0, FN_VARARGS, CA_PUBLIC},
05719 #ifdef USE_PYTHON
05720         {"PYTHON", fun_python, 1, FN_NO_EVAL, CA_WIZARD},
05721         {"PYTHONCALL", fun_pythoncall, 0, FN_VARARGS, CA_WIZARD},
05722 #endif
05723         {"R", fun_r, 1, 0, CA_PUBLIC},
05724         {"RAND", fun_rand, 1, 0, CA_PUBLIC},
05725         {"REGMATCH", fun_regmatch, 0, FN_VARARGS, CA_PUBLIC},
05726         {"REMOVE", fun_remove, 0, FN_VARARGS, CA_PUBLIC},
05727         {"REPEAT", fun_repeat, 2, 0, CA_PUBLIC},
05728         {"REPLACE", fun_replace, 0, FN_VARARGS, CA_PUBLIC},
05729         {"REST", fun_rest, 0, FN_VARARGS, CA_PUBLIC},
05730         {"REVERSE", fun_reverse, -1, 0, CA_PUBLIC},
05731         {"REVWORDS", fun_revwords, 0, FN_VARARGS, CA_PUBLIC},
05732         {"RJUST", fun_rjust, 0, FN_VARARGS, CA_PUBLIC},
05733         {"RLOC", fun_rloc, 2, 0, CA_PUBLIC},
05734         {"ROOM", fun_room, 1, 0, CA_PUBLIC},
05735         {"ROUND", fun_round, 2, 0, CA_PUBLIC},
05736         {"S", fun_s, -1, 0, CA_PUBLIC},
05737         {"SCRAMBLE", fun_scramble, 1, 0, CA_PUBLIC},
05738         {"SEARCH", fun_search, -1, 0, CA_PUBLIC},
05739         {"SECS", fun_secs, 0, 0, CA_PUBLIC},
05740         {"SECURE", fun_secure, -1, 0, CA_PUBLIC},
05741         {"SET", fun_set, 2, 0, CA_PUBLIC},
05742         {"SETDIFF", fun_setdiff, 0, FN_VARARGS, CA_PUBLIC},
05743         {"SETINTER", fun_setinter, 0, FN_VARARGS, CA_PUBLIC},
05744         {"SETLOCK", fun_setlock, 3, 0, CA_WIZARD},
05745         {"SETQ", fun_setq, 2, 0, CA_PUBLIC},
05746         {"SETR", fun_setr, 2, 0, CA_PUBLIC},
05747         {"SETUNION", fun_setunion, 0, FN_VARARGS, CA_PUBLIC},
05748         {"SHL", fun_shl, 2, 0, CA_PUBLIC},
05749         {"SHR", fun_shr, 2, 0, CA_PUBLIC},
05750         {"SHUFFLE", fun_shuffle, 0, FN_VARARGS, CA_PUBLIC},
05751         {"SIGN", fun_sign, 1, 0, CA_PUBLIC},
05752         {"SIN", fun_sin, 1, 0, CA_PUBLIC},
05753         {"SORT", fun_sort, 0, FN_VARARGS, CA_PUBLIC},
05754         {"SORTBY", fun_sortby, 0, FN_VARARGS, CA_PUBLIC},
05755         {"SPACE", fun_space, 1, 0, CA_PUBLIC},
05756         {"SPLICE", fun_splice, 0, FN_VARARGS, CA_PUBLIC},
05757         {"SQRT", fun_sqrt, 1, 0, CA_PUBLIC},
05758         {"SQUISH", fun_squish, 1, 0, CA_PUBLIC},
05759         {"STARTSECS", fun_startsecs, 0, 0, CA_PUBLIC},
05760         {"STARTTIME", fun_starttime, 0, 0, CA_PUBLIC},
05761         {"STATS", fun_stats, 1, 0, CA_PUBLIC},
05762         {"STRCAT", fun_strcat, 0, FN_VARARGS, CA_PUBLIC},
05763         {"STRIPANSI", fun_stripansi, 1, 0, CA_PUBLIC},
05764         {"STRLEN", fun_strlen, -1, 0, CA_PUBLIC},
05765         {"STRMATCH", fun_strmatch, 2, 0, CA_PUBLIC},
05766         {"STRTRUNC", fun_strtrunc, 2, 0, CA_PUBLIC},
05767         {"SUB", fun_sub, 2, 0, CA_PUBLIC},
05768         {"SUBEVAL", fun_subeval, 1, 0, CA_PUBLIC},
05769         {"SUBJ", fun_subj, 1, 0, CA_PUBLIC},
05770         {"SWITCH", fun_switch, 0, FN_VARARGS | FN_NO_EVAL, CA_PUBLIC},
05771         {"TAN", fun_tan, 1, 0, CA_PUBLIC},
05772         {"T", fun_t, 1, 0, CA_PUBLIC},
05773         {"TEL", fun_tel, 2, 0, CA_PUBLIC},
05774         {"TIME", fun_time, 0, 0, CA_PUBLIC},
05775         {"TRANSLATE", fun_translate, 2, 0, CA_PUBLIC},
05776         {"TRIM", fun_trim, 0, FN_VARARGS, CA_PUBLIC},
05777         {"TRUE", fun_t, 1, 0, CA_PUBLIC},
05778         {"TRUNC", fun_trunc, 1, 0, CA_PUBLIC},
05779         {"TYPE", fun_type, 1, 0, CA_PUBLIC},
05780         {"U", fun_u, 0, FN_VARARGS, CA_PUBLIC},
05781         {"UCSTR", fun_ucstr, -1, 0, CA_PUBLIC},
05782         {"UDEFAULT", fun_udefault, 0, FN_VARARGS | FN_NO_EVAL, CA_PUBLIC},
05783         {"ULOCAL", fun_ulocal, 0, FN_VARARGS, CA_PUBLIC},
05784         {"V", fun_v, 1, 0, CA_PUBLIC},
05785         {"VADD", fun_vadd, 0, FN_VARARGS, CA_PUBLIC},
05786         {"VALID", fun_valid, 2, FN_VARARGS, CA_PUBLIC},
05787         {"VDIM", fun_vdim, 0, FN_VARARGS, CA_PUBLIC},
05788         {"VERSION", fun_version, 0, 0, CA_PUBLIC},
05789         {"VISIBLE", fun_visible, 2, 0, CA_PUBLIC},
05790         {"VMAG", fun_vmag, 0, FN_VARARGS, CA_PUBLIC},
05791         {"VMUL", fun_vmul, 0, FN_VARARGS, CA_PUBLIC},
05792         {"VSUB", fun_vsub, 0, FN_VARARGS, CA_PUBLIC},
05793         {"VUNIT", fun_vunit, 0, FN_VARARGS, CA_PUBLIC},
05794         {"WHERE", fun_where, 1, 0, CA_PUBLIC},
05795         {"WORDPOS", fun_wordpos, 0, FN_VARARGS, CA_PUBLIC},
05796         {"WORDS", fun_words, 0, FN_VARARGS, CA_PUBLIC},
05797         {"XGET", fun_xget, 2, 0, CA_PUBLIC},
05798         {"XOR", fun_xor, 0, FN_VARARGS, CA_PUBLIC},
05799         {"ZFUN", fun_zfun, 0, FN_VARARGS, CA_PUBLIC},
05800         {"ZONE", fun_zone, 1, 0, CA_PUBLIC},
05801         {"ZPLAYERS", fun_zplayers, 1, 0, CA_PUBLIC},
05802         {"ZWHO", fun_zwho, 1, 0, CA_PUBLIC},
05803         {NULL, NULL, 0, 0, 0}
05804 };
05805 
05806 /* *INDENT-ON* */
05807 
05808 void init_functab()
05809 {
05810         FUN *fp;
05811         char *buff, *cp, *dp;
05812 
05813         buff = alloc_sbuf("init_functab");
05814         hashinit(&mudstate.func_htab, 100 * HASH_FACTOR);
05815         for(fp = flist; fp->name; fp++) {
05816                 cp = (char *) fp->name;
05817                 dp = buff;
05818                 while (*cp) {
05819                         *dp = ToLower(*cp);
05820                         cp++;
05821                         dp++;
05822                 }
05823                 *dp = '\0';
05824                 hashadd(buff, (int *) fp, &mudstate.func_htab);
05825         }
05826         free_sbuf(buff);
05827         ufun_head = NULL;
05828         hashinit(&mudstate.ufunc_htab, 11);
05829 }
05830 
05831 void do_function(dbref player, dbref cause, int key, char *fname,
05832                                  char *target)
05833 {
05834         UFUN *ufp, *ufp2;
05835         ATTR *ap;
05836         char *np, *bp;
05837         int atr, aflags;
05838         dbref obj, aowner;
05839 
05840         /*
05841          * Make a local uppercase copy of the function name 
05842          */
05843 
05844         bp = np = alloc_sbuf("add_user_func");
05845         safe_sb_str(fname, np, &bp);
05846         *bp = '\0';
05847         for(bp = np; *bp; bp++)
05848                 *bp = ToLower(*bp);
05849 
05850         /*
05851          * Verify that the function doesn't exist in the builtin table 
05852          */
05853 
05854         if(hashfind(np, &mudstate.func_htab) != NULL) {
05855                 notify_quiet(player,
05856                                          "Function already defined in builtin function table.");
05857                 free_sbuf(np);
05858                 return;
05859         }
05860         /*
05861          * Make sure the target object exists 
05862          */
05863 
05864         if(!parse_attrib(player, target, &obj, &atr)) {
05865                 notify_quiet(player, "I don't see that here.");
05866                 free_sbuf(np);
05867                 return;
05868         }
05869         /*
05870          * Make sure the attribute exists 
05871          */
05872 
05873         if(atr == NOTHING) {
05874                 notify_quiet(player, "No such attribute.");
05875                 free_sbuf(np);
05876                 return;
05877         }
05878         /*
05879          * Make sure attribute is readably by me 
05880          */
05881 
05882         ap = atr_num(atr);
05883         if(!ap) {
05884                 notify_quiet(player, "No such attribute.");
05885                 free_sbuf(np);
05886                 return;
05887         }
05888         atr_get_info(obj, atr, &aowner, &aflags);
05889         if(!See_attr(player, obj, ap, aowner, aflags)) {
05890                 notify_quiet(player, "Permission denied.");
05891                 free_sbuf(np);
05892                 return;
05893         }
05894         /*
05895          * Privileged functions require you control the obj.  
05896          */
05897 
05898         if((key & FN_PRIV) && !Controls(player, obj)) {
05899                 notify_quiet(player, "Permission denied.");
05900                 free_sbuf(np);
05901                 return;
05902         }
05903         /*
05904          * See if function already exists.  If so, redefine it 
05905          */
05906 
05907         ufp = (UFUN *) hashfind(np, &mudstate.ufunc_htab);
05908 
05909         if(!ufp) {
05910                 ufp = (UFUN *) malloc(sizeof(UFUN));
05911                 ufp->name = strsave(np);
05912                 for(bp = (char *) ufp->name; *bp; bp++)
05913                         *bp = ToUpper(*bp);
05914                 ufp->obj = obj;
05915                 ufp->atr = atr;
05916                 ufp->perms = CA_PUBLIC;
05917                 ufp->next = NULL;
05918                 if(!ufun_head) {
05919                         ufun_head = ufp;
05920                 } else {
05921                         for(ufp2 = ufun_head; ufp2->next; ufp2 = ufp2->next);
05922                         ufp2->next = ufp;
05923                 }
05924                 hashadd(np, (int *) ufp, &mudstate.ufunc_htab);
05925         }
05926         ufp->obj = obj;
05927         ufp->atr = atr;
05928         ufp->flags = key;
05929         free_sbuf(np);
05930         if(!Quiet(player)) {
05931         char buffer[MBUF_SIZE];
05932         snprintf(buffer, MBUF_SIZE - 1, "Function %s defined.", fname);
05933         notify_quiet(player, buffer);
05934     }
05935 }
05936 
05937 /*
05938  * ---------------------------------------------------------------------------
05939  * * list_functable: List available functions.
05940  */
05941 
05942 void list_functable(dbref player)
05943 {
05944         FUN *fp;
05945         UFUN *ufp;
05946         char *buf, *bp, *cp;
05947 
05948         buf = alloc_lbuf("list_functable");
05949         bp = buf;
05950 
05951         /* Hardcoded Functions */
05952         for(cp = (char *) "Functions:"; *cp; cp++)
05953                 *bp++ = *cp;
05954         for(fp = flist; fp->name; fp++) {
05955                 if(check_access(player, fp->perms)) {
05956                         *bp++ = ' ';
05957                         for(cp = (char *) (fp->name); *cp; cp++)
05958                                 *bp++ = *cp;
05959                 }
05960         }
05961         *bp = '\0';
05962         notify(player, buf);
05963 
05964         /* User-Defined functions (via @function) */
05965         bp = buf;
05966         safe_str("User-Functions:", buf, &bp);
05967 
05968         for(ufp = ufun_head; ufp; ufp = ufp->next) {
05969                 if(check_access(player, ufp->perms)) {
05970                         *bp++ = ' ';
05971                         for(cp = (char *) (ufp->name); *cp; cp++)
05972                                 *bp++ = *cp;
05973                 }
05974         }
05975         *bp = '\0';
05976         notify(player, buf);
05977         free_lbuf(buf);
05978 }
05979 
05980 /*
05981  * ---------------------------------------------------------------------------
05982  * * cf_func_access: set access on functions
05983  */
05984 
05985 int cf_func_access(int *vp, char *str, long extra, dbref player, char *cmd)
05986 {
05987         FUN *fp;
05988         UFUN *ufp;
05989         char *ap;
05990 
05991         for(ap = str; *ap && !isspace(*ap); ap++);
05992         if(*ap)
05993                 *ap++ = '\0';
05994 
05995         for(fp = flist; fp->name; fp++) {
05996                 if(!string_compare(fp->name, str)) {
05997                         return (cf_modify_bits(&fp->perms, ap, extra, player, cmd));
05998                 }
05999         }
06000         for(ufp = ufun_head; ufp; ufp = ufp->next) {
06001                 if(!string_compare(ufp->name, str)) {
06002                         return (cf_modify_bits(&ufp->perms, ap, extra, player, cmd));
06003                 }
06004         }
06005         cf_log_notfound(player, cmd, "Function", str);
06006         return -1;
06007 }

Generated on Mon May 28 04:25:20 2007 for BattletechMUX by  doxygen 1.4.7