//*****************************************************************************
//
// Program:     Shell Project -- part 2
//
// Author:      Travis Dillon - I only wrote the doline function
// Class:       CS 442
// Email:       tdillon@ace.cs.ohiou.edu
//
// Description: this is a simple shell that implements some functionality such
//              as exit, pwd, cd, and executing cmds.
//
// Date:        October 05, 2004
//
//*****************************************************************************


#include <string.h> 
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <fcntl.h>
#include "parser.h"
#include "bash.h"
#define MAX_DIR 1000
#define STDIN 0
#define STDOUT 1
#define STDERR 2
//static int line_num = 1;

int main(int argc, char *argv[])
{
   yydebug = 1;  /* turn on ugly YACC debugging */
   yydebug = 0;  /* turn off ugly YACC debugging */

   printf("\nߪsh%% ");  

   /* parse the input file */
   yyparse();

   exit(0);
}



//*****************************************************************************
//
// Function:   doline
//
// Purpose:    Simple but useful shell.  exit, pwd, cd, and execution of cmds
//
// Parameters: *pcmd - link lists of command structs
//
//
//*****************************************************************************



void doline(struct command *pcmd)
{
   char *pwd = getenv("PWD");
   char *home = getenv("HOME");
   static char temp[MAX_DIR],temp2[MAX_DIR];

   if(strcmp(pcmd -> command , "exit") == 0)
   {  //exit from the bash shell
      printf("exit\n");
      exit(EXIT_SUCCESS);
   }

   if(strcmp(pcmd -> command , "cd") == 0)
   {  //we are going to change the current directory
      if(pcmd -> argc == 1)
      {  //change to home directory
         if(chdir(home)) perror("Could not chdir(home)\n");
         else
         {
            strcpy(temp2,"PWD=");
            strncat(temp2,home,MAX_DIR);
            if(!(putenv(temp2)));
            else perror("");
         }     
         goto DONE;
      }
      else
      {  //change to a specified directory
         if(strcmp(pcmd -> argv[1], "..") == 0)
         {  //go to a parent directory
            char* x = strdup(pwd);
            strcpy(temp2,x);
            x = strrchr(temp2,47);
            *x = '\0';
            if(!chdir(temp2))  //make sure there is a parent directory
            {
               strcpy(temp, "PWD=");
               strncat(temp,temp2,MAX_DIR);
               if(!(putenv(temp)));
               else perror("");
            }
            else
            {
               perror("");
            }
            goto DONE;
         }
         //go to child directory specified by argv[1]
         strcpy(temp,pwd);
         strncat(temp,"/",MAX_DIR);
         strncat(temp,pcmd -> argv[1], MAX_DIR);
         if(!chdir(temp))  //check for a valid directory
         {  strcpy(temp2,"PWD=");
            strncat(temp2,temp,MAX_DIR);
            if(!(putenv(temp2)));
            else perror("");
         }
         else
         {  //no such directory
            perror("");
         }
         goto DONE;
      }
   }

   if(strcmp(pcmd -> command , "pwd") == 0)
   {  //output the current working directory
      printf(pwd);
      printf("\n");
      goto DONE;
   }

   int status = 0, pid = fork(), fd0 = -1, fd1 = -1, fd2 = -1;
   
   if(pcmd -> infile != NULL)
   {  //stdin is directed
      fd0 = open(pcmd -> infile, O_RDWR, 0644);
      if(fd0 < 0)
      {
         perror("");
      }
   }

   if(pcmd -> outfile != NULL)
   {  //stdout is directed      
      if(pcmd -> output_append)  //append to opened file
      {
         fd1 = open(pcmd -> outfile,O_APPEND | O_WRONLY | O_CREAT, 0644);
      }
      else
      {
         fd1 = open(pcmd -> outfile, O_WRONLY | O_CREAT, 0644);
      }
   }
   if(pcmd -> errfile != NULL)
   {  //stderr is directed      
      if(pcmd -> error_append)
      {
         fd2 - open(pcmd -> errfile, O_APPEND | O_CREAT | O_WRONLY, 0644);
      }
      else
      {
         fd2 = open(pcmd -> errfile, O_WRONLY | O_CREAT, 0644);
      }
   }

   if(pid)
   {//parent      
      pid = wait(&status);
   }
   else
   {//child
      if(pcmd -> infile != NULL)
      {  //stdin is directed
         if(!(dup2(fd0,STDIN) >= 0)) perror("error in dup2(fd0,STDIN)\n");
         close(fd0);
      }
      if(pcmd -> outfile != NULL)
      {  //stdout is directed 
         if(!(dup2(fd1,STDOUT) >= 0)) perror("error in dup2(fd1,STDOUT)\n");
         close(fd1);
      }
      if(pcmd -> errfile != NULL)
      {  //stderr is directed
         if(!(dup2(fd2,STDERR) >= 0)) perror("error in dup2(fd2,STDERR)\n");
         close(fd2);
      }
      int pid2 = fork();  //fork in child to elimnate zombies
      if(pid2)
      {
         if(pcmd -> is_back)
         {  //immediately exit if process runs in back ground
            exit(status);
         }
         else
         {  //wait for not back ground processes
            pid = wait(&status);
            exit(status);
         }
      }
      else
      {
         if(execvp(pcmd -> command,pcmd -> argv) == -1)  //execute process
         {  //check for valid file
            perror("");
         }
         exit(status);
      }
   }
   DONE:;
   printf("ߪsh%% ");
} /* end of doline(..) */