[PENNMUSH-ANNOUNCE] 1.7.4-patch14

dunemush@pennmush.org dunemush at pennmush.org
Wed, 23 Jan 2002 10:03:26 -0600


This is patch14 to PennMUSH 1.7.4. After applying this patch, you will
have version 1.7.4p14

To apply this patch, save it to a file in your top-level MUSH directory,
and do the following:
	patch -p1 < 1.7.4-patch14
	make install

If you use GNU patch 2.2, you probably want the above to be 'patch -b -p1',
not just 'patch -p1'.

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.

Then @shutdown and restart your MUSH.
    - Alan/Javelin

In this patch:

Minor Changes:
  * The global function invocation limit is now 5 times the per-evaluation
    function invocation limit, to provide some flexibility in cases
    where you run a small number of functions that cause a larger
    number of other functions to be evaluated (e.g., using tel()
    to move players into rooms with function-laden descriptions). [TAP]
Fixes:
  * Mortals are now restricted in which html tags they can generate
    when pueblo support is enabled. Suggested by BladedThoth.
  * @sitelock/name !<name> was improperly case-sensitive in its
    matching. Reported by Linda Antonsson.
  * Better invocation count checking and aborting on reaching limit.
    Reported by Ashen-Shugar. [TAP]
  * Beep characters are ignored when matching object listen patterns.
    Suggested by Wayne@PDX.
  * The end-of-dump marker is checked when reading the chat database.
    Suggested by Bellemore@M*U*S*H. [SW]
  * @lock obj=attrib:value locks were broken. Reported by Linda
    Antonsson.
  * Minor help fixes.

Prereq: 1.7.4p13
*** 1_7_4.189/Patchlevel Mon, 03 Dec 2001 10:13:02 -0600 dunemush (pennmush/5_Patchlevel 1.31 600)
--- 1_7_4.199(w)/Patchlevel Fri, 04 Jan 2002 14:27:42 -0600 dunemush (pennmush/5_Patchlevel 1.32 600)
***************
*** 1,2 ****
  Do not edit this file. It is maintained by the official PennMUSH patches.
! This is PennMUSH 1.7.4p13
--- 1,2 ----
  Do not edit this file. It is maintained by the official PennMUSH patches.
! This is PennMUSH 1.7.4p14
*** 1_7_4.189/CHANGES Mon, 03 Dec 2001 10:13:02 -0600 dunemush (pennmush/8_CHANGES 1.219.1.58 600)
--- 1_7_4.199(w)/CHANGES Tue, 15 Jan 2002 18:18:37 -0600 dunemush (pennmush/8_CHANGES 1.219.1.65 600)
***************
*** 17,22 ****
--- 17,45 ----
  
  ==========================================================================
  
+ Version 1.7.4 patchlevel 14		       January 4, 2002
+ 
+ Minor Changes:
+   * The global function invocation limit is now 5 times the per-evaluation
+     function invocation limit, to provide some flexibility in cases
+     where you run a small number of functions that cause a larger
+     number of other functions to be evaluated (e.g., using tel()
+     to move players into rooms with function-laden descriptions). [TAP]
+ Fixes:
+   * Mortals are now restricted in which html tags they can generate
+     when pueblo support is enabled. Suggested by BladedThoth.
+   * @sitelock/name !<name> was improperly case-sensitive in its
+     matching. Reported by Linda Antonsson.
+   * Better invocation count checking and aborting on reaching limit.
+     Reported by Ashen-Shugar. [TAP]
+   * Beep characters are ignored when matching object listen patterns.
+     Suggested by Wayne@PDX.
+   * The end-of-dump marker is checked when reading the chat database.
+     Suggested by Bellemore@M*U*S*H. [SW]
+   * @lock obj=attrib:value locks were broken. Reported by Linda
+     Antonsson.
+   * Minor help fixes.
+ 
  Version 1.7.4 patchlevel 13		       November 30, 2001
  
  Minor changes:
*** 1_7_4.189/game/txt/hlp/pennvers.hlp Mon, 03 Dec 2001 10:13:02 -0600 dunemush (pennmush/12_pennvers.h 1.169.1.42.1.2 600)
--- 1_7_4.199(w)/game/txt/hlp/pennvers.hlp Wed, 23 Jan 2002 09:53:18 -0600 dunemush (pennmush/12_pennvers.h 1.169.1.42.1.3 600)
***************
*** 1,5 ****
  & changes
! & 1.7.4p13
  This is a list of changes in this patchlevel which are probably of
  interest to players. More information about new commands and functions
  can probably be gotten via 'help <name of whatever>'. 'help credits'
--- 1,5 ----
  & changes
! & 1.7.4p14
  This is a list of changes in this patchlevel which are probably of
  interest to players. More information about new commands and functions
  can probably be gotten via 'help <name of whatever>'. 'help credits'
***************
*** 11,16 ****
--- 11,40 ----
  A list of the patchlevels associated with each release can
  be read in 'help patchlevels'.
  
+ Version 1.7.4 patchlevel 14		       January 4, 2002
+ 
+ Minor Changes:
+   * The global function invocation limit is now 5 times the per-evaluation
+     function invocation limit, to provide some flexibility in cases
+     where you run a small number of functions that cause a larger
+     number of other functions to be evaluated (e.g., using tel()
+     to move players into rooms with function-laden descriptions). [TAP]
+ Fixes:
+   * Mortals are now restricted in which html tags they can generate
+     when pueblo support is enabled. Suggested by BladedThoth.
+   * @sitelock/name !<name> was improperly case-sensitive in its
+     matching. Reported by Linda Antonsson.
+   * Better invocation count checking and aborting on reaching limit.
+     Reported by Ashen-Shugar. [TAP]
+   * Beep characters are ignored when matching object listen patterns.
+     Suggested by Wayne@PDX.
+   * The end-of-dump marker is checked when reading the chat database.
+     Suggested by Bellemore@M*U*S*H. [SW]
+   * @lock obj=attrib:value locks were broken. Reported by Linda
+     Antonsson.
+   * Minor help fixes.
+ 
+ & 1.7.4p13
  Version 1.7.4 patchlevel 13		       November 30, 2001
  
  Minor changes:
***************
*** 4924,4930 ****
  For information on a specific patchlevel of one of the versions listed,
  type 'help <version>p<patchlevel>'. For example, 'help 1.7.2p3'
  
! 1.7.4: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13
  1.7.3: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14
  1.7.2: 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, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35
--- 4948,4954 ----
  For information on a specific patchlevel of one of the versions listed,
  type 'help <version>p<patchlevel>'. For example, 'help 1.7.2p3'
  
! 1.7.4: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14
  1.7.3: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14
  1.7.2: 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, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35
*** 1_7_4.189/game/txt/hlp/pennpueb.hlp Tue, 04 Sep 2001 08:19:24 -0500 dunemush (pennmush/14_pennpueb.h 1.2.1.1 600)
--- 1_7_4.199(w)/game/txt/hlp/pennpueb.hlp Fri, 07 Dec 2001 23:25:44 -0600 dunemush (pennmush/14_pennpueb.h 1.2.1.3 600)
***************
*** 1,7 ****
  & PUEBLO
  & PUEBLO()
  Pueblo is a client made by Chaco (a now defunct company).
! It attempts to MIX HTML with MUSH, and does a decent job at it.
  There are other clients (notably MUSHclient) that also offer Pueblo 
  features.  If compiled into the MUSH, PennMUSH offers support for
  the enhanced features of Pueblo.
--- 1,7 ----
  & PUEBLO
  & PUEBLO()
  Pueblo is a client made by Chaco (a now defunct company).
! It attempts to mix HTML with MUSH, and does a decent job at it.
  There are other clients (notably MUSHclient) that also offer Pueblo 
  features.  If compiled into the MUSH, PennMUSH offers support for
  the enhanced features of Pueblo.
***************
*** 75,84 ****
  Each of these produces the HTML output:
    <A HREF="http://www.pennmush.org">PennMUSH</A>
  
  & HTML()
  Function: html(<string>)
  
! This will output string as a HTML Tag.
  
  Example:
    think [html(B)]
--- 75,87 ----
  Each of these produces the HTML output:
    <A HREF="http://www.pennmush.org">PennMUSH</A>
  
+ Mortals are restricted in the tags they may use. Most standard HTML
+ tags are ok; protocol-specific tags like SEND and XCH_CMD can only be
+ sent by Wizards. In addition, the html() function is Wizard-only.
  & HTML()
  Function: html(<string>)
  
! This wizard-only function will output string as a HTML Tag.
  
  Example:
    think [html(B)]
***************
*** 86,91 ****
--- 89,95 ----
  Will output (in HTML):
    <B>
  
+ Non-wizards should see the tag(), endtag(), and tagwrap() functions.
  & TAG()
  Function: tag(<name>,[param1[,param2...]])
  
*** 1_7_4.189/game/txt/hlp/pennfunc.hlp Mon, 15 Oct 2001 14:53:56 -0500 dunemush (pennmush/16_pennfunc.h 1.2.1.50.1.1.1.1.1.2.1.7.1.8.1.1.1.1.1.1 600)
--- 1_7_4.199(w)/game/txt/hlp/pennfunc.hlp Fri, 04 Jan 2002 14:26:46 -0600 dunemush (pennmush/16_pennfunc.h 1.2.1.50.1.1.1.1.1.2.1.7.1.8.1.1.1.1.1.1.1.1 600)
***************
*** 1426,1434 ****
    > say [map(strlen_fun, This is a test string)]
  
    > say [iter(lnum(3), ##, ,%r)]
!   You say, "1
!   2
!   3"
  & ILEV()
  & ITEXT()
  & INUM()
--- 1426,1434 ----
    > say [map(strlen_fun, This is a test string)]
  
    > say [iter(lnum(3), ##, ,%r)]
!   You say, "0
!   1
!   2"
  & ILEV()
  & ITEXT()
  & INUM()
*** 1_7_4.189/src/wiz.c Thu, 08 Nov 2001 14:56:16 -0600 dunemush (pennmush/b/23_wiz.c 1.44.1.1.1.1.1.2.1.7.1.1 660)
--- 1_7_4.199(w)/src/wiz.c Wed, 23 Jan 2002 09:58:48 -0600 dunemush (pennmush/b/23_wiz.c 1.44.1.1.1.1.1.2.1.7.1.1.1.1 660)
***************
*** 1823,1829 ****
  	    while (fgets(buffer, 79, fp)) {
  	      if ((p = strrchr(buffer, '\n')))
  		*p = '\0';
! 	      if (strcmp(buffer, site + 1) != 0)
  		fprintf(fptmp, "%s\n", buffer);
  	    }
  	    fclose(fp);
--- 1823,1829 ----
  	    while (fgets(buffer, 79, fp)) {
  	      if ((p = strrchr(buffer, '\n')))
  		*p = '\0';
! 	      if (strcasecmp(buffer, site + 1) != 0)
  		fprintf(fptmp, "%s\n", buffer);
  	    }
  	    fclose(fp);
*** 1_7_4.189/src/parse.c Mon, 30 Jul 2001 13:14:13 -0500 dunemush (pennmush/b/48_parse.c 1.23.1.10 660)
--- 1_7_4.199(w)/src/parse.c Wed, 23 Jan 2002 09:58:47 -0600 dunemush (pennmush/b/48_parse.c 1.23.1.10.1.2 660)
***************
*** 486,492 ****
        }
        break;
      case '%':			/* Percent substitutions */
!       if (!(eflags & PE_EVALUATE)) {
  	/* peak -- % escapes (at least) one character */
  	char savec;
  
--- 486,492 ----
        }
        break;
      case '%':			/* Percent substitutions */
!       if (!(eflags & PE_EVALUATE) || (*bp - buff >= BUFFER_LEN - 1)) {
  	/* peak -- % escapes (at least) one character */
  	char savec;
  
***************
*** 497,502 ****
--- 497,518 ----
  	  goto exit_sequence;
  	safe_chr(savec, buff, bp);
  	(*str)++;
+ 	switch (savec) {
+ 	case 'Q':
+ 	case 'q':
+ 	case 'V':
+ 	case 'v':
+ 	case 'W':
+ 	case 'w':
+ 	case 'X':
+ 	case 'x':
+ 	  /* These sequences escape two characters */
+ 	  savec = **str;
+ 	  if (!savec)
+ 	    goto exit_sequence;
+ 	  safe_chr(savec, buff, bp);
+ 	  (*str)++;
+ 	}
  	break;
        } else {
  	char savec, nextc;
***************
*** 724,729 ****
--- 740,746 ----
  	FUN *fp;
  	int temp_tflags;
  	int denied;
+ 
  	fargs = sargs;
  	for (j = 0; j < 10; j++)
  	  fargs[j] = NULL;
***************
*** 745,751 ****
  			       PE_NOTHING, PT_PAREN, pe_info);
  	    if (**str == ')')
  	      (*str)++;
! 	    goto exit_sequence;
  	  }
  	  safe_chr('(', buff, bp);
  	  if (**str == ' ') {
--- 762,768 ----
  			       PE_NOTHING, PT_PAREN, pe_info);
  	    if (**str == ')')
  	      (*str)++;
! 	    break;
  	  }
  	  safe_chr('(', buff, bp);
  	  if (**str == ' ') {
***************
*** 763,768 ****
--- 780,810 ----
  	  break;
  	}
  	*bp = startpos;
+ 
+ 	/* Check for the invocation limit */
+ 	if ((pe_info->fun_invocations >= FUNCTION_LIMIT) ||
+ 	    (global_fun_invocations >= FUNCTION_LIMIT * 5)) {
+ 	  int e_len = strlen(e_invoke);
+ 	  if ((buff + e_len > *bp) || strcmp(e_invoke, *bp - e_len))
+ 	    safe_str(T(e_invoke), buff, bp);
+ 	  process_expression(name, &tp, str,
+ 			     executor, caller, enactor,
+ 			     PE_NOTHING, PT_PAREN, pe_info);
+ 	  if (**str == ')')
+ 	    (*str)++;
+ 	  break;
+ 	}
+ 	/* Check for the recursion limit */
+ 	if ((pe_info->fun_depth + 1 >= RECURSION_LIMIT) ||
+ 	    (global_fun_recursions + 1 >= RECURSION_LIMIT * 5)) {
+ 	  safe_str(T("#-1 FUNCTION RECURSION LIMIT EXCEEDED"), buff, bp);
+ 	  process_expression(name, &tp, str,
+ 			     executor, caller, enactor,
+ 			     PE_NOTHING, PT_PAREN, pe_info);
+ 	  if (**str == ')')
+ 	    (*str)++;
+ 	  break;
+ 	}
  	/* Get the arguments */
  	temp_eflags = (eflags & ~PE_FUNCTION_MANDATORY)
  	  | PE_COMPRESS_SPACES | PE_EVALUATE | PE_FUNCTION_CHECK;
***************
*** 812,817 ****
--- 854,861 ----
  	if ((*str)[-1] != ')')
  	  (*str)--;
  	/* See if this function is enabled */
+ 	/* Can't do this check earlier, because of possible side effects
+ 	 * from the functions.  Bah. */
  	if (denied) {
  	  if (fp->flags & FN_DISABLED)
  	    safe_str(T(e_disabled), buff, bp);
***************
*** 852,870 ****
  	  } else {
  	    global_fun_recursions++;
  	    pe_info->fun_depth++;
! 	    if ((pe_info->fun_invocations >= FUNCTION_LIMIT) ||
! 		(global_fun_invocations >= FUNCTION_LIMIT)) {
! 	      int e_len = strlen(e_invoke);
! 	      if ((buff + e_len > *bp) || strcmp(e_invoke, *bp - e_len))
! 		safe_str(T(e_invoke), buff, bp);
! 	    } else if ((pe_info->fun_depth >= RECURSION_LIMIT) ||
! 		       (global_fun_recursions >= RECURSION_LIMIT)) {
! 	      safe_str(T("#-1 FUNCTION RECURSION LIMIT EXCEEDED"), buff, bp);
! 	    } else if (fp->flags & FN_BUILTIN) {
  	      global_fun_invocations++;
  	      pe_info->fun_invocations++;
! 	      fp->where.fun(buff, bp, nfargs, fargs, executor, caller, enactor,
! 			    fp->name, pe_info);
  	    } else {
  	      dbref thing;
  	      ATTR *attrib;
--- 896,906 ----
  	  } else {
  	    global_fun_recursions++;
  	    pe_info->fun_depth++;
! 	    if (fp->flags & FN_BUILTIN) {
  	      global_fun_invocations++;
  	      pe_info->fun_invocations++;
! 	      fp->where.fun(buff, bp, nfargs, fargs, executor, caller,
! 			    enactor, fp->name, pe_info);
  	    } else {
  	      dbref thing;
  	      ATTR *attrib;
*** 1_7_4.189/src/game.c Mon, 15 Oct 2001 14:53:56 -0500 dunemush (pennmush/c/10_game.c 1.50.1.8.1.1.1.1.2.1.1.1.2.1.1.4.1.1.1.1 660)
--- 1_7_4.199(w)/src/game.c Wed, 23 Jan 2002 09:58:47 -0600 dunemush (pennmush/c/10_game.c 1.50.1.8.1.1.1.1.2.1.1.1.2.1.1.4.1.1.1.1.1.1.1.1 660)
***************
*** 640,649 ****
    do_rawlog(LT_ERR, T("MUSH restarted, PID %d, at %s"),
  	    (int) getpid(), ctime(&start_time));
  
!   /* initialize all the hash tables: flags, functions, and attributes. */
    init_flag_hashtab();
    init_func_hashtab();
    init_math_hashtab();
    init_aname_hashtab();
    init_atr_name_tree();
    init_locks();
--- 640,650 ----
    do_rawlog(LT_ERR, T("MUSH restarted, PID %d, at %s"),
  	    (int) getpid(), ctime(&start_time));
  
!   /* initialize all the hash tables */
    init_flag_hashtab();
    init_func_hashtab();
    init_math_hashtab();
+   init_tag_hashtab();
    init_aname_hashtab();
    init_atr_name_tree();
    init_locks();
***************
*** 1891,1896 ****
--- 1892,1898 ----
  extern HASHTAB htab_function;
  extern HASHTAB htab_user_function;
  extern HASHTAB htab_math;
+ extern HASHTAB htab_tag;
  extern HASHTAB htab_player_list;
  extern HASHTAB htab_reserved_aliases;
  extern HASHTAB help_files;
***************
*** 1910,1915 ****
--- 1912,1918 ----
    hash_stats(player, &htab_function, "Functions");
    hash_stats(player, &htab_user_function, "@Functions");
    hash_stats(player, &htab_math, "Math funs");
+   hash_stats(player, &htab_tag, "HTML tags");
    hash_stats(player, &htab_player_list, "Players");
    hash_stats(player, &htab_reserved_aliases, "Aliases");
    hash_stats(player, &help_files, "HelpFiles");
*** 1_7_4.189/src/funstr.c Wed, 24 Oct 2001 10:41:46 -0500 dunemush (pennmush/c/13_funstr.c 1.28.1.1.1.2.1.4.1.6.1.1.1.1.1.2 660)
--- 1_7_4.199(w)/src/funstr.c Wed, 23 Jan 2002 09:58:46 -0600 dunemush (pennmush/c/13_funstr.c 1.28.1.1.1.2.1.4.1.6.1.1.1.1.1.2.1.1.1.1.1.1 660)
***************
*** 18,23 ****
--- 18,24 ----
  #include "flags.h"
  #include "dbdefs.h"
  #include "mushdb.h"
+ #include "htab.h"
  #include "lock.h"
  #include "confmagic.h"
  
***************
*** 25,30 ****
--- 26,33 ----
  #pragma warning( disable : 4761)	/* NJG: disable warning re conversion */
  #endif
  
+ HASHTAB htab_tag;
+ 
  static int wraplen _((char *str, int maxlen));
  
  int
***************
*** 960,997 ****
      safe_chr(BEEP_CHAR, buff, bp);
  }
  
  /* ARGSUSED */
  FUNCTION(fun_html)
  {
!   safe_tag(args[0], buff, bp);
  }
  
  /* ARGSUSED */
  FUNCTION(fun_tag)
  {
    int i;
!   safe_chr(TAG_START, buff, bp);
!   safe_str(args[0], buff, bp);
!   for (i = 1; i < nargs; i++) {
!     safe_chr(' ', buff, bp);
!     safe_str(args[i], buff, bp);
    }
-   safe_chr(TAG_END, buff, bp);
  }
  
  /* ARGSUSED */
  FUNCTION(fun_endtag)
  {
!   safe_tag_cancel(args[0], buff, bp);
  }
  
  /* ARGSUSED */
  FUNCTION(fun_tagwrap)
  {
!   if (nargs == 2)
!     safe_tag_wrap(args[0], NULL, args[1], buff, bp);
!   else
!     safe_tag_wrap(args[0], args[1], args[2], buff, bp);
  }
  
  #define COL_FLASH       (1)
--- 963,1038 ----
      safe_chr(BEEP_CHAR, buff, bp);
  }
  
+ /* All the safe tags from HTML 4.0 */
+ void
+ init_tag_hashtab()
+ {
+   static char dummy = 1;
+   int i = 0;
+   static const char *safetags[] = { "A", "B", "I", "U", "STRONG", "EM",
+     "ADDRESS", "BLOCKQUOTE", "CENTER", "DEL", "DIV",
+     "H1", "H2", "H3", "H4", "H5", "H6", "HR", "INS",
+     "P", "PRE", "DIR", "DL", "DT", "DD", "LI", "MENU", "OL", "UL",
+     "TABLE", "CAPTION", "COLGROUP", "COL", "THEAD", "TFOOT",
+     "TBODY", "TR", "TD", "TH",
+     "BR", "FONT", "IMG", "SPAN", "SUB", "SUP",
+     "ABBR", "ACRONYM", "CITE", "CODE", "DFN", "KBD", "SAMP", "VAR",
+     "BIG", "S", "SMALL", "STRIKE", "TT",
+     NULL
+   };
+   hashinit(&htab_tag, 64, 1);
+   while (safetags[i]) {
+     hashadd(safetags[i], (void *) &dummy, &htab_tag);
+     i++;
+   }
+ }
+ 
  /* ARGSUSED */
  FUNCTION(fun_html)
  {
!   if (!Wizard(executor))
!     safe_str(T(e_perm), buff, bp);
!   else
!     safe_tag(args[0], buff, bp);
  }
  
  /* ARGSUSED */
  FUNCTION(fun_tag)
  {
    int i;
!   if (!Wizard(executor) && !hash_find(&htab_tag, strupper(args[0])))
!     safe_str("#-1", buff, bp);
!   else {
!     safe_chr(TAG_START, buff, bp);
!     safe_str(args[0], buff, bp);
!     for (i = 1; i < nargs; i++) {
!       safe_chr(' ', buff, bp);
!       safe_str(args[i], buff, bp);
!     }
!     safe_chr(TAG_END, buff, bp);
    }
  }
  
  /* ARGSUSED */
  FUNCTION(fun_endtag)
  {
!   if (!Wizard(executor) && !hash_find(&htab_tag, strupper(args[0])))
!     safe_str("#-1", buff, bp);
!   else
!     safe_tag_cancel(args[0], buff, bp);
  }
  
  /* ARGSUSED */
  FUNCTION(fun_tagwrap)
  {
!   if (!Wizard(executor) && !hash_find(&htab_tag, strupper(args[0])))
!     safe_str("#-1", buff, bp);
!   else {
!     if (nargs == 2)
!       safe_tag_wrap(args[0], NULL, args[1], buff, bp);
!     else
!       safe_tag_wrap(args[0], args[1], args[2], buff, bp);
!   }
  }
  
  #define COL_FLASH       (1)
*** 1_7_4.189/src/funlist.c Tue, 25 Sep 2001 15:42:13 -0500 dunemush (pennmush/c/16_funlist.c 1.3.1.1.1.5.1.2.1.1.1.1.1.4.1.2.1.2.1.19.1.2.1.1.1.2.1.5.1.1 660)
--- 1_7_4.199(w)/src/funlist.c Wed, 23 Jan 2002 09:58:46 -0600 dunemush (pennmush/c/16_funlist.c 1.3.1.1.1.5.1.2.1.1.1.1.1.4.1.2.1.2.1.19.1.2.1.1.1.2.1.5.1.1.1.1.1.1 660)
***************
*** 351,356 ****
--- 351,357 ----
    char *cp;
    char *tptr[2];
    char sep;
+   int funccount;
  
    if (!delim_check(buff, bp, nargs, args, 4, &sep))
      return;
***************
*** 391,396 ****
--- 392,398 ----
  		     PE_DEFAULT, PT_DEFAULT, pe_info);
    *rp = '\0';
    strcpy(rsave, result);
+   funccount = pe_info->fun_invocations;
  
    /* handle the rest of the cases */
    while (cp && *cp) {
***************
*** 401,406 ****
--- 403,412 ----
      process_expression(result, &rp, &ap, thing, executor, enactor,
  		       PE_DEFAULT, PT_DEFAULT, pe_info);
      *rp = '\0';
+     if (pe_info->fun_invocations >= FUNCTION_LIMIT &&
+ 	pe_info->fun_invocations == funccount && !strcmp(rsave, result))
+       break;
+     funccount = pe_info->fun_invocations;
      strcpy(rsave, result);
    }
    safe_str(rsave, buff, bp);
*** 1_7_4.189/src/extmail.c Tue, 25 Sep 2001 16:27:49 -0500 dunemush (pennmush/c/22_extmail.c 1.44.1.6 660)
--- 1_7_4.199(w)/src/extmail.c Wed, 23 Jan 2002 09:58:46 -0600 dunemush (pennmush/c/22_extmail.c 1.44.1.7 660)
***************
*** 1855,1861 ****
      count++;
    }
  
!   OUTPUT(fprintf(fp, "***END OF DUMP***\n"));
    fflush(fp);
  
    if (count != mdb_top) {
--- 1855,1861 ----
      count++;
    }
  
!   OUTPUT(fputs(EOD, fp));
    fflush(fp);
  
    if (count != mdb_top) {
***************
*** 1974,1985 ****
    if (!mail_top) {
      /* mail_top could be 0 from an error or actually be 0. */
      if (nbuf1[0] == '0' && nbuf1[1] == '\n') {
!       char eodbuf[20];
!       fgets(eodbuf, sizeof(eodbuf), fp);
!       if (eodbuf && !strcmp(eodbuf, (mail_flags & MDBF_NEW_EOD)
! 			    ? "***END OF DUMP***\n" : "*** END OF DUMP ***\n"))
  	return 1;
!       do_rawlog(LT_ERR, T("MAIL: Trailing garbage in the mail database."));
      }
      return 0;
    }
--- 1974,1989 ----
    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];
!       fgets(buff, sizeof buff, fp);
!       if (!buff)
! 	do_rawlog(LT_ERR,
! 		  T("MAIL: Missing end-of-dump marker in mail database."));
!       else if (strcmp(buff, (mail_flags & MDBF_NEW_EOD)
! 		      ? "***END OF DUMP***\n" : "*** END OF DUMP ***\n") == 0)
  	return 1;
!       else
! 	do_rawlog(LT_ERR, T("MAIL: Trailing garbage in the mail database."));
      }
      return 0;
    }
***************
*** 2068,2080 ****
  	      mail_top, i);
    }
    {
!     char eodbuf[20];
!     fgets(eodbuf, sizeof(eodbuf), fp);
!     if (!(eodbuf && !strcmp(eodbuf, (mail_flags & MDBF_NEW_EOD)
! 			    ? "***END OF DUMP***\n" : "*** END OF DUMP ***\n"))) {
        /* There's still stuff. Icky. */
        do_rawlog(LT_ERR, T("MAIL: Trailing garbage in the mail database."));
-     }
    }
  
    do_mail_debug(GOD, (char *) "fix", (char *) "");
--- 2072,2086 ----
  	      mail_top, i);
    }
    {
!     char buff[20];
!     fgets(buff, sizeof buff, fp);
!     if (!buff)
!       do_rawlog(LT_ERR,
! 		T("MAIL: Missing end-of-dump marker in mail database."));
!     else if (strcmp(buff, (mail_flags & MDBF_NEW_EOD)
! 		    ? EOD : "*** END OF DUMP ***\n") != 0)
        /* There's still stuff. Icky. */
        do_rawlog(LT_ERR, T("MAIL: Trailing garbage in the mail database."));
    }
  
    do_mail_debug(GOD, (char *) "fix", (char *) "");
*** 1_7_4.189/src/extchat.c Mon, 03 Dec 2001 10:13:02 -0600 dunemush (pennmush/c/23_extchat.c 1.1.1.1.1.1.1.1.1.2.1.1.1.3.1.1.1.5.1.1.1.1.1.5.1.2.1.3.1.3.1.1.1.4.1.2.1.6.1.2.1.1.2.4.2.9.1.2.1.2.1.3.1.2.1.2.1.1 660)
--- 1_7_4.199(w)/src/extchat.c Wed, 23 Jan 2002 09:58:46 -0600 dunemush (pennmush/c/23_extchat.c 1.1.1.1.1.1.1.1.1.2.1.1.1.3.1.1.1.5.1.1.1.1.1.5.1.2.1.3.1.3.1.1.1.4.1.2.1.6.1.2.1.1.2.4.2.9.1.2.1.2.1.3.1.2.1.2.1.1.1.1 660)
***************
*** 149,154 ****
--- 149,155 ----
  {
    int i;
    CHAN *ch;
+   char buff[20];
  
    /* How many channels? */
    num_channels = getref(fp);
***************
*** 170,176 ****
      insert_channel(&ch);
    }
    num_channels = i;
!   /* There may be an END OF DUMP line, but we ignore it */
  
    return 1;
  }
--- 171,183 ----
      insert_channel(&ch);
    }
    num_channels = i;
! 
!   /* Check for **END OF DUMP*** */
!   fgets(buff, sizeof buff, fp);
!   if (!buff)
!     do_rawlog(LT_ERR, T("CHAT: No end-of-dump marker in the chat database."));
!   else if (strcmp(buff, EOD) != 0)
!     do_rawlog(LT_ERR, T("CHAT: Trailing garbage in the chat database."));
  
    return 1;
  }
***************
*** 580,586 ****
    for (ch = channels; ch; ch = ch->next) {
      save_channel(fp, ch);
    }
!   OUTPUT(fputs("***END OF DUMP***\n", fp));
    return 1;
  }
  
--- 587,593 ----
    for (ch = channels; ch; ch = ch->next) {
      save_channel(fp, ch);
    }
!   OUTPUT(fputs(EOD, fp));
    return 1;
  }
  
*** 1_7_4.189/src/db.c Sat, 17 Feb 2001 10:56:52 -0600 dunemush (pennmush/c/25_db.c 1.26 660)
--- 1_7_4.199(w)/src/db.c Wed, 23 Jan 2002 09:58:46 -0600 dunemush (pennmush/c/25_db.c 1.26.1.1 660)
***************
*** 65,70 ****
--- 65,72 ----
  
  dbref errobj;
  
+ const char *EOD = "***END OF DUMP***\n";
+ 
  #ifndef DB_INITIAL_SIZE
  #define DB_INITIAL_SIZE 5000
  #endif				/* DB_INITIAL_SIZE */
***************
*** 489,495 ****
      OUTPUT(fprintf(f, "!%d\n", i));
      db_write_object(f, i);
    }
!   OUTPUT(fputs("***END OF DUMP***\n", f));
  /*  fflush(f); */
    return (db_top);
  }
--- 491,497 ----
      OUTPUT(fprintf(f, "!%d\n", i));
      db_write_object(f, i);
    }
!   OUTPUT(fputs(EOD, f));
  /*  fflush(f); */
    return (db_top);
  }
***************
*** 663,669 ****
      if (i % paranoid_checkpt == 0)
        do_rawlog(LT_CHECK, T("\t...wrote up to object #%d\n"), i);
    }
!   OUTPUT(fputs("***END OF DUMP***\n", 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);
--- 665,671 ----
      if (i % paranoid_checkpt == 0)
        do_rawlog(LT_CHECK, T("\t...wrote up to object #%d\n"), i);
    }
!   OUTPUT(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);
***************
*** 1235,1241 ****
    int c;
    dbref i;
    struct object *o;
-   const char *end;
  #ifdef ADD_POWERS
    int flags, toggles, powers;
  #endif
--- 1237,1242 ----
***************
*** 1442,1453 ****
        break;
  
      case '*':
!       end = getstring_noalloc(f);
!       if (!strcmp(end, "***END OF DUMP***")) {
! 	do_rawlog(LT_ERR, T("ERROR: No end of dump %d"), i);
! 	return -1;
!       } else {
! 	{
  	  do_rawlog(LT_ERR, "READING: done");
  	  fix_free_list();
  	  if (!(indb_flags & DBF_NEW_LOCKS))
--- 1443,1456 ----
        break;
  
      case '*':
!       {
! 	char buff[80];
! 	ungetc('*', f);
! 	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;
! 	} else {
  	  do_rawlog(LT_ERR, "READING: done");
  	  fix_free_list();
  	  if (!(indb_flags & DBF_NEW_LOCKS))
*** 1_7_4.189/src/bsd.c Mon, 05 Nov 2001 10:50:45 -0600 dunemush (pennmush/c/38_bsd.c 1.58.1.11.1.2.1.5.1.7.1.14.1.13.1.9.1.4.1.2.1.12.1.1.1.1.1.2.1.1.1.13.1.1.1.1.1.1.1.1 660)
--- 1_7_4.199(w)/src/bsd.c Wed, 23 Jan 2002 09:58:45 -0600 dunemush (pennmush/c/38_bsd.c 1.58.1.11.1.2.1.5.1.7.1.14.1.13.1.9.1.4.1.2.1.12.1.1.1.1.1.2.1.1.1.13.1.1.1.1.1.1.1.1.1.1 660)
***************
*** 1117,1122 ****
--- 1117,1123 ----
  	  p++;
  	break;
        case '\r':
+       case BEEP_CHAR:
  	break;
        case ESC_CHAR:
  	while (*p && *p != 'm')
*** 1_7_4.189/src/boolexp.c Mon, 26 Feb 2001 11:53:44 -0600 dunemush (pennmush/c/39_boolexp.c 1.1.1.17 660)
--- 1_7_4.199(w)/src/boolexp.c Wed, 23 Jan 2002 09:58:45 -0600 dunemush (pennmush/c/39_boolexp.c 1.1.1.17 660)
***************
*** 262,269 ****
      case BOOLEXP_OWNER:
        return (Owner(b->sub1->thing) == Owner(player));
      case BOOLEXP_ATR:
!       a = atr_complete_match(player, b->atr_lock->name, target);
!       if (!a)
  	return 0;
        strcpy(tbuf1, uncompress(b->atr_lock->text));
        strcpy(tbuf2, uncompress(a->value));
--- 262,269 ----
      case BOOLEXP_OWNER:
        return (Owner(b->sub1->thing) == Owner(player));
      case BOOLEXP_ATR:
!       a = atr_get(player, b->atr_lock->name);
!       if (!a || !Can_Read_Attr(target, player, a))
  	return 0;
        strcpy(tbuf1, uncompress(b->atr_lock->text));
        strcpy(tbuf2, uncompress(a->value));
*** 1_7_4.189/src/attrib.c Wed, 24 Oct 2001 10:41:46 -0500 dunemush (pennmush/c/40_attrib.c 1.15.1.2.1.5.1.1.1.3.1.3.1.2.1.2.1.2.2.1.1.2.1.2.1.2 660)
--- 1_7_4.199(w)/src/attrib.c Wed, 23 Jan 2002 09:58:45 -0600 dunemush (pennmush/c/40_attrib.c 1.15.1.2.1.5.1.1.1.3.1.3.1.2.1.2.1.2.2.1.1.2.1.2.1.2 660)
***************
*** 528,533 ****
--- 528,534 ----
    return result;
  }
  
+ #ifdef NEVER
  ATTR *
  atr_complete_match(player, atr, privs)
      dbref player;
***************
*** 548,553 ****
--- 549,555 ----
  
    return NULL;
  }
+ #endif
  
  void
  atr_free(thing)
*** 1_7_4.189/hdrs/version.h Mon, 03 Dec 2001 10:13:02 -0600 dunemush (pennmush/c/47_version.h 1.32.1.2.1.7.1.9.1.1.1.1.1.2 660)
--- 1_7_4.199(w)/hdrs/version.h Wed, 23 Jan 2002 09:58:49 -0600 dunemush (pennmush/c/47_version.h 1.32.1.2.1.7.1.9.1.1.1.1.1.3 660)
***************
*** 1,2 ****
! #define VERSION "PennMUSH version 1.7.4 patchlevel 13 [11/30/2001]"
! #define SHORTVN "PennMUSH 1.7.4p13"
--- 1,2 ----
! #define VERSION "PennMUSH version 1.7.4 patchlevel 14 [01/04/2002]"
! #define SHORTVN "PennMUSH 1.7.4p14"
*** 1_7_4.189/hdrs/game.h Thu, 08 Nov 2001 14:56:16 -0600 dunemush (pennmush/d/12_game.h 1.28.1.2.1.1 660)
--- 1_7_4.199(w)/hdrs/game.h Wed, 23 Jan 2002 09:58:48 -0600 dunemush (pennmush/d/12_game.h 1.28.1.2.1.1.1.1.1.1 660)
***************
*** 17,22 ****
--- 17,23 ----
  extern void init_math_hashtab _((void));	/* funmath.c */
  extern void init_aname_hashtab _((void));	/* atr_tab.c */
  extern void init_flag_hashtab _((void));	/* flags.c */
+ extern void init_tag_hashtab _((void));	/* funstr.c */
  
  /* From bsd.c */
  extern void fcache_init _((void));
*** 1_7_4.189/hdrs/dbdefs.h Wed, 13 Sep 2000 14:49:45 -0500 dunemush (pennmush/d/18_dbdefs.h 1.1.1.1.1.1.1.1.1.1.1.2 660)
--- 1_7_4.199(w)/hdrs/dbdefs.h Wed, 23 Jan 2002 09:58:48 -0600 dunemush (pennmush/d/18_dbdefs.h 1.1.1.1.1.1.1.1.1.1.1.2.2.1 660)
***************
*** 318,321 ****
--- 318,323 ----
  
  #endif				/* USE_MAILER */
  
+ extern const char *EOD;
+ 
  #endif				/* __DBDEFS_H */
*** 1_7_4.189/win32/funs.h Tue, 13 Nov 2001 17:29:19 -0600 dunemush (pennmush/f/12_funs.h 1.11.1.9.2.8.2.1.1.1.1.2.1.1.1.1.1.1 660)
--- 1_7_4.199(w)/win32/funs.h Wed, 23 Jan 2002 09:58:45 -0600 dunemush (pennmush/f/12_funs.h 1.11.1.9.2.8.2.1.1.1.1.2.1.1.1.1.1.1 660)
***************
*** 292,294 ****
--- 292,295 ----
  FUNCTION_PROTO(fun_zemit);
  FUNCTION_PROTO(fun_zfun);
  FUNCTION_PROTO(fun_zone);
+ FUNCTION_PROTO(local_fun_silly);
*** 1_7_4.189/win32/cmds.h Tue, 13 Nov 2001 17:29:19 -0600 dunemush (pennmush/f/15_cmds.h 1.9.1.4.1.1.1.1.1.1.1.1.2.1.1.1.2.1.1.2.1.1.1.1 660)
--- 1_7_4.199(w)/win32/cmds.h Wed, 23 Jan 2002 09:58:45 -0600 dunemush (pennmush/f/15_cmds.h 1.9.1.4.1.1.1.1.1.1.1.1.2.1.1.1.2.1.1.2.1.1.1.1 660)
***************
*** 60,65 ****
--- 60,66 ----
  COMMAND_PROTO(cmd_link);
  COMMAND_PROTO(cmd_list);
  COMMAND_PROTO(cmd_listmotd);
+ COMMAND_PROTO(cmd_local_silly);
  COMMAND_PROTO(cmd_lock);
  COMMAND_PROTO(cmd_log);
  COMMAND_PROTO(cmd_logwipe);