// Shadowlands Forum Developers' ChangeLog                -*- c -*- (for emacs)
//
// NOTE: If you just want to read about new features for 1.9.6,
// please check out
//     http://shadowlands.org/forum/slf196/ChangeLog-userfeatures
//     http://shadowlands.org/forum/slf196/docs/features.html
//
// this ChangeLog uses yyyymmdd.hhmm format for a unique timestamp
// for each change; this makes it easy to grep the sources for exactly where
// these changes were made.
//
// Sometimes methods or other code is removed; you may need to look in
// the archives to find this code (and the accompanying timestamp) in an
// older version of the source.
//
// Unless the change has 'dschin' or 'matt' near it, jeremy implemented.
//
// bug fixes and changes not visible to users are (in parens).
//
// where a -- version # -- is noted, it includes all changes listed below
// it in the file; anything above it will be part of the next release.
//
// gaps of a few lines indicate no development work was done for a while.



/*
 * -=-=-=- 1.9.6.4 -=-=-=-  (1.9.6 maintenance release)  4 Jul 2008
 *
 *	Includes everything below this line, including 1.9.7-devel items.
 *
 * (20080704.0920) update INSTALL: PAM is more or less standard now
 *
 *	(Releasing 1.9.7-devel17 as 1.9.6.4 with no other changes.)
 *
 *
 * --1.9.7-devel17 --
 *
 * (20080523.2021) fix for fedora 9: passwd.c proto for time_t time.
 *
 * (20080523.0735) fix gcc assignment const warnings: virtdb.c
 *	Keep version 1.0.2 (from 2005) because no functional changes are
 *	being made to virtdb.c.
 *
 * (20080523.0711) fix pointer sign warnings: passwd-db-inc.c (no unsigned now)
 *
 * 20080523.0647 PAM: use "login" service, not "slforum".
 *	PAM has changed, we can't supply our own PAM file and expect it to
 *	work unmodified. Noted in INSTALL: May need to run as root for PAM.
 *	Also more logging - pam_check_pass calls Lprintf when bailing.
 *
 * 20080523.0610 rename Makefile-linux-fc4 to Makefile-linux-fedora,
 *	adjust comments in there; fc4 is old now.
 *	Remove "-Wmissing-prototypes" from Makefile-shared
 *
 * (20080405.0536) dschin: gcc tweaks (gcc 4.1)
 *
 *
 *
 * --1.9.7-devel16 --
 *
 * (20070128.1830) fix inf-loop bug in lpcat when \r\n or \n\r found
 *
 *
 *
 * --1.9.7-devel15 --
 *
 * (20060912.2328) gcc fixes for strict gcc4.1 (fedora core 5)
 *		Uses same makefile Makefile-linux-fc4.
 *
 *
 *
 * --1.9.7-devel14 --
 *
 * (20060704.1025) typo fix ChangeLog-userfeatures disze->dsize (1.9.5-devel49)
 *
 * (20060704.0940) new user state STATE_LOAD_PREFS between accept and enter.
 *	(user::state_is_load_prefs, user::loadPrefs, isUserAround changes)
 *
 * 20060704.0915: add !macro to listing in !help (and rearrange)
 *
 * (20060704.0910) in slfprefs.h, ALLOW_TOPICS is define/undef not 1/0.
 *	(always been that way; add clarify comments)
 *
 * (20060614.1235) don't set recap_lasttime for MSG_SYS messages
 *
 * (20060613.0600) write chimes to recap-log in room::CheckHourChime
 *
 * (20060610.1520) bugfix where !macro add prints Use: message too.
 *	(slforumcmd::c_macro missing 'else' before 'if edit')
 *
 * 20060610.1445: handle ^E(esc) and ^E^H (user::ManageInputNewCtrlChar,
 *	case ss_macro_addedit_readkey in SLForumUser::HandleAdminLine,
 *	tryExpandMacro.)  If the user already has a macro defined for esc
 *	or backspace, let them expand it, but can't create or edit one.
 *	Fixes "FORUM: No macro is defined for ^E ^H", "for ^E <esc>"
 *
 * 20060610.1400: add desc comment above user::hourlyChime.
 *
 * 20060608.0610: for timestamps/chimes, user::expandTimeTokens added
 *
 * 20060607.0610: for timestamps/chimes, recap_time[], recap_timetype[] added
 *
 * (20060603.1100) don't save lines with hintbits in recap
 *
 * 20060601.0700: USE_USERCOUNT_FILE, ::UpdateUserCount added
 *
 * 20060528.1140: recap buffer feature	(thanks M DeMaria)
 *	(room::recap, USE_RECAP, RECAP_LINES, and
 *	RECAP_IDLE_WARN_MINUTES prefs) using room::_BroadCast,
 *	printed with room::SendRecapToUser.  show_recap user pref.
 *	Text prefs RECAP_HEADER, RECAP_FOOTER, RECAP_FOOTER_IDLE_WARN_MIN,
 *	RECAP_FOOTER_IDLE_WARN_HR.
 *    FORUM: -- Recap of recent conversation --
 *    FORUM:     jeremy: k
 *    FORUM: -- Recap ends (IDLE: room quiet for 22 minutes) --
 *
 * (20060528.1127) add !me to listing in !help		(thanks M DeMaria)
 *
 * (20060528.1120) fix 'unsigned char..always true' warnings in
 *	user::keyDisplayLength, keyDisplayString
 *
 * (20060528.1110) clarify comment for AUTO_AWAY_TIME purpose in slfprefs.h
 *
 * (20060524.1250) add doc comment, fix harmless buglet in setAutoMsgchk
 *
 * 20060520.0945: SLF_PROMPT_CHAR, no longer hardcoded '>'.
 *	user::setAdmPrompt will change ">" or "> " to the prompt char.
 *
 *
 * --1.9.7-devel13 --
 *
 * (20051225.1925) confirm still compiles on rh9 (gcc-3.3)
 *
 * (20051219.2355) gcc4 fixes for fc4 compile; new file Makefile-linux-fc4.
 *    Also updated authlocal.c to note testing through kernel 2.6.11.
 *	passwd-db-inc.c: db4.3 ndbm compat; signedness warn fixes needed
 *	(virtdb bump to 1.0.2 for gcc4 fixes)
 *
 *
 * --1.9.7-devel12 --   (not announced)
 *
 * 20031204.2230: For compiling with stricter gcc3: Method definitions with
 *	parameter default values: comment-out default in .cc (defaults provided
 *	in the decl in .h)
 *
 *
 * -=-=-=- 1.9.6.3 -=-=-=-  (1.9.6 maintenance release)  25 Dec 2005
 *
 *	Includes everything below this line, including 1.9.7-devel items.
 *
 *	(Releasing 1.9.7-devel11 as 1.9.6.3 with no other changes.)
 *
 *
 * --1.9.7-devel11 --
 *
 * 20030703.0550: --nofork now accepted, in preference to -nofork (which is
 *	still accepted, but docs and Makefile "testrun" rule use --nofork)
 *
 * (20030703.0515): fix for rh9: passwd-db-inc.c looks for gdbm/ndbm.h instead
 *	of db1/ndbm.h .  This should not break Solaris, but Solaris build has
 *	not been tested lately.
 *
 *
 * -=-=-=- 1.9.6.2 -=-=-=-  (1.9.6 maintenance release)  7 Jan 2003
 *
 *	Includes everything below this line, including 1.9.7-devel items.
 *
 * (20030107.1940): virtdb util: Can now run -h / --help (an argc check was
 *	off by one); this is virtdb 1.0.1.
 *
 * (20030107.1920): ChangeLog: added info on _very_ old releases 980529,
 *	980620, 980703, for historical/hysterical purposes.
 *
 *
 * -- 1.9.7-devel10 --
 *
 * (20030103.0733): virtdb.c casts to eliminate gcc warnings for argcheck()
 *
 * (20030103.0730): Makefile tweak so virtdb compiles in linux
 *
 * 20030103.0230: Standalone utility virtdb is ready and tested!
 *
 * 20030103.0225: !set password cancels out if a blank password is typed;
 *	there had been no way to cancel, and a virtuser could accidentally
 *	clear their password (and thus not be able to log in at all).
 *
 * (20030103.0217): typedef struct slf_userinfo: add reminder that the
 *	struct passwd MUST be the first part for unix_validate to work.
 *
 * (20030103.0215): passwd-unix-inc.c: cast result of slf_getpwnam for gcc
 *
 * (20030103.0210): passwd-db-inc.c: add debug print if pw_name==NULL
 *
 * 20030103.0202: Give virtuser feedback when !set password is successful
 *
 * (20030101.0400): Add a couple debug prints to passwd-db-inc.c
 *	(Shown via Lprintf when DEBUG_INS_AND_OUTS is set)
 *
 * (20021229.1120): Change // to /* in comments in linkedlist.c, slforumutil.c,
 *	passwd-db-inc.c
 *
 *
 * -- 1.9.7-devel9 --  First release to run on OS X 10.1 with virtusers etc.
 *
 * (20021225.2000): virtuser db bugfix: slforumroom: constructor: If "test"
 *	open of virtuser database file creates it as a new 0-byte file,
 *	dbm_open may fail to reopen it; so if we create a 0-byte file here,
 *	delete it.
 *
 * (20021225.1930): passwd-db-inc.c.: room log debug prints if put_info fails
 *
 * (20021225.1600): passwd-db-inc.c: handle ndbm.h being in different locations
 *
 * (20021225.1530): admin substates: print message to user if virtusers are
 *	turned off / not accessible, and trying to add/edit/del/list them.
 *
 * (20021225.1205): Makefiles: Move -l* from Makefile-shared, no need on OS X.
 *
 * (20021225.1155): linkedlist.c, Makefiles: Define USE_MALLOC_H except for OSX
 *
 * (20021225.1150): slforumutil.c: slf_safe_fopen: Use EPERM if ENOSTR not def.
 *
 * (20021225.1145): slforumroom.cc: BindSocket nodelay setup -- remove SOL_TCP
 *	reference, since we use getprotobyname anyway.  (OS X fix)
 *	Do most programs hardcode 6 here anyway?
 *
 *
 *
 * (20021130.0830): Fix passwd.c so it compiles stub functions for virtuser
 *	calls when USE_VIRTUSERS is 0 (this means we don't need a lot of
 *	ifdefs in other files)
 *
 * (20021129.2000): Fix passwd.c so it knows OS X utmp format
 *
 *
 *
 *
 * -- 1.9.7-devel8 --
 *
 * 20020819.1740: !8ball can now take a question to ask; the question is
 *	announced publicly right above the 8ball's response.
 *
 * (20020811.0830): struct slfparam: Added field "kind", marking what kind of
 *	parameter it is. p_is_unused, p_is_str, p_is_int, p_is_user, p_is_cmd
 *	Wherever slfparams are made, sets this field.
 *
 *
 * -- 1.9.7-devel7 --
 *
 * (20020805.2110): slfprefs.h: Updated version from 1.9.6.1 to 1.9.7-devel7.
 *	Also made a note in TODO about auto-accept-guests.
 *	Otherwise identical to 1.9.6.1.
 *
 *
 * -=-=-=- 1.9.6.1 -=-=-=-  (1.9.6 maintenance release)  3 Aug 2002
 *
 *	Includes everything below this line, including 1.9.7-devel items.
 *
 * (20020803.0930): DUMP_CORE moved from Makefile-shared to slfprefs.h,
 *	now commented out by default.
 *
 * (20020803.0905): encapsulation: Added room::topicsAreOn(), setTopicsOnOff().
 *
 * (20020803.0900): slfcmd: Ensure ALL references to flarg[] contents check
 *	argc before reading from flarg[] !
 *
 * (20020803.0840): Remove segfault in cmd::c_topic (argc==0, it read flarg[0],
 *	which was NULL, on autotopic on return.)
 *
 * (20020803.0835): Don't autotopic on return if ! room->room_topics_on.
 *
 * (20020803.0210): Docs updated for recently added features.
 *
 * (20020803.0200): in !set output, showaidle now mentions !showaway/!users;
 *	msgchk changed from "check (minutes)" to "check interval (minutes)"
 *
 * (20020803.0120): If topics are off, and user is admin, hints them the admin
 *	command to turn topics on.  If !admin topics off is given, clears that
 *	hint bit (in case it's been a while) for all users.
 *
 * (20020803.0110): For localization: Added to slfprefs.h:
 *	TOPICS_DISABLED_MSG, TOPICS_ADMIN_ON_MSG.
 *
 * (20020803.0100): !prevtopic no longer lists empty "dummy topic":
 *	Old topic #3 set at 02 Aug 19:00 by nobody.  (0 comments)
 *	If it has comments, it will be listed.  (that is, if people !comment
 *	before the room's first !topic)
 *
 * (20020803.0030): Clear the flag that checks ^D^D / ESC ESC if the user in
 *	fact does not hit the key twice in a row.  (Added boolean flag
 *	substate_tracks_dblchar to SLFUser, checked in ManageInputNewChar)
 *	Fixes bug where two arrow keys would clear input line.
 *	Added note in TODO that we could parse other esc sequences from this.
 *
 * 20020802.1910: Add note to INSTALL about nbdm / gdbm
 *
 * 20020802.1850: ESC ESC clears input line, just in case.
 *
 * 20020802.1830: Prevent topic monopolizing -- the "Time until topic change
 *	allowed" is not reset when topic changes, unless topic setter also
 *	has changed.  This prevents any user from owning it for more than
 *	TOPIC_RESET_INTERVAL seconds.
 *
 *
 * -- 1.9.7-devel6 --
 *
 * (20020731.0725): Toward localization: Created constants HINT_WHISPERDONE_MSG
 *	and HINT_DONEWHISPERING_CMD_MSG in slfprefs.h, instead of hardcoded
 *	strings in slforumcmd::_i_toalso .
 *
 * 20020731.0720: Reword hint given on first whisper to:
 *	Type "!!" or ESC ESC when you're done whispering :-)
 *	(was "Type "!to all" when..." which is archaic)
 *
 * (20020731.0715): cmd::_i_toalso checks argc before trying flarg[1].strval,
 *	which won't exist if argc<2.
 *
 * 20020731.0710: New key: Can hit ESC twice to exit whisper ( !! / !to all )
 *	and keep your input line.
 *
 *
 * -- 1.9.7-devel5 --
 *
 * (20020728.1140): user::setAdmSubstate : when going to nonadmin, and keeping
 *	buffer, set the show_input field _before_ redisplaying input line with
 *	the proper prompt.  Otherwise it may hide input incorrectly.
 *
 * 20020728.1045: Now supports 60 users at a time.  userfield_t is unsigned
 *	long long, MAX_CHAT_USERS is 60.  (true max users for 64 bits is 62)
 *
 * (20020728.1040): userfield_t is unsigned; this should allow it to clear
 *	high bit on shift right, if by some calamity it becomes set.
 *
 * (20020728.1015): user::talkingTo: cast 1 to userfield_t before shift left;
 *	fixes problem of all-ones long long to_bits on 32bit platform.
 *	(the high bit of userfield_t should never be 1)  Also fixed in all
 *	other places where to_bits, from_bits, any other userfield_t var used.
 *
 * (20020728.0925): To remove cc warnings about using a void* to store a char
 *	in statedata for the macro substates, added field user::state_d_char.
 *
 *
 *
 * -- 1.9.7-devel4 --
 *
 * 20020723.1050: Added MSG_IDLESOON, !ignore idlesoon
 *
 *
 * -- 1.9.7-devel3 --
 *
 * (20020723.1040): c_topic reminds (hint msg) the user who just set topic that
 *	they may change it at any time.
 *
 * (20020723.1025): Added TOPICS_ON_AT_START to slfprefs.h -- defaults to 0.
 *	#define ALLOW_TOPICS is no longer commented out by default.
 *	!admin topics on/off dynamically enables/disables topics.
 *
 * 20020723.1015: The user who set the current topic can change it at any
 *	time; added slfuser param to topicTimeCheck, returns 0 for that user.
 *
 *
 * -- 1.9.7-devel2 --
 *
 * (20020711.0710): setAdmSubstate(ss_nonadmin) from ss_idlesoon_hitanykey
 *	no longer erroneously clears their input line.
 *
 *
 * -- 1.9.7-devel1 --
 *
 * (20020706.0945): Comment out code in RedisplayEntryLine that exits forum if
 *	the wrong prompt is chosen.  Kept the assert check that writes this to
 *	forum log.
 *
 * (20020706.0930): user::RedisplayEntryLine, user::HandleAdminLine: made sure
 *	the conditions are the same in both places for choosing admin/nonadmin
 *	prompt to display.  
 *
 *
 *
 * -=-=-=- 1.9.6 -=-=-=-    4 Jul 2002.
 *
 * 20020704.1945: Add !set showaidle pref -- show/hide AWAY:idle users in
 *	!showaway and !users listing
 *
 * (20020704.1930): Added public GetAwayTime(), isAWayFromIdle() to SLFUser.
 * 
 *
 * -- 1.9.6-devel3 --
 *
 * 20020704.1330: Add admin substate to warn user that they will go autoaway
 *	soon due to idle time, hit any key to clear idle.
 *
 * (20020704.1255): Add user::getAdmSubstate()
 *
 *
 * -- 1.9.6-devel2 --  ( internal snapshot for authlocal fix )
 *
 * (20020704.1210): Comment out dumpAuthlFailLogInfo, slf_send_file (unused).
 *
 * 20020704.1140: Update to authlocal.c 1.0.5 to fix spurious failed auths.
 *
 *
 *
 *
 *
 *
 * -- 1.9.6-devel1 --
 *
 * (20020514): comment out ancient alarm(5); in slforumutil:lpcat
 *
 * (20020514): added static dumpAuthlFailLogInfo to slforumuser.cc (called
 *	from HandleNoConnection()) to find why authlocal's failing sometimes
 *
 * (20020514): added static debug routine slf_send_file to slforumuser.cc
 *	(called from dumpAuthlFailLogInfo)
 *
 *
 * -=-=-=- 1.9.5 -=-=-=-    4 Apr 2002.
 *
 * 20020404.1224: Topics on/off can be toggled at runtime with !admin topic off
 *	if they are compiled in (if ALLOW_TOPICS is #defined in slfprefs.h)
 *
 * (20020404.0945): Added reminder about \201, \202 timestamps in user and room
 *
 * (20020404.0935): topics work again (broke when user prefs moved into struct,
 *	cosmetic dent with timebuf when u==null).  Also added check in
 *	!prevtopic # that # is set (name[0] not \0)
 *
 * 20020404.0929: Dice roll total var is unsigned
 *
 * (20020404.0920): Tweak prompt wording for "end macro with..."
 *
 * (20020404.0915): Remove macro debug prints (no longer needed)
 *
 *
 * -- 1.9.5-devel55 --
 *
 * 20020329.0210: Added !uptime command
 *
 * (20020329.0200): Fixed macro storage bug (cmd char after ^Q^U during macro
 *	record was not recognized and not changed to <cmd>)
 *
 *
 * -- 1.9.5-devel54 --
 *
 * (20020329.0140): authlocal is more careful now about partial lines
 *
 * (20020328.1540): Added <time.h> in world.h for new glibc compilation
 *
 * (20020328.1150): authlocal modified to work properly with the new
 *	/proc/net/tcp format in linux 2.4 kernel
 *
 * (20020327.1655): Room::_BroadCast no longer puts anything with a hint bit
 *	into lastpublicmsg (^N buffer)
 *
 *
 *
 *
 *
 *
 *
 * -- 1.9.5-devel53 --
 *
 * (20011030.0820): Fixed misspelling in response-8ball.h
 *
 *
 * -- 1.9.5-devel52 --
 *
 *  20011012.1445: 8ball messages are now public
 *
 * (20011012.1430): room::_BroadCast checks for users who somehow have
 *	user_fd=-1 but state != STATE_NO_CONNECTION; if this is the case,
 *	it prints a discon message and logs them out properly.
 *	(This helps guard against the fact that certain TCP connection losses
 *	 are disconnecting users without saying so.)
 *
 * (20011012.1420): Makes sure the start of a new day goes in the log
 *
 *
 * -- 1.9.5-devel51 --
 *
 * (20010921.1150): Fixed off-by-one error in malloc'd buffer bounds checking
 *	which should fix a crash while adding/editing a macro.  (This buffer
 *	was allocated in the heap, not the stack; there was no exploitable bug,
 *	just a crash-causer due to SIGSEGV.)
 *
 *
 * -- 1.9.5-devel50 --
 *
 * (20010920.0910): If compiled with DUMP_CORE defined, check ulimit -c and
 *	set our working dir to /tmp, so we can dump core there if need be.
 *
 *
 * -- 1.9.5-devel49 --
 *
 * (20010918.1200): Makes sure timers are NOT public by default; previous bug
 *	was that if you set a public timer, and replace it with a non-public
 *	timer, with no detail message, it will keep the public flag set.
 *
 * (20010918.1150): No longer sets you away if you're already away and change
 *	your hereidle.
 *
 * 20010918.1130: Docs: Alphabetized ctrl key listing, added reflow mode
 *	explanation.
 *
 * 20010918.1022: added "dsize" user pref, to set # sides on dice for !roll.
 *	(Also changed dice total to long long, and overhauled the dice display
 *	 code to never take up more than one line; it had assumptions about the
 *	 size of a single roll (2 chars).)
 *
 * 20010917.2321: added reflow mode.
 *
 * 20010917.1710: added cmd::c_8ball.
 *
 * (20010828.2340): slf_safe_fopen no longer attempts to write to stderr,
 *	since it may be closed; instead, it sets errno.
 *
 *
 * -- 1.9.5-devel48 --
 *
 * 20010807.1355: !who <username> now prints login IP as well
 *	(added struct in_addr user::loginfromip for this)
 *
 * 20010807.0005: Can now do !who <username> to print more detailed info.
 *	(Added user::printLoginDetails)
 *
 * (20010806.2214): Docs update: features.html/NewFeatures-1.9.5.html mention
 *	and explain !set jetlag
 *
 * (20010806.2200): "AWAY" on left side of colon is now AWAY_FROM_USERNAME
 *	in slfprefs.h, for easier adjusting.
 *
 * 20010806.2155: "jetlag" code is all done, incl. timers/alarms, EXCEPT
 *	that public timers are always announced/listed with jetlag 0.
 *
 *
 * -- 1.9.5-devel47 --
 *
 * (20010801.0302): "jetlag" conversion all done EXCEPT for timers/alarms.
 *
 * 20010801.0200: Attempted kicks no longer beep for everyone, just for the
 *	kicked user, and you can !ignore kicks.
 *
 * (20010731.2030): user::Send now expand \201 and \202 to the current user's
 *	local HH:MM and DD MMM HH:MM (taking jetlag into account).
 *
 * 20010731.1700: Added 'jetlag' user setting - handles being in a different
 *	timezone than the server.  (West coast users set jetlag to -3 if the
 *	server's on the east coast, for example)
 *
 *
 * -- 1.9.5-devel46 --
 *
 * 20010731.1555: Kicks no longer private.
 *
 * (20010730.1800): When adding a new virtuser, fill new struct slf_userinfo
 *	with zeroes (NULLs in the pointer fields).  This should fix that crash.
 *
 *
 * -- 1.9.5-devel45 -- [internal snapshot]
 *
 * (20010618.1710): Holding down <tab> will never run off the end of line.
 *
 * (20010618.1700): "<space>" replaced by "<sp>" when writing out.
 *	(It will still read both <space> and <sp> correctly.)
 *
 * 20010618.1655: Now warns on entry if you're ignoring public.
 *
 *
 *
 * -- 1.9.5-devel44 -- [internal snapshot]
 *
 * (20010419.1724): resetFieldsToDiscon now doesn't care if user_fd=-1
 *	when it comes to incrementing empty_slots; it only checks for if
 *	state is not STATE_NO_CONNECTION.  This should fix the out-of-slots
 *	problem we saw last night / this afternoon.
 *
 *
 * -- 1.9.5-devel43 --
 *
 * 20010418.1040: Changed c_roll.  Max # dice is now 1600 (can change this in
 *	slfprefs.h), but only the first 16 rolls (and total) are shown.
 *
 * (20010418.1020): Cosmetic bugfix for error msg if neither banner dir
 *	could be set.
 *
 * (20010418.1013): !roll 1 now says "die" not "dice".
 *
 * (20010418.0945): No longer says "is away" when whispering to yourself.
 *
 * (20010418.0930): Added running_macro flag to ::user, and added
 *	optional handle_tel_iac argument to ManageInputNewChar.
 *	Now deals properly with expanding telnet IAC in a macro.
 *	(Doesn't try to interpret it as IAC)
 *
 * (20010418.0842): main prints admin uid, if any, during startup.
 *
 * (20010418.0830): fixed room::_BroadCast and room::logprintf to print to
 *	stdout if -nofork specified and not logging to a file
 *
 * (20010418.0824): in main, moved perror before fprintf
 *
 * (20010418.0820): Minimum port # lowered to 2 (was 128)
 *
 *
 * -- 1.9.5-devel42 --
 *
 * (20010411.1629): ListCurrentMacros now properly escapes IAC.
 *
 * (20010411.1615): Added hint message during macro add/edit:
 *	"To enter control characters, precede them with Ctrl-Q."
 *	( added hint bit HINT_MACRO_CTRLQ )
 *
 * (20010411.1335): The strip-out-ctrl-chars (19990623.2335) code used in
 *	lpcat and room::doBanner now strips IAC (ascii 255) as well; this is
 *	much easier than finding and escaping them.  If anyone really really
 *	needs ascii 255 in the login banner or a spam banner, let me know and
 *	I will fix this.
 *
 * (20010411.1230): Now correctly doubles IAC characters before echoing
 *	in _sendOut and redisplayEntryLine.
 *
 * (20010411.1215): Now correctly handles double IAC on input and puts one
 *	IAC into buffer properly, including echoing back a double IAC.
 *
 * (20010410.2200): Bugfix: No longer clears input buffer (through setting the
 *	admin prompt) before expanding a macro.
 *
 *
 * -- 1.9.5-devel41 --
 *
 * (20010407.0001): SECURITY BUGFIX: Change in telnet parameters was causing
 *	remote logins to have local echo on (INCLUDING WHILE TYPING PASSWORD)
 *
 *
 * -- 1.9.5-devel40 --
 *
 * (20010406.1525): Euro char ('ascii' 128) now allowed.  (Previously was
 *	rejecting it, as a high-bit-set control character)
 *
 * (20010406.1507): Telnet options commented out for now -- they were turning
 *	off the requested features we ask for on connect.  But high bit support
 *	still works.
 *
 * (20010406.1440): High bit chars now supported properly and by default.
 *	( note: all high-bit chars fail isprint(c) in glibc-2.1, so i have
 *	  to manually check ascii value to decide whether we're calling
 *	  the ctrl char handler, or letting the char through. )
 *
 * (20010406.1255): added tel_bin_in, tel_bin_out bools (8-bit telnet binary)
 *	to struct bufinfo; wrote user::negotiate_telnet_binary.
 *
 * (20010406.1245): Now replies properly (well, negatively) to telnet options
 *	(user::HandleTelOpt)
 *
 *
 * -- 1.9.5-devel39 --
 *
 * (20010403.1530): New virtual user fields for "email" and "sponsoring user"
 *	are done and fully integrated with the admin menus.
 *
 *
 * -- 1.9.5-devel39-pre1 --  (internal checkpoint for new virtuser code)
 *
 * (20010403.1400): new in-db-record virtuser format code is done; but right
 *	now there isn't admin code to edit the new fields.
 *
 * (20010403.1200): passwd-db-inc.c: slf_virtuser_get_info: bugfix -
 *	wasn't freeing the newly allocated user struct if password
 *	fails to match; you can see why this would be a problem.
 *
 * (20010403.1035): passwd-db-inc.c: pack_pascal_string now treats NULL src
 *	strings as 0-length strings rather than an error.
 *
 * (20010402.2330): Created struct slf_userinfo, for holding the extended
 *	fields (email, sponsor) of a virtual user.  This is much easier to
 *	expand later than trying to cram more into struct passwd.
 *
 * (20010402.1611): Since slforum 2.0 devel could be a while, it's time to
 *	get a little organized.  Got off my backside and made "struct bufinfo"
 *	for buffer, yankbuffer, lastbuffer.  Also added prefs_t to group all
 *	the user preferences in one place.  (These are both in slforumuser.h)
 *
 *
 * -- 1.9.5-devel38 --
 *
 * 20010402.1430: Tabs can now be backspaced through properly: Previously,
 *	repeated spaces were mistaken for tabs, because we didn't remember
 *	whether whitespace was due to tabs or repeated spaces.  Now there's
 *	a buffer_tabmask that remembers this; see slforumuser.h for details.
 *
 * (20010402.1400): last line sent (^P buffer) now only set for public msgs.
 *
 * (20010402.1105): docs: mentioned "!to", "!also", "!to all" / "!!"
 *
 * (20010402.1050): "!to all" now typed for you (after a line wrap) if you're
 *	using "!to all" to speak and the line wraps.  Before, it was mistakenly
 *	only filling in "!to  ".
 *
 * (20010330.1240): Merged the 20010330.1140 fix into slf1.9.5-devel.
 *
 * -- 1.9.4.1 --  (1.9.4 maintenance release)
 *
 * SLF1.9.4: (20010330.1140): Small C++ syntax fix in SLForumCmd from
 *      &(me->wbListAdd) to &SLForumUser::wbListAdd allows more restrictive
 *      GCC's to compile SLForum.
 *	[ the other changes noted below are for 1.9.5-devel ]
 *
 * 20010329.1650: ChangeLog-userfeatures updated
 *
 * 20010329.1530: Docs updates
 *
 *
 * -- 1.9.5-devel37 --
 *
 * (20010329.1111): If you have no timer set, !timer would not display any
 *	public timers; this has been fixed.
 *
 * (20010329.1100): Fixed ANSI C++ warnings in slforumuser.cc; slf195 now
 *	compiles without any warning messages whatsoever.  (egcs-1.1.2)
 *
 * (20010329.1040): While away, typing a command with leading whitespace will
 *	no longer erroneously un-away you.
 *
 * (20010329.0950): Removed debugging code related to line length (not needed)
 *
 * (20010329.0940): Fixed the premature line wrap bug.  The ^W handler wasn't
 *	subtracting from cur_len.  (Well, it was subtracting 0.)
 *
 *
 * -- 1.9.5-devel36 --
 *
 * (20010328.2000): Added extra-paranoid debug to HandleGetLine;
 *	now checks cur_len, cur_pos, macro_input, buf before and after hit ret.
 *
 * (20010328.1549): Removed "curr substate" debugging logprintfs in slforumuser
 *
 *
 * -- 1.9.5-devel35 --
 *
 * (20010327.1700): Separated out ManageFullLine and ManageUserReturn
 *	from ManageChangedInputBuffer.
 *
 *
 * -- 1.9.5-devel34 --
 *
 * (20010322.1450): in _i_ignore, changed 0xffffff to (~0) .
 *
 * 20010322.1430: Now, if you're ignoring spam, and someone spams,
 *	it will tell you (along with a hint message on how to ignore that
 *	notification in future).
 *
 * (20010321.1545): debug: ^U now checks line length and the buffer actual
 *	length, and prints things to the log when it doesn't match
 *
 * (20010321.1505): that's fixed for good; now says "we heard the word x"
 *	if and only if the message was public -and- we're ignoring public.
 *
 *
 * -- 1.9.5-devel33 --
 *
 * (20010321.1500): no longer says "we heard the word x" unless ignoring publ.
 *
 * 20010321.1355: Removed 19990607.1800 feature: username and pw_gecos are
 *	no longer added to the listen list.  (Any words you want to listen to
 *	are saved with the rest of your prefs anyway.)
 *
 * (20010206.0900): Due to the change of 20010202.1045, a user logging in
 *	was finding themselves during STATE_FIND_DUPL.  Added code to
 *	user::HandleFindDupl() which, if the "found" user == this, calls
 *	GetUserIncremental a second time.
 *
 * 20010206.0800: Changed "Room uptime is" display; now just uses days,
 *	not years and months.
 *
 * (20010202.1045): Hopefully fixed the "myname to (null)>" prompt bug,
 *	by adding STATE_FIND_DUPL to the states which return true in
 *	user::IsUserAround.  In case i didn't, added debug code to
 *	setPromptFromTo which checks for NULL, prints a loud assert failed
 *	message, and dumps the relevant info (from and to indices, and the
 *	current contents of the user array) to the debug log.
 *
 * (20010201.0003): Oops.  Forum code assumes January is month 1, but localtime
 *	function says it's 0.  This explains the "Happy New Year!" chime at the
 *	start of feburary 1.  Fixed.
 *
 *
 * -- 1.9.5-devel32 --
 *
 * 20010127.1730: Can now !macro del to get rid of indiv. ones.
 *
 * (20010127.1630): Finished llist_remove_start and llist_remove_after
 *
 * (20010127.1330): Shortened <keystring> names for space, enter (CR),
 *	leftbracket (lt); added <^x>, <\nnn>.
 *
 *
 * -- 1.9.5-devel31 --
 *
 * (20010127.0525): Save and restore as much as possible of substate
 *	when managing IAC (telnet commands).  This eliminates the
 *	wait-forever-on-incorrect-pw bug.
 *
 * (20010127.0500): c_emote: if a user w/ a 9-char-long name emotes,
 *	last char of name no longer cut off
 *
 * 20010127.0440: Macros now saved and loaded with prefs!
 *
 * (20010127.0330): Eliminiated save during load (checks for running_cmd
 *	just about everywhere we'd call savePrefs if a user was running a cmd)
 *
 * (20010127.0040): Added check in redisplayEntryLine for user disconnecting
 *	during testv = uWrite (prompt) (and testv thus being -1).  Not having
 *	this check crashed our chat daemon with its 77-day uptime... oops.
 *
 * (20010126.2321): changed
 *          cur_len = stringDisplayLength (cp);
 * to
 *          cur_len = stringDisplayLength (buffer);
 * which should hopefully fix the line wrap bug
 *
 *
 *
 *
 * (20001118.1315): "ignoring banter"; changed to "ignoring public".
 *
 *
 *
 *
 *
 *
 * -- 1.9.5-devel30 --
 *
 *  (20001024.1415): keyDisplayString now returns "<lessthan>" for '<'
 *	because we use '<' at the beginning of all the other display strings.
 *
 *  (20001024.1350): Now remembers when we're adding a macro, and when we're
 *	editing an old one.  Also ASCIIZ's the macro value buffer properly.
 *	(Added "editing" bool field to macro_t struct.)
 *
 *  20001024.0830: Can now replace a macro's value with a new one.
 *	(!macro edit works)
 *
 *  20001024.0720: -nofork now lets you log to a file too.
 *
 *  (20001023.1845): Fixed a couple buggy calls to stringDisplayLength
 *
 *
 * -- 1.9.5-devel29 --
 *
 *  20001020.0900: Added !macro clear (clearCurrentMacros). 
 *
 *  (20001020.0800): Added macro_input flag, we now have separate
 *	display and string lengths for the buffer.
 *
 *  (20001017.0850): added cur_len for sep. from cur_pos
 *
 *  20001017.0835: c_to, c_also will now remind you if the person
 *	you're to'ing or also'ing is away. (FEATURE!)
 *
 *  (20001017.0830): bugfix: sendMessagesTo, sendMessagesAlso now
 *	share code; previously, if someone was logged in multiple
 *	times, sendMessagesAlso would only add one of them to the list.
 *
 *  (20001016.1900): Removed uchar, as our Makefiles declare _all_ chars
 *	to be unsigned.
 *
 *
 *  -- 1.9.5-devel28 --  (not public; macros milestone.)
 *
 *  (20001015.2010): Okay, basic macro functionality is done.
	- can make a macro
	- can play it back
	- can list 'em
	- they don't get saved
	- can't be deleted or edited yet
	- cur_pos need not be set right
	- macros not yet shared by all logins of a user,
	- macros can call macros, but no reentrancy.
 *      All this will be further developed soon.  See TODO. :)
 *
 *  (20001012.0130): Added c_macro (!macro cmd) and printCurrentMacros.
 *
 *  (20001012.0100): Added code to user::ManageInputNewCtrlChar for ^E.
 *	Rest of macro stuff is done enough for a prelim run.  (see TODO)
 *
 *  (20001011.1420): tryExpandMacro and macro_really_expand done
 *
 *  (20001011.0200): For entering ctrl chars within a macro:
 *	Added code to user::ManageInputNewCtrlChar and
 *	user::ManageInputNewChar to get into ^Q mode.
 *	(HandleAdminLine takes care of the quoted char.)
 *
 *  (20001006.0930): Added justSetState optional param to setAdmSubstate
 *
 *  (20001006.0010): added user::tryExpandMacro, macrolist, updated
 *	resetFieldsToDiscon
 *
 *  (20001005.2250): added ss_wait_macro_key substate, and handler code for
 *	it (special-case code at top of HandleAdminLine)
 *
 *
 * -- 1.9.5-devel27 --
 *
 *  (20001005.1710): Rearranged the TODO file, it looks respectable again
 *
 *  (20001004.1342): Changed ROLL_MAXDICE from 15 to 16.  Bwahaha.
 *
 *  (20001004.0920): ManageInputNewChar now checks for IAC and goes to
 *	awaitTelCmd to grab telnet esc codes; this takes care of the quotemark
 *	that windows users were seeing on their login prompt since we
 *	removed the STATE_GET_NAME username restrictions in devel26.
 *
 *  (20001003.1540): Fixed long-standing inconsistency in ManageUser
 *	where a discon would return -1 except for STATE_GET_NAME, where
 *	it would return 0.  This hack was from jkchatd (1998!) so someone
 *	disconnecting before they were accepted, wasn't announced as leaving.
 *	We've since developed cleaner ways to do this, of course.
 *	ManageUser now returns true to continue connection, false if it was
 *	disconnected.  The HandleNoConnection, HandleGetName, etc methods
 *	should do same, but since we'll be starting 2.0.0 from scratch,
 *	it's not worth the cleanup.
 *
 *
 * -- 1.9.5-devel26 --
 * ?????
 *
 *	Removed STATE_GET_NAME username restrictions
 *
 * ???
 * -- 1.9.5-devel25 --
 * 
 *  (20001002.1245): Added MAX_BANNER_LINES brake (defaults to 50).
 *	Also, banners are no longer logged, only their filename.
 *
 *  (20001002.1040): To make ManageInputNewChar a little shorter,
 *	broke out ctrl char handling into a new method, ManageInputNewCtrlChar.
 *	Also did some other cleaning up in ManageInputNewChar, it is much
 *	shorter and more straightforward now.
 *
 *  (20001002.1020): Changed all lpwrite calls in user, cmd to uWrite(buf,sz).
 *	( Except of course the one that implements uWrite(buf,sz). )
 *	All versions of uWrite now check and set user_fd=-1 .
 *
 *  (20001002.1015): user::Send methods were returning 0 not -1 if discon :(
 *
 *  (20001002.0900): Found and fixed longstanding thinko in slforumutil's
 *	lpwrite; if it had to retry, it would write "sz" bytes, but should
 *	write "todo" bytes.
 *
 *  (20001002.0830): Fix places that should check user_fd==-1 but don't.
 *	(ManageInputBuffer, HandleLockedLine, among others)
 *
 * -- 1.9.5-devel25 --
 *	Added a SIGUSR1 handler that prints all slots' status to the log.
 *
 * -- 1.9.5-devel24 --
 *	Added debugging printfs in places free_slots is changed.
 *
 * -- 1.9.5-devel23 --
 *
 * (20000926.1457): user constructor now sets STATE=STATE_NO_CONNECTION
 *	before calling resetFieldsToDiscon.
 *
 * (20000926.1448): Added STATE_SETUP_CONN transitory state.
 *	There is now one place in the code where room_empty_slots is increased,
 *	and one place in the code where it is decreased.
 *	This should fix the non-local-users no slots left bug.
 *
 *  (20000926.1300): resetFieldsToDiscon: moved ++(room->empty_slots)
 *	into user_fd!=-1 .
 *
 *  (20000926.1250): HandleNoConnection: now calls resetFieldsToDiscon
 *	if user_fd==-1 .
 *
 *  (20000925.1155): FindSlotForNewUser: changed "break" to "return" after
 *	ManageUser() call.  Still need to see why it reported the room
 *	full while saying 2 slots open...
 *
 *
 * -- 1.9.5-devel22 --
 *
 * (20000925.0710): !admin now always goes into interactive mode, since
 *	the batch mode isn't ready yet
 *
 * (20000925.0705): passwd-db-inc database ins and outs don't print to the
 *	debug log unless DEBUG_INS_AND_OUTS is defined as 1
 *
 * 200000925.0700: Hourly chime at midnight now announces the new weekday
 *
 * 200000925.0650: Can now use !ban none in addition to !ban clear
 *	(and also !listen none).
 *
 *
 *
 *
 *
 * -- 1.9.5-devel21 --
 *
 * (20000912.1200): Added bounds check 0-25 to !set rotamt.
 *
 * 20000912.0950: Added rot_offset (!set rotamt), defaults to 13.
 *
 * (20000912.0845): You now hear your own emotes even if you're ignoring 'em.
 *
 * (20000912.0815): A blank line will never be copied into lastpublicmsg
 *	(^N buffer) or the user's last sent line (^P buffer).  Also,
 *	system messages won't be copied into lastpublicmsg.
 *
 * 20000912.0810: Added rot13-with-rot10 user pref
 *
 * 20000912.0750: ^T now does rot13 of the input buffer
 *
 *
 * -- 1.9.5-devel20 --
 *
 * (20000908.1225): Bugfix and message change for the boundary of setting a
 *	timer for 1440 minutes.  The message now correctly says 1439 is the
 *	max # of minutes.
 *
 * (20000908.1220): Returning from away by hitting <CR> now works again;
 *	a check for alt cmd char had been added, but not a check for
 *	someone with -no- alt cmd char.  Fixed!
 *
 * (20000830.0310): in ManageChangedInputBuffer, when replacing altcmdchar
 *	with real cmd char, now checks for doubled char (the to-all command)
 *	and fixes that as well.
 *
 * (20000830.0300): in user::HandleNoConnection, resets lastkey/lastping
 *	before getting their name, etc.  This hopefully will prevent the
 *	go-idle-then-arrive problem.
 *
 * (20000822.1050): c_emote now resets idle time as it should.
 *
 *
 * -- 1.9.5-devel19 --
 *
 *  (20000818.1140): "seconds" removed from uptime report
 *
 *  (20000818.0040): tabcomplete for alt cmd char now works
 *
 *  (20000816.1905): auto-away no longer resets your idle time when it sets
 *	you away.
 *
 *  (20000816.1600): moved auto-away msg to slfprefs.h from hardcoded,
 *	and changed it from "idle" to "idle, auto-awayed" [and then back]
 *
 *
 * -- 1.9.5-devel18 --
 *
 *  (20000816.????): FILE CHANGE: renamed Makefile-linux to
 *	Makefile-linux-nopam, renamed Makefile-linux-pam to Makefile-linux .
 *
 *  20000816.1220: added uptime to !version.
 *	(added datediff to slforumutils.c, added room::printRoomUptime(u).)
 *
 * (20000815.2323): in user::validateAndDowncaseName, added '@' to list of
 *	nonvalid chars for a guest name; it changes this to 'a'.
 *
 * (20000815.1650): in user::HandleGetPw(), check for virtusers so a guest
 *	can't impersonate a virtuser.
 *
 * (20000815.1640): added Send
 *	(const char *fromsysusername,
 *	 int msgdescflags, const char *text, bool wants_beep)
 *	for private timer announcements.  These now beep as they should.
 *
 *  20000815.1630: !set altcmd alternate command char added
 *	(ManageChangedInputBuffer changes it to real one while clearing
 *	 whitespace from commands, and HandleAdminLine does similar.)
 *
 *  20000815.1530: !set autoaway added (auto-away when too idle)
 *
 *
 *  -- 1.9.5-devel17 --
 *
 *  (20000809.2100): Changed emote format:
 *	  jeremy: thumbs.twiddle();
 *	* dschin emotes vehemently *
 *	  jeremy: yep.
 *
 *  (20000803.1830): c_emote messages now have MSG_SYS so they say EMOTE:
 *	to the left of each line.
 *
 *
 *  -- 1.9.5-devel16 --
 *
 *  20000803.1240: FILE LOCATION CHANGE: 
 *	virtuser database is now virtuser.db, not virtuserdb.db
 *	user prefs are in <slfhomedir>/userpref/ instead of <slfhomedir> .
 *
 *  20000803.1220: added !me (c_emote) command, including MSG_EMOTE
 *	msgdesc flags and !ignore emote[s].  Known problem: if topics are
 *	turned on, !me doesn't show up on the brief list of commands;
 *	need to reorganize this.
 *
 *  (20000803.1200): bugfix: auto-msgchk now beeps as it should.
 *
 *
 * -- 1.9.5-devel15 --
 *
 *  (20000731.1000): For non-local login, sets promptlen/realpromptlen
 *	when it uses 'prompt' as scratch space for the DNS lookup.
 *	Fixes an assert crash, even though this "prompt" should never be
 *	displayed.
 *
 *  (20000719.1255): For non-admin users, !admin gives the "no such command"
 *	response.
 *
 *  (20000719.1235): Now quits the "add" area if you hit enter at the username
 *	prompt.
 *
 *  (20000719.1215): RedisplayEntryLine() now properly shows the input line
 *	when redisplaying during admin substate escape to command prompt
 *
 *
 * -- 1.9.5-devel14 --
 *
 * 20000719.1050: "make install" added
 *
 * (20000719.1030): slf_virtuser_get_info was closing db after getting the
 *	datum but before unpacking fields... when the db is closed, it corrupts
 *	the static area holding the fetched info from the db.  Fixed.
 *
 *
 * -- 1.9.5-devel13 --
 *
 * (20000719.0310): SECURITY FIX: could previously (since 1.9.5-devel7
 *	or so) see a user's pw onscreen after they unlocked.  Fixed.
 *	(forgot to set show_input in lock_me and try_unlock_me back when that
 *	var was moved from a param to a field, around -devel7.)
 *
 * (20000719.0230): All admins can now lock screen, if ALLOW_LOCKOUT defined.
 *
 * (20000718.1838): Added TCP_NODELAY to socket setup in slforumroom.cc
 *
 *
 * -- 1.9.5-devel12 --
 *
 * (20000718.0110): uses htonl(0x7f000001) instead of inet_aton("127.0.0.1");
 *	not all libs have inet_aton, but it's a simple thing we need here
 *
 * (20000718.0100): added debugging logprintfs to all virtuser-related code
 *	so we can see where and when it's screwing up, if in fact it is still
 *	screwing up.
 *
 * (20000718.0040): debugging: Lprintf(fmt,...) now allows C code to
 *	write to the room log
 *
 * 200000717.1620: now accepts cmdline params in any order :)
 *
 * (20000717.1525): virt users can now change their passwords. (previously
 *	couldn't due to typo in c_zebra)
 *
 * (20000717.1510): SECURITY: !admin now accessible only by admins ;)
 *
 * (20000715.1440): cleaned up cmdline parsing a little, with
 *	tryGetDirParam and tryGetBoolParam.
 *
 * (20000715.1415): cmdline opt reader now checks for when it expects a dirname
 *	and gets something starting with -, and prints an error msg.
 *
 * (20000715.1400): fixed bug present in -devel7 and up; coming back from away
 *	wouldn't redisplay entry line.  (there were ClearEntryLine() calls,
 *	at line 1701 and 2961 as of -devel11, without corresponding redisplays)
 *
 *
 * -- 1.9.5-devel11 --
 *
 * 20000714.2100: added SLF_MIN_REAL_USERID.  If the forum is being ran not as
 *	root but as a user, with this uid or greater, and that user logs in,
 *	they're admin.
 *
 *
 * -- 1.9.5-devel10 --
 *
 * 20000714.2050: added -bd cmdline option (banner dir)
 *
 * (20000714.2035): All edit-virtuser-field functions work and don't crash it
 *	anymore.
 *
 * (20000714.2020): SECURITY: anyone could access the admin menus by typing
 *	!admin ; fixed.
 *
 * (20000714.2010): fixed table entry for ss_nonadmin so show_input is set
 *	properly when exiting the admin system
 *
 * (20000714.2000): virtual users can now log in.
 *
 * (20000714.1845): fixed bad bug; the check for if we could write to the
 *	virtuser db was truncating it (used wb+ instead of ab+ for mode)
 *
 *
 * -- 1.9.5-devel9 --
 *
 * (20000714.1830): virtusers almost ready; can't log in yet though
 *
 * (20000714.1745): done merging fixes from 1.9.4-release into 1.9.5-develx
 *
 * (20000714.1414): slforum-username prefs now live in slfhomedir
 *
 * (20000714.1305): lockout-users now lives in slfhomedir, not hardcoded path
 *
 * (20000714.1300): added tryPrintLoginBanner();
 *	will try first from slfhomedir, then /etc,
 *	for issue.forum and then issue.net ; slfprefs.h to change. 
 *
 *
 * -- 1.9.5-devel8 --
 *
 * (20000702.2325): Sometimes, slfgetch returns \0 ; we return on that
 *	instead of trying to process it, now...
 *
 * (20000702.2250): Admin menu: The delete 'area' works properly
 *
 * (20000701.1235): All admin prompts for a given 'area' line up
 *
 * (20000701.1200): All interactive admin functions fully implemented
 *
 * (20000701.1120): Transitions from admin esc mode -> admin mode now properly
 *	sets promptlen=admpromptlen
 *
 *
 * -- 1.9.5-devel7 --
 *
 * (20000701.0930): the showInput param to get-input methods has been
 *	changed to a show_input slforumuser field; this ensures the program
 *	knows when not to show a user's input, even when redisplaying prompt
 *	after sending them info, or 'you have new mail', etc.
 *
 * (20000701.0820): Added an end-of-table marker to admInputSSBehavTable,
 *	and a check to SLForumUser constructor (runs once, then sets
 *	checked_admin_ss_table=true) to make sure it's not out of sync with
 *	the enum substate_t declaration.
 *
 * (20000630.1900): weird bug (apparent freezeup of user's connection in
 *	ss_editpw) was due to SLForumUser::admInputSSBehavTable	being out of
 *	sync w/ enum admin_substate_t... fixed.
 *
 *
 * -- 1.9.5-devel6 --
 *
 *  (20000630.1345): All admin substates done
 *
 *  (20000630.1330): SetAdmPrompt() now always clears the input buffer.
 *
 *
 * -- 1.9.5-devel5 --
 *
 *  (20000627.2030): ManageInputBuffer cmd-char handler is now a switch
 *	instead of a bunch of if's.  And it now handles the admin substate
 *	escape mode properly.
 *
 *  20000627.1210: Very minimal "list" admin fuctionality.
 *
 *  (20000627.1010): Admin prompts now line up like 'real' prompts;
 *	removed admpromptbuf, admprompt is now a char buffer[USERBUFSIZ]
 *	instead of just a char*.  Also changed <= to < in the if(promptlen
 *	<= 12 ) code of setPrompt/setAdmPrompt.
 *
 *
 * -- 1.9.5-devel4 --
 *
 *	(20000627.0845): Admin substates (except delete) done.
 *
 * -- 1.9.5-devel3 --
 *
 * (20000622.2230): It compiles again. (unix, not yet under win32)
 *
 * -- 1.9.5-devel3-inprog7 --
 *
 *  (20000622.1955): Moved admin substate handling to new file
 *	slforumuser-adminsubstate.inc.cc, included into slforumuser.cc
 *
 *  (20000622.1945): !set password is now fully implemented (but not tested).
 *
 *
 * -- 1.9.5-devel3-inprog6 --
 *
 *  (20000622.1800): re-merged stuff from work, home editing
 *
 *  ... much stuff not in here...hmmm.. about admin substates about pw.
 *
 *  20000615.0200: added admprompt, admpromptbuf, admpromptlen, realpromptlen
 *	and added setAdmPrompt to switch between real/admin prompt
 *	and added TEMPORARY CODE to RedisplayEntryLine which announces to room
 *	if the expected vs actual prompt length differ... we'll keep this
 *	til we've moved through all possible state transitions.
 *
 *  (20000615.0030): broke out ManageChangedinputbuffer
 *
 *   20000614.0200: user::setPromptFromTo() rewrites the prompt; this code
 *	was all over before.
 *
 *   20000613.0900: admin_substate slfuser field, HandleAdminLine() handler
 *
 *   20000613.0010: is_virt slfuser field
 *
 *   20000613.0000: !admin command
 *
 *
 * -- 1.9.5-devel2 --
 *
 *   20000612.2300: passwd-db-inc.c compiles.
 *
 *
 * -- 1.9.5-devel1 --
 *
 *  renamed user::setupListenList to setupRealUserInfo; it now checks to see
 *	if the user's in the admin group.
 *
 *  passwd-db-inc.c completed.
 *
 *  added admin_gid, users_gid to SLForumRoom.
 *
 *  added is_admin to SLForumUser.
 *
 *
 *
 * -- 1.9.4 --
 *
 *  (20000704.0830): Final docs tweaks.  
 *
 *  20000703.1445: New docs are done!  Check 'em out at
 *	http://shadowlands.org/forum/newdoc/
 *
 *  (20000703.1200): On startup, prints whether guests and topics are enabled
 *
 *
 * -- 1.9.4-devel37 --
 *
 *  (20000628.1500): i_msgchk_check no longer prints an error message, unless
 *	the user's running a command.  (If they're not running a command,
 *	i_msgchk_check is being invoked from the room's automsgchk handler.)
 *	It also prints a specific "You have no mailbox." message when it _is_
 *	printing an error message and the user has none, instead of the less
 *	friendly generic message printer.
 *
 *
 * -- 1.9.4-devel36 --
 *
 *  (20000623.1755): Consolidated whisperban check code into
 *	user::CheckBanned.  (removed SendCheckBan)  Code was
 *	previously in SendCheckBan (for !to <user> <msg> sending)
 *	and user::_sendOut (for standard sending)
 *
 *  (20000623.1720): Bug fix:
 *	Whispers sent via !to <user> <message> weren't being checked
 *	against the whisperban list, and could thus bypass a ban.
 *	(Added user::SendCheckBan method)
 *
 *  (20000623.1214): world.h: changed // to /*-style comments
 *
 *  (20000623.1210): Renamed TALKING_TO_SOME to TALKING_TO_MANY
 *
 *  (20000623.1205): Renamed setupListenList to setupRealUserInfo
 *
 *  (20000623.1154): Some comment clarifications
 *
 *  (20000623.1145): streamlined passwd.c; merged some duplicate code there
 *	with the aid of a couple ifdef's.
 *
 *
 * -- 1.9.4-devel35 --
 *
 *	One last docs runthrough and 1.9.4 will be ready.
 *
 *  20000623.0026: passwd-unix-inc.c:unix_validate now checks to see
 *	if the pwent password's not "x" even though shadow support is on,
 *	and uses that non-shadowed password to validate if that's the case.
 *	(This covers when we're compiling with shadow support, but shadow
 *	 is currently not installed.)
 *
 *  (20000623.0016): c_printwho now tells you when you're talking to all,
 *	instead of just being silent in that case. (cosmetic?)
 *
 *  (20000623.0007): fixed the occasional "yourname to (null)>" prompt bug.
 *	(FINALLY!  it was inadvertently introduced a year and a day ago.)
 *	Cause: When someone you where whispering to is logged in once,
 *	and they log in again and kick the self you were talking to, 
 *	the bits are set right, but talkingTo() can't get the name of the
 *	newly logged-in user, because when they started talking to 'em
 *	(through the newly logged-in calling talkToMeToo right before printing
 *	 the prompt to kick the old one), so it got (null) instead.
 *	Now uses GetUserByIndex(bitno, true) instead of GetUserByIndex(bitno)
 *	so it doesn't check IsUserAround(), it returns the *user regardless.	
 *
 *  (20000614.2220): cmd::c_zebra:
 *	Cosmetic bugfix; in current settings listings, tabself was misaligned.
 *
 *  (20000614.1245): user::ManageInputNewChar:
 *	Hitting ^W would do (n) backspaces, where n == # letters
 *	erased, even if showInput was false.  (Also, if local mode was
 *	on, would redisplay the input line, even if showInput was false.)
 *
 *
 * -- 1.9.4-devel34 --
 *
 *  (20000613.2000): That should conclude development for 1.9.4.
 *	Assuming no new bugs, 1.9.4-devel34 will be released as 1.9.4
 *	after a test period and doc review (thanks again matt!)
 *
 *  (20000613.1745): Whispering to self as a command (!to myname blah blah)
 *	no longer displays the line twice.
 *
 *  (20000613.1110): the code in ManageInputBuffer that actually reads
 *	from the socket has been moved to slfgetch()... it was in several
 *	other places as well, CNP style.  The rest has been moved to
 *	ManageInputNewChar.
 *
 *  20000612.2200: !lockout renamed to !lock
 *
 *
 * -- 1.9.4-devel33 --
 * 
 * 20000610.2000: for c_lockout: LOCKOUTUSERS_FILE lists those who can.
 *	(don't define LOCKOUT_ONLY_LOCKOUTUSERS to allow all users to.)
 *
 *
 * -- 1.9.4-devel32 --
 *
 * 20000610.1100: !ban <username> lets you disallow certain user(s) from
 *	whispering to you.
 *
 *
 * -- 1.9.4-devel31 --
 *
 * 20000610.1034: Guests must use !lockout guest to lock selves out,
 *	to confirm they know they can't unlock
 * 
 * (20000610.1030): ALLOW_LOCKOUT enables/disables c_lockout(default: disabled)
 *
 * 20000609.2030: !set tabself now allows you to tabcomplete to your own
 *	username, making it easier to make quick notes to yourself using chat.
 *
 * 20000607.1730?: c_lockout :)
 *
 * (20000607.0720): Changed authlocal to disallow connections from uid under
 *	100... well, they can still log in, but they'll be prompted for
 *	username/pw.
 *
 * (20000606.1820): In passwd-unix-inc.c, changed getpwnam to slf_getpwnam
 *
 * 20000529.0930: Added /var/lib/slforum/banners as standard banner directory,
 *	with /tmp/.banners as fallback.
 *
 *
 * -- 1.9.4-devel30 --
 *
 * (20000524.1345): Now compiles with topics enabled.
 *
 *
 * -- 1.9.4-devel29 --
 *
 * ^-- this should be the last devel release before 1.9.4... :)
 *
 * 20000523.1815: PAM support now works!  Had to make a service description
 *	file to stick in /etc/pam.d
 *
 * (20000523.1750): Now clears buffer after trying to validate pw, Just in Case
 *
 * 20000523.1600: LookForTimers now runs every 30 seconds, at :00 and :30 .
 *
 * (20000523.1555): LookForTimers wasn't checking for guest timeouts, because
 *	it used IsUserAccepted instead of IsUserAround... fixed.
 *
 * (20000523.1545): Now properly clears entry line before clearing screen
 *	by sending many blank lines.
 *
 * 20000523.1540: Prints the long legal hello message at the beginning of
 *	every successful run; previously did so only when ran w/ no params.
 *
 * 20000523.1530: Added default port number. (7777)
 *
 *
 * -- 1.9.4-devel28 --
 *
 *  20000514: Added skeleton of PAM support and other auth methods.
 *
 *
 * -- 1.9.4-devel27 --
 *
 * 20000513.1940: SHADOW SUPPORT WORKS.
 *	Problem was, passwd.c wasn't including slfprefs.h, and thus
 *	didn't know when USE_SHADOW was defined.  fixed :)
 *
 * 20000511.1720: automsgchk notifications now beep.
 *
 *
 * -- 1.9.4-devel26 --
 *
 * (20000511.0910): Bugfix: Was reporting new mail every msgchk interval.
 *	Had a >= where should've been != ... fixed
 *
 * (20000511.0705): Tweaked room::LookForTimers so it won't skip a minute
 *	by scheduling SIGALRM 60 seconds from :00 .
 *
 *
 * -- 1.9.4-devel25 --
 *
 * (20000510.1948): Partial command completion wasn't case-insensitive.  Fixed.
 *
 * (20000510.1940): After ^L, didn't print from: attribution if the person
 *	who sent the last line before ^L, sends the first line after.  Fixed.
 *
 * (20000510.1933): Alphabetized the !set display, except for command char,
 *	which goes first.
 *
 * (20000510.1923): first sked_alarm is right away, not PING_INTERVAL_SEC away
 *
 * 20000510.1900: auto-msgchk added (matt's idea)
 *
 * (20000508.??): added continue; to room::pingAndCheckTimeout when no user was
 *	in that slot; less wasted cycles
 *
 *
 * -- 1.9.4-devel24 --
 *
 * 20000506.1010: Added final timestamp in the log, ctime format, of when
 *	a run terminates, so we don't need to scroll back through the log
 *	to determine the date on which it ended.
 *
 * 20000506.0945: Added -h / -help commandline option.
 *
 * 20000506.0900: Added commandline option (+/-aa) for autoaccept guests,
 *	option for print guest-howto-message (+/-ghm), and in theory, can
 *	now accept the arguments after port # in any order.
 *
 *
 * -- 1.9.4-devel23 --
 *
 * 20000505.2040: Added guest auto-accept option at compile time (slfprefs.h).
 *	AUTO_ACCEPT_GUESTS defaults to 0, of course!  Also mentioned this
 *	in INSTALL.  Also changed GUEST_HOWTO_MESSAGE from an #ifdef to an #if.
 *
 * (20000505.1400): Began a separate ChangeLog-userfeatures file, less detailed
 *	than this one, which is really for developers.
 *
 * (20000504.1140): Documented user::Send return values
 *
 * 20000504.1130: ListenList is now checked only if the message being ignored
 *	is public; this means we no longer check listenlist for hourly chimes,
 *	etc. for folks ignoring those types of messages.
 *
 * (20000503.1540): When can't open backup wtmp file, clarified the error
 *	message to "NOT LOGGING LOGINS" from "NOT LOGGING".
 *
 *
 * -- 1.9.4-devel22 --
 *
 * (20000503.0740): If one was ignoring chimes, it would still print the
 *	hintmessage on how to ignore chimes.  Fixed.  (Had to change
 *	user::Send (const char*, int, bool) to take optional msgdescflags
 *	parameter.)
 *
 *
 * -- 1.9.4-devel21 --
 *
 * (20000502.0615): Fixed null-deref on very low memory condition in
 *	user::pingAndCheckTimeout().  This would probably never happen,
 *	but it's important to fix just in case.
 *
 * (20000502.0100): Finished reversing changelog.  (Yes, it was in
 *	time-increasing order in every version prior to this one.)
 *
 * (20000501.2050): When going from trueidle-off to trueidle-on,
 *	wouldn't update idle after the last keypress used to enter the command
 *	to move into that state. (fixed)
 *
 * 20000501.0940: Clarified the !here display; now says "x more people too
 *	idle, not shown" (added the more)
 *
 * 20000501.0900: !set now says "Your current settings" to emphasize that
 *	these are per-user preferences.
 *
 *
 * -- 1.9.4-devel20 --
 *
 * 20000430.1240: Listen list now saved and restored with other prefs
 *
 * (20000430.1230): listenListAdd now checks for dupes, and won't add a word
 *	if it's already in there. (using strcasecmp)
 *
 * 20000430.1200: Added ctrl-o for enable/disable command char
 *	(good for pasting things in.)
 *
 * (20000430.1120): Moved prefsfile path from hardcoded to slfprefs.h
 *
 * 20000430.1110: Added trueidle user preference (idle time based on last
 *	keypress (this was the old behavior) instead of last public action.)
 *
 * (20000430.1100): Cleaned up places where cmd_char was being sprintf'd in
 *	and we can now use \177 instead.
 *
 * (20000430.1045): Added reset-idles wherever the user takes a public action,
 *	since it's not set after every key anymore.
 *
 * (20000430.0400): c_here (ListUsers with exclude_idleones) now correctly
 *	says how many are _here_ and shown, not how many are logged in.
 *	(changed nu to (nu-notshown) at 20000430.0400 mark in ListUsers)
 *
 * (20000430.0005): c_help wasn't using uWriteSubst to print the cmd table,
 *	and neither was rndCommand().  Fixed.
 *
 * (20000429.2330): removed !zebra from user-visible commands. (!set remains)
 *
 * (20000429.2300): Documented all ctrl-chars in features.html
 *
 *
 * -- 1.9.4-devel19 --
 *
 * 20000429.2200: BEHAVIOR CHANGE in something long-established:
 *	Only public messages reset user idle time.
 *	(added all_keys_reset_idle field)
 *	(!set trueidle on for old behavior)
 *
 *
 * -- 1.9.4-devel18 --
 *
 * 20000429.1155: If the person you're whispering to leaves while you're
 *	typing a command, or typing a line that would be sent public using !!,
 *	that input would have been cleared; this is no longer so.
 *
 * (20000429.1130): Added code to HandleFindDupl to get rid of telnet commands
 *	(since these will be sent to this state, which is the initial state if
 *	connecting from localhost with authlocal enabled.)
 *	(Added states to parse telnet options, but they just ignore them at
 *	 present.)
 *
 * (20000429.1020): Fixed: If whispering to self (possibly among others), you
 *	saw the line sent to yourself twice.  (fixed.)
 *
 * (20000429.1015): Fixed the timer time-parsing bug that showed up only when
 *	a timer was already set.
 *
 * (20000426.1930): added uWriteSubst, and modified Send to substitute cmd char
 *	for all \177; no more !'s in help msgs if your cmd char is % or /, etc.
 *	Went through all .cc files and changed !'s to \177's in help text.
 *
 *
 *
 *
 * -- 1.9.4-devel17 --
 *
 * 20000401.1956: Fixed timer bug
 *
 * 20000401.1950: Added another second to ^D^D timeout for laggy modem users.
 *	(demaria request)
 *
 *
 * -- 1.9.4-devel16 --
 *
 * 20000321.1405: SECURITY FIX: Wasn't clearing yankbuffer on discon.  Fixed.
 *
 * 20000321.1400: added lastbuffer to user.  (Private, no getter.)
 *	Added ^P to user::ManageInputBuffer so a user can paste in the
 *	last public or private line sent.
 *	Added pasteIntoBuffer private method for ^Y, ^N, ^P.
 *
 * 20000321.1330: Added lastpublicmsg field to room.  (getLastPublicMsg()
 *	is getter).  Added ^N to user::ManageInputBuffer so a user can
 *	paste in the last public message.
 *
 *
 * -- 1.9.4-devel15 --
 *
 * 20000320.1100: added ALL_MESSAGES_TIMESTAMP feature to slfprefs.h,
 *	user::Send.  (Implements a feature requested.)
 *
 *
 * -- 1.9.4-devel14 --
 *
 * (20000305.1215): Prep for virtualization: moved all getpw* calls for
 *	getting users from the passwd file into passwd.c
 *
 * 20000305.1145: !timer/!alarm now display the old timer being replaced when
 *	setting a new one.
 *
 * (20000304.1600): Preferences for slforum now in slfprefs.h, for easy
 *	inclusion into files that don't want any of the prototypes or classes.
 *	(e.g., slforumutil.c)
 *
 *
 * -- 1.9.4-devel13 --
 *
 * (20000229.0001): !msgchk now says "you have old mail waiting", not "you have
 *	no new mail", so we don't see the word 'new' when we in fact have just
 *	old mail.  Thanks Demaria for suggestion.
 *
 * 20000227.2000: Broadcast messages with hint bits set are no longer logged;
 *	they are usage hints for the current room occupants, useless to the
 *	reader of the log.
 *
 * 20000227.1930: Hourly chimes now have a hint message telling how to ignore
 *	them if you so desire.  (As with all other hint messages, this only
 *	shows up once for each user, and is not displayed after the first
 *	time.)
 *
 * (20000227.0200): !timer/!alarm now lists public timers too
 *
 * (20000226.1850): Public timers are now announced to room when set.
 *
 * 20000226.1300: High-bit chars now allowed.  Any highbit ctrl chars are
 *	tossed out, and any highbit whitespace chars are converted to ASCII 32.
 *	[ note that this still doesn't work right, 20000302 ]
 *	[ need to impl. a state machine to handle telnet option negotiation ]
 *
 * (20000225.1605): removed !banner, now just !spam does c_banner
 *
 * 20000225.1600: now exits if can't open requested log file during startup.
 *
 *
 * -- 1.9.4-devel12 --
 *
 * 20000219.0700: slforumroom::listusers now says how many users are here but
 *	not shown.
 *
 * (20000219.0045): slforumuser::usercmds table now has all possible params
 *	for c_zebra in {|} form, not just W? .
 *
 * 20002019.0020: Simplified c_[un]ignore and its bloated help message by
 *	taking out banter and pbeep (demaria idea)
 *
 * (20000219.0018): c_showaway now shows the header line, as it should.
 *
 * 20000218.2300: rewrote c_msgchk, it should work for everyone now, and
 *	now uses no external commands or files in /tmp  :-)
 *
 *
 * -- 1.9.4-devel11 --
 *
 * 20000217.0430: Added SIGHUP handler which closes/reopens the transcript log
 *	file, for use with the logrotate(8) utility.  Eventually this handler
 *	will also re-read the slforum global config file, when we have one.
 *
 * (20000217.0415): converted "slforum.cc" to "slforumutil.c": this is more
 *	descriptive, slforummain.cc is the startup code and it was confusing
 *	to have an slforum.cc as well.  Also, as of this writing, (C vs C++),
 *	slforumutil.o is 33264 bytes; slforum.o was 54536 bytes for same code.
 *
 * 20000217.0343: Added option for public timers.
 *	Current syntax: !timer <time> public [<message>];
 *	as we parse it now, public must go after time.  We can fix that. :-)
 *
 * (20000217.0340): default command tab-completion !<tab> now works at any
 *	position; previously worked only at start of buffer.
 *
 * (20000217.0325): fixed c_timer bug where you couldn't do !timer 0 to turn
 *	a timer off (it said "out of range" if secs<1, now fixed to be <0).
 *
 *
 * -- 1.9.4-devel10 --
 *
 * (20000211.1645): Doing !to d<tab>, when d<tab> returned multiple matches,
 *	would say "multiple matches" _and_ insert a tab.  Fixed; now just
 *	says "multiple matches".
 *
 * 20000209.1630: Can now ignore system messages, because moves, rolls and
 *	hourly chimes are system messages.  We now just don't let the user
 *	ignore system messages, but they can ignore messages with other flags
 *	besides just MSG_SYS and MSG_PUBLIC set.
 *
 * 20000208.1445: Just plain !timer shows the current timer; now it also
 *	shows the timer_message, if any.  Also will show previous timer if
 *	any.	[ IsTimerSet indicates current timer; timer_expire_hour==-1
 *		  means no previous timer, any other value means there was one]
 *
 * (20000208.0808): Prefs files in /var/lib/slforum no longer start with ".".
 *	Also, loading/saving prefs put 'em in log (had a debug msg).  Fixed.
 *
 *
 * -- 1.9.4-devel9 --
 *
 * (20000207.1215): Loading prefs: !set _ignoreFlags was accidentally scaling
 *	the value by 60, cut-n-paste bug.  Fixed.
 *
 * (20000207.1145): Forgot to call me->savePrefs() from c_ignore().  Fixed.
 *
 *
 * -- 1.9.4-devel8 --
 *
 * 20000206.2045: user prefs now saved to /var/lib/slforum if it's writeable,
 *	/tmp if not.  Also, ignoreflags now saved too.
 *
 * 20000206.0200: message "Shadowlands Forum is exiting." now has a timestamp.
 *
 * (20000206.0140): c_zebra now checks to see if we're not running a command
 *	(and thus not reading in from the prefs file) and thus shouldn't save
 *	the file back out.
 *
 * 20000206.0130: set default hereidle threshold to 20 mins, from 15.
 *
 * 20000206.0100: dschin: All prefs now load! 
 *
 * (20000206.0025): nonguest connecting from non-localhost didn't set state to
 *	STATE_FIND_DUPL after getting password; fixed.
 *
 * 20000206.0001: at midnight, now announces the new date as well
 *
 * 20000205.1830: made commands.html a little clearer about !ignore/!listen
 *
 * 20000204.0900: hourly chime in very idle room now goes out to the room,
 *	but isn't logged.  (Previously didn't go to the room either)
 *
 *
 * -- 1.9.4-devel7 --
 *
 * (20000201.1310): added user::idleTime(time_t) to save 30 calls to time()
 *	in loops where we sort by idle.
 *
 * 20000201.1250: we now try to schedule our SIGALRMs at the beginning of
 *	the minute.  Matt's idea, cool eh?
 *
 * 20000201.1245: nixed Dong! for now in hourly chime, pending discussion on
 *	whether it's too obtrusive, etc.
 *
 * (20000201.1230): made user::setupListenList, where username and gecos are
 *	added to the listen list.  The code was in two places to do this
 *	previously, making it seem like either place was a good place to add
 *	other things to do on login; AcceptAndWelcomeUser is where such things
 *	should go.  Moved loadPrefs() to AcceptAndWelcomeUser.
 *
 *
 * -- 1.9.4-devel6 --

 *
 * 20000401.1956: Fixed timer bug
 *
 * 20000401.1950: Added another second to ^D^D timeout for laggy modem users.
 *	(demaria request)
 *
 *
 * -- 1.9.4-devel16 --
 *
 * 20000321.1405: SECURITY FIX: Wasn't clearing yankbuffer on discon.  Fixed.
 *
 * 20000321.1400: added lastbuffer to user.  (Private, no getter.)
 *	Added ^P to user::ManageInputBuffer so a user can paste in the
 *	last public or private line sent.
 *	Added pasteIntoBuffer private method for ^Y, ^N, ^P.
 *
 * 20000321.1330: Added lastpublicmsg field to room.  (getLastPublicMsg()
 *	is getter).  Added ^N to user::ManageInputBuffer so a user can
 *	paste in the last public message.
 *
 *
 * -- 1.9.4-devel15 --
 *
 * 20000320.1100: added ALL_MESSAGES_TIMESTAMP feature to slfprefs.h,
 *	user::Send.  (Implements a feature requested.)
 *
 *
 * -- 1.9.4-devel14 --
 *
 * (20000305.1215): Prep for virtualization: moved all getpw* calls for
 *	getting users from the passwd file into passwd.c
 *
 * 20000305.1145: !timer/!alarm now display the old timer being replaced when
 *	setting a new one.
 *
 * (20000304.1600): Preferences for slforum now in slfprefs.h, for easy
 *	inclusion into files that don't want any of the prototypes or classes.
 *	(e.g., slforumutil.c)
 *
 *
 * -- 1.9.4-devel13 --
 *
 * (20000229.0001): !msgchk now says "you have old mail waiting", not "you have
 *	no new mail", so we don't see the word 'new' when we in fact have just
 *	old mail.  Thanks Demaria for suggestion.
 *
 * 20000227.2000: Broadcast messages with hint bits set are no longer logged;
 *	they are usage hints for the current room occupants, useless to the
 *	reader of the log.
 *
 * 20000227.1930: Hourly chimes now have a hint message telling how to ignore
 *	them if you so desire.  (As with all other hint messages, this only
 *	shows up once for each user, and is not displayed after the first
 *	time.)
 *
 * (20000227.0200): !timer/!alarm now lists public timers too
 *
 * (20000226.1850): Public timers are now announced to room when set.
 *
 * 20000226.1300: High-bit chars now allowed.  Any highbit ctrl chars are
 *	tossed out, and any highbit whitespace chars are converted to ASCII 32.
 *	[ note that this still doesn't work right, 20000302 ]
 *	[ need to impl. a state machine to handle telnet option negotiation ]
 *
 * (20000225.1605): removed !banner, now just !spam does c_banner
 *
 * 20000225.1600: now exits if can't open requested log file during startup.
 *
 *
 * -- 1.9.4-devel12 --
 *
 * 20000219.0700: slforumroom::listusers now says how many users are here but
 *	not shown.
 *
 * (20000219.0045): slforumuser::usercmds table now has all possible params
 *	for c_zebra in {|} form, not just W? .
 *
 * 20002019.0020: Simplified c_[un]ignore and its bloated help message by
 *	taking out banter and pbeep (demaria idea)
 *
 * (20000219.0018): c_showaway now shows the header line, as it should.
 *
 * 20000218.2300: rewrote c_msgchk, it should work for everyone now, and
 *	now uses no external commands or files in /tmp  :-)
 *
 *
 * -- 1.9.4-devel11 --
 *
 * 20000217.0430: Added SIGHUP handler which closes/reopens the transcript log
 *	file, for use with the logrotate(8) utility.  Eventually this handler
 *	will also re-read the slforum global config file, when we have one.
 *
 * (20000217.0415): converted "slforum.cc" to "slforumutil.c": this is more
 *	descriptive, slforummain.cc is the startup code and it was confusing
 *	to have an slforum.cc as well.  Also, as of this writing, (C vs C++),
 *	slforumutil.o is 33264 bytes; slforum.o was 54536 bytes for same code.
 *
 * 20000217.0343: Added option for public timers.
 *	Current syntax: !timer <time> public [<message>];
 *	as we parse it now, public must go after time.  We can fix that. :-)
 *
 * (20000217.0340): default command tab-completion !<tab> now works at any
 *	position; previously worked only at start of buffer.
 *
 * (20000217.0325): fixed c_timer bug where you couldn't do !timer 0 to turn
 *	a timer off (it said "out of range" if secs<1, now fixed to be <0).
 *
 *
 * -- 1.9.4-devel10 --
 *
 * (20000211.1645): Doing !to d<tab>, when d<tab> returned multiple matches,
 *	would say "multiple matches" _and_ insert a tab.  Fixed; now just
 *	says "multiple matches".
 *
 * 20000209.1630: Can now ignore system messages, because moves, rolls and
 *	hourly chimes are system messages.  We now just don't let the user
 *	ignore system messages, but they can ignore messages with other flags
 *	besides just MSG_SYS and MSG_PUBLIC set.
 *
 * 20000208.1445: Just plain !timer shows the current timer; now it also
 *	shows the timer_message, if any.  Also will show previous timer if
 *	any.	[ IsTimerSet indicates current timer; timer_expire_hour==-1
 *		  means no previous timer, any other value means there was one]
 *
 * (20000208.0808): Prefs files in /var/lib/slforum no longer start with ".".
 *	Also, loading/saving prefs put 'em in log (had a debug msg).  Fixed.
 *
 *
 * -- 1.9.4-devel9 --
 *
 * (20000207.1215): Loading prefs: !set _ignoreFlags was accidentally scaling
 *	the value by 60, cut-n-paste bug.  Fixed.
 *
 * (20000207.1145): Forgot to call me->savePrefs() from c_ignore().  Fixed.
 *
 *
 * -- 1.9.4-devel8 --
 *
 * 20000206.2045: user prefs now saved to /var/lib/slforum if it's writeable,
 *	/tmp if not.  Also, ignoreflags now saved too.
 *
 * 20000206.0200: message "Shadowlands Forum is exiting." now has a timestamp.
 *
 * (20000206.0140): c_zebra now checks to see if we're not running a command
 *	(and thus not reading in from the prefs file) and thus shouldn't save
 *	the file back out.
 *
 * 20000206.0130: set default hereidle threshold to 20 mins, from 15.
 *
 * 20000206.0100: dschin: All prefs now load! 
 *
 * (20000206.0025): nonguest connecting from non-localhost didn't set state to
 *	STATE_FIND_DUPL after getting password; fixed.
 *
 * 20000206.0001: at midnight, now announces the new date as well
 *
 * 20000205.1830: made commands.html a little clearer about !ignore/!listen
 *
 * 20000204.0900: hourly chime in very idle room now goes out to the room,
 *	but isn't logged.  (Previously didn't go to the room either)
 *
 *
 * -- 1.9.4-devel7 --
 *
 * (20000201.1310): added user::idleTime(time_t) to save 30 calls to time()
 *	in loops where we sort by idle.
 *
 * 20000201.1250: we now try to schedule our SIGALRMs at the beginning of
 *	the minute.  Matt's idea, cool eh?
 *
 * 20000201.1245: nixed Dong! for now in hourly chime, pending discussion on
 *	whether it's too obtrusive, etc.
 *
 * (20000201.1230): made user::setupListenList, where username and gecos are
 *	added to the listen list.  The code was in two places to do this
 *	previously, making it seem like either place was a good place to add
 *	other things to do on login; AcceptAndWelcomeUser is where such things
 *	should go.  Moved loadPrefs() to AcceptAndWelcomeUser.
 *
 *
 * -- 1.9.4-devel6 --
 * 20000201.1225: re-added dschin announce "Shadowlands Forum is exiting"
 *	on SIGTERM catch, which was somehow not in 1.9.3 where it shoulda been.
 *
 * (20000201.1200): RE-MERGED IN 1.9.3 UPDATES FROM 1.9.2,
 *	plus Dan's persistent user prefs.
 *
 * 20000131.1430: changed "timer due to expire" to more cheerful "timer set for"
 *
 *
 * -- 1.9.4-devel5 --
 *
 * 20000131.1415: !timer now takes a time in minutes, or hh:mm absolute time.
 *
 * 20000131.1240: bug fix: !! was broken, fixed now. (expected 2 params, got 1)
 *
 *
 * -- 1.9.4-devel4 --
 *
 * (20000131.1200): constant TIMER_FROM_USERNAME instead of string "TIMER"
 *	scattered about code.
 *
 * (20000131.1130): user timers now use struct tm instead of strings;
 *	more efficient.
 *
 * 20000131.1110: removed "guest" assumption from the message "the guest
 *	x has timed out at _____"; normal users could do that too.
 *	Also changed the fake name "(logging in)" to "(asking name)".
 *
 * (20000131.1045): CheckHourChime() now uses struct tm instead of
 *	ctime() and string routines.
 *
 * 20000131.0945: added msgdesc bits MSG_HCHIME so hourly chime can be
 *	ignored by users.  Added to c_ignore.
 *
 * (20000131.0940): fixed LookForTimers() bug where pctime pointer was
 *	incremented inside a for-each-user conditional; if more than one
 *	user had a timer expire, this would have been incremented more
 *	than once.  We now have pctime+11 in a strncmp instead of
 *	pctime = pctime + 11 beforehand.
 *
 *
 * -- 1.9.4-devel3 --
 *
 * matted additions: (1.9.4-devel3 is matt's version)
 *
 * 20000129.1245: added hourly chime (room::CheckHourChime etc) - matted
 *
 * 20000126.1730: added c_timer - matted
 *
 *
 * -- 1.9.4-devel2 --
 *
 * (20000129.1630): made -devel2 tarball so Matt can merge 
 *      his cool new stuff
 *
 * 20000129.1140: HandleUserCommand parser now takes the initial ! off a
 *	cmdname parameter, if provided, to make !help <cmdname> user-friendlier
 *
 * 20000129.1040: Added '+' to argument spec for an slf command; the
 *	last argument can now be as many args of that type as the user wants.
 *
 * 20000129.1030: changed SLF_MAX_ARGC to 16, from 2.
 *
 * 20000129.1010: can now beep multiple users w/ c_beep
 *
 * 20000129.0930: c_listen now accepts any # of args to listen to words,
 *	and is much cleaner.
 *
 * (20000129.0515): changed comments in slforum.h, which is used by both
 *	C and C++ modules, to slash-star from slash-slash.
 *
 * (20000129.0445): resolved the atoi problem in parsing numeric params;
 *	this ended up being an egcs bug:
 ... hmm, numeric params don't seem to work.   See HandleUserCommand's parsing
    loop.  Well, they _do_ work, but only if a debugging printf calls atoi
    with what was _supposed_ to be parsed, it suddenly works.  Take out the
    printf, it doesn't work.
 - Resolved 20000129.0445: egcs bug.
	napalm /% rpm -q egcs
	egcs-1.1.2-12 has this.  -24 does not. (rh6.1 has -24, yay.)
	if this behavior crops up, define EGCS_ATOI_BUG_WORKAROUND
 *
 * (20000129.0400): added "const" to all methods not changing obj. state.
 *
 * 20000129.0200: cmdline parser in SLForumUser::HandleUserCommand now
 *	gives an error if an integer param was expected and something else
 *	was there instead: using strtol instead of atoi.
 *
 * (20000127.1150): bind() and accept() calls in  slforumuser and room: changed
 *	(sockaddr *) to the more correct (struct sockaddr *)
 *
 * (20000121.1100): wrote a proper comment for the cryptic bit in slforumroom::
 *	BindSocket that did the SO_REUSEADDR.
 *
 *
 * -- 1.9.4-devel1 --
 *
 * 200000117.1400: ALL_MESSAGES_BEEP define added to slforum.h
 *
 *
 * 
 *
 *
 *
 * -- 1.9.3 --
 *
 *
 * [Note: 1.9.3 was lost for a time in a disk crash, and not recovered
 *	til after 1.9.4 devel had begun (using 1.9.2 sources).  The
 *	changes shown below aren't merged into the main version til
 *	1.9.4-devel6. ]
 *
 * 19991116.0200: loadPrefs() and savePrefs() - persistent user prefs - dschin
 *
 * 19991115.1420: Fixed shadow password support.  Thanks to Dennis Owen
 *	Williamson for spotting this problem.
 *
 * 19991112.1325: mentioned in INSTALL where to set the flag to set up slforum
 *	for shadow password support
 *
 * 19991111.1840: max guests/remote logins; added empty_slots to SLForumRoom.
 *
 * (19991111.1830): added user::isUserConnected(), makes FindSlotForNewUser
 *	more encapsulated (no more checking for user->fd != -1)
 *
 * (19991111.1810): renamed room::LookForNewUsers to room::FindSlotForNewUser,
 *	more descriptive.
 *
 * (19991111.1740): rewrote the add portion of c_listen.  Much cleaner code,
 *	shorter, takes any # of args.
 *
 * (19991109.0114): finished going through and fixing ambiguities in ChangeLog.
 *	Insomnia cured, going to bed.
 *
 * 19991109.0050: Now announces "x has arrived" _after_ "y has accepted x",
 *	and privately tells x that y has done so after x has been
 *	AcceptAndWelcomeUser'd.
 *
 * 19991108.2245: !showaway now has a header line.  It looked weird
 *	without one.  (This _will_ be part of a version bump.)
 *	Added an optional bool parameter (with_header) to room::ListAways
 *	for this.
 *
 * (19991108.2220): Finished incomplete sentence at end of README. (oops)
 *	Fixed, re-tarred as 1.9.2.  (Not worth a version number bump.)
 *
 *
 * [Note: 1.9.3 was lost for a time in a disk crash, and not recovered
 *	til after 1.9.4-devel had begun (using 1.9.2 sources).  The
 *	changes shown above aren't merged into the main version til
 *	1.9.4-devel6. ]
 *
 *
 *
 *
 * 
 *
 *
 * -- 1.9.2 --
 *
 * 19991108.0105: c_zebra: added !set (retained !zebra), changed "escape"
 *	variable name to "command"
 *
 * (19991108.0055): fixed longstanding bug where typing !ignore blah
 *	only printed the first line of the usage/help message for c_ignore,
 *	instead of the whole thing.
 *
 * 19991108.0045: added !version command (suggestion by Matt);
 *	sends the VERSION_MESSAGE one-line version string, which I added
 *	for this purpose.
 *
 * 19991108.0030: c_listen: added check for argc==0 (oops), added check so
 *	guests can't make a listen list.  Also set a maximum size on the
 *	listen list of a user (LISTENLIST_MAXSIZE in slforum.h)
 *
 * 19991101.1540: fixed bug with ^Y on a ^K-buffer too long to fit onto the
 *	current input line; now truncates, puts what it can in the input buffer
 *	and doesn't send the line, so user can edit.
 *
 *
 * -- 1.9.1 --
 *
 * 19991031.0615: moved !roll to "checking stuff" in help summary to save
 *	a screen line on login.
 *
 * 19991031.0606: removed !local, now that we can do !zebra local {on/off}.
 *
 * 19991031.0530: !kick now warns the kickee in all cases the attempt fails
 *	(try by guest, or try to kick a non-guest) with a timestamp and a beep.
 *
 * (19991031.0525): Announcements about "guest requests entry" and "kicked" now
 *	have the MSG_MOVES msgdescbit, for users who don't really care and are
 *	ignoring such things.
 *
 * (19991031.0512): Added slforumroom::AnnounceTimestamp method
 *
 * (19991031.0400): Finally got around to adding setsockopt(SO_REUSEADDR)
 *	to get rid of that annoying "address in use, wait a few mins and try
 *	again, your eager users will have to wait, pleh." message. </past_rant>
 *
 * 19991031.0245: BEHAVIOR CHANGE in something long-established:
 *	After discussion w/ demaria and dschin, changed the default
 *	command character to '!' from '%' .
 *	(This would lead to much bitching for about four days, and then
 *	 everyone either loved it or used !zebra to set it to % for themself.)
 *	(This was in prep. for initial public release.)
 *
 * 19991031.0240: On login, only calls ListAways if ListUsers returns true,
 *	indicating some users are away.
 *
 * 19991031.0225: ^L now clears screen.  (Suggestion by Demaria)
 *
 * 19991031.0210: The %% command always was a shortcut for "%to all";
 *	it now accepts two of the current command character if that gets
 *	changed (Ex. '//'), instead of /% in this case.
 *
 * 19991031.0155: Can change the %here threshold, with %zebra hereidle <number>
 *
 * 19991031.0142: People not away, but more than 15 mins idle, no longer
 *	show up in %here.
 *
 * 19991031.0140: Lists both users and aways on login
 *
 * 19991031.0130: Made sure the who_sort_is_valid flag is set properly before
 *	listing the users/aways when user logs in.  (thanks Demaria)
 *
 *
 *
 * -- 1.9.0 --
 * ^
 * New features added, so I'm bumping the release number to 1.9.0-release:
 * Note also the release date.  Happy anniversary Draco!!!
 *
 * (19991030.0005): Fixed longstanding bug where "idle x days" wasn't lined up
 *	right; now, idle text is left-justified as it should be.
 *
 * 19991029.2345: BEHAVIOR CHANGE in something long-established:  The default
 *	%who now lists only users; %users shows users and away messages,
 *	and %showaway shows only away users and their messages.
 *	Changed return type of slforumroom::ListUsers and ListAways to bool;
 *	added HINT_SHOWAWAY; swapped names of c_who and c_users, and their
 *	descriptions in the big list of commands in slforumuser.cc.
 *
 * 19991029.2040: added %here command; can exclude away'd users from %who list
 *	(added idle_here_threshold to slforumuser) (thanks to Draco for sugg.)
 *
 * 19991029.2000: dschin: changed %listaway to %showaway (better tabcomplete)
 *
 *
 * -- 1.8.1-devel11 --
 *
 * 19991029.1445: incorporating dschin whoaway patch of 19991012.0100:
 *	dschin: implemented the split %who, but kept the legacy
 *      %who around... the new ones are (currently) called %users and 
 *	%listaway. We need to find a better name for %listaway because
 *	the tab completion currently conflists with %listen, so its not
 *	much help
 *
 * (19991028.1840): added slforumuser::cmd_char field, to specify the preferred
 *	character to escape commands.  Defaults to '%', of course.
 *
 * -- 1.8.1-devel10 --
 *
 * 19991027.2251: changed the messages in %kick so they look like system
 *	messages from FORUM:, as they should.
 *
 * (19991027.2250): fixed long-standing unnoticed, unabused bug where %kick
 *	w/ no args would deref a bad pointer and crash... thanks dschin
 *
 * -- 1.8.1-devel9 --
 *
 * (19991027.0048): in can't-kick message in slforumcmd:
 *	me->Send ("        -- Only guests can be kicked. --");     
 *	Changed to send, was uWrite.  Now erases prev cmdline as it should.
 *
 * 19991025.1430: added shadow password support
 *
 * (19991025.1400): fixed some ANSI C++ errors (previously warnings) so slforum
 *	compiles under gcc 2.95
 *
 * 19991021.1800: Tab-completion of usernames for commands will never complete
 *	to your name; this makes it easier to %to someone when you and she
 *	have usernames that start w/ the same letter. (suggestion: Demaria)
 *
 *
 * 
 *
 * -- 1.8.1-devel8 --
 *
 * 19991005.0850: cosmetic: switched the order of announcements
 *	"x has arrived" "y has accepted guest x" to the more logical way.
 *	(Later discovered this still wasn't working... fixed 19991109.0050)
 *
 * (19991003.0200): fixed a typo where HandleGetPw calls c_listen.
 *	an array subscript should've been 1, was 0, in the param array.
 *
 * (19991002.2050): fixed possible null deref in SLForumCmd::c_listen
 *
 * -- 1.8.1-devel7 --
 *
 * (19990927.1330): changed the way params are passed to funcs in slforumcmd.
 *	Now an argc and argv ("flargs") is used.  Also, slfparam is now a
 *	union type, not just a void pointer to be cast around freely.
 *
 * (19990924.2230): removed potential buffer overrun in c_banner
 *
 * -- 1.8.1-devel6 --
 *
 * (19990924.2055): changed strcats to strncats in slforumuser.cc
 *
 * (19990924.2045): added check for null param to top of c_rot13;
 *	this was a chat crasher.
 *
 * -- 1.8.1-devel5 --
 *
 * 19990924.0120: private beeps to someone are now heard, even if the recipient
 *	is ignoring beeps!  They can now %ignore privbeep or %ignore pbeep
 *	to ignore these beeps.  (suggestion: paras)
 *
 * 19990923.2105: tab completion won't try to complete if not a cmd.
 *
 * 19990923.2045: merged in (from dschin 19990922.1145):
 *	added %autowho and %autotopic.
 *	also made %roll take less screen lines, and made the Star Wars PRG
 *	rolling a #define, so it will roll normally, as expected.
 *
 *
 * -- 1.8.1-devel4 --
 *
 * (19990923.0011): VisuallyClearBuffer() now checks lpwrite result as it goes,
 *	prevents possible hang on userdiscon.  Also went through all of
 *	slforumuser.cc and added a check after every lpwrite call.
 *
 * 19990922.2330: guests can't call 'emselves "guest" anymore.
 *
 * 19990922.2100: lines/sec brake implemented.  checkMaxLinesBrake()
 *	is the crucial function.
 *
 *
 * -- 1.8.1-devel3 --
 *
 * 19990922.1445: added a \n to end of the usage messages for c_ignore;
 *	was previously cutting off the second line of this message when printed
 *
 * 19990920.1745: by default, guests cannot banner; added this feature.
 *	(Previously there was no check for this, and guests did gleefully
 *	 banner.)
 *
 *
 * -- 1.8.1-devel2 --
 *
 * (19990912.2315): ifdef'd out %topic, %comment in help msgs, if not compiled 
 *	in. (suggestion by Demaria)
 *
 * 19990907.1515: added automatic localhost-login authentication!
 *	No need to type username and password.  This only works in linux.
 *	Authlocal was decent to write, and fun to use.
 *
 * 19990827.1130: cosmetic: %topic/%comment now list date topic's set along
 *	w/ time.  ditto for %prevtopic.
 *
 *
 *
 *
 *
 * 19990816.0130: cosmetic bugs associated with topics without names fixed;
 *	other cosmetic improvements to prevtopic (now lists # comments for
 *	each, etc) and to away-messages as well: away messages now have more
 *	room.  When I fixed the comment format onscreen I also fixed the away-
 *	message format to be more roomy.
 *
 * (19990815.1830): comments for current topic are now kept in a linked list
 *	attached to the room.topic, just like for prev topics.  There is now
 *	one comment per user, not lost when the user logs out.
 *
 * (19990815.1645): user->comment wasn't being cleared in resetFieldsToDiscon.
 *	Fixed.
 *
 * 19990814.2145: added %prevtopic command.
 *
 * 19990814.1400: ^Y now appends the yankbuffer to current input line instead
 *	of overwriting it.
 *
 * (19990813.2215): prevtopics, and topic info (name, setter, time of set)
 *	moved into the TopicInfo data structure (defined in slforumroom.h)
 *
 * 19990811.1545: ctrl-k, ctrl-y yankbuffer added.  Thanks to Dan Chin
 *	for this idea.
 *
 *
 *
 *
 *
 *
 * (19990801.2230): back_one_tab was forgetting to replace the deleted
 *	char(s) with '\0'.  Fixed.
 *
 * 19990731.2245:  Possible to set a chatroom topic (with %topic) and
 *	have users comment on it (with %comment).  Leaving either argument
 *	blank will list the topic and all set comments.  Waiting time between
 *	topic resets is declared in slforum.h.  Resetting the topic resets
 *	all comments.  --matted
 *
 * 19990729.1200: dschin idea: backspace should go back one tab at a time,
 *	not one char at a time through tabs.  Added the back_one_tab
 *	function (from ManageInputBuffer) to implement this.
 *
 * 19990728.0100: pasted text containing tabs would be tab-expanded
 *	into a commandname or a username, which of course would fail,
 *	and give the user pasting it an error message _without_
 *	expanding the tab to spaces as it should.  Fixed.
 *
 *
 * -- 1.7.4 --
 *
 * (19990718.0040): %to all was causing crashes on cmdline-re-fill-in after
 *	word wrap; the fill-in routine forgot that -1 was a flag for "all"
 *	and tried to dereference it as an SLFChatUser* .  Thanks to Matted
 *	for finding and tickling this bug.
 *
 * (19990717.2305): fixed bug where a plain '%' while you're away would
 *	be said publicly, but wouldn't bring you back from being away.
 *	(in HandleGetLine)
 *
 * 19990717.2250: in FindCmdIndex, changed strcmp to strcasecmp;
 *	we now have case-insensitive command names, yay.
 *
 *
 * -- 1.7.3 --
 *
 * (19990706.2320): at end of HandleUserCommand, where it copies cmdline args
 *	onto a new wrapped line, it wasn't checking whether params were
 *	NULL or not, before deferencing them.  Fixed now.
 *
 * (19990706.2120): fixed a crock where... well, inside Send is where we check
 *	to see if we're ignoring what's being said.  If it's being ignored,
 *	we send the user a message saying "we heard the word blahfile" and
 *	no longer ignore it... but if they're listening for a word like
 *	'we' or 'heard' or 'the', it'll come back from being ignored there.
 *	Fixed to fix the ignoringbits flags _before_ sending that message,
 *	and also, we don't check MSG_SYS messages, we always print them.
 *	Thanks to jadaris for finding this bug.
 *
 * 19990706.1940: fixed a spot where the prompt wasn't 12 chars wide, causing
 *	long lines to wrap the last two or three characters to the next line.
 *
 *
 * -- 1.7.2 --
 *
 * (19990704.1530): fixed two places where we call room->GetUserByIndex()
 *	and then calls result->GetName() without checking that the result
 *	isn't null. (oops)  Checked all calls of that method, should be
 *	All Better Now.
 *
 * (19990704.1410): if command name didn't exist, it failed to erase the line,
 *	left the invalid command name there.  Fixed.
 *
 * (19990702.2300): fixed space-ctrlh... erm, we were sending the nonsense
 *	code space - \008 instead of space - \010 ; many thanks to gcc for NOT
 *	pointing out that 008 is not a valid octal number, and to me for being
 *	up so late to make such a mistake in the first place.
 *
 * (19990702.2015): added sked_alarm function; uniformly makes sure we don't
 *	unschedule an earlier SIGALRM for a later one.
 *
 * 19990702.1900: now sends a space-ctrlh to idle users every PING_INTERVAL_SEC
 *	seconds, so we know they haven't left, even if the room's idle.
 *
 *
 * -- 1.7.1 --
 *
 * (19990702.1430): input buffer length variable now rechecked after every
 *	command execution, unconditionally, because commands can change the
 *	content	of the buffer.  ^U now works properly again in all cases.
 *
 * 19990701.0050: Fixed rndcommand.  The list of rndcommands was
 *	missing a comma at the end of one line.  I added a comment above
 *	that list to remind folks to always put the comma in.
 *
 *
 *
 * -- 1.7.0 --
 * ^ So finally we have...
 *
 * 19990623.2335: ctrl and high-bit chars (under 32 or over 127, below 128+32)
 *	in lpcat are changed to spaces.
 *
 * 19990623.2330: no 1-letter words in listenListAdd
 *
 * 19990623.2000: added %printwho command to list who you're to-many-ing.
 *
 * 19990623.1830: talk to many now really _says_ " to many", and is
 *	padded out so everyone's talking in that whisper group has the same
 *	margin.
 *
 * (19990622.2050): set flag when we're running a command,
 *	and thus nobody should mess with our input line,
 *	we're busy messing with it ourself.
 *
 * 19990622.1950: Track the # unique people talking to, and properly
 *	set prompt.
 *
 * 19990617.1900: When someone leaves/discons, immediately tell other
 *	folks who are %to-ing them that they've left.  Renamed
 *	sendMessagesToNone to sendMessagesTofromNone.
 *
 * (19990617.1846): kicked out guest 'undocumen', and documented it by
 *	adding it to the ChangeLog, just in case.  ;)
 *
 * (19990617.1810): i_toalso now always returns the right result; before,
 *	it would ask to retain the "%to <user>" on the cmdline during a wrap,
 *	even if the whole command was "%to <user>" to change message target.
 *	Now, it clears the wrapped line if this is the case.
 *	Also, added ability of a usercmd to return RVAL_ALWAYS_CLEAR to clear
 *	the input line for this.
 *
 * (19990617.1710): fixed bug where if user disconnected during typing of
 *	a command, somehow HandleUserCommand got called anyway... this
 *	resulted in the -1 error value being lost.  Now, every return from
 *	HandleUserCommand always checks for user_fd==-1, and returns -1
 *	if this is the case.
 *
 *
 * -- 1.6.11 --
 *
 * 19990616.1500: a two-way private conversation no longer prints the
 *	entire <from> to <to>: attribution when the conversation switches
 *	to/from directions; instead, from <user>: or to <user>: will be
 *	printed.  This is to ensure that multiple conversations don't get
 *	confused; whenever you're talking with someone new, you will get
 *	the full <from> to <to>: attribution.
 *	This took two hours to do and debug thanks to Things The Compiler
 *	Assumed And Didn't Tell Me.  Ah well.
 *
 *
 * -- 1.6.10 --
 *
 * 19990615.?: commands will now not lose data or broadcast it!  We've wanted
 *	this for a while.  If a command executes because the user types 'til
 *	it runs out of line, it will find the last space (so as not to break
 *	a word), copy everything after that to a buffer, execute the command
 *	without that last word-fragment, then paste the fragment into the new
 *	blank line.  Also, commands can request that their arguments can be
 *	placed into the new line; for example, %to <user> <message> requests
 *	that its first param (<user>) goes on the line so what you type on
 *	the next line also is %to <user> !
 *
 * 19990615.1800: Disallow blank lines if they're not preceded by a line
 *	from the same person... this prevents some of the annoying spurious
 *	blank lines; blanks should be for whitespace among pasted code.
 *
 *
 * -- 1.6.9-2 --
 *
 * (19990615.?): edited all references to char arrays so they use
 *	the #define'd length of the array instead of number literals
 *	scattered through the code.
 *
 * 19990614.? : a line with a '%' by itself is now properly echoed to
 *	chat, not treated as an invalid command.
 *
 * -- 1.6.9 --
 *
 * 19990613.0400: trying out blank attrib lines in subsequent whispers from the
 *	same person, just like public chat.
 *
 * 19990612.2330: input line now lines up with lines above it instead of
 *	being left-justified.
 *
 *
 * -- 1.6.8 --
 *
 * 19990612.0055: ManageInputBuffer now expands tabs to spaces after
 *	non-alphanumeric chars; it still doesn't interfere with tab
 *	completion.  Before, it would only expand tabs after whitespace.
 *	Also now expands tabs by writing the spaces to user's terminal;
 *	before, it called RedisplayEntryLine() (which was much less efficient).
 *
 *
 * -- 1.6.7 --
 *
 * 19990607.1800: username, gecos info now placed in listen list on login.
 *
 * (19990607.1600): added Announce and Send methods that take msgdescflags.
 *
 * (19990607.0245): now un-aways if you type a whole line that wraps,
 *	which is after all semantically equivalent to if you type a shorter
 *	line and hit enter; either way, it goes to public chat and thus you
 *	should be un-away'd.
 *
 *
 * -- 1.6.6 --
 *
 * 19990606.0220: %ignore is now a bitfield, not a collection of boolean
 *	instance fields.  Yay.  Much easier to add new ignore types now.
 *	I added ignore-banners and ignore-rolls.
 *
 * 19990606.0130: added MAX_BLANK_LINES brake
 *
 * (19990606.0125): if you beep yourself, it doesn't print the message
 *	twice on your screen.  Thanks to Buffalo Mike for finding this one.
 *
 *
 * -- 1.6.5 --
 * ^ And the resulting file is version...
 *
 * (19990605.1700): all fopens replaced with slf_safe_fopen:
 *	won't follow symlinks, or open directories or block devs
 *	for reading or writing.
 *
 * (19990605.1645): added line to slforummain to ignore SIGPIPE;
 *	no need to crash if someone disconnects while we're writing a
 *	large buffer to their fd.
 *
 * (19990605.0130): fixed bug in cmdline parser that made it stop after
 *	the first param.
 *
 * (19990603.2340): c_beep now sends to all logins of the target user,
 *	not just the first one it finds.
 *
 * (19990529.1800): Auto cmd parsing!  Doesn't tab-complete intelligently yet.
 *	But it's now much easier to write new commands that take parameters.
 *	Also removed user::extractUserParam and extractStringParam
 *	hack/callback functions, which were there for cmds to manually
 *	do what auto cmd parsing now does.
 *
 *
 * -- 1.6.4 --
 *
 * ---- NAME CHANGE ---- Renamed everything from jdm___ to slf___
 *
 *
 * -- 1.6.3 --
 *
 * (19990527.2047) : disabled rndCommand() til it works right again,
 *	right now it segv's (see jdmchatuser::rndCommand for details)
 *
 * 19990522.1800: Solaris port.  ln -s Makefile-solaris-2-6 Makefile ; make
 *	to build it.
 *
 * 19990522.1515: now distinguishes between when someone leaves by %exit
 *	and when they've lost their connection. (thanks to Ro for suggestion)
 *
 * (19990522.0250): fixed segfault on exit (caused by double-freeing)
 *
 * (19990522.0230): fixed bug where you couldn't see your own public
 *	messages if you were ignoring public.
 *
 * (19990522.0200): fixed blank-lines-not-printed bug by just
 *	removing the code that exited HandleGetLine if the line
 *	was blank; it now stays in HandleGetLine, where it
 *	gets sent to all users with _sendOut .
 *
 * (19990522.0130): moved all version-specific messages to
 *	jdmchat.h, where they can be easily changed in one place.
 *	All specific info and configurable parameters should now
 *	reside in jdmchat.h .
 *
 * 19990522.0100: now sorts the %who list by idle time!
 *
 * (19990521.2330): lpcat now prints name of file and perror detail,
 *	if it can't open the file.
 *
 * (19990521.2330): failed lpcat of /etc/issue.forum and /etc/issue.net
 *	now ignored; this prevents chat from not accepting users if both
 *	of these files are missing or unreadable.)
 *
 *
 *
 *
 *
 * 990427.0100 dschin:
 *	When someone times out, it now prints the time.
 *
 * 990425.0100 dschin:
 *	now reads /etc/issue.forum for the logon banner, and falls back to
 *	/etc/issue.net
 *
 * 990417.0100 dschin:
 *	changed so that it tabs to the nearest columb mod TABWIDTH.
 *	This also eliminated the tab-complete bug, i think.
 *
 * 990416.1715 dschin:  tab expansion: if tab, and curpos-1 is a space or
 *	buffer[0], then insert spaces. useful for pasting code
 *
 * 19990406.2100: aak, STATE_GET_NAME rejected all non-isalpha() chars..
 *	this was too restrictive of the original author.  This is now
 *	broadened to all alphanumerics, plus '-' '_' and '.'
 *
 * 19990402.0000 dschin: only ignores whitespace for cmds. otherwise,
 *      pasted code is left-justified.
 *
 * 19990401.2300 dschin: ignores leading whitespace
 *
 * (19990401.0515): moved ChangeLog to separate file from jdmchatuser.cc
 *
 * 19990330.2200 dschin: %% is now %to all. (jdmusercmd.cc)
 * 
 *
 *
 *
 *
 * (19990224.2315) dschin: Prints from: after a call to c_help.
 *	Aesthetic bugfix.
 *
 * 19990222.2350: finally can ignore beeps.
 *	Since only sys messages beep, I added this to the 'branch'
 *	of send/uWrite/broadcast/etc that handles hitbitsets.
 *	(requested by gharial)
 *
 * 19990215.1900: When ignoring public chat, listen for specific words...
 *	un-ignore public when we hear them. (thanks to Mike for excellent
 *	suggestion)  I brought in linkedlist.[ch] for this.
 *
 * 19990215.0730: Implemented paras' suggestion: Don't print repeated
 *	username at left edge of each line, when a user sends several
 *	lines in a row.
 *
 * 19990212.0830: added %help and JDMChatUser::getHelpText(cmdname) (1.5.1)
 *
 * 19990211.0200: added %ignore public and %ignore guest...
 *	i really refuse to ignore specific people who are fellow users, that's
 *	something really juvenile.
 *
 * 19990209.2345: can now use %time or %date (tho only %time is in help menu)
 *
 * 19990206.1215: can now use %quit, %exit or %bye
 *	(only %exit and %quit are listed in help menu)
 *
 * 19990206.0300: %away now displays a line with time of %away.
 *
 * (19990201.1400) FindSlotForNewUser() now prints a "room full" message
 *	when the room is full and someone tries to log in; also, fixed the
 *	'ASSERT: ... discon but fd != -1' message bug; now it complains _and_
 *	sets fields to discon like it's s'posed to.
 *
 *
 *
 *
 *
 * 19990126.2100: finally modularized command handling!  Thought of getting
 *	around to this while shoveling, thurs night of week before last...
 *	now we have modular, more efficient command handling,
 *	_and_ tab completion for command names.
 *
 * 19990124.0110: dschin: Dice rolling with %roll;
 *	also, GUESTS_CANNOT_ROLL optional #define in jdmchat.h
 *
 * (19990113.1440) change sprintf to snprintf in makeAwayMessage
 *
 * 19990113.1412: added to_bits, from_bits bitfields to support %to-multiple;
 *	added methods getUserByIndex and sendToByIndex to JDMChatRoom.
 *
 *
 *
 *
 *
 *
 * (981219.0605): since substate is now time_t and not int, GetUserIncremental
 *	requires an int &, created a temp called usrnum.
 *
 * 981219.0600: tab now lists multiple matches if they exist; ^D now
 *	logs the user out if typed twice quickly (less than 2 sec apart).
 *	(reqested by Rowan)
 *
 *
 *
 *
 * 981207.0015: partial-user matching and completion (tab, ^D) support.
 *
 *
 *
 *
 *
 * 981108.1600: no more beep when going away (now consistent with leaving).
 *
 *
 *
 *
 * (981008.1950): if just '%' or '%help', won't say "no such command",
 *	just lists valid ones.	(thanks Rowan)
 *
 * (981006.1350): optionally keep substate across state transitions
 *
 * 981005.1930: un-%away only on <cr> on non-cmd when not in %to mode
 *
 * 981005.1025: added enforced wait on incorrect logins
 *	(added waittil field, checks in ManageUser(), sets in HandleGetPw() )
 *	As of 981008.1950, this _still_ doesn't work quite right...
 *
 * (981005.1015): better data encapsulation for changes of state;
 *	added setState(), prevstate.
 *
 * 981005.0955: added timestamp to login, logout announces.
 *	Uses the ctstr field (ret. by loginTimeStr()) to hold
 *	logout time in hh:mm form.
 *
 *
 *
 *
 *
 * (980914.0850): fixed: check for WasUserAccepted() before printing
 *	"has left"... before, you could log in, and just not type anything
 *	at the password field and let it time out, and it said to the room that
 *	you'd left, without ever having said you were there.
 *
 *	Used prevstate field of user object to store previous state when
 *	we go to STATE_NO_CONNECTION.  Added public WasUserAccepted()
 *	to return this info.
 *
 * (980914.0840): fixed: now prints hostname not host ip when possible
 *
 * 980911.2300: added optional guest-howto-message on login (for jpritch!)
 *	Define GUEST_HOWTO_MESSAGE to print it.
 *
 * 980910.0930: added ^W support to ManageInputBuffer
 *
 * 980903.2200: removed %beep due to awkward implementation, due to hardcoded
 *	^G's in strings.  Added SIGINT handler (which == the SIGTERM handler)
 *
 * (980903.1230): when init is complete, jdmchat now does chdir("/") to ensure
 *	we're not keeping any files/dirs/filesystems open we don't need...
 *	this is recommended for daemons and long-running processes.
 *
 * 980903.1200: guest timeout is announced to room.
 *
 * 980830.2000: %time command; also, kick-idle-self now announces to the room.
 *
 * 980809.1120: per user, can disable the beeps!
 *
 * 980809.1020: find and kick duplicate logins of yourself on login.
 *
 * 980809.0900: added SIGTERM handler that closes sockets up,
 *	and writes log file logout entries, before exiting.
 *
 *
 *
 *
 *
 * 980710.1530: now, only guests can be kicked;
 *	this fixed the can-kick-self race condition as well.
 *
 * (980709.1715): fixed linewrap-in-input bug for long prompts, and
 *	encapsulated setprompt
 *
 * 980709.1700: added hint bits
 * ( and encapsulated lpwrite(user_fd,msg) into uWrite(msg)
 *   and uWrite(msg, hintbits) )
 *
 * 980703.2345: added guest support
 *
 * (980703 release here, before guest support)
 *	Also added rndCommand(), resetFieldsToDiscon(),
 *	remember login/idle time; add room::logprintf(),
 *	added -nofork, prints out child pid on fork, away message usernames
 *	line up (%s -> %9s), room::getuserbyname, lpwrite(fd,buf) variant.
 *
 * 980702.1100: %who is multiple lines, include login/idle times and IP
 *
 * 980701.1500: added specify-recipient
 *   Note:
 *	Currently, if the target of private messages logs off,
 *	the sender of these messages will still send there
 *	for the next message (i.e., the discon check is in
 *	_sendOut)... better would be to set to broadcast when
 *	the person-has-left notification goes out.
 *
 *
 *
 * 980620: this release includes:
 *	modularized c++ classes to files (jdkchatuser.cc, jdkchatroom.cc)
 *	added %msgchk command (system /usr/bin/mh/msgchk, read the output)
 *	remember to set is_away=0 on disconnect
 *	prompt fix: "napalm login:" -> "login:"
 *	user::ManageInputBuffer(void) now returns ManageInputBuffer(0)
 *
 *
 * 980529: this release includes:
 *	strip slf binary in Makefile
 *      wtmp logging
 *      added %away, %clear
 *      translate to \r\n correctly in lpcat (for /etc/issue)
 *      announce arrived-from IP/dns
 *      welcome message after login, not before
 *      list users at login
 *      helpful: write command list if no matching cmd
 *
 *
 * 980524.1800: added word wrap on long lines
 *
 * 980524.1630: added username/password authentication
 * 	. added /etc/issue.net pretty login message
 *
 * 980524.1500: added useful stuff to ManageInputBuffer:
 *	. moved strlen() from inside printf() to a static int.
 *	. added ^U support
 *
 * -- down here is The Beginning of Development, from jdkchat 1.3 --
 * -- on 24 may 1998.  Twas such a short, simple program...  -jer --
 */
