This document provides instructions for writing a shell program in C++. The shell should use fork and exec system calls to launch programs, and wait/waitpid calls to wait for programs to finish. It should support built-in commands like exit, cd, and help. File redirection using >, <, >> should also be supported. The solution outlines the key components of a simple shell: a command parser, launching programs by forking and executing, and implementing built-in commands.
1. Write a shell in C/C++
**Prefer this to be written in C++**
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.
Solution
Shell program in C++
launching program:
int lsh_launch(char **args)
{
pid_t pid, wpid;
int status;
pid = fork();
if (pid == 0) {
// Child process
if (execvp(args[0], args) == -1) {
perror("lsh");
}
2. exit(EXIT_FAILURE);
} else if (pid < 0) {
// Error forking
perror("lsh");
} else {
// Parent process
do {
wpid = waitpid(pid, &status, WUNTRACED);
} while (!WIFEXITED(status) && !WIFSIGNALED(status));
}
return 1;
}
Commands to shell:
int lsh_cd(char **args);
int lsh_help(char **args);
int lsh_exit(char **args);
/*
List of builtin commands, followed by their corresponding functions.
*/
char *builtin_str[] = {
"cd",
"help",
"exit"
};
int (*builtin_func[]) (char **) = {
&lsh_cd,
&lsh_help,
&lsh_exit
};
int lsh_num_builtins() {
return sizeof(builtin_str) / sizeof(char *);
}
/*
Builtin function implementations.
*/
int lsh_cd(char **args)
3. {
if (args[1] == NULL) {
fprintf(stderr, "lsh: expected argument to "cd" ");
} else {
if (chdir(args[1]) != 0) {
perror("lsh");
}
}
return 1;
}
int lsh_help(char **args)
{
int i;
printf("This is shell program ");
printf("Type programs names and arguments, and hit enter. ");
printf("The following are built in: ");
for (i = 0; i < lsh_num_builtins(); i++) {
printf(" %s ", builtin_str[i]);
}
printf("Use command for information on other programs. ");
return 1;
}
int lsh_exit(char **args)
{
return 0;
}
implement Ish_execute():
int lsh_execute(char **args)
{
int i;
if (args[0] == NULL) {
// An empty command was entered.
return 1;
}
for (i = 0; i < lsh_num_builtins(); i++) {
if (strcmp(args[0], builtin_str[i]) == 0) {