Merge remote-tracking branch 'origin/0.73-development'
authorAri Johnson <ari@theari.com>
Mon, 19 Jan 2015 19:16:11 +0000 (14:16 -0500)
committerAri Johnson <ari@theari.com>
Mon, 19 Jan 2015 19:16:11 +0000 (14:16 -0500)
Also update code so that everything compiles

20 files changed:
1  2 
.gitignore
Makefile.in
game/mushcnf.dst
game/txt/hlp/cobra_chat.hlp
game/txt/hlp/cobra_func.hlp
hdrs/conf.h
hdrs/extchat.h
hdrs/mushdb.h
m4/ax_lua.m4
src/bsd.c
src/conf.c
src/division.c
src/extchat.c
src/funmath.c
src/funmisc.c
src/game.c
src/mushlua.c
src/set.c
src/speech.c
utils/mkcmds.pl

diff --cc .gitignore
index f30d534106414ea13958a424aa0f7a20fb5507ad,429ffdcbd720b5f70fa48363ef55549f693afd24..4fe6f7f6a3cfb4238a78b9dd24f64344b4d4cb40
@@@ -1,13 -1,25 +1,23 @@@
 -Configure
 +autom4te.cache
 +aclocal.m4
 +configure
  Makefile
 -.config
 -Obsolete
 -Wanted
 +config.log
 +config.status
  config.h
 -config.sh
 -config.sh.old
 -config_h.SH
 -confmagic.h
  options.h
  options.h.bak
 +test/alltests.sh
+ src/cmdlocal.c
+ src/console
+ src/console~
+ src/flaglocal.c
+ src/funlocal.c
+ src/local.c
+ utils/mkcmds.sh
+ win32/cmds.h
+ win32/funs.h
+ win32/switches.h
  hdrs/buildinf.h
  hdrs/cmds.h
  hdrs/funs.h
diff --cc Makefile.in
index 33ccdaa942c0760eb93363116d5ed038b99bb3a8,0000000000000000000000000000000000000000..7a780a077fa5cee507d2aad42bf3cec5484c5cc4
mode 100644,000000..100644
--- /dev/null
@@@ -1,227 -1,0 +1,227 @@@
- CCFLAGS=@CFLAGS@ -I.. -I../hdrs @OPENSSL_INCLUDES@ @CPPFLAGS@ @PCRE_CFLAGS@ -Werror
 +# Makefile for CobraMUSH 
 +
 +# - System configuration - #
 +
 +VERSION=0.80
 +PATCHLEVEL=0
 +
 +#
 +# This section of the file should be automatically configured by
 +# the Configure script. If it doesn't work, you might try starting
 +# from the Makefile.old that's included instead, and reporting
 +# your problem (including this Makefile) to pennmush-bugs@pennmush.org
 +#
 +# If you want to profile the code, add -pg -a -DPROFILING to CCFLAGS
 +# and (probably) remove -O
 +#
 +MAKE=@MAKE@
 +CC=@CC@
 +
 +SQL_CFLAGS=@MYSQL_CFLAGS@ @POSTGRESQL_CFLAGS@ @SQLITE3_CFLAGS@
 +SQL_LDFLAGS=@MYSQL_LDFLAGS@ @POSTGRESQL_LDFLAGS@ @SQLITE3_LDFLAGS@
 +LIBTOOL=@LIBTOOL@
 +
 +CPPFLAGS=@CPPFLAGS@
++CCFLAGS=@CFLAGS@ -I.. -I../hdrs @OPENSSL_INCLUDES@ @CPPFLAGS@ @PCRE_CFLAGS@ -Wall -Wno-comment -Wno-unused-but-set-variable -Werror
 +LDFLAGS=@LDFLAGS@  @OPENSSL_INCLUDES@
 +CLIBS=@LIBS@ @PCRE_LIBS@ @LIBLTDL@ @LIBLUA@ @OPENSSL_LIBS@
 +INSTALL=@INSTALL@
 +INSTALLDIR=$installdir
 +CP=@CP@
 +CHMOD=@CHMOD@
 +INSTALL_LINKS=@LN_S@ ../src/netmud netmush; @LN_S@ ../src/info_slave info_slave
 +
 +# stupid SYS V shell
 +SHELL=/bin/sh
 +# Where to install with 'make globalinstall'
 +GLOBAL_INSTALL=@libexecdir@
 +
 +all: config.h options.h autogen game/mush.cnf
 +      @echo "Making all in src."
 +      (cd src; @MAKE@ all "CC=$(CC)" "CCFLAGS=$(CCFLAGS)" \
 +      "LDFLAGS=$(LDFLAGS)" "CLIBS=$(CLIBS)" "MAKE=$(MAKE)" \
 +      "MAKEFLAGS=$(MAKEFLAGS)" "SQL_CFLAGS=$(SQL_CFLAGS)" \
 +      "SQL_LDFLAGS=$(SQL_LDFLAGS)")
 +      @echo "If the make was successful, use 'make install' to install links."
 +
 +config.h: configure
 +      @echo "Looks like your configure has been updated."
 +      @echo "Run that first. If you did just run configure and"
 +      @echo "it said that config.h was unchanged, 'touch config.h'"
 +      @echo "to suppress this message and continue compiling."
 +      @exit 1
 +
 +options.h: options.h.dist
 +      @echo "Please use 'make update' to update your options.h file from options.h.dist"
 +      @echo "You must cp options.h.dist to options.h and edit it."
 +      @exit 1
 +
 +autogen: hdrs/cmds.h hdrs/funs.h hdrs/switches.h
 +
 +hdrs/cmds.h: src/cmds.c src/command.c src/cque.c src/help.c src/set.c src/sql.c Patchlevel
 +      @PERL@ utils/mkcmds.pl commands
 +
 +hdrs/switches.h: src/SWITCHES Patchlevel
 +      @PERL@ utils/mkcmds.pl switches
 +
 +src/switchinc.c: src/SWITCHES Patchlevel
 +      @PERL@ utils/mkcmds.pl switches
 +
 +hdrs/funs.h: src/fun*.c src/bsd.c src/conf.c src/extmail.c src/help.c src/markup.c src/wiz.c src/sql.c Patchlevel
 +      @PERL@ utils/mkcmds.pl functions
 +
 +hdrs/patches.h: patches/*
 +      @PERL@ utils/mkcmds.pl patches
 +
 +install: localized all
 +      -rm -f game/netmush
 +      -rm -f game/info_slave
 +      (cd game; $(INSTALL_LINKS))
 +      (cd game/txt; make)
 +      @echo "If you plan to run multiple MUSHes, consider running 'make customize'"
 +
 +netmud: 
 +      (cd src; make netmud "CC=$(CC)" "CCFLAGS=$(CCFLAGS)" \
 +      "SQL_CFLAGS=$(SQL_CFLAGS)" "SQL_LDFLAGS=$(SQL_LDFLAGS)" \
 +      "LDFLAGS=$(LDFLAGS)" "CLIBS=$(CLIBS)" )
 +
 +access:
 +      utils/make_access_cnf.sh game
 +
 +pennmush.pot:
 +      (cd src; make ../po/pennmush.pot)
 +
 +localized:
 +      -echo "Localizing for your locale..."
 +      -(cd po; make localized)
 +
 +portmsg:
 +      (cd src; make portmsg "CC=$(CC)" "CCFLAGS=$(CCFLAGS)" \
 +      "LDFLAGS=$(LDFLAGS)" "CLIBS=$(CLIBS)" )
 +
 +ssl_slave:
 +      (cd src; make ssl_slave "CC=$(CC)" "CCFLAGS=$(CCFLAGS)" \
 +      "LDFLAGS=$(LDFLAGS)" "CLIBS=$(CLIBS)" "MAKE=$(MAKE)" \
 +      "MAKEFLAGS=$(MAKEFLAGS)")
 +
 +versions: CHANGES*
 +      -@rm -rf CHANGES*~ CHANGES*bak
 +      @utils/mkvershlp.pl game/txt/hlp CHANGES*
 +
 +safety:
 +      $(CP) src/*.c 
 +      $(CP) hdrs/*.h 
 +      $(CP) * 
 +
 +distdepend: hdrs/funs.h hdrs/cmds.h
 +      (cd src; @MAKE@ depend "CC=$(CC)" "CCFLAGS=$(CCFLAGS)" \
 +      "LDFLAGS=$(LDFLAGS)" "CLIBS=$(CLIBS)" )
 +
 +# REQUIRES GNU INDENT! DON'T INDENT WITH ANYTHING ELSE!
 +indent:
 +      @(cd src; make indent)
 +
 +customize: update-conf
 +      -@@PERL@ utils/customize.pl
 +
 +# The default place to find the runtime files is in this directory,
 +# but it can be overridden with env variables so people can use
 +# other game directories.
 +GAMEDIR=game
 +
 +update-conf: game/mush.cnf game/alias.cnf game/restrict.cnf game/names.cnf game/restart
 +
 +$(GAMEDIR)/alias.cnf: game/aliascnf.dst
 +      -@@TOUCH@ game/aliascnf.dst
 +      -@@PERL@ utils/update-cnf.pl $(GAMEDIR)/alias.cnf game/aliascnf.dst
 +
 +$(GAMEDIR)/restrict.cnf: game/restrictcnf.dst
 +      -@@TOUCH@ game/restrictcnf.dst
 +      -@@PERL@ utils/update-cnf.pl $(GAMEDIR)/restrict.cnf game/restrictcnf.dst
 +
 +$(GAMEDIR)/names.cnf: game/namescnf.dst
 +      if [ ! -f game/names.cnf ]; then \
 +              $(CP) game/namescnf.dst $(GAMEDIR)/names.cnf; \
 +      fi
 +
 +$(GAMEDIR)/restart: game/restart.dst
 +ifeq ("$(shell which bash)", "")
 +      @echo "********************************************************************************";
 +      @echo "* Restart script has been updated in this distribution.                        *";
 +      @echo "* However, bash has not been installed on your system.                         *";
 +      @echo "* Please cp game/restart.dst to game/restart if you would like our updated     *";
 +      @echo "* restart script.                                                              *";
 +      @echo "********************************************************************************";
 +else
 +      -@@BASH@ utils/checkrestart.sh
 +endif
 +
 +
 +$(GAMEDIR)/mush.cnf: game/mushcnf.dst
 +      -@@TOUCH@ game/mushcnf.dst
 +      -@@PERL@ utils/update-cnf.pl $(GAMEDIR)/mush.cnf game/mushcnf.dst
 +
 +update: update-hdr update-conf
 +
 +update-hdr:
 +      -@@TOUCH@ options.h.dist
 +      -@sleep 2
 +      -@@PERL@ utils/update.pl options.h options.h.dist
 +
 +test: netmud
 +      (cd test; @PERL@ alltests.pl)
 +
 +clean:
 +      (cd src; make clean)
 +      (cd game; rm -f netmush info_slave netmush~ info_slave~)
 +
 +distclean: 
 +      (cd hdrs; rm -f *.orig *~ \#* *.rej *.bak funs.h cmds.h buildinf.h patches.h)
 +      (cd utils; rm -f *.orig *~ \#* *.rej *.bak mkcmds.sh *.o)
 +      (cd game; rm -rf *.log netmush info_slave *.orig *.rej *~ *.bak mush.cnf)
 +      (cd src; make distclean; rm -f Makefile)
 +      (cd game/txt; make clean)
 +      (rm -rf .config Makefile config.h config.sh options.h)
 +
 +totallyclean: distclean 
 +      (cd hdrs; rm -rf *.rej)
 +      (cd src; rm -rf *.rej)
 +      -rm -f Makefile
 +
 +diffs:
 +      @make indent > /dev/null 2>&1
 +      @make versions > /dev/null 2>&1
 +      @make touchswitches > /dev/null 2>&1
 +      @make autogen > /dev/null 2>&1
 +      @(prcs diff -r$(VS) -N cobramush `cat MANIFEST` | grep -v 'Index:')
 +
 +commit: indent
 +      @svn commit
 +
 +patch: versions
 +      @make-patch-header
 +      @make diffs
 +
 +etags: 
 +      (cd src; make etags)
 +
 +ctags:
 +      (cd src; make ctags)
 +
 +touchswitches:
 +      @@TOUCH@ src/SWITCHES
 +
 +globalinstall: install
 +      (cd game/txt; make clean compose.sh)
 +#     $(INSTALLDIR) $(GLOBAL_INSTALL)
 +      $(CP) -R game/* $(GLOBAL_INSTALL)
 +      rm -f $(GLOBAL_INSTALL)/netmush $(GLOBAL_INSTALL)/info_slave
 +      $(INSTALL) config.sh $(GLOBAL_INSTALL)/config.sh
 +      $(INSTALL) src/netmud $(GLOBAL_INSTALL)/netmush
 +      $(INSTALL) src/info_slave utils/ln-dir.sh $(GLOBAL_INSTALL)
 +      $(CHMOD) a+rX -R $(GLOBAL_INSTALL)
 +      @echo "** Files installed in $(GLOBAL_INSTALL). Feel free to move them."
 +      @echo "** You can run $(GLOBAL_INSTALL)/ln-dir.sh to create a user directory,"
 +      @echo "** or symlink that to somewhere easier to run. You may wish to strip them."
 +
 +
Simple merge
Simple merge
index 4243d15381870171dc7e902ad849ae6c98fe48ed,dc2efaf7c7bf6b390e278d3a61ab9180e315a39a..e690e72139789be5aeaf385e1d53385e751e2e6a
@@@ -536,9 -516,9 +536,9 @@@ See also: BOOLEAN VALUES, or(), xor(), 
    result. It is useful in converting between cartesian and polar
    coordinates.
  
 -  See HELP CTU() for more on the angle type.
 +  See 'HELP CTU()' for more on the angle type.
  & ATRLOCK()
-   atrlock(<object>/<attrib>[, <on|off>])
+   atrlock(<object>/<attrib>[, <boolexp>])
  
    When given a single object/attribute pair as an argument, returns 1
    if the attribute is locked, 0 if unlocked, and #-1 if the attribute
diff --cc hdrs/conf.h
index 5168f4f7f0750975a152305e9300df2be567d6d4,31220eb8e24442be4c6f27c51ab41e93b7ac00e2..263244cc8acbd1d849c8c4d087d1d94ff7909650
@@@ -294,6 -306,8 +294,7 @@@ struct options_table 
    char command_log[256]; /**< File to log suspect commands */
    char trace_log[256]; /**< File to log trace data */
    char checkpt_log[256]; /**< File to log checkpoint data */
 -#ifdef HAS_MYSQL
+   char chatlog_dir[256]; /**< Directory to store chat logs */
    char sql_platform[256]; /**< Type of SQL server, or "disabled" */
    char sql_host[256]; /**< Hostname of sql server */
    char sql_username[256]; /**< Username for sql */
@@@ -460,6 -476,8 +461,7 @@@ int cf_time(const char *opt, const cha
  #define CMDLOG (options.command_log)
  #define TRACELOG (options.trace_log)
  #define CHECKLOG (options.checkpt_log)
 -#ifdef HAS_MYSQL
+ #define CHATLOGDIR (options.chatlog_dir)
  #define SQL_PLATFORM (options.sql_platform)
  #define SQL_HOST (options.sql_host)
  #define SQL_DB (options.sql_database)
diff --cc hdrs/extchat.h
index 493b7f5babadc67afe5f9a01054d96108fa54d0c,b005bb236485f5a910402697661d3d164079c756..3657e295de427b95643f67713128cf7ecb37cc2f
@@@ -91,23 -86,24 +91,24 @@@ struct chanuser 
   * into a sorted linked list.
   */
  struct channel {
 -  char name[CHAN_NAME_LEN];   /**< Channel name */
 -  char title[CHAN_TITLE_LEN]; /**< Channel description */
 -  long int type;              /**< Channel flags */
 -  long int cost;              /**< What it cost to make this channel */
 -  long int creator;           /**< This is who paid the cost for the channel */
 -  long int cobj;              /**< Channel object or #-1 */
 -  long int num_users;         /**< Number of connected users */
 -  long int max_users;         /**< Maximum allocated users */
 -  struct chanuser *users;     /**< Linked list of current users */
 -  long int num_messages;      /**< How many messages handled by this chan since startup */
 -  boolexp joinlock;   /**< Who may join */
 -  boolexp speaklock;  /**< Who may speak */
 -  boolexp modifylock; /**< Who may change things and boot people */
 -  boolexp seelock;    /**< Who can see this in a list */
 -  boolexp hidelock;   /**< Who may hide from view */
 -  struct channel *next;               /**< Next channel in linked list */
 -  BUFFERQ *bufferq;           /**< Pointer to channel recall buffer queue */
 +  char name[CHAN_NAME_LEN];     /**< Channel name */
 +  char title[CHAN_TITLE_LEN];   /**< Channel description */
 +  privbits type;                /**< Channel flags */
 +  int cost;             /**< What it cost to make this channel */
 +  dbref creator;                /**< This is who paid the cost for the channel */
 +  dbref mogrifier;              /**< This is the object that mogrifies the channel text. */
 +  int num_users;                /**< Number of connected users */
 +  int max_users;                /**< Maximum allocated users */
 +  struct chanuser *users;       /**< Linked list of current users */
 +  unsigned long int num_messages;       /**< How many messages handled by this chan since startup */
 +  boolexp joinlock;     /**< Who may join */
 +  boolexp speaklock;    /**< Who may speak */
 +  boolexp modifylock;   /**< Who may change things and boot people */
 +  boolexp seelock;      /**< Who can see this in a list */
 +  boolexp hidelock;     /**< Who may hide from view */
 +  struct channel *next;         /**< Next channel in linked list */
 +  BUFFERQ *bufferq;             /**< Pointer to channel recall buffer queue */
+   FILE *logfile;      /**< File to log channel in */
  };
  
  /** A list of channels on an object.
@@@ -130,18 -126,20 +131,19 @@@ struct na_cpass 
  
  
  /* Channel type flags and macros */
 -#define CHANNEL_PLAYER  0x1   /* Players may join */
 -#define CHANNEL_OBJECT  0x2   /* Objects may join */
 -#define CHANNEL_DISABLED 0x4  /* Channel is turned off */
 -#define CHANNEL_QUIET   0x8   /* No broadcasts connect/disconnect */
 -#define CHANNEL_ADMIN   0x10  /* Admins only */
 -#define CHANNEL_DIRECTOR 0x20 /* Directors only */
 -#define CHANNEL_CANHIDE 0x40  /* Can non-DARK players hide here? */
 -#define CHANNEL_OPEN    0x80  /* Can you speak if you're not joined? */
 -#define CHANNEL_NOTITLES 0x100        /* Don't show titles of speakers */
 -#define CHANNEL_NONAMES 0x200 /* Don't show names of speakers */
 -#define CHANNEL_NOCEMIT 0x400 /* Disallow @cemit */
 -#define CHANNEL_COBJ  0x800  /* Channel with a channel object */
 -#define CHANNEL_INTERACT      0x1000  /* Filter channel output through interactions */
 -#define CHANNEL_LOG   0x2000  /* Log the channel to a file */
 +#define CHANNEL_PLAYER  0x1U    /* Players may join */
 +#define CHANNEL_OBJECT  0x2U    /* Objects may join */
 +#define CHANNEL_DISABLED 0x4U   /* Channel is turned off */
 +#define CHANNEL_QUIET   0x8U    /* No broadcasts connect/disconnect */
 +#define CHANNEL_ADMIN   0x10U   /* Wizard and royalty only ok */
 +#define CHANNEL_DIRECTOR  0x20U   /* Wizard only ok */
 +#define CHANNEL_CANHIDE 0x40U   /* Can non-DARK Wizards hide here? */
 +#define CHANNEL_OPEN    0x80U   /* Can you speak if you're not joined? */
 +#define CHANNEL_NOTITLES 0x100U /* Don't show titles of speakers */
 +#define CHANNEL_NONAMES 0x200U  /* Don't show names of speakers */
 +#define CHANNEL_NOCEMIT 0x400U  /* Disallow @cemit */
 +#define CHANNEL_INTERACT 0x800U /* Filter channel output through interactions */
++#define CHANNEL_LOG   0x2000U /* Log the channel to a file */
  #define CHANNEL_DEFAULT_FLAGS   (CHANNEL_PLAYER)
  #define CL_JOIN 0x1
  #define CL_SPEAK 0x2
  #define Channel_Object(c) (ChanType(c) & CHANNEL_OBJECT)
  #define Channel_Player(c) (ChanType(c) & CHANNEL_PLAYER)
  #define Channel_Disabled(c) (ChanType(c) & CHANNEL_DISABLED)
 -#define Channel_Director(c) (ChanType(c) & CHANNEL_DIRECTOR)
 +#define Channel_Wizard(c) (ChanType(c) & CHANNEL_DIRECTOR)
  #define Channel_Admin(c) (ChanType(c) & CHANNEL_ADMIN)
++#define Channel_Director(c) (ChanType(c) & CHANNEL_DIRECTOR)
  #define Channel_CanHide(c) (ChanType(c) & CHANNEL_CANHIDE)
  #define Channel_NoTitles(c) (ChanType(c) & CHANNEL_NOTITLES)
  #define Channel_NoNames(c) (ChanType(c) & CHANNEL_NONAMES)
  #define Channel_NoCemit(c) (ChanType(c) & CHANNEL_NOCEMIT)
  #define Channel_Interact(c) (ChanType(c) & CHANNEL_INTERACT)
+ #define Channel_Log(c) (ChanType(c) & CHANNEL_LOG)
  #define Chan_Ok_Type(c,o) \
 -        ((ChanObj(c) == o) || (IsPlayer(o) && Channel_Player(c)) || \
 +        ((IsPlayer(o) && Channel_Player(c)) || \
           (IsThing(o) && Channel_Object(c)))
  #define Chan_Can(p,t) \
 -     (!(t & CHANNEL_DISABLED) && (!(t & CHANNEL_DIRECTOR) || Director(p)) || \
 -      (!(t & CHANNEL_ADMIN) || Admin(p) || div_powover(p,p,"Chat")))
 +     (!(t & CHANNEL_DISABLED) && (!(t & CHANNEL_DIRECTOR) || Director(p)) && \
 +      (!(t & CHANNEL_ADMIN) || Admin(p) || (div_powover(p,p,"Chat"))))
  /* Who can change channel privileges to type t */
 -#define Chan_Can_Priv(p,t,c) (!((t & CHANNEL_COBJ) && !(c & CHANNEL_COBJ)) && !(!(t & CHANNEL_COBJ) && (c & CHANNEL_COBJ)) && Chan_Can(p,t))
 +#define Chan_Can_Priv(p,t) (Chan_Can(p,t))
  #define Chan_Can_Access(c,p) (Chan_Can(p,ChanType(c)))
 +#define ChanMogrifier(c) ((c)->mogrifier)
  #define Chan_Can_Join(c,p) \
       (Chan_Can_Access(c,p) && \
 -      (eval_chan_lock(c,p,CLOCK_JOIN)))
 +     (eval_chan_lock(c,p, CLOCK_JOIN)))
  #define Chan_Can_Speak(c,p) \
       (Chan_Can_Access(c,p) && \
 -      (Loud(p) || eval_chan_lock(c,p, CLOCK_SPEAK)))
 +     (eval_chan_lock(c,p, CLOCK_SPEAK)))
  #define Chan_Can_Cemit(c,p) \
       (!Channel_NoCemit(c) && Chan_Can_Speak(c,p))
  #define Chan_Can_Modify(c,p) \
diff --cc hdrs/mushdb.h
index b8be3521e882d9bde1cb0233e2f5b2d1d1da4f55,a49fb07449eeeec2a85bedf13a80e59420e3aba5..fbeb421b33796ce852bed337ae901f024c770814
  #define HugeQueue(x)     OOREF(x,div_powover(x,x,"Queue"),div_powover(ooref,ooref,"Queue"))
  #define LookQueue(x)     OOREF(x,div_powover(x,x,"See_Queue"),div_powover(ooref,ooref,"See_Queue"))
  #define CanSeeQ(x,y)     OOREF(x,div_powover(x,y,"See_Queue"),div_powover(ooref,y,"See_Queue"))
+ #define CanLink(x,y) OOREF(x,div_powover(x,y,"Link"),div_powover(ooref,y,"Link"))
  #define HaltAny(x)       (Director(x) && OOREF(x,div_powover(x,x,"Halt"),div_powover(ooref,ooref,"Halt")))
  #define CanHalt(x,y)     OOREF(x,div_powover(x,y,"Halt"),div_powover(ooref,y,"Halt"))
 -#define CanNuke(x,y)  OOREF(x,div_powover(x,y,"Nuke"),div_powover(ooref, y, "Nuke"))
 +#define CanNuke(x,y)    OOREF(x,div_powover(x,y,"Nuke"),div_powover(ooref, y, "Nuke"))
  #define TC_NoPay(x)         (div_powover(x,x,"NoPay") || div_powover(Owner(x),Owner(x),"NoPay"))
 -#define NoPay(x)      OOREF(x,TC_NoPay(x),TC_NoPay(ooref))
 +#define NoPay(x)        OOREF(x,TC_NoPay(x),TC_NoPay(ooref))
  #define TC_MoneyAdmin(x)    (NoPay(x) && Prived(x))
 -#define MoneyAdmin(x)    OOREF(x,TC_MoneyAdmin(x),TC_MoneyAdmin(ooref))
 +#define MoneyAdmin(x)      OOREF(x,TC_MoneyAdmin(x),TC_MoneyAdmin(ooref))
  #define TC_NoQuota(x)       (div_powover(x,x,"NoQuota") || div_powover(Owner(x),Owner(x),"NoQuota"))
 -#define TC_DNoQuota(x)            (!!has_power(x, "NoQuota"))
 -#define NoQuota(x)    (IsDivision(x) ? OOREF(x,TC_DNoQuota(x), TC_DNoQuota(ooref)) :  OOREF(x,TC_NoQuota(x),TC_NoQuota(ooref)))
 +#define TC_DNoQuota(x)      (!!has_power(x, "NoQuota"))
 +#define NoQuota(x)      (IsDivision(x) ? OOREF(x,TC_DNoQuota(x), TC_DNoQuota(ooref)) :  OOREF(x,TC_NoQuota(x),TC_NoQuota(ooref)))
  #define CanSearch(x,y)   OOREF(x,(Owner(x) == Owner(y) || div_powover(x,y,"Search")),(Owner(ooref) == Owner(y) || div_powover(ooref,y,"Search") ))
  #define Global_Funcs(x)  OOREF(x,div_powover(x,x,"GFuncs"),div_powover(ooref,ooref,"GFuncs"))
  #define Create_Player(x) OOREF(x,div_powover(x,x,"PCreate"),div_powover(ooref,ooref,"PCreate"))
diff --cc m4/ax_lua.m4
index 41b19cdff40fbc10fd1c0a6d3b3d0f48639d4d9b,0000000000000000000000000000000000000000..eb86e681f8fe09bedb10d3aca6375a5881926a2a
mode 100644,000000..100644
--- /dev/null
@@@ -1,248 -1,0 +1,248 @@@
-     lua_myincs="lua5.1 lua-5.1.4"
 +# ===========================================================================
 +#          http://www.gnu.org/software/autoconf-archive/ax_lua.html
 +# ===========================================================================
 +#
 +# SYNOPSIS
 +#
 +#   AX_WITH_LUA
 +#   AX_PROG_LUA [(MIN-VERSION, [TOO-BIG-VERSION])]
 +#   AX_LUA_VERSION (MIN-VERSION, [TOO-BIG-VERSION])
 +#   AX_LUA_HEADERS
 +#   AX_LUA_HEADERS_VERSION (MIN-VERSION, [TOO-BIG-VERSION])
 +#   AX_LUA_LIBS
 +#   AX_LUA_READLINE
 +#
 +# DESCRIPTION
 +#
 +#   Detect Lua interpreter, headers and libraries, optionally enforcing a
 +#   particular range of versions. If only one version is given, then exactly
 +#   this version is required.
 +#
 +#   AX_WITH_LUA searches for a Lua interpreter and defines LUA if found.
 +#
 +#   AX_PROG_LUA searches for a Lua interpreter in the given version range,
 +#   if any, and defines LUA if found, or stops with an error if not.
 +#
 +#   AX_LUA_VERSION checks that the version of Lua is at least MIN-VERSION
 +#   and less than TOO-BIG-VERSION, if given.
 +#
 +#   AX_LUA_HEADERS searches for Lua headers and defines HAVE_LUA_H and
 +#   HAVE_LUALIB_H if found, and defines LUA_INCLUDE to the preprocessor
 +#   flags needed, if any.
 +#
 +#   AX_LUA_HEADERS_VERSION checks that the Lua headers' version is at least
 +#   MIN-VERSION, and less than TOO-BIG-VERSION, if given.
 +#
 +#   AX_LUA_LIBS searches for Lua libraries and defines LUA_LIB if found.
 +#
 +#   AX_LUA_READLINE configures Lua to be built with readline support, if
 +#   available. This macro requires AX_LIB_READLINE.
 +#
 +#   Versions are specified as three-digit integers whose first digit is the
 +#   major version and last two are the minor version (the same format as
 +#   LUA_VERSION_NUM in lua.h); e.g. 501 for Lua 5.1. The revision (e.g. the
 +#   "3" in "5.1.3") is ignored.
 +#
 +#   The following options are added by these macros:
 +#
 +#     --with-lua-suffix=ARG     Lua binaries and library files are
 +#                               suffixed with ARG.
 +#
 +# LICENSE
 +#
 +#   Copyright (c) 2011 Reuben Thomas <rrt@sc3d.org>
 +#   Copyright (c) 2009 Matthieu Moy <Matthieu.Moy@imag.fr>
 +#   Copyright (c) 2009 Tom Payne <twpayne@gmail.com>
 +#
 +#   This program is free software: you can redistribute it and/or modify it
 +#   under the terms of the GNU General Public License as published by the
 +#   Free Software Foundation, either version 3 of the License, or (at your
 +#   option) any later version.
 +#
 +#   This program is distributed in the hope that it will be useful, but
 +#   WITHOUT ANY WARRANTY; without even the implied warranty of
 +#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
 +#   Public License for more details.
 +#
 +#   You should have received a copy of the GNU General Public License along
 +#   with this program. If not, see <http://www.gnu.org/licenses/>.
 +#
 +#   As a special exception, the respective Autoconf Macro's copyright owner
 +#   gives unlimited permission to copy, distribute and modify the configure
 +#   scripts that are the output of Autoconf when processing the Macro. You
 +#   need not follow the terms of the GNU General Public License when using
 +#   or distributing such scripts, even though portions of the text of the
 +#   Macro appear in them. The GNU General Public License (GPL) does govern
 +#   all other use of the material that constitutes the Autoconf Macro.
 +#
 +#   This special exception to the GPL applies to versions of the Autoconf
 +#   Macro released by the Autoconf Archive. When you make and distribute a
 +#   modified version of the Autoconf Macro, you may extend this special
 +#   exception to the GPL to apply to your modified version as well.
 +
 +#serial 14
 +
 +dnl Helper function from previous metaconf methods
 +dnl
 +    AC_DEFUN([AX_CHECK_LOCAL_LUA], 
 +    [
 +    AC_MSG_NOTICE([Checking lua in local directories...])
-     AC_SEARCH_LIBS([lua_call], [lua lua5.1], , AC_MSG_ERROR([CobraMUSH requires lua]))], [
++    lua_myincs="lua5.1 lua-5.1.4 lua5.2"
 +    lua_otherincs=""
 +    lua_thisincl=""
 +    for lua_thisincl in $lua_myincs; do
 +      thispath=`pwd`
 +      AC_MSG_CHECKING([Checking in $thispath/$lua_thisincl])
 +      if test -f "$thispath/$lua_thisincl/src/lua.h"; then
 +        lua_h_path="$thispath/$lua_thisincl/src"
 +      AC_MSG_RESULT([yes.. found in sub src direcctory])
 +      break
 +      elif test -r "$thispath/$lua_thisincl/lua.h"; then
 +        lua_h_path="$thispath/$lua_thisincl"
 +      AC_MSG_RESULT([yes])
 +      break
 +      else
 +        lua_otherincs="$lua_otherincs $thisincl $thisincl/src"
 +        AC_MSG_RESULT([no])
 +      fi
 +    done
 +      
 +   AC_MSG_CHECKING([Checking for local lua lib at $lua_h_path])
 +   if  test -f "$lua_h_path/liblua.a"; then
 +     AC_MSG_RESULT([found])
 +     lua_ldflags="-L$lua_h_path"
 +   else
 +     AC_MSG_NOTICE([Could not locate local LUA library.])
 +     AC_MSG_ERROR([Either install LUA development global libraries or compile your local LUA installation])
 +   fi
 +      ])
 +
 +AC_DEFUN([AX_FIND_LUA],[
 +  AC_CHECK_HEADER([lua.h], [
-     AC_SEARCH_LIBS([lua_call], [lua lua5.1], , AC_MSG_ERROR([CobraMUSH requires lua]))
++    AC_SEARCH_LIBS([lua_callk], [lua lua5.1 lua5.2], , AC_MSG_ERROR([CobraMUSH requires lua]))], [
 +    AX_CHECK_LOCAL_LUA()
 +    LDFLAGS="$LDFLAGS $lua_ldflags"
 +    CFLAGS="$CFLAGS -I$lua_h_path"
++    AC_SEARCH_LIBS([lua_callk], [lua lua5.1 lua5.2], , AC_MSG_ERROR([CobraMUSH requires lua]))
 +    ])])
 +
 +dnl Helper function to declare extra options
 +AC_DEFUN([_AX_LUA_OPTS],
 +   [AC_ARG_WITH([lua-suffix],
 +     [AS_HELP_STRING([--with-lua-suffix=ARG],
 +        [Lua binary and library files are suffixed with ARG])])])dnl
 +
 +AC_DEFUN([AX_WITH_LUA],
 +  [_AX_LUA_OPTS
 +  if test "x$LUA" = x; then
 +    AC_PATH_PROG(LUA, lua$with_lua_suffix)
 +  fi])dnl
 +
 +AC_DEFUN([AX_PROG_LUA],
 +  [lua_min_version=$1
 +  lua_max_version=$2
 +  AX_WITH_LUA
 +  if test -z "$LUA"; then
 +    AC_MSG_FAILURE([Lua not found])
 +  fi
 +  if test -n "$lua_min_version"; then
 +    AX_LUA_VERSION($lua_min_version, $lua_max_version)
 +  fi
 +  AC_SUBST(LUA)])dnl
 +
 +dnl Helper function to parse minimum & maximum versions
 +AC_DEFUN([_AX_LUA_VERSIONS],
 +  [lua_min_version=$1
 +  lua_max_version=$2
 +  if test "x$lua_min_version" = x; then
 +    lua_min_version=0
 +  fi
 +  if test "x$lua_max_version" = x; then
 +    lua_max_version=$(($lua_min_version + 1))
 +  fi])
 +
 +AC_DEFUN([AX_LUA_VERSION],
 +  [_AX_LUA_OPTS
 +  _AX_LUA_VERSIONS($1, $2)
 +  AC_MSG_CHECKING([Lua version is in range $1 <= v < $2])
 +  if test "x$LUA" != x; then
 +    lua_text_version=$(LUA_INIT= $LUA -e 'print(_VERSION)' 2>&1 | cut -d' ' -f2)
 +    case $lua_text_version in
 +    5.2*)
 +      lua_version=502
 +      ;;
 +    5.1*)
 +      lua_version=501
 +      ;;
 +    5.0*)
 +      lua_version=500
 +      ;;
 +    4.0*)
 +      lua_version=400
 +      ;;
 +    *)
 +      lua_version=-1
 +      ;;
 +    esac
 +    if test $lua_version -ge "$lua_min_version" && test $lua_version -lt "$lua_max_version"; then
 +      AC_MSG_RESULT([yes])
 +    else
 +      AC_MSG_RESULT([no])
 +      AC_MSG_FAILURE([Lua version not in desired range.])
 +    fi
 +  else
 +    AC_MSG_RESULT([no])
 +    AC_MSG_FAILURE([Lua version not in desired range.])
 +  fi])dnl
 +
 +AC_DEFUN([AX_LUA_HEADERS],
 +  [_AX_LUA_OPTS
 +  LUA_OLD_CPPFLAGS="$CPPFLAGS"
 +  CPPFLAGS="$CPPFLAGS $LUA_INCLUDE"
 +  AC_CHECK_HEADERS([lua.h lualib.h])
 +  CPPFLAGS="$LUA_OLD_CPPFLAGS"]
 +  )dnl
 +
 +dnl Finder header location and place it in LUA_HEADER_PATH
 +
 +AC_DEFUN([AX_LUA_LIBS],
 +  [_AX_LUA_OPTS
 +  AC_CHECK_LIB([m], [exp], [lua_extra_libs="$lua_extra_libs -lm"], [])
 +  AC_CHECK_LIB([dl], [dlopen], [lua_extra_libs="$lua_extra_libs -ldl"], [])
 +  AC_CHECK_LIB([lua$with_lua_suffix],
 +    [lua_call],
 +    [LUA_LIB="$LUA_LIB -llua$with_lua_suffix $lua_extra_libs"],
 +    [],
 +    [$LUA_LIB $lua_extra_libs])])dnl
 +
 +AC_DEFUN([AX_LUA_HEADERS_VERSION],
 +  [_AX_LUA_OPTS
 +  _AX_LUA_VERSIONS($1, $2)
 +  AC_MSG_CHECKING([lua.h version is in range $1 <= v < $2])
 +  LUA_OLD_LIBS="$LIBS"
 +  LIBS="$LIBS $LUA_LIB"
 +  LUA_OLD_CPPFLAGS="$CPPFLAGS"
 +  CPPFLAGS="$CPPFLAGS $LUA_INCLUDE"
 +  AC_RUN_IFELSE([AC_LANG_SOURCE([[
 +#include <lua.h>
 +#include <stdlib.h>
 +#include <stdio.h>
 +int main()
 +{
 +  printf("(found %s, %d)... ", LUA_VERSION, LUA_VERSION_NUM);
 +  if (LUA_VERSION_NUM >= $lua_min_version && LUA_VERSION_NUM < $lua_max_version)
 +    exit(EXIT_SUCCESS);
 +  exit(EXIT_FAILURE);
 +}
 +]])],
 +  [AC_MSG_RESULT([yes])],
 +  [AC_MSG_RESULT([no])
 +  AC_MSG_FAILURE([lua.h version not in desired range])])
 +  LIBS="$LUA_OLD_LIBS"
 +  CPPFLAGS="$LUA_OLD_CPPFLAGS"])dnl
 +
 +AC_DEFUN([AX_LUA_READLINE],
 +  [AX_LIB_READLINE
 +  if test -n "$ac_cv_header_readline_readline_h" && test -n "$ac_cv_header_readline_history_h"; then
 +    LUA_LIBS_CFLAGS="-DLUA_USE_READLINE $LUA_LIBS_CFLAGS"
 +  fi])dnl
diff --cc src/bsd.c
index 60ed1065d9d2bb1f2e49b854eb35418971bdd2a5,5926ad6279fb751bf503c3829b7aae0ca6e22da9..28553c9bedce1fb54edc63e4a65bf4aac7599159
+++ b/src/bsd.c
@@@ -3086,51 -3161,25 +3086,49 @@@ static voi
  close_sockets(void)
  {
    DESC *d, *dnext;
-   ssize_t res;
 +  const char *shutmsg;
 +  int shutlen;
 +
 +  shutmsg = T(shutdown_message);
 +  shutlen = strlen(shutmsg);
  
    for (d = descriptor_list; d; d = dnext) {
      dnext = d->next;
 -#ifdef COMPILE_CONSOLE
 -    if(d->descriptor == 0) {
 -      write(STDOUT_FILENO, T(shutdown_message), strlen(T(shutdown_message)));
 -      write(STDOUT_FILENO, "\r\n", 2);
 +#ifdef HAVE_SSL
 +    if (!d->ssl) {
 +#endif
 +#ifdef HAVE_WRITEV
 +      struct iovec byebye[2];
 +      byebye[0].iov_base = (char *) shutmsg;
 +      byebye[0].iov_len = shutlen;
 +      byebye[1].iov_base = (char *) "\r\n";
 +      byebye[1].iov_len = 2;
-       /* FIXME: We're using res.. for the mere fact we get a warning otherwise.. */
-       res = writev(d->outdesc, byebye, 2);
++      (void) writev(d->outdesc, byebye, 2);
 +#else
 +      if (d->outdesc == console_outpt) {
 +        write(d->outdesc, shutmsg, shutlen);
 +        write(d->outdesc, (char *) "\r\n", 2);
 +      } else {
 +        send(d->outdesc, shutmsg, shutlen, 0);
 +        send(d->outdesc, (char *) "\r\n", 2, 0);
 +      }
 +#endif
 +#ifdef HAVE_SSL
      } else {
 -      send(d->descriptor, T(shutdown_message), strlen(T(shutdown_message)), 0);
 -      send(d->descriptor, "\r\n", 2, 0);
 -      if (shutdown(d->descriptor, 2) < 0)
 -      perror("shutdown");
 -      closesocket(d->descriptor);
 -    }
 -#else /* COMPILE_CONSOLE */
 -    send(d->descriptor, T(shutdown_message), strlen(T(shutdown_message)), 0);
 -    send(d->descriptor, "\r\n", 2, 0);
 -#ifdef HAS_OPENSSL
 -    if (d->ssl) {
 +      int offset;
 +      offset = 0;
 +      ssl_write(d->ssl, d->ssl_state, 0, 1, (uint8_t *) shutmsg,
 +                shutlen, &offset);
 +      offset = 0;
 +      ssl_write(d->ssl, d->ssl_state, 0, 1, (uint8_t *) "\r\n", 2,
 +                &offset);
 +      const char *shutmsg = T(shutdown_message);
 +      offset = 0;
 +      ssl_write(d->ssl, d->ssl_state, 0, 1, (uint8_t *) shutmsg,
 +                strlen(shutmsg), &offset);
 +      offset = 0;
 +      ssl_write(d->ssl, d->ssl_state, 0, 1, (uint8_t *) "\r\n", 2,
 +                &offset);
        ssl_close_connection(d->ssl);
        d->ssl = NULL;
        d->ssl_state = 0;
diff --cc src/conf.c
Simple merge
diff --cc src/division.c
Simple merge
diff --cc src/extchat.c
index b4be613b1c6a0e965ed79e313700fc5feb500f74,069a29ae637324ffa7df5b7c270ac5d8761da2a6..3fd5f1a2f9f77a74e9199c0dcd67054e0a83c6d4
  #include <sys/types.h>
  #endif
  #include <stdarg.h>
+ #include <sys/stat.h>
+ #include <errno.h>
  #include "conf.h"
 +
 +#ifdef CHAT_SYSTEM
  #include "externs.h"
  #include "attrib.h"
  #include "mushdb.h"
@@@ -73,28 -100,24 +75,31 @@@ static void channel_leave_self(dbref pl
  static void do_channel_who(dbref player, CHAN *chan);
  void chat_player_announce(dbref player, char *msg, int ungag);
  static int ok_channel_name(const char *n);
 -static void format_channel_broadcast(CHAN *chan, CHANUSER *u, dbref victim,
 -                                   int flags, const char *msg,
 -                                   const char *extra);
 +/*
 +static void format_channel_chat(CHAN *chan, CHANUSER *u, dbref victim,
 +                                int flags, const char *msg, const char *extra);
 +                              */
 +static void channel_send(CHAN *channel, dbref player, int flags,
 +                          const char *origmessage);
  static void list_partial_matches(dbref player, const char *name,
-                                  enum chan_match_type type);
+                                enum chan_match_type type);
+ static void begin_chat_log(CHAN *chan);
+ static void end_chat_log(CHAN *chan);
+ static void write_chat_log(CHAN *chan, char *buf);
  
 -const char *chan_speak_lock = "ChanSpeakLock";        /**< Name of speak lock */
 -const char *chan_join_lock = "ChanJoinLock";  /**< Name of join lock */
 -const char *chan_mod_lock = "ChanModLock";    /**< Name of modify lock */
 -const char *chan_see_lock = "ChanSeeLock";    /**< Name of see lock */
 -const char *chan_hide_lock = "ChanHideLock";  /**< Name of hide lock */
 +const char *chan_speak_lock = "ChanSpeakLock";  /**< Name of speak lock */
 +const char *chan_join_lock = "ChanJoinLock";    /**< Name of join lock */
 +const char *chan_mod_lock = "ChanModLock";      /**< Name of modify lock */
 +const char *chan_see_lock = "ChanSeeLock";      /**< Name of see lock */
 +const char *chan_hide_lock = "ChanHideLock";    /**< Name of hide lock */
  
 -#define CYES 1          /**< An affirmative. */
 -#define CNO 0   /**< A negative. */
 -#define ERR -1          /**< An error. Clever, eh? */
 +slab *channel_slab; /**< slab for 'struct channel' allocations */
 +slab *chanlist_slab; /**< slab for 'struct chanlist' allocations */
 +slab *chanuser_slab; /**< slab for 'struct chanuser' allocations */
 +
 +#define CHAN_YES 1     /**< An affirmative. */
 +#define CHAN_NO 0      /**< A negative. */
 +#define CHAN_ERR -1    /**< An error. Clever, eh? */
  
  /** Wrapper for insert_user() that generates a new CHANUSER and inserts it */
  #define insert_user_by_dbref(who,chan) \
@@@ -123,6 -144,8 +128,7 @@@ static PRIV priv_table[] = 
    {"NoNames", 'N', CHANNEL_NONAMES, CHANNEL_NONAMES},
    {"NoCemit", 'C', CHANNEL_NOCEMIT, CHANNEL_NOCEMIT},
    {"Interact", 'I', CHANNEL_INTERACT, CHANNEL_INTERACT},
 -  {"ChanObj", 'Z', CHANNEL_COBJ, CHANNEL_COBJ},
+   {"LogChannel", 'L', CHANNEL_LOG, CHANNEL_LOG},
    {NULL, '\0', 0, 0}
  };
  
@@@ -1311,7 -1395,7 +1324,6 @@@ static voi
  channel_join_self(dbref player, const char *name)
  {
    CHAN *chan = NULL;
--  CHANUSER *u;
  
    if (Guest(player)) {
      notify(player, T("Guests are not allowed to join channels."));
      }
    }
    if (insert_user_by_dbref(player, chan)) {
 -    notify_format(player, T("CHAT: You join channel %s."), ChanObjName(chan));
 -    u = onchannel(player, chan);
 -    if (!Channel_Quiet(chan) && !DarkLegal(player))
 -      format_channel_broadcast(chan, u, player, CB_CHECKQUIET | CB_PRESENCE,
 -                             T("%s %s has joined this channel."), NULL);
 +    notify_format(player, T("CHAT: You join channel <%s>."), ChanName(chan));
-     u = onchannel(player, chan);
      ChanNumUsers(chan)++;
 +    if (!Channel_Quiet(chan) && !DarkLegal(player))
 +      channel_send(chan, player,
 +                   CB_CHECKQUIET | CB_PRESENCE | CB_POSE,
 +                   T("has joined this channel."));
    } else {
      /* Should never happen */
      notify_format(player,
@@@ -1528,9 -1602,11 +1539,8 @@@ voi
  do_chat(dbref player, CHAN *chan, const char *arg1)
  {
    CHANUSER *u;
--  const char *gap;
 -  const char *someone = "Someone";
 -  char *title;
 -  const char *name;
 -  int canhear;
 +  char type;
 +  bool canhear;
  
    if (!Chan_Ok_Type(chan, player)) {
      notify_format(player,
      return;
    }
  
 -  if (!Channel_NoTitles(chan) && u &&CUtitle(u) && *CUtitle(u))
 -     title = CUtitle(u);
 -  else
 -    title = NULL;
 -  if (Channel_NoNames(chan))
 -    name = NULL;
 -  else
 -    name = accented_name(player);
 -  if (!title && !name)
 -    name = someone;
 -
    /* figure out what kind of message we have */
--  gap = " ";
 +  type = ':';
    switch (*arg1) {
    case SEMI_POSE_TOKEN:
--    gap = "";
 +    type = ';';
      /* FALLTHRU */
    case POSE_TOKEN:
      arg1 = arg1 + 1;
@@@ -1760,9 -1878,10 +1768,11 @@@ do_chan_admin(dbref player, char *name
      if (type)
        ChanType(chan) = type;
      ChanCreator(chan) = Owner(player);
 -    strcpy(ChanName(chan), name);
 +    ChanMogrifier(chan) = NOTHING;
 +    mush_strncpy(ChanName(chan), name, CHAN_NAME_LEN);
      insert_channel(&chan);
+     if(Channel_Log(chan))
+       begin_chat_log(chan);
      notify_format(player, T("CHAT: Channel <%s> created."), ChanName(chan));
      break;
    case 1:
      remove_channel(chan);
      strcpy(ChanName(chan), perms);
      insert_channel(&chan);
 -    channel_broadcast(chan, player, 0,
 -                    "<%s> %s has renamed channel %s to %s.",
 -                    ChanName(chan), Name(player), old, ChanName(chan));
+     if(Channel_Log(chan))
+       begin_chat_log(chan);
 +    snprintf(announcebuff, BUFFER_LEN, "has renamed %s to %s",
 +             old, ChanName(chan));
 +    channel_send(chan, player,
 +                 CB_CHECKQUIET | CB_PRESENCE | CB_POSE, announcebuff);
      notify(player, T("Channel renamed."));
      break;
    case 3:
        notify(player, T("Warning: channel will be disabled."));
      if (type == ChanType(chan)) {
        notify_format(player,
 -                  T
 -                  ("Invalid or same permissions on channel <%s>. No changes made."),
 -                  ChanName(chan));
 +                    T
 +                    ("Invalid or same permissions on channel <%s>. No changes made."),
 +                    ChanName(chan));
      } else {
+       if(Channel_Log(chan) && !(type & CHANNEL_LOG))
+         end_chat_log(chan);
+       else if(!Channel_Log(chan) && (type & CHANNEL_LOG))
+         begin_chat_log(chan);
        ChanType(chan) = type;
        notify_format(player,
 -                  T("Permissions on channel <%s> changed."), ChanName(chan));
 +                    T("Permissions on channel <%s> changed."), ChanName(chan));
      }
      break;
    }
@@@ -2085,10 -2202,9 +2105,10 @@@ do_channel_list(dbref player, const cha
    int numblanks;
  
    if (SUPPORT_PUEBLO)
 -    notify_noenter(player, tprintf("%cSAMP%c", TAG_START, TAG_END));
 -  notify_format(player, "%-30s %-5s %8s %-18s %-8s %-3s",
 -              "Name", "Users", "Msgs", T("Chan Type"), "Status", "Buf");
 +    notify_noenter(player, open_tag("SAMP"));
-   notify_format(player, "%-30s %-5s %8s %-16s %-8s %-3s",
++  notify_format(player, "%-30s %-5s %8s %-15s %-8s %-3s",
 +                T("Name"), T("Users"), T("Msgs"), T("Chan Type"), T("Status"),
 +                T("Buf"));
    for (c = channels; c; c = c->next) {
      strcpy(cleanname, remove_markup(ChanName(c), NULL));
      if (Chan_Can_See(c, player) && string_prefix(cleanname, partname)) {
        len = strlen(ChanName(c));
        numblanks = len - strlen(cleanname);
        if (numblanks > 0 && numblanks < CHAN_NAME_LEN) {
 -      memset(blanks, ' ', CHAN_NAME_LEN - 1);
 -      if (len > 30)
 -        numblanks -= (len - 30);
 -      if (numblanks < 0)
 -        numblanks = 0;
 -      blanks[numblanks] = '\0';
 +        memset(blanks, ' ', CHAN_NAME_LEN - 1);
 +        if (len > 30)
 +          numblanks -= (len - 30);
 +        if (numblanks < 0)
 +          numblanks = 0;
 +        blanks[numblanks] = '\0';
        } else {
 -      blanks[0] = '\0';
 +        blanks[0] = '\0';
        }
        notify_format(player,
-                     "%-30s%s %s %8ld [%c%c%c%c%c%c%c %c%c%c%c%c%c] [%-3s %c%c] %3d",
-                     ChanName(c), blanks, numusers, ChanNumMsgs(c),
-                     Channel_Disabled(c) ? 'D' : '-',
-                     Channel_Player(c) ? 'P' : '-',
-                     Channel_Object(c) ? 'O' : '-',
-                     Channel_Admin(c) ? 'A' : (Channel_Wizard(c) ? 'W' : '-'),
-                     Channel_Quiet(c) ? 'Q' : '-',
-                     Channel_CanHide(c) ? 'H' : '-', Channel_Open(c) ? 'o' : '-',
-                     /* Locks */
-                     ChanJoinLock(c) != TRUE_BOOLEXP ? 'j' : '-',
-                     ChanSpeakLock(c) != TRUE_BOOLEXP ? 's' : '-',
-                     ChanModLock(c) != TRUE_BOOLEXP ? 'm' : '-',
-                     ChanSeeLock(c) != TRUE_BOOLEXP ? 'v' : '-',
-                     ChanHideLock(c) != TRUE_BOOLEXP ? 'h' : '-',
-                     /* Does the player own it? */
-                     ChanCreator(c) == player ? '*' : '-',
-                     /* User status */
-                     u ? (Chanuser_Gag(u) ? T("Gag") : T("On")) : T("Off"),
-                     (u && Chanuser_Quiet(u)) ? 'Q' : ' ',
-                     (u && Chanuser_Hide(u)) ? 'H' : ' ',
-                     bufferq_blocks(ChanBufferQ(c)));
 -                  "%-30s%s %s %8ld [%c%c%c%c%c%c%c%c%c %c%c%c%c%c%c] [%-3s %c%c] %3d",
++                  "%-30s%s %s %8ld [%c%c%c%c%c%c%c%c %c%c%c%c%c%c] [%-3s %c%c] %3d",
+                   ChanName(c), blanks, numusers, ChanNumMsgs(c),
+                   Channel_Disabled(c) ? 'D' : '-',
+                   Channel_Player(c) ? 'P' : '-',
+                   Channel_Object(c) ? 'O' : '-',
+                   Channel_Admin(c) ? 'A' : (Channel_Director(c) ? 'W' : '-'),
+                   Channel_Quiet(c) ? 'Q' : '-',
+                   Channel_CanHide(c) ? 'H' : '-', Channel_Open(c) ? 'o' : '-',
 -                  (ChanType(c) & CHANNEL_COBJ) ? 'Z' : '-',
+                   Channel_Log(c) ? 'L' : '-',
+                   /* Locks */
+                   ChanJoinLock(c) != TRUE_BOOLEXP ? 'j' : '-',
+                   ChanSpeakLock(c) != TRUE_BOOLEXP ? 's' : '-',
+                   ChanModLock(c) != TRUE_BOOLEXP ? 'm' : '-',
+                   ChanSeeLock(c) != TRUE_BOOLEXP ? 'v' : '-',
+                   ChanHideLock(c) != TRUE_BOOLEXP ? 'h' : '-',
+                   /* Does the player own it? */
+                   ChanCreator(c) == player ? '*' : '-',
+                   /* User status */
+                   u ? (Chanuser_Gag(u) ? "Gag" : "On") : "Off",
+                   (u &&Chanuser_Quiet(u)) ? 'Q' : ' ',
+                   (u &&Chanuser_Hide(u)) ? 'H' : ' ',
+                   bufferq_lines(ChanBufferQ(c)));
      }
    }
    if (SUPPORT_PUEBLO)
@@@ -3525,179 -3497,29 +3546,181 @@@ channel_send(CHAN *channel, dbref playe
    if (Channel_Disabled(channel))
      return;
  
 -  va_start(args, fmt);
 +  speaker = onchannel(player, channel);
  
 -#ifdef HAS_VSNPRINTF
 -  (void) vsnprintf(tbuf1, sizeof tbuf1, fmt, args);
 -#else
 -  (void) vsprintf(tbuf1, fmt, args);
 -#endif
 -  va_end(args);
 -  tbuf1[BUFFER_LEN - 1] = '\0';
 +  snprintf(channame, BUFFER_LEN, "<%s>", ChanName(channel));
 +
 +  if (!Channel_NoTitles(channel) && speaker &&
 +      CUtitle(speaker) && *CUtitle(speaker)) {
 +    snprintf(title, BUFFER_LEN, "%s", CUtitle(speaker));
 +  } else {
 +    title[0] = '\0';
 +  }
 +
 +  if (Channel_NoNames(channel)) {
 +    playername[0] = '\0';
 +  } else {
 +    snprintf(playername, BUFFER_LEN, "%s", accented_name(player));
 +  }
 +  if (!title[0] && !playername[0]) {
 +    snprintf(playername, BUFFER_LEN, "%s", someone);
 +  }
 +
 +  if (flags & CB_PRESENCE) {
 +    ctype = "@";
 +  } else if (flags & CB_POSE) {
 +    ctype = ":";
 +  } else if (flags & CB_SEMIPOSE) {
 +    ctype = ";";
 +  } else if (flags & CB_EMIT) {
 +    ctype = "|";
 +  } else {
 +    ctype = "\"";
 +  }
 +
 +  snprintf(speechtext, BUFFER_LEN, "says");
 +
 +  snprintf(message, BUFFER_LEN, "%s", origmessage);
 +
 +  if (GoodObject(ChanMogrifier(channel))) {
 +    if (eval_lock(player, ChanMogrifier(channel), Use_Lock)) {
 +      mogrifier = ChanMogrifier(channel);
  
 -  nac.u = ChanUsers(channel);
 -  nac.checkquiet = (flags & CB_CHECKQUIET) ? 1 : 0;
 -  if (Channel_Interact(channel))
 +      argv[0] = ctype;
 +      argv[1] = ChanName(channel);
 +      argv[2] = message;
 +      argv[3] = playername;
 +      argv[4] = title;
 +
 +      blockstr = mogrify(mogrifier, "MOGRIFY`BLOCK", player, 6, argv, "");
 +      if (blockstr && *blockstr) {
 +        notify(player, blockstr);
 +        return;
 +      }
 +      // Do we override chatformats?
 +      if (parse_boolean
 +          (mogrify(mogrifier, "MOGRIFY`OVERRIDE", player, 6, argv, ""))) {
 +        override_chatformat = 1;
 +      }
 +
 +      argv[1] = ChanName(channel);
 +      argv[2] = ctype;
 +      argv[3] = message;
 +      argv[4] = title;
 +      argv[5] = playername;
 +
 +      argv[0] = channame;
 +      snprintf(channame, BUFFER_LEN, "%s",
 +               mogrify(mogrifier, "MOGRIFY`CHANNAME", player, 6, argv,
 +                       channame));
 +
 +      argv[0] = title;
 +      snprintf(title, BUFFER_LEN, "%s",
 +               mogrify(mogrifier, "MOGRIFY`TITLE", player, 6, argv, title));
 +
 +      argv[0] = playername;
 +      snprintf(playername, BUFFER_LEN, "%s",
 +               mogrify(mogrifier, "MOGRIFY`PLAYERNAME", player, 6, argv,
 +                       playername));
 +
 +      if (flags & CB_SPEECH) {
 +        argv[0] = speechtext;
 +        snprintf(speechtext, BUFFER_LEN, "%s",
 +                 mogrify(mogrifier, "MOGRIFY`SPEECHTEXT", player, 6, argv,
 +                         speechtext));
 +      }
 +
 +      argv[0] = message;
 +      snprintf(message, BUFFER_LEN, "%s",
 +               mogrify(mogrifier, "MOGRIFY`MESSAGE", player, 6, argv, message));
 +    }
 +  }
 +
 +  bp = buff;
 +
 +  *bp = '\0';
 +
 +  if (!(flags & CB_QUIET)) {
 +    safe_str(channame, buff, &bp);
 +    safe_chr(' ', buff, &bp);
 +  }
 +
 +  if (flags & CB_EMIT) {
 +    safe_str(message, buff, &bp);
 +  } else {
 +    if (!(flags & CB_PRESENCE)) {
 +      if (title[0]) {
 +        safe_str(title, buff, &bp);
 +        safe_chr(' ', buff, &bp);
 +      }
 +    }
 +    safe_str(playername, buff, &bp);
 +    switch (flags & CB_TYPE) {
 +    case CB_POSE:
 +      safe_chr(' ', buff, &bp);
 +    case CB_SEMIPOSE:
 +      safe_str(message, buff, &bp);
 +      break;
 +    case CB_SPEECH:
 +      safe_format(buff, &bp, " %s, \"%s\"", T(speechtext), message);
 +      break;
 +    }
 +  }
 +  *bp = '\0';
 +
 +  // @chatformat
 +  if (flags & CB_PRESENCE) {
 +    snprintf(title, BUFFER_LEN, "%s", message);
 +    snprintf(message, BUFFER_LEN, "%s %s", Name(player), title);
 +    title[0] = '\0';
 +  }
 +
 +  if (GoodObject(mogrifier)) {
 +    argv[0] = ctype;
 +    argv[1] = ChanName(channel);
 +    argv[2] = message;
 +    argv[3] = playername;
 +    argv[4] = title;
 +    argv[5] = buff;
 +    snprintf(buff, BUFFER_LEN, "%s",
 +             mogrify(mogrifier, "MOGRIFY`FORMAT", player, 6, argv, buff));
 +  }
 +
 +  if (Channel_Interact(channel)) {
      na_flags |= (flags & CB_PRESENCE) ? NA_INTER_PRESENCE : NA_INTER_HEAR;
 -  notify_anything(player, na_channel, &nac, ns_esnotify,
 -                na_flags | ((flags & CB_NOSPOOF) ? 0 : NA_SPOOF), tbuf1);
 +  }
 +
 +  if (!(flags & CB_NOSPOOF)) {
 +    na_flags |= NA_SPOOF;
 +  }
 +
 +  for (u = ChanUsers(channel); u; u = u->next) {
 +    current = CUdbref(u);
 +
 +    if (!(((flags & CB_CHECKQUIET) && Chanuser_Quiet(u)) ||
 +          Chanuser_Gag(u) || (IsPlayer(current) && !Connected(current)))) {
 +      if (override_chatformat
 +          || !vmessageformat(current, "CHATFORMAT", player,
 +                             na_flags,
 +                             6,
 +                             ctype,
 +                             ChanName(channel),
 +                             message, playername, title, buff)) {
 +        notify_anything(player, na_one, &current, ns_esnotify, na_flags, buff);
 +      }
 +    }
 +  }
 +
    if (ChanBufferQ(channel))
      add_to_bufferq(ChanBufferQ(channel), 0,
 -                 (flags & CB_NOSPOOF) ? player : NOTHING, tbuf1);
 +                   (flags & CB_NOSPOOF) ? player : NOTHING, buff);
+   if(Channel_Log(channel))
 -    write_chat_log(channel, tbuf1);
 -}
++    write_chat_log(channel, buff);
  
 +  if (!(flags & CB_PRESENCE) && !speaker) {
 +    notify_format(player, T("To channel %s: %s"), ChanName(channel), buff);
 +  }
 +}
  
  /** Recall past lines from the channel's buffer.
   * We try to recall no more lines that are requested by the player,
@@@ -3895,7 -3701,238 +3918,89 @@@ do_chan_buffer(dbref player, const cha
    }
  }
  
- /** Evaluate a channel lock with %0 set to the channel name.
 -static void
 -format_channel_broadcast(CHAN *chan, CHANUSER *u, dbref victim, int flags,
 -                       const char *msg, const char *extra)
 -{
 -  const char *title = NULL;
 -  if (extra && *extra)
 -    title = extra;
 -  else if (u &&CUtitle(u))
 -     title = CUtitle(u);
 -
 -  if (Channel_NoNames(chan)) {
 -    if (Channel_NoTitles(chan) || !title)
 -      channel_broadcast(chan, victim, flags, msg, ChanObjName(chan), "Someone");
 -    else
 -      channel_broadcast(chan, victim, flags, msg, ChanObjName(chan), title);
 -  } else
 -    channel_broadcast(chan, victim, flags, msg, ChanObjName(chan), Name(victim));
 -}
 -
+ static void
+ begin_chat_log(CHAN *chan)
+ {
+   struct stat st;
+   char filename[512];
+   int i, j;
+   if(!*CHATLOGDIR)
+     return;
+   if(stat(CHATLOGDIR, &st)) {
+     do_rawlog(LT_ERR, T("Unable to stat() chatlog_dir: %s"), strerror(errno));
+     return;
+   }
+   if(!S_ISDIR(st.st_mode)) {
+     do_rawlog(LT_ERR, T("chatlog_dir is not a directory"));
+     return;
+   }
+   strcpy(filename, CHATLOGDIR); /* N.B.: CHATLOGDIR is at most 256 bytes */
+   i = strlen(filename);
+   if(filename[i-1] != '/') {
+     filename[i] = '/';
+     i++;
+   }
+   j = strlen(ChanName(chan));
+   if((i + j) > 507) {
+     do_rawlog(LT_ERR,
+               T("Buffer length exceeded for chat log filename for channel %s"),
+               ChanName(chan));
+     return;
+   }
+   strcpy(filename + i, ChanName(chan));
+   i += j;
+   strcpy(filename + i, ".log");
+   filename[511] = '\0';
+   ChanLogFile(chan) = fopen(filename, "a");
+   if(!ChanLogFile(chan)) {
+     do_rawlog(LT_ERR, T("Unable to open log file for channel %s: %s"),
+               ChanName(chan), strerror(errno));
+     return;
+   }
+   write_chat_log(chan, "Beginning of log.");
+ }
+ static void
+ end_chat_log(CHAN *chan)
+ {
+   if(!ChanLogFile(chan))
+     return;
+   write_chat_log(chan, "End of log.");
+   fclose(ChanLogFile(chan));
+   ChanLogFile(chan) = NULL;
+ }
+ static void
+ write_chat_log(CHAN *chan, char *buf)
+ {
+   char tbuf[BUFFER_LEN];
+   struct tm *when;
+   char *clean;
+   if(!ChanLogFile(chan))
+     return;
+   when = localtime(&mudtime);
+   strftime(tbuf, sizeof tbuf, "[%m/%d %H:%M:%S] ", when);
+   fputs(tbuf, ChanLogFile(chan));
+   clean = remove_markup(buf, NULL);
+   fputs(clean, ChanLogFile(chan));
+   fputc('\n', ChanLogFile(chan));
+   fflush(ChanLogFile(chan));
+ }
 -static void
 -do_reset_cobj(player, name)
 -      dbref player;
 -      const char *name;
 -{
 -  CHAN *c;
 -  /* Test Channel */
 -   test_channel(player, name, c);
 -  if(!Chan_Can_Modify(c, player)) {
 -     notify(player, "CHAT: Oh come on.");
 -     return;
 -    }
 -   /* Now lets reset teh chan obj stuff on the channel */
 -    ChanType(c) &= ~CHANNEL_COBJ;
 -    ChanObj(c) = -1;
 -    notify(player,"ChanObj Reset.");
 -}
 -
 -    
 -static void
 -do_set_cobj(player, name, obj) 
 -        dbref player;
 -      const char *name;
 -      const char *obj;
 -{
 -  CHAN *c;
 -  dbref cobj;
 -  /* Test the channel */
 -    test_channel(player, name, c);
 -    
 -    if(!Chan_Can_Modify(c, player)) {
 -      notify(player, "CHAT: Oh come on.");
 -      return;
 -      }
 -      
 -     /* Not sure if all this shit works right, so be careful */
 -
 -     cobj = match_result(player, obj, TYPE_THING, MAT_ABSOLUTE);
 -              
 -     if(cobj == -1) {
 -        notify(player, "Invalid Object");
 -        return;
 -       }
 -     
 -     
 -     if(cobj == -2) {
 -         notify(player, "Ambigious Object");
 -         return; 
 -          }
 -
 -     if(!controls(player,cobj)) {
 -         notify(player,"You must own that object first");
 -       return;
 -       }
 -       
 -     if(Typeof(cobj) != TYPE_THING) {
 -         notify(player, "Must be an object");
 -         return;
 -     }
 -
 -     ChanType(c) |= CHANNEL_COBJ;
 -     ChanObj(c) = cobj;
 -
 -     notify(player,tprintf("Channel object for %s is now #%ld", ChanName(c),
 -                 ChanObj(c)) );
 -
 -}
 -
 -int ChanObjCheck(CHAN *c)
 - {
 - if(ChanType(c) & CHANNEL_COBJ) {
 -  if(Typeof(ChanObj(c)) == TYPE_GARBAGE) {
 -    ChanType(c) &= ~CHANNEL_COBJ;
 -    ChanObj(c) = -1;
 -    return 0;
 -    } else return 1;
 -   } else return 0;    
 -}
 -
 -const char *
 -ChanObjName(CHAN *c)
 -  {
 -    ATTR *nm;
 -    static char buff[BUFFER_LEN];
 -    static char tbuf[BUFFER_LEN];
 -    
 -    if(!c)
 -      return NULL;
 -   
 -   if(ChanType(c) & CHANNEL_COBJ) {
 -      if(Typeof(ChanObj(c)) == TYPE_GARBAGE) {
 -         ChanType(c) &= ~(CHANNEL_COBJ);
 -         ChanObj(c) = -1;
 -         strcpy(buff,tprintf("<%s>", ChanName(c)));
 -         return buff;    
 -      }
 - 
 -     nm = atr_get_noparent(ChanObj(c), "CHANNAME");
 -       if(nm) {
 -          strcpy(tbuf,atr_value(nm));
 -        strcpy(buff,(char *) nv_eval(ChanObj(c), tbuf));
 -        }
 -        else {
 -          strcpy(buff,tprintf("<%s>", ChanName(c)));
 -         }
 -   }
 -    else {
 -        strcpy(buff,tprintf("<%s>", ChanName(c))); }
 -
 -   return buff; 
 -}
 -
 -static char *nv_eval(dbref thing, const char *code) {
 -  static char my_buff[BUFFER_LEN * 3];
 -  char *my_bp = my_buff;
 -  char *tbuf = (char *) mush_malloc(BUFFER_LEN, "nv_eval");
 -  char *tbuf_ptr = tbuf;
 -
 -  strcpy(tbuf, code);
 -  process_expression(my_buff, &my_bp, (const char **) &tbuf,
 -                        thing, thing, thing, PE_DEFAULT, PT_DEFAULT,
 -                        (PE_Info *) NULL);
 -
 -  *my_bp = '\0';
 -
 -  mush_free((Malloc_t) tbuf_ptr, "nv_eval");
 -  return my_buff;
 -}
 -
 -
+ /* Evaluate a channel lock with %0 set to the channel name.
   * \param c the channel to test.
   * \param p the object trying to pass the lock.
   * \param type the type of channel lock to test.
diff --cc src/funmath.c
index 7e111851b6cabcad35b8b16445585f932d4c877d,574180a55e862aa0d369c06c763d1d03307d66cf..ef5b17374e8873db46fe5904f5cacaedd93fd0fd
@@@ -2196,8 -1902,7 +2196,9 @@@ MATH_FUNC(math_mean
  MATH_FUNC(math_div)
  {
  /* Division, truncating to match remainder */
 -  int divresult, n;
 +  IVAL divresult;
++  div_t q;
 +  int n;
  
    if (nptr < 1) {
      safe_chr('0', buff, bp);
@@@ -2366,8 -2077,7 +2373,9 @@@ MATH_FUNC(math_modulo
  MATH_FUNC(math_remainder)
  {
  /* Remainder */
 -  int divresult, n;
 +  IVAL divresult;
 +  int n;
++  div_t r;
  
    if (nptr < 1) {
      safe_chr('0', buff, bp);
diff --cc src/funmisc.c
index 8353cd4b979787facc8021694644b94de05da535,53db28d643a4e3b9ac927bb6638ebd63220ecf78..9c78e2a633535a35b0c4b3453087dcb00f151d32
@@@ -828,48 -706,48 +828,47 @@@ FUNCTION(fun_allof
  
  /* Signal Shit */
  FUNCTION(fun_signal) {
 -      enum qid_flags qsig = QID_FALSE;
 -      int signal_r;
 -
 -      if(!*args[0] || !*args[1])
 -              return;
 -      /* find out which signal we're using */
 -      if(string_prefix("kill", args[1]))
 -              qsig = QID_KILL;
 -      else if(string_prefix("freeze", args[1]))
 -              qsig = QID_FREEZE;
 -      else if(string_prefix("continue", args[1]))
 -              qsig = QID_CONT;
 -      else if(string_prefix("time", args[1]))
 -              qsig = QID_TIME;
 -      else if(string_prefix("query_t", args[1]))
 -              qsig = QID_QUERY_T;
 -      if(qsig == QID_FALSE) {
 -              safe_str("#-1 INVALID SIGNAL", buff, bp);
 -              return;
 -      } else if(qsig == QID_TIME && (!args[2] || !*args[2] ||
 +        enum qid_flags qsig = QID_FALSE;
 +        int signal_r;
 +
 +        if(!*args[0] || !*args[1])
 +                return;
 +        /* find out which signal we're using */
 +        if(string_prefix("kill", args[1]))
 +                qsig = QID_KILL;
 +        else if(string_prefix("freeze", args[1]))
 +                qsig = QID_FREEZE;
 +        else if(string_prefix("continue", args[1]))
 +                qsig = QID_CONT;
 +        else if(string_prefix("time", args[1]))
 +                qsig = QID_TIME;
 +        else if(string_prefix("query_t", args[1]))
 +                qsig = QID_QUERY_T;
 +        if(qsig == QID_FALSE) {
 +                safe_str("#-1 INVALID SIGNAL", buff, bp);
 +                return;
 +        } else if(qsig == QID_TIME && (!args[2] || !*args[2] ||
                                       atoi(args[2]) < 0)) {
 -              safe_str("#-1 INVALID TIME ARGUMENT", buff, bp);
 -              return;
 -      }
 -
 -      switch((signal_r = do_signal_qid(executor, atoi(args[0]), qsig, qsig == QID_TIME ? atoi(args[2]) : -1))) {
 -              case 0:
 -                      safe_str("#-1 INVALID TIME ARGUMENT", buff, bp);
 -                      break;
 -              case -1:
 -                      safe_str("#-1 INVALID QID", buff, bp);
 -                      break;
 -              case -2: /* we shouldn't be getting this */
 -                      safe_str("#-1 INVALID SIGNAL", buff, bp);
 -                      break;
 -              case -3:
 -                      safe_str("#-1 PERMISSION DENIED", buff, bp);
 -              default:
 -                      safe_integer(signal_r > -1 ? signal_r : 0, buff, bp);
 -                      break;
 -      }
 -              
 +                safe_str("#-1 INVALID TIME ARGUMENT", buff, bp);
 +                return;
 +        }
 +
 +        switch((signal_r = do_signal_qid(executor, atoi(args[0]), qsig, qsig == QID_TIME ? atoi(args[2]) : -1))) {
 +                case 0:
 +                        safe_str("#-1 INVALID TIME ARGUMENT", buff, bp);
 +                        break;
 +                case -1:
 +                        safe_str("#-1 INVALID QID", buff, bp);
 +                        break;
 +                case -2: /* we shouldn't be getting this */
 +                        safe_str("#-1 INVALID SIGNAL", buff, bp);
 +                        break;
 +                case -3:
 +                        safe_str("#-1 PERMISSION DENIED", buff, bp);
 +                default:
 +                        safe_integer(signal_r > -1 ? signal_r : 0, buff, bp);
 +                        break;
 +        }
-                 
  }
  
  FUNCTION(fun_trigger) {
diff --cc src/game.c
index 56f09f27a4b9e999011a21121dc2701139851b27,0ed5c1561cf8a059315ae5adb6d033b9590bceb7..b057b82aeee960730dab6b74720f70dd7fa19829
@@@ -1868,29 -1841,29 +1868,43 @@@ do_scan(dbref player, char *command, in
      }
      ptr = atrname;
      if ((Zone(player) != NOTHING)
 -      && (Zone(player) != Zone(Location(player)))) {
 +        && (Zone(player) != Zone(Location(player)))) {
        /* check the player's personal zone */
        if (IsRoom(Zone(player))) {
 -      if (Location(player) != Zone(player)) {
 -        notify(player, T("Matches on personal zone master room:"));
 -        DOLIST(thing, Contents(Zone(player))) {
 -          if (ScanFind(player, thing)) {
 -            *ptr = '\0';
 -            notify_format(player, "%s  [%d:%s]",
 -                          unparse_object(player, thing), num, atrname);
 -            ptr = atrname;
 -          }
 -        }
 -      }
 +        if (Location(player) != Zone(player)) {
 +          notify(player, T("Matches on personal zone master room:"));
 +          DOLIST(thing, Contents(Zone(player))) {
 +            if (ScanFind(player, thing)) {
 +              *ptr = '\0';
 +              notify_format(player, "%s  [%d:%s]",
 +                            unparse_object(player, thing), num, atrname);
 +              ptr = atrname;
 +            }
 +          }
 +        }
        } else if (ScanFind(player, Zone(player))) {
 -      *ptr = '\0';
 -      notify_format(player, T("Matched personal zone: %s  [%d:%s]"),
 -                    unparse_object(player, Zone(player)), num, atrname);
 +        *ptr = '\0';
 +        notify_format(player, T("Matched personal zone: %s  [%d:%s]"),
 +                      unparse_object(player, Zone(player)), num, atrname);
 +      }
 +    }
 +  }
 +  ptr = atrname;
 +  if ((flag & CHECK_DIVISION) && GoodObject(Division(player))) {
++    /* try division tree */
++    notify(player, T("Matches on objects in the division tree:"));
++    for (thing = Division(player); GoodObject(thing);
++       thing = Division(thing)) {
++      if (ScanFind(player, thing)) {
++        *ptr = '\0';
++      notify_format(player, "%s  [%d:%s]",
++                    unparse_object(player, thing), num, atrname);
++      ptr = atrname;
+       }
+     }
+   }
+   ptr = atrname;
+   if ((flag & CHECK_DIVISION) && GoodObject(Division(player))) {
      /* try division tree */
      notify(player, T("Matches on objects in the division tree:"));
      for (thing = Division(player); GoodObject(thing);
diff --cc src/mushlua.c
index a1fca31035510268820060800021b594dc72334f,0000000000000000000000000000000000000000..81628731967349a611cbe8f6d289d8f4c074e207
mode 100644,000000..100644
--- /dev/null
@@@ -1,62 -1,0 +1,62 @@@
-   mush_lua_env = lua_open();
 +/* lua API for CobraMUSH */
 +#include "config.h"
 +#include <string.h>
 +#include "conf.h"
 +#include "dbio.h"
 +#include "externs.h"
 +#include "parse.h"
 +#include "htab.h"
 +#include "command.h"
 +
 +#include "lua.h"
 +#include "lualib.h"
 +#include "lauxlib.h"
 +#include "mushlua.h"
 +
 +extern void luaopen_cobra(lua_State *);
 +static lua_State *mush_lua_env = NULL;
 +void mlua_test(dbref, char *);
 +
 +
 +void mush_lua_start() {
 +
++  mush_lua_env = lua_newstate(NULL, NULL);
 +  /* Load Global Values */
 +
 +
 +  /* Load Cobra SWIG Wrappers */
 +  luaopen_mush(mush_lua_env);
 +
 +  luaL_openlibs(mush_lua_env);
 +}
 +
 +void mush_lua_stop() {
 +
 +  if(!mush_lua_env)
 +    return;
 +
 +  lua_close(mush_lua_env);
 +}
 +
 +/* Until we have real stuff.. this tests my lua scripts.. */
 +void mlua_run(dbref enactor, char *filename) {
 +  int s;
 +
 +  s = luaL_loadfile(mush_lua_env, tprintf("lua/%s.lua", filename));
 +
 +  if(s==0)
 +    s = lua_pcall(mush_lua_env, 0, LUA_MULTRET, 0);
 +
 +  if(s != 0)
 +    notify_format(enactor, "Lua Error: %s\n", lua_tostring(mush_lua_env, -1));
 +}
 +
 +/* @lua <file> */
 +COMMAND(cmd_mushlua) {
 +  if(SW_ISSET(sw, SWITCH_RESTART)) {
 +    mush_lua_stop();
 +    mush_lua_start();
 +    notify(player, "Lua Engine Restarted.");
 +  } else 
 +    mlua_run(player, arg_left);
 +}
diff --cc src/set.c
Simple merge
diff --cc src/speech.c
index 0969a5fa4ada78ad9a74974f12edb5f1fdfd255d,713f95094d142f0d6f01e48d122c4bff796567d0..daa3ab3dce9cacb715ab57b5669a67d02089118f
@@@ -819,44 -702,47 +819,47 @@@ do_page(dbref player, const char *arg1
        fails_lock = !(override || eval_lock(player, target, Page_Lock));
        is_haven = !override && Haven(target);
        if (!Connected(target) || (Dark(target) && (is_haven || fails_lock))) {
 -      /* A player isn't connected if they aren't connected, or if
 -       * they're DARK and HAVEN, or DARK and the pagelock fails. */
 -      page_return(player, target, "Away", "AWAY",
 -                  tprintf(T("%s is not connected."), Name(target)));
 -      if (fails_lock)
 -        fail_lock(player, target, Page_Lock, NULL, NOTHING);
 -      safe_chr(' ', tbuf, &tp);
 -      safe_str_space(current, tbuf, &tp);
 +        /* A player isn't connected if they aren't connected, or if
 +         * they're DARK and HAVEN, or DARK and the pagelock fails. */
 +        page_return(player, target, "Away", "AWAY",
 +                    tprintf(T("%s is not connected."), Name(target)));
 +        if (fails_lock)
 +          fail_lock(player, target, Page_Lock, NULL, NOTHING);
 +        safe_chr(' ', tbuf, &tp);
 +        safe_str_space(current, tbuf, &tp);
  #ifdef RPMODE_SYS
-       } else if(RPMODE(player) && LEVEL(target) < 23) {
-               notify(player, "You can't do that in RPMODE.");
-               safe_chr(' ', tbuf, &tp);
-               safe_str_space(Name(target), tbuf, &tp);
+       } else if(RPMODE(player)
+               && !(Can_RPCHAT(player) || LEVEL(target) >= 23)) {
+             notify(player, "You can't do that in RPMODE.");
+             safe_chr(' ', tbuf, &tp);
+             safe_str_space(Name(target), tbuf, &tp);
  #endif
        } else if (is_haven) {
 -      page_return(player, target, "Haven", "HAVEN",
 -                  tprintf(T("%s is not accepting any pages."), Name(target)));
 -      safe_chr(' ', tbuf, &tp);
 -      safe_str_space(Name(target), tbuf, &tp);
 +        page_return(player, target, "Haven", "HAVEN",
 +                    tprintf(T("%s is not accepting any pages."), Name(target)));
 +        safe_chr(' ', tbuf, &tp);
 +        safe_str_space(Name(target), tbuf, &tp);
        } else if (fails_lock) {
 -      page_return(player, target, "Haven", "HAVEN",
 -                  tprintf(T("%s is not accepting your pages."),
 -                          Name(target)));
 -      fail_lock(player, target, Page_Lock, NULL, NOTHING);
 -      safe_chr(' ', tbuf, &tp);
 -      safe_str_space(Name(target), tbuf, &tp);
 +        page_return(player, target, "Haven", "HAVEN",
 +                    tprintf(T("%s is not accepting your pages."),
 +                            Name(target)));
 +        fail_lock(player, target, Page_Lock, NULL, NOTHING);
 +        safe_chr(' ', tbuf, &tp);
 +        safe_str_space(Name(target), tbuf, &tp);
-       } else if(RPMODE(target) && LEVEL(player) < 23 && LEVEL(target) < 23 ) {
-               page_return(player, target, 
-                    "RPMode", "RPMODE", 
-                       tprintf(T("%s is in RPMode and can not communicate OOCly at this moment."), Name(target)));
-                               safe_chr(' ', tbuf , &tp);
-                               safe_str_space(current, tbuf, &tp);
+ #ifdef RPMODE_SYS
+       } else if(RPMODE(target) && !(Can_RPCHAT(target) || (LEVEL(player) >= 23 && LEVEL(target) >= 23))) {
+             page_return(player, target, 
+                  "RPMode", "RPMODE", 
+                     tprintf(T("%s is in RPMode and can not communicate OOCly at this moment."), Name(target)));
+                             safe_chr(' ', tbuf , &tp);
+                             safe_str_space(current, tbuf, &tp);
+ #endif
 -                    } else if(hidden(target) && !CanSee(player,target)){
 -            /* this is a page that appears bad, but is good */
 -                page_return(player, target, "Away", "AWAY",
 -                         tprintf(T("%s is not connected."), Name(target)));
 -                safe_chr(' ', tbuf, &tp);
 -                safe_str_space(current, tbuf, &tp);
 +                      } else if(hidden(target) && !CanSee(player,target)){
 +              /* this is a page that appears bad, but is good */
 +                  page_return(player, target, "Away", "AWAY",
 +                           tprintf(T("%s is not connected."), Name(target)));
 +                  safe_chr(' ', tbuf, &tp);
 +                  safe_str_space(current, tbuf, &tp);
  
               almost_good[ag_count] = target;
               ag_count++;
diff --cc utils/mkcmds.pl
index 943bf90705d64313d4b56eecc848062decba0c1c,7198b24b8ff5b52d33b402e2c9fc2fbed7b7dbe3..7261598849116bc9b6acb4aaa22db0cd8b04f652
@@@ -14,268 -14,14 +14,11 @@@ use subs qw/make_patches make_switches 
  # Always present functions
  use subs qw/maybemove temp_header temp_source scan_files_for_pattern/;
  
- # Main loop, dispatch for each command line argument.
- foreach my $command (@ARGV) {
-     if ($command eq "patches") {
-         make_patches;
-     } elsif ($command eq "switches") {
-         make_switches;
-     } elsif ($command eq "commands") {
-         make_cmds;
-     } elsif ($command eq "functions") {
-         make_funs;
-     } elsif ($command eq "all") {
-         make_patches;
-         make_switches;
-         make_cmds;
-         make_funs;
-     } else {
-         warn "Unknown option '${command}'\n";
-     }
- }
- # Return name of a temp file in hdrs/
- sub temp_header {
-     return "hdrs/temp.$$.h";
- }
- # Return name of a temp file in src/
- sub temp_source {
-     return "src/temp.$$.c";
- }
- # maybemove(file1, file2) copies file1 to file 2 if they are different,
- # otherwise just deletes file1 and leaves file2 unchanged.
- sub maybemove {
-     my $from = shift;
-     my $to = shift;
-     if (compare $from, $to) {
-         if (move $from, $to) {
-             print "File ${to} updated.\n";
-         } else {
-             warn "Couldn't rename ${from} to ${to}: $!\n";
-         }
-     } else {
-         print "File ${to} unchanged.\n";
-         unlink $from;
-     }
- }
- # scan_files_for_pattern(glob-pattern, re) searches all files matching
- # glob-pattern for lines matching re, and returns a sorted list of
- # $1's for each matching line.
- sub scan_files_for_pattern {
-     my $filepattern = shift;
-     my $re = shift;
-     my @idents;
-     foreach my $file (glob $filepattern) {
-         open FILE, "<", $file 
-             or die "Cannot open ${file} for reading: $!\n";
-         while (<FILE>) {
-             chomp;
-             push @idents, $1 if m/$re/;
-         }
-         close FILE;
-     }
-     return sort @idents;
- }
- END {
-     # Make sure temp files get deleted.
-     my @files = (temp_header(), temp_source());
-     foreach my $file (@files) {
-         unlink $file if -f $file;
-     }
- }
- __DATA__
- sub make_patches {
-     print "Rebuilding list of installed patches\n";
-     my $tempfile = temp_header;
-     my $patchfile = "hdrs/patches.h";
-     my $auto_msg = "/* AUTOGENERATED FILE. DO NOT EDIT! */\n";
-     open PATCHES, ">", $tempfile
-         or die "Couldn't open $tempfile for writing: $!\n";
-     print PATCHES $auto_msg;
-     print PATCHES "#ifndef PATCHES_H\n";
-     print PATCHES "#define PATCHES_H\n";
-     my %patches;
-     if (-d "patches") {
-         foreach $file (<patches/*>) {
-             next if $file =~ /(?:\.bak|\.orig|\.rej|~)$/o;
-             open FILE, "<", $file
-                 or die "Couldn't open file '$file' for reading: $!\n";
-             my $name = undef;
-             my $version = undef;
-             LINE: while (<FILE>) {
-                 chomp;
-                 $name = $1 if m/^# Patch name: (.*)/o;
-                 $version = $1 if m/^# Patch version: (.*)/o;
-                 if (defined $name && defined $version) {
-                     $patches{$name} = $version;
-                     last LINE;
-                 }
-             }
-             close FILE;
-         }
-         if (scalar keys %patches > 0) {
-             print PATCHES '#define PATCHES "';
-             while (my ($name, $version) = each %patches) {
-                 print PATCHES "$name($version) ";                
-             }
-             print PATCHES '"', "\n";
-         } else {
-             print PATCHES "#undef PATCHES\n";
-         }
-     } else {
-         print PATCHES "#undef PATCHES\n";
-     }
-     print PATCHES "#endif /* PATCHES_H */\n";
-     close PATCHES;
-     
-     maybemove $tempfile, $patchfile;
- }
- sub make_switches {
-     print "Rebuilding command switch file and header.\n";
-     my $auto_msg = "/* AUTOGENERATED FILE. DO NOT EDIT! */\n";
-     
-     my $temphdr = temp_header;
-     my $tempsrc = temp_source;
-     open CMDHDR, "<", "hdrs/command.h" or
-         die "Unable to open hdrs/command.h for reading: $!\n";
-     my $numbytes = 20;
-     while (<CMDHDR>) {
-         if (m/^#define\s+NUM_BYTES\s+(\d+)/o) {
-             $numbytes = $1;
-             last;
-         }
-     }
-     close CMDHDR;
-     my $MAXSWITCHES = $numbytes * 8;
-     
-     my @switches = scan_files_for_pattern "src/SWITCHES", qr/^(.+)/;
-     
-     warn "Too many switches defined!\n" if length @switches > $MAXSWITCHES;
-     open HDR, ">", $temphdr or
-         die "Unable to open $temphdr for writing: $!\n";
-     open SRC, ">", $tempsrc or
-         die "Unable to open $tempsrc for writing: $1\n";
-     print HDR $auto_msg;
-     print HDR "#ifndef SWITCHES_H\n";
-     print HDR "#define SWITCHES_H\n";
-     print SRC $auto_msg;
-     print SRC "SWITCH_VALUE switch_list[] = {\n";
-     
-     my $n = 1;
-     foreach my $switch (@switches) {
-         print HDR "#define SWITCH_${switch} ${n}\n";
-         print SRC "  {\"${switch}\", SWITCH_${switch}},\n";
-         $n++;
-     }
-     
-     print SRC "  {NULL, 0}\n";
-     print SRC "};\n";
-     close SRC;
-     print HDR "#endif                          /* SWITCHES_H */\n";
-     close HDR;
-     maybemove $temphdr, "hdrs/switches.h";
-     maybemove $tempsrc, "src/switchinc.c";
- }
- # I really should combine this and make_funs into one function that does
- # the work with specific files/regexps/defines passed as arguments
- sub make_cmds {
-     my $auto_msg = "/* AUTOGENERATED FILE. DO NOT EDIT! */\n";
-     print "Rebuilding command prototype header.\n";
-     
-     my $tempfile = temp_header;
-     
-     my @commands =
-         scan_files_for_pattern "src/*.c", qr/^\s*COMMAND\(([^\)]+)\)/;
-     open HDR, ">", $tempfile
-         or die "Can't open ${tempfile} for writing: $!\n";
-     
-     print HDR $auto_msg;
-     print HDR "#ifndef CMDS_H\n";
-     print HDR "#define CMDS_H\n";
-     foreach my $command (@commands) {
-         print HDR "COMMAND_PROTO(${command});\n";
-     }
-     print HDR "#endif /* CMDS_H */\n";
-     close HDR;
-     maybemove $tempfile, "hdrs/cmds.h";
- }
- sub make_funs {
-     my $auto_msg = "/* AUTOGENERATED FILE. DO NOT EDIT! */\n";
-     print "Rebuilding function prototype header.\n";
-     
-     my $tempfile = temp_header;
-     
-     my @functions =
-         scan_files_for_pattern "src/*.c", qr/^\s*FUNCTION\(([^\)]+)\)/;
-     open HDR, ">", $tempfile
-         or die "Can't open ${tempfile} for writing: $!\n";
-     
-     print HDR $auto_msg;
-     print HDR "#ifndef FUNS_H\n";
-     print HDR "#define FUNS_H\n";
-     foreach my $function (@functions) {
-         print HDR "FUNCTION_PROTO(${function});\n";
-     }
-     print HDR "#endif /* FUNS_H */\n";
-     close HDR;
-     maybemove $tempfile, "hdrs/funs.h";
- }
- #!/usr/bin/perl -w
- # perl version of the old mkcmds.sh script. Runs faster by simply not running
- # a bazillion child processes. Also uses SelfLoader to avoid compiling functions
- # that are never used, since it's usually invoked with at most 1 argument.
- #
- use SelfLoader;
- use File::Compare;
- use File::Copy;
- use strict; # Please ma'am may I have another?
- # SelfLoaded functions
- use subs qw/make_patches make_switches make_cmds make_funs/;
- # Always present functions
- use subs qw/maybemove temp_header temp_source scan_files_for_pattern/;
--print "Starting...\n";
--
  # Main loop, dispatch for each command line argument.
  foreach my $command (@ARGV) {
      if ($command eq "switches") {
          make_switches;
      } elsif ($command eq "commands") {
--        print "Commands\n";
          make_cmds;
      } elsif ($command eq "functions") {
          make_funs;
@@@ -350,7 -96,7 +93,6 @@@ END 
  __DATA__
  
  sub make_switches {
--    print "Rebuilding command switch file and header.\n";
      my $auto_msg = "/* AUTOGENERATED FILE. DO NOT EDIT! */\n";
      
      my $temphdr = temp_header;
  sub make_cmds {
      my $auto_msg = "/* AUTOGENERATED FILE. DO NOT EDIT! */\n";
  
--    print "Rebuilding command prototype header.\n";
--    
      my $tempfile = temp_header;
--    
++
      my @commands =
          scan_files_for_pattern "src/*.c", qr/^\s*COMMAND\s?\(([^\)]+)\)*/;
  
      open HDR, ">", $tempfile
          or die "Can't open ${tempfile} for writing: $!\n";
--    
++
      print HDR $auto_msg;
      print HDR "#ifndef CMDS_H\n";
      print HDR "#define CMDS_H\n";
  sub make_funs {
      my $auto_msg = "/* AUTOGENERATED FILE. DO NOT EDIT! */\n";
  
--    print "Rebuilding function prototype header.\n";
--    
      my $tempfile = temp_header;
      
      my @functions =