Question

Overview Writing in the C language, implement a very basic shell, called smash. In this project,...

Overview

Writing in the C language, implement a very basic shell, called smash. In this project, we will work on processing strings and using the appropriate system calls.

Build System setup

Before we can start writing code we need to get our build system all setup. This will involve writing a very simple makefile. You should leverage your Makefile project for this part of the assignment!

Write a Makefile that provides the three targets listed below

all - The default rule. Builds your project.

smash - Builds your smash shell. Initially only one file smash.c

Make sure to use macros!

clean - Cleans your build directory and deletes any generated files.

Implement basic string processing

Start your program by reading from standard in and splitting the input string on spaces. To test your program echo the result to standard out.

We will leverage the strtok standard library call for this part of the assignment. Below is a basic example (modified from cplusplus.com):

1: char line[] ="ls -l -a";
2: char* token = strtok(line," ");
3: int i=0;
4: while (token != NULL){
5:   printf ("%d %s\n",i++,token);
6:   token = strtok (NULL, " ");
7: }
0 ls
1 -l
2 -a

We will also leverage the fgets standard library call to read input from standard-in.

1: #define MAXLINE 4096
2: 
3: char    buff[MAXLINE];
4: while (fgets(buff, MAXLINE, stdin) != NULL) {
5:      buff[strlen(buff) - 1] = '\0';    /* replace newline with null */
6: }
7: printf("%s\n",buff);

Smash built-in commands

Once you have your program reading from standard in you will add in a few basic commands and call your first system call! A shell will typically farm out 99% of the work to other programs. There are some things such as cd and exit that are built into the shell. We will be implementing a few built in commands before we start to fork/exec.

The Exit command

Your shell should exit when the user types in exit. You will need to use strcmp to compare the string literal "exit" with the user input.

The cd command

When a user types cd some/directory you will need to use the Linux system call chdir to change the directory of the current process (your smash process) to the given directory. If the user inputs an invalid directory, you need to output the string error: some/directory does not exist. Your shell will replace some/directory with the string the user input.

In order to determine if the chdir() command worked you will need to use the getcwd system call to get the current working directory after the cddir() command. Print the result to ensure that your directory did change. NOTE: Read the documentation for getcwd very carefully! You do NOT need to use malloc for this part of the project we are going to leverage a GNU extension to the POSIX.1-2001 standard that allows us to avoid malloc.

Your should print an error under the following conditions:

chdir() returned non-zero

getcwd() returned an unknown result

If the user enters any other command your shell should print the tokens in the format specified below. The $ is your smash prompt and will be hard coded for this part of the assignment. NOTE: Make sure and print the $ to stderr NOT stdout (use fprintf for this).

Example output

bash_shell>./smash
$exit
bash_shell>./smash
$ls -l -a
[0] ls
[1] -l
[2] -a
$cd /home
/home
$cd /asdfasdf
error: /asdfasdf does not exist
$exit
bash_shell>
0 0
Add a comment Improve this question Transcribed image text
Answer #1

#include <stdio.h>
#include <signal.h>
#include <sys/types.h>
#include <ctype.h>

//This method looks up the input command against the lookup for
//validity purposes
bool FunctionLookUp(char *argv, char *Lookup[])
{
   bool match = false;
   for(int i = 0; i < 10; i++){
       if(*Lookup[i] == *argv){
           match = true;
           break;}
   }
   return match;
}
void parse(char *line, char **argv)
{
     while (*line != '\0') {       /* if not the end of line ....... */
          while (*line == ' ' || *line == '\t' || *line == '\n')
               *line++ = '\0';     /* replace white spaces with 0    */
          *argv++ = line;          /* save the argument position     */
          while (*line != '\0' && *line != ' ' &&
                 *line != '\t' && *line != '\n')
               line++;             /* skip the argument until ...    */
     }
     *argv = '\0';                 /* mark the end of argument list */
}

bool CheckForwardSlash(char temp[], int size)
{
      bool present = false
      for(int i = 0; i < size; i++){
          if(temp[i] == '/'){
           present = true;
           break;
           }
      }
      return present;
}
void execute(char **argv)
{
     pid_t pid;
     int    status;
   
     if ((pid = fork()) < 0) {     /* fork a child process           */
          printf("*** ERROR: forking child process failed\n");
          exit(1);
     }
     else if (pid == 0) {          /* for the child process:         */
          if (execvp(*argv, argv) < 0) {     /* execute the command */
               printf("*** ERROR: exec failed\n");
               exit(1);
          }
     }
     else {                                  /* for the parent:      */
          while (wait(&status) != pid)       /* wait for completion */
               ;
     }
}


void main(void)
{
     char line[1024];                         // The input line               
     char *argv[3];                           // An array of pointers to the tokens (the tokens were parsed
                                               // from the input line)
     bool check1, check2 = false;

   //A look-up table that contains some of the valid commands
   char *LookUp[11] = {"emacs", "kill", "bye", "jobs", "fg", "chmod", "cd", "help", "cat", "cp"};
   
     while (1) {                              // repeating....       
          printf("tish >> ");                 // the prompt           
          gets(line);                         // read in the command line   
          printf("\n");
          parse(line, argv);                  // parse the line
     
          if (strcmp(argv[0], "bye") == 0)    // exit if the user enters bye
               {exit(0);}

                      //Input Validation//
                      ///////////////////

          //If the input is just a white space character, continue with the next iteration of the loop
          if (isspace(argv[0]))
           continue;    //If it is some sort of a white-space character,
                       //skip the current iteration of the while loop
  
          
          //Call a function that checks for the validity of the input command
          check2 = FunctionLookUp(argv, LookUp);
          if(check2 == false){
              fprintf("Invalid Command\n");
              continue;
          }

          //Test argv[0] for invalid internal commands. Check for Letters and Negative numbers.
          if(strcmp(argv[0], "kill") == 0){
           if(isaplha(argv[1]) || atoi(argv[1]) < 0){
           fprintf("Invald PID entered");
           fprintf("Enter a positive numeric number");
           continue;
           }
           }
         
                                                   
      
         int size = sizeof(argv[1]) + 1;
         char temp[size];
       strcpy(temp,agrv[1]);
         check1 = CheckForwardSlash(temp, size);
       //If true is returned by the CheckForwardSlash method, skip the rest of the while loop
         if(check1 == true){              
         printf("Invalid file format\n");
         printf("Avoid Forward Slashes in your file name\n");
         continue;
         }

                      //Input Validation Ends//
        ///////////////*********************//////////////////

       //Signals to catch the Ctrl-C and Ctrl/ combination
        signal(SIGINT, SIG_IGN);                   //The instructions said to ignore the SIGINT signal
        signal(SIGTERM, SIG_DFL);               //SIGTERM signal must be caught.
        execute(argv);                          //Finally, execute the command
     }
}

c program for shell

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>

#ifdef _WIN32
#include <windows.h>
#define chdir _chdir

#else
#include <unistd.h>
#endif

#define MAX_LENGTH 1024
#define DELIMS " \t\r\n"

int main(int argc, char *argv[]) {
char *cmd;
char line[MAX_LENGTH];

while (1) {
    printf("$ ");
    if (!fgets(line, MAX_LENGTH, stdin)) break;

    // Parse and execute command
    if ((cmd = strtok(line, DELIMS))) {
      // Clear errors
      errno = 0;

      if (strcmp(cmd, "cd") == 0) {
        char *arg = strtok(0, DELIMS);

        if (!arg) fprintf(stderr, "cd missing argument.\n");
        else chdir(arg);

      } else if (strcmp(cmd, "exit") == 0) {
        break;

      } else system(line);

      if (errno) perror("Command failed");
    }
}

return 0;
}

Add a comment
Know the answer?
Add Answer to:
Overview Writing in the C language, implement a very basic shell, called smash. In this project,...
Your Answer:

Post as a guest

Your Name:

What's your source?

Earn Coins

Coins can be redeemed for fabulous gifts.

Not the answer you're looking for? Ask your own homework help question. Our experts will answer your question WITHIN MINUTES for Free.
Similar Homework Help Questions
  • Project 1: Implementing a Shell 1 Overview In this individual project you will have to design...

    Project 1: Implementing a Shell 1 Overview In this individual project you will have to design and implement a simple shell command interpreter called mysh. The basic function of a shell is to accept lines of text as input and execute programs in response. The shell must be able to execute built-in commands in a process different from the one executing mysh. 2 Requirements When first started, your shell should initialize any necessary data structures and then enter a loop...

  • You are required to develop a simple Linux shell in C language “shell.c". The shell has...

    You are required to develop a simple Linux shell in C language “shell.c". The shell has to perform the following requirements: - - The shell prompt is “"myshell>". - Run commands either from current directory or from “/bin" directory using the "exec" system call. - Support output redirection like "command> filename" using "dup" system call. Note: save the output of the comment in the (filename). - Implement the “history shell command to list the last ten commands entered so far....

  • Creating a Shell Interface Using Java This project consists of modifying a Java program so that...

    Creating a Shell Interface Using Java This project consists of modifying a Java program so that it serves as a shell interface that accepts user commands and then executes each command in a separate process external to the Java virtual machine. Overview A shell interface provides the user with a prompt, after which the user enters the next command. The example below illustrates the prompt jsh> and the user’s next command: cat Prog.java. This command displays the file Prog.java on...

  • Update the program in the bottom using C++ to fit the requirements specified in the assignment....

    Update the program in the bottom using C++ to fit the requirements specified in the assignment. Description For this assignment, you will be writing a single program that enters a loop in which each iteration prompts the user for two, single-line inputs. If the text of either one of the inputs is “quit”, the program should immediately exit. If “quit” is not found, each of these lines of input will be treated as a command line to be executed. These...

  • Edit the code (shell.c) given to do the tasks asked! will rate for correct answer! Also,...

    Edit the code (shell.c) given to do the tasks asked! will rate for correct answer! Also, include a screen shot of the output and terminal window of each command you used. Read carefully to do this task please. shell.c code given below. #include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <sys/wait.h> #include <string.h> int main() { int PID; char lineGot[256]; char *cmd; while (1){ printf("cmd: "); fgets(lineGot, 256, stdin); // Get a string from user (includes \n) cmd = strtok(lineGot, "\n");...

  • Objective : Write a C Shell script which copies all files(*.java and *.class) from your home dire...

    Objective : Write a C Shell script which copies all files(*.java and *.class) from your home directory to a new one, and Analyze the new directory information such as number of files, user permissions, and disk usage. Sample Output:                                                    << CS Directory Analysis >>      Date:   ============================================================ Current Directory: /home/tomss New Directory Created : /home/tomss/pgm01 File information Total Number of files : 22 files Directory files:   0 files Plain text files:   10 files File have read permissions: 3 files File have...

  • The program is written in c. How to implement the following code without using printf basically...

    The program is written in c. How to implement the following code without using printf basically without stdio library? You are NOT allowed to use any functions available in <stdio.h> . This means you cannot use printf() to produce output. (For example: to print output in the terminal, you will need to write to standard output directly, using appropriate file system calls.) 1. Opens a file named logfle.txt in the current working directory. 2. Outputs (to standard output usually the...

  • Writing Unix Utilities in C (not C++ or C#) my-cat The program my-cat is a simple...

    Writing Unix Utilities in C (not C++ or C#) my-cat The program my-cat is a simple program. Generally, it reads a file as specified by the user and prints its contents. A typical usage is as follows, in which the user wants to see the contents of my-cat.c, and thus types: prompt> ./my-cat my-cat.c #include <stdio.h> ... As shown, my-cat reads the file my-cat.c and prints out its contents. The "./" before the my-cat above is a UNIX thing; it...

  • Hello, please help with the following, you're tasked with writing a shell script named “rpsm.sh”....

    Hello, please help with the following, you're tasked with writing a shell script named “rpsm.sh”. The script reports and prints (to stdout) selected storage management information. Think of it as “RePort Storage Management”. The easy way to describe what the script needs to do is to look at what it should display in the case where you provide incorrect parameters, or in the case where you provide “-h” for help: Usage: ./rpsm.sh <options>< directory> Reports selected information about specified directory...

  • ‘C’ programming language question Write a MENU DRIVEN program to A) Count the number of vowels...

    ‘C’ programming language question Write a MENU DRIVEN program to A) Count the number of vowels in the string B) Count the number of consonants in the string C) Convert the string to uppercase D) Convert the string to lowercase E) Display the current string X) Exit the program The program should start with a user prompt to enter a string, and let them type it in. Then the menu would be displayed. User may enter option in small case...

ADVERTISEMENT
Free Homework Help App
Download From Google Play
Scan Your Homework
to Get Instant Free Answers
Need Online Homework Help?
Ask a Question
Get Answers For Free
Most questions answered within 3 hours.
ADVERTISEMENT
ADVERTISEMENT
ADVERTISEMENT