What is the best way to protect stdin within a library?
I am writing a terminal based program that provides plugin
capability using the dlopen() API.
dlopen() is not part of standard C, so this group likely will
not be able to come up with the best answer for your question.
Sequencing program commands (typed) and library input
prompts will not happen if stdin is supplied by pipe
or redirection.
So, I would like to include a statement in the pluggin
header that disables stdin only within the pluggin's scope.
By disable, I expect the statement would result in a
compiler error.
stdin is defined by the C89 standard to be a macro [that
is an expression that will give the appropriate FILE*].
This suggests that in theory you could #undef stdin
and #define stdin to be something incompatible that would
generate a compile error if used.
There is also fd 0 to contend with.
File descriptors are not actually part of the C standard either.
They are very common, and have well defined semantics under
the POSIX 1003.1 standard, but they are technically extensions to C.
I am not clear as to what exactly you are trying to protect
against. Are you trying to protect against the plugin opening
(even by way of freopen()) stdin, on the grounds that the prompts
will not happen if the user is not careful enough to use
pty's? Or are you trying to prevent the user from reading
an already established stdin ?
If you are trying to stop the user from using stdin then you
are going to have some difficulties, as a determined user could,
in a typical installation, use something like (stdout-1) or (stderr-2)
[commonly, the expressions for stdin, stdout, stderr are
in terms of addresses of elements of an array that holds all 3,
so simple pointer arithmetic can be used to get a handle on the
other elements.] And users could easily look in their <stdio.h>
and use the expressions directly instead of through the
stdin macro.
If you want users to be able to write plugins that deal with
I/O but you want to protect stdin then you might need to
provide your own fopen() and so on that would end up being what
the user linked against. But that gets into deep questions about
what the symbol resolution order is when you do a dlopen(),
and questions about whether your system has an internal
equivilent to fopen() et al. that you could access from your
replacement routines.
I don't know what it would do to program efficiency, but is
an alternative strategy perhaps in order? When you are calling
those 'sequenced commands' and library routines, would it make
sense for you to have preserved a copy of stdin, and to
restore it into place as the active stdin before calling the
routines? Potentially you could do some optimization about this,
not doing the re-activation unless user-provided code had been
called since the last activation.