Back to top

Shell Implementation--Simple Illustration of How Bash Works

/**
* Skyred
* 2006-10-27
* This program creates a shell for a user to execute explicit
* commands. The parent reports the identification numbers of it and the child.
* > < | & are implemented
**/

#include /* file of data types needed for many compilers */
#include /* needed for fork, getpid procedures */
#include /* needed for perror */
#include /* needed for exit */
#include
#include
#include

#define LINE_LEN 80
#define MAX_ARGS 64
#define MAX_ARG_LEN 16
#define MAX_PATHS 64
#define MAX_PATH_LEN 96
#define WHITESPACE " ,\t\n"
#define TOKEN ":"

/**
* The husk shell takes a fully defined command at the 'Husk>> ' prompt,
* including as many command parameters as the called function needs. To quit
* the shell, the user simply types 'quit' and she will be returned to the
* parent shell.
**/

/* Function Prototypes */
int parseCommand(char *cl,char * argv[]);
/**
* parseCommand is a loop that takes a command that has been entered from Husk
* and executes the command in a child process. 'quit' is the command that
* exits the loop.
* PREREQ: The Husk>> shell will take an explicit command and execute it as if
* the command was being executed from /bin/bash.
* POSTCOND: As long as the command is not 'quit' the shell will return to the
* 'Husk>> ' prompt after execution.
**/

void readCommand(char *buffer);
/**
* readCommand is employed by the parseCommand loop to actually take the
* command from an open charachter stream (probably the keyboard). When used
* inside parseCommand, it has no PREREQs or POSTCONDs.
**/

int parsePath(char *[]);
/**
* This function 'cuts up' the $PATH environmental variable into discreete
* directories and places each into a cell of an array.
**/

char *lookup(char*, char*[]);
/**
* This function searches the directories in the array returned by
* parsePath() to see if the file name appears there. If it is there, the
* path is returned and will be executed.
**/

/* Function Bodies */
int main (void)
{
int result = 0;
char* commandLine = (char*) malloc( MAX_ARGS );
char* argv[MAX_ARGS];
/* variable to record process id of child */
pid_t pid;
char * dirs[MAX_PATHS];
char * cmdStr;
int temp = 1;
int wait_for_child = 1;
int fid;
int fd[2]; /* provide file descriptor pointer array for pipe */
/* within pipe:
fd[0] will be input end
fd[1] will be output end */

while(1)
{
printf("Huskpower>> ");
readCommand(commandLine);
parseCommand(commandLine,argv);
parsePath(dirs);
wait_for_child = 1; /* set the default value of wait_for_child*/
if (strcmp(argv[0],"quit") == 0)
break; /* user exit */
cmdStr = lookup(argv[0],dirs);

if (cmdStr == NULL){
continue;
}

if (pipe (fd) < 0){ /* create pipe and check for an error */
perror("pipe error");
exit (1);
}

if( 0 != pid ){
while (temp")==0){
fid = open (argv[temp+1], O_WRONLY | O_CREAT, S_IRWXU | S_IRWXG | S_IRWXO);
if (dup2(fid, STDOUT_FILENO) != STDOUT_FILENO){
perror("dup2 error for standard output");
exit(1);
}
close(fid); /* close fid, as standard out now set to file */
argv[temp] = NULL;
argv[temp+1] = NULL;
break;
}
temp++;
}
/* execute the program */
result = execv(cmdStr, argv);
}

if (wait_for_child){
/* wait for the child to terminate */
waitpid( pid, NULL, 0 );
}

free(*dirs);
free(*argv);
}
return 0; /* nessecary because we must return an int */
}

int parseCommand(char *cl,char * argv[])
{
int argc;
char *workingStr;
/* Parse command line */
argc = 0;
/* copy CommandLine string */
workingStr = strdup(cl);
argv[argc] = (char*) malloc(MAX_ARGS);
while ((argv[argc] = strsep(&workingStr, WHITESPACE)) != NULL)
{
argc++;
argv[argc] = (char*) malloc(MAX_ARGS);
}
argc++;
argv[argc] = NULL;
return 0; /* because we must return an int */
}

void readCommand(char *buffer)
{
gets(buffer);
}

int parsePath(char *dirs[]){
char * str;
int num = 0;
char *workingStr;
str = getenv( "PATH" );
workingStr = (char*)strdup(str);
dirs[num] = (char*) malloc(MAX_PATH_LEN);
while ((dirs[num] = (char*)strsep( &workingStr,TOKEN)) != NULL) {
num++;
dirs[num] = (char*) malloc(MAX_PATH_LEN);
}
}

char *lookup(char * cmd,char *dir[]){
int i = 0;
int ptr = 0;
char * cmd2 = (char * ) malloc(LINE_LEN);
if ((strstr(cmd,"/") != NULL) && (strstr(cmd,"/") == cmd)){
if(access(cmd,X_OK)==0){
return cmd;
}else{
printf("%s: command not found\n",*cmd);
return NULL;
}
}else{
strcpy(cmd2,"./");
strcat(cmd2, cmd);
if(access(cmd2,X_OK)==0){

return cmd2;
}else{
while(dir!=NULL){
strcpy(cmd2,dir);
if((access(strcat(strcat(cmd2,"/"),cmd),X_OK)) == 0){

return cmd2;
}
i++;
}
printf("%s: command not found\n",cmd);
return NULL;
}
}
}

添加新评论