00001
00002
00003
00004
00005
00006 #include "copyright.h"
00007 #include "autoconf.h"
00008 #include "config.h"
00009 #include "externs.h"
00010
00011 #include <limits.h>
00012 #include <math.h>
00013
00014 #include "ansi.h"
00015 #include "attrs.h"
00016 #include "command.h"
00017 #include "comsys.h"
00018 #include "functions.h"
00019 #include "misc.h"
00020 #include "pcre.h"
00021 #ifdef REALITY_LVLS
00022 #include "levels.h"
00023 #endif
00024
00025
00026
00027
00028
00029
00030
00031
00032 bool parse_and_get_attrib(dbref executor, char *fargs[], char **atext, dbref *thing, char *buff, char **bufc)
00033 {
00034 ATTR *ap;
00035
00036
00037
00038 if (!parse_attrib(executor, fargs[0], thing, &ap))
00039 {
00040 *thing = executor;
00041 ap = atr_str(fargs[0]);
00042 }
00043
00044
00045
00046 if (!ap)
00047 {
00048 return false;
00049 }
00050
00051
00052
00053 if (!See_attr(executor, *thing, ap))
00054 {
00055 safe_noperm(buff, bufc);
00056 return false;
00057 }
00058
00059 dbref aowner;
00060 int aflags;
00061 *atext = atr_pget(*thing, ap->number, &aowner, &aflags);
00062 if (!*atext)
00063 {
00064 return false;
00065 }
00066 else if (!**atext)
00067 {
00068 free_lbuf(*atext);
00069 return false;
00070 }
00071 return true;
00072 }
00073
00074 #define CWHO_ON 0
00075 #define CWHO_OFF 1
00076 #define CWHO_ALL 2
00077
00078 FUNCTION(fun_cwho)
00079 {
00080 UNUSED_PARAMETER(caller);
00081 UNUSED_PARAMETER(enactor);
00082 UNUSED_PARAMETER(cargs);
00083 UNUSED_PARAMETER(ncargs);
00084
00085 struct channel *ch = select_channel(fargs[0]);
00086 if (!ch)
00087 {
00088 safe_str("#-1 CHANNEL NOT FOUND", buff, bufc);
00089 return;
00090 }
00091 if ( !mudconf.have_comsys
00092 || ( !Comm_All(executor)
00093 && executor != ch->charge_who))
00094 {
00095 safe_noperm(buff, bufc);
00096 return;
00097 }
00098
00099 int match_type = CWHO_ON;
00100 if (nfargs == 2)
00101 {
00102 if (mux_stricmp(fargs[1], "all") == 0)
00103 {
00104 match_type = CWHO_ALL;
00105 }
00106 else if (mux_stricmp(fargs[1], "off") == 0)
00107 {
00108 match_type = CWHO_OFF;
00109 }
00110 else if (mux_stricmp(fargs[1], "on") == 0)
00111 {
00112 match_type = CWHO_ON;
00113 }
00114 }
00115
00116 ITL pContext;
00117 struct comuser *user;
00118 ItemToList_Init(&pContext, buff, bufc, '#');
00119 for (user = ch->on_users; user; user = user->on_next)
00120 {
00121 if ( ( match_type == CWHO_ALL
00122 || ( (Connected(user->who) || isThing(user->who))
00123 && ( (match_type == CWHO_ON && user->bUserIsOn)
00124 || (match_type == CWHO_OFF && !(user->bUserIsOn)))))
00125 && !ItemToList_AddInteger(&pContext, user->who))
00126 {
00127 break;
00128 }
00129 }
00130 ItemToList_Final(&pContext);
00131 }
00132
00133 FUNCTION(fun_beep)
00134 {
00135 UNUSED_PARAMETER(executor);
00136 UNUSED_PARAMETER(caller);
00137 UNUSED_PARAMETER(enactor);
00138 UNUSED_PARAMETER(fargs);
00139 UNUSED_PARAMETER(nfargs);
00140 UNUSED_PARAMETER(cargs);
00141 UNUSED_PARAMETER(ncargs);
00142
00143 safe_chr(BEEP_CHAR, buff, bufc);
00144 }
00145
00146 #define ANSI_F 0x00000001
00147 #define ANSI_H 0x00000002
00148 #define ANSI_U 0x00000004
00149 #define ANSI_I 0x00000008
00150 #define ANSI_FC 0x00000010
00151 #define ANSI_BC 0x00000020
00152
00153 static const unsigned char ansi_have_table[256] =
00154 {
00155 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00156 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00157 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00158 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00159 0, 0, ANSI_BC, ANSI_BC,
00160 0, 0, 0, ANSI_BC,
00161 0, 0, 0, 0,
00162 0, ANSI_BC, 0, 0,
00163 0, 0, ANSI_BC, 0,
00164 0, 0, 0, ANSI_BC,
00165 ANSI_BC, ANSI_BC, 0, 0,
00166 0, 0, 0, 0,
00167 0, 0, ANSI_FC, ANSI_FC,
00168 0, 0, ANSI_F, ANSI_FC,
00169 ANSI_H, ANSI_I, 0, 0,
00170 0, ANSI_FC, 0, 0,
00171 0, 0, ANSI_FC, 0,
00172 0, ANSI_U, 0, ANSI_FC,
00173 ANSI_FC, ANSI_FC, 0, 0,
00174 0, 0, 0, 0,
00175 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00176 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00177 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00178 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00179 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00180 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00181 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00182 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
00183 };
00184
00185 static void SimplifyColorLetters(char *pOut, char *pIn)
00186 {
00187 if ( pIn[0] == 'n'
00188 && pIn[1] == '\0')
00189 {
00190 pOut[0] = 'n';
00191 pOut[1] = '\0';
00192 return;
00193 }
00194 char *p;
00195 int have = 0;
00196 size_t nIn = strlen(pIn);
00197 for (p = pIn + nIn - 1; p >= pIn && *p != 'n'; p--)
00198 {
00199 int mask = ansi_have_table[(unsigned char)*p];
00200 if ( mask
00201 && (have & mask) == 0)
00202 {
00203 *pOut++ = *p;
00204 have |= mask;
00205 }
00206 }
00207 *pOut = '\0';
00208 }
00209
00210
00211
00212 FUNCTION(fun_ansi)
00213 {
00214 UNUSED_PARAMETER(executor);
00215 UNUSED_PARAMETER(caller);
00216 UNUSED_PARAMETER(enactor);
00217 UNUSED_PARAMETER(cargs);
00218 UNUSED_PARAMETER(ncargs);
00219
00220 int iArg0;
00221 for (iArg0 = 0; iArg0 + 1 < nfargs; iArg0 += 2)
00222 {
00223 char pOut[8];
00224 SimplifyColorLetters(pOut, fargs[iArg0]);
00225 char tmp[LBUF_SIZE];
00226 char *bp = tmp;
00227
00228 char *s = pOut;
00229 while (*s)
00230 {
00231 const char *pColor = ColorTable[(unsigned char)*s];
00232 if (pColor)
00233 {
00234 safe_str(pColor, tmp, &bp);
00235 }
00236 s++;
00237 }
00238 safe_str(fargs[iArg0+1], tmp, &bp);
00239 *bp = '\0';
00240 int nVisualWidth;
00241 size_t nBufferAvailable = LBUF_SIZE - (*bufc - buff) - 1;
00242 size_t nLen = ANSI_TruncateToField(tmp, nBufferAvailable, *bufc,
00243 LBUF_SIZE, &nVisualWidth, ANSI_ENDGOAL_NORMAL);
00244 *bufc += nLen;
00245 }
00246 }
00247
00248 FUNCTION(fun_zone)
00249 {
00250 UNUSED_PARAMETER(caller);
00251 UNUSED_PARAMETER(enactor);
00252 UNUSED_PARAMETER(nfargs);
00253 UNUSED_PARAMETER(cargs);
00254 UNUSED_PARAMETER(ncargs);
00255
00256 if (!mudconf.have_zones)
00257 {
00258 safe_str("#-1 ZONES DISABLED", buff, bufc);
00259 return;
00260 }
00261 dbref it = match_thing_quiet(executor, fargs[0]);
00262 if (!Good_obj(it))
00263 {
00264 safe_match_result(it, buff, bufc);
00265 }
00266 else if (Examinable(executor, it))
00267 {
00268 safe_tprintf_str(buff, bufc, "#%d", Zone(it));
00269 }
00270 else
00271 {
00272 safe_nothing(buff, bufc);
00273 }
00274 }
00275
00276 #ifdef SIDE_EFFECT_FUNCTIONS
00277
00278 static bool check_command(dbref player, char *name, char *buff, char **bufc)
00279 {
00280 CMDENT *cmdp = (CMDENT *)hashfindLEN(name, strlen(name), &mudstate.command_htab);
00281 if (cmdp)
00282 {
00283
00284
00285
00286
00287 if ( Invalid_Objtype(player)
00288 || !check_access(player, cmdp->perms)
00289 || ( !Builder(player)
00290 && Protect(CA_GBL_BUILD)
00291 && !(mudconf.control_flags & CF_BUILD)))
00292 {
00293 safe_noperm(buff, bufc);
00294 return true;
00295 }
00296 }
00297 return false;
00298 }
00299
00300 FUNCTION(fun_link)
00301 {
00302 UNUSED_PARAMETER(nfargs);
00303 UNUSED_PARAMETER(cargs);
00304 UNUSED_PARAMETER(ncargs);
00305
00306 if (check_command(executor, "@link", buff, bufc))
00307 {
00308 return;
00309 }
00310 do_link(executor, caller, enactor, 0, 2, fargs[0], fargs[1]);
00311 }
00312
00313 FUNCTION(fun_tel)
00314 {
00315 UNUSED_PARAMETER(nfargs);
00316 UNUSED_PARAMETER(cargs);
00317 UNUSED_PARAMETER(ncargs);
00318
00319 if (check_command(executor, "@teleport", buff, bufc))
00320 {
00321 return;
00322 }
00323 do_teleport(executor, caller, enactor, 0, 2, fargs[0], fargs[1]);
00324 }
00325
00326 FUNCTION(fun_pemit)
00327 {
00328 UNUSED_PARAMETER(caller);
00329 UNUSED_PARAMETER(enactor);
00330 UNUSED_PARAMETER(nfargs);
00331 UNUSED_PARAMETER(cargs);
00332 UNUSED_PARAMETER(ncargs);
00333
00334 if (check_command(executor, "@pemit", buff, bufc))
00335 {
00336 return;
00337 }
00338 do_pemit_list(executor, PEMIT_PEMIT, false, 0, fargs[0], 0, fargs[1]);
00339 }
00340
00341 FUNCTION(fun_oemit)
00342 {
00343 UNUSED_PARAMETER(caller);
00344 UNUSED_PARAMETER(enactor);
00345 UNUSED_PARAMETER(nfargs);
00346 UNUSED_PARAMETER(cargs);
00347 UNUSED_PARAMETER(ncargs);
00348
00349 if (check_command(executor, "@oemit", buff, bufc))
00350 {
00351 return;
00352 }
00353 do_pemit_single(executor, PEMIT_OEMIT, false, 0, fargs[0], 0, fargs[1]);
00354 }
00355
00356 FUNCTION(fun_emit)
00357 {
00358 UNUSED_PARAMETER(nfargs);
00359 UNUSED_PARAMETER(cargs);
00360 UNUSED_PARAMETER(ncargs);
00361
00362 if (check_command(executor, "@emit", buff, bufc))
00363 {
00364 return;
00365 }
00366 do_say(executor, caller, enactor, SAY_EMIT, fargs[0]);
00367 }
00368
00369 FUNCTION(fun_remit)
00370 {
00371 UNUSED_PARAMETER(caller);
00372 UNUSED_PARAMETER(enactor);
00373 UNUSED_PARAMETER(nfargs);
00374 UNUSED_PARAMETER(cargs);
00375 UNUSED_PARAMETER(ncargs);
00376
00377 if (check_command(executor, "@pemit", buff, bufc))
00378 {
00379 return;
00380 }
00381 do_pemit_single(executor, PEMIT_PEMIT, true, 0, fargs[0], 0, fargs[1]);
00382 }
00383
00384 FUNCTION(fun_cemit)
00385 {
00386 UNUSED_PARAMETER(cargs);
00387 UNUSED_PARAMETER(ncargs);
00388
00389 if (check_command(executor, "@cemit", buff, bufc))
00390 {
00391 return;
00392 }
00393 do_cemit(executor, caller, enactor, 0, nfargs, fargs[0], fargs[1]);
00394 }
00395
00396
00397
00398
00399 FUNCTION(fun_create)
00400 {
00401 SEP sep;
00402 if (!OPTIONAL_DELIM(3, sep, DELIM_DFLT))
00403 {
00404 return;
00405 }
00406
00407 char *name = fargs[0];
00408
00409 if (!name || !*name)
00410 {
00411 safe_str("#-1 ILLEGAL NAME", buff, bufc);
00412 return;
00413 }
00414 if (nfargs >= 3 && *fargs[2])
00415 {
00416 sep.str[0] = *fargs[2];
00417 }
00418 else
00419 {
00420 sep.str[0] = 't';
00421 }
00422
00423 dbref thing;
00424 int cost;
00425
00426 switch (sep.str[0])
00427 {
00428 case 'r':
00429
00430 if (check_command(executor, "@dig", buff, bufc))
00431 {
00432 return;
00433 }
00434 thing = create_obj(executor, TYPE_ROOM, name, 0);
00435 if (thing != NOTHING)
00436 {
00437 local_data_create(thing);
00438 }
00439 break;
00440
00441 case 'e':
00442
00443 if (check_command(executor, "@open", buff, bufc))
00444 {
00445 return;
00446 }
00447 thing = create_obj(executor, TYPE_EXIT, name, 0);
00448 if (thing != NOTHING)
00449 {
00450 s_Exits(thing, executor);
00451 s_Next(thing, Exits(executor));
00452 s_Exits(executor, thing);
00453 local_data_create(thing);
00454 }
00455 break;
00456
00457 default:
00458
00459 if (check_command(executor, "@create", buff, bufc))
00460 {
00461 return;
00462 }
00463 if (*fargs[1])
00464 {
00465 cost = mux_atol(fargs[1]);
00466 if ( cost < mudconf.createmin
00467 || mudconf.createmax < cost)
00468 {
00469 safe_range(buff, bufc);
00470 return;
00471 }
00472 }
00473 else
00474 {
00475 cost = mudconf.createmin;
00476 }
00477 thing = create_obj(executor, TYPE_THING, name, cost);
00478 if (thing != NOTHING)
00479 {
00480 move_via_generic(thing, executor, NOTHING, 0);
00481 s_Home(thing, new_home(executor));
00482 local_data_create(thing);
00483 }
00484 break;
00485 }
00486 safe_tprintf_str(buff, bufc, "#%d", thing);
00487 }
00488
00489 FUNCTION(fun_textfile)
00490 {
00491 UNUSED_PARAMETER(caller);
00492 UNUSED_PARAMETER(enactor);
00493 UNUSED_PARAMETER(nfargs);
00494 UNUSED_PARAMETER(cargs);
00495 UNUSED_PARAMETER(ncargs);
00496
00497 mux_strlwr(fargs[0]);
00498
00499 CMDENT_ONE_ARG *cmdp = (CMDENT_ONE_ARG *)hashfindLEN(fargs[0],
00500 strlen(fargs[0]), &mudstate.command_htab);
00501 if ( !cmdp
00502 || cmdp->handler != do_help)
00503 {
00504 safe_str("#-1 NOT FOUND", buff, bufc);
00505 return;
00506 }
00507
00508 if (check_command(executor, fargs[0], buff, bufc))
00509 {
00510 return;
00511 }
00512
00513 help_helper(executor, cmdp->extra, fargs[1], buff, bufc);
00514 }
00515
00516
00517
00518
00519
00520 static void set_attr_internal(dbref player, dbref thing, int attrnum, char *attrtext, int key, char *buff, char **bufc)
00521 {
00522 if (!Good_obj(thing))
00523 {
00524 safe_noperm(buff, bufc);
00525 notify_quiet(player, "You shouldn't be rummaging through the garbage.");
00526 return;
00527 }
00528
00529 dbref aowner;
00530 int aflags;
00531 ATTR *pattr = atr_num(attrnum);
00532 atr_pget_info(thing, attrnum, &aowner, &aflags);
00533 if ( pattr
00534 && bCanSetAttr(player, thing, pattr))
00535 {
00536 bool could_hear = Hearer(thing);
00537 atr_add(thing, attrnum, attrtext, Owner(player), aflags);
00538 handle_ears(thing, could_hear, Hearer(thing));
00539 if ( !(key & SET_QUIET)
00540 && !Quiet(player)
00541 && !Quiet(thing))
00542 {
00543 notify_quiet(player, "Set.");
00544 }
00545 }
00546 else
00547 {
00548 safe_noperm(buff, bufc);
00549 }
00550 }
00551
00552 FUNCTION(fun_set)
00553 {
00554 UNUSED_PARAMETER(caller);
00555 UNUSED_PARAMETER(enactor);
00556 UNUSED_PARAMETER(nfargs);
00557 UNUSED_PARAMETER(cargs);
00558 UNUSED_PARAMETER(ncargs);
00559
00560 if (check_command(executor, "@set", buff, bufc))
00561 {
00562 return;
00563 }
00564
00565 dbref thing, aowner;
00566 int aflags;
00567 ATTR *pattr;
00568
00569
00570
00571
00572 if (parse_attrib(executor, fargs[0], &thing, &pattr))
00573 {
00574 if ( pattr
00575 && See_attr(executor, thing, pattr))
00576 {
00577 char *flagname = fargs[1];
00578
00579
00580
00581 if (flagname[0] == '\0')
00582 {
00583 safe_str("#-1 UNSPECIFIED PARAMETER", buff, bufc);
00584 return;
00585 }
00586
00587
00588
00589 bool clear = false;
00590 if (flagname[0] == NOT_TOKEN)
00591 {
00592 flagname++;
00593 clear = true;
00594 }
00595
00596
00597
00598 int flagvalue;
00599 if (!search_nametab(executor, indiv_attraccess_nametab, flagname, &flagvalue))
00600 {
00601 safe_str("#-1 CANNOT SET", buff, bufc);
00602 return;
00603 }
00604
00605
00606
00607 if (!atr_get_info(thing, pattr->number, &aowner, &aflags))
00608 {
00609 safe_str("#-1 ATTRIBUTE NOT PRESENT ON OBJECT", buff, bufc);
00610 return;
00611 }
00612
00613
00614
00615 if (!bCanSetAttr(executor, thing, pattr))
00616 {
00617 safe_noperm(buff, bufc);
00618 return;
00619 }
00620
00621
00622
00623 if (clear)
00624 {
00625 aflags &= ~flagvalue;
00626 }
00627 else
00628 {
00629 aflags |= flagvalue;
00630 }
00631 atr_set_flags(thing, pattr->number, aflags);
00632 return;
00633 }
00634 }
00635
00636
00637
00638 thing = match_controlled_quiet(executor, fargs[0]);
00639 if (!Good_obj(thing))
00640 {
00641 safe_nothing(buff, bufc);
00642 return;
00643 }
00644
00645
00646
00647 char *p;
00648 for (p = fargs[1]; *p && *p != ':'; p++)
00649 {
00650 ;
00651 }
00652
00653 if (*p)
00654 {
00655 *p++ = 0;
00656 int atr = mkattr(executor, fargs[1]);
00657 if (atr <= 0)
00658 {
00659 safe_str("#-1 UNABLE TO CREATE ATTRIBUTE", buff, bufc);
00660 return;
00661 }
00662 pattr = atr_num(atr);
00663 if (!pattr)
00664 {
00665 safe_noperm(buff, bufc);
00666 return;
00667 }
00668 if (!bCanSetAttr(executor, thing, pattr))
00669 {
00670 safe_noperm(buff, bufc);
00671 return;
00672 }
00673 char *buff2 = alloc_lbuf("fun_set");
00674
00675
00676
00677 if (*p == '_')
00678 {
00679 ATTR *pattr2;
00680 dbref thing2;
00681
00682 strcpy(buff2, p + 1);
00683 if (!( parse_attrib(executor, p + 1, &thing2, &pattr2)
00684 && pattr2))
00685 {
00686 free_lbuf(buff2);
00687 safe_nomatch(buff, bufc);
00688 return;
00689 }
00690 p = buff2;
00691 atr_pget_str(buff2, thing2, pattr2->number, &aowner, &aflags);
00692
00693 if (!See_attr(executor, thing2, pattr2))
00694 {
00695 free_lbuf(buff2);
00696 safe_noperm(buff, bufc);
00697 return;
00698 }
00699 }
00700
00701
00702
00703 set_attr_internal(executor, thing, atr, p, 0, buff, bufc);
00704 free_lbuf(buff2);
00705 return;
00706 }
00707
00708
00709
00710 flag_set(thing, executor, fargs[1], 0);
00711 }
00712 #endif
00713
00714
00715
00716 static unsigned int GenCode(char *pCode, const char *pCodeASCII)
00717 {
00718
00719
00720 size_t nIn;
00721 char *pIn = strip_ansi(pCodeASCII, &nIn);
00722
00723
00724
00725 char *pOut = pCode;
00726 while (*pIn)
00727 {
00728 unsigned char ch = *pIn;
00729 if ( ' ' <= ch
00730 && ch <= '~')
00731 {
00732 *pOut++ = ch - ' ';
00733 }
00734 pIn++;
00735 }
00736 *pOut = '\0';
00737 return pOut - pCode;
00738 }
00739
00740 static char *crypt_code(char *code, char *text, bool type)
00741 {
00742 if ( !text
00743 || text[0] == '\0')
00744 {
00745 return "";
00746 }
00747 if ( !code
00748 || code[0] == '\0')
00749 {
00750 return text;
00751 }
00752
00753 char codebuff[LBUF_SIZE];
00754 unsigned int nCode = GenCode(codebuff, code);
00755 if (nCode == 0)
00756 {
00757 return text;
00758 }
00759
00760 static char textbuff[LBUF_SIZE];
00761 char *p = strip_ansi(text);
00762 char *q = codebuff;
00763 unsigned int nq = nCode;
00764 char *r = textbuff;
00765
00766 int iMod = '~' - ' ' + 1;
00767
00768
00769
00770 while (*p)
00771 {
00772 unsigned char ch = *p;
00773 if ( ' ' <= ch
00774 && ch <= '~')
00775 {
00776 int iCode = ch - ' ';
00777 if (type)
00778 {
00779 iCode += *q;
00780 if (iMod <= iCode)
00781 {
00782 iCode -= iMod;
00783 }
00784 }
00785 else
00786 {
00787 iCode -= *q;
00788 if (iCode < 0)
00789 {
00790 iCode += iMod;
00791 }
00792 }
00793 *r++ = iCode + ' ';
00794 q++;
00795 nq--;
00796 if (0 == nq)
00797 {
00798 q = codebuff;
00799 nq = nCode;
00800 }
00801 }
00802 p++;
00803 }
00804 *r = '\0';
00805 return textbuff;
00806 }
00807
00808
00809
00810
00811 FUNCTION(fun_encrypt)
00812 {
00813 UNUSED_PARAMETER(executor);
00814 UNUSED_PARAMETER(caller);
00815 UNUSED_PARAMETER(enactor);
00816 UNUSED_PARAMETER(nfargs);
00817 UNUSED_PARAMETER(cargs);
00818 UNUSED_PARAMETER(ncargs);
00819
00820 safe_str(crypt_code(fargs[1], fargs[0], true), buff, bufc);
00821 }
00822
00823 FUNCTION(fun_decrypt)
00824 {
00825 UNUSED_PARAMETER(executor);
00826 UNUSED_PARAMETER(caller);
00827 UNUSED_PARAMETER(enactor);
00828 UNUSED_PARAMETER(nfargs);
00829 UNUSED_PARAMETER(cargs);
00830 UNUSED_PARAMETER(ncargs);
00831
00832 safe_str(crypt_code(fargs[1], fargs[0], false), buff, bufc);
00833 }
00834
00835
00836
00837 static void scan_zone
00838 (
00839 dbref executor,
00840 char *szZone,
00841 int ObjectType,
00842 char *buff,
00843 char **bufc
00844 )
00845 {
00846 if (!mudconf.have_zones)
00847 {
00848 safe_str("#-1 ZONES DISABLED", buff, bufc);
00849 return;
00850 }
00851
00852 dbref it = match_thing_quiet(executor, szZone);
00853 if (!Good_obj(it))
00854 {
00855 safe_match_result(it, buff, bufc);
00856 return;
00857 }
00858 else if (!( WizRoy(executor)
00859 || Controls(executor, it)))
00860 {
00861 safe_noperm(buff, bufc);
00862 return;
00863 }
00864
00865 dbref i;
00866 ITL pContext;
00867 ItemToList_Init(&pContext, buff, bufc, '#');
00868 DO_WHOLE_DB(i)
00869 {
00870 if ( Typeof(i) == ObjectType
00871 && Zone(i) == it
00872 && !ItemToList_AddInteger(&pContext, i))
00873 {
00874 break;
00875 }
00876 }
00877 ItemToList_Final(&pContext);
00878 }
00879
00880 FUNCTION(fun_zwho)
00881 {
00882 UNUSED_PARAMETER(caller);
00883 UNUSED_PARAMETER(enactor);
00884 UNUSED_PARAMETER(nfargs);
00885 UNUSED_PARAMETER(cargs);
00886 UNUSED_PARAMETER(ncargs);
00887
00888 scan_zone(executor, fargs[0], TYPE_PLAYER, buff, bufc);
00889 }
00890
00891 FUNCTION(fun_inzone)
00892 {
00893 UNUSED_PARAMETER(caller);
00894 UNUSED_PARAMETER(enactor);
00895 UNUSED_PARAMETER(nfargs);
00896 UNUSED_PARAMETER(cargs);
00897 UNUSED_PARAMETER(ncargs);
00898
00899 scan_zone(executor, fargs[0], TYPE_ROOM, buff, bufc);
00900 }
00901
00902
00903
00904 FUNCTION(fun_children)
00905 {
00906 UNUSED_PARAMETER(caller);
00907 UNUSED_PARAMETER(enactor);
00908 UNUSED_PARAMETER(nfargs);
00909 UNUSED_PARAMETER(cargs);
00910 UNUSED_PARAMETER(ncargs);
00911
00912 dbref it = match_thing_quiet(executor, fargs[0]);
00913 if (!Good_obj(it))
00914 {
00915 safe_match_result(it, buff, bufc);
00916 return;
00917 }
00918 else if (!( WizRoy(executor)
00919 || Controls(executor, it)))
00920 {
00921 safe_noperm(buff, bufc);
00922 return;
00923 }
00924
00925 dbref i;
00926 ITL pContext;
00927 ItemToList_Init(&pContext, buff, bufc, '#');
00928 DO_WHOLE_DB(i)
00929 {
00930 if ( Parent(i) == it
00931 && !ItemToList_AddInteger(&pContext, i))
00932 {
00933 break;
00934 }
00935 }
00936 ItemToList_Final(&pContext);
00937 }
00938
00939 FUNCTION(fun_objeval)
00940 {
00941 UNUSED_PARAMETER(nfargs);
00942
00943 if (!*fargs[0])
00944 {
00945 return;
00946 }
00947 char *name = alloc_lbuf("fun_objeval");
00948 char *bp = name;
00949 char *str = fargs[0];
00950 mux_exec(name, &bp, executor, caller, enactor,
00951 EV_FCHECK | EV_STRIP_CURLY | EV_EVAL, &str, cargs, ncargs);
00952 *bp = '\0';
00953
00954 dbref obj = match_thing_quiet(executor, name);
00955 free_lbuf(name);
00956 if (!Good_obj(obj))
00957 {
00958 safe_match_result(obj, buff, bufc);
00959 return;
00960 }
00961
00962 if (!Controls(executor, obj))
00963 {
00964
00965
00966
00967
00968 obj = executor;
00969 }
00970
00971 mudstate.nObjEvalNest++;
00972 str = fargs[1];
00973 mux_exec(buff, bufc, obj, executor, enactor,
00974 EV_FCHECK | EV_STRIP_CURLY | EV_EVAL, &str, cargs, ncargs);
00975 mudstate.nObjEvalNest--;
00976 }
00977
00978 FUNCTION(fun_localize)
00979 {
00980 UNUSED_PARAMETER(nfargs);
00981
00982 char **preserve = NULL;
00983 int *preserve_len = NULL;
00984 preserve = PushPointers(MAX_GLOBAL_REGS);
00985 preserve_len = PushIntegers(MAX_GLOBAL_REGS);
00986 save_global_regs("fun_localize", preserve, preserve_len);
00987
00988 char *str = fargs[0];
00989 mux_exec(buff, bufc, executor, caller, enactor,
00990 EV_FCHECK | EV_STRIP_CURLY | EV_EVAL, &str, cargs, ncargs);
00991
00992 restore_global_regs("fun_localize", preserve, preserve_len);
00993 PopIntegers(preserve_len, MAX_GLOBAL_REGS);
00994 PopPointers(preserve, MAX_GLOBAL_REGS);
00995 }
00996
00997 FUNCTION(fun_null)
00998 {
00999 UNUSED_PARAMETER(buff);
01000 UNUSED_PARAMETER(bufc);
01001 UNUSED_PARAMETER(executor);
01002 UNUSED_PARAMETER(caller);
01003 UNUSED_PARAMETER(enactor);
01004 UNUSED_PARAMETER(fargs);
01005 UNUSED_PARAMETER(nfargs);
01006 UNUSED_PARAMETER(cargs);
01007 UNUSED_PARAMETER(ncargs);
01008
01009 return;
01010 }
01011
01012 FUNCTION(fun_squish)
01013 {
01014 UNUSED_PARAMETER(executor);
01015 UNUSED_PARAMETER(caller);
01016 UNUSED_PARAMETER(enactor);
01017 UNUSED_PARAMETER(cargs);
01018 UNUSED_PARAMETER(ncargs);
01019
01020 if (nfargs == 0)
01021 {
01022 return;
01023 }
01024
01025 SEP sep;
01026 if (!OPTIONAL_DELIM(2, sep, DELIM_DFLT))
01027 {
01028 return;
01029 }
01030
01031 char *p;
01032 char *q = fargs[0];
01033 while ((p = strchr(q, sep.str[0])) != NULL)
01034 {
01035 p = p + 1;
01036 size_t nLen = p - q;
01037 safe_copy_buf(q, nLen, buff, bufc);
01038 q = p;
01039 while (*q == sep.str[0])
01040 {
01041 q++;
01042 }
01043 }
01044 safe_str(q, buff, bufc);
01045 }
01046
01047 FUNCTION(fun_stripansi)
01048 {
01049 UNUSED_PARAMETER(executor);
01050 UNUSED_PARAMETER(caller);
01051 UNUSED_PARAMETER(enactor);
01052 UNUSED_PARAMETER(nfargs);
01053 UNUSED_PARAMETER(cargs);
01054 UNUSED_PARAMETER(ncargs);
01055
01056 safe_str(strip_ansi(fargs[0]), buff, bufc);
01057 }
01058
01059
01060
01061 FUNCTION(fun_zfun)
01062 {
01063 UNUSED_PARAMETER(caller);
01064 UNUSED_PARAMETER(cargs);
01065 UNUSED_PARAMETER(ncargs);
01066
01067 if (!mudconf.have_zones)
01068 {
01069 safe_str("#-1 ZONES DISABLED", buff, bufc);
01070 return;
01071 }
01072
01073 dbref zone = Zone(executor);
01074 if (!Good_obj(zone))
01075 {
01076 safe_str("#-1 INVALID ZONE", buff, bufc);
01077 return;
01078 }
01079
01080
01081
01082 int attrib = get_atr(fargs[0]);
01083 if (!attrib)
01084 {
01085 safe_str("#-1 NO SUCH USER FUNCTION", buff, bufc);
01086 return;
01087 }
01088 dbref aowner;
01089 int aflags;
01090 ATTR *pattr = atr_num(attrib);
01091 char *tbuf1 = atr_pget(zone, attrib, &aowner, &aflags);
01092 if ( !pattr
01093 || !See_attr(executor, zone, pattr))
01094 {
01095 safe_noperm(buff, bufc);
01096 free_lbuf(tbuf1);
01097 return;
01098 }
01099 char *str = tbuf1;
01100 mux_exec(buff, bufc, zone, executor, enactor,
01101 EV_EVAL | EV_STRIP_CURLY | EV_FCHECK, &str, &(fargs[1]), nfargs - 1);
01102 free_lbuf(tbuf1);
01103 }
01104
01105 FUNCTION(fun_columns)
01106 {
01107 SEP sep;
01108 if (!OPTIONAL_DELIM(3, sep, DELIM_STRING))
01109 {
01110 return;
01111 }
01112
01113 int nWidth = mux_atol(fargs[1]);
01114 int nIndent = 0;
01115 if (nfargs == 4)
01116 {
01117 nIndent = mux_atol(fargs[3]);
01118 if (nIndent < 0 || 77 < nIndent)
01119 {
01120 nIndent = 1;
01121 }
01122 }
01123
01124 int nRight = nIndent + nWidth;
01125 if ( nWidth < 1
01126 || 78 < nWidth
01127 || nRight < 1
01128 || 78 < nRight)
01129 {
01130 safe_range(buff, bufc);
01131 return;
01132 }
01133
01134 char *cp = trim_space_sep(fargs[0], &sep);
01135 if (!*cp)
01136 {
01137 return;
01138 }
01139
01140 int nColumns = (78-nIndent)/nWidth;
01141 int iColumn = 0;
01142
01143 int nBufferAvailable = LBUF_SIZE - (*bufc-buff) - 1;
01144 bool bNeedCRLF = false;
01145 while ( cp
01146 && 0 < nBufferAvailable)
01147 {
01148 if (iColumn == 0)
01149 {
01150 nBufferAvailable -= safe_fill(buff, bufc, ' ', nIndent);
01151 }
01152
01153 char *objstring = split_token(&cp, &sep);
01154 int nVisualWidth;
01155 int nLen = ANSI_TruncateToField(objstring, nBufferAvailable, *bufc,
01156 nWidth, &nVisualWidth, ANSI_ENDGOAL_NORMAL);
01157 *bufc += nLen;
01158 nBufferAvailable -= nLen;
01159
01160 if (nColumns-1 <= iColumn)
01161 {
01162 iColumn = 0;
01163 nBufferAvailable -= safe_copy_buf("\r\n", 2, buff, bufc);
01164 bNeedCRLF = false;
01165 }
01166 else
01167 {
01168 iColumn++;
01169 nBufferAvailable -= safe_fill(buff, bufc, ' ',
01170 nWidth - nVisualWidth);
01171 bNeedCRLF = true;
01172 }
01173 }
01174 if (bNeedCRLF)
01175 {
01176 safe_copy_buf("\r\n", 2, buff, bufc);
01177 }
01178 }
01179
01180
01181
01182
01183
01184
01185
01186 FUNCTION(fun_table)
01187 {
01188 UNUSED_PARAMETER(executor);
01189 UNUSED_PARAMETER(caller);
01190 UNUSED_PARAMETER(enactor);
01191 UNUSED_PARAMETER(cargs);
01192 UNUSED_PARAMETER(ncargs);
01193
01194
01195
01196 char *pPaddingStart = NULL;
01197 char *pPaddingEnd = NULL;
01198 if (nfargs == 6 && *fargs[5])
01199 {
01200 pPaddingStart = strip_ansi(fargs[5]);
01201 pPaddingEnd = strchr(pPaddingStart, '\0');
01202 }
01203
01204
01205
01206 char cSeparator = ' ';
01207 if (nfargs >= 5 && fargs[4][0] != '\0')
01208 {
01209 if (fargs[4][1] == '\0')
01210 {
01211 cSeparator = *fargs[4];
01212 }
01213 else
01214 {
01215 safe_str("#-1 SEPARATOR MUST BE ONE CHARACTER", buff, bufc);
01216 return;
01217 }
01218 }
01219
01220
01221
01222 char cDelimiter = ' ';
01223 if (nfargs >= 4 && fargs[3][0] != '\0')
01224 {
01225 if (fargs[3][1] == '\0')
01226 {
01227 cDelimiter = *fargs[3];
01228 }
01229 else
01230 {
01231 safe_str("#-1 DELIMITER MUST BE ONE CHARACTER", buff, bufc);
01232 return;
01233 }
01234 }
01235
01236
01237
01238 int nLineLength = 78;
01239 if (nfargs >= 3)
01240 {
01241 nLineLength = mux_atol(fargs[2]);
01242 }
01243
01244
01245
01246 int nFieldWidth = 10;
01247 if (nfargs >= 2)
01248 {
01249 nFieldWidth = mux_atol(fargs[1]);
01250 }
01251 else
01252 {
01253 nFieldWidth = 10;
01254 }
01255
01256
01257
01258 if ( nLineLength < 1
01259 || LBUF_SIZE <= nLineLength
01260 || nFieldWidth < 1
01261 || nLineLength < nFieldWidth)
01262 {
01263 safe_range(buff, bufc);
01264 return;
01265 }
01266
01267 int nNumCols = nLineLength / nFieldWidth;
01268 SEP sep;
01269 sep.n = 1;
01270 sep.str[0] = cDelimiter;
01271 char *pNext = trim_space_sep(fargs[0], &sep);
01272 if (!*pNext)
01273 {
01274 return;
01275 }
01276
01277 char *pCurrent = split_token(&pNext, &sep);
01278 if (!pCurrent)
01279 {
01280 return;
01281 }
01282
01283 int nBufferAvailable = LBUF_SIZE - (*bufc - buff) - 1;
01284 int nCurrentCol = nNumCols - 1;
01285 for (;;)
01286 {
01287 int nVisibleLength, nPaddingLength;
01288 int nStringLength =
01289 ANSI_TruncateToField( pCurrent, nBufferAvailable, *bufc,
01290 nFieldWidth, &nVisibleLength, ANSI_ENDGOAL_NORMAL);
01291
01292 *bufc += nStringLength;
01293 nBufferAvailable -= nStringLength;
01294
01295 nPaddingLength = nFieldWidth - nVisibleLength;
01296 if (nPaddingLength > nBufferAvailable)
01297 {
01298 nPaddingLength = nBufferAvailable;
01299 }
01300 if (nPaddingLength)
01301 {
01302 nBufferAvailable -= nPaddingLength;
01303 if (pPaddingStart)
01304 {
01305 for ( char *pPaddingCurrent = pPaddingStart;
01306 nPaddingLength > 0;
01307 nPaddingLength--)
01308 {
01309 **bufc = *pPaddingCurrent;
01310 (*bufc)++;
01311 pPaddingCurrent++;
01312
01313 if (pPaddingCurrent == pPaddingEnd)
01314 {
01315 pPaddingCurrent = pPaddingStart;
01316 }
01317 }
01318 }
01319 else
01320 {
01321 memset(*bufc, ' ', nPaddingLength);
01322 *bufc += nPaddingLength;
01323 }
01324 }
01325
01326 pCurrent = split_token(&pNext, &sep);
01327 if (!pCurrent)
01328 {
01329 break;
01330 }
01331
01332 if (!nCurrentCol)
01333 {
01334 nCurrentCol = nNumCols - 1;
01335 if (nBufferAvailable >= 2)
01336 {
01337 char *p = *bufc;
01338 p[0] = '\r';
01339 p[1] = '\n';
01340
01341 nBufferAvailable -= 2;
01342 *bufc += 2;
01343 }
01344 else
01345 {
01346
01347
01348
01349 if (!nBufferAvailable)
01350 {
01351 break;
01352 }
01353 }
01354 }
01355 else
01356 {
01357 nCurrentCol--;
01358 if (!nBufferAvailable)
01359 {
01360 break;
01361 }
01362 **bufc = cSeparator;
01363 (*bufc)++;
01364 nBufferAvailable--;
01365 }
01366 }
01367 }
01368
01369
01370
01371 static int mem_usage(dbref thing)
01372 {
01373 int k = sizeof(struct object) + strlen(Name(thing)) + 1;
01374
01375 char *as;
01376 for (int ca = atr_head(thing, &as); ca; ca = atr_next(&as))
01377 {
01378 size_t nLen;
01379 const char *str = atr_get_raw_LEN(thing, ca, &nLen);
01380 k += nLen+1;
01381 ATTR *pattr = atr_num(ca);
01382 if (pattr)
01383 {
01384 str = pattr->name;
01385 if ( str
01386 && *str)
01387 {
01388 k += strlen(str)+1;
01389 }
01390 }
01391 }
01392 return k;
01393 }
01394
01395 FUNCTION(fun_objmem)
01396 {
01397 UNUSED_PARAMETER(caller);
01398 UNUSED_PARAMETER(enactor);
01399 UNUSED_PARAMETER(nfargs);
01400 UNUSED_PARAMETER(cargs);
01401 UNUSED_PARAMETER(ncargs);
01402
01403 dbref thing = match_thing_quiet(executor, fargs[0]);
01404 if (!Good_obj(thing))
01405 {
01406 safe_match_result(thing, buff, bufc);
01407 }
01408 else if (Examinable(executor, thing))
01409 {
01410 safe_ltoa(mem_usage(thing), buff, bufc);
01411 }
01412 else
01413 {
01414 safe_noperm(buff, bufc);
01415 }
01416 }
01417
01418 FUNCTION(fun_playmem)
01419 {
01420 UNUSED_PARAMETER(caller);
01421 UNUSED_PARAMETER(enactor);
01422 UNUSED_PARAMETER(cargs);
01423 UNUSED_PARAMETER(ncargs);
01424
01425 dbref thing;
01426 if (nfargs == 1)
01427 {
01428 thing = match_thing_quiet(executor, fargs[0]);
01429 if (!Good_obj(thing))
01430 {
01431 safe_match_result(thing, buff, bufc);
01432 return;
01433 }
01434 else if (!Examinable(executor, thing))
01435 {
01436 safe_noperm(buff, bufc);
01437 return;
01438 }
01439 }
01440 else
01441 {
01442 thing = executor;
01443 }
01444 int tot = 0;
01445 dbref j;
01446 DO_WHOLE_DB(j)
01447 {
01448 if (Owner(j) == thing)
01449 {
01450 tot += mem_usage(j);
01451 }
01452 }
01453 safe_ltoa(tot, buff, bufc);
01454 }
01455
01456
01457
01458
01459 static bool handle_flaglists(dbref player, char *name, char *fstr, bool type)
01460 {
01461 dbref it = match_thing_quiet(player, name);
01462 if (!Good_obj(it))
01463 {
01464 return false;
01465 }
01466
01467 char *s;
01468 char flagletter[2];
01469 FLAGSET fset;
01470 FLAG p_type;
01471 bool negate = false;
01472 bool temp = false;
01473 bool ret = type;
01474
01475 for (s = fstr; *s; s++)
01476 {
01477
01478
01479
01480 if (*s == '!')
01481 {
01482 negate = true;
01483 s++;
01484 }
01485 else
01486 {
01487 negate = false;
01488 }
01489
01490 if (!*s)
01491 {
01492 return false;
01493 }
01494 flagletter[0] = *s;
01495 flagletter[1] = '\0';
01496
01497 if (!convert_flags(player, flagletter, &fset, &p_type))
01498 {
01499
01500
01501
01502
01503 if (type)
01504 {
01505 return false;
01506 }
01507 else
01508 {
01509 continue;
01510 }
01511 }
01512 else
01513 {
01514
01515
01516 if ( (Flags(it) & fset.word[FLAG_WORD1])
01517 || (Flags2(it) & fset.word[FLAG_WORD2])
01518 || (Flags3(it) & fset.word[FLAG_WORD3])
01519 || Typeof(it) == p_type)
01520 {
01521 if ( isPlayer(it)
01522 && fset.word[FLAG_WORD2] == CONNECTED
01523 && Hidden(it)
01524 && !See_Hidden(player))
01525 {
01526 temp = false;
01527 }
01528 else
01529 {
01530 temp = true;
01531 }
01532 }
01533 else
01534 {
01535 temp = false;
01536 }
01537
01538 if ( type
01539 && ( (negate && temp)
01540 || (!negate && !temp)))
01541 {
01542
01543
01544
01545
01546 return false;
01547
01548 }
01549 else if ( !type
01550 && ( (!negate && temp)
01551 || (negate && !temp)))
01552 {
01553
01554
01555
01556 ret |= true;
01557 }
01558
01559
01560
01561 }
01562 }
01563 return ret;
01564 }
01565
01566 FUNCTION(fun_orflags)
01567 {
01568 UNUSED_PARAMETER(caller);
01569 UNUSED_PARAMETER(enactor);
01570 UNUSED_PARAMETER(nfargs);
01571 UNUSED_PARAMETER(cargs);
01572 UNUSED_PARAMETER(ncargs);
01573
01574 safe_bool(handle_flaglists(executor, fargs[0], fargs[1], false), buff, bufc);
01575 }
01576
01577 FUNCTION(fun_andflags)
01578 {
01579 UNUSED_PARAMETER(caller);
01580 UNUSED_PARAMETER(enactor);
01581 UNUSED_PARAMETER(nfargs);
01582 UNUSED_PARAMETER(cargs);
01583 UNUSED_PARAMETER(ncargs);
01584
01585 safe_bool(handle_flaglists(executor, fargs[0], fargs[1], true), buff, bufc);
01586 }
01587
01588 FUNCTION(fun_strtrunc)
01589 {
01590 UNUSED_PARAMETER(executor);
01591 UNUSED_PARAMETER(caller);
01592 UNUSED_PARAMETER(enactor);
01593 UNUSED_PARAMETER(nfargs);
01594 UNUSED_PARAMETER(cargs);
01595 UNUSED_PARAMETER(ncargs);
01596
01597 int maxVisualWidth = mux_atol(fargs[1]);
01598 if (maxVisualWidth < 0)
01599 {
01600 safe_range(buff, bufc);
01601 return;
01602 }
01603 if (maxVisualWidth == 0)
01604 {
01605 return;
01606 }
01607 int nVisualWidth;
01608 char buf[LBUF_SIZE+1];
01609 ANSI_TruncateToField(fargs[0], LBUF_SIZE, buf, maxVisualWidth, &nVisualWidth, ANSI_ENDGOAL_NORMAL);
01610 safe_str(buf, buff, bufc);
01611 }
01612
01613 FUNCTION(fun_ifelse)
01614 {
01615
01616
01617 char *lbuff = alloc_lbuf("fun_ifelse");
01618 char *bp = lbuff;
01619 char *str = fargs[0];
01620 mux_exec(lbuff, &bp, executor, caller, enactor,
01621 EV_STRIP_CURLY | EV_FCHECK | EV_EVAL, &str, cargs, ncargs);
01622 *bp = '\0';
01623
01624 if (!xlate(lbuff))
01625 {
01626 if (nfargs == 3)
01627 {
01628 str = fargs[2];
01629 mux_exec(buff, bufc, executor, caller, enactor,
01630 EV_STRIP_CURLY | EV_FCHECK | EV_EVAL, &str, cargs, ncargs);
01631 }
01632 }
01633 else
01634 {
01635 str = fargs[1];
01636 mux_exec(buff, bufc, executor, caller, enactor,
01637 EV_STRIP_CURLY | EV_FCHECK | EV_EVAL, &str, cargs, ncargs);
01638 }
01639 free_lbuf(lbuff);
01640 }
01641
01642
01643
01644
01645
01646
01647
01648
01649
01650
01651 FUNCTION(fun_mail)
01652 {
01653 UNUSED_PARAMETER(caller);
01654 UNUSED_PARAMETER(enactor);
01655 UNUSED_PARAMETER(cargs);
01656 UNUSED_PARAMETER(ncargs);
01657
01658 if (!mudconf.have_mailer)
01659 {
01660 safe_str("#-1 MAILER DISABLED.", buff, bufc);
01661 return;
01662 }
01663
01664 dbref playerask;
01665 int num, rc, uc, cc;
01666
01667
01668
01669 if (nfargs == 0 || !fargs[0] || !fargs[0][0])
01670 {
01671 count_mail(executor, 0, &rc, &uc, &cc);
01672 safe_ltoa(rc + uc, buff, bufc);
01673 return;
01674 }
01675 else if (nfargs == 1)
01676 {
01677 if (!is_integer(fargs[0], NULL))
01678 {
01679
01680
01681
01682 playerask = lookup_player(executor, fargs[0], true);
01683 if (playerask == NOTHING)
01684 {
01685 playerask = match_thing_quiet(executor, fargs[0]);
01686 if (!isPlayer(playerask))
01687 {
01688 safe_str("#-1 NO SUCH PLAYER", buff, bufc);
01689 return;
01690 }
01691 }
01692 if (playerask == executor || Wizard(executor))
01693 {
01694 count_mail(playerask, 0, &rc, &uc, &cc);
01695 safe_tprintf_str(buff, bufc, "%d %d %d", rc, uc, cc);
01696 }
01697 else
01698 {
01699 safe_noperm(buff, bufc);
01700 }
01701 return;
01702 }
01703 else
01704 {
01705 playerask = executor;
01706 num = mux_atol(fargs[0]);
01707 }
01708 }
01709 else
01710 {
01711 playerask = lookup_player(executor, fargs[0], true);
01712 if (playerask == NOTHING)
01713 {
01714 safe_str("#-1 NO SUCH PLAYER", buff, bufc);
01715 return;
01716 }
01717 else if ( (playerask == executor && !mudstate.nObjEvalNest)
01718 || God(executor))
01719 {
01720 num = mux_atol(fargs[1]);
01721 }
01722 else
01723 {
01724 safe_noperm(buff, bufc);
01725 return;
01726 }
01727 }
01728
01729 if ( num < 1
01730 || !isPlayer(playerask))
01731 {
01732 safe_str("#-1 NO SUCH MESSAGE", buff, bufc);
01733 return;
01734 }
01735
01736 const char *p = mail_fetch_message(playerask, num);
01737 if (p)
01738 {
01739 safe_str(p, buff, bufc);
01740 return;
01741 }
01742
01743
01744
01745 safe_str("#-1 NO SUCH MESSAGE", buff, bufc);
01746 }
01747
01748
01749
01750
01751
01752
01753
01754
01755 FUNCTION(fun_mailfrom)
01756 {
01757 UNUSED_PARAMETER(caller);
01758 UNUSED_PARAMETER(enactor);
01759 UNUSED_PARAMETER(cargs);
01760 UNUSED_PARAMETER(ncargs);
01761
01762 if (!mudconf.have_mailer)
01763 {
01764 safe_str("#-1 MAILER DISABLED.", buff, bufc);
01765 return;
01766 }
01767
01768
01769
01770 int num;
01771 dbref playerask;
01772 if (nfargs == 1)
01773 {
01774 playerask = executor;
01775 num = mux_atol(fargs[0]);
01776 }
01777 else
01778 {
01779 playerask = lookup_player(executor, fargs[0], true);
01780 if (playerask == NOTHING)
01781 {
01782 safe_str("#-1 NO SUCH PLAYER", buff, bufc);
01783 return;
01784 }
01785 if ( playerask == executor
01786 || Wizard(executor))
01787 {
01788 num = mux_atol(fargs[1]);
01789 }
01790 else
01791 {
01792 safe_noperm(buff, bufc);
01793 return;
01794 }
01795 }
01796
01797 if ( num < 1
01798 || !isPlayer(playerask))
01799 {
01800 safe_str("#-1 NO SUCH MESSAGE", buff, bufc);
01801 return;
01802 }
01803
01804 int from = mail_fetch_from(playerask, num);
01805 if (NOTHING != from)
01806 {
01807 safe_tprintf_str(buff, bufc, "#%d", from);
01808 return;
01809 }
01810
01811
01812
01813 safe_str("#-1 NO SUCH MESSAGE", buff, bufc);
01814 }
01815
01816
01817
01818
01819
01820
01821 static void hasattr_handler(char *buff, char **bufc, dbref executor, char *fargs[],
01822 bool bCheckParent)
01823 {
01824 dbref thing = match_thing_quiet(executor, fargs[0]);
01825 if (!Good_obj(thing))
01826 {
01827 safe_match_result(thing, buff, bufc);
01828 return;
01829 }
01830
01831 ATTR *pattr = atr_str(fargs[1]);
01832 bool result = false;
01833 if (pattr)
01834 {
01835 if (!bCanReadAttr(executor, thing, pattr, bCheckParent))
01836 {
01837 safe_noperm(buff, bufc);
01838 return;
01839 }
01840 else
01841 {
01842 if (bCheckParent)
01843 {
01844 dbref aowner;
01845 int aflags;
01846 char *tbuf = atr_pget(thing, pattr->number, &aowner, &aflags);
01847 result = (tbuf[0] != '\0');
01848 free_lbuf(tbuf);
01849 }
01850 else
01851 {
01852 const char *tbuf = atr_get_raw(thing, pattr->number);
01853 result = (tbuf != NULL);
01854 }
01855 }
01856 }
01857 safe_bool(result, buff, bufc);
01858 }
01859
01860 FUNCTION(fun_hasattr)
01861 {
01862 UNUSED_PARAMETER(caller);
01863 UNUSED_PARAMETER(enactor);
01864 UNUSED_PARAMETER(nfargs);
01865 UNUSED_PARAMETER(cargs);
01866 UNUSED_PARAMETER(ncargs);
01867
01868 hasattr_handler(buff, bufc, executor, fargs, false);
01869 }
01870
01871 FUNCTION(fun_hasattrp)
01872 {
01873 UNUSED_PARAMETER(caller);
01874 UNUSED_PARAMETER(enactor);
01875 UNUSED_PARAMETER(nfargs);
01876 UNUSED_PARAMETER(cargs);
01877 UNUSED_PARAMETER(ncargs);
01878
01879 hasattr_handler(buff, bufc, executor, fargs, true);
01880 }
01881
01882
01883
01884
01885
01886
01887
01888
01889
01890
01891
01892
01893 #define DEFAULT_DEFAULT 1
01894 #define DEFAULT_EDEFAULT 2
01895 #define DEFAULT_UDEFAULT 4
01896
01897 static void default_handler(char *buff, char **bufc, dbref executor, dbref caller, dbref enactor,
01898 char *fargs[], int nfargs, char *cargs[], int ncargs, int key)
01899 {
01900
01901
01902 char *objattr = alloc_lbuf("default_handler");
01903 char *bp = objattr;
01904 char *str = fargs[0];
01905 mux_exec(objattr, &bp, executor, caller, enactor,
01906 EV_EVAL | EV_STRIP_CURLY | EV_FCHECK, &str, cargs, ncargs);
01907 *bp = '\0';
01908
01909
01910
01911 dbref thing;
01912 ATTR *pattr;
01913
01914 if (!parse_attrib(executor, objattr, &thing, &pattr))
01915 {
01916 thing = executor;
01917 pattr = atr_str(objattr);
01918 }
01919 free_lbuf(objattr);
01920
01921 if ( pattr
01922 && See_attr(executor, thing, pattr))
01923 {
01924 dbref aowner;
01925 int aflags;
01926 char *atr_gotten = atr_pget(thing, pattr->number, &aowner, &aflags);
01927 if (atr_gotten[0] != '\0')
01928 {
01929 switch (key)
01930 {
01931 case DEFAULT_DEFAULT:
01932 safe_str(atr_gotten, buff, bufc);
01933 break;
01934
01935 case DEFAULT_EDEFAULT:
01936 str = atr_gotten;
01937 mux_exec(buff, bufc, thing, executor, executor,
01938 EV_FIGNORE | EV_EVAL, &str, (char **)NULL, 0);
01939 break;
01940
01941 case DEFAULT_UDEFAULT:
01942 {
01943 char *xargs[MAX_ARG];
01944 int nxargs = nfargs-2;
01945 int i;
01946 for (i = 0; i < nxargs; i++)
01947 {
01948 xargs[i] = alloc_lbuf("fun_udefault_args");
01949 char *bp2 = xargs[i];
01950 str = fargs[i+2];
01951
01952 mux_exec(xargs[i], &bp2,
01953 thing, caller, enactor,
01954 EV_TOP | EV_STRIP_CURLY | EV_FCHECK | EV_EVAL,
01955 &str, cargs, ncargs);
01956 *bp2 = '\0';
01957 }
01958
01959 str = atr_gotten;
01960 mux_exec(buff, bufc, thing, caller, enactor,
01961 EV_FCHECK | EV_EVAL, &str, xargs, nxargs);
01962
01963 for (i = 0; i < nxargs; i++)
01964 {
01965 free_lbuf(xargs[i]);
01966 }
01967 }
01968 break;
01969
01970 }
01971 free_lbuf(atr_gotten);
01972 return;
01973 }
01974 free_lbuf(atr_gotten);
01975 }
01976
01977
01978
01979
01980 str = fargs[1];
01981 mux_exec(buff, bufc, executor, caller, enactor,
01982 EV_EVAL | EV_STRIP_CURLY | EV_FCHECK, &str, cargs, ncargs);
01983 }
01984
01985
01986 FUNCTION(fun_default)
01987 {
01988 default_handler(buff, bufc, executor, caller, enactor, fargs, nfargs, cargs,
01989 ncargs, DEFAULT_DEFAULT);
01990 }
01991
01992 FUNCTION(fun_edefault)
01993 {
01994 default_handler(buff, bufc, executor, caller, enactor, fargs, nfargs, cargs,
01995 ncargs, DEFAULT_EDEFAULT);
01996 }
01997
01998 FUNCTION(fun_udefault)
01999 {
02000 default_handler(buff, bufc, executor, caller, enactor, fargs, nfargs, cargs,
02001 ncargs, DEFAULT_UDEFAULT);
02002 }
02003
02004
02005
02006
02007
02008 FUNCTION(fun_findable)
02009 {
02010 UNUSED_PARAMETER(caller);
02011 UNUSED_PARAMETER(enactor);
02012 UNUSED_PARAMETER(nfargs);
02013 UNUSED_PARAMETER(cargs);
02014 UNUSED_PARAMETER(ncargs);
02015
02016 dbref obj = match_thing_quiet(executor, fargs[0]);
02017 if (!Good_obj(obj))
02018 {
02019 safe_match_result(obj, buff, bufc);
02020 safe_str(" (ARG1)", buff, bufc);
02021 return;
02022 }
02023 dbref victim = match_thing_quiet(executor, fargs[1]);
02024 if (!Good_obj(victim))
02025 {
02026 safe_match_result(victim, buff, bufc);
02027 safe_str(" (ARG2)", buff, bufc);
02028 return;
02029 }
02030 #ifndef WOD_REALMS
02031 #ifndef REALITY_LVLS
02032 safe_bool(locatable(obj, victim, obj), buff, bufc);
02033 #else
02034 if (IsReal(obj, victim))
02035 {
02036 safe_bool(locatable(obj, victim, obj), buff, bufc);
02037 }
02038 else safe_chr('0', buff, bufc);
02039 #endif
02040 #else
02041 #ifndef REALITY_LVLS
02042 if (REALM_DO_HIDDEN_FROM_YOU != DoThingToThingVisibility(obj, victim, ACTION_IS_STATIONARY))
02043 {
02044 safe_bool(locatable(obj, victim, obj), buff, bufc);
02045 }
02046 else
02047 {
02048 safe_chr('0', buff, bufc);
02049 }
02050
02051 #else
02052 if (REALM_DO_HIDDEN_FROM_YOU != DoThingToThingVisibility(obj, victim, ACTION_IS_STATIONARY))
02053 {
02054 safe_bool(locatable(obj, victim, obj), buff, bufc);
02055 }
02056 else if (IsReal(obj, victim))
02057 {
02058 safe_bool(locatable(obj, victim, obj), buff, bufc);
02059 }
02060 else safe_chr('0', buff, bufc);
02061 #endif
02062 #endif
02063 }
02064
02065
02066
02067
02068
02069 FUNCTION(fun_isword)
02070 {
02071 UNUSED_PARAMETER(executor);
02072 UNUSED_PARAMETER(caller);
02073 UNUSED_PARAMETER(enactor);
02074 UNUSED_PARAMETER(nfargs);
02075 UNUSED_PARAMETER(cargs);
02076 UNUSED_PARAMETER(ncargs);
02077
02078 char *p;
02079 bool result = true;
02080
02081 for (p = fargs[0]; *p; p++)
02082 {
02083 if (!mux_isalpha(*p))
02084 {
02085 result = false;
02086 break;
02087 }
02088 }
02089 safe_bool(result, buff, bufc);
02090 }
02091
02092
02093
02094
02095 FUNCTION(fun_visible)
02096 {
02097 UNUSED_PARAMETER(caller);
02098 UNUSED_PARAMETER(enactor);
02099 UNUSED_PARAMETER(nfargs);
02100 UNUSED_PARAMETER(cargs);
02101 UNUSED_PARAMETER(ncargs);
02102
02103 dbref it = match_thing_quiet(executor, fargs[0]);
02104 if (!Good_obj(it))
02105 {
02106 safe_match_result(it, buff, bufc);
02107 safe_str(" (ARG1)", buff, bufc);
02108 return;
02109 }
02110 else if (!Controls(executor, it))
02111 {
02112 safe_noperm(buff, bufc);
02113 return;
02114 }
02115
02116 bool result = false;
02117 dbref thing;
02118 ATTR *pattr;
02119 if (!parse_attrib(executor, fargs[1], &thing, &pattr))
02120 {
02121 thing = match_thing_quiet(executor, fargs[1]);
02122 if (!Good_obj(thing))
02123 {
02124 safe_match_result(thing, buff, bufc);
02125 safe_str(" (ARG2)", buff, bufc);
02126 return;
02127 }
02128 }
02129 if (Good_obj(thing))
02130 {
02131 if (pattr)
02132 {
02133 result = (See_attr(it, thing, pattr));
02134 }
02135 else
02136 {
02137 result = (Examinable(it, thing));
02138 }
02139 }
02140 safe_bool(result, buff, bufc);
02141 }
02142
02143
02144
02145
02146
02147
02148
02149
02150 FUNCTION(fun_elements)
02151 {
02152 SEP sep;
02153 if (!OPTIONAL_DELIM(3, sep, DELIM_DFLT|DELIM_STRING))
02154 {
02155 return;
02156 }
02157
02158 SEP osep = sep;
02159 if (!OPTIONAL_DELIM(4, osep, DELIM_NULL|DELIM_CRLF|DELIM_STRING|DELIM_INIT))
02160 {
02161 return;
02162 }
02163
02164 int nwords, cur;
02165 char *ptrs[LBUF_SIZE / 2];
02166 char *wordlist, *s, *r;
02167 bool bFirst = true;
02168
02169
02170
02171 wordlist = alloc_lbuf("fun_elements.wordlist");
02172 strcpy(wordlist, fargs[0]);
02173 nwords = list2arr(ptrs, LBUF_SIZE / 2, wordlist, &sep);
02174
02175 s = trim_space_sep(fargs[1], &sepSpace);
02176
02177
02178
02179
02180 do {
02181 r = split_token(&s, &sepSpace);
02182 cur = mux_atol(r) - 1;
02183 if ( cur >= 0
02184 && cur < nwords
02185 && ptrs[cur])
02186 {
02187 if (!bFirst)
02188 {
02189 print_sep(&osep, buff, bufc);
02190 }
02191 else
02192 {
02193 bFirst = false;
02194 }
02195 safe_str(ptrs[cur], buff, bufc);
02196 }
02197 } while (s);
02198 free_lbuf(wordlist);
02199 }
02200
02201
02202
02203
02204
02205
02206
02207
02208
02209 FUNCTION(fun_grab)
02210 {
02211 SEP sep;
02212 if (!OPTIONAL_DELIM(3, sep, DELIM_DFLT|DELIM_STRING))
02213 {
02214 return;
02215 }
02216
02217
02218
02219 char *s = trim_space_sep(fargs[0], &sep);
02220 do
02221 {
02222 char *r = split_token(&s, &sep);
02223 mudstate.wild_invk_ctr = 0;
02224 if (quick_wild(fargs[1], r))
02225 {
02226 safe_str(r, buff, bufc);
02227 return;
02228 }
02229 } while (s);
02230 }
02231
02232 FUNCTION(fun_graball)
02233 {
02234 SEP sep;
02235 if (!OPTIONAL_DELIM(3, sep, DELIM_DFLT|DELIM_STRING))
02236 {
02237 return;
02238 }
02239 SEP osep = sep;
02240 if (!OPTIONAL_DELIM(4, osep, DELIM_NULL|DELIM_CRLF|DELIM_STRING|DELIM_INIT))
02241 {
02242 return;
02243 }
02244
02245 bool bFirst = true;
02246 char *s = trim_space_sep(fargs[0], &sep);
02247 do
02248 {
02249 char *r = split_token(&s, &sep);
02250 mudstate.wild_invk_ctr = 0;
02251 if (quick_wild(fargs[1], r))
02252 {
02253 if (!bFirst)
02254 {
02255 print_sep(&osep, buff, bufc);
02256 }
02257 else
02258 {
02259 bFirst = false;
02260 }
02261 safe_str(r, buff, bufc);
02262 }
02263 } while (s);
02264 }
02265
02266
02267
02268
02269
02270 FUNCTION(fun_scramble)
02271 {
02272 UNUSED_PARAMETER(executor);
02273 UNUSED_PARAMETER(caller);
02274 UNUSED_PARAMETER(enactor);
02275 UNUSED_PARAMETER(nfargs);
02276 UNUSED_PARAMETER(cargs);
02277 UNUSED_PARAMETER(ncargs);
02278
02279 size_t n;
02280 char *old = strip_ansi(fargs[0], &n);
02281
02282 if (2 <= n)
02283 {
02284 unsigned int i;
02285 for (i = 0; i < n-1; i++)
02286 {
02287 int j = RandomINT32(i, n-1);
02288 char c = old[i];
02289 old[i] = old[j];
02290 old[j] = c;
02291 }
02292 }
02293 safe_str(old, buff, bufc);
02294 }
02295
02296
02297
02298
02299
02300 FUNCTION(fun_shuffle)
02301 {
02302 SEP sep;
02303 if (!OPTIONAL_DELIM(2, sep, DELIM_DFLT|DELIM_STRING))
02304 {
02305 return;
02306 }
02307
02308 SEP osep = sep;
02309 if (!OPTIONAL_DELIM(3, osep, DELIM_NULL|DELIM_CRLF|DELIM_STRING|DELIM_INIT))
02310 {
02311 return;
02312 }
02313
02314 char *words[LBUF_SIZE];
02315 int n, i, j;
02316
02317 n = list2arr(words, LBUF_SIZE, fargs[0], &sep);
02318
02319 for (i = 0; i < n-1; i++)
02320 {
02321 j = RandomINT32(i, n-1);
02322
02323
02324
02325 char *temp = words[i];
02326 words[i] = words[j];
02327 words[j] = temp;
02328 }
02329 arr2list(words, n, buff, bufc, &osep);
02330 }
02331
02332
02333
02334 FUNCTION(fun_pickrand)
02335 {
02336 if ( nfargs == 0
02337 || fargs[0][0] == '\0')
02338 {
02339 return;
02340 }
02341
02342 SEP sep;
02343 if (!OPTIONAL_DELIM(2, sep, DELIM_DFLT|DELIM_STRING))
02344 {
02345 return;
02346 }
02347
02348 char *s = trim_space_sep(fargs[0], &sep);
02349 char *t = s;
02350 if (s[0] == '\0')
02351 {
02352 return;
02353 }
02354 INT32 n;
02355 for (n = 0; t; t = next_token(t, &sep), n++)
02356 {
02357 ;
02358 }
02359
02360 if (n >= 1)
02361 {
02362 INT32 w = RandomINT32(0, n-1);
02363 for (n = 0; n < w; n++)
02364 {
02365 s = next_token(s, &sep);
02366 }
02367 t = split_token(&s, &sep);
02368 safe_str(t, buff, bufc);
02369 }
02370 }
02371
02372
02373
02374 static char ucomp_buff[LBUF_SIZE];
02375 static dbref ucomp_executor;
02376 static dbref ucomp_caller;
02377 static dbref ucomp_enactor;
02378
02379 static int u_comp(const void *s1, const void *s2)
02380 {
02381
02382
02383
02384 char *result, *tbuf, *elems[2], *bp, *str;
02385 int n;
02386
02387 if ( mudstate.func_invk_ctr > mudconf.func_invk_lim
02388 || mudstate.func_nest_lev > mudconf.func_nest_lim
02389 || MuxAlarm.bAlarmed)
02390 {
02391 return 0;
02392 }
02393
02394 tbuf = alloc_lbuf("u_comp");
02395 elems[0] = (char *)s1;
02396 elems[1] = (char *)s2;
02397 strcpy(tbuf, ucomp_buff);
02398 result = bp = alloc_lbuf("u_comp");
02399 str = tbuf;
02400 mux_exec(result, &bp, ucomp_executor, ucomp_caller, ucomp_enactor,
02401 EV_STRIP_CURLY | EV_FCHECK | EV_EVAL, &str, &(elems[0]), 2);
02402 *bp = '\0';
02403 if (!result)
02404 {
02405 n = 0;
02406 }
02407 else
02408 {
02409 n = mux_atol(result);
02410 free_lbuf(result);
02411 }
02412 free_lbuf(tbuf);
02413 return n;
02414 }
02415
02416 typedef int PV(const void *, const void *);
02417
02418 static void sane_qsort(void *array[], int left, int right, PV compare)
02419 {
02420
02421
02422
02423
02424 int i, last;
02425 void *tmp;
02426
02427 loop:
02428
02429 if (left >= right)
02430 {
02431 return;
02432 }
02433
02434
02435
02436
02437 i = RandomINT32(0, right - left);
02438 tmp = array[left + i];
02439 array[left + i] = array[left];
02440 array[left] = tmp;
02441
02442 last = left;
02443 for (i = left + 1; i <= right; i++) {
02444
02445
02446
02447
02448 if ((*compare) (array[i], array[left]) < 0)
02449 {
02450 last++;
02451 if (last == i)
02452 {
02453 continue;
02454 }
02455
02456 tmp = array[last];
02457 array[last] = array[i];
02458 array[i] = tmp;
02459 }
02460 }
02461
02462
02463
02464
02465 tmp = array[last];
02466 array[last] = array[left];
02467 array[left] = tmp;
02468
02469
02470
02471
02472 if ((last - left) < (right - last))
02473 {
02474 sane_qsort(array, left, last - 1, compare);
02475 left = last + 1;
02476 goto loop;
02477 }
02478 else
02479 {
02480 sane_qsort(array, last + 1, right, compare);
02481 right = last - 1;
02482 goto loop;
02483 }
02484 }
02485
02486 FUNCTION(fun_sortby)
02487 {
02488 SEP sep;
02489 if (!OPTIONAL_DELIM(3, sep, DELIM_DFLT|DELIM_STRING))
02490 {
02491 return;
02492 }
02493
02494 SEP osep = sep;
02495 if (!OPTIONAL_DELIM(4, osep, DELIM_NULL|DELIM_CRLF|DELIM_STRING|DELIM_INIT))
02496 {
02497 return;
02498 }
02499
02500 char *atext;
02501 dbref thing;
02502 if (!parse_and_get_attrib(executor, fargs, &atext, &thing, buff, bufc))
02503 {
02504 return;
02505 }
02506
02507 strcpy(ucomp_buff, atext);
02508 ucomp_executor = thing;
02509 ucomp_caller = executor;
02510 ucomp_enactor = enactor;
02511
02512 char *list = alloc_lbuf("fun_sortby");
02513 strcpy(list, fargs[1]);
02514 char *ptrs[LBUF_SIZE / 2];
02515 int nptrs = list2arr(ptrs, LBUF_SIZE / 2, list, &sep);
02516
02517 if (nptrs > 1)
02518 {
02519 sane_qsort((void **)ptrs, 0, nptrs - 1, u_comp);
02520 }
02521
02522 arr2list(ptrs, nptrs, buff, bufc, &osep);
02523 free_lbuf(list);
02524 free_lbuf(atext);
02525 }
02526
02527
02528
02529 FUNCTION(fun_last)
02530 {
02531
02532
02533 if (nfargs == 0)
02534 {
02535 return;
02536 }
02537
02538 SEP sep;
02539 if (!OPTIONAL_DELIM(2, sep, DELIM_DFLT|DELIM_STRING))
02540 {
02541 return;
02542 }
02543
02544 char *str;
02545 char *lstr = trim_space_sep(fargs[0], &sep);
02546 while (NULL != (str = next_token(lstr, &sep)))
02547 {
02548 lstr = str;
02549 }
02550 safe_str(lstr, buff, bufc);
02551 }
02552
02553
02554
02555 FUNCTION(fun_matchall)
02556 {
02557 SEP sep;
02558 if (!OPTIONAL_DELIM(3, sep, DELIM_DFLT|DELIM_STRING))
02559 {
02560 return;
02561 }
02562
02563 int wcount;
02564 char *r, *s, *old, tbuf[8];
02565 old = *bufc;
02566
02567
02568
02569
02570 wcount = 1;
02571 s = trim_space_sep(fargs[0], &sep);
02572 do
02573 {
02574 r = split_token(&s, &sep);
02575 mudstate.wild_invk_ctr = 0;
02576 if (quick_wild(fargs[1], r))
02577 {
02578 mux_ltoa(wcount, tbuf);
02579 if (old != *bufc)
02580 {
02581 safe_chr(' ', buff, bufc);
02582 }
02583 safe_str(tbuf, buff, bufc);
02584 }
02585 wcount++;
02586 } while (s);
02587
02588 if (*bufc == old)
02589 {
02590 safe_chr('0', buff, bufc);
02591 }
02592 }
02593
02594
02595
02596
02597
02598 FUNCTION(fun_ports)
02599 {
02600 UNUSED_PARAMETER(caller);
02601 UNUSED_PARAMETER(enactor);
02602 UNUSED_PARAMETER(nfargs);
02603 UNUSED_PARAMETER(cargs);
02604 UNUSED_PARAMETER(ncargs);
02605
02606 dbref target = lookup_player(executor, fargs[0], true);
02607 if (Good_obj(target))
02608 {
02609 if (target == executor || Wizard(executor))
02610 {
02611 if (Connected(target))
02612 {
02613 make_portlist(executor, target, buff, bufc);
02614 }
02615 }
02616 else
02617 {
02618 safe_noperm(buff, bufc);
02619 }
02620 }
02621 else
02622 {
02623 safe_nomatch(buff, bufc);
02624 }
02625 }
02626
02627
02628
02629
02630
02631
02632 FUNCTION(fun_mix)
02633 {
02634
02635
02636
02637
02638 SEP sep;
02639 int lastn;
02640
02641 if (nfargs < 4)
02642 {
02643 sep.n = 1;
02644 sep.str[0] = ' ';
02645 sep.str[1] = '\0';
02646 lastn = nfargs - 1;
02647 }
02648 else if (!OPTIONAL_DELIM(nfargs, sep, DELIM_DFLT|DELIM_STRING))
02649 {
02650 return;
02651 }
02652 else
02653 {
02654 lastn = nfargs - 2;
02655 }
02656
02657
02658
02659 dbref thing;
02660 char *atext;
02661 if (!parse_and_get_attrib(executor, fargs, &atext, &thing, buff, bufc))
02662 {
02663 return;
02664 }
02665
02666 char *cp[10];
02667 int i;
02668 for (i = 0; i < lastn; i++)
02669 {
02670 cp[i] = NULL;
02671 }
02672
02673
02674
02675 for (i = 0; i < lastn; i++)
02676 {
02677 cp[i] = trim_space_sep(fargs[i+1], &sep);
02678 }
02679 int twords;
02680 int nwords = countwords(cp[0], &sep);
02681 for (i = 1; i < lastn; i++)
02682 {
02683 twords = countwords(cp[i], &sep);
02684 if (twords > nwords)
02685 {
02686 nwords = twords;
02687 }
02688 }
02689 char *atextbuf = alloc_lbuf("fun_mix");
02690 char *str, *os[10];
02691 bool bFirst = true;
02692 for (int wc = 0; wc < nwords && mudstate.func_invk_ctr < mudconf.func_invk_lim && !MuxAlarm.bAlarmed; wc++)
02693 {
02694 if (!bFirst)
02695 {
02696 print_sep(&sep, buff, bufc);
02697 }
02698 else
02699 {
02700 bFirst = false;
02701 }
02702 for (i = 0; i < lastn; i++)
02703 {
02704 os[i] = split_token(&cp[i], &sep);
02705 }
02706 strcpy(atextbuf, atext);
02707 str = atextbuf;
02708 mux_exec(buff, bufc, thing, executor, enactor,
02709 EV_STRIP_CURLY | EV_FCHECK | EV_EVAL, &str, &(os[0]), lastn);
02710 }
02711 free_lbuf(atext);
02712 free_lbuf(atextbuf);
02713 }
02714
02715
02716
02717
02718
02719
02720
02721 FUNCTION(fun_foreach)
02722 {
02723 UNUSED_PARAMETER(caller);
02724 UNUSED_PARAMETER(enactor);
02725 UNUSED_PARAMETER(cargs);
02726 UNUSED_PARAMETER(ncargs);
02727
02728 if ( nfargs != 2
02729 && nfargs != 4)
02730 {
02731 safe_str("#-1 FUNCTION (FOREACH) EXPECTS 2 OR 4 ARGUMENTS", buff, bufc);
02732 return;
02733 }
02734
02735 char *atext;
02736 dbref thing;
02737 if (!parse_and_get_attrib(executor, fargs, &atext, &thing, buff, bufc))
02738 {
02739 return;
02740 }
02741
02742 char *str;
02743 char cbuf[2], prev = '\0';
02744 char *atextbuf = alloc_lbuf("fun_foreach");
02745 SEP sep;
02746 sep.n = 1;
02747 sep.str[0] = ' ';
02748 sep.str[1] = '\0';
02749 char *cp = trim_space_sep(fargs[1], &sep);
02750
02751 char *bp = cbuf;
02752
02753 cbuf[1] = '\0';
02754
02755 if (nfargs == 4)
02756 {
02757 bool flag = false;
02758 while ( cp
02759 && *cp
02760 && mudstate.func_invk_ctr < mudconf.func_invk_lim
02761 && !MuxAlarm.bAlarmed)
02762 {
02763 cbuf[0] = *cp++;
02764
02765 if (flag)
02766 {
02767 if ( cbuf[0] == *fargs[3]
02768 && prev != '\\'
02769 && prev != '%')
02770 {
02771 flag = false;
02772 continue;
02773 }
02774 }
02775 else
02776 {
02777 if ( cbuf[0] == *fargs[2]
02778 && prev != '\\'
02779 && prev != '%')
02780 {
02781 flag = true;
02782 continue;
02783 }
02784 else
02785 {
02786 safe_chr(cbuf[0], buff, bufc);
02787 continue;
02788 }
02789 }
02790
02791 strcpy(atextbuf, atext);
02792 str = atextbuf;
02793 mux_exec(buff, bufc, thing, executor, enactor,
02794 EV_STRIP_CURLY | EV_FCHECK | EV_EVAL, &str, &bp, 1);
02795 prev = cbuf[0];
02796 }
02797 }
02798 else
02799 {
02800 while ( cp
02801 && *cp
02802 && mudstate.func_invk_ctr < mudconf.func_invk_lim
02803 && !MuxAlarm.bAlarmed)
02804 {
02805 cbuf[0] = *cp++;
02806
02807 strcpy(atextbuf, atext);
02808 str = atextbuf;
02809 mux_exec(buff, bufc, thing, executor, enactor,
02810 EV_STRIP_CURLY | EV_FCHECK | EV_EVAL, &str, &bp, 1);
02811 }
02812 }
02813 free_lbuf(atextbuf);
02814 free_lbuf(atext);
02815 }
02816
02817
02818
02819
02820
02821 FUNCTION(fun_munge)
02822 {
02823 SEP sep;
02824 if (!OPTIONAL_DELIM(4, sep, DELIM_DFLT|DELIM_STRING))
02825 {
02826 return;
02827 }
02828
02829
02830
02831 char *atext;
02832 dbref thing;
02833 if (!parse_and_get_attrib(executor, fargs, &atext, &thing, buff, bufc))
02834 {
02835 return;
02836 }
02837
02838 int nptrs1, nptrs2, nresults, i, j;
02839 char *list1, *list2, *rlist, *bp, *str;
02840 char *ptrs1[LBUF_SIZE / 2], *ptrs2[LBUF_SIZE / 2], *results[LBUF_SIZE / 2];
02841 char *uargs[2];
02842
02843
02844
02845 list1 = alloc_lbuf("fun_munge.list1");
02846 list2 = alloc_lbuf("fun_munge.list2");
02847 strcpy(list1, fargs[1]);
02848 strcpy(list2, fargs[2]);
02849 nptrs1 = list2arr(ptrs1, LBUF_SIZE / 2, list1, &sep);
02850 nptrs2 = list2arr(ptrs2, LBUF_SIZE / 2, list2, &sep);
02851
02852 if (nptrs1 != nptrs2)
02853 {
02854 safe_str("#-1 LISTS MUST BE OF EQUAL SIZE", buff, bufc);
02855 free_lbuf(atext);
02856 free_lbuf(list1);
02857 free_lbuf(list2);
02858 return;
02859 }
02860
02861
02862
02863 bp = rlist = alloc_lbuf("fun_munge");
02864 str = atext;
02865 uargs[0] = fargs[1];
02866 uargs[1] = sep.str;
02867 mux_exec(rlist, &bp, executor, caller, enactor,
02868 EV_STRIP_CURLY | EV_FCHECK | EV_EVAL, &str, uargs, 2);
02869 *bp = '\0';
02870
02871
02872
02873
02874
02875 nresults = list2arr(results, LBUF_SIZE / 2, rlist, &sep);
02876
02877 bool bFirst = true;
02878 for (i = 0; i < nresults; i++)
02879 {
02880 for (j = 0; j < nptrs1; j++)
02881 {
02882 if (!strcmp(results[i], ptrs1[j]))
02883 {
02884 if (!bFirst)
02885 {
02886 print_sep(&sep, buff, bufc);
02887 }
02888 else
02889 {
02890 bFirst = false;
02891 }
02892 safe_str(ptrs2[j], buff, bufc);
02893 ptrs1[j][0] = '\0';
02894 break;
02895 }
02896 }
02897 }
02898 free_lbuf(atext);
02899 free_lbuf(list1);
02900 free_lbuf(list2);
02901 free_lbuf(rlist);
02902 }
02903
02904 FUNCTION(fun_die)
02905 {
02906 UNUSED_PARAMETER(executor);
02907 UNUSED_PARAMETER(caller);
02908 UNUSED_PARAMETER(enactor);
02909 UNUSED_PARAMETER(cargs);
02910 UNUSED_PARAMETER(ncargs);
02911
02912 int n = mux_atol(fargs[0]);
02913 int die = mux_atol(fargs[1]);
02914
02915 if ( n == 0
02916 || die <= 0)
02917 {
02918 safe_chr('0', buff, bufc);
02919 return;
02920 }
02921
02922 if ( n < 1
02923 || LBUF_SIZE <= n)
02924 {
02925 safe_range(buff, bufc);
02926 return;
02927 }
02928
02929 if ( 3 <= nfargs
02930 && isTRUE(mux_atol(fargs[2])))
02931 {
02932 ITL pContext;
02933 ItemToList_Init(&pContext, buff, bufc);
02934 for (int count = 0; count < n; count++)
02935 {
02936 if (!ItemToList_AddInteger(&pContext, RandomINT32(1, die)))
02937 {
02938 break;
02939 }
02940 }
02941 ItemToList_Final(&pContext);
02942 return;
02943 }
02944
02945 int total = 0;
02946 for (int count = 0; count < n; count++)
02947 {
02948 total += RandomINT32(1, die);
02949 }
02950
02951 safe_ltoa(total, buff, bufc);
02952 }
02953
02954 FUNCTION(fun_lrand)
02955 {
02956 SEP sep;
02957 if (!OPTIONAL_DELIM(4, sep, DELIM_NULL|DELIM_CRLF|DELIM_STRING))
02958 {
02959 return;
02960 }
02961
02962 int n_times = mux_atol(fargs[2]);
02963 if (n_times < 1)
02964 {
02965 return;
02966 }
02967 if (n_times > LBUF_SIZE)
02968 {
02969 n_times = LBUF_SIZE;
02970 }
02971 INT32 iLower = mux_atol(fargs[0]);
02972 INT32 iUpper = mux_atol(fargs[1]);
02973
02974 if (iLower <= iUpper)
02975 {
02976 for (int i = 0; i < n_times-1; i++)
02977 {
02978 INT32 val = RandomINT32(iLower, iUpper);
02979 safe_ltoa(val, buff, bufc);
02980 print_sep(&sep, buff, bufc);
02981 }
02982 INT32 val = RandomINT32(iLower, iUpper);
02983 safe_ltoa(val, buff, bufc);
02984 }
02985 }
02986
02987
02988
02989 FUNCTION(fun_lit)
02990 {
02991 UNUSED_PARAMETER(executor);
02992 UNUSED_PARAMETER(caller);
02993 UNUSED_PARAMETER(enactor);
02994 UNUSED_PARAMETER(nfargs);
02995 UNUSED_PARAMETER(cargs);
02996 UNUSED_PARAMETER(ncargs);
02997
02998
02999
03000 safe_str(fargs[0], buff, bufc);
03001 }
03002
03003 FUNCTION(fun_dumping)
03004 {
03005 UNUSED_PARAMETER(executor);
03006 UNUSED_PARAMETER(caller);
03007 UNUSED_PARAMETER(enactor);
03008 UNUSED_PARAMETER(fargs);
03009 UNUSED_PARAMETER(nfargs);
03010 UNUSED_PARAMETER(cargs);
03011 UNUSED_PARAMETER(ncargs);
03012
03013 #ifdef WIN32
03014 safe_chr('0', buff, bufc);
03015 #else // WIN32
03016 safe_bool(mudstate.dumping, buff, bufc);
03017 #endif // WIN32
03018 }
03019
03020
03021
03022
03023
03024
03025 static char aRadixTable[] =
03026 "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz@$";
03027
03028 FUNCTION(fun_unpack)
03029 {
03030 UNUSED_PARAMETER(executor);
03031 UNUSED_PARAMETER(caller);
03032 UNUSED_PARAMETER(enactor);
03033 UNUSED_PARAMETER(cargs);
03034 UNUSED_PARAMETER(ncargs);
03035
03036
03037
03038 INT64 iRadix = 64;
03039 if (nfargs == 2)
03040 {
03041 if ( !is_integer(fargs[1], NULL)
03042 || (iRadix = mux_atoi64(fargs[1])) < 2
03043 || 64 < iRadix)
03044 {
03045 safe_str("#-1 RADIX MUST BE A NUMBER BETWEEN 2 and 64", buff, bufc);
03046 return;
03047 }
03048 }
03049
03050
03051
03052 char MatchTable[256];
03053 memset(MatchTable, 0, sizeof(MatchTable));
03054 for (int i = 0; i < iRadix; i++)
03055 {
03056 MatchTable[(unsigned char)aRadixTable[i]] = i+1;
03057 }
03058
03059
03060
03061
03062 char *pString = fargs[0];
03063 INT64 sum;
03064 int c;
03065 int LeadingCharacter;
03066
03067
03068
03069 while (mux_isspace(*pString))
03070 {
03071 pString++;
03072 }
03073
03074
03075
03076 LeadingCharacter = c = *pString++;
03077 if (c == '-' || c == '+')
03078 {
03079 c = *pString++;
03080 }
03081
03082 sum = 0;
03083
03084
03085
03086 for (int iValue = MatchTable[(unsigned int)c];
03087 iValue;
03088 iValue = MatchTable[(unsigned int)c])
03089 {
03090 sum = iRadix * sum + iValue - 1;
03091 c = *pString++;
03092 }
03093
03094
03095
03096 if (LeadingCharacter == '-')
03097 {
03098 sum = -sum;
03099 }
03100 safe_i64toa(sum, buff, bufc);
03101 }
03102
03103 static size_t mux_Pack(INT64 val, int iRadix, char *buf)
03104 {
03105 char *p = buf;
03106
03107
03108
03109 if (val < 0)
03110 {
03111 *p++ = '-';
03112 val = -val;
03113 }
03114
03115 char *q = p;
03116 while (val > iRadix-1)
03117 {
03118 INT64 iDiv = val / iRadix;
03119 INT64 iTerm = val - iDiv * iRadix;
03120 val = iDiv;
03121 *p++ = aRadixTable[iTerm];
03122 }
03123 *p++ = aRadixTable[val];
03124
03125 int nLength = p - buf;
03126 *p-- = '\0';
03127
03128
03129
03130
03131
03132 while (q < p)
03133 {
03134
03135
03136 char temp = *p;
03137 *p = *q;
03138 *q = temp;
03139
03140
03141
03142 --p;
03143 ++q;
03144
03145
03146
03147 }
03148 return nLength;
03149 }
03150
03151 FUNCTION(fun_pack)
03152 {
03153 UNUSED_PARAMETER(executor);
03154 UNUSED_PARAMETER(caller);
03155 UNUSED_PARAMETER(enactor);
03156 UNUSED_PARAMETER(cargs);
03157 UNUSED_PARAMETER(ncargs);
03158
03159
03160
03161 if ( !is_integer(fargs[0], NULL)
03162 || (nfargs == 2 && !is_integer(fargs[1], NULL)))
03163 {
03164 safe_str("#-1 ARGUMENTS MUST BE NUMBERS", buff, bufc);
03165 return;
03166 }
03167 INT64 val = mux_atoi64(fargs[0]);
03168
03169
03170
03171 int iRadix = 64;
03172 if (nfargs == 2)
03173 {
03174 iRadix = mux_atol(fargs[1]);
03175 if (iRadix < 2 || 64 < iRadix)
03176 {
03177 safe_str("#-1 RADIX MUST BE A NUMBER BETWEEN 2 and 64", buff, bufc);
03178 return;
03179 }
03180 }
03181
03182 char TempBuffer[76];
03183 int nLength = mux_Pack(val, iRadix, TempBuffer);
03184 safe_copy_buf(TempBuffer, nLength, buff, bufc);
03185 }
03186
03187 FUNCTION(fun_strcat)
03188 {
03189 UNUSED_PARAMETER(executor);
03190 UNUSED_PARAMETER(caller);
03191 UNUSED_PARAMETER(enactor);
03192 UNUSED_PARAMETER(cargs);
03193 UNUSED_PARAMETER(ncargs);
03194
03195 int i;
03196 for (i = 0; i < nfargs; i++)
03197 {
03198 safe_str(fargs[i], buff, bufc);
03199 }
03200 }
03201
03202
03203
03204 static char *grep_util(dbref player, dbref thing, char *pattern, char *lookfor, int len, bool insensitive)
03205 {
03206
03207
03208
03209 dbref aowner;
03210 char *tbuf1, *buf;
03211 char *bp, *bufc;
03212 int ca, aflags;
03213
03214 tbuf1 = alloc_lbuf("grep_util");
03215 bufc = buf = alloc_lbuf("grep_util.parse_attrib");
03216 bp = tbuf1;
03217 safe_tprintf_str(buf, &bufc, "#%d/%s", thing, pattern);
03218 olist_push();
03219 if (parse_attrib_wild(player, buf, &thing, false, false, true))
03220 {
03221 BMH_State bmhs;
03222 if (insensitive)
03223 {
03224 BMH_PrepareI(&bmhs, len, lookfor);
03225 }
03226 else
03227 {
03228 BMH_Prepare(&bmhs, len, lookfor);
03229 }
03230
03231 for (ca = olist_first(); ca != NOTHING && !MuxAlarm.bAlarmed; ca = olist_next())
03232 {
03233 size_t nText;
03234 char *attrib = atr_get_LEN(thing, ca, &aowner, &aflags, &nText);
03235 int i;
03236 if (insensitive)
03237 {
03238 i = BMH_ExecuteI(&bmhs, len, lookfor, nText, attrib);
03239 }
03240 else
03241 {
03242 i = BMH_Execute(&bmhs, len, lookfor, nText, attrib);
03243 }
03244 if (i >= 0)
03245 {
03246 if (bp != tbuf1)
03247 {
03248 safe_chr(' ', tbuf1, &bp);
03249 }
03250 ATTR *ap = atr_num(ca);
03251 const char *pName = "(WARNING: Bad Attribute Number)";
03252 if (ap)
03253 {
03254 pName = ap->name;
03255 }
03256 safe_str(pName, tbuf1, &bp);
03257 }
03258 free_lbuf(attrib);
03259 }
03260 }
03261 free_lbuf(buf);
03262 *bp = '\0';
03263 olist_pop();
03264 return tbuf1;
03265 }
03266
03267 static void grep_handler(char *buff, char **bufc, dbref executor, char *fargs[],
03268 bool bCaseInsens)
03269 {
03270 dbref it = match_thing_quiet(executor, fargs[0]);
03271 if (!Good_obj(it))
03272 {
03273 safe_match_result(it, buff, bufc);
03274 return;
03275 }
03276
03277 if (!Examinable(executor, it))
03278 {
03279 safe_noperm(buff, bufc);
03280 return;
03281 }
03282
03283
03284
03285 if (!fargs[1] || !*fargs[1])
03286 {
03287 safe_str("#-1 NO SUCH ATTRIBUTE", buff, bufc);
03288 return;
03289 }
03290 if (!fargs[2] || !*fargs[2])
03291 {
03292 safe_str("#-1 INVALID GREP PATTERN", buff, bufc);
03293 return;
03294 }
03295 char *tp = grep_util(executor, it, fargs[1], fargs[2], strlen(fargs[2]), bCaseInsens);
03296 safe_str(tp, buff, bufc);
03297 free_lbuf(tp);
03298 }
03299
03300 FUNCTION(fun_grep)
03301 {
03302 UNUSED_PARAMETER(caller);
03303 UNUSED_PARAMETER(enactor);
03304 UNUSED_PARAMETER(nfargs);
03305 UNUSED_PARAMETER(cargs);
03306 UNUSED_PARAMETER(ncargs);
03307
03308 grep_handler(buff, bufc, executor, fargs, false);
03309 }
03310
03311 FUNCTION(fun_grepi)
03312 {
03313 UNUSED_PARAMETER(caller);
03314 UNUSED_PARAMETER(enactor);
03315 UNUSED_PARAMETER(nfargs);
03316 UNUSED_PARAMETER(cargs);
03317 UNUSED_PARAMETER(ncargs);
03318
03319 grep_handler(buff, bufc, executor, fargs, true);
03320 }
03321
03322
03323
03324 FUNCTION(fun_alphamax)
03325 {
03326 UNUSED_PARAMETER(executor);
03327 UNUSED_PARAMETER(caller);
03328 UNUSED_PARAMETER(enactor);
03329 UNUSED_PARAMETER(cargs);
03330 UNUSED_PARAMETER(ncargs);
03331
03332 char *amax = fargs[0];
03333 for (int i = 1; i < nfargs; i++)
03334 {
03335 if (fargs[i] && strcmp(amax, fargs[i]) < 0)
03336 {
03337 amax = fargs[i];
03338 }
03339 }
03340 safe_str(amax, buff, bufc);
03341 }
03342
03343
03344
03345 FUNCTION(fun_alphamin)
03346 {
03347 UNUSED_PARAMETER(executor);
03348 UNUSED_PARAMETER(caller);
03349 UNUSED_PARAMETER(enactor);
03350 UNUSED_PARAMETER(cargs);
03351 UNUSED_PARAMETER(ncargs);
03352
03353 char *amin = fargs[0];
03354 for (int i = 1; i < nfargs; i++)
03355 {
03356 if (fargs[i] && strcmp(amin, fargs[i]) > 0)
03357 {
03358 amin = fargs[i];
03359 }
03360 }
03361 safe_str(amin, buff, bufc);
03362 }
03363
03364
03365
03366 FUNCTION(fun_valid)
03367 {
03368 UNUSED_PARAMETER(executor);
03369 UNUSED_PARAMETER(caller);
03370 UNUSED_PARAMETER(enactor);
03371 UNUSED_PARAMETER(nfargs);
03372 UNUSED_PARAMETER(cargs);
03373 UNUSED_PARAMETER(ncargs);
03374
03375
03376
03377
03378 int nValidName;
03379 bool bValid;
03380 if (!*fargs[0] || !*fargs[1])
03381 {
03382 bValid = false;
03383 }
03384 else if (!mux_stricmp(fargs[0], "name"))
03385 {
03386 MakeCanonicalObjectName(fargs[1], &nValidName, &bValid);
03387 }
03388 else if (!mux_stricmp(fargs[0], "attrname"))
03389 {
03390 MakeCanonicalAttributeName(fargs[1], &nValidName, &bValid);
03391 }
03392 else if (!mux_stricmp(fargs[0], "playername"))
03393 {
03394 bValid = ValidatePlayerName(fargs[1]);
03395 }
03396 else
03397 {
03398 safe_nothing(buff, bufc);
03399 return;
03400 }
03401 safe_bool(bValid, buff, bufc);
03402 }
03403
03404
03405
03406 FUNCTION(fun_hastype)
03407 {
03408 UNUSED_PARAMETER(caller);
03409 UNUSED_PARAMETER(enactor);
03410 UNUSED_PARAMETER(nfargs);
03411 UNUSED_PARAMETER(cargs);
03412 UNUSED_PARAMETER(ncargs);
03413
03414 dbref it = match_thing_quiet(executor, fargs[0]);
03415 if (!Good_obj(it))
03416 {
03417 safe_match_result(it, buff, bufc);
03418 return;
03419 }
03420 bool bResult = false;
03421 switch (mux_tolower(fargs[1][0]))
03422 {
03423 case 'r':
03424
03425 bResult = isRoom(it);
03426 break;
03427
03428 case 'e':
03429
03430 bResult = isExit(it);
03431 break;
03432
03433 case 'p':
03434
03435 bResult = isPlayer(it);
03436 break;
03437
03438 case 't':
03439
03440 bResult = isThing(it);
03441 break;
03442
03443 default:
03444
03445 safe_str("#-1 NO SUCH TYPE", buff, bufc);
03446 break;
03447 }
03448 safe_bool(bResult, buff, bufc);
03449 }
03450
03451
03452
03453 FUNCTION(fun_lparent)
03454 {
03455 UNUSED_PARAMETER(caller);
03456 UNUSED_PARAMETER(enactor);
03457 UNUSED_PARAMETER(nfargs);
03458 UNUSED_PARAMETER(cargs);
03459 UNUSED_PARAMETER(ncargs);
03460
03461 dbref it = match_thing_quiet(executor, fargs[0]);
03462 if (!Good_obj(it))
03463 {
03464 safe_match_result(it, buff, bufc);
03465 return;
03466 }
03467 else if (!Examinable(executor, it))
03468 {
03469 safe_noperm(buff, bufc);
03470 return;
03471 }
03472
03473 ITL pContext;
03474 ItemToList_Init(&pContext, buff, bufc, '#');
03475 if (!ItemToList_AddInteger(&pContext, it))
03476 {
03477 ItemToList_Final(&pContext);
03478 return;
03479 }
03480
03481 dbref par = Parent(it);
03482
03483 int iNestLevel = 1;
03484 while ( Good_obj(par)
03485 && Examinable(executor, it)
03486 && iNestLevel < mudconf.parent_nest_lim)
03487 {
03488 if (!ItemToList_AddInteger(&pContext, par))
03489 {
03490 break;
03491 }
03492 it = par;
03493 par = Parent(par);
03494 iNestLevel++;
03495 }
03496 ItemToList_Final(&pContext);
03497 }
03498
03499
03500
03501 static int stacksize(dbref doer)
03502 {
03503 int i;
03504 STACK *sp;
03505 for (i = 0, sp = Stack(doer); sp != NULL; sp = sp->next, i++)
03506 {
03507
03508 ;
03509 }
03510 return i;
03511 }
03512
03513 FUNCTION(fun_lstack)
03514 {
03515 UNUSED_PARAMETER(caller);
03516 UNUSED_PARAMETER(enactor);
03517 UNUSED_PARAMETER(cargs);
03518 UNUSED_PARAMETER(ncargs);
03519
03520 STACK *sp;
03521 dbref doer;
03522
03523 if (nfargs == 0 || !*fargs[0])
03524 {
03525 doer = executor;
03526 }
03527 else
03528 {
03529 doer = match_thing_quiet(executor, fargs[0]);
03530 if (!Good_obj(doer))
03531 {
03532 safe_match_result(doer, buff, bufc);
03533 return;
03534 }
03535 }
03536
03537 if (!Controls(executor, doer))
03538 {
03539 safe_noperm(buff, bufc);
03540 return;
03541 }
03542 for (sp = Stack(doer); sp != NULL; sp = sp->next)
03543 {
03544 safe_str(sp->data, buff, bufc);
03545 if (sp->next != NULL)
03546 {
03547 safe_chr(' ', buff, bufc);
03548 }
03549 }
03550 }
03551
03552
03553
03554 void stack_clr(dbref obj)
03555 {
03556
03557
03558 STACK *sp, *next;
03559 for (sp = Stack(obj); sp != NULL; sp = next)
03560 {
03561 next = sp->next;
03562 free_lbuf(sp->data);
03563 MEMFREE(sp);
03564 sp = NULL;
03565 }
03566 s_Stack(obj, NULL);
03567 }
03568
03569 FUNCTION(fun_empty)
03570 {
03571 UNUSED_PARAMETER(caller);
03572 UNUSED_PARAMETER(enactor);
03573 UNUSED_PARAMETER(cargs);
03574 UNUSED_PARAMETER(ncargs);
03575
03576 dbref doer;
03577
03578 if (nfargs == 0 || !*fargs[0])
03579 {
03580 doer = executor;
03581 }
03582 else
03583 {
03584 doer = match_thing_quiet(executor, fargs[0]);
03585 if (!Good_obj(doer))
03586 {
03587 safe_match_result(doer, buff, bufc);
03588 return;
03589 }
03590 }
03591
03592 if (!Controls(executor, doer))
03593 {
03594 safe_noperm(buff, bufc);
03595 return;
03596 }
03597 stack_clr(doer);
03598 }
03599
03600 FUNCTION(fun_items)
03601 {
03602 UNUSED_PARAMETER(caller);
03603 UNUSED_PARAMETER(enactor);
03604 UNUSED_PARAMETER(cargs);
03605 UNUSED_PARAMETER(ncargs);
03606
03607 dbref doer;
03608
03609 if (nfargs == 0 || !*fargs[0])
03610 {
03611 doer = executor;
03612 }
03613 else
03614 {
03615 doer = match_thing_quiet(executor, fargs[0]);
03616 if (!Good_obj(doer))
03617 {
03618 safe_match_result(doer, buff, bufc);
03619 return;
03620 }
03621 }
03622
03623 if (!Controls(executor, doer))
03624 {
03625 safe_noperm(buff, bufc);
03626 return;
03627 }
03628 safe_ltoa(stacksize(doer), buff, bufc);
03629 }
03630
03631 FUNCTION(fun_peek)
03632 {
03633 UNUSED_PARAMETER(caller);
03634 UNUSED_PARAMETER(enactor);
03635 UNUSED_PARAMETER(cargs);
03636 UNUSED_PARAMETER(ncargs);
03637
03638 STACK *sp;
03639 dbref doer;
03640 int count, pos;
03641
03642 if (nfargs <= 0 || !*fargs[0])
03643 {
03644 doer = executor;
03645 }
03646 else
03647 {
03648 doer = match_thing_quiet(executor, fargs[0]);
03649 if (!Good_obj(doer))
03650 {
03651 safe_match_result(doer, buff, bufc);
03652 return;
03653 }
03654 }
03655
03656 if (!Controls(executor, doer))
03657 {
03658 safe_noperm(buff, bufc);
03659 return;
03660 }
03661 if (nfargs <= 1 || !*fargs[1])
03662 {
03663 pos = 0;
03664 }
03665 else
03666 {
03667 pos = mux_atol(fargs[1]);
03668 }
03669
03670 if (stacksize(doer) == 0)
03671 {
03672 return;
03673 }
03674 if (pos > (stacksize(doer) - 1))
03675 {
03676 safe_str("#-1 POSITION TOO LARGE", buff, bufc);
03677 return;
03678 }
03679 count = 0;
03680 sp = Stack(doer);
03681 while (count != pos)
03682 {
03683 if (sp == NULL)
03684 {
03685 return;
03686 }
03687 count++;
03688 sp = sp->next;
03689 }
03690
03691 safe_str(sp->data, buff, bufc);
03692 }
03693
03694 FUNCTION(fun_pop)
03695 {
03696 UNUSED_PARAMETER(caller);
03697 UNUSED_PARAMETER(enactor);
03698 UNUSED_PARAMETER(cargs);
03699 UNUSED_PARAMETER(ncargs);
03700
03701 dbref doer;
03702
03703 if (nfargs <= 0 || !*fargs[0])
03704 {
03705 doer = executor;
03706 }
03707 else
03708 {
03709 doer = match_thing_quiet(executor, fargs[0]);
03710 if (!Good_obj(doer))
03711 {
03712 safe_match_result(doer, buff, bufc);
03713 return;
03714 }
03715 }
03716 if (!Controls(executor, doer))
03717 {
03718 safe_noperm(buff, bufc);
03719 return;
03720 }
03721
03722 int pos;
03723 if (nfargs <= 1 || !*fargs[1])
03724 {
03725 pos = 0;
03726 }
03727 else
03728 {
03729 pos = mux_atol(fargs[1]);
03730 }
03731 if (stacksize(doer) == 0)
03732 {
03733 return;
03734 }
03735 if (pos > (stacksize(doer) - 1))
03736 {
03737 safe_str("#-1 POSITION TOO LARGE", buff, bufc);
03738 return;
03739 }
03740
03741 STACK *sp = Stack(doer);
03742 STACK *prev = NULL;
03743 int count = 0;
03744 while (count != pos)
03745 {
03746 if (sp == NULL)
03747 {
03748 return;
03749 }
03750 prev = sp;
03751 sp = sp->next;
03752 count++;
03753 }
03754
03755 safe_str(sp->data, buff, bufc);
03756 if (count == 0)
03757 {
03758 s_Stack(doer, sp->next);
03759 free_lbuf(sp->data);
03760 MEMFREE(sp);
03761 sp = NULL;
03762 }
03763 else
03764 {
03765 prev->next = sp->next;
03766 free_lbuf(sp->data);
03767 MEMFREE(sp);
03768 sp = NULL;
03769 }
03770 }
03771
03772 FUNCTION(fun_push)
03773 {
03774 UNUSED_PARAMETER(caller);
03775 UNUSED_PARAMETER(enactor);
03776 UNUSED_PARAMETER(cargs);
03777 UNUSED_PARAMETER(ncargs);
03778
03779 dbref doer;
03780 char *data;
03781
03782 if (nfargs <= 1 || !*fargs[1])
03783 {
03784 doer = executor;
03785 data = fargs[0];
03786 }
03787 else
03788 {
03789 doer = match_thing_quiet(executor, fargs[0]);
03790 if (!Good_obj(doer))
03791 {
03792 safe_match_result(doer, buff, bufc);
03793 return;
03794 }
03795 data = fargs[1];
03796 }
03797
03798 if (!Controls(executor, doer))
03799 {
03800 safe_noperm(buff, bufc);
03801 return;
03802 }
03803 if (stacksize(doer) >= mudconf.stack_limit)
03804 {
03805 safe_str("#-1 STACK SIZE EXCEEDED", buff, bufc);
03806 return;
03807 }
03808 STACK *sp = (STACK *)MEMALLOC(sizeof(STACK));
03809 ISOUTOFMEMORY(sp);
03810 sp->next = Stack(doer);
03811 sp->data = alloc_lbuf("push");
03812 strcpy(sp->data, data);
03813 s_Stack(doer, sp);
03814 }
03815
03816
03817
03818
03819
03820
03821
03822
03823
03824
03825
03826
03827
03828
03829 static void real_regmatch(const char *search, const char *pattern, char *registers,
03830 int nfargs, char *buff, char **bufc, bool cis)
03831 {
03832 if (MuxAlarm.bAlarmed)
03833 {
03834 return;
03835 }
03836
03837 const char *errptr;
03838 int erroffset;
03839
03840
03841
03842 const int ovecsize = 6 * MAX_GLOBAL_REGS;
03843 int ovec[ovecsize];
03844
03845 pcre *re = pcre_compile(pattern, cis ? PCRE_CASELESS : 0,
03846 &errptr, &erroffset, NULL);
03847 if (!re)
03848 {
03849
03850
03851 safe_str("#-1 REGEXP ERROR ", buff, bufc);
03852 safe_str(errptr, buff, bufc);
03853 return;
03854 }
03855
03856 int matches = pcre_exec(re, NULL, search, strlen(search), 0, 0,
03857 ovec, ovecsize);
03858 if (matches == 0)
03859 {
03860
03861
03862
03863 matches = ovecsize / 3;
03864 }
03865 safe_bool(matches > 0, buff, bufc);
03866 if (matches < 0)
03867 {
03868 matches = 0;
03869 }
03870
03871
03872
03873 if (nfargs != 3)
03874 {
03875 MEMFREE(re);
03876 return;
03877 }
03878
03879
03880
03881
03882
03883 const int NSUBEXP = 2 * MAX_GLOBAL_REGS;
03884 char *qregs[NSUBEXP];
03885 SEP sep;
03886 sep.n = 1;
03887 memcpy(sep.str, " ", 2);
03888 int nqregs = list2arr(qregs, NSUBEXP, registers, &sep);
03889 int i;
03890 for (i = 0; i < nqregs; i++)
03891 {
03892 int curq;
03893 if ( qregs[i]
03894 && *qregs[i]
03895 && (curq = mux_RegisterSet[(unsigned char)qregs[i][0]]) != -1
03896 && qregs[i][1] == '\0'
03897 && curq < MAX_GLOBAL_REGS)
03898 {
03899 if (!mudstate.global_regs[curq])
03900 {
03901 mudstate.global_regs[curq] = alloc_lbuf("fun_regmatch");
03902 }
03903 int len;
03904 len = pcre_copy_substring(search, ovec, matches, i,
03905 mudstate.global_regs[curq], LBUF_SIZE);
03906 mudstate.glob_reg_len[curq] = (len > 0 ? len : 0);
03907 }
03908 }
03909 MEMFREE(re);
03910 }
03911
03912 FUNCTION(fun_regmatch)
03913 {
03914 UNUSED_PARAMETER(executor);
03915 UNUSED_PARAMETER(enactor);
03916 UNUSED_PARAMETER(caller);
03917 UNUSED_PARAMETER(enactor);
03918 UNUSED_PARAMETER(cargs);
03919 UNUSED_PARAMETER(ncargs);
03920
03921 real_regmatch(fargs[0], fargs[1], fargs[2], nfargs, buff, bufc, false);
03922 }
03923
03924 FUNCTION(fun_regmatchi)
03925 {
03926 UNUSED_PARAMETER(executor);
03927 UNUSED_PARAMETER(enactor);
03928 UNUSED_PARAMETER(caller);
03929 UNUSED_PARAMETER(enactor);
03930 UNUSED_PARAMETER(cargs);
03931 UNUSED_PARAMETER(ncargs);
03932
03933 real_regmatch(fargs[0], fargs[1], fargs[2], nfargs, buff, bufc, true);
03934 }
03935
03936
03937
03938
03939
03940
03941
03942 static void real_regrab(char *search, const char *pattern, SEP *psep, char *buff,
03943 char **bufc, bool cis, bool all)
03944 {
03945 if (MuxAlarm.bAlarmed)
03946 {
03947 return;
03948 }
03949 pcre *re;
03950 pcre_extra *study = NULL;
03951 const char *errptr;
03952 int erroffset;
03953
03954
03955
03956 const int ovecsize = 6 * MAX_GLOBAL_REGS;
03957 int ovec[ovecsize];
03958
03959 re = pcre_compile(pattern, cis ? PCRE_CASELESS : 0,
03960 &errptr, &erroffset, NULL);
03961 if (!re)
03962 {
03963
03964
03965 safe_str("#-1 REGEXP ERROR ", buff, bufc);
03966 safe_str(errptr, buff, bufc);
03967 return;
03968 }
03969
03970 if (all)
03971 {
03972 study = pcre_study(re, 0, &errptr);
03973 }
03974
03975 bool first = true;
03976 char *s = trim_space_sep(search, psep);
03977 do
03978 {
03979 char *r = split_token(&s, psep);
03980 if ( !MuxAlarm.bAlarmed
03981 && pcre_exec(re, study, r, strlen(r), 0, 0, ovec, ovecsize) >= 0)
03982 {
03983 if (first)
03984 {
03985 first = false;
03986 }
03987 else
03988 {
03989 print_sep(psep, buff, bufc);
03990 }
03991 safe_str(r, buff, bufc);
03992 if (!all)
03993 {
03994 break;
03995 }
03996 }
03997 } while (s);
03998
03999 MEMFREE(re);
04000 if (study)
04001 {
04002 MEMFREE(study);
04003 }
04004 }
04005
04006 FUNCTION(fun_regrab)
04007 {
04008 SEP sep;
04009 if (!OPTIONAL_DELIM(3, sep, DELIM_DFLT|DELIM_STRING))
04010 {
04011 return;
04012 }
04013 real_regrab(fargs[0], fargs[1], &sep, buff, bufc, false, false);
04014 }
04015
04016 FUNCTION(fun_regrabi)
04017 {
04018 SEP sep;
04019 if (!OPTIONAL_DELIM(3, sep, DELIM_DFLT|DELIM_STRING))
04020 {
04021 return;
04022 }
04023 real_regrab(fargs[0], fargs[1], &sep, buff, bufc, true, false);
04024 }
04025
04026 FUNCTION(fun_regraball)
04027 {
04028 SEP sep;
04029 if (!OPTIONAL_DELIM(3, sep, DELIM_DFLT|DELIM_STRING))
04030 {
04031 return;
04032 }
04033 real_regrab(fargs[0], fargs[1], &sep, buff, bufc, false, true);
04034 }
04035
04036 FUNCTION(fun_regraballi)
04037 {
04038 SEP sep;
04039 if (!OPTIONAL_DELIM(3, sep, DELIM_DFLT|DELIM_STRING))
04040 {
04041 return;
04042 }
04043 real_regrab(fargs[0], fargs[1], &sep, buff, bufc, true, true);
04044 }
04045
04046
04047
04048
04049
04050
04051
04052
04053 FUNCTION(fun_translate)
04054 {
04055 UNUSED_PARAMETER(executor);
04056 UNUSED_PARAMETER(caller);
04057 UNUSED_PARAMETER(enactor);
04058 UNUSED_PARAMETER(nfargs);
04059 UNUSED_PARAMETER(cargs);
04060 UNUSED_PARAMETER(ncargs);
04061
04062 int ch = fargs[1][0];
04063 bool type = (ch == 'p' || ch == '1');
04064 safe_str(translate_string(fargs[0], type), buff, bufc);
04065 }
04066
04067
04068
04069
04070 CBitField::CBitField(unsigned int nMaximum_arg)
04071 {
04072 nMaximum = 0;
04073 nInts = 0;
04074 pInts = NULL;
04075 pMasks = NULL;
04076
04077 nBitsPer = sizeof(UINT32)*8;
04078
04079
04080
04081 nShift = 0;
04082 unsigned int i = 1;
04083 while (i < nBitsPer)
04084 {
04085 nShift++;
04086 i <<= 1;
04087 }
04088
04089
04090
04091 nMask = nBitsPer - 1;
04092
04093
04094
04095 Resize(nMaximum_arg);
04096 }
04097
04098 #define MINIMUM_RESIZE (4096*sizeof(UINT32))
04099
04100 void CBitField::Resize(unsigned int nMaximum_arg)
04101 {
04102 if ( 0 < nMaximum_arg
04103 && nMaximum < nMaximum_arg)
04104 {
04105 unsigned int nNewMaximum = nMaximum_arg;
04106
04107
04108
04109 if ( pMasks
04110 && nNewMaximum < nMaximum + MINIMUM_RESIZE)
04111 {
04112 nNewMaximum = nMaximum + MINIMUM_RESIZE;
04113 }
04114
04115 size_t nNewInts = (nNewMaximum+nBitsPer) >> nShift;
04116 UINT32 *pNewMasks = (UINT32 *)MEMALLOC((nNewInts+nBitsPer)
04117 * sizeof(UINT32));
04118 ISOUTOFMEMORY(pNewMasks);
04119 UINT32 *pNewInts = pNewMasks + nBitsPer;
04120
04121
04122
04123 if (pMasks)
04124 {
04125
04126
04127
04128 memcpy(pNewMasks, pMasks, (nInts+nBitsPer)*sizeof(UINT32));
04129 memset(pNewInts + nInts, 0, (nNewInts - nInts)*sizeof(UINT32));
04130
04131
04132
04133 MEMFREE(pMasks);
04134
04135
04136
04137 nMaximum = nNewMaximum;
04138 nInts = nNewInts;
04139 pMasks = pNewMasks;
04140 pInts = pNewInts;
04141 }
04142 else
04143 {
04144
04145
04146 nMaximum = nNewMaximum;
04147 nInts = nNewInts;
04148 pMasks = pNewMasks;
04149 pInts = pNewInts;
04150
04151
04152
04153 for (unsigned int i = 0; i < nBitsPer; i++)
04154 {
04155 pMasks[i] = ((UINT32)1) << i;
04156 }
04157
04158
04159
04160 ClearAll();
04161 }
04162 }
04163 }
04164
04165 CBitField::~CBitField(void)
04166 {
04167 pInts = NULL;
04168 if (pMasks)
04169 {
04170 MEMFREE(pMasks);
04171 pMasks = NULL;
04172 }
04173 }
04174
04175 void CBitField::ClearAll(void)
04176 {
04177 memset(pInts, 0, nInts*sizeof(UINT32));
04178 }
04179
04180 void CBitField::Set(unsigned int i)
04181 {
04182 if (i <= nMaximum)
04183 {
04184 pInts[i>>nShift] |= pMasks[i&nMask];
04185 }
04186 }
04187
04188 void CBitField::Clear(unsigned int i)
04189 {
04190 if (i <= nMaximum)
04191 {
04192 pInts[i>>nShift] &= ~pMasks[i&nMask];
04193 }
04194 }
04195
04196 bool CBitField::IsSet(unsigned int i)
04197 {
04198 if (i <= nMaximum)
04199 {
04200 if (pInts[i>>nShift] & pMasks[i&nMask])
04201 {
04202 return true;
04203 }
04204 }
04205 return false;
04206 }
04207
04208
04209
04210
04211
04212
04213
04214
04215
04216
04217
04218
04219
04220
04221 static void room_list
04222 (
04223 dbref player,
04224 dbref enactor,
04225 dbref room,
04226 int level,
04227 int maxlevels,
04228 bool showall
04229 )
04230 {
04231
04232
04233 if ( ( level == maxlevels
04234 || showall)
04235 && ( Examinable(player, room)
04236 || Location(player) == room
04237 || room == enactor))
04238 {
04239 mudstate.bfReport.Set(room);
04240 }
04241
04242
04243
04244 if (level >= maxlevels)
04245 {
04246 return;
04247 }
04248
04249
04250
04251 int lev;
04252 dbref parent;
04253 ITER_PARENTS(room, parent, lev)
04254 {
04255
04256
04257 if (!Has_exits(parent))
04258 {
04259 continue;
04260 }
04261 int key = 0;
04262 if (Examinable(player, parent))
04263 {
04264 key |= VE_LOC_XAM;
04265 }
04266 if (Dark(parent))
04267 {
04268 key |= VE_LOC_DARK;
04269 }
04270 if (Dark(room))
04271 {
04272 key |= VE_BASE_DARK;
04273 }
04274
04275 dbref thing;
04276 DOLIST(thing, Exits(parent))
04277 {
04278 dbref loc = Location(thing);
04279 if ( exit_visible(thing, player, key)
04280 && !mudstate.bfTraverse.IsSet(loc))
04281 {
04282 mudstate.bfTraverse.Set(loc);
04283 room_list(player, enactor, loc, (level + 1), maxlevels, showall);
04284 }
04285 }
04286 }
04287 }
04288
04289 FUNCTION(fun_lrooms)
04290 {
04291 UNUSED_PARAMETER(caller);
04292 UNUSED_PARAMETER(cargs);
04293 UNUSED_PARAMETER(ncargs);
04294
04295 dbref room = match_thing_quiet(executor, fargs[0]);
04296 if (!Good_obj(room))
04297 {
04298 safe_match_result(room, buff, bufc);
04299 return;
04300 }
04301 else if (!isRoom(room))
04302 {
04303 safe_str("#-1 FIRST ARGUMENT MUST BE A ROOM", buff, bufc);
04304 return;
04305 }
04306
04307 int N = 1;
04308 if (nfargs >= 2)
04309 {
04310 N = mux_atol(fargs[1]);
04311 if (N < 0)
04312 {
04313 safe_str("#-1 SECOND ARGUMENT MUST BE A POSITIVE NUMBER",
04314 buff, bufc);
04315 return;
04316 }
04317 else if (N > 50)
04318 {
04319
04320
04321
04322 safe_str("#-1 SECOND ARGUMENT IS TOO LARGE", buff, bufc);
04323 return;
04324 }
04325 }
04326
04327 bool B = true;
04328 if (nfargs == 3)
04329 {
04330 B = xlate(fargs[2]);
04331 }
04332
04333 mudstate.bfReport.Resize(mudstate.db_top-1);
04334 mudstate.bfTraverse.Resize(mudstate.db_top-1);
04335 mudstate.bfReport.ClearAll();
04336 mudstate.bfTraverse.ClearAll();
04337
04338 mudstate.bfTraverse.Set(room);
04339 room_list(executor, enactor, room, 0, N, B);
04340 mudstate.bfReport.Clear(room);
04341
04342 ITL pContext;
04343 ItemToList_Init(&pContext, buff, bufc, '#');
04344 dbref i;
04345 DO_WHOLE_DB(i)
04346 {
04347 if ( mudstate.bfReport.IsSet(i)
04348 && !ItemToList_AddInteger(&pContext, i))
04349 {
04350 break;
04351 }
04352 }
04353 ItemToList_Final(&pContext);
04354 }