PennMUSH Enhancements 1.8.3p7 Applied.
authorRick L Bird <nveid@yahoo.com>
Fri, 22 Apr 2011 17:39:37 +0000 (13:39 -0400)
committerRick L Bird <nveid@yahoo.com>
Fri, 22 Apr 2011 17:39:37 +0000 (13:39 -0400)
This commit refs #69, #70, #71, #72, #73, #74, #75, #76, #77, #78
Also refs #79, #80, #81, #82, #83, #84, #85, #86, #87, #88, #89, #90,
And refs #91, and #92

75 files changed:
COPYRITE
config.h.in
configure.ac
game/mushcnf.dst
game/txt/hlp/cobra_chat.hlp
game/txt/hlp/cobra_cmd.hlp
game/txt/hlp/cobra_func.hlp
hdrs/access.h
hdrs/attrib.h
hdrs/boolexp.h
hdrs/conf.h
hdrs/dbio.h
hdrs/division.h
hdrs/externs.h
hdrs/extmail.h
hdrs/flags.h
hdrs/function.h
hdrs/game.h
hdrs/malias.h
hdrs/shs.h
src/Makefile.in
src/SWITCHES
src/access.c
src/attrib.c
src/bsd.c
src/chunk.c
src/cmds.c
src/command.c
src/comp_h.c
src/comp_w.c
src/comp_w8.c
src/conf.c
src/cque.c
src/create.c
src/cron.c
src/db.c
src/destroy.c
src/division.c
src/extmail.c
src/flags.c
src/funcrypt.c
src/function.c
src/fundb.c
src/fundiv.c
src/funlist.c
src/funmath.c
src/funmisc.c
src/funstr.c
src/game.c
src/help.c
src/htab.c
src/ident.c
src/lock.c
src/log.c
src/look.c
src/malias.c
src/markup.c
src/match.c
src/mymalloc.c
src/myrlimit.c
src/myssl.c
src/notify.c
src/parse.c
src/pcre.c
src/player.c
src/sort.c
src/speech.c
src/tables.c
src/utils.c
src/version.c
src/wild.c
src/wiz.c
test/PennMUSH.pm
test/testhastype.pl
utils/gentables.c

index b5631d80d1ac83cff3d3703e776ee10ebd592e32..083ef3cb53134e24297181af4e7df53b1d642276 100644 (file)
--- a/COPYRITE
+++ b/COPYRITE
  * of CobraMUSH derived from or inspired by PennMUSH, TinyMUSH 2.0,
  * TinyMUSH 2.2, or TinyMUD.
  */
+
+ IV: Additional Copyrights
+
++ Penn includes the SIMD-oriented Fast Mersenne Twister PRNG:
+
+Copyright (c) 2006,2007 Mutsuo Saito, Makoto Matsumoto and Hiroshima
+University. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+    * Neither the name of the Hiroshima University nor the names of
+      its contributors may be used to endorse or promote products
+      derived from this software without specific prior written
+      permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
++ Penn includes a heavily modified old version of the Perl Compatible
+Regular Expression library:
+
+                       Written by Philip Hazel
+           Copyright (c) 1997-2005 University of Cambridge
+
+-----------------------------------------------------------------------------
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright notice,
+      this list of conditions and the following disclaimer.
+
+    * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+
+    * Neither the name of the University of Cambridge nor the names of its
+      contributors may be used to endorse or promote products derived from
+      this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+-----------------------------------------------------------------------------
+
index f6b09a32733592f4e5b80231b61f6a939842c5a5..d8d13956bd2ac18b7babffe93931945bb484a389 100644 (file)
 
 #undef HAVE_LIBFAM
 
+#undef HAVE_ZLIB_H
+
+#undef HAVE_LIBZ
+
 /* C99ish headers. The first two are really really nice to have. */
 
 #undef HAVE_STDINT_H
@@ -265,6 +269,9 @@ typedef void Free_t;
 
 #undef HAVE__VSNPRINTF_S
 
+#undef HAVE_VASPRINTF
+
+#undef HAVE_STRCHRNUL
 
 #undef HAVE_STRDUP
 
@@ -304,7 +311,7 @@ typedef void Free_t;
 
 #undef HAVE_EPOLL_CTL
 
-#undef HAVE_VALLOC
+#undef HAVE_POSIX_MEMALIGN
 
 #undef HAVE_WRITEV
 
@@ -320,6 +327,10 @@ typedef void Free_t;
 
 #undef HAVE_PWRITE
 
+#undef HAVE_POSIX_FADVISE
+
+#undef HAVE_POSIX_FALLOCATE
+
 /* Variables and defines */
 
 #undef HAVE_H_ERRNO
@@ -340,6 +351,8 @@ typedef void Free_t;
 
 #undef DONT_TRANSLATE
 
+#undef INFO_SLAVE
+
 #undef HAVE_UPTIME
 
 /* Path to uptime */
@@ -350,6 +363,9 @@ typedef void Free_t;
 /* Path to sendmail */
 #undef SENDMAIL
 
+#undef HAVE_ED
+#undef ED_PATH
+
 #undef HAVE_SAFE_TOUPPER
 
 /* Optional language features */
@@ -370,6 +386,20 @@ typedef void Free_t;
 
 #undef GCC_MALLOC_CALL
 
+
+/* Turn on SSE2 stuff automatically if supported (IE, x86-64 or x86 with the right -march switch) */
+#undef HAVE_SSE2
+#ifdef __SSE2__
+#define HAVE_SSE2
+#endif
+
+#undef HAVE_SSE3
+#ifdef __SSE3__
+#define HAVE_SSE3
+#endif
+
+#undef HAVE_ALTIVEC
+
 /* TODO: Change in source */
 #define RESTRICT restrict
 
index 5aa4dc929da9ea90a47b801c09593e39579e56e0..8086f714eaf8cc6bbacbb2d6473767c62ddc4c16 100644 (file)
@@ -79,10 +79,7 @@ CFLAGS="-g $CFLAGS -W"
  fi
 fi
 
-AX_GCC_OPTION([-fstack-protector], [], [], [
-   CFLAGS="$CFLAGS -fstack-protector"
-], [])
-
+# Reduce the size of the binary on PowerPC OS X 
 case "${build_cpu}-${build_os}" in
   powerpc*-darwin*) 
    AX_GCC_OPTION([-mdynamic-no-pic], [], [], [
@@ -91,6 +88,20 @@ case "${build_cpu}-${build_os}" in
   ;;
 esac
 
+
+# Some useful security-related compiler, assembler and linker options
+AX_GCC_OPTION([-fstack-protector], [], [], [
+   CFLAGS="$CFLAGS -fstack-protector"
+], [])
+AX_LD_CHECK_FLAG([-Wl,-z,noexecstack], [], [], [
+   LDFLAGS="$LDFLAGS -Wl,-z,noexecstack"
+], [])
+AX_LD_CHECK_FLAG([-Wa,--noexecstack], [], [], [
+   CFLAGS="$CFLAGS -Wa,--noexecstack"
+], [])
+
+
+
 if test "${CTAGS+set}" != "set" -a "${EXCTAGS+set}" = "set"; then
        CTAGS=$EXCTAGS
 fi
@@ -105,13 +116,19 @@ if test "${UPTIME+set}" = "set"; then
  AC_DEFINE_UNQUOTED([UPTIME], "$UPTIME")
 fi
 
-AC_ARG_VAR(SENDMAIL, Path to sendmail)
+AC_ARG_VAR(SENDMAIL, [Path to sendmail])
 AC_PATH_PROG(SENDMAIL, sendmail)
 if test "${SENDMAIL+set}" = "set"; then
  AC_DEFINE([HAVE_SENDMAIL])
  AC_DEFINE_UNQUOTED([SENDMAIL], "$SENDMAIL")
 fi
 
+AC_ARG_VAR(ED, [Path to ed])
+AC_PATH_PROG(ED, ed)
+if test "${ED+set}" = "set"; then
+   AC_DEFINE([HAVE_ED])
+   AC_DEFINE_UNQUOTED([ED_PATH], "$ED -s")
+fi
 
 ### Headers
 # Usually there's no need to check for standard C89 headers.
@@ -142,6 +159,8 @@ AC_CHECK_HEADER(sys/stat.h, [AC_DEFINE(I_SYS_STAT)])
 AC_CHECK_HEADER(sys/types.h, [AC_DEFINE(I_SYS_TYPES)])
 AC_CHECK_HEADERS([sys/un.h ieeefp.h sys/resource.h sys/event.h sys/uio.h])
 AC_CHECK_HEADERS([poll.h sys/epoll.h sys/select.h sys/inotify.h fam.h])
+AC_CHECK_HEADERS([zlib.h])
+
 ### C language support
 # Only need to check C99 and GNU extensions
 
@@ -181,6 +200,7 @@ AC_CHECK_LIB(intl, gettext)
 AC_CHECK_LIB(crypt, crypt)
 LIB_SOCKET_NSL
 AC_CHECK_LIB(fam, FAMOpen)
+AC_CHECK_LIB(z, gzungetc)
 
 # with_ssl=set
 CHECK_SSL
@@ -242,9 +262,9 @@ AC_FUNC_SETPGRP
 fi
 AC_CHECK_FUNCS([cbrt log2 round imaxdiv])
 AC_CHECK_FUNCS([getuid geteuid seteuid getpriority setpriority])
-AC_CHECK_FUNCS([socketpair sigaction sigprocmask valloc writev])
+AC_CHECK_FUNCS([socketpair sigaction sigprocmask posix_memalign writev])
 AC_CHECK_FUNCS([fcntl pselect poll ppoll pollts kqueue epoll_ctl inotify_init])
-AC_CHECK_FUNCS([pread pwrite])
+AC_CHECK_FUNCS([pread pwrite posix_fadvise posix_fallocate])
 
 AC_FUNC_SNPRINTF
 if test "x$ac_cv_have_working_snprintf" = xyes; then
@@ -253,11 +273,11 @@ fi
 if test "x$ac_cv_have_working_vsnprintf" = xyes; then
 AC_DEFINE(HAS_VSNPRINTF)
 fi
-AC_CHECK_FUNCS(_vsnprintf_s)
+AC_CHECK_FUNCS([_vsnprintf_s vasprintf])
 
 AC_CHECK_FUNCS([strcasecmp strncasecmp _stricmp _strnicmp strdup])
 AC_FUNC_STRCOLL
-AC_CHECK_FUNCS([strxfrm _strncoll _stricoll _strnicoll strdup])
+AC_CHECK_FUNCS([strxfrm _strncoll _stricoll _strnicoll strchrnul])
 AC_CHECK_FUNC(sysconf, [AC_DEFINE(HAS_SYSCONF)])
 AC_CHECK_FUNC(textdomain, [AC_DEFINE(HAS_TEXTDOMAIN)])
 
@@ -339,9 +359,95 @@ if test "$enable_nls" = "no"; then
 AC_DEFINE(DONT_TRANSLATE)
 fi
 
+AC_ARG_ENABLE(info_slave, AS_HELP_STRING([--disable-info_slave],
+                         [Don't use a separate process for hostname lookups]),
+                         enable_info_slave=$enableval, enable_info_slave=yes)
+if test "$enable_info_slave" = yes; then
+   AC_SUBST(INFO_SLAVE_TARGET, info_slave)
+   AC_DEFINE(INFO_SLAVE)
+fi
+
+AC_ARG_ENABLE(sse2, AS_HELP_STRING([--enable-sse2],
+  [Use SSE2 instructions (Requires a CPU that supports SSE2)]))
+AC_ARG_ENABLE(sse3, AS_HELP_STRING([--enable-sse3],
+  [Use SSE3 instructions (Requires a CPU that supports SSE3)]))
+AC_ARG_ENABLE(altivec, AS_HELP_STRING([--enable-altivec],
+  [Use PowerPC Altivec instructions (Requires a CPU that supports Altivec)]))
+
+if test "$enable_sse2" = yes; then
+   AC_DEFINE(HAVE_SSE2)
+   CFLAGS="$CFLAGS -msse2"
+fi
+
+if test "$enable_sse3" = yes; then
+   AC_DEFINE(HAVE_SSE2)
+   AC_DEFINE(HAVE_SSE3)
+   CFLAGS="$CFLAGS -msse2 -msse3"
+fi
+
+if test "$enable_altivec" = yes; then
+   AC_DEFINE(HAVE_ALTIVEC)
+   CFLAGS="$CFLAGS -maltivec -faltivec"
+fi
+
 ### Output
 
+if test ${PCRE_LIBS+set} = set; then
+   which_pcre="System"
+else
+   which_pcre="Local (Consider getting your sysadmin to install pcre)"
+fi
+
+
+echo "Configuration summary:"
+echo "* Compiler: $CC"
+echo "* Compiler flags: $CFLAGS"
+echo "* PCRE: $which_pcre"
+if test "$enable_sql" = yes; then
+ sql_servers=""
+ if test "$found_mysql" = yes; then
+  sql_servers+="MySQL "
+ fi
+ if test "$found_postgresql" = yes; then
+  sql_servers+="Postgres "
+ fi
+ if test "$found_sqlite" = yes; then
+  sql_servers+="Sqlite3 "
+ fi
+ echo "* SQL support: ${sql_servers:-No}"
+else
+ echo "* SQL support: No"
+fi
+
+if test "$HAVE_SSL" = yes; then
+ echo "* SSL support: Yes"
+else
+ echo "* SSL support: No"
+fi
+
+if test "$enable_info_slave" = yes; then
+   echo "* Info slave will be used for hostname lookups."
+else
+   echo "* Hostname lookups will be done by the mush process."
+fi
+
+if test "$enable_nls" = yes -a "${ac_cv_lib_intl_gettext:+set}" = set; then
+   echo "* Translation support: Yes"
+else
+   echo "* Translation support: No"
+fi
+
+if test "$enable_ipv6" = yes; then
+  echo "* IPv6 sockets will be used if possible."
+else
+  echo "* Sockets are limited to IPv4"
+fi
+
+
+
 AC_CONFIG_FILES([Makefile src/Makefile])
 AC_CONFIG_FILES([game/txt/compose.sh], [chmod +x game/txt/compose.sh])
 AC_CONFIG_FILES([test/alltests.sh], [chmod +x test/alltests.sh])
 AC_OUTPUT
+
+
index c806c6745807340fcd58cc1cbde442a24cfd5f2d..76a9d673e358b692e07d44a561361041584321e8 100644 (file)
@@ -63,6 +63,10 @@ flag_database   data/flagdb
 #compress_suffix
 #
 # Use these 3 lines for gzip compression
+# Note: If the mush is built with zlib and you use plain 'gzip' and
+# 'gunzip', the library will be used instead of external programs. If
+# you want to force using the programs, just specify the full path to
+# them; e.g. /usr/bin/gzip
 #compress_program gzip
 #uncompress_program gunzip
 #compress_suffix .gz
@@ -157,6 +161,15 @@ chunk_swap_file    data/chunkswap
 # gain some locality benefits and overhead savings.
 chunk_cache_memory     1000000
 
+# The amount of space, in kibibytes, to initially allocate for the
+# swap file. The swap file may grow bigger than this figure, but won't
+# shrink to less. Only works on some OSes; ignored on those that don't
+# support the posix_fallocate() system call. 
+# For best results, set it to a larger value than the size of your
+# swap file is after the game has been running for a while. How much
+# larger depends on how fast the database is growing.
+chunk_swap_initial_size 2048
+
 # The number of attributes that may be moved at one time, once per
 # second.  The higher the value, the faster memory gets defragmented,
 # but at a greater CPU cost.
index 5d655cc9dff7a1fb6be9069c63e1a8d9a57c22ef..dbe5724b9b7c71ec1a9e21c94e3476addb93049a 100644 (file)
@@ -167,6 +167,93 @@ See also: chat
   /brief switch is included, players on the channel aren't listed.
   @channel/chown allows a Wizard to change the owner of a channel.
 
+  See "help @channel6" for more.
+& @channel6
+  @channel/mogrifier <channel> = <object>
+
+  The Mogrifier lets you tweak every aspect of a channel's output, before
+  it goes to individual players' @chatformats.
+
+  <object> must be an object that you control, and it can have any or all
+  of these attributes which are evaluated when channel messages are generated.
+
+  Before it begins Mogrifying, its MOGRIFY`BLOCK is called, using the same
+  arguments as @chatformat. If MOGRIFY`BLOCK returns a non-empty string, then
+  the resultant string is sent to the player, and the message is not
+  broadcasted.
+
+  A number of separate mogrifiers can be used. Check "help @chat mogrifying"
+  for details.
+
+  After all of these are called, MOGRIFY`FORMAT is called. It has the exact
+  same use as @chatformat, but is on a channel-wide level. It receives all
+  mogrified text (if any), so is generally intended only for reformatting the
+  whole channel text. It is also overridden by individual @chatformats.
+
+  See "help @chat mogrifying" for examples.
+& @chat mogrifying
+Mogrifying individual pieces of the channel chatter text:
+
+  If any of these evaluate to a non-null string, they replace that portion
+  of the chat message.
+
+  %0 - (Depends on the mogrifier.)
+  %1 - Channel name (unmogrified).
+  %2 - Chat type (", :, ;, |)
+  %3 - Message.
+  %4 - Player chan title.
+  %5 - Player name.
+
+  MOGRIFY`CHANNAME: %0 = default channel display. (e.g: "<Public>").
+  MOGRIFY`TITLE: %0 = The player's title, if any.
+  MOGRIFY`PLAYERNAME: %0 = The player's name.
+  MOGRIFY`SPEECHTEXT: %0 = "says"
+  MOGRIFY`MESSAGE: %0 = <the content of the say, pose, semipose or emit>
+
+  See "help @chat mogrifying2" for examples.
+& @chat mogrifying2
+For Talk Like a Pirate Day (Sep 19):
+
+> @create Pirate Filter
+> @chan/mogrifier public=Pirate Filter
+> &MOGRIFY`BLOCK Pirate Filter=if(regmatch(%5,ninja),We don't need no ninjas!)
+> &MOGRIFY`TITLE Pirate Filter=switch(poss(%#),her,Wench,Buccaneer)
+> &MOGRIFY`SPEECHTEXT Pirate Filter=yo-hos
+> &MOGRIFY`MESSAGE Pirate Filter=edit(%0,r,rrr)
+> &MOGRIFY`CHANNAME Pirate Filter=(%1-Yarr!)
+
+Output:
+
+> +public Hello
+(Public-Yarr!) Buccaneer Walker yo-hos, "Hello"
+
+> +public :thinks it's talk like a pirate day?
+(Public-Yarr!) Buccaneer Walker thinks it's talk like a pirrrate day?
+
+> +public Pirates suck, Ninjas are better!
+We don't need no ninjas!
+(And the message is blocked, won't be sent out).
+
+  See "help @chat mogrifying3" for another example.
+& @chat mogrifying3
+For keeping a channel PG and safe, and altering the channel name from
+<Public> to [Public], with a green "Public".
+
+> @create PG Channel Mogrifier
+> @chan/mogrifier public=PG Channel Mogrifier
+> &BADWORDS PG=list of bad words
+> &MOGRIFY`MESSAGE PG=regeditall(%0,\\b([edit(v(badwords),%b,|)])\\b,***)
+> &MOGRIFY`CHANNAME PG=\[[ansi(g,%1)]\]
+> &MOGRIFY`title PG=if(strlen(%0),\(%0\))
+
+Output: (With a channel title of "Fast") ("Public" is green)
+> +p Hello
+[Public] (Fast) Walker says, "hello"
+> +p what the list is going on bad bad?
+[Public] (Fast) Walker says, "what the *** is going on *** ***?"
+
+Combine MOGRIFY`FORMAT with speak() and you can have plenty of fun:
+On-channel language systems and more!
 & channel-list
 Here's the legend for reading the @channel/list output:
 
index 8d6434f7e6e1d5ee89ba6ce6984a8af97c250263..374657ab7c34f2fbb8c712e7995717695f62f077 100644 (file)
@@ -673,7 +673,7 @@ See also: @create
   @config/attribs
   @config/flags
   @config/list[/lowercase] [<option|option-type>]
-  @config/set option=value
+  @config/set|save option=value
   
   This command lists the MUSH configuration parameters, indicating what
   special things are enabled, and the cost of certain commands.
@@ -687,6 +687,8 @@ See also: @create
                    if given one; lists the option-types if not.
   /set        --   Director only, changes parameters from the mush. See
                    help @config parameters for available ones.
+  /save       --   Like /set, but also modifies the config file so the
+                   change persists over reboots. God only.
 & @conformat
   @conformat <object> [=<format>]
 
@@ -814,7 +816,7 @@ See also: give, MONEY, @pay, money()
 
 See also: ATTRIBUTES, NON-STANDARD ATTRIBUTES
 & @create
-  @create <name> [=<cost>]
+  @create <name>[=<cost>[,<dbref>]]
 
   Creates a thing with the specified name. Creating a thing costs
   a certain amount of MUSH money, which usually defaults to 10 pennies.
@@ -824,6 +826,10 @@ See also: ATTRIBUTES, NON-STANDARD ATTRIBUTES
   Once you have created a thing, you can use it as a PUPPET, to store
   USER-DEFINED COMMANDS, or just as a prop. Some MUSHes choose to limit 
   the number of objects that players can create by setting a QUOTA.
+  
+  Wizards can also specify the dbref of a garbage object to use when
+  creating the object. Otherwise, the object is given the next
+  available dbref.
  
 See also: give, @quota, MONEY
 & @dbck
@@ -2602,7 +2608,7 @@ See also: give
 
 See also: give
 & @pcreate
-  @pcreate <name> = <password>
+  @pcreate <name> = <password>[, <dbref>]
 
   This Director-only command creates a player with the given name and
   password.
index 823677e35be0b861d4fb3fbe8a035156edc72dad..9e447909e4bdddef5b18255918b9ec9fbdcd74c7 100644 (file)
@@ -3591,6 +3591,7 @@ See also: anonymous attributes, sorting, sortby()
    d       Sorts dbrefs.
    n       Sorts integer numbers.
    f       Sorts decimal numbers.
+   m       Sorts strings with embedded numbers and dbrefs (as names).
    name    Sorts dbrefs by their names. (Maybe case-sensitive)
    namei   Sorts dbrefs by their names. (Always case-insensitive)
    conn    Sorts dbrefs by their connection time.
index 1409c7e21d2cd3a77d48d35b8554f3ec85479ffe..89524ebfd6cc3b7bce1038c90fe421f8c0346433 100644 (file)
@@ -57,6 +57,6 @@ bool add_access_sitelock(dbref player, const char *host, dbref who,
 int remove_access_sitelock(const char *pattern);
 void do_list_access(dbref player);
 int parse_access_options
-  (const char *opts, dbref *who, uint32_t * can, uint32_t * cant, dbref player);
+  (const char *opts, dbref *who, uint32_t *can, uint32_t *cant, dbref player);
 
 #endif                          /* __ACCESS_H */
index 3e4c30ff1a401ae92cb60146a60fd6c7418bb3f4..6354ca2655b2e136606f97ce18758533c2179bd7 100644 (file)
@@ -81,7 +81,7 @@ extern void atr_free_all(dbref thing);
 extern void atr_cpy(dbref dest, dbref source);
 extern char const *convert_atr(int oldatr);
 extern int atr_comm_match(dbref thing, dbref player, int type, int end,
-                          char const *str, int just_match, char *atrname,
+                          char const *str, int just_match, int check_locks, char *atrname,
                           char **abp, dbref *errobj);
 extern int atr_comm_divmatch(dbref thing, dbref player, int type, int end,
                              char const *str, int just_match, char *atrname,
index e0ec95890d2e68afbc24397040f00132c7641855..d5ff2eec28e5fd3d8ec119e393333488e541bd23 100644 (file)
@@ -2,6 +2,7 @@
 #define BOOLEXP_H
 #include "copyrite.h"
 #include "chunk.h"
+#include "dbio.h"
 
 typedef chunk_reference_t boolexp;
 
@@ -24,8 +25,8 @@ extern boolexp parse_boolexp(dbref player, const char *buf, lock_type ltype);
 extern boolexp parse_boolexp_d(dbref player, const char *buf, lock_type ltype,
                                int derefs);
 extern void free_boolexp(boolexp b);
-boolexp getboolexp(FILE * f, const char *ltype);
-void putboolexp(FILE * f, boolexp b);
+boolexp getboolexp(PENNFILE *f, const char *ltype);
+void putboolexp(PENNFILE *f, boolexp b);
 enum u_b_f {
   UB_ALL, /**< Use names of objects */
   UB_DBREF, /**< Use dbrefs */
index 88d5414c56746bad4b36516e92c71f7da97190ee..eda877c662ef96f3b8054fa275944228aea7e76e 100644 (file)
@@ -274,8 +274,8 @@ struct options_table {
   int player_name_len;  /**< Maximum length of player names */
   int queue_entry_cpu_time;     /**< Maximum cpu time allowed per queue entry */
   int ascii_names;      /**< Are object names restricted to ascii characters? */
-  int max_global_fns;   /**< Maximum number of functions */
   char chunk_swap_file[256];    /**< Name of the attribute swap file */
+  int chunk_swap_initial; /**< Disc space to reserve for the swap file, in kibibytes */
   int chunk_cache_memory;       /**< Memory to use for the attribute cache */
   int chunk_migrate_amount;     /**< Number of attrs to migrate each second */
   int read_remote_desc; /**< Can players read DESCRIBE attribute remotely? */
@@ -451,7 +451,6 @@ int cf_time(const char *opt, const char *val, void *loc, int maxval,
 #define TINY_MATH (options.tiny_math)
 #define NEWLINE_ONE_CHAR (options.newline_one_char)
 #define ONLY_ASCII_NAMES (options.ascii_names)
-#define MAX_GLOBAL_FNS (options.max_global_fns)
 #define USE_QUOTA (options.use_quota)
 #define EMPTY_ATTRS (options.empty_attrs)
 #define FUNCTION_SIDE_EFFECTS (options.function_side_effects)
index d1ec24b14bae068faf1a8471f4deb38f3aff82bb..c1d33566fb2ebdd38fbf7e89bed87e37189802b9 100644 (file)
@@ -9,44 +9,67 @@
 
 #include <setjmp.h>
 #include <stdio.h>
+#ifdef HAVE_ZLIB_H
+#include <zlib.h>
+#endif
 #ifdef HAVE_STDINT_H
 #include <stdint.h>
 #endif
 
 extern jmp_buf db_err;
 
-/** Run a function, and jump if error */
-#define OUTPUT(fun) do { if ((fun) < 0) longjmp(db_err, 1); } while (0)
+typedef struct pennfile {
+  enum { PFT_FILE, PFT_PIPE, PFT_GZFILE } type;
+  union {
+    FILE *f;
+#ifdef HAVE_LIBZ
+    gzFile g;
+#endif
+  } handle;
+} PENNFILE;
 
+PENNFILE *penn_fopen(const char *, const char *);
+void penn_fclose(PENNFILE *);
 
+int penn_fgetc(PENNFILE *);
+char *penn_fgets(char *, int, PENNFILE *);
+int penn_fputc(int, PENNFILE *);
+int penn_fputs(const char *, PENNFILE *);
+int penn_fprintf(PENNFILE *, const char *fmt, ...)
+  __attribute__ ((__format__(__printf__, 2, 3)));
+int penn_ungetc(int, PENNFILE *);
+
+int penn_feof(PENNFILE *);
 /* Output */
-extern void putref(FILE * f, long int ref);
-extern void putstring(FILE * f, const char *s);
-extern void db_write_labeled_string(FILE * f, char const *label, char const *value);
-extern void db_write_labeled_int(FILE * f, char const *label, int value);
-extern void db_write_labeld_uint32(FILE *, char const *, uint32_t);
-extern void db_write_labeled_dbref(FILE * f, char const *label, dbref value);
+extern void putref(PENNFILE *f, long int ref);
+extern void putstring(PENNFILE *f, const char *s);
+extern void db_write_labeled_string(PENNFILE *f, char const *label, char const *value);
+extern void db_write_labeled_int(PENNFILE *f, char const *label, int value);
+extern void db_write_labeld_uint32(PENNFILE *, char const *, uint32_t);
+extern void db_write_labeled_dbref(PENNFILE *f, char const *label, dbref value);
  
-extern void db_write_flag_db(FILE *);
+extern void db_write_flag_db(PENNFILE *);
 
-extern dbref db_write(FILE * f, int flag);
-extern int db_paranoid_write(FILE * f, int flag);
+extern dbref db_write(PENNFILE * f, int flag);
+extern int db_paranoid_write(PENNFILE * f, int flag);
 
 /* Input functions */
-extern char *getstring_noalloc(FILE * f);
-extern long getref(FILE * f);
-extern void db_read_this_labeled_string(FILE * f, const char *label, char **val);
-extern void db_read_labeled_string(FILE * f, char **label, char **val);
-extern void db_read_this_labeled_int(FILE * f, const char *label, int *val);
-extern void db_read_this_labeled_uint32(FILE * f, const char *lable, uint32_t * val);
-extern void db_read_labeled_int(FILE * f, char **label, int *val);
-extern void db_read_labeled_uint32(FILE * f, char **label, uint32_t * val);
-extern void db_read_this_labeled_dbref(FILE * f, const char *label, dbref *val);
-extern void db_read_labeled_dbref(FILE * f, char **label, dbref *val);
-extern int load_flag_db(FILE *);
+extern char *getstring_noalloc(PENNFILE * f);
+extern long getref(PENNFILE * f);
+extern void db_read_this_labeled_string(PENNFILE * f, const char *label, char **val);
+extern void db_read_labeled_string(PENNFILE * f, char **label, char **val);
+extern void db_read_this_labeled_int(PENNFILE * f, const char *label, int *val);
+extern void db_read_this_labeled_uint32(PENNFILE * f, const char *lable, uint32_t * val);
+extern void db_read_labeled_int(PENNFILE * f, char **label, int *val);
+extern void db_read_labeled_uint32(PENNFILE * f, char **label, uint32_t * val);
+extern void db_read_this_labeled_dbref(PENNFILE * f, const char *label, dbref *val);
+extern void db_read_labeled_dbref(PENNFILE * f, char **label, dbref *val);
+extern int load_flag_db(PENNFILE *);
 
 extern void init_postconvert();
 
-extern dbref db_read(FILE * f);
+extern dbref db_read(PENNFILE * f);
 
 #endif
index cce2ed84b4d6deba3f7b6e72809f4e0486f362e8..e9e99adf276a95a426ca1fc13ed89d36a6a9b4ac 100644 (file)
@@ -304,8 +304,8 @@ extern void init_powers();
 extern div_pbits new_power_bitmask();
 extern char power_is_zero(div_pbits pbits, int bytes);
 extern void do_power_cmd(dbref, const char *, const char *, const char *);
-extern void powers_read_all(FILE *);
-extern void power_write_all(FILE *);
+extern void powers_read_all(PENNFILE *);
+extern void power_write_all(PENNFILE *);
 extern POWER *has_power(dbref object, const char *name);
 extern div_pbits convert_old_cobra_powers(unsigned char *dp_bytes);
 extern char *powergroups_list(dbref, char);
index 7f8efdf42241875985e419c7eb45d1ccad451d89..08ff6f29cb9e3852015ad77feea7bcf0ff9a52fb 100644 (file)
@@ -294,7 +294,7 @@ extern const char *get_namedreg(HASHTAB *, const char *);
 
 /* From create.c */
 extern dbref do_dig(dbref player, const char *name, char **argv, int tport);
-extern dbref do_create(dbref player, char *name, int cost);
+extern dbref do_create(dbref player, char *name, int cost, char *newdbref);
 extern dbref do_real_open(dbref player, const char *direction,
                           const char *linkto, dbref pseudo);
 extern void do_open(dbref player, const char *direction, char **links);
@@ -362,7 +362,7 @@ dbref lookup_player(const char *name);
 dbref lookup_player_name(const char *name);
 /* from player.c */
 dbref create_player(const char *name, const char *password,
-                    const char *host, const char *ip);
+                    const char *host, const char *ip, dbref try_dbref);
 dbref connect_player(const char *name, const char *password,
                      const char *host, const char *ip, char *errbuf);
 void check_last(dbref player, const char *host, const char *ip);
@@ -490,7 +490,11 @@ extern char *strlower(const char *s);
 extern char *strinitial(const char *s);
 extern char *upcasestr(char *s);
 extern char *skip_space(const char *s);
+#ifdef HAVE_STRCHRNUL
+#define seek_char(s,c) strchrnul((s),(c))
+#else
 extern char *seek_char(const char *s, char c);
+#endif
 extern size_t u_strlen(const unsigned char *s);
 extern unsigned char *u_strncpy
   (unsigned char *restrict target, const unsigned char *restrict source,
@@ -632,7 +636,7 @@ strdup(const char *s) __attribute_malloc__;
 #define mush_free(ptr,tag) mush_free_where((ptr), (tag), __FILE__, __LINE__)
     void mush_free_where(void *restrict ptr, const char *restrict check,
                          const char *restrict filename, int line);
-    long get_random_long(long low, long high);
+    uint32_t get_random32(uint32_t low, uint32_t high);
     char *fullalias(dbref it);
     char *shortalias(dbref it);
     char *shortname(dbref it);
@@ -718,6 +722,7 @@ strdup(const char *s) __attribute_malloc__;
 /* From destroy.c */
     void do_undestroy(dbref player, char *name);
     dbref free_get(void);
+    int make_first_free(dbref object);
     void fix_free_list(void);
     void purge(void);
     void do_purge(dbref player);
index 6a2ca867bf96af9c1ab075818f7c16a654e8a8b5..2903d6d145f9d4a26b3a5618262855d5ea5117a7 100644 (file)
@@ -74,8 +74,8 @@ extern void set_player_folder(dbref player, int fnum);
 extern void add_folder_name(dbref player, int fld, const char *name);
 extern struct mail *find_exact_starting_point(dbref player);
 extern void check_mail(dbref player, int folder, int silent);
-extern int dump_mail(FILE * fp);
-extern int load_mail(FILE * fp);
+extern int dump_mail(PENNFILE * fp);
+extern int load_mail(PENNFILE * fp);
 extern void mail_init(void);
 extern int mdb_top;
 extern void do_mail(dbref player, char *arg1, char *arg2);
index 601ae56b2aa5b79da1c46692306d8b392eba0644..85a09ade88d6b9ac7606e93da6e3b8bb9daebda6 100644 (file)
@@ -8,6 +8,7 @@
 
 #include "mushtype.h"
 #include "ptab.h"
+#include "dbio.h"
 #include "division.h"
 
 typedef struct flag_info FLAG;
@@ -78,8 +79,8 @@ extern int has_any_bits(const char *ns, object_flag_type source, object_flag_typ
 extern object_flag_type string_to_bits(const char *ns, const char *str);
 extern const char *bits_to_string(const char *ns, object_flag_type bitmask, dbref privs,
                                   dbref thing);
-extern void flag_write_all(FILE *, const char *);
-extern void flag_read_all(FILE *, const char *);
+extern void flag_write_all(PENNFILE *, const char *);
+extern void flag_read_all(PENNFILE *, const char *);
 extern int type_from_old_flags(long old_flags);
 extern object_flag_type flags_from_old_flags(long old_flags, long old_toggles,
                                              int type);
index 556039a4d95b3b0b8f11c8cd1ef510c922a327be..8c4a4749b26acafac35349b1cdc74e619d0882ab 100644 (file)
@@ -48,15 +48,18 @@ typedef struct fun FUN;
 typedef void (*function_func) (FUN *, char *, char **, int, char *[], int[],
                                dbref, dbref, dbref, const char *, PE_Info *);
 
+typedef struct userfn_entry USERFN_ENTRY;
+
 /** A calling pointer to a function.
  * This union holds either a pointer to a function's code or
  * the offset of the function in the user-defined function table.
  */
 union fun_call {
   function_func fun;    /**< Pointer to compiled function code */
-  size_t offset;        /**< Offset into user-defined function table */
+  USERFN_ENTRY *ufun;   /**< Pointer to @function location */
 };
 
+
 /** A function.
  * This structure represents a mushcode function.
  */
@@ -75,20 +78,15 @@ struct fun {
   boolexp lock; /* Usability lock */
 };
 
-typedef struct userfn_entry USERFN_ENTRY;
 
 /** A user-defined function
  * This structure represents an entry in the user-defined function table.
  */
 struct userfn_entry {
-  char *fn;             /**< Name of the function */
   dbref thing;          /**< Dbref of object where the function is defined */
   char *name;           /**< Name of attribute where the function is defined */
-  unsigned int flags;   /**< Bitflags of function */
 };
 
-extern USERFN_ENTRY *userfn_tab;
-
 void do_userfn(char *buff, char **bp,
                dbref obj, ATTR *attrib,
                int nargs, char **args,
index 65856af09cc0a6ff5969b0cb275e820144df0e52..b153960b547298cc804734e17a6abc4580e36274 100644 (file)
@@ -52,7 +52,7 @@ extern void do_hook_list(dbref player, char *command);
 
 /* From compress.c */
 #if (COMPRESSION_TYPE > 0)
-extern int init_compress(FILE * f);
+int init_compress(PENNFILE *f);
 #endif
 
 /* From conf.c */
@@ -158,9 +158,10 @@ extern void do_enable(dbref player, const char *param, int state);
 extern void do_kick(dbref player, const char *num);
 extern void do_search(dbref player, const char *arg1, char **arg3);
 extern dbref do_pcreate
-  (dbref creator, const char *player_name, const char *player_password);
-extern void do_quota
-  (dbref player, const char *arg1, const char *arg2, int set_q);
+  (dbref creator, const char *player_name, const char *player_password,
+   const char *try_dbref);
+extern void do_quota(dbref player, const char *arg1, const char *arg2,
+                     int set_q);
 extern void do_allquota(dbref player, const char *arg1, int quiet);
 extern void do_teleport
   (dbref player, const char *arg1, const char *arg2, int silent, int inside);
@@ -181,7 +182,7 @@ extern void do_sitelock
 extern void do_sitelock_name(dbref player, const char *name);
 extern void do_chownall
   (dbref player, const char *name, const char *target, int preserve);
-extern void NORETURN do_reboot(dbref player, int flag);
+extern void do_reboot(dbref player, int flag);
 
 /* From destroy.c */
 extern void do_dbck(dbref player);
index 8cee083104f217b98099e1365622cdabfbf45361..2eb7136256a7262ac07c691f028f8a4a7636e0e8 100644 (file)
@@ -42,8 +42,8 @@ extern void do_malias_stats(dbref player);
 extern void do_malias_nuke(dbref player);
 extern void do_malias_add(dbref player, char *alias, char *tolist);
 extern void do_malias_remove(dbref player, char *alias, char *tolist);
-extern void load_malias(FILE * fp);
-extern void save_malias(FILE * fp);
+void load_malias(PENNFILE *fp);
+void save_malias(PENNFILE *fp);
 extern void malias_cleanup(dbref player);
 extern void do_malias_set(dbref player, char *alias, char *tolist);
 #else                           /* MAIL_ALIASES */
index 3f9d7449c3fbb6571e83aa88808feb16a3a8893a..ee5554a653a0aa2df7a297c3841d5c4d77d582bd 100644 (file)
@@ -1,8 +1,7 @@
 #ifndef _SHS_H
 #define _SHS_H
 
-#include "config.h"
-#ifdef HAVE_STDINT
+#ifdef HAVE_STDINT_H
 #include <stdint.h>
 #endif
 
 #define LONG SHS_LONG
 #endif
 
-#ifdef __MINGW32__
-typedef unsigned char BYTE;
-typedef long LONG;
-#else
-typedef unsigned char BYTE;
-#ifdef HAS_UINT32_T
-typedef uint32_t LONG;
-#else
-typedef unsigned int LONG;
-#endif
-#endif
+typedef uint8_t BYTE;
+typedef uint32_t LONG;          /* Ick. */
 
 #define SHS_BLOCKSIZE 64
 
index 25d9af6d0289970ddaebc8c641a9e4658b941f12..a54504873cadc8a21c67e0c57941b95f689dec70 100644 (file)
@@ -25,7 +25,8 @@ C_FILES=access.c atr_tab.c attrib.c boolexp.c bsd.c bufferq.c chunk.c \
        plyrlist.c predicat.c privtab.c prog.c info_master.c ptab.c rob.c       \
        services.c set.c shs.c sig.c sort.c speech.c sql.c strdup.c     \
        strtree.c strutil.c tables.c timer.c unparse.c utils.c          \
-       version.c wait.c warnings.c wild.c wiz.c
+       version.c wait.c warnings.c wild.c wiz.c \
+       SFMT.c
 
 
 # .o versions of above - these are used in the build
@@ -41,7 +42,8 @@ O_FILES=bsd.o access.o atr_tab.o attrib.o boolexp.o bufferq.o chunk.o \
        plyrlist.o prog.o info_master.o predicat.o privtab.o ptab.o rob.o       \
        services.o set.o shs.o sig.o sort.o speech.o sql.o strdup.o     \
        strtree.o strutil.o tables.o timer.o unparse.o utils.o          \
-       version.o wait.o warnings.o wild.o wiz.o
+       version.o wait.o warnings.o wild.o wiz.o \
+       SFMT.o
 
 # This is a dummy target, in case you type 'make' in the source
 # directory (likely for emacs users who M-x compile.)
@@ -118,27 +120,26 @@ indent:
        -T accent_info -T acsflag -T aig_func -T ALIST -T ansi_data \
        -T ansi_string -T atr_err -T ATRALIAS -T ATTR -T BOOL -T boolexp \
        -T boolexp_type -T BQUE -T branch_chain -T BUFFERQ -T bvm_opcode \
-       -T BYTE -T CDESC -T CHAN -T CHANLIST -T CHANUSER \
-       -T chunk_reference_t -T CNode -T COMLIST -T command_func \
-       -T COMMAND_INFO -T comp_func -T compile_data -T COMSORTSTRUC \
-       -T config_func -T CType -T dbref -T Debug_Info -T DESC \
-       -T dfa_match_data -T eptrblock -T EVAL_CONTEXT -T FBLOCK \
-       -T fd_type -T FLAG -T FLAG_ALIAS -T FLAGSPACE -T folder_array \
-       -T FUN -T function_func -T FUNTAB -T GLOBALTAB -T hash_func \
-       -T HASHENT -T HASHTAB -T heapframe -T help_file -T help_indx \
-       -T ident_t -T im_key -T imaxdiv_t -T intmap -T IVAL \
-       -T list_type_list -T lock_list -T lock_type -T LOCKMSGINFO \
-       -T LONG -T ltype -T MAIL -T mail_flag -T makerecord \
-       -T markup_information -T match_data -T MATH -T MEM -T na_lookup \
-       -T NVAL -T object_flag_type -T OPTTAB -T patricia \
+       -T BYTE -T CHAN -T CHANLIST -T CHANUSER -T chunk_reference_t \
+       -T CNode -T COMLIST -T command_func -T COMMAND_INFO -T comp_func \
+       -T compile_data -T COMSORTSTRUC -T config_func -T CType -T dbref \
+       -T Debug_Info -T DESC -T dfa_match_data -T eptrblock \
+       -T EVAL_CONTEXT -T FBLOCK -T fd_type -T FLAG -T FLAG_ALIAS \
+       -T FLAGSPACE -T folder_array -T FUN -T function_func -T FUNTAB \
+       -T GLOBALTAB -T hash_func -T HASHENT -T HASHTAB -T heapframe \
+       -T help_file -T help_indx -T ident_t -T im_key -T imaxdiv_t \
+       -T intmap -T IVAL -T list_type_list -T lock_list -T lock_type \
+       -T LOCKMSGINFO -T LONG -T ltype -T MAIL -T mail_flag \
+       -T makerecord -T markup_information -T match_data -T MATH -T MEM \
+       -T na_lookup -T NVAL -T object_flag_type -T OPTTAB -T patricia \
        -T pcre_study_data -T pcre_uint16 -T pcre_uint32 -T PE_Info \
-       -T PENNCONF -T PENNCONFGROUP -T Port_t -T PRIV -T privbits \
-       -T PTAB -T ptab_entry -T qsort_func -T real_pcre \
+       -T PENNCONF -T PENNCONFGROUP -T PENNFILE -T Port_t -T PRIV \
+       -T privbits -T PTAB -T ptab_entry -T qsort_func -T real_pcre \
        -T recursion_info -T Region -T RegionHeader -T s_rec -T SHS_INFO \
        -T slab -T sqlplatform -T STFunc -T StrNode -T StrTree \
        -T switch_mask -T SWITCH_VALUE -T tcheck -T tlist \
-       -T ucp_type_table -T UIVAL -T uschar -T UsedAttr -T USERFN_ENTRY \
-       -T WAIT_TYPE -T warn_type -T Word \
+       -T ucp_type_table -T uint32_t -T uint64_t -T UIVAL -T uschar \
+       -T UsedAttr -T USERFN_ENTRY -T w128_t -T WAIT_TYPE -T warn_type \
        $$file ; done)
 
 clean:
index 63214d2be2c30878b60ac200d0859b70ef43d8e6..8afca236ec890209f72fc5a23eb43733e72e4436 100644 (file)
@@ -81,6 +81,7 @@ MAX
 ME
 MEMBERS
 MOD
+MOGRIFIER
 MORTAL
 MOTD
 MUTE
@@ -130,6 +131,7 @@ RETROACTIVE
 ROOM
 ROOMS
 RSARGS
+SAVE
 SEE
 SEEFLAG
 SELF
index 7310bf533821485ed3008286d982b30690abcd70..148baa926e692e0b37a993c8464c4b945482a8ff 100644 (file)
@@ -121,7 +121,7 @@ extern const unsigned char *tables;
 static void
 sitelock_free(struct access *ap)
 {
-  mush_free(ap->host, "sitelock.rule.host");
+  mush_free(ap->host, "sitelock.rule.pattern");
   if (ap->comment)
     mush_free(ap->comment, "sitelock.rule.comment");
   if (ap->re)
@@ -151,7 +151,7 @@ sitelock_alloc(const char *host, dbref who,
   tmp->who = who;
   tmp->can = can;
   tmp->cant = cant;
-  tmp->host = mush_strdup(host, "sitelock.rule.host");
+  tmp->host = mush_strdup(host, "sitelock.rule.pattern");
   if (comment && *comment)
     tmp->comment = mush_strdup(comment, "sitelock.rule.comment");
   else
@@ -381,10 +381,10 @@ site_can_access(const char *hname, uint32_t flag, dbref who)
    if (ap->can & ACS_SITELOCK)
      continue;
    if ((ap->can & ACS_REGEXP)
-       ? (qcomp_regexp_match(ap->re, hname)
-          || (p && qcomp_regexp_match(ap->re, p)))
-       : (quick_wild(ap->host, hname)
-          || (p && quick_wild(ap->host, p)))
+        ? (qcomp_regexp_match(ap->re, hname)
+           || (p && qcomp_regexp_match(ap->re, p)))
+        : (quick_wild(ap->host, hname)
+           || (p && quick_wild(ap->host, p)))
        && (ap->who == AMBIGUOUS || ap->who == who)) {
       /* Got one */
       if (flag & ACS_CONNECT) {
@@ -442,10 +442,10 @@ site_check_access(const char *hname, dbref who, int *rulenum)
     if (ap->can & ACS_SITELOCK)
       continue;
     if (((ap->can & ACS_REGEXP)
-        ? (qcomp_regexp_match(ap->re, hname)
-           || (p && qcomp_regexp_match(ap->re, p)))
-        : (quick_wild(ap->host, hname)
-           || (p && quick_wild(ap->host, p))))
+         ? (qcomp_regexp_match(ap->re, hname)
+            || (p && qcomp_regexp_match(ap->re, p)))
+         : (quick_wild(ap->host, hname)
+            || (p && quick_wild(ap->host, p))))
         && (ap->who == AMBIGUOUS || ap->who == who)) {
       /* Got one */
       return ap;
@@ -691,8 +691,8 @@ do_list_access(dbref player)
  * This makes a copy of the options string, so it's not modified.
  */
 int
-parse_access_options(const char *opts, dbref *who, uint32_t * can,
-                     uint32_t * cant, dbref player)
+parse_access_options(const char *opts, dbref *who, uint32_t *can,
+                     uint32_t *cant, dbref player)
 {
   char myopts[BUFFER_LEN];
   char *p;
index e2b3590d8b5968fe5c9e87569b05f49e1a9e643a..b459356309af7f82dcc824d99e0333c62f814955 100644 (file)
@@ -233,13 +233,69 @@ atr_sub_branch(ATTR * branch)
 
 /** Scan an attribute list for an attribute with the specified name.
  * This continues from whatever start point is passed in.
- * \param atr the start of the list to search from
- * \param name the attribute name to look for
- * \return the matching attribute, or NULL
+ * 
+ * Attributes are stored as sorted linked lists. This means that
+ * search is O(N) in the worst case. An unsuccessful search is usually
+ * better than that, because we don't have to look at every attribute
+ * unless you're looking for something greater than all the attributes
+ * on the object. There are a couple of possibilities I've been
+ * mulling over for... um... years... about ways to improve this.
+ *
+ * Option 1 is to change the data structure. I'd use a hybrid between
+ * a standard linked list and a skip list. Most objects have under 5
+ * attributes on them. With this few, a linear linked list is
+ * fine. When more attribute are added, though, it would turn into a
+ * skip list, with all current attributes having a depth of 1, and
+ * further attributes having a randomly chosen depth with a cap of,
+ * say, 5 (I'll have to work out the math to find the optimum
+ * size). This will provide O(lg N) searches on objects with lots of
+ * attributes and yet not take up lots of extra memory on objects with
+ * only a few attributes -- a problem with using a tree structure. All
+ * the code for this is in my head; I just need to sit down and write
+ * it.
+ *
+ * Option 2 is to speed up the current lookup. There are a lot of
+ * string comparisions that we don't strictly need: All attributes
+ * with the same name use the same underlying storage from a string
+ * pool. You can look up an attribute name and then just compare
+ * pointers, saving a lot of calls to strcoll(). The string pool is
+ * implemented using a red-black tree, so it needs O(lg P) string
+ * comparisions + O(N) pointer equality comparisions (P is the number
+ * of unique attribute names in the pool, N the number of attributes
+ * on the object). Hmm. I'm not so sure that's much of an improvement
+ * after all...  Let's try it out anyways and see what happens. Don't
+ * expect this to be permanent, though.
+ *
+ * \param atr the start of the list to search from \param name the
+ * attribute name to look for \return the matching attribute, or NULL
  */
 static ATTR *
 find_atr_in_list(ATTR * atr, char const *name)
 {
+#define ATR_PTR_CMP
+#ifdef ATR_PTR_CMP
+  /* New way; pointer comparisions */
+  const char *memoized;
+
+  memoized = st_find(name, &atr_names);
+  if (!memoized)                /* This attribute name doesn't exist on any object */
+    return NULL;
+
+  while (atr) {
+    if (AL_NAME(atr) == memoized)
+      return atr;
+#if 0
+    /* Unfortunately, this will break under many locales, since
+       attribute list sorting uses strcoll() and not strcmp().  */
+    else if (*memoized < *AL_NAME(atr))
+      return NULL;              /* Can't be any of the remaining attributes */
+#endif
+    else
+      atr = AL_NEXT(atr);
+  }
+#else
+  /* Old way; lots of string comparisions */
+
   int comp;
 
   while (atr) {
@@ -250,6 +306,7 @@ find_atr_in_list(ATTR * atr, char const *name)
       return atr;
     atr = AL_NEXT(atr);
   }
+#endif
 
   return NULL;
 }
@@ -1171,7 +1228,7 @@ use_attr(UsedAttr ** prev, char const *name, uint32_t no_prog)
  */
 int
 atr_comm_match(dbref thing, dbref player, int type, int end,
-               char const *str, int just_match, char *atrname, char **abp,
+               char const *str, int just_match, int check_locks, char *atrname, char **abp,
                dbref * errobj)
 {
   uint32_t flag_mask;
@@ -1185,15 +1242,16 @@ atr_comm_match(dbref thing, dbref player, int type, int end,
   UsedAttr *used_list, **prev;
   ATTR *skip[ATTRIBUTE_NAME_LIMIT / 2];
   int skipcount;
-  int lock_checked = 0;
+  int lock_checked = !check_locks;
   char match_space[BUFFER_LEN * 2];
   ssize_t match_space_len = BUFFER_LEN * 2;
   dbref local_ooref;
 
   /* check for lots of easy ways out */
-  if ((type != '$' && type != '^') || !GoodObject(thing) || Halted(thing)
-      || (type == '$' && NoCommand(thing)))
+  if (type != '$' && type != '^')
     return 0;
+  if (check_locks && (!GoodObject(thing) || Halted(thing) || (type == '$' && NoCommand(thing))))
+       return 0;
 
   if (type == '$') {
     flag_mask = AF_COMMAND;
index b643541dd0977bf72ea5a318c0ce29e46bd2e1f8..a2bb918ce38748e7582df1a72a62ac53d776c8b5 100644 (file)
--- a/src/bsd.c
+++ b/src/bsd.c
 #include "dbdefs.h"
 #include "flags.h"
 #include "lock.h"
-#include "help.h"
 #include "match.h"
 #include "ansi.h"
 #include "pueblo.h"
@@ -1098,10 +1097,17 @@ shovechars(Port_t port __attribute__ ((__unused__)),
                   WTERMSIG(dump_status));
         flag_broadcast("ROYALTY WIZARD", 0,
                        T("GAME: ERROR! Forking database save failed!"));
-      } else if (WIFEXITED(dump_status) && WEXITSTATUS(dump_status) == 0) {
-        time(&globals.last_dump_time);
-        if (DUMP_NOFORK_COMPLETE && *DUMP_NOFORK_COMPLETE)
-          flag_broadcast(0, 0, "%s", DUMP_NOFORK_COMPLETE);
+      } else if (WIFEXITED(dump_status)) {
+        if (WEXITSTATUS(dump_status) == 0) {
+          time(&globals.last_dump_time);
+          if (DUMP_NOFORK_COMPLETE && *DUMP_NOFORK_COMPLETE)
+            flag_broadcast(0, 0, "%s", DUMP_NOFORK_COMPLETE);
+        } else {
+          do_rawlog(LT_ERR, T("ERROR! forking dump exited with exit code %d"),
+                    WEXITSTATUS(dump_status));
+          flag_broadcast("ROYALTY WIZARD", 0,
+                         T("GAME: ERROR! Forking database save failed!"));
+        }
       }
       dump_error = 0;
       dump_status = 0;
@@ -2753,7 +2759,7 @@ check_connect(DESC *d, const char *msg)
                 user, d->addr, d->descriptor);
       return 0;
     }
-    player = create_player(user, password, d->addr, d->ip);
+    player = create_player(user, password, d->addr, d->ip, NOTHING);
     if (player == NOTHING) {
       queue_string_eol(d, T(create_fail));
       do_rawlog(LT_CONN,
@@ -2867,6 +2873,7 @@ close_sockets(void)
   DESC *d, *dnext;
   const char *shutmsg;
   int shutlen;
+  ssize_t res;
 
   shutmsg = T(shutdown_message);
   shutlen = strlen(shutmsg);
@@ -2882,7 +2889,8 @@ close_sockets(void)
       byebye[0].iov_len = shutlen;
       byebye[1].iov_base = (char *) "\r\n";
       byebye[1].iov_len = 2;
-      writev(d->outdesc, byebye, 2);
+      /* FIXME: We're using res.. for the mere fact we get a warning otherwise.. */
+      res = writev(d->outdesc, byebye, 2);
 #else
       if (d->outdesc == console_outpt) {
         write(d->outdesc, shutmsg, shutlen);
@@ -3423,6 +3431,7 @@ announce_connect(dbref player, int isnew, int num)
 {
   dbref loc;
   char tbuf1[BUFFER_LEN];
+  char *message;
   char *myenv[2];
   dbref zone;
   dbref obj;
@@ -3438,15 +3447,14 @@ announce_connect(dbref player, int isnew, int num)
 
   /* Redundant, but better for translators */
   if (Dark(player)) {
-    snprintf(tbuf1, BUFFER_LEN, (num > 1) ? T("%s has DARK-reconnected.") :
-             T("%s has DARK-connected."), Name(player));
+    message = (num > 1) ? T("has DARK-reconnected.") : T("has DARK-connected.");
   } else if (hidden(player)) {
-    snprintf(tbuf1, BUFFER_LEN, (num > 1) ? T("%s has HIDDEN-reconnected.") :
-             T("%s has HIDDEN-connected."), Name(player));
+    message = (num > 1) ? T("has HIDDEN-reconnected.") :
+      T("has HIDDEN-connected.");
   } else {
-    snprintf(tbuf1, BUFFER_LEN, (num > 1) ? T("%s has reconnected.") :
-             T("%s has connected."), Name(player));
+    message = (num > 1) ? T("has reconnected.") : T("has connected.");
   }
+  snprintf(tbuf1, BUFFER_LEN, "%s %s", Name(player), message);
 
   /* send out messages */
   if (!Dark(player))
@@ -3454,7 +3462,7 @@ announce_connect(dbref player, int isnew, int num)
 
 #ifdef CHAT_SYSTEM
   if (ANNOUNCE_CONNECTS)
-    chat_player_announce(player, tbuf1, (num == 1));
+    chat_player_announce(player, message, (num == 1));
 #endif /* CHAT_SYSTEM */
 
   loc = Location(player);
@@ -3533,6 +3541,8 @@ announce_connect(dbref player, int isnew, int num)
   strcpy(global_eval_context.ccom, "");
 }
 
+/* TODO: Compare to present day PennMUSH announce_disconnect.. We do things differently, though I think we should match up with the basic method 
+ * */
 void
 announce_disconnect(dbref player)
 {
@@ -3540,6 +3550,7 @@ announce_disconnect(dbref player)
   int num;
   DESC *d;
   char tbuf1[BUFFER_LEN];
+ /* TODO: See above,  char *message; */
   dbref zone, obj;
   int j;
   struct module_entry_t *m;
@@ -4771,7 +4782,7 @@ close_ssl_connections(void)
 void
 dump_reboot_db(void)
 {
-  FILE *f;
+  PENNFILE *f;
   DESC *d;
   SU_PATH *exit_path;
   long flags = RDBF_SCREENSIZE | RDBF_TTYPE | RDBF_PUEBLO_CHECKSUM
@@ -4781,14 +4792,14 @@ dump_reboot_db(void)
     exit(0);
   } else {
 
-    f = fopen(REBOOTFILE, "w");
+    f = penn_fopen(REBOOTFILE, "w");
     /* This shouldn't happen */
     if (!f) {
       flag_broadcast(0, 0, T("GAME: Error writing reboot database!"));
       exit(0);
     }
     /* Write out the reboot db flags here */
-    fprintf(f, "V%ld\n", flags);
+    penn_fprintf(f, "V%ld\n", flags);
     putref(f, sock);
     putref(f, maxd);
     /* First, iterate through all descriptors to get to the end
@@ -4835,7 +4846,7 @@ dump_reboot_db(void)
     putstring(f, poll_msg);
     putref(f, globals.first_start_time);
     putref(f, globals.reboot_count);
-    fclose(f);
+    penn_fclose(f);
   }
 }
 
@@ -4844,7 +4855,7 @@ dump_reboot_db(void)
 void
 load_reboot_db(void)
 {
-  FILE *f;
+  PENNFILE *f;
   DESC *d = NULL;
   DESC *closed = NULL, *nextclosed;
   int val;
@@ -4855,7 +4866,7 @@ load_reboot_db(void)
   char tbuf1[BUFFER_LEN];
   SU_PATH *epnext, *epprev;
   dbref exit_path;
-  f = fopen(REBOOTFILE, "r");
+  f = penn_fopen(REBOOTFILE, "r");
   if (!f) {
     restarting = 0;
     return;
@@ -4866,11 +4877,11 @@ load_reboot_db(void)
    * If not, assume we're using the original format, in which the
    * sock appears first
    * */
-  c = getc(f);                  /* Skip the V */
+  c = penn_fgetc(f);            /* Skip the V */
   if (c == 'V') {
     flags = getref(f);
   } else {
-    ungetc(c, f);
+    penn_ungetc(c, f);
   }
 
   sock = getref(f);
@@ -5017,7 +5028,7 @@ load_reboot_db(void)
   }
 #endif
 
-  fclose(f);
+  penn_fclose(f);
   remove(REBOOTFILE);
   flag_broadcast(0, 0, T("GAME: Reboot finished."));
 }
@@ -5394,6 +5405,19 @@ do_reboot(dbref player, int flag)
   struct module_entry_t *m;
   void (*handle)();
 
+#ifndef WIN32
+  /* Quick and dirty check to make sure the executable is still
+     there. Not a security check to speak of, hence the race condition
+     implied by using access() doesn't matter. The exec can still fail
+     for various reasons, but if it does, it gets logged and you get an
+     inadvertent full @shutdown. */
+  if (access(saved_argv[0], R_OK | X_OK) < 0) {
+    notify_format(player, T("Unable to reboot using executable '%s': %s"),
+                  saved_argv[0], strerror(errno));
+    return;
+  }
+#endif
+
   if (player == NOTHING) {
     flag_broadcast(0, 0,
                    T
@@ -5453,7 +5477,10 @@ do_reboot(dbref player, int flag)
 #else
   execl("cobramush.exe", "cobramush.exe", "/run", NULL);
 #endif                          /* WIN32 */
-  exit(1);                      /* Shouldn't ever get here, but just in case... */
+  /* Shouldn't ever get here, but just in case... */
+  fprintf(stderr, "Unable to restart game: exec: %s\nAborting.",
+          strerror(errno));
+  exit(1);
 }
 
 /* File modification watching code. Linux-specific for now. 
index 304db95d68189a9cc7b915529d90bb29c3f02473..1098f2990dab47f836da1520a9f0ad99771f742a 100644 (file)
 #include <limits.h>
 #include <string.h>
 #include <stdlib.h>
+
+#define _XOPEN_SOURCE 600
 #include <stdarg.h>
 #include <fcntl.h>
 #include <assert.h>
 #include <wtypes.h>
 #include <io.h>
 #else
-#define _XOPEN_SOURCE 500
 #define __USE_UNIX98
 #include <unistd.h>
 #endif
 #include <errno.h>
+#ifdef I_SYS_STAT
+#include <sys/stat.h>
+#endif
+
 
 #include "externs.h"
 #include "boolexp.h"
@@ -2353,6 +2358,12 @@ chunk_init(void)
   cache_head = NULL;
   cache_tail = NULL;
 
+#ifdef HAVE_POSIX_FALLOCATE
+  /* Reserve some space for the swap file to start with. */
+  if (options.chunk_swap_initial > 0)
+    posix_fallocate(swap_fd, 0, (options.chunk_swap_initial * 1024));
+#endif
+
   region_count = 0;
   region_array_len = FIXME_INIT_REGION_LEN;
 #ifdef DEBUG_CHUNK_MALLOC
@@ -2484,6 +2495,19 @@ chunk_fork_file(void)
     j++;
   }
 
+#ifdef HAVE_POSIX_FALLOCATE
+  /* Try to reserve all the space needed for the child's copy of the chunk file all at once. */
+  {
+    struct stat fsize;
+    if (fstat(swap_fd, &fsize) == 0)
+      posix_fallocate(swap_fd_child, 0, fsize.st_size);
+  }
+#endif
+
+#ifdef HAVE_POSIX_FADVISE
+  posix_fadvise(swap_fd, 0, 0, POSIX_FADV_SEQUENTIAL);
+#endif
+
   rhp = find_available_cache_region();
   prev = rhp->prev;
   next = rhp->next;
@@ -2498,6 +2522,10 @@ chunk_fork_file(void)
   rhp->prev = prev;
   rhp->next = next;
 
+#ifdef HAVE_POSIX_FADVISE
+  posix_fadvise(swap_fd, 0, 0, POSIX_FADV_RANDOM);
+#endif
+
   return 1;
 }
 
@@ -2522,6 +2550,11 @@ chunk_fork_child(void)
     return;
 
   close(swap_fd);
+
+#ifdef HAVE_POSIX_FADVISE
+  posix_fadvise(swap_fd_child, 0, 0, POSIX_FADV_RANDOM);
+#endif
+
   swap_fd = swap_fd_child;
   swap_fd_child = -1;
 }
index 253555f90bd8d76334b825c3e9fa47570d2ffaab..c66766121916e2f21bdc54f0d6feb6c46afdc35c 100644 (file)
@@ -192,11 +192,29 @@ COMMAND(cmd_config)
       notify(player, T("What did you want to set?"));
       return;
     }
-    if (!config_set(arg_left, arg_right, 1, 0)
-        && !config_set(arg_left, arg_right, 1, 1))
-      notify(player, T("Couldn't set that option"));
-    else
-      notify(player, T("Option set."));
+    {
+      int source = SW_ISSET(sw, SWITCH_SAVE) ? 2 : 1;
+      if (source == 2) {
+       if (!God(player)) {
+       /* Only god can alter the original config file. */
+         notify(player, T("You can't remake the world in your image."));
+         return;
+       }     
+      }
+      if (!config_set(arg_left, arg_right, source, 0)
+          && !config_set(arg_left, arg_right, source, 1))
+        notify(player, T("Couldn't set that option"));
+      else {
+        if (source == 2) {
+#ifdef HAVE_ED
+          notify(player, T("Option set and saved."));
+#else
+          notify(player, T("Option set but not saved (Saves disabled.)"));
+#endif
+        } else
+          notify(player, T("Option set."));
+      }
+    }
   } else
     do_config_list(player, arg_left, lc);
 }
@@ -208,7 +226,19 @@ COMMAND(cmd_cpattr)
 
 COMMAND(cmd_create)
 {
-  do_create(player, arg_left, parse_integer(arg_right));
+
+  int cost = 0;
+  char *newdbref;
+
+  if (args_right[1] && *args_right[1])
+    cost = parse_integer(args_right[1]);
+
+  if (args_right[2] && *args_right[2])
+    newdbref = args_right[2];
+  else
+    newdbref = (char *) NULL;
+
+  do_create(player, arg_left, cost, newdbref);
 }
 
 COMMAND(cmd_clone)
@@ -802,7 +832,14 @@ COMMAND(cmd_password)
 
 COMMAND(cmd_pcreate)
 {
-  do_pcreate(player, arg_left, arg_right);
+  const char *newdbref;
+
+  if (args_right[2] && *args_right[2])
+    newdbref = args_right[2];
+  else
+    newdbref = NULL;
+
+  do_pcreate(player, arg_left, args_right[1], newdbref);
 }
 
 COMMAND(cmd_pemit)
index d7c863a0e27b51e062e1ac878eb9224fd039da3c..7d203fcd320b80d3a4eda92fd93d34f652e4774f 100644 (file)
@@ -114,7 +114,7 @@ COMLIST commands[] = {
 #endif  CHAT_SYSTEM 
 */
   {"@CONFIG",
-   "SET LOWERCASE LIST GLOBALS DEFAULTS COSTS FLAGS POWERS FUNCTIONS COMMANDS ATTRIBS",
+   "SET SAVE LOWERCASE LIST GLOBALS DEFAULTS COSTS FLAGS POWERS FUNCTIONS COMMANDS ATTRIBS",
    cmd_config, CMD_T_ANY | CMD_T_EQSPLIT, NULL},
   {"@CPATTR", "CONVERT NOFLAGCOPY", cmd_cpattr,
    CMD_T_ANY | CMD_T_EQSPLIT | CMD_T_RS_ARGS,
@@ -2038,7 +2038,7 @@ run_hook_override(COMMAND_INFO *cmd, dbref player, const char *commandraw)
                           cmd->hooks.override.attrname, commandraw);
   } else {
     return atr_comm_match(cmd->hooks.override.obj, player, '$', ':', commandraw,
-                          0, NULL, NULL, NULL);
+                          0, 1, NULL, NULL, NULL);
   }
 }
 
index 72ea30f4e25f6a450ca6718a92994ef5a403333a..d401d319f33fa6c8965dac7e7fe827f0994b4706 100644 (file)
@@ -23,6 +23,7 @@
 #include "externs.h"
 #include "mushdb.h"
 #include "mymalloc.h"
+#include "dbio.h"
 #ifdef WIN32
 #pragma warning( disable : 4244)        /* NJG: disable warning re conversion */
 #endif
@@ -58,7 +59,7 @@ slab *huffman_slab = NULL;
 static int fix_tree_depth(CNode *node, int height, int zeros);
 static void add_ones(CNode *node);
 static void build_ctable(CNode *root, CType code, int numbits);
-int init_compress(FILE * f);
+int init_compress(PENNFILE *f);
 
 
 /** Huffman-compress a string.
@@ -321,7 +322,7 @@ build_ctable(CNode *root, CType code, int numbits)
  * \param f filehandle to read from to build the tree.
  */
 int
-init_compress(FILE * f)
+init_compress(PENNFILE *f)
 {
   int total;
   unsigned char c;
@@ -361,8 +362,8 @@ init_compress(FILE * f)
   /* Part 2: count frequencies */
   if (f) {
     total = 0;
-    while (!feof(f) && (!SAMPLE_SIZE || (total++ < SAMPLE_SIZE))) {
-      c = fgetc(f);
+    while (!penn_feof(f) && (!SAMPLE_SIZE || (total++ < SAMPLE_SIZE))) {
+      c = penn_fgetc(f);
       table[c].freq++;
     }
   }
index d30835e091366322872e29d92a338d64a1ae0a60..7692cf0dc5674873978cad8360a926bd53d5961f 100644 (file)
@@ -159,7 +159,7 @@ static long total_entries = 0;
 static unsigned char *b;
 
 static void output_previous_word(void);
-int init_compress(FILE *f);
+int init_compress(PENNFILE *f);
 #ifdef COMP_STATS
 void compress_stats(long *entries, long *mem_used,
                     long *total_uncompressed, long *total_compressed);
@@ -359,7 +359,7 @@ safe_uncompress(unsigned char const *s)
  * \param f (unused).
  */
 int
-init_compress(FILE *f __attribute__ ((__unused__)))
+init_compress(PENNFILE *f __attribute__ ((__unused__)))
 {
   memset(words, 0, sizeof words);
   memset(words_len, 0, sizeof words_len);
index 0657ee08e4a02cddcae19e7081926f6f9c5eba0e..fb85c222edaf1f57e1f699788d738662c295244e 100644 (file)
@@ -160,7 +160,7 @@ static long total_entries = 0;
 static unsigned char *b;
 
 static void output_previous_word(void);
-int init_compress(FILE * f);
+int init_compress(PENNFILE * f);
 #ifdef COMP_STATS
 void compress_stats(long *entries, long *mem_used,
                     long *total_uncompressed, long *total_compressed);
@@ -364,7 +364,7 @@ safe_uncompress(unsigned char const *s)
  * \param f (unused).
  */
 int
-init_compress(FILE * f __attribute__ ((__unused__)))
+init_compress(PENNFILE * f __attribute__ ((__unused__)))
 {
   memset(words, 0, sizeof words);
   memset(words_len, 0, sizeof words_len);
index 0028904cb94c71511b6bfc26c5caa483c2eaaa15..847e4e0007256c78460e19ad740e7e5ca4ba8495 100644 (file)
@@ -23,6 +23,7 @@
 #include <string.h>
 #include <stdlib.h>
 #include <ctype.h>
+#include <errno.h>
 
 #include "conf.h"
 #include "externs.h"
@@ -43,8 +44,7 @@
 time_t mudtime;                 /**< game time, in seconds */
 
 static void show_compile_options(dbref player);
-static char *config_list_helper(dbref player, COBRA_CONF *cp, int lc);
-static char *config_list_helper2(dbref player, COBRA_CONF *cp, int lc);
+static char *config_to_string(dbref player, COBRA_CONF *cp, int lc);
 
 OPTTAB options;         /**< The table of configuration options */
 HASHTAB local_options;  /**< Hash table for local config options */
@@ -343,8 +343,6 @@ COBRA_CONF conftable[] = {
   {"queue_entry_cpu_time", cf_int, &options.queue_entry_cpu_time, 100000, 0,
    "limits"}
   ,
-  {"max_global_fns", cf_int, &options.max_global_fns, 2000, 0, 0}
-  ,
   {"use_quota", cf_bool, &options.use_quota, 2, 0, "limits"}
   ,
   {"max_channels", cf_int, &options.max_channels, 1000, 0, "chat"}
@@ -484,6 +482,9 @@ COBRA_CONF conftable[] = {
   {"chunk_swap_file", cf_str, options.chunk_swap_file,
    sizeof options.chunk_swap_file, 0, "files"}
   ,
+  {"chunk_swap_initial_size", cf_int, &options.chunk_swap_initial, 1000000, 0,
+   "files"}
+  ,
   {"chunk_cache_memory", cf_int, &options.chunk_cache_memory,
    1000000000, 65510 * 2, "files"}
   ,
@@ -865,6 +866,46 @@ validate_config(void)
 #undef VALIDATE
 }
 
+static char *toplevel_cfile = NULL;
+
+static void
+append_restriction(const char *r, const char *what, const char *opts)
+{
+  FILE *out;
+
+  out = fopen(toplevel_cfile, "a");
+  if (out) {
+    fprintf(out, "# Added by @config/save\n%s %s %s\n\n", r, what, opts);
+    fclose(out);
+  }
+}
+
+/* Not perfect -- things defined in included config files won't
+   get changed -- but it'll catch most cases.
+*/
+static void
+save_config_option(COBRA_CONF *cp)
+{
+#if defined(HAVE_ED)
+  FILE *ed;
+
+  /* ed is the standard! Why reinvent it? */
+
+  ed = popen(ED_PATH, "w");
+  if (!ed) {
+    do_rawlog(LT_ERR, "Unable to open ed: %s", strerror(errno));
+    return;
+  }
+
+  fprintf(ed, "e %s\n", toplevel_cfile);
+  fprintf(ed, ",s/^[[:space:]]*%s[[:space:]].*$/%s/\n", cp->name,
+          trim_space_sep(config_to_string(GOD, cp, 1), ' '));
+  fputs("wq\n", ed);
+  pclose(ed);
+#endif
+
+}
+
 /** Set a configuration option.
  * This function sets a runtime configuration option. During the load
  * of the configuration file, it gets run twice - once to set the
@@ -872,7 +913,7 @@ validate_config(void)
  * that require having the flag table available.
  * \param opt name of the option.
  * \param val value to set the option to.
- * \param source 0 if being set from mush.cnf, 1 from softcode.
+ * \param source 0 if being set from mush.cnf, 1 from softcode, 2 from softcode and saving.
  * \param restrictions 1 if we're setting restriction options, 0 for others.
  * \retval 1 success.
  * \retval 0 failure.
@@ -927,6 +968,8 @@ config_set(const char *opt, char *val, int source, int restrictions)
       }
       return 0;
     }
+    if (source == 2)
+      append_restriction("restrict_command", val, p);
     return 1;
   } else if (!strcasecmp(opt, "restrict_function")) {
     if (!restrictions)
@@ -950,6 +993,8 @@ config_set(const char *opt, char *val, int source, int restrictions)
       }
       return 0;
     }
+    if (source == 2)
+      append_restriction("restrict_function", val, p);
     return 1;
   } else if (!strcasecmp(opt, "reserve_alias")) {
     if (!restrictions)
@@ -975,6 +1020,8 @@ config_set(const char *opt, char *val, int source, int restrictions)
       }
       return 0;
     }
+    if (source == 2)
+      append_restriction("reserve_alias", val, p);
     return 1;
   } else if (!strcasecmp(opt, "attribute_alias")) {
     if (!restrictions)
@@ -995,6 +1042,8 @@ config_set(const char *opt, char *val, int source, int restrictions)
       }
       return 0;
     }
+    if (source == 2)
+      append_restriction("attribute_alias", val, p);
     return 1;
   } else if (!strcasecmp(opt, "function_alias")) {
     if (!restrictions)
@@ -1015,6 +1064,8 @@ config_set(const char *opt, char *val, int source, int restrictions)
       }
       return 0;
     }
+    if (source == 2)
+      append_restriction("function_alias", val, p);
     return 1;
   } else if (!strcasecmp(opt, "help_command")
              || !strcasecmp(opt, "ahelp_command")) {
@@ -1023,7 +1074,7 @@ config_set(const char *opt, char *val, int source, int restrictions)
     if (!restrictions)
       return 0;
     /* Add a new help-like command */
-    if (source == 1)
+    if (source >= 1)            /* Can't do this from @config/set */
       return 0;
     if (!val || !*val) {
       do_rawlog(LT_ERR,
@@ -1056,20 +1107,26 @@ config_set(const char *opt, char *val, int source, int restrictions)
                      && strcmp(cp->group, "messages") != 0))
         && !strcasecmp(cp->name, opt)) {
       i = cp->handler(opt, val, cp->loc, cp->max, source);
-      if (i)
+      if (i) {
         cp->overridden = 1;
+       if(source == 2)
+         save_config_option(cp);
+      }
       return i;
     }
   }
-  for (cp = (COBRA_CONF *) hash_firstentry(&local_options); cp;
-       cp = (COBRA_CONF *) hash_nextentry(&local_options)) {
-    int i = 0;
+  for (cp = hash_firstentry(&local_options); cp;
+      cp = hash_nextentry(&local_options)) {
+  int i = 0;
     if ((!source || (cp->group && strcmp(cp->group, "files") != 0
                      && strcmp(cp->group, "messages") != 0))
         && !strcasecmp(cp->name, opt)) {
       i = cp->handler(opt, val, cp->loc, cp->max, source);
-      if (i)
+      if (i) {
         cp->overridden = 1;
+       if(source == 2)
+         save_config_option(cp);
+      }
       return i;
     }
   }
@@ -1241,7 +1298,6 @@ conf_default_set(void)
   options.max_guest_pennies = 100000;
   options.max_depth = 10;
   options.max_parents = 10;
-  options.max_global_fns = 50;
   options.purge_interval = 601;
   options.dbck_interval = 599;
   options.max_attrcount = 2048;
@@ -1252,6 +1308,7 @@ conf_default_set(void)
   options.ascii_names = 1;
   options.call_lim = 10000;
   strcpy(options.chunk_swap_file, "data/chunkswap");
+  options.chunk_swap_initial = 2048;
   options.chunk_cache_memory = 1000000;
   options.chunk_migrate_amount = 50;
   options.read_remote_desc = 0;
@@ -1302,8 +1359,8 @@ config_file_startup(const char *conf, int restrictions)
   COBRA_CONF *cp;
   char tbuf1[BUFFER_LEN];
   char *p, *q, *s;
-
   static char cfile[BUFFER_LEN];        /* Remember the last one */
+
   if (conf_recursion == 0) {
     if (conf && *conf)
       strcpy(cfile, conf);
@@ -1313,6 +1370,8 @@ config_file_startup(const char *conf, int restrictions)
       return 0;
     }
     do_rawlog(LT_ERR, "Reading %s", cfile);
+    if (toplevel_cfile == NULL)
+      toplevel_cfile = mush_strdup(cfile, "config.file");
   } else {
     if (conf && *conf)
       fp = fopen(conf, FOPEN_READ);
@@ -1467,7 +1526,7 @@ do_config_list(dbref player, const char *type, int lc)
       /* It wasn't a group. Is is one or more specific options? */
       for (cp = conftable; cp->name; cp++) {
         if (cp->group && string_prefix(cp->name, type)) {
-          notify(player, config_list_helper(player, cp, lc));
+          notify(player, config_to_string(player, cp, lc));
           found = 1;
         }
       }
@@ -1476,7 +1535,7 @@ do_config_list(dbref player, const char *type, int lc)
         for (cp = (COBRA_CONF *) hash_firstentry(&local_options); cp;
              cp = (COBRA_CONF *) hash_nextentry(&local_options)) {
           if (cp->group && !strcasecmp(cp->name, type)) {
-            notify(player, config_list_helper(player, cp, lc));
+            notify(player, config_to_string(player, cp, lc));
             found = 1;
           }
         }
@@ -1497,13 +1556,13 @@ do_config_list(dbref player, const char *type, int lc)
       else {
         for (cp = conftable; cp->name; cp++) {
           if (cp->group && !strcmp(cp->group, cgp->name)) {
-            notify(player, config_list_helper(player, cp, lc));
+            notify(player, config_to_string(player, cp, lc));
           }
         }
         for (cp = (COBRA_CONF *) hash_firstentry(&local_options); cp;
              cp = (COBRA_CONF *) hash_nextentry(&local_options)) {
           if (cp->group && !strcasecmp(cp->group, cgp->name)) {
-            notify(player, config_list_helper(player, cp, lc));
+            notify(player, config_to_string(player, cp, lc));
           }
         }
       }
@@ -1524,7 +1583,9 @@ do_config_list(dbref player, const char *type, int lc)
 /** Lowercase a string if we've been asked to */
 #define MAYBE_LC(x) (lc ? strlower(x) : x)
 static char *
-config_list_helper(dbref player __attribute__ ((__unused__)), COBRA_CONF *cp, int lc)
+config_to_string(dbref player
+                  __attribute__ ((__unused__)), COBRA_CONF *cp, int lc
+                  __attribute__ ((__unused__)))
 {
   static char result[BUFFER_LEN];
   char *bp = result;
@@ -1564,8 +1625,9 @@ config_list_helper(dbref player __attribute__ ((__unused__)), COBRA_CONF *cp, in
 
 /* This one doesn't return the names */
 static char *
-config_list_helper2(dbref player __attribute__ ((__unused__)), COBRA_CONF *cp, int lc
-                    __attribute__ ((__unused__)))
+config_to_string2(dbref player
+                  __attribute__ ((__unused__)), COBRA_CONF *cp, int lc
+                  __attribute__ ((__unused__)))
 {
   static char result[BUFFER_LEN];
   char *bp = result;
@@ -1609,14 +1671,14 @@ FUNCTION(fun_config)
   if (args[0] && *args[0]) {
     for (cp = conftable; cp->name; cp++) {
       if (cp->group && !strcasecmp(cp->name, args[0])) {
-        safe_str(config_list_helper2(executor, cp, 0), buff, bp);
+        safe_str(config_to_string2(executor, cp, 0), buff, bp);
         return;
       }
     }
     for (cp = (COBRA_CONF *) hash_firstentry(&local_options); cp;
          cp = (COBRA_CONF *) hash_nextentry(&local_options)) {
       if (cp->group && !strcasecmp(cp->name, args[0])) {
-        safe_str(config_list_helper2(executor, cp, 0), buff, bp);
+        safe_str(config_to_string2(executor, cp, 0), buff, bp);
         return;
       }
     }
@@ -1755,6 +1817,22 @@ show_compile_options(dbref player)
   notify(player, T(" Changed help files will be automatically reindexed."));
 #endif
 
+#ifdef HAVE_SSE2
+  notify(player, T(" SSE2 instructions are being used."));
+#endif
+
+#ifdef HAVE_SSE3
+  notify(player, T(" SSE3 instructions are being used."));
+#endif
+
+#ifdef HAVE_ALTIVEC
+  notify(player, T(" Altivec instructions are being used."));
+#endif
 
+#ifdef HAVE_ED
+  notify(player, T(" @config/save is enabled."));
+#else
+  notify(player, T(" @config/save is disabled."));
+#endif
 
 }
index f15ab28eb451a4c0dd983466ed685de41504f021..94ee972bde9140a2f9637da9753e793644d50dcc 100644 (file)
@@ -72,8 +72,6 @@ typedef struct bque {
   HASHTAB namedregs;
 } BQUE;
 
-slab *bque_slab = NULL; /**< slab for 'struct bque' allocations */
-
 intmap *queue_map = NULL;
 static uint32_t top_qid = 1;
 #define MAX_PID (1U << 15)
@@ -117,8 +115,6 @@ extern sig_atomic_t cpu_time_limit_hit; /**< Have we used too much CPU? */
 void
 init_queue(void)
 {
-  bque_slab = slab_create("command queues", sizeof(BQUE));
-  slab_set_opt(bque_slab, SLAB_ALLOC_BEST_FIT, 1);
   queue_map = im_new();
 }
 
@@ -209,18 +205,18 @@ free_qentry(BQUE * point)
   int a;
   for (a = 0; a < 10; a++)
     if (point->env[a]) {
-      mush_free(point->env[a], "bqueue_env");
+      mush_free(point->env[a], "cqueue.env");
     }
   for (a = 0; a < NUMQ; a++)
     if (point->rval[a]) {
-      mush_free(point->rval[a], "bqueue_rval");
+      mush_free(point->rval[a], "cqueue.rval");
     }
   if (point->semattr)
     mush_free(point->semattr, "bqueue_semattr");
   if (point->comm)
-    mush_free(point->comm, "bqueue_comm");
+    mush_free(point->comm, "cqueue.comm");
   im_delete(queue_map, point->qid);
-  slab_free(bque_slab, point);
+  mush_free(point, "cqueue");
 }
 
 static int
@@ -229,7 +225,7 @@ pay_queue(dbref player, const char *command)
   int estcost;
   estcost =
       QUEUE_COST +
-      (QUEUE_LOSS ? ((get_random_long(0, QUEUE_LOSS - 1) == 0) ? 1 : 0) :
+      (QUEUE_LOSS ? ((get_random32(0, QUEUE_LOSS - 1) == 0) ? 1 : 0) :
        0);
   if (!quiet_payfor(player, estcost)) {
     notify(Owner(player), T("Not enough money to queue command."));
@@ -333,9 +329,9 @@ parse_que(dbref player, const char *command, dbref cause)
     notify(player, T("Queue entry table full. Try again later."));
     return;
   }
-  tmp = (BQUE *) slab_malloc(bque_slab, NULL);
+  tmp = (BQUE *) mush_malloc(sizeof *tmp, "cqueue");
   tmp->qid = qid;
-  tmp->comm = mush_strdup(command, "bqueue_comm");
+  tmp->comm = mush_strdup(command, "cqueue.comm");
   tmp->semattr = NULL;
   tmp->player = player;
   tmp->queued = QUEUE_PER_OWNER ? Owner(player) : player;
@@ -348,14 +344,14 @@ parse_que(dbref player, const char *command, dbref cause)
     if (!global_eval_context.wnxt[a])
       tmp->env[a] = NULL;
     else {
-      tmp->env[a] = mush_strdup(global_eval_context.wnxt[a], "bqueue_env");
+      tmp->env[a] = mush_strdup(global_eval_context.wnxt[a], "cqueue.env");
     }
   for (a = 0; a < NUMQ; a++)
     if (!global_eval_context.rnxt[a] || !global_eval_context.rnxt[a][0])
       tmp->rval[a] = NULL;
     else {
       tmp->rval[a] =
-          mush_strdup(global_eval_context.rnxt[a], "bqueue_rval");
+          mush_strdup(global_eval_context.rnxt[a], "cqueue.rval");
     }
   init_namedregs(&tmp->namedregs);
   copy_namedregs(&tmp->namedregs, &global_eval_context.namedregs);
@@ -386,9 +382,9 @@ div_parse_que(dbref division, const char *command, dbref called_division,
     return;
   if ((qid = create_qid()) == -1)       /* No room to process shit.. don't do shit */
     return;
-  tmp = (BQUE *) slab_malloc(bque_slab, NULL);
+  tmp = (BQUE *) mush_malloc(sizeof *tmp, "cqueue");
   tmp->qid = qid;
-  tmp->comm = mush_strdup(command, "bqueue_comm");
+  tmp->comm = mush_strdup(command, "cqueue.comm");
   tmp->semattr = NULL;
   tmp->player = division;
   tmp->queued = QUEUE_PER_OWNER ? Owner(division) : division;
@@ -402,14 +398,14 @@ div_parse_que(dbref division, const char *command, dbref called_division,
     if (!global_eval_context.wnxt[a])
       tmp->env[a] = NULL;
     else {
-      tmp->env[a] = mush_strdup(global_eval_context.wnxt[a], "bqueue_env");
+      tmp->env[a] = mush_strdup(global_eval_context.wnxt[a], "cqueue.env");
     }
   for (a = 0; a < NUMQ; a++)
     if (!global_eval_context.rnxt[a] || !global_eval_context.rnxt[a][0])
       tmp->rval[a] = NULL;
     else {
       tmp->rval[a] =
-          mush_strdup(global_eval_context.rnxt[a], "bqueue_rval");
+          mush_strdup(global_eval_context.rnxt[a], "cqueue.rval");
     }
   init_namedregs(&tmp->namedregs);
   copy_namedregs(&tmp->namedregs, &global_eval_context.namedregs);
@@ -532,9 +528,9 @@ wait_que(dbref player, int waittill, char *command, dbref cause, dbref sem,
     return -1;
   if ((qid = create_qid()) == -1)       /* can not obtain a QID */
     return -1;
-  tmp = (BQUE *) slab_malloc(bque_slab, NULL);
+  tmp = (BQUE *) mush_malloc(sizeof *tmp, "cqueue");
   tmp->qid = qid;
-  tmp->comm = mush_strdup(command, "bqueue_comm");
+  tmp->comm = mush_strdup(command, "cqueue.comm");
   tmp->player = player;
   tmp->queued = QUEUE_PER_OWNER ? Owner(player) : player;
   tmp->realcause = tmp->cause = cause;
@@ -546,7 +542,7 @@ wait_que(dbref player, int waittill, char *command, dbref cause, dbref sem,
     if (!global_eval_context.wnxt[a])
       tmp->env[a] = NULL;
     else {
-      tmp->env[a] = mush_strdup(global_eval_context.wnxt[a], "bqueue_env");
+      tmp->env[a] = mush_strdup(global_eval_context.wnxt[a], "cqueue.env");
     }
   }
   for (a = 0; a < NUMQ; a++) {
@@ -554,7 +550,7 @@ wait_que(dbref player, int waittill, char *command, dbref cause, dbref sem,
       tmp->rval[a] = NULL;
     else {
       tmp->rval[a] =
-          mush_strdup(global_eval_context.rnxt[a], "bqueue_rval");
+          mush_strdup(global_eval_context.rnxt[a], "cqueue.rval");
     }
   }
   init_namedregs(&tmp->namedregs);
@@ -586,7 +582,7 @@ wait_que(dbref player, int waittill, char *command, dbref cause, dbref sem,
 
     /* Put it on the end of the semaphore queue */
     tmp->semattr =
-        mush_strdup(semattr ? semattr : "SEMAPHORE", "bqueue_semattr");
+      mush_strdup(semattr ? semattr : "SEMAPHORE", "cqueue.semattr");
     if (qsemlast != NULL) {
       qsemlast->next = tmp;
       qsemlast = tmp;
index 7f347bd247178fd310afce535c2e453b9be72df1..cb0cbfe3d9358f38393c4ad654f0f14fece39b44 100644 (file)
@@ -458,10 +458,11 @@ do_dig(dbref player, const char *name, char **argv, int tport)
  * \param player the enactor.
  * \param name name of thing to create.
  * \param cost pennies spent in creation.
+ * \paran newdbref the (unparsed) dbref to give the object, or NULL to use the next free
  * \return dbref of new thing, or NOTHING.
  */
 dbref
-do_create(dbref player, char *name, int cost)
+do_create(dbref player, char *name, int cost, char *newdbref)
 {
   struct module_entry_t *m;
   void (*handle)(dbref);
@@ -477,6 +478,25 @@ do_create(dbref player, char *name, int cost)
   } else if (cost < OBJECT_COST) {
     cost = OBJECT_COST;
   }
+
+  if (newdbref && *newdbref) {
+    /* move newdbref to the start of the free list */
+    if (!has_flag_by_name(player, "WIZARD", NOTYPE)) {
+      notify(player, T("Permission denied."));
+      return NOTHING;
+    }
+    thing = parse_dbref(newdbref);
+    if (thing == NOTHING || !GoodObject(thing) || !IsGarbage(thing)) {
+      notify(player, T("That is not a valid dbref."));
+      return NOTHING;
+    }
+
+    if (!make_first_free(thing)) {
+      notify(player, T("Unable to create object with that dbref."));
+      return NOTHING;
+    }
+  }
+
   if (can_pay_fees(player, cost)) {
     /* create the object */
     thing = new_object();
@@ -533,7 +553,6 @@ clone_object(dbref player, dbref thing, const char *newname, int preserve)
 
   memcpy(REFDB(clone), REFDB(thing), sizeof(struct object));
   Owner(clone) = Owner(player);
-  Name(clone) = NULL;
   if (newname && *newname)
     set_name(clone, newname);
   else
index 32719618bb0590dadee2935ded6fe0b933edcb6e..35e6b8fcd4c85145d59268a00908f69f495ed2f0 100644 (file)
@@ -19,9 +19,7 @@
 #include "cron.h"
 
 #include <ctype.h>
-#ifdef I_STRING
 #include <string.h>
-#endif
 
 #ifdef MUSHCRON
 
index 360a5f5530a50c094850f4b1a58e3e354aaa3001..b430c23d5fe4d5d52ca988b18ea090e8167632d3 100644 (file)
--- a/src/db.c
+++ b/src/db.c
@@ -8,7 +8,7 @@
 
 #include "copyrite.h"
 #include "config.h"
-
+#define _GNU_SOURCE
 #include <stdio.h>
 #include <ctype.h>
 #include <string.h>
@@ -21,6 +21,8 @@
 #include <time.h>
 #endif
 #include <stdlib.h>
+#include <stdarg.h>
+#include <errno.h>
 #include <ltdl.h>
 #include "conf.h"
 #include "dbio.h"
@@ -87,22 +89,22 @@ HASHTAB htab_objdata_keys;    /**< Object data keys hash table */
 
 static void db_grow(dbref newtop);
 
-static void db_write_obj_basic(FILE * f, dbref i, struct object *o);
-int db_paranoid_write_object(FILE * f, dbref i, int flag);
-void putlocks(FILE * f, lock_list *l);
-void getlocks(dbref i, FILE * f);
-void get_new_locks(dbref i, FILE * f, int c);
-void db_read_attrs(FILE * f, dbref i, int c);
-int get_list(FILE * f, dbref i);
-static unsigned char * getbytes(FILE * f);
-void putbytes(FILE * f, unsigned char *lbytes, int byte_limit);
+static void db_write_obj_basic(PENNFILE * f, dbref i, struct object *o);
+int db_paranoid_write_object(PENNFILE * f, dbref i, int flag);
+void putlocks(PENNFILE * f, lock_list *l);
+void getlocks(dbref i, PENNFILE * f);
+void get_new_locks(dbref i, PENNFILE * f, int c);
+void db_read_attrs(PENNFILE * f, dbref i, int c);
+int get_list(PENNFILE * f, dbref i);
+static unsigned char * getbytes(PENNFILE * f);
+void putbytes(PENNFILE * f, unsigned char *lbytes, int byte_limit);
 void db_free(void);
-int load_flag_db(FILE *);
-void db_write_flag_db(FILE *);
+int load_flag_db(PENNFILE *);
+void db_write_flag_db(PENNFILE *);
 static void init_objdata_htab(int size, void(*free_data)(void*));
-static void db_write_flags(FILE * f);
-static void db_write_powers(FILE * f);
-static dbref db_read_oldstyle(FILE * f);
+static void db_write_flags(PENNFILE * f);
+static void db_write_powers(PENNFILE * f);
+static dbref db_read_oldstyle(PENNFILE * f);
 
 StrTree object_names;       /**< String tree of object names */
 StrTree _clastmods;
@@ -279,9 +281,9 @@ new_object(void)
  * \param ref value to write.
  */
 void
-putref(FILE * f, long int ref)
+putref(PENNFILE *f, long int ref)
 {
-  OUTPUT(fprintf(f, "%ld\n", ref));
+  penn_fprintf(f, "%ld\n", ref);
 }
 
 /** Output a string to a file.
@@ -291,22 +293,22 @@ putref(FILE * f, long int ref)
  * \param s value to write.
  */
 void
-putstring(FILE * f, const char *s)
+putstring(PENNFILE *f, const char *s)
 {
-  OUTPUT(putc('"', f));
+  penn_fputc('"', f);
   while (*s) {
     switch (*s) {
     case '\\':
     case '"':
-      OUTPUT(putc('\\', f));
+      penn_fputc('\\', f);
       /* FALL THROUGH */
     default:
-      OUTPUT(putc(*s, f));
+      penn_fputc(*s, f);
     }
     s++;
   }
-  OUTPUT(putc('"', f));
-  OUTPUT(putc('\n', f));
+  penn_fputc('"', f);
+  penn_fputc('\n', f);
 }
 
 /** Read a labeled entry from a database.
@@ -320,7 +322,7 @@ putstring(FILE * f, const char *s)
  * buffer containing the value that was read.
  */
 void
-db_read_labeled_string(FILE * f, char **label, char **value)
+db_read_labeled_string(PENNFILE *f, char **label, char **value)
 {
   static char lbuf[BUFFER_LEN], vbuf[BUFFER_LEN];
   int c;
@@ -334,14 +336,14 @@ db_read_labeled_string(FILE * f, char **label, char **value)
   dbline++;
 
   do {
-    c = getc(f);
+    c = penn_fgetc(f);
     while (isspace(c)) {
       if (c == '\n')
         dbline++;
-      c = getc(f);
+      c = penn_fgetc(f);
     }
     if (c == '#') {
-      while ((c = getc(f)) != '\n' && c != EOF) {
+      while ((c = penn_fgetc(f)) != '\n' && c != EOF) {
         /* nothing */
       }
       if (c == '\n')
@@ -365,7 +367,7 @@ db_read_labeled_string(FILE * f, char **label, char **value)
       longjmp(db_err, 1);
     }
     safe_chr(c, lbuf, &p);
-    c = getc(f);
+    c = penn_fgetc(f);
   } while (c != EOF && !isspace(c));
   *p++ = '\0';
   if (p >= lbuf + BUFFER_LEN)
@@ -373,7 +375,7 @@ db_read_labeled_string(FILE * f, char **label, char **value)
 
   /* suck up separating whitespace */
   while (c != '\n' && c != EOF && isspace(c))
-    c = getc(f);
+    c = penn_fgetc(f);
 
   /* check for presence of a value, which we must have. */
   if (c == EOF || c == '\n') {
@@ -393,11 +395,11 @@ db_read_labeled_string(FILE * f, char **label, char **value)
     int sline;
     sline = dbline;
     for (;;) {
-      c = getc(f);
+      c = penn_fgetc(f);
       if (c == '"')
         break;
       if (c == '\\')
-        c = getc(f);
+        c = penn_fgetc(f);
       if (c == EOF) {
         do_rawlog(LT_ERR, "DB: Unclosed quoted string starting on line %d",
                   sline);
@@ -412,7 +414,7 @@ db_read_labeled_string(FILE * f, char **label, char **value)
       safe_chr(c, vbuf, &p);
     }
     do {
-      c = getc(f);
+      c = penn_fgetc(f);
       if (c != EOF && !isspace(c)) {
         do_rawlog(LT_ERR, "DB: Garbage after quoted string, line %d", dbline);
         longjmp(db_err, 1);
@@ -428,7 +430,7 @@ db_read_labeled_string(FILE * f, char **label, char **value)
         longjmp(db_err, 1);
       }
       safe_chr(c, vbuf, &p);
-      c = getc(f);
+      c = penn_fgetc(f);
     } while (c != EOF && c != '\n');
     if (c == '\n' && (p - vbuf >= 2) && (*(p - 2) == '\r')) {
       /* Oops, we read in \r\n at the end of this value. Drop the \r */
@@ -452,7 +454,7 @@ db_read_labeled_string(FILE * f, char **label, char **value)
  * buffer containing the value that was read.
  */
 void
-db_read_this_labeled_string(FILE * f, const char *label, char **value)
+db_read_this_labeled_string(PENNFILE *f, const char *label, char **value)
 {
   char *readlabel;
 
@@ -474,7 +476,7 @@ db_read_this_labeled_string(FILE * f, const char *label, char **value)
  * \param value pointer to update to the number that was read.
  */
 void
-db_read_this_labeled_int(FILE * f, const char *label, int *value)
+db_read_this_labeled_int(PENNFILE *f, const char *label, int *value)
 {
   char *readlabel;
   char *readvalue;
@@ -498,7 +500,7 @@ db_read_this_labeled_int(FILE * f, const char *label, int *value)
  * \param value pointer to update to the number that was read.
  */
 void
-db_read_labeled_int(FILE * f, char **label, int *value)
+db_read_labeled_int(PENNFILE *f, char **label, int *value)
 {
   char *readvalue;
   db_read_labeled_string(f, label, &readvalue);
@@ -513,7 +515,7 @@ db_read_labeled_int(FILE * f, char **label, int *value)
  * \param value pointer to update to the number that was read.
  */
 void
-db_read_this_labeled_uint32(FILE * f, const char *label, uint32_t * value)
+db_read_this_labeled_uint32(PENNFILE *f, const char *label, uint32_t *value)
 {
   char *readlabel;
   char *readvalue;
@@ -537,7 +539,7 @@ db_read_this_labeled_uint32(FILE * f, const char *label, uint32_t * value)
  * \param value pointer to update to the number that was read.
  */
 void
-db_read_labeled_uint32(FILE * f, char **label, uint32_t * value)
+db_read_labeled_uint32(PENNFILE *f, char **label, uint32_t *value)
 {
   char *readvalue;
   db_read_labeled_string(f, label, &readvalue);
@@ -554,7 +556,7 @@ db_read_labeled_uint32(FILE * f, char **label, uint32_t * value)
  * \param value pointer to update to the time_t that was read.
  */
 void
-db_read_this_labeled_time_t(FILE * f, const char *label, time_t *value)
+db_read_this_labeled_time_t(PENNFILE * f, const char *label, time_t *value)
 {
   char *readlabel;
   char *readvalue;
@@ -578,7 +580,7 @@ db_read_this_labeled_time_t(FILE * f, const char *label, time_t *value)
  * \param value pointer to update to the time_t that was read.
  */
 void
-db_read_labeled_time_t(FILE * f, char **label, time_t *value)
+db_read_labeled_time_t(PENNFILE * f, char **label, time_t *value)
 {
   char *readvalue;
   db_read_labeled_string(f, label, &readvalue);
@@ -593,7 +595,7 @@ db_read_labeled_time_t(FILE * f, char **label, time_t *value)
  * \param value pointer to update to the dbref that was read.
  */
 void
-db_read_this_labeled_dbref(FILE * f, const char *label, dbref *val)
+db_read_this_labeled_dbref(PENNFILE *f, const char *label, dbref *val)
 {
   char *readlabel;
   char *readvalue;
@@ -616,7 +618,7 @@ db_read_this_labeled_dbref(FILE * f, const char *label, dbref *val)
  * \param value pointer to update to the dbref that was read.
  */
 void
-db_read_labeled_dbref(FILE * f, char **label, dbref *val)
+db_read_labeled_dbref(PENNFILE *f, char **label, dbref *val)
 {
   char *readvalue;
   db_read_labeled_string(f, label, &readvalue);
@@ -624,35 +626,35 @@ db_read_labeled_dbref(FILE * f, char **label, dbref *val)
 }
 
 static void
-db_write_label(FILE * f, char const *l)
+db_write_label(PENNFILE * f, char const *l)
 {
-  OUTPUT(fputs(l, f));
-  OUTPUT(putc(' ', f));
+  penn_fputs(l, f);
+  penn_fputc(' ', f);
 }
 
 void
-db_write_labeled_string(FILE * f, char const *label, char const *value)
+db_write_labeled_string(PENNFILE * f, char const *label, char const *value)
 {
   db_write_label(f, label);
   putstring(f, value);
 }
 
 void
-db_write_labeled_int(FILE * f, char const *label, int value)
+db_write_labeled_int(PENNFILE * f, char const *label, int value)
 {
-  OUTPUT(fprintf(f, "%s %d\n", label, value));
+  penn_fprintf(f, "%s %d\n", label, value);
 }
 
 void
-db_write_labeled_time_t(FILE * f, char const *label, time_t value)
+db_write_labeled_time_t(PENNFILE * f, char const *label, time_t value)
 {
-  OUTPUT(fprintf(f, "%s %zu\n", label, value));
+  penn_fprintf(f, "%s %zu\n", label, value);
 }
 
 void
-db_write_labeled_dbref(FILE * f, char const *label, dbref value)
+db_write_labeled_dbref(PENNFILE * f, char const *label, dbref value)
 {
-  OUTPUT(fprintf(f, "%s #%d\n", label, value));
+  penn_fprintf(f, "%s #%d\n", label, value);
 }
 
 /** Write a boolexp to a file in unparsed (text) form.
@@ -660,7 +662,7 @@ db_write_labeled_dbref(FILE * f, char const *label, dbref value)
  * \param b pointer to boolexp to write.
  */
 void
-putboolexp(FILE * f, boolexp b)
+putboolexp(PENNFILE *f, boolexp b)
 {
   db_write_labeled_string(f, "  key", unparse_boolexp(GOD, b, UB_DBREF));
 }
@@ -670,7 +672,7 @@ putboolexp(FILE * f, boolexp b)
  * \param l pointer to lock_list to write.
  */
 void
-putlocks(FILE * f, lock_list *l)
+putlocks(PENNFILE *f, lock_list *l)
 {
   lock_list *ll;
   int count = 0;
@@ -696,7 +698,7 @@ putlocks(FILE * f, lock_list *l)
  * \param o pointer to object to write.
  */
 static void
-db_write_obj_basic(FILE * f, dbref i, struct object *o)
+db_write_obj_basic(PENNFILE *f, dbref i, struct object *o)
 {
   db_write_labeled_string(f, "name", o->name);
   db_write_labeled_dbref(f, "location", o->location);
@@ -731,7 +733,7 @@ db_write_obj_basic(FILE * f, dbref i, struct object *o)
  * \param i dbref of object to write.
  */
 int
-db_write_object(FILE * f, dbref i)
+db_write_object(PENNFILE *f, dbref i)
 {
   struct object *o;
   ALIST *list;
@@ -784,7 +786,7 @@ db_write_object(FILE * f, dbref i)
  * \return the number of objects in the database (db_top)
  */
 dbref
-db_write(FILE * f, int flag)
+db_write(PENNFILE *f, int flag)
 {
   dbref i;
   int dbflag;
@@ -818,10 +820,10 @@ db_write(FILE * f, int flag)
   dbflag += DBF_NEW_ATR_LOCK;
   dbflag += DBF_ATR_MODTIME;
 
-  OUTPUT(fprintf(f, "+V%d\n", dbflag * 256 + 2));
+  penn_fprintf(f, "+V%d\n", dbflag * 256 + 2);
   db_write_labeled_string(f, "savedtime", show_time(mudtime, 1));
 
-  OUTPUT(fprintf(f, "~%d\n", db_top));
+  penn_fprintf(f, "~%d\n", db_top);
   for (i = 0; i < db_top; i++) {
 #ifdef WIN32
 #ifndef __MINGW32__
@@ -832,23 +834,23 @@ db_write(FILE * f, int flag)
 #endif
     if (IsGarbage(i))
       continue;
-    OUTPUT(fprintf(f, "!%d\n", i));
+    penn_fprintf(f, "!%d\n", i);
     db_write_object(f, i);
   }
-  OUTPUT(fputs(EOD, f));
+  penn_fputs(EOD, f);
   return db_top;
 }
 
 static void
-db_write_flags(FILE * f)
+db_write_flags(PENNFILE * f)
 {
-  OUTPUT(fprintf(f, "+FLAGS LIST\n"));
+  penn_fprintf(f, "+FLAGS LIST\n");
   flag_write_all(f, "FLAG");
 }
 
 static void
-db_write_powers(FILE *f) {
-  OUTPUT(fprintf(f, "+POWERS LIST\n"));
+db_write_powers(PENNFILE *f) {
+  penn_fprintf(f, "+POWERS LIST\n");
   power_write_all(f);
 }
 
@@ -862,7 +864,7 @@ db_write_powers(FILE *f) {
  * \param flag 1 = debug, 0 = normal
  */
 int
-db_paranoid_write_object(FILE * f, dbref i, int flag)
+db_paranoid_write_object(PENNFILE *f, dbref i, int flag)
 {
   struct object *o;
   ALIST *list, *next;
@@ -986,7 +988,7 @@ db_paranoid_write_object(FILE * f, dbref i, int flag)
  * \return the number of objects in the database (db_top)
  */
 dbref
-db_paranoid_write(FILE * f, int flag)
+db_paranoid_write(PENNFILE *f, int flag)
 {
   dbref i;
   int dbflag;
@@ -1018,12 +1020,12 @@ db_paranoid_write(FILE * f, int flag)
 
   do_rawlog(LT_CHECK, "PARANOID WRITE BEGINNING...\n");
 
-  OUTPUT(fprintf(f, "+V%d\n", dbflag * 256 + 2));
+  penn_fprintf(f, "+V%d\n", dbflag * 256 + 2);
 
   db_write_labeled_string(f, "savedtime", show_time(mudtime, 1));
   db_write_flags(f);
   db_write_powers(f);
-  OUTPUT(fprintf(f, "~%d\n", db_top));
+  penn_fprintf(f, "~%d\n", db_top);
 
   /* write out each object */
   for (i = 0; i < db_top; i++) {
@@ -1034,13 +1036,13 @@ db_paranoid_write(FILE * f, int flag)
 #endif
     if (IsGarbage(i))
       continue;
-    OUTPUT(fprintf(f, "!%d\n", i));
+    penn_fprintf(f, "!%d\n", i);
     db_paranoid_write_object(f, i, flag);
     /* print out a message every so many objects */
     if (i % globals.paranoid_checkpt == 0)
       do_rawlog(LT_CHECK, T("\t...wrote up to object #%d\n"), i);
   }
-  OUTPUT(fputs(EOD, f));
+  penn_fputs(EOD, f);
   do_rawlog(LT_CHECK, T("\t...finished at object #%d\n"), i - 1);
   do_rawlog(LT_CHECK, "END OF PARANOID WRITE.\n");
   return db_top;
@@ -1052,10 +1054,10 @@ db_paranoid_write(FILE * f, int flag)
  * \return long int read.
  */
 long int
-getref(FILE * f)
+getref(PENNFILE *f)
 {
   static char buf[BUFFER_LEN];
-  if (!fgets(buf, sizeof(buf), f)) {
+  if (!penn_fgets(buf, sizeof(buf), f)) {
     do_rawlog(LT_ERR, T("Unexpected EOF at line %d"), dbline);
     longjmp(db_err, 1);
   }
@@ -1073,14 +1075,14 @@ getref(FILE * f)
  * \return pointer to static buffer containing string read.
  */
 char *
-getstring_noalloc(FILE * f)
+getstring_noalloc(PENNFILE *f)
 {
   static char buf[BUFFER_LEN];
   char *p;
   int c;
 
   p = buf;
-  c = fgetc(f);
+  c = penn_fgetc(f);
   if (c == EOF) {
     do_rawlog(LT_ERR, T("Unexpected EOF at line %d"), dbline);
     longjmp(db_err, 1);
@@ -1094,26 +1096,26 @@ getstring_noalloc(FILE * f)
         return buf;
       }
       safe_chr(c, buf, &p);
-      c = fgetc(f);
+      c = penn_fgetc(f);
     }
   } else {
     for (;;) {
-      c = fgetc(f);
+      c = penn_fgetc(f);
       if (c == '"') {
         /* It's a closing quote if it's followed by \r or \n */
-        c = fgetc(f);
+        c = penn_fgetc(f);
         if (c == '\r') {
           /* Get a possible \n, too */
-          if ((c = fgetc(f)) != '\n')
-            ungetc(c, f);
+          if ((c = penn_fgetc(f)) != '\n')
+            penn_ungetc(c, f);
           else
             dbline++;
         } else if (c != '\n')
-          ungetc(c, f);
+          penn_ungetc(c, f);
         *p = '\0';
         return buf;
       } else if (c == '\\') {
-        c = fgetc(f);
+        c = penn_fgetc(f);
       }
       if ((c == '\0') || (c == EOF)) {
         *p = '\0';
@@ -1132,7 +1134,7 @@ getstring_noalloc(FILE * f)
  * \return pointer to boolexp read.
  */
 boolexp
-getboolexp(FILE * f, const char *type)
+getboolexp(PENNFILE *f, const char *type)
 {
   char *val;
   db_read_this_labeled_string(f, "key", &val);
@@ -1149,7 +1151,7 @@ extern PRIV lock_privs[];
  * \param c number of locks, or -1 if not yet known.
  */
 void
-get_new_locks(dbref i, FILE * f, int c)
+get_new_locks(dbref i, PENNFILE *f, int c)
 {
   char *val, *key;
   dbref creator;
@@ -1166,8 +1168,8 @@ get_new_locks(dbref i, FILE * f, int c)
   for (;;) {
     int ch;
 
-    ch = fgetc(f);
-    ungetc(ch, f);
+    ch = penn_fgetc(f);
+    penn_ungetc(ch, f);
 
     if (ch != ' ')
       break;
@@ -1210,15 +1212,15 @@ get_new_locks(dbref i, FILE * f, int c)
  * \param f file pointer to read from.
  */
 void
-getlocks(dbref i, FILE * f)
+getlocks(dbref i, PENNFILE *f)
 {
   /* Assumes it begins at the beginning of a line. */
   int c;
   boolexp b;
   char buf[BUFFER_LEN], *p;
-  while ((c = getc(f)), c != EOF && c == '_') {
+  while ((c = penn_fgetc(f)), c != EOF && c == '_') {
     p = buf;
-    while ((c = getc(f)), c != EOF && c != '|') {
+    while ((c = penn_fgetc(f)), c != EOF && c != '|') {
       *p++ = c;
     }
     *p = '\0';
@@ -1234,47 +1236,47 @@ getlocks(dbref i, FILE * f)
       add_lock_raw(Owner(i), i, buf, b, LF_DEFAULT);
     }
   }
-  ungetc(c, f);
+  penn_ungetc(c, f);
   return;
 }
 
 void
-putbytes(FILE * f, unsigned char *lbytes, int byte_limit) {
+putbytes(PENNFILE * f, unsigned char *lbytes, int byte_limit) {
   int i;
 
-  OUTPUT(putc('\"', f));
+  penn_fputc('\"', f);
 
   for(i = 0; i < byte_limit; ++i) {
     switch(lbytes[i]) {
       case '\"':
       case '\\':
-        OUTPUT(putc('\\', f));
+        penn_fputc('\\', f);
       default:
-        OUTPUT(putc(lbytes[i], f));
+        penn_fputc(lbytes[i], f);
     }
   }
 
-  OUTPUT(putc('\"', f));
-  OUTPUT(putc('\n', f));
+  penn_fputc('\"', f);
+  penn_fputc('\n', f);
 }
 
 unsigned char *
-getbytes(FILE * f) {
+getbytes(PENNFILE * f) {
   static unsigned char byte_buf[BUFFER_LEN];
   unsigned char *bp;
   int i;
 
   memset(byte_buf, 0, BUFFER_LEN);
   bp = byte_buf;
-  (void) fgetc(f);      /* Skip the leading " */
+  (void) penn_fgetc(f);      /* Skip the leading " */
   for(;;) {
-    i = fgetc(f);
+    i = penn_fgetc(f);
     if(i == '\"') {
-      if((i = fgetc(f)) != '\n')
-        ungetc(i, f);
+      if((i = penn_fgetc(f)) != '\n')
+        penn_ungetc(i, f);
       break;
     } else if(i == '\\') {
-      i = fgetc(f);
+      i = penn_fgetc(f);
     }
     if(i == EOF)
       break;
@@ -1313,7 +1315,7 @@ db_free(void)
  * \param i dbref for the attribute list.
  */
 int
-get_list(FILE * f, dbref i)
+get_list(PENNFILE *f, dbref i)
 {
   int c;
   char *p, *q;
@@ -1328,12 +1330,12 @@ get_list(FILE * f, dbref i)
   List(i) = NULL;
   tbuf1[0] = '\0';
   while (1)
-    switch (c = getc(f)) {
+    switch (c = penn_fgetc(f)) {
     case ']':                   /* new style attribs, read name then value */
       /* Using getstring_noalloc here will cause problems with attribute
          names starting with ". This is probably a better fix than just
          disallowing " in attribute names. */
-      fgets(tbuf1, BUFFER_LEN + 150, f);
+      penn_fgets(tbuf1, BUFFER_LEN + 150, f);
       if (!(p = strchr(tbuf1, '^'))) {
         do_rawlog(LT_ERR, T("ERROR: Bad format on new attributes. object #%d"),
                   i);
@@ -1389,7 +1391,7 @@ get_list(FILE * f, dbref i)
       return -1;
       break;
     case '<':                   /* end of list */
-      if ('\n' != getc(f)) {
+      if ('\n' != penn_fgetc(f)) {
         do_rawlog(LT_ERR, T("ERROR: no line feed after < on object %d"), i);
         return -1;
       }
@@ -1416,7 +1418,7 @@ get_list(FILE * f, dbref i)
 extern PRIV attr_privs_view[];
 
 void
-db_read_attrs(FILE * f, dbref i, int count)
+db_read_attrs(PENNFILE *f, dbref i, int count)
 {
    char name[ATTRIBUTE_NAME_LIMIT + 1];
    char l_key[BUFFER_LEN];
@@ -1435,8 +1437,8 @@ db_read_attrs(FILE * f, dbref i, int count)
    for(;;) {
      int c;
  
-     c = fgetc(f);
-     ungetc(c, f);
+    c = penn_fgetc(f);
+    penn_ungetc(c, f);
      
      if (c != ' ')
        break;
@@ -1495,13 +1497,13 @@ db_read_attrs(FILE * f, dbref i, int count)
 /* Load Seperate Flag Database
  */
 
-int load_flag_db(FILE *f) {
+int load_flag_db(PENNFILE *f) {
   int c;
   char *tmp;
 
   loading_db = 1;
   
-  if((c = fgetc(f)) != '+' && (c = fgetc(f)) != '+') {
+  if((c = penn_fgetc(f)) != '+' && (c = penn_fgetc(f)) != '+') {
     do_rawlog(LT_ERR, T("Flag database does not start with a version string"));
     return -1;
   }
@@ -1511,9 +1513,9 @@ int load_flag_db(FILE *f) {
   db_read_this_labeled_string(f, "savedtime", &tmp); /* We don't use this info anywhere 'yet' */
   do_rawlog(LT_ERR, T("Loading flag databased saved on %s UTC"), tmp);
 
-  while((c = fgetc(f)) != EOF) {
+  while((c = penn_fgetc(f)) != EOF) {
     if(c == '+') {
-        c = fgetc(f);
+        c = penn_fgetc(f);
          if(c == 'F') {
            (void) getstring_noalloc(f);
            flag_read_all(f, "FLAG");
@@ -1526,8 +1528,8 @@ int load_flag_db(FILE *f) {
          }
     } else if(c == '*'){
       char buff[80];
-      ungetc('*', f);
-      fgets(buff, sizeof buff, f);
+      penn_ungetc('*', f);
+      penn_fgets(buff, sizeof buff, f);
       if(strcmp(buff, EOD) != 0){
         do_rawlog(LT_ERR, T("ERROR: No end of dump entry."));
         return -1;
@@ -1544,7 +1546,7 @@ int load_flag_db(FILE *f) {
   return 0;
 }
 
-void db_write_flag_db(FILE *f) {
+void db_write_flag_db(PENNFILE *f) {
   int flags;
 
   /* Write out db flags */
@@ -1552,11 +1554,11 @@ void db_write_flag_db(FILE *f) {
   flags += FLAG_DBF_CQUOTA_RENAME;
   /* */
 
-  OUTPUT(fprintf(f, "+V%ld\n", flagdb_flags * 256 + 2));
+  penn_fprintf(f, "+V%ld\n", flagdb_flags * 256 + 2);
   db_write_labeled_string(f, "savedtime", show_time(mudtime, 1));
   db_write_flags(f);
   db_write_powers(f);
-  OUTPUT(fputs(EOD, f));
+  penn_fputs(EOD, f);
 }
 
 
@@ -1567,7 +1569,7 @@ void db_write_flag_db(FILE *f) {
  */
 
 static dbref
-db_read_oldstyle(FILE * f)
+db_read_oldstyle(PENNFILE *f)
 {
   int c, opbits;
   dbref i;
@@ -1579,7 +1581,7 @@ db_read_oldstyle(FILE * f)
   for (i = 0;; i++) {
     /* Loop invariant: we always begin at the beginning of a line. */
     errobj = i;
-    c = getc(f);
+    c = penn_fgetc(f);
     switch (c) {
       /* make sure database is at least this big *1.5 */
     case '~':
@@ -1588,7 +1590,7 @@ db_read_oldstyle(FILE * f)
       break;
       /* Use the MUSH 2.0 header stuff to see what's in this db */
     case '+':
-      c = getc(f);              /* Skip the V */
+      c = penn_fgetc(f);        /* Skip the V */
       if (c == 'F') {
         (void) getstring_noalloc(f);
         flag_read_all(f, "FLAG");
@@ -1754,8 +1756,8 @@ db_read_oldstyle(FILE * f)
     case '*':
       {
         char buff[80];
-        ungetc('*', f);
-        fgets(buff, sizeof buff, f);
+        penn_ungetc('*', f);
+        penn_fgets(buff, sizeof buff, f);
         if (strcmp(buff, EOD) != 0) {
           do_rawlog(LT_ERR, T("ERROR: No end of dump after object #%d"), i - 1);
           return -1;
@@ -1823,7 +1825,7 @@ db_read_oldstyle(FILE * f)
  * \return number of objects in the database.
  */
 dbref
-db_read(FILE * f)
+db_read(PENNFILE *f)
 {
   int c;
   dbref i = 0;
@@ -1847,12 +1849,12 @@ db_read(FILE * f)
   db_free();
   indb_flags = 1;
 
-  c = fgetc(f);
+  c = penn_fgetc(f);
   if (c != '+') {
     do_rawlog(LT_ERR, T("Database does not start with a version string"));
     return -1;
   }
-  c = fgetc(f);
+  c = penn_fgetc(f);
   if (c != 'V') {
     do_rawlog(LT_ERR, T("Database does not start with a version string"));
     return -1;
@@ -1878,10 +1880,10 @@ db_read(FILE * f)
 
   do_rawlog(LT_ERR, T("Loading database saved on %s UTC"), db_timestamp);
 
-  while ((c = fgetc(f)) != EOF) {
+  while ((c = penn_fgetc(f)) != EOF) {
     switch (c) {
     case '+':
-      c = fgetc(f);
+      c = penn_fgetc(f);
       if (c == 'F') {
         (void) getstring_noalloc(f);
         flag_read_all(f, "FLAG");
@@ -1955,8 +1957,8 @@ db_read(FILE * f)
         db_grow(i + 1);
         o = db + i;
         while (1) {
-          c = fgetc(f);
-          ungetc(c, f);
+          c = penn_fgetc(f);
+          penn_ungetc(c, f);
           /* At the start of another object or the EOD marker */
           if (c == '!' || c == '*')
             break;
@@ -2106,8 +2108,8 @@ db_read(FILE * f)
     case '*':
       {
         char buff[80];
-        ungetc('*', f);
-        fgets(buff, sizeof buff, f);
+        penn_ungetc('*', f);
+        penn_fgets(buff, sizeof buff, f);
         if (strcmp(buff, EOD) != 0) {
           do_rawlog(LT_ERR, T("ERROR: No end of dump after object #%d"), i - 1);
           return -1;
@@ -2335,3 +2337,201 @@ create_minimal_db(void)
 #endif
   mail_init();
 }
+
+
+/** Run a function, and jump if error */
+#define OUTPUT(fun) do { if ((fun) < 0) longjmp(db_err, 1); } while (0)
+
+/* Wrapper for fopen for use in reboot code. */
+PENNFILE *
+penn_fopen(const char *filename, const char *mode)
+{
+  PENNFILE *pf;
+
+  pf = mush_malloc(sizeof *pf, "pennfile");
+  pf->type = PFT_FILE;
+  pf->handle.f = fopen(filename, mode);
+  if (!pf->handle.f) {
+    do_rawlog(LT_ERR, "Unable to open %s in mode '%s': %s",
+              filename, mode, strerror(errno));
+    mush_free(pf, "pennfile");
+    return NULL;
+  }
+  return pf;
+}
+
+/* Close a db file, which may really be a pipe */
+void
+penn_fclose(PENNFILE *pf)
+{
+  switch (pf->type) {
+  case PFT_PIPE:
+#ifndef WIN32
+    pclose(pf->handle.f);
+#endif
+    break;
+  case PFT_FILE:
+    fclose(pf->handle.f);
+    break;
+  case PFT_GZFILE:
+#ifdef HAVE_LIBZ
+    gzclose(pf->handle.g);
+#endif
+    break;
+  }
+  mush_free(pf, "pennfile");
+}
+
+
+int
+penn_fgetc(PENNFILE *f)
+{
+  switch (f->type) {
+  case PFT_FILE:
+  case PFT_PIPE:
+    return fgetc(f->handle.f);
+    break;
+  case PFT_GZFILE:
+#ifdef HAVE_LIBZ
+    return gzgetc(f->handle.g);
+#endif
+    break;
+  }
+  return 0;
+}
+
+char *
+penn_fgets(char *buf, int len, PENNFILE *pf)
+{
+  switch (pf->type) {
+  case PFT_FILE:
+  case PFT_PIPE:
+    return fgets(buf, len, pf->handle.f);
+  case PFT_GZFILE:
+#ifdef HAVE_LIBZ
+    return gzgets(pf->handle.g, buf, len);
+#endif
+    break;
+  }
+  return NULL;
+}
+
+int
+penn_fputc(int c, PENNFILE *f)
+{
+  switch (f->type) {
+  case PFT_FILE:
+  case PFT_PIPE:
+    OUTPUT(fputc(c, f->handle.f));
+    break;
+  case PFT_GZFILE:
+#ifdef HAVE_LIBZ
+    OUTPUT(gzputc(f->handle.g, c));
+#endif
+    break;
+  }
+  return 0;
+}
+
+int
+penn_fputs(const char *s, PENNFILE *f)
+{
+  switch (f->type) {
+  case PFT_FILE:
+  case PFT_PIPE:
+    OUTPUT(fputs(s, f->handle.f));
+    break;
+  case PFT_GZFILE:
+#ifdef HAVE_LIBZ
+    OUTPUT(gzputs(f->handle.g, s));
+#endif
+  }
+  return 0;
+}
+
+int
+penn_fprintf(PENNFILE *f, const char *fmt, ...)
+{
+  va_list ap;
+  int r = -1;
+
+  switch (f->type) {
+  case PFT_FILE:
+  case PFT_PIPE:
+    va_start(ap, fmt);
+    r = vfprintf(f->handle.f, fmt, ap);
+    va_end(ap);
+    if (r < 0)
+      longjmp(db_err, 1);
+    break;
+  case PFT_GZFILE:
+#ifdef HAVE_LIBZ
+    /* No equivalent to vfprintf in zlib... */
+#ifdef HAVE_VASPRINTF
+    {                           /* Safe GNU/BSD way */
+      char *line = NULL;
+      va_start(ap, fmt);
+      r = vasprintf(&line, fmt, ap);
+      va_end(ap);
+      if (r > -1) {
+        OUTPUT(gzputs(f->handle.g, line));
+        free(line);
+      } else
+        longjmp(db_err, 1);
+    }
+#else
+    {
+      char line[BUFFER_LEN * 2];
+
+      va_start(ap, fmt);
+#ifdef HAVE_VSNPRINTF
+      r = vsnprintf(line, sizeof line, fmt, ap);
+#else
+      r = vsprintf(line, fmt, ap);
+#endif
+      va_end(ap, fmt);
+      if (r > -1)
+        OUTPUT(gzputs(f->handle.g, line));
+      else
+        longjmp(db_err, 1);
+    }
+#endif
+#endif
+    break;
+  }
+  return r;
+}
+
+int
+penn_ungetc(int c, PENNFILE *f)
+{
+  switch (f->type) {
+  case PFT_FILE:
+  case PFT_PIPE:
+    OUTPUT(ungetc(c, f->handle.f));
+    break;
+  case PFT_GZFILE:
+#ifdef HAVE_LIBZ
+    OUTPUT(gzungetc(c, f->handle.g));
+#endif
+    break;
+  }
+  return c;
+
+}
+
+int
+penn_feof(PENNFILE *pf)
+{
+  switch (pf->type) {
+  case PFT_FILE:
+  case PFT_PIPE:
+    return feof(pf->handle.f);
+  case PFT_GZFILE:
+#ifdef HAVE_LIBZ
+    return gzeof(pf->handle.g);
+#endif
+    break;
+  }
+  return 0;
+}
index 7eb5400528d6d8db40bd4ecc33762476de43d3b3..f954a6f8250cbed9f386c30cfc4151542f0820ac 100644 (file)
@@ -928,6 +928,32 @@ clear_exit(dbref thing)
   giveto(Owner(thing), EXIT_COST);
 }
 
+/** If object is in the free list, move it to the very beginning.
+ * \param object dbref of object to move
+ * \return 1 if object is moved successfully, 0 otherwise
+ */
+int
+make_first_free(dbref object)
+{
+  dbref curr;
+  dbref prev = NOTHING;
+
+  if (first_free == NOTHING || !GoodObject(object) || !IsGarbage(object))
+    return 0;                   /* no garbage, or object isn't garbage */
+  else if (first_free == object)
+    return 1;                   /* object is already at the head of the queue */
+  for (curr = first_free; Next(curr); curr = Next(curr)) {
+    if (curr == object) {
+      Next(prev) = Next(curr);
+      Next(curr) = first_free;
+      first_free = curr;
+      return 1;
+    } else
+      prev = curr;
+  }
+  return 0;
+
+}
 
 /** Return a cleaned up object off the free list or NOTHING.
  * \return a garbage object or NOTHING.
index f657a06766c428f6ee0520a324a1eff62fc8cd4b..297f43851143c0ffa80ed1119361ac9a167ce601 100644 (file)
@@ -38,9 +38,9 @@ static void power_add(POWER * pow);
 static POWER *new_power(void);
 static void realloc_object_powers(int);
 static void power_add_additional();
-static void power_read(FILE *);
-static void powergroup_read(FILE *);
-static void power_read_alias(FILE *);
+static void power_read(PENNFILE *);
+static void powergroup_read(PENNFILE *);
+static void power_read_alias(PENNFILE *);
 static void clear_all_powers();
 static int power_delete(const char *);
 static int check_old_power_ycode(int, unsigned char *);
@@ -65,7 +65,7 @@ int can_have_power_at(dbref, POWER *);
 POWER *add_power_type(const char *name, const char *type);
 void init_powers();
 div_pbits new_power_bitmask();
-void powers_read_all(FILE * in);
+void powers_read_all(PENNFILE * in);
 POWER *has_power(dbref, const char *);
 int can_have_pg(dbref object, POWERGROUP * pgrp);
 void do_list_powers(dbref player, const char *name);
@@ -349,7 +349,7 @@ PTAB powergroup_ptab;
 /* Database Functions {{{2 */
 /* powers_read_all() {{{3 */
 void
-powers_read_all(FILE * in)
+powers_read_all(PENNFILE * in)
 {
   int count;
 
@@ -403,7 +403,7 @@ init_powers()
 
 /* powers_read() {{{3 - database power read routine */
 static void
-power_read(FILE * in)
+power_read(PENNFILE * in)
 {
   char power_name[BUFFER_LEN];
   char *power_type;
@@ -422,7 +422,7 @@ power_read(FILE * in)
 
 /* powergroup_read() {{{3 - database powergroup read routine */
 static void
-powergroup_read(FILE * in)
+powergroup_read(PENNFILE * in)
 {
   POWERGROUP *pgrp;
   div_pbits dbits;
@@ -451,7 +451,7 @@ powergroup_read(FILE * in)
 
 /* power_read_alias() {{{3 */
 static void
-power_read_alias(FILE * in)
+power_read_alias(PENNFILE * in)
 {
   POWER *power;
   char alias_name[BUFFER_LEN];
@@ -476,7 +476,7 @@ power_read_alias(FILE * in)
 
 /* power_write_all() {{{3 */
 void
-power_write_all(FILE * file)
+power_write_all(PENNFILE * file)
 {
   POWER *power;
   POWERGROUP *pgrp;
@@ -1603,7 +1603,7 @@ create_div(dbref owner, const char *name)
   }
   Parent(obj) = SDIV(owner).object;
   current_state.divisions++;
-  sprintf(buf, object_header(owner, obj));
+  strcpy(buf, object_header(owner, obj));
   notify_format(owner, T("Division created: %s  Parent division: %s"),
                 buf, buf2);
   return obj;
index 10f98c7819749b37e01e58096b3d6d840bb8bf18..b925a5522e5ad60d5c8a721e17c11394b41f9653 100644 (file)
@@ -1,3 +1,4 @@
+
 /**
  * \file extmail.c
  *
@@ -1884,7 +1885,7 @@ FUNCTION(fun_mailsubject)
  * \return number of mail messages saved.
  */
 int
-dump_mail(FILE * fp)
+dump_mail(PENNFILE *fp)
 {
   MAIL *mp;
   int count = 0;
@@ -1896,11 +1897,11 @@ dump_mail(FILE * fp)
   mail_flags += MDBF_SENDERCTIME;
 
   if (mail_flags)
-    fprintf(fp, "+%d\n", mail_flags);
+    penn_fprintf(fp, "+%d\n", mail_flags);
 
   save_malias(fp);
 
-  OUTPUT(fprintf(fp, "%d\n", mdb_top));
+  penn_fprintf(fp, "%d\n", mdb_top);
 
   for (mp = HEAD; mp != NULL; mp = mp->next) {
     putref(fp, mp->to);
@@ -1916,15 +1917,14 @@ dump_mail(FILE * fp)
     count++;
   }
 
-  OUTPUT(fputs(EOD, fp));
-  fflush(fp);
+  penn_fputs(EOD, fp);
 
   if (count != mdb_top) {
     do_log(LT_ERR, 0, 0, T("MAIL: Count of messages is %d, mdb_top is %d."),
            count, mdb_top);
     mdb_top = count;            /* Doesn't help if we forked, but oh well */
   }
-  return (count);
+  return count;
 }
 
 
@@ -2014,7 +2014,7 @@ mail_init(void)
  * \param fp pointer to filehandle from which to load mail.
  */
 int
-load_mail(FILE * fp)
+load_mail(PENNFILE *fp)
 {
   char nbuf1[8];
   unsigned char *tbuf = NULL;
@@ -2029,7 +2029,7 @@ load_mail(FILE * fp)
   struct tm ttm;
 
   /* find out how many messages we should be loading */
-  fgets(nbuf1, sizeof(nbuf1), fp);
+  penn_fgets(nbuf1, sizeof(nbuf1), fp);
   /* If it starts with +, it's telling us the mail db flags */
   if (*nbuf1 == '+') {
     mail_flags = atoi(nbuf1 + 1);
@@ -2037,14 +2037,14 @@ load_mail(FILE * fp)
     if (mail_flags & MDBF_ALIASES) {
       load_malias(fp);
     }
-    fgets(nbuf1, sizeof(nbuf1), fp);
+    penn_fgets(nbuf1, sizeof(nbuf1), fp);
   }
   mail_top = atoi(nbuf1);
   if (!mail_top) {
     /* mail_top could be 0 from an error or actually be 0. */
     if (nbuf1[0] == '0' && nbuf1[1] == '\n') {
       char buff[20];
-      if (!fgets(buff, sizeof buff, fp))
+      if (!penn_fgets(buff, sizeof buff, fp))
         do_rawlog(LT_ERR,
                   T("MAIL: Missing end-of-dump marker in mail database."));
       else if (strcmp(buff, (mail_flags & MDBF_NEW_EOD)
@@ -2159,7 +2159,7 @@ load_mail(FILE * fp)
   }
   {
     char buff[20];
-    if (!fgets(buff, sizeof buff, fp))
+    if (!penn_fgets(buff, sizeof buff, fp))
       do_rawlog(LT_ERR,
                 T("MAIL: Missing end-of-dump marker in mail database."));
     else if (strcmp(buff, (mail_flags & MDBF_NEW_EOD)
index 5f67a94bd900486587288ed33bee95904272ec7b..2109d0994126d80cecf6219378eb900370c81721 100644 (file)
@@ -60,10 +60,10 @@ static FLAG *letter_to_flagptr(FLAGSPACE * n, char c, int type);
 static void flag_add(FLAGSPACE * n, const char *name, FLAG *f);
 static int has_flag(dbref thing, FLAG *f);
 
-static FLAG *flag_read(FILE * in);
-static FLAG *flag_read_oldstyle(FILE * in);
-static void flag_read_all_oldstyle(FILE * in, const char *ns);
-static void flag_write(FILE * out, FLAG *f, const char *name);
+static FLAG *flag_read(PENNFILE * in);
+static FLAG *flag_read_oldstyle(PENNFILE * in);
+static void flag_read_all_oldstyle(PENNFILE * in, const char *ns);
+static void flag_write(PENNFILE * out, FLAG *f, const char *name);
 static FLAG *flag_hash_lookup(FLAGSPACE * n, const char *name, int type);
 static FLAG *clone_flag(FLAG *f);
 static FLAG *new_flag(void);
@@ -71,7 +71,7 @@ static void flag_add_additional(void);
 static char *list_aliases(FLAGSPACE * n, FLAG *given);
 static void realloc_object_flag_bitmasks(int numbytes);
 static FLAG *match_flag_ns(FLAGSPACE * n, const char *name);
-static void flag_fake_read(FILE *);
+static void flag_fake_read(PENNFILE *);
 
 PTAB ptab_flag;                 /**< Table of flags by name, inc. aliases */
 HASHTAB htab_flagspaces;                /**< Hash of flagspaces */
@@ -424,7 +424,7 @@ realloc_object_flag_bitmasks(int numbytes)
 
 /* Read in a flag from a file and return it */
 static FLAG *
-flag_read_oldstyle(FILE * in)
+flag_read_oldstyle(PENNFILE *in)
 {
   FLAG *f;
   char *c;
@@ -445,7 +445,7 @@ flag_read_oldstyle(FILE * in)
 }
 
 static FLAG *
-flag_alias_read_oldstyle(FILE * in, char *alias)
+flag_alias_read_oldstyle(PENNFILE * in, char *alias)
 {
   FLAG *f;
   char *c;
@@ -484,7 +484,7 @@ flag_alias_read_oldstyle(FILE * in, char *alias)
  * \param ns name of namespace to search.
  */
 static void
-flag_read_all_oldstyle(FILE * in, const char *ns)
+flag_read_all_oldstyle(PENNFILE *in, const char *ns)
 {
   FLAG *f;
   FLAGSPACE *n;
@@ -508,7 +508,7 @@ flag_read_all_oldstyle(FILE * in, const char *ns)
 
 /* Read in a flag from a file and return it */
 static FLAG *
-flag_read(FILE * in)
+flag_read(PENNFILE *in)
 {
   FLAG *f;
   char *c;
@@ -538,7 +538,7 @@ flag_read(FILE * in)
 }
 
 static FLAG *
-flag_alias_read(FILE * in, char *alias, FLAGSPACE *n)
+flag_alias_read(PENNFILE *in, char *alias, FLAGSPACE *n)
 {
   FLAG *f;
   char *c;
@@ -574,7 +574,7 @@ flag_alias_read(FILE * in, char *alias, FLAGSPACE *n)
  * \param ns name of namespace to search.
  */
 void
-flag_read_all(FILE * in, const char *ns)
+flag_read_all(PENNFILE *in, const char *ns)
 {
   FLAG *f;
   FLAGSPACE *n;
@@ -603,8 +603,8 @@ flag_read_all(FILE * in, const char *ns)
   for (;;) {
     int c;
 
-    c = fgetc(in);
-    ungetc(c, in);
+    c = penn_fgetc(in);
+    penn_ungetc(c, in);
 
    if (c != ' ')
       break;
@@ -625,8 +625,8 @@ flag_read_all(FILE * in, const char *ns)
   for (found = 0 ;;) {
     int c;
     
-    c = fgetc(in);
-    ungetc(c, in);
+    c = penn_fgetc(in);
+    penn_ungetc(c, in);
 
     if (c != ' ')
       break;
@@ -645,7 +645,7 @@ flag_read_all(FILE * in, const char *ns)
   flag_add_additional();
 }
 
-static void flag_fake_read(FILE *f) {
+static void flag_fake_read(PENNFILE *f) {
   int count;
 
   /* Read shit into NULL-ville */
@@ -668,7 +668,7 @@ static void flag_fake_read(FILE *f) {
 
 /* Write a flag out to a file */
 static void
-flag_write(FILE * out, FLAG *f, const char *name)
+flag_write(PENNFILE *out, FLAG *f, const char *name)
 {
   db_write_labeled_string(out, " name", name);
  db_write_labeled_string(out, "  letter", tprintf("%c", f->letter));
@@ -682,7 +682,7 @@ flag_write(FILE * out, FLAG *f, const char *name)
 
 /* Write a flag alias out to a file */
 static void
-flag_alias_write(FILE * out, FLAG *f, const char *name)
+flag_alias_write(PENNFILE *out, FLAG *f, const char *name)
 {
   db_write_labeled_string(out, " name", f->name);
   db_write_labeled_string(out, "  alias", name);
@@ -694,7 +694,7 @@ flag_alias_write(FILE * out, FLAG *f, const char *name)
  * \param out file pointer to write to.
  */
 void
-flag_write_all(FILE * out, const char *ns)
+flag_write_all(PENNFILE *out, const char *ns)
 {
   int i, count;
   FLAG *f;
@@ -1447,6 +1447,7 @@ set_flag(dbref player, dbref thing, const char *flag, int negate,
   dbref icloc, absroom;
 #endif /* RPMODE_SYS */
   FLAGSPACE *n;
+  int current;
 
   n = (FLAGSPACE *) hashfind("FLAG", &htab_flagspaces);
   if ((f = flag_hash_lookup(n, flag, Typeof(thing))) == NULL) {
@@ -1547,6 +1548,8 @@ set_flag(dbref player, dbref thing, const char *flag, int negate,
 
   twiddle_flag(thing, f, negate);
 
+  current = sees_flag(player, thing, f->name);
+
 #ifdef RPMODE_SYS
   if(is_flag(f, "RPMODE")) {
         dbref oldloc;
@@ -1680,6 +1683,8 @@ set_flag(dbref player, dbref thing, const char *flag, int negate,
       safe_str(Name(thing), tbuf1, &tp);
       safe_str(" - ", tbuf1, &tp);
       safe_str(f->name, tbuf1, &tp);
+      if (!current)
+        safe_str(" (already)", tbuf1, &tp);
       safe_str(T(" reset."), tbuf1, &tp);
       *tp = '\0';
       notify(player, tbuf1);
@@ -1752,6 +1757,8 @@ set_flag(dbref player, dbref thing, const char *flag, int negate,
       safe_str(Name(thing), tbuf1, &tp);
       safe_str(" - ", tbuf1, &tp);
       safe_str(f->name, tbuf1, &tp);
+      if (current)
+        safe_str(" (already)", tbuf1, &tp);
       safe_str(T(" set."), tbuf1, &tp);
       *tp = '\0';
       notify(player, tbuf1);
index 82e328035fc6d3f6e26d9cffb99cfb31103da67a..5ec3bb1f940ce31af60372b5162b3660d56d323d 100644 (file)
@@ -40,7 +40,9 @@
 static char *crunch_code(char *code);
 static char *crypt_code(char *code, char *text, int type);
 
+#ifdef HAVE_SSL
 static void safe_hexchar(unsigned char c, char *buff, char **bp);
+#endif /* HAVE_SSL */
 
 static bool
 encode_base64
@@ -112,7 +114,7 @@ decode_base64(char *encoded, int len, char *buff, char **bp)
     BIO_free(b64);
     return false;
   }
-  len = BIO_set_close(bmem, BIO_NOCLOSE);
+  /*  len = BIO_set_close(bmem, BIO_NOCLOSE); This makes valgrind report a memory leak. */
 
   bio = BIO_push(b64, bmem);
 
@@ -154,6 +156,7 @@ decode_base64(char *encoded, int len, char *buff, char **bp)
     } else if (dlen == 0)
       break;
     else {
+      BIO_free_all(bio);
       *bp = sbp;
       safe_str(T("#-1 CONVERSION ERROR"), buff, bp);
       return false;
@@ -376,6 +379,7 @@ FUNCTION(fun_digest)
 #endif
 }
 
+#ifdef HAVE_SSL
 static void
 safe_hexchar(unsigned char c, char *buff, char **bp)
 {
@@ -389,3 +393,4 @@ safe_hexchar(unsigned char c, char *buff, char **bp)
     (*bp)++;
   }
 }
+#endif /* HAVE_SSL */
index 3c8f8566146b809aa412d70060aba1cdf8f80340..070330cf8c22730b2cf9bf8361adaf2e327667a2 100644 (file)
@@ -33,11 +33,9 @@ static void func_hash_insert(const char *name, FUN *func);
 static int apply_restrictions(unsigned int result, const char *restriction);
 static char *build_function_report(dbref player, FUN *fp);
  
-USERFN_ENTRY *userfn_tab;   /**< Table of user-defined functions */
 HASHTAB htab_function;      /**< Function hash table */
 HASHTAB htab_user_function; /**< User-defined function hash table */
 slab *function_slab; /**< slab for 'struct fun' allocations */
-slab *userfun_slab; /**< slab for 'struct userfn_entry' allocations */
  
 /* -------------------------------------------------------------------------*
  * Utilities.
@@ -388,7 +386,7 @@ FUNTAB flist[] = {
   {"CONVUTCSECS", fun_convsecs, 1, 1, FN_REG},
   {"CONVTIME", fun_convtime, 1, 1, FN_REG},
   {"COR", fun_cor, 2, INT_MAX, FN_NOPARSE},
-  {"CREATE", fun_create, 1, 2, FN_REG},
+  {"CREATE", fun_create, 1, 3, FN_REG},
   {"CSECS", fun_csecs, 1, 1, FN_REG},
   {"CTIME", fun_ctime, 1, 2, FN_REG},
   {"DEC", fun_dec, 1, 1, FN_REG},
@@ -608,7 +606,7 @@ FUNTAB flist[] = {
   {"OOREF", fun_ooref, 0, 0, FN_REG},
   {"OWNER", fun_owner, 1, 1, FN_REG},
   {"PARENT", fun_parent, 1, 2, FN_REG},
-  {"PCREATE", fun_pcreate, 1, 2, FN_REG},
+  {"PCREATE", fun_pcreate, 2, 3, FN_REG},
   {"PEMIT", fun_pemit, 2, -2, FN_REG},
   {"PGHASPOWER", fun_pghaspower, 3, 4, FN_REG},
   {"PGPOWERS", fun_pgpowers, 2, 2, FN_REG},
@@ -955,7 +953,6 @@ init_func_hashtab(void)
 void
 function_init_postconfig(void)
 {
-  userfn_tab = mush_calloc(MAX_GLOBAL_FNS, sizeof(USERFN_ENTRY), "userfn_tab");
 }
 
 /** Check permissions to run a function.
@@ -1085,9 +1082,6 @@ strip_braces(const char *str)
  * User-defined global function handlers 
  */
 
-
-static size_t userfn_count = 0;
-
 static int
 apply_restrictions(unsigned int result, const char *xres)
 {
@@ -1229,8 +1223,7 @@ do_function_restrict(dbref player, const char *name, const char *restriction,
     safe_format(tbuf1, &bp, "%s %s - ", T("Builtin function"), fp->name);
   else
     safe_format(tbuf1, &bp, "%s #%d/%s - ", T("@function"),
-                userfn_tab[fp->where.offset].thing,
-                userfn_tab[fp->where.offset].name);
+                fp->where.ufun->thing, fp->where.ufun->name);
   if (fp->flags == flags)
     safe_str(T("Restrictions unchanged."), tbuf1, &bp);
   else
@@ -1250,8 +1243,8 @@ func_comp(const void *s1, const void *s2)
   a = *(const FUN **) s1;
   b = *(const FUN **) s2;
 
-  da = userfn_tab[a->where.offset].thing;
-  db = userfn_tab[b->where.offset].thing;
+  da = a->where.ufun->thing;
+  db = b->where.ufun->thing;
 
   if (da == db)
     return strcmp(a->name, b->name);
@@ -1280,6 +1273,7 @@ do_function(dbref player, char *name, char *argv[], int preserve)
   char *bp = tbuf1;
   dbref thing;
   FUN *fp;
+  size_t userfn_count = htab_user_function.entries;
 
   /* if no arguments, just give the list of user functions, by walking
    * the function hash table, and looking up all functions marked
@@ -1310,8 +1304,7 @@ do_function(dbref player, char *name, char *argv[], int preserve)
         fp = funclist[n];
         notify_format(player,
                       "%-32s %6d    %s", fp->name,
-                      userfn_tab[fp->where.offset].thing,
-                      userfn_tab[fp->where.offset].name);
+                      fp->where.ufun->thing, fp->where.ufun->name);
       }
       mush_free(funclist, "function.fp.list");
     } else {
@@ -1375,10 +1368,6 @@ do_function(dbref player, char *name, char *argv[], int preserve)
 
   fp = func_hash_lookup(upcasestr(name));
   if (!fp) {
-    if (userfn_count >= (size_t) MAX_GLOBAL_FNS) {
-      notify(player, T("Function table full."));
-      return;
-    }
     if (argv[6] && *argv[6]) {
       notify(player, T("Expected between 1 and 5 arguments."));
       return;
@@ -1386,7 +1375,6 @@ do_function(dbref player, char *name, char *argv[], int preserve)
     /* a completely new entry. First, insert it into general hash table */
     fp = slab_malloc(function_slab, NULL);
     fp->name = mush_strdup(name, "func_hash.name");
-    fp->where.offset = userfn_count;
     if (argv[3] && *argv[3]) {
       fp->minargs = parse_integer(argv[3]);
       if (fp->minargs < 0)
@@ -1413,11 +1401,9 @@ do_function(dbref player, char *name, char *argv[], int preserve)
     hashadd(name, fp, &htab_user_function);
 
     /* now add it to the user function table */
-    userfn_tab[userfn_count].thing = thing;
-    userfn_tab[userfn_count].name =
-      mush_strdup(upcasestr(argv[2]), "userfn_tab.name");
-    userfn_tab[userfn_count].fn = mush_strdup(name, "usrfn_tab.fn");
-    userfn_count++;
+    fp->where.ufun = mush_malloc(sizeof(USERFN_ENTRY), "userfn");
+    fp->where.ufun->thing = thing;
+    fp->where.ufun->name = mush_strdup(upcasestr(argv[2]), "userfn.name");
 
     notify(player, T("Function added."));
     return;
@@ -1429,23 +1415,16 @@ do_function(dbref player, char *name, char *argv[], int preserve)
       return;
     }
     if (fp->flags & FN_BUILTIN) {       /* Overriding a built in function */
-      if (userfn_count >= (size_t) MAX_GLOBAL_FNS) {
-        notify(player, T("Function table full."));
-        return;
-      }
       fp = slab_malloc(function_slab, NULL);
       fp->name = mush_strdup(name, "func_hash.name");
-      fp->where.offset = userfn_count;
+      fp->where.ufun = mush_malloc(sizeof(USERFN_ENTRY), "userfn");
       fp->flags = 0;
-      userfn_count++;
       hashadd(name, fp, &htab_user_function);
     }
-    userfn_tab[fp->where.offset].thing = thing;
-    if (userfn_tab[fp->where.offset].name)
-      mush_free((Malloc_t) userfn_tab[fp->where.offset].name,
-                "userfn_tab.name");
-    userfn_tab[fp->where.offset].name =
-      mush_strdup(upcasestr(argv[2]), "userfn_tab.name");
+    fp->where.ufun->thing = thing;
+    if (fp->where.ufun->name)
+      mush_free(fp->where.ufun->name, "userfn.name");
+    fp->where.ufun->name = mush_strdup(upcasestr(argv[2]), "userfn.name");
     if (argv[3] && *argv[3]) {
       fp->minargs = parse_integer(argv[3]);
       if (fp->minargs < 0)
@@ -1480,26 +1459,12 @@ do_function(dbref player, char *name, char *argv[], int preserve)
 static void
 delete_function(void *data)
 {
-  size_t table_index, i;
   FUN *fp = data;
 
-  table_index = fp->where.offset;
   mush_free((void *) fp->name, "func_hash.name");
+  mush_free(fp->where.ufun->name, "userfn.name");
+  mush_free(fp->where.ufun, "userfn");
   slab_free(function_slab, fp);
-  /* Fix up the user function table. Expensive, but how often will
-   * we need to delete an @function anyway?
-   */
-  mush_free(userfn_tab[table_index].name, "userfn_tab.name");
-  mush_free(userfn_tab[table_index].fn, "usrfn_tab.fn");
-  userfn_count--;
-  for (i = table_index; i < userfn_count; i++) {
-    fp = (FUN *) hashfind(userfn_tab[i + 1].fn, &htab_user_function);
-    fp->where.offset = i;
-    userfn_tab[i].thing = userfn_tab[i + 1].thing;
-    userfn_tab[i].name = userfn_tab[i + 1].name;
-    userfn_tab[i].fn = userfn_tab[i + 1].fn;
-  }
-
 }
 
 /** Restore an overridden built-in function.
@@ -1582,7 +1547,7 @@ do_function_delete(dbref player, char *name)
     return;
   }
 
-  if (!controls(player, userfn_tab[fp->where.offset].thing)) {
+  if (!controls(player, fp->where.ufun->thing)) {
     notify(player, T("You can't delete that @function."));
     return;
   }
@@ -1776,12 +1741,9 @@ build_function_report(dbref player, FUN *fp)
   safe_format(buff, &bp, T("Flags     : %s"), tbuf);
   safe_chr('\n', buff, &bp);
 
-  if (!(fp->flags & FN_BUILTIN) && Global_Funcs(player)) {
-    safe_format(buff, &bp, T("Location  : #%d/%s"),
-                userfn_tab[fp->where.offset].thing,
-                userfn_tab[fp->where.offset].name);
-    safe_chr('\n', buff, &bp);
-  }
+  if (!(fp->flags & FN_BUILTIN) && Global_Funcs(player))
+    safe_format(buff, &bp, T("Location  : #%d/%s\n"),
+                fp->where.ufun->thing, fp->where.ufun->name);
 
   maxargs = abs(fp->maxargs);
 
index 806a3f646ebf9de81b27ca765c8f39a9f585b21f..ac603cfe971fc932921ba0f6090bdcfdffd15c24 100644 (file)
@@ -1182,7 +1182,8 @@ FUNCTION(fun_elock)
   it = match_thing(executor, args[0]);
   ltype = get_locktype(p);
 
-  if (!GoodObject(it) || (ltype == NULL) ||!Can_Read_Lock(executor, it, ltype)) {
+  if (!GoodObject(it) || !GoodObject(victim)
+      || (ltype == NULL) ||!Can_Read_Lock(executor, it, ltype)) {
     safe_str("#-1", buff, bp);
     return;
   }
@@ -1518,8 +1519,10 @@ FUNCTION(fun_alias)
   dbref it;
 
   it = match_thing(executor, args[0]);
-  if (!GoodObject(it))
+  if (!GoodObject(it)) {
     safe_str(T(e_notvis), buff, bp);
+    return;
+  }
 
   /* Support changing alias via function if side-effects are enabled */
   if (nargs == 2) {
@@ -1872,7 +1875,7 @@ FUNCTION(fun_create)
     cost = parse_integer(args[1]);
   else
     cost = OBJECT_COST;
-  safe_dbref(do_create(executor, args[0], cost), buff, bp);
+  safe_dbref(do_create(executor, args[0], cost, args[2]), buff, bp);
 }
 
 /* ARGSUSED */
@@ -1886,7 +1889,7 @@ FUNCTION(fun_pcreate)
     safe_str(T(e_perm), buff, bp);
     return;
   }
-  safe_dbref(do_pcreate(executor, args[0], args[1]), buff, bp);
+  safe_dbref(do_pcreate(executor, args[0], args[1], args[2]), buff, bp);
 }
 
 /* ARGSUSED */
index 67a7912759612cbd07eb329ae7e6258f6854f838..4b73a02247270e19115c9579c3b64cf50eb6cfa1 100644 (file)
@@ -3,11 +3,8 @@
 #include "copyrite.h"
 
 #include "config.h"
-#ifdef I_STRING
 #include <string.h>
-#else
 #include <strings.h>
-#endif
 #include "conf.h"
 #include "externs.h"
 #include "division.h"
index 1197fef4c79b50a7619f19fd30d14447cb7d570c..9bfc1327ca4d3015cdfd936e602384f93fc9281b 100644 (file)
@@ -8,6 +8,7 @@
 #include "copyrite.h"
 
 #include "config.h"
+#define _GNU_SOURCE
 #include <string.h>
 #include <ctype.h>
 #include "conf.h"
@@ -663,7 +664,7 @@ FUNCTION(fun_shuffle)
   /* shuffle it */
   for (i = 0; i < n; i++) {
     char *tmp;
-    j = get_random_long(i, n - 1);
+    j = get_random32(i, n - 1);
     tmp = words[j];
     words[j] = words[i];
     words[i] = tmp;
@@ -1403,7 +1404,7 @@ FUNCTION(fun_randword)
 
   s = trim_space_sep(args[0], sep);
   word_count = do_wordcount(s, sep);
-  word_index = get_random_long(0, word_count - 1);
+  word_index = get_random32(0, word_count - 1);
 
   /* Go to the start of the token we're interested in. */
   while (word_index && s) {
index 82fe2aaf3714c0ad883631214a24a3d9ab44897b..7405edcbbe2ed34ed6b95e6a5e0745ce4aa6e202 100644 (file)
 #include <string.h>
 #include <ctype.h>
 #include <errno.h>
+
+#ifdef HAVE_SSE2
+#include <emmintrin.h>
+#endif
+#ifdef HAVE_SSE3
+#include <pmmintrin.h>
+#endif
 #include "conf.h"
 #include "externs.h"
 #include "sort.h"
@@ -845,9 +852,43 @@ FUNCTION(fun_vcross)
     vec2[n] = parse_number(v2[n]);
   }
 
+
+#ifdef HAVE_SSE2
+  {
+    __m128d xy1, xy2, xy3, xy4, z1, z2;
+
+    xy1 = _mm_set_pd(vec1[2], vec1[1]);
+    xy2 = _mm_set_pd(vec2[0], vec2[2]);
+    xy3 = _mm_set_pd(vec2[2], vec2[1]);
+    xy4 = _mm_set_pd(vec1[0], vec1[2]);
+    z1 = _mm_set_pd(vec2[0], vec1[0]);
+    z2 = _mm_set_pd(vec1[1], vec2[1]);
+
+    xy1 = _mm_mul_pd(xy1, xy2);
+    xy2 = _mm_mul_pd(xy3, xy4);
+    xy3 = _mm_sub_pd(xy1, xy2);
+    z1 = _mm_mul_pd(z1, z2);
+
+#ifdef HAVE_SSE3
+    z1 = _mm_hsub_pd(z1, z2);
+    _mm_store_sd(cross + 2, z1);
+#else
+    {
+      /* SSE2 version */
+      double zsub[2] __attribute__ ((__aligned__(16)));
+      _mm_store_pd(zsub, z1);
+      cross[2] = zsub[0] - zsub[1];
+    }
+#endif
+
+    _mm_store_pd(cross, xy3);
+  }
+#else
+  /* Scalar version */
   cross[0] = vec1[1] * vec2[2] - vec2[1] * vec1[2];
   cross[1] = vec1[2] * vec2[0] - vec2[2] * vec1[0];
   cross[2] = vec1[0] * vec2[1] - vec2[0] * vec1[1];
+#endif
 
   safe_number(cross[0], buff, bp);
   safe_chr(sep, buff, bp);
@@ -1107,8 +1148,9 @@ FUNCTION(fun_ln)
   safe_number(log(num), buff, bp);
 }
 
-#ifndef HAVE_LOG2
-static double
+/* Cygwin has a log2 that configure doesn't detect. Macro, maybe? */
+#if !defined(HAVE_LOG2) && !defined(__CYGWIN__)
+static inline double
 log2(double x)
 {
   return log(x) / log(2.0);
@@ -1786,32 +1828,71 @@ FUNCTION(fun_lmath)
   mush_free(ptr, "string");
 }
 
-extern char from_base_64[256];
-extern char to_base_64[];
-
-extern char from_base_36[256];
-extern char to_base_36[];
-
+/* Walker probably needs to convert from_base_XX arrays to a form
+   suitable for putting in utils/gentables.c. Copy & paste is not it. ;)  */
+signed char from_base_64[256] = {
+  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, 62, -1, 63,
+  52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1,
+  -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
+  15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, 63,
+  -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
+  41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+};
+
+signed char to_base_64[] =
+  "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
+
+signed char from_base_36[256] = {
+  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+  0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1,
+  -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
+  25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1,
+  -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
+  25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+};
+signed char to_base_36[] = "0123456789abcdefghijklmnopqrstuvwxyz";
 FUNCTION(fun_baseconv)
 {
-  long n;
+  unsigned long n;
+  int isnegative = 0;
   int m;
-  int from, to;
+  unsigned int from, to;
   char *ptr;
   char numbuff[BUFFER_LEN], *nbp;
 
 
-  /* Base 36 by default */
-  char *frombase = from_base_36;
-  char *tobase = to_base_36;
+  /* Base 36 by default. */
+  signed char *frombase = from_base_36;
+  signed char *tobase = to_base_36;
 
   if (!(is_integer(args[1]) && is_integer(args[2]))) {
     safe_str(T(e_ints), buff, bp);
     return;
   }
 
-  from = parse_integer(args[1]);
-  to = parse_integer(args[2]);
+  from = parse_uinteger(args[1]);
+  to = parse_uinteger(args[2]);
 
   if (from < 2 || from > 64) {
     safe_str(T("#-1 FROM BASE OUT OF RANGE"), buff, bp);
@@ -1830,10 +1911,15 @@ FUNCTION(fun_baseconv)
   if (to > 36) {
     tobase = to_base_64;
   }
-  // Parse it.
+
+  /* Parse it. */
   ptr = trim_space_sep(args[0], ' ');
   n = 0;
   while (ptr && *ptr) {
+    if (*ptr == '-') {
+      isnegative = 1;
+      continue;
+    }
     n *= from;
     if (frombase[(unsigned char) *ptr] >= 0) {
       n += frombase[(unsigned char) *ptr];
@@ -1844,7 +1930,7 @@ FUNCTION(fun_baseconv)
     }
   }
 
-  // Handle the 0-case. (And quickly handle < to_base case, too!)
+  /* Handle the 0-case. (And quickly handle < to_base case, too!) */
   if (n < to) {
     safe_chr(tobase[(unsigned char) n], buff, bp);
     return;
@@ -1852,15 +1938,18 @@ FUNCTION(fun_baseconv)
 
   nbp = numbuff;
 
-  // This comes out backwards.
+  /* This comes out backwards. */
   while (n > 0) {
     m = n % to;
     n = n / to;
     safe_chr(tobase[(unsigned char) m], numbuff, &nbp);
   }
 
-  // Reverse back onto buff.
+  /* Reverse back onto buff. */
   nbp--;
+  if (isnegative) {
+    safe_chr('-', buff, bp);
+  }
   while (nbp >= numbuff) {
     safe_chr(*nbp, buff, bp);
     nbp--;
index a971acb832e54e154205c9173ce195e568b4d5a4..1b4c886c5675ad58545e295aa567020844fecfd3 100644 (file)
@@ -331,7 +331,7 @@ FUNCTION(fun_rand)
     return;
   }
 
-  safe_integer(get_random_long(low, high), buff, bp);
+  safe_integer(get_random32(low, high), buff, bp);
 }
 
 /* ARGSUSED */
@@ -362,11 +362,11 @@ FUNCTION(fun_die)
         first = 0;
       else
         safe_chr(' ', buff, bp);
-      safe_uinteger(get_random_long(1, die), buff, bp);
+      safe_uinteger(get_random32(1, die), buff, bp);
     }
   } else {
     for (count = 0; count < n; count++)
-      total += get_random_long(1, die);
+      total += get_random32(1, die);
 
     safe_uinteger(total, buff, bp);
   }
@@ -578,12 +578,7 @@ FUNCTION(fun_restarts)
   safe_integer(globals.reboot_count, buff, bp);
 }
 
-/* Data for soundex functions */
-static char soundex_val[26] = {
-  0, 1, 2, 3, 0, 1, 2, 0, 0,
-  2, 2, 4, 5, 5, 0, 1, 2, 6,
-  2, 3, 0, 1, 0, 2, 0, 2
-};
+extern char soundex_val[UCHAR_MAX + 1];
 
 /* The actual soundex routine */
 static char *
@@ -593,28 +588,27 @@ soundex(str)
   static char tbuf1[BUFFER_LEN];
   char *p, *q;
 
-  tbuf1[0] = '\0';
-  tbuf1[1] = '\0';
-  tbuf1[2] = '\0';
-  tbuf1[3] = '\0';
+  q = remove_markup(str, NULL);
+  memset(tbuf1, '\0', 4);
 
   p = tbuf1;
-  q = upcasestr(remove_markup(str, NULL));
+
   /* First character is just copied */
-  *p = *q++;
+  *p = UPCASE(*q);
+  q++;
   /* Special case for PH->F */
-  if ((*p == 'P') && *q && (*q == 'H')) {
+  if ((UPCASE(*p) == 'P') && *q && (UPCASE(*q) == 'H')) {
     *p = 'F';
     q++;
   }
   p++;
-  /* Convert letters to soundex values, squash duplicates */
+  /* Convert letters to soundex values, squash duplicates, skip accents and other non-ascii characters */
   while (*q) {
     if (!isalpha((unsigned char) *q) || (unsigned char) *q > 127) {
       q++;
       continue;
     }
-    *p = soundex_val[*q++ - 'A'] + '0';
+    *p = soundex_val[(unsigned char) *q++];
     if (*p != *(p - 1))
       p++;
   }
index 49eccc0a29bef20a126364b387e03b38345ad44d..ba6ba26ac33fa62642578ac916ceb4a11bb26f99 100644 (file)
@@ -588,6 +588,7 @@ FUNCTION(fun_lpos)
 FUNCTION(fun_strmatch)
 {
   char tbuf[BUFFER_LEN];
+  char pattern[BUFFER_LEN];
   char *ret[36];
   char *t;
   size_t len;
@@ -603,8 +604,10 @@ FUNCTION(fun_strmatch)
 
   t = remove_markup(args[0], &len);
   memcpy(tbuf, t, len);
+  t = remove_markup(args[1], &len);
+  memcpy(pattern, t, len);
   memset(ret, 0, 36);
-  matches = wild_match_case_r(remove_markup(args[1], NULL), tbuf, 0, ret,
+  matches = wild_match_case_r(pattern, tbuf, 0, ret,
                               NUMQ, match_space, match_space_len);
   safe_boolean(matches, buff, bp);
 
@@ -2005,7 +2008,7 @@ FUNCTION(fun_speak)
   const char *speaker_name;
   char *open, *close;
   char *start, *end = NULL;
-  bool transform = 0, null = 0, say = 0;
+  bool transform = 0, null = 0, say = 0, starting_fragment = 0;
   char *wenv[3];
   int funccount;
   int fragment = 0;
@@ -2150,6 +2153,7 @@ FUNCTION(fun_speak)
   } else {
     /* We're in say mode and the first char isn't open, start there */
     start = string;
+    starting_fragment = 1;
   }
 
   funccount = pe_info->fun_invocations;
@@ -2176,8 +2180,11 @@ FUNCTION(fun_speak)
         (pe_info->fun_invocations == funccount))
       break;
     if (end && *end) {
-      if (say)
-        safe_str(close, buff, bp);
+      if (!starting_fragment) {
+        if (say)
+          safe_str(close, buff, bp);
+        starting_fragment = 0;
+      }
     }
     if (!end || !*end)
       break;
@@ -2187,6 +2194,7 @@ FUNCTION(fun_speak)
       if (start && *start && (start - end > (ptrdiff_t) strlen(open)))
         safe_str(chopstr(end, start - end + 1), buff, bp);
       start += strlen(open);
+      end = NULL;
     } else {
       /* No more opens, so we're done, and end has the rest */
       break;
index 55015db650fd78d0d129b13245536392a593c0d5..7a2c0a1942b95ea475623d64e8d4fb2b3061a9e6 100644 (file)
@@ -106,9 +106,8 @@ extern void initialize_mt(void);
 extern const unsigned char *tables;
 extern void conf_default_set(void);
 static bool dump_database_internal(void);
-static FILE *db_open(const char *filename);
-static FILE *db_open_write(const char *filename);
-static void db_close(FILE * f);
+static PENNFILE *db_open(const char *);
+static PENNFILE *db_open_write(const char *);
 static int fail_commands(dbref player);
 void do_readcache(dbref player);
 int check_alias(const char *command, const char *list);
@@ -326,7 +325,7 @@ dump_database_internal(void)
   char realdumpfile[2048];
   char realtmpfl[2048];
   char tmpfl[2048];
-  FILE *f = NULL;
+  PENNFILE *f = NULL;
   struct module_entry_t *m;
   void (*handle)();
 
@@ -342,7 +341,7 @@ dump_database_internal(void)
        compression slave. Boo! */
     do_rawlog(LT_ERR, T("ERROR! Database save failed."));
     if(f)
-      db_close(f);
+      penn_fclose(f);
 #ifndef PROFILING
 #ifdef HAS_ITIMER
     install_sig_handler(SIGPROF, signal_cpu_limit);
@@ -367,7 +366,7 @@ dump_database_internal(void)
       if((f = db_open_write(tmpfl)) != NULL) {
         use_flagfile = 1;
         db_write_flag_db(f);
-        db_close(f);
+        penn_fclose(f);
 #ifdef WIN32
         unlink(realdumpfile);
 #endif
@@ -401,7 +400,7 @@ dump_database_internal(void)
         db_paranoid_write(f, 1);
         break;
       }
-      db_close(f);
+      penn_fclose(f);
 #ifdef WIN32
       /* Win32 systems can't rename over an existing file, so unlink first */
       unlink(realdumpfile);
@@ -421,7 +420,7 @@ dump_database_internal(void)
     if (mdb_top >= 0) {
       if ((f = db_open_write(tmpfl)) != NULL) {
         dump_mail(f);
-        db_close(f);
+        penn_fclose(f);
 #ifdef WIN32
         unlink(realdumpfile);
 #endif
@@ -441,7 +440,7 @@ dump_database_internal(void)
     sprintf(realtmpfl, "%s%s", tmpfl, options.compresssuff);
     if ((f = db_open_write(tmpfl)) != NULL) {
       save_chatdb(f);
-      db_close(f);
+      penn_fclose(f);
 #ifdef WIN32
       unlink(realdumpfile);
 #endif
@@ -477,7 +476,7 @@ void
 mush_panic(const char *message)
 {
   const char *panicfile = options.crash_db;
-  FILE *f = NULL;
+  PENNFILE *f = NULL;
   static int already_panicking = 0;
 
   if (already_panicking) {
@@ -506,7 +505,7 @@ mush_panic(const char *message)
       do_rawlog(LT_ERR, T("CANNOT DUMP PANIC DB. OOPS."));
       _exit(134);
     } else {
-      if ((f = fopen(panicfile, FOPEN_WRITE)) == NULL) {
+      if ((f = penn_fopen(panicfile, FOPEN_WRITE)) == NULL) {
         do_rawlog(LT_ERR, T("CANNOT OPEN PANIC FILE, YOU LOSE"));
         _exit(135);
       } else {
@@ -518,7 +517,7 @@ mush_panic(const char *message)
 #ifdef CHAT_SYSTEM
         save_chatdb(f);
 #endif /* CHAT_SYSTEM */
-        fclose(f);
+        penn_fclose(f);
         do_rawlog(LT_ERR, T("DUMPING: %s (done)"), panicfile);
       }
     }
@@ -666,7 +665,7 @@ fork_and_dump(int forking)
       chunk_fork_done();
 #endif
     if (!nofork) {
-      _exit(status);            /* !!! */
+      _exit(status ? 0 : 1);    /* d_d_i() returns true on success but exit code should be 0 on success */
     } else {
       reserve_fd();
       if (status && DUMP_NOFORK_COMPLETE && *DUMP_NOFORK_COMPLETE)
@@ -885,7 +884,7 @@ extern int dbline;
 int
 init_game_dbs(void)
 {
-  FILE *f;
+  PENNFILE *f;
   int c;
   const char *infile, *outfile;
 #ifdef USE_MAILER
@@ -919,7 +918,7 @@ init_game_dbs(void)
       if(load_flag_db(f) != 0)
         use_flagfile = 0;
       do_rawlog(LT_ERR, "LOADING: %s(done)", flag_file);
-      db_close(f);
+      penn_fclose(f);
     }
   } else use_flagfile = 0;
 
@@ -935,7 +934,7 @@ init_game_dbs(void)
     return 0;
   }
 
-  c = getc(f);
+  c = penn_fgetc(f);
   if (c == EOF) {
     do_rawlog(LT_ERR, "Couldn't read %s! Creating minimal world.", infile);
     init_compress(NULL);
@@ -943,7 +942,7 @@ init_game_dbs(void)
     return 0;
   }
 
-  ungetc(c, f);
+  penn_ungetc(c, f);
 
   if (setjmp(db_err) == 0) {
     /* ok, read it in */
@@ -955,7 +954,7 @@ init_game_dbs(void)
     do_rawlog(LT_ERR, "ANALYZING: %s (done)", infile);
 
     /* everything ok */
-    db_close(f);
+    penn_fclose(f);
 
     f = db_open(infile);
     if (!f)
@@ -966,7 +965,7 @@ init_game_dbs(void)
     dbline = 0;
     if (db_read(f) < 0) {
       do_rawlog(LT_ERR, "ERROR LOADING %s", infile);
-      db_close(f);
+      penn_fclose(f);
       return -1;
     }
     do_rawlog(LT_ERR, "LOADING: %s (done)", infile);
@@ -975,10 +974,10 @@ init_game_dbs(void)
      * format db, with everything shoved together. In that case,
      * don't close the file
      */
-    panicdb = ((globals.indb_flags & DBF_PANIC) && !feof(f));
+    panicdb = ((globals.indb_flags & DBF_PANIC) && !penn_feof(f));
 
     if (!panicdb)
-      db_close(f);
+      penn_fclose(f);
 
     /* complain about bad config options */
     if (!GoodObject(PLAYER_START) || (!IsRoom(PLAYER_START)))
@@ -1004,11 +1003,11 @@ init_game_dbs(void)
       do_rawlog(LT_ERR, T("LOADING: Trying to get mail from %s"), infile);
       if (load_mail(f) <= 0) {
         do_rawlog(LT_ERR, T("FAILED: Reverting to normal maildb"));
-        db_close(f);
+        penn_fclose(f);
         panicdb = 0;
       }
     } else                      /* Close the panicdb file handle */
-      db_close(f);
+      penn_fclose(f);
 
     if (!panicdb) {
       f = db_open(mailfile);
@@ -1018,7 +1017,7 @@ init_game_dbs(void)
         dbline = 0;
         load_mail(f);
         do_rawlog(LT_ERR, "LOADING: %s (done)", mailfile);
-        db_close(f);
+        penn_fclose(f);
       }
     }
 #endif /* USE_MAILER */
@@ -1030,7 +1029,7 @@ init_game_dbs(void)
       do_rawlog(LT_ERR, T("LOADING: Trying to get chat from %s"), infile);
       if (load_chatdb(f) <= 0) {
         do_rawlog(LT_ERR, T("FAILED: Reverting to normal chatdb"));
-        db_close(f);
+        penn_fclose(f);
         panicdb = 0;
       }
     }
@@ -1046,7 +1045,7 @@ init_game_dbs(void)
           do_rawlog(LT_ERR, "ERROR LOADING %s", options.chatdb);
           return -1;
         }
-        db_close(f);
+        penn_fclose(f);
       }
     }
 #endif /* CHAT_SYSTEM */
@@ -1074,7 +1073,7 @@ do_readcache(dbref player)
 /** Check each attribute on each object in x for a $command matching cptr */
 #define list_match(x)        list_check(x, player, '$', ':', cptr, 0)
 /** Check each attribute on x for a $command matching cptr */
-#define cmd_match(x)         atr_comm_match(x, player, '$', ':', cptr, 0, NULL, NULL, &errdb)
+#define cmd_match(x)         atr_comm_match(x, player, '$', ':', cptr, 0, 1, NULL, NULL, &errdb)
 #define MAYBE_ADD_ERRDB(errdb)  \
         do { \
           if (GoodObject(errdb) && errdblist) { \
@@ -1446,7 +1445,7 @@ list_check(dbref thing, dbref player, char type, char end, char *str,
 
   while (thing != NOTHING) {
     if (atr_comm_match
-        (thing, player, type, end, str, just_match, NULL, NULL, &errdb))
+        (thing, player, type, end, str, just_match, 1, NULL, NULL, &errdb))
       match = 1;
     else {
       MAYBE_ADD_ERRDB(errdb);
@@ -1648,7 +1647,7 @@ bind_and_queue(dbref player, dbref cause, char *action,
 /** Would the scan command find an matching attribute on x for player p? */
 #define ScanFind(p,x)  \
   (Can_Examine(p,x) && \
-      ((num = atr_comm_match(x, p, '$', ':', command, 1, atrname, &ptr, NULL)) != 0))
+      ((num = atr_comm_match(x, p, '$', ':', command, 1, 1, atrname, &ptr, NULL)) != 0))
 
 /** Scan for matches of $commands.
  * This function scans for possible matches of user-def'd commands from the
@@ -2305,44 +2304,80 @@ do_uptime(dbref player)
 }
 
 
-/* Open a db file, which may be compressed, and return a file pointer */
-static FILE *
-db_open(const char *filename)
+/* Open a db file, which may be compressed, and return a file pointer. These probably should be moved into db.c or 
+ a new dbio.c */
+static PENNFILE *
+db_open(const char *fname)
 {
-  FILE *f;
+  PENNFILE *pf;
+  char filename[BUFFER_LEN];
+
+  snprintf(filename, sizeof filename, "%s%s", fname, options.compresssuff);
+
+  pf = mush_malloc(sizeof *pf, "pennfile");
+
+#ifdef HAVE_LIBZ
+  if (*options.uncompressprog && strcmp(options.uncompressprog, "gunzip") == 0) {
+    pf->type = PFT_GZFILE;
+    pf->handle.g = gzopen(filename, "rb");
+    if (!pf->handle.g) {
+      mush_free(pf, "pennfile");
+      longjmp(db_err, 1);
+    }
+    return pf;
+  }
+#endif
+
 #ifndef WIN32
-  if (options.uncompressprog && *options.uncompressprog) {
+  if (*options.uncompressprog) {
+    pf->type = PFT_PIPE;
     /* We do this because on some machines (SGI Irix, for example),
      * the popen will not return NULL if the mailfile isn't there.
      */
-    f = fopen(tprintf("%s%s", filename, options.compresssuff), "r");
-    if (f) {
-      fclose(f);
-      f =
+
+    if (access(filename, R_OK) == 0) {
+      pf->handle.f =
 #ifdef __LCC__
         (FILE *)
 #endif
-        popen(tprintf
-              ("%s < %s%s", options.uncompressprog, filename,
-               options.compresssuff), "r");
+        popen(tprintf("%s < '%s'", options.uncompressprog, filename), "r");
       /* Force the pipe to be fully buffered */
-      if (f)
-        setvbuf(f, NULL, _IOFBF, BUFSIZ);
+      if (pf->handle.f) {
+        setvbuf(pf->handle.f, NULL, _IOFBF, BUFSIZ);
+      } else
+        do_rawlog(LT_ERR, "Unable to run '%s < %s': %s",
+                  options.uncompressprog, filename, strerror(errno));
+    } else {
+      mush_free(pf, "pennfile");
+      longjmp(db_err, 1);
     }
   } else
 #endif                          /* WIN32 */
   {
-    f = fopen(filename, FOPEN_READ);
+    pf->type = PFT_FILE;
+    pf->handle.f = fopen(filename, FOPEN_READ);
+#ifdef HAVE_POSIX_FADVISE
+    if (pf->handle.f)
+      posix_fadvise(fileno(pf->handle.f), 0, 0, POSIX_FADV_SEQUENTIAL);
+#endif
+
   }
-  return f;
+  if (!pf->handle.f) {
+    mush_free(pf, "pennfile");
+    longjmp(db_err, 1);
+  }
+  return pf;
 }
 
 /* Open a file or pipe (if compressing) for writing */
-static FILE *
-db_open_write(const char *filename)
+static PENNFILE *
+db_open_write(const char *fname)
 {
-  FILE *f;
+  PENNFILE *pf;
   char workdir[BUFFER_LEN];
+  char filename[BUFFER_LEN];
+
+  snprintf(filename, sizeof filename, "%s%s", fname, options.compresssuff);
 
   /* Be safe in case our game directory was removed and restored,
    * in which case our inode is screwy
@@ -2363,43 +2398,50 @@ db_open_write(const char *filename)
             "getcwd failed during db_open_write, errno %d (%s)\n",
             errno, strerror(errno));
   }
+
+  pf = mush_malloc(sizeof *pf, "pennfile");
+
+#ifdef HAVE_LIBZ
+  if (*options.compressprog && strcmp(options.compressprog, "gzip") == 0) {
+    pf->type = PFT_GZFILE;
+    pf->handle.g = gzopen(filename, "wb");
+    if (!pf->handle.g) {
+      mush_free(pf, "pennfile");
+      longjmp(db_err, 1);
+    }
+    return pf;
+  }
+#endif
+
 #ifndef WIN32
-  if (options.compressprog && *options.compressprog) {
-    f =
+  if (*options.compressprog) {
+    pf->type = PFT_PIPE;
+    pf->handle.f =
 #ifdef __LCC__
       (FILE *)
 #endif
-      popen(tprintf
-            ("%s >%s%s", options.compressprog, filename,
-             options.compresssuff), "w");
+      popen(tprintf("%s > '%s'", options.compressprog, filename), "w");
     /* Force the pipe to be fully buffered */
-    if (f)
-      setvbuf(f, NULL, _IOFBF, BUFSIZ);
+    if (pf->handle.f) {
+      setvbuf(pf->handle.f, NULL, _IOFBF, BUFSIZ);
+    } else
+      do_rawlog(LT_ERR, "Unable to run '%s > %s': %s",
+                options.compressprog, filename, strerror(errno));
+
   } else
 #endif                          /* WIN32 */
   {
-    f = fopen(filename, FOPEN_WRITE);
+    pf->type = PFT_FILE;
+    pf->handle.f = fopen(filename, "wb");
   }
-  if (!f)
+  if (!pf->handle.f) {
+    mush_free(pf, "pennfile");
     longjmp(db_err, 1);
-  return f;
-}
-
-
-/* Close a db file, which may really be a pipe */
-static void
-db_close(FILE * f)
-{
-#ifndef WIN32
-  if (options.compressprog && *options.compressprog) {
-    pclose(f);
-  } else
-#endif                          /* WIN32 */
-  {
-    fclose(f);
   }
+  return pf;
 }
 
+
 /** List various goodies.
  * \verbatim
  * This function implements @list.
index 30abcd3f8e268ce1f48f82049d5eba88fc29b7b0..efc269dfe673e908657112c98dc76aa3fa0eb317 100644 (file)
@@ -11,6 +11,7 @@
 #include <ctype.h>
 #include <stdio.h>
 #include <errno.h>
+#include <fcntl.h>
 #include "conf.h"
 #include "externs.h"
 #include "boolexp.h"
@@ -383,6 +384,10 @@ help_build_index(help_file *h, int restricted)
 
   in_topic = 0;
 
+#ifdef HAVE_POSIX_FADVISE
+  posix_fadvise(fileno(rfp), 0, 0, POSIX_FADV_SEQUENTIAL);
+#endif
+
   while (fgets(line, LINE_SIZE, rfp) != NULL) {
     ++lineno;
     if (ntopics == 0) {
index 42983805031feccf188bdcb31d5e76b5a2022dff..3f749956e56f3414eb011e7a6f92ceec7ad4732b 100644 (file)
@@ -48,6 +48,9 @@
 #ifdef HAVE_STDINT_H
 #include <stdint.h>
 #endif
+#ifdef HAS_OPENSSL
+#include <openssl/bn.h>
+#endif
 #include "conf.h"
 #include "externs.h"
 
@@ -263,7 +266,7 @@ penn_hash(const char *key, int len)
   return hash;
 }
 
-typedef uint32_t(*hash_func) (const char *, int);
+typedef uint32_t (*hash_func) (const char *, int);
 
 hash_func hash_functions[] = {
   hsieh_hash,
@@ -279,11 +282,39 @@ hash_func hash_functions[] = {
 enum { NHASH_TRIES = 3, NHASH_MOD = 8 };
 
 /* Return the next prime number after its arg */
-static int
-next_prime_after(int val)
+static unsigned int
+next_prime_after(unsigned int val)
 {
+#ifdef HAS_OPENSSL
+  /* Calculate primes on the fly using OpenSSL. Takes up less space
+     than using a table, deals better with pathologically large tables. */
+  static BIGNUM *p = NULL;
+  static BN_CTX *ctx = NULL;
+
+  if (!ctx)
+    ctx = BN_CTX_new();
+  if (!p)
+    p = BN_new();
+
+  /* Make sure we only try odd numbers; evens can't be primes. */
+  if (val & 0x1)
+    val += 2;
+  else
+    val += 1;
+
+  while (1) {
+    BN_set_word(p, val);
+    if (BN_is_prime(p, BN_prime_checks, NULL, ctx, NULL) > 0)
+      break;
+    val += 2;
+  }
+
+  return val;
+
+#else
+  /* For non-SSL systems; use a static table of primes that should be more than big enough. */
   /* Most of the first thousand primes */
-  static int primes[] = {
+  static unsigned int primes[] = {
     7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79,
     83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157,
     163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239,
@@ -382,6 +413,7 @@ next_prime_after(int val)
     return val + 1;
   else
     return primes[n];
+#endif
 }
 
 /** Initialize a hashtable.
@@ -460,7 +492,7 @@ hash_insert(HASHTAB *htab, const char *key, void *data)
     }
 
     /* None. Use a random func and bump the existing element */
-    n = htab->hashfunc_offset + get_random_long(0, NHASH_TRIES - 1);
+    n = htab->hashfunc_offset + get_random32(0, NHASH_TRIES - 1);
     n %= NHASH_MOD;
     hval = (hash_functions[n]) (bump.key, keylen) % htab->hashsize;
     temp = htab->buckets[hval];
index ef451c249206eb752ebf88518ca5380e7730c57f..4fa38d4eb5020c7cc29ff1cfec20d4499d384b1e 100644 (file)
@@ -20,7 +20,6 @@
 #ifdef I_SYS_TYPES
 #include <sys/types.h>
 #endif
-#include <time.h>
 #ifdef I_SYS_TIME
 #include <sys/time.h>
 #ifdef TIME_WITH_SYS_TIME
index 10bd2840d0c093276314ca91ccfa48bfdeab8bf9..552443e6ca1d0405f464bbf10c093340ce1bb5d1 100644 (file)
@@ -43,7 +43,6 @@
 #include "match.h"
 #include "log.h"
 #include "flags.h"
-#include "dbdefs.h"
 #include "mymalloc.h"
 #include "strtree.h"
 #include "privtab.h"
index abfd7f8cf9ab170f7f31d4eec56a74c5f2d82b83..e30c09bf0c31445b1fcdc6016e8b553b9e1df3e7 100644 (file)
--- a/src/log.c
+++ b/src/log.c
@@ -24,7 +24,6 @@
 #include <time.h>
 #endif
 #endif
-#include <time.h>
 #ifdef I_SYS_TYPES
 #include <sys/types.h>
 #endif
index 56eb82f23565519d22a119eb4d7085108aa494b1..bc2898d272fd38891167ab30273bc5b4b918ca4b 100644 (file)
@@ -8,7 +8,7 @@
 
 #include "config.h"
 #include "copyrite.h"
-
+#define _GNU_SOURCE
 #include <string.h>
 #include <ctype.h>
 
index a019a30c306395a4815007a7d457804aaa1d8380..2f4fff3c1f271e381fb5235c17abefc5c8c14f0c 100644 (file)
@@ -988,7 +988,7 @@ get_malias(dbref player, char *alias)
  * \param fp file pointer to read from.
  */
 void
-load_malias(FILE * fp)
+load_malias(PENNFILE *fp)
 {
   int i, j;
   char buffer[BUFFER_LEN];
@@ -1025,7 +1025,7 @@ load_malias(FILE * fp)
       m->members = NULL;
     }
   }
-  s = fgets(buffer, sizeof(buffer), fp);
+  s = penn_fgets(buffer, sizeof(buffer), fp);
 
   if (!s || strcmp(buffer, "\"*** End of MALIAS ***\"\n") != 0) {
     do_rawlog(LT_ERR, T("MAIL: Error reading MALIAS list"));
@@ -1036,7 +1036,7 @@ load_malias(FILE * fp)
  * \param fp file pointer to write to.
  */
 void
-save_malias(FILE * fp)
+save_malias(PENNFILE *fp)
 {
   int i, j;
   struct mail_alias *m;
index 0dead9f0d07811e5892f8e062f48b80ee62e3642..9710c24daae60a55ca4e19de1d5e47266b1958ea 100644 (file)
@@ -1587,7 +1587,7 @@ scramble_ansi_string(ansi_string *as)
     pos[i] = i;
 
   for (i = 0; i < as->len; i++) {
-    j = get_random_long(0, as->len - 1);
+    j = get_random32(0, as->len - 1);
     k = pos[i];
     pos[i] = pos[j];
     pos[j] = k;
index 58b66e8e9b9d28d267b2c1c3aad62a459a0c4893..08801c6b4ebf0e925cf75c8253ab8ee47b768cff 100644 (file)
@@ -240,8 +240,10 @@ match_result_internal(dbref who, const char *xname, int type, long flags)
 
   sname = name = mush_strdup(xname, "mri.string");
 
-  /* Check for adjective phrases */
-  matchnum = parse_english(&name, &flags);
+  if (flags & MAT_ENGLISH) {
+    /* Check for adjective phrases */
+    matchnum = parse_english(&name, &flags);
+  }
 
   /* Perform matching. We've already had flags restricted by any
    * adjective phrases. If matchnum is set, collect the matchnum'th
index 8ded5e23c24df8a5e473e632cdc0a8b19cac9442..4b5481ea02d82f4be4add95c662e4b34a09d5c31 100644 (file)
@@ -32,6 +32,8 @@
 #include <stddef.h>
 #include <limits.h>
 #include <assert.h>
+#include <errno.h>
+#include <string.h>
 #ifdef HAVE_UNISTD_H
 #include <unistd.h>
 #endif
 #include "getpgsiz.h"
 #include "mymalloc.h"
 
-/* An undefined or illegal MALLOC_PACKAGE is treated as system 
- * malloc, because we're such nice forgiving people
- */
-#if (MALLOC_PACKAGE == 1)
-#include "csrimalloc.c"
-#elif (MALLOC_PACKAGE == 2)
-#include "csrimalloc.c"
-#endif
-
-
 /** A malloc wrapper that tracks type of allocation.
  * This should be used in preference to malloc() when possible,
  * to enable memory leak tracing with MEM_CHECK.
@@ -256,22 +248,24 @@ static struct slab_page *
 slab_alloc_page(struct slab *sl)
 {
   struct slab_page *sp;
-  uint8_t *page;
+  uint8_t *page = NULL;
   int n;
+  int pgsize;
 
-#if defined(HAVE_VALLOC) && MALLOC_TYPE == 0
-  /* valloc() allocates on a page boundry. Many malloc()s do also,
-     but prefer this in case of one that implements valloc() without
-     malloc() having the same behavior for chunks the size of a page. 
+  pgsize = getpagesize();
 
-     TODO: Consider using mmap() or /dev/null instead, and adding an
-     access-pattern option that uses madvise() to give usage hints to
-     the VM system. That might only do any good on multi-page allocations,
-     though.
+#ifdef HAVE_POSIX_MEMALIGN
+  /* Used to use valloc() here, but on some systems, memory returned by
+     valloc() can't be passed to free(). Those same systems probably won't have
+     posix_memalign. Deal.
    */
-  page = valloc(getpagesize());
+  if (posix_memalign((void **) &page, pgsize, pgsize) < 0) {
+    do_rawlog(LT_ERR, "Unable to allocate %d bytes via posix_memalign: %s",
+              pgsize, strerror(errno));
+    page = malloc(pgsize);
+  }
 #else
-  page = malloc(getpagesize());
+  page = malloc(pgsize);
 #endif
 
   sp = (struct slab_page *) page;
@@ -551,7 +545,7 @@ slab_describe(dbref player, slab *sl)
 extern slab *attrib_slab, *lock_slab, *boolexp_slab, *bvm_asmnode_slab,
   *bvm_strnode_slab, *flag_slab, *player_dbref_slab,
   *command_slab,  *mail_slab,
-  *bque_slab, *text_block_slab, *function_slab, *memcheck_slab, *intmap_slab;
+  *text_block_slab, *function_slab, *memcheck_slab, *intmap_slab;
 #ifdef CHAT_SYSTEM 
 extern slab *chanuser_slab, *chanlist_slab, *channel_slab;
 #endif
@@ -569,7 +563,6 @@ do_list_allocations(dbref player)
     return;
   }
   slab_describe(player, attrib_slab);
-  slab_describe(player, bque_slab);
 #ifdef DEBUG
   /* These should always be 0. No need to display them most of the
      time. */
index 8de95d17276d6e5be029fd6236dcdc90bf63ecc9..10727e6560cfa13710f5bb4e79a44c02c6e18670 100644 (file)
@@ -13,9 +13,6 @@
 
 #include <stdio.h>
 #include <stdarg.h>
-#ifdef I_SYS_TYPES
-#include <sys/types.h>
-#endif
 #ifdef WIN32
 #define FD_SETSIZE 256
 #include <windows.h>
index 068a7827caf3bcdf9816a8f98ff521c73d88f669..4f96c20ec49b0d0524cc600d35a3117dceedbcb6 100644 (file)
@@ -105,8 +105,6 @@ static DH *get_dh1024(void);
 static BIO *bio_err = NULL;
 static SSL_CTX *ctx = NULL;
 
-uint32_t genrand_int32(void);
-
 /** Initialize the SSL context.
  * \return pointer to SSL context object.
  */
@@ -135,7 +133,7 @@ ssl_init(void)
     int n;
 
     for (n = 0; n < 4; n++)
-      gibberish[n] = genrand_int32();
+      gibberish[n] = gen_rand32();
 
     RAND_seed(gibberish, sizeof gibberish);
 
index 92e16ceb553dae672572ba2a39100be7c49d3ad5..487d44489dbdf92f832c52ad3dd90ddcdcd12bfd 100644 (file)
@@ -957,7 +957,7 @@ notify_anything_loc(dbref speaker, na_lookup func,
        && eval_lock(speaker, target, Listen_Lock)
       )
       atr_comm_match(target, speaker, '^', ':',
-                     (char *) notify_makestring(msgbuf, messages, NA_ASCII), 0,
+                     (char *) notify_makestring(msgbuf, messages, NA_ASCII), 0, 1,
                      NULL, NULL, NULL);
 
     /* If object is flagged AUDIBLE and has a @FORWARDLIST, send
index 022ea95193b3fe46570d076877e0008ec79a2b06..6b25ca18c429c0d50bf708461a38b6c88f79185e 100644 (file)
@@ -1516,18 +1516,18 @@ process_expression(char *buff, char **bp, char const **str,
               ATTR *attrib;
               global_fun_invocations++;
               pe_info->fun_invocations++;
-              thing = userfn_tab[fp->where.offset].thing;
-              attrib = atr_get(thing, userfn_tab[fp->where.offset].name);
+              thing = fp->where.ufun->thing;
+              attrib = atr_get(thing, fp->where.ufun->name);
               if (!attrib) {
                 do_rawlog(LT_ERR,
                           T("ERROR: @function (%s) without attribute (#%d/%s)"),
-                          fp->name, thing, userfn_tab[fp->where.offset].name);
+                          fp->name, thing, fp->where.ufun->name);
                 safe_str("#-1 @FUNCTION (", buff, bp);
                 safe_str(fp->name, buff, bp);
                 safe_str(") MISSING ATTRIBUTE (", buff, bp);
                 safe_dbref(thing, buff, bp);
                 safe_chr('/', buff, bp);
-                safe_str(userfn_tab[fp->where.offset].name, buff, bp);
+                safe_str(fp->where.ufun->name, buff, bp);
                 safe_chr(')', buff, bp);
               } else {
                 char *preserve[NUMQ];
index db6a6841c50b24aa6ee4f8bc8f6e18d420fcd015..f9d5f230c0315ce1eaf10a947d263b88cda10919 100644 (file)
@@ -1255,6 +1255,8 @@ int
 
 
 
+
+
 pcre_get_substring_list(const char *subject, int *ovector, int stringcount,
                         const char ***listptr);
 
@@ -1343,6 +1345,8 @@ int
 
 
 
+
+
 pcre_get_substring(const char *subject, int *ovector, int stringcount,
                    int stringnumber, const char **stringptr);
 
@@ -1398,6 +1402,8 @@ int
 
 
 
+
+
 pcre_get_named_substring(const pcre * code, const char *subject, int *ovector,
                          int stringcount, const char *stringname,
                          const char **stringptr);
@@ -2283,6 +2289,8 @@ static BOOL
 
 
 
+
+
 compile_regex(int, int, int *, uschar **, const uschar **, int *, BOOL, int,
               int *, int *, branch_chain *, compile_data *);
 
index e26391965232e46a6ea2e526ccb67baad54e652f..5fcd58b08915989bce4f614f9a48549065ab274a 100644 (file)
@@ -56,13 +56,13 @@ extern struct module_entry_t *module_list;
 dbref email_register_player
   (const char *name, const char *email, const char *host, const char *ip);
 static dbref make_player
-  (const char *name, const char *password, const char *host, const char *ip);
-static dbref create_guest(const char *host, const char *ip);
-void do_password
-  (dbref player, dbref cause, const char *old, const char *newobj);
-
-static const char pword_attr[] = "XYXXY";
-
+  (const char *name, const char *password, const char *host, const char *ip,
+   dbref try_dbref);
+void do_password(dbref player, dbref cause, const char *old,
+                 const char *newobj);
+ static const char pword_attr[] = "XYXXY";
+dbref create_guest(const char *host, const char *ip);
 extern struct db_stat_info current_state;
 
 /** Check a player's password against a given string.
@@ -221,7 +221,7 @@ dbref create_guest(const char *host, const char *ip) {
                 do_log(LT_CONN, 0, 0, T("Failed creation (no db space) from %s"), host);
                 return NOTHING;
           }
-          gst_id = make_player(guest_name, "", host, ip);
+          gst_id = make_player(guest_name, "", host, ip, NOTHING);
         } else  { /* Reset Guest */
                 object_flag_type flags;
                 flags = string_to_bits("FLAG", options.player_flags);
@@ -244,12 +244,13 @@ dbref create_guest(const char *host, const char *ip) {
  * \param password initial password of created player.
  * \param host host from which creation is attempted.
  * \param ip ip address from which creation is attempted.
+ * \param try_dbref NOTHING or dbref of garbage object to use.
  * \return dbref of created player, NOTHING if bad name, AMBIGUOUS if bad
  *  password.
  */
 dbref
 create_player(const char *name, const char *password, const char *host,
-              const char *ip)
+              const char *ip, dbref try_dbref)
 {
   dbref player;
   if (!ok_player_name(name, NOTHING, NOTHING)) {
@@ -266,7 +267,7 @@ create_player(const char *name, const char *password, const char *host,
     return NOTHING;
   }
   /* else he doesn't already exist, create him */
-  player = make_player(name, password, host, ip);
+  player = make_player(name, password, host, ip, try_dbref);
   SLEVEL(player) = LEVEL_UNREGISTERED;
   powergroup_db_set(NOTHING, player, PLAYER_DEF_POWERGROUP, 1);
   return player;
@@ -356,9 +357,9 @@ email_register_player(const char *name, const char *email, const char *host,
   }
 
   /* Come up with a random password of length 7-12 chars */
-  len = get_random_long(7, 12);
+  len = get_random32(7, 12);
   for (i = 0; i < len; i++)
-    passwd[i] = elems[get_random_long(0, NELEMS - 1)];
+    passwd[i] = elems[get_random32(0, NELEMS - 1)];
   passwd[len] = '\0';
 
   /* If we've made it here, we can send the email and create the
@@ -395,7 +396,7 @@ email_register_player(const char *name, const char *email, const char *host,
   pclose(fp);
   reserve_fd();
   /* Ok, all's well, make a player */
-  player = make_player(name, passwd, host, ip);
+  player = make_player(name, passwd, host, ip, NOTHING);
   (void) atr_add(player, "REGISTERED_EMAIL", email, GOD, 0);
   SLEVEL(player) = LEVEL_UNREGISTERED;
   powergroup_db_set(NOTHING, player, PLAYER_DEF_POWERGROUP, 1);
@@ -415,7 +416,7 @@ email_register_player(const char *name, const char *email, const char *host,
 
 static dbref
 make_player(const char *name, const char *password, const char *host,
-            const char *ip)
+            const char *ip, dbref try_dbref)
 {
 
   dbref player;
@@ -424,6 +425,11 @@ make_player(const char *name, const char *password, const char *host,
   struct module_entry_t *m;
   void (*handle)(dbref player);
 
+  if (try_dbref != NOTHING && GoodObject(try_dbref) && IsGarbage(try_dbref)) {
+    if (!make_first_free(try_dbref))
+      return NOTHING;
+  }
+
   player = new_object();
 
   /* initialize everything */
index eaefc5b2298970927bb0897f3a5b8f37a5b9af0a..d68683199956a153a75b990da9bfc54928a7d6a9 100644 (file)
@@ -6,6 +6,7 @@
 
 #include "config.h"
 #include <string.h>
+#include <ctype.h>
 #include <math.h>
 #include "conf.h"
 #include "externs.h"
@@ -172,7 +173,7 @@ loop:
   /* Pick something at random at swap it into the leftmost slot   */
   /* This is the pivot, we'll put it back in the right spot later */
 
-  i = get_random_long(left, right);
+  i = get_random32(left, right);
   tmp = array[i];
   array[i] = array[left];
   array[left] = tmp;
@@ -246,8 +247,6 @@ struct sort_record {
     dbref player __attribute__ ((__unused__)), \
     char *sortflags __attribute__ ((__unused__)))
 
-
-
 GENRECORD(gen_alphanum)
 {
   size_t len;
@@ -260,6 +259,91 @@ GENRECORD(gen_alphanum)
   }
 }
 
+#define RealGoodObject(x) (GoodObject(x) && !IsGarbage(x))
+
+GENRECORD(gen_magic)
+{
+  static char buff[BUFFER_LEN];
+  char *bp = buff;
+  char *s = rec->val;
+  int intval;
+  int numdigits;
+  dbref victim;
+
+  while (s && *s) {
+    switch (*s) {
+    case ESC_CHAR:
+      while (*s && *s != 'm')
+        s++;
+      break;
+    case TAG_START:
+      while (*s && *s != TAG_END)
+        s++;
+      break;
+    case '0':
+    case '1':
+    case '2':
+    case '3':
+    case '4':
+    case '5':
+    case '6':
+    case '7':
+    case '8':
+    case '9':
+      intval = 0;
+      while (*s && isdigit(*s)) {
+        intval *= 10;
+        intval += *s - '0';
+        s++;
+      }
+      safe_format(buff, &bp, "%.20d", intval);
+      if (*s == '.') {
+        s++;
+        if (isdigit(*s)) {
+          intval = 0;
+          numdigits = 0;
+          while (*s && isdigit(*s)) {
+            intval *= 10;
+            intval += *s - '0';
+            numdigits++;
+            s++;
+          }
+          safe_format(buff, &bp, "%d", intval);
+          numdigits = 20 - numdigits;
+          while (numdigits > 0) {
+            safe_chr('0', buff, &bp);
+            numdigits--;
+          }
+        }
+      }
+      break;
+    case NUMBER_TOKEN:
+      if (isdigit(*(s + 1))) {
+        s++;
+        victim = 0;
+        while (*s && isdigit(*s)) {
+          victim *= 10;
+          victim += *s - '0';
+          s++;
+        }
+        if (GoodObject(victim)) {
+          safe_str(Name(victim), buff, &bp);
+        } else {
+          safe_str("#-1 NO SUCH OBJECT VISIBLE", buff, &bp);
+        }
+        break;
+      }
+    default:
+      safe_chr(*s, buff, &bp);
+    }
+    if (*s)
+      s++;
+  }
+  *bp = '\0';
+  rec->memo.str.s = mush_strdup(buff, "genrecord");
+  rec->memo.str.freestr = 1;
+}
+
 GENRECORD(gen_dbref)
 {
   rec->memo.num = qparse_dbref(rec->val);
@@ -275,8 +359,6 @@ GENRECORD(gen_float)
   rec->memo.numval = parse_number(rec->val);
 }
 
-#define RealGoodObject(x) (GoodObject(x) && !IsGarbage(x))
-
 GENRECORD(gen_db_name)
 {
   rec->memo.str.s = (char *) "";
@@ -466,6 +548,7 @@ char INSENS_ALPHANUM_LIST[] = "I";
 char DBREF_LIST[] = "D";
 char NUMERIC_LIST[] = "N";
 char FLOAT_LIST[] = "F";
+char MAGIC_LIST[] = "M";
 char DBREF_NAME_LIST[] = "NAME";
 char DBREF_NAMEI_LIST[] = "NAMEI";
 char DBREF_IDLE_LIST[] = "IDLE";
@@ -484,6 +567,7 @@ list_type_list ltypelist[] = {
   {DBREF_LIST, gen_dbref, i_comp, 0},
   {NUMERIC_LIST, gen_num, i_comp, 0},
   {FLOAT_LIST, gen_float, f_comp, 0},
+  {MAGIC_LIST, gen_magic, si_comp, 0},
   {DBREF_NAME_LIST, gen_db_name, si_comp, IS_DB | IS_STRING},
   {DBREF_NAMEI_LIST, gen_db_name, si_comp, IS_DB | IS_STRING},
   {DBREF_IDLE_LIST, gen_db_idle, i_comp, IS_DB},
index a166b64d25818a3866f67c1d164bcbd8f6dad930..77145d586887f2362eba3d750fe4489903d74412 100644 (file)
@@ -358,7 +358,7 @@ do_whisper(dbref player, const char *arg1, const char *arg2, int noisy)
   tp = tbuf;
   safe_str(T(" to "), tbuf, &tp);
   for (who = 0; who < gcount; who++) {
-    if (noisy && (get_random_long(0, 100) < WHISPER_LOUDNESS))
+    if (noisy && (get_random32(0, 100) < (uint32_t) WHISPER_LOUDNESS))
       overheard = 1;
     safe_itemizer(who + 1, (who == gcount - 1), ",", T("and"), " ", tbuf, &tp);
     safe_str(Name(good[who]), tbuf, &tp);
@@ -710,8 +710,8 @@ messageformat(dbref player, const char *attribute, dbref enactor, int flags,
   static char messbuff[BUFFER_LEN];
 
   *messbuff = '\0';
-  if (!call_attrib(player, attribute, (const char **) argv, numargs,
-                   messbuff, enactor, NULL)) {
+  if (call_attrib(player, attribute, (const char **) argv, numargs,
+                  messbuff, enactor, NULL)) {
     /* We have a returned value. Notify the player. */
     if (*messbuff)
       notify_anything(enactor, na_one, &player, ns_esnotify, flags, messbuff);
index e483bf9795f69fe896ee9f5d1e706a4886ef0e6a..e432d270a8a446245725c7748d0c4d8c9c5b1cea 100644 (file)
@@ -40,49 +40,6 @@ signed char qreg_indexes[256] = {
  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
 };
 
-char from_base_64[256] = {
-  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, 62, -1, 63,
-  52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1,
-  -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
-  15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, 63,
-  -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
-  41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1,
-  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
-};
-
-char to_base_64[] =
-  "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
-
-char from_base_36[256] = {
-  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-  0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1,
-  -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
-  25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1,
-  -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
-  25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1,
-  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
-};
-
-char to_base_36[] = "0123456789abcdefghijklmnopqrstuvwxyz";
-
 char active_table[256] = {
   1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
   0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  0,  0,  0,  0,
@@ -197,6 +154,25 @@ char valid_ansi_codes[256] = {
   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
 };
 
+char soundex_val[256] = {
+  48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
+  48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
+  48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
+  48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
+  48, 48, 49, 50, 51, 48, 49, 50, 48, 48, 50, 50, 52, 53, 53, 48,
+  49, 50, 54, 50, 51, 48, 49, 48, 50, 48, 50, 48, 48, 48, 48, 48,
+  48, 48, 49, 50, 51, 48, 49, 50, 48, 48, 50, 50, 52, 53, 53, 48,
+  49, 50, 54, 50, 51, 48, 49, 48, 50, 48, 50, 48, 48, 48, 48, 48,
+  48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
+  48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
+  48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
+  48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
+  48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
+  48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
+  48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
+  48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48
+};
+
 typedef struct {
 const char *base;
 const char *entity;
@@ -362,7 +338,7 @@ accent_info accent_table[256] = {
 {NULL, NULL},
 {NULL, NULL},
 {NULL, NULL},
-{" ", "&nbsp;"},
+{NULL, NULL},
 {"!", "&iexcl;"},
 {NULL, NULL},
 {NULL, NULL},
index caefcdbf84722242260aedf9b595992275767201..c6b169f8da3a9572c5ae766e21704fc12f1ac4d3 100644 (file)
@@ -48,6 +48,7 @@
 #include "attrib.h"
 #include "parse.h"
 #include "lock.h"
+#include "SFMT.h"
 #include "modules.h"
 
 
@@ -55,9 +56,6 @@ extern struct module_entry_t *module_list;
 
 dbref find_entrance(dbref door);
 void initialize_mt(void);
-uint32_t genrand_int32(void);
-static void init_genrand(unsigned long);
-static void init_by_array(unsigned long *, int);
 extern int local_can_interact_first(dbref from, dbref to, int type);
 extern int local_can_interact_last(dbref from, dbref to, int type);
 
@@ -305,8 +303,8 @@ call_ufun(ufun_attrib * ufun, char **wenv_args, int wenv_argc, char *ret,
  * of the process_expression are stored in.
  * \param enactor The enactor.
  * \param pe_info The pe_info passed to the FUNCTION
- * \retval 0 success
- * \retval 1 No such attribute, or failed.
+ * \retval 1 success
+ * \retval 0 No such attribute, or failed.
  */
 bool
 call_attrib(dbref thing, const char *attrname, const char *wenv_args[],
@@ -327,22 +325,22 @@ call_attrib(dbref thing, const char *attrname, const char *wenv_args[],
 
   /* Make sure we have a valid object to call first */
   if (!GoodObject(thing) || IsGarbage(thing))
-    return 1;
+    return 0;
 
   if (attrname == NULL || !*attrname)
-    return 1;
+    return 0;
 
   /* Fetch the attrib contents */
   attrib = (ATTR *) atr_get(thing, attrname);
   if (attrib == NULL)
-    return 1;
+    return 0;
 
   mush_strncpy(atrbuf, atr_value(attrib), BUFFER_LEN);
 
   if (!*atrbuf) {
     if (ret)
       *ret = '\0';
-    return 0;
+    return 1;
   }
 
   save_global_regs("localize", saver);
@@ -402,7 +400,7 @@ call_attrib(dbref thing, const char *attrname, const char *wenv_args[],
   restore_regexp_context(&rsave);
   restore_global_regs("localize", saver);
 
-  return pe_ret;
+  return !pe_ret;
 }
 
 /** Given an exit, find the room that is its source through brute force.
@@ -542,29 +540,18 @@ reverse(dbref list)
 }
 
 
-#define N 624 /**< PRNG constant */
-
-/* We use the Mersenne Twister PRNG. It's quite good as PRNGS go,
- * much better than the typical ones provided in system libc's.
- *
- * The following two functions are based on the reference implementation,
- * with changes in the seeding function to use /dev/urandom as a seed
- * if possible.
- *
- * The Mersenne Twister homepage is:
- *  http://www.math.keio.ac.jp/~matumoto/emt.html
- *
- * You can get the reference code there.
- */
-
 
-/** Wrapper to choose a seed and initialize the Mersenne Twister PRNG. */
+/** Wrapper to choose a seed and initialize the Mersenne Twister PRNG. 
+ * The actual MT code lives in SFMT.c and hdrs/SFMT*.h */
 void
 initialize_mt(void)
 {
 #ifdef HAS_DEV_URANDOM
   int fd;
-  unsigned long buf[N];
+  uint32_t buf[4];              /* The linux manpage for /dev/urandom
+                                   advises against reading large amounts of
+                                   data from it; we used to read 624*4 (Or *8 on 64-bit systems)
+                                   bytes. The new figure is much more reasonable. */
 
   fd = open("/dev/urandom", O_RDONLY);
   if (fd >= 0) {
@@ -585,134 +572,13 @@ initialize_mt(void)
 #endif
   /* Default seeder. Pick a seed that's fairly random */
 #ifdef WIN32
-  init_genrand(GetCurrentProcessId() | (time(NULL) << 16));
+  init_gen_rand(GetCurrentProcessId() | (time(NULL) << 16));
 #else
-  init_genrand(getpid() | (time(NULL) << 16));
+  init_gen_rand(getpid() | (time(NULL) << 16));
 #endif
 }
 
 
-/* A C-program for MT19937, with initialization improved 2002/1/26.*/
-/* Coded by Takuji Nishimura and Makoto Matsumoto.                 */
-
-/* Before using, initialize the state by using init_genrand(seed)  */
-/* or init_by_array(init_key, key_length).                         */
-
-/* This library is free software.                                  */
-/* This library is distributed in the hope that it will be useful, */
-/* but WITHOUT ANY WARRANTY; without even the implied warranty of  */
-/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.            */
-
-/* Copyright (C) 1997, 2002 Makoto Matsumoto and Takuji Nishimura. */
-/* Any feedback is very welcome.                                   */
-/* http://www.math.keio.ac.jp/matumoto/emt.html                    */
-/* email: matumoto@math.keio.ac.jp                                 */
-
-/* Period parameters */
-#define M 397  /**< PRNG constant */
-#define MATRIX_A 0x9908b0dfUL   /**< PRNG constant vector a */
-#define UPPER_MASK 0x80000000UL /**< PRNG most significant w-r bits */
-#define LOWER_MASK 0x7fffffffUL /**< PRNG least significant r bits */
-
-static unsigned long mt[N];     /* the array for the state vector  */
-static int mti = N + 1;         /* mti==N+1 means mt[N] is not initialized */
-
-/** initializes mt[N] with a seed.
- * \param a seed value.
- */
-static void
-init_genrand(unsigned long s)
-{
-  mt[0] = s & 0xffffffffUL;
-  for (mti = 1; mti < N; mti++) {
-    mt[mti] = (1812433253UL * (mt[mti - 1] ^ (mt[mti - 1] >> 30)) + mti);
-    /* See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier. */
-    /* In the previous versions, MSBs of the seed affect   */
-    /* only MSBs of the array mt[].                        */
-    /* 2002/01/09 modified by Makoto Matsumoto             */
-    mt[mti] &= 0xffffffffUL;
-    /* for >32 bit machines */
-  }
-}
-
-/** initialize by an array with array-length
- * \param init_key the array for initializing keys 
- * \param key_length the array's length 
- */
-static void
-init_by_array(unsigned long init_key[], int key_length)
-{
-  int i, j, k;
-  init_genrand(19650218UL);
-  i = 1;
-  j = 0;
-  k = (N > key_length ? N : key_length);
-  for (; k; k--) {
-    mt[i] = (mt[i] ^ ((mt[i - 1] ^ (mt[i - 1] >> 30)) * 1664525UL))
-      + init_key[j] + j;        /* non linear */
-    mt[i] &= 0xffffffffUL;      /* for WORDSIZE > 32 machines */
-    i++;
-    j++;
-    if (i >= N) {
-      mt[0] = mt[N - 1];
-      i = 1;
-    }
-    if (j >= key_length)
-      j = 0;
-  }
-  for (k = N - 1; k; k--) {
-    mt[i] = (mt[i] ^ ((mt[i - 1] ^ (mt[i - 1] >> 30)) * 1566083941UL))
-      - i;                      /* non linear */
-    mt[i] &= 0xffffffffUL;      /* for WORDSIZE > 32 machines */
-    i++;
-    if (i >= N) {
-      mt[0] = mt[N - 1];
-      i = 1;
-    }
-  }
-
-  mt[0] = 0x80000000UL;         /* MSB is 1; assuring non-zero initial array */
-}
-
-/* generates a random number on [0,0xffffffff]-interval */
-uint32_t
-genrand_int32(void)
-{
-  unsigned long y;
-  static unsigned long mag01[2] = { 0x0UL, MATRIX_A };
-  /* mag01[x] = x * MATRIX_A  for x=0,1 */
-
-  if (mti >= N) {               /* generate N words at one time */
-    int kk;
-
-    if (mti == N + 1)           /* if init_genrand() has not been called, */
-      init_genrand(5489UL);     /* a default initial seed is used */
-
-    for (kk = 0; kk < N - M; kk++) {
-      y = (mt[kk] & UPPER_MASK) | (mt[kk + 1] & LOWER_MASK);
-      mt[kk] = mt[kk + M] ^ (y >> 1) ^ mag01[y & 0x1UL];
-    }
-    for (; kk < N - 1; kk++) {
-      y = (mt[kk] & UPPER_MASK) | (mt[kk + 1] & LOWER_MASK);
-      mt[kk] = mt[kk + (M - N)] ^ (y >> 1) ^ mag01[y & 0x1UL];
-    }
-    y = (mt[N - 1] & UPPER_MASK) | (mt[0] & LOWER_MASK);
-    mt[N - 1] = mt[M - 1] ^ (y >> 1) ^ mag01[y & 0x1UL];
-
-    mti = 0;
-  }
-
-  y = mt[mti++];
-
-  /* Tempering */
-  y ^= (y >> 11);
-  y ^= (y << 7) & 0x9d2c5680UL;
-  y ^= (y << 15) & 0xefc60000UL;
-  y ^= (y >> 18);
-
-  return y;
-}
-
 
 /** Get a uniform random long between low and high values, inclusive.
  * Based on MUX's RandomINT32()
@@ -720,10 +586,10 @@ genrand_int32(void)
  * \param high upper bound for random number.
  * \return random number between low and high, or 0 or -1 for error.
  */
-long
-get_random_long(long low, long high)
+uint32_t
+get_random32(uint32_t low, uint32_t high)
 {
-  unsigned long x, n, n_limit;
+  uint32_t x, n, n_limit;
 
   /* Validate parameters */
   if (high < low) {
@@ -732,11 +598,7 @@ get_random_long(long low, long high)
     return low;
   }
 
-  x = high - low;
-  if (LONG_MAX < x) {
-    return -1;
-  }
-  x++;
+  x = high - low + 1;
 
   /* We can now look for an random number on the interval [0,x-1].
      //
@@ -755,10 +617,10 @@ get_random_long(long low, long high)
      // we will call getrand() is less than 2.
    */
 
-  n_limit = ULONG_MAX - (ULONG_MAX % x);
+  n_limit = UINT32_MAX - (UINT32_MAX % x);
 
   do {
-    n = genrand_int32();
+    n = gen_rand32();
   } while (n >= n_limit);
 
   return low + (n % x);
index 0a364aeffcb69cf5a27ea34ebad21b8001914172..ec9de19695a4e7966036c8490422e24b938f0b68 100644 (file)
@@ -41,6 +41,5 @@ do_version(player)
   notify_format(player, T("Build date: %s"), BUILDDATE);
   notify_format(player, T("Compiler: %s"), COMPILER);
   notify_format(player, T("Compilation flags: %s"), CCFLAGS);
-  notify_format(player, T("Malloc package: %d"), MALLOC_PACKAGE);
 #endif
 }
index 4170f693f2c0734ec0df4a502d25e80c0bf77146..0dea11d18cd9f00a4af427f908d9c211f00f8042 100644 (file)
 /** Maximum number of wildcarded arguments */
 #define NUMARGS (10)
 
+/** Skip across all ansi and pueblo markup. */
+#define SKIP_ANSI(x) do { \
+      if (*x == TAG_START) { \
+        while (*x && (*x != TAG_END)) x++; \
+        if (*x) x++; \
+      } else if (*x == ESC_CHAR) { \
+        while (*x && (*x != 'm')) x++; \
+        if (*x) x++; \
+      } \
+  } while ((*x == TAG_START) || (*x == ESC_CHAR))
+
 const unsigned char *tables = NULL;  /** Pointer to character tables */
 
 static bool wild1
@@ -89,6 +100,7 @@ bool
 quick_wild_new(const char *restrict tstr, const char *restrict dstr, bool cs)
 {
   while (*tstr != '*') {
+    SKIP_ANSI(dstr);
     switch (*tstr) {
     case '?':
       /* Single character match.  Return false if at
@@ -129,6 +141,7 @@ quick_wild_new(const char *restrict tstr, const char *restrict dstr, bool cs)
       if (!*dstr)
         return 0;
       dstr++;
+      SKIP_ANSI(dstr);
     }
     tstr++;
   }
@@ -146,6 +159,7 @@ quick_wild_new(const char *restrict tstr, const char *restrict dstr, bool cs)
     if (EQUAL(cs, *dstr, *tstr) && quick_wild_new(tstr + 1, dstr + 1, cs))
       return 1;
     dstr++;
+    SKIP_ANSI(dstr);
   }
   return 0;
 }
@@ -172,6 +186,7 @@ atr_wild(const char *restrict tstr, const char *restrict dstr)
     return !strchr(dstr, '`');
 
   while (*tstr != '*') {
+    SKIP_ANSI(dstr);
     switch (*tstr) {
     case '?':
       /* Single character match.  Return false if at
@@ -216,6 +231,7 @@ atr_wild(const char *restrict tstr, const char *restrict dstr)
       if (!*dstr || *dstr == '`')
         return 0;
       dstr++;
+      SKIP_ANSI(dstr);
       starcount = 0;
     } else
       starcount++;
@@ -236,6 +252,7 @@ atr_wild(const char *restrict tstr, const char *restrict dstr)
       if (*dstr != '`' && atr_wild(tstr + 1, dstr + 1))
         return 1;
       dstr++;
+      SKIP_ANSI(dstr);
     }
   } else {
     /* Skip over a backslash in the pattern string if it is there. */
@@ -253,6 +270,7 @@ atr_wild(const char *restrict tstr, const char *restrict dstr)
       if (starcount < 2 && *dstr == '`')
         return 0;
       dstr++;
+      SKIP_ANSI(dstr);
     }
   }
   return 0;
@@ -275,6 +293,7 @@ wild1(const char *restrict tstr, const char *restrict dstr, int arg,
   int argpos, numextra;
 
   while (*tstr != '*') {
+    SKIP_ANSI(dstr);
     switch (*tstr) {
     case '?':
       /* Single character match.  Return false if at
@@ -354,6 +373,7 @@ wild1(const char *restrict tstr, const char *restrict dstr, int arg,
           *(*wbuf)++ = '\0';
           *len -= 2;
         }
+        SKIP_ANSI(datapos);
 
         /* Jump to the fast routine if we can. */
         if (argpos >= (int) max || *len < 1)
@@ -371,6 +391,7 @@ wild1(const char *restrict tstr, const char *restrict dstr, int arg,
         return 0;
       tstr++;
       dstr++;
+      SKIP_ANSI(dstr);
       arg++;
       numextra++;
     }
@@ -383,10 +404,12 @@ wild1(const char *restrict tstr, const char *restrict dstr, int arg,
   /* Check for possible matches.  This loop terminates either at
    * end of data (resulting in failure), or at a successful match.
    */
-  if (!*tstr)
-    while (*dstr)
+  if (!*tstr) {
+    while (*dstr) {
       dstr++;
-  else {
+      SKIP_ANSI(dstr);
+    }
+  } else {
     while (1) {
       if (EQUAL(cs, *dstr, *tstr) &&
           ((arg < (int) max) ? wild1(tstr, dstr, arg, wbuf, len, cs, ary, max)
@@ -395,6 +418,7 @@ wild1(const char *restrict tstr, const char *restrict dstr, int arg,
       if (!*dstr)
         return 0;
       dstr++;
+      SKIP_ANSI(dstr);
     }
   }
 
@@ -411,6 +435,7 @@ wild1(const char *restrict tstr, const char *restrict dstr, int arg,
       *(*wbuf)++ = '\0';
       *len -= datalen + 1;
       datapos = dstr - numextra;
+      SKIP_ANSI(datapos);
     }
   }
 
@@ -425,6 +450,7 @@ wild1(const char *restrict tstr, const char *restrict dstr, int arg,
       *len -= 2;
       numextra--;
     }
+    SKIP_ANSI(datapos);
   }
 
   /* It's done! */
@@ -447,6 +473,7 @@ wild(const char *restrict s, const char *restrict d, int p, bool cs,
   /* Do fast match to see if pattern matches. If yes, do it again,
      remembering this time.. */
   while ((*s != '*') && (*s != '?')) {
+    SKIP_ANSI(d);
     if (*s == '\\')
       s++;
     if (NOTEQUAL(cs, *d, *s))
@@ -708,7 +735,10 @@ check_literals(const char *restrict tstr, const char *restrict dstr, bool cs)
   char dbuf1[BUFFER_LEN];
   const char delims[] = "?*";
   char *sp, *dp;
-  mush_strncpy(dbuf1, dstr, BUFFER_LEN);
+  size_t len = 0;
+
+  dp = remove_markup(dstr, &len);
+  memcpy(dbuf1, dp, len);
   mush_strncpy(tbuf1, strip_backslashes(tstr), BUFFER_LEN);
   if (!cs) {
     upcasestr(tbuf1);
@@ -717,7 +747,7 @@ check_literals(const char *restrict tstr, const char *restrict dstr, bool cs)
   dp = dbuf1;
   sp = strtok(tbuf1, delims);
   while (sp) {
-    if (!dp)
+    if (!dp || !*dp)
       return 0;
     if (!(dp = strstr(dp, sp)))
       return 0;
index 73473d2ccb720b0ce25e116ae2f2c376b2b95dc1..6470e5cf794e3d29d1fd4a8ff2c2d32ae2ccbc8a 100644 (file)
--- a/src/wiz.c
+++ b/src/wiz.c
@@ -80,6 +80,8 @@ struct search_spec {
   int count;  /**< Limited results: return this many */
   int end;    /**< Limited results: return until this one.*/
   boolexp lock;  /**< Boolexp to check against the objects. */
+  char cmdstring[BUFFER_LEN];
+  char listenstring[BUFFER_LEN];
 };
 
 int tport_dest_ok(dbref player, dbref victim, dbref dest);
@@ -104,10 +106,12 @@ extern char errlog[BUFFER_LEN];
  * \param creator the enactor.
  * \param player_name name of player to create.
  * \param player_password password for player.
+ * \param try_dbref if non-empty, the garbage object to use for the new player.
  * \return dbref of created player object, or NOTHING if failure.
  */
 dbref
-do_pcreate(dbref creator, const char *player_name, const char *player_password)
+do_pcreate(dbref creator, const char *player_name, const char *player_password,
+           const char *try_dbref)
 {
   dbref player;
 
@@ -117,7 +121,13 @@ do_pcreate(dbref creator, const char *player_name, const char *player_password)
   }
   if (!can_pay_fees(creator, 0))
     return NOTHING;
-  player = create_player(player_name, player_password, "None", "None");
+
+  if (try_dbref && *try_dbref)
+    player = parse_dbref(try_dbref);
+  else
+    player = NOTHING;
+
+  player = create_player(player_name, player_password, "None", "None", player);
   if (player == NOTHING) {
     notify_format(creator, T("Failure creating '%s' (bad name)"), player_name);
     return NOTHING;
@@ -1752,6 +1762,8 @@ fill_search_spec(dbref player, const char *owner, int nargs, const char **args,
   spec->start = 1;              /* 1-indexed */
   spec->count = 0;
   spec->lock = TRUE_BOOLEXP;
+  strcpy(spec->cmdstring, "");
+  strcpy(spec->listenstring, "");
 
   /* set limits on who we search */
   if (!owner || !*owner || strcasecmp(owner, "all") == 0)
@@ -1938,6 +1950,10 @@ fill_search_spec(dbref player, const char *owner, int nargs, const char **args,
       spec->lock = parse_boolexp(player, restriction, "Search");
     } else if (string_prefix("eval", class)) {
       strcpy(spec->eval, restriction);
+    } else if (string_prefix("command", class)) {
+      strcpy(spec->cmdstring, restriction);
+    } else if (string_prefix("listen", class)) {
+      strcpy(spec->listenstring, restriction);
     } else if (string_prefix("ethings", class) ||
                string_prefix("eobjects", class)) {
       strcpy(spec->eval, restriction);
@@ -1996,6 +2012,9 @@ raw_search(dbref player, const char *owner, int nargs, const char **args,
   int n;
   struct search_spec spec;
   int count = 0;
+  int ret = 0;
+  ATTR *a;
+  char lbuff[BUFFER_LEN];
 
   /* make sure player has money to do the search */
   if (!payfor(player, FIND_COST)) {
@@ -2064,6 +2083,27 @@ raw_search(dbref player, const char *owner, int nargs, const char **args,
     }
     if(spec.lock != TRUE_BOOLEXP && !eval_boolexp(n, spec.lock, player, NULL))
       continue;
+    if (spec.cmdstring[0] &&
+        !atr_comm_match(n, player, '$', ':', spec.cmdstring, 1, 0,
+                        NULL, NULL, NULL))
+      continue;
+    if (spec.listenstring[0]) {
+      ret = 0;
+      /* do @listen stuff */
+      a = atr_get_noparent(n, "LISTEN");
+      if (a) {
+        strcpy(lbuff, atr_value(a));
+        ret = AF_Regexp(a)
+          ? regexp_match_case_r(lbuff, spec.listenstring,
+                                AF_Case(a), NULL, 0, NULL, 0)
+          : wild_match_case_r(lbuff, spec.listenstring,
+                              AF_Case(a), NULL, 0, NULL, 0);
+      }
+      if (!ret &&
+          !atr_comm_match(n, player, '^', ':', spec.listenstring, 1, 0,
+                          NULL, NULL, NULL))
+        continue;
+    }
     if (*spec.eval) {
       char *ebuf1;
       const char *ebuf2;
index 8bf8e29e6a390310cd36ecfa185d34edff336953..df46cace7f9d8bcea05e6e6abc7efee27ab60b90 100644 (file)
@@ -68,7 +68,7 @@ sub start {
   } elsif (defined($child)) {
     chdir("testgame");
     my @execargs = ("./netmush", "--no-session", "test.cnf");
-    unshift @execargs, "valgrind", '--log-file=../valgrind-%p.log'
+    unshift @execargs, "valgrind", "--tool=memcheck", '--log-file=../valgrind-%p.log', "--leak-check=full"
        if $self->{VALGRIND};
     exec @execargs;
   } else {
index 1b14e46e2858c5d9d8fe036696b6612bd5d69e7e..90b2587d3da82a5efefea4acc97dfb17f5ad6797 100644 (file)
@@ -2,11 +2,11 @@ expect 2 failures!
 run tests:
 test('hastype.1', $god, 'think hastype(#0, room)', ['1', '!#-1']);
 test('hastype.2', $god, 'think hastype(#1, player)', ['1', '!#-1']);
-test('hastype.3', $god, '@create foo', []);
-test('hastype.4', $god, 'think hastype(foo, thing)', ['1', '!#-1']);
-test('hastype.5', $god, '@rec foo', []);
-test('hastype.6', $god, '@rec foo', []);
-test('hastype.7', $god, 'think hastype(#3, garbage)', ['1', '!#-1']);
-test('hastype.8', $god, '@open foo', []);
-test('hastype.9', $god, 'think hastype(#3, exit)', ['1', '!#-1']);
+$god->command('@create foo');
+test('hastype.3', $god, 'think hastype(foo, thing)', ['1', '!#-1']);
+$god->command('@rec foo');
+$god->command('@rec foo');
+test('hastype.4', $god, 'think hastype(#3, garbage)', ['1', '!#-1']);
+$god->command('@open foo');
+test('hastype.5', $god, 'think hastype(#3, exit)', ['1', '!#-1']);
 
index b6e9d39618a0edb6384ce6acac0702fce9212ba6..bacc396d913f6e81384d167711504d789afb9d59 100644 (file)
@@ -117,6 +117,17 @@ char ansi_codes[UCHAR_MAX + 1] = {
   ['/'] = 1, ['a'] = 1
 };
 
+/* Values used in soundex hashing */
+char soundex_codes[UCHAR_MAX + 1] = {
+  ['B'] = 1, ['P'] = 1, ['F'] = 1, ['V'] = 1, ['b'] = 1, ['p'] = 1, ['f'] = 1, ['v'] = 1,
+  ['C'] = 2, ['G'] = 2, ['J'] = 2, ['K'] = 2, ['Q'] = 2, ['S'] = 2, ['X'] = 2, ['Z'] = 2,
+  ['c'] = 2, ['g'] = 2, ['j'] = 2, ['k'] = 2, ['q'] = 2, ['s'] = 2, ['x'] = 2, ['z'] = 2,
+  ['D'] = 3, ['T'] = 3, ['d'] = 3, ['t'] = 3,
+  ['L'] = 4, ['l'] = 4,
+  ['M'] = 5, ['N'] = 5, ['m'] = 5, ['n'] = 5,
+  ['R'] = 6, ['r'] = 6
+};
+
 /** Accented characters 
  *
  * The table is for ISO 8859-1 character set.
@@ -265,6 +276,7 @@ void print_entity_table(const char *name,
 }
 
 
+
 int main(int argc, char *argv[]) {
   printf("/* This file was generated by running %s compiled from\n"
         " * %s. Edit that file, not this one, when making changes. */\n"
@@ -276,6 +288,7 @@ int main(int argc, char *argv[]) {
   print_table_bool("char", "valid_timefmt_codes", valid_timefmt_codes, 0);
   print_table_bool("char", "escaped_chars", escaped_chars, 0);
   print_table_bool("char", "valid_ansi_codes", ansi_codes, 0);
+  print_table_bool("char", "soundex_val", soundex_codes, '0');
   print_entity_table("accent_table", entity_table);
   return EXIT_SUCCESS;
 }