1

I'm trying to use exec to execute a list of commands given as arguments.

Example input when In run the program would be ./assn2 ls date.

When I do this only the first command is executed.

#include<stdio.h>
#include<stdlib.h>
#include<sys/wait.h>
#include<unistd.h>


int main(int argc, char *argv[])
{
  int args = argc-1;

  pid_t childpid = fork();

  // error
  if (childpid < 0)
  {
    perror("fork() error");
    exit(-1);
  }

  // parent process
  if (childpid != 0)
  {
    printf("Parent Process started, now waiting for ID: %d\n", childpid);
    wait(NULL);
    printf("Parent Process resumeed. Child exit code 0. Now terminating\n");
    exit(0);
  }

  // child process
  if (args > 0)
  {
    printf("Child process has begun.  %d argument/s provided\n", args);

    int i;
    for (i = 1; i <= argc; i++)
    {
      execlp(argv[i], argv[i], NULL);
    }
    execvp(argv[1], argv);
  }
  else
  {
    printf("No arguments provided, terminating child\n");
  }

  return 0;
}
Borodin
  • 126,100
  • 9
  • 70
  • 144
wcroundy
  • 21
  • 3
  • 2
    `for(i = 1; i <= argc; i++)` - this is going out of array bounds. End `exec*` functions do not return, so obviously you can't execute them sequentially in the same process.. – Eugene Sh. Sep 22 '17 at 17:52
  • Read http://advancedlinuxprogramming.com/ and [execvp(3)](http://man7.org/linux/man-pages/man3/execvp.3.html) – Basile Starynkevitch Sep 22 '17 at 17:58
  • 1
    If you're going to exec two programs, you're going to need two subprocesses, so you're going to need to call `fork` twice. I believe you'll want to move the `fork` call into the loop. If you only have one subprocess (as you do here), once you make a successful call to exec, you've overwritten that process with the new code you exec'ed, and your later call(s) to exec will never occur. – Steve Summit Sep 22 '17 at 18:02
  • 1
    `execlp(argv[i] ,argv[i], NULL);` --> `execlp(argv[i] ,argv[i], (void*)NULL);` Cast needed as `NULL` may be an `int` 0. [Ref](https://stackoverflow.com/a/21559462/2410359) – chux - Reinstate Monica Sep 22 '17 at 18:30

2 Answers2

3

Once the first child process execs (and succeeds), the for loop no longer continues because the an execlp would just replace the current process image with the command being exec'ed.

What you want to do is to loop over the command line arguments in the parent process and exec once for each of the command. Something like is probably what you're after:

   for(int i = 1; i < argc; i++) {
       pid_t pid = fork();
       if (pid == 0) {
           execlp(argv[i] ,argv[i], (char*)0);
           perror("exec");
       } else if (pid > 0) {
           wait(NULL);
       } else {
           perror("fork");
           exit(1);
       }
  }
P.P
  • 117,907
  • 20
  • 175
  • 238
1

What are you trying to achieve with the sequential calls to execlp() and execvp()? These functions are not meant to return. I think you should read the ref:

The exec() family of functions replaces the current process image with a new process image. [..] The exec() functions only return if an error has occurred.

As a result you cannot execute them one after another in the same process.

Read about fork():

fork() creates a new process by duplicating the calling process.


Moreover, here:

for(i = 1; i <= argc; i++)

you go out of bounds, since argv starts indexing from 0, and ends at argc - 1.

Chnage it to:

for(i = 1; i < argc; i++)
gsamaras
  • 71,951
  • 46
  • 188
  • 305
  • 1
    And in case the significance of "replacing the process image" is not immediately evident to the OP, you can't get much clearer than this, from the same reference: "The exec() functions only return if an error has occurred." – John Bollinger Sep 22 '17 at 18:17