+static void command_pre_select(int mode, fd_set *rfds, int *max_fileno)
+{
+ /* check command pipe only in COMMAND_MODE */
+ if (mode != COMMAND_MODE)
+ return;
+ if (command_fds[0] >= 0)
+ para_fd_set(command_fds[0], rfds, max_fileno);
+ if (command_fds[1] >= 0)
+ para_fd_set(command_fds[1], rfds, max_fileno);
+}
+
+static int command_post_select(int mode, fd_set *rfds)
+{
+ int i, ret;
+ static char command_buf[2][COMMAND_BUF_SIZE];
+ static int cbo[2]; /* command buf offsets */
+ static unsigned flags[2]; /* for for_each_line() */
+
+ if (mode != COMMAND_MODE)
+ return 0;
+ for (i = 0; i < 2; i++) {
+ size_t sz;
+ if (command_fds[i] < 0)
+ continue;
+ ret = read_nonblock(command_fds[i],
+ command_buf[i] + cbo[i],
+ COMMAND_BUF_SIZE - 1 - cbo[i], rfds, &sz);
+ cbo[i] += sz;
+ sz = cbo[i];
+ cbo[i] = for_each_line(flags[i], command_buf[i], cbo[i],
+ add_output_line, &i);
+ if (sz != cbo[i]) { /* at least one line found */
+ wrefresh(bot.win);
+ flags[i] = 0;
+ }
+ if (ret < 0) {
+ PARA_NOTICE_LOG("closing command fd %d: %s",
+ i, para_strerror(-ret));
+ close(command_fds[i]);
+ command_fds[i] = -1;
+ flags[i] = 0;
+ cbo[i] = 0;
+ if (command_fds[!i] < 0) /* both fds closed */
+ return -1;
+ }
+ if (cbo[i] == COMMAND_BUF_SIZE - 1) {
+ PARA_NOTICE_LOG("discarding overlong line");
+ cbo[i] = 0;
+ flags[i] = FELF_DISCARD_FIRST;
+ }
+ }
+ return 1;
+}
+
+static void input_pre_select(int mode, fd_set *rfds, int *max_fileno)
+{
+ if (mode == GETCH_MODE || mode == COMMAND_MODE)
+ para_fd_set(STDIN_FILENO, rfds, max_fileno);
+}
+
+static int input_post_select(int mode)
+{
+ int ret;
+
+ switch (mode) {
+ case COMMAND_MODE:
+ ret = wgetch(top.win);
+ if (ret != ERR && ret != KEY_RESIZE) {
+ if (cmd_pid)
+ kill(cmd_pid, SIGTERM);
+ return -1;
+ }
+ return 0;
+ case GETCH_MODE:
+ ret = wgetch(top.win);
+ if (ret != ERR && ret != KEY_RESIZE)
+ return ret;
+ return 0;
+ case EXTERNAL_MODE:
+ if (cmd_pid == 0)
+ return -1;
+ return 0;
+ default:
+ assert(false); /* bug */
+ }
+}
+