EPIC5-2.2

*** News 03/27/2021 -- EPIC5-2.1.7 (2011 - Cinereous) released here

*** News 03/21/2022 -- New built in function $rgb()
	There are three ways to call the $rgb() function:
	   1. As three numbers
		$rgb(255 0 255)
	   2. As a string
		$rgb(#FF00FF)
	   3. As kwargs
		$rgb({"r":255, "g":0, "b":255, "attr":true})

	This will return a string that will change to the indicated color.
	(ie, it is of the form ^Xab, where "ab" are two hex digits)
	The kwarg version is the only way to prevent prefixing with ^X
	(ie, to get the color number).   The 'attr' flag is optional.

*** News 03/06/2022 -- New serverctl(DONT_CONNECT), sets the -s CLI
	The -s command line option ("dont connect to a server") can now
	be set by your ~/.epicrc with 
		@serverctl(DONT_CONNECT 1)
	Obviously this only matters at client startup.  Setting it at
	any other time is pointless

*** News 03/06/2022 -- New math operator: "??" -- Coalesce
	The coalesce operator is a binary operator that returns the left
	value if the left value is true-y, otherwise returns the right
	value.  Therefore, "x ?? y" is shorthand for "x ? x : y"
	The operator precedence is the same as "||".

*** News 03/06/2022 -- New /set BROKEN_AIXTERM
	Some terminal emulators are silly and don't/can't/won't support
	bold and color at the same time, instead insisting that you send
	proprietary/non-standard ansi codes that were pioneered by a
	vendor that also couldn't get its terminal emulator to properly
	emulate real terminals.

	If you are using such an emulator, you can /set broken_aixterm
	and bold colors will send aixterm codes instead of standard codes.

*** News 02/06/2022 -- What is $serverctl(GET x OPEN)?
	Zlonix asked me to document "what does OPEN mean for a server?"

	A server is "open" when it has a file descriptor open.  
	This is entirely different from whether it is connected to IRC.
	(for that, use $serverctl(GET x CONNECTED))

	When a server is "open" then it is under the active management
	of the client.  When a server is "closed" then the client has 
	stopped paying attention to it and nothing further will happen
	with it until the user (or script) does something.

	During the course of a connection, several *different*
	file descriptors get used by a server as it goes through the
	server states:

	Server State	Is "Open"?	What is fd used for?
	-------------	-------------	----------------------------
	CREATED		No
	RECONNECT	No
	DNS		Yes*		DNS helper subprocess
	CONNECTING	Yes*		socket that is not yet connect()ed
	SSL_CONNECTING	Yes*		connected socket not yet ssl'd
	REGISTERING	Yes		socket that is trying to get on irc
	SYNCING		Yes		socket that is on irc
	ACTIVE		Yes		socket that is on irc
	EOF		Yes*		socket that has seen an end-of-file
	ERROR		Yes*		socket that has fatal error
	CLOSING		Yes*		socket that is shutting down
	CLOSED		No		
	DELETED		No		

	* - Just because a server is "open" does not mean that it is useful
	    for IRC purposes.  It only means that the fd has not yet been
	    closed at the OS level.  These states still have an 'fd that 
	    has not been close(2)d', but don't represent useful states

*** News 02/05/2022 -- New $serverctl(GET x NEXT_SERVER_IN_GROUP)
	This will return the server that /server + will connect to

*** News 11/11/2021 -- $json_implode() takes kwargs, adds "compact mode"
	The standard behavior of $json_implode() is to take a single word 
	as an argument, the root of a assign tree to convert into a json 
	object.
		$json_implode(q)	# Collapse $q.* into json object

	The standard behavior of $json_implode() is to return a "human-
	formatted" string, with newlines and indentation.  This is nice 
	for looking at, but isn't appropriate for every situation.

	So $json_implode() is our pilot test for json object argument lists.
	It now supports the following two arguments:
		root	  string    The root of the assign tree (required)
		compact	  boolean   false - return human readable (default)
				    true - return one line

	Example:
		@ q.one = [val1]
		@ q.two = [val2]
	then,
		$json_implode({"root": "q", "compact": true})
	would return
		{"one":"val1","two","val2"}

	
*** News 11/18/2021 -- New concept -- json object as argument list ("kwargs")
	You'll start noticing something new happening more and more.
	The idea of "json object as an argument list" is being introduced,
	to allow passing of parameters in a more deterministic way.

	JSON objects (also known as "dicts") are a collection of key-value pairs.
		{ "field1", "val1", "field2", "val2"}
	You already operate on these with $json_implode() and $json_explode().
	Most RESTful APIs in the world send and receive them.  

	For backwards compatability reasons, of course, this feature will be
	rolled out on a case-by-case basis whenever it seems appropriate.
	But, occasionally, a new feature might be available only through json
	object arguments because it makes sense.

*** News 10/06/2021 -- EPIC5-2.1.6 (1981 - Impignorate) released Here

*** News 09/21/2021 -- Another round of clang static analysis
	Somewhere around here we did another round of static analysis
	with clang's analyzer, and fixed whatever it recommended.

*** News 09/19/2021 -- "reconnect" script has been reimplemented
	The reconnect script has been renamed to "reconnect.orig".
	If you want the original behavior, just /load reconnect.orig
	The new script is based on improvements we've made in epic5
	to make reconnection logic more reliable and dependable.

*** News 09/11/2021 -- New option,  $serverctl(GET x PADDR)
	The $serverctl(GET x PADDR) returns the server's presentation
	address.  This is "1.2.3.4" for ipv4, or "2600::1" for ipv6.
	This represents the IP address we're connected to.

*** News 09/11/2021 -- New /window operation, /WINDOW CLEARREGEX <regex>
	This was requested by Zlonix.

	The /WINDOW CLEARREGEX <regex> operation removes all items from
	the window's lastlog whose text (what you see on the screen) 
	matches the <regex>.  Removing them from the lastlog removes
	them from the scrollback and your screen as well.  This is useful
	for making conversations with annoying bots go away retroactively.
	Example:	/window clearregex annoybot

*** News 09/11/2021 -- New /ON, /ON RECONNECT_REQUIRED 
	The /ON RECONNECT_REQUIRED hook is thrown by the client when it
	feels that a reconnection intervention is appropriate.  
	We are going to start this small, and build in more use cases
	as we go forward.

	  1. When server is in ACTIVE state and the socket dies
	  2. When a write to the server fails

	In these situations, your script should take whatever measures
	are necessary to save the state of windows, channels, etc,
	in preparation for the upcoming disconnection.

	This /ON is thrown while the server is in a state of chaos.
	The internal state of the system is wrong, and you must assume
	that the connection to the server has already been lost.  

	YOU MUST _*_*_NOT_*_*_ try to do anything clever in this /on.
	If you have this idea of moving windows or servers or channels,
	please don't!  I recommend setting up /timer's and /defer's so
	you can do those sorts of changes away from the blast radius.

	YOU MUST _*_*_NEVER_*_*_ attempt to do any direct intervention
	in this /on -- instead, you should save information and create 
	a timer to deal with the problem later.  YOU HAVE BEEN WARNED.

	/ON RECONNECT_REQUIRED currently provides this information
		$0 	The server that unexpected failed on us.
			Reconnection will be required.  Remember,
			you cannot do reconnection in the /on, you
			have to schedule it to happen "later"

*** News 09/08/2021 -- New /window operation, /WINDOW CLEARLEVEL [levels]
	This was requested by Zlonix.

	The /WINDOW CLEARLEVEL [levels] operation removes all items from
	the window's lastlog of the levels you specify.  Removing them
	from your lastlog removes them from your screen as well.  This is
	useful for making noise go away retroactively
	Example:	/window clearlevel joins,parts,quits,kicks

*** News 09/08/2021 -- New statement type: block-with-arglist
	The ircII syntax now supports a new statement type, which I'm 
	calling a "block with arglist"

		(arglist) {block}

	You could also think of this as an "inline anonymous function".
	For the purposes of the statement, $* is modified by (arglist)
	and then {block} is run.

	Please note there are several caveats to this:
	  1. Arglist is not magic, it is syntactic sugar.  So it creates real 
	     local variables, and those local variables have their ordinary 
	     scope.  So they will persist after the end of the statement.
	  2. The statement only modifies $* during the statement itself.
	     So after {block} is run, $* goes back to what it was originally.
	  3. Note that this is a *statement* and not a *block* so if you are
	     working with something that expects a block, wrap it in {}s to
	     create a block.
		if (# == 3) {(arg0, arg1, arg2) {... code ...}}
	  4. Arglist processing isn't "free" so doing it in a tight loop will
	     be slower than doing it outside of the loop

*** News 09/07/2021 -- Pass window refnum in /ON CHANNEL_LOST
	The /ON CHANNEL_LOST hook now provides the window that a channel
	was in as $2
		$0 - The server refnum of a channel
		$1 - The name of a channel
		$2 - The window refnum of a channel

*** News 09/06/2021 -- Functions for JSON document handling
	Some time ago some new functions appeared for handling
	JSON documents, but they were not documented.  So now
	I am going to document them!

	CONVERTING JSON DOCS TO /ASSIGNS
	--------------------------------
	Syntax:    $json_explode(varbase json-document)

	An example is worth a thousand words:

	    $json_explode(e {"one": 1, "two": { "sub1", "hi", "sub2", "bye" })
	will result in three new assigns
		$e[one]		-> 1
		$e[two][sub1]	-> hi
		$e[two][sub2]	-> bye

	CONVERTING ASSIGNS TO JSON DOCS
	-------------------------------
	Syntax:	   $json_implode(varbase)

	This converts everything under $varbase[*] into a JSON doc.

	HANDLING ERRORS
	--------------
	If there is an error, $json_error() will tell you about it.

*** News 09/06/2021 -- SSL handling improvements (take 2)
	The other day I posted some info on how the SSL handling has been 
	improved.  But then things got revamped again, so I delete the old 
	info and am replacing it with this info.

	1) Step one - You connect to an SSL server
	 You connect to an irc server doing something like
		/SERVER irc.example.com:6697:type=irc-ssl
	 This goes through connect()ing to the server, and then doing an 
	 SSL_connect() to set up the certificate exchange and TLS negotiation.

	2) Step two - The SSL handshake is completed
	 After the SSL_connect() step has completed, we now have a fully 
	 functioning TLS socket with an SSL certificate.  Before we use the 
	 TLS socket, we're supposed to verify we trust the SSL certificate, 
	 to ensure we're talking to who we think we are.

	3) Step three - The client watches the certificate verification
	 OpenSSL "verifies" the certificate and the client provides
	 a C function to tag along for the ride.  The callback function
	 is called every time:
	   (1) An error is discovered, or
	   (2) There are no (further) errors in a certificate.
	 Thus, if a certificate is trusted, it will only report 
	 "no problems" for each link in the chain.

	 This permits the client to trap and categorize every error that
	 happens - some certificates have multiple problems!  There are
	 three buckets the client uses:
		(1) Self-signed certificates
		(2) Incorrect-hostname certificates
		(3) Any other (serious) error
	 The client tracks the "most serious error" (if there is one),
	 using the above priorities.

	4) Step four - The cliet offers you /ON SSL_SERVER_CERT
	  The client sets $serverctl(SET <refnum> SSL_ACCEPT_CERT -1)
	  and then throws /ON SSL_SERVER_CERT.   The use of -1 is on
	  purpose so the client can determine whether your /ON handler
	  sets it to 0 or 1.  

	  If your handler does a $serverctl(SET <retval> SSL_ACCEPT_CERT 0|1)
	  then that is taken as the final disposition of the handling, and 
	  nothing further occurs. (ie, it skips the rest of the steps)

	  Parameters of /ON SSL_SERVER_CERT
		$0  The fd of the socket
		    (Use $serverctl(FROM_SERVER) to get the server refnum)
		$1  Certificate Subject, url-encoded
		$2  Certificate Issuer, url-encoded
		$3  Bits used in the public key 
		$4  OpenSSL error code of the "most serious error"
			(18 is "Self-signed certificate",
			 62 is "Hostname mismatch",
			 everything else is irregular/bad)
		$5  The SSL regime being used (ie, TLSv1.2)
		$6  The Certificate Hash
		$7  Was there a hostname mismatch?  0 = no error, 1 = error
		$8  Was there a self-signed error?  0 = no error, 1 = error
		$9  Was there another (serious) error?  
			0 = no other error 1 = other error
		$10 Was there any error of any kind?  
			0 = no errors of any kind, 1 = some kind of error

	5) Step five - The client makes a provisional decision
	  Next, the client looks at the errors and decides whether
	  it thinks the cert is ok.  
	    * Cert has no errors 		   -> ACCEPT
	    * Cert has "self signed" or "wrong hostname" error
	      and /SET ACCEPT_INVALID_SSL_CERT ON  -> ACCEPT
	    * Cert has "self signed" or "wrong hostname" error
	      and /SET ACCEPT_INVALID_SSL_CERT OFF -> REJECT
	    * Cert has any serious error	   -> REJECT
	  The client sets this provisional value with 
		$serverctl(SET <refnum> SSL_ACCEPT_CERT 0|1)

	6) Step six - The client offers you /ON SERVER_SSL_EVAL
	  Then, the client hooks /ON SERVER_SSL_EVAL.  At this point,
	  all of the information your script needs to make a fully 
	  informed decision to accept or overrule the client's choice
	  is available.  Your handler is not obligated to make any
	  change, but it certainly can if it wants to 

	  Parameters of /ON SERVER_SSL_EVAL
		$0  The server refnum
		$1  The "ourname" of the server (what you /server'd to)
		$2  Was there any error at all? 
			0 = no errors of any kind   1 = some kind of error
		$3  Was there a hostname mismatch?  0 = no error, 1 = error
		$4  Was there a self-signed error?  0 = no error, 1 = error
		$5  Was there another (serious) error?
			0 = no other error, 1 = other error
		$6  What does the client suggest?
			0 = reject certificate, 1 = accept certificate

	  Using $serverctl() to get info about the certificate
	  Use $serverctl(GET <refnum> <item>) where <item> is:
		SSL_CIPHER		The encryption cipher being used
		SSL_PEM			The certificate (in PEM format)
		SSL_CERT_HASH		The certificate's hash
		SSL_PKEY_BITS		The bits in the public key
		SSL_SUBJECT		Who the cert was issued to
		SSL_SUBJECT_URL		Who the cert was issued to (url-encoded)
		SSL_ISSUER		Who issued the cert
		SSL_ISSUER_URL		Who issued the cert (url-encoded)
		SSL_VERSION		What version of SSL being used (ie, TLSv1.2)
		SSL_SANS		Subject Alternate Names in the cert
		SSL_CHECKHOST_ERROR	Hostname Mismatch error - 0 (no) 1 (yes)
		SSL_SELF_SIGNED_ERROR	Self-signed error - 0 (no) 1 (yes)
		SSL_OTHER_ERROR	        Any other (serious) error - 0 (no) 1 (yes)
		SSL_MOST_SERIOUS_ERROR	The OpenSSL error code of the most serious error
					18 (self-signed) and 62 (hostname mismatch)
					are considered non-serious (routine) errors
		SSL_VERIFY_ERROR	Any error at all - 0 (no) 1 (yes)
		SSL_ACCEPT_CERT		Is this cert headed for acceptance?  0 (no) 1 (yes)

	   Use $serverctl(SET <refnum> SSL_ACCEPT_CERT 0) to reject the cert
	   Use $serverctl(SET <refnum> SSL_ACCEPT_CERT 1) to accept the cert
	   If you don't do anything, the client will do the most reasonable thing

	7) Step seven - The client moves forward
	  Finally, everyone has had a chance to weigh in.  
	  Whatever the value of $serverctl(GET <refnum> SSL_ACCEPT_CERT) 
	  is after all this, is used to accept or reject the SSL connection.

*** News 09/02/2021 -- Configuring SSL Ciphers
	Now, if you know what you are doing, you can set
	the SSL Ciphersuites that the client will use for
	SSL connections, via
		/SET SSL_CIPHERS <stuff>
	If you don't know what you're doing, don't touch.
	The default value is "unset", which means we let
	openssl choose the ciphers for us.

*** News 09/02/2021 -- SSL Handling improvements
	[replaced -- see above]

*** News 08/30/2021 -- New server description field "ssl-strict"
	[this feature was removed]

*** News 05/29/2021 -- EPIC5-2.1.5 released here (Fecund) (Commit id: 1945)

*** News 05/25/2021 -- Updated configure to autoconf-2.69
	We upgraded configure from autoconf-2.13 to 2.69 here.
	Along the way, we fixed the support for python3.8+

*** News 05/20/2021 -- Windows have UUIDs ($windowctl(GET x UUID))
	Every window now receives an immutable UUID when it is 
	created.  This UUID is globally unique and cannot be changed.

	Although the UUID is not user-facing (as in /window list),
	you can get it with $windowctl(GET refnum UUID).

	The UUID is an lval (that is, it does not contain hyphens),
	so you can use it as part of a variable name if you wish.

*** News 05/20/2021 -- New concept, "claiming channels"
	When EPIC receives a protocol JOIN message for a channel, 
	it has to decide what window to put the channel in.  
	A common request has been the opportunity to let scripts 
	decide where new channels should go, rather than it being 
	hardcoded.

	So now when a JOIN is received, an /ON will be thrown 
	(see below) which is an invitiation for your script to do
	whatever preparatory work for the channel you see fit.

	One thing in particular is /WINDOW CLAIM (see below), which
	tells EPIC which window the channel should be put into.
	As part of this process, EPIC will suggest a window the 
	channel should go into, unless you choose to overrule that.

	*** NONE OF THIS APPLIES TO /JOIN or /WINDOW CHANNEL
	    when the user is deliberately moving a channel they are
	    already on between windows.  You can't stop that.

*** News 05/20/2021 -- New /ON, /ON CHANNEL_CLAIM 
	The /ON CHANNEL_CLAIM is thrown when a JOIN is received,
	but before the client has assigned the channel to a window.
		$0 - The server refnum 
		$1 - The channel being joined
		$2 - The window refnum epic proposes to put the
		     window into.

	If your handler does /WINDOW CLAIM in any particular window,
	then the channel will go to that window that you specify.

	At this time, you can only do /WINDOW CLAIM in a window that
	is connected to the server in $0. In the future, this will
	probably change.  But for now, a /WINDOW BIND in a "window
	connected to the wrong server" is treated as invalid.

	If you do not do a valid /WINDOW CLAIM, then the channel will
	go into the window proposed by EPIC.

*** News 05/20/2021 -- New /WINDOW operation. /WINDOW CLAIM #channel
	During the handling of an /ON CHANNEL_CLAIM, you may perform
	the /WINDOW CLAIM operation to direct EPIC to put the new
	channel into a particular window.

	You must pass the name of the channel as a paraemter.
	It is available as $1 in the /on.

	You may only claim the channel in a window that is connected
	to the correct server (from $0).  Attempting to claim a 
	channel in a window connected to the wrong server is invalid
	and has no effect.   This will change in the future.

*** News 05/20/2021 -- $uuid4() can now return lvals (NODASHES)
	You can now get a uuid4 that is valid as an lval if you
	supply NODASHES as the only argument
		@ a.$uuid4(NODASHES) = [whatever]

	ALL ARGUMENTS TO THIS FUNCTION ARE RESERVED FOR FUTURE EXPANSION.
	There are now two defined behaviors:
		$uuid4()	 - UUID4 with dashes
		$uuid4(NODASHES) - UUID4 without dashes
	EVERYTHING ELSE IS UNDEFINED BEHAVIOR (ie, other arguments may 
	do something today, but forwards compatability is not guaranteed)

*** News 03/26/2021 -- EPIC5-2.1.4 released here (Redound) (Commit id: 1927)

*** News 02/13/2021 -- /UNLOAD now supports /TIMERs
	If you create a /TIMER in a script you /LOAD with /PACKAGE
	the timer will be tagged just like any aliases or assigns
	or ons or whatever.

	Note that /TIMERs are _not_ tagged if they are created 
	after /load time.  This includes but is not limited to 
	timers created by aliases that are tagged; as well as
	timers that create new versions of themselves (but it 
	will catch timers that run forever)

*** News 02/10/2021 -- New /WINDOW operation, /WINDOW UNCLEAR
	There was already an /UNCLEAR command, and a /CLEAR and
	/WINDOW CLEAR command, but there was no /WINDOW UNCLEAR.
	WHy not? Anyways...

*** News 02/07/2021 -- Low level operations on cutbuffer - $inputctl()
	Harzilein asked if there was a way to manipulate the cutbuffer
	without having to put something in the input line.  As it happens,
	that has never been requested before.  So here we go!

	$inputctl(GET cutbuffer)
		This returns the cut buffer.  This is the same as $U

	$inputctl(SET cutbuffer ... new value ...)
		This sets the cut buffer.  This would be effectively
		the same as:
		 * Saving the input line (with $L)
		 * Erasing the input line (parsekey ERASE_LINE)
		 * /TYPEing what you want into the cut buffer
		 * Erasing the input line (to put it into the cut buffer)
		 * /TYPEing the origial input line
		But this doesn't require you to disrupt the input line.

		Please remember that there is only one cut buffer,
		and a large number of operations replace it -- so 
		whatever you put in the cut buffer, use it quickly,
		or the user might clobber it.

*** News 02/05/2021 -- /ON SERVER_STATUS changed to /ON SERVER_STATE
	Some expressed some confusion about whather "SERVER STATUS"
	and "SERVER STATE" were the same thing, and what the states
	were and what they meant.  To reduce this confusion, there
	will be only one term, "SERVER STATE". However, much code
	already uses "SERVER STATUS".  So we have to support both.

	For now, /ON SERVER_STATUS and /ON SERVER_STATE will both 
	exist side by side.   However, I recommend you use 
	/ON SERVER_STATE for new code, and think about migrating
	your old code.   There will come a day when /ON SERVER_STATUS
	will beoome an alias for /ON SERVER_STATE.

	To be unambiguous, using /ON SERVER_STATUS will never break.
	But you should know the official name is going to be 
	SERVER_STATE.

	The stock scripts have been updated.  You can get the changes
	by making sure to do a 'make install'

*** News 02/05/2021 -- $serverctl(GET x STATUS) changed to STATE
	As per the above, both $serverctl(GET x STATUS) and 
	$serverctl(GET x STATE) will return the server's state.
	However, you are encouraged to start using "STATE", since
	that is now the official term for it.

	The stock scripts have been updated.  You can get the changes
	by making sure to do a 'make install'

*** News 07/03/2020 -- New /WINDOW operation, /WINDOW DELETE_KILL
	Harzilein pointed out:
	  1) You cannot delete the last window on a screen
	  2) Deleting a screen does not kill a window
	  3) Therefore, deleting a screen necessarily orphans a window
	But what if you don't want to orphan a window when you kill a
	screeN?  

	The /WINDOW DELETE_KILL operation does a /WINDOW DELETE and
	then does a /WINDOW KILL on the window that was the current
	window.  There are several caveats to this *which i reserve
	the right to change in the future*
	
	Caveat 1) Only the "current window" gets killed.  So if you 
	    DELETE_KILL a screen with multiple windows, other windows
	    will be orphaned in the ordinary way.  I reserve the right
 	    to change this behavior (it will be documented)
	Caveat 2) If you cannot kill the window for other reasons, 
	    such as /window killable off, then the attempt to kill the
	    window will fail, and it will be orphaned.

*** News 05/11/2020 -- EPIC5-2.1.2 released here (Lugubrious) (Commit id: 1908)

*** News 05/09/2020 -- New built in function $execctl()
	You can now program the /EXEC command with this low level function

	--- warning ---
	Many of the things you can set here are not sanity checked.
	If you feed it garbage in, you will get garbage out.
	If you need safety rails, use the /EXEC command.
	--- warning ---

	Usage:
	------
	$execctl(REFNUMS)
		Get all refnums in the entire system (as integers)
	$execctl(REFNUM <description>)
		Convert a description (like %3 or %myproc) into a refnum integer

	$execctl(NEW <commands>)
		Create a new /exec process (does not run it!)
	$execctl(LAUNCH <refnum>)
		Run an /exec process that hasn't been started yet
	$execctl(CLOSEIN <refnum>)
		Close the STDIN to the process (this means you can't send any
		more data to the program.  This is useful for programs
		that wait until they've got an EOF from stdin to do their 
		thing)
	$execctl(CLOSEOUT <refnum>)
		Close the STDOUT and STDERR from the process (this means 
		we won't receive any more output from the program.  This is
		useful if we don't want any more output from the program.
		Many programs will die from SIGPIPE if stdout is closed)
	$execctl(SIGNAL <signal> <refnum>)
		KILL (send a signal) to a process.  The <signal> may either
		be an integer (like $execctl(SIGNAL 9 3) or it may
		be a short name (like $execctlSIGNAL HUP 3) to kill 
		process 3.

	$execctl(GET <refnum> [FIELD])
	$execctl(SET <refnum> [FIELD] [VALUE])
		You can GET all the fields of the object, and SET some of them.
		Some fields cannot be changed after the process is launched.

	Field		Set?	Notes
	-------------	------	-----------------------------------
	REFNUM		No	The integer refnum - never repeated.
	REFNUM_DESC	No	The "target" version (ie, %3)
	LOGICAL		Yes	The user-supplied name - must be unique
	LOGICAL_DESC	No	The "target" version (ie, %myproc)
				-- This will change if you SET LOGICAL
	COMMANDS	Yes	The commands to run (**)
	DIRECT		Yes	Whether to use a shell (**)
	REDIRECT	Yes	Either PRIVMSG or NOTICE
	WHO		Yes	The target to send output to
				-- Output from the process is redirected verbatim
	WINDOW_REFNUM	Yes	The window this exec runs in context of
				-- Undefined behavior if window does not exist
	SERVER_REFNUM	Yes	The server this exec runs in context of
				-- This is for redirects and code callbacks
	LINES_LIMIT	Yes	How many lines to receive before CLOSEOUT
				-- 0 means "no limit"
	STDOUTC		Yes	ircII code for every complete line of stdout
	STDOUTPC	Yes	ircII code for every partial line of stdout
	STDERRC		Yes	ircII code for every complete line of stderr
	STDERRPC	Yes	ircII code for every partial line of stderr

	PID		No	The process id of the process (after launch)
				-- This is -1 before launch
	STARTED_AT	No	When the process was created or launched
				-- It is first set when creation happens
				-- It is last set when launched
	P_STDIN		No	File descriptor to talk to process's STDIN
	P_STDOUT	No	File descriptor to read from process's STDOUT
	P_STDERR	No	File descriptor to read form process's STDERR
				-- There is nothing you can do with these.
				-- Don't try.
	LINES_RECVD	No	How many lines of output the process has sent
	LINES_SENT	No	How many lines we sent to the process
	EXITED		No	0 if process has exited yet -- 1 if it has
	TERMSIG		No	The signal that killed the process
				-- It is -1 if the process has not died
				-- It is -1 if the process exited normally
	RETCODE		No	The exit code of the process
				-- It is -1 if the process has not died
				-- It is -1 if the process was killed
	DUMB		No	Reserved for future/internal use
	DISOWNED	No	Reserved for future/internal use
	(Note: ** - Cannot be SET after launch)

*** News 05/08/2020 -- New flag to /EXEC, /EXEC -NOLAUNCH
	The /EXEC -NOLAUNCH flag directs the /EXEC command not to launch 
	a process that has not already launched.  You can launch it later 
	merely by referencing it with its name or refnum.

		/EXEC -nolaunch -name myproc ls -l
		/EXEC -nolaunch -limit 5 %myproc
		/EXEC %myproc

	Many /EXEC operations do not work on an unlaunched process.

*** News 05/07/2020 -- New function, $uuid4()
	This function returns a random UUID4 string.  If you know what that is,
	you might know why it's handy to be able to have one.

	ALL ARGUMENTS TO THIS FUNCTION ARE RESERVED FOR FUTURE EXPANSION.
	To get the default behavior, pass no arguments to this function.
	Forwards compatability is not guaranteed if you pass undefined args

*** News 05/07/2020 -- New /ON, /ON SEND_EXEC
	Whenever text is being sent to an /EXEC process, either through /EXEC -IN
	or /MSG %proc or a /QUERY or whatever, it is displayed to your screen.
	The /ON SEND_EXEC process will let you adorn how this text is displayed,
	instead of it just being displayed blankly as it has always done.

*** News 05/07/2020 -- The /EXEC command
	The /EXEC command has always been part of ircII, but it hasn't
	changed much during EPIC's lifetime.  There were some rough edges
	related to querying exec'd processes, things not always going
	to the windows people expected, some flags not being able to be
	used with other flags, etc.

	So the /EXEC command has been substantially revamped, with an intention
	of everything being "do what i expect".  If you find things that are 
	weirdly behaving, please let me know!

	Instead of describing the changes, let's just level-set the behavior:

	Every /EXEC command can create or modify one process

	[The most general explanation of the syntax]
	Modify an existing running exec:
		/EXEC [options] %refnum [extra arguments]
		/EXEC [options] %logical-name [extra arguments]

	Create a new exec:
		/EXEC [options] commands to run
		/EXEC [options] (commands to run) [extra-arguments]

	OPTIONS to /EXEC

	   [ Options related to sending data to/from the process ]
		-CLOSE
			Close the process's STDIN, STDOUT, and STDERR
		-CLOSEIN
			Close the process's STDIN
		-CLOSEOUT
			Close the process's STDOUT and STDERR
		-IN [extra arguments]
			Send data to a process

	   [ Options related to how the process integrates with ircII ]
		-NAME
			Change the logical name of a process
		-OUT
			Send all output from the process to the now-current 
			channel in the now-current window.
		-WINDOW
			Display all output from or related to the process to the 
			now-current window.
		-WINTARGET <windesc>
			Display all output from or related to the process to the 
			specified window
		-MSG [target]
			Send all output from the process to the target.
			The target can be an irc, dcc chat, or other exec,
			or anything you can send a message to.
			Messages sent over IRC are sent as PRIVMSGs
		-NOTICE
			Send all output from the process to the target.
			Messages sent over IRC are sent as NOTICEs.

	    [ Options related to scripting with processes ]
		-LINE {code}
			Run {code} for each full line of output from stdout of the process.
			$* will be the line of output
		-LINEPART {code}
			Run {code} for each incomplete line of output from stdout of the process.
			$* will be the incomplete line of output
		-ERROR {code}
			Run {code} for each full line of output from stderr of the process.
			$* will be the incomplete line of output
		-ERRORPART {code}
			Run {code} for each incomplete line of output from stderr of the process.
			$* will be the incomplete line of output
		-END {code}
			Run {code} when the process has completed.  This means when the process
			has exited and all of its output has been processed.  (Sometimes this 
			lags the actual exit)
				$0 is the logical process name or its refnum
				$1 is the signal that killed it (if it was killed)
				$2 is the exit code (if it exited)

	    [ Options that don't fit in the other categories ]
		-DIRECT
			Run the program directly -- do not use a shell.  
			Advantages:  The command you give is literally executed
			Disadvantages: If you depend on filename globbing or aliases, well, tough
		-LIMIT <number>
			Read <number> lines from the process and then -CLOSE it.

	    [ Options related to sending a signal to the process ]
		-<signal_number>
			Send the signal to the process, similar to kill -<signal_number> <pid>
		-<signal_name>
			Send the signal to the process, similar to kill -<signal_name> <pid>

	Additionally, %<procref> or %<procname> are full blown message targets that you can 
	/msg or /query or whatever you want, just like all other targets.

	[Examples of how this works]


*** News 04/26/2020 -- New python script, 'shortener'
	You can load this script with
		pyload shortener
	This script provides an in-client URL shortening service.
	Whenever someone provides a URL in a message, the service
	will create a short URL that will be served by an http
	redirection server that runs in client

	Example:
	--------
	<nick> hey, please visit www.frobnitz.com/really-long-and-wraps
        +onto-the-next-line-so-you-can-tpaste-it
	*** http://127.0.0.1:8080/1

	Then you can visit http://127.0.0.1:8080/1 and it will
	redirect you to the original url.

*** News 02/24/2019 -- EPIC5-2.1.1 (Abulia) was released here
	Even though not everything is done, I think I've probably
	dragged my feet long enough

*** News 11/28/2018 -- /EXEC -WINTARGET outsputs to a window by name (caf)
	The normal behavior of /EXEC is to send the output of a command
	to the current window (or is it the OTHER window?  I forget)
	Before this, you couldn't ordinarily send it to just any old
	random window you wanted.  

	You can use /EXEC -WINTARGET to send it to any window you want:
	Example:
		/exec -wintarget msgwin ls

*** News 02/24/2019 -- EPIC5-2.1.1 released here (Abulia) (Commit id: 1899)

*** News 02/05/2018 -- CTCP UTC now implemented as script
	Given the below feature, CTCP PING support has been 
	rewritten, and CTCP UTC is now scripted.

*** News 02/13/2018 -- New flag for $ctcpctl(), "REPLACE_ARGS"
	There are actually two kinds of CTCPs that replace things

	* CTCP PING replaces its argument(s), but is otherwise
	  handled "normally"
		NOTICE nick :\001PING <sec> <usec>\001
	  becomes
		NOTICE nick :\001PING <sec> seconds\001

	* CTCP UTC replaces itself entirely:
		PRIVMSG nick :\001UTC 1518582810\001
	  becomes
		PRIVMSG nick :Tue Feb 13 22:33:30 2018

	So it's not enough to say that "a CTCP handler can replace 
	itself by returning a string", you need to be able to say
	whether this CTCP replaces its arguments only, or whether
	it replaces itself entirely.

	  * $ctcpctl(SET <ctcp-name> REPLACE_ARGS 1)
	  * $ctcpctl(SET <ctcp-name> REPLACE_ARGS 0)
		Select whether or not a CTCP handler that returns a 
		string replaces its arguments (like CTCP PING) or 
		replaces itself entirely (like CTCP UTC).  
		The default is 0 (replace entirely)

*** News 02/05/2018 -- Some CTCPs are now implemented as scripts
	YOU NEED TO START DOING /LOAD ctcp  IN YOUR STARTUP SCRIPTS.

	One of the larger projects in EPIC5 was to move as many
	hard coded things into scripts as was feasible, so you,
	the user (or the script you're using) can have as complete
	control over them.  We've moved a lot of functionality out
	into scripts.

	Traditionally those users who don't have startup scripts 
	(~/.epicrc or ~/.ircrc) get /load global as their startup
	script.  One of the things /load global does is /load builtins
	which brings in the scripted features.  

	Now /load builtins will /load ctcp, which implements these 
	core CTCP functions entirely in ircII, so you are welcome 
	to modify or remove them, as _you_ choose.

		VERSION		PING		ECHO
		CLIENTINFO	USERINFO	ERRMSG
		FINGER		TIME

	Maybe more will be migrated in the future.  But this is a good
	start for now.  This is also a great example of how to 
	build your own first-class ctcp handlers!

*** News 02/04/2018 -- User-defined CTCP handlers with $ctcpctl()
	You can now create your own first-class user-defined CTCP handlers.

	A CTCP handler is a block of code that takes four arguments:
	  $0  - The person making the request
	  $1  - The target of the request (you, or a channel you're on)
	  $2  - The CTCP that was sent 
	  $3- - Arguments (if any) to the CTCP

	A CTCP request handler is a CTCP handler that handles incoming 	
	requests (over PRIVMSG).  A CTCP request handler can either 
	   (1) generate a response or 
	   (2) substitute something.  
	A response can be generated with:
	      /CTCP $0 $2 Your Response Here
	A substitute string is /return'ed by your handler, and replaces
	the CTCP in the original message.

	A CTCP response handler is a CTCP handler that handles incoming 
	responses (over NOTICE).  A CTCP request handler can either
	   (1) Output the response in a special way or
	   (2) substitute something
	CTCP response handlers are unusual, because the ordinary handling
	of CTCP responses is the expected behavior.

	Syntax:
	  * $ctcpctl(SET <ctcp-name> REQUEST {<code>})
		Register <code> as a CTCP handler for <ctcp-name> requests.

	  * $ctcpctl(SET <ctcp-name> RESPONSE {<code>})
		Register <code> as a CTCP handler for <ctcp-name> responses.
		(Note -- handling responses is unusual.  Normally you just
		 let the client output responses in the ordinary way)

	  * $ctcpctl(SET <ctcp-name> DESCRIPTION <string>)
		SET <string> as the CLIENTINFO for <ctcp-name>.  That is,
		when someone does /CTCP CLIENTINFO <ctcp-name>, <string> 
		will be returned as the description for this CTCP.

	  * $ctcpctl(SET <ctcp-name> SPECIAL 1)
	  * $ctcpctl(SET <ctcp-name> SPECIAL 0)
		Enable/Disable a CTCP as being "Special".  A "Special" CTCP
		is a remote function call, and handles everything itself.
		There are only two "special" CTCPs -- ACTION (/me) and DCC.
		I'm not sure if anyone will create a "special" user-defined CTCP

	   * $ctcpctl(SET <ctcp-name> RAW 1)
	   * $ctcpctl(SET <ctcp-name> RAW 0)
		Enable/Disable a CTCP has requiring the "raw data".
		Ordinary CTCPs transport strings, and they have to be recoded
		according to /encode-ing rules.  But some CTCPs transport 
		binary data, and so the handler needs access to the raw binary
		data.  Ordinarily, the raw/binary data is CTCP encoded, which
		mens you can pass it to $xform("-CTCP") to recover the raw
		bytes (although it might not be a C string, so you can't 
		assign it to a variable.)

	   There are corresponding GET operations for the above

	You can get all the registered CTCPs with
	   * $ctcpctl(ALL)

	Very soon, quite a few CTCP types will be migrated out to a script that
	will be /load'ed from /load global, and you may have to add it to your
	own start scripts if you do not /load global.

	I need to write much better examples for all this.  To look at this you'd
	scratch your head and wonder why you care.  But being able to add new 
	CTCPs instead of requiring them to be written in C in a new version of
	epic is expected to help a lot of people.


*** News 01/16/2018 -- New status expando %{1}P ("status prefix") and variables
	The %{1}P value will expand to a "when window current" or "when window
	not current" value.  The idea is to put this at the start of your 
	/set status_format or /window status_format type variables.

	When a window is current, %{1}P will expand to either
		/window status_prefix_when_current
	or
		/set status_prefix_when_current

	When a window is not current, %{1}P will expand to either
		/window status_prefix_when_not_current
	or
		/set status_prefix_when_not_current

	You can use this all in your ~/.epicrc, like so:
		set status_format %{1}P%T [%R] %*%=%@%N%#%S%{1}H%H%B%Q%A%C%+%I%O%M%F%L %D %U %W
		set status_prefix_when_current ^C37,40
		set status_prefix_when_not_current ^C37,44
	which will make your status bar white-on-black when current,
	and white-on-blue when not current.


EPIC5-2.0
EPIC5-1.8

*** News 08/05/2016 -- EPIC5-2.0.1 released here (Commit id: 1869)

*** News 01/30/2016 -- EPIC5-2.0 released here (Commit id: 1864)

*** News 01/30/2016 -- EPIC5-1.8 released here (Commit id: 1862)

*** News 01/30/2016 -- /WINDOW LOGFILE and /SET LOGFILE more like /LOG FILNAME
	Historically, changing a logfile name (with /WINDOW LOGFILE and
	/SET LOGFILE) does not affect the log status.  This leads to 
	unexpected behavior if you do /WINDOW LOG ON LOGFILE foo.txt
	because /WINDOW LOGFILE only changes the filename the *next* time
	you open the log, not affecting the currently open log.

	The behavior of /LOG FILENAME is more in line with what people 
	said they expected.  If you change /LOG FILENAME while the 
	log is ON, then it will 1) close the existing log, 2) change
	the filename, and 3) re-open the log under the new name.

	The behavior of /WINDOW LOGFILE and /SET LOGFILE have been changed
	to match the behavior of /LOG FILENAME -- changing the logfile name
	while it is open will close the existing log and open a new one.

EPIC5-1.6

*** News 01/30/2016 -- EPIC5-1.6 released here (Commit id: 1854)

*** News 01/08/2016 -- Per-server vhosts now restrict protocol (ipv4/ipv6)
	Historically, the client tries to connect to the server using the
	addresses as they are returned in order.  (This is a great thing 
	for round-robin or geographic-aware dns resolvers.)

	However, if you have a per-server vhost, you probably intend that
	epic use that vhost to connect to the server.  But what happens if
	your vhost is ipv4 only or ipv6 only, and the first address to the
	server is to the other protocol?  Historically, epic will just go 
	ahead and connect without your vhost.

	You've been able to correct this behavior by specifying explicitly
	the protocol family:
		/server irc.foo.com:proto=v6:vhost=irc.leet6.com
	Some folks said it violated POLA, so here's a new rule:

	"If you set a per-server vhost, then that server can only be 
	 connected to if the vhost can be used.  If ths means that no
