| iMatix home page
| << | < | > | >>
SFL Logo SFL
Version 2.11

 

process_create

#include "sflproc.h"
PROCESS
process_create (
    const char *filename,               /*  Name of file to execute          */
    char *argv [],                      /*  Arguments for process, or NULL   */
    const char *workdir,                /*  Working directory, or NULL       */
    const char *std_in,                 /*  Stdin device, or NULL            */
    const char *std_out,                /*  Stdout device, or NULL           */
    const char *std_err,                /*  Stderr device, or NULL           */
    char *envv [],                      /*  Environment variables, or NULL   */
    Bool  wait                          /*  Wait for process to end          */
)

Synopsis

Creates a subprocess and returns a PROCESS identifying the new process. Optionally directs standard input, output, and error streams to specified devices. The caller can also specify environment symbols that the subprocess can access. Accepts these arguments:
filename File to execute; if bare filename, searches PATH.
argv [] List of arguments; argv [0] is filename; ends in a NULL.
workdir Working directory; if NULL, remains in current directory.
std in Device to use for standard input; NULL = no redirection.
std out Device to use for standard output; NULL = no redirection.
std err Device to use for standard error; NULL = no redirection.
envs [] List of environment symbols to define, or NULL.
If argv is NULL, parses the filename argument into words delimited by whitespace and builds the necessary argv table automatically. Use this feature to execute a command with arguments, specified as one string. The envv list consists of strings in the form "name=value", ending in a NULL pointer. If the envv argument is null, the environment of the current process is passed. Otherwise the envv environment is used. If the child command detects an error at startup, it may exit with an error status. The sleep allows this error to be collected by calling process status() after this call. Returns child process id, or 0 if there was an error. Under VMS, the filename must have been defined as a command before the calling process was started; the path is disregarded. Under OS/2 the filename can be the name of a CMD script, and this will be run with the interpreter specified in the first line (EXTPROC line, or "'/'*!" line; or failing that with the default command interpreter. Under Unix, Windows, and OS/2 this function is implemented using the process create full() function. Known bugs: when parsing filename argument into words, does not handle quotes in any special way; "this text" is 2 words, '"this' and 'text"'. You should have passed the filename through process esc() before adding any optional arguments.

Source Code - (sflproc.c)

{
#if (defined (__UNIX__) || defined (__OS2__) || defined (WIN32))
    PROCESS_DATA
        procinfo = PROCESS_DATA_INIT;
    PROCESS
        process = NULL_PROCESS;

    ASSERT (filename);
    if (!filename)
        return (NULL_PROCESS);

    /*  Set up information to start the new process                          */
    procinfo.filename = filename;
    procinfo.argv     = argv;
    procinfo.workdir  = workdir;
    procinfo.envv     = envv;
    procinfo.wait     = wait;

    /*  process_setinfo handles:
     *  1.  Determining if the path can be searched
     *  2.  Determining if root privileges should be preserved (if applicable)
     *  3.  Redirecting IO streams (if required)
     */
    if (process setinfo (&procinfo, std_in, std_out, TRUE, std_err, FALSE) == 0)
      {
        process = process create full (&procinfo);
        process close io (&procinfo);
        /*  Stuff value into errno, to emulate old behaviour                 */
        errno = procinfo.error;
      }
    return (process);

#elif (defined (__VMS__))
    PROCESS
        process;                        /*  Our created process handle       */
    char
        *curdir,                        /*  Current directory                */
        *clean_filename,                /*  Unescaped filename               */
        *full_filename = NULL,
        *full_std_in   = NULL,
        *full_std_out  = NULL;
    qbyte
        process_flags;                  /*  Process creation flags           */
    int
        argn,                           /*  Argument number                  */
        rc;                             /*  Return code from lib$spawn       */
    Bool
        rebuilt_argv = FALSE;           /*  Did we rebuild argv[]?           */

    VMS_STRING (command_dsc, "");       /*  Define string descriptors        */
    VMS_STRING (std_in_dsc,  "");
    VMS_STRING (std_out_dsc, "");

    /*  If argv[] array was not supplied, build it now from filename         */
    if (!argv)
      {
        argv = tok split (filename);
        filename = argv [0];
        rebuilt_argv = TRUE;
      }
    /*  If filename contains a path or extension, disregard them             */
    clean_filename = strrchr (filename, '/');
    if (clean_filename)
        clean_filename++;
    else
        clean_filename = (char *) filename;
    if (strchr (clean_filename, '.'))
       *strchr (clean_filename, '.') = '\0';

    /*  Rebuild full command from filename and arguments                     */
    full_filename = mem_alloc (tok text size ((char **) argv)
                               + strlen (clean_filename) + 1);
    strcpy (full_filename, clean_filename);
    for (argn = 1; argv [argn]; argn++)
        xstrcat (full_filename, " ", argv [argn], NULL);

    /*  Free argument table if we allocated it dynamically here              */
    if (rebuilt_argv)
        tok free (argv);

    command_dsc.value  = full_filename;
    command_dsc.length = strlen (full_filename);

    /*  Prepare full names for stdin and stdout                              */
    curdir = get curdir ();
    if (std_in)
      {
        if (strchr (std_in, '/'))       /*  If already with path, use as is  */
            full_std_in = mem_strdup (std_in);
        else
          {
            xstrcpy_debug ();
            full_std_in = xstrcpy (NULL, curdir, "/", std_in, NULL);
          }
        translate_to_vms  (full_std_in);
        std_in_dsc.value = full_std_in;
      }
    if (std_out)
      {
        if (strchr (std_out, '/'))      /*  If already with path, use as is  */
            full_std_out = mem_strdup (std_out);
        else
          {
            xstrcpy_debug ();
            full_std_out = xstrcpy (NULL, curdir, "/", std_out, NULL);
          }
        translate_to_vms   (full_std_out);
        std_out_dsc.value = full_std_out;
      }
    std_in_dsc.length  = std_in?  strlen (std_in_dsc.value): 0;
    std_out_dsc.length = std_out? strlen (std_out_dsc.value): 0;

    /*  If requested, change to working directory                            */
    if (workdir)
        chdir (workdir);

    /*  Prepare process flags                                                */
    if (wait)
        process_flags = 0;
    else
        process_flags = 1;              /*  Bit 1 = don't wait for child     */

    process = mem_alloc (sizeof (PROC_HANDLE));
    process-> id     = 0;
    process-> status = 0;               /*  Completion status                */

/*  char *envv [],  */                  /*  Environment variables, or NULL   */

    rc = lib$spawn (
        &command_dsc,                   /*  Command to run                   */
        std_in?  &std_in_dsc: NULL,     /*  Stdin descriptor                 */
        std_out? &std_out_dsc: NULL,    /*  Stdout+stderr                    */
        &process_flags,                 /*  Options for new process          */
        &NULL,                          /*  Process name -- generated        */
        &process-> id,                  /*  Returned process ID              */
        &process-> status);

    if (workdir)                        /*  Switch back to original dir      */
        chdir (curdir);
    mem_free (curdir);

    mem_strfree (&full_filename);       /*  Deallocate various buffers,      */
    mem_strfree (&full_std_in);         /*    if they were used              */
    mem_strfree (&full_std_out);        /*                                   */

    /*  Return process ID.  If we waited for completion, the process id      */
    /*  is always NULL.                                                      */
    if (rc != 1)                        /*  Process failed with error        */
      {
        process close (process);
        process = NULL;
      }
    else
    if (wait)                           /*  Finished with process            */
        process close (process);

    return (process);

#else
    return ((PROCESS) 0);               /*  Not supported on this system     */
#endif
}

| << | < | > | >> iMatix Copyright © 1996-2000 iMatix Corporation