/*******************************************************************/ /* OS Shell /* By: Simon Foucher /* 360 223 197 /* /* Purpose: Unix OS shell /* Interprets commands as specified in the assignment statement /* /* /*******************************************************************/ /*******************************************************************/ /* /* Includes /*******************************************************************/ #include #include #include //#include /*******************************************************************/ /* /* Global variables: /* verbose: 1 = ON, 0 = OFF /* userprompt: User defined prompt display (can be modified /* using shell function PROMPT [VALUE]) /*******************************************************************/ int verbose = 0; char userprompt[] = ".$"; /* Functions /* /*******************************************************************/ /* Big help file /* /* Purpose: Displays help file when user inputs -H or HELP /* /* /*******************************************************************/ void Help (void) { printf("Shell commands (ALL IN UPPER CASES):\n\n" " -H --Returns a help screen describing the execution syntax\n" " -V --Sets the shell in verbose mode\n\n" " SET VAR VALUE --put VALUE into the shell memory with the variable name VAR\n" " GET VAR --Display the value stored in VAR\n" " VER --Returns shell's programmer's name, info\n" " CLR --Clears the screen\n" " PROMPT VALUE --Permits user to customize prompt with the string in VALUE\n" " SCRIPT [*.txt]--Interpres the specified script file\n" " HELP --Display all the commands you defined in the shell\n" " VERBOSE ON/OFF--Toggles verbose mode on or off (VERBOSE ON = -V)\n" " EXIT --Terminates the shell (Return 1=error occured\n" " [ANY OTHER COMMAND] will be passed to the OS in lower cases\n\n");} /*******************************************************************/ /* Small help file /* /* Displayed when user fails to properly initialize shell /* /* Purpose: tells user how to launch shell /* /*******************************************************************/ void help(void) { printf("\nTo launch the shell, type: \nmysh [parameter] [parameter]\n" " -v Launches shell in verbose mode\n" " -h Launches shell and displys help file\n"); } /*******************************************************************/ /* /* Shell /* /* Purpose: Interprets user commands and acts accordingly /* The commands are outlined in the 'Big Help file' function /* /*******************************************************************/ int shell(void) { char userinput[100]; //100 characters should be more than ennough to gather user input /*******************************************************************/ /* The memory data structure has been set up in a manner /* easily convertive to a "user adjustabe" size /* /* Since the memory pointer we are using (int memprt) /* is 8 bits, we will restrict memory to 255 characters (2^8) /* /* The memory data structure consists of a single character array, containing /* "NAME1 VALUE1 NAME2 VALUE2 ETC..." /* /* By separating name and value by a space, we reduce the risk of an accidental /* collision when searching memory (For example, given a data structure like /* NAME1VALUE1NAME2VALUE2, a variable named "E1VA" would be found both at /* it's real location and partly in NAME1 and VALUE1 /* /* We will use varname and varvalue (both strings) as tokens containing the /* name of a user variable and its value. This will facilitate the searching process. /* /* memleft will keep track of how much memory is left in the shell /* and warn user when the shell is out of memory /*******************************************************************/ int memptr =0, memleft = 255; char proceed[1]; int i, j, cs; char shellmemory[memleft]; char varname[30], varvalue[30]; char getlocation[100]; char record[100]; //to record data in open file for script function FILE *fp; /* file pointer */ /*******************************************************************/ /* /* The shell will be executing until the user types EXIT /* Implemented using exitshell (exit if exitshell = 0) /*******************************************************************/ int exitshell = 1; while(exitshell) { if(verbose) { printf("\nPlease enter a command (-H or HELP to display help file)\n"); } printf("%s ",userprompt); fgets(userinput, 100, stdin); //Command line interpreter: //First we detect the command entered and numerize it as an integer to use switch/case cs = 0; //Default case, will pass the command to OS if(strstr(userinput, "SET ")) cs = 1; if(strstr(userinput, "GET ")) cs = 2; if(strstr(userinput, "EXIT")) cs = 3; if(strstr(userinput, "HELP") || strstr(userinput, "-H")) cs = 4; if(strstr(userinput, "-V") || strstr(userinput, "VERBOSE ON")) cs = 5; if(strstr(userinput, "VERBOSE OFF")) cs = 6; if(strstr(userinput, "VER") && userinput[3] == '\n') cs = 7; //The second condition avoids confusinf with VERBOSE if(strstr(userinput, "CLR")) cs = 8; if(strstr(userinput, "PROMPT")) cs = 9; // scriptcount = 1; /****************************************************************************** /* scriptcount counts the number of commands that needs to be executed. /* Default is 1; for single commands. In the case of the command script, /* scriptfile counts the number of commands to execute and runs them /* until scriptfile == 0 (Not fully implemented) /* /******************************************************************************/ //**************************************SCRIPT TEXT FILE******************************************************** if(strstr(userinput, "SCRIPT")) { //Haven't had time to implement this function //First we extract the file name i = 6; while(userinput[i] != '\0') { varname[i-7] = userinput[i]; i++; } varname[i-7] = '\0'; //Since the loop breaks b4 null is transfered, we manually enter it if(verbose) { printf("Are you sure you want to script file '%s'[Y/N]", varname); fgets(proceed, 2, stdin); } if(!verbose || strstr(proceed, "Y")) { // open file for output if ((fp = fopen("varname", "w"))==NULL) { printf("Cannot open file \n"); } //fp points to the start of the text file. The commands will be extracted one line at a time for(j = 0; j < 25; j++) { while(fgets(record, sizeof(record), fp) != NULL); printf("\n Extracting '%s'\n", record); } //scriptcount = j; } fclose(fp); printf("The script functino will be implement in V1.02\n"); }//End of user input SCRIPT /***************************************************** /* Didn't have time to fully implement scripting /* the commands are extracted form the text file /* but not yet passed to the command line interpreter /*****************************************************/ // while(scriptcount) // { /****************************************************** /* the following loop will be executed as long /* as there is script left to be executed. /* (default is 1, except when scripting a text fle /******************************************************/ proceed[0] = 'N'; //resets the value to no. If verbose, user will change proceed to Y to execute command switch(cs) { //**************************************SET***************************************************************** case 1: /****************************************************************************** //First, we extract the new VARIABLE's name and store it into varname //If userinput = SET VARIABLE VALUE, i+4 points to the 1st letter of variable //We will transfer characters from the user input to varname until we hit a ' ' /*******************************************************************************/ i = 0; while(userinput[i+4] != ' ') { varname[i] = userinput[i+4]; i++; } varname[i] = '\0'; //Since the loop breaks b4 null is transfered, we manually enter it /****************************************************************************** //Then we extract the new VARIABLE's value and store it into varvalue //At this point, i points to the " " between VARIABLE and VALUE /******************************************************************************/ i++; //Now i points to the first element of the VALUE j = 0; //Because VARIABLE name has an arbitrary lenght, we'll use a second pointer for varvalue reset at 0 while(userinput[i+4] != '\n') { varvalue[j] = userinput[i+4]; i++; j++; } varvalue[j] = '\0'; //Since the loop breaks b4 null is transfered, we manually enter it //Perform a memory test to make sure that the variable name is not already taken if(strstr(shellmemory, varname)) { printf("ERROR: Variable name already taken. Please choose a different name\nOperation cancelled\n\n"); } else { //Now we perform a memory test to ensure that there is ennough space to store new data // 'i' counted the lenght of varname and varvalue. When stored, they will take i+1 bits of space (1 for the space seperating variables) if(memleft - i > 0) { //Verbose mode prompt if(verbose) { printf("Are you sure you want to create a variable \nnamed: '%s' with value: '%s' to shell memory?\n" "(FYI, You have %d bits of memory left) [Y/N]", varname, varvalue, memleft); fgets(proceed, 2, stdin); } if(!verbose || strstr(proceed, "Y")) { //First we enter the VARIABLE name into the shell memory i=0; while(varname[i] != '\0') { shellmemory[memptr] = varname[i]; i++; memptr++; } shellmemory[memptr] = ' '; //Add a space after variable name in memory memptr++; //Then we enter the variable's VALUE into the shell's memory i=0; while(varvalue[i] != '\0') { shellmemory[memptr] = varvalue[i]; i++; memptr++; } shellmemory[memptr] = ' '; //Add a space after variable name in memory memptr++; memleft = 255 - memptr; } }//End of if there was ennough memory else { printf("Operation cancelled => need %d bits of space and only %d left in shell memory.\n" "Delete variables of free more memory before proceeding\n", i, memleft); } }//End of variable name not already taken //scriptcount--; break; //End of case SET //**************************************GET******************************************************************** case 2: /****************************************************************************** //First, we extract the VARIABLE's name and store it into varname //If userinput = GET VARIABLE, i+4 points to the 1st letter of variable //We will transfer characters from the user input to varname until we hit a '\0' /******************************************************************************/ i = 0; while(userinput[i+4] != '\n') { varname[i] = userinput[i+4]; i++; } varname[i] = '\0'; //Since the loop breaks b4 null is transfered, we manually enter it //Verbose mode prompt if(verbose) { printf("Are you sure you want to read the value of '%s'?[Y/N]", varname); fgets(proceed, 2, stdin); } if(!verbose || strstr(proceed, "Y")) { /****************************************************************************** //strspn Returns a pointer to the first element of the VARIABLE's name //By adding 'i' (=varname's lenght + NULL), we are pointing at the value /******************************************************************************/ if(!strstr(shellmemory, varname))printf("Unable to locate a variable named '%s' in memory!\n", varname); else { j = strcspn(shellmemory, varname) + i + 1; /****************************************************************************** // 'j' points at the start of the value. The following code will extract and display that value /******************************************************************************/ i = 0; while(shellmemory[j] != ' ') { varvalue[i] = shellmemory[j]; i++; j++; } varvalue[i] = '\0'; //Since the loop breaks b4 null is transfered, we manually enter it printf("The variable '%s' has a value of '%s'\n", varname, varvalue); } } break; //End of GET operation //**************************************EXIT******************************************************************* case 3: if(verbose) { printf("Are you sure you want to quit? [Y/N]\n"); fgets(proceed, 2, stdin); } if(!verbose || strstr(proceed, "Y")) { printf("Thank you for using the shell.\nExiting Shell\n\n"); exitshell = !strstr(userinput, "EXIT"); //exitshell=0 if user typed 'EXIT' } //scriptcount--; break; //**************************************HELP******************************************************************* case 4: if(verbose) { printf("Are you sure you want display help file? [Y/N]\n"); fgets(proceed, 2, stdin); } if(!verbose || strstr(proceed, "Y")) { Help(); } //scriptcount--; break; //**************************************VERBOSE MODE*********************************************************** case 5: if(verbose)printf("The shell is already in verbose mode\n\n"); else { verbose = 1; printf("Shell is now in Verbose mode\n\n"); } break; case 6: if(verbose) { printf("Are you sure you want turn off verbose mode?\nYou won't get these helpfull prompts anymore [Y/N]\n"); fgets(proceed, 2, stdin); if(strstr(proceed, "Y")) { verbose = 0; printf("Verbose mode turned OFF\n\n"); } } else//Verbose was already turned off { printf("Verbose mode was already turned off\n\n"); } //scriptcount--; break; //**************************************VERSION***************************************************************** case 7: if(verbose) { printf("Are you sure you want display Shell info? [Y/N]\n"); fgets(proceed, 2, stdin); } if(!verbose || strstr(proceed, "Y")) { printf("\n\nOS Shell ver 1.01beta\n" "Created on 2008.09.25\n" "By Simon Foucher\n\n"); } //scriptcount--; break; //**************************************CLEAR SCREEN************************************************************ //was using clrscr() function from conio.h which is DOS specific... This is a less elegant way to implement it case 8: if(verbose) { printf("Are you sure you want to clear screen?\n(Unsaved data will be permanently lost)[Y/N]"); fgets(proceed, 2, stdin); } if(!verbose || strstr(proceed, "Y")) { for(i = 0; i < 200; i++)printf("\n"); } //scriptcount--; break; //**************************************EDIT USER PROMPT******************************************************** case 9: i = 6; while(userinput[i] != '\0') { varname[i-7] = userinput[i]; i++; } varname[i-7] = '\0'; //Since the loop breaks b4 null is transfered, we manually enter it if(verbose) { printf("Are you sure you want to change the prompt\nfrom '%s' to '%s'? [Y/N]", userprompt, varname); fgets(proceed, 2, stdin); } if(!verbose || strstr(proceed, "Y")) { strcpy(userprompt, varname); } //scriptcount--; break; //**************************************SYSTEM CALLS*********************************************************** default: /* if(verbose) { printf("Command not recognized by mysh. Do you wish to call the OS for the command '%s'? [Y/N]", userinput); fgets(proceed, 2, stdin); } */ if(!verbose || strstr(proceed, "Y")) { system(userinput); } //scriptcount--; }//End of the switch //}//End of while(scriptcount); didn't have time to implement //************************************************************************************************************** }//While EXIT!=1, loop back to top of shell return 0; } int main() { char launchinput[300]; fgets(launchinput, 300, stdin); /*Get shell launch command*/ int launch, hlp, ver; if(strstr(launchinput, "mysh")) //Shell is launched { printf("Loading shell\n"); if(strstr(launchinput, "-h")) //user typed -h; help is displayed { Help(); } if(strstr(launchinput, "-v")){ //Verbose mode is turned on verbose = 1; //Global boolean variable to keep track of verbose mode printf("[Verbose mode = ON]"); } shell(); } else { //Help file displayed and error code returned printf("INVALID ENTRY\n\n"); help(); return(1); } return (0); }