RUN

The RUN instruction executes the command passed as argument.

Syntax

RUN command 
  [ IN {FORM|LINE} MODE ]
  [ RETURNING variable | WITHOUT WAITING ]
  1. command is a string expression with the command to be executed.
  2. variable is an integer variable receiving the execution status of the command.

Understanding the RUN command

The RUN instruction hands the argument command to the command interpreter. When not specifying the WITHOUT WAITING clause, the calling process waits for the called process to finish execution. Otherwise, the calling process waits the command termination.

Important: The RUN instruction has limited support on mobile platforms.
  • The RUN instruction is not supported on mobile devices, because of operating system limitations.
  • RUN command WITHOUT WAITING is not supported when programs run on an application server and display on a mobile device, because the Genero GUI protocol is not able to handle multiple connections at the same time.

Defining the command execution shell

In order to execute the command line, the RUN instruction uses the OS-specific shell defined in the environment of the current user. On UNIX™, this is defined by the SHELL environment variable. On Windows®, this is defined by COMSPEC. On Windows, the program defined by the COMSPEC variable must support the /c option as CMD.EXE.

Waiting for the subprocess

By default, the runtime system waits for the end of the execution of the command, suspending the execution of the current program. After executing the command, the display of the parent program is restored.

If you specify WITHOUT WAITING, the specified command line is executed as a background process, and generally does not affect the visual display. This clause can be used when the command takes some time to execute, and the parent program does not need the result to continue. It is also typically used in GUI mode to start another program. Do not use this clause in TUI mode when the sub-program displays forms, otherwise both programs would run simultaneously on the same terminal.

Catching the execution status

The RETURNING clause saves the termination status code of the command that RUN executes in a program variable of type SMALLINT. Examine the variable after execution to determine the next action to take. A status code of zero usually indicates that the command has terminated normally. A non-zero exit status indicates an error.

Important:

The execution status provided by the RETURNING clause is platform-dependent. On UNIX systems, the value is composed of two bytes having different meanings. On Windows platforms, the execution status is usually zero for success, not zero if an error occurred.

On UNIX systems, the lower byte (x mod 256) of the return status defines the termination status of the RUN command. The higher byte (x / 256) of the return status defines the execution status of the program. On Windows systems, the value of the return status defines the execution status of the program.

IN LINE MODE and IN FORM MODE

When using the TUI mode, programs operate by default in line mode, but as many statements take it into form mode (including OPTIONS statements that set keys, DISPLAY, OPEN WINDOW, DISPLAY FORM, and other screen interaction statements), typical interactive TUI programs are actually in form mode most of the time.

According to the type of command to be executed, you may need to use the IN {LINE|FORM} MODE clause with the RUN instruction. It defines how the terminal or the graphical front-end behaves when running the child process.

Besides RUN, the OPTIONS, START REPORT and START REPORT... TO PIPE instructions can explicitly specify a screen mode.

If no screen mode is specified in the RUN command, the current value from the OPTIONS statement is used. This is, by default, IN LINE MODE.

Note: With START REPORT using PIPE specifications, the default screen mode is IN FORM MODE.

When the RUN statement specifies IN FORM MODE, the program remains in form mode if it is currently in form mode, but it does not enter form mode if it is currently in line mode. When the prevailing RUN option specifies IN LINE MODE, the program remains in line mode if it is currently in line mode, and it switches to line mode if it is currently in form mode. This also applies to the PIPE option.

Typically, if you need to run another interactive program, you must use the IN LINE MODE clause:

  • In TUI mode, the terminal is in the same state (in terms if tty options) as when the program began. Usually the terminal input is in cooked mode, with interrupts enabled and input not becoming available until after a newline character is typed.
  • In GUI mode, if the WITHOUT WAITING clause in used, the front-end is warned before the child process is started (this causes a first network round-trip) After the child is started, the front-end is warned that the command was executed (second network round-trip). If the RUN command must wait for child termination (i.e. no WITHOUT WAITING clause is used), no particular action is taken.

However, if you want to execute a subprocess running silently (batch program without output), you must use the IN FORM MODE clause:

  • In TUI mode, the screen stays in form mode if it was in form mode, which saves a clear / redraw of the screen. The FORM mode specifies the terminal raw mode, in which each character of input becomes available to the program as it is typed or read.
  • In GUI mode, no particular action is taken to warn the front-end (there is no need to warn the front-end for batch program execution).

To summarize, no matter if you are in TUI or GUI mode, run silent (batch) programs in FORM MODE, and if the program to run is interactive, or displays messages to the terminal, or if you don't known what it does, use the LINE MODE (which is the default).

Important: Executing an interactive Genero program with RUN … IN FORM MODE WITHOUT WAITING (or with RUN … WITHOUT WAITING and the FORM MODE is set by OPTIONS), can lead to unexpected behavior.

A good practice is to encapsulate child program and system command execution in functions.

Example

MAIN
  DEFINE result SMALLINT
  CALL runApplication("app2 -p xxx")
  CALL runBatch("ls -l", FALSE) RETURNING result 
  CALL runBatch("ls -l > /tmp/files", TRUE) RETURNING result 
END MAIN

FUNCTION runApplication(pname)
  DEFINE pname, cmd STRING
  LET cmd = "fglrun " || pname 
  IF fgl_getenv("FGLGUI") == 0 THEN
    RUN cmd 
  ELSE
    RUN cmd WITHOUT WAITING
  END IF
END FUNCTION

FUNCTION runBatch(cmd, silent)
  DEFINE cmd STRING
  DEFINE silent STRING
  DEFINE result SMALLINT
  IF silent THEN
    RUN cmd IN FORM MODE RETURNING result 
  ELSE
    RUN cmd IN LINE MODE RETURNING result 
  END IF
  IF fgl_getenv("OS") MATCHES "Win*" THEN
    RETURN result 
  ELSE
    RETURN ( result / 256 )
  END IF
END FUNCTION