diff options
author | David Zeuthen <davidz@redhat.com> | 2010-10-06 15:13:46 -0400 |
---|---|---|
committer | David Zeuthen <davidz@redhat.com> | 2010-10-06 15:13:46 -0400 |
commit | 1331349d2e97bceaadf8d8cf0b6b5c11c83577a5 (patch) | |
tree | 56cee7e3234b6b2b8a72d4ed561c6b07b267c83b /stc/stc.c | |
parent | d03c35c1d0a486a45e9206267aca155fc4448394 (diff) |
Updates
Signed-off-by: David Zeuthen <davidz@redhat.com>
Diffstat (limited to 'stc/stc.c')
-rw-r--r-- | stc/stc.c | 440 |
1 files changed, 431 insertions, 9 deletions
@@ -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; |