Using redirection for a simple process controller
[Autolink] Menu
/* ------------------------------------------------------------------ */
/* This is a simple process controller in REXX. */
/* It starts one or more programs and restarts them if they end. */
/* */
/* It uses the redirection of the handle 3 into a file as semaphore */
/* to check if the program is still running. */
/* (Hint: You can use all handles from 1 to 9 for this purpose; */
/* handle 0 is the handle for STDIN) */
/* */
/* Note also that this method does _not_ work for all programs, for */
/* example VIEW.EXE in OS/2 WARP 4! */
/* */
/* */
/* (c) 1996 Bernd Schemmer, Germany, EMail: Bernd.Schemmer@gmx.de */
/* */
/* get the name of this program */
parse source . . thisProgram
/* install an error handler for CTRL-BREAK */
signal on halt
call log "Initializing ..."
/* load the neccessary REXXUTIL functions */
call rxFuncAdd "SysLoadFuncs", "REXXUTIL", "SysLoadFuncs"
call SysLoadFuncs
/* stem with the programs to start */
programsToStart.0 = 0
i = programsToStart.0
/* The entry for VIEW.EXE does _not_ work in */
/* OS/2 WARP 4!!! */
i=i+1;
programsToStart.i.Name = "VIEW.EXE" /* program name */
programsToStart.i.Parameter = "CMDREF.INF" /* program parameter */
programsToStart.i.SemFile = "$$VIEW$$" /* "semaphore" file */
/* Note: */
/* Use special code to get the names for the */
/* semaphore files if you want to run this */
/* program more than ones at the same time!!! */
/* (e.g. use the routine GetTempFile from RXT&T) */
i=i+1;
programsToStart.i.Name = "E.EXE"
programsToStart.i.Parameter = ""
programsToStart.i.SemFile = "$$E$$"
i=i+1;
programsToStart.i.Name = "ICONEDIT.EXE"
programsToStart.i.Parameter = ""
programsToStart.i.SemFile = "$$ICON$$"
programsToStart.0 = i
/* get the directory for the "semaphore" files */
tempDir = value( "TEMP",, "OS2ENVIRONMENT" )
if tempDir = "" then
tempDir = value( "TMP",, "OS2ENVIRONMENT" )
if tempDir = "" then
tempDir = ".\"
if right( tempDir,1 ) <> "\" then
tempDir = tempDir || "\"
call log "Starting the programs ..."
/* marker for the initial round */
firstRound = 1
/* no. of processes started in the initial round */
programsStarted = 0
do forever
do i = 1 to programsToStart.0
curProgram = programsToStart.i.name
curParams = programsToStart.i.Parameter
curSemFile = tempDir || programsToStart.i.SemFile
/* ignore empty entries */
if curProgram = "" then
iterate
/* check, if we can write to the semaphore file */
if stream( curSemFile, "c", "OPEN WRITE" ) = "READY:" then
do
/* we can write to the semaphore file -> */
/* program seems not to be running */
call stream curSemFile, "c", "CLOSE"
if firstRound = 0 then
do
/* program ended for misc. reason -> restart it */
call log "Program """ || curProgram || """ ended. "
call log "Restarting the program: " || curProgram
call log "Parameter are: " || curParams
end /* if firstRound = 0 then */
else
do
/* program not yet started -> start it */
call log "Starting the program: " || curProgram
call log "Parameter are: " || curParams
end /* else */
/* start/restart the program */
/* (redirect handle 3 into the "semaphore" file) */
"@start " curProgram curParams "3>" || curSemFile
if stream( curSemFile, "c", "OPEN WRITE" ) = "READY:" then
do
/* error starting the program */
call stream curSemFile, "c", "CLOSE"
call log "Error starting """ || curProgram || """"
call log "Now ignoring the program " || curProgram
programsToStart.i.name = ""
end /* if stream( curSemFile, "c", "OPEN WRITE" ) = "READY:" then */
else
if firstRound = 1 then
programsStarted = programsStarted +1
end /* if stream( curSemFile, "c", "OPEN WRITE" ) = "READY:" then */
else
do
if firstRound <> 0 then
do
/* cannot use the semaphore file */
call log "Error using the semaphore file " || curSemFile
call log "Now ignoring the program " || curProgram
programsToStart.i.name = ""
end /* if firstRound <> 0 then */
end /* else */
end /* do i = 1 to programsToStart.0 */
if firstRound = 1 then
if programsStarted = 0 then
do
call log "Could not start any of the programs!"
call log "Program ends."
leave
end /* if programsStarted = 0 then */
else
call log programsStarted || " program(s) started."
firstRound = 0
/* wait 2 seconds before we check again */
call SysSleep 2
end /* do forever */
exit
/* ------------------------------------------------------------------ */
log: PROCEDURE expose thisProgram
parse arg message
say "[" || fileSpec( "N", thisProgram ) || " - " || ,
date() time() || "]" message
RETURN
/* ------------------------------------------------------------------ */
/* error handler for CTRL-BREAK */
halt:
call log "CTRL-BREAK received. Doing housekeeping ..."
call log "Press any key after closing all programs started from " || ,
thisprogram || " ..."
"@PAUSE >NUL"
call log "Deleting the semaphore files ... "
do i = 1 to programsToStart.0
curSemFile = tempDir || programsToStart.i.SemFile
curProgram = programsToStart.i.name
if curProgram <> "" then
do
call log "Deleting " || curSemFile
"@del " curSemFile "2>NUL 1>NUL"
if rc <> 0 then
do
call log "Error " || rc || " deleting " || curSemFile
call log "(Maybe " || curProgram || " is still running.)"
end /* if rc <> 0 then */
end /* if curProgram <> "" then */
end /* do i = 1 to programsToStart.0 */
call log "Program ended."
exit 0
/* ------------------------------------------------------------------ */
[Back: Navigate another program]
[Next: Variable handling]