//*****************************************************************************
//
// Program: Shell Project -- part 3
//
// 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 pipelines
//
// Date: October 14, 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("");
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, fd0 = -1, fd1 = -1, fd2 = -1, temp_in = dup(STDIN),
temp_out = dup(STDOUT), temp_error = dup(STDERR);
if(pcmd -> infile != NULL)
{ //stdin is directed
fd0 = open(pcmd -> infile, O_RDWR, 0644);
if(fd0 < 0) perror("");
}
else
{ //input from standard in
fd0 = dup(STDIN);
if(!(fd0 >= 0)) perror("");
}
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);
}
}
while(pcmd != NULL)
{ //for all simple commands
dup2(fd0, STDIN);
if(close(fd0) == -1) perror("");
if(pcmd -> nextpipe == NULL)
{ //last command check for output redirection
if(pcmd -> outfile != NULL)
{ //output redirection
if(pcmd -> output_append)
{
fd1 = open(pcmd -> outfile, O_APPEND | O_WRONLY | O_CREAT, 0644);
}
else
{
fd1 = open(pcmd -> outfile, O_WRONLY | O_CREAT, 0644);
}
}
else
{ //no redirection, output to standard out
fd1 = dup(temp_out);
if(!(fd1 >= 0)) perror("");
}
}
else
{//not last simple command
int fdpipe[2];
if(pipe(fdpipe) == -1) perror("");
fd0 = fdpipe[STDIN]; //hook up input side of pipe
fd1 = fdpipe[STDOUT]; //hook up output side of pipe
}
if(!(dup2(fd1,STDOUT) >= 0)) perror(""); //standard out to out of pipe
if(close(fd1) == -1) perror("");
pid = fork();
if(pid == -1) perror("");
if(pid)
{//parent
pid = wait(&status);
}
else
{//child
int pid2 = fork(); //fork in child to eliminate zombies
if(pid2 == -1) perror("");
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);
}
}
pcmd = pcmd -> nextpipe;
} //end while done with all pipes
if(!(dup2(temp_in, STDIN) >= 0)) perror(""); //reestablish standard in
if(!(dup2(temp_out, STDOUT) >= 0)) perror(""); //reestablish standard out
if(!(dup2(temp_error, STDERR) >= 0)) perror(""); //reestablish standard err
DONE:;
printf("ߪsh%% ");
} /* end of doline(..) */