2015-07-17
Your standard input is a tty in a number of surprising cases
Every once in a while, someone writing a program decides that
checking to see whether standard input is a tty (via isatty())
is a great way of determining 'am I being run interactively or
not?'. This certainly sounds like a good way to do this check if
you aren't familiar with Unix and don't actually test any number
of situations, but in fact it is wrong almost all of the time.
For a start, this is wrong if your command is just being run in a shell script. Commands run from a shell script inherit the script's standard input; if you just ran the script itself from a shell command line, well, that's your tty. No Unix shell can behave differently because passing stdin to script commands is what lets shell scripts work in the middle of pipelines. But plain commands are the obvious case, so let's go for an odder one:
var=$(/some/command ....)
You guessed it: /some/command inherits the shell's standard input
and thus may have its standard input connected to your tty. Its
standard output is not a tty, of course; it's being collected by
the shell instead.
Now let's talk about GNU Make. Plain commands in Makefiles are like
plain commands in shell scripts; make gets your standard input
and passes it to commands being run. In my opinion this is far less
defensible than with shell scripts, although I'm sure someone has
a setup that uses make and a Makefile in the middle of a pipeline
and counts on the commands run from the Makefile being able to read
standard input. Still, I suspect a certain number of people would
be surprised by that.
GNU Make has a feature where it can run a shell command as it parses the Makefile in order to do things like set up the value of Makefile variables. This looks like (in the simple version):
AVAR := $(shell /some/command ...)
This too can have isatty(stdin) be true. Like the shell, GNU Make
passes its standard input down even to things being run via command
substitution.
The short form version of this is almost anything that's run even
indirectly by a user from their shell prompt may have standard input
being a tty. Run from a shell script that's run from three levels
of Makefiles (and makes) that are started from a shell script
that's spawned from a C program that does a system()? Unless
there's a pipeline somewhere in there, you probably still have
standard input connected to the user's tty.
It follows that checking isatty(stdin) is a terrible way of seeing
whether or not your program is being run interactively, unless the
version of 'interactively' you care about is whether you're being
run from something that's totally detached from the user, like a
crontab or a ssh remote command execution (possibly an automated
one). Standard input not being a tty doesn't guarantee this, of
course, but if standard input is a tty you can be pretty sure that
you aren't being run from crontab et al.
(The corollary of this is that if you're writing shell scripts and
so on, you may sometimes want to deliberately disconnect standard
input from what it normally would be. This doesn't totally stop
people from talking to the user (they can always explicitly open
/dev/tty), but at least it makes it less likely to happen by
more or less accident.)
2015-07-13
My personal view of OpenBSD
I have nothing against OpenBSD in situations where it works well; we run it for firewalls and a few other narrow purposes which it does well at. But I have no love for it either and left to my own devices I probably wouldn't use it for anything. Certainly I can't imagine running OpenBSD on a personal machine.
Some of this is an extension of my pragmatic and technical views on FreeBSD versus Linux, with a bit of the cultural bad blood thrown in as well. Some of it is all of the sober, calm impacts of OpenBSD's culture, since I have good reasons not to run systems where I don't think I'm going to have very much fun trying to get support or help or report bugs. But that's the easy to write about and incomplete version.
The core truth is that I don't want to associate myself with the OpenBSD culture that I described. I no longer want to be anywhere near a community that is abrasive in general and hostile to newcomers (either openly or simply by being 'clever'), one where people abusing each other on mailing lists is a perfectly okay event, and so on. My hands are not clean here, because I have been one of those clever people in the past (and part of the appreciative audience of such clever people, too). But looking back at that part of my past conduct now mostly makes me wince. Today, I try to be better and do better.
(I'm not entirely consistent, given that Linux has its own issues with this. But I feel that they are less pervasive because Linux is a much more split up system; there is no one group of people that is the entire main system the way there is with OpenBSD.)
Even if I never experienced or even saw the dark side of OpenBSD, I would know that it was there. And these days I simply don't want to hang around that sort of a place; it's not something that I find pleasant any more. And in turn that taints OpenBSD itself, because it is the heart of that culture.
PS: I don't know if what I hear about OpenBSD's culture is actually true (or if it's still true). That's why I've called it folklore. But if it isn't true, well, the OpenBSD people have a problem, because it is very pervasive folklore (and does historically clearly have some basis in fact) and I'm not sure people are going to easily believe that it's false.
(Not that I expect that the people in the OpenBSD community care about this issue or my views. Rather the contrary; it would be surprising if they were not perfectly fine with the current state of their community, and maybe rather enjoy it just the way it is.)