Find the answer to your Linux question:
Results 1 to 2 of 2
Hi, i am trying to build a simple shell program that allow me to run commands in foreground and background modes . in case of foreground i think its work ...
  1. #1
    Just Joined!
    Join Date
    May 2007
    Posts
    1

    simple command interpreter

    Hi,

    i am trying to build a simple shell program that allow me to run commands in foreground and background modes .

    in case of foreground i think its work fine but when i run a command i a background mode by adding & at the end of the command the program freezes until i press enter then i get the segmentaion fault error .

    kindly take a look at this code an let me know where is the mistake .

    thanks

    Code:
    // simple shell
    // executes one command a time without arguments and flags
    // not supports pipelines 
    // not supports input/output redirection 
    
    #include	<sys/types.h>
    #include	<sys/wait.h>
    #include        <unistd.h>
    #include        <stdio.h>
    #include        <string.h>
    #include        <stdlib.h>
    
    #define MAXLINE 2048
    enum {FOREGROUND,BACKGROUND};
    static volatile sig_atomic_t sigflag; /* set nonzero by sig handler */
    static sigset_t newmask, oldmask, zeromask;
    
    void  executeCommand(char *cmd);
    void forkProcess(char **,int cnt);
    void wait_child(void);
    void collect_child();
    void sig_handler();
    
    int main(void)
    {
    	char	buf[MAXLINE];
    
    	printf("smash:>");	/* print prompt (printf requires %% to print %) */
    	while (fgets(buf, MAXLINE, stdin)!=NULL) 
    	{
    		buf[strlen(buf) - 1] = 0;	/* replace newline with null */
    		
    		executeCommand(buf);
    		printf("smash:>");
    		
    	}
    	exit(0);
    }
    
    void  executeCommand(char *cmd)
    {
    	char **argsList=NULL;
    	int argsCnt=0;
    	
    	char *ptr;
    	char *tmpCmd=strdup(cmd);
    	
    	ptr=strtok(tmpCmd," 	");
    	
    	while(ptr!=NULL)
    	{
    		argsList=(char**)realloc(argsList,sizeof(char**)*(++argsCnt)+1);
    		argsList[argsCnt-1]=strdup(ptr); 
    		ptr=strtok(NULL," 	");
    	}
    	
    	argsList[argsCnt]=NULL;
    	
    	if(strcmp(argsList[0],"exit")==0)
    	{
    		if(argsCnt==1)
    		{
    			printf("Bye\n");
    			exit(0);
    		}
    		else
    			printf("error : exit does'nt accept arguments.\n")	;	
    	}
    	
    	else if(strcmp(argsList[0],"cd")==0)
    	{
    		if(argsCnt==2)
    			chdir(argsList[1]);
    		else
    			printf("error : invalid number of arguments for cd.\n");	
    	}
    	
    	else 
    		forkProcess(argsList,argsCnt);
    }
    
    void forkProcess(char **argsList,int cnt)
    {
    	pid_t	pid;
    	int runStyle;
    	
    	
    	if(strcmp(argsList[cnt-1],"&")==0)
    	{
    		runStyle=BACKGROUND ;
    		argsList[cnt-1]=NULL;
    	}
    	else
    		runStyle=FOREGROUND;
    	
    		
    	if ( (pid = fork()) < 0)
    		fprintf(stderr,"fork error");
    
    	if (pid == 0) 
    	{		
    		if (execvp(argsList[0], argsList)< 0)
    		  fprintf(stderr,"execl error");
    	}
    	else //parent
    	{		
    		if(runStyle==FOREGROUND)  
    		{
    			printf("waitttt\n");
    			wait_child();
    		}
    		else
    		{
    			if (signal(SIGCHLD, sig_handler) == SIG_ERR)        
    				printf("signal(SIGUSR1) error");    
    		}
    	}
    }
    
    void sig_handler()
    {
    	pid_t	pid;
    	int	status;
    	
    	printf("sig handler\n");
    	sigflag = 1;
    	
    	if ((pid=wait(&status)) < 0)	
    	{
          		perror("Wait failed\n");
          		exit(3);
        	}
        	else
    	{
          		if (WIFEXITED(status))
            		printf ("Pid %d terminated with status %d\n", pid, WEXITSTATUS(status));
          		else if (WIFSIGNALED(status))
            		printf ("Pid %d terminated by signal %d\n", pid, WTERMSIG(status));
        	}	
    }
    
    void wait_child(void){   
    
    	if (signal(SIGCHLD, sig_handler) == SIG_ERR)        
    		printf("signal(SIGUSR1) error");    
    		
    	sigemptyset(&zeromask);    
    	sigemptyset(&newmask);    
    	sigaddset(&newmask, SIGCHLD);    
      
    	
    	if (sigprocmask(SIG_BLOCK, &newmask, &oldmask) < 0)        
    		printf("SIG_BLOCK error");
     
    		
    	while (sigflag == 0)        
    		sigsuspend(&zeromask);  /* and wait for child */    
    	
    	sigflag = 0;    /*     * Reset signal mask to original value.     */    
    
    	if (sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0)        
    		printf("SIG_SETMASK error");
    
    }

  2. #2
    Trusted Penguin Cabhan's Avatar
    Join Date
    Jan 2005
    Location
    Seattle, WA, USA
    Posts
    3,230
    I can't find the exact error, but I advise you to throw in some debug statements to ensure that background processes are being properly detected, and that the '&' is actually being removed. Because I suspect that the probably lies there.
    DISTRO=Arch
    Registered Linux User #388732

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
...