Thread: Doing my own shell, how to properly execute processes in background/foreground?

Threaded View

Previous Post Previous Post   Next Post Next Post
  1. #1
    Registered User
    Join Date
    Mar 2006
    Posts
    158

    Doing my own shell, how to properly execute processes in background/foreground?

    Hi,

    I have this stuff to do for university that's basically a simple custom shell and I'm currently having some difficulties.

    The basic functionality is already done, I read a command from the stdin and execute it with execvp(). After that, with wait(NULL), I wait for that process to finish before returning to the shell. I now can properly run processes in the foreground one at a time. Time to implement background processes...

    The first step is to check if the "&" is the last argument, if it is, run the process in the background. To do that I simply check for the "&" and set a background variable to true or false accordingly. Then, if background == false do not wait for the process to finish and return to the shell.

    So far so good... Now my problem...

    When running processes in the background like this, it's likely they end up "zombies" right? I need to take care of them and for that, I believe I need to handle the SIGCHLD signal... At least I need to use the signal() function to handle something because that's part of the exercise. And that's what I did as you'll see in the code below...

    Now my questions:

    1) Is this code ok or should I do it differently? I ask this because if I run a process in the foreground, there will be two waits, the first one (wait(NULL)) right after executing the command and a second one (waitpid(-1, &status, WNOHANG)) right after the process terminates or is killed/stopped/whatever.

    I don't think that this should happen. First because it doesn't make sense to call wait two times for a foreground process, the first wait will turn the second one redundant. Second because part of my exercise is that I need to print the status changes of the processes but there's no reason to do this for foreground processes. So basically, I need to call the waitpid() in childSignalHandler() only for background processes.

    How should I solve this then?

    2) As I said in my first question, I need to print the status changes of the processes running in the background. Any changes how to handle this? My first guess is that I simply need to print the value of status after waitpid() in childSignalHandler(). Is that it?

    That's almost all I want to know, I still have a couple of more things that I want to accomplish but they are not part of the exercise for university, they are just some things I want to do to improve my custom shell a little bit, I'll talk about them later...

    I was just going to forget about the code lol, here it is:
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <unistd.h>
    #include <wait.h>
    #include <signal.h>
    #include <sys/types.h>
    
    #include "data.h"
    
    
    void childSignalHandler(int signum) {
    	int status;
    	pid_t pid;
    	
    	pid = waitpid(-1, &status, WNOHANG);
    }
    
    int main(int argc, char **argv) {
    	char bBuffer[BUFSIZ], *pArgs[10], *aPtr = NULL, *sPtr;
    	bool background;
    	ssize_t rBytes;
    	int aCount;
    	pid_t pid;
    	
    	signal(SIGCHLD, childSignalHandler);
    	
    	while(1) {
    		write(1, "\e[1;31mmyBash \e[1;32m# \e[0m", 27);
    		rBytes = read(0, bBuffer, BUFSIZ-1);
    		
    		if(rBytes == -1) {
    			perror("read");
    			exit(1);
    		}
    		
    		bBuffer[rBytes-1] = '\0';
    		
    		if(!strcasecmp(bBuffer, "exit")) {
    			exit(0);
    		}
    		
    		sPtr = bBuffer;
    		aCount = 0;
    		
    		do {
    			aPtr = strsep(&sPtr, " ");
    			pArgs[aCount++] = aPtr;
    		} while(aPtr);
    
    		background = FALSE;
    		
    		if(!strcmp(pArgs[aCount-2], "&")) {
    			pArgs[aCount-2] = NULL;
    			background = TRUE;
    		}
    		
    		if(strlen(pArgs[0]) > 1) {
    			pid = fork();
    			
    			if(pid == -1) {
    				perror("fork");
    				exit(1);
    			}
    
    			if(pid == 0) {
    				execvp(pArgs[0], pArgs);
    				exit(0);
    			}
    			
    			if(!background) {
    				wait(NULL);
    			}
    		}
    	}
    
    	return 0;
    }
    Last edited by Nazgulled; 05-23-2009 at 01:52 PM.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Develop. Shell , Backgrounds processes
    By Barassa in forum C Programming
    Replies: 0
    Last Post: 10-22-2008, 02:42 PM
  2. binary tree of processes
    By gregulator in forum C Programming
    Replies: 1
    Last Post: 02-28-2005, 12:59 AM
  3. Program to execute shell commands.
    By LiquidLithium in forum C++ Programming
    Replies: 6
    Last Post: 09-01-2004, 12:22 PM
  4. Shell execute... but piping
    By nickname_changed in forum C++ Programming
    Replies: 2
    Last Post: 05-21-2003, 07:39 AM
  5. Problems with Shell Execute
    By golfinguy4 in forum Windows Programming
    Replies: 3
    Last Post: 12-03-2002, 12:37 PM