Subject: bug#6323: Enhancement request: Add wronly to Coreutils

From: Daniel Trebbien <[email-masked]>
Date: Tue, 1 Jun 2010 19:48:44 -0400

On 2010-06-01, Eric Blake <[email-masked]> wrote:
> On 06/01/2010 05:59 AM, Daniel Trebbien wrote:
>> Over the past few days I have been working on a new Linux command-line
>> utility which I'm calling `wronly` (https://launchpad.net/wronly).
>> Basically what it does is copy its standard input to a file that is
>> specified on the command line, but also closes its standard out and
>> standard error if parsing of the command line options succeeds. It
>> also supports a `--no-follow` option, the code for which I'm pretty
>> proud of.
>
> Would you mind showing actual command line examples of how you envision
> using this?

I don't intend to use `wronly` from the command line, but rather in a
C program that basically execs `sudo wronly FILE` *in the background*.
I can already exec `sudo`, of course, but because it uses `/dev/tty`
by default, it kind of takes over.

`sudo` with the `-S` option causes it to write the password prompt (if
it requires a password at that time) to standard error and read the
password from standard in. The problem is: how do I know if `sudo`
requires a password? I need to try to read the password prompt from
standard error, but if the password is not required, then the parent
process will wait for data on standard error while the child process
(`wronly` by this time) waits for data on standard in.

My first thought was to create a `tee_wrapper` program that closes its
standard error, creates a pipe for a "dummy" standard error stream,
execs `tee` with the write end of this dummy pipe and duplicate
descriptors of standard in and out, and reads from the dummy pipe into
a trash buffer continually until the `tee` child process exits (to
prevent deadlock if `tee` manages to write enough data to the pipe
that it reaches the end of the OS buffer and blocks). All of this
seemed silly.

I could ask the `sudo` maintainers for a new option to make *it* close
its standard error, but then they would be adding in the same steps
that I outlined for the `tee_wrapper` program. Therefore, I thought
about submitting a patch for `tee`. Looking into the code for `tee`, I
then thought that it would be better if I just wrote a slightly
different variant of the utility for the reason that I outlined in
paragraph two of my first email. Also, the variant could support
additional options such as `--no-follow`, `--no-atime`, `--no-create`,
and `--executable` which would require substantial changes to `tee` in
order to implement these features the "right way". (By this, I mean
that different combinations of `--no-follow`, `--no-atime`,
`--no-create`, and `--executable` could be used with all of the files
that are specified on the command line.)

Please see the attached C file for a proof-of-concept of exec'ing sudo
"in the background". I wrote it rather quickly, so don't make fun of
it too much :)  You can test it with:

sudo rm TEST.txt
sudo -k
./exec_sudo_wronly
sudo rm TEST.txt
./exec_sudo_wronly

>>
>> I am aware of the similar `tee` program that is already part of GNU
>> Coreutils, but I did not think that it would be wise for me to write a
>> patch for `tee` that just causes `tee` to similarly close its standard
>> error. I needed a program like `tee` that would close the standard
>> error stream, so I figured that there might be uses if such a program
>> were to close standard out as well. Of course, closing standard out in
>> `tee` would fundamentally break the utility, but I'm also not sure if
>> closing standard error in `tee` would cause problems for existing
>> scripts that depend on it.
>
> Actually, there's nothing wrong with patching tee to add another command
> line option, if it really does make sense to add this functionality.
> But right now, without a demonstration of why this is needed, and why:
>
> cmd | tee file >&- 2>&-
>
> does not already do what you want, it's hard to make any decisions.
>

Looking back at what I thought versus what I think now, I realize that
the `tee_wrapper` program can be made a lot less "silly" if instead of
creating a pipe for `tee`'s standard error, `tee_wrapper` opened a
writable handle to `/dev/null`. Even then, though, `tee_wrapper` could
not add support for `--no-follow`, `--no-atime`, `--no-create`, and
`--executable`.

I am not sure what is preferred for bringing support for
`--no-follow`, `--no-atime`, `--no-create`, and `--executable` to a
`tee`-like program in Coreutils:  adding a separate utility such as
`wronly` or trying to update `tee`. Either way, I am happy to help.