Write a shell in C/C++ **Prefer this to be written in C++** You do NOT need to b
ID: 3782619 • Letter: W
Question
Write a shell in C/C++
**Prefer this to be written in C++**
You do NOT need to be concerned with piping the output of commands to other commands or background job control
Your shell should use the fork system call and the execv system call (or one of its variants) to execute commands. The shell needs to use either wait or waitpid system calls to wait for a program to complete execution. You should recognize the command exit to mean that your shell program should terminate by calling the exit() system call.
A very simple shell such as this needs at least the following components:
a command-line parser to figure out what the user is trying to do.
If a valid command has been entered, the shell should use fork to create a new child process, and the child process should exec the command.
Your shell will need to support file redirection. Use the same syntax as defined in the Bash shell: a single '>' implies that one needs to redirect the standard output of the program being started to the referenced file while a single '<' implies the same with standard input. The double '>>' implies that standard output will append to an existing file rather than create a new file (similar behavior is required for the '<<' operator and standard input). You do not need to implement support for the Bash pipeline operator '|'.
Before calling exec to begin execution, the child process may have to close stdin (file desriptor 0) and/or stdout (file descriptor 0), open the corresponding file and use the dup2 system call to make it the appropriate file descriptor. Don't forget to use the close system call to close the old file descriptor.
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 execute_command(char **, int, char **);
void handle_signal(int);
int parser(char *, char **, char **, int *);
void split(char *);
#define INPUT_STRING_SIZE 80
#define NORMAL 00
#define O_R 11//O_R
#define I_R 22
#define PIPELINE 33
#define BG 44
#define OUTPUT_APP 55
typedef void (*sighandler_t)(int);
int main(int argc, char *argv[])
{
int i, mode = NORMAL, Argc;
size_t len = INPUT_STRING_SIZE;
char *cpt, *input, *Argv[INPUT_STRING_SIZE], *supplement = NULL;
input = (char*)malloc(sizeof(char)*INPUT_STRING_SIZE);
char curDir[100];
while(1)
{
mode = NORMAL;
getcwd(curDir, 100);
printf("%s@%s->", getlogin(),curDir);
getline( &input, &len, stdin);
if(strcmp(input, "exit ") == 0)
exit(0);
Argc = parser(input, Argv, &supplement, &mode);
if(strcmp(*Argv, "cd") == 0)
{
chdir(Argv[1]);
}
else
execute_command(Argv, mode, &supplement);
}
return 0;
}
int parser(char *input, char *Argv[], char **supplement, int *mode)
{
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 '&':
*mode = BG;
break;
case '>':
*mode = O_R;
*Argv = '';
src++;
if(*src == '>')
{
*mode = OUTPUT_APP;
src++;
}
while(*src == ' ' || *src == ' ')
src++;
*supplement = src;
split(*supplement);
stop = 1;
break;
case '<':
*mode = I_R;
*Argv = '';
src++;
while(*src == ' ' || *src == ' ')
src++;
*supplement = src;
split(*supplement);
stop = 1;
break;
case '|':
*mode = PIPELINE;
*Argv = '';
src++;
while(*src == ' ' || *src == ' ')
src++;
*supplement = 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 execute_command(char **Argv, int mode, char **supplement)
{
pid_t pid, pid2;
FILE *fp;
int mode2 = NORMAL, Argc, status1, status2;
char *Argv2[INPUT_STRING_SIZE], *supplement2 = NULL;
int myPipe[2];
if(mode == PIPELINE)
{
if(pipe(myPipe)) //create pipe
{
fprintf(stderr, "Pipe failed!");
exit(-1);
}
parser(*supplement, Argv2, &supplement2, &mode2);
}
pid = fork();
if( pid < 0)
{
printf("Error occured");
exit(-1);
}
else if(pid == 0)
{
switch(mode)
{
case O_R:
fp = fopen(*supplement, "w+");
dup2(fileno(fp), 1);
break;
case OUTPUT_APP:
fp = fopen(*supplement, "a");
dup2(fileno(fp), 1);
break;
case I_R:
fp = fopen(*supplement, "r");
dup2(fileno(fp), 0);
break;
case PIPELINE:
close(myPipe[0]); //close input of pipe
dup2(myPipe[1], fileno(stdout));
close(myPipe[1]);
break;
}
execvp(*Argv, Argv);
}
else
{
if(mode == BG)
;
else if(mode == PIPELINE)
{
waitpid(pid, &status1, 0);
pid2 = fork();
if(pid2 < 0)
{
printf("error ");
exit(-1);
}
else if(pid2 == 0)
{
close(myPipe[1]); //close output to pipe
dup2(myPipe[0], fileno(stdin));
close(myPipe[0]);
execvp(*Argv2, Argv2);
}
else
{
close(myPipe[0]);
close(myPipe[1]);
}
}
else
waitpid(pid, &status1, 0);
//wait(NULL);
}
}
=========================================================
Output:
akshay@akshay-Inspiron-3537:~/Chegg$ g++ shell.cpp
akshay@akshay-Inspiron-3537:~/Chegg$ ./a.out
akshay@/home/akshay/Chegg->
Related Questions
drjack9650@gmail.com
Navigate
Integrity-first tutoring: explanations and feedback only — we do not complete graded work. Learn more.