.ig >>
<STYLE TYPE="text/css">
<!--
        A:link{text-decoration:none}
        A:visited{text-decoration:none}
        A:active{text-decoration:none}
        OL,UL,P,BODY,TD,TR,TH,FORM { font-family: arial,helvetica,sans-serif;; font-size:small; color: #333333; }

        H1 { font-size: x-large; font-family: arial,helvetica,sans-serif; }
        H2 { font-size: large; font-family: arial,helvetica,sans-serif; }
        H3 { font-size: medium; font-family: arial,helvetica,sans-serif; }
        H4 { font-size: small; font-family: arial,helvetica,sans-serif; }
-->
</STYLE>
<title>quisp: shell command interface</title>
<body bgcolor=99cc99 vlink=0000FF>
<br>
<br>
<center>
<table cellpadding=2 bgcolor=FFFFFF width=550 ><tr>
<td align=right><a href="quisp_home.html">
<img src="img/quisp2.gif" border=0><br><small>quick server pages</a> &nbsp; &nbsp; </td></tr>
<td>
.>>

.TH shell command interface TDH "01-JUN-2005   TDH scg@jax.org" 

.SH Shell command interface
The \fB#shell\fR directive
provides a convenient facility for invoking shell commands and
capturing/parsing the results, for maximum flexibility in interfacing
with the shell and other programs.  Several
.ig >>
<a href="#examples">
.>>
\0examples
.ig >>
</a>
.>>
are provided below.

.LP
\fBSecurity concern:\fR avoid using user-supplied values (such as CGI user variables, or variables derived from them) when building
shell commands (hackers can do things like drop in \fC|id|\fR or \fC|telnet ..|\fR).  
Where there's no alternative, #shell / #endshell provides 
automatic removal of hazardous shell metacharacters present in variables that are evaluated 
within the \fC#shell / #endshell\fR construct. The developer should verify that this is working as expected.
The following are automatically removed when QUISP variables
are evaluated within a #shell / #endshell construct: \fC " ' ` $ \\ ; | ../ \fR
(this was updated with
.ig >>
<a href="../../download">
.>>
\0patch 1.27-01
.ig >>
</a>
.>>
).
This set of characters is
.ig >>
<a href="config.html">
.>>
\0configurable
.ig >>
</a>
.>>
and also settable dynamically using
.ig >>
<a href="mode.html">
.>>
\0#mode.
.ig >>
</a>
.>>
For this same reason it is also good practice to enclose all shell command arguments in 
double quotes.
Developers must understand this potential security hole and verify that shell metacharacter screening
is indeed working as they want it to, in their application.

.ig >>
<br><br><br>
.>>

.SH #shell - #endshell
Issue a shell command.
The shell command can be one or more lines in length.
QUISP variables and other directives such as \fC#if\fR can be used to build the shell command.
Results can be displayed directly or captured for further processing.
The shell command's exit code is available via 
.ig >>
<a href="#functions">
.>>
\0$shellexitcode()
.ig >>
</a>
.>>
and the number of output lines is available via 
.ig >>
<a href="#functions">
.>>
\0$shellrowcount().
.ig >>
</a>
.>>
.LP
Usage: 
.nf
 \0 #shell [\fImode\fC]
 \0    \fIshellcommand(s)\fR
 \0    ...
 \0 #endshell\fR
.fi

.LP
\fImode\fR may be one of the following:
.IP \0
\fCdump\fR - write the results directly to standard output.  This is the default.
.IP \0
\fCprocessrows\fR - individual result lines will be available via the \fC$shellrow()\fR function.
.IP \0
\fCdumptab\fR - result lines are parsed into fields and written to standard output delimited by tabs.
.IP \0
\fCdumphtml\fR - result lines are parsed into fields and written to standard output as HTML table rows.
.IP \0
\fCdumpsilent\fR - don't display result lines at all, but row count will be available via \fC$shellrowcount\fR.
.LP
Note: \fImode\fR may optionally begin with a pound sign (\fC#\fR) for readability.
.LP
Note: \fC#sql\fR directives cannot be embedded within \fC#shell\fR / \fC#endshell\fR.


.ig >>
<a name=PROJDIR></a>
.>>
.ig >>
<br><br><br>
.>>
.SH @PROJDIR
.LP
The variable \fC@PROJDIR\fR, which is set in your project config file, contains the full
path name of the project directory and may be used to build shell commands that 
reference files therein.

.ig >>
<a name=HTMLPATH></a>
.>>
.ig >>
<br><br>
.>>
.SH @HTMLPATH
The variable \fC@HTMLPATH\fR, which is set in your project config file,
contains the full path name of the directory on your system where static files
such as images reside.  It may be useful when issueing shell commands.


.ig >>
<br><br><br>
.>>
.ig >>
<a name=functions></a>
.>>
.SH Functions
These functions may be used in conjunction with the \fC#shell\fR command:

.ig >>
<br><br>
.>>

.LP
\fB$shellrow( fieldname1, .., fieldnameN )\fR
.IP \0
Get the next line of shell command results and parse into fields.
Result fields are loaded into variables that use names \fIfieldname1 .. fieldnameN\fR.
Returns 0 on success, 1 if no more result lines, or an error code > 1.
.IP \0
If only one fieldname is given, the entire result line will be loaded.
If two or more fieldnames are given, result fields will be delimited on whitespace by default,
or TAB if \fC$shellfielddelim( tab )\fR was called previously, and individual fields will be
loaded into variables.
If \fC$shellreadheader()\fR was called initially to read a result field name header then
no fieldnames should be given with \fC$shellrow()\fR.
.IP \0
You can also use this function to capture \fCtag: value\fR result lines; to do this, use
\fC$shellrow( #varvaluepair )\fR, and values will be loaded into variables named using the tag.


.ig >>
<br><br><br>
.>>
.LP
\fB$shellrowcount( )\fR
.IP \0
Return the number of result rows produced by the most recently invoked shell command.


.ig >>
<br><br><br>
.>>
.LP
\fB$shellexitcode( )\fR
.IP \0
Return the final exit code of the most recently invoked shell command.


.ig >>
<br><br><br>
.>>
.LP
\fB$shellfielddelim( s )\fR
.IP \0
Set the delimitation method for parsing shell command result fields.
Allowable values for \fIs\fR
are \fCtab\fR, \fCwhitespace\fR, or \fCline\fR (which takes the entire
line, without trailing newline, as a field).  
.IP \0
Example: \fC#call shellfielddelim( whitespace )\fR

.ig >>
<br><br><br>
.>>
.LP
\fB$shellfieldconvert( convertmode )\fR
.IP
Perform conversions on shell command result fields.
Currently the only supported \fCconvertmode\fR is \fCshsql\fR,
which causes conversions useful when using shell commands to process
shsql data files (nulls are converted to zero-length strings, and
embedded underscores are converted to spaces).
.IP \0
Example: \fC#call $shellfieldconvert( shsql )\fR

.ig >>
<br><br><br>
.>>
.LP
\fB$shellreadheader( )\fR
.IP \0
For shell commands that produce output where the first line contains field names,
this function can be used to load the header.  Afterwards, \fC$shellrow()\fR,
if it is passed no arguments, will load fields into variables based on the header.
.IP \0
Example:
.nf
\0 #shell
\0   mycommand
\0 #endshell
\0 #shellreadheader()
\0 #while $shellrow() = 0
\0   ...
.fi


.ig >>
<br><br><br>
.>>
.ig >>
<a name=examples></a>
.>>
.SH Examples

.LP
\fBExample 1.  Get a numeric value out of the last line of a file and multiply it by 1.25:\fR
.nf
\0 #shell processrows
\0   tail -1 today.dat | cut -f 3
\0 #endshell
\0 #call $shellrow(TODAY_TOTAL)
\0 #set MAX = $arith(@TODAY_TOTAL*1.25)
.fi

\fBExample 2. Invoke a grep command and display the results:\fR
.nf
 \0 #set searchword = "macula"
 \0 <pre>
 \0 #shell 
 \0   grep "@searchword" /home/steve/textfiles/*
 \0 #endshell
 \0 </pre>
 \0 #if $shellrowcount() != 0
 \0  <h3>Nothing found</h3>
 \0 #endif
.fi

.LP
\fBExample 3. Same as above but add a sed command and display results as HTML table rows:\fR
.nf
 \0 #set searchword = "macula"
 \0 <table cellpadding=2>
 \0 #shell dumphtml
 \0   grep "@searchword" /home/steve/textfiles/* |
 \0    sed "s/^.*://"
 \0 #endshell
 \0 </table>
 \0 #if $shellrowcount() != 0
 \0  <h3>Nothing found</h3>
 \0 #endif
.fi

.LP
\fBExample 4. Invoke a command that computes correlations and process the results one row at a time:\fR
.nf
  \0 #shell processrows
  \0   correlate all
  \0 #endshell
  \0 <table cellpadding=2>
  \0 #while $shellrow( var1, var2, pearson, n ) == 0 
  \0   <tr><td>@var1</td><td>@var2</td><td>@pearson</td><td>N = @n</td></tr>
  \0 #endloop
  \0 </table>
  \0 #if $shellrowcount() < 1 
  \0   <h3>No correlations computed</h3>
  \0 #endif
.fi

.LP
\fBExample 5. Invoke a shell command and capture its exit code:\fR
.nf
  \0 #shell
  \0   addlog @DATE @TIME @READING
  \0 #endshell
  \0 #if $shellexitcode() != 0
  \0   <h3>Addlog failed!</h3>
  \0 #endif
.fi

.ig >>
<br>
<br>
</td></tr>
<td align=right>
<a href="quisp_home.html">
<img src="img/quisp2.gif" border=0></a><br>
<small>quick server pages &nbsp; &nbsp;<br>
<a href="Copyright.html">Copyright Steve Grubb</a> &nbsp; &nbsp;
</td></tr>
</table>
.>>
