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
Related Questions
drjack9650@gmail.com
Navigate
Integrity-first tutoring: explanations and feedback only — we do not complete graded work. Learn more.