1 year ago
#363434
be-student
grep never terminates in this code (using fork, fd)
When I execute this function with "ls -a | grep test", it prints test testing testing.c correctly but it never terminates until I press ctrl+c to exit.
void executeCMD(char *cmdline)
{
char *argv[MAXARGS]; /* Argument list execve() */
char buf[MAXLINE]; /* Holds modified command line */
int bg; /* Should the job run in bg or fg? */
pid_t pid; /* Process id */
// char *testing[]={"ls",NULL};
// int *pipes[100]={NULL};
int fd[2];
strcpy(buf, cmdline); // copy buf=cmdline;
// parse line to MAXLINE * MAXARGS array ls -a | grep asdf => argv={"ls","-a","|","grep","asdf"}
bg = parseline(buf, argv);
bg = bg;
// we need to start working here
char **working = argv;
// Pipe is in the cmdline?
int isPipe = strchr(cmdline, '|') == NULL ? 0 : 1;
// stdout fd in child process;
if (isPipe)
{
if (pipe(fd) < 0)
{
printf("pipe error");
exit(1);
}
}
while (1)
{
// printf("while start\n");
char *real[MAXARGS] = {NULL}; // argv before pipe
if (working == NULL) // ignore empty line
break;
printf("execute command %s with argv %s\n", working[0], working[1]);
// ex) ls -a | greap a => real={"ls","-a"} parse Argv array that we need to do once
int index = parseargv(working, real); // index means pipe is here after working similar to isPipe after here
if (index == -1) // there is no pipe
working = NULL;
else // there is pipe
working = &(argv[index + 1]);
// parsing end
// fork to start process
if ((pid = fork()) == 0)
{
if (index != -1)
{
dup2(fd[1], 1);
close(fd[1]);
}
if (aftersecond)
{
dup2(fd[0], 0);
close(fd[0]);
}
// execute command. using execvp
CMD(real);
// background check
return;
}
else
{
/* Parent waits for foreground job to terminate */
int stat;
if (wait(&stat) < 0)
{
printf("waitpid error");
exit(1);
}
aftersecond = 1;
}
}
}
void CMD(char **real)
{
// builtin_command handles only exit
if (!builtin_command(real))
{
if (strcmp(real[0], "exit") == 0)
exit(0);
else if (strcmp(real[0], "cd") == 0)
changeDirectory(real);
// printf("execute command %s\n", real[0]);
if (execvp(real[0], real) < 0)
{ // ex) /bin/ls ls -al &
printf("%s: Command not found.\n", real[0]);
exit(0);
}
}
}
Everything except that works really well.
When I tried "echo hello | echo world", it works well, producing "world".
When it comes to use command that needs to accept data from before pipe it runs forever.
I think the problem is at closing pipe at the parent process but I can't find how.
c
pipe
fork
dup2
0 Answers
Your Answer