/* ------------------------------------------------------------------ */ /* 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 /* ------------------------------------------------------------------ */