From d213300dedddb522c986d6ff397f15ad43325be7 Mon Sep 17 00:00:00 2001 From: Guyzmo Date: Tue, 10 Jan 2017 13:59:40 +0100 Subject: [PATCH] Support of relative paths sourcing and cyclic source detection Added HEAP/FILO structure and global singleton to contain the the list of config files that have been sourced, and detect cyclic sourcing. Implemented with a simple heap API: - `path_heap_push()` - `path_heap_pop()` - `path_heap_front()` - `path_heap_find()` Added a new method `to_absolute_path()` to convert a path into an absolute path, relatively to another config file's path. Using POSIX methods to do so, adding libgen's header in `mutt.h`. Closes #282 Closes #290 --- init.c | 78 +++++++++++++++++++++++++++++++++++++++++++++++++++---- mutt.h | 10 +++++++ muttlib.c | 32 +++++++++++++++++++++++ 3 files changed, 115 insertions(+), 5 deletions(-) diff --git a/init.c b/init.c index a920ef82b..3e3016d6c 100644 --- a/init.c +++ b/init.c @@ -2607,23 +2607,88 @@ static int parse_set (BUFFER *tmp, BUFFER *s, unsigned long data, BUFFER *err) return (r); } +/* Heap structure + * FILO designed to contain the list of config files that have been sourced + * and avoid cyclic sourcing */ +static HEAP *MuttrcHeap; + +/* Use POSIX functions to convert a path to absolute, relatively to another path + * Args: + * - path: instance containing the relative path to the file we want the absolute + * path of. Should be at least of PATH_MAX length, will contain the full result. + * - reference: path to a file which directory will be set as reference for setting + * up the absolute path. + * Returns: TRUE (1) on success, FALSE (0) otherwise. + */ +static int to_absolute_path(char *path, const char *reference) +{ + char *ref_tmp, *dirpath; + char abs_path[PATH_MAX]; + int path_len; + + /* if path is already absolute, don't do anything */ + if ((strlen(path) > 1) && (path[0] == '/')) + { + return TRUE; + } + + ref_tmp = strdup(reference); + dirpath = dirname(ref_tmp); // get directory name of + strncpy(abs_path, dirpath, PATH_MAX); + strncat(abs_path, "/", PATH_MAX - 1); // append a / at the end of the path + + free(ref_tmp); + path_len = PATH_MAX - strlen(path); + + strncat(abs_path, path, path_len > 0 ? path_len : 0); + + path = realpath(abs_path, path); + + if (!path) + { + printf("Error: issue converting path to absolute (%s)", strerror(errno)); + return FALSE; + } + + return TRUE; +} + #define MAXERRS 128 /* reads the specified initialization file. returns -1 if errors were found so that we can pause to let the user know... */ -static int source_rc (const char *rcfile, BUFFER *err) +static int source_rc (const char *rcfile_path, BUFFER *err) { FILE *f; int line = 0, rc = 0, conv = 0, line_rc; BUFFER token; char *linebuf = NULL; char *currentline = NULL; + char rcfile[PATH_MAX]; size_t buflen; + pid_t pid; - dprint (2, (debugfile, "Reading configuration file '%s'.\n", - rcfile)); - + strncpy(rcfile, rcfile_path, PATH_MAX); + + if (!to_absolute_path(rcfile, mutt_front_heap(MuttrcHeap))) + { + mutt_error("Error: impossible to build path of '%s'.", rcfile_path); + return (-1); + } + + dprint(2, (debugfile, "Reading configuration file '%s'.\n", rcfile)); + + if (!MuttrcHeap || mutt_find_heap(MuttrcHeap, rcfile) == NULL) + { + mutt_push_heap(&MuttrcHeap, rcfile); + } + else + { + mutt_error("Error: Cyclic sourcing of configuration file '%s'.", rcfile); + return (-1); + } + if ((f = mutt_open_read (rcfile, &pid)) == NULL) { snprintf (err->data, err->dsize, "%s: %s", rcfile, strerror (errno)); @@ -2672,6 +2737,9 @@ static int source_rc (const char *rcfile, BUFFER *err) : _("source: reading aborted due to too many errors in %s"), rcfile); rc = -1; } + + mutt_pop_heap(&MuttrcHeap); + return (rc); } @@ -2693,7 +2761,7 @@ static int parse_source (BUFFER *tmp, BUFFER *s, unsigned long data, BUFFER *err } strfcpy (path, tmp->data, sizeof (path)); mutt_expand_path (path, sizeof (path)); - return (source_rc (path, err)); + return source_rc (path, err); } /* line command to execute diff --git a/mutt.h b/mutt.h index 3c70f4a9c..686c4643e 100644 --- a/mutt.h +++ b/mutt.h @@ -57,6 +57,7 @@ #define PATH_MAX _POSIX_PATH_MAX #endif +#include #include #include @@ -630,6 +631,8 @@ typedef struct list_t struct list_t *next; } LIST; +typedef struct list_t HEAP; + typedef struct rx_list_t { REGEXP *rx; @@ -645,6 +648,7 @@ typedef struct spam_list_t } SPAM_LIST; #define mutt_new_list() safe_calloc (1, sizeof (LIST)) +#define mutt_new_heap() safe_calloc(1, sizeof(HEAP)) #define mutt_new_rx_list() safe_calloc (1, sizeof (RX_LIST)) #define mutt_new_spam_list() safe_calloc (1, sizeof (SPAM_LIST)) void mutt_free_list (LIST **); @@ -660,6 +664,12 @@ LIST *mutt_add_list_n (LIST*, const void *, size_t); LIST *mutt_find_list (LIST *, const char *); int mutt_remove_from_rx_list (RX_LIST **l, const char *str); +/* handle heap */ +void mutt_push_heap(HEAP **head, const char *data); +int mutt_pop_heap(HEAP **head); +const char *mutt_front_heap(HEAP *head); +HEAP *mutt_find_heap(HEAP *head, const char *data); + void mutt_init (int, LIST *); typedef struct alias diff --git a/muttlib.c b/muttlib.c index 809728b1f..62548dc64 100644 --- a/muttlib.c +++ b/muttlib.c @@ -283,6 +283,38 @@ LIST *mutt_find_list (LIST *l, const char *data) return NULL; } +void mutt_push_heap(HEAP **head, const char *data) +{ + HEAP *tmp; + tmp = safe_malloc(sizeof(HEAP)); + tmp->data = safe_strdup(data); + tmp->next = *head; + *head = tmp; +} + +int mutt_pop_heap(HEAP **head) +{ + HEAP *elt = *head; + if (!elt) + return 0; + *head = elt->next; + free(elt->data); + free(elt); + return 1; +} + +const char *mutt_front_heap(HEAP *head) +{ + if (!head || !head->data) + return ""; + return head->data; +} + +HEAP *mutt_find_heap(HEAP *head, const char *data) +{ + return (HEAP *) mutt_find_list((LIST *) head, data); +} + int mutt_remove_from_rx_list (RX_LIST **l, const char *str) { RX_LIST *p, *last = NULL; -- 2.40.0