zach adams
zach adams

Reputation: 29

why does ls with execvp work when i hardcode it in but when I read it in through input it wont work

When my code looks like this I can run ls -la perfectly.

    char * ls_args[3] = {"ls","-la",NULL};

                pid_t c_pid, pid;
                int status;

                c_pid = fork();

                if (c_pid == 0){
                     /* CHILD */

                     printf("Child: executing ls\n");

                     //execute ls                                                                                                                                                               
                    execvp( ls_args[0], ls_args);
                    //only get here if exec failed                                                                                                                                             
                    perror("execve failed");
                    }else if (c_pid > 0){
                     /* PARENT */

                        if( (pid = wait(&status)) < 0){
                            perror("wait");
                             _exit(1);
                         }

                         printf("Parent: finished\n");

                        }else{
                            perror("fork failed");
                            _exit(1);
                        }


            }

but when I do this, it doesn't work and it is so confusing becuase when I read in ls from the line and pass it to execvp isnt it the same thing as ls_args[0]? but it doesnt work this way. any help would be great thank you

        arguments[count] = NULL;
                pid_t c_pid, pid;
                int status;

                c_pid = fork();

                if (c_pid == 0){
                     /* CHILD */

                     printf("Child: executing ls\n");

                     //execute ls                                                                                                                                                               
                    execvp( arguments[0], arguments);
                    //only get here if exec failed                                                                                                                                             
                    perror("execve failed");
                    }else if (c_pid > 0){
                     /* PARENT */

                        if( (pid = wait(&status)) < 0){
                            perror("wait");
                             _exit(1);
                         }

                         printf("Parent: finished\n");

                        }else{
                            perror("fork failed");
                            _exit(1);
                        }


            }

what is in arguments[0] is "ls". also when I check the lengths of each of these and compare them as long as the string inside it is the same thing.

my complete code

    int main(){

char *line;
int quit = 1;
char **arguments;
char *directory;
int count = 0;
char *comand = "ls";
int done  = 1;

printf("\n\n\n\n\n\n\nLinux Shell: \nCreated by: Zach Adams\n\n");
 //while this is one it will keep looping

while(1){ //will run until user enters quit
    done  = 1;
    count = 0;
    print_shell_name();
    line = (char *)malloc(sizeof(line));
    arguments = (char **)malloc(sizeof(char*));
    line = fgets(line,MAX,stdin);
    quit = strncmp(line,"quit",4);
    if(quit == 0)
        exit(0);

    int i = 0; //parsing line 
    char *p = strtok(line, " "); //will save the string up to the token entered
    free(line);
    while(p!= NULL){
        arguments[i++] = p; //putting the command or argument into an array of arguments
        p = strtok(NULL," "); //null is a pointer to the first argument and continues to scan where prev call ends until it gets to token again
        count++;
    }
    p = strtok(arguments[count-1], "\n"); //get the new line character off of the end 
    arguments[count-1] = p;
    if((strncmp(arguments[0],"cd",2)==0) || (strncmp(arguments[0],"clr",3)==0) //run internal commands
        || (strncmp(arguments[0],"dir",3) ==0) || (strncmp(arguments[0],"environ",7)==0) || (strncmp(arguments[0],"echo",4)==0)
            || (strncmp(arguments[0],"help",4)==0) || (strncmp(arguments[0],"pause",5)==0)){
                execute(arguments,count); //execute internal commands
            }else if(arguments[0] == NULL){
                printf("NULL arg");
            }else{
                //char * ls_args[3] = {"ls","-la",NULL};
                arguments[count] = NULL;
                pid_t c_pid, pid;
                int status;

                c_pid = fork();

                if (c_pid == 0){
                     /* CHILD */

                     printf("Child: executing ls\n");

                     //execute ls                                                                                                                                                               
                    execvp( arguments[0], arguments);
                    //only get here if exec failed                                                                                                                                             
                    perror("execve failed");
                    }else if (c_pid > 0){
                     /* PARENT */

                        if( (pid = wait(&status)) < 0){
                            perror("wait");
                             _exit(1);
                         }

                         printf("Parent: finished\n");

                        }else{
                            perror("fork failed");
                            _exit(1);
                        }


            }

            free(arguments);

            }

return 0;

}

Upvotes: 0

Views: 132

Answers (1)

Andrew Henle
Andrew Henle

Reputation: 1

This code destroys the line variable you're using strtok() on:

char *p = strtok(line, " "); //will save the string up to the token entered
free(line);

When you call

strtok(NULL," ")

later on, strtok() is still trying to parse line, which has been freed.

Upvotes: 1

Related Questions