Peng Shuai
Peng Shuai

Reputation: 23

creating a shell like program in C

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.

Upvotes: 2

Views: 243

Answers (1)

P.P
P.P

Reputation: 121347

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.

Upvotes: 2

Related Questions