I got the piping of several commands working. Now Id like to execute this with received arguments (*argv[]) and not hard coded like here.
Ived tried using the rest of the execve family but no progress. Ive been thinking to put everything (argv) in an array of pointers and adding NULL at the end of where each pointer points, then iterate through it.
Passed argument ( , included): echo "test" , wc , cowsay
int main(int argc, char *argv[]) {
char *echo[] = {"echo", "test", NULL};
char *rev[] = {"rev", NULL};
char *wc[] = {"wc", NULL};
char **cmd[] = {echo, wc, rev, NULL};
loop_pipe(cmd);
return (0);
}
void loop_pipe(char ***cmd) {
int p[2];
pid_t pid;
int fd_in = 0;
while (*cmd != NULL) {
pipe(p);
if ((pid = fork()) == -1) {
exit(EXIT_FAILURE);
} else if (pid == 0) {
dup2(fd_in, 0); //change the input according to the old one
if (*(cmd + 1) != NULL)
dup2(p[1], 1);
close(p[0]);
execvp((*cmd)[0], *cmd);
exit(EXIT_FAILURE);
} else {
wait(NULL);
close(p[1]);
fd_in = p[0]; //save the input for the next command
cmd++;
}
}
}
You did all the multiprocessing part. You only need to do some array shuffling, to convert array of strings to array of arrays of strings.
If you don’t mind iterating the array two times, you can do like the following:
You can refine this using special properties of
argv, e.g. thatargv[argc] == NULL, or thatargv, as well as the argument strings themselves, is actually writable.