CONCEPT
	erq - External Request Demon

DESCRIPTION
	Up to version 3.2.1@61, LPMud utilized two external programs
	in an ad-hoc manner to solve problems: the 'hname' program to
	resolve IP addresses into meaningful hostnames, and the
	'indent' program to properly indent LPC files.
	In version 3.2.1@61 both functions were united in a
	generalized 'erq' process, to which additional functions may
	be attached. Unfortunately it was never documented by Amylaar,
	so the information presented here had to be reverse engineered
	from the sources - better take it with a grain of salt.

	The erq feature is available if the driver is compiled with
	ERQ_DEMON defined (in config.h).

	When the driver starts up, it tries to fork off the program
	'BINDIR/erq --forked' (with BINDIR defined in the Makefile).
	If this succeeds, the erq may talk with the driver through
	stdin and stdout (piped through AF_UNIX sockets).

	At runtime, the erq may be changed/removed from within the
	mudlib using the efun attach_erq_demon(). This efun is given
	an interactive object as argument, and takes the connection
	away(!) from this object and stores it as the erq connection
	to use (an old erq connection is closed first). The object
	(which now no longer is interactive) is then no longer needed,
	but may continue to exist.
	The erq attached this way of course has to use the sockets it
	opened to communicate with the driver.

	Most of the communication between erq and driver is going to
	be initiated by the driver (the erq has to look up the
	hostnames for given IP addresses), but using the efun
	send_erq() the mudlib may talk with the erq as well.

	The communication between driver and erq is done using
	messages of specified structures and constants (defined in
	util/erq.h resp. sys/erq.h). The 'int32's are signed integers
	of four byte length, and are sent with the MSByte first.
	Every message must be sent atomically!

	The head of the messages is always the same:

	  struct erq_msghead {
	    int32  msglen;  /* Total size of message in bytes */
	    int32  handle;  /* Identification number */
          }

	The 'handle' number is set by the driver (do not make
	assumptions about its value) and is used to associated the erq
	responses with the pending requests. This way the erq is free
	to respond in an order different to those of the incoming
	requests.

	The messages send to the erq follow this symbolic format:

	  struct to_erq_msg {
	    int32  msglen;
	    int32  handle;
	    char   request;
	    char   data[0];
	  }

	The 'request' denotes which service is requested from the erq,
	the size and content of 'data' depends on the requested
	service.

	The answer message from the erq to the driver (if there is one
	at all) may have two forms:

	  struct from_erq_msg {
	    int32  msglen;
	    int32  handle;
	    char   data[0];
	  }

	  struct from_erq_keep_msg {
	    int32        msglen;
	    const int32  keep = ERQ_KEEP_HANDLE;
	    int32        handle;
	    char         data[0];
	  }

	The replied data from the erq is stored in 'data', which size
	and content depends on the request answered. The answer is
	identified by 'header.handle'. Normally, one request results
	in just one response sent by the erq using struct from_erq_msg,
	so the handle is recycled after this response.
	Shall the erq send several responses (or break one response
	into several parts), the struct from_erq_keep_msg has to be
	used for all but the last response - this message with its
	included special handle keeps the real handle alive.

	
	Mudlib generated erq-calls specify the 'request' and the
	'data' to be sent, and receive the 'data' replied. When
	dealing with spawned programs, the first byte of the returned
	'data' determines the content type of the received message.
	The actual 'data' which the lpc programs get to see is sent
	and retrieved as arrays of byte integers (integers in the
	range of 0..255).


	The actual interface between erq demon and driver is limited
	to the general message formats and the hostname lookup
	mechanism. The driver is meant to withstand erq demon failures
	at least in a garbage-in garbage-out fashion. You could add
	new requests to the erq demon, or write your own from scratch,
	without changing the driver.


	Currently five services are predefined in the supplied
	erq-demon (util/erq.c in the driver source archive): looking
	up a hostname, execution, forking or spawning an external
	program, authentification of a connection, and handling of
	external UDP/TCP connections. As mentioned above, only the
	hostname-lookup is a true must.

	For a program to be executable for erq, it must be placed in
	or below ERQ_DIR (defined in config.h). On most unix systems,
	it is possible to use a symlink instead of the whole program
	if you want a standard binary. You could even symlink entire
	directories like /usr/sbin, but chances are you make a big
	security hole this way :-)


	Hostname lookup:

	  request  : ERQ_RLOOKUP
	  data sent: struct in_addr.s_addr addr // the address to resolve
	  data recv: struct in_addr.s_addr addr // the resolved address
	             char[]                name // the hostname (if any)

	  If the sent address can't be resolved, just the address is
	  to be returned. The string need not be 0-terminated.


	Execute/Fork program:

	  request  : ERQ_EXECUTE/ERQ_FORK
	  data sent: char[] command  // the command to execute
	  data recv: char   status = CHILD_FREE
	             char   rc       // the success/error code
	             char   info     // additional information

	  The erq executes the sent command using the execv().
	  The erq does the processing of the command line arguments
	  (which must not contain '\') and checks the validity of the
	  command (it must not start with '/' nor contain '..'), which
	  is interpreted relative to ERQ_DIR.
	  The external program is executed from a fork()ed instance of
	  the erq, however, with ERQ_EXECUTE the erq waits until the
	  external program finished before replying its response, with
	  ERQ_FORK the response is immediately sent back.

	  Possible return codes are:
	    ERQ_OK         : Operation succeeded.
	    ERQ_E_ARGLENGTH: Too long command.
	    ERQ_E_ARGFORMAT: Illegal argument given (contains '\');
	    ERQ_E_ARGNUMBER: Too much arguments (>= 96).
	    ERQ_E_ILLEGAL  : Command from outside ERQ_DIR requested.
	    ERQ_E_PATHLEN  : Commandpath too long.
	    ERQ_E_FORKFAIL : Command could not be forked;
	                     info holds the errno value.

	  ERQ_EXECUTE features some more return codes:
	    ERQ_OK         : Operation succeeded, <info> holds the exit status.
	    ERQ_SIGNALED   : Command terminated the signal <info>.
	    ERQ_E_NOTFOUND : No process found to wait() for.
	    ERQ_E_UNKNOWN  : Unknown exit condition from wait().


	Spawn program:

	  request  : ERQ_SPAWN
	  data sent: char[] command  // the command to execute
	  data recv: Spawn failed:
	             char   rc       // the error code (see ERQ_FORK)
	             char   info     // additional information
	  data recv: Spawn succeeded:
	             char   rc = ERQ_OK
	             char[] ticket         // the spawn ticket.

	  The erq executes the sent command as if given an ERQ_FORK
	  command, but returns additional information about the
	  started process to allow further communication.
	  In contrast to ERQ_FORK, ERQ_SPAWNED processes may be
	  controlled via ERQ_KILL, receive data from the mud via
	  ERQ_SEND on their stdin, and output from their stdout/stderr
	  is sent back to the mud.
	  The spawned process is identified by its <ticket> (don't
	  make any assumptions about its length), the transaction itself
	  by <handle>.


	Send data to spawned program:

	  request  : ERQ_SEND
	  data sent: char[] ticket // the addressed process ticket.
	             char[] text   // the text to send.
	  data recv: char   rc     // the success/error code.
	             int32  info   // opt: additional info.

	  The <text> is sent to the stdin of the spawned process
	  identified by <ticket>.

	  Possible return codes are:
	    ERQ_OK          : Operation succeeded, no <info> is replied.
	    ERQ_E_TICKET    : The given ticket is invalid, no <info> replied.
	    ERQ_E_INCOMPLETE: Only <info> chars of the text have been
	                      sent.
	    ERQ_E_WOULDBLOCK: Error E_WOULDBLOCK (also stored in <info>)
	                      happened while sending the text.
	    ERQ_E_PIPE      : Error E_PIPE (also stored in <info>)
	                      happened while sending the text.
	    ERQ_E_UNKNOWN   : The error with code <info> happened
	                      while sending the data.


	Send a signal to a spawned program:

	  request  : ERQ_KILL
	  data sent: char[] ticket // the addressed process ticket
	             int32  signal // the signal to send
	  data recv: char   rc     // the success/error code

	  The <signal> is sent to the spawned process identified by <ticket>.

	  Possible return codes are:
	    ERQ_OK          : Operation succeeded, no <info> is replied.
	    ERQ_E_TICKET    : The given ticket is invalid, no <info> replied.
	    ERQ_E_ILLEGAL   : The given signal is illegal.
	

	Data replies from spawned programs:

	  data recv: char   out_or_err  // type of text output
	             char[] text        // text output by child process

	  The child process controlled by the erq did output <text>
	  on stdout (<out_or_err> == ERQ_STDOUT) resp. on stderr
	  (<out_or_err> == ERQ_STDERR).


	Exit notifications from spawned programs:

	  data recv: char   rc          // the exit code
	             char   info        // additional information.

	  The child process controlled by the erq did terminate.
	  Possible exit codes are:
	    ERQ_EXITED    : Process exited with status <info>.
	    ERQ_SIGNALED  : Process terminated by signal <info>.
	    ERQ_E_UNKNOWN : Process terminated for unknown reason.


	Authentificate connection (see rfc 931):

	  request  : ERQ_AUTH
	  data sent: struct sockaddr_in remote // the address to check
	             int32              port   // the mud port
	  data recv: char[]             reply  // the data received by authd

	  The erq attempts to connect the authd on the remote system
	  and to verify the connection between the remote port and the
	  mud port. The latter will normally be the port number of the
	  socket on besides of the gamedriver, retrieveable by
	  query_ip_number().
	  The answer from the authd (one line of text) if there is any
	  is returned as result.


	Open an UPD port:

	  request  : ERQ_OPEN_UDP
	  data sent: char[2] port   // the port number to open (network order)
	  data recv: Open failed:
                     char    rc     // the success/error code.
	             char    info   // opt: additional info.
	  data recv: Open succeeded:
	             char   rc = ERQ_OK
	             char[] ticket  // the connection ticket.

	  The erq opens an UDP-port on the host machine with the given
	  port number.
	  Possible exit codes are:
	    ERQ_OK          : Operation succeeded.
	    ERQ_E_ARGLENGTH : The port number given does not consist
	                      of two bytes.
	    ERQ_E_NSLOTS    : The max number of child processes (given
	                      in <info>) is exhausted.
	    ERQ_E_UNKNOWN   : Error <info> occured in one of the system
	                      calls done to open the port.

	  Once the port is open, it is treated as if is just another
	  spawned program.


	Send data over an UDP port:

	  request  : ERQ_SEND
	  data sent: char[]  ticket // the addressed port's ticket.
	             int32   addr   // address of receiver.
	             char[2] port   // port of receiver.
	             char[]  text   // the text to send.
	  data recv: char   rc     // the success/error code.
	             int32  info   // opt: additional info.

	  The <text> is sent from our port <ticket> to the network
	  address <addr>, port <port>.

	  Possible return codes are:
	    ERQ_OK          : Operation succeeded, no <info> is replied.
	    ERQ_E_TICKET    : The given ticket is invalid, no <info> replied.
	    ERQ_E_INCOMPLETE: Only <info> chars of the text have been
	                      sent.
	    ERQ_E_WOULDBLOCK: Error E_WOULDBLOCK (also stored in <info>)
	                      happened while sending the text.
	    ERQ_E_PIPE      : Error E_PIPE (also stored in <info>)
	                      happened while sending the text.
	    ERQ_E_UNKNOWN   : The error with code <info> happened
	                      while sending the data.


	Close an UDP port:

	  request  : ERQ_KILL
	  data sent: char[]  ticket // the addressed port's ticket
	             int32   signal // the signal to send (ignored)
	  data recv: char    rc = ERQ_OK

	  The port <ticket> is closed. The <signal> must be sent, but
	  its value is ignored.


	Data received over an UDP connection:

	  data recv: char    out_or_err = ERQ_STDOUT
	             int32   addr    // ip-address of sender
	             char[2] port    // port of sender
	             char[]  text    // data received

	  The UPD port controlled by the erq did receive <text> over
	  the network from the sender at <addr>, reply port number <port>.


	Note: the requests ERQ_OPEN_TCP and ERQ_LISTEN are defined,
	but not implemented yet.


HISTORY
	The erq was introduced with 3.2.1@61.
	ERQ_AUTH was introduced with 3.2.1@81.
	ERQ_SEND, ERQ_SPAWN, ERQ_KILL were introduced with 3.2.1@82.
	ERQ_OPEN_UDP, ERQ_OPEN_TCP, ERQ_LIST were introduced with 3.2.1@98.

SEE ALSO
	attach_erq_demon(E), send_erq(E), stale_erq(M), rfc 931
	query_ip_number(E)
