+static int do_select(int mode);
+
+/* read from command pipe and print data to bot window */
+static void exec_and_display_cmd(const char *cmd)
+{
+ int ret, fds[3] = {0, 1, 1};
+
+ outputf(COLOR_COMMAND, "%s", cmd);
+ ret = para_exec_cmdline_pid(&cmd_pid, cmd, fds);
+ if (ret < 0)
+ return;
+ ret = mark_fd_nonblocking(fds[1]);
+ if (ret < 0)
+ goto fail;
+ ret = mark_fd_nonblocking(fds[2]);
+ if (ret < 0)
+ goto fail;
+ command_fds[0] = fds[1];
+ command_fds[1] = fds[2];
+ if (do_select(COMMAND_MODE) >= 0)
+ PARA_INFO_LOG("command complete\n");
+ else
+ PARA_NOTICE_LOG("command aborted\n");
+ print_in_bar(COLOR_MSG, " ");
+ return;
+fail:
+ PARA_ERROR_LOG("%s\n", para_strerror(-ret));
+ close(command_fds[0]);
+ close(command_fds[1]);
+}
+
+static void para_cmd(char *cmd)
+{
+ char *c;
+
+ print_in_bar(COLOR_MSG, "executing client command, hit any key to abort\n");
+ c = make_message(BINDIR "/para_client -- %s", cmd);
+ exec_and_display_cmd(c);
+ free(c);
+}
+
+static void display_cmd(char *cmd)
+{
+ print_in_bar(COLOR_MSG, "executing display command, hit any key to abort");
+ exec_and_display_cmd(cmd);
+}
+
+/*
+ * shutdown curses and stat pipe before executing external commands
+ */
+static void external_cmd(char *cmd)
+{
+ int fds[3] = {-1, -1, -1};
+
+ if (cmd_pid)
+ return;
+ shutdown_curses();
+ if (para_exec_cmdline_pid(&cmd_pid, cmd, fds) < 0)
+ return;
+ do_select(EXTERNAL_MODE);
+ init_curses();
+}
+
+static void handle_command(int c)
+{
+ int i;
+
+ /* first check user-defined key bindings */
+ for (i = 0; i < conf.key_map_given; ++i) {
+ char *tmp, *handler, *arg;
+
+ tmp = para_strdup(conf.key_map_arg[i]);
+ if (!split_key_map(tmp, &handler, &arg)) {
+ free(tmp);
+ return;
+ }
+ if (strcmp(tmp, km_keyname(c))) {
+ free(tmp);
+ continue;
+ }
+ if (*handler == 'd')
+ display_cmd(arg);
+ else if (*handler == 'x')
+ external_cmd(arg);
+ else if (*handler == 'p')
+ para_cmd(arg);
+ else if (*handler == 'i') {
+ int num = find_cmd_byname(arg);
+ if (num >= 0)
+ command_list[num].handler();
+ }
+ free(tmp);
+ return;
+ }
+ /* not found, check internal key bindings */
+ for (i = 0; command_list[i].handler; i++) {
+ if (!strcmp(km_keyname(c), command_list[i].key)) {
+ command_list[i].handler();
+ return;
+ }
+ }
+ print_in_bar(COLOR_ERRMSG, "key '%s' is not bound, press ? for help",
+ km_keyname(c));
+}
+