cdev-1.7.2n

This commit is contained in:
2022-12-13 12:44:04 +01:00
commit b3b88fc333
1357 changed files with 338883 additions and 0 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 948 B

View File

@@ -0,0 +1,948 @@
<! This document generated using mif2html Version 1.0 - Walt Akers - 1996 !>
<head>
<title>CDEV Script Service</title>
</head>
<body bgcolor="#E0E0FF">
<body>
<! ************************ FILE : cdevScriptServiceTITLE.mif *****************************!>
<br><hr><br>
<table width=100%>
<tr><td>
<! ***** Empty Column ***** !>
</td>
<td valign=top>
<!*** Start ADDRESS-VERSION ***!><font size=+2 color=Black>
CDEV Script Service
</p>
</p>
A Tool for Using Interactive Scripts from CDEV
</p>
</p>
Walt Akers
</p>
</p>
Version 1.0 February 11, 1997
</p>
</p>
TJNAF - Thomas Jefferson National Accelerator Facility
</p>
<!*** Finish ADDRESS-VERSION ***!></p></font>
</td></tr>
</table>
<! *************************** TABLE OF CONTENTS ****************************!>
<br><hr><br>
<table width=100%>
<tr><td>
<! ***** Empty Column ***** !>
</td>
<td valign=top align=center>
<!*** Start CLASS-TOC-TITLE ***!><font size=+3><strong>
Table of Contents
<!*** Finish CLASS-TOC-TITLE ***!></p></strong></font>
</td></tr>
<tr><td>
<! ***** Empty Column ***** !>
</td>
<td valign=top>
<table>
<tr><td valign=top align=right>
<!*** Start HEADING1TOC ***!><font size=+1 color=Black>
1.
<!*** Finish HEADING1TOC ***!><br></font>
</td>
<td valign=top>
<!*** Start HEADING1TOC ***!><font size=+1 color=Black>
<a href="cdevScriptService.html#TOCREF1">Script Service Fundamentals</a>
<!*** Finish HEADING1TOC ***!><br></font>
</td></tr>
<tr><td valign=top>
<!*** Start UHEADING2TOC ***!><font size=+1 color=Black>
<!*** Finish UHEADING2TOC ***!><br></font>
</td>
<td valign=top>
<!*** Start UHEADING2TOC ***!><font size=+1 color=Black>
<a href="cdevScriptService.html#TOCREF2">Overview of the Script Service</a>
<!*** Finish UHEADING2TOC ***!><br></font>
</td></tr>
<tr><td valign=top>
<!*** Start UHEADING2TOC ***!><font size=+1 color=Black>
<!*** Finish UHEADING2TOC ***!><br></font>
</td>
<td valign=top>
<!*** Start UHEADING2TOC ***!><font size=+1 color=Black>
<a href="cdevScriptService.html#TOCREF3">Features of the Script Service</a>
<!*** Finish UHEADING2TOC ***!><br></font>
</td></tr>
<tr><td valign=top align=right>
<!*** Start HEADING1TOC ***!><font size=+1 color=Black>
2.
<!*** Finish HEADING1TOC ***!><br></font>
</td>
<td valign=top>
<!*** Start HEADING1TOC ***!><font size=+1 color=Black>
<a href="cdevScriptService.html#TOCREF4">Building the Script Service</a>
<!*** Finish HEADING1TOC ***!><br></font>
</td></tr>
<tr><td valign=top>
<!*** Start UHEADING2TOC ***!><font size=+1 color=Black>
<!*** Finish UHEADING2TOC ***!><br></font>
</td>
<td valign=top>
<!*** Start UHEADING2TOC ***!><font size=+1 color=Black>
<a href="cdevScriptService.html#TOCREF5">Location of Files</a>
<!*** Finish UHEADING2TOC ***!><br></font>
</td></tr>
<tr><td valign=top>
<!*** Start UHEADING2TOC ***!><font size=+1 color=Black>
<!*** Finish UHEADING2TOC ***!><br></font>
</td>
<td valign=top>
<!*** Start UHEADING2TOC ***!><font size=+1 color=Black>
<a href="cdevScriptService.html#TOCREF6">Steps to Building Service</a>
<!*** Finish UHEADING2TOC ***!><br></font>
</td></tr>
<tr><td valign=top align=right>
<!*** Start HEADING1TOC ***!><font size=+1 color=Black>
3.
<!*** Finish HEADING1TOC ***!><br></font>
</td>
<td valign=top>
<!*** Start HEADING1TOC ***!><font size=+1 color=Black>
<a href="cdevScriptService.html#TOCREF7">Structure of Data Provided to the Script</a>
<!*** Finish HEADING1TOC ***!><br></font>
</td></tr>
<tr><td valign=top>
<!*** Start UHEADING2TOC ***!><font size=+1 color=Black>
<!*** Finish UHEADING2TOC ***!><br></font>
</td>
<td valign=top>
<!*** Start UHEADING2TOC ***!><font size=+1 color=Black>
<a href="cdevScriptService.html#TOCREF8">General Form of Data String</a>
<!*** Finish UHEADING2TOC ***!><br></font>
</td></tr>
<tr><td valign=top>
<!*** Start UHEADING2TOC ***!><font size=+1 color=Black>
<!*** Finish UHEADING2TOC ***!><br></font>
</td>
<td valign=top>
<!*** Start UHEADING2TOC ***!><font size=+1 color=Black>
<a href="cdevScriptService.html#TOCREF9">Representation of Scalar Data</a>
<!*** Finish UHEADING2TOC ***!><br></font>
</td></tr>
<tr><td valign=top>
<!*** Start UHEADING2TOC ***!><font size=+1 color=Black>
<!*** Finish UHEADING2TOC ***!><br></font>
</td>
<td valign=top>
<!*** Start UHEADING2TOC ***!><font size=+1 color=Black>
<a href="cdevScriptService.html#TOCREF10">Representation of Array Data</a>
<!*** Finish UHEADING2TOC ***!><br></font>
</td></tr>
<tr><td valign=top align=right>
<!*** Start HEADING1TOC ***!><font size=+1 color=Black>
4.
<!*** Finish HEADING1TOC ***!><br></font>
</td>
<td valign=top>
<!*** Start HEADING1TOC ***!><font size=+1 color=Black>
<a href="cdevScriptService.html#TOCREF11">Structure of Data Returned from the Script</a>
<!*** Finish HEADING1TOC ***!><br></font>
</td></tr>
<tr><td valign=top>
<!*** Start UHEADING2TOC ***!><font size=+1 color=Black>
<!*** Finish UHEADING2TOC ***!><br></font>
</td>
<td valign=top>
<!*** Start UHEADING2TOC ***!><font size=+1 color=Black>
<a href="cdevScriptService.html#TOCREF12">Returning Data to the Calling CDEV Application</a>
<!*** Finish UHEADING2TOC ***!><br></font>
</td></tr>
<tr><td valign=top>
<!*** Start UHEADING2TOC ***!><font size=+1 color=Black>
<!*** Finish UHEADING2TOC ***!><br></font>
</td>
<td valign=top>
<!*** Start UHEADING2TOC ***!><font size=+1 color=Black>
<a href="cdevScriptService.html#TOCREF13">General Form of String Data </a>
<!*** Finish UHEADING2TOC ***!><br></font>
</td></tr>
<tr><td valign=top>
<!*** Start UHEADING2TOC ***!><font size=+1 color=Black>
<!*** Finish UHEADING2TOC ***!><br></font>
</td>
<td valign=top>
<!*** Start UHEADING2TOC ***!><font size=+1 color=Black>
<a href="cdevScriptService.html#TOCREF14">Returning a Single Result Packet </a>
<!*** Finish UHEADING2TOC ***!><br></font>
</td></tr>
<tr><td valign=top>
<!*** Start UHEADING2TOC ***!><font size=+1 color=Black>
<!*** Finish UHEADING2TOC ***!><br></font>
</td>
<td valign=top>
<!*** Start UHEADING2TOC ***!><font size=+1 color=Black>
<a href="cdevScriptService.html#TOCREF15">Returning Multiple Result Packets </a>
<!*** Finish UHEADING2TOC ***!><br></font>
</td></tr>
<tr><td valign=top>
<!*** Start UHEADING2TOC ***!><font size=+1 color=Black>
<!*** Finish UHEADING2TOC ***!><br></font>
</td>
<td valign=top>
<!*** Start UHEADING2TOC ***!><font size=+1 color=Black>
<a href="cdevScriptService.html#TOCREF16">Special Considerations</a>
<!*** Finish UHEADING2TOC ***!><br></font>
</td></tr>
<tr><td valign=top align=right>
<!*** Start HEADING1TOC ***!><font size=+1 color=Black>
5.
<!*** Finish HEADING1TOC ***!><br></font>
</td>
<td valign=top>
<!*** Start HEADING1TOC ***!><font size=+1 color=Black>
<a href="cdevScriptService.html#TOCREF17">DDL Entries for the Script Service</a>
<!*** Finish HEADING1TOC ***!><br></font>
</td></tr>
<tr><td valign=top>
<!*** Start UHEADING2TOC ***!><font size=+1 color=Black>
<!*** Finish UHEADING2TOC ***!><br></font>
</td>
<td valign=top>
<!*** Start UHEADING2TOC ***!><font size=+1 color=Black>
<a href="cdevScriptService.html#TOCREF18">Setting Up the DDL </a>
<!*** Finish UHEADING2TOC ***!><br></font>
</td></tr>
</table>
</td></tr>
</table>
<! **************************** LIST OF FIGURES *****************************!>
<br><hr><br>
<table width=100%>
<tr><td>
<! ***** Empty Column ***** !>
</td>
<td valign=top align=center>
<!*** Start CLASS-LOF-TITLE ***!><font size=+3><strong>
List of Figures
<!*** Finish CLASS-LOF-TITLE ***!></p></strong></font>
</td></tr>
<tr><td>
<! ***** Empty Column ***** !>
</td>
<td valign=top>
<!*** Start FIGURELOF ***!><font size=+1 color=Black>
Figure 7:
<a href="cdevScriptService.html#LOFREF1">General form of string representation of cdevData</a>
<!*** Finish FIGURELOF ***!><br></font>
<!*** Start FIGURELOF ***!><font size=+1 color=Black>
Figure 8:
<a href="cdevScriptService.html#LOFREF2">String representation of scalar data in a cdevData object</a>
<!*** Finish FIGURELOF ***!><br></font>
<!*** Start FIGURELOF ***!><font size=+1 color=Black>
Figure 9:
<a href="cdevScriptService.html#LOFREF3">String representation of array data</a>
<!*** Finish FIGURELOF ***!><br></font>
<!*** Start FIGURELOF ***!><font size=+1 color=Black>
Figure 10:
<a href="cdevScriptService.html#LOFREF4">Returning a single result packet to the CDEV application</a>
<!*** Finish FIGURELOF ***!><br></font>
<!*** Start FIGURELOF ***!><font size=+1 color=Black>
Figure 11:
<a href="cdevScriptService.html#LOFREF5">Returning a multiple result packets to the CDEV application</a>
<!*** Finish FIGURELOF ***!><br></font>
<!*** Start FIGURELOF ***!><font size=+1 color=Black>
Figure 12:
<a href="cdevScriptService.html#LOFREF6">Simple DDL file for the Script Service</a>
<!*** Finish FIGURELOF ***!><br></font>
</td></tr>
</table>
<! ************************ FILE : ./cdevScriptService.mif *****************************!>
<br><hr><br>
<table width=100%>
<tr><td valign=top align=right>
<!*** Start HEADING1 ***!><font size=+3 color=Black><strong>
1.
<!*** Finish HEADING1 ***!></p></strong></font>
</td>
<td valign=top>
<!*** Start HEADING1 ***!><font size=+3 color=Black><strong>
<a name="TOCREF1">
Script Service Fundamentals
</a> <!*** Finish HEADING1 ***!></p></strong></font>
</td></tr>
<tr><td valign=top>
<!*** Start UHEADING2 ***!><font size=+1 color=Black><strong>
<a name="TOCREF2">
Overview of the
Script Service
</a> <!*** Finish UHEADING2 ***!></p></strong></font>
</td>
<td valign=top>
<!*** Start BODY ***!><font size=+1 color=Black>
The CDEV Script Service is designed to allow a a CDEV application to execute an
external script to process a message. The output that is produced by the executable
will be returned to the caller in the form of a cdevData. The CDEV Script Service
meets the following requirements.
<!*** Finish BODY ***!></p></font>
</td></tr>
<tr><td valign=top>
<!*** Start UHEADING2 ***!><font size=+1 color=Black><strong>
<a name="TOCREF3">
Features of the
Script Service
</a> <!*** Finish UHEADING2 ***!></p></strong></font>
</td>
<td valign=top>
<table>
<tr><td valign=top>
<!*** Start BULLETED ***!><font size=+1 color=Black>
<img src="bullet.jpg">
<!*** Finish BULLETED ***!></p></font>
</td>
<td valign=top>
<!*** Start BULLETED ***!><font size=+1 color=Black>
The filename of the script is associated with a CDEV device/message
combination by using the &quot;filename&quot; field of the class-data in the CDEV DDL file.
Syntax is described later in this document.
<!*** Finish BULLETED ***!></p></font>
</td></tr>
<tr><td valign=top>
<!*** Start BULLETED ***!><font size=+1 color=Black>
<img src="bullet.jpg">
<!*** Finish BULLETED ***!></p></font>
</td>
<td valign=top>
<!*** Start BULLETED ***!><font size=+1 color=Black>
A new process will be spawned for the script each time it is executed. Its standard
output (stdout) file descriptor will be redirected to return data to the main CDEV
application, allowing the script to return results to the parent process.
<!*** Finish BULLETED ***!></p></font>
</td></tr>
<tr><td valign=top>
<!*** Start BULLETED ***!><font size=+1 color=Black>
<img src="bullet.jpg">
<!*** Finish BULLETED ***!></p></font>
</td>
<td valign=top>
<!*** Start BULLETED ***!><font size=+1 color=Black>
The external executable file can be any form of user shell, batch file or binary
application that is supported on the host platform.
<!*** Finish BULLETED ***!></p></font>
</td></tr>
<tr><td valign=top>
<!*** Start BULLETED ***!><font size=+1 color=Black>
<img src="bullet.jpg">
<!*** Finish BULLETED ***!></p></font>
</td>
<td valign=top>
<!*** Start BULLETED ***!><font size=+1 color=Black>
The Script Service supports all of CDEV's send mechanisms; &quot;send&quot;,
&quot;sendNoBlock&quot; and &quot;sendCallback&quot;. Because of limits imposed on the number of
active processes, the user is advised to use the synchronous &quot;send&quot; method
whenever practical.
<!*** Finish BULLETED ***!></p></font>
</td></tr>
<tr><td valign=top>
<!*** Start BULLETED ***!><font size=+1 color=Black>
<img src="bullet.jpg">
<!*** Finish BULLETED ***!></p></font>
</td>
<td valign=top>
<!*** Start BULLETED ***!><font size=+1 color=Black>
When called by CDEV, the script will receive three arguments; the name of the
CDEV device associated with the request, the message string that was submitted
to the device, and a string that describes the contents of the outbound cdevData
object.
<!*** Finish BULLETED ***!></p></font>
</td></tr>
<tr><td valign=top>
<!*** Start BULLETED ***!><font size=+1 color=Black>
<img src="bullet.jpg">
<!*** Finish BULLETED ***!></p></font>
</td>
<td valign=top>
<!*** Start BULLETED ***!><font size=+1 color=Black>
The reply that is written to the standard output by the script must have a specific
format as described later in this document. A script may return more than one
reply packet to the caller.
<!*** Finish BULLETED ***!></p></font>
</td></tr>
<tr><td valign=top>
<!*** Start BULLETED ***!><font size=+1 color=Black>
<img src="bullet.jpg">
<!*** Finish BULLETED ***!></p></font>
</td>
<td valign=top>
<!*** Start BULLETED ***!><font size=+1 color=Black>
The script notifies CDEV that it has written its last reply packet by writing &quot;done&quot;
alone on a line to the standard output.
<!*** Finish BULLETED ***!></p></font>
</td></tr>
<tr><td valign=top>
<!*** Start BULLETED ***!><font size=+1 color=Black>
<img src="bullet.jpg">
<!*** Finish BULLETED ***!></p></font>
</td>
<td valign=top>
<!*** Start BULLETED ***!><font size=+1 color=Black>
If the script is to return multiple results, it should write &quot;end&quot; alone on a line to the
standard output between each packet, and write &quot;done&quot; alone on a line following
the last packet.
<!*** Finish BULLETED ***!></p></font>
</td></tr>
<tr><td valign=top>
<!*** Start BULLETED ***!><font size=+1 color=Black>
<img src="bullet.jpg">
<!*** Finish BULLETED ***!></p></font>
</td>
<td valign=top>
<!*** Start BULLETED ***!><font size=+1 color=Black>
If the script returns a value in the &quot;status&quot; tag of its reply packet, this will be
provided to the caller as the completion code of the message. Traditionally a
status of 0 indicates success, and all other values indicated an error occurred.
<!*** Finish BULLETED ***!></p></font>
</td></tr>
<tr><td valign=top>
<!*** Start BULLETED ***!><font size=+1 color=Black>
<img src="bullet.jpg">
<!*** Finish BULLETED ***!></p></font>
</td>
<td valign=top>
<!*** Start BULLETED ***!><font size=+1 color=Black>
Because the callback mechanism of the Script Service is triggered by output from
the script, the script developer should at least write &quot;done&quot; to the standard output
even if the application returns no output.
<!*** Finish BULLETED ***!></p></font>
</td></tr>
</table>
</td></tr>
<tr><td valign=top align=right>
<!*** Start HEADING1 ***!><font size=+3 color=Black><strong>
2.
<!*** Finish HEADING1 ***!></p></strong></font>
</td>
<td valign=top>
<!*** Start HEADING1 ***!><font size=+3 color=Black><strong>
<a name="TOCREF4">
Building the Script Service
</a> <!*** Finish HEADING1 ***!></p></strong></font>
</td></tr>
<tr><td valign=top>
<!*** Start UHEADING2 ***!><font size=+1 color=Black><strong>
<a name="TOCREF5">
Location of Files
</a> <!*** Finish UHEADING2 ***!></p></strong></font>
</td>
<td valign=top>
<!*** Start BODY ***!><font size=+1 color=Black>
The source code for the Script Service is provided with the CDEV distribution starting
with version 1.5. The source code is located in the directory $CDEV/extensions/
ScriptService. The following steps should be taken to build the ScriptService.
<!*** Finish BODY ***!></p></font>
</td></tr>
<tr><td valign=top>
<!*** Start UHEADING2 ***!><font size=+1 color=Black><strong>
<a name="TOCREF6">
Steps to Building
Service
</a> <!*** Finish UHEADING2 ***!></p></strong></font>
</td>
<td valign=top>
<table>
<tr><td valign=top>
<!*** Start NUMBERED ***!><font size=+1 color=Black>
1.
<!*** Finish NUMBERED ***!></p></font>
</td>
<td valign=top>
<!*** Start NUMBERED ***!><font size=+1 color=Black>
Obtain and install the CDEV distribution - Version 1.5 or higher.
<!*** Finish NUMBERED ***!></p></font>
</td></tr>
<tr><td valign=top>
<!*** Start NUMBERED ***!><font size=+1 color=Black>
2.
<!*** Finish NUMBERED ***!></p></font>
</td>
<td valign=top>
<!*** Start NUMBERED ***!><font size=+1 color=Black>
Follow the installation steps to build CDEV on your system. This includes setting
all of the environment variables required by CDEV.
<!*** Finish NUMBERED ***!></p></font>
</td></tr>
<tr><td valign=top>
<!*** Start NUMBERED ***!><font size=+1 color=Black>
3.
<!*** Finish NUMBERED ***!></p></font>
</td>
<td valign=top>
<!*** Start NUMBERED ***!><font size=+1 color=Black>
Change directories to <em>$CDEV/extensions/ScriptService/src</em>.
<!*** Finish NUMBERED ***!></p></font>
</td></tr>
<tr><td valign=top>
<!*** Start NUMBERED ***!><font size=+1 color=Black>
4.
<!*** Finish NUMBERED ***!></p></font>
</td>
<td valign=top>
<!*** Start NUMBERED ***!><font size=+1 color=Black>
There is a collection of platform specific makefiles in the directory <em>$CDEV/
extensions/cdevGenericServer/include/makeinclude</em>. Link the makefile that is
appropriate to your architecture to the file Makefile.OS.
<!*** Finish NUMBERED ***!></p></font>
<!*** Start INDENTED ***!><font size=+1 color=Black>
For example, to link to the makefile for HP-UX, you would type the following
command.
</p>
</p>
<em>ln -s Makefile.hpux Makefile.OS</em>
</p>
<!*** Finish INDENTED ***!></p></font>
</td></tr>
<tr><td valign=top>
<!*** Start NUMBERED ***!><font size=+1 color=Black>
5.
<!*** Finish NUMBERED ***!></p></font>
</td>
<td valign=top>
<!*** Start NUMBERED ***!><font size=+1 color=Black>
Type make to compile and link the Script Service shared object. Note that you
must be using GNU make in order to build this distribution.
<!*** Finish NUMBERED ***!></p></font>
</td></tr>
</table>
<!*** Start BODY ***!><font size=+1 color=Black>
Upon completion the Makefile will generate the shared object for the Script Service
and will install it into your CDEVSHOBJ directory. At this point you are ready to use
the Script Service.
<!*** Finish BODY ***!></p></font>
</td></tr>
<tr><td valign=top align=right>
<!*** Start HEADING1 ***!><font size=+3 color=Black><strong>
3.
<!*** Finish HEADING1 ***!></p></strong></font>
</td>
<td valign=top>
<!*** Start HEADING1 ***!><font size=+3 color=Black><strong>
<a name="TOCREF7">
Structure of Data Provided to the Script
</a> <!*** Finish HEADING1 ***!></p></strong></font>
</td></tr>
<tr><td valign=top>
<!*** Start UHEADING2 ***!><font size=+1 color=Black><strong>
<a name="TOCREF8">
General Form of
Data String
</a> <!*** Finish UHEADING2 ***!></p></strong></font>
</td>
<td valign=top>
<!*** Start BODY ***!><font size=+1 color=Black>
When a developer makes a CDEV send call, he may provide outbound data in the
form of a cdevData object. Before calling the script, this data is converted into a string
and provided as the third argument to the application (the first argument is the device
name and the second is the message). The structure of the outbound data string is of
the following form.
</p>
<!*** Finish BODY ***!></p></font>
<!*** Start FIGURE ***!><font size=+0 color=Black><em>
Figure 7:
<a name="LOFREF1">
General form of string representation of cdevData
<table border=1><tr><td>
<table>
<tr><td>
<! ***** Empty Column ***** !>
</td>
<td valign=top>
<!*** Start PROGRAM ***!><pre><font size=+0 color=Black><strong><em>
tag1=&quot;string value&quot;
tag2=1.00
<!*** Finish PROGRAM ***!></strong></em></font></pre>
</td></tr>
</table>
</tr></td></table>
<AFrame 13>
</a> <!*** Finish FIGURE ***!></p></em></font>
<!*** Start BODY ***!><font size=+1 color=Black>
<!*** Finish BODY ***!></p></font>
</td></tr>
<tr><td valign=top>
<!*** Start UHEADING2 ***!><font size=+1 color=Black><strong>
<a name="TOCREF9">
Representation of
Scalar Data
</a> <!*** Finish UHEADING2 ***!></p></strong></font>
</td>
<td valign=top>
<!*** Start BODY ***!><font size=+1 color=Black>
The above example shows two data entries of the form <em>tag=value</em>. Each entry is
separated by a carriage return. The first entry has a tag name of <em>'tag1'</em> and a value of
<em>'string value'</em>. You will note that <em>'string value'</em> is enclosed in double quotes in the
example. This is used to notify the script that the value is a non-numeric character
string. In the second data entry the value <em>'1.0' </em>is not enclosed in quotes, indicating that
the value is a number.
</p>
The following example illustrates how scalar values stored in a cdevData object would
look when they are passed to the script.
</p>
<!*** Finish BODY ***!></p></font>
<!*** Start FIGURE ***!><font size=+0 color=Black><em>
Figure 8:
<a name="LOFREF2">
String representation of scalar data in a cdevData object
<table border=1><tr><td>
<table>
<tr><td>
<! ***** Empty Column ***** !>
</td>
<td valign=top>
<!*** Start PROGRAM ***!><pre><font size=+0 color=Black><strong><em>
Data stored in cdevData object:
Tag: value
Data Type: character string
Value: Test
Tag: status
Data Type: integer
Value: 0
Tag: controlHigh
Data Type: double
Value: 1.001
String representation provided to script:
value=&quot;Test&quot;\\n
status=0\\n
controlHigh=1.001\\n
<!*** Finish PROGRAM ***!></strong></em></font></pre>
</td></tr>
</table>
</tr></td></table>
<AFrame 1>
</a> <!*** Finish FIGURE ***!></p></em></font>
<!*** Start BODY ***!><font size=+1 color=Black>
<!*** Finish BODY ***!></p></font>
</td></tr>
<tr><td valign=top>
<!*** Start UHEADING2 ***!><font size=+1 color=Black><strong>
<a name="TOCREF10">
Representation of
Array Data
</a> <!*** Finish UHEADING2 ***!></p></strong></font>
</td>
<td valign=top>
<!*** Start BODY ***!><font size=+1 color=Black>
If array data is stored in the outbound cdevData object, it too can be provided to the
script. The data is structured in the standard C format where opening and closing
braces mark the beginning and end (respectively) of each array bound. The following
example illustrates how various arrays would be represented as strings.
<!*** Finish BODY ***!></p></font>
<!*** Start FIGURE ***!><font size=+0 color=Black><em>
Figure 9:
<a name="LOFREF3">
String representation of array data
<table border=1><tr><td>
<table>
<tr><td>
<! ***** Empty Column ***** !>
</td>
<td valign=top>
<!*** Start PROGRAM ***!><pre><font size=+0 color=Black><strong><em>
Data stored in cdevData object:
Tag: value
Data Type: character string [3]
Value: &quot;value1&quot; &quot;value2&quot; &quot;value3&quot;
String representation provided to script:
value={&quot;value1&quot;,&quot;value2&quot;,&quot;value3&quot;}\\n
<AFrame 5>
Data stored in cdevData object:
Tag: value
Data Type: double [3]
Value: 1.0, 2.0, 3.01
String representation provided to script:
value={1,2,3.01}\\n
<AFrame 6>
Data stored in cdevData object:
Tag: value
Data Type: double [3][2]
Value: 1.0, 2.0, 3.0, 4.0, 5.0, 6.0
String representation provided to script:
value={{1,2},{3,4},{5,6}}\\n
<!*** Finish PROGRAM ***!></strong></em></font></pre>
</td></tr>
</table>
</tr></td></table>
<AFrame 3>
</a> <!*** Finish FIGURE ***!></p></em></font>
</td></tr>
<tr><td valign=top align=right>
<!*** Start HEADING1 ***!><font size=+3 color=Black><strong>
4.
<!*** Finish HEADING1 ***!></p></strong></font>
</td>
<td valign=top>
<!*** Start HEADING1 ***!><font size=+3 color=Black><strong>
<a name="TOCREF11">
Structure of Data Returned from the Script
</a> <!*** Finish HEADING1 ***!></p></strong></font>
</td></tr>
<tr><td valign=top>
<!*** Start UHEADING2 ***!><font size=+1 color=Black><strong>
<a name="TOCREF12">
Returning Data to
the Calling CDEV
Application
</a> <!*** Finish UHEADING2 ***!></p></strong></font>
</td>
<td valign=top>
<!*** Start BODY ***!><font size=+1 color=Black>
Before CDEV starts the script, it creates a pipe that is used to pass data between the
script and the CDEV application. One end of this pipe is maintained by the application
and the other end of the pipe is provided to the script as its standard output. This
means that anytime the script uses the &quot;echo&quot; command or the &quot;printf&quot; command, the
data that it output's will be transmitted through the pipe to the parent application.
</p>
The script is responsible for formatting the data into a collection of character strings
that can be recognized by the CDEV application.
<!*** Finish BODY ***!></p></font>
</td></tr>
<tr><td valign=top>
<!*** Start UHEADING2 ***!><font size=+1 color=Black><strong>
<a name="TOCREF13">
General Form of
String Data
</a> <!*** Finish UHEADING2 ***!></p></strong></font>
</td>
<td valign=top>
<!*** Start BODY ***!><font size=+1 color=Black>
In general, the data that is returned from a script is of the same form as described in
the preceding section, &quot;<em>Structure of Data Provided to the Script</em>&quot;. The most notable
difference is that the script must terminate the list by providing a character string that
indicates that the group of data items is complete; the string &quot;<em>end</em>&quot; or &quot;<em>done</em>&quot; alone on
a line.
<!*** Finish BODY ***!></p></font>
</td></tr>
<tr><td valign=top>
<!*** Start UHEADING2 ***!><font size=+1 color=Black><strong>
<a name="TOCREF14">
Returning a
Single Result
Packet
</a> <!*** Finish UHEADING2 ***!></p></strong></font>
</td>
<td valign=top>
<!*** Start BODY ***!><font size=+1 color=Black>
If the script is going to return exactly one result packet (<em>a group of tags and values that
will be used to populate the result cdevData</em>), then it should write the string &quot;<em>done</em>&quot; on
a line by itself immediately following the output data. This will notify the Script Service
that no more data will be returned from the script.
</p>
The following example shows how a single result will be returned from a script. Note
that the &quot;status&quot; tag contains the completion code that will be returned to the CDEV
application.
<!*** Finish BODY ***!></p></font>
<!*** Start FIGURE ***!><font size=+0 color=Black><em>
Figure 10:
<a name="LOFREF4">
Returning a single result packet to the CDEV application
<table border=1><tr><td>
<table>
<tr><td>
<! ***** Empty Column ***** !>
</td>
<td valign=top>
<!*** Start PROGRAM ***!><pre><font size=+0 color=Black><strong><em>
#\\! /bin/csh -f
echo value=\\&quot;Test\\&quot;
echo status=0
echo controlLow=1.5
echo controlHigh=25.1
echo done
<!*** Finish PROGRAM ***!></strong></em></font></pre>
</td></tr>
</table>
</tr></td></table>
<AFrame 7>
</a> <!*** Finish FIGURE ***!></p></em></font>
</td></tr>
<tr><td valign=top>
<!*** Start UHEADING2 ***!><font size=+1 color=Black><strong>
<a name="TOCREF15">
Returning
Multiple Result
Packets
</a> <!*** Finish UHEADING2 ***!></p></strong></font>
</td>
<td valign=top>
<!*** Start BODY ***!><font size=+1 color=Black>
Returning multiple results from a single script execution is not generally advised.
However, If the script is going to return more than one result packet, then each interim
packet should be terminated by the &quot;<em>end</em>&quot; keyword on a line by itself. The &quot;<em>done</em>&quot;
keyword should follow the last entry.
</p>
The following example shows how two results will be returned from a script.
<!*** Finish BODY ***!></p></font>
<!*** Start FIGURE ***!><font size=+0 color=Black><em>
Figure 11:
<a name="LOFREF5">
Returning a multiple result packets to the CDEV application
<table border=1><tr><td>
<table>
<tr><td>
<! ***** Empty Column ***** !>
</td>
<td valign=top>
<!*** Start PROGRAM ***!><pre><font size=+0 color=Black><strong><em>
#\\! /bin/csh -f
echo value=\\&quot;Start Result 1\\&quot;
echo status=0
echo end
echo value=\\&quot;Start Result 2\\&quot;
echo status=-1
echo done
<!*** Finish PROGRAM ***!></strong></em></font></pre>
</td></tr>
</table>
</tr></td></table>
<AFrame 9>
</a> <!*** Finish FIGURE ***!></p></em></font>
</td></tr>
<tr><td valign=top>
<!*** Start UHEADING2 ***!><font size=+1 color=Black><strong>
<a name="TOCREF16">
Special
Considerations
</a> <!*** Finish UHEADING2 ***!></p></strong></font>
</td>
<td valign=top>
<!*** Start BODY ***!><font size=+1 color=Black>
If the script that is being executed will not return a result, then the developer should
still write &quot;<em>done&quot;</em> to the standard output in order to notify the CDEV application that it
should no longer wait for output. If the script is not returning a result, it may write the
terminating <em>&quot;done&quot;</em> at the beginning of the script or at the end. Because synchronous
calls will block until a reply is received, the developer should return a result to the
CDEV application as quickly as possible.
</p>
If the developer never writes anything to the standard output, then the user specified
CDEV callback will never be executed... therefore, it is crucial to notify the CDEV
application when the script has completed.
<!*** Finish BODY ***!></p></font>
</td></tr>
<tr><td valign=top align=right>
<!*** Start HEADING1 ***!><font size=+3 color=Black><strong>
5.
<!*** Finish HEADING1 ***!></p></strong></font>
</td>
<td valign=top>
<!*** Start HEADING1 ***!><font size=+3 color=Black><strong>
<a name="TOCREF17">
DDL Entries for the Script Service
</a> <!*** Finish HEADING1 ***!></p></strong></font>
</td></tr>
<tr><td valign=top>
<!*** Start UHEADING2 ***!><font size=+1 color=Black><strong>
<a name="TOCREF18">
Setting Up the
DDL
</a> <!*** Finish UHEADING2 ***!></p></strong></font>
</td>
<td valign=top>
<!*** Start BODY ***!><font size=+1 color=Black>
The following example illustrates how to add a service entry to identify the Script
Service and how to use the class-data to specify the filename that the Script Service
will execute to service a message.
<!*** Finish BODY ***!></p></font>
<!*** Start FIGURE ***!><font size=+0 color=Black><em>
Figure 12:
<a name="LOFREF6">
Simple DDL file for the Script Service
<table border=1><tr><td>
<table>
<tr><td>
<! ***** Empty Column ***** !>
</td>
<td valign=top>
<!*** Start PROGRAM ***!><pre><font size=+0 color=Black><strong><em>
/*
* This is the service definition, it tells CDEV that there is
* a service named Script and that it will use the cdevData
* tag 'filename' to read configuration information from the
* DDL file entries.
*/
service Script
{
tags {filename}
}
/*
* This class definition identifies the class scriptClass which
* supports the &quot;get and &quot;set&quot; commands on attributes &quot;attrib0&quot;
* and &quot;attrib1&quot;. Note that attrib0 will call script /bin/ouch
* and attrib1 will call script /bin/wammo.
*/
class scriptClass
{
verbs {get, set}
attributes
{
attrib0 Script {filename = /bin/ouch};
attrib1 Script {filename = /bin/wammo};
}
}
/*
* Finally, the CDEV DDL identifies two devices that are of type
* scriptClass. Any time one of the supported messages is passed
* to one of these devices it will activate the corresponding
* script.
*/
scriptClass : device0, device1;
<!*** Finish PROGRAM ***!></strong></em></font></pre>
</td></tr>
</table>
</tr></td></table>
<AFrame 11>
</a> <!*** Finish FIGURE ***!></p></em></font>
<!*** Start BODY ***!><font size=+1 color=Black>
<!*** Finish BODY ***!></p></font>
</td></tr>
</table>
</body>

View File

@@ -0,0 +1,21 @@
#! /bin/csh
if( -f fmbatch.dat) rm fmbatch.dat
if( -d html) rm -rf html
mkdir -p html
cp $CDEV/doc/bullet.jpg html
foreach x (`find . -name \*.doc -a ! -name \*TOC.doc -a ! -name \*LOF.doc`)
echo "Open $x" >> fmbatch.dat
echo "SaveAs ma $x html/`basename $x .doc`.mif" >> fmbatch.dat
end
fmbatch fmbatch.dat
cd html
foreach x (`find . -name \*.mif -a ! -name \*TITLE.mif`)
mif2html -t 'CDEV Script Service' -o `basename $x .mif`.html `basename $x .mif`TITLE.mif \-TOC \-LOF $x
end
rm *.mif

View File

@@ -0,0 +1,46 @@
ARCH = OS
SHOBJ = YES
include $(CDEV)/extensions/cdevGenericServer/include/makeinclude/Makefile.$(ARCH)
APPNAME = "CDEV/ACE Script Service"
CXXINCLUDES = -I./
BASEBIN = ./
SO_LIBS = $(OSLIBS)
SO_SRCS = ScriptService.cc \
ScriptRequestObject.cc \
ScriptList.cc
OBJS = $(OBJDIR)/ScriptService.o \
$(OBJDIR)/ScriptRequestObject.o \
$(OBJDIR)/ScriptList.o
# ******************************************************************************
# * The BINARIES definition names all of the binary files that should be deleted
# * whenever "make clean" is executed.
# ******************************************************************************
BINARIES = $(CDEVLIB)/libScriptService.a \
$(CDEVSHOBJ)/$(CDEVVERSION)/ScriptService.so
ifeq ($(SHOBJ), YES)
LIBS = $(CDEVLIBS) $(OSLIBS)
TARGETS = $(CDEVSHOBJ)/$(CDEVVERSION)/ScriptService.so
else
LIBS = $(CDEVLIBS) -lScriptService $(OSLIBS)
TARGETS = $(CDEVLIB)/libScriptService.a
endif
targets : $(TARGETS)
$(CDEVSHOBJ)/$(CDEVVERSION)/ScriptService.so : $(OBJS)
@rm -f $@
@$(SOBUILD)
@mkdir -p $(CDEVSHOBJ)/$(CDEVVERSION)
@echo "<= Done...\n"
$(CDEVLIB)/libScriptService.a : $(OBJS)
@rm -f $@
@echo "=> Building archive library $(@F)"
@echo " => Linking $(@F) from objects"
@$(LINK.a) $@ $^
@$(RANLIB) $@ > /dev/null
@echo "<= Done...\n"

View File

@@ -0,0 +1,958 @@
// -----------------------------------------------------------------------------
// Copyright (c) 1995 Southeastern Universities Research Association,
// Continuous Electron Beam Accelerator Facility
//
// This software was developed under a United States Government license
// described in the NOTICE file included as part of this distribution.
//
// -----------------------------------------------------------------------------
//
// Description:
// This header file contains the class definitions for the classes
// associated with the construction of a script service.
//
// Author: Walt Akers
//
// Revision History:
// ScriptList.cc,v
// Revision 1.3 1997/02/14 20:43:40 akers
// Ongoing improvement
//
// Revision 1.2 1997/02/14 20:06:32 akers
// Ongoing improvement
//
// Revision 1.1 1997/02/11 17:37:22 akers
// Directory restructure
//
// Revision 1.7 1997/02/10 20:31:23 akers
// Ongoing improvement
//
// Revision 1.6 1997/02/07 16:19:43 akers
// Ongoing development
//
// Revision 1.5 1997/02/06 20:27:48 akers
// Ongoing development
//
// Revision 1.4 1997/01/31 21:09:58 akers
// Ongoing Development
//
// Revision 1.3 1997/01/31 18:51:26 akers
// Ongoing development
//
// Revision 1.2 1997/01/31 16:21:22 akers
// Ongoing development
//
// Revision 1.1 1997/01/30 20:35:33 akers
// Initial installation of Script Service
//
// -----------------------------------------------------------------------------
#include <ScriptList.h>
// *****************************************************************************
// * ScriptData::ScriptData :
// * Constructor for the class...
// *****************************************************************************
ScriptData::ScriptData ( cdevTranObj & Xobj )
: next(NULL), data(new cdevData),
xobj(&Xobj), inputBuf(NULL),
inputBufLen(0), amntRead(0),
process(0), finished(0), callbackCount(0)
{
// *********************************************************************
// * Attempt to create the pipe that will be used to return
// * the result to the class.
// *********************************************************************
if(pipe((int *)&sp)!=0)
{
sp.readFD = -1;
sp.writeFD = -1;
}
}
// *****************************************************************************
// * ScriptData::data2Buffer :
// * This method is used to convert a cdevData object into a
// * series of strings that can be used by the script.
// *****************************************************************************
int ScriptData::data2Buffer ( cdevData & data, char *& buf, int &bufLen)
{
cdevDataIterator iter(&data);
int i;
int idx = 0;
struct DataPack
{
char * tag;
char ** ptr;
double * dPtr;
size_t ptrCnt;
int quoted;
cdevBounds * bounds;
size_t boundsCnt;
} dataPack[256];
memset(dataPack, 0, sizeof(dataPack));
// *********************************************************************
// * Iterate through the cdevData object and collect the data
// * that is stored into an array of character strings.
// *********************************************************************
for(bufLen=0, iter.init(); !iter && idx<256; idx++)
{
// *************************************************************
// * Get the tag string and add the length of that plus
// * the length of a seperating equals sign (=) to the
// * buffer length.
// *************************************************************
data.tagI2C(iter.tag(), dataPack[idx].tag);
bufLen+=strlen(dataPack[idx].tag)+2;
// *************************************************************
// * Get the number of elements in the array.
// *************************************************************
data.getElems(dataPack[idx].tag, &dataPack[idx].ptrCnt);
// *************************************************************
// * If the data object is a string, add two times the
// * number of elements to the buffer length (to account
// * for double quotes around each entry.)
// *************************************************************
if(data.getType(dataPack[idx].tag)==CDEV_STRING ||
data.getType(dataPack[idx].tag)==CDEV_TIMESTAMP)
{
dataPack[idx].quoted = 1;
bufLen+=(2*dataPack[idx].ptrCnt);
// *****************************************************
// * Allocate an array of character strings to
// * be used to extract the array as a
// * collection of strings and increase the
// * buffer length to accomodate all of the
// * items.
// *****************************************************
dataPack[idx].ptr = new char * [dataPack[idx].ptrCnt];
data.get(dataPack[idx].tag, dataPack[idx].ptr);
for(i=0; i<dataPack[idx].ptrCnt; i++)
{
bufLen+=strlen(dataPack[idx].ptr[i]);
}
}
else
{
// *****************************************************
// * Allocate an array of doubles to
// * be used to extract the array as a
// * collection and increase the buffer length
// * to accomodate all of the items.
// *****************************************************
dataPack[idx].dPtr = new double [dataPack[idx].ptrCnt];
data.get(dataPack[idx].tag, dataPack[idx].dPtr);
bufLen += 21*dataPack[idx].ptrCnt;
}
// *************************************************************
// * Add 1 character for each entry to account for
// * commas between entries.
// *************************************************************
bufLen += dataPack[idx].ptrCnt;
// *************************************************************
// * Get the number of dimensions in the tagged data
// * item.
// *************************************************************
data.getDim(dataPack[idx].tag, &dataPack[idx].boundsCnt);
// *************************************************************
// * If the data is an array or vector, then calculate
// * the amount of space that will have to be used
// * to store the separating brace characters (and commas).
// *************************************************************
if(dataPack[idx].boundsCnt!=0)
{
int braceCount = 1;
dataPack[idx].bounds = new cdevBounds[dataPack[idx].boundsCnt];
data.getBounds(dataPack[idx].tag, dataPack[idx].bounds, dataPack[idx].boundsCnt);
for(i=0; i<dataPack[idx].boundsCnt-1; i++)
{
if(i==0) braceCount +=
dataPack[idx].bounds[i].length;
else braceCount +=
dataPack[idx].bounds[i-1].length*
dataPack[idx].bounds[i].length;
}
bufLen += braceCount*3;
}
// *************************************************************
// * Add space for the separating carriage return.
// *************************************************************
bufLen+=1;
// *************************************************************
// * Move to the next item in the list.
// *************************************************************
++iter;
}
// *********************************************************************
// * Allocate a buffer of sufficient size to hold the result
// * plus a NULL terminating character and an opening and closing
// * single quote.
// *********************************************************************
if(idx) {
buf = new char [bufLen+1+2];
*buf = 0;
}
else {
buf = NULL;
bufLen = 0;
}
// *********************************************************************
// * Walk through each item in the list and place it in the
// * data buffer.
// *********************************************************************
int max = idx;
for(idx=0; idx<max; idx++)
{
char * ptr = buf+strlen(buf);
sprintf(ptr, "%s=", dataPack[idx].tag);
if(!dataPack[idx].boundsCnt)
{
if(dataPack[idx].quoted)
sprintf(ptr+strlen(ptr), "\"%s\"\n", dataPack[idx].ptr[0]);
else sprintf(ptr+strlen(ptr), "%g\n", dataPack[idx].dPtr[0]);
}
else {
size_t ptrIdx = 0;
strcat(ptr, "{");
if(dataPack[idx].quoted)
{
dataArray2Buffer(ptr+strlen(ptr),
dataPack[idx].ptr,
ptrIdx,
dataPack[idx].bounds,
dataPack[idx].boundsCnt,
0);
}
else
{
dataArray2Buffer(ptr+strlen(ptr),
dataPack[idx].dPtr,
ptrIdx,
dataPack[idx].bounds,
dataPack[idx].boundsCnt,
0);
}
strcat(ptr, "}\n");
}
// *************************************************************
// * Delete the allocated contents of the dataPack once
// * it is no longer needed.
// *************************************************************
if(dataPack[idx].quoted)
{
for(int j=0; j<dataPack[idx].ptrCnt; j++)
{
delete dataPack[idx].ptr[j];
}
delete dataPack[idx].ptr;
}
else delete dataPack[idx].dPtr;
delete dataPack[idx].bounds;
}
return CDEV_SUCCESS;
}
// *****************************************************************************
// * ScriptList::dataArray2Buffer :
// * This is a method that is called recursively to dump the contents
// * of a string array to the buffer.
// *****************************************************************************
void ScriptData::dataArray2Buffer (char * output,
char ** ptr,
size_t & ptrIdx,
cdevBounds * bounds,
size_t nBounds,
size_t boundsIdx)
{
for(int i=0; i<bounds[boundsIdx].length; i++)
{
if(boundsIdx<nBounds-1)
{
strcat(output, "{");
dataArray2Buffer(output+strlen(output), ptr, ptrIdx, bounds, nBounds, boundsIdx+1);
if(i+1<bounds[boundsIdx].length) strcat(output, "},");
else strcat(output, "}");
}
else {
output+=strlen(output);
if(i+1<bounds[boundsIdx].length) sprintf(output, "\"%s\",", ptr[ptrIdx++]);
else sprintf(output, "\"%s\"", ptr[ptrIdx++]);
}
}
}
// *****************************************************************************
// * ScriptList::dataArray2Buffer :
// * This is a method that is called recursively to dump the contents
// * of a double array to the buffer.
// *****************************************************************************
void ScriptData::dataArray2Buffer (char * output,
double * ptr,
size_t & ptrIdx,
cdevBounds * bounds,
size_t nBounds,
size_t boundsIdx)
{
for(int i=0; i<bounds[boundsIdx].length; i++)
{
if(boundsIdx<nBounds-1)
{
strcat(output, "{");
dataArray2Buffer(output+strlen(output), ptr, ptrIdx, bounds, nBounds, boundsIdx+1);
if(i+1<bounds[boundsIdx].length) strcat(output, "},");
else strcat(output, "}");
}
else {
output+=strlen(output);
if(i+1<bounds[boundsIdx].length) sprintf(output, "%g,", ptr[ptrIdx++]);
else sprintf(output, "%g", ptr[ptrIdx++]);
}
}
}
// *****************************************************************************
// * ScriptData::buffer2Data :
// * This method allows the ScriptData class to read the inbound
// * results of the script inot a cdevData buffer.
// *
// * Each line of the result should be structured as such.
// *
// * Tag value\n
// *
// * All results are assumed to be doubles unless they are enclosed
// * in double quotes (").
// *
// * If an array of items is returned, it should be enclosed in
// * braces as described below.
// *
// * 1) Returning a string:
// *
// * value="Test"\n
// * status "Running very well"\n
// *
// * 2) Returning a double:
// * value=10.01\n
// * status=1\n
// *
// * 3) Returning an array of strings
// * value={"John","Jacob","Jingleheimer","Schmidt"}\n
// *
// * 4) Returning a two dimensional array of doubles: ie x[2][3]
// * value={{1.0,2.0,3.0}{4.0,5.0,6.0}}\n
// *
// *****************************************************************************
int ScriptData::buffer2Data ( char * &buf, cdevData & data )
{
int done = 0;
char * ptr = buf;
while(ptr && *ptr)
{
while(isspace(*ptr)) ptr++;
char * tag = ptr;
// *************************************************************
// * Find the end of the tag and remove any trailing
// * spaces that are associated with it.
// *************************************************************
if(*tag) ptr = strchr(ptr, '=');
// *************************************************************
// * If the pointer does not point to a valid line, jump to
// * the next line and continue from the top of the loop.
// *************************************************************
if(!ptr || !(*ptr))
{
ptr = strchr(ptr, '\n');
continue;
}
else {
char *temp = ptr-1;
*(ptr++) = 0;
while(isspace(*temp)) *(temp--)=0;
}
// *************************************************************
// * Find the beginning of the data.
// *************************************************************
while(*ptr && isspace(*ptr)) ptr++;
// *************************************************************
// * Beginning of an array of things.
// *************************************************************
if(*ptr=='{')
{
cdevDataTypes dataType = CDEV_DOUBLE;
char ** strData = NULL;
double * dblData = NULL;
char * tPtr = ptr;
cdevBounds * bounds;
int nDim = 0;
int dimIdx = 0;
int itmCnt = 0;
int itmIdx = 0;
int chkSum = 1;
// *****************************************************
// * Count the number of opening braces, this will
// * indicate the number of dimensions in the array.
// *****************************************************
while(*(tPtr++)=='{') nDim++;
bounds = new cdevBounds[nDim];
for(dimIdx=0; dimIdx<nDim; dimIdx++)
{
bounds[dimIdx].offset = 0;
bounds[dimIdx].length = 0;
}
// *****************************************************
// * Now count the number of the dimensions in the array
// *****************************************************
for(tPtr=ptr+1, dimIdx=0; dimIdx>=0 && *tPtr; tPtr++)
{
if(*tPtr=='"')
{
tPtr = strchr(tPtr+1, '"');
dataType = CDEV_STRING;
}
else if(*tPtr=='}')
{
if(dimIdx==nDim-1) bounds[dimIdx].length++;
dimIdx--;
}
else if(*tPtr=='{')
{
bounds[dimIdx++].length++;
}
else if(*tPtr==',' && dimIdx==nDim-1)
{
bounds[dimIdx].length++;
}
}
// *****************************************************
// * At this point, the last element of the bounds
// * array will contain the total count of items.
// *****************************************************
itmCnt = bounds[nDim-1].length;
// *****************************************************
// * To set each bounds element to its actual array
// * dimension, it will be necessary to divide it by
// * the size of its predecessor - working backwards.
// *****************************************************
for(dimIdx = nDim-2; dimIdx>=0; dimIdx--)
{
bounds[dimIdx+1].length /= bounds[dimIdx].length;
}
for(dimIdx = 0; dimIdx<nDim; dimIdx++)
{
chkSum*=bounds[dimIdx].length;
}
if(chkSum==itmCnt && chkSum>0)
{
// *****************************************************
// * Allocate a buffer of the correct type to hold the
// * data.
// *****************************************************
if(dataType == CDEV_STRING) strData = new char *[itmCnt];
else dblData = new double [itmCnt];
// *****************************************************
// * Walk through the data and accumulate the items
// * into the array.
// *****************************************************
tPtr = ptr;
dimIdx = -1;
do {
if(*tPtr=='{')
{
int jumpTheComma = 0;
dimIdx++;
tPtr++;
if(*tPtr && dimIdx==nDim-1) do
{
if(*tPtr==',' && jumpTheComma) tPtr++;
while(isspace(*tPtr)) tPtr++;
if(dataType==CDEV_DOUBLE)
{
dblData[itmIdx++] = atof(tPtr);
while(*tPtr && *tPtr!=',' && *tPtr!='}') tPtr++;
}
else {
char oldEndVal;
char * ePtr;
if(*tPtr=='"')
{
tPtr++;
ePtr = strchr(tPtr, '"');
}
else for(ePtr=tPtr; *ePtr && *ePtr!=',' && *ePtr!='}'; ePtr++);
if(ePtr)
{
oldEndVal = *ePtr;
*ePtr = 0;
}
strData[itmIdx++] = strdup(tPtr);
if(ePtr)
{
*ePtr = oldEndVal;
tPtr = (*ePtr=='"')?ePtr+1:ePtr;
}
else tPtr = tPtr+strlen(tPtr);
}
jumpTheComma = (*tPtr==',')?1:0;
} while(*tPtr!='}' && *tPtr);
}
else if(*tPtr=='}')
{
dimIdx--;
tPtr++;
}
else tPtr++;
} while (*tPtr && itmIdx<itmCnt && dimIdx>=0);
if(dataType==CDEV_STRING)
{
data.insert(tag, strData, itmCnt, nDim);
for(int x=0; x<itmCnt; x++) delete strData[x];
delete strData;
}
else {
data.insert(tag, dblData, itmCnt, nDim);
delete dblData;
}
data.setBounds(tag, bounds, nDim);
}
delete bounds;
for(ptr=tPtr; *ptr && *ptr!='\n'; ptr++);
}
// *************************************************************
// * Beginning of a string.
// *************************************************************
else if(*ptr=='"')
{
ptr++;
char * temp = ptr;
while(*temp!='"') temp++;
if(*temp=='"')
{
*(temp++)=0;
data.insert(tag, ptr);
}
for(ptr = temp; *ptr && *ptr!='\n'; ptr++);
}
// *************************************************************
// * Beginning of a double.
// *************************************************************
else if(*ptr)
{
data.insert(tag, atof(ptr));
while(*ptr && *ptr!='\n') ptr++;
}
}
return CDEV_SUCCESS;
}
// *****************************************************************************
// * ScriptData::fireCallback :
// * Deploys the callback associated with the class instance.
// *****************************************************************************
void ScriptData::fireCallback ( int result, void * arg, cdevRequestObject &req, cdevData & data, int partial)
{
// *********************************************************************
// * Fire the user provided callback and increment the counter.
// *********************************************************************
xobj->userCallback_->fireCallback ( result, arg, req, data, partial );
callbackCount++;
}
// *****************************************************************************
// * ScriptData::dispatch :
// * This method is responsible for collecting data from the
// * read file descriptor, and executing the callback associated
// * with it.
// *
// * This method will return the number of messages that it handled.
// *****************************************************************************
int ScriptData::dispatch ( void )
{
int nHandled = 0;
if(!finished)
{
int count = 0;
int stat_val;
// *************************************************************
// * Find out how many bytes are ready to read.
// *************************************************************
while(ioctl(sp.readFD, FIONREAD, &count)==0 && count>0)
{
// *****************************************************
// * If the input buffer has not already been
// * allocated, then allocate a new one that
// * is of sufficient size in increments of
// * 1024 bytes.
// *****************************************************
if(inputBufLen==0)
{
inputBufLen = (count/1024+1)*1024;
inputBuf = (char *)malloc(inputBufLen);
}
// *****************************************************
// * If the existing buffer is not sufficiently
// * large, then allocate a new one that is
// * of sufficient size in increments of
// * 1024 bytes.
// *********************************************
else if(amntRead + count > inputBufLen)
{
inputBufLen = ((amntRead+count)/1024+1)*1024;
inputBuf = (char *)realloc(inputBuf, inputBufLen);
}
// *****************************************************
// * Read the data that is ready into the buffer
// *****************************************************
amntRead += read(sp.readFD, inputBuf+amntRead, count);
// *****************************************************
// * NULL terminate the buffer to prevent memory
// * overruns while performing string operations
// *****************************************************
inputBuf[amntRead] = 0;
int done = 0;
// *****************************************************
// * Search the data for the "done" or "end" keywords
// * on a line by themselves... Either of these
// * keywords indicate the end of a data transmission.
// *****************************************************
do {
char * ePtr = NULL;
if (strncmp(inputBuf, "end\n", 4)==0 ||
strncmp(inputBuf, "done\n", 5)==0)
{
ePtr = inputBuf;
}
else if((ePtr = strstr(inputBuf, "\nend\n"))!=NULL ||
(ePtr = strstr(inputBuf, "\ndone\n"))!=NULL)
{
ePtr++;
}
else done = 1;
if(ePtr && *ePtr)
{
if(*ePtr=='d')
{
*ePtr = 0;
ePtr += 5;
finished = 1;
}
else {
*ePtr = 0;
ePtr += 4;
}
buffer2Data (inputBuf, *data);
strcpy(inputBuf, ePtr);
amntRead = strlen(inputBuf);
// *************************************
// * If no more data is ready,
// * determine if the process
// * is still alive.
// *************************************
stat_val = 0;
if(waitpid(process, &stat_val, WNOHANG)==process &&
(errno==ECHILD || WIFEXITED(stat_val)))
{
finished = 1;
}
// *************************************
// * Transfer the data from the
// * temporary data object into
// * the user-defined result
// * data object.
// *************************************
if(xobj->resultData_==NULL)
xobj->resultData_ = data;
else *(xobj->resultData_) = *data;
// *************************************
// * Fire the user provided
// * callback and increment the
// * callback counter. The status as
// * returned in the cdevData object
// * is the status for the request.
// *************************************
int status = CDEV_SUCCESS;
xobj->resultData_->get("status", &status);
fireCallback
(
status,
xobj->userCallback_->userarg(),
*xobj->reqObj_,
*xobj->resultData_,
!finished);
nHandled++;
}
} while(!done && !finished);
}
// *************************************************************
// * When no more data is ready, determine if the process is
// * still alive.
// *************************************************************
if(!finished && waitpid(process, &stat_val, WNOHANG)==process &&
(errno==ECHILD || WIFEXITED(stat_val)))
{
finished = 1;
}
}
return nHandled;
}
// *****************************************************************************
// * ScriptData::~ScriptData :
// * The destructor is protected to prevent it from being deleted by
// * anyone except the ScriptList class.
// *****************************************************************************
ScriptData::~ScriptData ( void )
{
static int killCount = 0;
if(callbackCount==0)
{
data->remove();
fireCallback (
CDEV_SUCCESS,
xobj->userCallback_->userarg(),
*xobj->reqObj_,
*data);
}
if(inputBuf) delete inputBuf;
if(sp.readFD != -1) close(sp.readFD);
if(sp.writeFD != -1) close(sp.writeFD);
if(data) delete data;
if(xobj)
{
xobj->removeFromGrps();
delete xobj;
}
}
// *****************************************************************************
// * ScriptList::ScriptList :
// * This is the constructor for the ScriptList class. It
// * initializes the internals of the class to 0.
// *****************************************************************************
ScriptList::ScriptList ( void ) : scripts(NULL), fdList(NULL), fdCount(0), fdMax(0)
{
};
// *****************************************************************************
// * ScriptList::ScriptList :
// * This method will walk through the list of ScriptData objects and
// * will delete each of them in sequence.
// *
// * Note that is no callbacks have been delivered for the specified
// * ScriptData object, it will deliver a single callback with
// * CDEV_ERROR as the status prior to terminating.
// *****************************************************************************
ScriptList::~ScriptList ( void )
{
ScriptData * curr;
while(scripts!=NULL)
{
curr = scripts;
scripts = scripts->next;
delete curr;
}
}
// *****************************************************************************
// * ScriptList::find :
// * This method allows the caller to locate the ScriptData object
// * that is associated with a specified file descriptor.
// *****************************************************************************
ScriptData * ScriptList::find ( int fd )
{
ScriptData * curr = scripts;
while(curr->sp.readFD != fd && curr!=NULL)
{
curr = curr->next;
}
return curr;
}
// *****************************************************************************
// * ScriptList::insert :
// * This method allows the caller to insert a new ScriptData object
// * into the list of scripts that is managed by this list. Once
// * added to the list the file descriptor associated with the
// * ScriptData object will be placed on the list of file
// * descriptors that will be polled by the cdevSystem object.
// *****************************************************************************
void ScriptList::insert ( ScriptData & script )
{
script.next = scripts;
scripts = &script;
if(fdCount >= fdMax)
{
fdMax = (fdMax>1)?(fdMax*2):16;
fdList = (int *)realloc(fdList, fdMax*sizeof(int));
}
if(fdCount==0) fdList[fdCount++] = selector.readfd();
fdList[fdCount++] = script.sp.readFD;
}
// *****************************************************************************
// * ScriptList::remove :
// * This method calls the remove(fd) method to remove the ScriptData
// * object that is specified by the caller.
// *****************************************************************************
void ScriptList::remove ( ScriptData & script )
{
remove(script.sp.readFD);
}
// *****************************************************************************
// * ScriptList::remove :
// * This method will walk through all scripts in the list until it
// * locates the file descriptor specified by fd. The method will
// * then remove the ScriptData object that is associated with that
// * file descriptor.
// *
// * The fdList and fdCount variables will be updated once the dead
// * file descriptor has been removed.
// *****************************************************************************
void ScriptList::remove ( int fd )
{
ScriptData * prev = NULL;
ScriptData * curr = scripts;
while(curr!=NULL && curr->sp.readFD!=fd)
{
prev = curr;
curr = prev->next;
}
if(curr!=NULL)
{
if(prev!=NULL) prev->next = curr->next;
else scripts = curr->next;
delete curr;
for(fdCount=0, curr = scripts; curr!=NULL; curr=curr->next)
{
fdList[fdCount++] = curr->sp.readFD;
}
}
}
// *****************************************************************************
// * ScriptList::getFd :
// * This method allows the caller to obtain the list of file
// * descriptors that are in use in all scripts. These descriptors
// * will be used to perform ending at the cdevSystem level.
// *
// * Note that this list is updated and maintained each time the
// * user calls "insert" to add a new file descriptor of "remove" to
// * extract an old one.
// *****************************************************************************
int ScriptList::getFd ( int * &fd, int & numFd )
{
fd = fdList;
numFd = fdCount;
return CDEV_SUCCESS;
}
// *****************************************************************************
// * ScriptList::poll :
// * This method is called to poll for events on a list of scripts
// * that are currently executing. This method will return the
// * count of callbacks that were dispatched during this pass through
// * poll.
// *****************************************************************************
int ScriptList::poll ( void )
{
int nHandled = 0;
ScriptData * prev = NULL;
ScriptData * curr = scripts;
// *********************************************************************
// * Clear any events that might be stored in the selector object.
// *********************************************************************
selector.purge();
// *********************************************************************
// * Walk through each script and call the dispatch method to
// * fire callbacks for all file descriptors that have data
// * ready.
// *********************************************************************
for(curr=scripts; curr!=NULL; curr = curr->next)
{
nHandled+=curr->dispatch();
}
// *********************************************************************
// * Walk through the list of scripts again. This time, check
// * the finished flag to determine if each script has run to
// * completion. If so, remove the script from the list of
// * scripts and delete it.
// *********************************************************************
for(prev=NULL, curr=scripts; curr!=NULL; )
{
if(curr->finished)
{
int deadFd = curr->sp.readFD;
curr = curr->next;
remove(deadFd);
}
else {
prev = curr;
curr = prev->next;
}
}
// *********************************************************************
// * Return the total number of callbacks that were fired. This
// * value will be used to allow for polling until at least one
// * event has been processed.
// *********************************************************************
return nHandled;
}

View File

@@ -0,0 +1,113 @@
/*
* -----------------------------------------------------------------------------
* Copyright (c) 1995 Southeastern Universities Research Association,
* Continuous Electron Beam Accelerator Facility
*
* This software was developed under a United States Government license
* described in the NOTICE file included as part of this distribution.
*
* -----------------------------------------------------------------------------
*
* Description:
* This header file contains the class definitions for the classes
* associated with the construction of a script service.
*
* Author: Walt Akers
*
* -----------------------------------------------------------------------------
*/
#include <sys/ioctl.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <unistd.h>
#include <ctype.h>
#include <cdevData.h>
#include <cdevTranObj.h>
#include <cdevSelector.h>
// *****************************************************************************
// * class ScriptData :
// * This contains the information associated with a single script. A list
// * of ScriptData objects is maintained and accessed through the ScriptList
// * object.
// *
// * Note: because this object is only accessed through the ScriptList
// * object, all data items have been made public to improve performance.
// *****************************************************************************
class ScriptData
{
public:
typedef struct {
int readFD;
int writeFD;
} SocketPair;
ScriptData * next;
SocketPair sp;
cdevTranObj * xobj;
cdevData * data;
char * inputBuf;
int inputBufLen;
int amntRead;
pid_t process;
int finished;
int callbackCount;
ScriptData ( cdevTranObj & Xobj );
~ScriptData (void);
static int data2Buffer (cdevData & data, char *& buf, int &bufLen);
static void dataArray2Buffer (char * output,
char ** ptr,
size_t & ptrIdx,
cdevBounds * bounds,
size_t nBounds,
size_t boundsIdx);
static void dataArray2Buffer (char * output,
double * ptr,
size_t & ptrIdx,
cdevBounds * bounds,
size_t nBounds,
size_t boundsIdx);
static int buffer2Data (char * &buf, cdevData & data );
void fireCallback (int result,
void * arg,
cdevRequestObject &req,
cdevData & data,
int partial=0);
int dispatch (void);
};
// *****************************************************************************
// * class ScriptList:
// * This class maintains a list of ScriptData objects that represent all
// * of the scripts that are currently being run by the ScriptService. The
// * ScriptService object will use the methods of this object to perform
// * operations on the items in the list.
// *
// * Because this class is only accessible through the ScriptService, its
// * internals have been made public to improve performance.
// *****************************************************************************
class ScriptList
{
public:
static cdevSelector selector;
ScriptData * scripts;
int * fdList;
int fdCount;
int fdMax;
ScriptList (void);
~ScriptList (void);
ScriptData * find ( int fd );
void insert ( ScriptData & script );
void remove ( ScriptData & script );
void remove ( int fd );
int getFd ( int * &fd, int & numFd );
int poll ( void );
};

View File

@@ -0,0 +1,134 @@
//-----------------------------------------------------------------------------
// Copyright (c) 1995 Southeastern Universities Research Association,
// Continuous Electron Beam Accelerator Facility
//
// This software was developed under a United States Government license
// described in the NOTICE file included as part of this distribution.
//
//-----------------------------------------------------------------------------
//
// Description:
// This header file contains the class definitions for the classes
// associated with the construction of a model request object.
//
// Author: Walt Akers
//
// Revision History:
// ScriptRequestObject.cc,v
// Revision 1.1 1997/02/11 17:37:24 akers
// Directory restructure
//
// Revision 1.1 1997/01/30 20:35:34 akers
// Initial installation of Script Service
//
//-----------------------------------------------------------------------------
//
#include <ScriptService.h>
#include <ScriptRequestObject.h>
#include <cdevClock.h>
int ScriptRequestObject::syncCode = 0;
// *********************************************************************
// * ScriptRequestObject::ScriptRequestObject :
// * This constructor initializes the internals of a device/message
// * pair associated with the model server.
// *
// * Returns nothing.
// *********************************************************************
ScriptRequestObject::ScriptRequestObject ( char * device, char * message, cdevSystem & system)
: cdevRequestObject(device, message, system), syncFinished(0)
{
}
// *****************************************************************************
// * ScriptRequestObject::sendNoBlock :
// * This function allows the caller to submit an asynchronous message to the
// * server for processing.
// *****************************************************************************
int ScriptRequestObject::sendNoBlock (cdevData * in, cdevData * out)
{
ScriptService * svc = (ScriptService *)service_;
cdevTranObj * xobj = new cdevTranObj(&system_, this, out, &svc->asyncCallback);
cdevData * Data = ((in==NULL)?new cdevData:new cdevData(*in));
return svc->submit(*xobj, *Data);
}
// *****************************************************************************
// * ScriptRequestObject::sendCallback :
// * This function allows the caller to submit an asynchronous message to the
// * server for processing.
// *****************************************************************************
int ScriptRequestObject::sendCallback (cdevData * in, cdevCallback & callback)
{
ScriptService * svc = (ScriptService *)service_;
cdevTranObj * xobj = new cdevTranObj(&system_, this, NULL, new cdevCallback(callback));
cdevData * Data = ((in==NULL)?new cdevData:new cdevData(*in));
xobj->enableDeleteCbk();
return svc->submit(*xobj, *Data);
}
// *****************************************************************************
// * ScriptRequestObject::send :
// * The send interface is used to provide synchronous I/O with the service.
// *
// * Returns CDEV_SUCCESS on success or CDEV_ERROR on error.
// *****************************************************************************
int ScriptRequestObject::send ( cdevData * in, cdevData * out )
{
int status = CDEV_SUCCESS;
ScriptService * svc = (ScriptService *)service_;
cdevCallback * cb = new cdevCallback(ScriptService::syncCallbackFunc, (void *)++syncCode);
cdevTranObj * xobj = new cdevTranObj(&system_, this, out, cb);
cdevData * Data = ((in==NULL)?new cdevData:new cdevData(*in));
xobj->enableDeleteCbk();
if((status = svc->submit(*xobj, *Data))==CDEV_SUCCESS)
{
// *************************************************************
// * I used to wait for a response here only if the outbound
// * cdevData object was non-null. However, that provided
// * unexpected behavior to the client. Now I wait whether
// * output data is expected or not.
// *************************************************************
cdevTimeValue t((double)SEND_WAIT_PERIOD);
cdevClock timer;
timer.schedule(NULL,t);
// *************************************************************
// * WAITING WITH system_.pend():
// * Previously I was using system_.pend() to process events
// * while waiting for the service to respond. This resulted
// * in a lock-up when the connection could not be
// * established or if the connection collapsed while in use.
// *
// * WAITING WITH system_.poll():
// * When in a heavy inbound traffic situation, the calls from other
// * services will trample all over the inbound data coming from the
// * model service. This results in unreliable delivery and
// * processing of messages from the model server.
// *
// * WAITING WITH service_.poll():
// * So far so good.
// *************************************************************
for(syncFinished=0; !syncFinished && !timer.expired(); svc->poll());
if (!syncFinished)
{
status = CDEV_ERROR;
system_.reportError(
CDEV_SEVERITY_ERROR,
"cdevRequestObject",
this,
"Transaction wasn't processed after %i seconds",
SEND_WAIT_PERIOD);
}
else status = syncStatus;
}
return status;
}

View File

@@ -0,0 +1,121 @@
/*
*-----------------------------------------------------------------------------
* Copyright (c) 1995 Southeastern Universities Research Association,
* Continuous Electron Beam Accelerator Facility
*
* This software was developed under a United States Government license
* described in the NOTICE file included as part of this distribution.
*
*-----------------------------------------------------------------------------
*
* Description:
* This header file contains the class definitions for the classes
* associated with the construction of a request object.
*
* Author: Walt Akers
*
*-----------------------------------------------------------------------------
*/
#if !defined (_SCRIPT_REQUEST_OBJECT_H_)
#define _SCRIPT_REQUEST_OBJECT_H_
#include <cdevRequestObject.h>
#include <cdevTranObj.h>
#include <cdevGroup.h>
#include <cdevErrCode.h>
// *****************************************************************************
// * ScriptRequestObject:
// * The ScriptRequestObject class provides the interface for sending
// * messages to a server. All device/message commands are routed
// * through a ScriptRequestObject either directly or indirectly.
// *****************************************************************************
class ScriptRequestObject : public cdevRequestObject
{
friend class ScriptService;
public:
// *********************************************************************
// * This is how long the system will wait for a reply to be returned
// * from a send.
// *********************************************************************
enum { SEND_WAIT_PERIOD=30 };
// *********************************************************************
// * ScriptRequestObject::ScriptRequestObject :
// * This constructor initializes the internals of a device/message
// * pair associated with the server.
// *
// * Returns nothing.
// *********************************************************************
ScriptRequestObject ( char * device, char * message,
cdevSystem & system = cdevSystem::defaultSystem() );
// *********************************************************************
// * ScriptRequestObject::~ScriptRequestObject :
// * This destructor performs any deallocation or shutdown operations
// * necessary, prior to the destruction of the object.
// *
// * Returns nothing.
// *********************************************************************
virtual ~ScriptRequestObject ( void ) {}
// *********************************************************************
// * ScriptRequestObject::send :
// * The send interface is used to provide synchronous I/O with the
// * service.
// *
// * Returns CDEV_SUCCESS on success or CDEV_ERROR on error.
// *********************************************************************
int send ( cdevData & in, cdevData & out )
{ return send(&in, &out); }
int send ( cdevData * in, cdevData & out )
{ return send(in, &out); }
int send ( cdevData & in, cdevData * out )
{ return send(&in, out); }
int send ( cdevData * in, cdevData * out );
// *********************************************************************
// * ScriptRequestObject::sendNoBlock :
// * The sendNoBlock interface is used in conjunction with cdevGroup
// * or cdevSystem to execute a series of operations. During the
// * early implementation of this product, these functions will be
// * linked directly to the send call.
// *
// * Returns CDEV_SUCCESS on success or CDEV_ERROR on error.
// *********************************************************************
int sendNoBlock (cdevData & in, cdevData & out)
{ return sendNoBlock(&in, &out); }
int sendNoBlock (cdevData * in, cdevData & out)
{ return sendNoBlock(in, &out); }
int sendNoBlock (cdevData & in, cdevData * out)
{ return sendNoBlock(&in, out); }
int sendNoBlock (cdevData * in, cdevData * out);
// *********************************************************************
// * ScriptRequestObject::sendCallback :
// * The sendCallback interface provides asynchronous communications
// * with the server. During the early implementation of this
// * product, these functions will be linked directly to the send
// * call.
// *
// * Returns CDEV_SUCCESS on success or CDEV_ERROR on error.
// *********************************************************************
int sendCallback (cdevData & in, cdevCallback & callback)
{ return sendCallback(&in, callback); }
int sendCallback (cdevData * in, cdevCallback & callback);
// *********************************************************************
// * ScriptRequestObject::className :
// * This function returns the name of the class as a constant string
// *********************************************************************
const char * className ( void ) const { return "ScriptRequestObject"; }
private:
int syncFinished;
int syncStatus;
static int syncCode;
};
#endif /* _SCRIPT_REQUEST_OBJECT_H_ */

View File

@@ -0,0 +1,381 @@
// -----------------------------------------------------------------------------
// Copyright (c) 1995 Southeastern Universities Research Association,
// Continuous Electron Beam Accelerator Facility
//
// This software was developed under a United States Government license
// described in the NOTICE file included as part of this distribution.
//
// -----------------------------------------------------------------------------
//
// Description:
// This header file contains the class definitions for the classes
// associated with the construction of a script service.
//
// Author: Walt Akers
//
// Revision History:
// ScriptService.cc,v
// Revision 1.3 1997/02/14 20:43:41 akers
// Ongoing improvement
//
// Revision 1.2 1997/02/14 20:06:32 akers
// Ongoing improvement
//
// Revision 1.1 1997/02/11 17:37:27 akers
// Directory restructure
//
// Revision 1.3 1997/01/31 18:51:27 akers
// Ongoing development
//
// Revision 1.2 1997/01/31 16:21:24 akers
// Ongoing development
//
// Revision 1.1 1997/01/30 20:35:35 akers
// Initial installation of Script Service
//
// -----------------------------------------------------------------------------
#include <signal.h>
#include "ScriptService.h"
#include "cdevDirectory.h"
#include "cdevClock.h"
#include "ScriptList.h"
cdevSelector ScriptList::selector;
// ****************************************************************************
// * This function is an interrupt handler that will be executed whenever the
// * program receives a SIGCHLD signal. When called it will execute the poll
// * method of the default server, in order to remove any dead Script Service
// * processes.
// ****************************************************************************
static void SIGCHLD_handler (int)
{
ScriptList::selector.insertEvent();
}
// *********************************************************************
// * newScriptService :
// * This method is called by the cdevSystem object to load the
// * initial instance of the ScriptService.
// *********************************************************************
cdevService * newScriptService ( char * name, cdevSystem * system )
{
signal(SIGCHLD, SIGCHLD_handler);
return new ScriptService(name, *system);
}
// *********************************************************************
// * ScriptService::ScriptService :
// * This is the constructor for the script service. It determines
// * the tag number for the "filename" tag if it does not already
// * exist and allocates the ScriptList object that will be used
// * to hold the individual script instances.
// *********************************************************************
ScriptService::ScriptService ( char * name, cdevSystem & system )
: cdevService(name, system),
FILENAME_TAG(1000),
asyncCallback(asyncCallbackFunc, NULL)
{
scripts = new ScriptList;
while(cdevData::tagC2I("filename", &FILENAME_TAG)!=CDEV_SUCCESS)
{
cdevData::insertTag(++FILENAME_TAG, "filename");
}
}
// *********************************************************************
// * ScriptService::~ScriptService :
// * This is the destructor for the script service,it does nothing
// * but act as a placeholder for the virtual destructor.
// *********************************************************************
ScriptService::~ScriptService ( void )
{
}
// *********************************************************************
// * ScriptService::getRequestObject :
// * This is the interface that cdev objects will use to obtain a
// * ScriptRequestObject object. The ScriptRequestObject
// * represents a combined device and message pair that is associated
// * with the ScriptService.
// *
// * Returns CDEV_SUCCESS on success or CDEV_ERROR on error.
// *********************************************************************
int ScriptService::getRequestObject ( char * device, char * message, cdevRequestObject * &req)
{
req = new ScriptRequestObject (device, message, system_);
return (req ? CDEV_SUCCESS : CDEV_ERROR);
}
// *****************************************************************************
// * ScriptService::getFd
// * This function will return the list of file descriptors that the
// * ScriptService is using. This will allow the file descriptors to be
// * used in global select and poll calls performed at the cdevSystem class
// * level.
// *
// * Returns CDEV_SUCCESS on success or CDEV_ERROR on error.
// *****************************************************************************
int ScriptService::getFd ( int * &fd, int & numFd )
{
fd = scripts->fdList;
numFd = scripts->fdCount;
return CDEV_SUCCESS;
}
// *********************************************************************
// * ScriptService::flush :
// * This function flushes all communications buffers that the
// * service may have open.
// *
// * Returns CDEV_SUCCESS on success or CDEV_ERROR on error.
// *********************************************************************
int ScriptService::flush ( void )
{
return CDEV_SUCCESS;
}
// *****************************************************************************
// * ScriptService::poll :
// * This function polls the file descriptors used by the service
// * until one of them becomes active or a discrete amount of time
// * has expired.
// *
// * Returns CDEV_SUCCESS on success or CDEV_ERROR on error.
// *****************************************************************************
int ScriptService::poll ( void )
{
if(scripts->fdCount>0) scripts->poll();
return CDEV_SUCCESS;
}
// *****************************************************************************
// * ScriptService::pend :
// * Pends until the named file descriptor (or any file descriptor
// * if fd = -1) is ready. Will pend forever if the descriptor does
// * not become active.
// *
// * Returns CDEV_SUCCESS on success or CDEV_ERROR on error.
// *****************************************************************************
int ScriptService::pend ( int )
{
while(scripts->fdCount>0 && scripts->poll()==0);
return CDEV_SUCCESS;
}
// *****************************************************************************
// * ScriptService::pend :
// * Pends until the named file descriptor (or any file descriptor
// * if fd = -1) is ready. Will pend for no longer than the user
// * specified number of seconds.
// *
// * Returns CDEV_SUCCESS on success or CDEV_ERROR on error.
// *****************************************************************************
int ScriptService::pend ( double seconds, int )
{
if(scripts->fdCount > 0)
{
int nHandled = 0;
cdevTimeValue sec = seconds;
cdevClock timer;
timer.schedule(NULL, sec);
do {
nHandled = scripts->poll();
} while(!nHandled &&
!timer.expired() &&
scripts->fdCount>0);
}
return CDEV_SUCCESS;
}
// *****************************************************************************
// * ScriptService::submit :
// * This is the mechanism that the request object will use to submit a
// * message to the service. It is important to note that all of the
// * data provided to this object becomes the property of the service and
// * must not be accessed afterwords.
// *****************************************************************************
int ScriptService::submit ( cdevTranObj &xobj, cdevData &data )
{
int status = CDEV_SUCCESS;
// *********************************************************************
// * Attempt to read the script filename from the DDL file.
// *********************************************************************
ScriptData *script = new ScriptData(xobj);
cdevData temp;
char DDL_request[256];
sprintf (DDL_request,
"resolveServiceData %s %s",
xobj.reqObj_->device().name(),
xobj.reqObj_->message());
if((system_.nameServer()).send(DDL_request, NULL, &temp)==CDEV_SUCCESS)
{
*DDL_request = 0;
temp.get (FILENAME_TAG, DDL_request, 256);
}
else *DDL_request = 0;
// *********************************************************************
// * If the script file was loaded, then begin the process of creating
// * a pipe to retrieve the output of the script, and forking off an
// * additional process to handle execution.
// *********************************************************************
if(*DDL_request)
{
char * parms = NULL;
int bufLen = 0;
// *************************************************************
// * Extract the data from the user provided output cdevData
// * object into a string that can be passed to the script.
// *************************************************************
ScriptData::data2Buffer(data, parms, bufLen);
// *************************************************************
// * Make a copy standard output for later use to restore the
// * standard output file descriptor in the main thread...
// * This is because the behaviour of vfork on some systems
// * will leave the file descriptor in the main thread modified.
// *************************************************************
int fd = dup(1);
// *************************************************************
// * Set the standard output file descriptor to the write file
// * descriptor of the socket pair.
// *************************************************************
dup2(script->sp.writeFD, 1);
// *************************************************************
// * Fork the process to allow the user application to continue
// * running in the original branch, and the script to be
// * executed in the new (child) process.
// *************************************************************
switch((script->process = vfork()))
{
// *****************************************************
// * 0 Indicates that we are in the new child process.
// *****************************************************
case 0:
{
if(bufLen)
{
execl(DDL_request,
DDL_request,
xobj.reqObj_->device().name(),
xobj.reqObj_->message(),
parms, NULL);
}
else {
execl(DDL_request,
DDL_request,
xobj.reqObj_->device().name(),
xobj.reqObj_->message(),
NULL);
}
exit(-1);
}
break;
// *****************************************************
// * -1 Indicates that a new process could not be
// * forked.
// *****************************************************
case -1:
{
// *********************************************
// * Restore the standard output file descriptor
// *********************************************
dup2(fd, 1);
close(fd);
system_.reportError(
CDEV_SEVERITY_ERROR,
"ScriptService",
xobj.reqObj_,
"Failed to fork a new process");
script->fireCallback(CDEV_ERROR,
xobj.userCallback_->userarg(),
*xobj.reqObj_,
*script->data);
status = CDEV_ERROR;
delete script;
}
break;
// *****************************************************
// * Any other value indicates that we are in the parent
// * and the value is the process ID of the new child.
// *****************************************************
default:
{
// *********************************************
// * Restore the standard output file descriptor
// *********************************************
dup2(fd, 1);
close(fd);
// *********************************************
// * Insert the script into the list.
// *********************************************
scripts->insert(*script);
}
break;
}
// *************************************************************
// * Delete parameters (if any).
// *************************************************************
if(bufLen) delete parms;
}
else {
system_.reportError(
CDEV_SEVERITY_ERROR,
"ScriptService",
xobj.reqObj_,
"No filename specified for request %s %s",
xobj.reqObj_->device().name(),
xobj.reqObj_->message());
script->fireCallback(CDEV_ERROR,
xobj.userCallback_->userarg(),
*xobj.reqObj_,
*script->data);
status = CDEV_ERROR;
delete script;
}
return status;
}
// *****************************************************************************
// * ScriptService::getNameServer :
// * This function should obtain the default name server for this object.
// * It does nothing for now.
// *****************************************************************************
int ScriptService::getNameServer(cdevDevice * &ns)
{
ns = 0;
return CDEV_SUCCESS;
}

View File

@@ -0,0 +1,166 @@
/*
*-----------------------------------------------------------------------------
* Copyright (c) 1995 Southeastern Universities Research Association,
* Continuous Electron Beam Accelerator Facility
*
* This software was developed under a United States Government license
* described in the NOTICE file included as part of this distribution.
*
*-----------------------------------------------------------------------------
*
* Description:
* This header file contains the class definitions for the classes
* associated with the construction of a script service.
*
* Author: Walt Akers
*
*-----------------------------------------------------------------------------
*/
#if !defined (_SCRIPT_SERVICE_H_)
#define _SCRIPT_SERVICE_H_
#include <cdevService.h>
#include "ScriptRequestObject.h"
extern "C" cdevService *newScriptService ( char * name, cdevSystem * system );
class ScriptService : public cdevService
{
friend class ScriptRequestObject;
public:
// *********************************************************************
// * ScriptService::ScriptService :
// * This constructor is responsible for performing all service
// * initialization.
// *********************************************************************
ScriptService ( char * name, cdevSystem & system );
// *********************************************************************
// * ScriptService::~ScriptService :
// * The destructor is protected to prevent it from being called
// * directly. The destructor performs any clean-up or shutdown
// * operations.
// *
// * Returns nothing.
// *********************************************************************
~ScriptService ( void );
// *********************************************************************
// * ScriptService::installTags :
// * Installs the tags that the service and service applications
// * will use. This function is static to allow servers to setup
// * the necessary tags without having to instanciate a
// * ScriptService object.
// *********************************************************************
void installTags ( void );
// *********************************************************************
// * ScriptService::getRequestObject :
// * This is the interface that cdev objects will use to obtain a
// * cdevSimpleRequestObject object. The cdevSimpleRequestObject
// * represents a combined device and message pair that is associated
// * with the ScriptService.
// *
// * Returns CDEV_SUCCESS on success or CDEV_ERROR on error.
// *********************************************************************
int getRequestObject (char *, char *, cdevRequestObject * &);
// *********************************************************************
// * ScriptService::getFd
// * This function will return the list of file descriptors that the
// * ScriptService is using. This will allow the file
// * descriptors to be used in global select and poll calls performed
// * at the cdevSystem class level.
// *
// * Returns CDEV_SUCCESS on success or CDEV_ERROR on error.
// *********************************************************************
int getFd ( int * &fd, int & numFd );
// *********************************************************************
// * ScriptService::flush :
// * This function flushes all communications buffers that the
// * service may have open.
// *
// * Returns CDEV_SUCCESS on success or CDEV_ERROR on error.
// *********************************************************************
int flush ( void );
// *********************************************************************
// * ScriptService::poll :
// * This function polls the file descriptors used by the service
// * until one of them becomes active or a discrete amount of time
// * has expired.
// *
// * Returns CDEV_SUCCESS on success or CDEV_ERROR on error.
// *********************************************************************
int poll ( void );
// *********************************************************************
// * ScriptService::pend :
// * Pends until the named file descriptor (or any file descriptor
// * if fd = -1) is ready. Will pend for no longer than the user
// * specified number of seconds.
// *
// * Returns CDEV_SUCCESS on success or CDEV_ERROR on error.
// *********************************************************************
int pend ( double seconds, int = -1);
// *********************************************************************
// * ScriptService::pend :
// * Pends until the named file descriptor (or any file descriptor
// * if fd = -1) is ready. Will pend forever if the descriptor does
// * not become active.
// *
// * Returns CDEV_SUCCESS on success or CDEV_ERROR on error.
// *********************************************************************
int pend ( int = -1);
// *********************************************************************
// * ScriptService::submit :
// * This is the mechanism that the request object will use to submit
// * a message to the service. It is important to note that all of
// * the data provided to this object becomes the property of the
// * service and must not be accessed afterwords.
// *********************************************************************
int submit (cdevTranObj &, cdevData &);
// *********************************************************************
// * ScriptService::getNameServer :
// * This function should obtain the default name server for this
// * object. It does nothing for now.
// *********************************************************************
int getNameServer(cdevDevice * &ns);
// *********************************************************************
// * ScriptService::asyncCallback :
// * This method is called in response to a sendNoBlock reply.
// *********************************************************************
static void asyncCallbackFunc (int, void *, cdevRequestObject &, cdevData &)
{
}
// *********************************************************************
// * ScriptService::syncCallback :
// * This method is called whenever a send is requested from a
// * ScriptRequestObject.
// *********************************************************************
static void syncCallbackFunc ( int status, void *arg, cdevRequestObject &req, cdevData &)
{
ScriptRequestObject * sReq = (ScriptRequestObject *)&req;
int syncCode = (int)arg;
if(syncCode == sReq->syncCode)
{
sReq->syncFinished = 1;
sReq->syncStatus = status;
}
}
protected:
int FILENAME_TAG;
class ScriptList * scripts;
cdevCallback asyncCallback;
};
#endif /* _SCRIPT_SERVICE_H_ */

View File

@@ -0,0 +1,39 @@
ARCH = OS
SHOBJ = YES
include $(CDEV)/extensions/cdevGenericServer/include/makeinclude/Makefile.$(ARCH)
APPNAME = "CDEV/ACE Script Service Tests"
CXXINCLUDES = -I./
BASEBIN = ./
SO_LIBS = $(OSLIBS)
# ******************************************************************************
# * The BINARIES definition names all of the binary files that should be deleted
# * whenever "make clean" is executed.
# ******************************************************************************
BINARIES = $(BASEBIN)/TestProgram $(BASEBIN)/TestProgram2
ifeq ($(SHOBJ), YES)
LIBS = $(CDEVLIBS) $(OSLIBS)
TARGETS = $(BASEBIN)/TestProgram \
$(BASEBIN)/TestProgram2
else
LIBS = $(CDEVLIBS) -lScriptService $(OSLIBS)
TARGETS = $(BASEBIN)/TestProgram \
$(BASEBIN)/TestProgram2
endif
targets : $(TARGETS)
$(BASEBIN)/TestProgram : $(OBJDIR)/TestProgram.o
@rm -f $@
@echo "=> $(CXX) -o $(@F) $(^F)"
@$(LINK.cc) $^ -o $@ $(LIBS)
@echo "<= Done...\n"
$(BASEBIN)/TestProgram2 : $(OBJDIR)/TestProgram2.o
@rm -f $@
@echo "=> $(CXX) -o $(@F) $(^F)"
@$(LINK.cc) $^ -o $@ $(LIBS)
@echo "<= Done...\n"

View File

@@ -0,0 +1,27 @@
service Script
{
tags {filename}
}
class scriptClass
{
verbs {get, set, monitorOn, monitorOff}
attributes
{
attrib0 Script {filename = <>.attrib0};
attrib1 Script {filename = <>.attrib1};
attrib2 Script {filename = <>.attrib2};
attrib3 Script {filename = <>.attrib3};
attrib4 Script {filename = <>.attrib4};
attrib5 Script {filename = <>.attrib5};
attrib6 Script {filename = <>.attrib6};
attrib7 Script {filename = <>.attrib7};
attrib8 Script {filename = <>.attrib8};
attrib9 Script;
}
}
scriptClass :
device0, device1, device2, device3, device4,
device5, device6, device7, device8, device9
;

Binary file not shown.

View File

@@ -0,0 +1,76 @@
#include <cdevSystem.h>
#include <cdevRequestObject.h>
#include <cdevCallback.h>
#include <cdevGroup.h>
void callback (int, void *arg, cdevRequestObject &, cdevData &)
{
static int totalCount = 0;
int * resultCount = (int *)arg;
(*resultCount)++;
fprintf(stdout, "Total count = %i\n", ++totalCount);
}
char * data[2][2][3] =
{
{{"1", "2", "3"}, {"4", "5", "6"}},
{{"1", "2", "3"}, {"4", "5", "6"}},
};
double dData[2][2][3] =
{
{{1.1, 2.2, 3.3}, {4.4, 5.5, 6.6}},
{{1.7, 2.8, 3.9}, {4.11, 5.12, 6.13}}
};
cdevBounds bounds[3] =
{{0, 2},
{0, 2},
{0, 3}};
int main ( void )
{
int resultCount = 0;
cdevData in;
cdevRequestObject & req = cdevRequestObject::attachRef("device0", "get attrib0");
cdevCallback cb (callback, &resultCount);
in.insert("value", (char **)data, 12, 3);
in.setBounds("value", bounds, 3);
in.insert("severity", (double*)dData, 12, 3);
in.setBounds("severity", bounds, 3);
in.insert("status", "Testing");
for(int i=0; i<10; i++)
{
resultCount = 0;
for(int j=0; j<20; j++)
{
req.sendCallback(in, cb);
}
while(resultCount<26) cdevSystem::defaultSystem().poll();
}
}
/*
#include "ScriptList.cc"
int main()
{
cdevData in, out;
char * buf;
int bufLen;
in.insert("value", (char **)data, 12, 3);
in.setBounds("value", bounds, 3);
in.insert("severity", (double*)dData, 12, 3);
in.setBounds("severity", bounds, 3);
in.insert("status", "Testing");
ScriptData::data2Buffer(in, buf, bufLen);
ScriptData::buffer2Data(buf, out);
out.asciiDump();
delete buf;
}
*/

Binary file not shown.

View File

@@ -0,0 +1,27 @@
#include <cdevSystem.h>
#include <cdevRequestObject.h>
#include <cdevCallback.h>
#include <cdevGroup.h>
int done = 0;
void callback (int, void *, cdevRequestObject &, cdevData &data)
{
static int resultCount = 0;
done = cdevCallback::isTransactionDone();
fprintf(stdout, "Result count %i - %s done...\n", ++resultCount, done?" ":"NOT");
if(done) data.asciiDump();
}
int main ( void )
{
cdevData in;
cdevRequestObject & req = cdevRequestObject::attachRef("device0", "get attrib0");
cdevCallback cb (callback, NULL);
req.sendCallback(in, cb);
while(!done)
{
cdevSystem::defaultSystem().pend();
}
}

View File

@@ -0,0 +1,386 @@
#! /bin/csh -f
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value={{1,2,3},{4,5,6}}\nseverity="NOT so GOOD"\nstatus=0\ncontrolLow={1, 2, 3}\ndone\n'

View File

@@ -0,0 +1 @@
#! /bin/csh

View File

@@ -0,0 +1,15 @@
load /lib/milli.a
load /lib/libc.sl
load /usr/csite4/CenterLine/pa-hpux8/lib/libC.a
load -G /usr/csite/cdev/1.5/lib/hpux-09.XX/libcdev.a
load -D_OS_MAJOR_=9 \
-D_OS_MINOR_=7 \
-I/usr/csite/cdev/1.5/include \
-g -D_HAS_CA -pta \
-I./ -I../src\
../src/ScriptList.cc \
../src/ScriptService.cc \
../src/ScriptRequestObject.cc \
TestProgram2.cc \
-ly -ll -L/lib -lm
link