/*--------------------------------------------------------------------
* 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.