Tiny Shell Exercise

The goal of this exercise is to complete writing a simple Unix shell program that executes user commands. Last class we wrote a simple program that reads user commands in a loop and executes the command
       ls -l
regardless of user input. For your reference, we include the code below.

#include <stdio.h> #define MAXCMD 100 char *cmdarg[] = {"ls", "-l", 0}; char cmdbuf[MAXBUF]; // used to store the input command int main() { int ret; while(1) { printf("\ntsh>"); fflush(stdout); // force prompt onto the screen fgets(cmdbuf, MAXBUF, stdin); // read user command // Should tokenize cmdbuf and store tokens into cmdarg // Instead, we simply execute ls if(strcmp(cmdbuf, "quit\n") == 0) exit(0); ret = fork(); // create new process if(ret == 0) { // Child code execvp("ls", cmdarg); printf("\nChild done\n"); } else { // Parent code wait(0); printf("\nParent done\n"); } } }

To help you finish the shell, we also implemented a function called parseline that parses the user command and builds the array of tokens (ASCII text words delimited by whitespaces). To use this function, you must allocate space for the array of arguments and pass it as a second argument to the function, as follows:
      #define MAXARGS 20
      
      // ...

      char * cmdarg[MAXARGS];

      // ...

      parseline("ls -l\n", cmdarg);
The call above would set
     cmdarg[0] = "ls";
     cmdarg[1] = "-l";
     cmdarg[2] = 0;
The code for the parseline function is appended below. Your job is to complete the tiny shell. Your shell should be able to execute simple commands such as
     ls -l
     ps -ef 
     finger mdamian
     grep 'const char *' yourshell.c
Submit a printed copy of your code (which should be well documented) and a sample output. Have fun!
/* 
 * parseline - Parse the command line and build the argv array.
 * 
 * Characters enclosed in single quotes are treated as a single argument.  
 */

void parseline(const char *cmdline, char **argv) 
{
    static char array[MAXLINE]; /* holds local copy of command line */
    char *buf = array;          /* ptr that traverses command line */
    char *delim;                /* points to first space delimiter */
    int argc;                   /* number of args */

    strcpy(buf, cmdline);
    buf[strlen(buf)-1] = ' ';  /* replace trailing '\n' with space */
    while (*buf && (*buf == ' ')) /* ignore leading spaces */
	buf++;

    /* Build the argv list */
    argc = 0;
    if (*buf == '\'') {
	buf++;
	delim = strchr(buf, '\'');
    }
    else {
	delim = strchr(buf, ' ');
    }

    while (delim) {
	argv[argc++] = buf;
	*delim = '\0';
	buf = delim + 1;
	while (*buf && (*buf == ' ')) /* ignore spaces */
	       buf++;

	if (*buf == '\'') {
	    buf++;
	    delim = strchr(buf, '\'');
	}
	else {
	    delim = strchr(buf, ' ');
	}
    }
    argv[argc] = NULL;
}