A double pipe is used to execute the command “ls -ltr | grep 3340 | wc –l”. Howe
ID: 3681977 • Letter: A
Question
A double pipe is used to execute the command “ls -ltr | grep 3340 | wc –l”. However, our program is static: it means that code need to be modified and rebuilt if we want to change the commands to execute. In this part, we make our program dynamic instead of static. The following requirements should be implemented:
1- Source file will be called Dynamic.cpp, executable called dynamic.
2- The piped commands to execute need to be passed as arguments to dynamic,and not hardcoded.
3- The max number of arguments should not exceed 5, and not less than 2 (otherwise print an error message)
4- Each argument should be a unix/linux command with its parameters.
The first argument will be the first to execute, followed by the second one, etc.. We will assume that only valid commands can be used, for simplicity Example: the followings are possible command executions
The Program is
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
int main(int argc, char **argv) {
int status;
char *cat_args[] = {"ls", "-ltr", NULL};
char *grep_args[] = {"grep", "3340", NULL};
char *wc_args[] = {"wc", "-l", NULL};
// create two pipe to send the output of "ls" process to "grep" process and to "wc" process
int pipe_A[2];
int pipe_B[2];
pipe(pipe_A);
pipe(pipe_B);
pid_t pid_A, pid_B;
//first child
if( !(pid_A = fork()) ) {
close(pipe_A[0]);
dup2(pipe_A[1], 1); /* redirect standard output to pipe_A write end */
close(pipe_A[1]);
execvp(*cat_args, cat_args);
exit(0);
}
//second child
else if( !(pid_B = fork()) ) {
close(pipe_A[1]);
dup2(pipe_A[0], 0); /* redirect standard input to pipe_A read end */
close(pipe_A[0]);
close(pipe_B[0]);
dup2(pipe_B[1], 1); /* redirect standard output to pipe_B write end */
close(pipe_B[1]);
execvp(*grep_args, grep_args);
}
//parent
else {
close(pipe_A[1]);
close(pipe_A[0]);
close(pipe_B[1]);
dup2(pipe_B[0], 0); /* redirect standard input to pipe_B read end */
close(pipe_B[0]);
execvp(*wc_args, wc_args);
}
close(pipe_B[1]);
close(pipe_B[0]);
return(0);
}
Program execution Shell equivalent dynamic “ls –ltr” “grep 3340” ls –ltr |grep 3340 dynamic “ls –ltr” “grep 3340” “grep hi” wc -l ls –ltr |grep 3340| grep hi| wc-l dynamic “ls –ltr” errorExplanation / Answer
#include <libgen.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/wait.h>
#include <unistd.h>
void read_all(int src, int dst) {
char buf[BUFSIZ];
ssize_t bytes_read, bytes_written;
while ((bytes_read = read(src, buf, BUFSIZ)) > 0) {
bytes_written = 0;
while (bytes_written < bytes_read)
bytes_written += write(dst,
buf + bytes_written,
bytes_read - bytes_written);
}
}
int main(int argc, char** argv) {
if (argc < 2) {
printf("usage: %s <program> [<arg> ...] ", basename(argv[0]));
return EXIT_FAILURE;
}
// create pipes for standard input, output, and error
int stdin_pipe[2];
int stdout_pipe[2];
int stderr_pipe[2];
pipe(stdin_pipe);
pipe(stdout_pipe);
pipe(stderr_pipe);
if (fork() == 0) {
// child process
// close write end of stdin and read ends of stdout and stderr
close(stdin_pipe[1]);
close(stdout_pipe[0]);
close(stderr_pipe[0]);
// change child's stdin, stdout, and stderr to use pipes
dup2(stdin_pipe[0], STDIN_FILENO);
dup2(stdout_pipe[1], STDOUT_FILENO);
dup2(stderr_pipe[1], STDERR_FILENO);
// exec the given program
if (execvp(argv[1], argv+1) == -1) {
perror("failed to start subprocess");
return EXIT_FAILURE;
}
}
// parent process
// close read end of stdin and write ends of stdout and stderr
close(stdin_pipe[0]);
close(stdout_pipe[1]);
close(stderr_pipe[1]);
// pass input to the child process
read_all(STDIN_FILENO, stdin_pipe[1]);
close(stdin_pipe[1]);
// wait for child to finish
wait(NULL);
// read child's stdout and stderr
puts(" child's stdout:");
fflush(stdout);
read_all(stdout_pipe[0], STDOUT_FILENO);
close(stdout_pipe[0]);
puts(" child's stderr:");
fflush(stdout);
read_all(stderr_pipe[0], STDOUT_FILENO);
close(stderr_pipe[0]);
return EXIT_SUCCESS;
}
Related Questions
drjack9650@gmail.com
Navigate
Integrity-first tutoring: explanations and feedback only — we do not complete graded work. Learn more.