connecting alternative output stream to terminal

C

Christof Warlich

Hi,

besides stdout and stderr, I would like to connect a third
output stream to my terminal, as I want to be able to redirect
stdout, stderr and the third output stream separately. But the
following attempt:

#include <unistd.h>
#include <stdio.h>
int main(void) {
FILE *stdalt = fdopen(dup(fileno(stderr)), "w");
printf("Alternative file descriptor: %d\n", fileno(stdalt));
fprintf(stdout, "STDOUT\n");
fprintf(stderr, "STDERR\n");
fprintf(stdalt, "STDALT\n");
return 0;
}

does not do what I intended: When I run the program, I see that
the newly created descriptor has number 3 as expected:

$ ./a.out
Alternative file descriptor: 3
STDOUT
STDERR
STDALT

but when I redirect stderr, stdalt gets redirected as well:

../a.out 2>/dev/null
Alternative file descriptor: 3
STDOUT

But I'd like to get something like this:

$ ./a.out 2>/dev/null
Alternative file descriptor: 3
STDOUT
STDALT

$ ./a.out 3>/dev/null
Alternative file descriptor: 3
STDOUT
STDERR

Can anyone tell how to do this right?

Thanks,

Christof
 
F

Falcon Kirtaran

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Christof said:
Hi,

besides stdout and stderr, I would like to connect a third
output stream to my terminal, as I want to be able to redirect
stdout, stderr and the third output stream separately. But the
following attempt:

#include <unistd.h>
#include <stdio.h>
int main(void) {
FILE *stdalt = fdopen(dup(fileno(stderr)), "w");
printf("Alternative file descriptor: %d\n", fileno(stdalt));
fprintf(stdout, "STDOUT\n");
fprintf(stderr, "STDERR\n");
fprintf(stdalt, "STDALT\n");
return 0;
}

does not do what I intended: When I run the program, I see that
the newly created descriptor has number 3 as expected:

$ ./a.out
Alternative file descriptor: 3
STDOUT
STDERR
STDALT

but when I redirect stderr, stdalt gets redirected as well:

./a.out 2>/dev/null
Alternative file descriptor: 3
STDOUT

But I'd like to get something like this:

$ ./a.out 2>/dev/null
Alternative file descriptor: 3
STDOUT
STDALT

$ ./a.out 3>/dev/null
Alternative file descriptor: 3
STDOUT
STDERR

Can anyone tell how to do this right?

Thanks,

Christof

In POSIX, when file number 3 is redirected, it should be open when
main() is called. Thus, you should be able to try dup(3) and check the
return code (you can close() the file number dup() gave you if you
wish). If it failed, the redirect is not in use (and so you could set
your stdalt to standard output or dup() standard output or something
like that). It's a bit of a hack, though...

- --
- --Falcon Darkstar Kirtaran
- --
- --OpenPGP: (7902:4457) 9282:A431

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.9 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org

iQIcBAEBAgAGBQJJacl+AAoJEKmxP9YxEE4rUaYP/1ScJlNPLolm+uLW12nRTBrV
6jHYlZK3dJbMcs382RKiWS9hvE3wi4/VRsiPbuNIC0BblcI12sPHjN3D+Vv4rht8
Frefe4+yA/55xTfDqD0FsLsgLS2zhLO/X/iBEkfqItl+P/dc+vyooK9RZzFcl3uR
1WPtaFrpu44DlPhXSgKBpqR8/wQMuyCkf94Ly2xBkKtoYa7bE1ajuoPFOrn5egQg
Yn/DniNYDxbYHqgDHDt1yPUwI7sIa76LNouZwvDnFD8iw/2Q2ypE30gjGiK67REt
CCKzV6RvTiQ3Q2EDzf0nM6g9MKBhcliU8NGLBrE99/y9aLjCa7MThivw9P/IaT2d
Y7CmELNT7JpbR5AkXeX6bw8XBRA05mrmU7x1eVrnXYJGJnNy0QNvH8zeSft93wtK
Lmx0k5rby9Vbgbq1aSNyeXvemWdnjUaKesMxkVT0o6nYmtoza8+arifcmBCsUI+e
hEiV7H7qP3lsxgbAINE29+YG5VF929ChQY9SB5vWbTARJyH/8A4u+nQ5ZJaVv1Ag
jmJ9hD2Edv9RhybLgNgdEWqcYgx+XawomwrXUIK2m8eeEyouHAHJF0hdWS+ioF7D
BidKJaTwBwbZfeq+CE19ktWqL9CkFeu58OK0Q7+Xk6XFP2LCyRJR1Rm02UpakRkH
m19024R7XP+54J1Ik8nH
=jfrx
-----END PGP SIGNATURE-----
 
C

Christof Warlich

Falcon said:
In POSIX, when file number 3 is redirected, it should be open when
main() is called.
Thanks, yes, I just found that out meanwhile as well :).
Thus, you should be able to try dup(3) and check the
return code (you can close() the file number dup() gave you if you
wish). If it failed, the redirect is not in use (and so you could set
your stdalt to standard output or dup() standard output or something
like that). It's a bit of a hack, though...
Oh yes, seems to be ... But thanks for the advice, the following code
does the job:

#include <unistd.h>
#include <stdio.h>
int main(void) {
FILE *stdalt;
int tmp = dup(3);
if(tmp == -1) {
stdalt = fdopen(dup(2), "w");
stdalt = freopen("/dev/tty", "w", stdalt);
}
else {
close(tmp);
stdalt = fdopen(3, "w");
}
printf("Alternative file descriptor: %d\n", fileno(stdalt));
fprintf(stdout, "STDOUT\n");
fprintf(stderr, "STDERR\n");
fprintf(stdalt, "STDALT\n");
return 0;
}

$ ./a.out 1>xxx
STDERR
STDALT
$ ./a.out 2>xxx
Alternative file descriptor: 3
STDOUT
STDALT
$ ./a.out 3>xxx
Alternative file descriptor: 3
STDOUT
STDERR

I'd really like to know why I have to use freopen on stdalt with
/dev/tty though. Whithout it, I get

../a.out 2>xxx
Alternative file descriptor: 3
STDOUT

Everything else stays the same as above. Any ideas?

Thanks a lot,

Christof
 
R

Richard

Flash Gordon said:
You need to ask over in comp.unix.programmer as this is a Unix issue
rather than a C issue.

Actually it could be a C issue. Since he didn't include the header for
fdopen ....

You missed a good chance there.

In addition, since when was POSIX only Unix?

If you do not know enough about a subject it is better you do not
redirect people to the wrong place.

"Portable Operating System Interface"
 
F

Flash Gordon

Richard said:
Actually it could be a C issue. Since he didn't include the header for
fdopen ....

You missed a good chance there.

True. However I knew that someone else here would address any ossible C
issues that I missed.
In addition, since when was POSIX only Unix?

It isn't and I've used it else where. So?
If you do not know enough about a subject it is better you do not
redirect people to the wrong place.

"Portable Operating System Interface"

Ah, so you are claiming not to know that they discus POSIX on
comp.unix.programmer. I, on the other hand, know that they do. If you
don't know enough about what is acceptable on a group don't try claiming
it is the wrong place.
 
F

Falcon Kirtaran

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Christof said:
Thanks, yes, I just found that out meanwhile as well :).
Oh yes, seems to be ... But thanks for the advice, the following code
does the job:

#include <unistd.h>
#include <stdio.h>
int main(void) {
FILE *stdalt;
int tmp = dup(3);
if(tmp == -1) {
stdalt = fdopen(dup(2), "w");
stdalt = freopen("/dev/tty", "w", stdalt);
}
else {
close(tmp);
stdalt = fdopen(3, "w");
}
printf("Alternative file descriptor: %d\n", fileno(stdalt));
fprintf(stdout, "STDOUT\n");
fprintf(stderr, "STDERR\n");
fprintf(stdalt, "STDALT\n");
return 0;
}

$ ./a.out 1>xxx
STDERR
STDALT
$ ./a.out 2>xxx
Alternative file descriptor: 3
STDOUT
STDALT
$ ./a.out 3>xxx
Alternative file descriptor: 3
STDOUT
STDERR

I'd really like to know why I have to use freopen on stdalt with
/dev/tty though. Whithout it, I get

./a.out 2>xxx
Alternative file descriptor: 3
STDOUT

Everything else stays the same as above. Any ideas?

Thanks a lot,

Christof

If you fopen() on 2, but 2 is redirected, whatever you've fopen()ed will
correspond to the same file as 2 does. You could probably replace

stdalt = fdopen(dup(2), "w");
stdalt = freopen("/dev/tty", "w", stdalt);

with

stdalt = fopen("/dev/tty", "w");

- --
- --Falcon Darkstar Kirtaran
- --
- --OpenPGP: (7902:4457) 9282:A431

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.9 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org

iQIcBAEBAgAGBQJJai6YAAoJEKmxP9YxEE4rdNEP/2v8ftJ0Iy3eybMaFRLC1PAa
zCzDVKvsgM2O/oNa+MxFo11uiFXIqkcfVSyYWDuISF2QP7M9bfSIjEjLNygW7Xq4
WzLvfbHKsZ5px8dGHpQc43xk30+D1adSKyC9fO9COM9iAM9r7gquxucq5y/BIrc0
5LQHKeO26P/APov7HRwR3+N4O3WFm9YjBgNPqsW1pMhGq0tER/5mX1NWtzx09ysz
ycD2Kpm3CJYX/nBbWDtSSGz/K+qWmODmelb4Xr2pim12Ns9O2sDXnv7mSYGCyMTS
XB4xGKwU2o2jQrdUvyn3kYUAXUCNpkuENvBw5uLc6/6C5oFgUzP6GohE43wT8Nby
0i7bw7GGuQTEj4zTu9XT8ebgfzxZK29u6BoXdepZHUMz4zqsSJs/vHi2sGntNIfY
f6esA8wLWI2fu2lEV8CNG9VyaBS//RaUm1+I/9lScuRMaIhGsNlu+Rga/+3PAJzL
pL12CD8+XrBdfSFE0O57O1jiIXxjIYEr9erPubuYVi6XR5Vx/6eIonmJD82ZA2fy
H8geqF7z6eHjAg1JP9l/GfL4BLXhIIMhMaKiQE9N0g8WLnxRM9H//vk5vRKN6YIL
KwUDVVFuLKXwYwlLRb7Zm1dXSF6FxpYIzUVUfebB+wtU77Vkyf8lmQrmLzksdPrz
kqJQiKnPEgSq37FZrUM/
=74vs
-----END PGP SIGNATURE-----
 
C

Christof Warlich

Falcon said:
If you fopen() on 2, but 2 is redirected, whatever you've fopen()ed will
correspond to the same file as 2 does. You could probably replace

stdalt = fdopen(dup(2), "w");
stdalt = freopen("/dev/tty", "w", stdalt);

with

stdalt = fopen("/dev/tty", "w");

Yes, that works as well and is much easier to understand.
Again, many thanks for the advice.

Regards,

Christof
 
C

Christof Warlich

Flash said:
You need to ask over in comp.unix.programmer as this is a Unix issue
rather than a C issue.
You are right, this would probably have been the better place to ask.
But anyway, I'm quite happy with the advice I got from Falcon Kirtaran.

Regards,

Christof
 
F

Falcon Kirtaran

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Christof said:
Yes, that works as well and is much easier to understand.
Again, many thanks for the advice.

Regards,

Christof

Yay! Anytime.

- --
- --Falcon Darkstar Kirtaran
- --
- --OpenPGP: (7902:4457) 9282:A431

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.9 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org

iQIcBAEBAgAGBQJJamojAAoJEKmxP9YxEE4ri1YQAJg4984x2E11ccKHr6fY0AWC
zmOB950G1+yUo6FE4cZMkNI6dQh+Iad/71tAK7/yjY8m1HvP/eJNbCL801n3G6UB
cWhbBcNIBz9OnZi4eVXYbxVAIyPVZwybRlEXJBmSp3ZcNZYsV1zNCv0lpOHLYgyF
74mArPcl9ZDDcjyNk9H5CoeNmfXG2vxDy6QhP5X3qzraDzTkLdKgSv+lLuqfe5kh
aZKp7vqR4+uf3xt3YTgtyEFCluk8Xuaql8uvCkq0f/KcRJwW8n9BGaRcS3GP3zeu
V8ggWoOqhhpQwIE0nJvTqJgbtF3Hh/FOBOtamIWAP9O2FaJcbC/GzmT6LmVg1i87
fOkOux2cWQCKw0z1q0+AiWDM0EReA5mbLN8QXhMiEjVMz1941A6JY5BWlOf9NhwD
yTdmjw5nZNRYO/kCZTo6Ivus/fbFne1zmc8Cs3JsIdXgtXVIx83+BCPaDbA2Ey1V
LKfNzuQB77WOv+tzswQl/LEzvfRTtYpTZwlgb/guq/J+a26FPU2XhaggUodd+MJI
ozkL9UpGIlfj1BPpIy2lG+hhagYYoLv5LXpKdZ+WXhAnyNiZTax8h9E0DU76NNlL
hqyAPN769XUZ7/q5gSbgcphbKHlK9Uo6Opu8MpVQFmcxvSE6b/DK2soKjz5Fb7cm
kkLYk8zmc8OdBYo2sXDH
=N6/2
-----END PGP SIGNATURE-----
 
C

Christof Warlich

Han said:
You can make the test less clumsy through the use of dup2(). Here's
an idiom that many real-world C programmers use:

-----------------------------------------------------
#include <stdio.h>
#include <unistd.h>

int main(void)
{
if(dup2(3, 3) == -1) /* 3 invalid; EBADF? */
puts("not already open!");
else /* does nothing */
puts("already open!");

return 0;
}
-----------------------------------------------------

Yes, this makes things even more simple, as it avoids the need
for the close() call. So to sum up again, my code would the look
like this:

#include <unistd.h>
#include <stdio.h>
int main(void) {
FILE *stdalt;
if(dup2(3, 3) == -1) {
stdalt = fopen("/dev/tty", "w");
}
else {
stdalt = fdopen(3, "w");
}
printf("Alternative file descriptor: %d\n", fileno(stdalt));
fprintf(stdout, "STDOUT\n");
fprintf(stderr, "STDERR\n");
fprintf(stdalt, "STDALT\n");
return 0;
}

Thanks for this further improvement as well,

Christof
 
C

CBFalconer

Christof said:
.... snip ...

Yes, this makes things even more simple, as it avoids the need
for the close() call. So to sum up again, my code would the look
like this:

#include <unistd.h>
#include <stdio.h>
int main(void) {

Please don't encourage Hans off-topic postings. unistd.h is not a
standard C header, and thus is off-topic on c.l.c. We attempt to
limit things to the portable C language, that is not OS dependant,
but does depend on the C standard. comp.unix.programmer would
probably be a suitable newsgroup.
 
A

Antoninus Twink

We attempt to limit things [snip usual blather]

Ah, the royal "we" again.

This is not a moderated group, and each person can make his or her own
decision about what is appropriate to post here.
 
R

Richard

Antoninus Twink said:
We attempt to limit things [snip usual blather]

Ah, the royal "we" again.

This is not a moderated group, and each person can make his or her own
decision about what is appropriate to post here.

Also I have a header called "unistd.h" which contains

#define H_FLAG 0


Why is this off topic?
 
C

CBFalconer

William said:
It is not. However, I would agree with Chuck that the majority
of this thread is off topic, as the primary focus of the thread
is dup, dup2, and shell redirections. Those topics have little
to do with C as a language.

He referred to <unistd.h>, which is not a standard C header.
"unistd.h" is in the users domain, and is another matter.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,770
Messages
2,569,584
Members
45,075
Latest member
MakersCBDBloodSupport

Latest Threads

Top