mux/src/funceval.cpp

Go to the documentation of this file.
00001 // funceval.cpp -- MUX function handlers.
00002 //
00003 // $Id: funceval.cpp,v 1.106 2007/04/14 04:57:05 sdennis Exp $
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 /* REALITY_LVLS */
00024 
00025 /* Note: Many functions in this file have been taken, whole or in part, from
00026  * PennMUSH 1.50, and TinyMUSH 2.2, for softcode compatibility. The
00027  * maintainers of MUX would like to thank those responsible for PennMUSH 1.50
00028  * and TinyMUSH 2.2, and hope we have adequately noted in the source where
00029  * credit is due.
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     // Two possibilities for the first arg: <obj>/<attr> and <attr>.
00037     //
00038     if (!parse_attrib(executor, fargs[0], thing, &ap))
00039     {
00040         *thing = executor;
00041         ap = atr_str(fargs[0]);
00042     }
00043 
00044     // Make sure we got a good attribute.
00045     //
00046     if (!ap)
00047     {
00048         return false;
00049     }
00050 
00051     // Use it if we can access it, otherwise return an error.
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,      // 0x00-0x0F
00156     0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0,      // 0x10-0x1F
00157     0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0,      // 0x20-0x2F
00158     0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0,      // 0x30-0x3F
00159     0,           0,             ANSI_BC,     ANSI_BC,     // 0x40-0x43
00160     0,           0,             0,           ANSI_BC,     // 0x44-0x47
00161     0,           0,             0,           0,           // 0x48-0x4B
00162     0,           ANSI_BC,       0,           0,           // 0x4B-0x4F
00163     0,           0,             ANSI_BC,     0,           // 0x50-0x53
00164     0,           0,             0,           ANSI_BC,     // 0x54-0x57
00165     ANSI_BC,     ANSI_BC,       0,           0,           // 0x58-0x5B
00166     0,           0,             0,           0,           // 0x5B-0x5F
00167     0,           0,             ANSI_FC,     ANSI_FC,     // 0x60-0x63
00168     0,           0,             ANSI_F,      ANSI_FC,     // 0x64-0x67
00169     ANSI_H,      ANSI_I,        0,           0,           // 0x68-0x6B
00170     0,           ANSI_FC,       0,           0,           // 0x6C-0x6F
00171     0,           0,             ANSI_FC,     0,           // 0x70-0x73
00172     0,           ANSI_U,        0,           ANSI_FC,     // 0x74-0x77
00173     ANSI_FC,     ANSI_FC,       0,           0,           // 0x78-0x7B
00174     0,           0,             0,           0,           // 0x7B-0x7F
00175     0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0,      // 0x80-0x8F
00176     0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0,      // 0x90-0x9F
00177     0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0,      // 0xA0-0xAF
00178     0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0,      // 0xB0-0xBF
00179     0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0,      // 0xC0-0xCF
00180     0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0,      // 0xD0-0xDF
00181     0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0,      // 0xE0-0xEF
00182     0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0       // 0xF0-0xFF
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 // This function was originally taken from PennMUSH 1.50
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         // Perform checks similiar to (but not exactly like) the
00284         // ones in process_cmdent(): object type checks, permission
00285         // checks, ands global flags.
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 // fun_create: Creates a room, thing or exit.
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  * fun_set: sets an attribute on an object
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     // See if we have the <obj>/<attr> form, which is how you set
00570     // attribute flags.
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             // You must specify a flag name.
00580             //
00581             if (flagname[0] == '\0')
00582             {
00583                 safe_str("#-1 UNSPECIFIED PARAMETER", buff, bufc);
00584                 return;
00585             }
00586 
00587             // Check for clearing.
00588             //
00589             bool clear = false;
00590             if (flagname[0] == NOT_TOKEN)
00591             {
00592                 flagname++;
00593                 clear = true;
00594             }
00595 
00596             // Make sure player specified a valid attribute flag.
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             // Make sure the object has the attribute present.
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             // Make sure we can write to the attribute.
00614             //
00615             if (!bCanSetAttr(executor, thing, pattr))
00616             {
00617                 safe_noperm(buff, bufc);
00618                 return;
00619             }
00620 
00621             // Go do it.
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     // Find thing.
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     // Check for attr set first.
00646     //
00647     char *p;
00648     for (p = fargs[1]; *p && *p != ':'; p++)
00649     {
00650         ; // Nothing
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         // Check for _
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         // Go set it.
00702         //
00703         set_attr_internal(executor, thing, atr, p, 0, buff, bufc);
00704         free_lbuf(buff2);
00705         return;
00706     }
00707 
00708     // Set/clear a flag.
00709     //
00710     flag_set(thing, executor, fargs[1], 0);
00711 }
00712 #endif
00713 
00714 // Generate a substitution array.
00715 //
00716 static unsigned int GenCode(char *pCode, const char *pCodeASCII)
00717 {
00718     // Strip out the ANSI.
00719     //
00720     size_t nIn;
00721     char *pIn = strip_ansi(pCodeASCII, &nIn);
00722 
00723     // Process the printable characters.
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     // Encryption loop:
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 // Code for encrypt() and decrypt() was taken from the DarkZone
00809 // server.
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 // Borrowed from DarkZone
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 // Borrowed from DarkZone
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         // The right circumstances were not met, so we are evaluating
00965         // as the executor who gave the command instead of the
00966         // requested object.
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 // Borrowed from PennMUSH 1.50
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     // Find the user function attribute.
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 // table(<list>,<field width>,<line length>,<delimiter>,<output separator>, <padding>)
01181 //
01182 // Ported from PennMUSH 1.7.3 by Morgan.
01183 //
01184 // TODO: Support ANSI in output separator and padding.
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     // Check argument numbers, assign values and defaults if necessary.
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     // Get single-character separator.
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     // Get single-character delimiter.
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     // Get line length.
01237     //
01238     int nLineLength = 78;
01239     if (nfargs >= 3)
01240     {
01241         nLineLength = mux_atol(fargs[2]);
01242     }
01243 
01244     // Get field width.
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     // Validate nFieldWidth and nLineLength.
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         {