The error is always stored in plugin_ctx, but it is only set into errstr
if the API version is enough. (Previously it worked the opposite:
we only stored the error if API level was enough.)
Plugins can raise a sudo.PluginError exception to add context message
for the failure.
The callback's errstr gets filled up with the specified message.
But, as sudo expects a string constant (will not free the string),
we store it in the plugin context at least until next callback
invocation.
Unfortunately the test did not catch this mistake, because it only
searches that "Python policy plugin API version" string is present
and does not check the version.
On each plugin initialization we create a separate python interpreter
which gets stored in the plugin_ctx. The main interpreter is
stored in py_ctx and is used for creating more interpreters (if more plugins
get loaded) and final python deinitialization.
The "traceback" module import and the ImportBlocker initialization was
moved, because it has to happen inside the plugin specific interpreters.
When calling validate() python function, TypeError exception was thrown
("argument list must be a tuple"), because the call does not have
arguments, and python does not accept empty tuple for execution. NULL
must be used instead, which was handled as argument construction failure
previously.
IO/Group/Policy Python API version is displayed instead of sudo version,
because that is not very meaningful in this context.
They are only displayed in verbose mode.
Example plugins express it more concrete that they are displaying their
version, not the API version.