summaryrefslogtreecommitdiff
path: root/stc/stc.c
diff options
context:
space:
mode:
authorDavid Zeuthen <davidz@redhat.com>2010-10-06 15:13:46 -0400
committerDavid Zeuthen <davidz@redhat.com>2010-10-06 15:13:46 -0400
commit1331349d2e97bceaadf8d8cf0b6b5c11c83577a5 (patch)
tree56cee7e3234b6b2b8a72d4ed561c6b07b267c83b /stc/stc.c
parentd03c35c1d0a486a45e9206267aca155fc4448394 (diff)
Updates
Signed-off-by: David Zeuthen <davidz@redhat.com>
Diffstat (limited to 'stc/stc.c')
-rw-r--r--stc/stc.c440
1 files changed, 431 insertions, 9 deletions
diff --git a/stc/stc.c b/stc/stc.c
index 589f13c..7197f4b 100644
--- a/stc/stc.c
+++ b/stc/stc.c
@@ -25,6 +25,8 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <termios.h>
+#include <unistd.h>
#include "stc.h"
@@ -285,6 +287,9 @@ handle_command_list (gint *argc,
const gchar *target;
const gchar *const *options;
const gchar *const *deps;
+ const gchar *const *slave_devices;
+ const gchar *device;
+ const gchar *mount_path;
type = stc_item_get_item_type (item);
id = stc_item_get_id (item);
@@ -387,6 +392,47 @@ handle_command_list (gint *argc,
enum_to_str (STC_TYPE_ITEM_STATE, stc_item_get_state (item)),
_color_get (_COLOR_RESET));
+ slave_devices = stc_item_get_slave_devices (item);
+ device = stc_item_get_device (item);
+ mount_path = stc_item_get_mount_path (item);
+ if (slave_devices != NULL)
+ {
+ g_print (" %sSlave Devices:%s ",
+ _color_get (_COLOR_FG_WHITE),
+ _color_get (_COLOR_RESET));
+ for (n = 0; slave_devices[n] != NULL; n++)
+ {
+ if (n != 0)
+ g_print ("\n ");
+ g_print ("%s%s%s%s",
+ _color_get (_COLOR_FG_YELLOW),
+ _color_get (_COLOR_BOLD_ON),
+ slave_devices[n],
+ _color_get (_COLOR_RESET));
+ }
+ g_print ("\n");
+ }
+ if (device != NULL)
+ {
+ g_print (" %sDevice:%s %s%s%s%s\n",
+ _color_get (_COLOR_FG_WHITE),
+ _color_get (_COLOR_RESET),
+ _color_get (_COLOR_FG_YELLOW),
+ _color_get (_COLOR_BOLD_ON),
+ device,
+ _color_get (_COLOR_RESET));
+ }
+ if (mount_path != NULL)
+ {
+ g_print (" %sMount Path:%s %s%s%s%s\n",
+ _color_get (_COLOR_FG_WHITE),
+ _color_get (_COLOR_RESET),
+ _color_get (_COLOR_FG_YELLOW),
+ _color_get (_COLOR_BOLD_ON),
+ mount_path,
+ _color_get (_COLOR_RESET));
+ }
+
g_print ("\n");
}
g_list_foreach (items, (GFunc) g_object_unref, NULL);
@@ -403,6 +449,384 @@ handle_command_list (gint *argc,
/* ---------------------------------------------------------------------------------------------------- */
+static gchar *
+ask_user (const gchar *info,
+ const gchar *prompt,
+ gboolean echo_on)
+{
+ gchar *ret;
+ const gchar *tty_name;
+ GString *str;
+ FILE *tty;
+ struct termios ts, ots;
+
+ ret = NULL;
+ tty = NULL;
+
+ if (!_color_stdin_is_tty)
+ goto out;
+
+ tty_name = ctermid (NULL);
+ if (tty_name == NULL)
+ goto out;
+
+ tty = fopen (tty_name, "r+");
+ if (tty == NULL)
+ goto out;
+
+ fprintf (tty, "%s", info);
+ fprintf (tty, "%s", prompt);
+ fflush (tty);
+
+ setbuf (tty, NULL);
+
+ /* TODO: We really ought to block SIGINT and STGSTP (and probably
+ * other signals too) so we can restore the terminal (since we
+ * turn off echoing). See e.g. Advanced Programming in the
+ * UNIX Environment 2nd edition (Steves and Rago) section
+ * 18.10, pg 660 where this is suggested. See also various
+ * getpass(3) implementations
+ *
+ * Anyway, On modern Linux not doing this doesn't seem to be a
+ * problem - looks like modern shells restore echoing anyway
+ * on the first input. So maybe it's not even worth solving
+ * the problem.
+ */
+
+ if (!echo_on)
+ {
+ tcgetattr (fileno (tty), &ts);
+ ots = ts;
+ ts.c_lflag &= ~(ECHO | ECHOE | ECHOK | ECHONL);
+ tcsetattr (fileno (tty), TCSAFLUSH, &ts);
+ }
+
+ str = g_string_new (NULL);
+ while (TRUE)
+ {
+ gint c;
+ c = getc (tty);
+ if (c == '\n')
+ {
+ /* ok, done */
+ break;
+ }
+ else if (c == EOF)
+ {
+ if (!echo_on)
+ {
+ tcsetattr (fileno (tty), TCSAFLUSH, &ots);
+ }
+ g_error ("Got unexpected EOF while reading from controlling terminal.");
+ abort ();
+ break;
+ }
+ else
+ {
+ g_string_append_c (str, c);
+ }
+ }
+ if (!echo_on)
+ {
+ tcsetattr (fileno (tty), TCSAFLUSH, &ots);
+ }
+ putc ('\n', tty);
+
+ ret = g_strdup (str->str);
+
+ memset (str->str, '\0', str->len);
+ g_string_free (str, TRUE);
+
+ out:
+ if (tty != NULL)
+ fclose (tty);
+
+ return ret;
+}
+
+static gboolean
+on_may_start_degraded (StcOperation *operation,
+ StcItem *item,
+ gpointer user_data)
+{
+ gboolean ret;
+ gchar *s;
+ GString *str;
+ const gchar *const *slave_devices;
+ guint num_slave_devices;
+ guint n;
+
+ ret = FALSE;
+
+ slave_devices = stc_item_get_slave_devices (item);
+ g_assert (slave_devices != NULL);
+ num_slave_devices = g_strv_length ((gchar **) slave_devices);
+ g_assert_cmpint (num_slave_devices, >, 0);
+ str = g_string_new (NULL);
+ g_string_append_printf (str,
+ "Item %s%s%s%s of type %s%s%s%s can only start degraded (",
+ _color_get (_COLOR_FG_BLUE),
+ _color_get (_COLOR_BOLD_ON),
+ stc_item_get_id (item),
+ _color_get (_COLOR_RESET),
+ _color_get (_COLOR_FG_CYAN),
+ _color_get (_COLOR_BOLD_ON),
+ enum_to_str (STC_TYPE_ITEM_TYPE, stc_item_get_item_type (item)),
+ _color_get (_COLOR_RESET));
+ for (n = 0; n < num_slave_devices; n++)
+ {
+ if (n > 0)
+ g_string_append (str, ", ");
+ g_string_append_printf (str,
+ "%s%s%s%s",
+ _color_get (_COLOR_FG_YELLOW),
+ _color_get (_COLOR_BOLD_ON),
+ slave_devices[n],
+ _color_get (_COLOR_RESET));
+ }
+ g_string_append (str, ")\n");
+ s = ask_user (str->str,
+ "OK to start degraded (yes/no)? ",
+ TRUE);
+
+ for (n = 0; s[n] != 0; n++)
+ s[n] = g_ascii_tolower (s[n]);
+ if (g_strcmp0 (s, "yes") == 0)
+ ret = TRUE;
+ g_free (s);
+
+ g_string_free (str, TRUE);
+
+ return ret;
+}
+
+static gchar *
+on_request_passphrase (StcOperation *operation,
+ StcItem *item,
+ gpointer user_data)
+{
+ gchar *ret;
+ GString *str;
+ const gchar *const *slave_devices;
+ guint num_slave_devices;
+ guint n;
+
+ ret = NULL;
+
+ slave_devices = stc_item_get_slave_devices (item);
+ g_assert (slave_devices != NULL);
+ num_slave_devices = g_strv_length ((gchar **) slave_devices);
+ g_assert_cmpint (num_slave_devices, >, 0);
+ str = g_string_new (NULL);
+ g_string_append_printf (str,
+ "Passphrase needed for item %s%s%s%s of type %s%s%s%s (",
+ _color_get (_COLOR_FG_BLUE),
+ _color_get (_COLOR_BOLD_ON),
+ stc_item_get_id (item),
+ _color_get (_COLOR_RESET),
+ _color_get (_COLOR_FG_CYAN),
+ _color_get (_COLOR_BOLD_ON),
+ enum_to_str (STC_TYPE_ITEM_TYPE, stc_item_get_item_type (item)),
+ _color_get (_COLOR_RESET));
+ for (n = 0; n < num_slave_devices; n++)
+ {
+ if (n > 0)
+ g_string_append (str, ", ");
+ g_string_append_printf (str,
+ "%s%s%s%s",
+ _color_get (_COLOR_FG_YELLOW),
+ _color_get (_COLOR_BOLD_ON),
+ slave_devices[n],
+ _color_get (_COLOR_RESET));
+ }
+ g_string_append (str, ")\n");
+ ret = ask_user (str->str,
+ "Passphrase: ",
+ FALSE);
+ g_string_free (str, TRUE);
+ return ret;
+}
+
+
+
+static gchar *opt_start_stop_id = NULL;
+
+static const GOptionEntry command_start_stop_entries[] =
+{
+ { "id", 'i', 0, G_OPTION_ARG_STRING, &opt_start_stop_id, "Configuration item", NULL},
+ { NULL }
+};
+
+static gint
+handle_command_start_stop (gint *argc,
+ gchar **argv[],
+ gboolean request_completion,
+ const gchar *completion_cur,
+ const gchar *completion_prev,
+ gboolean is_start)
+{
+ gint ret;
+ GOptionContext *o;
+ gchar *s;
+ StcMonitor *monitor;
+ StcItem *item;
+ GList *items;
+ GList *l;
+ gboolean complete_ids;
+ GError *error;
+ StcOperation *operation;
+
+ ret = 1;
+ monitor = NULL;
+ item = NULL;
+ opt_start_stop_id = NULL;
+ operation = NULL;
+
+ modify_argv0_for_command (argc, argv, is_start ? "start" : "stop");
+
+ o = g_option_context_new (NULL);
+ if (request_completion)
+ g_option_context_set_ignore_unknown_options (o, TRUE);
+ g_option_context_set_help_enabled (o, FALSE);
+ g_option_context_set_summary (o, is_start ? "Start configuration item." : "Stop configuration item");
+ g_option_context_add_main_entries (o, command_start_stop_entries, NULL /* GETTEXT_PACKAGE*/);
+
+ complete_ids = FALSE;
+ if (request_completion && (g_strcmp0 (completion_prev, "--id") == 0 || g_strcmp0 (completion_prev, "-i") == 0))
+ {
+ complete_ids = TRUE;
+ remove_arg ((*argc) - 1, argc, argv);
+ }
+
+ if (!g_option_context_parse (o, argc, argv, NULL))
+ {
+ if (!request_completion)
+ {
+ s = g_option_context_get_help (o, FALSE, NULL);
+ g_printerr ("%s", s);
+ g_free (s);
+ goto out;
+ }
+ }
+
+ if (request_completion &&
+ (opt_start_stop_id == NULL && !complete_ids))
+ {
+ g_print ("--id \n");
+ }
+
+ monitor = stc_monitor_new (error_handler, NULL);
+
+ if (complete_ids)
+ {
+ items = stc_monitor_get_items (monitor);
+ for (l = items; l != NULL; l = l->next)
+ {
+ StcItem *item = STC_ITEM (l->data);
+ StcItemState state;
+ state = stc_item_get_state (item);
+ if (is_start)
+ {
+ if (state == STC_ITEM_STATE_CAN_START_DEPENDENCIES ||
+ state == STC_ITEM_STATE_CAN_START_DEGRADED ||
+ state == STC_ITEM_STATE_CAN_START)
+ {
+ g_print ("%s \n", stc_item_get_id (item));
+ }
+ }
+ else
+ {
+ if (state == STC_ITEM_STATE_STARTED)
+ {
+ g_print ("%s \n", stc_item_get_id (item));
+ }
+ }
+ }
+ g_list_foreach (items, (GFunc) g_object_unref, NULL);
+ g_list_free (items);
+ }
+
+ /* done with completion */
+ if (request_completion)
+ goto out;
+
+ if (opt_start_stop_id != NULL)
+ {
+ item = stc_monitor_get_item_by_id (monitor, opt_start_stop_id);
+ if (item == NULL)
+ {
+ g_printerr ("Error looking up item with id %s\n", opt_start_stop_id);
+ goto out;
+ }
+ }
+ else
+ {
+ s = g_option_context_get_help (o, FALSE, NULL);
+ g_printerr ("%s", s);
+ g_free (s);
+ goto out;
+ }
+
+ operation = stc_operation_new ();
+ g_signal_connect (operation,
+ "may-start-degraded",
+ G_CALLBACK (on_may_start_degraded),
+ NULL);
+ g_signal_connect (operation,
+ "request-passphrase",
+ G_CALLBACK (on_request_passphrase),
+ NULL);
+
+ if (is_start)
+ {
+ error = NULL;
+ if (!stc_item_start_sync (item,
+ operation,
+ NULL, /* GCancellable* */
+ &error))
+ {
+ g_printerr ("Error starting configuration item with id %s: %s (%s, %d)\n",
+ stc_item_get_id (item),
+ error->message,
+ g_quark_to_string (error->domain),
+ error->code);
+ g_error_free (error);
+ goto out;
+ }
+ }
+ else
+ {
+ error = NULL;
+ if (!stc_item_stop_sync (item,
+ operation,
+ NULL, /* GCancellable* */
+ &error))
+ {
+ g_printerr ("Error stopping configuration item with id %s: %s (%s, %d)\n",
+ stc_item_get_id (item),
+ error->message,
+ g_quark_to_string (error->domain),
+ error->code);
+ g_error_free (error);
+ goto out;
+ }
+ }
+
+ ret = 0;
+
+ out:
+ if (operation != NULL)
+ g_object_unref (operation);
+ if (item != NULL)
+ g_object_unref (item);
+ if (monitor != NULL)
+ g_object_unref (monitor);
+ g_option_context_free (o);
+ return ret;
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
static void
usage (gint *argc, gchar **argv[], gboolean use_stdout)
{
@@ -419,8 +843,8 @@ usage (gint *argc, gchar **argv[], gboolean use_stdout)
" help Shows this information\n"
//" info Shows information about an object\n"
" list Lists all configuration entries\n"
- //" apply Mount a device\n"
- //" unapply Unmount a device\n"
+ " start Start (e.g. mount/assemble) a configuration item\n"
+ " stop Stop (e.g. unmount/disassemble) a configuration item\n"
"\n"
"Use \"%s COMMAND --help\" to get help on each command.\n",
program_name);
@@ -576,18 +1000,16 @@ main (int argc, char *argv[])
completion_prev);
goto out;
}
-#if 0
- else if (g_strcmp0 (command, "apply") == 0 || g_strcmp0 (command, "unapply") == 0)
+ else if (g_strcmp0 (command, "start") == 0 || g_strcmp0 (command, "stop") == 0)
{
- ret = handle_command_apply_unapply (&argc,
+ ret = handle_command_start_stop (&argc,
&argv,
request_completion,
completion_cur,
completion_prev,
- g_strcmp0 (command, "apply") == 0);
+ g_strcmp0 (command, "start") == 0);
goto out;
}
-#endif
else if (g_strcmp0 (command, "complete") == 0 && argc == 4 && !request_completion)
{
const gchar *completion_line;
@@ -656,8 +1078,8 @@ main (int argc, char *argv[])
g_print ("help \n"
//"info \n"
"list \n"
- //"apply \n"
- //"unapply \n"
+ "start \n"
+ "stop \n"
);
ret = 0;
goto out;