diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index a7bc50a4d1..c11be4eafa 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 86255a9676..ebe131dc51 100644 --- a/src/util/virpolkit.c +++ b/src/util/virpolkit.c @@ -20,6 +20,7 @@ */ #include +#include #include #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 (!virFileIsExecutable(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 a577d59452..7bcd040e5e 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);