simple shell in C

This shell is called mosh (My Own Shell). When invoke, it should be able to read a command typed on its prompt ($) and execute it in a new process. It should also have a shell variable similar to PATH in bash. Shell variables are set as follows:

PATH=/usr/bin:/bin

The executable for the command is searched in the directories in the path and the first one found should be executed.

mosh should also be able to handle pipes (not more than one pipe) similar to bash.

Implementation in C

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

#define INPUT_SIZE 512
#define BUF_SIZE 10

char** split_String(char *input_ptr,char *buffer[BUF_SIZE],int *n_args);
/**
*Main function of the shell
*/
int main(){
    char input[INPUT_SIZE];
    char *buffer[BUF_SIZE];
    char *pipe_forw[BUF_SIZE];
    char *ext_array[BUF_SIZE];
    char **buf;
    char *input_ptr;
    int status_1,status_2;
    int counter=0;int ispipe;
    int pfds[2];
    int num_of_args=0;int prev_args_pipe=0;
    int n_args;
    printf("\n\t----------------------------------------------------");
    printf("\n\t\t\tWelcome to MY SHELL");
    printf("\n\t----------------------------------------------------\n\n");
    while(1){
        //Get the directory root path
        char root[100];
        printf("mosh:~");
        printf("%s%s",getcwd(root,100),"$ ");

        /*char *PATH;
        PATH="/bin/";
        char prog[INPUT_SIZE];
        strcpy(prog, PATH);*/

        //Take the std input from the keyboard
        fgets(input,sizeof(input),stdin);
        input_ptr=input;
        //Split the input string
        buf=split_String(input_ptr,buffer,&n_args);
        //Check whether # of arguments is zero
        if(n_args==0){
            continue;
        }
        ispipe=0;
        //Take the split result to a char * array
        for(counter=0;counter<sizeof(buf);counter++){
            if((&*buf[counter])=='\0')
                break;
            num_of_args=counter+1;
            //Take and hold the pipe index from the char * array
            if(strcmp(&*buf[counter],"|")==0){
                ispipe=num_of_args;
            }
            if(&*buf[counter]=='\0'){
                ext_array[counter]='\0';
                break;
            }
            else
                ext_array[counter]=&*buf[counter];
        }
        //Compare the input string is exit
        if(strcasecmp(&*buf[0],"exit")==0){
            exit(0);
        }
        //Check the cd command
        if(strcasecmp(&*buf[0],"cd")==0){
            chdir(ext_array[1]);
            continue;
        }
        //Check the path
        if(strcasecmp(&*buf[0],"$path")==0){
            printf("%s\n",getenv("PATH"));
            //printf("%s\n",PATH);
            continue;
        }
        //Create a new process
        pid_t pid=fork();
        pid_t pid_2;
        if(pid == -1){
            perror("Undefined");
            continue;
        }
        //Child running
        else if(pid==0){
            //Check whether input includes the pipe
            if(ispipe){
                //Count the # of args after the pipe symbol
                prev_args_pipe=num_of_args-ispipe;
                //These args put in to the another array
                for(counter=0;counter<prev_args_pipe;counter++){
                    pipe_forw[counter]=ext_array[ispipe+counter];
                    pipe_forw[counter+1]='\0';
                }
                num_of_args=ispipe;
                //Pipe symbol index convert to the NULL
                ext_array[ispipe-1]='\0';
                //Create the pipe
                pipe(pfds);
                //Run the child process
                if((pid_2=fork())==0){
                    close(1);
                    dup(pfds[1]);
                    close(pfds[0]);
                    int chk_value=execvp(ext_array[0],ext_array);
                    if(chk_value == -1){
                        printf("Error: Command Not Found\n");
                    }
               
                    /*strcat(prog, ext_array[0]);
                    execv(prog,ext_array);*/

                    exit(127);
                }
                //Run the parent process
                else{
                    waitpid(&status_2);
                    close(0);
                    dup(pfds[0]);
                    close(pfds[1]);
                    int chk_value=execvp(pipe_forw[0],pipe_forw);
                    if(chk_value == -1){
                        printf("Error: Command Not Found\n");
                    }
                    /*strcat(prog, pipe_forw[0]);
                    execv(prog,pipe_forw);*/

                    exit(128);
                }
            }
            //Run the command without pipe
            else{
            int chk_value=execvp(buffer[0],buffer);
            if(chk_value == -1){
                printf("Error: Command Not Found\n");
            }
            /*strcat(prog, buffer[0]);
            execv(prog,buffer);*/

            }
            exit(127);
        }
        //Parent is waiting until child terminates
        else{
            wait(&status_1);
        }
    }
    return 0;
}

/**
*Split the input buffer string
*/
char** split_String(char *input_ptr,char *buffer[BUF_SIZE],int *n_args){
    int counter;
    for(counter=0;counter<BUF_SIZE;counter++){
        if((buffer[counter]=strtok(input_ptr," \t\n"))=='\0'){
            *n_args=counter;
            break;
        }
        input_ptr=NULL;
    }
    return buffer;
}

Comments

Popular posts from this blog

Solve the Maze by DFS (Depth First Search)

Rabin Karp Algorithm

Text-to-Speech converter