bharath muppa
bharath muppa

Reputation: 1079

wait(NULL) function is not working and parent process is running before child always

I have a problem with the following code. It is like a manual shell program implementation using C on a Unix platform. If the user enters a command, it should execute and return corresponding result. If the user enters '&' at end then the parent process need not wait for child process to complete.

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <signal.h>
#include <stdlib.h>
#include <string.h>

#define HISTORY_LIMIT 20
#define BUFFER_LIMIT 100
#define MAX_WORDS 50

int count = 0;
char history[HISTORY_LIMIT][BUFFER_LIMIT];

int tokenize(char *str, char **args, int *bRun)
{
    int i, argc = 0;
    char *token;
    if (count == HISTORY_LIMIT)
    {
        // alignHistory();
    }
    // strcpy(history[count],str);
    count++;
    token = strtok(str, " \t\n");
    for (i = 0; token != NULL; i++)
    {
        args[i] = token;
        token = strtok(NULL, " \t\n");
        argc++;
    }

    for (i = 0; i < argc; i++)
    {
        if (strcmp(args[i], "&") == 0)
        {
            *bRun = 1;
            args[i] = NULL;
        }
    }

    return argc;
} // end of tokenize function

void handleSignal(int sign)
{
    if (sign == SIGINT)
    {
        // getHistory();
    }
}  // end of handlesignal

int main(void)
{
    char *args[MAX_WORDS];
    char buffer[BUFFER_LIMIT];
    pid_t pid;
    int argc;
    int bgRun = 0;
    if (signal(SIGINT, handleSignal) == SIG_ERR)
    {
        printf("can't handle ctrl-c");
        return 0;
    }
    while (1)
    {
        bgRun = 0;
        memset(args, 0, MAX_WORDS);
        printf("osh>");
        fgets(buffer, BUFFER_LIMIT, stdin);
        argc = tokenize(buffer, args, &bgRun);
        if (argc == 0)
            continue;

        if (strcmp(args[0], "exit") == 0)
            break;
        if (strcmp(args[0], "history") == 0)
            getHistory();
        // else if(strcmp(args[0],"hello")==0)printf("Hi There, How are you ?\n");
        else
        {
            pid = fork();

            if (pid == 0)
            {
                execvp(args[0], args);
                return 0;
            }
            else
            {
                if (bgRun == 0)
                    wait(NULL);
            }
        }
    }
}

Output is:

osh>whoami
root
osh>whoami &
osh>root
whoami
osh>root

But the required result should be like this (if & is used in command)

osh>whoami
root
osh>whoami &
osh>root
whoami
root    
osh>

So I have used bgRun int variable and assigned 1 if command has 1 but that was not working. I think it is problem with wait(NULL). Please save me from this demon.

Upvotes: 1

Views: 2065

Answers (1)

Ben Voigt
Ben Voigt

Reputation: 283733

You aren't saying which child process to wait for, so the third command (which should not be backgrounded) is considered to complete when the second command exits.

oops.

You need to handle SIGCHLD and reap background processes when they terminate, and also check that the exited process is the one you're currently running "foreground", and not a background job completing. waitpid() allows you to wait for a specific process.

Upvotes: 2

Related Questions