void cli_context_loop (cli_context_t *ctx, gint argc, gchar **argv) { /* Execute command, if connection status is ok */ if (argc == 0) { gchar *filename = configuration_get_string (ctx->config, "HISTORY_FILE"); ctx->mode = CLI_EXECUTION_MODE_SHELL; /* print welcome message before initialising readline */ if (configuration_get_boolean (ctx->config, "SHELL_START_MESSAGE")) { g_printf (_("Welcome to the XMMS2 CLI shell!\n")); g_printf (_("Type 'help' to list the available commands " "and 'exit' (or CTRL-D) to leave the shell.\n")); } readline_resume (ctx); read_history (filename); using_history (); while (!cli_context_in_status (ctx, CLI_ACTION_STATUS_FINISH)) { cli_context_event_loop_select (ctx); } write_history (filename); } else { ctx->mode = CLI_EXECUTION_MODE_INLINE; cli_context_command_or_flag_dispatch (ctx, argc , argv); while (cli_context_in_status (ctx, CLI_ACTION_STATUS_BUSY) || cli_context_in_status (ctx, CLI_ACTION_STATUS_REFRESH)) { cli_context_event_loop_select (ctx); } } }
static gboolean cli_context_command_runnable (cli_context_t *ctx, command_action_t *action) { xmmsc_connection_t *conn = cli_context_xmms_async (ctx); gint n = 0; /* Require connection, abort on failure */ if (COMMAND_REQ_CHECK(action, COMMAND_REQ_CONNECTION) && !conn) { gboolean autostart; autostart = !COMMAND_REQ_CHECK(action, COMMAND_REQ_NO_AUTOSTART); if (!cli_context_connect (ctx, autostart) && autostart) { return FALSE; } } /* Get the cache ready if needed */ if (COMMAND_REQ_CHECK(action, COMMAND_REQ_CACHE)) { /* If executing an alias have to refresh manually */ if (cli_context_in_status (ctx, CLI_ACTION_STATUS_ALIAS)) { cli_context_cache_refresh (ctx); } while (cli_context_cache_refreshing (ctx)) { /* Obviously, there is a problem with updating the cache, abort */ if (n == MAX_CACHE_REFRESH_LOOP) { g_printf (_("Failed to update the cache!")); return FALSE; } cli_context_event_loop_select (ctx); n++; } } return TRUE; }
void cli_context_execute_command (cli_context_t *ctx, gchar *input) { while (input && *input == ' ') ++input; if (input == NULL) { if (!cli_context_in_status (ctx, CLI_ACTION_STATUS_ALIAS)) { /* End of stream, quit */ cli_context_loop_stop (ctx); g_printf ("\n"); } } else if (*input != 0) { gint argc; gchar **argv, *listop; GError *error = NULL; if ((listop = strchr (input, ';'))) { *listop++ = '\0'; } if (g_shell_parse_argv (input, &argc, &argv, &error)) { if (!cli_context_in_status (ctx, CLI_ACTION_STATUS_ALIAS)) { add_history (input); } cli_context_command_dispatch (ctx, argc, argv); g_strfreev (argv); if (listop && *listop) { g_printf ("\n"); cli_context_execute_command (ctx, listop); } } else { g_printf (_("Error: %s\n"), error->message); g_error_free (error); } } }
void readline_status_mode_exit (void) { Keymap active; g_assert (cli_context_in_status (readline_cli_ctx, CLI_ACTION_STATUS_REFRESH)); active = rl_get_keymap (); rl_set_keymap (rl_get_keymap_by_name (readline_keymap)); rl_discard_keymap (active); rl_callback_handler_remove (); g_free (readline_keymap); status_free (cli_context_status_entry (readline_cli_ctx)); // TODO: handle via cli_context_free or somesuch? cli_context_status_mode_exit (readline_cli_ctx); }
static void cli_context_event_loop_select (cli_context_t *ctx) { xmmsc_connection_t *conn = cli_context_xmms_async (ctx); fd_set rfds, wfds; gint modfds; gint xmms2fd; gint maxfds = 0; FD_ZERO(&rfds); FD_ZERO(&wfds); /* Listen to xmms2 if connected */ if (conn) { xmms2fd = xmmsc_io_fd_get (conn); if (xmms2fd == -1) { g_printf (_("Error: failed to retrieve XMMS2 file descriptor!")); return; } FD_SET(xmms2fd, &rfds); if (xmmsc_io_want_out (conn)) { FD_SET(xmms2fd, &wfds); } if (maxfds < xmms2fd) { maxfds = xmms2fd; } } /* Listen to readline in shell mode or status mode */ if ((cli_context_in_mode (ctx, CLI_EXECUTION_MODE_SHELL) && cli_context_in_status (ctx, CLI_ACTION_STATUS_READY)) || cli_context_in_status (ctx, CLI_ACTION_STATUS_REFRESH)) { FD_SET(STDIN_FILENO, &rfds); if (maxfds < STDIN_FILENO) { maxfds = STDIN_FILENO; } } if (cli_context_in_status (ctx, CLI_ACTION_STATUS_REFRESH)) { struct timeval refresh; refresh.tv_sec = cli_context_refresh_interval (ctx); refresh.tv_usec = 0; modfds = select (maxfds + 1, &rfds, &wfds, NULL, &refresh); } else { modfds = select (maxfds + 1, &rfds, &wfds, NULL, NULL); } if (modfds < 0 && errno != EINTR) { g_printf (_("Error: invalid I/O result!")); return; } else if (modfds != 0) { /* Get/send data to xmms2 */ if (conn) { if (FD_ISSET(xmms2fd, &rfds) && !xmmsc_io_in_handle (conn)) { return; } if (FD_ISSET(xmms2fd, &wfds) && !xmmsc_io_out_handle (conn)) { return; } } /* User input found, read it */ if ((cli_context_in_mode (ctx, CLI_EXECUTION_MODE_SHELL) || cli_context_in_status (ctx, CLI_ACTION_STATUS_REFRESH)) && FD_ISSET(STDIN_FILENO, &rfds)) { rl_callback_read_char (); } } /* Status -refresh Ask theefer: use callbacks for update and -refresh only for print? Nesciens: Yes, please! */ if (cli_context_in_status (ctx, CLI_ACTION_STATUS_REFRESH)) { cli_context_refresh_status (ctx); } }