Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Why does write() to stdin work?

107 views
Skip to first unread message

ishwar...@gmail.com

unread,
Apr 23, 2013, 9:59:59 AM4/23/13
to
Tried the following code under gcc and it writes to stdin??

#include <stdio.h>
#include <stdlib.h>

int main()
{
int k;
for(k= 0; k < 4; k++)
write(k, "Hello world!\n", 13);
}

Any poiners?
-ishwar

Eric Sosman

unread,
Apr 23, 2013, 10:33:58 AM4/23/13
to
comp.unix.programmer.

--
Eric Sosman
eso...@comcast-dot-net.invalid

osmium

unread,
Apr 23, 2013, 11:52:52 AM4/23/13
to
There is an "fwrite()" in C but no "write()". so you must have stumbled
across a gcc extension. There is probably a command line way to force gcc
to do ANSI C if you don't like this result.


James Kuyper

unread,
Apr 23, 2013, 11:58:43 AM4/23/13
to
write() is not a C standard library function, so the reason why it did
or did not work depends upon the library that provides write(), so your
question should be directed to a forum appropriate to that library. If,
for instance, it's the Unix standard library function, then you should
try comp.unix.programmer.

How do you know that it worked? As far as I can tell, your program makes
no attempt to determine whether or not the call to write() was
successful. For example, if this is the Unix function, your code doesn't
check the return value from write(), which should be 13 for a successful
call, nor does it check the value of errno, which should be 0 after a
successful call, unless it was already set to a non-zero value before
the call.


ishwar...@gmail.com

unread,
Apr 23, 2013, 12:39:48 PM4/23/13
to
write() a is system call Unix systems, does not return failure and I will try comp.unix.programmer group.

Thanks for the effort.

-ishwar

Keith Thompson

unread,
Apr 23, 2013, 1:05:53 PM4/23/13
to
write() isn't a gcc extension; it's defined by POSIX.

--
Keith Thompson (The_Other_Keith) ks...@mib.org <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"

Nobody

unread,
Apr 23, 2013, 9:14:36 PM4/23/13
to
On Tue, 23 Apr 2013 09:39:48 -0700, ishwar.rattan wrote:

> write() a is system call Unix systems, does not return failure

On success, it returns the number of bytes written. On failure, it returns
-1 and sets errno to indicate the nature of the failure. In your example,
it will return -1 and set errno to EBADF.

Edward A. Falk

unread,
Apr 23, 2013, 9:38:47 PM4/23/13
to
It doesn't work.

You just got very lucky the one time you tried it, probably because you
left stdin connected to your terminal which is also an output device
*and* you happened to be linked to a runtime library that let you get
away with it. Under different conditions, your code would probably fail.

You have encountered undefined behavior. From my quotes file:

What undefined means is:

undefined.
Do not rely on the results.
You have gone outside the domain of the function
You have broken the programming model of the C language.
Here there be dragons!
The implementors can do anything they want.
Be careful.
Use a different algorithm.
This is non-portable.
Don't do it.


Here's one of the rules about being a good programmer: Don't
just try things until they work. Read the documentation and
write code that adheres to the specifications. Just because
it worked today doesn't mean it will work tomorrow.

--
-Ed Falk, fa...@despams.r.us.com
http://thespamdiaries.blogspot.com/

glen herrmannsfeldt

unread,
Apr 23, 2013, 10:08:54 PM4/23/13
to
There is no rule against writing to file descriptor zero.

The convention for inetd programs is that they read and write
of fd 0.

If fd 0 is a terminal, writing should be fine.

-- glen

William Ahern

unread,
Apr 23, 2013, 10:11:35 PM4/23/13
to
I'm curious: are you obstinate, or genuinely naive? Please don't take that
the wrong way. If your intention was to impress upon the OP a distinction
between C and POSIX, I applaud your methods. ;)

If you're genuinely unaware of POSIX write(), or the overwhelming
likelihood the OP was speaking in that context, I'm similarly intrigued.

Ian Collins

unread,
Apr 23, 2013, 10:55:26 PM4/23/13
to
ishwar...@gmail.com wrote:
> Tried the following code under gcc and it writes to stdin??
>
> #include <stdio.h>
> #include <stdlib.h>
>
> int main()
> {
> int k;
> for(k= 0; k < 4; k++)
> write(k, "Hello world!\n", 13);
> }

Just one thing to add: check the return value of write (always good
practice) and you will see where your code fails.

--
Ian Collins

Keith Thompson

unread,
Apr 23, 2013, 11:58:45 PM4/23/13
to
How is the behavior undefined?

If you mean that the C standard doesn't define the behavior of
write(), that's true but hardly useful; the POSIX standard does.

Somewhat off-topic:

As far as I can tell from a quick reading of the POSIX specification,
a call to write() can either succeed or fail. I'd naively expect
it to fail on an attempt to write to a file descriptor not opened
for writing, but I don't see anything that says it's *required*
to fail. And even if it were, failure is not undefined behavior;
write() would simply return -1 and set errno.

(I certainly think that writing to stdin is a silly thing to do.)

Barry Schwarz

unread,
Apr 24, 2013, 1:14:37 AM4/24/13
to
On Tue, 23 Apr 2013 20:58:45 -0700, Keith Thompson <ks...@mib.org>
wrote:

>fa...@rahul.net (Edward A. Falk) writes:
>> It doesn't work.
>>
>> You just got very lucky the one time you tried it, probably because you
>> left stdin connected to your terminal which is also an output device
>> *and* you happened to be linked to a runtime library that let you get
>> away with it. Under different conditions, your code would probably fail.
>>
>> You have encountered undefined behavior. From my quotes file:
>>
>> What undefined means is:
>>
>> undefined.
>> Do not rely on the results.
>> You have gone outside the domain of the function
>> You have broken the programming model of the C language.
>> Here there be dragons!
>> The implementors can do anything they want.
>> Be careful.
>> Use a different algorithm.
>> This is non-portable.
>> Don't do it.
>>
>>
>> Here's one of the rules about being a good programmer: Don't
>> just try things until they work. Read the documentation and
>> write code that adheres to the specifications. Just because
>> it worked today doesn't mean it will work tomorrow.
>
>How is the behavior undefined?

If he is indeed using the posix function, then the third argument
needs to be a size_t, not an int. But there is no prototype in scope
for write so the compiler does not know to convert the 13 to a size_t.
size_t need not have the same size as int and unsigned int..

And the second argument passes muster only because void* and char* are
guaranteed to have the same representation and alignment. I don't
think the absence of the const qualifier on this argument changes
anything one way or the other.

--
Remove del for email

James Kuyper

unread,
Apr 24, 2013, 8:02:13 AM4/24/13
to
#define _POSIX_C_SOURCE 1
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main(void)
{
int k;
printf("stdin:%d stdout:%d stderr:%d\n",
fileno(stdin), fileno(stdout), fileno(stderr));
for(k= 0; k < 4; k++)
{
errno = 0;
int bytes = write(k, "Hello world!\n", 13);
printf("k:%d bytes:%d errno:%d\n", k, bytes, errno);
}
return 0;
}


Output:
stdin:0 stdout:1 stderr:2
Hello world!
k:0 bytes:13 errno:0
Hello world!
k:1 bytes:13 errno:0
Hello world!
k:2 bytes:13 errno:0
k:3 bytes:-1 errno:9
--
James Kuyper

Edward A. Falk

unread,
Apr 24, 2013, 10:04:31 AM4/24/13
to
In article <lnfvyge...@nuthaus.mib.org>,
Keith Thompson <ks...@mib.org> wrote:
>
>As far as I can tell from a quick reading of the POSIX specification,
>a call to write() can either succeed or fail. I'd naively expect
>it to fail on an attempt to write to a file descriptor not opened
>for writing, but I don't see anything that says it's *required*
>to fail.

That's the undefined part. OP went outside the spec and got
lucky. That won't always happen.

Keith Thompson

unread,
Apr 24, 2013, 11:38:00 AM4/24/13
to
fa...@rahul.net (Edward A. Falk) writes:
> In article <lnfvyge...@nuthaus.mib.org>,
> Keith Thompson <ks...@mib.org> wrote:
>>
>>As far as I can tell from a quick reading of the POSIX specification,
>>a call to write() can either succeed or fail. I'd naively expect
>>it to fail on an attempt to write to a file descriptor not opened
>>for writing, but I don't see anything that says it's *required*
>>to fail.
>
> That's the undefined part. OP went outside the spec and got
> lucky. That won't always happen.

My interpretation of the POSIX spec is that write() either succeeds
or fails. If you give it a bad pointer as the second argument,
or a size for the third argument that exceeds the available data
pointed to by the second argument, the behavior is undefined.
But if you pass 0 (standard input) as the first argument, that's
a valid file descriptor argument -- just one you might not have
*permission* to write to.

Quoting the POSIX spec
(http://pubs.opengroup.org/onlinepubs/9699919799/toc.htm):

These functions shall fail if:
...
[EBADF]
The fildes argument is not a valid file descriptor open for
writing.

That looks pretty well-defined to me.

The implementation *might* be non-conforming because it permits
writes to standard input, but I don't see any permission for the
implementation to throw up its hands and unleash the nasal demons.
I'd have to look further to determine whether 0 may be considered
to be "open for writing"; searching the spec for "0" is unlikely
to be useful.

Keith Thompson

unread,
Apr 24, 2013, 11:40:55 AM4/24/13
to
Barry Schwarz <schw...@dqel.com> writes:
> On Tue, 23 Apr 2013 20:58:45 -0700, Keith Thompson <ks...@mib.org>
> wrote:
[...]
>>How is the behavior undefined?
>
> If he is indeed using the posix function, then the third argument
> needs to be a size_t, not an int. But there is no prototype in scope
> for write so the compiler does not know to convert the 13 to a size_t.
> size_t need not have the same size as int and unsigned int..
>
> And the second argument passes muster only because void* and char* are
> guaranteed to have the same representation and alignment. I don't
> think the absence of the const qualifier on this argument changes
> anything one way or the other.

There is no *declaration* in scope, prototype or not. The call is a
constraint violation; there is no implication in the standard that it
will even *attempt* to convert the int argument to size_t.

So yes, given the missing #include directive the program's behavior is
undefined *if* the compiler doesn't simply reject it.

(But that's not what Ed Falk was referring to.)

James Kuyper

unread,
Apr 24, 2013, 1:08:47 PM4/24/13
to
On 04/24/2013 11:38 AM, Keith Thompson wrote:
...
> My interpretation of the POSIX spec is that write() either succeeds
> or fails. If you give it a bad pointer as the second argument,
> or a size for the third argument that exceeds the available data
> pointed to by the second argument, the behavior is undefined.
> But if you pass 0 (standard input) as the first argument, that's
> a valid file descriptor argument -- just one you might not have
> *permission* to write to.
>
> Quoting the POSIX spec
> (http://pubs.opengroup.org/onlinepubs/9699919799/toc.htm):
>
> These functions shall fail if:
> ...
> [EBADF]
> The fildes argument is not a valid file descriptor open for
> writing.
>
> That looks pretty well-defined to me.
>
> The implementation *might* be non-conforming because it permits
> writes to standard input, but I don't see any permission for the
> implementation to throw up its hands and unleash the nasal demons.
> I'd have to look further to determine whether 0 may be considered
> to be "open for writing"; searching the spec for "0" is unlikely
> to be useful.

I searched for stdin, and found:

"At program start-up, three streams shall be predefined and need not be
opened explicitly: standard input (for reading conventional input),
standard output (for writing conventional output), and standard error
(for writing diagnostic output)."
Note that it does not say "opened for reading only" or "opened for
writing only". Oddly enough, it does specify:

"The stderr stream is expected to be open for reading and writing." I've
never even thought about the possibility of reading from stderr - I
wonder what the use case was that prompted that change (it was
introduced in Issue 6)? If stderr is seekable, I suppose one part of a
process could read an error message produced by a different part of the
process?


glen herrmannsfeldt

unread,
Apr 24, 2013, 2:15:20 PM4/24/13
to
James Kuyper <james...@verizon.net> wrote:

(snip)

> I searched for stdin, and found:

> "At program start-up, three streams shall be predefined and need not be
> opened explicitly: standard input (for reading conventional input),
> standard output (for writing conventional output), and standard error
> (for writing diagnostic output)."
> Note that it does not say "opened for reading only" or "opened for
> writing only". Oddly enough, it does specify:

> "The stderr stream is expected to be open for reading and writing." I've
> never even thought about the possibility of reading from stderr - I
> wonder what the use case was that prompted that change (it was
> introduced in Issue 6)? If stderr is seekable, I suppose one part of a
> process could read an error message produced by a different part of the
> process?

(snip)

I haven't thought about this one for a while.

Consider programs that might have both stdin and stdout redirected,
then write a question (do you really want to ...?) to stderr, and then
wait for a reply. Where do you read the reply from?

-- glen

Edward A. Falk

unread,
Apr 24, 2013, 2:18:00 PM4/24/13
to
In article <76pen813iuj4fufq7...@4ax.com>,
Barry Schwarz <schw...@dqel.com> wrote:
>
>If he is indeed using the posix function, then the third argument
>needs to be a size_t, not an int. But there is no prototype in scope
>for write so the compiler does not know to convert the 13 to a size_t.
>size_t need not have the same size as int and unsigned int..

Ahh, I totally missed that part.

This brings me back to what I said about following the spec
and not just trying things until it works.

The write(2) man page says to #include <unistd.h> in order to
call this function. If you don't do this, then you're doing
it wrong.

I've been programming C for a living for a very long time, and
I still read the man pages before I call a function, just to
be sure.

Ken Brody

unread,
Apr 25, 2013, 10:36:38 AM4/25/13
to
On 4/23/2013 9:59 AM, ishwar...@gmail.com wrote:
My guess is that, in your environment, stdin and stdout, while being
different handles, are actually duplicate read/write handles to the current
tty. At least by default.

Consider redirecting stdin, so that it is not a duplicate of stdout, and see
if you get the same results:

echo | my_program

However, this whole topic is OT for clc, as write() is not standard C but
POSIX. And even then, you may be dealing with UB, as I doubt that there is
any guarantee that stdin is writable.

Ken Brody

unread,
Apr 25, 2013, 11:15:54 AM4/25/13
to
On 4/24/2013 2:15 PM, glen herrmannsfeldt wrote:
> James Kuyper <james...@verizon.net> wrote:
[...]
>> "The stderr stream is expected to be open for reading and writing." I've
>> never even thought about the possibility of reading from stderr - I
>> wonder what the use case was that prompted that change (it was
>> introduced in Issue 6)? If stderr is seekable, I suppose one part of a
>> process could read an error message produced by a different part of the
>> process?
>
> (snip)
>
> I haven't thought about this one for a while.
>
> Consider programs that might have both stdin and stdout redirected,
> then write a question (do you really want to ...?) to stderr, and then
> wait for a reply. Where do you read the reply from?

From "/dev/tty", of course. :-)

(BTW, I wouldn't use stderr for asking the question, either.)

Tim Rentsch

unread,
Apr 25, 2013, 12:27:11 PM4/25/13
to
fa...@rahul.net (Edward A. Falk) writes:

> In article <lnfvyge...@nuthaus.mib.org>,
> Keith Thompson <ks...@mib.org> wrote:
>>
>>As far as I can tell from a quick reading of the POSIX specification,
>>a call to write() can either succeed or fail. I'd naively expect
>>it to fail on an attempt to write to a file descriptor not opened
>>for writing, but I don't see anything that says it's *required*
>>to fail.
>
> That's the undefined part. OP went outside the spec and got
> lucky. That won't always happen.

I'd like to offer some counterpoint to the various "what
happened is undefined behavior" remarks.

1. There may indeed have been a declaration in scope,
resulting from flags or compiler option settings. We
cannot say for sure just by looking at the source.

2. Presumably the code compiled and ran, so either
there was an earlier declaration, or one was not
necessary for a successful compile.

3. A declaration is not necessary for a successful
compile in C90. Alternatively, there may have been a
compiler option to treat an undeclared function the
same way as C90 does (after issuing a diagnostic) in a
C99 compilation, which is a conforming choice.

4. Under C90 rules, there is technically undefined
behavior because of type incompatibility, but of a kind
that is benign in implementations where (as is likely
here) size_t == unsigned int (and ssize_t == int).
That's because of guarantees about representations of
the types involved, and also because of what happened
later with C99 (see next).

5. Under C99/C11 rules, the situation mentioned in (4)
was incorporated into the language definition and is
defined behavior.

6. The ISO C standard and POSIX both use (AFAIK) the
term "undefined behavior", and it may even be defined
the same way in both cases. In spite of that there is
a big difference between the two kinds of undefined
behavior, and glossing over that distinction does more
harm than good.

7. AFAICS there is no undefined behavior as far as the
write() call itself is concerned. Looking at the man
page, what write() does looks well-defined for all inputs
(with some non-portable aspects for special files, but
still not undefined behavior). What this write() call
does may be surprising and unexplained by its defining
document, but that's not because of undefined behavior
in the write() call.

8. The question being asked orginally is about why a call
to write() on stdin works. The answer to that question
has to do with the environment where the program was run,
even in the case where size_t != unsigned int. Focusing
on undefined behavior, especially to the exclusion of
other considerations, is a distraction from the question
and a disservice to the questioner.

9. Some people may feel that the posted code displays
some poor coding practices (or fails to follow some good
ones), and consider it important that these be pointed
out. And maybe that's right. But just saying the code
has undefined behavior is not a good way to do that.

glen herrmannsfeldt

unread,
Apr 25, 2013, 12:49:55 PM4/25/13
to
Some years ago (SunOS 3.x if I remember right) I had a program that
wrote to /dev/tty. When I rlogin to another machine to run it, the
output would come out on the screen of that machine, not on mine.
(Confusing to the person using that machine.)

Not quite as long ago, we had some HP software to run under HP-UX.
We installed a new version, which wrote messages to /dev/console.
The getty that was supposed to allow console login then failed, as
the device was in use. I went into the executable file and change it
to /dev/null (The messages weren't that useful) and then called HP.
I told them I had changed it to /dev/null, and the phone person thought
that was a fine solution and didn't even want to take a bug report.

-- glen

James Kuyper

unread,
Apr 25, 2013, 12:51:05 PM4/25/13
to
On 04/25/2013 10:36 AM, Ken Brody wrote:
...
> However, this whole topic is OT for clc, as write() is not standard C but
> POSIX. And even then, you may be dealing with UB, as I doubt that there is
> any guarantee that stdin is writable.

I couldn't find any specification that stdin is (or is not) writable.
However, either way, the behavior should be well-defined (by POSIX, not
by the C standard): if stdin is writable, write() should perform
normally. If not, it should set errno to EBADF and return 0.

Keith Thompson

unread,
Apr 25, 2013, 3:14:46 PM4/25/13
to
A quibble: the name "stdin" refers to the FILE* object declared in
<stdio.h>. The program we're discussing refers to file descriptor 0,
which refers to standard input, but not to "stdin". (File descriptors
are POSIX-specific.)

Veering back on-topic, I don't see anything in the C standard that says
writing to stdin will necessarily fail. N1570 7.21.3p7 says:

At program startup, three text streams are predefined and need not
be opened explicitly -- *standard input* (for reading conventional
input), *standard output* (for writing conventional output), and
*standard error* (for writing diagnostic output).

And stdin, stdout, and stderr, respectively, are associated with those
streams.

As far as I can tell, a conforming implementation *could*, but need not,
open the standard input stream with the equivalent of

stdin = fopen("some_name", "r+");

which would enable both input and output.

(On my system, `write(0, ...)` succeeds, while `fputs("...", stdin)`
fails.)

James Kuyper

unread,
Apr 25, 2013, 3:25:30 PM4/25/13
to
On 04/25/2013 03:14 PM, Keith Thompson wrote:
...
> A quibble: the name "stdin" refers to the FILE* object declared in
> <stdio.h>. The program we're discussing refers to file descriptor 0,
> which refers to standard input, but not to "stdin". (File descriptors
> are POSIX-specific.)

Yes, and POSIX specifies that file descriptor 0 corresponds to stdin.

Keith Thompson

unread,
Apr 25, 2013, 3:54:57 PM4/25/13
to
Quite: but the writability of stdin and the writability of file
descriptor 0 are two distinct questions (and, at least on some systems,
have different answers).

Nobody

unread,
Apr 25, 2013, 5:39:35 PM4/25/13
to
On Wed, 24 Apr 2013 02:08:54 +0000, glen herrmannsfeldt wrote:

>>> write() a is system call Unix systems, does not return failure
>
>> On success, it returns the number of bytes written. On failure, it
>> returns -1 and sets errno to indicate the nature of the failure. In your
>> example, it will return -1 and set errno to EBADF.

I should have clarified that the above was discussing the situation where
fd 0 is not, in fact, writeable.

> There is no rule against writing to file descriptor zero.
>
> The convention for inetd programs is that they read and write of fd 0.

inetd accepts a connection and dup2()s the socket to fds 0, 1, and 2 in
the child process. The intention is that "simple" programs which read from
stdin and write to stdout and/or stderr are automatically usable as inetd
services, while code which expects a single descriptor which refers to a
socket can also be used.

> If fd 0 is a terminal, writing should be fine.

More accurately: if the standard descriptors inherited by the program
remain as they were initally set up by getty, writing to fd 0 will be fine.

Conventionally, getty open()s the terminal read-write then dup()s the
terminal fd to fds 0, 1 and 2. While this doesn't appear to be formally
specified (neither getty nor login are specified by POSIX), opening the
terminal once for each descriptor could break programs which assume the
conventional behaviour (e.g. each descriptor would have a separate
O_NONBLOCK flag).

Nobody

unread,
Apr 25, 2013, 5:51:19 PM4/25/13
to
On Tue, 23 Apr 2013 20:58:45 -0700, Keith Thompson wrote:

> Somewhat off-topic:
>
> As far as I can tell from a quick reading of the POSIX specification, a
> call to write() can either succeed or fail.

Technically true, but a more useful "taxonomy" of results is that it can
write all of the requested data, write only some of it, or fail. Not
allowing for a partial write (or not handling it correctly, e.g.
treating it as a persistent failure instead of a transient failure) is a
common bug.

> (I certainly think that writing to stdin is a silly thing to do.)

It depends whether you mean "FILE* stdin" or "int STDIN_FILENO".
Writing to the latter isn't universally as bad an idea as to the former.

glen herrmannsfeldt

unread,
Apr 25, 2013, 6:56:15 PM4/25/13
to
Keith Thompson <ks...@mib.org> wrote:
> James Kuyper <james...@verizon.net> writes:

(snip)

>> I couldn't find any specification that stdin is (or is not) writable.
>> However, either way, the behavior should be well-defined (by POSIX, not
>> by the C standard): if stdin is writable, write() should perform
>> normally. If not, it should set errno to EBADF and return 0.

> A quibble: the name "stdin" refers to the FILE* object declared in
> <stdio.h>. The program we're discussing refers to file descriptor 0,
> which refers to standard input, but not to "stdin". (File descriptors
> are POSIX-specific.)

Looking at the man pages for unix shells, it seems that csh uses the
term stdout once, and never stdin or stderr. That one is probably a
mistake, as more generally they use "standard input", "standard output"
and "diagnostic output".

bash recognizes redirect to files named /dev/stdin, /dev/stdout, and
/dev/stderr and redirects as appropriate.

Some systems also include in the actual /dev tree entries for
/dev/stdin, /dev/stdout, and /dev/stderr. This usage seems to be copied
from the C standard usage, but not connected to the C standard.

Otherwise, many unix programmers might use the term stdin where the more
correct 'standard input' should be used.

-- glen

Keith Thompson

unread,
Apr 25, 2013, 9:47:29 PM4/25/13
to
glen herrmannsfeldt <g...@ugcs.caltech.edu> writes:
> Keith Thompson <ks...@mib.org> wrote:
>> James Kuyper <james...@verizon.net> writes:
> (snip)
>
>>> I couldn't find any specification that stdin is (or is not) writable.
>>> However, either way, the behavior should be well-defined (by POSIX, not
>>> by the C standard): if stdin is writable, write() should perform
>>> normally. If not, it should set errno to EBADF and return 0.
>
>> A quibble: the name "stdin" refers to the FILE* object declared in
>> <stdio.h>. The program we're discussing refers to file descriptor 0,
>> which refers to standard input, but not to "stdin". (File descriptors
>> are POSIX-specific.)
>
> Looking at the man pages for unix shells, it seems that csh uses the
> term stdout once, and never stdin or stderr. That one is probably a
> mistake, as more generally they use "standard input", "standard output"
> and "diagnostic output".
>
> bash recognizes redirect to files named /dev/stdin, /dev/stdout, and
> /dev/stderr and redirects as appropriate.

I seem to recall that not actually working as specified, but I don't
remember the details (which are off-topic anyway).

> Some systems also include in the actual /dev tree entries for
> /dev/stdin, /dev/stdout, and /dev/stderr. This usage seems to be copied
> from the C standard usage, but not connected to the C standard.
>
> Otherwise, many unix programmers might use the term stdin where the more
> correct 'standard input' should be used.

There's an unfortunate but understandable tendency, when a short
technical term is derived from a longer English word or phrase but
doesn't mean exactly the same thing, to use the shorter term in place of
the longer one.

Examples: "stdout" for "standard output", "int" for "integer", "const"
for "constant", "EOF" for "end of file".

army1987

unread,
Apr 27, 2013, 6:49:13 PM4/27/13
to
On Tue, 23 Apr 2013 11:58:43 -0400, James Kuyper wrote:

> How do you know that it worked? As far as I can tell, your program makes
> no attempt to determine whether or not the call to write() was
> successful.

He/she noticed that the terminal did display four lines each containing
"Hello world!"?

--
[ T H I S S P A C E I S F O R R E N T ]
Troppo poca cultura ci rende ignoranti, troppa ci rende folli.
-- fathermckenzie di it.cultura.linguistica.italiano
<http://xkcd.com/397/>

James Kuyper

unread,
Apr 27, 2013, 7:13:50 PM4/27/13
to
On 04/27/2013 06:49 PM, army1987 wrote:
> On Tue, 23 Apr 2013 11:58:43 -0400, James Kuyper wrote:
>
>> How do you know that it worked? As far as I can tell, your program makes
>> no attempt to determine whether or not the call to write() was
>> successful.
>
> He/she noticed that the terminal did display four lines each containing
> "Hello world!"?

That's not what happened when I ran his program. I only got three lines,
and his program provided no mechanism for determining which call to
write() failed. On my system, it was the fourth one, but I had to modify
the program to determine that.
--
James Kuyper

James Dow Allen

unread,
Apr 27, 2013, 11:22:20 PM4/27/13
to
On Apr 26, 2:25 am, James Kuyper <jameskuy...@verizon.net> wrote:
> Yes, and POSIX specifies that file descriptor 0 corresponds to stdin.

(My post does not consider what POSIX systems may or must
do, but on what most (or all?) UNIX systems do in fact do.
If that's off-topic here, please disregard this post.
BTW, Cygwin and Linux both behave like Unix on the two
points made below.)

1. Consider a program with the following executable code:
fclose(stdin); /* close any input script
*/
freopen("Torture.log", "a", stderr); /* redirect diagnostics
*/
freopen("/dev/tty", "r", stdin); /* use terminal for input
*/
printf("stdin=%d stderr=%d\n", fileno(stdin), fileno(stderr));
I think this code is mostly posix. Yet, as shown by the
output of printf, it reverses the file descriptors for
stdin and stderr! Posix errors: Is this a spec bug?

2. On another matter, writing to stdin is very ancient in
Unix. I learned this when browsing source code for
a standard utility -- sorry, don't remember which --
and noted that it had a "write(0, ..." for some error
message as an emergency when neither 1 nor 2 was connected
to a terminal.

James



James Dow Allen

unread,
Apr 27, 2013, 11:25:32 PM4/27/13
to
On Apr 28, 10:22 am, James Dow Allen <jdallen2...@yahoo.com> wrote:
> Posix errors:  Is this a spec bug?

I meant to write:
> Posix experts:  Is this a bug in the specification?

Is substituting homonyms when typing a sign of
old age? I must be getting very old as
"experts" and "errors" aren't very homonymous.

James

James Kuyper

unread,
Apr 28, 2013, 9:58:19 AM4/28/13
to
On 04/27/2013 11:22 PM, James Dow Allen wrote:
> On Apr 26, 2:25�am, James Kuyper <jameskuy...@verizon.net> wrote:
>> Yes, and POSIX specifies that file descriptor 0 corresponds to stdin.
>
> (My post does not consider what POSIX systems may or must
> do, but on what most (or all?) UNIX systems do in fact do.
> If that's off-topic here, please disregard this post.
> BTW, Cygwin and Linux both behave like Unix on the two
> points made below.)
>
> 1. Consider a program with the following executable code:
> fclose(stdin); /* close any input script
> */
> freopen("Torture.log", "a", stderr); /* redirect diagnostics
> */
> freopen("/dev/tty", "r", stdin); /* use terminal for input
> */
> printf("stdin=%d stderr=%d\n", fileno(stdin), fileno(stderr));
> I think this code is mostly posix. Yet, as shown by the
> output of printf, it reverses the file descriptors for
> stdin and stderr! Posix errors: Is this a spec bug?

Later, he corrected that last sentence:
> I meant to write:
> Posix experts: �Is this a bug in the specification?

"The following symbolic values in <unistd.h> define the file descriptors
that shall be associated with the C-language stdin, stdout, and stderr
when the application is started:

STDIN_FILENO
Standard input value, stdin. Its value is 0.
STDOUT_FILENO
Standard output value, stdout. Its value is 1.
STDERR_FILENO
Standard error value, stderr. Its value is 2."

Key words: "when the application is started".
--
James Kuyper
0 new messages