bug-ed
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Buffered I/O and ed shell escape command


From: Sören Tempel
Subject: Buffered I/O and ed shell escape command
Date: Tue, 28 Dec 2021 21:03:27 +0100

Hi,

I did some experiments with the shell escape command today and noticed
that the command behavior depends on the output stream on my system:

        $ cat /tmp/ed-cmd
        !echo foo
        !!
        $ ed < /tmp/ed-cmd
        foo
        !
        echo foo
        foo
        !
        $ ed < /tmp/ed-cmd > /tmp/ed-out.txt
        foo
        !
        foo
        echo foo
        !

If the standard output is line buffered (i.e. a TTY) everything works as
expected. However, if standard output is a file, the modified command
string of the second command (echo foo) is written *after* the command
was executed. This is IMHO not conforming to POSIX which mandates that
the modified command string must be written *before* the command is
executed.

Looking at the source code, the problem seems to be that buffered output
streams are not flushed before the given command is executed using
system(3). As such, the executed command may write data (unbuffered) to
standard output and after the command terminated, data potentially
buffered by ed is written to it. As such, the output order depends on
whether standard output is line buffered.

My hypothesis seems to be confirmed by the fact that applying the
following patch fixes the outlined problem:

diff -upr ed-1.18-pre3.orig/main_loop.c ed-1.18-pre3/main_loop.c
--- ed-1.18-pre3.orig/main_loop.c       2021-12-28 20:40:49.170833983 +0100
+++ ed-1.18-pre3/main_loop.c    2021-12-28 20:40:53.594162095 +0100
@@ -678,6 +678,7 @@ pflabel:      if( !check_addr_range2( ad
     case '!': if( unexpected_address( addr_cnt ) ) return ERR;
               fnp = get_shell_command( ibufpp );
               if( !fnp ) return ERR;
+              fflush ( NULL ); /* flush any buffered I/O */
               if( system( fnp + 1 ) < 0 )
                 { set_error_msg( "Can't create shell process" ); return ERR; }
               if( !scripted() ) fputs( "!\n", stdout );

However, I also tested this with the OpenBSD implementation of ed(1) and
this implementation also exhibits different behavior depending on
standard output buffering. I am therefore not sure if I am simply
misunderstanding the specification of the shell escape command in POSIX
or if this is indeed a bug.

I would welcome any sort of feedback on my outlined observations.

Greetings,
Sören



reply via email to

[Prev in Thread] Current Thread [Next in Thread]