]> granicus.if.org Git - neomutt/commitdiff
free resources
authorRichard Russon <rich@flatcap.org>
Sat, 7 Apr 2018 23:00:09 +0000 (00:00 +0100)
committerRichard Russon <rich@flatcap.org>
Sat, 7 Apr 2018 23:00:09 +0000 (00:00 +0100)
color.c
globals.h
history.c
hook.c
init.c
keymap.c
keymap.h
main.c
mutt/list.c
mutt/list.h
protos.h

diff --git a/color.c b/color.c
index 992913aab17bfb51ae69bea692b84c8254db8154..47ba612ba88c72cd71216d65ce2014fd30e086a2 100644 (file)
--- a/color.c
+++ b/color.c
 int *ColorQuote = NULL;
 int ColorQuoteUsed;
 int ColorDefs[MT_COLOR_MAX];
-struct ColorLineHead ColorHdrList = STAILQ_HEAD_INITIALIZER(ColorHdrList);
-struct ColorLineHead ColorBodyList = STAILQ_HEAD_INITIALIZER(ColorBodyList);
 struct ColorLineHead ColorAttachList = STAILQ_HEAD_INITIALIZER(ColorAttachList);
-struct ColorLineHead ColorStatusList = STAILQ_HEAD_INITIALIZER(ColorStatusList);
-struct ColorLineHead ColorIndexList = STAILQ_HEAD_INITIALIZER(ColorIndexList);
+struct ColorLineHead ColorBodyList = STAILQ_HEAD_INITIALIZER(ColorBodyList);
+struct ColorLineHead ColorHdrList = STAILQ_HEAD_INITIALIZER(ColorHdrList);
 struct ColorLineHead ColorIndexAuthorList = STAILQ_HEAD_INITIALIZER(ColorIndexAuthorList);
 struct ColorLineHead ColorIndexFlagsList = STAILQ_HEAD_INITIALIZER(ColorIndexFlagsList);
+struct ColorLineHead ColorIndexList = STAILQ_HEAD_INITIALIZER(ColorIndexList);
 struct ColorLineHead ColorIndexSubjectList = STAILQ_HEAD_INITIALIZER(ColorIndexSubjectList);
 struct ColorLineHead ColorIndexTagList = STAILQ_HEAD_INITIALIZER(ColorIndexTagList);
+struct ColorLineHead ColorStatusList = STAILQ_HEAD_INITIALIZER(ColorStatusList);
 
 /* local to this file */
 static int ColorQuoteSize;
@@ -161,7 +161,7 @@ static void free_color_line(struct ColorLine *tmp, int free_colors)
     return;
 
 #ifdef HAVE_COLOR
-  if (free_colors && tmp->fg != -1 && tmp->bg != -1)
+  if (free_colors && (tmp->fg != -1) && (tmp->bg != -1))
     mutt_free_color(tmp->fg, tmp->bg);
 #endif
 
@@ -1023,3 +1023,40 @@ int mutt_parse_mono(struct Buffer *buf, struct Buffer *s, unsigned long data,
 
   return parse_color(buf, s, err, parse_attr_spec, dry_run, false);
 }
+
+/**
+ * mutt_free_color_list - Free a list of colours
+ * @param head ColorLine List
+ */
+static void mutt_free_color_list(struct ColorLineHead *head)
+{
+  struct ColorLine *np, *tmp;
+  STAILQ_FOREACH_SAFE(np, head, entries, tmp)
+  {
+    STAILQ_REMOVE(head, np, ColorLine, entries);
+    free_color_line(np, true);
+  }
+}
+
+void mutt_free_colors(void)
+{
+  mutt_free_color_list(&ColorAttachList);
+  mutt_free_color_list(&ColorBodyList);
+  mutt_free_color_list(&ColorHdrList);
+  mutt_free_color_list(&ColorIndexAuthorList);
+  mutt_free_color_list(&ColorIndexFlagsList);
+  mutt_free_color_list(&ColorIndexList);
+  mutt_free_color_list(&ColorIndexSubjectList);
+  mutt_free_color_list(&ColorIndexTagList);
+  mutt_free_color_list(&ColorStatusList);
+
+  struct ColorList *cl = ColorList;
+  struct ColorList *next = NULL;
+  while (cl)
+  {
+    next = cl->next;
+    FREE(&cl);
+    cl = next;
+  }
+  ColorList = NULL;
+}
index 941d8f4d4dc96d6ab27b490cbd3d375de44a80a3..47a61a198cb34546ed19591b5aeb0f6f87519f39 100644 (file)
--- a/globals.h
+++ b/globals.h
@@ -44,8 +44,6 @@ WHERE char AttachmentMarker[STRING];
 WHERE char *HomeDir;
 WHERE char *ShortHostname;
 
-WHERE struct ListHead Muttrc INITVAL(STAILQ_HEAD_INITIALIZER(Muttrc));
-
 WHERE char *Username;
 
 WHERE char *CurrentFolder;
@@ -58,17 +56,25 @@ WHERE struct Hash *ReverseAliases;
 WHERE struct Hash *TagTransforms;
 WHERE struct Hash *TagFormats;
 
-WHERE struct ListHead AutoViewList INITVAL(STAILQ_HEAD_INITIALIZER(AutoViewList));
+/* Lists of strings */
 WHERE struct ListHead AlternativeOrderList INITVAL(STAILQ_HEAD_INITIALIZER(AlternativeOrderList));
-WHERE struct ListHead AttachAllow INITVAL(STAILQ_HEAD_INITIALIZER(AttachAllow));
-WHERE struct ListHead AttachExclude INITVAL(STAILQ_HEAD_INITIALIZER(AttachExclude));
-WHERE struct ListHead InlineAllow INITVAL(STAILQ_HEAD_INITIALIZER(InlineAllow));
-WHERE struct ListHead InlineExclude INITVAL(STAILQ_HEAD_INITIALIZER(InlineExclude));
+WHERE struct ListHead AutoViewList INITVAL(STAILQ_HEAD_INITIALIZER(AutoViewList));
 WHERE struct ListHead HeaderOrderList INITVAL(STAILQ_HEAD_INITIALIZER(HeaderOrderList));
 WHERE struct ListHead Ignore INITVAL(STAILQ_HEAD_INITIALIZER(Ignore));
 WHERE struct ListHead MailToAllow INITVAL(STAILQ_HEAD_INITIALIZER(MailToAllow));
 WHERE struct ListHead MimeLookupList INITVAL(STAILQ_HEAD_INITIALIZER(MimeLookupList));
+WHERE struct ListHead Muttrc INITVAL(STAILQ_HEAD_INITIALIZER(Muttrc));
+#ifdef USE_SIDEBAR
+WHERE struct ListHead SidebarWhitelist INITVAL(STAILQ_HEAD_INITIALIZER(SidebarWhitelist));
+#endif
 WHERE struct ListHead UnIgnore INITVAL(STAILQ_HEAD_INITIALIZER(UnIgnore));
+WHERE struct ListHead UserHeader INITVAL(STAILQ_HEAD_INITIALIZER(UserHeader));
+
+/* Lists of AttachMatch */
+WHERE struct ListHead AttachAllow INITVAL(STAILQ_HEAD_INITIALIZER(AttachAllow));
+WHERE struct ListHead AttachExclude INITVAL(STAILQ_HEAD_INITIALIZER(AttachExclude));
+WHERE struct ListHead InlineAllow INITVAL(STAILQ_HEAD_INITIALIZER(InlineAllow));
+WHERE struct ListHead InlineExclude INITVAL(STAILQ_HEAD_INITIALIZER(InlineExclude));
 
 WHERE struct RegexList *Alternates;
 WHERE struct RegexList *UnAlternates;
@@ -82,10 +88,6 @@ WHERE struct ReplaceList *SubjectRegexList;
 
 WHERE unsigned short Counter;
 
-#ifdef USE_SIDEBAR
-WHERE struct ListHead SidebarWhitelist INITVAL(STAILQ_HEAD_INITIALIZER(SidebarWhitelist));
-#endif
-
 /* flags for received signals */
 WHERE SIG_ATOMIC_VOLATILE_T SigAlrm;
 WHERE SIG_ATOMIC_VOLATILE_T SigInt;
@@ -94,7 +96,6 @@ WHERE SIG_ATOMIC_VOLATILE_T SigWinch;
 WHERE int CurrentMenu;
 
 WHERE struct Alias *Aliases;
-WHERE struct ListHead UserHeader INITVAL(STAILQ_HEAD_INITIALIZER(UserHeader));
 
 /* All the variables below are backing for config items */
 
index 7abd2de2badd900625389805f0894edd226983c1..b9cd3cae2e35991ba38b1c2c15e728eaaaa7899e 100644 (file)
--- a/history.c
+++ b/history.c
@@ -541,11 +541,14 @@ void mutt_hist_free(void)
   for (enum HistoryClass hclass = HC_FIRST; hclass < HC_LAST; hclass++)
   {
     struct History *h = &Histories[hclass];
+    if (!h->hist)
+      continue;
+
     for (int i = 0; i < History; i++)
     {
       FREE(&h->hist[i]);
     }
-    FREE(&Histories[hclass]);
+    FREE(&h->hist);
   }
 }
 
diff --git a/hook.c b/hook.c
index bea902e42ab8f6e0ea7320bf9f8d510ec194405a..69a551e891cdc615dba02e2e96b467f32b6b9c14 100644 (file)
--- a/hook.c
+++ b/hook.c
@@ -278,12 +278,12 @@ static void delete_hook(struct Hook *h)
 }
 
 /**
- * delete_hooks - Delete matching hooks
+ * mutt_delete_hooks - Delete matching hooks
  * @param type
  * * Hook type to delete, e.g. #MUTT_SENDHOOK
  * * Or, 0 to delete all hooks
  */
-static void delete_hooks(int type)
+void mutt_delete_hooks(int type)
 {
   struct Hook *h = NULL;
   struct Hook *tmp = NULL;
@@ -312,7 +312,7 @@ int mutt_parse_unhook(struct Buffer *buf, struct Buffer *s, unsigned long data,
                  _("unhook: Can't do unhook * from within a hook."));
         return -1;
       }
-      delete_hooks(0);
+      mutt_delete_hooks(0);
       mutt_ch_lookup_remove();
     }
     else
@@ -335,7 +335,7 @@ int mutt_parse_unhook(struct Buffer *buf, struct Buffer *s, unsigned long data,
                  buf->data, buf->data);
         return -1;
       }
-      delete_hooks(type);
+      mutt_delete_hooks(type);
     }
   }
   return 0;
diff --git a/init.c b/init.c
index 1f1b7629168fc16a7e93a45a2d2f4aa8977d667c..0e80c389196d04549596eb8aad816b8dae81819a 100644 (file)
--- a/init.c
+++ b/init.c
@@ -56,6 +56,7 @@
 #include "ncrypt/ncrypt.h"
 #include "options.h"
 #include "pattern.h"
+#include "protos.h"
 #include "sidebar.h"
 #include "version.h"
 #ifdef USE_NOTMUCH
     return -1;                                                                       \
   }
 
+/* LIFO designed to contain the list of config files that have been sourced and
+ * avoid cyclic sourcing */
+static struct ListHead MuttrcStack = STAILQ_HEAD_INITIALIZER(MuttrcStack);
+
+#define MAXERRS 128
+
+#define NUMVARS mutt_array_size(MuttVars)
+#define NUMCOMMANDS mutt_array_size(Commands)
+
+/* initial string that starts completion. No telling how much crap
+ * the user has typed so far. Allocate LONG_STRING just to be sure! */
+static char UserTyped[LONG_STRING] = { 0 };
+
+static int NumMatched = 0;             /* Number of matches for completion */
+static char Completed[STRING] = { 0 }; /* completed string (command or variable) */
+static const char **Matches;
+/* this is a lie until mutt_init runs: */
+static int MatchesListsize = MAX(NUMVARS, NUMCOMMANDS) + 10;
+
 /**
  * struct MyVar - A user-set variable
  */
@@ -704,6 +724,23 @@ static void free_opt(struct Option *p)
   }
 }
 
+/**
+ * mutt_free_attachmatch - Free an AttachMatch
+ * @param am AttachMatch to free
+ *
+ * @note We don't free minor because it is either a pointer into major,
+ *       or a static string.
+ */
+void mutt_free_attachmatch(struct AttachMatch **am)
+{
+  if (!am || !*am)
+    return;
+
+  regfree(&(*am)->minor_regex);
+  FREE(&(*am)->major);
+  FREE(am);
+}
+
 /**
  * mutt_free_opts - clean up before quitting
  */
@@ -712,13 +749,59 @@ void mutt_free_opts(void)
   for (int i = 0; MuttVars[i].name; i++)
     free_opt(MuttVars + i);
 
+  FREE(&Matches);
+
+  mutt_alias_free(&Aliases);
+
   mutt_regexlist_free(&Alternates);
-  mutt_regexlist_free(&UnAlternates);
   mutt_regexlist_free(&MailLists);
-  mutt_regexlist_free(&UnMailLists);
+  mutt_regexlist_free(&NoSpamList);
   mutt_regexlist_free(&SubscribedLists);
+  mutt_regexlist_free(&UnAlternates);
+  mutt_regexlist_free(&UnMailLists);
   mutt_regexlist_free(&UnSubscribedLists);
-  mutt_regexlist_free(&NoSpamList);
+
+  mutt_hash_destroy(&Groups);
+  mutt_hash_destroy(&ReverseAliases);
+  mutt_hash_destroy(&TagFormats);
+  mutt_hash_destroy(&TagTransforms);
+
+  /* Lists of strings */
+  mutt_list_free(&AlternativeOrderList);
+  mutt_list_free(&AutoViewList);
+  mutt_list_free(&HeaderOrderList);
+  mutt_list_free(&Ignore);
+  mutt_list_free(&MailToAllow);
+  mutt_list_free(&MimeLookupList);
+  mutt_list_free(&Muttrc);
+  mutt_list_free(&MuttrcStack);
+#ifdef USE_SIDEBAR
+  mutt_list_free(&SidebarWhitelist);
+#endif
+  mutt_list_free(&UnIgnore);
+  mutt_list_free(&UserHeader);
+
+  /* Lists of AttachMatch */
+  mutt_list_free_type(&AttachAllow, (list_free_t) mutt_free_attachmatch);
+  mutt_list_free_type(&AttachExclude, (list_free_t) mutt_free_attachmatch);
+  mutt_list_free_type(&InlineAllow, (list_free_t) mutt_free_attachmatch);
+  mutt_list_free_type(&InlineExclude, (list_free_t) mutt_free_attachmatch);
+
+  mutt_free_colors();
+
+  FREE(&CurrentFolder);
+  FREE(&HomeDir);
+  FREE(&LastFolder);
+  FREE(&ShortHostname);
+  FREE(&Username);
+
+  mutt_replacelist_free(&SpamList);
+  mutt_replacelist_free(&SubjectRegexList);
+
+  mutt_delete_hooks(0);
+
+  mutt_hist_free();
+  mutt_free_keys();
 }
 
 /**
@@ -2764,12 +2847,6 @@ static int parse_set(struct Buffer *buf, struct Buffer *s, unsigned long data,
   return r;
 }
 
-/* LIFO designed to contain the list of config files that have been sourced and
- * avoid cyclic sourcing */
-static struct ListHead MuttrcStack = STAILQ_HEAD_INITIALIZER(MuttrcStack);
-
-#define MAXERRS 128
-
 /**
  * source_rc - Read an initialization file
  * @param rcfile_path Path to initialization file
@@ -2904,6 +2981,8 @@ static int source_rc(const char *rcfile_path, struct Buffer *err)
 
   if (!ispipe && !STAILQ_EMPTY(&MuttrcStack))
   {
+    struct ListNode *np = STAILQ_FIRST(&MuttrcStack);
+    FREE(&np->data);
     STAILQ_REMOVE_HEAD(&MuttrcStack, entries);
   }
 
@@ -2999,19 +3078,6 @@ finish:
   return r;
 }
 
-#define NUMVARS mutt_array_size(MuttVars)
-#define NUMCOMMANDS mutt_array_size(Commands)
-
-/* initial string that starts completion. No telling how much crap
- * the user has typed so far. Allocate LONG_STRING just to be sure! */
-static char UserTyped[LONG_STRING] = { 0 };
-
-static int NumMatched = 0;             /* Number of matches for completion */
-static char Completed[STRING] = { 0 }; /* completed string (command or variable) */
-static const char **Matches;
-/* this is a lie until mutt_init runs: */
-static int MatchesListsize = MAX(NUMVARS, NUMCOMMANDS) + 10;
-
 static void matches_ensure_morespace(int current)
 {
   if (current > MatchesListsize - 2)
index cd2ed034d8381e0895e62bcc38f6a85b57e9d4b7..663a5485fe37d4add0ef5a03aa67c66a82e5bf2f 100644 (file)
--- a/keymap.c
+++ b/keymap.c
@@ -1260,3 +1260,28 @@ void mutt_what_key(void)
   mutt_flushinp();
   mutt_clear_error();
 }
+
+/**
+ * mutt_free_keys - Free the key maps
+ */
+void mutt_free_keys(void)
+{
+  struct Keymap *map = NULL;
+  struct Keymap *next = NULL;
+
+  for (int i = 0; i < MENU_MAX; i++)
+  {
+    for (map = Keymaps[i]; map; map = next)
+    {
+      next = map->next;
+
+      FREE(&map->macro);
+      FREE(&map->descr);
+      FREE(&map->keys);
+      FREE(&map);
+    }
+
+    Keymaps[i] = NULL;
+  }
+}
+
index 36d4497e68c360a4db7162a7937571e93778af42..41ff761c4aaf7970959f1b0aa5927b2a6123a608 100644 (file)
--- a/keymap.h
+++ b/keymap.h
@@ -129,4 +129,6 @@ extern const struct Binding OpSmime[];
 extern const struct Binding OpMix[];
 #endif
 
+void mutt_free_keys(void);
+
 #endif /* _MUTT_KEYMAP_H */
diff --git a/main.c b/main.c
index b7ba4fc24926c25681fc261d6a76881be579c58e..7f34a5ed6628d04e42ccf6f9e885a86f67ab2416 100644 (file)
--- a/main.c
+++ b/main.c
@@ -584,6 +584,7 @@ int main(int argc, char *argv[], char *envp[])
     for (; optind < argc; optind++)
       mutt_list_insert_tail(&queries, mutt_str_strdup(argv[optind]));
     rc = mutt_query_variables(&queries);
+    mutt_list_free(&queries);
     goto main_curses;
   }
 
@@ -1051,7 +1052,6 @@ int main(int argc, char *argv[], char *envp[])
 #endif
     log_queue_empty();
     mutt_log_stop();
-    mutt_free_opts();
     mutt_window_free();
     // TEST43: neomutt (no change to mailbox)
     // TEST44: neomutt (change mailbox)
@@ -1068,5 +1068,7 @@ main_curses:
     puts(ErrorBuf);
 main_exit:
   mutt_envlist_free();
+  mutt_free_opts();
+  mutt_free_keys();
   return rc;
 }
index 20acbc9f9e85e023b17bb0e4542d19f40d368bf9..66ae3073701ff6df402f39a3db8fafdd6bb4f13a 100644 (file)
@@ -113,6 +113,27 @@ void mutt_list_free(struct ListHead *h)
   STAILQ_INIT(h);
 }
 
+/**
+ * mutt_list_free_type - Free a List of type
+ * @param h Head of the List
+ * @param fn Function to free contents of ListNode
+ */
+void mutt_list_free_type(struct ListHead *h, list_free_t fn)
+{
+  if (!h || !fn)
+    return;
+
+  struct ListNode *np = STAILQ_FIRST(h), *next = NULL;
+  while (np)
+  {
+    next = STAILQ_NEXT(np, entries);
+    fn((void **) &np->data);
+    FREE(&np);
+    np = next;
+  }
+  STAILQ_INIT(h);
+}
+
 /**
  * mutt_list_clear - Free a list, but NOT its strings
  * @param h Head of the List
index 32425fbfc49e381f56430d28c71ca27afaaa9518..56cd841d7a6c1bb8591c92aa47020259b27c9c5b 100644 (file)
@@ -44,10 +44,13 @@ struct ListNode
  */
 STAILQ_HEAD(ListHead, ListNode);
 
+typedef void (*list_free_t)(void **ptr);
+
 void             mutt_list_clear(struct ListHead *h);
 int              mutt_list_compare(const struct ListHead *ah, const struct ListHead *bh);
 struct ListNode *mutt_list_find(struct ListHead *h, const char *data);
 void             mutt_list_free(struct ListHead *h);
+void             mutt_list_free_type(struct ListHead *h, list_free_t fn);
 struct ListNode *mutt_list_insert_after(struct ListHead *h, struct ListNode *n, char *s);
 struct ListNode *mutt_list_insert_head(struct ListHead *h, char *s);
 struct ListNode *mutt_list_insert_tail(struct ListHead *h, char *s);
index 3f755779b30255434fd612544566ef33d82396b4..ed736d8f0457e1de3d02606b9ee72528fb485884 100644 (file)
--- a/protos.h
+++ b/protos.h
@@ -41,6 +41,7 @@ struct Address;
 struct Alias;
 struct Body;
 struct Buffer;
+struct ColorLineHead;
 struct Context;
 struct EnterState;
 struct Envelope;
@@ -178,6 +179,7 @@ void mutt_format_s_tree(char *buf, size_t buflen, const char *prec, const char *
 void mutt_forward_intro(struct Context *ctx, struct Header *cur, FILE *fp);
 void mutt_forward_trailer(struct Context *ctx, struct Header *cur, FILE *fp);
 void mutt_free_color(int fg, int bg);
+void mutt_free_colors(void);
 void mutt_help(int menu);
 void mutt_check_lookup_list(struct Body *b, char *type, size_t len);
 void mutt_make_attribution(struct Context *ctx, struct Header *cur, FILE *out);
@@ -300,6 +302,7 @@ int mutt_rfc822_parse_line(struct Envelope *e, struct Header *hdr, char *line, c
 int mutt_parse_score(struct Buffer *buf, struct Buffer *s, unsigned long data, struct Buffer *err);
 int mutt_parse_unscore(struct Buffer *buf, struct Buffer *s, unsigned long data, struct Buffer *err);
 int mutt_parse_unhook(struct Buffer *buf, struct Buffer *s, unsigned long data, struct Buffer *err);
+void mutt_delete_hooks(int type);
 int mutt_pipe_attachment(FILE *fp, struct Body *b, const char *path, char *outfile);
 int mutt_print_attachment(FILE *fp, struct Body *a);
 int mutt_query_complete(char *buf, size_t buflen);