With this function we can decide whether to try running the polkit text agent only if it is available, removing a potential needless error saying that the agent binary does not exist, which is useful especially when running the agent before knowing whether it is going to be needed. Signed-off-by: Martin Kletzander <mkletzan@xxxxxxxxxx> --- src/libvirt_private.syms | 1 + src/util/virpolkit.c | 44 ++++++++++++++++++++++++++++++++++++++++ src/util/virpolkit.h | 1 + 3 files changed, 46 insertions(+) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index a7bc50a4d16d..c11be4eafa19 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -3078,6 +3078,7 @@ virPidFileWritePath; # util/virpolkit.h +virPolkitAgentAvailable; virPolkitAgentCreate; virPolkitAgentDestroy; virPolkitCheckAuth; diff --git a/src/util/virpolkit.c b/src/util/virpolkit.c index 86255a96760f..3b333547d70b 100644 --- a/src/util/virpolkit.c +++ b/src/util/virpolkit.c @@ -20,6 +20,7 @@ */ #include <config.h> +#include <fcntl.h> #include <unistd.h> #include "virpolkit.h" @@ -217,6 +218,42 @@ virPolkitAgentCreate(void) } +/* + * virPolkitAgentAvailable + * + * This function does some preliminary checking that the pkttyagent does not + * fail starting so that it can be started without waiting for first failed + * connection with VIR_ERR_AUTH_UNAVAILABLE. + */ +bool +virPolkitAgentAvailable(void) +{ + const char *termid = ctermid(NULL); + VIR_AUTOCLOSE fd = -1; + + if (!virFileExists(PKTTYAGENT)) + return false; + + if (!termid) + return false; + + /* + *The pkttyagent needs to open the controlling terminal. + * + * Just in case we are running without a ctty make sure this open() does not + * change that. + * + * We could check if our session has a controlling terminal available + * instead, but it would require parsing `/proc/self/stat` on Linux, which + * is not portable and moreover requires way more work than just open(). + */ + fd = open(termid, O_RDWR | O_NOCTTY); + if (fd < 0) + return false; + + return true; +} + #else /* ! WITH_POLKIT */ int virPolkitCheckAuth(const char *actionid G_GNUC_UNUSED, @@ -247,4 +284,11 @@ virPolkitAgentCreate(void) _("polkit text authentication agent unavailable")); return NULL; } + +bool +virPolkitAgentAvailable(void) +{ + return false; +} + #endif /* WITH_POLKIT */ diff --git a/src/util/virpolkit.h b/src/util/virpolkit.h index a577d59452ba..7bcd040e5e06 100644 --- a/src/util/virpolkit.h +++ b/src/util/virpolkit.h @@ -37,3 +37,4 @@ typedef struct _virPolkitAgent virPolkitAgent; void virPolkitAgentDestroy(virPolkitAgent *cmd); virPolkitAgent *virPolkitAgentCreate(void); +bool virPolkitAgentAvailable(void); -- 2.34.0