View Full Version : Redirect stdout using dup
spank
04-02-2008, 05:51 AM
int main(int argc, char *argv[])
{
int f = open("test.txt", O_CREAT|O_RDWR, 0666);
int out=dup(1);
if(f==-1)
perror("open()");
dup2(f, 1);
printf("Hello world\n");
printf("%d\n",close(f));
close(1);
printf("test\n");
return 0;
}
I want to redirect stdout to a file ... and after I print something I want to go back to print to the usual screen output. I can't get back to printing on the screen
Please help!
matsp
04-02-2008, 06:14 AM
You probably want to restore the original stdout after you've dup'd it to be f.
--
Mats
spank
04-02-2008, 06:34 AM
yap!
brewbuck
04-02-2008, 09:52 AM
Also, using dup2() is usually redundant. These two are equivalent:
fd = open(...);
dup2(fd, 1);
And:
fd = open(...);
close(1);
dup(fd);
On UNIX, the next new file descriptor is always the last one closed, unless nothing was closed, in which case it picks a free one. Thus, close(1) ensures that the following call to dup(fd) will duplicate it to file descriptor 1.
The first example is one line of code shorter, but the second is generally preferable, because of this:
If newfd was open, any errors that would have been reported at close()
time, are lost. A careful programmer will not use dup2 without closing
newfd first.
And because you are about to close() anyway, there's no point in calling dup2() since dup() ensures you'll get the correct descriptor. However, in this case, you are not closing the original stdout, but duping it over to some new descriptor, so the problem doesn't show up here. It can show up elsewhere though.
spank
04-02-2008, 10:43 AM
#include <fcntl.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
int pid, status;
int pid1, pid2;
switch(pid=fork())
{
case 0:
{
close(1);dup(0);
pid1 = fork();
if(pid1==0)
{
execl ("/bin/ls", "ls", "-1", (char *)0);
exit(-1);
}
else
{
wait(&status);
}
pid2 = fork();
if(pid2==0)
{
execl ("/bin/cat", "cat", (char *)0);
exit(-1);
}
else
{
wait(&status);
}
break;
}
default:
{
wait(&status);
}
}
return 0;
}
I want this to have the effect of ls -1 | cat so I redirect the stdout to stdin. Where do I go wrong? Please help!
brewbuck
04-02-2008, 10:46 AM
You aren't calling pipe() anywhere. Without creating a pipe, how do you expect data to get from one process to another?
CornedBee
04-02-2008, 11:11 AM
On UNIX, the next new file descriptor is always the last one closed
Not true. You get the lowest available file descriptor.
#include <stdio.h>
#include <unistd.h>
int main(void)
{
int sout = dup(1);
close(1);
close(2);
int sin2 = dup(0);
dup2(sout, 1);
printf("dup(stdin): %d\n", sin2);
return 0;
}
Prints:
dup(stdin): 1
spank
04-02-2008, 11:14 AM
#include <fcntl.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
int pid, status;
int pid1, pid2;
int filedes[2];
pipe(filedes);
switch(pid=fork())
{
case 0:
{
//close(1);dup(0);
pid1 = fork();
if(pid1==0)
{
dup2(filedes[1], 1);
// close(filedes[0]);
execl ("/bin/ls", "ls", "-lh", (char *)0);
exit(-1);
}
else
{
wait(&status);
}
pid2 = fork();
if(pid2==0)
{
dup2(filedes[0], 0);
// close(filedes[1]);
execl ("/bin/cat", "cat", (char *)0);
exit(-1);
}
else
{
wait(&status);
}
break;
}
default:
{
wait(&status);
}
}
close(filedes[0]);
close(filedes[1]);
return 0;
}
ok... now 2 questions. why doesn't this program exits ? it remains in cat (i belive). And second why is there the need to close the other side of the pipe ?
CornedBee
04-02-2008, 11:16 AM
exec displaces the current process.
brewbuck
04-02-2008, 11:26 AM
Not true. You get the lowest available file descriptor.
Which is just the last one closed, if you only close one at a time :) The problem was close(1) immediately followed by close(2).
CornedBee
04-02-2008, 11:30 AM
Problem? I was just demonstrating that my definition is universally true, while yours, despite the word "always", is just a special case (the last descriptor closed is actually the lowest free one).
brewbuck
04-02-2008, 11:32 AM
Problem? I was just demonstrating that my definition is universally true, while yours, despite the word "always", is just a special case (the last descriptor closed is actually the lowest free one).
Yeah, I was being facetious. At any rate, the close/dup trick is pervasive.
CornedBee
04-02-2008, 11:35 AM
So it is, but luckily only for the low descriptors stdin, stdout and stderr. Anything above that and it becomes unreliable.
idelovski
04-03-2008, 05:16 PM
> And second why is there the need to close the other side of the pipe ?
Parent doesn't need those descriptors - two of the children need it and unless you close them,
the process that reads would wait forever and I think that is why cat blocks in your case. It never
receives eof or something like that.
vBulletin® v3.7.0, Copyright ©2000-2009, Jelsoft Enterprises Ltd.