Introduction

For this assignment, you will be writing your very own shell-- the mini-shell!

Shell's (or sometimes called command-line interfaces) are text based applications that serve as an intermediate between the user and the operating system. The shell is also a tool for how a user interacts with the operating system. Previously, we have written many scripts that our shell can execute by running various programs. The shell that you build with this assignment will be something you can continually expand on in the future, and perhaps distribute as your own one day! Let us take a closer look at the parts to get started.

Part 1 - Signals

In your shell, you will have to implement a signal handler. We have very briefly discussed signal handlers, so make sure you are familiar with the concept.

Provided below is an example that you can use.

#include < stdio.h>
#include < stdlib.h>
#include < signal.h> // This is new!


// Create a signal handler
void sigint_handler(int sig){
// Ask yourself why 35?
write(1,"Terminating through signal handlern",35);
exit(0);
}

int main(){

// Install our signal handler
signal(SIGINT, sigint_handler);

printf("You can only terminate by pressing Ctrl+Cn");

while(1){
printf("Running forever!n");
sleep(1);
}

return 0;
}
  • The following page provides details about signals: https://ftp.gnu.org/old-gnu/Manuals/glibc-2.2.3/html_chapter/libc_24.html
  • The following article provides a nice introduction as well: https://www.thegeekstuff.com/2012/03/catch-signals-sample-c-code/

Part 2 - Mini-Shell

You are now ready to create Mini-Shell. Mini-Shell is inspired by other popular shells. The good news is you can validate the behavior of your shell against the Unix terminal to ensure it is working.

At a high level, implementing mini-shell takes the following components:

  • You will have a function that reads in commands a user types.
  • Your program will execute in an infinite loop.
  • Your program will execute child processes from the shell (the shell is the parent process) based on the command.

The specifications for your shell

  • You should have a prompt "mini-shell>" in front of each command that is typed out.
    • (If you want to be creative you can include the machine name or other information you can derive).
  • The maximum input size(i.e. BUFFER SIZE) on a given line will be 80 characters for our shell. You can specify this as a constant global variable.
  • Implement a signal handler so when the user presses 'Ctrl+C' the text 'mini-shell terminated' is printed out.
    • Make sure that all child processes are terminated when this occurs!
  • When you launch a new child process from your shell, the child process should run in the foreground by default until it is completed.
    • Here are some examples: https://www.tutorialspoint.com/unix/unix-processes.htm
  • If the user adds the pipe '|' then the output of one process should be the input to the next process.
    • You can assume only one '|' will be used at most. e.g. ls -l | wc
    • Here are some examples: https://www.tutorialspoint.com/unix/unix-pipes-filters.htm
  • Your shell should have some built-in functions that you will have to implement (i.e. functions written in C code). These include 'exit' to terminate your shell, 'cd' so you may change directories, and 'help' explaining all the built-in commands available in your shell.
    • You can test cd by moving up or down the directory tree. (Hint the C library has commands for this)
    • help should print out all of the built-in commands that you provide (including your user made one).
    • exit should terminate the shell. Note: If you launch another shell from within your shell, exit should only close out of the most recently launched shell.
  • You will want to think about how to store these built-in commands.
    • I will hint that using an array with commands and an array of function pointers is one possibly effective solution.
    • What is a function pointer? https://www.geeksforgeeks.org/function-pointer-in-c/
    • You can further think about what an array of function pointers looks like and why this may be appropriate.
  • If a command is not found, your shell should print out an error message, and resume execution.
    • e.g. mini-shell>Command not found--Did you mean something else?
  • You need to implement and document 1 addditional built-in command that you choose here.
    • This built-in command can be of your choosing, but should not be trivial (i.e. not just print a message or clear the screen).
    • An example might be 'history' which stores all of the previous commands a user has typed in and prints them out.
    • Another example may be 'guessinggame' which plays a little game in the terminal for guessing random numbers.
    • Another example may be when the user presses 'tab' a list of programs that can run are found.
    • You can be creative here. The constraint is that you are implementing this functionality in C, and not calling a script.
    • (Edit the readme below with your built-in command)
Academic Honesty!
It is not our intention to break the school's academic policy. Posted solutions are meant to be used as a reference and should not be submitted as is. We are not held liable for any misuse of the solutions. Please see the frequently asked questions page for further questions and inquiries.
Kindly complete the form. Please provide a valid email address and we will get back to you within 24 hours. Payment is through PayPal, Buy me a Coffee or Cryptocurrency. We are a nonprofit organization however we need funds to keep this organization operating and to be able to complete our research and development projects.