I have been trying to support certain built in commands such as 'cd' and 'help'. If I do 'ls' or 'mkdir' it executes them fine and they do what they are supposed to. If I type the command 'help' I get a segmentation fault and if I type 'cd' it does nothing. I think I may have to use a script? but im not sure.

/* -----------------------------------------------------------------------------
FILE: shell.c
 
NAME:

DESCRIPTION: A SHELL SKELETON
-------------------------------------------------------------------------------*/

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <strings.h>
#include <readline/readline.h>
#include <readline/history.h>
#include "parse.h"   // local file include declarations for parse-related structs


enum BUILTIN_COMMANDS { NO_SUCH_BUILTIN=0, EXIT, JOBS, HELP };


/* -----------------------------------------------------------------------------
FUNCTION: buildPrompt()
DESCRIPTION: prints out the current location or path as the prompt
-------------------------------------------------------------------------------*/
/*
char  * buildPrompt()
{
	long length=0;
	size_t size;
	char *pthAry;
	char *pthPtr;
	char *final[100];
	int i=1;

	final[0]='{';
	length=1024;				// sets length to the largest possible path length
	size=length;
	pthPtr=getcwd(pthAry, size);	// obtains current path and stores result in 'pthPtr'			+
	
	return pthPtr;
}
 */
/* -----------------------------------------------------------------------------
FUNCTION: isBuild()
DESCRIPTION:
-------------------------------------------------------------------------------*/
int isBuiltInCommand( char * cmd )
{
  	if( strncmp(cmd, "exit", strlen( "exit" ) ) == 0 )
	{
		return EXIT;
  	}
	if( strncmp(cmd, "help", strlen( "help" ) ) == 0 )
	{
		printf("List of built-in commands:\n");
		printf("-jobs: provides numbered list of processes executing in background\n");
		printf("-cd: changes working directory to specified one; Syntax: cd directoryPath\n");
		printf("-history: prints numbered list of recent commands\n");
		printf("-kill: kills process; Syntax: kill %num ('num' being the number provided from 'jobs' command)\n");
		printf("-help: lists commands, their syntax, and their funtion\n");
		printf("-exit: terminates the program\n\n");

		return HELP;
  	}
	if( strncmp(cmd, "cd", strlen( "cd" ) ) == 0 )
	{
		//how to do this?
	}

  return NO_SUCH_BUILTIN;
}
/* -----------------------------------------------------------------------------
FUNCTION: handle_sigchld()
DESCRIPTION:
-------------------------------------------------------------------------------*/
void handle_sigchld( int s )
{
	signal( SIGCHLD, handle_sigchld );
    /* execute non-blocking waitpid, loop because we may only receive
     * a single signal if multiple processes exit around the same time.
     */
    while( waitpid(0, NULL, WNOHANG) > 0) ;
}

/* -----------------------------------------------------------------------------
FUNCTION: main()
DESCRIPTION:
-------------------------------------------------------------------------------*/
int main( int argc, char **argv )
{
  int childPid;
  char * cmdLine;
  parseInfo *info; 		// info stores all the information returned by parser.
  struct commandType *com; 	// com stores command name and Arg list for one command.

  fprintf( stdout, "This is the SHELL version 0.2\n" ) ;


  while(1)
  {
    	// insert your code here
	signal( SIGCHLD, handle_sigchld );

	/*
	print prompt
	*/

	long length=0;
	size_t size;
	char *pthAry;
	char *pthPtr;

	length=1024;			// sets length to the largest possible path length
	size=length;
	pthPtr=getcwd(NULL, size);	// obtains current path and stores result in 'pthPtr'			+
	printf("{");
	printf(pthPtr);
	printf("} ");

	/*
	Read input from user
	*/
    	cmdLine = readline(NULL);
    	if( cmdLine == NULL ) 
	{
      		fprintf(stderr, "Unable to read command\n");
      		continue;
    	}

    	// insert your code about history and !x !-x here

    	// calls the parser
    	info = parse( cmdLine );
        if( info == NULL )
	{
      		free(cmdLine);
      		continue;
    	}


    	// prints the info struct
    	print_info( info );

    	//com contains the info. of the command before the first "|"
    	com = &info->CommArray[0];	
    	if( (com == NULL)  || (com->command == NULL)) 
    	{
      		free_info(info);
      		free(cmdLine);
      		continue;
    	}

    	//com->command tells the command name of com
    	if( isBuiltInCommand( com->command ) == EXIT )
	{
      		exit(1);
    	}
	else if(isBuiltInCommand( com->command ) == HELP )
	{
		//
	}
	else
	{
		childPid=fork();
		if(childPid == 0)
		{
			if (execvp(com->command, com->VarList) < 0) //execute command, wait for child
			{     
              	 printf("\n**PROCESS EXECUTION FAILED**\n");  //if error, print message
			 exit(1);
          		}
		
		}
		else
		{
			//if is background
			//if is background w/ job....
			//record in list of background jobs
			
			waitpid(-1, NULL, WUNTRACED );
			//waitpid(*childPid);
		}
	}


  //insert your code here / commands etc.



  free_info(info);

  free(cmdLine);

  }/* while(1) */



}

Try "cd..", to get back to the next higher level directory (parent). After the cd, if you don't use the two dots, you should specify the directory name you want to change to.

Try "dir", instead of "ls".

What OS are you using?

Edited 5 Years Ago by Adak: n/a

Try "cd..", to get back to the next higher level directory (parent). After the cd, if you don't use the two dots, you should specify the directory name you want to change to.

Try "dir", instead of "ls".

What OS are you using?

I'm running this on a linux server. I know to use 'cd ..' to go up to the next level, but when I try and use the command in my shell I remain in the same directory. Just an fyi i am terrible at programming, at C in particular

The segfault is due to the % at line 61. Escape it as %%num.
To change directory, use chdir().

Thank you! For chdir() do i need to get the original path and the concatenate the requested directory onto the original?

This article has been dead for over six months. Start a new discussion instead.