Run a program from within a program


Match word(s).

If you have any questions or comments,
please visit us on the Forums.

FAQ > How do I... (Level 2) > Run a program from within a program

This item was added on: 2003/02/07

There are various ways to run another program from within your own. Most of the good ones are compiler dependant, so best research your help files before going too far

In all the example code below you'll find some sample output. In the cases where a child program has been invoked, this source was used to make that child:


#include <stdio.h> 

int main(int argc, char *argv[] )
{
  int i = 0;
  printf("I am the child\n");
  while (--argc)
    printf ("Arg %d %s\n", ++i, *++argv);
  return 0;
}


Now, we'll start with a simple example of system().

OPTION 1 - system()

Prototype:
int system (const char * s);

This function executes a command specified in s, and returns after the command has been completed. A few reasons not to use this method are:

  • The child program is uninterruptible from the parent program. This means that you cannot stop the program you have started. If it takes 5 hours to complete, that's how long your program will wait
  • You cannot communicate or share variables with the child process
  • For various security reasons, its unsafe and may leave your system open to exploitation.
  • In system terms, its relatively slow.

    Having said that, it is easy to use, and these things have their place. Here is a example of how to use it.

    
    /*
     * This example assumes the program you want to execute
     * is called child.exe, and resides in the same 
     * directory as this program
     */
    
    #include <stdlib.h> 
    #include <stdio.h> 
    #include <string.h> 
    
    int main()
    {
      char child1[] = "child.exe";
      char child2[BUFSIZ];
      
      /* 
       * Execute by passing the name directly 
       */
      system ("child.exe");
      
      /*
       * Execute by passing an array name
       */
      system (child1);
      
      /*
       * Build a buffer, and execute the commands within it
       */
      strcpy (child2, "child.exe");
      strcat (child2, " -aparm -b");
      
      printf ("Executing %s\n", child2);
      system (child2);
      
      return 0;
    }
    
    /*
     * Program output:
     I am the child
     I am the child
     Executing child.exe -aparm -b
     I am the child
     Arg 1 -aparm
     Arg 2 -b
     *
     */
    
    

    OPTION 2 - spawn

    There a family of functions collectively known as spawn. These are:

    #include <process.h>
    int spawnl(   mode, path, arg0, arg1..., argn, 
                  NULL );
    int spawnle(  mode, path, arg0, arg1..., argn, 
                  NULL, envp);
    int spawnlp(  mode, file, arg0, arg1..., argn, 
                  NULL );
    int spawnlpe( mode, file, arg0, arg1..., argn, 
                  NULL, envp);
    int spawnv(   mode, path, argv );
    int spawnve(  mode, path, argv, envp );
    int spawnvp(  mode, file, argv );
    int spawnvpe( mode, file, argv, envp );
    
    int         mode;      /* mode for parent      */
    const char *path;      /* file name incl. path */
    const char *file;      /* file name            */
    const char *arg0,..., 
               *argn;      /* arguments            */
    char *const argv[];    /* array of arguments   */
    char *const envp[];    /* environment strings  */
    

    These functions create and execute a new child process, named by path or file (depending on the form of the function used). The value of mode determines how the program is loaded, and how the parent program will behave after the child program is initiated.

    P_WAIT
    The child program is loaded into memory and executed, and then the parent program resumes execution.
    P_NOWAIT
    Causes the parent program to execute concurrently with the new child process.
    P_NOWAITO
    Causes the parent program to execute concurrently with the new child process. The wait() function cannot be used to obtain the exit code.
    P_OVERLAY
    The child program replaces the parent program in memory and is executed. No return is made to the parent program.

    The various forms of the spawn functions are:

  • The l form : These contain an argument list, terminated by a NULL pointer. The argument arg0 should point to a filename that is associated with the child program.
  • The v form : These contain a pointer to an argument vector. The value in argv[0] should point to a filename that is associated with the child program. The last member of argv must be a NULL pointer. The value of argv cannot be NULL, but argv[0] can be a NULL pointer if no argument strings are passed.
  • The p form : These use paths listed in the PATH environment variable to locate the program to be loaded, provided certain conditions are met.
  • The e form : These pass a pointer to a new environment for the child program. The argument envp is an array of character pointers to null-terminated strings. The array of pointers is terminated by a NULL pointer. The value of envp cannot be NULL, but envp[0] can be a NULL pointer, if no environment strings are passed.

    
    #include <stdio.h> 
    #include <process.h> 
    
    int main(void)
    {
      
      puts("Spawning child with spawnl");
      
      spawnl( P_WAIT, "child.exe",
        "child.exe", "Using spawnl", "Arg1", "Arg2", NULL );
        
      return 0;
    }
    
    /*
     * Program output:
     Spawning child with spawnl
     I am the child
     Arg 1 Using
     Arg 2 spawnl
     Arg 3 Arg1
     Arg 4 Arg2
     *
     */
    
    

    
    #include <stdio.h> 
    #include <process.h> 
    
    int main(void)
    {
      char *my_args[4];
      
      my_args[0] = "child.exe";
      my_args[1] = "arg1";
      my_args[2] = "arg2";
      my_args[3] = NULL;
      
      puts("Spawning child with spawnv");
      
      spawnv( P_WAIT, "child.exe", my_args);
        
      return 0;
    }
    
    /*
     * Program output:
     Spawning child with spawnv
     I am the child
     Arg 1 arg1
     Arg 2 arg2
     *
     */
     
    

    OPTION 3 - fork/exec

    Using a combination of fork and exec, you can duplicate your running program in memory, then turn the second copy into another program altogether.

    Prototypes:
    #include <sys/types.h>
    #include <unistd.h>
    pid_t fork( void );

    The exec family consists of:

    #include <unistd.h>
    int execl(   path, arg0, arg1..., argn, NULL );
    int execle(  path, arg0, arg1..., argn, NULL,
                 envp );
    int execlp(  file, arg0, arg1..., argn, NULL );
    int execlpe( file, arg0, arg1..., argn, NULL,
                 envp );
    int execv(   path, argv );
    int execve(  path, argv, envp );
    int execvp(  file, argv );
    int execvpe( file, argv, envp );
    
    const char *path;     /* file name incl. path */
    const char *file;     /* file name            */
    const char *arg0,..., 
               *argn;     /* arguments            */
    char *const argv[];   /* array of arguments   */
    char *const envp[];   /* environment strings  */
    

    These have the same forms to the spawn functions (l, v, p and e).

    
    #include <stdio.h> 
    #include <stdlib.h> 
    #include <sys/types.h>
    #include <unistd.h> 
    
    
    int main(void)
    {
      char *my_args[5];
      pid_t pid;
      
      my_args[0] = "child.exe";
      my_args[1] = "arg1";
      my_args[2] = "arg2";
      my_args[3] = NULL;
      
      puts ("fork()ing");
      
      switch ((pid = fork()))
      {
        case -1:
          /* Fork() has failed */
          perror ("fork");
          break;
        case 0:
          /* This is processed by the child */
          execv ("child.exe", my_args);
          puts("Uh oh! If this prints, execv() must have failed");
          exit(EXIT_FAILURE);
          break;
        default:
          /* This is processed by the parent */
          puts ("This is a message from the parent");
          break;
      }
      
      puts ("End of parent program");
      return 0;
    }
    
    /*
     * Program output:
     fork()ing
     This is a message from the parent
     End of parent program
     I am the child
     Arg 1 arg1
     Arg 2 arg2
     *
     */
    
    

    Further options

    Windows options: (Credit: Sunlight) Use one of the _spawn functions, or CreateProcess, or ShellExecute. Which one you use depends on what you want to do. _spawn is simplest (and most portable), CreateProcess gives you the most control, ShellExecute gives you the most flexibility (starts documents as well as files, for example).

    Here are some examples of Windows versions, compliments of Fordy.

    Using CreateProcess()

    
    #include <windows.h> 
    
    int main(void)
    {
      char szPath[] = "C:\\WINDOWS\\system32\\Calc.exe";
      PROCESS_INFORMATION pif;  //Gives info on the thread and..
                               //..process for the new process
      STARTUPINFO si;          //Defines how to start the program
    
      ZeroMemory(&si,sizeof(si)); //Zero the STARTUPINFO struct
      si.cb = sizeof(si);         //Must set size of structure
    
      BOOL bRet = CreateProcess(
            szPath, //Path to executable file
            NULL,   //Command string - not needed here
            NULL,   //Process handle not inherited
            NULL,   //Thread handle not inherited
            FALSE,  //No inheritance of handles
            0,      //No special flags
            NULL,   //Same environment block as this prog
            NULL,   //Current directory - no separate path
            &si,    //Pointer to STARTUPINFO
            &pif);   //Pointer to PROCESS_INFORMATION
    
      if(bRet == FALSE)
      {
        MessageBox(HWND_DESKTOP,"Unable to start program","",MB_OK);
        return 1;
      }
    
      CloseHandle(pif.hProcess);   //Close handle to process
      CloseHandle(pif.hThread);    //Close handle to thread
    
      return 0;
    }
    
    

    Using ShellExecute()

    
    #include <windows.h>  //You need shell32.lib for this one 
    
    int main(void)
    {
      char szPath[] = "C:\\WINDOWS\\system32\\Calc.exe";
    
      HINSTANCE hRet = ShellExecute(
            HWND_DESKTOP, //Parent window
            "open",       //Operation to perform
            szPath,       //Path to program
            NULL,         //Parameters
            NULL,         //Default directory
            SW_SHOW);     //How to open
    
      /*
      The function returns a HINSTANCE (not really useful in this case)
      So therefore, to test its result, we cast it to a LONG.
      Any value over 32 represents success!
      */
    
      if((LONG)hRet <= 32)
      {
        MessageBox(HWND_DESKTOP,"Unable to start program","",MB_OK);
        return 1;
      }
    
      return 0;
    }
    
    

  • Script provided by SmartCGIs