This is patch05 to PennMUSH 1.8.2. After applying this patch, you will have version 1.8.2p5 To apply this patch, save it to a file in your top-level 1.8.2p4 MUSH directory, and do the following: patch -p0 < 1.8.2-patch05 ./Configure make install If you use GNU patch 2.2, you probably want the above to be 'patch -b -p0', not just 'patch -p0'. Unix (or cygwin) users need not worry about failed hunks in src/switchinc.c, hdrs/switches.h, hdrs/cmds.h, or hdrs/funs.h. These files are automatically rebuilt on compile. On the off chance they appear not to be, simply rm them and re-run make. Then @shutdown and restart your MUSH. - Shawn/Raevnos In this patch: Minor changes: * Removed the gmalloc malloc option. [SW] * Assorted gcc warning fixes. [SW] Fixes: * Cleaned up some unsafe signal handler functions. [SW] Prereq: 1.8.2p4 *** Patchlevel (.../p4) (revision 927) --- Patchlevel (.../p5) (revision 927) *************** *** 1,2 **** Do not edit this file. It is maintained by the official PennMUSH patches. ! This is PennMUSH 1.8.2p4 --- 1,2 ---- Do not edit this file. It is maintained by the official PennMUSH patches. ! This is PennMUSH 1.8.2p5 Index: src/Makefile.SH =================================================================== *** src/Makefile.SH (.../p4) (revision 927) --- src/Makefile.SH (.../p5) (revision 927) *************** *** 206,216 **** ../utils/fixdepend.pl Makefile.SH echo '!NO!SUBS!' >> Makefile.SH ! # Requires GNU indent! 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 \ -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 \ --- 206,216 ---- ../utils/fixdepend.pl Makefile.SH echo '!NO!SUBS!' >> Makefile.SH ! # Requires GNU indent 1.2 or better! ! indent: (set +e; for file in *.dst *.c ../hdrs/*.h ; do echo $$file; \ ! /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: src/wiz.c =================================================================== *** src/wiz.c (.../p4) (revision 927) --- src/wiz.c (.../p5) (revision 927) *************** *** 1836,1844 **** } if (!class || !*class || !restriction) continue; ! if (isdigit((unsigned char) *class) || ! ((*class == '#') && *(class + 1) ! && isdigit((unsigned char) *(class + 1)))) { size_t offset = 0; if (*class == '#') offset = 1; --- 1836,1844 ---- } if (!class || !*class || !restriction) continue; ! if (isdigit((unsigned char) *class) || ((*class == '#') && *(class + 1) ! && isdigit((unsigned char) ! *(class + 1)))) { size_t offset = 0; if (*class == '#') offset = 1; Index: src/attrib.c =================================================================== *** src/attrib.c (.../p4) (revision 927) --- src/attrib.c (.../p5) (revision 927) *************** *** 401,407 **** #define set_default_flags(atr,flags) \ do { \ ATTR *std = atr_match(AL_NAME((atr))); \ ! if (std && !(flags) && !strcmp(AL_NAME(std), AL_NAME((atr)))) { \ AL_FLAGS(atr) = AL_FLAGS(std); \ } else { \ AL_FLAGS(atr) = flags; \ --- 401,407 ---- #define set_default_flags(atr,flags) \ do { \ ATTR *std = atr_match(AL_NAME((atr))); \ ! if (std && !(flags) && !strcmp(AL_NAME(std), AL_NAME((atr)))) { \ AL_FLAGS(atr) = AL_FLAGS(std); \ } else { \ AL_FLAGS(atr) = flags; \ *************** *** 568,575 **** free(t); } } else { ! if (!AL_FLAGS(root) & AF_ROOT) /* Upgrading old database */ ! AL_FLAGS(root) |= AF_ROOT; } } --- 568,575 ---- free(t); } } else { ! if (!AL_FLAGS(root) & AF_ROOT) /* Upgrading old database */ ! AL_FLAGS(root) |= AF_ROOT; } } *************** *** 660,666 **** AL_CREATOR(root) = Owner(player); if (!EMPTY_ATTRS) { unsigned char *t = compress(" "); ! if (!t) mush_panic(T("Unable to allocate memory in atr_add()!")); root->data = chunk_create(t, u_strlen(t), 0); free(t); --- 660,666 ---- AL_CREATOR(root) = Owner(player); if (!EMPTY_ATTRS) { unsigned char *t = compress(" "); ! if (!t) mush_panic(T("Unable to allocate memory in atr_add()!")); root->data = chunk_create(t, u_strlen(t), 0); free(t); *************** *** 1295,1300 **** --- 1295,1302 ---- 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) *************** *** 1368,1374 **** match_found = 0; if (AF_Regexp(ptr)) { ! if (regexp_match_case(tbuf2 + 1, str, AF_Case(ptr))) { match_found = 1; match++; } --- 1370,1378 ---- match_found = 0; if (AF_Regexp(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++; } *************** *** 1376,1382 **** if (quick_wild_new(tbuf2 + 1, str, AF_Case(ptr))) { match_found = 1; match++; ! wild_match_case(tbuf2 + 1, str, AF_Case(ptr)); } } if (match_found) { --- 1380,1389 ---- if (quick_wild_new(tbuf2 + 1, str, AF_Case(ptr))) { match_found = 1; match++; ! 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) { *************** *** 1485,1491 **** match_found = 0; if (AF_Regexp(ptr)) { ! if (regexp_match_case(tbuf2 + 1, str, AF_Case(ptr))) { match_found = 1; match++; } --- 1492,1500 ---- match_found = 0; if (AF_Regexp(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++; } *************** *** 1493,1499 **** if (quick_wild_new(tbuf2 + 1, str, AF_Case(ptr))) { match_found = 1; match++; ! wild_match_case(tbuf2 + 1, str, AF_Case(ptr)); } } if (match_found) { --- 1502,1511 ---- if (quick_wild_new(tbuf2 + 1, str, AF_Case(ptr))) { match_found = 1; match++; ! 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) { *************** *** 1558,1563 **** --- 1570,1577 ---- 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)) *************** *** 1591,1598 **** 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))) { if (!eval_lock(player, thing, Command_Lock) || !eval_lock(player, thing, Use_Lock)) return 0; --- 1605,1619 ---- strcpy(tbuf2, tbuf1); if (AF_Regexp(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: src/access.c =================================================================== *** src/access.c (.../p4) (revision 927) --- src/access.c (.../p5) (revision 927) *************** *** 330,340 **** 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)) #ifdef FORCE_IPV4 ! || regexp_match_case(ip4_to_ip6(ap->host), hname, 0) ! || (p && regexp_match_case(ip4_to_ip6(ap->host), p, 0)) #endif ) : (quick_wild(ap->host, hname) --- 330,340 ---- for (ap = access_top; ap; ap = ap->next) { if (!(ap->can & ACS_SITELOCK) && ((ap->can & ACS_REGEXP) ! ? (quick_regexp_match(ap->host, hname, 0) ! || (p && quick_regexp_match(ap->host, p, 0)) #ifdef FORCE_IPV4 ! || 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) *************** *** 400,410 **** (*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)) #ifdef FORCE_IPV4 ! || regexp_match_case(ip4_to_ip6(ap->host), hname, 0) ! || (p && regexp_match_case(ip4_to_ip6(ap->host), p, 0)) #endif ) : (quick_wild(ap->host, hname) --- 400,410 ---- (*rulenum)++; if (!(ap->can & ACS_SITELOCK) && ((ap->can & ACS_REGEXP) ! ? (quick_regexp_match(ap->host, hname, 0) ! || (p && quick_regexp_match(ap->host, p, 0)) #ifdef FORCE_IPV4 ! || 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: src/bsd.c =================================================================== *** src/bsd.c (.../p4) (revision 927) --- src/bsd.c (.../p5) (revision 927) *************** *** 371,376 **** --- 371,380 ---- 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(time_t dt); *************** *** 384,389 **** --- 388,394 ---- 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 void reopen_logs(void); void load_reboot_db(void); *************** *** 838,843 **** --- 843,874 ---- 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; + } + #ifdef INFO_SLAVE + 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")); *************** *** 3035,3058 **** { #ifdef INFO_SLAVE if (info_slave_pid > -1 && pid == info_slave_pid) { - do_rawlog(LT_ERR, T("info_slave on pid %d exited!"), pid); info_slave_state = 0; info_slave_pid = -1; } else #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)); ! flag_broadcast("ROYALTY WIZARD", 0, ! T("GAME: ERROR! Forking database save failed!")); ! } 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); ! ! } forked_dump_pid = -1; } } --- 3066,3080 ---- { #ifdef INFO_SLAVE if (info_slave_pid > -1 && pid == info_slave_pid) { info_slave_state = 0; info_slave_pid = -1; + slave_error = pid; } else #endif if (forked_dump_pid > -1 && pid == forked_dump_pid) { /* Most failures are handled by the forked mush already */ ! dump_error = forked_dump_pid; ! dump_status = my_stat; forked_dump_pid = -1; } } Index: src/wild.c =================================================================== *** src/wild.c (.../p4) (revision 927) --- src/wild.c (.../p5) (revision 927) *************** *** 30,35 **** --- 30,36 ---- #include "conf.h" #include "case.h" #include "externs.h" + #include "ansi.h" #include "mymalloc.h" #include "parse.h" #include "pcre.h" *************** *** 46,58 **** 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); static int check_literals(const char *RESTRICT tstr, const char *RESTRICT dstr, int cs); static char *strip_backslashes(const char *str); --- 47,57 ---- const unsigned char *tables = NULL; /** Pointer to character tables */ static int wild1 (const char *RESTRICT tstr, const char *RESTRICT dstr, int arg, ! 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); *************** *** 271,277 **** */ static int wild1(const char *RESTRICT tstr, const char *RESTRICT dstr, int arg, ! char **RESTRICT wbuf, int cs) { const char *datapos; int argpos, numextra; --- 270,276 ---- */ static int wild1(const char *RESTRICT tstr, const char *RESTRICT dstr, int arg, ! char **wbuf, int *len, int cs, char **ary, int max) { const char *datapos; int argpos, numextra; *************** *** 285,297 **** if (!*dstr) return 0; ! global_eval_context.wnxt[arg++] = *wbuf; ! *(*wbuf)++ = *dstr; ! *(*wbuf)++ = '\0'; /* Jump to the fast routine if we can. */ ! if (arg >= NUMARGS) return quick_wild_new(tstr + 1, dstr + 1, cs); break; case '\\': --- 284,299 ---- if (!*dstr) return 0; ! if (*len >= 2) { ! ary[arg++] = *wbuf; ! *(*wbuf)++ = *dstr; ! *(*wbuf)++ = '\0'; ! *len -= 2; ! } /* Jump to the fast routine if we can. */ ! if (arg >= (int) max || *len < 2) return quick_wild_new(tstr + 1, dstr + 1, cs); break; case '\\': *************** *** 315,323 **** /* 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; return 1; } /* Remember current position for filling in the '*' return. */ --- 317,330 ---- /* If at end of pattern, slurp the rest, and leave. */ if (!tstr[1]) { ! 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. */ *************** *** 330,350 **** /* Fill in arguments if someone put another '*' * before a fixed string. */ ! global_eval_context.wnxt[argpos++] = *wbuf; ! *(*wbuf)++ = '\0'; /* Jump to the fast routine if we can. */ ! if (argpos >= NUMARGS) 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'; /* Jump to the fast routine if we can. */ ! if (argpos >= NUMARGS) return quick_wild_new(tstr, dstr, cs); } } --- 337,363 ---- /* Fill in arguments if someone put another '*' * before a fixed string. */ ! if (*len >= 1) { ! ary[argpos++] = *wbuf; ! *(*wbuf)++ = '\0'; ! *len -= 1; ! } /* Jump to the fast routine if we can. */ ! if (argpos >= (int) max || *len < 2) return quick_wild_new(tstr, dstr, cs); /* Fill in any intervening '?'s */ while (argpos < arg) { ! if (*len >= 2) { ! ary[argpos++] = *wbuf; ! *(*wbuf)++ = *datapos++; ! *(*wbuf)++ = '\0'; ! *len -= 2; ! } /* Jump to the fast routine if we can. */ ! if (argpos >= (int) max || *len < 1) return quick_wild_new(tstr, dstr, cs); } } *************** *** 377,383 **** else { while (1) { if (EQUAL(cs, *dstr, *tstr) && ! ((arg < NUMARGS) ? wild1(tstr, dstr, arg, wbuf, cs) : quick_wild_new(tstr, dstr, cs))) break; if (!*dstr) --- 390,396 ---- else { while (1) { if (EQUAL(cs, *dstr, *tstr) && ! ((arg < (int) max) ? wild1(tstr, dstr, arg, wbuf, len, cs, ary, max) : quick_wild_new(tstr, dstr, cs))) break; if (!*dstr) *************** *** 389,408 **** /* 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; /* Fill in any trailing '?'s that are left. */ while (numextra) { ! if (argpos >= NUMARGS) return 1; ! global_eval_context.wnxt[argpos++] = *wbuf; ! *(*wbuf)++ = *datapos++; ! *(*wbuf)++ = '\0'; ! numextra--; } /* It's done! */ --- 402,431 ---- /* Found a match! Fill in all remaining arguments. * First do the '*'... */ ! { ! 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 >= (int) max || *len < 2) return 1; ! if (*len >= 2) { ! ary[argpos++] = *wbuf; ! *(*wbuf)++ = *datapos++; ! *(*wbuf)++ = '\0'; ! *len -= 2; ! numextra--; ! } } /* It's done! */ *************** *** 419,429 **** * Side Effect: this routine modifies the 'wnxt' global variable. */ static int ! wild(const char *RESTRICT s, const char *RESTRICT d, int p, int cs) { ! char *buffer = wspace; ! ! /* Do fast match. */ while ((*s != '*') && (*s != '?')) { if (*s == '\\') s++; --- 442,452 ---- * Side Effect: this routine modifies the 'wnxt' global variable. */ static int ! wild(const char *RESTRICT s, const char *RESTRICT d, int p, int cs, ! char **ary, int max, char *buffer, int len) { ! /* Do fast match to see if pattern matches. If yes, do it again, ! remembering this time.. */ while ((*s != '*') && (*s != '?')) { if (*s == '\\') s++; *************** *** 440,468 **** return 0; /* Do the match. */ ! return wild1(s, d, p, &buffer, cs); } ! /** Wildcard match, possibly case-sensitive, and remember the wild 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. * \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) { ! 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; ! return wild(s, d, 0, cs); } /** Regexp match, possibly case-sensitive, and remember matched subexpressions. --- 463,498 ---- return 0; /* Do the match. */ ! return wild1(s, d, p, &buffer, &len, cs, ary, max); } ! /** 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_r(const char *RESTRICT s, const char *RESTRICT d, int cs, ! char **matches, int nmatches, char *data, int len) { ! 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. *************** *** 471,492 **** * * \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. */ int ! regexp_match_case(const char *RESTRICT s, const char *RESTRICT d, int cs) { - int j; pcre *re; int i; - static char wtmp[NUMARGS][BUFFER_LEN]; const char *errptr; int erroffset; int offsets[99]; int subpatterns; if ((re = pcre_compile(s, (cs ? 0 : PCRE_CASELESS), &errptr, &erroffset, tables)) == NULL) { /* --- 501,531 ---- * * \param s regexp to match against. * \param d string to check. ! * \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_r(const char *RESTRICT s, const char *RESTRICT val, int cs, ! char **matches, int nmatches, char *data, int len) { pcre *re; int i; 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) { /* *************** *** 497,507 **** return 0; } add_check("pcre"); /* * 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)) < 0) { mush_free(re, "pcre"); return 0; --- 536,547 ---- 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, delenn - 1, 0, 0, offsets, 99)) < 0) { mush_free(re, "pcre"); return 0; *************** *** 519,535 **** * 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; ! 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]; } mush_free(re, "pcre"); --- 559,578 ---- * with other languages. */ ! 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; ! ! strcpy(data, submatch); ! matches[i] = data; ! data += sublen + 1; ! len -= sublen + 1; } mush_free(re, "pcre"); *************** *** 551,556 **** --- 594,601 ---- 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]; *************** *** 572,582 **** return 0; } add_check("pcre"); /* * 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); mush_free(re, "pcre"); --- 617,628 ---- 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, sptr, slen - 1, 0, 0, offsets, 99); mush_free(re, "pcre"); *************** *** 642,650 **** 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)); if (!cs) { upcasestr(tbuf1); upcasestr(dbuf1); --- 688,695 ---- char dbuf1[BUFFER_LEN]; const char delims[] = "?*"; char *sp, *dp; ! mush_strncpy(dbuf1, dstr, BUFFER_LEN); ! mush_strncpy(tbuf1, strip_backslashes(tstr), BUFFER_LEN); if (!cs) { upcasestr(tbuf1); upcasestr(dbuf1); Index: src/strutil.c =================================================================== *** src/strutil.c (.../p4) (revision 927) --- src/strutil.c (.../p5) (revision 927) *************** *** 1246,1251 **** --- 1246,1280 ---- 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: src/notify.c =================================================================== *** src/notify.c (.../p4) (revision 927) --- src/notify.c (.../p5) (revision 927) *************** *** 330,337 **** if (flags & NA_PROMPT) { bp = tbuf; safe_str((char *) messages[type].message, tbuf, &bp); ! safe_chr(IAC, tbuf, &bp); ! safe_chr(GOAHEAD, tbuf, &bp); *bp = '\0'; return (unsigned char *) tbuf; } else --- 330,337 ---- if (flags & NA_PROMPT) { bp = tbuf; safe_str((char *) messages[type].message, tbuf, &bp); ! safe_chr((char) IAC, tbuf, &bp); ! safe_chr((char) GOAHEAD, tbuf, &bp); *bp = '\0'; return (unsigned char *) tbuf; } else *************** *** 370,377 **** if (flags & NA_PROMPT) { bp = tbuf; safe_str((char *) messages[type].message, tbuf, &bp); ! safe_chr(IAC, tbuf, &bp); ! safe_chr(GOAHEAD, tbuf, &bp); *bp = '\0'; return (unsigned char *) tbuf; } --- 370,377 ---- if (flags & NA_PROMPT) { bp = tbuf; safe_str((char *) messages[type].message, tbuf, &bp); ! safe_chr((char) IAC, tbuf, &bp); ! safe_chr((char) GOAHEAD, tbuf, &bp); *bp = '\0'; return (unsigned char *) tbuf; } *************** *** 420,427 **** if (flags & NA_PROMPT) { bp = tbuf; safe_str((char *) messages[type].message, tbuf, &bp); ! safe_chr(IAC, tbuf, &bp); ! safe_chr(GOAHEAD, tbuf, &bp); *bp = '\0'; return (unsigned char *) tbuf; } --- 420,427 ---- if (flags & NA_PROMPT) { bp = tbuf; safe_str((char *) messages[type].message, tbuf, &bp); ! safe_chr((char) IAC, tbuf, &bp); ! safe_chr((char) GOAHEAD, tbuf, &bp); *bp = '\0'; return (unsigned char *) tbuf; } *************** *** 532,539 **** if (flags & NA_PROMPT) { bp = tbuf; safe_str((char *) messages[type].message, tbuf, &bp); ! safe_chr(IAC, tbuf, &bp); ! safe_chr(GOAHEAD, tbuf, &bp); *bp = '\0'; return (unsigned char *) tbuf; } --- 532,539 ---- if (flags & NA_PROMPT) { bp = tbuf; safe_str((char *) messages[type].message, tbuf, &bp); ! safe_chr((char) IAC, tbuf, &bp); ! safe_chr((char) GOAHEAD, tbuf, &bp); *bp = '\0'; return (unsigned char *) tbuf; } *************** *** 914,931 **** /* do @listen stuff */ a = atr_get_noparent(target, "LISTEN"); if (a) { if (!tbuf1) tbuf1 = (char *) mush_malloc(BUFFER_LEN, "string"); strcpy(tbuf1, atr_value(a)); if (AF_Regexp(a) ! ? regexp_match_case(tbuf1, (char *) notify_makestring(msgbuf, messages, NA_ASCII, 0), ! AF_Case(a)) ! : wild_match_case(tbuf1, ! (char *) notify_makestring(msgbuf, messages, ! NA_ASCII, 0), ! AF_Case(a))) { if (eval_lock(speaker, target, Listen_Lock)) if (PLAYER_AHEAR || (!IsPlayer(target))) { if (speaker != target) --- 914,935 ---- /* 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_r(tbuf1, ! (char *) notify_makestring(msgbuf, messages, ! NA_ASCII, 0), ! 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, 0), ! 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: game/txt/hlp/pennfunc.hlp =================================================================== *** game/txt/hlp/pennfunc.hlp (.../p4) (revision 927) --- game/txt/hlp/pennfunc.hlp (.../p5) (revision 927) *************** *** 1877,1886 **** lattrp([/]) Returns a space-separated list of the attribute names on the object ! that you are permitted to examine. To see the complete list, ! you must either be a Wizard or Royalty, own the object, have the ! See_All power, or have the object set VISUAL 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 --- 1877,1886 ---- lattrp([/]) Returns a space-separated list of the attribute names on the object ! that you are permitted to examine. To see the complete list, you ! must either be a Wizard or Royalty, own the object, have the See_All ! power, or have the object set 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: game/txt/hlp/pennv182.hlp =================================================================== *** game/txt/hlp/pennv182.hlp (.../p4) (revision 927) --- game/txt/hlp/pennv182.hlp (.../p5) (revision 927) *************** *** 1,4 **** ! & 1.8.2p4 & changes This is a list of changes in this patchlevel which are probably of interest to players. More information about new commands and functions --- 1,4 ---- ! & 1.8.2p5 & changes This is a list of changes in this patchlevel which are probably of interest to players. More information about new commands and functions *************** *** 11,16 **** --- 11,26 ---- A list of the patchlevels associated with each release can be read in 'help patchlevels'. + Version 1.8.2 patchlevel 5 June 13, 2007 + + Minor changes: + * Removed the gmalloc malloc option. [SW] + * Assorted gcc warning fixes. [SW] + + Fixes: + * Cleaned up some unsafe signal handler functions. [SW] + + & 1.8.2p4 Version 1.8.2 patchlevel 4 May 16, 2007 Minor changes: Index: game/txt/hlp/pennvOLD.hlp =================================================================== *** game/txt/hlp/pennvOLD.hlp (.../p4) (revision 927) --- game/txt/hlp/pennvOLD.hlp (.../p5) (revision 927) *************** *** 4417,4423 **** For information on a specific patchlevel of one of the versions listed, type 'help p'. For example, 'help 1.7.2p3' ! 1.8.2: 0, 1, 2, 3, 4 1.8.1: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 1.8.0: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13 1.7.7: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, --- 4417,4423 ---- For information on a specific patchlevel of one of the versions listed, type 'help p'. For example, 'help 1.7.2p3' ! 1.8.2: 0, 1, 2, 3, 4, 5 1.8.1: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 1.8.0: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13 1.7.7: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, Index: CHANGES.182 =================================================================== *** CHANGES.182 (.../p4) (revision 927) --- CHANGES.182 (.../p5) (revision 927) *************** *** 14,19 **** --- 14,28 ---- ========================================================================== + Version 1.8.2 patchlevel 5 June 13, 2007 + + Minor changes: + * Removed the gmalloc malloc option. [SW] + * Assorted gcc warning fixes. [SW] + + Fixes: + * Cleaned up some unsafe signal handler functions. [SW] + Version 1.8.2 patchlevel 4 May 16, 2007 Minor changes: Index: hdrs/pcre.h =================================================================== *** hdrs/pcre.h (.../p4) (revision 927) --- hdrs/pcre.h (.../p5) (revision 927) *************** *** 183,188 **** --- 183,189 ---- 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: hdrs/attrib.h =================================================================== *** hdrs/attrib.h (.../p4) (revision 927) --- hdrs/attrib.h (.../p5) (revision 927) *************** *** 126,132 **** #define AF_NEARBY 0x1000000 /**< Override AF_VISUAL if remote */ #define AF_PUBLIC 0x2000000 /**< Override SAFER_UFUN */ #define AF_ANON 0x4000000 /**< INTERNAL: Attribute doesn't really ! exist in the database */ #define AF_NONAME 0x8000000 /**< No name in did_it */ #define AF_NOSPACE 0x10000000 /**< No space in did_it */ #define AF_MHEAR 0x20000000 /**< ^-listens can be triggered by %! */ --- 126,132 ---- #define AF_NEARBY 0x1000000 /**< Override AF_VISUAL if remote */ #define AF_PUBLIC 0x2000000 /**< Override SAFER_UFUN */ #define AF_ANON 0x4000000 /**< INTERNAL: Attribute doesn't really ! exist in the database */ #define AF_NONAME 0x8000000 /**< No name in did_it */ #define AF_NOSPACE 0x10000000 /**< No space in did_it */ #define AF_MHEAR 0x20000000 /**< ^-listens can be triggered by %! */ Index: hdrs/version.h =================================================================== *** hdrs/version.h (.../p4) (revision 927) --- hdrs/version.h (.../p5) (revision 927) *************** *** 1,4 **** #define VERSION "1.8.2" ! #define PATCHLEVEL "4" ! #define PATCHDATE "[04/16/2007]" ! #define NUMVERSION 1008002004 --- 1,4 ---- #define VERSION "1.8.2" ! #define PATCHLEVEL "5" ! #define PATCHDATE "[06/13/2007]" ! #define NUMVERSION 1008002005 Index: hdrs/externs.h =================================================================== *** hdrs/externs.h (.../p4) (revision 927) --- hdrs/externs.h (.../p5) (revision 927) *************** *** 480,485 **** --- 480,487 ---- const char *RESTRICT tmplate, size_t len, char *buff, char **bp); + 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__; *************** *** 569,586 **** 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 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 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) --- 571,585 ---- 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_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_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-insensitive) local wildcard match */ #define local_wild_match(s,d) local_wild_match_case(s, d, 0)