Next: , Previous: , 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: , Previous: , Up: Part I Goodies   [Contents][Index]