Saket Soni


back to home


// A small elementary unix shell...
// Author: Saket Soni
#include
#include
#include
#include
#include
#include
#include

char ** mainArgv = 0;
int     mainArgc   = 0;

int  lastCommandExitStatus = -1;
int  runInBackGround   = 0;
char errMsg   [1024] ;
int  isLoginShell      = 0;
char *currentDirectory = 0;
char *oldDirectory     = 0;
char homeDir  [1024] ;
char *userName         = 0;
char hostName [1024] ;
 
class ShellVariable
{
	char * name;
	char * value;
public:
	ShellVariable ( const char * strName, const char * strValue )
	{
		if ( strName == NULL || strValue == NULL )
			throw "null argument passed to constructor of ShellVariable function ";
		name = (char*) malloc ( strlen(strName)+1 );
		if ( name == NULL )
			throw "out of memory ";
		value = (char *) malloc ( strlen(strValue)+1 );
		if ( value == NULL )
		{
			free ( name );
			throw "out of memory ";
		}
		strcpy(name,strName);
		strcpy(value,strValue);
	}
	~ShellVariable ()
	{
		if ( name )
			free ( name );
		if ( value )
			free ( value );
	}
	const char * getName ()
	{
		return name;
	}
	const char * getValue ()
	{
		return value;
	}
	void setValue ( const char * str )
	{
		if ( str == NULL )
			throw "null argument passed to setValue function of ShellVariable Class ";
		if ( value )
			free ( value );
		value = (char *) malloc ( strlen(str)+1 );
		if ( value == NULL )	{
			if ( name )
				free ( name );
			throw "out of memory ";
		}
		strcpy(value,str);
	}
	bool isEquals ( const char * str )
	{
		if ( str == NULL )
			throw "null argument passed to isEqual function of ShellVariable Class ";
		char * pch = strchr(str,'=');
		if ( pch == NULL )
			return ( strcmp(name,str) == 0 );
		const char * ptr1 = str;
		char * ptr2 = name;
		while ( ptr1 != str )
			if ( *ptr1++ != *ptr2++ )
				return false;
		return true;
	}
};
ShellVariable * shellVariableArray[1024];
int numOfShellVariables = 0;

class Command
{
	int  numArgs;
	char * redirStdout;
	char * redirStdin;
	char * redirStderr;
	char * argument[50];
	bool isVariableSetCommand;

public:
	Command ( const char * str )
	{
		if ( str == NULL )
			throw "invalid command "; 
		numArgs = 0;
		redirStdout = redirStdin = redirStderr = NULL;
		isVariableSetCommand = false;
		set ( str );
	}
	bool isVariableSetCmd()
	{
		return isVariableSetCommand;
	}
	const char * getName()
	{
		return argument[0];
	}
	int getNumArgs()
	{
		return numArgs;
	}
	const char * getArg ( int indx )
	{
		if ( indx < 0 || indx >= numArgs )
			return NULL;
		return argument[indx];
	}
	char ** getArgList()
	{
		return argument;
	}
	const char * getRedirStdout()
	{
		return redirStdout;
	}
	const char * getRedirStderr()
	{
		return redirStderr;
	}
	const char * getRedirStdin()
	{
		return redirStdin;
	}
	bool isInternalCommand()
	{
		return (  ( strcmp ( argument[0], "exit"   ) == 0 ) ||
					 ( strcmp ( argument[0], "logout" ) == 0 ) ||
					 ( strcmp ( argument[0], "cd"     ) == 0 ) ||
					 ( strcmp ( argument[0], "set"	 ) == 0 ) ||
					 ( strcmp ( argument[0], "echo"   ) == 0 ) );
	}
	void set ( const char * str )
	{
		char temp[100];
		if ( redirStdout )
			free ( redirStdout );
		if ( redirStdin )
			free ( redirStdin );
		if ( redirStderr )
			free ( redirStderr );
		redirStdout = redirStdin = redirStderr = NULL;
		char *tempStr = (char*) malloc ( strlen(str)+1 );	// must be freed before exiting from the 

function.
		if ( tempStr == NULL )
			throw "out of memory ";
		strcpy(tempStr,str);
		char *k1 = strstr(tempStr," 2>");
		if ( k1 )
		{
			char *k2 = strstr(k1+3," 2>");
			if ( k2 )	{
				free ( tempStr ); tempStr = NULL;
				throw "cannot have more than one stderr redirection in a command ";
			}
			k2 = k1+3;
			while ( *k2 == ' ' || *k2 == '\t' )
				k2++;
			char *k3 = temp;
			while ( *k2 != ' ' && *k2 != '\t' && *k2 != '>' && *k2 != '<' && *k2 != 0 )
				*k3++ = *k2++;
			*k3 = 0;
			if ( temp[0] == 0 )	{
				free ( tempStr ); tempStr = NULL;
				throw "no filename specified for redirecting stderr ";
			}
			k3 = (char*) malloc ( strlen(temp)+1 );
			if ( k3 == NULL )	{
				free ( tempStr ); tempStr = NULL;
				throw "out of memory ";
			}
			strcpy(k3,temp);
			redirStderr = k3;
			while ( *k2 != 0 )
				*k1++ = *k2++;
			*k1 = 0;
		}
		k1 = strchr(tempStr,'>');
		if ( k1 )
		{
			char *k2 = strchr(k1+1,'>');
			if ( k2 )	{
				free ( tempStr ); tempStr = NULL;
				throw "cannot have more than one stdout redirection in a command ";
			}
			k2 = k1+1;
			while ( *k2 == ' ' || *k2 == 't' )
				*k2++;
			char *k3 = temp;
			while ( *k2 != ' ' && *k2 != '\t' && *k2 != '<' && *k2 != 0 )
				*k3++ = *k2++;
			*k3 = 0;
			if ( temp[0] == 0 )	{
				free ( tempStr ); tempStr = NULL;
				throw "no filename specified for redirecting stdout ";
			}
			k3 = (char*) malloc ( strlen(temp)+1 );
			if ( k3 == NULL )	{
				free ( tempStr ); tempStr = NULL;
				throw "out of memory ";
			}
			strcpy(k3,temp);
			redirStdout = k3;
			while ( *k2 != 0 )
				*k1++ = *k2++;
			*k1 = 0;
		}
		k1 = strchr(tempStr,'<');
		if ( k1 )
		{
			char *k2 = strchr(k1+1,'<');
			if ( k2 )	{
				free ( tempStr ); tempStr = NULL;
				throw "cannot have more than one stdin redirection in a command ";
			}
			k2 = k1+1;
			while ( *k2 == ' ' || *k2 == 't' )
				*k2++;
			char *k3 = temp;
			while ( *k2 != ' ' && *k2 != '\t' && *k2 != 0 )
				*k3++ = *k2++;
			*k3 = 0;
			if ( temp[0] == 0 )	{
				free ( tempStr ); tempStr = NULL;
				throw "no filename specified for redirecting stdin ";
			}
			k3 = (char*) malloc ( strlen(temp)+1 );
			if ( k3 == NULL )	{
				free ( tempStr ); tempStr = NULL;
				throw "out of memory ";
			}
			strcpy(k3,temp);
			redirStdin = k3;
			while ( *k2 != 0 )
				*k1++ = *k2++;
			*k1 = 0;
		}
		k1 = strtok ( tempStr, " \t" );
		if ( k1 == NULL )	{
			free ( tempStr ); tempStr = NULL;
			throw "invalid command ";
		}
		argument[0] = (char*) malloc(strlen(k1)+1);
		if ( argument[0] == NULL )	{
			free ( tempStr ); tempStr = NULL;
			throw "out of memory ";
		}
		strcpy(argument[0],k1);
		numArgs = 1;
		while ( k1 = strtok(0," \t") )
		{
			argument[numArgs] = (char*) malloc(strlen(k1)+1);
			if ( argument[numArgs] == NULL )	{
				free ( tempStr ); tempStr = NULL;
				for ( int i = numArgs-1 ; i >= 0 ; i-- )
					free ( argument[i] );
				numArgs = 0;
				throw "out of memory ";
			}
			strcpy(argument[numArgs],k1);
			numArgs++;
		}
		argument[numArgs] = NULL;

		// checking if the command is for setting a shell variable ...
		isVariableSetCommand = false;
		char * sptr1 = strchr ( argument[0], '=' );
		if ( sptr1 != NULL && sptr1 != argument[0] && ( *(sptr1-1) != ' ' ) )
		{
			strcpy(tempStr,str);			// make a fresh copy of str in tempStr !!
			sptr1 = strchr ( tempStr, '=' );
			if ( *(sptr1+1) != ' ' && *(sptr1+1) != 0 )
			{
				for ( int i = 0 ; i < numArgs ; i++ )
					free ( argument[i] );	// free all previous arguments ...
				numArgs = 0;
	
				k1 = strtok ( tempStr, " \t=" );	// find name ...
				argument[0] = (char*) malloc(strlen(k1)+1);
				if ( argument[0] == NULL )	{
					free ( tempStr ); tempStr = NULL;
					throw "out of memory ";
				}
				strcpy(argument[0],k1);
				k1 = strtok ( 0, "\n" );
				argument[1] = (char*) malloc(strlen(k1)+1);
				if ( argument[1] == NULL )	{
					free ( tempStr ); tempStr = NULL;
					free ( argument[0] ); argument[0] = NULL;
					throw "out of memory ";
				}
				strcpy(argument[1],k1);
				numArgs = 2;
				isVariableSetCommand = true;
			}
			else	{
				sptr1++;
				bool nullValue = true;
				while ( *sptr1 != 0 )
				{
					if ( *sptr1 != ' ' && *sptr1 != '\t' )	{
						nullValue = false;
						break;
					}
					sptr1++;
				}
				if ( nullValue == true )
				{
					for ( int i = 0 ; i < numArgs ; i++ )
						free ( argument[i] );	// free all previous arguments ...
					numArgs = 0;
					k1 = strtok ( tempStr, " \t=" );	// find name ...
					argument[0] = (char*) malloc(strlen(k1)+1);
					if ( argument[0] == NULL )	{
						free ( tempStr ); tempStr = NULL;
						throw "out of memory ";
					}
					strcpy(argument[0],k1);
					numArgs = 1;
					isVariableSetCommand = true;
				}
			}
		}		

		// adding color to the ls command ...
		if ( strcmp ( argument[0], "ls" ) == 0 )	// if ls, then add --color
		{
			bool hasColor = false;
			for ( int i = 1 ; i < numArgs ; i++ )
				if  ( strncmp ( argument[i], "--color", sizeof("--color")-1 ) == 0 )	{
					hasColor = true;
					break;
				}
			if ( ! hasColor )
			{
				k1 = NULL;
				k1 = (char*) malloc ( sizeof("--color") );
				if ( k1 == NULL )	{
					free ( tempStr ); tempStr = NULL;
					throw "out of memory ";
				}
				strcpy ( k1, "--color" );
				argument[numArgs++] = k1;
				argument[numArgs] = 0;
			}
		}
		free ( tempStr );
	}
	void display()
	{
		printf ( "Command : ", numArgs );
		for ( int i = 0 ; i < numArgs ; i++ )
			printf ( "%s ",argument[i] );
		printf ( "\n  numArgs   : %d\n", numArgs );
		for ( int i = 0 ; i < numArgs ; i++ )
			printf ( "    %d.) %s\n", i, argument[i] );
		printf ( "  Stdout redirection : %s\n", redirStdout);
		printf ( "  Stderr redirection : %s\n", redirStderr);
		printf ( "  Stdin  redirection : %s\n", redirStdin);
	}
	bool equals ( const char * str )
	{
		if ( numArgs == 0 )
			return false;
		return ( ( strcmp ( argument[0], str ) == 0 ) ? true : false );
	}
	~Command()
	{
		if ( redirStdout )
			free ( redirStdout );
		if ( redirStdin )
			free ( redirStdin );
		if ( redirStderr )
			free ( redirStderr );
		for ( int i = 0 ; i < numArgs ; i++ )
			if ( argument[i] )
				free ( argument[i] );
	}
};

void evaluate$ ( char * str )
{
	char shellVarName[100];
	char mystr[1024];
	if ( str == NULL )
		return;
	char * ptr1 = strchr ( str, '$' );
	if ( ptr1 == NULL )
		return;
	do
	{
		char ch = *(ptr1+1);
		if ( ch == 0 )
			return;
		if ( ch == '\t' || ch == ' ' )
			continue;
		*ptr1++ = 0;
		strcpy ( mystr, str );
		int i = 0;
		char *ptr2 = ptr1;
		while ( *ptr2 != 0 && *ptr2 != ' ' && *ptr2 != '\t' )
			shellVarName[i++] = *ptr2++;
		shellVarName[i] = 0;
		
		char *ptr3 = ptr1;
		while ( *ptr2 != 0 )
			*ptr3++ = *ptr2++;
		*ptr3 = 0;
		bool doesVariableExists = false;
		i = 0;
		for ( i = 0 ; i < numOfShellVariables ; i++ )
			if ( shellVariableArray[i]->isEquals(shellVarName) )	{
				doesVariableExists = true;
				break;
			}
		if ( doesVariableExists == true )
			strcat ( mystr, shellVariableArray[i]->getValue() );
		strcat ( mystr, ptr1 );
		strcpy ( str, mystr );
	} while ( ptr1 = strchr ( str, '$' ) );
}

int main ( int argc, char * argv[] )
{
	int  counter1             = -1;
	int  inputLen          = 0;
	char input   [1024] ;
	Command *command [100];
	int  numCommands       = 0;
	int  myStdin           = -1;
	int  myStdout          = -1;
	int  myStderr          = -1;
  

	// make command line arguments accessible to all functions ...
	mainArgv = argv;
	mainArgc = argc;

	// check whether the shell is a login shell or not ...
	if ( strcmp ( argv[0], "-shell" ) == 0 )
		isLoginShell = 1;
	for ( counter1 = 1 ; counter1 < argc ; counter1++ )
	{
		if ( strcmp ( argv[counter1],"-l" ) == 0 )
			isLoginShell = 1;
		else if ( strcmp ( argv[counter1], "--login" ) == 0 )
			isLoginShell = 1;
		else  {
			fprintf ( stderr,"shell: invalid argument!\n" );
			return 1;
		}
	}

	// adding path entry in the list of shell varibles ...









	//  get basic information about user and his/her environment ...
	currentDirectory = get_current_dir_name();
	userName         = getlogin();
	gethostname ( hostName, sizeof ( hostName ) );
	strcpy(homeDir,currentDirectory);

	while ( 1 )  //  infinite loop for reading commands ...
	{
		// show prompt to the user ...
		fflush ( stdin );
		printf ( "[%s@%s     %s]\n$ ", userName, hostName, currentDirectory );
		fflush ( stdout );

		// read command from the user ...
		inputLen = read ( 0, input, sizeof(input) );
		char * str1 = strchr(input,'\n');
		if ( str1 != NULL )				// removing '\n' ...
			*str1 = 0;
		str1 = strchr(input,'\r');
		if ( str1 != NULL )				// removing '\r' ...
			*str1 = 0;

		// find and evalute $'s ...
		evaluate$ ( input );

		// check whether to run in background or not ...
		str1 = strchr ( input, '&' );
		runInBackGround = 0;
		if ( str1 )
		{
			char * str2 = strrchr ( input, '&' );
			if ( str1 != str2 )  {
				fprintf ( stderr, "%s: systax error near unexpected token \'&\'\n",
										mainArgv[0] );
				continue;
			}
			else  {   // set global variable to indicate run in background ...
				runInBackGround = 1;
				*str1++ = 0;
			}  
		}

		// delete all previous commands ...
		for ( int i = 0 ; i < numCommands ; i++ )
			delete command[i];
		numCommands = 0;

		// parse the input to check if it is set variable command ...
		Command * temp = NULL ;
		try	{
			temp = new Command (input) ;
		}
		catch ( const char * estr )	{
			fprintf ( stderr, "%s: %s\n", mainArgv[0], estr );
			continue;
		}
		if ( temp->isVariableSetCmd() )
		{
			bool doesVariableExists = false;
			int i = 0;
			for ( i = 0 ; i < numOfShellVariables ; i++ )
				if ( shellVariableArray[i]->isEquals(temp->getName()) )	{
					doesVariableExists = true;
					break;
				}
			if ( doesVariableExists == true )	{
				if ( temp->getNumArgs() == 2 )	{
					shellVariableArray[i]->setValue(temp->getArg(1));
					delete temp;
				}
				else	{
					delete shellVariableArray[i];
					for ( int k = i+1 ; k < numOfShellVariables ; k++ )
						shellVariableArray[k-1] = shellVariableArray[k];
					numOfShellVariables--;
					delete temp;
				}
			}
			else	{
				if ( temp->getNumArgs() == 2 )	{
					shellVariableArray[numOfShellVariables] = new ShellVariable( 

temp->getName(),
															

										 temp->getArg(1) );
					numOfShellVariables++;
					delete temp;
				}
			}
			continue;
		}
		else
			delete temp;

		// parse the input to find the various commands ...
		str1 = input;
		char *str2 = strchr ( input, '|' );
		if ( str2 )
		{
			*str2 = 0;
			try	{
				temp = new Command(str1);
			}
			catch ( const char * estr )	{
				fprintf ( stderr, "%s: %s\n", mainArgv[0], estr );
				continue;
			}
			command[0] = temp;
			numCommands++;
			try	{
				str1 = str2+1;
				str2 = strchr ( str1, '|' );
				while ( str2 )	{
					*str2 = 0;
					temp = new Command ( str1 );
					command[numCommands++] = temp;
					str1 = str2+1;
					str2 = strchr ( str1, '|' );
				}
				temp = new Command ( str1 );
				command[numCommands++] = temp;
			}
			catch ( const char * estr )	{
				fprintf ( stderr, "%s: %s\n", mainArgv[0], estr );
				numCommands = 0;
				continue;
			}
		}
		else
		{
			try	{
				temp = new Command(input);
			}
			catch ( const char * estr )	{
				fprintf ( stderr, "%s: %s\n", mainArgv[0], estr );
				continue;
			}
			command[0] = temp;
			numCommands++;
		}

		if ( numCommands > 1 )  // if one of the commands is an internal command then cannot use pipe!!
		{
			bool foundInternalCommand = false;
			int i;
			for ( i = 0 ; i < numCommands ; i++ )
				if ( command[i]->isInternalCommand() )	{
					foundInternalCommand = true;
					break;
				}
			if ( foundInternalCommand )
			{
				sprintf ( errMsg, "%s: cannot use '%s' with pipes ", mainArgv[0], 

command[i]->getName() );
				perror  ( errMsg );
				continue;
			}
		}

		if ( numCommands == 1 )
		{
			// check for internal commands and execute ...
			if ( strcmp ( command[0]->getName(), "exit" ) == 0 )             // exit ...
			{
				if ( isLoginShell )
					exit ( 0 );
				switch ( command[0]->getNumArgs() )
				{
				case 1:
					_exit ( lastCommandExitStatus );
				case 2:	{
					const char * str3 = command[0]->getArg(1);
					int len = strlen ( str3 );
					bool isNumber = true;
					for ( int i = 0 ; i < len ; i++ )
						if ( ! isdigit ( str3[i] ) )  {
							isNumber = false;
							break;
						}
					if ( isNumber == true )
						_exit ( atoi ( str3 ) );
					else
						fprintf ( stderr, "%s: exit: %s: numeric argument required",
										mainArgv[0], str3 );
					}
					break;
				default:
					fprintf ( stderr, "%s: exit: too many arguments", mainArgv[0] );
				}
			}
			else if ( strcmp ( command[0]->getName(), "logout" ) == 0 )      // logout ...
			{
				if ( ! isLoginShell )
					fprintf ( stderr, "%s: logout: not login shell: use \'exit\'\n",
										mainArgv[0] );
				else
					_exit ( 0 );
			}
			else if ( strcmp ( command[0]->getName(), "cd" ) == 0 )          // cd ...
			{
				int chdirStatus = -1;
				if ( command[0]->getNumArgs() == 1 )
					chdirStatus = chdir ( homeDir );
				else if ( strcmp ( command[0]->getArg(1), "-" ) == 0 )	{
					if ( oldDirectory )
						chdirStatus = chdir ( oldDirectory );
					else
						chdirStatus = 0;
				}
				else
					chdirStatus = chdir ( command[0]->getArg(1) );
				if ( chdirStatus == -1 )  {
					sprintf ( errMsg, "%s: cd: %s", mainArgv[0], command[0]->getArg(1) );
					perror  ( errMsg );
				}
				else  {
					if ( oldDirectory )
						free ( oldDirectory );
					oldDirectory = currentDirectory ;
					currentDirectory = get_current_dir_name (); 
				}
			}
			else if ( strcmp ( command[0]->getName(), "set" ) == 0 )         // set ...
			{
				for ( int i = 0 ; i < numOfShellVariables ; i++ )
					

fprintf(stdout,"%s=%s\n",shellVariableArray[i]->getName(),shellVariableArray[i]->getValue());
			}
			else												

								  // external command ...
			{
				int childPId = fork();
				switch ( childPId )
				{
				case 0:                 // child process starts here ...
					if ( command[0]->getRedirStdout() )	{		// stdout 

redirection ...
						int fd = creat ( command[0]->getRedirStdout(), 00644 );
						close(1);
						dup(fd);
						close(fd);
					}
					if ( command[0]->getRedirStdin() )	{		// stdin 

redirection ...
						int fd = open  ( command[0]->getRedirStdin(), O_RDONLY );
						if ( fd == -1 )	{
							sprintf ( errMsg, "%s: %s", mainArgv[0], 

command[0]->getName() );
							perror  ( errMsg );
							_exit(1);
						}
						close(0);
						dup(fd);
						close(fd);
					}
					if ( command[0]->getRedirStderr() )	{		// stderr 

redirection ...
						int fd = creat ( command[0]->getRedirStderr(), 00644 );
						close(2);
						dup(fd);
						close(fd);
					}
					execvp  ( command[0]->getName(), command[0]->getArgList() ) ; // start new 

program ...
					sprintf ( errMsg, "%s: %s", mainArgv[0], command[0]->getName() );
					perror  ( errMsg );
					_exit (1) ;                    // error child process ends here ...
				case -1:                // if no child has been forked ...
					sprintf ( errMsg, "%s: %s", mainArgv[0], command[0]->getName() );
					perror  ( errMsg );
					break;
				default:                // if parent process continues here ...
					if ( runInBackGround == 0 )
					{
						int waitStatus = -1;
						do
						{
							waitStatus = wait ( &lastCommandExitStatus );
							if ( waitStatus == -1 )
							{
								sprintf ( errMsg, "%s: %s", mainArgv[0], 

command[0]->getName() );
								perror  ( errMsg );
								break;
							}
						} while ( waitStatus != childPId );  // remove all dead child 

processes ...
					}
				}
			}
		}
		else	// pipes exists ( with only external commands ) ...
		{
			int childPId = fork();
			switch ( childPId )
			{
			case 0:                 // child process starts here ...
				{
					int comK = numCommands-2;
					int pipefdR[2];
					pipe ( pipefdR );
					int lastInputFd = pipefdR[0];
					int firstOutputFd = -1;
					int pipefdL[2];
					for ( ; comK > 0 ; comK-- )
					{
						pipe ( pipefdL );
						int grandChild = fork();
						if ( grandChild == 0 )		// grandchild process starts here 

...
						{
							if ( command[comK]->getRedirStderr() )	{		// 

stderr redirection ...
								int fd = creat ( command[comK]->getRedirStderr(), 

00644 );
								close(2);
								dup(fd);
								close(fd);
							}
							close(1);
							dup(pipefdR[1]);		// replacing stdout with 

output to pipe on the right!
							close(pipefdR[1]);
							close(pipefdR[0]);
							close(0);
							dup(pipefdL[0]);		// replacing stdin  with 

input from pipe on the left!
							close(pipefdL[0]);
							close(pipefdL[1]);
							execvp  ( command[comK]->getName(), 

command[comK]->getArgList() ) ; // start new
															

														  

// process ...
					      sprintf ( errMsg, "%s: %s", mainArgv[comK], command[comK]->getName() 

);
					      perror  ( errMsg );
//							killpg(0,SIGKILL);
					      _exit(1) ;           // on error grandchild process ends here ...
						}
						else if ( grandChild == -1 )
						{
							sprintf ( errMsg, "%s: %s", mainArgv[0], 

command[comK]->getName() );
							perror  ( errMsg );
//							killpg(0,SIGKILL);
							_exit(1);
						}
						else	{						// child, 

i.e parent of grandchild ...
							close ( pipefdR[1] );
							close ( pipefdL[0] );
							pipefdR[1] = pipefdL[1];
						}
					}
					firstOutputFd = pipefdR[1];
					int grandChild = fork();
					if ( grandChild == 0 )
					{
						if ( command[0]->getRedirStdin() )	{		// stdin 

redirection ...
							int fd = open  ( command[0]->getRedirStdin(), O_RDONLY );
							if ( fd == -1 )	{
								sprintf ( errMsg, "%s: %s", mainArgv[0], 

command[0]->getName() );
								perror  ( errMsg );
								_exit(1);
							}
							close(0);
							dup(fd);
							close(fd);
						}
						if ( command[0]->getRedirStderr() )	{		// stderr 

redirection ...
							int fd = creat ( command[0]->getRedirStderr(), 00644 );
							close (2);
							dup(fd);
							close(fd);
						}
						close(1);
						dup(firstOutputFd);	// replacing stdout with output to pipe on 

the right!
						close(firstOutputFd);
						execvp  ( command[0]->getName(), command[0]->getArgList() ) ; // 

start new process ...
				      sprintf ( errMsg, "%s: %s", mainArgv[0], command[0]->getName() );
				      perror  ( errMsg );
//						killpg(0,SIGKILL);
				      _exit (1) ;           // on error grandchild process ends here ...
					}
					else if ( grandChild == -1 )
					{
						sprintf ( errMsg, "%s: %s", mainArgv[0], command[0]->getName() );
						perror  ( errMsg );
//						killpg(0,SIGKILL);
						_exit(1);
					}
												// child, i.e 

parent of grandchild ...
					close(firstOutputFd);
					close(0);
					dup(lastInputFd);
					close(lastInputFd);
					comK = numCommands-1;
					execvp  ( command[comK]->getName(), command[comK]->getArgList() ) ; // 

start new process ...
			      sprintf ( errMsg, "%s: %s", mainArgv[0], command[comK]->getName() );
			      perror  ( errMsg );
//					killpg(0,SIGKILL);
			      _exit (1) ;           // on error grandchild process ends here ...
				}
			case -1:                // if no child has been forked ...
				sprintf ( errMsg, "%s: %s", mainArgv[0], command[0]->getName() );
				perror  ( errMsg );
				break;
			default:                // parent process continues here ...
				if ( runInBackGround == 0 )
				{
					int waitStatus = -1;
					do
					{
						waitStatus = wait ( &lastCommandExitStatus );
						if ( waitStatus == -1 )
						{
							sprintf ( errMsg, "%s: %s", mainArgv[0], 

command[0]->getName() );
							perror  ( errMsg );
							break;
						}
					} while ( waitStatus != childPId );  // remove all dead child processes ...
				}
			}
		}

	}	// end of the infinite loop of the shell !!!

	return 0;
}



back to home



Locations of visitors to this page 1