Quote:
Originally posted by itsme86
The "split" happens in the reverse direction. Instead of having one file descriptor that points to two places it makes it so you have two file descriptors that point to one place.
|
Hmm, it seems like you're right. Thats what I thought, but wasn't sure.
From dup(2):
Code:
SYNOPSIS
#include <unistd.h>
int dup(int oldfd);
int dup2(int oldfd, int newfd);
DESCRIPTION
dup and dup2 create a copy of the file descriptor oldfd.
After successful return of dup or dup2, the old and new descriptors may be used interchangeably. They
share locks, file position pointers and flags; for example, if the file position is modified by using
lseek on one of the descriptors, the position is also changed for the other.
The two descriptors do not share the close-on-exec flag, however.
dup uses the lowest-numbered unused descriptor for the new descriptor.
dup2 makes newfd be the copy of oldfd, closing newfd first if necessary.
I wrote this code to test what I had previously thought about dup2...Basically what it tries/tried to do was read a filename argument, open that file, and try to write data to stdout AND the file. It didn't work
I *can* interchange using STDOUT_FILENO and the new fd, the way you mentioned. This is what I thought dup and dup2 did, this kind of proved it...
Code:
/* test writing to multiple file descriptors at once */
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
#define FILE_FLAGS O_CREAT|O_WRONLY|O_APPEND
#define FILE_MODE S_IWRITE|S_IREAD
int main(int argc, char* argv[])
{
char buf[80];
ssize_t bytes_read;
int fd;
if(argc != 2)
{
fprintf(stderr, "usage: ./dup-test <filename>\n");
exit(1);
}
if((fd = open(argv[1], FILE_FLAGS, FILE_MODE)) == -1)
{
perror("dup-test: error opening file");
exit(1);
}
if(dup2(STDOUT_FILENO, fd) == -1)
{
perror("dup-test: error duplicating file descriptor");
exit(1);
}
while((bytes_read = read(STDIN_FILENO, buf, 80)) != 0)
{
if(bytes_read < 0)
{
perror("dup-test: error reading data");
exit(1);
}
if(write(STDOUT_FILENO, buf, bytes_read) < 0)
{
perror("dup-test: error writing data");
exit(1);
}
}
return 0;
}
So is there any way to cleanly do what I'm attempting? I want to write something in my code that looks like this:
Code:
/* setup program for logging all output to output file
AND stdout at the same time */
int main(int argc, char * argv[])
{
/* process options... */
switch(option) {
/* set up program logging and continue on as normal */
case 'l':
logoutput(output_log);
break;
/* run the rest of the program */
}
/* run the rest of the program */
}
Sending output to tee isn't the best idea for this program, because output will come from all over the place, so I'd have to test if we're logging output every time I write to stdout (which happens alot). Also, output to a file is optional, its far from the default behaviour.
I'm kind of stumped on a clean way to handle this problem.