Start a Process - start_process, find_on_path

Cogent Tools Demo and Tutorials: Version 4.0
Prev | Chapter 9. Common Functions for Any Program (in `lib/common.g`) | Next

# 9.5. Start a Process - `start_process`, `find_on_path`

       /*--------------------------------------------------------------------
        * 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;
        }

Prev | Home | Next
Control Button Functionality - `start_stop` | Up | Handling Terminated Processes - `child_died`

Copyright 1995-2002 by Cogent Real-Time Systems, Inc.