Command Log (XForms (Forms Library) - Version 1.2 (Rev. 4) A Graphical User Interface Toolkit for X)

Next: Colormap, Previous: Messages and Questions, Up: Part I Goodies [Contents][Index]

### 6.2 Command Log

In a number of situations, a GUI is created specifically to make an existing command-line oriented program easier to use. For stylistic considerations, you probably don’t want to have the output (`stderr` and `stdout`) as a result of running the command printed on the terminal. Rather you want to log all the messages to a browser so the user can decide if and when to view the log. For this, a goodie is available

    long fl_exe_command(const char *cmd, int block);

This function, similar to a `system(3)` call, forks a new process that runs the command `cmd`, which must be a (null-terminated) string containing a command line passed to the (sh) shell. The output (both `stderr` and `stdout`) of `cmd` is logged into a browser, which can be presented to the user when appropriate (see below). The `block` argument is a flag indicating if the function should wait for the child process to finish. If the argument `block` is true (non-zero), the function waits until the command `cmd` completes and then returns the exit status of the command `cmd` (i.e., the status one gets form `wait()` or `waitpid()`, so use `WEXITSTATUS()` on it if you want the return or `exit()` value from the program started)). If the argument `block` is false (0), the function returns immediately without waiting for the command to finish. In this case, the function returns the process ID of the child process or -1 if an error occured.

Unlike other goodies, `fl_exe_command()` does not deactivate other forms even in blockng mode. This means that the user can interact with the GUI while `fl_exe_command()` waits for the child process to finish. If this is not desired, you can use `fl_deactivate_all_forms()` and `fl_activate_all_forms()` to wrap the function.

If `fl_exe_command()` is called in non-blocking mode, the following function should be called to clean up related processes and resources before the caller exits (otherwise a zombie process may result)

    int fl_end_command(long pid);

where `pid` is the process ID returned by `fl_exe_command()`. The function suspends the current process and waits until the child process is completed, then it returns the exit status of the child process or -1 if an error has occurred.

There is another routine that will wait for all the child processes initiated by `fl_exe_command()` to complete

    int fl_end_all_command(void)

The function returns the status of the last child process.

You can also poll the status of a child process using the following routine

    int fl_check_command(long pid);

where `pid` is the process ID returned by `fl_exe_command()`. The function returns the following values: 0 if the child process is finished; 1 if the child process still exists (running or stopped) and -1 if an error has occurred inside the function.

If some interaction with the command being executed is desired, the following functions may be more appropriate. These functions operates almost exactly as the `popen(3)` and `pclose(3)` functions:

    FILE *fl_popen(const char *command, const char *type);
    int fl_pclose(FILE *stream);

The `fl_popen()` function executes the command in a child process, and logs the `stderr` messages into the command log. Further, if type is `"w"`, `stdout` will also be logged into the command browser. `fl_pclose()` should be used to clean up the child process.

To show or hide the logs of the command output, use the following functions

    int fl_show_command_log(int border);
    void fl_hide_command_log(void);

where `border` is the same as that used in `fl_show_form()`. These two routines can be called anytime anywhere after `fl_initialize()` has been invoked.

The command log is by default placed at the top-right corner of the screen. To change the default placement, use the following routine

    void fl_set_command_log_position(int x, int y);

where `x` and `y` are the coordinates of the upper-left corner of the form relative to the root window. The logging of the output is accumulative, i.e., `fl_exe_command()` does not clear the browser. To clear the browser, use the following routine

    void fl_clear_command_log(void);

It is possible to add arbitrary text to the command browser via the following routine

    void fl_addto_command_log(const char *txt);
    void fl_addto_command_log_f(const char *fmt, ...);

where `txt` for `fl_addto_command_log()` is a string and `fmt` for `fl_addto_command_log_f()` is a format string like for `printf()` that gets expanded using the following arguments. This string, with possible embedded newlines, gets added to the last line of the browser using `fl_addto_browser_chars()`.

Finally, there is a routine that can be used to obtain the GUI structure of the command browser

    typedef struct {
        FL_FORM   * form;           /* the form */
        FL_OBJECT * browser;        /* the browser */
        FL_OBJECT * close_browser;  /* the close button */
        FL_OBJECT * clear_browser;  /* the clear button */
    } FD_CMDLOG;

    FD_CMDLOG *fl_get_command_log_fdstruct(void);

From the information returned the application program can change various attributes of the command browser and its associated objects. Note however, that you should not hide/show the form or free any members of the structure.

Next: Colormap, Previous: Messages and Questions, Up: Part I Goodies [Contents][Index]