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

C/C++: As we introduced in class, the four functional characters (<, >, |, &) ar

ID: 3801242 • Letter: C

Question

C/C++:
As we introduced in class, the four functional characters (<, >, |, &) are for input redirection, output redirection, pipe and background jobs respectively. By default, they can be interpreted correctly by a UNIX terminal, but not by a C/C++ program. In a UNIX terminal if you type in “echo hello > file1”, you will find a file named “file1” created which has string “hello” stored inside, and that’s because the terminal interpreted “>” correctly and redirected the output of string “hello” from screen to “file1”.
In our Project 1, we want you to write a C/C++ program to interpret all these four functional characters as a UNIX terminal does. So when your program is running, we expect it to allow the user to type in a command line, and if the user types in “echo hello > file1”, the same thing as in a UNIX terminal should happen. This is only the test for output redirection, and we expect the other three functional characters to be interpreted correctly as well.
Note that function “system” cannot be used in your program because it will do everything for you. For example, “system(“echo hello > file1”);” can give the right result without needing you to do anything. Instead, we want you to use system calls for process management and file systems, such as fork, waitpid, execvp, exit, pipe, dup, open, close, etc. First, your program should read in the user’s command line and store it in an array. Then it checks if any of the four functional characters is in the array and will do corresponding work if so.
Use output redirection as an example, if I input “echo hello > file1”, my C/C++ program should read them in, and store them in an array whose name is “args”, with args[0] having “echo”, args[1] having “hello”, args[2] having “>” and args[3] having “file1”. Then my program checks if any of the four functional characters exits, and yes, “>” is found in args[2]. After this my program can do corresponding work: since “>” is in args[2], the following argument—args[3]—should be the output redirection destination, thus my program creates a file called “file1” (using system call “create”) and redirects standard output to “file1” (using system call “dup2”, there can be multiple solutions). Finally, my program executes the command by calling “execvp(args[0], args);”.

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->echo hello > file1
akshay@/home/akshay/Chegg->exit

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

After runing code content of file1

file1

hello

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