X-Git-Url: http://git.tuebingen.mpg.de/?p=paraslash.git;a=blobdiff_plain;f=gui.c;h=61ce0432856304f065e2720d273b07454040a367;hp=9b7c2f992520896f2ae33918854604b37bbc7720;hb=aa581f6e3f8cb9e007de97c6d3f25b2ff9b6533d;hpb=ccd288cee4d15e54640d87c1451b46c3ff0e2591 diff --git a/gui.c b/gui.c index 9b7c2f99..61ce0432 100644 --- a/gui.c +++ b/gui.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 1998-2014 Andre Noll + * Copyright (C) 1998-2014 Andre Noll * * Licensed under the GPL v2. For licencing details see COPYING. */ @@ -124,11 +124,12 @@ GUI_COMMANDS static struct gui_command command_list[] = {GUI_COMMANDS {.name = NULL}}; struct input_task { - struct task task; + struct task *task; }; struct status_task { - struct task task; + struct task *task; + pid_t pid; char *buf; int bufsize, loaded; struct timeval next_exec; @@ -139,7 +140,7 @@ struct status_task { #define COMMAND_BUF_SIZE 32768 struct exec_task { - struct task task; + struct task *task; char command_buf[2][COMMAND_BUF_SIZE]; /* stdout/stderr of command */ int cbo[2]; /* command buf offsets */ unsigned flags[2]; /* passed to for_each_line() */ @@ -596,29 +597,42 @@ static void clear_all_items(void) } } -static void status_pre_select(struct sched *s, struct task *t) +static void status_pre_select(struct sched *s, void *context) { - struct status_task *st = container_of(t, struct status_task, task); + struct status_task *st = context; if (st->fd >= 0) - return para_fd_set(st->fd, &s->rfds, &s->max_fileno); - sched_request_barrier_or_min_delay(&st->next_exec, s); + 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, struct task *t) +static int status_post_select(struct sched *s, void *context) { - struct status_task *st = container_of(t, struct status_task, task); + struct status_task *st = context; size_t sz; - pid_t pid; 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(&pid, conf.stat_cmd_arg, fds); + ret = para_exec_cmdline_pid(&st->pid, conf.stat_cmd_arg, fds); if (ret < 0) return 0; ret = mark_fd_nonblocking(fds[1]); @@ -672,7 +686,7 @@ static void init_wins(int top_lines) int bot_lines = LINES - top_lines - 3, sb_lines = 1, in_lines = 1, sep_lines = 1; - assume_default_colors(theme.default_fg, theme.default_bg); + assume_default_colors(theme.dflt.fg, theme.dflt.bg); if (top.win) { wresize(top.win, top_lines, COLS); mvwin(top.win, top_y, 0); @@ -744,16 +758,16 @@ static void init_colors_or_die(void) die(EXIT_FAILURE, "fatal: failed to start colors\n"); FOR_EACH_STATUS_ITEM(i) if (theme.data[i].len) - init_pair_or_die(i + 1, theme.data[i].fg, - theme.data[i].bg); - init_pair_or_die(COLOR_STATUSBAR, theme.sb_fg, theme.sb_bg); - init_pair_or_die(COLOR_COMMAND, theme.cmd_fg, theme.cmd_bg); - init_pair_or_die(COLOR_OUTPUT, theme.output_fg, theme.output_bg); - init_pair_or_die(COLOR_MSG, theme.msg_fg, theme.msg_bg); - init_pair_or_die(COLOR_ERRMSG, theme.err_msg_fg, theme.err_msg_bg); - init_pair_or_die(COLOR_SEPARATOR, theme.sep_fg, theme.sep_bg); - init_pair_or_die(COLOR_TOP, theme.default_fg, theme.default_bg); - init_pair_or_die(COLOR_BOT, theme.default_fg, theme.default_bg); + init_pair_or_die(i + 1, theme.data[i].color.fg, + theme.data[i].color.bg); + init_pair_or_die(COLOR_STATUSBAR, theme.sb.fg, theme.sb.bg); + init_pair_or_die(COLOR_COMMAND, theme.cmd.fg, theme.cmd.bg); + init_pair_or_die(COLOR_OUTPUT, theme.output.fg, theme.output.bg); + init_pair_or_die(COLOR_MSG, theme.msg.fg, theme.msg.bg); + init_pair_or_die(COLOR_ERRMSG, theme.err_msg.fg, theme.err_msg.bg); + init_pair_or_die(COLOR_SEPARATOR, theme.sep.fg, theme.sep.bg); + init_pair_or_die(COLOR_TOP, theme.dflt.fg, theme.dflt.bg); + init_pair_or_die(COLOR_BOT, theme.dflt.fg, theme.dflt.bg); } /* (Re-)initialize the curses library. */ @@ -781,23 +795,6 @@ static void init_curses(void) // noecho(); /* don't echo input */ } -static void check_sigchld(void) -{ - int ret; - pid_t pid; - -reap_next_child: - ret = para_reap_child(&pid); - if (ret <= 0) - return; - if (pid == exec_pid) { - exec_pid = 0; - init_curses(); - print_in_bar(COLOR_MSG, " "); - } - goto reap_next_child; -} - /* * This sucker modifies its first argument. *handler and *arg are * pointers to 0-terminated strings (inside line). Crap. @@ -876,12 +873,12 @@ static void parse_config_file_or_die(bool override) gui_cmdline_parser_config_file(config_file, &conf, ¶ms); loglevel = get_loglevel_by_name(conf.loglevel_arg); check_key_map_args_or_die(); - theme_init(conf.theme_arg, &theme); err = false; out: free(config_file); if (err) exit(EXIT_FAILURE); + theme_init(conf.theme_arg, &theme); } /* reread configuration, terminate on errors */ @@ -900,7 +897,7 @@ static void reread_conf(void) /* * React to various signal-related events */ -static int signal_post_select(struct sched *s, __a_unused struct task *t) +static int signal_post_select(struct sched *s, __a_unused void *context) { int ret = para_next_signal(&s->rfds); @@ -910,13 +907,6 @@ static int signal_post_select(struct sched *s, __a_unused struct task *t) case SIGTERM: die(EXIT_FAILURE, "only the good die young (caught SIGTERM)\n"); return 1; - case SIGWINCH: - if (curses_active()) { - shutdown_curses(); - init_curses(); - redraw_bot_win(); - } - return 1; case SIGINT: PARA_WARNING_LOG("caught SIGINT, reset\n"); /* Nothing to do. SIGINT killed our child which gets noticed @@ -928,7 +918,7 @@ static int signal_post_select(struct sched *s, __a_unused struct task *t) reread_conf(); return 1; case SIGCHLD: - check_sigchld(); + task_notify_all(s, E_GUI_SIGCHLD); return 1; } return 1; @@ -943,26 +933,32 @@ static enum exec_status exec_status(void) return EXEC_IDLE; } -static void exec_pre_select(struct sched *s, __a_unused struct task *t) +static void exec_pre_select(struct sched *s, void *context) { - enum exec_status es = exec_status(); - - if (es != EXEC_DCMD) - return; + struct exec_task *et = context; if (exec_fds[0] >= 0) para_fd_set(exec_fds[0], &s->rfds, &s->max_fileno); if (exec_fds[1] >= 0) para_fd_set(exec_fds[1], &s->rfds, &s->max_fileno); + if (task_get_notification(et->task) < 0) + sched_min_delay(s); } -static int exec_post_select(struct sched *s, struct task *t) +static int exec_post_select(struct sched *s, void *context) { - struct exec_task *ct = container_of(t, struct exec_task, task); + struct exec_task *ct = context; int i, ret; - enum exec_status es = exec_status(); - if (es != EXEC_DCMD) - return 0; + ret = task_get_notification(ct->task); + if (ret == -E_GUI_SIGCHLD && exec_pid > 0) { + int exit_status; + if (waitpid(exec_pid, &exit_status, WNOHANG) == exec_pid) { + exec_pid = 0; + init_curses(); + PARA_INFO_LOG("command exit status: %d", exit_status); + print_in_bar(COLOR_MSG, " "); + } + } for (i = 0; i < 2; i++) { size_t sz; if (exec_fds[i] < 0) @@ -998,7 +994,7 @@ static int exec_post_select(struct sched *s, struct task *t) return 0; } -static void input_pre_select(struct sched *s, __a_unused struct task *t) +static void input_pre_select(struct sched *s, __a_unused void *context) { if (exec_status() != EXEC_XCMD) para_fd_set(STDIN_FILENO, &s->rfds, &s->max_fileno); @@ -1095,7 +1091,7 @@ static void handle_command(int c) km_keyname(c)); } -static int input_post_select(__a_unused struct sched *s, __a_unused struct task *t) +static int input_post_select(__a_unused struct sched *s, __a_unused void *context) { int ret; enum exec_status exs = exec_status(); @@ -1118,20 +1114,26 @@ static int input_post_select(__a_unused struct sched *s, __a_unused struct task in.needs_update = sep.needs_update = false; } ret = wgetch(top.win); - if (ret == ERR || ret == KEY_RESIZE) + if (ret == ERR) return 0; - if (exs == EXEC_IDLE) { - handle_command(ret); + if (ret == KEY_RESIZE) { + if (curses_active()) { + shutdown_curses(); + init_curses(); + redraw_bot_win(); + } return 0; } - if (exec_pid != 0) + if (exs == EXEC_IDLE) + handle_command(ret); + else if (exec_pid > 0) kill(exec_pid, SIGTERM); return 0; } -static void signal_pre_select(struct sched *s, struct task *t) +static void signal_pre_select(struct sched *s, void *context) { - struct signal_task *st = container_of(t, struct signal_task, task); + struct signal_task *st = context; para_fd_set(st->fd, &s->rfds, &s->max_fileno); } @@ -1405,52 +1407,49 @@ __noreturn static void print_help_and_die(void) static int setup_tasks_and_schedule(void) { + struct exec_task exec_task = {.task = NULL}; + struct status_task status_task = {.fd = -1}; + struct input_task input_task = {.task = NULL}; + struct signal_task signal_task = {.task = NULL}; struct sched sched = { .default_timeout = { .tv_sec = conf.timeout_arg / 1000, .tv_usec = (conf.timeout_arg % 1000) * 1000, }, }; - struct exec_task exec_task = { - .task = { - .status = "exec", - .pre_select = exec_pre_select, - .post_select = exec_post_select, - }, - }; - struct status_task status_task = { - .task = { - .status = "status", - .pre_select = status_pre_select, - .post_select = status_post_select, - }, - .fd = -1 - }; - struct input_task input_task = { - .task = { - .status = "input", - .pre_select = input_pre_select, - .post_select = input_post_select, - }, - }; - struct signal_task signal_task = { - .task = { - .status = "signal", - .pre_select = signal_pre_select, - .post_select = signal_post_select, - }, - }; + + exec_task.task = task_register(&(struct task_info) { + .name = "exec", + .pre_select = exec_pre_select, + .post_select = exec_post_select, + .context = &exec_task, + }, &sched); + + status_task.task = task_register(&(struct task_info) { + .name = "status", + .pre_select = status_pre_select, + .post_select = status_post_select, + .context = &status_task, + }, &sched); + + input_task.task = task_register(&(struct task_info) { + .name = "input", + .pre_select = input_pre_select, + .post_select = input_post_select, + .context = &input_task, + }, &sched); + signal_task.fd = para_signal_init(); para_install_sighandler(SIGINT); para_install_sighandler(SIGTERM); para_install_sighandler(SIGCHLD); - para_install_sighandler(SIGWINCH); para_install_sighandler(SIGUSR1); - - register_task(&sched, &exec_task.task); - register_task(&sched, &status_task.task); - register_task(&sched, &input_task.task); - register_task(&sched, &signal_task.task); + signal_task.task = task_register(&(struct task_info) { + .name = "signal", + .pre_select = signal_pre_select, + .post_select = signal_post_select, + .context = &signal_task, + }, &sched); return schedule(&sched); }