1 year ago

#363434

test-img

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

Accepted video resources