use exec with a command typed from keyboard

387 Views Asked by At

I create an array of strings to put attributes to the command (e.g. ls -l), but exec command wants an array of chars, how can i resolve it? this code should create a child which execute a command chosen by input.. I have even some problems with the wait() when pid != 0.. Can you help me out to finish it? Thank you a lot.

int main(void) {

        char array[100];
        char character;
        int i = 0;
        char* point;
        int j = 0;

        printf ("Digit a string");
        printf ("\n");
        do {
            character = getchar();
            array[i] = character;
            i++;
        }
        while (character != '\n');
        array[i-1] = '\0';
        i = 0;

        char* string[100];

        char *word = strtok(array, " .");
        while (word != NULL) {
            printf("%s\n", word);
            string[j] = word;
            word = strtok(NULL, " .");

        }

        printf ("\n");  

    pid_t  pid;
    pid = fork();

        if (pid == -1) {

        perror("");

    }else if (pid == 0) {

        if (execlp(string, NULL) < 0) {     /* execute the command  */

                    exit(1);
            }
      else {

        //.. wait until the child ends
        wait(pid);



      }
   }
    return;
}
1

There are 1 best solutions below

1
On BEST ANSWER

Your big issue is you are not using execlp correctly. execlp takes a variable number of arguments that are the arguments passed to the program. It is expected to work like this:

execlp("ls", "ls", "-l", NULL);

What you have is an array of arguments so you want to use one of the v variants of exec. You can find all the variants here. So what you want to do is something more like this:

execvp(string[0], string);

Note that the command itself is one of the arguments as in both examples. Another issue with your program is you are not incrementing j in your loop where you are using strtok. Also note that for execvp the last element of the array should be NULL so exec knows what it has found the last argument. One final thing is that you do not have to check the return value of any of the exec functions. If exec returned that means there was an error, otherwise it never returns. errno is set when exec fails so you can check that. For completeness find, sections of corrected code below with comments:

char *word = strtok(array, " .");
j = 0;
while (word != NULL) {
  printf("%s\n", word);
  string[j++] = word; // Increment j
  word = strtok(NULL, " .");
}
string[j] = NULL; // Make sure the array is NULL terminated

And where you call exec

execvp(string[0], string); // You most likely want execvp, execv would work as 
                           // well but that takes an entire path and not a filename
fprintf(stderr, "Failed to exec"); // If the program reached this point we know exec failed
exit(1);

Let me explain he comment at execvp in greater detail. The exec variants with a p in their name take a filename instead of a path. These variants will mimic how a shell works and use the PATH environment variable to look for the binary. Therefore if you do something like execlp("ls", "ls", "-l", NULL); it will work assuming you have ls in one of the folders specified by PATH. If you do execl("ls", "ls", "-l", NULL); (not the lack of a p) it will fail as "ls" is not a valid path; it would have to be something like "/usr/bin/ls" instead. Which version you want, something that takes a filename or a file path, depends on your application.