PennMUSH 182p5 Incorporation
authorRick Bird <nveid@bender.theari.com>
Sat, 26 Mar 2011 18:10:14 +0000 (14:10 -0400)
committerRick Bird <nveid@bender.theari.com>
Sat, 26 Mar 2011 18:10:14 +0000 (14:10 -0400)
  * Removed the gmalloc malloc option. [SW]
  * Assorted gcc warning fixes. [SW]
  * Cleaned up some unsafe signal handler functions. [SW]

game/txt/hlp/cobra_func.hlp
hdrs/externs.h
hdrs/pcre.h
src/Makefile.SH
src/access.c
src/attrib.c
src/bsd.c
src/notify.c
src/strutil.c
src/wild.c
src/wiz.c

index 6b2e5147afbd050da84939fb37b20226a796e57b..12c1c71826bd2deaa427233ec51ead20ffe3ef27 100644 (file)
@@ -1890,7 +1890,8 @@ See also: first(), rest()
   Returns a space-separated list of the attribute names on the object
   that you are permitted to examine. To see the complete list, own the 
   object, have the See_All power over the object, or have the object set 
-  VISUAL in order to use this function on the object.
+  VISUAL and pass its examine lock in order to use this function on the 
+  object.
   
   If a wildcarded attribute pattern is provided, only attribute names
   matching that pattern will be returned. lattr() uses the same
index f95f84187e816b5b825931716cbbf55a8234dc85..a05905c1cbd5f9fed2beaa0fe16445b233683102 100644 (file)
@@ -534,7 +534,8 @@ extern int safe_ansi_string2(ansi_string *as, size_t start, size_t len, char *bu
                           char **bp);
 
    extern char *str_escaped_chr(const char *RESTRICT string, char escape_chr);
-    extern char *replace_string
+   extern char *mush_strncpy(char *restrict, const char *, size_t);
+   extern char *replace_string
       (const char *RESTRICT old, const char *RESTRICT newbit,
        const char *RESTRICT string) __attribute_malloc__;
     extern char *replace_string2(const char *old[2], const char *newbits[2],
@@ -623,18 +624,15 @@ extern int safe_ansi_string2(ansi_string *as, size_t start, size_t len, char *bu
     extern int wildcard(const char *s);
     extern int quick_wild_new(const char *RESTRICT tstr,
                              const char *RESTRICT dstr, int cs);
-    extern int regexp_match_case(const char *RESTRICT s, const char *RESTRICT d,
-                                int cs);
+    extern int regexp_match_case_r(const char *RESTRICT s,
+                                  const char *RESTRICT d, int cs, char **, int,
+                                  char *, int);
     extern int quick_regexp_match(const char *RESTRICT s,
                                  const char *RESTRICT d, int cs);
-    extern int wild_match_case(const char *RESTRICT s, const char *RESTRICT d,
-                              int cs);
+    extern int wild_match_case_r(const char *RESTRICT s, const char *RESTRICT d,
+                                int cs, char **, int, char *, int);
     extern int quick_wild(const char *RESTRICT tsr, const char *RESTRICT dstr);
     extern int atr_wild(const char *RESTRICT tstr, const char *RESTRICT dstr);
-/** Default (case-sensitive) regex match */
-#define regexp_match(s,d) regexp_match_case(s,d,1)
-/** Default (case-insensitive) wildcard match */
-#define wild_match(s,d) wild_match_case(s,d,0)
 /** Default (case-insensitive) local wildcard match */
 #define local_wild_match(s,d) local_wild_match_case(s, d, 0)
 
index 65f7a85001cd29963c9a8fced6d737900acf2901..27f5c7d54de397fd82f3156cabf8e872223415c8 100644 (file)
@@ -183,6 +183,7 @@ without modification. */
   extern pcre *pcre_compile(const char *, int, const char **,
                            int *, const unsigned char *);
   extern int pcre_copy_substring(const char *, int *, int, int, char *, int);
+  int pcre_get_substring(const char *, int *, int, int, const char **);
   extern int pcre_exec(const pcre *, const pcre_extra *,
                       const char *, int, int, int, int *, int);
   extern const unsigned char *pcre_maketables(void);
index e2afef76d6d5bebc529548580109915a3a304ecf..488824345f95499b7a2bed9f7a2ac59aa733872e 100644 (file)
@@ -202,11 +202,11 @@ depend: funlocal.c cmdlocal.c local.c flaglocal.c
        makedepend -fMakefile.SH -w10 -- -I../hdrs -I.. $(CFLAGS) -- $(C_FILES) $(H_FILES)
        perl ../utils/fixdepend.pl Makefile.SH
 
-# Requires GNU indent! 
+# Requires GNU indent 1.2 or better! 
+
 indent:
        (set +e; for file in *.dst *.c  ../hdrs/*.h ; do echo $$file; \
-       /usr/bin/expand $$file > tmpfile; mv -f tmpfile $$file; \
-       /usr/bin/indent -npro -kr -ci2 -ss -psl -ip4 -i2 -cs -l80 -lc75 \
+       /usr/bin/indent -npro -kr -ci2 -ss -psl -ip4 -i2 -cs -l80 -lc75 -nut \
        -T atr_err -T ATRALIAS -T DESC -T CNode -T CONF -T BQUE -T FUN \
        -T NVAL -T i_rec -T f_rec -T USERFN_ENTRY -T PRIV -T FLAG \
        -T FLAGENT -T FLAG_ALIAS -T tlist -T u -T stat -T tcheck -T ATTR \
index 6d1bee4d9b2779404f9c2ce85f066c96fd894fb6..fa2101d25216fa620a87b982a4a43f28349780d5 100644 (file)
@@ -332,11 +332,11 @@ site_can_access(const char *hname, int flag, dbref who)
   for (ap = access_top; ap; ap = ap->next) {
     if (!(ap->can & ACS_SITELOCK)
        && ((ap->can & ACS_REGEXP)
-           ? (regexp_match_case(ap->host, hname, 0)
-              || (p && regexp_match_case(ap->host, p, 0))
+           ? (quick_regexp_match(ap->host, hname, 0)
+              || (p && quick_regexp_match(ap->host, p, 0))
 #ifdef FORCE_IPV4
-              || regexp_match_case(ip4_to_ip6(ap->host), hname, 0)
-              || (p && regexp_match_case(ip4_to_ip6(ap->host), p, 0))
+              || quick_regexp_match(ip4_to_ip6(ap->host), hname, 0)
+              || (p && quick_regexp_match(ip4_to_ip6(ap->host), p, 0))
 #endif
            )
            : (quick_wild(ap->host, hname)
@@ -402,11 +402,11 @@ site_check_access(const char *hname, dbref who, int *rulenum)
     (*rulenum)++;
     if (!(ap->can & ACS_SITELOCK)
        && ((ap->can & ACS_REGEXP)
-           ? (regexp_match_case(ap->host, hname, 0)
-              || (p && regexp_match_case(ap->host, p, 0))
+           ? (quick_regexp_match(ap->host, hname, 0)
+              || (p && quick_regexp_match(ap->host, p, 0))
 #ifdef FORCE_IPV4
-              || regexp_match_case(ip4_to_ip6(ap->host), hname, 0)
-              || (p && regexp_match_case(ip4_to_ip6(ap->host), p, 0))
+              || quick_regexp_match(ip4_to_ip6(ap->host), hname, 0)
+              || (p && quick_regexp_match(ip4_to_ip6(ap->host), p, 0))
 #endif
            )
            : (quick_wild(ap->host, hname)
index c506f912f64e55405685c7b37e55443744ae2ab4..2e08e42e1f440b1ac52091c65a6bf1bcec2d51fa 100644 (file)
@@ -550,8 +550,8 @@ atr_new_add(dbref thing, const char *RESTRICT atr, const char *RESTRICT s,
        free(t);
       }
     } else {
-      if (!AL_FLAGS(root) & AF_ROOT)   /* Upgrading old database */
-       AL_FLAGS(root) |= AF_ROOT; 
+      if (!AL_FLAGS(root) & AF_ROOT)   /* Upgrading old database */
+       AL_FLAGS(root) |= AF_ROOT;
     }
   }
 
@@ -1165,6 +1165,8 @@ atr_comm_match(dbref thing, dbref player, int type, int end,
   ATTR *skip[ATTRIBUTE_NAME_LIMIT / 2];
   int skipcount;
   int lock_checked = 0;
+  char match_space[BUFFER_LEN * 2];
+  int match_space_len = BUFFER_LEN * 2;
   dbref local_ooref;
 
   /* check for lots of easy ways out */
@@ -1239,7 +1241,9 @@ atr_comm_match(dbref thing, dbref player, int type, int end,
 
     match_found = 0;
     if (AF_Regexp(ptr)) {
-      if (regexp_match_case(tbuf2 + 1, str, AF_Case(ptr))) {
+      if (regexp_match_case_r(tbuf2 + 1, str, AF_Case(ptr),
+                             global_eval_context.wnxt, 10,
+                             match_space, match_space_len)) {
         match_found = 1;
         match++;
       }
@@ -1247,7 +1251,10 @@ atr_comm_match(dbref thing, dbref player, int type, int end,
       if (quick_wild_new(tbuf2 + 1, str, AF_Case(ptr))) {
         match_found = 1;
         match++;
-        wild_match_case(tbuf2 + 1, str, AF_Case(ptr));
+       if (!just_match)
+         wild_match_case_r(tbuf2 + 1, str, AF_Case(ptr),
+                           global_eval_context.wnxt, 10,
+                           match_space, match_space_len);
       }
     }
     if (match_found) {
@@ -1360,7 +1367,9 @@ atr_comm_match(dbref thing, dbref player, int type, int end,
 
       match_found = 0;
       if (AF_Regexp(ptr)) {
-        if (regexp_match_case(tbuf2 + 1, str, AF_Case(ptr))) {
+       if (regexp_match_case_r(tbuf2 + 1, str, AF_Case(ptr),
+                               global_eval_context.wnxt, 10,
+                               match_space, match_space_len)) {
           match_found = 1;
           match++;
         }
@@ -1368,7 +1377,10 @@ atr_comm_match(dbref thing, dbref player, int type, int end,
         if (quick_wild_new(tbuf2 + 1, str, AF_Case(ptr))) {
           match_found = 1;
           match++;
-          wild_match_case(tbuf2 + 1, str, AF_Case(ptr));
+         if (!just_match)
+           wild_match_case_r(tbuf2 + 1, str, AF_Case(ptr),
+                             global_eval_context.wnxt, 10,
+                             match_space, match_space_len);
         }
       }
       if (match_found) {
@@ -1440,6 +1452,8 @@ atr_comm_divmatch(dbref thing, dbref player, int type, int end,
   ATTR *skip[ATTRIBUTE_NAME_LIMIT / 2];
   int skipcount;
   int lock_checked = 0;
+  char match_space[BUFFER_LEN * 2];
+  int match_space_len = BUFFER_LEN * 2;
 
   /* check for lots of easy ways out */
   if ((type != '$' && type != '^') || !GoodObject(thing) || Halted(thing)
@@ -1513,7 +1527,9 @@ atr_comm_divmatch(dbref thing, dbref player, int type, int end,
 
     match_found = 0;
     if (AF_Regexp(ptr)) {
-      if (regexp_match_case(tbuf2 + 1, str, AF_Case(ptr))) {
+       if (regexp_match_case_r(tbuf2 + 1, str, AF_Case(ptr),
+                               global_eval_context.wnxt, 10,
+                               match_space, match_space_len)) {
         match_found = 1;
         match++;
       }
@@ -1521,7 +1537,10 @@ atr_comm_divmatch(dbref thing, dbref player, int type, int end,
       if (quick_wild_new(tbuf2 + 1, str, AF_Case(ptr))) {
         match_found = 1;
         match++;
-        wild_match_case(tbuf2 + 1, str, AF_Case(ptr));
+       if(!just_match)
+         wild_match_case_r(tbuf2 + 1, str, AF_Case(ptr),
+             global_eval_context.wnxt, 10,
+             match_space, match_space_len);
       }
     }
     if (match_found) {
@@ -1635,7 +1654,9 @@ atr_comm_divmatch(dbref thing, dbref player, int type, int end,
 
       match_found = 0;
       if (AF_Regexp(ptr)) {
-        if (regexp_match_case(tbuf2 + 1, str, AF_Case(ptr))) {
+       if (regexp_match_case_r(tbuf2 + 1, str, AF_Case(ptr),
+                               global_eval_context.wnxt, 10,
+                               match_space, match_space_len)) {
           match_found = 1;
           match++;
         }
@@ -1643,8 +1664,11 @@ atr_comm_divmatch(dbref thing, dbref player, int type, int end,
         if (quick_wild_new(tbuf2 + 1, str, AF_Case(ptr))) {
           match_found = 1;
           match++;
-          wild_match_case(tbuf2 + 1, str, AF_Case(ptr));
-        }
+         if(!just_match)
+           wild_match_case_r(tbuf2 + 1, str, AF_Case(ptr),
+                             global_eval_context.wnxt, 10,
+                             match_space, match_space_len);
+       }
       }
       if (match_found) {
         /* Since we're still checking the lock on the child, not the
@@ -1714,6 +1738,8 @@ one_comm_match(dbref thing, dbref player, const char *atr, const char *str)
   char tbuf1[BUFFER_LEN];
   char tbuf2[BUFFER_LEN];
   char *s;
+  char match_space[BUFFER_LEN * 2];
+  int match_space_len = BUFFER_LEN * 2;
 
   /* check for lots of easy ways out */
   if (!GoodObject(thing) || Halted(thing) || NoCommand(thing))
@@ -1747,8 +1773,12 @@ one_comm_match(dbref thing, dbref player, const char *atr, const char *str)
     strcpy(tbuf2, tbuf1);
 
   if (AF_Regexp(ptr) ?
-      regexp_match_case(tbuf2 + 1, str, AF_Case(ptr)) :
-      wild_match_case(tbuf2 + 1, str, AF_Case(ptr))) {
+      regexp_match_case_r(tbuf2 + 1, str, AF_Case(ptr),
+       global_eval_context.wnxt, 10, match_space,
+       match_space_len) : wild_match_case_r(tbuf2 + 1, str,
+         AF_Case(ptr), global_eval_context.  wnxt, 10, match_space,
+         match_space_len))
+  {
     if (!eval_lock(player, thing, Command_Lock)
         || !eval_lock(player, thing, Use_Lock))
       return 0;
index 4f623d14f13a3ba99c210ccbed7de9d41a4bfc91..b3269b00a950bd4d1b9e4bb6a451365b41491f4e 100644 (file)
--- a/src/bsd.c
+++ b/src/bsd.c
@@ -396,6 +396,10 @@ void NORETURN bailout(int sig);
 void WIN32_CDECL signal_shutdown(int sig);
 void WIN32_CDECL signal_dump(int sig);
 void reaper(int sig);
+#ifndef WIN32
+sig_atomic_t dump_error = 0;
+WAIT_TYPE dump_status = 0;
+#endif
 extern Pid_t forked_dump_pid;  /**< Process id of forking dump process */
 static void dump_users(DESC *call_by, char *match, int doing);
 static const char *time_format_1(long int dt);
@@ -409,6 +413,7 @@ static void promote_info_slave(void);
 static void query_info_slave(int fd);
 static void reap_info_slave(void);
 void kill_info_slave(void);
+sig_atomic_t slave_error = 0;
 #endif
 #endif
 void reopen_logs(void);
@@ -960,6 +965,32 @@ shovechars(Port_t port, Port_t sslport __attribute__ ((__unused__)))
 
     process_commands();
 
+    /* Check signal handler flags */
+
+#ifndef WIN32
+    if (dump_error) {
+      if (WIFSIGNALED(dump_status)) {
+       do_rawlog(LT_ERR, T("ERROR! forking dump exited with signal %d"),
+                 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);
+      }
+      dump_error = 0;
+      dump_status = 0;
+    }
+#if defined(INFO_SLAVE) && !defined(COMPILE_CONSOLE)
+    if (slave_error) {
+      do_rawlog(LT_ERR, T("info_slave on pid %d exited unexpectedly!"),
+               slave_error);
+      slave_error = 0;
+    }
+#endif
+#endif                         /* !WIN32 */
+
     if (signal_shutdown_flag) {
       flag_broadcast(0, 0, T("GAME: Shutdown by external signal"));
       do_rawlog(LT_ERR, T("SHUTDOWN by external signal"));
@@ -3408,20 +3439,14 @@ reaper(int sig __attribute__ ((__unused__)))
       do_rawlog(LT_ERR, T("info_slave on pid %d exited!"), pid);
       info_slave_state = 0;
       info_slave_pid = -1;
+      slave_error = pid;
     } else
 #endif
 #endif
     if (forked_dump_pid > -1 && pid == forked_dump_pid) {
       /* Most failures are handled by the forked mush already */
-      if (WIFSIGNALED(my_stat)) {
-       do_rawlog(LT_ERR, T("ERROR! forking dump exited with signal %d"),
-                 WTERMSIG(my_stat));
-      } else if (WIFEXITED(my_stat) && WEXITSTATUS(my_stat) == 0) {
-       time(&globals.last_dump_time);
-       if (DUMP_NOFORK_COMPLETE && *DUMP_NOFORK_COMPLETE)
-         flag_broadcast(0, 0, "%s", DUMP_NOFORK_COMPLETE);
-
-      }
+      dump_error = forked_dump_pid;
+      dump_status = my_stat;
       forked_dump_pid = -1;
     }
   }
index 0d49cbbde7bbfd6912d36a7ac6a978e9302aaf36..df415d42e5e5dd66a4cfb335e500dcb62de0d5f1 100644 (file)
@@ -919,16 +919,22 @@ notify_anything_loc(dbref speaker, na_lookup func,
     /* do @listen stuff */
     a = atr_get_noparent(target, "LISTEN");
     if (a) {
+      char match_space[BUFFER_LEN * 2];
+      int match_space_len = BUFFER_LEN * 2;
       if (!tbuf1)
        tbuf1 = (char *) mush_malloc(BUFFER_LEN, "string");
       strcpy(tbuf1, atr_value(a));
       if (AF_Regexp(a)
-         ? regexp_match_case(tbuf1,
+         ? regexp_match_case_r(tbuf1,
+                               (char *) notify_makestring(msgbuf, messages,
+                                                          NA_ASCII),
+                               AF_Case(a), global_eval_context.wnxt, 10,
+                               match_space, match_space_len)
+         : wild_match_case_r(tbuf1,
                              (char *) notify_makestring(msgbuf, messages,
-                                                        NA_ASCII), AF_Case(a))
-         : wild_match_case(tbuf1,
-                           (char *) notify_makestring(msgbuf, messages,
-                                                      NA_ASCII), AF_Case(a))) {
+                                                        NA_ASCII),
+                             AF_Case(a), global_eval_context.wnxt, 10,
+                             match_space, match_space_len)) {
        if (eval_lock(speaker, target, Listen_Lock))
          if (PLAYER_AHEAR || (!IsPlayer(target))) {
            if (speaker != target)
index c177da5d84bf323380bd30ccc70728074118a4f7..6fb5bf3f2210c25f13afb828669a8881cb7f4ee5 100644 (file)
@@ -1271,6 +1271,35 @@ remove_markup(const char *orig, size_t * s_len)
   return buff;
 }
 
+/** Safe version of strncpy() that always nul-terminates the
+ * destination string. The only reason it's not called
+ * safe_strncpy() is to avoid confusion with the unrelated
+ * safe_*() pennstr functions.
+ * \param dst the destination string to copy to
+ * \param src the source string to copy from
+ * \param len the maximum number of bytes to copy
+ * return dst
+ */
+char *
+mush_strncpy(char *RESTRICT dst, const char *RESTRICT src, size_t len)
+{
+  size_t n = 0;
+  char *start = dst;
+
+  if (!src || !dst || len == 0)
+    return dst;
+
+  len--;
+
+  while (*src && n < len) {
+    *dst++ = *src++;
+    n++;
+  }
+
+  *dst = '\0';
+  return start;
+}
+
 
 /** Safely append an int to a string. Returns a true value on failure.
  * This will someday take extra arguments for use with our version 
index 29c692fa3392b7a84e397cacbf0cff48f51a9bb9..15ca7a009c932c117b8a9c37bfde43721e1e9cfc 100644 (file)
@@ -30,6 +30,7 @@
 #include "conf.h"
 #include "case.h"
 #include "externs.h"
+#include "ansi.h"
 #include "mymalloc.h"
 #include "parse.h"
 #include "pcre.h"
 
 const unsigned char *tables = NULL;  /** Pointer to character tables */
 
-static char wspace[3 * BUFFER_LEN + NUMARGS];  /* argument return buffer */
-                                               /* big to match tprintf */
-
 static int wild1
   (const char *RESTRICT tstr, const char *RESTRICT dstr, int arg,
-   char **RESTRICT wbuf, int cs);
-static int wild(const char *RESTRICT s, const char *RESTRICT d, int p, int cs);
+   char **wbuf, int *len, int cs, char **ary, int max);
+static int wild(const char *RESTRICT s, const char *RESTRICT d, int p, int cs,
+               char **ary, int max, char *buffer, int len);
 static int check_literals(const char *RESTRICT tstr, const char *RESTRICT dstr,
                          int cs);
 static char *strip_backslashes(const char *str);
@@ -267,7 +266,7 @@ atr_wild(const char *RESTRICT tstr, const char *RESTRICT dstr)
  */
 static int
 wild1(const char *RESTRICT tstr, const char *RESTRICT dstr, int arg,
-      char **RESTRICT wbuf, int cs)
+      char **wbuf, int *len, int cs, char **ary, int max)
 {
   const char *datapos;
   int argpos, numextra;
@@ -281,13 +280,16 @@ wild1(const char *RESTRICT tstr, const char *RESTRICT dstr, int arg,
       if (!*dstr)
        return 0;
 
-      global_eval_context.wnxt[arg++] = *wbuf;
-      *(*wbuf)++ = *dstr;
-      *(*wbuf)++ = '\0';
+      if (*len >= 2) {
+       ary[arg++] = *wbuf;
+       *(*wbuf)++ = *dstr;
+       *(*wbuf)++ = '\0';
+       *len -= 2;
+      }
 
       /* Jump to the fast routine if we can. */
 
-      if (arg >= NUMARGS)
+      if (arg >= (int) max || *len < 2)
        return quick_wild_new(tstr + 1, dstr + 1, cs);
       break;
     case '\\':
@@ -311,9 +313,14 @@ wild1(const char *RESTRICT tstr, const char *RESTRICT dstr, int arg,
 
   /* If at end of pattern, slurp the rest, and leave. */
   if (!tstr[1]) {
-    global_eval_context.wnxt[arg] = *wbuf;
-    strcpy(*wbuf, dstr);
-    *wbuf += strlen(dstr) + 2;
+    int tlen;
+    tlen = strlen(dstr);
+    if (tlen < *len) {
+      ary[arg] = *wbuf;
+      strcpy(*wbuf, dstr);
+      *wbuf += tlen + 2;
+      *len -= tlen + 1;
+    }
     return 1;
   }
   /* Remember current position for filling in the '*' return. */
@@ -326,21 +333,27 @@ wild1(const char *RESTRICT tstr, const char *RESTRICT dstr, int arg,
       /* Fill in arguments if someone put another '*'
        * before a fixed string.
        */
-      global_eval_context.wnxt[argpos++] = *wbuf;
-      *(*wbuf)++ = '\0';
+      if (*len >= 1) {
+       ary[argpos++] = *wbuf;
+       *(*wbuf)++ = '\0';
+       *len -= 1;
+      }
 
       /* Jump to the fast routine if we can. */
-      if (argpos >= NUMARGS)
+      if (argpos >= (int) max || *len < 2)
        return quick_wild_new(tstr, dstr, cs);
 
       /* Fill in any intervening '?'s */
       while (argpos < arg) {
-       global_eval_context.wnxt[argpos++] = *wbuf;
-       *(*wbuf)++ = *datapos++;
-       *(*wbuf)++ = '\0';
+       if (*len >= 2) {
+         ary[argpos++] = *wbuf;
+         *(*wbuf)++ = *datapos++;
+         *(*wbuf)++ = '\0';
+         *len -= 2;
+       }
 
        /* Jump to the fast routine if we can. */
-       if (argpos >= NUMARGS)
+       if (argpos >= (int) max || *len < 1)
          return quick_wild_new(tstr, dstr, cs);
       }
     }
@@ -373,7 +386,7 @@ wild1(const char *RESTRICT tstr, const char *RESTRICT dstr, int arg,
   else {
     while (1) {
       if (EQUAL(cs, *dstr, *tstr) &&
-         ((arg < NUMARGS) ? wild1(tstr, dstr, arg, wbuf, cs)
+         ((arg < (int) max) ? wild1(tstr, dstr, arg, wbuf, len, cs, ary, max)
           : quick_wild_new(tstr, dstr, cs)))
        break;
       if (!*dstr)
@@ -385,20 +398,30 @@ wild1(const char *RESTRICT tstr, const char *RESTRICT dstr, int arg,
   /* Found a match!  Fill in all remaining arguments.
    * First do the '*'...
    */
-  global_eval_context.wnxt[argpos++] = *wbuf;
-  strncpy(*wbuf, datapos, (dstr - datapos) - numextra);
-  *wbuf += (dstr - datapos) - numextra;
-  *(*wbuf)++ = '\0';
-  datapos = dstr - numextra;
+  {
+    int datalen;
+    datalen = (dstr - datapos) - numextra;
+    if (datalen + 1 <= *len) {
+      ary[argpos++] = *wbuf;
+      strncpy(*wbuf, datapos, datalen);
+      *wbuf += datalen;
+      *(*wbuf)++ = '\0';
+      *len -= datalen + 1;
+      datapos = dstr - numextra;
+    }
+  }
 
   /* Fill in any trailing '?'s that are left. */
   while (numextra) {
-    if (argpos >= NUMARGS)
+    if (argpos >= (int) max || *len < 2)
       return 1;
-    global_eval_context.wnxt[argpos++] = *wbuf;
-    *(*wbuf)++ = *datapos++;
-    *(*wbuf)++ = '\0';
-    numextra--;
+    if (*len >= 2) {
+      ary[argpos++] = *wbuf;
+      *(*wbuf)++ = *datapos++;
+      *(*wbuf)++ = '\0';
+      *len -= 2;
+      numextra--;
+    }
   }
 
   /* It's done! */
@@ -415,11 +438,11 @@ wild1(const char *RESTRICT tstr, const char *RESTRICT dstr, int arg,
  * Side Effect: this routine modifies the 'global_eval_context.wnxt' global variable.
  */
 static int
-wild(const char *RESTRICT s, const char *RESTRICT d, int p, int cs)
+wild(const char *RESTRICT s, const char *RESTRICT d, int p, int cs,
+     char **ary, int max, char *buffer, int len)
 {
-  char *buffer = wspace;
-
-  /* Do fast match. */
+  /* Do fast match to see if pattern matches. If yes, do it again,
+     remembering this time.. */
   while ((*s != '*') && (*s != '?')) {
     if (*s == '\\')
       s++;
@@ -436,30 +459,36 @@ wild(const char *RESTRICT s, const char *RESTRICT d, int p, int cs)
     return 0;
 
   /* Do the match. */
-  return wild1(s, d, p, &buffer, cs);
+  return wild1(s, d, p, &buffer, &len, cs, ary, max);
 }
 
-/** Wildcard match, possibly case-sensitive, and remember the wild data.
- *
+/** Wildcard match, possibly case-sensitive, and remember the wild data
+ *  in matches, storing them in data.
  * This routine will cause crashes if fed NULLs instead of strings.
  *
  * \param s pattern to match against.
  * \param d string to check.
  * \param cs if 1, case-sensitive; if 0, case-insensitive.
+ * \param ary An array to store the grabs in
+ * \param max Number of elements ary can hold
+ * \param data Buffer used to hold the matches. The elements of ary
+ *    are set to pointers into this  buffer.
+ * \param len The number of bytes in data. Twice the length of d should
+ *    be enough.
  * \retval 1 d matches s.
  * \retval 0 d doesn't match s.
  */
 int
-wild_match_case(const char *RESTRICT s, const char *RESTRICT d, int cs)
+wild_match_case_r(const char *RESTRICT s, const char *RESTRICT d, int cs,
+                 char **matches, int nmatches, char *data, int len)
 {
-  int j;
-  /* Clear %0-%9 and r(0) - r(9) */
-  for (j = 0; j < NUMARGS; j++)
-    global_eval_context.wnxt[j] = (char *) NULL;
-  for (j = 0; j < NUMQ; j++)
-    global_eval_context.rnxt[j] = (char *) NULL;
-  clear_namedregs(&global_eval_context.namedregsnxt);
-  return wild(s, d, 0, cs);
+  int n;
+
+  for (n = 0; n < nmatches; n++)
+    matches[n] = NULL;
+
+  return wild(s, d, 0, cs, matches, nmatches, data, len);
 }
 
 /** Regexp match, possibly case-sensitive, and remember matched subexpressions.
@@ -468,22 +497,31 @@ wild_match_case(const char *RESTRICT s, const char *RESTRICT d, int cs)
  *
  * \param s regexp to match against.
  * \param d string to check.
- * \param cs if 1, case-sensitive; if 0, case-insensitive.
- * \retval 1 d matches s.
- * \retval 0 d doesn't match s.
+ * \param cs if 1, case-sensitive; if 0, case-insensitive
+ * \param matches array to store matched subexpressions in
+ * \param nmatches the size of the matches array
+ * \param data buffer space to copy matches into. The elements of
+ *   array point into here
+ * \param len The size of data
+ * \retval 1 d matches s
+ * \retval 0 d doesn't match s
  */
 int
-regexp_match_case(const char *RESTRICT s, const char *RESTRICT d, int cs)
+regexp_match_case_r(const char *RESTRICT s, const char *RESTRICT val, int cs,
+                   char **matches, int nmatches, char *data, int len)
 {
-  int j;
   pcre *re;
   int i;
-  static char wtmp[NUMARGS][BUFFER_LEN];
   const char *errptr;
+  const char *d;
+  size_t delenn;
   int erroffset;
   int offsets[99];
   int subpatterns;
 
+  for (i = 0; i < nmatches; i++)
+    matches[i] = NULL;
+
   if ((re = pcre_compile(s, (cs ? 0 : PCRE_CASELESS), &errptr, &erroffset,
                         tables)) == NULL) {
     /*
@@ -494,11 +532,12 @@ regexp_match_case(const char *RESTRICT s, const char *RESTRICT d, int cs)
     return 0;
   }
   add_check("pcre");
+  d = remove_markup(val, &delenn);
   /* 
    * Now we try to match the pattern. The relevant fields will
    * automatically be filled in by this.
    */
-  if ((subpatterns = pcre_exec(re, NULL, d, strlen(d), 0, 0, offsets, 99))
+  if ((subpatterns = pcre_exec(re, NULL, d, delenn - 1, 0, 0, offsets, 99))
       < 0) {
     mush_free(re, "pcre");
     return 0;
@@ -516,18 +555,20 @@ regexp_match_case(const char *RESTRICT s, const char *RESTRICT d, int cs)
    * with other languages.
    */
 
-  /* Clear %0-%9 and r(0) - r(9) */
-  for (j = 0; j < NUMARGS; j++) {
-    wtmp[j][0] = '\0';
-    global_eval_context.wnxt[j] = (char *) NULL;
-  }
-  for (j = 0; j < NUMQ; j++)
-    global_eval_context.rnxt[j] = (char *) NULL;
-  clear_namedregs(&global_eval_context.namedregsnxt);
+  for (i = 0; i < nmatches && i < subpatterns && len > 1; i++) {
+    int sublen;
+    const char *submatch;
+  
+    pcre_get_substring(d, offsets, subpatterns, (int) i, &submatch);
+    sublen = strlen(submatch);
+
+    if (sublen >= len)
+      break;
 
-  for (i = 0; (i < 10) && (i < NUMARGS); i++) {
-    pcre_copy_substring(d, offsets, subpatterns, i, wtmp[i], BUFFER_LEN);
-    global_eval_context.wnxt[i] = wtmp[i];
+    strcpy(data, submatch);
+    matches[i] = data;
+    data += sublen + 1;
+    len -= sublen + 1;
   }
 
   mush_free(re, "pcre");
@@ -549,6 +590,8 @@ int
 quick_regexp_match(const char *RESTRICT s, const char *RESTRICT d, int cs)
 {
   pcre *re;
+  const char *sptr;
+  size_t slen;
   const char *errptr;
   int erroffset;
   int offsets[99];
@@ -570,11 +613,12 @@ quick_regexp_match(const char *RESTRICT s, const char *RESTRICT d, int cs)
     return 0;
   }
   add_check("pcre");
+  sptr = remove_markup(d, &slen);
   /* 
    * Now we try to match the pattern. The relevant fields will
    * automatically be filled in by this.
    */
-  r = pcre_exec(re, NULL, d, strlen(d), 0, 0, offsets, 99);
+  r = pcre_exec(re, NULL, sptr, slen - 1, 0, 0, offsets, 99); 
 
   mush_free(re, "pcre");
 
@@ -640,9 +684,8 @@ check_literals(const char *RESTRICT tstr, const char *RESTRICT dstr, int cs)
   char dbuf1[BUFFER_LEN];
   const char delims[] = "?*";
   char *sp, *dp;
-  strncpy(dbuf1, dstr, BUFFER_LEN - 1);
-  dbuf1[BUFFER_LEN - 1] = '\0';
-  strcpy(tbuf1, strip_backslashes(tstr));
+  mush_strncpy(dbuf1, dstr, BUFFER_LEN);
+  mush_strncpy(tbuf1, strip_backslashes(tstr), BUFFER_LEN);
   if (!cs) {
     upcasestr(tbuf1);
     upcasestr(dbuf1);
index 6d74e9633e5e4845559207ee397eb0d2d68fd36c..d2721330eaa9d51ec4bc802d1eff8af770f267ae 100644 (file)
--- a/src/wiz.c
+++ b/src/wiz.c
@@ -1761,9 +1761,9 @@ fill_search_spec(dbref player, const char *owner, int nargs, const char **args,
     restriction = args[n + 1];
     /* A special old-timey kludge */
     if (class && !*class && restriction && *restriction) {
-      if (isdigit((unsigned char) *restriction)
-         || ((*restriction == '#') && *(restriction + 1)
-             && isdigit((unsigned char) *(restriction + 1)))) {
+    if (isdigit((unsigned char) *class) || ((*class == '#') && *(class + 1)
+                                           && isdigit((unsigned char)
+                                                      *(class + 1)))) {
       size_t offset = 0;
       if (*restriction == '#')
         offset = 1;