+static void status_pre_select(struct sched *s, void *context)
+{
+ struct status_task *st = context;
+
+ if (st->fd >= 0)
+ para_fd_set(st->fd, &s->rfds, &s->max_fileno);
+ if (task_get_notification(st->task) < 0)
+ return sched_min_delay(s);
+ if (st->fd < 0)
+ sched_request_barrier_or_min_delay(&st->next_exec, s);
+}
+
+static int status_post_select(struct sched *s, void *context)
+{
+ struct status_task *st = context;
+ size_t sz;
+ int ret, ret2;
+
+ ret = task_get_notification(st->task);
+ if (ret == -E_GUI_SIGCHLD && st->pid > 0) {
+ int exit_status;
+ if (waitpid(st->pid, &exit_status, WNOHANG) == st->pid) {
+ st->pid = 0;
+ PARA_ERROR_LOG("stat command exit status: %d",
+ exit_status);
+ }
+ }
+ if (st->fd < 0) {
+ int fds[3] = {0, 1, 0};
+ if (st->pid > 0)
+ return 0;
+ /* Avoid busy loop */
+ if (tv_diff(&st->next_exec, now, NULL) > 0)
+ return 0;
+ st->next_exec.tv_sec = now->tv_sec + 2;
+ ret = para_exec_cmdline_pid(&st->pid, conf.stat_cmd_arg, fds);
+ if (ret < 0)
+ return 0;
+ ret = mark_fd_nonblocking(fds[1]);
+ if (ret < 0) {
+ close(fds[1]);
+ return 0;
+ }
+ st->fd = fds[1];
+ return 0;
+ }
+
+ if (st->loaded >= st->bufsize) {
+ if (st->bufsize > 1000 * 1000) {
+ st->loaded = 0;
+ return 0;
+ }
+ st->bufsize += st->bufsize + 1000;
+ st->buf = para_realloc(st->buf, st->bufsize);
+ }
+ assert(st->loaded < st->bufsize);
+ ret = read_nonblock(st->fd, st->buf + st->loaded,
+ st->bufsize - st->loaded, &s->rfds, &sz);
+ st->loaded += sz;
+ ret2 = for_each_stat_item(st->buf, st->loaded, update_item);
+ if (ret < 0 || ret2 < 0) {
+ st->loaded = 0;
+ PARA_NOTICE_LOG("closing stat pipe: %s\n",
+ para_strerror(ret < 0? -ret : -ret2));
+ close(st->fd);
+ st->fd = -1;
+ clear_all_items();
+ free(stat_content[SI_BASENAME]);
+ stat_content[SI_BASENAME] =
+ para_strdup("stat command terminated!?");
+ print_all_items();
+ return 0;
+ }
+ sz = ret2; /* what is left */
+ if (sz > 0 && sz < st->loaded)
+ memmove(st->buf, st->buf + st->loaded - sz, sz);
+ st->loaded = sz;
+ return 0;
+}
+
+/*
+ * init all windows
+ */
+static void init_wins(int top_lines)
+{
+ int top_y = 0, bot_y = top_lines + 1, sb_y = LINES - 2,
+ in_y = LINES - 1, sep_y = top_lines;
+ int bot_lines = LINES - top_lines - 3, sb_lines = 1, in_lines = 1,
+ sep_lines = 1;
+
+ assume_default_colors(theme.dflt.fg, theme.dflt.bg);
+ if (top.win) {
+ wresize(top.win, top_lines, COLS);
+ mvwin(top.win, top_y, 0);
+
+ wresize(sb.win, sb_lines, COLS);
+ mvwin(sb.win, sb_y, 0);
+
+ wresize(sep.win, sep_lines, COLS);
+ mvwin(sep.win, sep_y, 0);
+
+ wresize(bot.win, bot_lines, COLS);
+ mvwin(bot.win, bot_y, 0);
+
+ wresize(in.win, in_lines, COLS);
+ mvwin(in.win, in_y, 0);
+ } else {
+ sep.win = newwin(sep_lines, COLS, sep_y, 0);
+ top.win = newwin(top_lines, COLS, top_y, 0);
+ bot.win = newwin(bot_lines, COLS, bot_y, 0);
+ sb.win = newwin(sb_lines, COLS, sb_y, 0);
+ in.win = newwin(in_lines, COLS, in_y, 0);
+ if (!top.win || !bot.win || !sb.win || !in.win || !sep.win)
+ die(EXIT_FAILURE, "Error: Cannot create curses windows\n");
+ wclear(bot.win);
+ wclear(sb.win);
+ wclear(in.win);
+ scrollok(bot.win, 1);
+ wattron(sb.win, COLOR_PAIR(COLOR_STATUSBAR));
+ wattron(sep.win, COLOR_PAIR(COLOR_SEPARATOR));
+ wattron(bot.win, COLOR_PAIR(COLOR_BOT));
+ wattron(top.win, COLOR_PAIR(COLOR_TOP));
+ nodelay(top.win, 1);
+ nodelay(bot.win, 1);
+ nodelay(sb.win, 1);
+ nodelay(in.win, 0);
+
+ keypad(top.win, 1);
+ keypad(bot.win, 1);
+ keypad(sb.win, 1);
+ keypad(in.win, 1);
+ }
+ wmove(sep.win, 0, 0);
+ whline(sep.win, theme.sep_char, COLS);
+ wclear(top.win);
+ print_all_items();
+ //wclear(bot.win);
+ wnoutrefresh(top.win);
+ wnoutrefresh(bot.win);
+ print_status_bar();
+ wnoutrefresh(sb.win);
+ wnoutrefresh(in.win);
+ wnoutrefresh(sep.win);
+ doupdate();
+}
+