tech-userlevel archive

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

What should we do with the -n flag in sh ?

Some of you might have seen the reply I just sent to PR bin/43255

That PR was about "sh -nc" (which in NetBSD sh simply ignores the -n)
Fixing that is trivial, and will be done.

But there's a lot more to decide about -n in sh, it is currently
just barely implemented ... just enough to shoot yourself in the
foot I think, though it does allow for syntax checking of scripts
with a usage like

	sh -n

This message is to ask for guidance about how everyone believes it
should operate.

First, although POSIX allows -n to be ignored in interactive shells,
NetBSD does not do that, as much as -n works, it works in all shells.

So, if you start a sh, and in it type "set -n", then your shell will
do nothing, until you exit with ^D.   Well, it does syntax check its
input (as it is supposed to do), but it executes nothing.   That "nothing"
obviously includes "set +n" so there's no way to undo "set -n", and
also includes "exit", so ^D is the only way out ... so you better hope
that you don't have -I set!   If you have both the I and n options set,
there is no way (from inside the shell) to make it quit - if you send
it EOF, it tells you nicely to use "exit" to exit, but when you try
that, it ignored you (as it should.)

I suspect the right fix for this one is to do as POSIX permits, and
ignore -n in interactive shells.   But I am not sure which method
to use to do that ... it could be done by any of ...

Making it an error to attempt to set -n in an interactive shell
(that has the benefit that you would get an error message and
know what has happened.)

Silently ignoring the attempt to set -n in an interactive shell
(or allowing the set to happen, but quickly undoing it again.)
This way, $- would not show the n flag set, so you would at least
be able to work out what happened, but if you're sourcing ('.' cmd)
a script that does "set -n" into an interactive shell, you wouldn't
be bothered by error messages that you did not directly cause.

Allowing the set -n to happen (so $- includes 'n') but simply ignoring
it in interactive shells (ones with -i set).

Opinions?   (or suggestions for other ways to handle this, or to simply
allow it to remain as it is now.)

Next, when -n is in force, just what should it control ?

A good way to ask this is to give an example ...

What should be the effect of

	while set -n; do echo foo; done

bash and zsh just (silently) loop forever.   That is, once the set -n
is done, the 'echo' command is not executed, and I suspect, nor are any
more "set -n" commands (but one of them is enough.)   But the "while"
is already started, and is going to keep running until one of the commands
that is now never run returns a non-zero status.

/bin/ksh (from NetBSD) just echo's foo forever.   So does NetBSD sh
currently, but that is because we don't really understand -n at all.
The src/bin/sh/options.h file even has it marked as unimplemented (just
the same as -b etc are marked) though that is not quite true.  I don't
know if ksh is doing the same, or it has some other implementation choice.

My opinion on this is that once -n is set, all command execution stops,
including while (until, for, ...) loops that were in progress, and all
that is left of the shell is a syntax parser.

What do the rest of you think, just how devious to the -n checks need
to be.

For now, my current sources are done the way I think -n should work
(all stop now) and ignoring interactive mode.   But this happens to
be one of the easier parts of the shell to handle, and any of the
implementation possibilities should be reasonably easy to make happen.


Home | Main Index | Thread Index | Old Index