summaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
authorDavid Zeuthen <davidz@redhat.com>2007-03-27 12:38:49 -0400
committerDavid Zeuthen <davidz@redhat.com>2007-03-27 12:38:49 -0400
commit020bccd8fa1e96d2b20b4b8b2e47820511044ac1 (patch)
treeb70d6b84fa519f2756ad7bde388d5a07e7bad314 /tools
parent298285e2a279e81368dddee604b1884628e66b29 (diff)
add new hal-lock(1) utility
Before anyone starts complaining about 0.5.9 freeze, it's OK to add this for 0.5.9 as such a utility is key to making legacy apps work well. It also helped me uncover bugs in the libhal API and locking logic.
Diffstat (limited to 'tools')
-rw-r--r--tools/Makefile.am6
-rw-r--r--tools/hal-lock.c232
2 files changed, 237 insertions, 1 deletions
diff --git a/tools/Makefile.am b/tools/Makefile.am
index 3c5a3026..0f73f61c 100644
--- a/tools/Makefile.am
+++ b/tools/Makefile.am
@@ -30,7 +30,8 @@ bin_PROGRAMS = \
hal-find-by-capability \
hal-find-by-property \
hal-device \
- hal-is-caller-locked-out
+ hal-is-caller-locked-out \
+ hal-lock
lshal_SOURCES = lshal.c
lshal_LDADD = @GLIB_LIBS@ $(top_builddir)/libhal/libhal.la
@@ -53,6 +54,9 @@ hal_device_LDADD = @DBUS_LIBS@ $(top_builddir)/libhal/libhal.la
hal_is_caller_locked_out_SOURCES = hal-is-caller-locked-out.c
hal_is_caller_locked_out_LDADD = @DBUS_LIBS@ $(top_builddir)/libhal/libhal.la
+hal_lock_SOURCES = hal-lock.c
+hal_lock_LDADD = @GLIB_LIBS@ @DBUS_LIBS@ $(top_builddir)/libhal/libhal.la
+
libexec_PROGRAMS = \
hal-storage-mount \
hal-storage-unmount \
diff --git a/tools/hal-lock.c b/tools/hal-lock.c
new file mode 100644
index 00000000..cd54f26d
--- /dev/null
+++ b/tools/hal-lock.c
@@ -0,0 +1,232 @@
+/***************************************************************************
+ * CVSID: $Id$
+ *
+ * hal-lock.c : Lock an interface
+ *
+ * Copyright (C) 2007 David Zeuthen, <david@fubar.dk>
+ *
+ * Licensed under the Academic Free License version 2.1
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ **************************************************************************/
+
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <getopt.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <signal.h>
+#include <glib.h>
+
+#include "libhal.h"
+
+/**
+ * usage:
+ * @argc: Number of arguments given to program
+ * @argv: Arguments given to program
+ *
+ * Print out program usage.
+ */
+static void
+usage (int argc, char *argv[])
+{
+ fprintf (stderr,
+ "\n"
+ "usage : hal-lock --interface <interface>\n"
+ " --run <program-and-args>\n"
+ " [--udi <udi>]\n"
+ " [--exclusive]\n"
+ " [--help] [--version]\n");
+ fprintf (stderr,
+ "\n"
+ " --interface Interface to lock\n"
+ " --run Program to run if the lock was acquired\n"
+ " --udi Unique Device Id of device to lock. If\n"
+ " ommitted the global lock will be tried\n"
+ " --exclusive Whether the lock can be held by others\n"
+ " --version Show version and exit\n"
+ " --help Show this information and exit\n"
+ "\n"
+ "This program will attempt to grab a lock on a given interface.\n"
+ "Unless, a specific UDI is given, the global lock will be tried.\n"
+ "If the lock was succesfully acquired the program specified by\n"
+ "the option --run will be run and upon termination this program\n"
+ "will exit with exit code 0. If the lock wasn't acquired or an\n"
+ "error occured while taking the lock, this program will exit with a\n"
+ "non-zero exit code and the given program will not be run.\n"
+ "\n");
+}
+
+/**
+ * main:
+ * @argc: Number of arguments given to program
+ * @argv: Arguments given to program
+ *
+ * Returns: Return code
+ *
+ * Main entry point
+ */
+int
+main (int argc, char *argv[])
+{
+ char *udi = NULL;
+ char *interface = NULL;
+ char *run = NULL;
+ dbus_bool_t is_version = FALSE;
+ dbus_bool_t exclusive = FALSE;
+ dbus_bool_t got_lock = FALSE;
+ DBusError error;
+ LibHalContext *hal_ctx;
+ int ret;
+ GError *g_error = NULL;
+
+ ret = 1;
+
+ if (argc <= 1) {
+ usage (argc, argv);
+ goto out;
+ }
+
+ while (1) {
+ int c;
+ int option_index = 0;
+ const char *opt;
+ static struct option long_options[] = {
+ {"udi", 1, NULL, 0},
+ {"interface", 1, NULL, 0},
+ {"run", 1, NULL, 0},
+ {"exclusive", 0, NULL, 0},
+ {"version", 0, NULL, 0},
+ {"help", 0, NULL, 0},
+ {NULL, 0, NULL, 0}
+ };
+
+ c = getopt_long (argc, argv, "",
+ long_options, &option_index);
+ if (c == -1)
+ break;
+
+ switch (c) {
+ case 0:
+ opt = long_options[option_index].name;
+
+ if (strcmp (opt, "help") == 0) {
+ usage (argc, argv);
+ return 0;
+ } else if (strcmp (opt, "version") == 0) {
+ is_version = TRUE;
+ } else if (strcmp (opt, "udi") == 0) {
+ udi = strdup (optarg);
+ } else if (strcmp (opt, "run") == 0) {
+ run = strdup (optarg);
+ } else if (strcmp (opt, "exclusive") == 0) {
+ exclusive = TRUE;
+ } else if (strcmp (opt, "interface") == 0) {
+ interface = strdup (optarg);
+ }
+ break;
+
+ default:
+ usage (argc, argv);
+ return 1;
+ break;
+ }
+ }
+
+ if (is_version) {
+ printf ("hal-lock " PACKAGE_VERSION "\n");
+ ret = 0;
+ goto out;
+ }
+
+ if (interface == NULL || run == NULL) {
+ usage (argc, argv);
+ goto out;
+ }
+
+
+ dbus_error_init (&error);
+ if ((hal_ctx = libhal_ctx_new ()) == NULL) {
+ fprintf (stderr, "error: libhal_ctx_new\n");
+ goto out;
+ }
+ if (!libhal_ctx_set_dbus_connection (hal_ctx, dbus_bus_get (DBUS_BUS_SYSTEM, &error))) {
+ fprintf (stderr, "error: libhal_ctx_set_dbus_connection: %s: %s\n", error.name, error.message);
+ LIBHAL_FREE_DBUS_ERROR (&error);
+ goto out;
+ }
+ if (!libhal_ctx_init (hal_ctx, &error)) {
+ if (dbus_error_is_set(&error)) {
+ fprintf (stderr, "error: libhal_ctx_init: %s: %s\n", error.name, error.message);
+ dbus_error_free (&error);
+ }
+ fprintf (stderr, "Could not initialise connection to hald.\n"
+ "Normally this means the HAL daemon (hald) is not running or not ready.\n");
+ goto out;
+ }
+
+ if (udi != NULL) {
+ got_lock = libhal_device_acquire_interface_lock (hal_ctx,
+ udi,
+ interface,
+ exclusive,
+ &error);
+ } else {
+ got_lock = libhal_acquire_global_interface_lock (hal_ctx,
+ interface,
+ exclusive,
+ &error);
+ }
+
+ if (dbus_error_is_set(&error)) {
+ fprintf (stderr,
+ "error: %s: %s: %s\n",
+ udi != NULL ? "libhal_device_acquire_interface_lock" :
+ "libhal_acquire_global_interface_lock",
+ error.name,
+ error.message);
+ dbus_error_free (&error);
+ goto out;
+ }
+
+ if (!got_lock) {
+ goto out;
+ }
+
+ /* now run the program while holding the lock */
+ if (!g_spawn_command_line_sync (run,
+ NULL,
+ NULL,
+ NULL,
+ &g_error)) {
+
+ fprintf (stderr, "error: g_spawn_command_line_sync: %s\n", g_error->message);
+ g_error_free (g_error);
+ goto out;
+ }
+
+ ret = 0;
+
+out:
+ return ret;
+}