2

I am trying to create a simple c program that takes user input, passes it to underlying shell and return the ouput of the user command. For eg: pwd will give the present working directory.

I want to do this using fork() and exec() in an infinite loop but I am facing two problems:

  1. My loop terminates after first run
  2. It only takes first argument. 'ls -ltr' will give me the output of 'ls' and not 'ls -ltr'

    int runit(char*);
    
    void main() {
    
    int pid=0;                          
    char command[50];
    while(1)
    
    {
        int d=0;
        printf("Please enter your command!\n");
        scanf("%s", &command);
        switch (pid = fork()) 
        {
            case 0:                    // a fork returns 0 to the child 
                printf("Child process \n");
                d=runit(command);
                if(d==-1){
                printf("command not found \n");}
                break;
    
            default:
                wait(5);               // a fork returns a pid to the parent 
                printf("Parent process \n"); 
                break;
    
            case -1:                   //if something went wrong 
                perror("fork");
                exit(1);
    
        }
      }                
    }
    
    int runit(char* command) {                     //executing the command
    
        char path[50]="/bin/";
    
        int d = execl(strcat(path,command),command,NULL,NULL);     
    
        return(d);
    
    }
    

Can somebody tell me what I am doing wrong or guide me how to correct this.

1 Answer 1

2

This input reading

scanf("%s", &command);

would stop at the first whitespace (unless input failure occurs -- you should check the return value of scanf() in any case). So, when you input ls -ltr, command will have just ls. You need to read lines. For example, use fgets() to read input (and make sure to handle the trailing newline):

fgets(command, sizeof command, stdin);
command[strcspn(command, "\n")] = 0; /* to remove \n if present */

And the next problem is that execl() takes multiple arguments. That means this usage:

int d = execl(strcat(path,command),command,NULL,NULL);     

is broken. You need to split the input command into multiple strings and pass each arguments to execl(). A better option to store the individual strings in an array and use execv() instead.

Another thing you need to be aware of is exec*() family functions do not return on success. So, the return code check isn't very useful - instead you can just use perror() to know why it failed if it failed.

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks. This was really helpful. I changed from scanf to gets and modified execl() command and it worked. It works with execv() as well. But which one is better? I prefer execl() just because of the simplicity over execv()
There's no "better" between execl and execv - they just differ in their arguments. So, use whichever is convenient for your use case.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.