manipulate fd underlying stream

comp.lang.c FAQ 12.33 says:
>Q: How can I redirect stdin or stdout to a file from within a program?
>A: Use freopen. If you're calling a function f() which writes to stdout,
>and you want to send its output to a file, and you don't have the option
>of rewriting f, you can use a sequence like:
>
> freopen(file, "w", stdout);
> f();
>

Hmmm ...

>See, however, question 12.34.
>Question 12.34
>Q: Once I've used freopen, how can I get the original stdout (or stdin) back?
>A: There isn't a good way. If you need to switch back, the best solution is not
>to have used freopen in the first place.

Why not leave the stream unchanged, and manipulate its underlying file
descriptor:

a) fflush() the stdio stream
b) dup the stdio fd to an unused fd, saving a copy of it.
c) close the stdio fd
d) use open() to get an fd for the desired file, and compare the fd
number to STDIN_FILENO or STDOUT_FILENO, as appropriate, to be sure
it matches; if not, use dup2() to copy it to the stdio fd
e) when done, use dup2() to copy the saved fd back to the stdio fd

Advertisements

On 07/31/10 12:56 PM, John Kelly wrote:
>
> comp.lang.c FAQ 12.33 says:
>
>> Q: How can I redirect stdin or stdout to a file from within a program?
>
>> A: Use freopen. If you're calling a function f() which writes to stdout,
>> and you want to send its output to a file, and you don't have the option
>> of rewriting f, you can use a sequence like:
>>
>> freopen(file, "w", stdout);
>> f();
>>
>
> Hmmm ...
>
>
>> See, however, question 12.34.
>
>> Question 12.34
>
>> Q: Once I've used freopen, how can I get the original stdout (or stdin) back?
>
>> A: There isn't a good way. If you need to switch back, the best solution is not
>> to have used freopen in the first place.
>
>
> Why not leave the stream unchanged, and manipulate its underlying file
> descriptor:

Because there isn't a standard way of doing that.
> a) fflush() the stdio stream
> b) dup the stdio fd to an unused fd, saving a copy of it.

Advertisements

On 7/30/2010 8:56 PM, John Kelly wrote:
>
> comp.lang.c FAQ 12.33 says:
>
>> Q: How can I redirect stdin or stdout to a file from within a program?
>
>> A: Use freopen. If you're calling a function f() which writes to stdout,
>> and you want to send its output to a file, and you don't have the option
>> of rewriting f, you can use a sequence like:
>>
>> freopen(file, "w", stdout);
>> f();
>
> Hmmm ...
>
>> See, however, question 12.34.
>
>> Question 12.34
>
>> Q: Once I've used freopen, how can I get the original stdout (or stdin) back?
>
>> A: There isn't a good way. If you need to switch back, the best solution is not
>> to have used freopen in the first place.
>
>
> Why not leave the stream unchanged, and manipulate its underlying file
> descriptor:

"Close?" What's that?
> d) use open() to get an fd for the desired file, and compare the fd
> number to STDIN_FILENO or STDOUT_FILENO, as appropriate, to be sure

What's "open?" And what are these strange, all-caps things
that sort of look like they might be macros?
> it matches; if not, use dup2() to copy it to the stdio fd
> e) when done, use dup2() to copy the saved fd back to the stdio fd

"Dup2?" Hunh?

In short, you're assuming (1) a specific kind of host system,
and (2) a whole lot about the way C streams are implemented on that
system. In CS-speak, you are writing to the implementation rather
than to the interface.

I recall dealing with some code that tried to mix-'n-match C's
streams with POSIX primitives: It would fread() from a file until it
came to something it knew would be a blob, then it did an lseek() to
the fseek() position to synchronize the two current offsets, then
it slurped the blob with read() "because it's more efficient," then
did an fseek() to the lseek() spot to re-synchronize. Clever, clever,
clever -- and utterly hopeless on VMS, the platform I was porting to.
Dirtbag code with a dirtbag outcome.

On Fri, 30 Jul 2010 21:20:03 -0400, Eric Sosman
<> wrote:
> In short, you're assuming (1) a specific kind of host system,
>and (2) a whole lot about the way C streams are implemented on that
>system. In CS-speak, you are writing to the implementation rather
>than to the interface.

I think of a dominant implementation as a virtual interface.

> I recall dealing with some code that tried to mix-'n-match C's
>streams with POSIX primitives: It would fread() from a file until it
>came to something it knew would be a blob, then it did an lseek() to
>the fseek() position to synchronize the two current offsets, then
>it slurped the blob with read() "because it's more efficient," then
>did an fseek() to the lseek() spot to re-synchronize. Clever, clever,
>clever -- and utterly hopeless on VMS, the platform I was porting to.
>Dirtbag code with a dirtbag outcome.

On 07/31/10 01:40 PM, John Kelly wrote:
> On Fri, 30 Jul 2010 21:20:03 -0400, Eric Sosman
> <> wrote:
>
>> In short, you're assuming (1) a specific kind of host system,
>> and (2) a whole lot about the way C streams are implemented on that
>> system. In CS-speak, you are writing to the implementation rather
>> than to the interface.
>
> I think of a dominant implementation as a virtual interface.

On 2010-07-31, John Kelly <> wrote:
>>See, however, question 12.34.
>
>>Question 12.34
>
>>Q: Once I've used freopen, how can I get the original stdout (or stdin) back?
>
>>A: There isn't a good way. If you need to switch back, the best solution is not
>>to have used freopen in the first place.
>
> Why not leave the stream unchanged, and manipulate its underlying file
> descriptor:
>
> a) fflush() the stdio stream
> b) dup the stdio fd to an unused fd, saving a copy of it.
> c) close the stdio fd
> d) use open() to get an fd for the desired file, and compare the fd
> number to STDIN_FILENO or STDOUT_FILENO, as appropriate, to be sure
> it matches; if not, use dup2() to copy it to the stdio fd
> e) when done, use dup2() to copy the saved fd back to the stdio fd

As others have pointed out, this is POSIX specific and you will probably
get better advice from comp.unix.programming.

Looking at the man page for dup on Linux, I don't see anything that
explicitly prevents you from copying the file descriptor and copying it
back; but, that doesn't mean there might not be implementation bugs on some
platform that make it an unwise choice to use.

Personally, I don't understand why you would bother going through all of
that trouble instead of just leaving stdin alone and using fprinf()
explicitly. Then there is never any confusion about where stdin points at
any given time.

On Sat, 31 Jul 2010 02:54:08 +0000 (UTC), Tim Harig <>
wrote:
>On 2010-07-31, John Kelly <> wrote:
>> Why not leave the stream unchanged, and manipulate its underlying file
>> descriptor:
>>
>> a) fflush() the stdio stream
>> b) dup the stdio fd to an unused fd, saving a copy of it.
>> c) close the stdio fd
>> d) use open() to get an fd for the desired file, and compare the fd
>> number to STDIN_FILENO or STDOUT_FILENO, as appropriate, to be sure
>> it matches; if not, use dup2() to copy it to the stdio fd
>> e) when done, use dup2() to copy the saved fd back to the stdio fd
>
>As others have pointed out, this is POSIX specific and you will probably
>get better advice from comp.unix.programming.
>
>Looking at the man page for dup on Linux, I don't see anything that
>explicitly prevents you from copying the file descriptor and copying it
>back; but, that doesn't mean there might not be implementation bugs on some
>platform that make it an unwise choice to use.

I've not experienced any problems on Linux.

>Personally, I don't understand why you would bother going through all of
>that trouble instead of just leaving stdin alone and using fprinf()
>explicitly. Then there is never any confusion about where stdin points at
>any given time.

Maybe I have generic code that uses stdin/stdout, and the caller wants
to manipulate fds and point them somewhere else.

On Sat, 31 Jul 2010 05:06:01 +0100, Richard Heathfield
<> wrote:
>Tim Harig wrote:
>> On 2010-07-31, John Kelly <> wrote:
><snip>
>
>>> e) when done, use dup2() to copy the saved fd back to the stdio fd
>>
>> As others have pointed out, this is POSIX specific and you will probably
>> get better advice from comp.unix.programming.
>
>Just a note for the files - it's actually comp.unix.programmer that he
>needs. AFAIK, comp.unix.programming is a myth.

Too ways to look at this ...
1) Windows NT and Windows 2000 O/S did support a POSIX subsystem.
Windows XP and later do not.
2) The more popular C compilers for Windows still support POSIX to
some degree or the other.
The VC++ compiler* still supports POSIX, but it is considered
"deprecated". Details can be found in the help files.

[*as of VC 2008, not sure about the 2010 release.]

Microsoft O/S and compilers only support POSIX 1003.1 which was
earlier than even current versions available at the time, and thus
limited in POSIX services, as well as denied access to many Windows
services.

So the answer to your question is technically 'yes' for some versions
of Windows and very simple applications, but generally 'no' for use as
a migration or cross-platform tool.

On Jul 31, 1:05 am, ralph <> wrote:
> 1) Windows NT and Windows 2000 O/S did support a POSIX subsystem.
> Windows XP and later do not.
There is a computer at my office running XP with the MS-bought
Interix. Even later Windows versions have POSIX subsystems. POSIX is
thus supported, but not built-in, perhaps.

Step 1: Turning on the SUA features
The Subsystem for Unix-based Applications (SUA) is part of the Windows
OS distribution. Installing the subsystem requires no additional CD or
download. It's a component/feature of the base distribution of Windows
Server 2008, Windows Server 2008/R2, Windows Server 2003 R2, Windows 7
and Windows Vista Ultimate & Enterprise. All you need to do is turn the
feature on.

>So the answer to your question is technically 'yes' for some versions
>of Windows and very simple applications, but generally 'no' for use as
>a migration or cross-platform tool.

Step 2: Installing the Utilities and SDK for Unix-based Applications
Once the SUA "feature" is turned on, the next step is to download the
Utilities and SDK. From the Start menu, under All Programs then under
Subsystem for Unix-based Applications you can find the link to download
the Utilities and SDK from the Microsoft website. Alternatively, you
can visit the download site directly: Installing and Using Utilities and
SDK for Unix-based Applications. This page is important as it outlines
the difference between a standard (default) installation and a custom
install.

Note: A common pitfall is to just accept the default installation. The
default install does not include the GNU utilities and GNU SDK.

Note: We recommend for a Windows systems that the installation happen as
the Local Administrator (not as a user in the Administrators Group).

On 2010-07-31, John Kelly <> wrote:
> Do you want to shoo away Linux C programmers from c.l.c?

Not likely -- my day job is about 98% Linux these days. But I generally
don't talk about the POSIX-specific stuff here, because that's not
related to C. With a few exceptions (and admittedly, I actually
work with those exceptions a fair bit!), the POSIX stuff I do is
language-agnostic, and you could ask the same questions, and get the
same answers, when talking about perl or Ruby programs that were
working with the POSIX interfaces.

I think the big thing people are pursuing in trying to direct
people to other newsgroups is to maximize discussion quality and
value. If you ask POSIX questions here, there are two likely
problems:

1. The discussion will be at best totally uninteresting to a large
number of readers. This makes the group less valuable to them and
might cause them to leave -- but there are some very serious C experts
who happen to mostly not be using Unix.

2. The discussion will pick up a lot of things said by people who
aren't that interested in or good at POSIX, and who as a result don't
really know what they're talking about -- but the real POSIX experts
are mostly not here, or not here with intent to talk about POSIX.

So if instead those questions are asked in a group more specific
to the environment they apply in, everyone gets a better newsgroup
experience, and the questions get better answers -- which are seen
by people more interested in those answers.

Long story short, it seems that, as long as there's enough traffic
to justify multiple newsgroups, everyone seems to win when those
newsgroups keep to their topics, and separation of topics is observed.

(And keep in mind, I'm writing this from the perspective of someone
who has written some code which does stuff like "intercept underlying
file operations and manipulate the values apparently returned by
the library." I know more about what happens in several common C
libraries when you start messing around with file descriptors than
anyone but a library maintainer is ever likely to have reason to
know; I just don't think it's topical here.)

On Sat, 31 Jul 2010 13:10:24 +0000 (UTC),
(Kenny McCormack) wrote:
>In article <>,
>John Kelly <> wrote a bunch of good stuff, as he
>usually does:
>>Do you want to shoo away Linux C programmers from c.l.c?
>Obviously, yes. Their whole goal is to shoo everyone away, so that they
>can do their collective jerk-off over the Almight C Standards document.

I'm not sure to what extent Mr. Sosman seeks to edify and
to what extent he seeks to amuse, but I don't think I'm alone
in saying that programming for a non-Unix system has no
conceivable purpose in the ivory tower. Non-Unix programmers have
some other purpose: avarice for filthy lucre, writing viruses,
etc.

In a newsgroup on restaurants we wouldn't be condemned if we
assumed OP is not some villain serving rat poison to customers.
Why then, in a C programming forum, do we ask why OP isn't some
sado-masochist programming a system without open() and close()?

But, no, they won't stay there.
>>I assumed you understood that by now.
>
>Code is more fun than standards.

Not to these jerkoffs.

And this is probably as good a time as any for me to re-iterate a point
I've made many times before. These people are actually almost all old
Unix hands and they are perfectly comfortable with Unix-isms (like
read() and write()). Normally, there'd be no problem discussing Unix-y
things here, but the problem is that when, in the early 90s, the Unix
guys saw the world going MS and Windows (sorry, guys, but it is true),
they went apeshit and they realized that their beloved newsgroups (and
specifically CLC) were about to go all "lpParm" on them and they
couldn't stand that.

So, they concocoted this "What's in the standard and only what's in the
standard" nonsense and made a pact to stand by it. Part of that pact
was that they had to pretend not to understand or know anything about
the Unix-y stuff (or any other so-called "system specific" stuff). That
was the price paid to ward off the evils of "lpParm".

(And yes, just in case it isn't clear to the numskulls, I'm using
"lpParm" as a metaphor for all the Windows-y stuff. The stuff that
drives these guys to madness...)

--
Just for a change of pace, this sig is *not* an obscure reference to
comp.lang.c...

On Sat, 31 Jul 2010 15:02:31 +0000 (UTC),
(Kenny McCormack) wrote:
>In article <>,
>John Kelly <> wrote:
>
>>Code is more fun than standards.
>
>Not to these jerkoffs.
>
>And this is probably as good a time as any for me to re-iterate a point
>I've made many times before. These people are actually almost all old
>Unix hands and they are perfectly comfortable with Unix-isms (like
>read() and write()). Normally, there'd be no problem discussing Unix-y
>things here, but the problem is that when, in the early 90s, the Unix
>guys saw the world going MS and Windows (sorry, guys, but it is true),
>they went apeshit

Share This Page

Welcome to The Coding Forums!

Welcome to the Coding Forums, the place to chat about anything related to programming and coding languages.

Please join our friendly community by clicking the button below - it only takes a few seconds and is totally free. You'll be able to ask questions about coding or chat with the community and help others.
Sign up now!