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(a)redhat.com>
---
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