/*-------------------------------------------------------------------- * Function: start_process * Returns: t or nil * Description: Starts a process using a fork and exec pair. It places * the new process ID, name, and associated GUI button in * a list so that we can use SIGCHLD to clean up the child * list and the screen at once. *------------------------------------------------------------------*/ function start_process (button, prog, process_name, args) { local pid; if ((prog == "gnuplot") && (find_on_path("gnuplot") == nil)) { anygui_makemsg(string("\nIt looks like you don't have\n", "gnuplot on your system.", "\n\nYou must install gnuplot to make plots.\n")); } else if ((prog == "textlog") && (find_on_path("textlog") == nil)) { anygui_makemsg(string("To work correctly, this part of the demo requires", " the Cascade TextLogger,\nwhich apparently is not", " installed on your system.\n\n", "You can download the Cascade TextLogger from the Cogent Web Site\n", "at http://www.cogent.ca/Software/TextLogger_Software.html")); }
The gnuplot program is an open-source plotting program that is not currently available in QNX, and may or may not be installed on a user's Linux machine. So we have to check for it, using the find_on_path function (below), and if it is missing, display a message box, using the anygui_makemsg function.
else { block_signal(SIGCHLD); if ((pid = fork()) == 0) { /* This is the child process. */ exec (prog, car(args), cadr(args), caddr(args), car(cdddr(args)), car(nth_cdr(args, 4)), car(nth_cdr(args, 5)), car(nth_cdr(args, 6)), car(nth_cdr(args, 7)), car(nth_cdr(args, 8)), car(nth_cdr(args, 9))); /* In case the above exec commands fails, the following will be * called, and it's virtually guaranteed not to fail. Thus in * any circumstance a child process gets created.*/ exec("/bin/true"); } Children = cons (list (pid, process_name, button, prog), Children); unblock_signal(SIGCHLD); pid; } }
The Gamma functions used here are fork to spawn a child process, exec to execute a program, list to create a list, and cons to add new elements to a list.
The list Children is an association list, which is a list whose members are also lists. Usually each sub-list within an association list has two members, and the list is typically used to store values and look them up, associating the second member of the sub-list with the first. In this case, each sub-list has three members, but it follows the same principle. You can see how the sub-list members of Children are accessed by looking at the child_died function.
When a process starts, the start_process function adds the process ID, name, and associated button to the Children association list, so that it can be found and stopped when necessary.
The find_on_path function uses the Gamma string_split, getenv, cdr, car, string and access functions to determine whether a command can be found in the PATH of the current operating system.
/*-------------------------------------------------------------------- * Function: find_on_path * Returns: t on success, or nil * Description: Determines if a command exists on the operating system. * Used by start_process when loading the Log or History * programs to check whether the gnuplot and/or the Cascade * TextLogger program is installed on the system. Also * used by program_startup to check that the Cascade * DataHub and Cascade Historian are installed. *------------------------------------------------------------------*/ function find_on_path(name) { local bin_path = string_split (getenv("PATH"), ":", 0); local found; for (; !found && bin_path; bin_path = cdr(bin_path)) { if (access (string(car(bin_path),"/",name), 0) == 0) found = car(bin_path); } found; }
Copyright © 1995-2010 by Cogent Real-Time Systems, Inc. All rights reserved.