diff options
author | Jon Gjengset <jon@thesquareplanet.com> | 2019-10-24 12:28:32 -0400 |
---|---|---|
committer | Jon Gjengset <jon@thesquareplanet.com> | 2019-10-24 12:28:32 -0400 |
commit | 16436ef65b3bde49ff74d1bfa9144495059aafd5 (patch) | |
tree | 0bdce49ba7dbe3cc7c8c630507b76ef9572561fa | |
parent | Allow noninteractive icon (#4) (diff) | |
download | mktrayicon-16436ef65b3bde49ff74d1bfa9144495059aafd5.tar.gz mktrayicon-16436ef65b3bde49ff74d1bfa9144495059aafd5.tar.bz2 mktrayicon-16436ef65b3bde49ff74d1bfa9144495059aafd5.zip |
Handle newlines in params
-rw-r--r-- | mktrayicon.c | 134 |
1 files changed, 111 insertions, 23 deletions
diff --git a/mktrayicon.c b/mktrayicon.c index 4ac4779..b6c456c 100644 --- a/mktrayicon.c +++ b/mktrayicon.c @@ -11,6 +11,9 @@ #include <string.h> #include <sys/stat.h> #include <unistd.h> +#include <ctype.h> + +#define DEBUG 1 GtkStatusIcon *icon; char *onclick = NULL; @@ -81,19 +84,21 @@ gboolean do_quit(gpointer data) gpointer watch_fifo(gpointer argv) { char *buf = malloc(1024*sizeof(char)); + char cmd; char *param; + char *tmp = malloc(1024*sizeof(char)); char *read; - size_t len; + size_t len, i; char *fifo_path = (char*)argv; FILE *fifo; struct stat fifo_st; /* outer is for open */ - while (1) { + outer: while (1) { if (stat(fifo_path, &fifo_st) != 0) { perror("FIFO does not exist, exiting\n"); gdk_threads_add_idle(do_quit, fifo); - break; + return NULL; } fifo = fopen(fifo_path, "r"); @@ -101,17 +106,20 @@ gpointer watch_fifo(gpointer argv) if (fifo == NULL) { perror("FIFO went away, exiting\n"); gdk_threads_add_idle(do_quit, fifo); - break; + return NULL; } /* inner is for read */ while (1) { + fprintf(stderr, "reading\n"); read = fgets(buf, 1024 * sizeof(char), fifo); + fprintf(stderr, "read\n"); if (read == NULL) { /* no more data in pipe, reopen and block */ fclose(fifo); - break; + fprintf(stderr, "closed\n"); + goto outer; } /* trim string */ @@ -121,28 +129,100 @@ gpointer watch_fifo(gpointer argv) if (*read == '\0') { /* empty command */ + fprintf(stderr, "empty\n"); continue; } - /* get rid of trailing newline */ - len = strlen(buf); - buf[len-1] = '\0'; - len -= 1; - - /* we have to malloc this on every call, because the memory is - * reused and the _idle functions are called asynchronously */ + cmd = *read; + fprintf(stderr, "cmd %c\n", cmd); + len = strlen(read); if (len < 3) { - param = malloc(1*sizeof(char)); - *param = '\0'; + param = NULL; + } else if (*(read + 2) != '\'') { + // unquoted string + read += 2; + len -= 2; + // trim trailing whitespace + i = len - 1; + while (i > 0) { + if (!isspace(read[i])) { + len = i + 1; + read[len] = '\0'; + break; + } + i -= 1; + } + param = malloc((len+1)*sizeof(char)); + strncpy(param, read, len+1); } else { - param = malloc((len-2+1)*sizeof(char)); - strncpy(param, buf+2, len-2+1); + // quoted string + read += 3; + len -= 3; + *tmp = '\0'; + *(tmp+1024-1) = '\0'; + // keep track of what we have so far + strncpy(tmp, read, 1023); + + // now keep reading until we have the end quote + while (1) { + // check for terminating ' + if (len != 0) { + // search backwards past whitespace + i = len - 1; + while (i > 0) { + if (!isspace(tmp[i])) { + break; + } + i -= 1; + } + if (tmp[i] == '\'') { + // maybe the end! + // let's make sure it isn't escaped + if (i >= 2 && tmp[i-2] == '\\') { + } else { + // it's not! + // we're done. + // trim off the ' and + // any whitespace we walked past + len = i; + tmp[len] = '\0'; + break; + } + } + } + + if (len == 1023) { + // we can't read any more + // but also haven't found the end + // forcibly terminate the string + fprintf(stderr, "Quoted string too long (max 1023 chars)\n"); + break; + } + + // we don't have the end of the string yet + read = fgets(buf, 1024 * sizeof(char), fifo); + if (read == NULL) { + /* no more data in pipe, reopen and block */ + fclose(fifo); + goto outer; + } + // note that we don't trim here, because we're + // in a quoted string. + strncpy(tmp + len, read, 1023 - len); + len += strlen(tmp + len); + } + + // quoted string is now in param[0:len] + param = malloc((len+1)*sizeof(char)); + strncpy(param, tmp, len+1); } - switch (*buf) { + switch (cmd) { case 'q': gdk_threads_add_idle(do_quit, param); - free(param); + if (param != NULL) { + free(param); + } break; case 't': /* tooltip */ gdk_threads_add_idle(set_tooltip, param); @@ -152,11 +232,15 @@ gpointer watch_fifo(gpointer argv) break; case 'h': /* hide */ gdk_threads_add_idle(set_visible, (void *)0); - free(param); + if (param != NULL) { + free(param); + } break; case 's': /* show */ gdk_threads_add_idle(set_visible, (void *)1); - free(param); + if (param != NULL) { + free(param); + } break; case 'c': /* click */ if (onclick != NULL) { @@ -164,7 +248,7 @@ gpointer watch_fifo(gpointer argv) onclick = NULL; } - if (*param == '\0') { + if (param != NULL && *param == '\0') { #ifdef DEBUG printf("Removing onclick handler\n"); #endif @@ -178,11 +262,15 @@ gpointer watch_fifo(gpointer argv) break; case 'm': /* menu */ fprintf(stderr, "Menu command not yet implemented\n"); - free(param); + if (param != NULL) { + free(param); + } break; default: fprintf(stderr, "Unknown command: '%c'\n", *buf); - free(param); + if (param != NULL) { + free(param); + } } gdk_flush(); |