write: Make get_btr_value() return void.
[paraslash.git] / gui.c
diff --git a/gui.c b/gui.c
index 5b44819c05afc074fadca3a5a7d5c1ece9fe8b8f..865ed658afc4197f4ba29ce5344be38fcbd48bad 100644 (file)
--- a/gui.c
+++ b/gui.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 1998-2009 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 1998-2010 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
@@ -54,7 +54,7 @@ static int cmd_died, curses_active;
 static pid_t cmd_pid;
 
 static int command_pipe = -1;
-static int audiod_pipe = -1;
+static int stat_pipe = -1;
 static struct gui_args_info conf;
 
 enum {GETCH_MODE, COMMAND_MODE, EXTERNAL_MODE};
@@ -191,20 +191,6 @@ static struct gui_command command_list[] = {
        }
 };
 
-static int para_open_audiod_pipe(char *cmd)
-{
-       int fds[3] = {0, 1, 0};
-       pid_t pid;
-       int ret = para_exec_cmdline_pid(&pid, cmd, fds);
-       if (ret < 0)
-               return ret;
-       ret = mark_fd_nonblocking(fds[1]);
-       if (ret > 0)
-               return fds[1];
-       close(fds[1]);
-       return ret;
-}
-
 static int find_cmd_byname(char *name)
 {
        int i;
@@ -308,9 +294,9 @@ static int align_str(WINDOW* win, char *str, unsigned int len,
                str[len] = '\0';
                num = 0;
        }
-       /* replace newlines by spaces */
+       /* replace control characters by spaces */
        for (i = 0; i < len && str[i]; i++) {
-               if (str[i] == '\n')
+               if (str[i] == '\n' || str[i] == '\r' || str[i] == '\f')
                        str[i] = ' ';
        }
        if (align == LEFT) {
@@ -708,12 +694,15 @@ print:
        return 1;
 }
 
-static int read_audiod_pipe(int fd)
+static int read_stat_pipe(fd_set *rfds)
 {
        static char *buf;
        static int bufsize, loaded;
-       int ret;
+       int ret, ret2;
+       size_t sz;
 
+       if (stat_pipe < 0)
+               return 0;
        if (loaded >= bufsize) {
                if (bufsize > 1000 * 1000) {
                        loaded = 0;
@@ -723,14 +712,18 @@ static int read_audiod_pipe(int fd)
                buf = para_realloc(buf, bufsize);
        }
        assert(loaded < bufsize);
-       ret = read(fd, buf + loaded, bufsize - loaded);
-       if (ret <= 0)
-               return ret;
-       loaded += ret;
-       ret = for_each_stat_item(buf, loaded, update_item);
-       if (ret < 0)
-               return ret;
-       loaded = ret;
+       ret = read_nonblock(stat_pipe, buf + loaded, bufsize - loaded,
+               rfds, &sz);
+       loaded += sz;
+       ret2 = for_each_stat_item(buf, loaded, update_item);
+       if (ret < 0 || ret2 < 0) {
+               loaded = 0;
+               return ret2 < 0? ret2 : ret;
+       }
+       sz = ret2; /* what is left */
+       if (sz > 0 && sz < loaded)
+               memmove(buf, buf + loaded - sz, sz);
+       loaded = sz;
        return 1;
 }
 
@@ -900,15 +893,30 @@ static void handle_signal(int sig)
        }
 }
 
-static int open_audiod_pipe(void)
+static int open_stat_pipe(void)
 {
        static int init = 1;
+       int ret, fds[3] = {0, 1, 0};
+       pid_t pid;
 
        if (init)
                init = 0;
        else
-               sleep(1);
-       return para_open_audiod_pipe(conf.stat_cmd_arg);
+               /*
+                * Sleep a bit to avoid a busy loop. As the call to sleep() may
+                * be interrupted by SIGCHLD, we simply wait until the call
+                * succeeds.
+                */
+               while (sleep(2))
+                       ; /* nothing */
+       ret = para_exec_cmdline_pid(&pid, conf.stat_cmd_arg, fds);
+       if (ret < 0)
+               return ret;
+       ret = mark_fd_nonblocking(fds[1]);
+       if (ret >= 0)
+               return fds[1];
+       close(fds[1]);
+       return ret;
 }
 
 /*
@@ -929,7 +937,7 @@ static int do_select(int mode)
 {
        fd_set rfds;
        int ret;
-       int max_fileno, cp_numread = 1;
+       int max_fileno;
        char command_buf[4096] = "";
        int cbo = 0; /* command buf offset */
        struct timeval tv;
@@ -939,11 +947,10 @@ repeat:
 //     ret = refresh_status();
        FD_ZERO(&rfds);
        max_fileno = 0;
-       /* audiod pipe */
-       if (audiod_pipe < 0)
-               audiod_pipe = open_audiod_pipe();
-       if (audiod_pipe >= 0)
-               para_fd_set(audiod_pipe, &rfds, &max_fileno);
+       if (stat_pipe < 0)
+               stat_pipe = open_stat_pipe();
+       if (stat_pipe >= 0)
+               para_fd_set(stat_pipe, &rfds, &max_fileno);
        /* signal pipe */
        para_fd_set(signal_pipe, &rfds, &max_fileno);
        /* command pipe only for COMMAND_MODE */
@@ -953,46 +960,41 @@ repeat:
        if (ret <= 0)
                goto check_return; /* skip fd checks */
        /* signals */
-       if (FD_ISSET(signal_pipe, &rfds)) {
-               int sig_nr = para_next_signal();
-               if (sig_nr > 0)
-                       handle_signal(sig_nr);
-       }
+       ret = para_next_signal(&rfds);
+       if (ret > 0)
+               handle_signal(ret);
        /* read command pipe if ready */
-       if (command_pipe >= 0 && mode == COMMAND_MODE &&
-                       FD_ISSET(command_pipe, &rfds)) {
-               cp_numread = read(command_pipe, command_buf + cbo,
-                       sizeof(command_buf) - 1 - cbo);
-               if (cp_numread >= 0)
-                       cbo += cp_numread;
-               else {
-                       if (cp_numread < 0)
-                               PARA_ERROR_LOG("read error (%d)", cp_numread);
+       if (command_pipe >= 0 && mode == COMMAND_MODE) {
+               size_t sz;
+               ret = read_nonblock(command_pipe, command_buf + cbo,
+                       sizeof(command_buf) - 1 - cbo, &rfds, &sz);
+               cbo += sz;
+               sz = cbo;
+               cbo = for_each_line(command_buf, cbo, &add_output_line, NULL);
+               if (sz != cbo)
+                       wrefresh(bot.win);
+               if (ret < 0) {
+                       PARA_NOTICE_LOG("closing command pipe: %s",
+                               para_strerror(-ret));
                        close(command_pipe);
                        command_pipe = -1;
+                       return 0;
                }
        }
-       if (audiod_pipe >= 0 && FD_ISSET(audiod_pipe, &rfds))
-               if (read_audiod_pipe(audiod_pipe) <= 0) {
-                       close(audiod_pipe);
-                       audiod_pipe = -1;
-                       clear_all_items();
-                       free(stat_content[SI_BASENAME]);
-                       stat_content[SI_BASENAME] =
-                               para_strdup("audiod not running!?");
-                       print_all_items();
-               }
+       ret = read_stat_pipe(&rfds);
+       if (ret < 0) {
+               PARA_NOTICE_LOG("closing stat pipe: %s\n", para_strerror(-ret));
+               close(stat_pipe);
+               stat_pipe = -1;
+               clear_all_items();
+               free(stat_content[SI_BASENAME]);
+               stat_content[SI_BASENAME] =
+                       para_strdup("stat command terminated!?");
+               print_all_items();
+       }
 check_return:
        switch (mode) {
        case COMMAND_MODE:
-               if (cp_numread <= 0 && !cbo) /* command complete */
-                       return 0;
-               if (cbo)
-                       cbo = for_each_line(command_buf, cbo,
-                               &add_output_line, NULL);
-               if (cp_numread <= 0)
-                       cbo = 0;
-               wrefresh(bot.win);
                ret = wgetch(top.win);
                if (ret != ERR && ret != KEY_RESIZE) {
                        if (command_pipe) {
@@ -1348,31 +1350,30 @@ static void handle_command(int c)
 
        /* first check user's key bindings */
        for (i = 0; i < conf.key_map_given; ++i) {
-               char tmp[MAXLINE], *handler, *arg;
+               char *tmp, *handler, *arg;
 
-               strcpy(tmp, conf.key_map_arg[i]);
-               if (!split_key_map(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))) {
-                       if (*handler == 'd') {
-                               display_cmd(arg);
-                               return;
-                       }
-                       if (*handler == 'x') {
-                               external_cmd(arg);
-                               return;
-                       }
-                       if (*handler == 'p') {
-                               client_cmd_cmdline(arg);
-                               return;
-                       }
-                       if (*handler == 'i') {
-                               int num = find_cmd_byname(arg);
-                               if (num >= 0)
-                                       command_list[num].handler();
-                               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')
+                       client_cmd_cmdline(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++) {