run2
=============================================================================
This package provides two utilities: 'run2' and 'checkX'. The first is
a more powerful replacement for the venerable 'run' utility that has long
been a part of the cygwin distribution. The second is a test utility that
detects whether an Xserver is active, and exits with an appropriate status
value.

For a realistic example of run2 usage, run the config-run2-example.sh script.
It will generate:
  /usr/local/bin/cygshell.xml
and a shortcut (in the current directory) that launches run2 with that xml
file. This shortcut will launch
  1) mintty if there is no Xserver running, or
  2) urxvt-X.exe (rxvt-unicode) if there is.
This script requires cygutils-1.4.2 or above. You can move the shortcut to
any location you like.

The run2 utility
=============================================================================
'run2' launches console programs while hiding any actual console (dos
box) that may ordinarily be associated with them. In addition, 'run2' can:
  * set/modify environment variables before launching the target program
  * specify a specify start directory from which to launch the target
  * detect whether an X server is active or not, and launch one of two
    different targets -- with different command line arguments, environment
    settings, and startup dirs.
In fact, the name 'run2' is rather a pun: it is a successor to the original
'run' utility, but also it is capable of launching two different targets.

'run2' uses an external XML configuration file to control its own operation,
and to specify the settings which should be applied to the target program(s).
As an example, you could have a windows shortcut with the following target:

   C:\cygwin\bin\run2.exe --notty /usr/bin/rxvt.xml

where rxvt.xml could specify:
   (a) in all cases, the PATH variable should have '/usr/bin' appended.
       This can help when you don't ordinarily include the cygwin directories
       in your "global" windows PATH, but the target program is located in
       some directory other than /usr/bin -- and so would not, usually, be
       able to find cygwin1.dll.
   (b) if an Xserver is detected, then the TERM variable should be set to
       rxvt-unicode, the LANG variable should be set to en_US.UTF-8, and
       the urxvtc-X.exe executable launched with an appropriate -display
       argument and shell.
   (c) if an Xserver is not detected, then the TERM variable should be set
       to rxvt-cygwin-native, and LANG variable should be unset, and the
       rxvt.exe executable launched in native mode.
The format of the configuration file is specified as an XML schema, in
/usr/share/doc/run2/run2.xsd. (Note that the utility uses a compiled-in
version of this schema; modifying the .xsd file will have no effect). For
an example configuration file, see /usr/share/doc/run2/run2-demo.xml.

The configuration file has four main elements:
  1. SelfOptions -- a list of Args that are passed to the
     run2 executable itself.  These arguments actually
     override the ones passed on the command line.
     This must be present, but need not have any Arg elements.
  2. Global -- This must be present. It has two sub-elements:
     a. Environment -- has Set, Append, and Prepend elements.
        to manipulate environment variables. This must be
        present, but need not contain any actual elements.
     b. Target -- this is optional. It can be used to
        specify a single target program that will always
        be launched. If specified, then the next two
        sections must not be included. The format is as
        specified below.
  3. GDI -- the target program to be launched when an
     Xserver is not detected. If Global::Target is not
     specified, then it must be present; conversely, if
     Global::Target is specified, it may not appear. It
     contains two sub-elements.
     a. Environment -- same as above
     b. Target -- this is required for the GDI element.
        It must specify the filename of the target program,
        and optionally the directory in which to start
        the application. It may optionally contain a sequence
        of Arg elements, specifying options and arguments to
        be passed to the target application.
  4. X11 -- the target program to be launched when an
     Xserver is detected. If Global::Target is not specified,
     then it must be present; conversely, if Global::Target
     is specified, it may not appear. It contains two
     sub-elements.
     a. Environment -- same as above
     b. Target -- same as above

Each Arg element's text is word-split, so
  <Arg>-d -b</Arg>
actually becomes two separate arguments. However, single- and double-
quotes, and backslashes, may be used to escape spaces, so that
  <Arg>-p "C:/Documents and Settings/user"</Arg>
is two argumetns, not four.  Furthermore, as the XML specification does
not allow two hyphens to appear within an XML comment, the following
would be invalid XML:
  <!-- <Arg>--debug</Arg> -->
It is often useful to comment out arguments like this, AND such arguments
often contain the '--' sequence. Therefore, as a special feature when
parsing <Arg> text, the trigraph '-!-' will be unconditionally replaced
with '--', so that
       <Arg>-!-debug</Arg>
  <!-- <Arg>-!-debug</Arg> -->
will each do what you expect.

Also, in no case is variable interpolation performed. That is,
  <Environment>
    <Prepend var="PATH" value="/home/${USER}/bin"/>
  </Environment>
will not do what you might want. This feature may be added later. Neither
is '~' interpolated in Environment settings, although the underlying
execution engine (that is, cygwin itself) may support it. However, see
below...

Finally, both the start directory and the target executable filename may
begin with '~' to specify the current user's home directory, or a
subdirectory thereof.  Also, '~username' is supported, though I suspect it
would be somewhat less useful. '~' defaults to the value of $HOME, or if
unset then the contents of /etc/passwd is consulted. For '~username',
/etc/passwd is always used.

=============================================================================
Usage: run2.exe [OPTIONS] xmlfile
Launches a target app, based information specified in the xmlfile
argument. Optionally, determines if an Xserver is available or not,
and launches one of two different target apps. Also, may be used
to set environment variables before launching the target.
Options:
  -h|--help              print this help message and exit
  -v|--version           print version information and exit
  -d|--display STRING    use STRING instead of $DISPLAY
  -x|--xlibname STRING   use exactly STRING instead of fuzzy cygX11-n.dll search
  -t|--timeout FLOAT     allow FLOAT seconds to connect with Xserver
                         defaults to 0.5, use 0.0 for Xlib's (safe, 12s) timeout
     --force-gdi         unconditionally launch GDI configuration
     --force-x11         unconditionally launch X11 configuration
  -w|--wait              wait for the target app to complete before returning
     --nogui             disable informational popups
     --notty             disable stderr messages
     --silent            suppress all but fatal error messages (default)
     --no-silent         allow (fatal and non-fatal) error messages
     --no-verbose        same as --no-silent
     --verbose           allow error, warning, and info messages
     --debug[=N]         turn on debugging messages, as well as
                         those enabled by --verbose. N defaults to 1
                         --debug=0 is the same as --verbose. Values
                         higher than 1 enable increasing details
=============================================================================

Commentary -- Output messages
-----------------------------------------------------------------------------
The --nogui, --notty, --silent, --no-silent, --verbose, --no-verbose,
and --debug[=N] options all interact to control how "chatty" the 'run2'
utility is when executing. Ordinarily, when used from a windows shortcut,
you want --notty (so that fatal error messages cause popup windows,
rather than sending text to the invisible console), and a very low level
of verboseness.  However, when using 'run2' from the command line, it's
probably better to use --nogui and perhaps, a slightly more verbose level
of output.  My suggestion is:

  In shortcuts, use '--notty' and the default (e.g. '--silent') options,
  which results in only fatal error messages being displayed in popup
  windows.

  From the command line, use '--nogui' and '--verbose', to send
  (fatal and non-fatal) error, warning, and info messages to the
  terminal.

Note that --debug=[2 or higher] should never be combined with --notty,
because in that case each and every debug message results in a separate
popup window. There are a LOT of them at level 2, 3, and 4.  Even
--debug=1 is a bit overwhelming in --notty mode, but it is sometimes
necessary to figure out why something works from the command line but
not from a shortcut.

Commentary -- Finding the X server
-----------------------------------------------------------------------------
'run2' attempts to dynamically load the X11 DLL in order to contanct
the Xserver. Therefore, this package does not explicitly depend on
the X DLLs.

Ordinarily, 'run2' searches the $PATH to find the X11 DLL. However,
if you do not typically include the cygwin directories in your system
PATH, this may fail when 'run2' is used from a shortcut. To work
around this problem, add '/usr/bin' to the PATH variable using an
Append (or Prepend) element in the Global::Environment section of
the target xml.

'run2' uses a fuzzy search to locate the X11 DLL.  Within each
directory on its search path, it looks for a DLL named 'cygX11-N.dll'
where N is between 6,7,8, or 9 (in reverse order, to guarantee that
newer DLLs are loaded instead of older ones).  If you want to
specify exactly the name (but not path) of the X11 DLL to load,
use the --xlibname runtime option.

Once 'run2' locates and loads the X11 DLL, it attempts to contact an
Xserver running on $DISPLAY.  To choose another $DISPLAY, use the
--display runtime option (or change the value of the DISPLAY
environment variable using a Set element in the Global::Environment
section of the target xml).

Commentary -- Timeouts when contacting the X server
-----------------------------------------------------------------------------
Finally, it is sometimes necessary to adjust the --timeout option. First,
some background: if there is no Xserver running on $DISPLAY, but $DISPLAY
is actually set (non-empty) and the cygX11-*.dll is installed, then
XOpenDisplay() takes a long time to return.  Xlib's built-in communication
timeout is something like 12 to 15 seconds.  So, 'run2' spins off a separate
thread to call XOpenDisplay -- and the main thread detaches it if it doesn't
answer back "soon enough".  The default timeout for the main thread to give
up on the worker is 0.5 seconds.  After that delay, the worker thread is
detached and the main thread continues -- it will then launch the GDI
target and exit (unless --wait, in which case the main thread will not
immediately exit but will instead wait for the GDI target to finish and
exit).  From the time that the main thread detaches the worker thread, that
thread will hang around waiting for XOpenDisplay() to return for another
10 seconds or so before it too dies, but that's transparent to the user --
who only is ever forced to wait 0.5 seconds for an answer, not 15 seconds.

This default timeout of 0.5 seconds seems to work well -- it's not too
short, but it's not annoying long either.  However, on a slower machine
or if $DISPLAY points to a remote machine with a long latency, it is
possible that the main thread will give up before the worker thread
completes its ultimately *successful* call to a running Xserver.  In this
case, use --timeout to increase the main thread's patience.  (On my
machine, "too short" was 0.01 seconds, so the default 0.5 should work
for just about anybody.)

However, note that if DISPLAY is unset, there is no long delay; XOpenDisplay
itself returns immediately (with failure code) without even attempting to
contact an Xserver. The only time there might be a long delay -- and the
case for which this thread-based solution was crafted to solve -- is when
DISPLAY is set (say, to ":0" like the cygwin rxvt.exe requires to indicate
"native GDI" mode), but there is no actual Xserver running.

The checkX utility
=============================================================================
This quick-n-dirty utility can be used to check if X is installed on the
machine and if the Xserver is running.  checkX is (mostly) silent by
default (unless configured with --disable-silent) and will only print
or popup "unusual" -- that is, fatal -- error messages. All it does is
return a status (0 or 1).  This utility is now just a test program for
one of the components of the 'run2' program. It has found some use as
a "barrier" program in some cygwin Xserver startup scripts: e.g.

   XWin --some --options
   checkX --notty -t 12 -d $DISPLAY
   # start other clients...

Ignoring issues with non-invisible consoles and needing a working shell,
and the 'run2' utility's extra features like setting environment variables,
one could implement a version of 'run2' using the 'checkX' program as
follows:

  #!/bin/sh
  if checkX ; then
    # start X-based program
  else
    # start some native MSWindowing alternative
  fi

=============================================================================
Usage: checkX.exe [OPTION]...
Determines if X is installed, Xserver is running on specified DISPLAY
and will accept clients. Returns 0 if yes, nonzero otherwise

Options:
  -h|--help                  print this help message and exit
  -v|--version               print version information and exit
  -d|--display STRING        use STRING instead of $DISPLAY
  -l|--location              print location of Xlib DLL on stdout
  -a|--appendpath STRING     append STRING to value of $PATH (cumulative)
  -p|--prependpath STRING    prepend STRING to value of $PATH (cumulative)
  -r|--replacepath STRING    use STRING instead of $PATH when searching
  -x|--xlibname STRING       use exactly STRING instead of fuzzy cygX11-n.dll search
  -t|--timeout FLOAT         allow FLOAT seconds to connect with Xserver
                             defaults to 0.5, use 0.0 for Xlib's (safe, 12s) timeout
     --nogui                 disable informational popups
     --notty                 disable stderr messages
     --silent                suppress all but fatal error messages (default)
     --no-silent             allow (fatal and non-fatal) error messages
     --no-verbose            same as --no-silent
     --verbose               allow error, warning, and info messages
     --debug[=N]             turn on debugging messages, as well as
                             those enabled by --verbose. N defaults to 1
                             --debug=0 is the same as --verbose. Values
                             higher than 1 enable increasing details

Note that -a defaults to '/usr/bin:/usr/X11R6/bin'.  To eliminate the default,
use '-a ""'
=============================================================================

Usually, no runtime options need be specified; checkX just works.  However,
sometimes its behavior might need tweaking, so a description of its runtime
options follows.

Commentary -- Output messages
-----------------------------------------------------------------------------
The --nogui, --notty, --silent, --no-silent, --verbose, --no-verbose,
and --debug[=N] options operate in a manner similar to that described
for 'run2.exe' above. However, as 'checkX' is a much simpler program,
the range of messages is much smaller.  Most useful in this case is
the --no-silent option, which in this case would simply display
WHY a failure code was returned ("couldn't find Xlib DLL", "couldn't
connect to $DISPLAY", etc).

The --notty turns off any stdio output, forcing checkX to use
MessageBox popups (not that this matters except for truly exceptional
fatal errors in the default "mostly silent" mode).  Remember, "couldn't
connect to $DISPLAY" is not considered a fatal error; it's simply
expected that sometimes there won't BE an Xserver. Exceptional "Fatal
Errors" are things like "out of memory", etc.

Similarly, --nogui disables MessageBox popups (again, not an issue in
the default "mostly silent" mode).  If neither tty nor gui are disabled,
then TTY is preferred.

Commentary -- Finding the X server, Timeouts
-----------------------------------------------------------------------------
Just like the 'run2' utility and as discussed above, the --display,
--xlibname, and --timeout options can be used to influence the
process of contacting the X server.  However, as 'checkX' has
no xml configuration (and thus, no Global::Environment section
in which to manipulate $PATH), 'checkX' supports three additional
command line arguments with more limited functionality:
  --appendpath
  --prependpath
  --replacepath
can be used to manipulate the PATH variable, prior to any attempt
to located the X11 DLL.

--location prints the cygwin path to the X11 DLL as checkX
determined it, onto stdout.  This is regardless of silent-mode,
disable-tty, or whatever.  You want the location, you'll get the
location.


Licensing
=============================================================================
This software is released under various simultaneous licenses. Mostly,
individual source files are covered by either an MIT/X or BSD license.
However, as the contact-the-Xserver functionality used by checkX.exe and
(the full version of [see Non-Cygwin (native win32/mingw) ports, below])
run2.exe really only works with cygwin -- and as both programs as compiled
on cygwin each link against the GPL'ed cygwin DLL, distribution of compiled
run2.exe and checkX.exe binaries requires GPL-ish distibution of the run2
package source. Also, the run2.exe program uses two files that are derived
directly from the GPL run.exe program -- so the run2.exe utility is, itself,
explicitly GPL even though much of the underlying source code is MIT/X or
BSD.  Finally, the icons included in the run2.exe binary are under various
copy-leftish licenses, including LGPLv2.1 and Creative Commons Attribution
ShareAlike (CC-BY-SA).

Non-Cygwin (native win32/mingw) ports
=============================================================================
run2.exe currently requires cygwin, but a more limited version (which
supported only the Global::Target mode of operation) could easily be
ported to native win32. While Patches are Thoughtfully Considered (PTC),
I believe that such a modified version would require very ugly changes
not only to the code, but also to the build machinery.  This will only
get worse once cygwin-1.7 specific features like support for (really)
long filenames, Unicode/wide char XML contents, and wide char filenames,
are added.  Therefore, I believe -- and encourage -- a native-win32/
mingw-specific port to be implemented as a cooperative fork, or branch
in the existing repository, rather than cluttering the code and build
machinery with more #ifdefs and AM_CONDITIONALS.

