diff options
author | Ingo Bürk <admin@airblader.de> | 2020-05-01 13:17:09 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-05-01 13:17:09 +0200 |
commit | ef03d7c4794d35cf322288c93577ea777a17c697 (patch) | |
tree | 672d98eebbf93f1e81907bb323712910977a2abf /src | |
parent | 55b5fb2172956c030c0989335396d664eeaa0ef6 (diff) | |
parent | 94d10968c94ad1a13392db1e17ed26265336fd33 (diff) |
Merge pull request #415 from orestisfl/resolve-tilde
Resolve tilde
Diffstat (limited to 'src')
-rw-r--r-- | src/general.c | 55 | ||||
-rw-r--r-- | src/print_file_contents.c | 14 |
2 files changed, 59 insertions, 10 deletions
diff --git a/src/general.c b/src/general.c index e3d4f96..6036b69 100644 --- a/src/general.c +++ b/src/general.c @@ -6,11 +6,18 @@ #include <stdio.h> #include <stdlib.h> #include <unistd.h> +#include <glob.h> #include <sys/fcntl.h> #include <sys/stat.h> #include "i3status.h" +#define exit_if_null(pointer, ...) \ + { \ + if (pointer == NULL) \ + die(__VA_ARGS__); \ + } + /* * Reads size bytes into the destination buffer from filename. * @@ -34,6 +41,54 @@ bool slurp(const char *filename, char *destination, int size) { } /* + * This function resolves ~ in pathnames. + * It may resolve wildcards in the first part of the path, but if no match + * or multiple matches are found, it just returns a copy of path as given. + * + */ +char *resolve_tilde(const char *path) { + static glob_t globbuf; + char *head, *tail, *result = NULL; + + tail = strchr(path, '/'); + head = strndup(path, tail ? (size_t)(tail - path) : strlen(path)); + + int res = glob(head, GLOB_TILDE, NULL, &globbuf); + free(head); + /* no match, or many wildcard matches are bad */ + if (res == GLOB_NOMATCH || globbuf.gl_pathc != 1) + result = sstrdup(path); + else if (res != 0) { + die("glob() failed"); + } else { + head = globbuf.gl_pathv[0]; + result = scalloc(strlen(head) + (tail ? strlen(tail) : 0) + 1); + strcpy(result, head); + if (tail) { + strcat(result, tail); + } + } + globfree(&globbuf); + + return result; +} + +char *sstrdup(const char *str) { + if (str == NULL) { + return NULL; + } + char *result = strdup(str); + exit_if_null(result, "Error: out of memory (strdup())\n"); + return result; +} + +void *scalloc(size_t size) { + void *result = calloc(size, 1); + exit_if_null(result, "Error: out of memory (calloc(%zu))\n", size); + return result; +} + +/* * Skip the given character for exactly 'amount' times, returns * a pointer to the first non-'character' character in 'input'. * diff --git a/src/print_file_contents.c b/src/print_file_contents.c index 65813f5..b66321a 100644 --- a/src/print_file_contents.c +++ b/src/print_file_contents.c @@ -14,24 +14,18 @@ #define STRING_SIZE 10 -static void *scalloc(size_t size) { - void *result = calloc(size, 1); - if (result == NULL) { - die("Error: out of memory (calloc(%zu))\n", size); - } - return result; -} - void print_file_contents(yajl_gen json_gen, char *buffer, const char *title, const char *path, const char *format, const char *format_bad, const int max_chars) { const char *walk = format; char *outwalk = buffer; char *buf = scalloc(max_chars * sizeof(char) + 1); - int n = -1; - int fd = open(path, O_RDONLY); + char *abs_path = resolve_tilde(path); + int fd = open(abs_path, O_RDONLY); + free(abs_path); INSTANCE(path); + int n = -1; if (fd > -1) { n = read(fd, buf, max_chars); if (n != -1) { |