LinuxQuestions.org
Latest LQ Deal: Latest LQ Deals
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 05-30-2007, 02:57 AM   #1
Ayman.mashal
LQ Newbie
 
Registered: May 2005
Posts: 21

Rep: Reputation: 15
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");

}
 
Old 05-30-2007, 06:23 PM   #2
wjevans_7d1@yahoo.co
Member
 
Registered: Jun 2006
Location: Mariposa
Distribution: Slackware 9.1
Posts: 938

Rep: Reputation: 31
Of course the program is supposed to "freeze" until you press <Enter>. Function fgets() gets a whole line (usually) from the keyboard, and doesn't return control to your program until you press the <Enter> key.

As far as the segmentation fault goes, I recommend using gdb.
 
Old 05-31-2007, 12:11 AM   #3
Ayman.mashal
LQ Newbie
 
Registered: May 2005
Posts: 21

Original Poster
Rep: Reputation: 15
its freezing after entering a command and hit enter

for example if i enter
smash:>ls & <enter>

the command run and give the output and i get a message that the command exits with status 0
but then it freeze and if i hit a key i get the segmentaion fault.

so its not related to the fgets
 
Old 05-31-2007, 12:54 AM   #4
sibtay
Member
 
Registered: Aug 2004
Location: U.S
Distribution: Ubuntu
Posts: 145

Rep: Reputation: 15
Quote:
Originally Posted by Ayman.mashal
its freezing after entering a command and hit enter

for example if i enter
smash:>ls & <enter>

the command run and give the output and i get a message that the command exits with status 0
but then it freeze and if i hit a key i get the segmentaion fault.

so its not related to the fgets
Note that you are invoking the fgets function in a loop. If you look at your forkProcess function, it will not return in the child process scenario, however for the parent code it WILL return. Consequently fgets would get invoked again, and the parent program would once again await user input.
 
Old 05-31-2007, 03:56 AM   #5
Ayman.mashal
LQ Newbie
 
Registered: May 2005
Posts: 21

Original Poster
Rep: Reputation: 15
but that what i need the program should accept the user commands until its enter the exit command
 
Old 05-31-2007, 08:40 AM   #6
sibtay
Member
 
Registered: Aug 2004
Location: U.S
Distribution: Ubuntu
Posts: 145

Rep: Reputation: 15
Quote:
Originally Posted by Ayman.mashal
but that what i need the program should accept the user commands until its enter the exit command
Have you tried entering anything except Enter?
 
Old 06-03-2007, 01:49 AM   #7
Ayman.mashal
LQ Newbie
 
Registered: May 2005
Posts: 21

Original Poster
Rep: Reputation: 15
why after its finishing executing the command in background state its returns waiting for the user input without printing the smash:> prompt ???
 
Old 06-04-2007, 08:06 AM   #8
wjevans_7d1@yahoo.co
Member
 
Registered: Jun 2006
Location: Mariposa
Distribution: Slackware 9.1
Posts: 938

Rep: Reputation: 31
I'm confused as to what you experience, and I may also not be clear on what you expect.

It's a good thing that you posted the program itself. That's a start. Now, could you please use the program script to run your program and demonstrate its misbehavior? Then exit out of script and post the content of file typescript to this thread? That way we'll get a clear picture of what's happening when you run the program.
 
  


Reply

Tags
fgets, fork, linux



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
MySmartCI - The Simple and Small command interpreter MaaSTaaR General 0 07-25-2006 08:47 PM
"Bad Interpreter -- command not found" when I run ./configure on Ubuntu -- Hoary Hedg GeoRanger Linux - Newbie 5 03-27-2006 01:52 AM
Command Line Interpreter prady Linux - Newbie 1 02-19-2006 09:58 PM
taming python's interpreter 'help()' command southsibling Programming 7 06-04-2005 06:58 PM
scheme interpreter w/ command-line editing nazdrowie Programming 1 12-03-2004 08:20 AM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 02:07 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration