System Interfaces
=================

The `core.sys` package contains interfaces for interacting with the operating system.
At this time, these interfaces are focused on launching other processes.


Starting Processes
-------------------

The following free functions are provided to ask the operating system to open files (and web
addresses through [stormname:core.io.Url]s), as well as starting arbitrary programs.

```stormdoc
- core.sys.open(*)
- core.sys.execute(*)
```

The class [stormname:core.sys.Execute] provides more control over process execution. It has the
following members:

```stormdoc
@core.sys.Execute
- ._init(*)
- .workingDirectory(*)
- .newTerminal(*)
- .newGroup(*)
- .detach(*)
```

Note that the members that set properties return the object itself. This is to make it possible to
chain such calls into a single line. For example, to start a program in a new terminal window, one
can write:

```bsstmt
Execute("emacs", ["~/.emacs"]).newTerminal().detach();
```

This design also allows extending the capabilities of the [stormname:core.sys.Execute] interface in
the future without creating many combinations of the `execute` overload.


### Notes for Windows

On Windows, the `open` function calls the Win32 function `ShellExecute`, which takes file
associations into account. This makes the `open` function roughly equivalent to typing the URL in
the "Run" dialog.

The functionality provided by `Execute` is based around the Win32 function `CreateProcess`. While it
is straight-forward to map most of the functionality to `CreateProcess`, there is one notable
exception: namely that Windows treats all command-line arguments as a single string that is passed
to the program. It is then up to each individual program to split the string into individual
arguments. Storm constructs a string of the quoted arguments for you, using a format that
corresponds to what the C runtime library understands. This should cover most use-cases. However, a
notable exception from this convention is `cmd.exe`.


### Notes for Linux

The `open` function is implemented by calling the `xdg-open` program on Linux. This makes Storm
respect the file associations that are set up by the desktop environment. However, `xdg-open` is not
always installed, and it is not always possible to detect errors from `xdg-open` as it sometimes
forks off the new process, and sometimes simply execs into it. Storm does its best to account for
this and interprets the exit codes from `xdg-open`, but since it does not always terminate quickly
Storm has to wait for a while before it is able to determine whether `xdg-open` succeeded or not.

The functionality provided by `Execute` generally maps well to `exec` and `fork` on Linux. One
difficulty is that there is no well-established way to determine which terminal emulator to launch
for terminal applications. The implementation currently has the following approach:

1. If the program `xdg-terminal-exec` is installed, it is used. While `xdg-terminal-exec` is new, it
   represents a standardized way in which programs can ask to start a new instance of the user's
   preferred terminal emulator.

2. Inspect the environment variable `STORM_TERM_COMMAND`. If it is set, Storm will append the
   program to start to the end of the command and execute it (after splitting `STORM_TERM_COMMAND`
   on spaces). For example, to launch `xterm`, one could set `export STORM_TERM_COMMAND="xterm -e"`.

3. Attempt to launch `xterm` using `xterm -e` followed by the command.

4. If everything else fails, throw an error.

Finally, it is worth noting that old versions of `xdg-terminal-exec` did not support any command
line arguments. Since Storm uses `xdg-terminal-exec -- <command>` to avoid problems with commands
that start with dashes, old versions of `xdg-terminal-exec` will launch a terminal that just
complains that it is unable to launch the command `--`. To solve this problem, you need a newer
version of `xdg-terminal-exec` (it is not possible to detect the old version programmatically as it
does not accept any command line parameters such as `--version`).
