Academic Integrity: tutoring, explanations, and feedback — we don’t complete graded work or submit on a student’s behalf.

Using C++, you are to design a simple shell which implements a subset of the fun

ID: 3822718 • Letter: U

Question

Using C++, you are to design a simple shell which implements a subset of the
functionality of the Bourne Again Shell (Bash). The requirements for your shell are as
follows:
Continually prompt for textual user input on a command line.
Parse user input according the the provided grammar (see below)
When a user enters a well formed command, execute it in the same way as a shell. You must use the commands fork and exec to accomplish this. You may NOT use
the C++ system() command.
Allow users to pipe the standard output from one command to the input of another
an arbitrary number of times.
Support input redirection from a le and output redirection to a le.
Allow users to specify whether the process will run in the background or foreground
using an '&'. (Commands to run in the foreground do not have an '&', and commands
that run in the background do)

Explanation / Answer

#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>
#include <bits/stdc++.h>


void Run_command(char **, int, char **);
void handle_signal(int);
int spliter(char *, char **, char **, int *);
void split(char *);

#define SIZE 80

#define NR                00
#define O_R    11
#define I_R    22
#define PL            33
#define BG           44
#define OUTPUT   55


typedef void (*sighandler_t)(int);

int main(int argc, char *argv[])
{
   int i, m = NR, Argc;
   size_t len = SIZE;
   char *cpt, *input, *Argv[SIZE], *sp = NULL;
   input = (char*)malloc(sizeof(char)*SIZE);
  
   char curLoc[100];
  
   while(1)
   {
       m = NR;
       getcwd(curLoc, 100);
       printf("%s@%s->", getlogin(),curLoc);
       getline( &input, &len, stdin);
       if(strcmp(input, "exit ") == 0)
           exit(0);
       Argc = spliter(input, Argv, &sp, &m);
       if(strcmp(*Argv, "cd") == 0)
       {
           chdir(Argv[1]);
       }
       else
           Run_command(Argv, m, &sp);
   }
   return 0;
}

int spliter(char *input, char *Argv[], char **sp, int *m)
{
   int Argc = 0, stop = 0;
   char *src = input;
   while(*src != '' && stop == 0)
   {
       *Argv = src;
       Argc++;
       while(*src != ' ' && *src != ' ' && *src != '' && *src != ' ' && stop == 0)
       {
           switch(*src)
           {
               case '&'://check for background process
                   *m = BG;
                   break;
               case '>'://redirection
                   *m = O_R;
                   *Argv = '';
                   src++;
                   if(*src == '>')
                   {
                       *m = OUTPUT;
                       src++;
                   }
                   while(*src == ' ' || *src == ' ')
                       src++;
                   *sp = src;
                   split(*sp);
                   stop = 1;
                   break;
               case '<'://redirection
                   *m = I_R;
                   *Argv = '';
                   src++;
                   while(*src == ' ' || *src == ' ')
                       src++;
                   *sp = src;
                   split(*sp);
                   stop = 1;
                   break;
               case '|'://ipie command
                   *m = PL;
                   *Argv = '';
                   src++;
                   while(*src == ' ' || *src == ' ')
                       src++;
                   *sp = src;
                   stop = 1;
                   break;
           }
           src++;
       }
       while((*src == ' ' || *src == ' ' || *src == ' ') && stop == 0)
       {
           *src = '';
           src++;
       }
       Argv++;
   }
  
   *Argv = '';
   return Argc;
}

void split(char *src)
{
   while(*src != ' ' && *src != ' ' && *src != ' ')
   {
       src++;
   }
   *src = '';
}

void Run_command(char **Argv, int m, char **sp)
{
   pid_t pid, pid2;
   FILE *fp;
   int m2 = NR, Argc, status1, status2;
   char *Argv2[SIZE], *sp2 = NULL;
   int myp[2];
   if(m == PL)
   {
       if(pipe(myp))                   //create pipe
       {
           fprintf(stderr, " failed!");
           exit(-1);
       }
       spliter(*sp, Argv2, &sp2, &m2);
   }
   pid = fork();
   if( pid < 0)
   {
       printf("Error");
       exit(-1);
   }
   else if(pid == 0)
   {
       switch(m)
       {
           case O_R:
               fp = fopen(*sp, "w+");
               dup2(fileno(fp), 1);
               break;
           case OUTPUT:
               fp = fopen(*sp, "a");
               dup2(fileno(fp), 1);
               break;
           case I_R:
               fp = fopen(*sp, "r");
               dup2(fileno(fp), 0);
               break;
           case PL:
               close(myp[0]);       //close input of pipe
               dup2(myp[1], fileno(stdout));
               close(myp[1]);
               break;
       }
       execvp(*Argv, Argv);
   }
   else
   {
       if(m == BG)
           ;
       else if(m == PL)
       {
           waitpid(pid, &status1, 0);      
           pid2 = fork();
           if(pid2 < 0)
           {
               printf("error ");
               exit(-1);
           }
           else if(pid2 == 0)
           {
               close(myp[1]);       //close output to pipe
               dup2(myp[0], fileno(stdin));
               close(myp[0]);
               execvp(*Argv2, Argv2);
           }
           else
           {
              
               close(myp[0]);
               close(myp[1]);
           }
       }
       else
           waitpid(pid, &status1, 0);

   }
}

===========================================================================

Output:

akshay@akshay-Inspiron-3537:~/Chegg$ g++ shell.cpp
akshay@akshay-Inspiron-3537:~/Chegg$ ./a.out
akshay@/home/akshay/Chegg->ps
PID TTY TIME CMD
3443 pts/0 00:00:00 bash
3568 pts/0 00:00:00 python
7023 pts/0 00:00:00 a.out
7026 pts/0 00:00:00 a.out
7189 pts/0 00:00:00 a.out
7190 pts/0 00:00:00 ps
akshay@/home/akshay/Chegg->exit

===================================================================

Hire Me For All Your Tutoring Needs
Integrity-first tutoring: clear explanations, guidance, and feedback.
Drop an Email at
drjack9650@gmail.com
Chat Now And Get Quote