Reputation: 1079
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
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