Question: Instructions Extend your code from the ps 2 - simple shell assignment so that it also handles I / O redirection, allowing the standard output

Instructions
Extend your code from the ps2-simple shell assignment so that it also handles I/O redirection, allowing the standard output to be redirected to an output file. For example:
% shell.out cat < input > output
This command specifies that the input file will be used to read data, and the output will be directed to the specified output file instead of the terminal. To accomplish this, you will need to use the dup2 system call. Additionally, you should enhance the parser to recognize the < and > symbols. If these symbols are present, the parser should tie STDIN_FILENO and STDOUT_FILENO to the respective file descriptors.
For additional learning support to assist you in solving this assignment, please refer to the materials listed at the bottom of the page and to the 'Relevant External Materials' page on Canvas.
Submission: Commit the following to your GitHub repository:
Your source code.
a Makefile that compiles and runs your program efficiently.
a README file that details any dependencies and provides step-by-step instructions on using the Makefile to compile and run the program.
Code from ps2- Simple Shell:
/*
Alena Fisher
10/27/2024
*/
#include "../include/SimpleShell.h"
using namespace std;
void SimpleShell::execute(const vector& argv)
{
int status;
pid_t child;
// Spawning a child process
child = fork();
// Parent process portion
if (child >0){
cout <<"("<< getpid()<<") : I am a parent process waiting..." << endl;
waitpid(child, &status, 0); // Wait for child process to finish
cout << "Waiting complete" << endl;
}
// Child process portion
else if (child ==0){
cout << "I am a child executing a new environment" << endl;
// Ensure there's at least one argument
if (argv.empty()){
cerr << "Error: No command to execute" << endl;
_exit(1);
}
// Prepare arguments for exec (must end with nullptr)
vector args;
for (const auto& arg : argv){
args.push_back(arg.c_str());
}
args.push_back(nullptr);
/*
1. Execute the ls command. execvp is a function that replaces the current process image
with a new process image. In this case, it is the command stored in args[0]
2. const_cast is used to cast the vector from const char* to char* const* because having 'char*'
is required by execvp for the second argument.
3. args.data() returns a pointer to the vector
4.'==-1': -1 is returned after attempting to execute the command if it fails. If it fails,
a message is printed. After this the program exits '_exit(1)'
*/
if(execvp(args[0], const_cast(args.data()))==-1){
perror("exec failed");
_exit(1);
}
}
else {
perror("fork failed"); // Error handling if fork fails
exit(1);
}
}
void SimpleShell::parse(const string& line, vector& tokens, const string& delimiter)
{
size_t start =0;
size_t end =0;
while ((end = line.find(delimiter, start))!= string::npos){
if (end != start){// Ignore empty tokens
tokens.push_back(line.substr(start, end - start));
}
start = end + delimiter.length();
}
if (start < line.length()){// Add the last token
tokens.push_back(line.substr(start));
}
}
void SimpleShell::run()
{
while (true){
string line;
vector tokens;
// Print the prompt
cout <<"("<< getpid()<<")%";
// Get input from the keyboard
if (!getline(cin, line)){
break; // Exit the shell if input fails (e.g., EOF)
}
// Parse the input into tokens
parse(line, tokens, "");
if (tokens.empty()){
continue; // Skip empty input
}
// Execute the user command
execute(tokens);
}
}
int main()
{
SimpleShell shell;
shell.run(); // Start the shell loop
return 0;
}

Step by Step Solution

There are 3 Steps involved in it

1 Expert Approved Answer
Step: 1 Unlock blur-text-image
Question Has Been Solved by an Expert!

Get step-by-step solutions from verified subject matter experts

Step: 2 Unlock
Step: 3 Unlock

Students Have Also Explored These Related Programming Questions!