]> granicus.if.org Git - neomutt/commitdiff
Support of relative paths sourcing and cyclic source detection
authorGuyzmo <guyzmo+github+pub@m0g.net>
Tue, 10 Jan 2017 12:59:40 +0000 (13:59 +0100)
committerRichard Russon <rich@flatcap.org>
Mon, 23 Jan 2017 11:40:57 +0000 (11:40 +0000)
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
mutt.h
muttlib.c

diff --git a/init.c b/init.c
index a920ef82b63ad71b6884ef339ccc6ba9db6903f5..3e3016d6c45b96d76b41e705ad4a7cb6f4ad306d 100644 (file)
--- 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 3c70f4a9c17c3a161a0938e81334334e67cb5d2f..686c4643efcbf3b86e3a495fc4837322bc557a27 100644 (file)
--- a/mutt.h
+++ b/mutt.h
@@ -57,6 +57,7 @@
 #define PATH_MAX _POSIX_PATH_MAX
 #endif
 
+#include <libgen.h>
 #include <pwd.h>
 #include <grp.h>
 
@@ -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
index 809728b1fce871927f1332f601668ff84bf35926..62548dc6441c1a2725aa8d3e382276c32a7ffeb5 100644 (file)
--- 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;