//level1.c
/*
Author: William P. Henry Jr.
Name: level1.c
Class: CS 360
Started: Fall 2006
Updated: November 21, 2006
*/
#define FILE_SYSTEM_LOCAL
#include "fileSystemGlobals.h"
//sets up "cwd" node reference for the path stuff
#define DIRECTORY_LOCAL
#include "directoryGlobals.h"
//places globals for the path in this main file
#define PATH_LOCAL
#include "pathGlobals.h"
#include "pathProcessing.h"
//contains static global variable for operations
//including a string table for commands
#define COMMAND_LOCAL
#include "commandGlobals.h"
#include "commandProcessing.h"
//lseek, write, close, read
#include <unistd.h>
//malloc, free
#include <stdlib.h>
#include "type.h"
#include "super.h"
#include "gd.h"
#include "bmap.h"
#include "imap.h"
#include "inode.h"
#include "dir.h"
#include "block.h"
#include "util.h"
#include "alloc_dealloc.h"
//initialize array of recognized commands (global from
//the commandGlobals.h file change the size there if you
//make any additions or removals here */
const char *cmd[] = {"mkdir", "rmdir", "ls", "cd", "pwd", "creat", "rm", "quit", "help", "?", "menu", "reload", "echo", "exit", 0};
//full list of enums kept in program to preserve
//concepts from legacy code (lab 1)
enum commandEnums {MKDIR = 0, RMDIR, LS, CD, PWD, CREAT, RM, QUIT, HELP, QUESTION, MENU, RELOAD, ECHO, EXIT };
int main(int argc,char** argv, char** env)
{
//need program name and file system to mount
//otherwise, return
if(argc != 2)
{
printf("\nusage: \"level1 <file system>\"\n\n");
return -1;
}//end if inappropriate arguments
//initialize globals for file system
if(0==initFileSystemGlobals(argv[1]))
{
printf("initialized!\n");
}//end if initialized
else
{
printf("not initialized. quitting.\n");
return -1;
}//end if error
//**************************************************************
//****************BEGIN RUNNING CODE SECTION********************
//**************************************************************
// int i;
/*
for(i=0;i<15;++i)
{
printf("index %u is %s\n",i,cmd[i]);
}
*/
printf("\n*************BEGIN LEVEL1.C MAIN****************\n");
//CREATE PROGRAM-LOCAL VARIABLES
int ID = 0;
char* fullInputString = malloc(256*(sizeof(char)));
char* command = malloc(256*(sizeof(char)));
char* arguments = malloc(256*(sizeof(char)));
char localBuf[256];
//used for getting content from strtok without
//obliterating areas, follow up strok with strcpy
//using this variable
char* tmpCharPtr=0;
//used in child process
char* fullCmd = malloc(256*(sizeof(char)));
char* fullFilePath = malloc(256*(sizeof(char)));
// printf("address of fullFilePath 0x%x\n",(&(fullFilePath)));
// printf("address of fullInputString 0x%x\n",(&(fullInputString)));
// printf("address of command 0x%x\n",(&(command)));
// printf("address of fullCmd 0x%x\n",(&(fullCmd)));
// printf("address of arguments 0x%x\n",(&(arguments)));
//do I need these?
// int pid = 0;
// int retval = 0;
// int status = 0;
//MAIN PROCESSING LOOP*
while(1)
{
//PROMPT, THEN PROCESS LINE INPUT
printf("wphix $: ");
fgets(inputLine, 256, stdin);
//copy the full input string for use passing into
//other functions, overwrite the final '\n'
//leftover from user hitting "enter"
strcpy(fullInputString, inputLine);
fullInputString[strlen(fullInputString)-1] = '\0';
inputLine[strlen(inputLine)-1] = '\0';
//get command, don't obliterate heap memory
//SCOTT--ORIGINALLY THIS WAS command=strtok(inputLine, " ");
tmpCharPtr = strtok(inputLine, " ");
if(0 == tmpCharPtr)
{
strcpy(command,"");
}//end if
else
{
strcpy(command,tmpCharPtr);
}//end else
//SCOTT--ORIGINALLY THIS WAS command=strtok(0, "\n");
//get args to command, don't obliterate heap memory
tmpCharPtr = strtok(0, "\n");
if(0 == tmpCharPtr)
{
strcpy(arguments,"");
}//end if
else
{
strcpy(arguments,tmpCharPtr);
}//end else
//*COMMAND PROCESSING: IF CAN HANDLE LOCALLY, DO SO*
//returns values as enumerated above
ID = findCmd(command);
switch(ID)
{
case(MKDIR):
printf("in case <<mkdir>>. not implemented.\n");
break;
case(RMDIR):
printf("in case <<rmdir>>. not implemented.\n");
break;
case(LS):
printf("in case <<ls>>. not implemented.\n");
break;
case(CD):
printf("in case <<cd>>. not implemented.\n");
//printf("found %s at index %d\n", cmd[ID], ID);
//if( 0 == arguments )
//{
//printf("no argument given for cd\n");
// chdir(homeBuf);
// localBuf[0]='\0';
// if( 0 == getcwd(localBuf, 256) )
// {
// printf("getcwd(localBuf, 256) failed\n");
// }//end if
// else
// {
// printf("PWD is: %s\n", localBuf);
// }//end else (so getcwd worked)
//}//end if no arguments are passed
//else if( 0 == chdir( arguments ) )
//{
//printf("was given %s to change to\n", arguments);
// localBuf[0]='\0';
// if( 0 == getcwd(localBuf, 256) )
// {
// printf("getcwd(localBuf, 256) failed\n");
// }//end if
// else
// {
// printf("PWD is: %s\n", localBuf);
// }//end else (so getcwd worked)
//}//end if worked, print blah
//else
//{
// printf("%s isn't a recognized directory\n", arguments);
//}//else failed to chdir
break;
case(PWD):
printf("in case <<pwd>>. not implemented.\n");
break;
case(CREAT):
printf("in case <<creat>>. not implemented.\n");
break;
case(RM):
printf("in case <<rm>>. not implemented.\n");
break;
case(QUIT):
printf("quitting\n");
//using goto to handle freeing of malloc'ed stuff
goto quitCleanUp;
break;
case(QUESTION):
printf("in case <<?>>. not implemented.\n");
break;
case(MENU):
printf("in case <<menu>>. not implemented.\n");
break;
case(RELOAD):
printf("in case <<reload>>. not implemented.\n");
break;
case(ECHO):
if( 0 == arguments )
{
printf("\n");
}//end if null
else
{
printf("%s\n", arguments);
}//end else print args
break;
case(EXIT):
printf("exiting\n");
free(fullFilePath);
free(fullInputString);
free(command);
free(arguments);
// free(fullCmd);
exit(0);
break;
//*COMMAND PROCESSING: MAKE A SYSTEM CALL TO HANDLE THINGS I CAN'T
default:
{
//I HATE THAT THIS HAS TO BE HERE...BUT THE CODE WON'T
//COMPILE WITHOUT THIS
//***IT IS A KNOWN BUG FOR GCC (I FILED A BUG REPORT
//WITH THEM AND THEY TOLD ME IT WAS BEING WORKED ON)***
//arguments to pass in to new function
//pointers will point to memory in parent that
//will not be modified during child's execution
printf("IN THE DEFAULT CASE!!\n");
printf("IMPLEMENT WHATEVER IT IS YOU ");
printf("ASKED FOR.\n");
/*
char *myArgv[64];
//-***********COPY ARGUMENTS INTO NEW ARGV*************
//using fullInputString, tokenized, as the argv's to pass in
int counter = 0;
myArgv[counter] = (char*)strtok( fullInputString, " " );
do
{
//strtok returns null on last call, so the
//index past the last valid path will hold zero
myArgv[++counter] = (char*)strtok( NULL , " " );
}//end while return not null
while( 0 != myArgv[counter] );
//-************FORK*********************
printf("parent mysh with PID:%d forks child\n", getpid());
pid = fork();
if(0 == pid)
{
//CHILD
printf("in child\n");
//-see if argv[1] is "<", ">" or ">>"
//-if argv[2] is absolute, try opening the file
//-else iteratively try creating its path from
//the pathPointers stuff (fullFilePath will hold
//the file path)
//used for call to "close"
int fileDesToClose=0;
//a decision below relies on this being -1 to start with
int openedFile=-1;
//treated as a boolean
int needToOpenFile=0;
//used for the flags for the call to open
int my_oflags;
printf("before checks\n");
//-*****CHECK FOR <, >, OR >> *****
//and set variables if they are found
if( 0 != myArgv[1] )
{
if( 0 == strcmp("<", myArgv[1]) )
{
// printf("compare for \"<\"\n");
//close stdin
fileDesToClose=0;
needToOpenFile=1;
my_oflags=O_RDONLY;
}//end if is input
else if( 0 == strcmp(">", myArgv[1]) )
{
// printf("compare for \">\"\n");
//close stdout
fileDesToClose=1;
needToOpenFile=1;
my_oflags=O_WRONLY|O_CREAT|O_TRUNC;
}//end else if is output
else if( 0 == strcmp(">>", myArgv[1]) )
{
// printf("compare for \">>\"\n");
//close stdout but will use concatenation
fileDesToClose=1;
needToOpenFile=1;
my_oflags=O_WRONLY|O_CREAT|O_APPEND;
}//end else if is output with concatenation
}//end if there is a myargv[1]
printf("needToOpenFile holds %d\n", needToOpenFile);
if( 1 == needToOpenFile )
{
printf("need to open file...\n");
close(fileDesToClose);
if( isAbsolute(myArgv[2]) )
{
// printf("file to open is abs path\n");
if( -1 == open(myArgv[2],my_oflags) )
{
// printf("open %s failed\n", myArgv[2]);
exit(2);
}//end if failed
}//end if is absolute
else
{
printf("file to open is NOT abs path\n");
int idx = 0;
do
{
fullFilePath[0]='\0';
strcpy(fullFilePath,pathPointers[idx]);
strcat(fullFilePath,"/");
strcat(fullFilePath, myArgv[2]);
// printf("trying %s, ", fullFilePath);
openedFile = open(fullFilePath, my_oflags);
if( -1 != openedFile )
{
// printf("file was opened\n");
}//if file was opened
else
{
// printf("file not opened\n");
++idx;
}
}//end do
while( 0 != pathPointers[idx] && -1 == openedFile );
printf("\n");
//try to open a file in the pwd
if( -1 == openedFile )
{
// printf("trying to open in pwd\n");
fullFilePath[0]='\0';
strcpy(fullFilePath,getenv("PWD"));
strcat(fullFilePath,"/");
strcat(fullFilePath, myArgv[2]);
// printf("trying %s, ", fullFilePath);
openedFile = open(fullFilePath, my_oflags);
}//end if -1 = openedFile try to open from pwd
if( -1 == openedFile )
{
printf("after all efforts, file not opened\n");
exit(3);
}//end if file not opened
else
{
//should I iterate through it all
//and copy stuff down? or just leave
//it as it is and put a "zero" at the
//appropriate index?
myArgv[1] = 0;
}//end else file was opened, so modify argv[1]
}//end else is not absolute
}//end if need to open file
//if path is absolute, pass it as argument
//if path is relative, rebuild path from cwd
if( isAbsolute(command) )
{
if( -1 == execve(command, myArgv, env) )
{
printf("attempt to run \"%s\" failed\n", command);
exit(2);
}//end if
}//end if is absolute path
else
{
int num = 0;
do
{
fullCmd[0]='\0';
strcpy(fullCmd,pathPointers[num]);
strcat(fullCmd,"/");
strcat(fullCmd, command);
// printf("trying %s, ", fullCmd);
execve(fullCmd, myArgv, env);
++num;
}//end do
while( 0 != pathPointers[num] );
printf("\n");
}//end else is relative
exit(3);
}//end if zero is pid, so in child
else
{
//PARENT
retval = waitpid(pid, &status, 0);
printf("in parent\n");
if( WIFEXITED(status) )
{
printf("child pid:%d exited normally\n", pid);
printf("with exit status:%d\n", WEXITSTATUS(status));
if( retval != pid )
{
printf("and waitpid's retval:%d\n", retval);
}//end if inequal retval and pid
}//end if exited normally
}//end else
*/
break;
//I HATE THAT THIS HAS TO BE HERE, AND I HAVE NO IDEA WHY,
//BUT AFTER I DOWNLOADED A NEW COMPILER VERSION IT GAVE
//ME THE STRANGEST ERROR ON CODE THAT HAD BEEN WORKING
//SO I MESSED WITH IT AND FINALLY FOUND THE PROBLEM BY
//PUTTING CURLY BRACES AROUND THE CODE BLOCK
//***IT IS A KNOWN BUG FOR GCC (I FILED A BUG REPORT
//WITH THEM AND THEY TOLD ME IT WAS BEING WORKED ON)***
}//end default block
}//end switch
}//end while loop
quitCleanUp:
// printf("address of fullFilePath 0x%x\n",(&(fullFilePath)));
free(fullFilePath);
// printf("address of fullInputString 0x%x\n",(&(fullInputString)));
free(fullInputString);
// printf("address of command 0x%x\n",(&(command)));
free(command);
// printf("address of fullCmd 0x%x\n",(&(fullCmd)));
free(fullCmd);
// printf("arguments: %s\n", arguments);
// printf("address of arguments 0x%x\n",(&(arguments)));
free(arguments);
printf("**************END LEVEL1.C MAIN*****************\n\n");
//**************************************************************
//******************END RUNNING CODE SECTION********************
//**************************************************************
return 0;
}//end main