/**
 * COMS 4118: Operating Systems
 * Homework 1.1: Simple Shell
 *
 *
 * @version 0.3
 * @date January 27, 2003
 * @author Michael Locasto <locasto@cs.columbia.edu>
*/

#define HISTORY_LIMIT 100

#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <ctype.h>

//#include <mcheck.h>

extern int errno;

  struct node_type{
    char* command;
    struct node_type* link;
  };

  typedef struct node_type node;

/**
 * from this: !xxxx\0
 * return this: xxxx\0
 * returns -1 if the command is not in the list
 *
*/
int getCommandNumber( char* cmdtext ){

    int i=0;
    char* num;
    int result=-1;
    int len = strlen( cmdtext );

    num = (char*)calloc( len, sizeof(char) );

    for( i=1;i<len;i++ ){
      num[i-1]=cmdtext[i];
    }

    result = atoi( num );
    free( num );
    num=NULL;

    return result;
}

/**
 * A method to push a directory name onto the stack
 *
*/
node* push( node* top, char* currentdir, const int len ){

  int j=0;
  char* newdir;
  node* pointer = top;
  node* newtop;

  newdir = (char*)malloc( len+1 );
  if( NULL==newdir )
  	return top;
  for( j=0;j<=len;j++){ newdir[j]='\0'; }
  strncat( newdir, currentdir, len );

  if( top==NULL ){
     top=(node*)malloc(sizeof(node));
     if( top==NULL ){
	  free( newdir );
	  newdir=NULL;
	  return NULL;
     }
     top->link=NULL;
     top->command=newdir;
     return top;
  }else{
    //don't go all the way down list, insert at front
    newtop=(node*)malloc(sizeof(node));
    if( newtop==NULL ){
	free( newdir );
	newdir=NULL;
        return top;
    }
    newtop->command=newdir;
    newtop->link=pointer;
    top=newtop;
    return top;
  }

}


/**
 * prints the stack one entry per line, top element first
*/
void printstack( node* top ){

   node* pointer=top;
   int i=1;

   while( NULL!=pointer ){
     printf( "\n [%d]  %s",i,pointer->command );
     i++;
     pointer = pointer->link;
   }
   printf( "\n" );

}

/**
 * a method to peek at the data on top of the stack
*/
char* peek( node* top ){

   char* targetdir;
   int j=0;
   int len=0;

   if( NULL==top ){
     return NULL;
   }else{
     len = strlen( top->command );
     targetdir = (char*)malloc( len+1 );
     if( targetdir==NULL )
        return NULL;
     for( j=0;j<=len;j++){ targetdir[j]='\0'; }
     strncat( targetdir, top->command, len );
     //printf( "\nsh::pop() - targetdir=%s\n",targetdir );
   }

   return targetdir;
}

/**
 * remove the top of the stack and return the new top
*/
node* pop( node* top ){

  node* oldtop = top;

  if( NULL==top ){
  	return NULL;
  }else{
    free(top->command);
    top->command=NULL;
    top = (top->link);
    oldtop->link = NULL;
    free(oldtop);
    oldtop=NULL;
  }
  return top;
}


/**
 * A method to add a command to the history
 * if the addition causes HISTORY_LIMIT to be exceeded,
 * drop the oldest command
 *
 * general form taken from http://www.cs.cf.ac.uk/Dave/C/node11.html#SECTION001130000000000000000
 *
 *
*/
node* addToHistory( node* head, char* input, const int inputLength ){

  node* pointer = head;
  node* ptr = head; //save so we can safely delete if we move on
  int i=1; //count how many command are currently in here
  char* newInstruction;
  int j=0;

  newInstruction = (char*)malloc( inputLength+1 );
  if( NULL==newInstruction )
    return head;
  for( j=0;j<=inputLength;j++){ newInstruction[j]='\0'; }
  strncat( newInstruction, input, inputLength );

  if( pointer != NULL ){

    while( pointer->link!=NULL ){
       pointer=pointer->link;
       i++;
    }
    i++; //count the command with a NULL link

    if( i>HISTORY_LIMIT ){
       head=head->link;
       free( ptr->command );
       ptr->command=NULL;
       free( ptr );
       ptr=NULL;
    }

    pointer->link=(node*) malloc(sizeof(node));
    if( pointer->link==NULL ){
	free(newInstruction);
	newInstruction=NULL;
        return head;
    }
    pointer=pointer->link;
    pointer->link=NULL;
    pointer->command=newInstruction;
  }else{
    head=(node*) malloc(sizeof(node));
    if( head==NULL ){
	free(newInstruction);
	newInstruction=NULL;
        return NULL;
    }
    head->link=NULL;
    head->command=newInstruction;
  }

  return head;

}

/** make sure to check if they try to request something not in the list
 * and return null if so
 * Do the check for the 'base command' in here so we don't have to
 * do recursion in the main loop. Be sure to return something that IS a
 * char and not a number.
 *
*/
char* getCommand( node* head, const int i ){

   node* pointer=head;
   int j=1;

   while( pointer!=NULL && j<i ){
       pointer=pointer->link;
       j++;
   }

   if( pointer==NULL ){
   	 return NULL;
   }else{
   	 return pointer->command;
   }
}


/**
 * print the history, one item per line, as specified.
 *
*/
void printHistory( node* head ){

  node* pointer;
  int i;

  pointer = head;
  i=1;

  while( pointer!=NULL ){
     printf( "\n [%d]  %s",i,pointer->command );
     i++;
     pointer = pointer->link;
  }
  printf( "\n" );

}


/**
 * a blocking I/O method for reading in an arbitrary
 * amount of keyboard input and malloc'ing whatever
 * is needed beyond the default buffer.
 *
*/
char* readFully(){

 /** 1k of input chars should be plenty big*/
 char buffer[1025]={0};

 char* alpha_buffer="";
 char* beta_buffer="";

 /**
  * 0 means alpha_buffer holds current data
  * 1 means beta_buffer holds current data
 */
 int flag=0;

 /**
  * 0 means we stayed within 1024 chars of input
  * 1 means we had to malloc and use the data buffers
 */
 int bufferOverFlow=0;

 /** the new length of the data buffer */
 int newLength=0;

 /** the result of reading fully */
 char* output;

 /** current symbol being read*/
 int ch=0;

 /** current position in the buffer */
 int i=0;

 /** counter for clearing the buffer */
 int j=0;

 alpha_buffer = (char*) malloc( 1 );
 if( NULL!=alpha_buffer ){
   alpha_buffer[0]='\0';
 }else{
   return "";
 }
 beta_buffer = (char*) malloc( 1 );
 if( NULL!=beta_buffer ){
   beta_buffer[0]='\0';
 }else{
  return "";
 }

  for( j=0;j<1024;j++ ){ buffer[j]='\0'; }
  buffer[1024]='\0';

  ch=getchar();
  while( (ch!='\n') && (ch!=EOF) ){
    if( (i>=0) && (i<512) ){
        buffer[i]=(char)ch;
    }else if( i==512 ){
        bufferOverFlow=1;

		if( flag==0 ){
			/*alpha_buffer holds current data*/
			newLength = strlen(buffer) + 1 + strlen( alpha_buffer );
			beta_buffer = (char*) malloc( newLength );
			if( NULL == beta_buffer ){
				return "";
			}else{
				/*clear data buffer*/
				for( j=0;j<newLength;j++ ){ beta_buffer[j]='\0'; }
				/*copy alpha in*/
				strncat( beta_buffer, alpha_buffer, (strlen(alpha_buffer)) );
				/*then copy buffer in*/
				strncat( beta_buffer, buffer, (strlen(buffer)) );
				/*free old*/
				free( alpha_buffer );
				alpha_buffer=NULL;
				flag=1;
				/*beta_buffer now holds data*/
			}
		}else if( flag==1 ){
			/*beta_buffer holds current data*/
			newLength = strlen(buffer)+ 1 + strlen( beta_buffer );
			alpha_buffer = (char*) malloc( newLength );
			if( NULL == alpha_buffer ){
				return "";
			}else{
				/*clear data buffer*/
				for( j=0;j<newLength;j++ ){ alpha_buffer[j]='\0'; }
				/*copy beta in*/
				strncat( alpha_buffer, beta_buffer, (strlen(beta_buffer)) );
				/*then copy buffer in*/
				strncat( alpha_buffer, buffer, (strlen(buffer)) );
				/*free old*/
				free( beta_buffer );
				beta_buffer=NULL;
				flag=0;
				/*alpha_buffer now holds data*/
			}

		}

		for( j=0;j<513;j++ ){ buffer[j]='\0'; }
		i=0;
		buffer[i]=ch;

	}else{
		return "";
	}
	++i;
	ch=getchar();
  }


  /*flush anything in the buffer to alpha or beta*/
  if( buffer[0]=='\0' || buffer[0]=='\n' || buffer[0]==EOF ){
	/*nothing in buffer, no need to act*/
  }else{
	if( bufferOverFlow==1 ){
		/*cat the buffer to our current data buffer*/
		if( flag==0 ){
			/*alpha_buffer holds current data*/
			newLength = strlen( buffer )+ 1 + strlen( alpha_buffer );
			beta_buffer = (char*) malloc( newLength );
			if( NULL == beta_buffer ){
				return "";
			}else{
				/*clear data buffer*/
				for( j=0;j<newLength;j++ ){ beta_buffer[j]='\0'; }
				/*copy alpha in*/
				strncat( beta_buffer, alpha_buffer, (strlen(alpha_buffer)) );
				/*then copy buffer in*/
				strncat( beta_buffer, buffer, (strlen(buffer)) );
				/*free old*/
				free( alpha_buffer );
				alpha_buffer=NULL;
				flag=1;
				/*beta_buffer now holds data*/
			}
		}else if( flag==1 ){
			/*beta_buffer holds current data*/
			newLength = strlen( buffer )+ 1 + strlen( beta_buffer );
			alpha_buffer = (char*) malloc( newLength );
			if( NULL == alpha_buffer ){
				return "";
			}else{
				/*clear data buffer*/
				for( j=0;j<newLength;j++ ){ alpha_buffer[j]='\0'; }
				/*copy beta in*/
				strncat( alpha_buffer, beta_buffer, (strlen(beta_buffer)) );
				/*then copy buffer in*/
				strncat( alpha_buffer, buffer, (strlen(buffer)) );
				/*free old*/
				free( beta_buffer );
				beta_buffer=NULL;
				flag=0;
				/*alpha_buffer now holds data*/
			}
		}
	}
 }

 if( 0==bufferOverFlow ){
	output = buffer;
 }else if( bufferOverFlow==1 ){
	if( flag==0 ){
		output = alpha_buffer;
	}else if( flag==1 ){
		output = beta_buffer;
	}
 }

 return ((char*)output);

}

/**
 * The main method. Includes the primary command
 * interpreter loop and fork execution.
 *
*/
int main( int argc, char* argv[] ){

 const int ARG_LIMIT = 20;

  /** the front of the history queue */
  node* head = NULL;

  /** data type for a command (see Operating Systems: A Modern Perspective, by Gary Nutt)*/
  struct command_t{
     char* name;
     int argc;
     char* argv[ ARG_LIMIT+1 ];
  };

  /** an instance of the command data type */
  struct command_t* command;

  char* HOME;
  char* PWD;
  char* MYPATH;
  char* CWD;

  /** exit flag and main return value */
  int my_exit=0;

  /** number to display in the prompt */
  int command_counter=1;

  /** the pid of this process to display in the prompt */
  int my_pid = getpid();

  /** the pid for the parent|child test */
  int pid=0;

  /** child exit status */
  int status=0;

  /** the keyboard input */
  char* input;

  /** length of keyboard input, less one '\0' char */
  int inputLength=0;

  /** an integer capturing the result of the chdir() system call */
  int commandResult=0;

  /** number of the command in a ! command */
  int cmd_number=0;

  /** a flag indicating whether or not we could
   * form a command or allocate memory for it
  */
  int haveCommand=0;

  /** target directory for a popd() command */
  char* targetdir;

  /** intermediate variable for forming a command */
  char* token;
  int tokens=0; //including command
  int j=0; //counter for clearing
  int i=0; //count through the entire command string
  int k=0; //count through a token
  int limit=0; //counter to arg limit (including command)
  int firsttoken=0; //false, have we seen the first token? (name of command)

  node* top;
  top=NULL;
  targetdir=NULL;
  HOME = getenv( "HOME" );
  PWD = getenv( "PWD" );
  MYPATH = getenv( "PATH" );
  CWD = getcwd( NULL, 0 );


  //setenv( "MALLOC_TRACE", "/home/michael/classes/os/hw1/memlog.log", 1 );
  
  //putenv( "MALLOC_TRACE=/home/michael/classes/os/hw1/memlog.log" );
  //mtrace();

   /** primary sh interpreter loop:
    * - print prompt
    * - receive keyboard input
    * - parse input to form command
    * - test for special cases (and add to history)
    * - fork and execute
   */
   while( !my_exit ){

    /**print prompt*/
    printf( "\r%d-msh[%d]$ ", my_pid, command_counter );

    /*read command line*/
    input = readFully();
    inputLength = strlen(input);

    //printf( "\ninput=%s\nlen=%d\n", input, inputLength );

    if( inputLength>0 ){

       //form command
      token = (char*)malloc( inputLength );

      if( NULL!=token ){

        for( j=0;j<inputLength;j++ ){ token[j]='\0'; }

        while( i<=inputLength && limit<ARG_LIMIT ){
          if( input[i]=='\t' || input[i]=='\n' || input[i]==' '){
	        tokens++;
		    if( firsttoken==0 ){
			  firsttoken=1;
			  command->name = (char*) malloc( k+1 );
			  for( j=0;j<(k+1);j++ ){ command->name[j]='\0'; }
			  strncat( command->name, token, k );
			  command->argv[(limit=0)] = (char*) malloc( k+1 );
			  for( j=0;j<(k+1);j++ ){ command->argv[limit][j]='\0'; }
			  strncat( command->argv[limit], token, k );
			  limit++;
		    }else{
			  command->argv[limit] = (char*) malloc( k+1 );
			  for( j=0;j<(k+1);j++ ){ command->argv[limit][j]='\0'; }
			  strncat( command->argv[limit], token, k );
			  limit++;
		    }
		    for( j=0;j<=k;j++ ){ token[j]='\0'; }
		    k=0;
          }else if( input[i]=='\0' ){
		    token[k]=input[i];
		    i=inputLength;
		    tokens++;
		    if( firsttoken==0 ){
			  firsttoken=1;
			  command->name = (char*) malloc( k+1 );
			  for( j=0;j<(k+1);j++ ){ command->name[j]='\0'; }
			  strncat( command->name, token, k );
			  command->argv[(limit=0)] = (char*) malloc( k+1 );
			  for( j=0;j<(k+1);j++ ){ command->argv[limit][j]='\0'; }
			  strncat( command->argv[limit], token, k );
			  limit++;
		    }else{
			  command->argv[limit] = (char*) malloc( k+1 );
			  for( j=0;j<(k+1);j++ ){ command->argv[limit][j]='\0'; }
			  strncat( command->argv[limit], token, k );
			  limit++;
		    }
		    for( j=0;j<=k;j++ ){ token[j]='\0'; }
		    k=0;
          }else{
            token[k]=input[i];
            k++;
          }//end if input[i]...
          ++i;
        }//end while( i<=inputLength...
        command->argc = tokens;
        command->argv[limit]=NULL;
        //printf( "\ncommand.name=%s",command->name );
        //printf( "\ncommand.argc=%d",command->argc );
        //printf( "\nlimit=%d\n",limit );
        //for( j=0;j<=limit;j++ ){
	     //printf( "\ncommand.argv[%d]=%s",j,command->argv[j] );
        //}
        //printf( "\n" );
        haveCommand=1;
       }else{
         //printf( "\nFailed to allocate enough memory for the token." );
	     //continue;
	     haveCommand=0;
       }//end if token..

       free(token);
       token=NULL;
       i=0;
       j=0;
       k=0;
       limit=0;
       firsttoken=0;
       tokens=0;

       //built-in functions
       if( haveCommand ){

         if( 0==strcmp( command->name, "exit" ) ){
           my_exit=1;
         }else if( 0==strcmp( command->name, "cd" ) ){

           head = addToHistory( head, input, inputLength );

           if( command->argv[1]!=NULL ){
              commandResult = chdir( command->argv[1] );
              free( CWD );
              CWD = NULL;
              CWD = getcwd( NULL, 0 );
           }else{
              if( HOME!=NULL ){
                 commandResult=chdir( HOME );
                 free( CWD );
                 CWD = NULL;
                 CWD = getcwd( NULL, 0 );
              }
           }

           if( commandResult==-1 ){
              printf("\nsh: error: %s\n",strerror(errno));
           }

         }else if( 0==strcmp( command->name, "history" ) ){

           head = addToHistory( head, input, inputLength );
           printHistory( head );

         }else if( 0==strncmp( command->name, "!", 1 ) ){

           cmd_number = getCommandNumber( command->name );
           if( cmd_number<=0 ){
              //might have been an alpha char, we could handle this,
              //but remember, this is a SIMPLE shell
              //do nothing
           }else{

              input=getCommand( head, cmd_number );
              if( NULL != input ){
		inputLength = strlen(input);
                printf( "\n[%d] %s\n", cmd_number, input );
		//free up previous command, at the end of the loop, the
		//command we create here gets freed up automagically
                free( command->name );
                command->name=NULL;
                for( j=0;j<(command->argc);j++ ){
                  free( command->argv[j] );
                  command->argv[j]=NULL;
                }
                command->argc=0;
                command->argv[ARG_LIMIT]=NULL;
                haveCommand=0;

				//form new command
				if( inputLength>0 ){

				       //form command
				      token = (char*)malloc( inputLength );

				      if( NULL!=token ){
				        for( j=0;j<inputLength;j++ ){ token[j]='\0'; }
				        while( i<=inputLength && limit<ARG_LIMIT ){
				          if( input[i]=='\t' || input[i]=='\n' || input[i]==' '){
					        tokens++;
						    if( firsttoken==0 ){
							  firsttoken=1;
							  command->name = (char*) malloc( k+1 );
							  for( j=0;j<(k+1);j++ ){ command->name[j]='\0'; }
							  strncat( command->name, token, k );
							  command->argv[(limit=0)] = (char*) malloc( k+1 );
							  for( j=0;j<(k+1);j++ ){ command->argv[limit][j]='\0'; }
							  strncat( command->argv[limit], token, k );
							  limit++;
						    }else{
							  command->argv[limit] = (char*) malloc( k+1 );
							  for( j=0;j<(k+1);j++ ){ command->argv[limit][j]='\0'; }
							  strncat( command->argv[limit], token, k );
							  limit++;
						    }
						    for( j=0;j<=k;j++ ){ token[j]='\0'; }
						    k=0;
				          }else if( input[i]=='\0' ){
						    token[k]=input[i];
						    i=inputLength;
						    tokens++;
						    if( firsttoken==0 ){
							  firsttoken=1;
							  command->name = (char*) malloc( k+1 );
							  for( j=0;j<(k+1);j++ ){ command->name[j]='\0'; }
							  strncat( command->name, token, k );
							  command->argv[(limit=0)] = (char*) malloc( k+1 );
							  for( j=0;j<(k+1);j++ ){ command->argv[limit][j]='\0'; }
							  strncat( command->argv[limit], token, k );
							  limit++;
						    }else{
							  command->argv[limit] = (char*) malloc( k+1 );
							  for( j=0;j<(k+1);j++ ){ command->argv[limit][j]='\0'; }
							  strncat( command->argv[limit], token, k );
							  limit++;
						    }
						    for( j=0;j<=k;j++ ){ token[j]='\0'; }
						    k=0;
				          }else{
				            token[k]=input[i];
				            k++;
				          }//end if input[i]...
				          ++i;
				        }//end while( i<=inputLength...
				        command->argc = tokens;
				        command->argv[limit]=NULL;
				        //printf( "\ncommand.name=%s",command->name );
				        //printf( "\ncommand.argc=%d",command->argc );
				        //printf( "\nlimit=%d\n",limit );
				        //for( j=0;j<=limit;j++ ){
					     //printf( "\ncommand.argv[%d]=%s",j,command->argv[j] );
				        //}
				        //printf( "\n" );
				        haveCommand=1;
				       }else{
				         //printf( "\nFailed to allocate enough memory for the token." );
					     //continue;
					     haveCommand=0;
				       }//end if token..
				       free(token);
				       token=NULL;
				       i=0;
				       j=0;
				       k=0;
				       limit=0;
				       firsttoken=0;
                                       tokens=0;

		if( haveCommand ){

                   if( 0==strcmp( command->name, "exit" ) ){
                     my_exit=1;
                   }else if( 0==strcmp( command->name, "cd" ) ){

                     head = addToHistory( head, input, inputLength );
                     if( command->argv[1]!=NULL ){
                        commandResult = chdir( command->argv[1] );
                        free( CWD );
                        CWD = NULL;
                        CWD = getcwd( NULL, 0 );
                     }else{
                        if( HOME!=NULL ){
                          commandResult=chdir( HOME );
                          free( CWD );
                          CWD = NULL;
	                  CWD = getcwd( NULL, 0 );
                        }
                     }

                     if( commandResult==-1 ){
                         printf("\nsh: error: %s\n",strerror(errno));
                     }

                   }else if( 0==strcmp( command->name, "history" ) ){

                     head = addToHistory( head, input, inputLength );
                     printHistory( head );

                   }else if( 0==strncmp( command->name, "!", 1 ) ){
                     printf( "\ndirect recursive ! commands are supported via a different method. You should never get here.\n" );
		   }else if( 0==strcmp( command->name, "dirs" ) ){

		     head = addToHistory( head, input, inputLength );
		     printstack( top );

		   }else if( 0==strcmp( command->name, "pushd" ) ){

		     head = addToHistory( head, input, inputLength );
		     top = push( top, CWD, strlen(CWD) );

			 if( command->argv[1]!=NULL ){
			   commandResult = chdir( command->argv[1] );
			   free( CWD );
                           CWD = getcwd( NULL, 0 );
			 }else{
			   if( HOME!=NULL ){
			      commandResult=chdir( HOME );
			      free( CWD );
                              CWD = getcwd( NULL, 0 );
			   }
			 }

			 if( commandResult==-1 ){
			    printf("\nsh: error: %s\n",strerror(errno));
                         }

		    }else if( 0==strcmp( command->name, "popd" ) ){

		     head = addToHistory( head, input, inputLength );
		     targetdir = peek(top);
		     top = pop(top);
		     commandResult = chdir( targetdir );
		     free(CWD);
		     CWD=getcwd( NULL, 0 );
		     if( commandResult==-1 ){
			   printf("\nsh: error: %s\n",strerror(errno));
                     }

                   }else{
                     //execute new command (fork)
                     head = addToHistory( head, input, inputLength );
                     pid = fork();
                     if( pid==0 ){
                       errno=0;
                       execvp( command->name, command->argv );
                       printf( "\nsh: error (%d): %s\n",errno, strerror(errno) );
                       return -1;
                     }else if( pid>0 ){
                       waitpid( pid, &status, 0 );
                       //printf( "\nChild exit status was: %d\n", status );
                     }else if( pid<0 ){
                       //there was an error creating the child
                       printf( "\nsh: command failed, could not fork()\n" );
                     }

				   }//end if..else built-in commands

			    }//end if haveCommand

			   }//end if inputLength>0
		     }//end if NULL!=input
           }//end if..else cmd_number<=0

         }else if( 0==strcmp( command->name, "dirs" ) ){

	       head = addToHistory( head, input, inputLength );
	       printstack( top );

         }else if( 0==strcmp( command->name, "pushd" ) ){

           head = addToHistory( head, input, inputLength );
           top = push( top, CWD, strlen(CWD) );

           if( command->argv[1]!=NULL ){
             commandResult = chdir( command->argv[1] );
             free(CWD);
	     CWD=getcwd( NULL, 0 );
           }else{
             if( HOME!=NULL ){
               commandResult=chdir( HOME );
               free(CWD);
  	       CWD=getcwd( NULL, 0 );
             }
           }

           if( commandResult==-1 ){
              printf("\nsh: error: %s\n",strerror(errno));
           }

         }else if( 0==strcmp( command->name, "popd" ) ){

            head = addToHistory( head, input, inputLength );
	    targetdir = peek(top);
	    top = pop(top);
	    commandResult = chdir( targetdir );
	    free(CWD);
	    CWD=getcwd( NULL, 0 );
            if( commandResult==-1 ){
		  printf("\nsh: error: %s\n",strerror(errno));
            }

         }else{

          //create a process to execute the command
	  //printf( "\nHave command=%s.\n",command->name );
	  head = addToHistory( head, input, inputLength );
          pid = fork();
          if( pid==0 ){
            errno=0;
            execvp( command->name, command->argv );
            printf( "\nsh: error (%d): %s\n",errno, strerror(errno) );
            return -1;
          }else if( pid>0 ){
            waitpid( pid, &status, 0 );
            //printf( "\nChild exit status was: %d\n", status );
          }else if( pid<0 ){
            //there was an error creating the child
            printf( "\nsh: command failed, could not fork()\n" );
          }

         }//end built-in command checks

       //if( my_exit==0 ){
         free( command->name );
         command->name=NULL;

         for( j=0;j<(command->argc);j++ ){
            free( command->argv[j] );
            command->argv[j]=NULL;
         }
         command->argc=0;
         command->argv[ARG_LIMIT]=NULL;
         haveCommand=0;
       //}
       ++command_counter;

     }//end if haveCommand

   }//end if inputlength is not 0

  }//end while

  while( head!=NULL ){
    node* next = head->link;
    free( head->command );
    head->command=NULL;
    free( head );
    head = NULL;
    head = next;
  }

  while( top!=NULL ){
   top=pop(top);
  }

  printf( "\n" );

  //return 0;
  _exit(0);
}
