home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 8 Other
/
08-Other.zip
/
lsmt213c.zip
/
rxnpipes.inf
(
.txt
)
< prev
next >
Wrap
OS/2 Help File
|
1995-12-22
|
28KB
|
1,217 lines
ΓòÉΓòÉΓòÉ 1. Rexx Named Pipes ΓòÉΓòÉΓòÉ
The following sections describe RxNPipes, a function package for use by IBM
employees that provides access to OS/2 Named Pipes from Rexx.
ΓòÉΓòÉΓòÉ 1.1. Introduction ΓòÉΓòÉΓòÉ
RxNPipes is a Dynamic Link Library (DLL) which provides the REXX programmer
with many functions dealing with the operation of OS/2 Named Pipes. These
functions allow Rexx procedures running in different sessions to communicate
among themselves.
This package is for use by IBM employees only.
RxNPipes requires that you are already running under OS/2 2.x or higher with
OS/2 Procedures Language 2/REXX installed.
Installation of RxNPipes is described in Installation.
To be able to use an RxNPipes function in a REXX program, you must first add
the functions using the built-in REXX function RxFuncAdd.
Example:
call RxFuncAdd "RxNPCreate","RxNPipes","RxNPCreate"
The above example would add the RxNPCreate function so that it can be used.
The RxNPipes function RxNPLoadFuncs will automatically load all other RxNPipes
functions. To do this from within a programme, add the following instructions:
call RxFuncAdd "RxNPLoadFuncs","RxNPipes","RxNPLoadFuncs"
call RxNPLoadFuncs
Once the RxNPipes functions are loaded by RxNPLoadFuncs they are usable by all
OS/2 sessions.
The main RxNPipes functions are listed in the Contents. Additional functions
that return values used in return code are displayed when you select the "+"
sign beside "Errors and Error Codes".
The functions provided are:
RxNPLoadFuncs
RxNPDropFuncs
RxNPCreate
RxNPOpen
RxNPRead
RxNPWrite
RxNPReconnect
RxNPClose
RxNPCreateSem
RxNPWaitFree
RxNPWaitRead
RxNPQuery
RxNPDebug
RxNPVersion
Functions which explain errors and error codes.
- RxNPErrNotFound
- RxNPErrAccessDenied
- RxNPErrInvalidHandle
- RxNPErrNoMemory
- RxNPErrNoStructures
- RxNPErrInvalidParm
- RxNPErrInterrupt
- RxNPErrBroken
- RxNPErrBad
- RxNPErrBusy
- RxNPErrNoData
- RxNPErrNotConnected
- RxNPErrMoreData
- RxNPErrTimeout
- RxNPExplainErr
These functions should normally be used in a REXX parse statement, as:
parse value RxNPOpen(PipeName) with retcode handle .
In some cases the RxNPipes functions return debugging tokens beyond those
documented here. These additional tokens are subject to change and should be
ignored. They are not part of the programming interface to RxNPipes.
ΓòÉΓòÉΓòÉ 1.2. Debugging ΓòÉΓòÉΓòÉ
The underlying Dos... function calls, their return codes, and other pertinent
information are available to the user of these functions.
This is triggered by the REXX Variable RxNPipes.0, as described below.
The information displayed depends on the particular function call and is
subject to change from release to release. A single RxNPipes function call may
result in more than one Dos... function call, and therefore more than one line
of diagnostic output.
The format and content of this information is not a programming interface.
There are 4 possible destinations for trace information:
The screen (stdout),
A Rexx stem variable,
A queue, such as that provided by PMPrintf, or
A named file.
selected according to the value, which may be specified in upper, lower, or
mixed case, in RxNPipes.0:
If this variable has the value "TRACE", then diagnostic information about
every Dos... function call will be displayed on Standard Output (stdout).
If this has a non-negative numeric value RxNPipes.0 will be incremented
and its new value, i, will be used to store the debugging information in
RxNPipes.i instead of displaying it.
If the variable RxNPipes.0 begins with "\QUEUES\", diagnostic information
about every Dos... function call is sent to the queue named by
RxNPipes.0. If RxNPipes.0 contains "\QUEUES\" alone the queue name
"\QUEUES\PRINTF32" (the default for PMPrintf) is assumed.
If the variable RxNPipes.0 contains a file name, which is recognised by:
- having a period (.) or a backslash (\) in the first position, or
- having a colon (:) in the second position, and
- not being a queue name.
the trace information is appended to the named file which is opened,
written to, and closed for each trace event.
Trace information sent to queues or files is preceded by a timestamp taking
the form "YYYYMMDD HHMMSShh [pid]: ", where pid is the process id. If the
queue or file cannot be opened the trace request is silently ignored.
In addition, the function RxNPDebug can be used to place arbitrary information
in the debug stream.
ΓòÉΓòÉΓòÉ 1.3. Return Codes ΓòÉΓòÉΓòÉ
These functions return the last-seen return code from the underlying Dos...
functions executed on behalf of the user.
Arbitrarily, the return codes ERROR_FILE_NOT_FOUND and ERROR_PATH_NOT_FOUND are
consolidated into a single NotFound value (RxNPErrNotFound(), which happens to
be the ERROR_PATH_NOT_FOUND value) in places where this type of return is
expected.
Equally arbitrarily, the return codes ERROR_SEM_TIMEOUT and ERROR_TIMEOUT are
consolidated into a single Timeout value (RxNPErrTimeout(), which happens to be
the ERROR_TIMEOUT value) in places where this type of return is expected.
These consolidations happen after the debugging information that is described
in Debugging Information is produced.
ΓòÉΓòÉΓòÉ 1.4. RxNPLoadFuncs ΓòÉΓòÉΓòÉ
Function: RxNPLoadFuncs
Purpose: Use this functions to load all the remaining functions in the
RxNPipes Package.
Syntax: parse value RxNPLoadFuncs() with version
version Version identification. This always
takes the form
"RxNPipes Version X.X ..."
Example:
call RxNPLoadFuncs
ΓòÉΓòÉΓòÉ 1.5. RxNPDropFuncs ΓòÉΓòÉΓòÉ
Function: RxNPDropFuncs
Purpose: Use this functions to drop all the loaded RxNPipes functions.
Once this function is processed by any REXX programme, the
RxNPipes functions are no longer accessible in any OS/2
session.
Syntax: call RxNPDropFuncs
Example:
call RxNPDropFuncs
ΓòÉΓòÉΓòÉ 1.6. RxNPCreate ΓòÉΓòÉΓòÉ
Function: RxNPCreate
Purpose: Use this function to Create a named pipe, specify its
characteristics, and make it ready for communication.
Syntax: parse value
RxNPCreate(name,direction,blocking,instances,buffer1,buffer2)
with retcode handle .
name The name of the Pipe. This must take
the form "\pipe\...". This parameter
is required.
direction The direction of flow through the
pipe. This must be one of: "Duplex"
(the default), "Inbound, or
"Outbound". Only the first character
of this parameter is significant. Case
is Ignored.
blocking The blocking mode of the pipe. This
must be "Wait" (the default) or
"Nowait". Only the first character of
this parameter is significant. Case is
Ignored.
instances The number of instances permitted for
this pipe. This must be "Unlimited"
(the default, only the first character
of this parameter being significant
with case ignored), or a number
between 1 and 254.
buffer1 The buffer size for the pipe. For
Duplex pipes, this is the size of the
inbound buffer. The default is 4096
bytes.
buffer2 The outbound buffer size for a duplex
pipe. This is valid for Duplex pipes
only. The default is 4096 bytes.
retcode The return code from the underlying
Dos... function.
handle The pipe handle
Example:
parse value RxNPCreate(pipe,"Duplex","Wait",1) with retcode handle .
ΓòÉΓòÉΓòÉ 1.7. RxNPOpen ΓòÉΓòÉΓòÉ
Function: RxNPOpen
Purpose: Use this function to open an existing Named Pipe.
Syntax: parse value RxNPOpen(name) with retcode handle .
name The name of the Pipe. This must take
the form "\pipe\...". This parameter
is required.
retcode The return code from the underlying
Dos... function.
handle The handle of the pipe, to be used in
subsequent calls to RxNPipes
functions.
Example:
parse value RxNPOpen("\pipe\exmppipe") with retcode handle .
if retcode=RxNPErrNotFound() then do
say "Pipe does not exist"
return
end
if retcode=RxNPErrBusy() then
retcode=RxNPWaitFree("\pipe\exmppipe")
ΓòÉΓòÉΓòÉ 1.8. RxNPRead ΓòÉΓòÉΓòÉ
Function: RxNPRead
Purpose: Use this function to read messages from an opened Named Pipe.
Syntax: parse value RxNPRead(handle,<symbol>,<buffer size>) with
retcode len message
handle The pipe handle (as returned by
RxNPCreate or RxNPOpen) from which a
message is to be read. This parameter
is required.
symbol The name of a REXX variable in which
the returned message is placed. This
parameter is optional; if not
specified the received data are
returned as part of the function
return value.
If an invalid Rexx symbol name is
given, up to buffer size bytes will be
read from the pipe (and discarded)
before the syntax error is detected.
buffer size The size of buffer to be used to
receive the message. This parameter is
optional; if not specified, a
4096-byte buffer will be used.
retcode The return code from the underlying
Dos... function.
len The number of bytes in the returned
message.
message The text of the message read. This is
supplied only if there is no symbol
parameter.
Example:
parse value RxNPRead(handle,"retval") with retcode len
if retcode <> 0 then do
say "Read Error: retcode="retcode"," RxNPExplainErr(retcode)
return
end
say "Received message:" retval
ΓòÉΓòÉΓòÉ 1.9. RxNPWrite ΓòÉΓòÉΓòÉ
Function: RxNPWrite
Purpose: Use this function to write a message to an opened Named Pipe.
Syntax: parse value RxNPWrite(handle,message) with retcode .
handle The pipe handle (as returned by
RxNPCreate or RxNPOpen) from which a
message is to be read. This parameter
is required.
message The message to be written to the Named
Pipe. This parameter is required.
retcode The return code from the underlying
Dos... function.
Example:
parse value RxNPWrite(handle,"return message") with retcode .
if retcode<>0 then do
say "Write Error: retcode="retcode"," RxNPExplainErr(retcode)
return
end
ΓòÉΓòÉΓòÉ 1.10. RxNPReconnect ΓòÉΓòÉΓòÉ
Function: RxNPReconnect
Purpose: Use this function to re-enable a Named Pipe for communication
with another client.
Syntax: parse value RxNPReconnect(handle) with retcode .
handle The pipe handle (as returned by
RxNPCreate or RxNPOpen) from which a
message is to be read. This parameter
is required.
retcode The return code from the underlying
Dos... function.
Example:
parse value RxNPQuery(handle) with retcode state .
select
when retcode<>0 then do
say "Return code="retcode "querying pipe" pipe RxNPExplainErr(retcode)
return
end
when state="CLOSING" then do
parse value RxNPReconnect(handle) with retcode .
if retcode<>0 then do
say "Reconnect: retcode="retcode RxNPExplainErr(retcode)
return
end
end
otherwise nop
end
ΓòÉΓòÉΓòÉ 1.11. RxNPClose ΓòÉΓòÉΓòÉ
Function: RxNPClose
Purpose: Use this function to close an Named Pipe.
Syntax: parse value RxNPClose(handle) with retcode .
handle The pipe handle (as returned by
RxNPCreate or RxNPOpen) which is to be
closed. This parameter is required.
retcode The return code from the underlying
Dos... function.
Example:
call RxNPClose handle
ΓòÉΓòÉΓòÉ 1.12. RxNPCreateSem ΓòÉΓòÉΓòÉ
Function: RxNPCreateSem
Purpose: Use this function to create a semaphore that can be used to
wait for Pipes that do not block.
Syntax: parse value RxNPCreateSem(handle) with retcode semaphore .
handle The pipe handle (as returned by
RxNPCreate or RxNPOpen) with which
this semaphore is to be associated.
This parameter is required.
retcode The return code from the underlying
Dos... function.
semaphore A semaphore that can be used by
RxNPWaitRead to wait for activity at
the other end of the named pipe
identified by handle.
Example: See RxNPWaitRead.
ΓòÉΓòÉΓòÉ 1.13. RxNPWaitFree ΓòÉΓòÉΓòÉ
Function: RxNPWaitFree
Purpose: Use this function to wait until a Named Pipe is available for
opening and subsequent use.
Syntax: parse value RxNPWaitFree(name,<timeout>) with retcode .
name The name of the Pipe. This must take
the form "\pipe\...". This parameter
is required.
timeout This parameter is optional. If
specified, it it the time (in
milliseconds) to wait for the
specified Named Pipe to be available
for opening.
retcode The return code from the underlying
Dos... function.
Example:
do until retcode<>RxNPErrBusy() /* repeat; someone else may have been waiting too! */
parse value RxNPWaitFree("\pipe\exampipe",10000) with retcode . /* wait 10 sec for the pipe */
if retcode=RxNPErrTimeout() then do
say "Timout waiting for pipe"
return 0
end
parse value RxNPOpen("\pipe\exampipe") with retcode handle .
end
if retcode <> 0 then do
say "Open Error: retcode="retcode"," RxNPExplainErr(retcode)
return
end
ΓòÉΓòÉΓòÉ 1.14. RxNPWaitRead ΓòÉΓòÉΓòÉ
Function: RxNPWaitRead
Purpose: Use this function to wait for data to be available.
Syntax: parse value RxNPWaitRead(handle,semaphore,timeout) with
retcode .
handle The pipe handle (as returned by
RxNPCreate or RxNPOpen) from which a
message will be read by a subsequent
call to RxNPRead. This parameter is
required.
semaphore The semaphore handle (as returned by
RxNPCreateSem)
timeout This parameter is optional. If
specified, it it the time (in
milliseconds) to wait for data to
become available in the specified
pipe.
retcode The return code from the underlying
Dos... function.
Example:
parse value RxNPRead(handle) with retcode len message
do while retcode=RxNPErrNodata() | len=0
do forever
parse value RxNPWaitRead(handle,semaphore,4000) with retcode .
if retcode<>RxNPTimeout() then leave
say "timeout tick every 4 seconds at" time()
/* do here whatever needs doing every 4 seconds */
end
parse value RxNPRead(handle) with retcode len message
end
ΓòÉΓòÉΓòÉ 1.15. RxNPQuery ΓòÉΓòÉΓòÉ
Function: RxNPQuery
Purpose: Use this function to retrieve information about the current
state of the Named Pipe.
Syntax: parse value RxNPQuery(handle) with retcode state instance
pipebytes msgbytes cs nw .
handle The pipe handle (as returned by
RxNPCreate or RxNPOpen) for which
information is required. This
parameter is required.
retcode The return code from the underlying
Dos... function.
state The current state of the Pipe. This
will be one of "LISTENING",
"CONNECTED", "CLOSING", or
"DISCONNECTED".
The pipe is in a listening state after
the server issues DosConnectNPipe by
calling RxNPCreate or RxNPReconnect. A
listening pipe is ready to accept an
RxNPOpen() request. If the pipe is not
in a listening state, DosOpen returns
RxNPErrBusy().
The pipe is in a connected state after
a client has successfully issued
DosOpen by calling RxNPOpen(). The
connected pipe allows the server and
the client to read and write to the
pipe provided both have valid handles.
The pipe is in a closing state after
the last DosClose request has been
made by calling RxNPClose to the pipe
by either the client or the server.
When DosClose has been issued for the
client handle and all of its
duplicates, the client end of the pipe
is closed. The serving end must
acknowledge the closing of the client
end by issuing either
DosDisConnectNPipe by calling
RxNPReconnect or DosClose by calling
RxNPClose. Issuing DosClose
deallocates the pipe.
The pipe is in a disconnected state
immediately after a call to
DosCreateNPipe, or DosDisConnectNPipe.
A disconnected pipe cannot accept a
call to DosOpen. The server must issue
DosDisConnectNPipe before the pipe can
be opened by a client. This state
should not occur when using RxNPipes.
instance The current instance of a named pipe
that can have more than one instance
(as specified in the RxNPCreate call).
pipebytes The number of bytes buffered in the
pipe (including message header bytes)
msgbytes The number of bytes in the current
message.
cs "C" if called from the client end of
the pipe, "S" if called from the
server end.
nw "N" of the Pipe does not block (opened
with "Nowait"), "W" if it does (opened
with "Wait").
Example:
parse value RxNPQuery(handle) with retcode state .
if retcode<>0 then do
say "Query Error: retcode="retcode"," RxNPExplainErr(retcode)
return
end
if state="CLOSING" then do
parse value RxNPReconnect(handle) with retcode .
if retcode<>0 then do
say "Reconnect: retcode="retcode
return
end
end
ΓòÉΓòÉΓòÉ 1.16. RxNPDebug ΓòÉΓòÉΓòÉ
Function: RxNPDebug
Purpose: Use this functions to put arbitrary strings on the debug
stream (see Debugging).
Syntax: call RxNPDebug string1<,string2>...
Example:
parse source . . self
parse args argstring
call RxNPDebug self "starting",argstring
ΓòÉΓòÉΓòÉ 1.17. RxNPVersion ΓòÉΓòÉΓòÉ
Function: RxNPVersion
Purpose: From version 2.0, this function returns the numeric version
of the RxNPipes DLL.
Syntax: parse value RxNPVersion() with ver .
ΓòÉΓòÉΓòÉ 1.18. Errors and Error codes ΓòÉΓòÉΓòÉ
These functions return the error codes associated with various Named Pipe
conditions.
ΓòÉΓòÉΓòÉ 1.18.1. RxNPErrNotFound (3) ΓòÉΓòÉΓòÉ
This function returns the error code associated with the File Not Found
Condition.
ΓòÉΓòÉΓòÉ 1.18.2. RxNPErrAccessDenied (5) ΓòÉΓòÉΓòÉ
This function returns the error code associated with the Access Denied
Condition.
ΓòÉΓòÉΓòÉ 1.18.3. RxNPErrInvalidHandle (6) ΓòÉΓòÉΓòÉ
This function returns the error code associated with the Invalid Handle
Condition.
ΓòÉΓòÉΓòÉ 1.18.4. RxNPErrNoMemory (8) ΓòÉΓòÉΓòÉ
This function returns the error code associated with the No Memory Condition.
ΓòÉΓòÉΓòÉ 1.18.5. RxNPErrNoStructures (84) ΓòÉΓòÉΓòÉ
This function returns the error code associated with the Out of Structures
Condition.
ΓòÉΓòÉΓòÉ 1.18.6. RxNPErrInvalidParm (87) ΓòÉΓòÉΓòÉ
This function returns the error code associated with the Invalid Parameter
Condition.
ΓòÉΓòÉΓòÉ 1.18.7. RxNPErrInterrupt (95) ΓòÉΓòÉΓòÉ
This function returns the error code associated with the Interrupt Condition.
ΓòÉΓòÉΓòÉ 1.18.8. RxNPErrBroken (109) ΓòÉΓòÉΓòÉ
This function returns the error code associated with the Broken Pipe Condition.
ΓòÉΓòÉΓòÉ 1.18.9. RxNPErrBad (230) ΓòÉΓòÉΓòÉ
This function returns the error code associated with the Bad Pipe Condition.
ΓòÉΓòÉΓòÉ 1.18.10. RxNPErrBusy (231) ΓòÉΓòÉΓòÉ
This function returns the error code associated with the Pipe Busy Condition.
ΓòÉΓòÉΓòÉ 1.18.11. RxNPErrNoData (232) ΓòÉΓòÉΓòÉ
This function returns the error code associated with the No Data Condition.
ΓòÉΓòÉΓòÉ 1.18.12. RxNPErrNotConnected (233) ΓòÉΓòÉΓòÉ
This function returns the error code associated with the Pipe Not Connected
Condition.
ΓòÉΓòÉΓòÉ 1.18.13. RxNPErrMoreData (234) ΓòÉΓòÉΓòÉ
This function returns the error code associated with the More Data Condition.
ΓòÉΓòÉΓòÉ 1.18.14. RxNPErrTimeout (640) ΓòÉΓòÉΓòÉ
This function returns the error code associated with the Timeout Condition.
ΓòÉΓòÉΓòÉ 1.18.15. RxNPExplainErr ΓòÉΓòÉΓòÉ
Function: RxNPExplainErr
Purpose: Use this function to return a string explaining the meaning
of a return code.
Syntax: errstring = RxNPExplainErr(retcode)
retcode A return code returned by a Named Pipe
function. This parameter is required.
errstring A text string explaining the error.
Example:
if retcode <> 0 then do
say "Retcode="retcode"," RxNPExplainErr(retcode)
return
end
ΓòÉΓòÉΓòÉ 1.19. Examples ΓòÉΓòÉΓòÉ
The following examples illustrate many of these functions
ΓòÉΓòÉΓòÉ 1.19.1. CalcSamp - A full duplex Named Pipe with no Asychronous processing ΓòÉΓòÉΓòÉ
/* sample for RxNPipes, duplex, wait calculator */
trace 'o'
signal on syntax
pipe="\pipe\calculator"
mark = "/SERVER"
RxNPipes.0="TRACE"
if RxFuncQuery("SysSleep") then
call RxFuncAdd 'SysSleep', 'RexxUtil', 'SysSleep'
if RxFuncQuery("RxNpLoadFuncs") then do
call RxFuncAdd 'RxNPLoadFuncs', 'RxNPipes', 'RxNPLoadFuncs'
say RxNPLoadFuncs()
end
parse source . . self .
parse arg expression
if left(strip(expression),length(mark)) = mark then signal server
RxNPipes.0=0
busy=RxNPErrBusy()
timeout=RxNPErrTimeout()
notfound=RxNPErrNotFound()
parse value RxNPOpen(pipe) with retcode handle .
if retcode=notfound then do
"start ""Piped Calculator Server""/f" self mark
do 60
parse value RxNPOpen(pipe) with retcode handle .
if retcode <> notfound then leave
say "Waiting for Server to start"
call syssleep 1
end
end
do 10 while retcode=busy
x=time()
retcode=RxNPWaitFree(pipe,10000) /* wait 10 sec for it to free up */
if retcode=timeout then do /* this happens only if one process ties it up for 10 seconds */
say "Timout waiting for server"
return 0
end
if retcode<>0 then do
say "Wait Error: retcode="retcode"," RxNPExplainErr(retcode) "in line" whatline()
return
end
parse value RxNPOpen(pipe) with retcode handle .
end
if retcode <> 0 then do
say "Open Error: retcode="retcode"," RxNPExplainErr(retcode) "in line" whatline()
return
end
say 'Expression: "'expression'"'
retcode=RxNPWrite(handle,expression)
if retcode <> 0 then do
say "Write Error: retcode="retcode"," RxNPExplainErr(retcode) "in line" whatline()
return
end
parse value RxNPRead(handle,"retval") with retcode len
if retcode <> 0 then do
say "Read Error: retcode="retcode"," RxNPExplainErr(retcode) "in line" whatline()
return
end
say 'Result: "'retval'"'
say
call RxNPClose handle
do i=1 to RxNPipes.0
parse var RxNPipes.i f1 f2 d
say "["i"]" f1 f2
say "["i"]" strip(d)
say
end
return
server:
"mode co80,45"
parse value RxNPCreate(pipe,"Duplex","Wait",1) with retcode handle .
if retcode<>0 then do
say "Create Error: retcode="retcode"," RxNPExplainErr(retcode) "creating pipe" pipe "in line" whatline()
return
end
signal on halt
do forever
parse value RxNPRead(handle) with retcode len expression
if retcode<>0 then do
say "Read Error: retcode="retcode"," RxNPExplainErr(retcode) "in line" whatline()
call syssleep 30
return
end
if right(expression,2)="0d0a"x then expression=left(expression,length(expression)-2) /* in case message comes from ECHO */
parse value RxNPQuery(handle) with retcode state .
select
when retcode<>0 then do
say "Query Error: retcode="retcode"," RxNPExplainErr(retcode) "in line" whatline()
call syssleep 30
return
end
when translate(expression)="STOP" then do
call RxNPClose handle
"exit"
end
when translate(expression)="DISP" then do
if datatype(RxNPipes.0,"N") then do i=1 to RxNPipes.0
parse var RxNPipes.i f1 f2 d
say "["i"]" f1 f2
say "["i"]" strip(d)
say
end
drop RxNPipes.
RxNPipes.0=0
parse value RxNPWrite(handle,"Done") with retcode .
end
when translate(expression)="NOTRACE" then do
drop RxNPipes.
end
when translate(expression)="DROP" then do
call RxNPClose handle
call RxNPDropFuncs
"exit"
end
when state="CLOSING" then do
parse value RxNPReconnect(handle) with retcode .
if retcode<>0 then do
say "Reconnect Error: retcode="retcode"," RxNPExplainErr(retcode) "in line" whatline()
call syssleep 30
return
end
end
otherwise do
if len=0 then retval="Empty expression received"
else retval=evaluate(expression)
say 'Received: "'expression'" Returning: "'retval'"'
parse value RxNPWrite(handle,retval) with retcode .
if retcode<>0 then do
say "Write Error: retcode="retcode"," RxNPExplainErr(retcode) "in line" whatline()
return
end
end
end
end
evaluate: procedure
parse arg expression
signal on syntax name BADVAL
signal on novalue name BADVAL
interpret "Push" expression
parse pull retval
call syssleep 3 /* simulate processing time */
return retval
BADVAL:
return expression
syntax:
errcode=rc
errline=sigl
say "Error" errcode "("errortext(errcode)") in line" errline":"
say sourceline(errline)
return
halt:
errline=sigl
say "Halt in line" errline":"
say sourceline(errline)
call SysSleep 10
"exit"
whatline:
return "line="sigl
ΓòÉΓòÉΓòÉ 1.19.2. MsgSamp - An Inbound Named Pipe with Asychronous processing ΓòÉΓòÉΓòÉ
/* sample for RxNPipes, inbound, nowait message receiver */
trace 'o'
signal on syntax
pipe="\pipe\message"
mark = "/SERVER"
if RxFuncQuery("SysSleep") then
call RxFuncAdd 'SysSleep', 'RexxUtil', 'SysSleep'
if RxFuncQuery("RxNpLoadFuncs") then do
call RxFuncAdd 'RxNPLoadFuncs', 'RxNPipes', 'RxNPLoadFuncs'
say RxNPLoadFuncs()
end
parse source . . self .
parse arg message
if left(strip(message),length(mark)) = mark then signal server
RxNPipes.0=".\rxnpipes.log"
busy=RxNPErrBusy()
timeout=RxNPErrTimeout()
notfound=RxNPErrNotFound()
parse value RxNPOpen(pipe) with retcode handle .
if retcode=notfound then do
"start ""Piped Message Server"" /f" self mark
do 60
parse value RxNPOpen(pipe) with retcode handle .
if retcode <> notfound then leave
say "Waiting for Server to start"
call syssleep 1
end
end
do 20 while retcode=busy
x=time()
retcode=RxNPWaitFree(pipe,10000) /* wait 10 sec for it to free up */
if retcode=timeout then do /* this happens only if one process ties it up for 10 seconds */
say "Timout waiting for server"
return 0
end
if retcode<>0 then do
say "Wait Error: retcode="retcode"," RxNPExplainErr(retcode)"in line" whatline()
return
end
parse value RxNPOpen(pipe) with retcode handle .
end
if retcode <> 0 then do
say "Open Error: retcode="retcode"," RxNPExplainErr(retcode) "in line" whatline()
if retcode <> 0 then return
end
say "message:" message
retcode=RxNPWrite(handle,message)
if retcode <> 0 then do
say "Write Error: retcode="retcode"," RxNPExplainErr(retcode) "in line" whatline()
return
end
call RxNPClose handle
return
server:
trace 'o'
"mode co80,45"
busy=RxNPErrBusy()
timeout=RxNPErrTimeout()
notfound=RxNPErrNotFound()
nodata=RxNPErrNoData()
parse value RxNPCreate(pipe,"Inbound","NoWait") with retcode handle .
if retcode<>0 then do
say "Return code="retcode "creating pipe" pipe
return
end
signal on halt
parse value RxNPCreateSem(handle) with retcode semaphore .
if retcode<>0 then do
say "Return code="retcode "creating semaphore" RxNPExplainErr(retcode) "in line" whatline()
return
end
do forever
parse value RxNPRead(handle) with retcode len message
do while retcode=nodata | len=0
parse value RxNPQuery(handle) with retcode state .
select
when retcode<>0 then do
say "Return code="retcode "querying pipe" pipe RxNPExplainErr(retcode) "in line" whatline()
call syssleep 30
return
end
when state="CLOSING" then do
parse value RxNPReconnect(handle) with retcode .
if retcode<>0 then do
say "Reconnect: retcode="retcode RxNPExplainErr(retcode) "in line" whatline()
call syssleep 30
return
end
end
otherwise nop
end
SaveRxNpipe=""
TimeCount=-1
do forever
parse value RxNPWaitRead(handle,semaphore,4000) with retcode .
if retcode<>timeout then do
leave
end
TimeCount=TimeCount+1
say "timeout tick every 4 seconds at" time()
if datatype(RxNPipes.0,"N") then do
SaveRxNpipe=1+RxNPipes.0
drop RxNPipes.0
end
end
if SaveRxNPipe<>"" then do
RxNPipes.SaveRxNPipe="= =" TimeCount "timeouts skipped"
RxNPipes.0=SaveRxNPipe
end
parse value RxNPRead(handle) with retcode len message
end
if retcode<>0 then do
say "Return code="retcode "reading pipe" pipe RxNPExplainErr(retcode) "in line" whatline()
call syssleep 30
return
end
if right(message,2)="0d0a"x then message=left(message,length(message)-2) /* in case message comes from ECHO */
select
when translate(message)="STOP" then do
call RxNPClose handle
"exit"
end
when translate(message)="DROP" then do
call RxNPClose handle
call RxNPDropFuncs
"exit"
end
when translate(message)="DISP" then do
if datatype(RxNPipes.0,"N") then do i=1 to RxNPipes.0
parse var RxNPipes.i f1 f2 d
say "["i"]" f1 f2
say "["i"]" strip(d)
say
end
drop RxNPipes.
RxNPipes.0=0
end
when translate(message)="NOTRACE" then do
drop RxNPipes.
end
otherwise do
say 'Received: "'message'"'
end
end
parse value RxNPQuery(handle) with retcode state .
select
when retcode<>0 then do
say "Return code="retcode "querying pipe" pipe RxNPExplainErr(retcode) "in line" whatline()
call syssleep 30
return
end
when state="CLOSING" then do
parse value RxNPReconnect(handle) with retcode .
if retcode<>0 then do
say "Reconnect: retcode="retcode RxNPExplainErr(retcode) "in line" whatline()
call syssleep 30
return
end
end
otherwise nop
end
end
return
syntax:
errcode=rc
errline=sigl
say "Error" errcode "("errortext(errcode)") in line" errline":"
say sourceline(errline)
return
halt:
errline=sigl
say "Halt in line" errline":"
say sourceline(errline)
call SysSleep 10
"exit"
whatline:
return sigl
ΓòÉΓòÉΓòÉ 1.20. Installation ΓòÉΓòÉΓòÉ
There are 4 files in this package:
RxNPipes.dll
RxNPipes.inf
magsamp.cmd
calcsamp.cmd
the latter 2 being examples only, and not essential to the operation of
RxNPipes.
RxNPipes.dll must be copied to a directory in the LIBPATH (in CONFIG.SYS) to
enable the facilities described here.
RxNPipes.inf may be copied to a directory in the BOOKSHELF path (in
CONFIG.SYS) to enable the commands
view RxNpipes
and
help RxNPipes topic
or included as part of the REXX environment variable, as in
set rexx=c:\os2\book\rexx.inf+d:\packages\rxpipe\rxnpipes.inf
to enable these functions to appear as a natural part of the REXX environment.
In the latter case the help text in this file will appear as part of the
overall REXX help.
ΓòÉΓòÉΓòÉ 1.21. Notes ΓòÉΓòÉΓòÉ
ΓòÉΓòÉΓòÉ 1.21.1. Version 2.00: 22nd December 1995 ΓòÉΓòÉΓòÉ
Fixed a bug in the trace output for the openmode parameter in RxNPOpen. Allowed
tracing to a PMPRINTF (or any other Queue-supporting) session. Added
RxNPDebug() and RxNPVersion().
ΓòÉΓòÉΓòÉ 1.21.2. Version 1.40: 27th July 1994 ΓòÉΓòÉΓòÉ
Added an optional parameter to RxNPRead to specify the size of receive buffer
to use. The default size is still 4096 bytes.
ΓòÉΓòÉΓòÉ 1.21.3. Version 1.30: 23rd May 1994 ΓòÉΓòÉΓòÉ
Fixed a bug in returning the received message (from RxNPRead) as part of the
function return value when the number of bytes received was greater than about
250.
ΓòÉΓòÉΓòÉ 1.21.4. Version 1.20: 20th February 1994 ΓòÉΓòÉΓòÉ
Trace to file contains process id.
Formatting improvements made to .inf file
Incorrect references to RXNPipe changed to RXNPipes in the .inf file.
This version was never put on OS2TOOLS
ΓòÉΓòÉΓòÉ 1.21.5. Version 1.10: 17th October 1993 ΓòÉΓòÉΓòÉ
Trace output can be directed to a file. See Debugging.
Samples fixed to load the SysSleep() function from REXXUTIL if required.
ΓòÉΓòÉΓòÉ 1.21.6. Version 1.00: 15th September 1993 ΓòÉΓòÉΓòÉ
Minor editorial changes
Compiled with GA-level of IBM C Set++.
ΓòÉΓòÉΓòÉ 1.21.7. Version 0.71: 7th September 1993 ΓòÉΓòÉΓòÉ
Code and INF file marked "IBM Internal Use Only"
ΓòÉΓòÉΓòÉ 1.21.8. Version 0.07: 6th September 1993 ΓòÉΓòÉΓòÉ
This is the first external release.
This package was compiled with a Beta Version of the IBM C/C++ Tools Product.
My GA version has been ordered but has not arrived; this package will remain at
version 0.x until I can rebuild it with the GA product.
RxNPipes was built as a static-linked subsystem, so there should be no
requirement for other DLLs on your system.
When I first started working on this, but before I released it to anyone else,
I called it RxNPipe in some places and RxNPipes in others. It should be called
RxNPipes consistently; any reference to the name RxNPipe, either in this .inf
file or in the code, is an error.