I have an assignment I'm working on and I'm having difficulty finishing it. The idea is to write a program if.c that executes one program and if that succeeds it executes the second program. I'm supposed to suppress the standard output of the first program and unsupress standard output for the second. I'm getting the error message on multiple tests. For instance: "./if echo no then echo yes" returns "echo:write error: Bad file descriptor". I've tried finding what I'm doing wrong online but no luck.
Here's my code:
#include <fcntl.h>
#include <sys/wait.h>
#include <stdio.h>
#include "tlpi_hdr.h"
int main(int argc, char *argv[])
{
if(argc < 4){
fprintf(stderr,"Incorrect number of arguments.\n");
exit(EXIT_FAILURE);
}
int thenArg = 0;
char then[4];
strcpy(then,"then");
for(int x=1; x<argc; x++){
if(strncmp(argv[x], then, 4) == 0) thenArg = x;
}
if(thenArg == 0){
fprintf(stderr,"No 'then' argument found.\n");
exit(EXIT_FAILURE);
}
int save_out = dup(STDOUT_FILENO);
if(save_out == -1){
fprintf(stderr,"Error in dup(STDOUT_FILENO)\n");
exit(EXIT_FAILURE);
}
int devNull = open("/dev/null",0);
if(devNull == -1){
fprintf(stderr,"Error in open('/dev/null',0)\n");
exit(EXIT_FAILURE);
}
int dup2Result = dup2(devNull, STDOUT_FILENO);
if(dup2Result == -1) {
fprintf(stderr,"Error in dup2(devNull, STDOUT_FILENO)\n");
exit(EXIT_FAILURE);
}
int program1argLocation = 1;
int program2argLocation = thenArg + 1;
int program1argCount = thenArg-1;
int program2argCount = argc-(program2argLocation);
char *program1args[program1argCount+1];
char *program2args[program2argCount+1];
for(int i=0; i<program1argCount; i++){
program1args[i]=argv[program1argLocation + i];
}
program1args[program1argCount] = NULL;
for(int i=0; i<program2argCount; i++){
program2args[i]=argv[program2argLocation + i];
}
program2args[program2argCount] = NULL;
pid_t pid = fork();
int child_status;
switch (pid) {
case -1:
fprintf(stderr,"Fork failed\n");
exit(EXIT_FAILURE);
case 0: //child
//child will run program 1
if(execvp(program1args[0],&program1args[0]) == -1){
fprintf(stderr,"Program 1 Failed.\n");
exit(EXIT_FAILURE);
}
default: //parent
//parent will run program2
pid = wait(&child_status);
if(WEXITSTATUS(child_status) == 0){
dup2(save_out, STDOUT_FILENO);
int prog2status = execvp(program2args[0],&program2args[0]);
if(prog2status == -1) {
fprintf(stderr,"Program 2 failed.\n");
exit(EXIT_FAILURE);
}
}
}
}
You can send output to /dev/null, by using command >/dev/null syntax.
If fd1 is not a valid file descriptor, dup2() fails and does not close fd2. If a file descriptor does not already exist, dup2() can be used to create one, a duplicate of fd1. F_CLOEXEC is cleared in fd2.
The dup2() function returns a descriptor with the value fildes2. The descriptor refers to the same file as fildes, and it will close the file that fildes2 was associated with. For more information about the processing which may occur when the file is closed, see close()--Close File or Socket Descriptor.
There will be a lot of files that a regular, non-root user cannot read. This will result in many “Permission denied” errors. These clutter the output and make it harder to spot the results that you're looking for. Since “Permission denied” errors are part of stderr, you can redirect them to “/dev/null.”
Your error is here:
int devNull = open("/dev/null",0);
To use devNull
as STDOUT_FILENO
, it must be opened for writing:
int devNull = open("/dev/null", O_WRONLY);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With