Robert Elz via austin-group-l at The Open Group dixit:

>  | > You might prefer that it "fflush(stdout); if (ferror(stdout)) ..." but
>  | > there's nothing explicit in the standard that says that it has to do 
> that.

>There was no argument based upon C functions - the use of them was
>just a shorthand to make a point.

Using the same shorthand, I changed mksh tonight to do pretty much
what you described, in a second patch:

@@ pseudo @@
 int
 call_builtin(func_t builtinfunc, int argc, char *argv[])
 {
     int exitstatus;

     stdout = fdopen(1, "w");
     exitstatus = (*builtinfunc)(argc, argv, environ);
     fflush(stdout);
+    if (ferror(stdout)) {
+        fprintf(stderr, "%s: write: %s\n", argv[0], strerror(errno));
+        if (exitstatus == 0)
+            exitstatus = 1;
+    }
     return (exitstatus);
 }

This handles pwd and (if compiled in) printf; I also added the same
error message to the echo/print builtin for where it detects errors
as it uses the write(2) syscall, not the stdio replacement, internally.

We’ll see whether that breaks anything. Incidentally, if true encounters
an error on stdout during operation now, it can return false — except it
never accesses stdout, thus this cannot happen.

Vincent will probably see whether this solves his problem; he’s got to
notify me if there are any other builtins to take care of.

Ugh. This is a “magic fix”… I don’t like this, but it’ll do, I think.
If the builtin encountered other errors and already exited nōn-zero,
that will be that, but otherwise, it runs on until the buffers are
flushed as write errors may not be recognised before that. If that’s
not enough, I don’t know. In that case I’d question the standard harder.

> exit() as part of its processing flushes the stdio buffers.  Including stdout.
> That's when the actual write from the process happens - but it is far too
> late then for pwd to do anything about it, exit() never returns, no pwd
> supplied code ever runs again (unless it set an atexit() - but it has no
> need for that, and doesn't).   I see nothing in the standard allowing exit()
> to terminate the process with any exit status other than the one handed to
> it, do you?   What's more, it would be extremely unlikely for exit() to be
> writing messages to stderr, which as you mentioned in a previous message is
> a requirement if the exit code is not 0 (for most utilities).

And yet, this is pretty much what I had to implement to hopefully
satisfy demands from here.

>  | The standard requires that pwd writes to stdout.
>
>The question is just what that means in terms of the interfaces available.
>pwd called printf, printf reported no error.   Stdout has been written to
>as far as I'm concerned when that has happened.

EXACTLY!

However, there’s one case in which I can see the reason of those
requesting this.

To set this up, I mounted a very small memory filesystem on /mnt,
made it owned by my user and created /mnt/foo, 0 bytes long, then
filled it up by writing to /mnt/bar etc. until no writes succeed.

Now, first the old, then the CVS HEAD shell:

tg@tglase-bsd:~ $ /bin/mksh -c pwd >/mnt/foo; echo $?

/mnt: write failed, filesystem is full
0
tg@tglase-bsd:~ $ /usr/obj/bin/mksh/mksh -c pwd >/mnt/foo; echo $?

/mnt: write failed, filesystem is full
/usr/obj/bin/mksh/mksh: pwd: write: No space left on device
1

The “write failed, filesystem is full” message comes from the kernel,
which is very helpful here. But yes, there’s the output. In scripts,
I’d expect writing “x=$(pwd)” instead of “pwd >x; x=$(cat x)”, but the
latter is necessary in some cases (e.g. escaping subshells, pipelines,
etc). In those situations, it would be nice if “pwd >x” failed, even
if it’s no problem of pwd(1) strictly spoken.

That’s my nightly change’s reason.

Tests (including bugreports, but let’s hope for none) welcome.

bye,
//mirabilos
-- 
Gestern Nacht ist mein IRC-Netzwerk explodiert. Ich hatte nicht damit
gerechnet, darum bin ich blutverschmiert… wer konnte ahnen, daß SIE so
reagier’n… gestern Nacht ist mein IRC-Netzwerk explodiert~~~
        (as of 2021-06-15 The MirOS Project temporarily reconvenes on OFTC)

Reply via email to