# Execute Shell Commands

You can invoke shell-commands during processing of a hsc source. The output of the command can be assigned to an special attribute or immediately being included into the document. This can be useful to include data from external applications (like databases), prepared by scripts (eg. Rexx), which of course you have to write yourself.

This functionality is provided by the hsc tag `<$exec>`

## Possible Attributes

`COMMAND:string/required`
  Specifies command to be executed. This attribute is required
`INCLUDE:bool`
  If this attribute occurs, the output the command sends to `stdout` (or the filename specified with `FILE`) is included in the document.
`ATTRIBUTE:string`
  Using this attribute, you can select an attribute you've created before using `<$define>` to store the data the command sends to `stdout`.
`FILE:string`
  Specifies filename where the command is expected to store the output. The filename is relative to the source-directory. If this attribute is not set, `hsc` will assume the command to output to `stdout` and will redirect the output to a temporary file. This attribute is only useful if you have also set at least one of `INCLUDE` or `ATTRIBUTE`
`TEMPORARY:bool`
  This attribute has the same meaning as within `<$include>`. Note that it can be reasonable to specify it, even if you set a specific output-file, and not only for temporary-files created by `hsc`.
`REMOVE:enum("auto|on|off")="auto"`
  This attribute tells `hsc` what to do with the output-file after all data have been read. If you set it to `REMOVE="off"`, the file will be left untouched. If no one else is going to remove it, it will continue to exist until doomsday or the next head-crash.

  If you didn't specify an output filename (using `FILE`), this can clutter your temporary-directory (usually "t:") with loads of files having strange names like "hsc0x321764.tmp".

  To avoid this, you can set `REMOVE="on"`, so the output-file will always be removed.

  By default, `REMOVE="auto"` is set. This will remove the file, if `TEMPORARY` has been enabled, and - if `INCLUDE` has been activated, too - no messages showed up during including the file.

  Note: Never trust freeware-programmers when they start removing your files. So never use `<$exec>` on important data without any backup, and always use `REMOVE="off"` if your data are not really completely temporary.

Additionally, you can use all attributes of `<$include>` that change the appearance of the included data, like `PRE`, `SOURCE` etc. - Of course, this only makes sense if the `INCLUDE`-attribute has been set.

You can set both `INCLUDE` and `ATTRIBUTE` with one call to `<$exec>`.

## Examples

`<$exec COMMAND="dpaint">`
  Invokes Deluxe-Paint. Now you can paint whatever you like. When you quit the program, `hsc` will continue to process it's source. Note that this is not a very useful example.
`<$exec COMMAND="list #?.hsc" TEMPORARY INCLUDE SOURCE PRE>`
  List all hsc-sources in the current directory and include this list into the current document. The output of the `list`-command is redirected to a temporary file, which is removed afterwards.
`<$exec COMMAND="echo Hello! >echo.tmp" TEMPORARY INCLUDE FILE="echo.tmp">`
  List all hsc-sources in the current directory and include this list into the current document. The output of the `list`-command is obviously redirected to a file called echo.tmp, which `hsc` tries to read because of the `FILE`-attribute.
`<$define output:string>`
`<$exec COMMAND="list #?.hsc" ATTRIBUTE="output">`
  List all *.hsc-files in current directory and assign output to the attribute `output`; no data are included into the current document.

## A More Complex Example

If you want to create a portable hsc source to insert a listing of a directory, you could try something like this:

    <$if COND=(HSC.SYSTEM="AMIGA")>
      <$exec COMMAND="list DIRS" TEMPORARY INCLUDE SOURCE PRE>
    <$elseif COND=(HSC.SYSTEM="UNIX")>
      <$exec COMMAND="ls -ld" TEMPORARY INCLUDE SOURCE PRE>
    <$else>
      <$message text="operating system not supported" class="warning">
    </$if>

And the data created by this code sequence would look like this:

    drwxr-xr-x 9 buildd buildd 4096 Apr  4 08:26 .

## Computing Complex Data

As `hsc` is only a simple preprocessor, but not a programming language, it can not do certain things. For example, there are no string functions. But you can use external commands to gain the same result.

The Rexx-script grafflwerk/StripNastyChars.rexx together with grafflwerk/StripNastyChars.hsc shows how to strip all but alpha numeric characters from a given string.

To better understand what StripNastyChars.rexx, you can first try to call it from the command line. Set your working directory to grafflwerk, and type:

    rx StripNastyChars.rexx bla:sülz:fasel

results in

    blaslzfasel

If you tried this yourself, you maybe noticed that the Rexx-script does not output a linefeed at the end of line. This is done by avoiding to use

    SAY stripped

to display the converted data. Instead, you will find a

    call WriteCH(stdout, stripped)

This simply is because StripNastyChars.hsc assigns the output of this script to a target attribute called `clean-data` by means of

    <$exec command=("rx StripNastyChars.rexx " + nasty-data) ATTRIBUTE=clean-data>

Because of obvious reasons, the linefeed character created by `SAY` would be unwanted in the value of the target attribute. Therefor, the interesting part of the created HTML document will look like:

    Converted "This#Text|Contains!Ñâ§ïÿ/Characters"
    to        "ThisTextContainsCharacters".

It should be easy for you to put this functionality in a macro.

## Problems

Technically speaking, `hsc` redirects the output of you command by appending a " `>`filename" to the command-string. For example, if you called

    <$exec COMMAND="list #?.hsc" INCLUDE>

`hsc` will invoke the command like

    list #?.hsc >hsc0x321764.tmp

with hsc0x321764.tmp chosen as temporary output file by `hsc`. If you specify the `FILE` attribute, you tell `hsc` where to expect the output. But now you are responsible to redirect it yourself. For example,

    <$exec COMMAND="list #?.hsc >list.tmp"   INCLUDE FILE="list.tmp">
    <$exec COMMAND="list #?.hsc TO list.tmp" INCLUDE FILE="list.tmp">

will both create an output in list.tmp, where `hsc` will also look for it. But the next one will fail:

    <$exec COMMAND="list #?.hsc >list.tmp" FILE="tmp.list">

The reason is obvious: The command outputs to list.tmp, but `hsc` tries to read tmp.list, which most likely will not exist.

Another problem will occur, if you redirect the output yourself within the command call, but do not specify the `FILE`-attribute: `hsc` will try to redirect the output twice: For example,

    <$exec COMMAND="list #?.hsc >list.tmp" INCLUDE>

will try to invoke something like

    list #?.hsc >list.tmp >hsc0x321764.tmp

The behavior of this call is system dependent, but there's a general statement on this topic: it most likely won't work.