isCOBOL implementation of CALL SYSTEM and the iscobol.system.exec property

Question ID : 113
Created on 2009-11-26 at 5:01 PM
Author : Veryant Support [support@veryant.com]

Online URL : http://support.veryant.com/support/phpkb/question.php?ID=113



The SYSTEM library routine is used in a program to run an operating system command line as if it was executed from a command prompt, shell, script, batch file, or shortcut.

By default, the isCOBOL implementation of SYSTEM uses the java.lang.Runtime.exec() Java API (mainly for its portability because it's supported and functions the same on all platforms).
For more information about this API, see this link.
However, this Java API has some limitations. For example, it does not support redirection of stdin, stdout, or stderr using the '<', '>', and '|' symbols within the command parameter string.
To address these limitations isCOBOL provides a framework property, iscobol.system.exec, that can be used to customize the behavior of the SYSTEM routine.

Setting iscobol.system.exec to a system command

The iscobol.system.exec property specifies the name of a command to be executed when the SYSTEM routine is called.
The SYSTEM routine constructs a command line using the value of the iscobol.system.exec property followed by the SYSTEM routine's parameter within double-quotes.
For example, setting:

   iscobol.system.exec=sh -c
on UNIX/Linux and executing:
  call "SYSTEM" using "ls > out"
will cause the following command to be executed:
   sh -c "ls > out"
For another example, setting:
   iscobol.system.exec=cmd /c
on Windows and executing:
   call "SYSTEM" using "dir > out"
will cause the following command to be executed:
   cmd /c "dir > out"

Setting iscobol.system.exec to access the C library system

Setting the iscobol.system.exec property to the special value "c" will cause isCOBOL to use the C library system() function instead of the Java API.
This setting is provided for compatibility with other COBOLs.
For example, Micro Focus COBOL and ACUCOBOL-GT implement SYSTEM using the C library system() function.

Set iscobol.system.exec=c to match Micro Focus COBOL and ACUCOBOL-GT behavior of CALL "SYSTEM".

Note:
On Windows the C library system() function is located in the MSVCRT.DLL.
In order to load that DLL add the following property setting:

   iscobol.shared_library_list=msvcrt.dll
or add the following call to your program:
   call "msvcrt.dll"

Note:
With iscobol.system.exec=c programs compiled with -cp option require the SYSTEM parameter to be null terminated (i.e. end with a low-value).
(Note that Micro Focus COBOL programs have the same requirement. So if the program functioned correctly with Micro Focus COBOL then the code probably already null terminates the parameter.)

C$RUN and C$SYSTEM compatibility

isCOBOL also provides C$RUN and C$SYSTEM for compatibility with ACUCOBOL-GT.
The difference between these routines and SYSTEM is that SYSTEM runs the command synchronously so that the program waits for the command to complete before continuing.
C$RUN runs the command asynchronously so that the program continues to run in parallel with the command.
C$SYSTEM combines the functionality of SYSTEM and C$RUN and runs a command synchronously or asynchronously depending on a "flags" parameter.

The iscobol.system.exec property does not affect C$RUN and C$SYSTEM.
With isCOBOL C$RUN and C$SYSTEM always use the java.lang.Runtime.exec() Java API.
To get identical behavior to ACUCOBOL-GT for these routines it is necessary to replace them with calls to SYSTEM or calls to your own subprogram that calls SYSTEM.
For example, you can easily write your own C$RUN or C$SYSTEM routine in COBOL.

Threads in isCOBOL are real OS threads, not merely emulated threads such as in ACUCOBOL-GT.
C$RUN could be implemented by calling SYSTEM in a separate thread.
For example,

   call THREAD "SYSTEM" using "sort input.txt > sorted.txt"
will run the sort asynchronously.
In other words, the CALL will return immediately without waiting for the sort to complete.

At the end of your program you can add the following line to wait for all threads to complete before exiting the process:
  WAIT FOR LAST THREAD
Here is an example program for UNIX/Linux:
   PROGRAM-ID. TESTSYSTEM.
   PROCEDURE DIVISION.
       SET ENVIRONMENT "system.exec" to "c".
       CALL "SYSTEM" USING "ls -lrt * > ls.out.txt".
       CALL THREAD "SYSTEM" USING "sort < ls.out.txt > ls.sort.txt".
       WAIT FOR LAST THREAD.
       GOBACK.
And here is an example program for Windows:
   PROGRAM-ID. TESTSYSTEM.
   PROCEDURE DIVISION.
       SET ENVIRONMENT "system.exec" to "c".
       CALL "msvcrt.dll".
       CALL "SYSTEM" USING "dir * > dir.out.txt".
       CALL THREAD "SYSTEM" USING "sort < dir.out.txt > dir.sort.txt".
       WAIT FOR LAST THREAD.
       GOBACK.
Note
that in the above programs you could delete the SET ENVIRONMENT and the CALL "msvcrt.dll" statements and instead add the following lines to your iscobol.properties file:
   iscobol.system.exec=c
   iscobol.shared_library_list=msvcrt.dll


Back to Original Question