From: Rick Bird Date: Sat, 26 Mar 2011 18:10:14 +0000 (-0400) Subject: PennMUSH 182p5 Incorporation X-Git-Url: https://git.theari.com/?a=commitdiff_plain;h=e31c370d47478ee2acc2bb8d94264522f85c1723;p=cobramush.git PennMUSH 182p5 Incorporation * Removed the gmalloc malloc option. [SW] * Assorted gcc warning fixes. [SW] * Cleaned up some unsafe signal handler functions. [SW] --- diff --git a/game/txt/hlp/cobra_func.hlp b/game/txt/hlp/cobra_func.hlp index 6b2e514..12c1c71 100644 --- a/game/txt/hlp/cobra_func.hlp +++ b/game/txt/hlp/cobra_func.hlp @@ -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 diff --git a/hdrs/externs.h b/hdrs/externs.h index f95f841..a05905c 100644 --- a/hdrs/externs.h +++ b/hdrs/externs.h @@ -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) diff --git a/hdrs/pcre.h b/hdrs/pcre.h index 65f7a85..27f5c7d 100644 --- a/hdrs/pcre.h +++ b/hdrs/pcre.h @@ -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); diff --git a/src/Makefile.SH b/src/Makefile.SH index e2afef7..4888243 100644 --- a/src/Makefile.SH +++ b/src/Makefile.SH @@ -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 \ diff --git a/src/access.c b/src/access.c index 6d1bee4..fa2101d 100644 --- a/src/access.c +++ b/src/access.c @@ -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) diff --git a/src/attrib.c b/src/attrib.c index c506f91..2e08e42 100644 --- a/src/attrib.c +++ b/src/attrib.c @@ -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; diff --git a/src/bsd.c b/src/bsd.c index 4f623d1..b3269b0 100644 --- 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; } } diff --git a/src/notify.c b/src/notify.c index 0d49cbb..df415d4 100644 --- a/src/notify.c +++ b/src/notify.c @@ -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) diff --git a/src/strutil.c b/src/strutil.c index c177da5..6fb5bf3 100644 --- a/src/strutil.c +++ b/src/strutil.c @@ -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 diff --git a/src/wild.c b/src/wild.c index 29c692f..15ca7a0 100644 --- a/src/wild.c +++ b/src/wild.c @@ -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" @@ -46,13 +47,11 @@ 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); diff --git a/src/wiz.c b/src/wiz.c index 6d74e96..d272133 100644 --- 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;