]> git.sur5r.net Git - i3/i3status/blobdiff - i3status.c
Bugfix: In term-output, clear line before drawing new one
[i3/i3status] / i3status.c
index df233f75911de0fcab6c75fdb6857c961d2a7695..ded5799279472d902be652b4a10f5d4d3b9e8149 100644 (file)
 /* socket file descriptor for general purposes */
 int general_socket;
 
+static bool exit_upon_signal = false;
+
 cfg_t *cfg, *cfg_general, *cfg_section;
 
 /*
- * Exit upon SIGPIPE because when we have nowhere to write to, gathering
- * system information is pointless.
+ * Set the exit_upon_signal flag, because one cannot do anything in a safe
+ * manner in a signal handler (e.g. fprintf, which we really want to do for
+ * debugging purposes), see
+ * https://www.securecoding.cert.org/confluence/display/seccode/SIG30-C.+Call+only+asynchronous-safe+functions+within+signal+handlers
  *
  */
-void sigpipe(int signum) {
-        fprintf(stderr, "Received SIGPIPE, exiting\n");
-        exit(1);
+void fatalsig(int signum) {
+        exit_upon_signal = true;
 }
 
 /*
@@ -321,8 +324,15 @@ int main(int argc, char *argv[]) {
 
         struct sigaction action;
         memset(&action, 0, sizeof(struct sigaction));
-        action.sa_handler = sigpipe;
+        action.sa_handler = fatalsig;
+
+        /* Exit upon SIGPIPE because when we have nowhere to write to, gathering system
+         * information is pointless. Also exit explicitly on SIGTERM and SIGINT because
+         * only this will trigger a reset of the cursor in the terminal output-format.
+         */
         sigaction(SIGPIPE, &action, NULL);
+        sigaction(SIGTERM, &action, NULL);
+        sigaction(SIGINT, &action, NULL);
 
         memset(&action, 0, sizeof(struct sigaction));
         action.sa_handler = sigusr1;
@@ -376,6 +386,8 @@ int main(int argc, char *argv[]) {
                 output_format = O_XMOBAR;
         else if (strcasecmp(output_str, "i3bar") == 0)
                 output_format = O_I3BAR;
+        else if (strcasecmp(output_str, "term") == 0)
+                output_format = O_TERM;
         else if (strcasecmp(output_str, "none") == 0)
                 output_format = O_NONE;
         else die("Unknown output format: \"%s\"\n", output_str);
@@ -400,6 +412,12 @@ int main(int argc, char *argv[]) {
                 yajl_gen_array_open(json_gen);
                 yajl_gen_clear(json_gen);
         }
+        if (output_format == O_TERM) {
+                /* Save the cursor-position and hide the cursor */
+                printf("\033[s\033[?25l");
+                /* Undo at exit */
+                atexit(&reset_cursor);
+        }
 
         if ((general_socket = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
                 die("Could not create socket\n");
@@ -415,10 +433,17 @@ int main(int argc, char *argv[]) {
         char buffer[4096];
 
         while (1) {
+                if (exit_upon_signal) {
+                        fprintf(stderr, "Exiting due to signal.\n");
+                        exit(1);
+                }
                 struct timeval tv;
                 gettimeofday(&tv, NULL);
                 if (output_format == O_I3BAR)
                         yajl_gen_array_open(json_gen);
+                else if (output_format == O_TERM)
+                        /* Restore the cursor-position, clear line */
+                        printf("\033[u\033[K");
                 for (j = 0; j < cfg_size(cfg, "order"); j++) {
                         if (j > 0)
                                 print_seperator();