Bitsized
Bitsized

Reputation: 3

Shell Commands in C (Error using Execvp)

I want to run the following command "ls | date" but whenever i isolate the ls and the date, they don't execute using execvp.

Problem:

Isolated:ls
ls: impossible to acess 'ld-linux-x86-64.so.2': Unknown directory or file
ls: impossible to acess 'ld-linux-x86-64.so.2': Unknown directory or file
Isolated: date
ls: impossible to acess 'date': Unknown directory or file

In the code, i want to check the ";" but when i check " " && "|" it isolates the parameters i want... but they don't run.

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

int main() {

 char command_line[256]="ls | date";
 char *ptr_current_command;
 char *saveptr1;
 char *saveptr2;
 char *saveptr3;
 char *ptr_current_parameter;
 char *ptr_current_parameter2;

 char *str[256];
 int i=0;
 int wait_child;
 pid_t pid;



    //Uses Strtok to recognize token ";"     
    ptr_current_command=strtok_r(command_line, ";", &saveptr1);
while (ptr_current_command != NULL) {
    //printf("current_command: %s\n", ptr_current_command);

    //Uses Strtok to recognize token " "
    ptr_current_parameter=strtok_r(ptr_current_command, " ", &saveptr2);
    while(ptr_current_parameter != NULL){
       //printf("\tcurrent_parameter: %s\n", ptr_current_parameter);

       //Uses Strtok to recognize token "|"
       ptr_current_parameter2=strtok_r(ptr_current_parameter, "|", &saveptr3);
       while(ptr_current_parameter2 != NULL){
           printf("\t\tIsolei: %s\n", ptr_current_parameter2);


            str[i]=ptr_current_parameter2;
            i++;           
           //Closes token by token until final NULL of "|"
           ptr_current_parameter2=strtok_r(NULL, "|", &saveptr3);
        }


       pid=fork();
    if (pid < 0) { perror("fork"); exit(errno); }
    if (pid == 0){
        execvp(str[0], str);
        perror("execvp"); exit(errno);
        }   
    if (wait_child)
        waitpid(pid, NULL, 0);      

       //Fecha Delimitador Espaço
       ptr_current_parameter=strtok_r(NULL, " ", &saveptr2);
         }


    //Closes token by token until final NULL of ";"         
    ptr_current_command=strtok_r(NULL, ";", &saveptr1);
    }

return 0;
}

Upvotes: 0

Views: 337

Answers (1)

dbush
dbush

Reputation: 223689

Two issues here.

First, you aren't building str correctly. It has to contain a NULL pointer value after the last parameter, otherwise execvp won't know which option is the last.

Since str is uninitialized, the contents of any element beyond the ones you set in the inner are undefined. Attempting to read those elements (as execvp does) invokes undefined behavior.

After the inner loop, you need to set the current index to NULL.

The second issue is that you don't reset i to 0 when entering the inner loop. So even if the first command works, the second one won't because it keeps writing past the parameters for the first command.

Your inner loop should look like this after the fix:

   i = 0;   // reset i for each command
   while(ptr_current_parameter2 != NULL){
       printf("\t\tIsolei: %s\n", ptr_current_parameter2);


        str[i]=ptr_current_parameter2;
        i++;           
       //Closes token by token until final NULL of "|"
       ptr_current_parameter2=strtok_r(NULL, "|", &saveptr3);
    }
    str[i] = NULL;  // terminate the list

Upvotes: 1

Related Questions