c - Implementing pipelining in a Linux shell -
i'm trying develop shell in linux operating systems project. 1 of requirements support pipelining (where calling ls -l|less passes output of first command second). i'm trying use c pipe() , dup2() commands redirection doesn't seem happening (less complains didn't receive filename). can identify i'm going wrong/how might go fixing that?
edit: i'm thinking need use either freopen or fdopen somewhere since i'm not using read() or write()... correct?
(i've heard others who've done project using freopen() way solve problem; if think better, tips going direction appreciated.)
here's execute_external() function, executes commands not built-in shell. various commands in pipe (e.g. [ls -l] , [less]) stored in commands[] array.
void execute_external() { int numcommands = 1; char **commands; commands = malloc(sizeof(char *)); if(strstr(raw_command, "|") != null) { numcommands = separate_pipeline_commands(commands); } else { commands[0] = malloc(strlen(raw_command) * sizeof(char)); commands[0] = raw_command; } int i; int pipefd[2]; (i = 0; < numcommands; i++) { char **parameters_array = malloc(strlen(commands[i]) * sizeof(char *)); int num_params; num_params = str_to_str_array(commands[i], parameters_array); if (numcommands > 1 && > 0 && != numcommands - 1) { if (pipe(pipefd) == -1) { printf("could not open pipe."); } } pid_t pid = fork(); pmesg(2, "process forked. id = %i. \n", pid); int status; if (fork < 0) { fprintf(to_write_to, "could not fork process complete external command.\n"); exit(exit_failure); } if (pid == 0) // child process { if (numcommands > 1) { close(pipefd[1]); } // close unused write end of pipe if (i == 0) // may pipelining , first process { dup2(1, pipefd[1]); // set source descriptor (for next iteration of loop) proc's stdout } if (i !=0 && (i != numcommands-1)) // pipelining , not first or last process { dup2(pipefd[0], 0); // set stdin of process source of previous process } if (execvp(parameters_array[0], parameters_array) < 0) { fprintf(to_write_to, "could not execute external command. errno: %i.\n", errno); exit(exit_failure); } else { pmesg(2, "executed child process.\n");} } else { if (numcommands > 1) { close(pipefd[0]); } // close unused read end of pipe if (backgrounding == 0) { while(wait(&status) != pid); }// wait child finish executing } free(parameters_array); } free(commands); }
it looks there couple of bugs going on in code.
first, dup2's in child. in order connect pipe need dup2 stdout of parent write end pipefd[1] of pipe. hook read end stdin.
also looks on of dup2's backwards dup2 fildes duplicated fildes2. when reassign stdin want dup2(in, 0) , stdout want dup2(out, 1).
so stripped down piece of piping code going like:
int pipefd[2]; pipe(pipefd); pid_t pid = fork(); if (pid == 0) //the child { dup2(pipefd[0], 0); } else { dup2(pipefd[1], 1); }
Comments
Post a Comment