[PENNMUSH-ANNOUNCE] 1.7.7-patch18

dunemush at tala.mede.uic.edu dunemush at tala.mede.uic.edu
Wed Aug 20 00:45:44 CDT 2003


THIS PATCH FIXES A SECURITY BUG INTRODUCED IN 1.7.7p17 - IF YOU USE
1.7.7p17, PLEASE UPGRADE!

This is patch18 to PennMUSH 1.7.7. After applying this patch, you will
have version 1.7.7p18

To apply this patch, save it to a file in your top-level MUSH directory,
and do the following:
	patch -p1 < 1.7.7-patch18
	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. On the off chance they appear not to be, simply
rm them and re-run make.

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

In this patch:

Major Changes:
  * The flag handling code has been additionally abstracted to 
    allow, in a future patchlevel, @powers to be handled in the
    same way that flags are now.
Minor Changes:
  * Wrap the OS-dependant code for making sure the mush always has a free
    file descriptor available for use in a pair of functions. [SW]
Fixes:
  * Linted some ssl-related warnings. Reported by Cheetah at M*U*S*H.
  * Compile failed in timer.c unless USE_MAILER was defined.
    Reported by Sunny at M*U*S*H.
  * Bug allowing players to view internal and mortal_dark attributes
    introduced in p17 has been fixed. [TAP]


Prereq: 1.7.7p17
*** 1_7_7.551/Patchlevel Mon, 11 Aug 2003 16:14:42 -0500 dunemush (pennmush/5_Patchlevel 1.17.1.11.1.19 600)
--- 1_7_7.557(w)/Patchlevel Tue, 19 Aug 2003 17:49:34 -0500 dunemush (pennmush/5_Patchlevel 1.17.1.11.1.20 600)
***************
*** 1,2 ****
  Do not edit this file. It is maintained by the official PennMUSH patches.
! This is PennMUSH 1.7.7p17
--- 1,2 ----
  Do not edit this file. It is maintained by the official PennMUSH patches.
! This is PennMUSH 1.7.7p18
*** 1_7_7.551/CHANGES.177 Sun, 17 Aug 2003 08:30:54 -0500 dunemush (pennmush/g/23_CHANGES 1.48.1.128 600)
--- 1_7_7.557(w)/CHANGES.177 Tue, 19 Aug 2003 17:49:55 -0500 dunemush (pennmush/g/23_CHANGES 1.48.1.133 600)
***************
*** 18,23 ****
--- 18,40 ----
  
  ==========================================================================
  
+ Version 1.7.7 patchlevel 18                     August 19, 2003
+ 
+ Major Changes:
+   * The flag handling code has been additionally abstracted to 
+     allow, in a future patchlevel, @powers to be handled in the
+     same way that flags are now.
+ Minor Changes:
+   * Wrap the OS-dependant code for making sure the mush always has a free
+     file descriptor available for use in a pair of functions. [SW]
+ Fixes:
+   * Linted some ssl-related warnings. Reported by Cheetah at M*U*S*H.
+   * Compile failed in timer.c unless USE_MAILER was defined.
+     Reported by Sunny at M*U*S*H.
+   * Bug allowing players to view internal and mortal_dark attributes
+     introduced in p17 has been fixed. [TAP]
+ 
+ 
  Version 1.7.7 patchlevel 17                     August 11, 2003
  
  Major changes:
*** 1_7_7.551/src/wiz.c Thu, 17 Jul 2003 16:30:15 -0500 dunemush (pennmush/b/23_wiz.c 1.44.1.1.1.1.1.2.1.7.1.1.1.1.1.1.1.1.1.1.1.8.1.2.2.2.1.2.1.1.1.1.1.1.1.2.1.1.1.2.2.14 660)
--- 1_7_7.557(w)/src/wiz.c Tue, 19 Aug 2003 23:36:08 -0500 dunemush (pennmush/b/23_wiz.c 1.44.1.1.1.1.1.2.1.7.1.1.1.1.1.1.1.1.1.1.1.8.1.2.2.2.1.2.1.1.1.1.1.1.1.2.1.1.1.2.2.16 660)
***************
*** 64,70 ****
  #ifdef I_SYS_FILE
  #include <sys/file.h>
  #endif
- extern int reserved;
  #endif
  
  static int tport_dest_ok(dbref player, dbref victim, dbref dest);
--- 64,69 ----
***************
*** 990,996 ****
  
    notify(player, object_header(player, thing));
    notify_format(player, T("Flags value: %s"),
! 		bits_to_string(Flags(thing), GOD, NOTHING));
    notify_format(player, T("Powers value: 0x%08x"), Powers(thing));
  
    notify_format(player, "Next: %d", Next(thing));
--- 989,995 ----
  
    notify(player, object_header(player, thing));
    notify_format(player, T("Flags value: %s"),
! 		bits_to_string("FLAG", Flags(thing), GOD, NOTHING));
    notify_format(player, T("Powers value: 0x%08x"), Powers(thing));
  
    notify_format(player, "Next: %d", Next(thing));
***************
*** 1626,1633 ****
      for (n = low; n <= high; n++) {
        if ((restrict_owner == ANY_OWNER || Owner(n) == restrict_owner)
  	  && (restrict_type == NOTYPE || Typeof(n) == restrict_type)
! 	  && ((sclass == S_FLAG) ? flaglist_check(player, n, restriction, 1)
! 	      : flaglist_check_long(player, n, restriction, 1))) {
  	if (nresults >= result_size) {
  	  dbref *newresults;
  	  result_size *= 2;
--- 1625,1633 ----
      for (n = low; n <= high; n++) {
        if ((restrict_owner == ANY_OWNER || Owner(n) == restrict_owner)
  	  && (restrict_type == NOTYPE || Typeof(n) == restrict_type)
! 	  && ((sclass == S_FLAG) ?
! 	      flaglist_check("FLAG", player, n, restriction, 1)
! 	      : flaglist_check_long("FLAG", player, n, restriction, 1))) {
  	if (nresults >= result_size) {
  	  dbref *newresults;
  	  result_size *= 2;
***************
*** 1812,1820 ****
      case 2:
        if (!site || !*site) {
  	/* List bad names */
! #ifndef WIN32
! 	close(reserved);
! #endif
  #ifdef macintosh
  	if ((fp = fopen(NAMES_FILE, "rb")) == NULL) {
  #else
--- 1812,1818 ----
      case 2:
        if (!site || !*site) {
  	/* List bad names */
! 	release_fd();
  #ifdef macintosh
  	if ((fp = fopen(NAMES_FILE, "rb")) == NULL) {
  #else
***************
*** 1829,1843 ****
  	  }
  	  fclose(fp);
  	}
! #ifndef WIN32
! 	reserved = open("/dev/null", O_RDWR);
! #endif
  	return;
        }
        if (site[0] == '!') {	/* Delete a name */
! #ifndef WIN32
! 	close(reserved);
! #endif
  #ifdef macintosh
  	if ((fp = fopen(NAMES_FILE, "rb")) != NULL) {
  	  if ((fptmp = fopen("tmp.tmp", "wb")) == NULL) {
--- 1827,1837 ----
  	  }
  	  fclose(fp);
  	}
! 	reserve_fd();
  	return;
        }
        if (site[0] == '!') {	/* Delete a name */
! 	release_fd();
  #ifdef macintosh
  	if ((fp = fopen(NAMES_FILE, "rb")) != NULL) {
  	  if ((fptmp = fopen("tmp.tmp", "wb")) == NULL) {
***************
*** 1870,1884 ****
  	  }
  	} else
  	  notify(player, T("Unable to delete name."));
! #ifndef WIN32
! 	reserved = open("/dev/null", O_RDWR);
! #endif
! 	return;
        }
        /* Add a name */
! #ifndef WIN32
!       close(reserved);
! #endif
  #ifdef macintosh
        if ((fp = fopen(NAMES_FILE, "ab")) != NULL) {
  #else
--- 1864,1873 ----
  	  }
  	} else
  	  notify(player, T("Unable to delete name."));
! 	reserve_fd();
        }
        /* Add a name */
!       release_fd();
  #ifdef macintosh
        if ((fp = fopen(NAMES_FILE, "ab")) != NULL) {
  #else
***************
*** 1892,1900 ****
        } else {
  	notify(player, T("Error writing to file."));
        }
! #ifndef WIN32
!       reserved = open("/dev/null", O_RDWR);
! #endif
        break;
      }
    }
--- 1881,1887 ----
        } else {
  	notify(player, T("Error writing to file."));
        }
!       reserve_fd();
        break;
      }
    }
*** 1_7_7.551/src/timer.c Sun, 17 Aug 2003 08:30:54 -0500 dunemush (pennmush/b/29_timer.c 1.29.1.7.1.11 660)
--- 1_7_7.557(w)/src/timer.c Tue, 19 Aug 2003 23:36:07 -0500 dunemush (pennmush/b/29_timer.c 1.29.1.7.1.12 660)
***************
*** 123,129 ****
--- 123,131 ----
    int actual;
    ATTR *aptr;
    lock_list *lptr;
+ #ifdef USE_MAILER
    MAIL *mp;
+ #endif
  
    if (db_top == 0)
      return;
***************
*** 137,147 ****
--- 139,151 ----
      for (lptr = Locks(end_obj); lptr; lptr = L_NEXT(lptr))
        if (L_KEY(lptr) != NULL_CHUNK_REFERENCE)
  	actual++;
+ #ifdef USE_MAILER
      if (IsPlayer(end_obj)) {
        for (mp = find_exact_starting_point(end_obj); mp; mp = mp->next)
  	if (mp->msgid != NULL_CHUNK_REFERENCE)
  	  actual++;
      }
+ #endif
      end_obj = (end_obj + 1) % db_top;
    } while (actual < amount && end_obj != start_obj);
  
***************
*** 175,180 ****
--- 179,185 ----
  	refs[actual] = &(lptr->key);
  	actual++;
        }
+ #ifdef USE_MAILER
      if (IsPlayer(start_obj)) {
        for (mp = find_exact_starting_point(start_obj); mp; mp = mp->next)
  	if (mp->msgid != NULL_CHUNK_REFERENCE) {
***************
*** 182,187 ****
--- 187,193 ----
  	  actual++;
  	}
      }
+ #endif
      start_obj = (start_obj + 1) % db_top;
    } while (start_obj != end_obj);
  
*** 1_7_7.551/src/player.c Mon, 23 Jun 2003 16:03:37 -0500 dunemush (pennmush/b/47_player.c 1.15.1.1.1.1.1.4.1.6.1.1.1.2 660)
--- 1_7_7.557(w)/src/player.c Tue, 19 Aug 2003 23:36:03 -0500 dunemush (pennmush/b/47_player.c 1.15.1.1.1.1.1.4.1.6.1.1.1.4 660)
***************
*** 46,53 ****
  #include "extmail.h"
  #include "confmagic.h"
  
- extern int reserved;
- 
  dbref email_register_player
    (const char *name, const char *email, const char *host, const char *ip);
  static dbref make_player
--- 46,51 ----
***************
*** 317,325 ****
     *  1) We'll use sendmail -t, so we don't pass user-given values to a shell.
     */
  
! #ifndef WIN32
!   close(reserved);
! #endif
    if ((fp =
  #ifdef __LCC__
         (FILE *)
--- 315,321 ----
     *  1) We'll use sendmail -t, so we don't pass user-given values to a shell.
     */
  
!   release_fd();
    if ((fp =
  #ifdef __LCC__
         (FILE *)
***************
*** 328,336 ****
      do_log(LT_CONN, 0, 0,
  	   T("Failed registration of %s by %s: unable to open sendmail"),
  	   name, email);
! #ifndef WIN32
!     reserved = open("/dev/null", O_RDWR);
! #endif
      return NOTHING;
    }
    fprintf(fp, T("Subject: [%s] Registration of %s\n"), MUDNAME, name);
--- 324,330 ----
      do_log(LT_CONN, 0, 0,
  	   T("Failed registration of %s by %s: unable to open sendmail"),
  	   name, email);
!     reserve_fd();
      return NOTHING;
    }
    fprintf(fp, T("Subject: [%s] Registration of %s\n"), MUDNAME, name);
***************
*** 347,355 ****
    fprintf(fp, "\tconnect %s %s\n", name, passwd);
    fprintf(fp, "\n");
    pclose(fp);
! #ifndef WIN32
!   reserved = open("/dev/null", O_RDWR);
! #endif
    /* Ok, all's well, make a player */
    player = make_player(name, passwd, host, ip);
    (void) atr_add(player, "REGISTERED_EMAIL", email, GOD, NOTHING);
--- 341,347 ----
    fprintf(fp, "\tconnect %s %s\n", name, passwd);
    fprintf(fp, "\n");
    pclose(fp);
!   reserve_fd();
    /* Ok, all's well, make a player */
    player = make_player(name, passwd, host, ip);
    (void) atr_add(player, "REGISTERED_EMAIL", email, GOD, NOTHING);
***************
*** 385,392 ****
    Owner(player) = player;
    Parent(player) = NOTHING;
    Type(player) = TYPE_PLAYER;
!   flags = string_to_bits(options.player_flags);
!   copy_flag_bitmask(Flags(player), flags);
    destroy_flag_bitmask(flags);
    if (Suspect_Site(host, player) || Suspect_Site(ip, player))
      set_flag_internal(player, "SUSPECT");
--- 377,384 ----
    Owner(player) = player;
    Parent(player) = NOTHING;
    Type(player) = TYPE_PLAYER;
!   flags = string_to_bits("FLAG", options.player_flags);
!   copy_flag_bitmask("FLAG", Flags(player), flags);
    destroy_flag_bitmask(flags);
    if (Suspect_Site(host, player) || Suspect_Site(ip, player))
      set_flag_internal(player, "SUSPECT");
*** 1_7_7.551/src/game.c Mon, 11 Aug 2003 15:42:46 -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.1.1.1.1.1.1.2.1.1.2.1.1.1.1.1.1.1.2.1.1.1.2.1.1.1.1.1.1.1.1.1.5.1.3.1.2.1.2.1.1.1.1.1.1.1.1.1.10 660)
--- 1_7_7.557(w)/src/game.c Tue, 19 Aug 2003 23:36:02 -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.1.1.1.1.1.1.2.1.1.2.1.1.1.1.1.1.1.2.1.1.1.2.1.1.1.1.1.1.1.1.1.5.1.3.1.2.1.2.1.1.1.1.1.1.1.1.1.12 660)
***************
*** 101,107 ****
  time_t last_dump_time = 0;	/**< Time of last successful db save */
  int reboot_count = 0;		/**< Number of reboots so far */
  static int epoch = 0;
! int reserved;			/**< Reserved file descriptor */
  int depth = 0;			/**< excessive recursion prevention */
  extern dbref cplr;
  extern char ccom[];
--- 101,107 ----
  time_t last_dump_time = 0;	/**< Time of last successful db save */
  int reboot_count = 0;		/**< Number of reboots so far */
  static int epoch = 0;
! static int reserved;			/**< Reserved file descriptor */
  int depth = 0;			/**< excessive recursion prevention */
  extern dbref cplr;
  extern char ccom[];
***************
*** 154,159 ****
--- 154,177 ----
  
  Pid_t forked_dump_pid = -1;
  
+ /** Open /dev/null to reserve a file descriptor that can be reused later. */
+ void
+ reserve_fd(void)
+ {
+ #ifndef WIN32
+   reserved = open("/dev/null", O_RDWR);
+ #endif
+ }
+ 
+ /** Release the reserved file descriptor for other use. */
+ void
+ release_fd(void)
+ {
+ #ifndef WIN32
+   close(reserved);
+ #endif
+ }
+ 
  /** User command to dump the database.
   * \verbatim
   * This implements the @dump command.
***************
*** 576,591 ****
    }
    if (nofork || (!nofork && child == 0)) {
      /* in the child */
! #ifndef WIN32
!     close(reserved);		/* get that file descriptor back */
! #endif
      status = dump_database_internal();
      if (!nofork) {
        _exit(status);		/* !!! */
      } else {
! #ifndef WIN32
!       reserved = open("/dev/null", O_RDWR);
! #endif
        if (DUMP_NOFORK_COMPLETE && *DUMP_NOFORK_COMPLETE)
  	flag_broadcast(0, 0, "%s", DUMP_NOFORK_COMPLETE);
      }
--- 594,605 ----
    }
    if (nofork || (!nofork && child == 0)) {
      /* in the child */
!     release_fd();
      status = dump_database_internal();
      if (!nofork) {
        _exit(status);		/* !!! */
      } else {
!       reserve_fd();
        if (DUMP_NOFORK_COMPLETE && *DUMP_NOFORK_COMPLETE)
  	flag_broadcast(0, 0, "%s", DUMP_NOFORK_COMPLETE);
      }
***************
*** 681,687 ****
  	    (int) getpid(), show_time(start_time, 0));
  
    /* initialize all the hash and prefix tables */
!   init_flag_table();
    init_func_hashtab();
    init_math_hashtab();
    init_tag_hashtab();
--- 695,702 ----
  	    (int) getpid(), show_time(start_time, 0));
  
    /* initialize all the hash and prefix tables */
!   init_flagspaces();
!   init_flag_table("FLAG");
    init_func_hashtab();
    init_math_hashtab();
    init_tag_hashtab();
*** 1_7_7.551/src/fundb.c Mon, 11 Aug 2003 14:04:21 -0500 dunemush (pennmush/c/17_fundb.c 1.1.1.1.1.1.1.1.1.1.1.1.1.3.1.1.1.1.1.7.1.3.1.3.1.3.1.2.1.2.1.3.2.1.2.1.2.1.1.1.1.4.1.1.1.1.1.1.1.1.1.1.1.3.1.1.2.2.2.1.1.1.1.1.1.16 660)
--- 1_7_7.557(w)/src/fundb.c Tue, 19 Aug 2003 23:36:02 -0500 dunemush (pennmush/c/17_fundb.c 1.1.1.1.1.1.1.1.1.1.1.1.1.3.1.1.1.1.1.7.1.3.1.3.1.3.1.2.1.2.1.3.2.1.2.1.2.1.1.1.1.4.1.1.1.1.1.1.1.1.1.1.1.3.1.1.2.2.2.1.1.1.1.1.1.17 660)
***************
*** 419,425 ****
    char *p;
    ATTR *a;
    if (nargs == 0) {
!     safe_str(list_all_flags(NULL, executor, 0x1), buff, bp);
      return;
    }
    if ((p = strchr(args[0], '/')))
--- 419,425 ----
    char *p;
    ATTR *a;
    if (nargs == 0) {
!     safe_str(list_all_flags("FLAG", NULL, executor, 0x1), buff, bp);
      return;
    }
    if ((p = strchr(args[0], '/')))
***************
*** 450,456 ****
    char *p;
    ATTR *a;
    if (nargs == 0) {
!     safe_str(list_all_flags(NULL, executor, 0x2), buff, bp);
      return;
    }
    if ((p = strchr(args[0], '/')))
--- 450,456 ----
    char *p;
    ATTR *a;
    if (nargs == 0) {
!     safe_str(list_all_flags("FLAG", NULL, executor, 0x2), buff, bp);
      return;
    }
    if ((p = strchr(args[0], '/')))
***************
*** 470,476 ****
      safe_str(privs_to_string(attr_privs, AL_FLAGS(a)), buff, bp);
    } else {
      /* Object flags, visible to all */
!     safe_str(bits_to_string(Flags(thing), executor, thing), buff, bp);
    }
  }
  
--- 470,476 ----
      safe_str(privs_to_string(attr_privs, AL_FLAGS(a)), buff, bp);
    } else {
      /* Object flags, visible to all */
!     safe_str(bits_to_string("FLAG", Flags(thing), executor, thing), buff, bp);
    }
  }
  
***************
*** 1026,1053 ****
  FUNCTION(fun_orflags)
  {
    dbref it = match_thing(executor, args[0]);
!   safe_boolean(flaglist_check(executor, it, args[1], 0), buff, bp);
  }
  
  /* ARGSUSED */
  FUNCTION(fun_andflags)
  {
    dbref it = match_thing(executor, args[0]);
!   safe_boolean(flaglist_check(executor, it, args[1], 1), buff, bp);
  }
  
  /* ARGSUSED */
  FUNCTION(fun_orlflags)
  {
    dbref it = match_thing(executor, args[0]);
!   safe_boolean(flaglist_check_long(executor, it, args[1], 0), buff, bp);
  }
  
  /* ARGSUSED */
  FUNCTION(fun_andlflags)
  {
    dbref it = match_thing(executor, args[0]);
!   safe_boolean(flaglist_check_long(executor, it, args[1], 1), buff, bp);
  }
  
  static lock_type
--- 1026,1053 ----
  FUNCTION(fun_orflags)
  {
    dbref it = match_thing(executor, args[0]);
!   safe_boolean(flaglist_check("FLAG", executor, it, args[1], 0), buff, bp);
  }
  
  /* ARGSUSED */
  FUNCTION(fun_andflags)
  {
    dbref it = match_thing(executor, args[0]);
!   safe_boolean(flaglist_check("FLAG", executor, it, args[1], 1), buff, bp);
  }
  
  /* ARGSUSED */
  FUNCTION(fun_orlflags)
  {
    dbref it = match_thing(executor, args[0]);
!   safe_boolean(flaglist_check_long("FLAG", executor, it, args[1], 0), buff, bp);
  }
  
  /* ARGSUSED */
  FUNCTION(fun_andlflags)
  {
    dbref it = match_thing(executor, args[0]);
!   safe_boolean(flaglist_check_long("FLAG", executor, it, args[1], 1), buff, bp);
  }
  
  static lock_type
*** 1_7_7.551/src/flags.c Thu, 17 Jul 2003 15:25:22 -0500 dunemush (pennmush/c/20_flags.c 1.1.1.1.1.1.1.1.1.1.1.1.1.6.1.2.1.1.1.1.1.2.2.2.2.1.2.1.1.3.1.2.1.1.1.1.1.1.1.1.1.3.1.9.1.2.2.1.1.2.1.52 660)
--- 1_7_7.557(w)/src/flags.c Tue, 19 Aug 2003 23:36:02 -0500 dunemush (pennmush/c/20_flags.c 1.1.1.1.1.1.1.1.1.1.1.1.1.6.1.2.1.1.1.1.1.2.2.2.2.1.2.1.1.3.1.2.1.1.1.1.1.1.1.1.1.3.1.9.1.2.2.1.1.2.1.53 660)
***************
*** 35,40 ****
--- 35,41 ----
  #include "parse.h"
  #include "match.h"
  #include "ptab.h"
+ #include "htab.h"
  #include "privtab.h"
  #include "game.h"
  #include "flags.h"
***************
*** 46,73 ****
  
  
  static int can_set_flag(dbref player, dbref thing, FLAG *flagp, int negate);
! static FLAG *letter_to_flagptr(char c, int type);
! static void flag_add(const char *name, FLAG *f);
  static int has_flag(dbref thing, FLAG *f);
  
  void decompile_flags(dbref player, dbref thing, const char *name);
  void decompile_powers(dbref player, dbref thing, const char *name);
  static FLAG *flag_read(FILE * in);
  static void flag_write(FILE * out, FLAG *f, const char *name);
  static FLAG *clone_flag(FLAG *f);
  static FLAG *new_flag(void);
  static void flag_add_additional(void);
! static char *list_aliases(FLAG *given);
  static void realloc_object_flag_bitmasks(int numbytes);
  
  PTAB ptab_flag;			/**< Table of flags by name, inc. aliases */
! FLAG **flags = NULL;		/**< A variable-length array of pointers, 
!                                  * to canonical flags, indexed by bit 
!                                  * position. Aliases not inclued. */
! static int flagbits = 0;	/* The current length of the flags array */
  
  extern PTAB ptab_command;	/* Uses flag bitmasks */
  
  
  /** This is the old default flag table. We still use it when we have to
   * convert old dbs, but once you have a converted db, it's the flag
--- 47,74 ----
  
  
  static int can_set_flag(dbref player, dbref thing, FLAG *flagp, int negate);
! static FLAG *letter_to_flagptr(FLAGSPACE * n, char c, int type);
! static void flag_add(FLAGSPACE * n, const char *name, FLAG *f);
  static int has_flag(dbref thing, FLAG *f);
  
  void decompile_flags(dbref player, dbref thing, const char *name);
  void decompile_powers(dbref player, dbref thing, const char *name);
  static FLAG *flag_read(FILE * in);
  static void flag_write(FILE * out, FLAG *f, const char *name);
+ static FLAG *flag_hash_lookup(FLAGSPACE * n, const char *name, int type);
  static FLAG *clone_flag(FLAG *f);
  static FLAG *new_flag(void);
  static void flag_add_additional(void);
! static char *list_aliases(FLAGSPACE * n, FLAG *given);
  static void realloc_object_flag_bitmasks(int numbytes);
+ static FLAG *match_flag_ns(FLAGSPACE * n, const char *name);
  
  PTAB ptab_flag;			/**< Table of flags by name, inc. aliases */
! HASHTAB htab_flagspaces;		/**< Hash of flagspaces */
  
  extern PTAB ptab_command;	/* Uses flag bitmasks */
  
+ #define Flagspace_Lookup(n,ns)  if (!(n = (FLAGSPACE *)hashfind(ns,&htab_flagspaces))) panic("Unable to locate flagspace");
  
  /** This is the old default flag table. We still use it when we have to
   * convert old dbs, but once you have a converted db, it's the flag
***************
*** 283,289 ****
  FLAG *
  match_flag(const char *name)
  {
!   return (FLAG *) ptab_find(&ptab_flag, name);
  }
  
  /** Given a flag name and mask of types, return a pointer to a flag struct.
--- 284,301 ----
  FLAG *
  match_flag(const char *name)
  {
!   return (FLAG *) match_flag_ns(hashfind("FLAG", &htab_flagspaces), name);
! }
! 
! /** Convenience function to return a pointer to a flag struct
!  * given the name.
!  * \param name name of flag to find.
!  * \return poiner to flag structure, or NULL.
!  */
! static FLAG *
! match_flag_ns(FLAGSPACE * n, const char *name)
! {
!   return (FLAG *) ptab_find(n->tab, name);
  }
  
  /** Given a flag name and mask of types, return a pointer to a flag struct.
***************
*** 291,306 ****
   * right type. If that fails, it tries to match flag characters if the
   * name is a single character. If all else fails, it tries to match
   * against an object type name.
   * \param name name of flag to find.
   * \param type mask of desired flag object types.
   * \return pointer to flag structure, or NULL.
   */
! FLAG *
! flag_hash_lookup(const char *name, int type)
  {
    FLAG *f;
  
!   f = match_flag(name);
    if (f && !(f->perms & F_DISABLED)) {
      if (f->type & type)
        return f;
--- 303,319 ----
   * right type. If that fails, it tries to match flag characters if the
   * name is a single character. If all else fails, it tries to match
   * against an object type name.
+  * \param n pointer to flagspace to search.
   * \param name name of flag to find.
   * \param type mask of desired flag object types.
   * \return pointer to flag structure, or NULL.
   */
! static FLAG *
! flag_hash_lookup(FLAGSPACE * n, const char *name, int type)
  {
    FLAG *f;
  
!   f = match_flag_ns(n, name);
    if (f && !(f->perms & F_DISABLED)) {
      if (f->type & type)
        return f;
***************
*** 309,322 ****
  
    /* If the name is a single character, search the flag characters */
    if (name && *name && !*(name + 1)) {
!     if ((f = letter_to_flagptr(*name, type)))
        return f;
    }
  
    /* provided for backwards compatibility: type flag checking */
!   for (f = type_table; f->name != NULL; f++)
!     if (string_prefix(name, f->name))
!       return f;
    return NULL;
  }
  
--- 322,338 ----
  
    /* If the name is a single character, search the flag characters */
    if (name && *name && !*(name + 1)) {
!     if ((f = letter_to_flagptr(n, *name, type)))
        return f;
    }
  
    /* provided for backwards compatibility: type flag checking */
!   if (n->flag_table == flag_table) {
!     for (f = type_table; f->name != NULL; f++)
!       if (string_prefix(name, f->name))
! 	return f;
!   }
! 
    return NULL;
  }
  
***************
*** 335,348 ****
  
  /* Deallocate all flag-related memory */
  static void
! clear_all_flags(void)
  {
!   ptab_free(&ptab_flag);
    /* Finally, the flags array */
!   if (flags)
!     free(flags);
!   flags = NULL;
!   flagbits = 0;
  }
  
  static FLAG *
--- 351,364 ----
  
  /* Deallocate all flag-related memory */
  static void
! clear_all_flags(FLAGSPACE * n)
  {
!   ptab_free(n->tab);
    /* Finally, the flags array */
!   if (n->flags)
!     free(n->flags);
!   n->flags = NULL;
!   n->flagbits = 0;
  }
  
  static FLAG *
***************
*** 365,383 ****
   * f->bitpos is used.
   */
  static void
! flag_add(const char *name, FLAG *f)
  {
    /* If this flag has no bitpos assigned, assign it the next one.
     * We could improve this algorithm to use the next available
     * slot after deletions, too, but this will do for now.
     */
    if (f->bitpos < 0)
!     f->bitpos = flagbits;
  
    /* Insert the flag in the ptab by the given name (maybe an alias) */
!   ptab_start_inserts(&ptab_flag);
!   ptab_insert(&ptab_flag, name, f);
!   ptab_end_inserts(&ptab_flag);
  
    /* Is this a canonical flag (as opposed to an alias?)
     * If it's an alias, we're done.
--- 381,399 ----
   * f->bitpos is used.
   */
  static void
! flag_add(FLAGSPACE * n, const char *name, FLAG *f)
  {
    /* If this flag has no bitpos assigned, assign it the next one.
     * We could improve this algorithm to use the next available
     * slot after deletions, too, but this will do for now.
     */
    if (f->bitpos < 0)
!     f->bitpos = n->flagbits;
  
    /* Insert the flag in the ptab by the given name (maybe an alias) */
!   ptab_start_inserts(n->tab);
!   ptab_insert(n->tab, name, f);
!   ptab_end_inserts(n->tab);
  
    /* Is this a canonical flag (as opposed to an alias?)
     * If it's an alias, we're done.
***************
*** 386,420 ****
     * (An alias would have a previously used bitpos that's already 
     * indexing a flag in the flags array)
     */
!   if ((f->bitpos >= flagbits) || (flags[f->bitpos] == NULL)) {
      /* It's a canonical flag */
      int i;
!     if (f->bitpos >= flagbits) {
        /* Oops, we need a bigger array */
!       if (flagbits == 0)
! 	flags = (FLAG **) malloc(sizeof(FLAG *));
        else {
! 	flags = (FLAG **) realloc(flags, (f->bitpos + 1) * sizeof(FLAG *));
! 	if (!flags)
  	  panic("Unable to reallocate flags array!\n");
        }
        /* Make sure the new space is full of NULLs */
!       for (i = flagbits; i <= f->bitpos; i++)
! 	flags[i] = NULL;
      }
      /* Put the canonical flag in the flags array */
!     flags[f->bitpos] = f;
!     flagbits = f->bitpos + 1;
!     if (flagbits % 8 == 1) {
        /* We've crossed over a byte boundary, so we need to realloc
         * all the flags on all our objects to get them an additional
         * byte.
         */
!       realloc_object_flag_bitmasks((flagbits + 7) / 8);
      }
    }
  }
  
  static void
  realloc_object_flag_bitmasks(int numbytes)
  {
--- 402,440 ----
     * (An alias would have a previously used bitpos that's already 
     * indexing a flag in the flags array)
     */
!   if ((f->bitpos >= n->flagbits) || (n->flags[f->bitpos] == NULL)) {
      /* It's a canonical flag */
      int i;
!     if (f->bitpos >= n->flagbits) {
        /* Oops, we need a bigger array */
!       if (n->flagbits == 0)
! 	n->flags = (FLAG **) malloc(sizeof(FLAG *));
        else {
! 	n->flags =
! 	  (FLAG **) realloc(n->flags, (f->bitpos + 1) * sizeof(FLAG *));
! 	if (!n->flags)
  	  panic("Unable to reallocate flags array!\n");
        }
        /* Make sure the new space is full of NULLs */
!       for (i = n->flagbits; i <= f->bitpos; i++)
! 	n->flags[i] = NULL;
      }
      /* Put the canonical flag in the flags array */
!     n->flags[f->bitpos] = f;
!     n->flagbits = f->bitpos + 1;
!     if (n->flagbits % 8 == 1) {
        /* We've crossed over a byte boundary, so we need to realloc
         * all the flags on all our objects to get them an additional
         * byte.
         */
!       realloc_object_flag_bitmasks((n->flagbits + 7) / 8);
      }
    }
  }
  
+ /* Eventually, this need to compute numbytes itself from the
+  * total bytes required for flags + powers
+  */
  static void
  realloc_object_flag_bitmasks(int numbytes)
  {
***************
*** 504,521 ****
   * \param in file pointer to read from.
   */
  void
! flag_read_all(FILE * in)
  {
    FLAG *f;
    char alias[BUFFER_LEN];
    /* If we are reading flags from the db, they are definitive. */
!   clear_all_flags();
    while ((f = flag_read(in))) {
!     flag_add(f->name, f);
    }
    /* Assumes we'll always have at least one alias */
    while ((f = flag_alias_read(in, alias))) {
!     flag_add(alias, f);
    }
    flag_add_additional();
  }
--- 524,547 ----
   * \param in file pointer to read from.
   */
  void
! flag_read_all(FILE * in, const char *ns)
  {
    FLAG *f;
+   FLAGSPACE *n;
    char alias[BUFFER_LEN];
+ 
+   if (!(n = (FLAGSPACE *) hashfind(ns, &htab_flagspaces))) {
+     do_rawlog(LT_ERR, T("FLAG READ: Unable to locate flagspace %s."), ns);
+     return;
+   }
    /* If we are reading flags from the db, they are definitive. */
!   clear_all_flags(n);
    while ((f = flag_read(in))) {
!     flag_add(n, f->name, f);
    }
    /* Assumes we'll always have at least one alias */
    while ((f = flag_alias_read(in, alias))) {
!     flag_add(n, alias, f);
    }
    flag_add_additional();
  }
***************
*** 547,599 ****
   * \param out file pointer to write to.
   */
  void
! flag_write_all(FILE * out)
  {
    int i;
    FLAG *f;
    char flagname[BUFFER_LEN];
    /* Write out canonical flags first */
!   for (i = 0; i < flagbits; i++) {
!     if (flags[i])
!       flag_write(out, flags[i], flags[i]->name);
    }
    putstring(out, "FLAG ALIASES");
    /* Now write out aliases. An alias is a flag in the ptab whose
     * name isn't the same as the name of the canonical flag in its
     * bit position
     */
!   f = ptab_firstentry_new(&ptab_flag, flagname);
    while (f) {
!     if (strcmp(flags[f->bitpos]->name, flagname)) {
        /* This is an alias! */
        flag_alias_write(out, f, flagname);
      }
!     f = ptab_nextentry_new(&ptab_flag, flagname);
    }
    putstring(out, "END OF FLAGS");
  }
  
  
! /** Initialize the flag table with defaults.
   * This function loads the standard flags as a baseline 
   * (and for dbs that haven't yet converted).
   */
  void
! init_flag_table(void)
  {
    FLAG *f, *cf;
    FLAG_ALIAS *a;
!   ptab_init(&ptab_flag);
    /* do regular flags first */
!   for (f = flag_table; f->name; f++) {
      cf = clone_flag(f);
      cf->bitpos = -1;
!     flag_add(cf->name, cf);
    }
    /* now add in the aliases */
!   for (a = flag_alias_tab; a->alias; a++) {
!     if ((f = match_flag(a->realname)))
!       flag_add(a->alias, f);
      else
        do_rawlog(LT_ERR,
  		T("FLAG INIT: flag alias %s matches no known flag."), a->alias);
--- 573,656 ----
   * \param out file pointer to write to.
   */
  void
! flag_write_all(FILE * out, const char *ns)
  {
    int i;
    FLAG *f;
+   FLAGSPACE *n;
    char flagname[BUFFER_LEN];
+ 
+   if (!(n = (FLAGSPACE *) hashfind(ns, &htab_flagspaces))) {
+     do_rawlog(LT_ERR, T("FLAG WRITE: Unable to locate flagspace %s."), ns);
+     return;
+   }
    /* Write out canonical flags first */
!   for (i = 0; i < n->flagbits; i++) {
!     if (n->flags[i])
!       flag_write(out, n->flags[i], n->flags[i]->name);
    }
    putstring(out, "FLAG ALIASES");
    /* Now write out aliases. An alias is a flag in the ptab whose
     * name isn't the same as the name of the canonical flag in its
     * bit position
     */
!   f = ptab_firstentry_new(n->tab, flagname);
    while (f) {
!     if (strcmp(n->flags[f->bitpos]->name, flagname)) {
        /* This is an alias! */
        flag_alias_write(out, f, flagname);
      }
!     f = ptab_nextentry_new(n->tab, flagname);
    }
    putstring(out, "END OF FLAGS");
  }
  
+ /** Initialize the flagspaces.
+  */
+ void
+ init_flagspaces(void)
+ {
+   FLAGSPACE *flags;
+ 
+   hashinit(&htab_flagspaces, 4, sizeof(FLAGSPACE));
+   flags = (FLAGSPACE *) mush_malloc(sizeof(FLAGSPACE), "flagspace");
+   flags->tab = &ptab_flag;
+   flags->flagbits = 0;
+   flags->flags = NULL;
+   flags->flag_table = flag_table;
+   flags->flag_alias_table = flag_alias_tab;
+   hashadd("FLAG", (void *) flags, &htab_flagspaces);
+ }
+ 
  
! /** Initialize a flag table with defaults.
   * This function loads the standard flags as a baseline 
   * (and for dbs that haven't yet converted).
+  * \param ns name of flagspace to initialize.
   */
  void
! init_flag_table(const char *ns)
  {
    FLAG *f, *cf;
    FLAG_ALIAS *a;
!   FLAGSPACE *n;
! 
!   if (!(n = (FLAGSPACE *) hashfind(ns, &htab_flagspaces))) {
!     do_rawlog(LT_ERR, T("FLAG INIT: Unable to locate flagspace %s."), ns);
!     return;
!   }
! 
!   ptab_init(n->tab);
    /* do regular flags first */
!   for (f = n->flag_table; f->name; f++) {
      cf = clone_flag(f);
      cf->bitpos = -1;
!     flag_add(n, cf->name, cf);
    }
    /* now add in the aliases */
!   for (a = n->flag_alias_table; a->alias; a++) {
!     if ((f = match_flag_ns(n, a->realname)))
!       flag_add(n, a->alias, f);
      else
        do_rawlog(LT_ERR,
  		T("FLAG INIT: flag alias %s matches no known flag."), a->alias);
***************
*** 657,663 ****
  flags_from_old_flags(long old_flags, long old_toggles, int type)
  {
    FLAG *f, *newf;
!   object_flag_type bitmask = new_flag_bitmask();
    for (f = flag_table; f->name; f++) {
      if (f->type == NOTYPE) {
        if (f->bitpos & old_flags) {
--- 714,721 ----
  flags_from_old_flags(long old_flags, long old_toggles, int type)
  {
    FLAG *f, *newf;
!   object_flag_type bitmask = new_flag_bitmask("FLAG");
! 
    for (f = flag_table; f->name; f++) {
      if (f->type == NOTYPE) {
        if (f->bitpos & old_flags) {
***************
*** 685,696 ****
  
  /* Given a single character, return the matching flag definition */
  static FLAG *
! letter_to_flagptr(char c, int type)
  {
    FLAG *f;
    int i;
!   for (i = 0; i < flagbits; i++)
!     if ((f = flags[i])) {
        /* Doh! Kludge-city. We'll ignore the CHOWN_OK flag on players, because
         * it's more useful to check 'C' as COLOR. Argle.
         */
--- 743,754 ----
  
  /* Given a single character, return the matching flag definition */
  static FLAG *
! letter_to_flagptr(FLAGSPACE * n, char c, int type)
  {
    FLAG *f;
    int i;
!   for (i = 0; i < n->flagbits; i++)
!     if ((f = n->flags[i])) {
        /* Doh! Kludge-city. We'll ignore the CHOWN_OK flag on players, because
         * it's more useful to check 'C' as COLOR. Argle.
         */
***************
*** 712,718 ****
  /** Locate a specific bit within a byte given a bit position */
  #define FlagBit(x) (7 - (x % 8))
  /** How many bytes do we need for a flag bitmask? */
! #define FlagBytes  ((size_t)((flagbits + 7) / 8))
  
  /** Allocate a new flag bitmask.
   * This function allocates a new flag bitmask of sufficient length
--- 770,777 ----
  /** Locate a specific bit within a byte given a bit position */
  #define FlagBit(x) (7 - (x % 8))
  /** How many bytes do we need for a flag bitmask? */
! #define FlagBytes(n)  ((size_t)((n->flagbits + 7) / 8))
! 
  
  /** Allocate a new flag bitmask.
   * This function allocates a new flag bitmask of sufficient length
***************
*** 721,733 ****
   * \return a newly allocated zeroed flag bitmask.
   */
  object_flag_type
! new_flag_bitmask(void)
  {
    object_flag_type bitmask;
!   bitmask = (object_flag_type) mush_malloc(FlagBytes, "flag_bitmask");
    if (!bitmask)
      panic("Unable to allocate memory for flag bitmask");
!   memset(bitmask, 0, FlagBytes);
    return bitmask;
  }
  
--- 780,794 ----
   * \return a newly allocated zeroed flag bitmask.
   */
  object_flag_type
! new_flag_bitmask(const char *ns)
  {
    object_flag_type bitmask;
!   FLAGSPACE *n;
!   Flagspace_Lookup(n, ns);
!   bitmask = (object_flag_type) mush_malloc(FlagBytes(n), "flag_bitmask");
    if (!bitmask)
      panic("Unable to allocate memory for flag bitmask");
!   memset(bitmask, 0, FlagBytes(n));
    return bitmask;
  }
  
***************
*** 739,751 ****
   * \return a newly allocated clone of the given bitmask.
   */
  object_flag_type
! clone_flag_bitmask(object_flag_type given)
  {
    object_flag_type bitmask;
!   bitmask = (object_flag_type) mush_malloc(FlagBytes, "flag_bitmask");
    if (!bitmask)
      panic("Unable to allocate memory for flag bitmask");
!   memcpy(bitmask, given, FlagBytes);
    return bitmask;
  }
  
--- 800,814 ----
   * \return a newly allocated clone of the given bitmask.
   */
  object_flag_type
! clone_flag_bitmask(const char *ns, object_flag_type given)
  {
    object_flag_type bitmask;
!   FLAGSPACE *n;
!   Flagspace_Lookup(n, ns);
!   bitmask = (object_flag_type) mush_malloc(FlagBytes(n), "flag_bitmask");
    if (!bitmask)
      panic("Unable to allocate memory for flag bitmask");
!   memcpy(bitmask, given, FlagBytes(n));
    return bitmask;
  }
  
***************
*** 756,764 ****
   */
  /* Copy a given bitmask to an already-allocated destination bitmask */
  void
! copy_flag_bitmask(object_flag_type dest, object_flag_type given)
  {
!   memcpy((void *) dest, (void *) given, FlagBytes);
  }
  
  /** Deallocate a flag bitmask.
--- 819,829 ----
   */
  /* Copy a given bitmask to an already-allocated destination bitmask */
  void
! copy_flag_bitmask(const char *ns, object_flag_type dest, object_flag_type given)
  {
!   FLAGSPACE *n;
!   Flagspace_Lookup(n, ns);
!   memcpy((void *) dest, (void *) given, FlagBytes(n));
  }
  
  /** Deallocate a flag bitmask.
***************
*** 834,844 ****
   * \retval 0 at least one bit in bitmask is not set in source.
   */
  int
! has_all_bits(object_flag_type source, object_flag_type bitmask)
  {
    unsigned int i;
    int ok = 1;
!   for (i = 0; i < FlagBytes; i++)
      ok &= ((*(bitmask + i) & *(source + i)) == *(bitmask + i));
    return ok;
  }
--- 899,911 ----
   * \retval 0 at least one bit in bitmask is not set in source.
   */
  int
! has_all_bits(const char *ns, object_flag_type source, object_flag_type bitmask)
  {
    unsigned int i;
    int ok = 1;
!   FLAGSPACE *n;
!   Flagspace_Lookup(n, ns);
!   for (i = 0; i < FlagBytes(n); i++)
      ok &= ((*(bitmask + i) & *(source + i)) == *(bitmask + i));
    return ok;
  }
***************
*** 849,859 ****
   * \retval 0 at least one bit in bitmask is 1.
   */
  int
! null_flagmask(object_flag_type source)
  {
    unsigned int i;
    int bad = 0;
!   for (i = 0; i < FlagBytes; i++)
      bad |= *(source + i);
    return (!bad);
  }
--- 916,928 ----
   * \retval 0 at least one bit in bitmask is 1.
   */
  int
! null_flagmask(const char *ns, object_flag_type source)
  {
    unsigned int i;
    int bad = 0;
!   FLAGSPACE *n;
!   Flagspace_Lookup(n, ns);
!   for (i = 0; i < FlagBytes(n); i++)
      bad |= *(source + i);
    return (!bad);
  }
***************
*** 867,877 ****
   * \retval 0 no bits in bitmask are set in source.
   */
  int
! has_any_bits(object_flag_type source, object_flag_type bitmask)
  {
    unsigned int i;
    int ok = 0;
!   for (i = 0; i < FlagBytes; i++)
      ok |= (*(bitmask + i) & *(source + i));
    return ok;
  }
--- 936,948 ----
   * \retval 0 no bits in bitmask are set in source.
   */
  int
! has_any_bits(const char *ns, object_flag_type source, object_flag_type bitmask)
  {
    unsigned int i;
    int ok = 0;
!   FLAGSPACE *n;
!   Flagspace_Lookup(n, ns);
!   for (i = 0; i < FlagBytes(n); i++)
      ok |= (*(bitmask + i) & *(source + i));
    return ok;
  }
***************
*** 884,899 ****
   * \return string representation of bitmask (list of flags).
   */
  const char *
! bits_to_string(object_flag_type bitmask, dbref privs, dbref thing)
  {
    FLAG *f;
    int i;
    int first = 1;
    static char buf[BUFFER_LEN];
    char *bp;
    bp = buf;
!   for (i = 0; i < flagbits; i++) {
!     if ((f = flags[i])) {
        if (has_bit(bitmask, f->bitpos) &&
  	  (!GoodObject(thing) || Can_See_Flag(privs, thing, f))) {
  	if (!first)
--- 955,974 ----
   * \return string representation of bitmask (list of flags).
   */
  const char *
! bits_to_string(const char *ns, object_flag_type bitmask, dbref privs,
! 	       dbref thing)
  {
    FLAG *f;
+   FLAGSPACE *n;
    int i;
    int first = 1;
    static char buf[BUFFER_LEN];
    char *bp;
+ 
+   Flagspace_Lookup(n, ns);
    bp = buf;
!   for (i = 0; i < n->flagbits; i++) {
!     if ((f = n->flags[i])) {
        if (has_bit(bitmask, f->bitpos) &&
  	  (!GoodObject(thing) || Can_See_Flag(privs, thing, f))) {
  	if (!first)
***************
*** 914,932 ****
   * \return a newly allocated flag bitmask.
   */
  object_flag_type
! string_to_bits(const char *str)
  {
    object_flag_type bitmask;
    char *copy, *s, *sp;
    FLAG *f;
!   bitmask = new_flag_bitmask();
    if (!str)
      return bitmask;		/* We're done, then */
    copy = strdup(str);
    s = trim_space_sep(copy, ' ');
    while (s) {
      sp = split_token(&s, ' ');
!     if (!(f = match_flag(sp)))
        /* Now what do we do? Ignore it? */
        continue;
      set_flag_bitmask(bitmask, f->bitpos);
--- 989,1013 ----
   * \return a newly allocated flag bitmask.
   */
  object_flag_type
! string_to_bits(const char *ns, const char *str)
  {
    object_flag_type bitmask;
    char *copy, *s, *sp;
    FLAG *f;
!   FLAGSPACE *n;
! 
!   bitmask = new_flag_bitmask(ns);
!   if (!(n = (FLAGSPACE *) hashfind(ns, &htab_flagspaces))) {
!     do_rawlog(LT_ERR, T("FLAG: Unable to locate flagspace %s."), ns);
!     return bitmask;
!   }
    if (!str)
      return bitmask;		/* We're done, then */
    copy = strdup(str);
    s = trim_space_sep(copy, ' ');
    while (s) {
      sp = split_token(&s, ' ');
!     if (!(f = match_flag_ns(n, sp)))
        /* Now what do we do? Ignore it? */
        continue;
      set_flag_bitmask(bitmask, f->bitpos);
***************
*** 954,960 ****
  has_flag_by_name(dbref thing, const char *flag, int type)
  {
    FLAG *f;
!   f = flag_hash_lookup(flag, type);
    if (!f)
      return 0;
    return has_flag(thing, f);
--- 1035,1043 ----
  has_flag_by_name(dbref thing, const char *flag, int type)
  {
    FLAG *f;
!   FLAGSPACE *n;
!   n = hashfind("FLAG", &htab_flagspaces);
!   f = flag_hash_lookup(n, flag, type);
    if (!f)
      return 0;
    return has_flag(thing, f);
***************
*** 1053,1058 ****
--- 1136,1144 ----
    char *p;
    FLAG *f;
    int i;
+   FLAGSPACE *n;
+ 
+   Flagspace_Lookup(n, "FLAG");
    p = buf;
    switch (Typeof(thing)) {
    case TYPE_GARBAGE:
***************
*** 1071,1078 ****
      *p++ = 'P';
      break;
    }
!   for (i = 0; i < flagbits; i++) {
!     if ((f = flags[i])) {
        if (has_flag(thing, f) && Can_See_Flag(player, thing, f))
  	*p++ = f->letter;
      }
--- 1157,1164 ----
      *p++ = 'P';
      break;
    }
!   for (i = 0; i < n->flagbits; i++) {
!     if ((f = n->flags[i])) {
        if (has_flag(thing, f) && Can_See_Flag(player, thing, f))
  	*p++ = f->letter;
      }
***************
*** 1095,1101 ****
    safe_str(T("Type: "), buf, &bp);
    safe_str(privs_to_string(type_privs, Typeof(thing)), buf, &bp);
    safe_str(T(" Flags: "), buf, &bp);
!   safe_str(bits_to_string(Flags(thing), player, thing), buf, &bp);
    *bp = '\0';
    return buf;
  }
--- 1181,1187 ----
    safe_str(T("Type: "), buf, &bp);
    safe_str(privs_to_string(type_privs, Typeof(thing)), buf, &bp);
    safe_str(T(" Flags: "), buf, &bp);
!   safe_str(bits_to_string("FLAG", Flags(thing), player, thing), buf, &bp);
    *bp = '\0';
    return buf;
  }
***************
*** 1112,1119 ****
  {
    FLAG *f;
    int i;
!   for (i = 0; i < flagbits; i++)
!     if ((f = flags[i])) {
        if (has_flag(thing, f) && Can_See_Flag(player, thing, f))
  	notify_format(player, "@set %s = %s", name, f->name);
      }
--- 1198,1207 ----
  {
    FLAG *f;
    int i;
!   FLAGSPACE *n;
!   Flagspace_Lookup(n, "FLAG");
!   for (i = 0; i < n->flagbits; i++)
!     if ((f = n->flags[i])) {
        if (has_flag(thing, f) && Can_See_Flag(player, thing, f))
  	notify_format(player, "@set %s = %s", name, f->name);
      }
***************
*** 1128,1140 ****
   * \param negate if 1, clear the flag, if 0, set the flag.
   */
  void
! twiddle_flag_internal(dbref thing, const char *flag, int negate)
  {
    FLAG *f;
    if (IsGarbage(thing))
      return;
!   if ((f = flag_hash_lookup(flag, Typeof(thing))))
!     twiddle_flag(thing, f, negate);
  }
  
  
--- 1216,1232 ----
   * \param negate if 1, clear the flag, if 0, set the flag.
   */
  void
! twiddle_flag_internal(const char *ns, dbref thing, const char *flag, int negate)
  {
    FLAG *f;
+   FLAGSPACE *n;
    if (IsGarbage(thing))
      return;
!   n = (FLAGSPACE *) hashfind(ns, &htab_flagspaces);
!   if ((f = flag_hash_lookup(n, flag, Typeof(thing)))) {
!     if (n->flag_table == flag_table)
!       twiddle_flag(thing, f, negate);
!   }
  }
  
  
***************
*** 1157,1163 ****
    FLAG *f;
    char tbuf1[BUFFER_LEN];
    char *tp;
!   if ((f = flag_hash_lookup(flag, Typeof(thing))) == NULL) {
      notify(player, T("I don't recognize that flag."));
      return;
    }
--- 1249,1258 ----
    FLAG *f;
    char tbuf1[BUFFER_LEN];
    char *tp;
!   FLAGSPACE *n;
! 
!   n = (FLAGSPACE *) hashfind("FLAG", &htab_flagspaces);
!   if ((f = flag_hash_lookup(n, flag, Typeof(thing))) == NULL) {
      notify(player, T("I don't recognize that flag."));
      return;
    }
***************
*** 1314,1328 ****
   * \retval 0 object has no (or not all) flags.
   */
  int
! flaglist_check(dbref player, dbref it, const char *fstr, int type)
  {
    char *s;
    FLAG *fp;
    int negate, temp;
    int ret = type;
    negate = temp = 0;
    if (!GoodObject(it))
      return 0;
    for (s = (char *) fstr; *s; s++) {
      /* Check for a negation sign. If we find it, we note it and 
       * increment the pointer to the next character.
--- 1409,1430 ----
   * \retval 0 object has no (or not all) flags.
   */
  int
! flaglist_check(const char *ns, dbref player, dbref it, const char *fstr,
! 	       int type)
  {
    char *s;
    FLAG *fp;
    int negate, temp;
    int ret = type;
+   FLAGSPACE *n;
+ 
    negate = temp = 0;
    if (!GoodObject(it))
      return 0;
+   if (!(n = (FLAGSPACE *) hashfind(ns, &htab_flagspaces))) {
+     do_rawlog(LT_ERR, T("FLAG: Unable to locate flagspace %s"), ns);
+     return 0;
+   }
    for (s = (char *) fstr; *s; s++) {
      /* Check for a negation sign. If we find it, we note it and 
       * increment the pointer to the next character.
***************
*** 1339,1345 ****
         * Fail the check. */
        return (type == 1) ? 0 : ret;
      /* Find the flag. */
!     if ((fp = letter_to_flagptr(*s, Typeof(it))) == NULL) {
        /* Maybe *s is a type specifier (P, T, E, R). These aren't really
         * flags, but we grandfather them in to preserve old code
         */
--- 1441,1447 ----
         * Fail the check. */
        return (type == 1) ? 0 : ret;
      /* Find the flag. */
!     if ((fp = letter_to_flagptr(n, *s, Typeof(it))) == NULL) {
        /* Maybe *s is a type specifier (P, T, E, R). These aren't really
         * flags, but we grandfather them in to preserve old code
         */
***************
*** 1396,1410 ****
   * \retval 0 object has no (or not all) flags.
   */
  int
! flaglist_check_long(dbref player, dbref it, const char *fstr, int type)
  {
    char *s, *copy, *sp;
    FLAG *fp;
    int negate, temp;
    int ret = type;
    negate = temp = 0;
    if (!GoodObject(it))
      return 0;
    copy = strdup(fstr);
    sp = trim_space_sep(copy, ' ');
    while (sp) {
--- 1498,1518 ----
   * \retval 0 object has no (or not all) flags.
   */
  int
! flaglist_check_long(const char *ns, dbref player, dbref it, const char *fstr,
! 		    int type)
  {
    char *s, *copy, *sp;
    FLAG *fp;
    int negate, temp;
    int ret = type;
+   FLAGSPACE *n;
    negate = temp = 0;
    if (!GoodObject(it))
      return 0;
+   if (!(n = (FLAGSPACE *) hashfind(ns, &htab_flagspaces))) {
+     do_rawlog(LT_ERR, T("FLAG: Unable to locate flagspace %s"), ns);
+     return 0;
+   }
    copy = strdup(fstr);
    sp = trim_space_sep(copy, ' ');
    while (sp) {
***************
*** 1424,1430 ****
         * Fail the check. */
        return (type == 1) ? 0 : ret;
      /* Find the flag. */
!     if (!(fp = flag_hash_lookup(s, Typeof(it)))) {
        /* Either we got a '!' that wasn't followed by a letter, or
         * we couldn't find that flag. For AND, since we've failed
         * a check, we can return false. Otherwise we just go on.
--- 1532,1538 ----
         * Fail the check. */
        return (type == 1) ? 0 : ret;
      /* Find the flag. */
!     if (!(fp = flag_hash_lookup(n, s, Typeof(it)))) {
        /* Either we got a '!' that wasn't followed by a letter, or
         * we couldn't find that flag. For AND, since we've failed
         * a check, we can return false. Otherwise we just go on.
***************
*** 1480,1486 ****
  {
    /* Does thing have the flag named name && can privs see it? */
    FLAG *f;
!   if ((f = flag_hash_lookup(name, Typeof(thing))) == NULL)
      return 0;
    return has_flag(thing, f) && Can_See_Flag(privs, thing, f);
  }
--- 1588,1596 ----
  {
    /* Does thing have the flag named name && can privs see it? */
    FLAG *f;
!   FLAGSPACE *n;
!   n = hashfind("FLAG", &htab_flagspaces);
!   if ((f = flag_hash_lookup(n, name, Typeof(thing))) == NULL)
      return 0;
    return has_flag(thing, f) && Can_See_Flag(privs, thing, f);
  }
***************
*** 1504,1512 ****
--- 1614,1624 ----
  	 int perms, int negate_perms)
  {
    FLAG *f;
+   FLAGSPACE *n;
    /* Don't double-add */
    if (match_flag(name))
      return;
+   n = hashfind("FLAG", &htab_flagspaces);
    f = new_flag();
    f->name = strdup(strupper(name));
    f->letter = letter;
***************
*** 1514,1520 ****
    f->perms = perms;
    f->negate_perms = negate_perms;
    f->bitpos = -1;
!   flag_add(f->name, f);
  }
  
  
--- 1626,1632 ----
    f->perms = perms;
    f->negate_perms = negate_perms;
    f->bitpos = -1;
!   flag_add(n, f->name, f);
  }
  
  
***************
*** 1533,1539 ****
  void
  do_list_flags(dbref player, const char *arg, int lc)
  {
!   char *b = list_all_flags(arg, player, 0x3);
    notify_format(player, T("Flags: %s"), lc ? strlower(b) : b);
  }
  
--- 1645,1651 ----
  void
  do_list_flags(dbref player, const char *arg, int lc)
  {
!   char *b = list_all_flags("FLAG", arg, player, 0x3);
    notify_format(player, T("Flags: %s"), lc ? strlower(b) : b);
  }
  
***************
*** 1545,1564 ****
   * \param name name of the flag to describe.
   */
  void
! do_flag_info(dbref player, const char *name)
  {
    FLAG *f;
    /* Find the flag */
!   f = flag_hash_lookup(name, NOTYPE);
    if (!f && God(player))
!     f = match_flag(name);
    if (!f) {
      notify(player, T("No such flag."));
      return;
    }
    notify_format(player, T("Flag name: %s"), f->name);
    notify_format(player, T("Flag char: %c"), f->letter);
!   notify_format(player, "  Aliases: %s", list_aliases(f));
    notify_format(player, "  Type(s): %s", privs_to_string(type_privs, f->type));
    notify_format(player, "    Perms: %s", privs_to_string(flag_privs, f->perms));
    notify_format(player, "ResetPrms: %s",
--- 1657,1683 ----
   * \param name name of the flag to describe.
   */
  void
! do_flag_info(const char *ns, dbref player, const char *name)
  {
    FLAG *f;
+   FLAGSPACE *n;
+   /* Find the flagspace */
+   if (!(n = (FLAGSPACE *) hashfind(ns, &htab_flagspaces))) {
+     do_rawlog(LT_ERR, T("FLAG: Unable to locate flagspace %s"), ns);
+     return;
+   }
+ 
    /* Find the flag */
!   f = flag_hash_lookup(n, name, NOTYPE);
    if (!f && God(player))
!     f = match_flag_ns(n, name);
    if (!f) {
      notify(player, T("No such flag."));
      return;
    }
    notify_format(player, T("Flag name: %s"), f->name);
    notify_format(player, T("Flag char: %c"), f->letter);
!   notify_format(player, "  Aliases: %s", list_aliases(n, f));
    notify_format(player, "  Type(s): %s", privs_to_string(type_privs, f->type));
    notify_format(player, "    Perms: %s", privs_to_string(flag_privs, f->perms));
    notify_format(player, "ResetPrms: %s",
***************
*** 1581,1592 ****
  do_flag_restrict(dbref player, const char *name, char *args_right[])
  {
    FLAG *f;
    int perms, negate_perms;
    if (!God(player)) {
      notify(player, T("You don't have enough magic for that."));
      return;
    }
!   if (!(f = flag_hash_lookup(name, NOTYPE))) {
      notify(player, T("No such flag."));
      return;
    }
--- 1700,1714 ----
  do_flag_restrict(dbref player, const char *name, char *args_right[])
  {
    FLAG *f;
+   FLAGSPACE *n;
    int perms, negate_perms;
+ 
    if (!God(player)) {
      notify(player, T("You don't have enough magic for that."));
      return;
    }
!   n = hashfind("FLAG", &htab_flagspaces);
!   if (!(f = flag_hash_lookup(n, name, NOTYPE))) {
      notify(player, T("No such flag."));
      return;
    }
***************
*** 1645,1650 ****
--- 1767,1774 ----
    int perms = F_ANY;
    int negate_perms = F_ANY;
    FLAG *f;
+   FLAGSPACE *n;
+ 
    if (!God(player)) {
      notify(player, T("You don't have enough magic for that."));
      return;
***************
*** 1661,1670 ****
      notify(player, T("Flag names may not contain spaces."));
      return;
    }
!   if ((f = flag_hash_lookup(name, NOTYPE))) {
!     notify_format(player, T("Name conflicts with the %s flag."), f->name);
!     return;
!   }
    /* Do we have a letter? */
    if (args_right[1]) {
      if (strlen(args_right[1]) > 1) {
--- 1785,1791 ----
      notify(player, T("Flag names may not contain spaces."));
      return;
    }
!   Flagspace_Lookup(n, "FLAG");
    /* Do we have a letter? */
    if (args_right[1]) {
      if (strlen(args_right[1]) > 1) {
***************
*** 1683,1689 ****
      }
      /* Is this letter already in use for this type? */
      if (*args_right[1]) {
!       if ((f = letter_to_flagptr(*args_right[1], type))) {
  	notify_format(player, T("Letter conflicts with the %s flag."), f->name);
  	return;
        }
--- 1804,1810 ----
      }
      /* Is this letter already in use for this type? */
      if (*args_right[1]) {
!       if ((f = letter_to_flagptr(n, *args_right[1], type))) {
  	notify_format(player, T("Letter conflicts with the %s flag."), f->name);
  	return;
        }
***************
*** 1717,1723 ****
    add_flag(name, letter, type, perms, negate_perms);
    /* Did it work? */
    if ((f = match_flag(name)))
!     do_flag_info(player, name);
    else
      notify(player, T("Unknown failure adding flag."));
  }
--- 1838,1844 ----
    add_flag(name, letter, type, perms, negate_perms);
    /* Did it work? */
    if ((f = match_flag(name)))
!     do_flag_info("FLAG", player, name);
    else
      notify(player, T("Unknown failure adding flag."));
  }
***************
*** 1734,1739 ****
--- 1855,1861 ----
  do_flag_alias(dbref player, const char *name, const char *alias)
  {
    FLAG *f;
+   FLAGSPACE *n;
    if (!God(player)) {
      notify(player, T("You don't look like God."));
      return;
***************
*** 1750,1762 ****
      notify(player, T("Flag aliases may not contain spaces."));
      return;
    }
!   f = match_flag(alias);
    if (f) {
      notify_format(player, T("That alias already matches the %s flag."),
  		  f->name);
      return;
    }
!   f = match_flag(name);
    if (!f) {
      notify(player, T("I don't know that flag."));
      return;
--- 1872,1885 ----
      notify(player, T("Flag aliases may not contain spaces."));
      return;
    }
!   n = hashfind("FLAG", &htab_flagspaces);
!   f = match_flag_ns(n, alias);
    if (f) {
      notify_format(player, T("That alias already matches the %s flag."),
  		  f->name);
      return;
    }
!   f = match_flag_ns(n, name);
    if (!f) {
      notify(player, T("I don't know that flag."));
      return;
***************
*** 1766,1776 ****
      return;
    }
    /* Insert the flag in the ptab by the given alias */
!   ptab_start_inserts(&ptab_flag);
!   ptab_insert(&ptab_flag, alias, f);
!   ptab_end_inserts(&ptab_flag);
!   if ((f = match_flag(alias)))
!     do_flag_info(player, alias);
    else
      notify(player, T("Unknown failure adding alias."));
  }
--- 1889,1899 ----
      return;
    }
    /* Insert the flag in the ptab by the given alias */
!   ptab_start_inserts(n->tab);
!   ptab_insert(n->tab, alias, f);
!   ptab_end_inserts(n->tab);
!   if ((f = match_flag_ns(n, alias)))
!     do_flag_info("FLAG", player, alias);
    else
      notify(player, T("Unknown failure adding alias."));
  }
***************
*** 1824,1834 ****
    char flagname[BUFFER_LEN];
    dbref i;
    int got_one;
    if (!God(player)) {
      notify(player, T("You don't look like God."));
      return;
    }
!   f = ptab_find_exact(&ptab_flag, name);
    if (!f) {
      notify(player, T("I don't know that flag."));
      return;
--- 1947,1960 ----
    char flagname[BUFFER_LEN];
    dbref i;
    int got_one;
+   FLAGSPACE *n;
+ 
    if (!God(player)) {
      notify(player, T("You don't look like God."));
      return;
    }
!   n = (FLAGSPACE *) hashfind("FLAG", &htab_flagspaces);
!   f = ptab_find_exact(n->tab, name);
    if (!f) {
      notify(player, T("I don't know that flag."));
      return;
***************
*** 1842,1865 ****
     */
    do {
      got_one = 0;
!     tmpf = ptab_firstentry_new(&ptab_flag, flagname);
      while (tmpf) {
        if (!strcmp(tmpf->name, f->name) &&
! 	  strcmp(flags[f->bitpos]->name, flagname)) {
! 	ptab_delete(&ptab_flag, flagname);
  	got_one = 1;
  	break;
        }
!       tmpf = ptab_nextentry_new(&ptab_flag, flagname);
      }
    } while (got_one);
    /* Reset the flag on all objects */
    for (i = 0; i < db_top; i++)
      twiddle_flag(i, f, 1);
    /* Remove the flag's entry in flags */
!   flags[f->bitpos] = NULL;
    /* Remove the flag from the ptab */
!   ptab_delete(&ptab_flag, f->name);
    notify_format(player, T("Flag %s deleted."), f->name);
    /* Free the flag. Don't use mush_free, see new_flag() */
    free((Malloc_t) f);
--- 1968,1991 ----
     */
    do {
      got_one = 0;
!     tmpf = ptab_firstentry_new(n->tab, flagname);
      while (tmpf) {
        if (!strcmp(tmpf->name, f->name) &&
! 	  strcmp(n->flags[f->bitpos]->name, flagname)) {
! 	ptab_delete(n->tab, flagname);
  	got_one = 1;
  	break;
        }
!       tmpf = ptab_nextentry_new(n->tab, flagname);
      }
    } while (got_one);
    /* Reset the flag on all objects */
    for (i = 0; i < db_top; i++)
      twiddle_flag(i, f, 1);
    /* Remove the flag's entry in flags */
!   n->flags[f->bitpos] = NULL;
    /* Remove the flag from the ptab */
!   ptab_delete(n->tab, f->name);
    notify_format(player, T("Flag %s deleted."), f->name);
    /* Free the flag. Don't use mush_free, see new_flag() */
    free((Malloc_t) f);
***************
*** 1897,1903 ****
  
  
  static char *
! list_aliases(FLAG *given)
  {
    FLAG *f;
    static char buf[BUFFER_LEN];
--- 2023,2029 ----
  
  
  static char *
! list_aliases(FLAGSPACE * n, FLAG *given)
  {
    FLAG *f;
    static char buf[BUFFER_LEN];
***************
*** 1905,1921 ****
    char flagname[BUFFER_LEN];
    int first = 1;
    bp = buf;
!   f = ptab_firstentry_new(&ptab_flag, flagname);
    while (f) {
      if (!strcmp(given->name, f->name) &&
! 	strcmp(flags[f->bitpos]->name, flagname)) {
        /* This is an alias! */
        if (!first)
  	safe_chr(' ', buf, &bp);
        first = 0;
        safe_str(flagname, buf, &bp);
      }
!     f = ptab_nextentry_new(&ptab_flag, flagname);
    }
    *bp = '\0';
    return buf;
--- 2031,2047 ----
    char flagname[BUFFER_LEN];
    int first = 1;
    bp = buf;
!   f = ptab_firstentry_new(n->tab, flagname);
    while (f) {
      if (!strcmp(given->name, f->name) &&
! 	strcmp(n->flags[f->bitpos]->name, flagname)) {
        /* This is an alias! */
        if (!first)
  	safe_chr(' ', buf, &bp);
        first = 0;
        safe_str(flagname, buf, &bp);
      }
!     f = ptab_nextentry_new(n->tab, flagname);
    }
    *bp = '\0';
    return buf;
***************
*** 1928,1934 ****
   * \param which a bitmask of 0x1 (flag chars) and 0x2 (flag names)u
   */
  char *
! list_all_flags(const char *name, dbref privs, int which)
  {
    FLAG *f;
    char **ptrs;
--- 2054,2060 ----
   * \param which a bitmask of 0x1 (flag chars) and 0x2 (flag names)u
   */
  char *
! list_all_flags(const char *ns, const char *name, dbref privs, int which)
  {
    FLAG *f;
    char **ptrs;
***************
*** 1936,1945 ****
    static char buf[BUFFER_LEN];
    char *bp;
    int disallowed;
    disallowed = God(privs) ? F_INTERNAL : (F_INTERNAL | F_DISABLED);
!   ptrs = (char **) malloc(flagbits * sizeof(char *));
!   for (i = 0; i < flagbits; i++) {
!     if ((f = flags[i]) && !(f->perms & disallowed)) {
        if (!name || !*name || quick_wild(name, f->name))
  	ptrs[numptrs++] = (char *) f->name;
      }
--- 2062,2074 ----
    static char buf[BUFFER_LEN];
    char *bp;
    int disallowed;
+   FLAGSPACE *n;
+ 
+   Flagspace_Lookup(n, ns);
    disallowed = God(privs) ? F_INTERNAL : (F_INTERNAL | F_DISABLED);
!   ptrs = (char **) malloc(n->flagbits * sizeof(char *));
!   for (i = 0; i < n->flagbits; i++) {
!     if ((f = n->flags[i]) && !(f->perms & disallowed)) {
        if (!name || !*name || quick_wild(name, f->name))
  	ptrs[numptrs++] = (char *) f->name;
      }
***************
*** 1952,1958 ****
        if (i)
  	safe_chr(' ', buf, &bp);
        safe_str(ptrs[i], buf, &bp);
!       f = match_flag(ptrs[i]);
        if (f && (f->letter != '\0'))
  	safe_format(buf, &bp, " (%c)", f->letter);
        break;
--- 2081,2087 ----
        if (i)
  	safe_chr(' ', buf, &bp);
        safe_str(ptrs[i], buf, &bp);
!       f = match_flag_ns(n, ptrs[i]);
        if (f && (f->letter != '\0'))
  	safe_format(buf, &bp, " (%c)", f->letter);
        break;
***************
*** 1962,1968 ****
        safe_str(ptrs[i], buf, &bp);
        break;
      case 0x1:
!       f = match_flag(ptrs[i]);
        if (f && (f->letter != '\0'))
  	safe_chr(f->letter, buf, &bp);
        break;
--- 2091,2097 ----
        safe_str(ptrs[i], buf, &bp);
        break;
      case 0x1:
!       f = match_flag_ns(n, ptrs[i]);
        if (f && (f->letter != '\0'))
  	safe_chr(f->letter, buf, &bp);
        break;
***************
*** 2056,2062 ****
      if (powers)
        safe_chr('\n', fbuf, &bp);
      safe_str("Flags      : ", fbuf, &bp);
!     safe_str(bits_to_string(flagmask, GOD, NOTHING), fbuf, &bp);
    }
  
    *bp = '\0';
--- 2185,2191 ----
      if (powers)
        safe_chr('\n', fbuf, &bp);
      safe_str("Flags      : ", fbuf, &bp);
!     safe_str(bits_to_string("FLAG", flagmask, GOD, NOTHING), fbuf, &bp);
    }
  
    *bp = '\0';
*** 1_7_7.551/src/db.c Thu, 14 Aug 2003 12:02:03 -0500 dunemush (pennmush/c/25_db.c 1.26.1.1.1.1.1.6.1.1.1.3 660)
--- 1_7_7.557(w)/src/db.c Tue, 19 Aug 2003 23:36:01 -0500 dunemush (pennmush/c/25_db.c 1.26.1.1.1.1.1.6.1.1.1.4 660)
***************
*** 216,222 ****
    o->zone = NOTHING;
    o->penn = 0;
    o->type = TYPE_GARBAGE;
!   o->flags = new_flag_bitmask();
    o->powers = 0;
    o->warnings = 0;
    o->modification_time = o->creation_time = mudtime;
--- 216,222 ----
    o->zone = NOTHING;
    o->penn = 0;
    o->type = TYPE_GARBAGE;
!   o->flags = new_flag_bitmask("FLAG");
    o->powers = 0;
    o->warnings = 0;
    o->modification_time = o->creation_time = mudtime;
***************
*** 455,461 ****
    putref(f, o->zone);
    putref(f, Pennies(i));
    putref(f, Typeof(i));
!   putstring(f, bits_to_string(o->flags, GOD, NOTHING));
    putref(f, o->powers);
    /* Original chat system wrote chat channels to the db here. 
     * That's no longer done, they're written to chatdb 
--- 455,461 ----
    putref(f, o->zone);
    putref(f, Pennies(i));
    putref(f, Typeof(i));
!   putstring(f, bits_to_string("FLAG", o->flags, GOD, NOTHING));
    putref(f, o->powers);
    /* Original chat system wrote chat channels to the db here. 
     * That's no longer done, they're written to chatdb 
***************
*** 556,562 ****
  db_write_flags(FILE * f)
  {
    OUTPUT(fprintf(f, "+FLAGS LIST\n"));
!   flag_write_all(f);
  }
  
  
--- 556,562 ----
  db_write_flags(FILE * f)
  {
    OUTPUT(fprintf(f, "+FLAGS LIST\n"));
!   flag_write_all(f, "FLAG");
  }
  
  
***************
*** 1055,1061 ****
  	}
        } else if (c == 'F') {
  	(void) getstring_noalloc(f);
! 	flag_read_all(f);
        } else {
  	do_rawlog(LT_ERR, T("Unrecognized database format!"));
  	return -1;
--- 1055,1061 ----
  	}
        } else if (c == 'F') {
  	(void) getstring_noalloc(f);
! 	flag_read_all(f, "FLAG");
        } else {
  	do_rawlog(LT_ERR, T("Unrecognized database format!"));
  	return -1;
***************
*** 1087,1093 ****
        s_Pennies(i, getref(f));
        if (indb_flags & DBF_NEW_FLAGS) {
  	o->type = getref(f);
! 	o->flags = string_to_bits(getstring_noalloc(f));
        } else {
  	int old_flags, old_toggles;
  	old_flags = getref(f);
--- 1087,1093 ----
        s_Pennies(i, getref(f));
        if (indb_flags & DBF_NEW_FLAGS) {
  	o->type = getref(f);
! 	o->flags = string_to_bits("FLAG", getstring_noalloc(f));
        } else {
  	int old_flags, old_toggles;
  	old_flags = getref(f);
*** 1_7_7.551/src/create.c Mon, 12 May 2003 16:54:32 -0500 dunemush (pennmush/c/27_create.c 1.27.1.3.1.1.1.1.1.1.1.2.1.1.1.1.1.22 660)
--- 1_7_7.557(w)/src/create.c Tue, 19 Aug 2003 23:36:01 -0500 dunemush (pennmush/c/27_create.c 1.27.1.3.1.1.1.1.1.1.1.2.1.1.1.1.1.23 660)
***************
*** 122,128 ****
      Zone(new_exit) = Zone(player);
      Source(new_exit) = loc;
      Type(new_exit) = TYPE_EXIT;
!     Flags(new_exit) = string_to_bits(options.exit_flags);
  
      /* link it in */
      PUSH(new_exit, Exits(loc));
--- 122,128 ----
      Zone(new_exit) = Zone(player);
      Source(new_exit) = loc;
      Type(new_exit) = TYPE_EXIT;
!     Flags(new_exit) = string_to_bits("FLAG", options.exit_flags);
  
      /* link it in */
      PUSH(new_exit, Exits(loc));
***************
*** 389,395 ****
      Owner(room) = Owner(player);
      Zone(room) = Zone(player);
      Type(room) = TYPE_ROOM;
!     Flags(room) = string_to_bits(options.room_flags);
  
      notify_format(player, T("%s created with room number %d."), name, room);
      if (argv[1] && *argv[1]) {
--- 389,395 ----
      Owner(room) = Owner(player);
      Zone(room) = Zone(player);
      Type(room) = TYPE_ROOM;
!     Flags(room) = string_to_bits("FLAG", options.room_flags);
  
      notify_format(player, T("%s created with room number %d."), name, room);
      if (argv[1] && *argv[1]) {
***************
*** 452,458 ****
      Zone(thing) = Zone(player);
      s_Pennies(thing, cost);
      Type(thing) = TYPE_THING;
!     Flags(thing) = string_to_bits(options.thing_flags);
  
      /* home is here (if we can link to it) or player's home */
      if ((loc = Location(player)) != NOTHING &&
--- 452,458 ----
      Zone(thing) = Zone(player);
      s_Pennies(thing, cost);
      Type(thing) = TYPE_THING;
!     Flags(thing) = string_to_bits("FLAG", options.thing_flags);
  
      /* home is here (if we can link to it) or player's home */
      if ((loc = Location(player)) != NOTHING &&
***************
*** 498,504 ****
    clone_locks(player, thing, clone);
    Zone(clone) = Zone(thing);
    Parent(clone) = Parent(thing);
!   Flags(clone) = clone_flag_bitmask(Flags(thing));
    if (!preserve) {
      clear_flag_internal(clone, "WIZARD");
      clear_flag_internal(clone, "ROYALTY");
--- 498,504 ----
    clone_locks(player, thing, clone);
    Zone(clone) = Zone(thing);
    Parent(clone) = Parent(thing);
!   Flags(clone) = clone_flag_bitmask("FLAG", Flags(thing));
    if (!preserve) {
      clear_flag_internal(clone, "WIZARD");
      clear_flag_internal(clone, "ROYALTY");
***************
*** 621,627 ****
        clone_locks(player, thing, clone);
        Zone(clone) = Zone(thing);
        Parent(clone) = Parent(thing);
!       Flags(clone) = clone_flag_bitmask(Flags(thing));
        if (!preserve) {
  	clear_flag_internal(clone, "WIZARD");
  	clear_flag_internal(clone, "ROYALTY");
--- 621,627 ----
        clone_locks(player, thing, clone);
        Zone(clone) = Zone(thing);
        Parent(clone) = Parent(thing);
!       Flags(clone) = clone_flag_bitmask("FLAG", Flags(thing));
        if (!preserve) {
  	clear_flag_internal(clone, "WIZARD");
  	clear_flag_internal(clone, "ROYALTY");
*** 1_7_7.551/src/command.c Mon, 11 Aug 2003 15:42:46 -0500 dunemush (pennmush/c/36_command.c 1.56.1.1.1.1.1.1.1.2.1.1.1.1.1.5.1.2.1.1.1.1.1.2.1.3.1.10.1.1.3.10 660)
--- 1_7_7.557(w)/src/command.c Tue, 19 Aug 2003 23:36:01 -0500 dunemush (pennmush/c/36_command.c 1.56.1.1.1.1.1.1.1.2.1.1.1.1.1.5.1.2.1.1.1.1.1.2.1.3.1.10.1.1.3.11 660)
***************
*** 450,456 ****
    switch_mask *sw = switchmask(switchstr);
  
    if (flagstr)
!     flagmask = string_to_bits(flagstr);
    ptab_start_inserts(&ptab_command);
    ptab_insert(&ptab_command, name,
  	      make_command(name, type, flagmask, powers, sw, func));
--- 450,456 ----
    switch_mask *sw = switchmask(switchstr);
  
    if (flagstr)
!     flagmask = string_to_bits("FLAG", flagstr);
    ptab_start_inserts(&ptab_command);
    ptab_insert(&ptab_command, name,
  	      make_command(name, type, flagmask, powers, sw, func));
***************
*** 600,608 ****
    ptab_start_inserts(&ptab_command);
    for (cmd = commands; cmd->name; cmd++) {
      ptab_insert(&ptab_command, cmd->name,
! 		make_command(cmd->name, cmd->type, string_to_bits(cmd->flagstr),
! 			     cmd->powers, switchmask(cmd->switches),
! 			     cmd->func));
    }
    ptab_end_inserts(&ptab_command);
  
--- 600,608 ----
    ptab_start_inserts(&ptab_command);
    for (cmd = commands; cmd->name; cmd++) {
      ptab_insert(&ptab_command, cmd->name,
! 		make_command(cmd->name, cmd->type,
! 			     string_to_bits("FLAG", cmd->flagstr), cmd->powers,
! 			     switchmask(cmd->switches), cmd->func));
    }
    ptab_end_inserts(&ptab_command);
  
***************
*** 1141,1147 ****
  	clear_flag_bitmask(command->flagmask, wiz->bitpos);
        } else {
  	if (!command->flagmask)
! 	  command->flagmask = new_flag_bitmask();
  	set_flag_bitmask(command->flagmask, roy->bitpos);
  	set_flag_bitmask(command->flagmask, wiz->bitpos);
        }
--- 1141,1147 ----
  	clear_flag_bitmask(command->flagmask, wiz->bitpos);
        } else {
  	if (!command->flagmask)
! 	  command->flagmask = new_flag_bitmask("FLAG");
  	set_flag_bitmask(command->flagmask, roy->bitpos);
  	set_flag_bitmask(command->flagmask, wiz->bitpos);
        }
***************
*** 1155,1161 ****
  	clear_flag_bitmask(command->flagmask, mask->bitpos);
        else {
  	if (!command->flagmask)
! 	  command->flagmask = new_flag_bitmask();
  	set_flag_bitmask(command->flagmask, mask->bitpos);
        }
      } else if ((powers = match_power(restriction))) {
--- 1155,1161 ----
  	clear_flag_bitmask(command->flagmask, mask->bitpos);
        else {
  	if (!command->flagmask)
! 	  command->flagmask = new_flag_bitmask("FLAG");
  	set_flag_bitmask(command->flagmask, mask->bitpos);
        }
      } else if ((powers = match_power(restriction))) {
***************
*** 1388,1394 ****
     * any match, the player is ok to do the command.
     */
    ok = 1;
!   check_flags = cmd->flagmask && !null_flagmask(cmd->flagmask);
  
    if (!((!cmd->powers && !check_flags) ||
  	(cmd->powers && (cmd->powers & Powers(player))) ||
--- 1388,1394 ----
     * any match, the player is ok to do the command.
     */
    ok = 1;
!   check_flags = cmd->flagmask && !null_flagmask("FLAG", cmd->flagmask);
  
    if (!((!cmd->powers && !check_flags) ||
  	(cmd->powers && (cmd->powers & Powers(player))) ||
*** 1_7_7.551/src/cmds.c Wed, 02 Jul 2003 14:19:13 -0500 dunemush (pennmush/c/37_cmds.c 1.33.1.1.1.2.1.2.2.3.1.1.1.2.1.1.1.3.1.8.1.1.2.2.2.19 660)
--- 1_7_7.557(w)/src/cmds.c Tue, 19 Aug 2003 23:36:00 -0500 dunemush (pennmush/c/37_cmds.c 1.33.1.1.1.2.1.2.2.3.1.1.1.2.1.1.1.3.1.8.1.1.2.2.2.20 660)
***************
*** 290,296 ****
    else if (SW_ISSET(sw, SWITCH_ENABLE))
      do_flag_enable(player, arg_left);
    else
!     do_flag_info(player, arg_left);
  }
  
  COMMAND (cmd_force) {
--- 290,296 ----
    else if (SW_ISSET(sw, SWITCH_ENABLE))
      do_flag_enable(player, arg_left);
    else
!     do_flag_info("FLAG", player, arg_left);
  }
  
  COMMAND (cmd_force) {
*** 1_7_7.551/src/bsd.c Sun, 17 Aug 2003 08:30:54 -0500 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.1.3.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.3.1.8.2.1.1.1.1.1.1.1.1.2.1.1.1.1.1.1.1.1.1.1.1.19 660)
--- 1_7_7.557(w)/src/bsd.c Tue, 19 Aug 2003 23:36:00 -0500 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.1.3.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.3.1.8.2.1.1.1.1.1.1.1.1.2.1.1.1.1.1.1.1.1.1.1.1.21 660)
***************
*** 165,171 ****
  extern int errno;		/**< Error number for routines that use it */
  #endif
  #endif
- extern int reserved;		/**< A reserved file descriptor */
  static int extrafd;
  int shutdown_flag = 0;		/**< Is it time to shut down? */
  extern int paranoid_dump;	/**< Are we doing a paranoid dump? */
--- 165,170 ----
***************
*** 268,275 ****
--- 267,276 ----
  static const char *register_success =
    "Registration successful! You will receive your password by email.";
  static const char *shutdown_message = "Going down - Bye";
+ #ifdef HAS_OPENSSL
  static const char *ssl_shutdown_message =
    "GAME: SSL connections must be dropped, sorry.";
+ #endif
  static const char *asterisk_line =
    "**********************************************************************";
  /** Where we save the descriptor info across reboots. */
***************
*** 296,303 ****
  
  DESC *descriptor_list = NULL;	/**< The linked list of descriptors */
  
! static int sock, sslsock = 0;
  #ifdef HAS_OPENSSL
  SSL *ssl_master_socket = NULL;
  #endif
  static int ndescriptors = 0;
--- 297,305 ----
  
  DESC *descriptor_list = NULL;	/**< The linked list of descriptors */
  
! static int sock;
  #ifdef HAS_OPENSSL
+ static int sslsock = 0;
  SSL *ssl_master_socket = NULL;
  #endif
  static int ndescriptors = 0;
***************
*** 640,648 ****
    init_game_config(confname);
  
    /* save a file descriptor */
  #ifndef macintosh
  #ifndef WIN32
-   reserved = open("/dev/null", O_RDWR);
    extrafd = open("/dev/null", O_RDWR);
  #endif
  #endif
--- 642,650 ----
    init_game_config(confname);
  
    /* save a file descriptor */
+   reserve_fd();
  #ifndef macintosh
  #ifndef WIN32
    extrafd = open("/dev/null", O_RDWR);
  #endif
  #endif
***************
*** 1411,1424 ****
      int fd, n;
      struct stat sb;
  
! #ifndef macintosh
!     close(reserved);
! #endif
      if ((fd = open(filename, O_RDONLY, 0)) < 0) {
        do_log(LT_ERR, 0, 0, T("Couldn't open cached text file '%s'"), filename);
! #ifndef macintosh
!       reserved = open("/dev/null", O_RDWR);
! #endif
        return -1;
      }
  
--- 1413,1422 ----
      int fd, n;
      struct stat sb;
  
!     release_fd();
      if ((fd = open(filename, O_RDONLY, 0)) < 0) {
        do_log(LT_ERR, 0, 0, T("Couldn't open cached text file '%s'"), filename);
!       reserve_fd();
        return -1;
      }
  
***************
*** 1426,1434 ****
        do_log(LT_ERR, 0, 0, T("Couldn't get the size of text file '%s'"),
  	     filename);
        close(fd);
! #ifndef macintosh
!       reserved = open("/dev/null", O_RDWR);
! #endif
        return -1;
      }
  
--- 1424,1430 ----
        do_log(LT_ERR, 0, 0, T("Couldn't get the size of text file '%s'"),
  	     filename);
        close(fd);
!       reserve_fd();
        return -1;
      }
  
***************
*** 1437,1445 ****
        do_log(LT_ERR, 0, 0, T("Couldn't allocate %d bytes of memory for '%s'!"),
  	     (int) sb.st_size, filename);
        close(fd);
! #ifndef macintosh
!       reserved = open("/dev/null", O_RDWR);
! #endif
        return -1;
      }
  
--- 1433,1439 ----
        do_log(LT_ERR, 0, 0, T("Couldn't allocate %d bytes of memory for '%s'!"),
  	     (int) sb.st_size, filename);
        close(fd);
!       reserve_fd();
        return -1;
      }
  
***************
*** 1448,1463 ****
        close(fd);
        mush_free(fb->buff, "fcache_data");
        fb->buff = NULL;
! #ifndef macintosh
!       reserved = open("/dev/null", O_RDWR);
! #endif
        return -1;
      }
  
      close(fd);
! #ifndef macintosh
!     reserved = open("/dev/null", O_RDWR);
! #endif
      fb->len = sb.st_size;
  
  #ifdef macintosh
--- 1442,1453 ----
        close(fd);
        mush_free(fb->buff, "fcache_data");
        fb->buff = NULL;
!       reserve_fd();
        return -1;
      }
  
      close(fd);
!     reserve_fd();
      fb->len = sb.st_size;
  
  #ifdef macintosh
***************
*** 1669,1674 ****
--- 1659,1665 ----
    ndescriptors--;
  }
  
+ /* ARGSUSED */
  static DESC *
  initializesock(int s, char *addr, char *ip, int use_ssl)
  {
***************
*** 2532,2537 ****
--- 2523,2529 ----
  
  }
  
+ /* ARGSUSED */
  static int
  process_input(DESC *d, int output_ready)
  {
*** 1_7_7.551/src/attrib.c Sun, 17 Aug 2003 15:38:47 -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.1.1.1.3.1.1.1.1.1.1.3.23 660)
--- 1_7_7.557(w)/src/attrib.c Tue, 19 Aug 2003 23:36:00 -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.1.1.1.3.1.1.1.1.1.1.3.24 660)
***************
*** 594,605 ****
  
    if (!wildcard(name)) {
      ptr = atr_get_noparent(thing, strupper(name));
!     if (ptr && (object_visual || Is_Visible_Attr(thing, ptr)))
        result = func(player, thing, name, ptr, args);
    } else {
      for (ptr = List(thing); ptr; ptr = next) {
        next = AL_NEXT(ptr);
!       if ((object_visual || Is_Visible_Attr(thing, ptr))
  	  && local_wild_match(name, AL_NAME(ptr)))
  	result += func(player, thing, name, ptr, args);
      }
--- 594,607 ----
  
    if (!wildcard(name)) {
      ptr = atr_get_noparent(thing, strupper(name));
!     if (ptr && (object_visual ? Can_Read_Attr(player, thing, ptr)
! 		: Is_Visible_Attr(thing, ptr)))
        result = func(player, thing, name, ptr, args);
    } else {
      for (ptr = List(thing); ptr; ptr = next) {
        next = AL_NEXT(ptr);
!       if ((object_visual ? Can_Read_Attr(player, thing, ptr)
! 	   : Is_Visible_Attr(thing, ptr))
  	  && local_wild_match(name, AL_NAME(ptr)))
  	result += func(player, thing, name, ptr, args);
      }
*** 1_7_7.551/src/access.c Mon, 16 Jun 2003 23:53:35 -0500 dunemush (pennmush/c/43_access.c 1.11.1.2.1.4.1.6 660)
--- 1_7_7.557(w)/src/access.c Tue, 19 Aug 2003 23:36:00 -0500 dunemush (pennmush/c/43_access.c 1.11.1.2.1.4.1.7 660)
***************
*** 114,120 ****
  };
  
  static struct access *access_top;
- extern int reserved;		/**< reserved file descriptor */
  static int add_access_node
    (const char *host, const dbref who, const int can, const int cant,
     const char *comment);
--- 114,119 ----
***************
*** 177,185 ****
    }
    access_top = NULL;
    /* Be sure we have a file descriptor */
! #ifndef WIN32
!   close(reserved);
! #endif
  #ifdef macintosh
    fp = fopen(ACCESS_FILE, "rb");
  #else
--- 176,182 ----
    }
    access_top = NULL;
    /* Be sure we have a file descriptor */
!   release_fd();
  #ifdef macintosh
    fp = fopen(ACCESS_FILE, "rb");
  #else
***************
*** 227,235 ****
      retval = 1;
      fclose(fp);
    }
! #ifndef WIN32
!   reserved = open("/dev/null", O_RDWR);
! #endif
    return retval;
  }
  
--- 224,230 ----
      retval = 1;
      fclose(fp);
    }
!   reserve_fd();
    return retval;
  }
  
***************
*** 246,254 ****
  
    sprintf(tmpf, "%s.tmp", ACCESS_FILE);
    /* Be sure we have a file descriptor */
! #ifndef WIN32
!   close(reserved);
! #endif
  #ifdef macintosh
    fp = fopen(tmpf, "wb");
  #else
--- 241,247 ----
  
    sprintf(tmpf, "%s.tmp", ACCESS_FILE);
    /* Be sure we have a file descriptor */
!   release_fd();
  #ifdef macintosh
    fp = fopen(tmpf, "wb");
  #else
***************
*** 296,304 ****
  #endif
      rename(tmpf, ACCESS_FILE);
    }
! #ifndef WIN32
!   reserved = open("/dev/null", O_RDWR);
! #endif
    return;
  }
  
--- 289,295 ----
  #endif
      rename(tmpf, ACCESS_FILE);
    }
!   reserve_fd();
    return;
  }
  
*** 1_7_7.551/hdrs/csrimalloc.h Mon, 28 Apr 2003 22:37:00 -0500 dunemush (pennmush/c/45_csrimalloc 1.8 660)
--- 1_7_7.557(w)/hdrs/csrimalloc.h Tue, 19 Aug 2003 23:36:08 -0500 dunemush (pennmush/c/45_csrimalloc 1.9 660)
***************
*** 90,96 ****
--- 90,98 ----
   *  SunOS3.5, this works fine.
   */
  #ifdef __GNUC__
+ #ifndef alloca
  #define alloca(n) __builtin_alloca(n)
+ #endif
  #endif				/* __GNUC__ */
  #ifdef sparc
  #define alloca(n) __builtin_alloca(n)
*** 1_7_7.551/hdrs/version.h Mon, 11 Aug 2003 16:14:42 -0500 dunemush (pennmush/c/47_version.h 1.32.1.2.1.7.1.9.1.1.1.17.1.21 660)
--- 1_7_7.557(w)/hdrs/version.h Tue, 19 Aug 2003 23:36:09 -0500 dunemush (pennmush/c/47_version.h 1.32.1.2.1.7.1.9.1.1.1.17.1.22 660)
***************
*** 1,3 ****
! #define VERSION "PennMUSH version 1.7.7 patchlevel 17 [08/11/2003]"
! #define SHORTVN "PennMUSH 1.7.7p17"
! #define NUMVERSION 001007007017
--- 1,3 ----
! #define VERSION "PennMUSH version 1.7.7 patchlevel 18 [08/19/2003]"
! #define SHORTVN "PennMUSH 1.7.7p18"
! #define NUMVERSION 001007007018
*** 1_7_7.551/hdrs/game.h Mon, 03 Feb 2003 11:05:37 -0600 dunemush (pennmush/d/12_game.h 1.28.1.2.1.1.1.1.1.1.1.7.1.5 660)
--- 1_7_7.557(w)/hdrs/game.h Tue, 19 Aug 2003 23:36:08 -0500 dunemush (pennmush/d/12_game.h 1.28.1.2.1.1.1.1.1.1.1.7.1.6 660)
***************
*** 16,22 ****
  extern void init_func_hashtab(void);	/* eval.c */
  extern void init_math_hashtab(void);	/* funmath.c */
  extern void init_aname_table(void);	/* atr_tab.c */
! extern void init_flag_table(void);	/* flags.c */
  extern void init_tag_hashtab(void);	/* funstr.c */
  extern void init_pronouns(void);	/* funstr.c */
  
--- 16,23 ----
  extern void init_func_hashtab(void);	/* eval.c */
  extern void init_math_hashtab(void);	/* funmath.c */
  extern void init_aname_table(void);	/* atr_tab.c */
! extern void init_flagspaces(void);	/* flags.c */
! extern void init_flag_table(const char *ns);	/* flags.c */
  extern void init_tag_hashtab(void);	/* funstr.c */
  extern void init_pronouns(void);	/* funstr.c */
  
*** 1_7_7.551/hdrs/flags.h Tue, 11 Mar 2003 12:38:07 -0600 dunemush (pennmush/d/14_flags.h 1.1.1.1.1.1.1.1.1.2.1.3.2.1.1.4.1.1.1.1.2.1.1.24 660)
--- 1_7_7.557(w)/hdrs/flags.h Tue, 19 Aug 2003 23:36:08 -0500 dunemush (pennmush/d/14_flags.h 1.1.1.1.1.1.1.1.1.2.1.3.2.1.1.4.1.1.1.1.2.1.1.25 660)
***************
*** 6,11 ****
--- 6,13 ----
  #define __FLAGS_H
  
  #include "conf.h"
+ #include "ptab.h"
+ 
  typedef struct flag_info FLAG;
  
  /** A flag.
***************
*** 52,59 ****
    const char *realname;		/**< The real name of the power */
  };
  
  /* From flags.c */
- extern FLAG *flag_hash_lookup(const char *name, int type);
  extern int has_flag_by_name(dbref thing, const char *flag, int type);
  extern const char *unparse_flags(dbref thing, dbref player);
  extern const char *flag_description(dbref player, dbref thing);
--- 54,75 ----
    const char *realname;		/**< The real name of the power */
  };
  
+ typedef struct flagspace FLAGSPACE;
+ 
+ /** A flagspace.
+  * A structure that contains all the information necessary to manage
+  * a set of flags, powers, or whatever.
+  */
+ struct flagspace {
+   PTAB *tab;			/**< Prefix table storing flags by name/alias */
+   FLAG **flags;			/**< Variable-length array of pointers to canonical flags, indexed by bit */
+   int flagbits;			/**< Current length of the flags array */
+   FLAG *flag_table;		/**< Pointer to flag table */
+   FLAG_ALIAS *flag_alias_table;	/**< Pointer to flag alias table */
+ };
+ 
+ 
  /* From flags.c */
  extern int has_flag_by_name(dbref thing, const char *flag, int type);
  extern const char *unparse_flags(dbref thing, dbref player);
  extern const char *flag_description(dbref player, dbref thing);
***************
*** 62,97 ****
  		     int hear, int listener);
  extern const char *power_description(dbref thing);
  extern int find_power(const char *name);
! extern int flaglist_check(dbref player, dbref it, const char *fstr, int type);
! extern int flaglist_check_long(dbref player, dbref it, const char *fstr,
! 			       int type);
  extern FLAG *match_flag(const char *name);
  extern int match_power(const char *name);
  extern const char *show_command_flags(object_flag_type flags, int powers);
! extern void twiddle_flag_internal(dbref thing, const char *flag, int negate);
! extern object_flag_type new_flag_bitmask(void);
! extern object_flag_type clone_flag_bitmask(object_flag_type given);
! extern void copy_flag_bitmask(object_flag_type dest, object_flag_type given);
  extern void destroy_flag_bitmask(object_flag_type bitmask);
  extern void set_flag_bitmask(object_flag_type bitmask, int bit);
  extern void clear_flag_bitmask(object_flag_type bitmask, int bit);
  extern int has_bit(object_flag_type bitmask, int bitpos);
! extern int has_all_bits(object_flag_type source, object_flag_type bitmask);
! extern int null_flagmask(object_flag_type source);
! extern int has_any_bits(object_flag_type source, object_flag_type bitmask);
! extern object_flag_type string_to_bits(const char *str);
! extern const char *bits_to_string(object_flag_type bitmask, dbref privs,
! 				  dbref thing);
! extern void flag_write_all(FILE *);
! extern void flag_read_all(FILE *);
  extern int type_from_old_flags(long old_flags);
  extern object_flag_type flags_from_old_flags(long old_flags, long old_toggles,
  					     int type);
  extern void add_flag(const char *name, const char letter, int type,
  		     int perms, int negate_perms);
  extern void do_list_flags(dbref player, const char *arg, int lc);
! extern char *list_all_flags(const char *name, dbref privs, int which);
! extern void do_flag_info(dbref player, const char *name);
  extern void do_flag_delete(dbref player, const char *name);
  extern void do_flag_disable(dbref player, const char *name);
  extern void do_flag_alias(dbref player, const char *name, const char *alias);
--- 78,120 ----
  		     int hear, int listener);
  extern const char *power_description(dbref thing);
  extern int find_power(const char *name);
! extern int flaglist_check(const char *ns, dbref player, dbref it,
! 			  const char *fstr, int type);
! extern int flaglist_check_long(const char *ns, dbref player, dbref it,
! 			       const char *fstr, int type);
  extern FLAG *match_flag(const char *name);
  extern int match_power(const char *name);
  extern const char *show_command_flags(object_flag_type flags, int powers);
! extern void twiddle_flag_internal(const char *ns, dbref thing, const char *flag,
! 				  int negate);
! extern object_flag_type new_flag_bitmask(const char *ns);
! extern object_flag_type clone_flag_bitmask(const char *ns,
! 					   object_flag_type given);
! extern void copy_flag_bitmask(const char *ns, object_flag_type dest,
! 			      object_flag_type given);
  extern void destroy_flag_bitmask(object_flag_type bitmask);
  extern void set_flag_bitmask(object_flag_type bitmask, int bit);
  extern void clear_flag_bitmask(object_flag_type bitmask, int bit);
  extern int has_bit(object_flag_type bitmask, int bitpos);
! extern int has_all_bits(const char *ns, object_flag_type source,
! 			object_flag_type bitmask);
! extern int null_flagmask(const char *ns, object_flag_type source);
! extern int has_any_bits(const char *ns, object_flag_type source,
! 			object_flag_type bitmask);
! extern object_flag_type string_to_bits(const char *ns, const char *str);
! extern const char *bits_to_string(const char *ns, object_flag_type bitmask,
! 				  dbref privs, dbref thing);
! extern void flag_write_all(FILE *, const char *);
! extern void flag_read_all(FILE *, const char *);
  extern int type_from_old_flags(long old_flags);
  extern object_flag_type flags_from_old_flags(long old_flags, long old_toggles,
  					     int type);
  extern void add_flag(const char *name, const char letter, int type,
  		     int perms, int negate_perms);
  extern void do_list_flags(dbref player, const char *arg, int lc);
! extern char *list_all_flags(const char *ns, const char *name, dbref privs,
! 			    int which);
! extern void do_flag_info(const char *ns, dbref player, const char *name);
  extern void do_flag_delete(dbref player, const char *name);
  extern void do_flag_disable(dbref player, const char *name);
  extern void do_flag_alias(dbref player, const char *name, const char *alias);
***************
*** 103,114 ****
  
  #define twiddle_flag_bitmask(bm,b,neg) (neg ? clear_flag_bitmask(bm,b) : \
                                                  set_flag_bitmask(bm,b))
! #define has_all_flags_by_mask(x,bm) has_all_bits(Flags(x),bm)
! #define has_any_flags_by_mask(x,bm) has_any_bits(Flags(x),bm)
  #define twiddle_flag(thing,f,negate) \
    twiddle_flag_bitmask(Flags(thing),f->bitpos,negate)
! #define set_flag_internal(t,f) twiddle_flag_internal(t,f,0)
! #define clear_flag_internal(t,f) twiddle_flag_internal(t,f,1)
  
  /*---------------------------------------------------------------------
   * Object types (no longer part of the flags)
--- 126,137 ----
  
  #define twiddle_flag_bitmask(bm,b,neg) (neg ? clear_flag_bitmask(bm,b) : \
                                                  set_flag_bitmask(bm,b))
! #define has_all_flags_by_mask(x,bm) has_all_bits("FLAG",Flags(x),bm)
! #define has_any_flags_by_mask(x,bm) has_any_bits("FLAG",Flags(x),bm)
  #define twiddle_flag(thing,f,negate) \
    twiddle_flag_bitmask(Flags(thing),f->bitpos,negate)
! #define set_flag_internal(t,f) twiddle_flag_internal("FLAG",t,f,0)
! #define clear_flag_internal(t,f) twiddle_flag_internal("FLAG",t,f,1)
  
  /*---------------------------------------------------------------------
   * Object types (no longer part of the flags)
*** 1_7_7.551/hdrs/externs.h Thu, 17 Jul 2003 16:30:15 -0500 dunemush (pennmush/d/16_externs.h 1.1.1.53.1.2.1.8.2.1.1.2.1.1.1.1.1.2.1.6.1.3.1.4.3.1.1.1.1.12 660)
--- 1_7_7.557(w)/hdrs/externs.h Tue, 19 Aug 2003 23:36:08 -0500 dunemush (pennmush/d/16_externs.h 1.1.1.53.1.2.1.8.2.1.1.2.1.1.1.1.1.2.1.6.1.3.1.4.3.1.1.1.1.13 660)
***************
*** 181,186 ****
--- 181,189 ----
  extern dbref orator;
  int parse_chat(dbref player, char *command);
  extern void fork_and_dump(int forking);
+ void reserve_fd(void);
+ void release_fd(void);
+ 
  
  /* From look.c */
  /** Enumeration of types of looks that can be performed */
*** 1_7_7.551/win32/funs.h Mon, 18 Aug 2003 12:06:39 -0500 dunemush (pennmush/f/12_funs.h 1.11.1.9.2.8.2.1.1.1.1.2.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.8.1.3.1.7.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.9 660)
--- 1_7_7.557(w)/win32/funs.h Tue, 19 Aug 2003 17:50:07 -0500 dunemush (pennmush/f/12_funs.h 1.11.1.9.2.8.2.1.1.1.1.2.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.8.1.3.1.7.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.10 660)
***************
*** 322,324 ****
--- 322,325 ----
  FUNCTION_PROTO(fun_zemit);
  FUNCTION_PROTO(fun_zfun);
  FUNCTION_PROTO(fun_zone);
+ FUNCTION_PROTO(local_fun_silly);
*** 1_7_7.551/win32/cmds.h Tue, 12 Aug 2003 11:05:22 -0500 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.1.1.1.1.1.1.1.1.1.1.1.9.1.7.2.4.1.2.3.1.1.1.1.1.1.6 660)
--- 1_7_7.557(w)/win32/cmds.h Tue, 19 Aug 2003 17:50:03 -0500 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.1.1.1.1.1.1.1.1.1.1.1.9.1.7.2.4.1.2.3.1.1.1.1.1.1.7 660)
***************
*** 62,67 ****
--- 62,68 ----
  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);
*** 1_7_7.551/game/txt/hlp/pennvOLD.hlp Wed, 02 Jul 2003 14:19:13 -0500 dunemush (pennmush/g/30_pennvOLD.h 1.1.1.1.1.1.1.1.1.1.1.2 660)
--- 1_7_7.557(w)/game/txt/hlp/pennvOLD.hlp Tue, 19 Aug 2003 23:36:10 -0500 dunemush (pennmush/g/30_pennvOLD.h 1.1.1.1.1.1.1.1.1.1.1.3 660)
***************
*** 4417,4423 ****
  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.7: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17
  1.7.6: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13
  1.7.5: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12
  1.7.4: 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 <version>p<patchlevel>'. For example, 'help 1.7.2p3'
  
! 1.7.7: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18
  1.7.6: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13
  1.7.5: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12
  1.7.4: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
*** 1_7_7.551/game/txt/hlp/pennv177.hlp Sun, 17 Aug 2003 08:30:54 -0500 dunemush (pennmush/g/34_pennv177.h 1.97 660)
--- 1_7_7.557(w)/game/txt/hlp/pennv177.hlp Tue, 19 Aug 2003 23:36:09 -0500 dunemush (pennmush/g/34_pennv177.h 1.102 660)
***************
*** 1,4 ****
! & 1.7.7p17
  & 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.7.7p18
  & 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,34 ----
  A list of the patchlevels associated with each release can
  be read in 'help patchlevels'.
  
+ Version 1.7.7 patchlevel 18                     August 19, 2003
+ 
+ Major Changes:
+   * The flag handling code has been additionally abstracted to 
+     allow, in a future patchlevel, @powers to be handled in the
+     same way that flags are now.
+ Minor Changes:
+   * Wrap the OS-dependant code for making sure the mush always has a free
+     file descriptor available for use in a pair of functions. [SW]
+ Fixes:
+   * Linted some ssl-related warnings. Reported by Cheetah at M*U*S*H.
+   * Compile failed in timer.c unless USE_MAILER was defined.
+     Reported by Sunny at M*U*S*H.
+   * Bug allowing players to view internal and mortal_dark attributes
+     introduced in p17 has been fixed. [TAP]
+ 
+ 
+ & 1.7.7p17
  Version 1.7.7 patchlevel 17                     August 11, 2003
  
  Major changes:
*** 1_7_7.551/src/myssl.c Sun, 10 Aug 2003 14:55:57 -0500 dunemush (pennmush/g/40_myssl.c 1.15 660)
--- 1_7_7.557(w)/src/myssl.c Tue, 19 Aug 2003 23:36:03 -0500 dunemush (pennmush/g/40_myssl.c 1.17 660)
***************
*** 1,4 ****
! /* Code to support SSL connections */
  
  #include "copyrite.h"
  #include "config.h"
--- 1,14 ----
! /**
!  * \file myssl.c
!  *
!  * \brief Code to support SSL connections in PennMUSH.
!  *
!  * This file contains nearly all of the code that interacts with the
!  * OpenSSL libraries to suppose SSL connections in PennMUSH.
!  *
!  * Lots of stuff here taken from Eric Rescorla's 2001 Linux Journal
!  * articles "An Introduction to OpenSSL Programming"
!  */
  
  #include "copyrite.h"
  #include "config.h"
***************
*** 90,109 ****
  static int client_verify_callback(int preverify_ok, X509_STORE_CTX * x509_ctx);
  static DH *get_dh1024(void);
  
- /* Right now, we expect to call this from the loop in bsd.c, but
-  * ideally, this API will also allow us to write a separate
-  * SSL thread and call these functions there instead.
-  *
-  * Functions:
-  * ssl_init() - initialize the ssl stuff
-  *
-  * Lots of stuff here taken from Eric Rescorla's 2001 Linux Journal
-  * articles "An Introduction to OpenSSL Programming"
-  */
  
  static BIO *bio_err = NULL;
  static SSL_CTX *ctx = NULL;
  
  SSL_CTX *
  ssl_init(void)
  {
--- 100,112 ----
  static int client_verify_callback(int preverify_ok, X509_STORE_CTX * x509_ctx);
  static DH *get_dh1024(void);
  
  
  static BIO *bio_err = NULL;
  static SSL_CTX *ctx = NULL;
  
+ /** Initialize the SSL context.
+  * \return pointer to SSL context object.
+  */
  SSL_CTX *
  ssl_init(void)
  {
***************
*** 239,244 ****
--- 242,249 ----
  
  
  /** Associate an SSL object with a socket and return it.
+  * \param sock socket descriptor to associate with an SSL object.
+  * \return pointer to SSL object.
   */
  SSL *
  ssl_setup_socket(int sock)
***************
*** 253,258 ****
--- 258,270 ----
    return ssl;
  }
  
+ /** Close down an SSL connection and free the object.
+  * \param ssl pointer to SSL object to close down.
+  * Technically, this function sends a shutdown notification
+  * and then frees the object without waiting for acknowledgement
+  * of the shutdown. If there were a good way to do that, it would
+  * be better.
+  */
  void
  ssl_close_connection(SSL * ssl)
  {
***************
*** 293,298 ****
--- 305,317 ----
  }
  
  
+ /** Perform an SSL handshake.
+  * In some cases, a handshake may block, so we may have to call this
+  * function again. Accordingly, we return state information that
+  * tells us if we need to do that.
+  * \param ssl pointer to an SSL object.
+  * \return resulting state of the object.
+  */
  int
  ssl_handshake(SSL * ssl)
  {
***************
*** 305,323 ****
        /* We must want for the socket to be readable, and then repeat
         * the call.
         */
!       ssl_debugdump("SSL_resume wants read");
        state = MYSSL_RB | MYSSL_HANDSHAKE;
        break;
      case SSL_ERROR_WANT_WRITE:
        /* We must want for the socket to be writable, and then repeat
         * the call.
         */
!       ssl_debugdump("SSL_resume wants write");
        state = MYSSL_WB | MYSSL_HANDSHAKE;
        break;
      default:
        /* Oops, don't know what's wrong */
!       ssl_errordump("Error resuming connection");
        state = -1;
      }
    } else {
--- 324,342 ----
        /* We must want for the socket to be readable, and then repeat
         * the call.
         */
!       ssl_debugdump("SSL_do_handshake wants read");
        state = MYSSL_RB | MYSSL_HANDSHAKE;
        break;
      case SSL_ERROR_WANT_WRITE:
        /* We must want for the socket to be writable, and then repeat
         * the call.
         */
!       ssl_debugdump("SSL_do_handshake wants write");
        state = MYSSL_WB | MYSSL_HANDSHAKE;
        break;
      default:
        /* Oops, don't know what's wrong */
!       ssl_errordump("Error in ssl_handshake");
        state = -1;
      }
    } else {


More information about the Pennmush-announce mailing list