chiark / gitweb /
Merge memory hygeine branch
authorRichard Kettlewell <rjk@greenend.org.uk>
Sun, 18 Jul 2010 16:08:21 +0000 (17:08 +0100)
committerRichard Kettlewell <rjk@greenend.org.uk>
Sun, 18 Jul 2010 16:08:21 +0000 (17:08 +0100)
19 files changed:
clients/disorder.c
disobedience/login.c
lib/Makefile.am
lib/asprintf.c
lib/authhash.c
lib/authhash.h
lib/charset.h
lib/charsetf.c [new file with mode: 0644]
lib/client-common.c
lib/client.c
lib/configuration.c
lib/configuration.h
lib/fprintf.c
lib/kvp.c
lib/kvp.h
lib/queue.c
lib/queue.h
lib/vector.c
lib/vector.h

index 1d55b8db6a7f14eedba2f555e69a5e13872dfb88..53fce74c778c0b5aaf6c24d634f291b5f24ed731 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * This file is part of DisOrder.
- * Copyright (C) 2004-2008 Richard Kettlewell
+ * Copyright (C) 2004-2009 Richard Kettlewell
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -98,7 +98,9 @@ static void cf_version(char attribute((unused)) **argv) {
   char *v;
 
   if(disorder_version(getclient(), &v)) exit(EXIT_FAILURE);
-  xprintf("%s\n", nullcheck(utf82mb(v)));
+  v = nullcheck(utf82mb_f(v));
+  xprintf("%s\n", v);
+  xfree(v);
 }
 
 static void print_queue_entry(const struct queue_entry *q) {
@@ -173,13 +175,12 @@ static void cf_rescan(char attribute((unused)) **argv) {
 
 static void cf_somequeue(int (*fn)(disorder_client *c,
                                   struct queue_entry **qp)) {
-  struct queue_entry *q;
+  struct queue_entry *q, *qbase;
 
-  if(fn(getclient(), &q)) exit(EXIT_FAILURE);
-  while(q) {
+  if(fn(getclient(), &qbase)) exit(EXIT_FAILURE);
+  for(q = qbase; q; q = q->next)
     print_queue_entry(q);
-    q = q->next;
-  }
+  queue_free(qbase, 1);
 }
 
 static void cf_recent(char attribute((unused)) **argv) {
@@ -225,16 +226,17 @@ static void cf_somelist(char **argv,
                        int (*fn)(disorder_client *c,
                                  const char *arg, const char *re,
                                  char ***vecp, int *nvecp)) {
-  char **vec;
+  char **vec, **base;
   const char *re;
 
   if(argv[1])
     re = xstrdup(argv[1] + 1);
   else
     re = 0;
-  if(fn(getclient(), argv[0], re, &vec, 0)) exit(EXIT_FAILURE);
-  while(*vec)
-    xprintf("%s\n", nullcheck(utf82mb(*vec++)));
+  if(fn(getclient(), argv[0], re, &base, 0)) exit(EXIT_FAILURE);
+  for(vec = base; *vec; ++vec)
+    xprintf("%s\n", nullcheck(utf82mb_f(*vec)));
+  xfree(base);
 }
 
 static int isarg_regexp(const char *s) {
@@ -257,7 +259,7 @@ static void cf_get(char **argv) {
   char *value;
 
   if(disorder_get(getclient(), argv[0], argv[1], &value)) exit(EXIT_FAILURE);
-  xprintf("%s\n", nullcheck(utf82mb(value)));
+  xprintf("%s\n", nullcheck(utf82mb_f(value)));
 }
 
 static void cf_length(char **argv) {
@@ -276,12 +278,13 @@ static void cf_unset(char **argv) {
 }
 
 static void cf_prefs(char **argv) {
-  struct kvp *k;
+  struct kvp *k, *base;
 
-  if(disorder_prefs(getclient(), argv[0], &k)) exit(EXIT_FAILURE);
-  for(; k; k = k->next)
+  if(disorder_prefs(getclient(), argv[0], &base)) exit(EXIT_FAILURE);
+  for(k = base; k; k = k->next)
     xprintf("%s = %s\n",
            nullcheck(utf82mb(k->name)), nullcheck(utf82mb(k->value)));
+  kvp_free(base);
 }
 
 static void cf_search(char **argv) {
@@ -291,6 +294,7 @@ static void cf_search(char **argv) {
   if(disorder_search(getclient(), *argv, &results, &nresults)) exit(EXIT_FAILURE);
   for(n = 0; n < nresults; ++n)
     xprintf("%s\n", nullcheck(utf82mb(results[n])));
+  free_strings(nresults, results);
 }
 
 static void cf_random_disable(char attribute((unused)) **argv) {
@@ -303,10 +307,12 @@ static void cf_random_enable(char attribute((unused)) **argv) {
 
 static void cf_stats(char attribute((unused)) **argv) {
   char **vec;
+  int nvec;
 
-  if(disorder_stats(getclient(), &vec, 0)) exit(EXIT_FAILURE);
-  while(*vec)
-      xprintf("%s\n", nullcheck(utf82mb(*vec++)));
+  if(disorder_stats(getclient(), &vec, &nvec)) exit(EXIT_FAILURE);
+  for(int n = 0; n < nvec; ++n)
+    xprintf("%s\n", nullcheck(utf82mb(vec[n])));
+  free_strings(nvec, vec);
 }
 
 static void cf_get_volume(char attribute((unused)) **argv) {
@@ -339,7 +345,7 @@ static void cf_part(char **argv) {
   char *s;
 
   if(disorder_part(getclient(), &s, argv[0], argv[1], argv[2])) exit(EXIT_FAILURE);
-  xprintf("%s\n", nullcheck(utf82mb(s)));
+  xprintf("%s\n", nullcheck(utf82mb_f(s)));
 }
 
 static int isarg_filename(const char *s) {
@@ -354,7 +360,7 @@ static void cf_resolve(char **argv) {
   char *track;
 
   if(disorder_resolve(getclient(), &track, argv[0])) exit(EXIT_FAILURE);
-  xprintf("%s\n", nullcheck(utf82mb(track)));
+  xprintf("%s\n", nullcheck(utf82mb_f(track)));
 }
 
 static void cf_pause(char attribute((unused)) **argv) {
@@ -385,7 +391,7 @@ static void cf_get_global(char **argv) {
   char *value;
 
   if(disorder_get_global(getclient(), argv[0], &value)) exit(EXIT_FAILURE);
-  xprintf("%s\n", nullcheck(utf82mb(value)));
+  xprintf("%s\n", nullcheck(utf82mb_f(value)));
 }
 
 static void cf_set_global(char **argv) {
@@ -446,7 +452,7 @@ static void cf_userinfo(char **argv) {
 
   if(disorder_userinfo(getclient(), argv[0], argv[1], &s))
     exit(EXIT_FAILURE);
-  xprintf("%s\n", nullcheck(utf82mb(s)));
+  xprintf("%s\n", nullcheck(utf82mb_f(s)));
 }
 
 static int isarg_option(const char *arg) {
@@ -609,11 +615,13 @@ static void cf_adopt(char **argv) {
 
 static void cf_playlists(char attribute((unused)) **argv) {
   char **vec;
+  int nvec;
 
-  if(disorder_playlists(getclient(), &vec, 0))
+  if(disorder_playlists(getclient(), &vec, &nvec))
     exit(EXIT_FAILURE);
-  while(*vec)
-    xprintf("%s\n", nullcheck(utf82mb(*vec++)));
+  for(int n = 0; n < nvec; ++n)
+    xprintf("%s\n", nullcheck(utf82mb(vec[n])));
+  free_strings(nvec, vec);
 }
 
 static void cf_playlist_del(char **argv) {
@@ -623,11 +631,13 @@ static void cf_playlist_del(char **argv) {
 
 static void cf_playlist_get(char **argv) {
   char **vec;
+  int nvec;
 
-  if(disorder_playlist_get(getclient(), argv[0], &vec, 0))
+  if(disorder_playlist_get(getclient(), argv[0], &vec, &nvec))
     exit(EXIT_FAILURE);
-  while(*vec)
-    xprintf("%s\n", nullcheck(utf82mb(*vec++)));
+  for(int n = 0; n < nvec; ++n)
+    xprintf("%s\n", nullcheck(utf82mb(vec[n])));
+  free_strings(nvec, vec);
 }
 
 static void cf_playlist_set(char **argv) {
@@ -864,11 +874,14 @@ int main(int argc, char **argv) {
   }
   if(config_read(0, NULL)) disorder_fatal(0, "cannot read configuration");
   if(user) {
-    config->username = user;
+    xfree(config->username);
+    config->username = xstrdup(user);
     config->password = 0;
   }
-  if(password)
-    config->password = password;
+  if(password) {
+    xfree(config->password);
+    config->password = xstrdup(password);
+  }
   if(local)
     config->connect.af = -1;
   if(wfr)
@@ -889,7 +902,7 @@ int main(int argc, char **argv) {
     vector_init(&args);
     /* Include the command name in the args, but at element -1, for
      * the benefit of subcommand getopt calls */
-    vector_append(&args, argv[n]);
+    vector_append(&args, xstrdup(argv[n]));
     n++;
     for(j = 0; j < commands[i].min; ++j)
       vector_append(&args, nullcheck(mb2utf8(argv[n + j])));
@@ -899,10 +912,13 @@ int main(int argc, char **argv) {
       vector_append(&args, nullcheck(mb2utf8(argv[n + j])));
     vector_terminate(&args);
     commands[i].fn(args.vec + 1);
+    vector_clear(&args);
     n += j;
   }
   if(client && disorder_close(client)) exit(EXIT_FAILURE);
   if(fclose(stdout) < 0) disorder_fatal(errno, "error closing stdout");
+  config_free(config);
+  xfree(client);
   return status;
 }
 
index a02c1c6e698188013c2a5e80051a5083ab8d92ed..0c6e7d74dd44756d10f123f6bbaba055aafc59e3 100644 (file)
@@ -120,11 +120,13 @@ static void set_service(struct config *c, const char *s) {
 }
 
 static void set_username(struct config *c, const char *s) {
-  c->username = s;
+  xfree(c->username);
+  c->username = xstrdup(s);
 }
 
 static void set_password(struct config *c, const char *s) {
-  c->password = s;
+  xfree(c->password);
+  c->password = xstrdup(s);
 }
 
 /** @brief Table used to generate the form */
index ff0eb8b18074c706f70162946386e19b641cde8d..eea622032829866a1af95a9ed135fd8d5d140d74 100644 (file)
@@ -25,7 +25,7 @@ else
 TRACKDB=trackdb-stub.c
 endif
 
-libdisorder_a_SOURCES=charset.c charset.h              \
+libdisorder_a_SOURCES=charset.c charsetf.c charset.h   \
        addr.c addr.h                                   \
        arcfour.c arcfour.h                             \
        authhash.c authhash.h                           \
index da37319012c19f5f6a85a9c8f0f7a5577f280d48..fd9fa6cbdce2dde0faadc6e6c1ed48e07469f547 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * This file is part of DisOrder
- * Copyright (C) 2004-2008 Richard Kettlewell
+ * Copyright (C) 2004-2009 Richard Kettlewell
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
 int byte_vasprintf(char **ptrp,
                   const char *fmt,
                   va_list ap) {
+  struct sink *s;
   struct dynstr d;
   int n;
 
   dynstr_init(&d);
-  if((n = byte_vsinkprintf(sink_dynstr(&d), fmt, ap)) >= 0) {
+  s = sink_dynstr(&d);
+  n = byte_vsinkprintf(s, fmt, ap);
+  xfree(s);
+  if(n >= 0) {
     dynstr_terminate(&d);
     *ptrp = d.vec;
   }
index 8cc96f904542949d984c5104efe83be04040ff42..c06c233ed26642833a92517ce9ae425a93ba758e 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * This file is part of DisOrder
- * Copyright (C) 2004, 2006, 2007 Richard Kettlewell
+ * Copyright (C) 2004, 2006, 2007, 2009 Richard Kettlewell
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -64,10 +64,10 @@ static const struct algorithm algorithms[] = {
  * Computes H(challenge|password) and returns it as a newly allocated hex
  * string, or returns NULL on error.
  */
-const char *authhash(const void *challenge, size_t nchallenge,
-                    const char *password, const char *algo) {
+char *authhash(const void *challenge, size_t nchallenge,
+               const char *password, const char *algo) {
   gcrypt_hash_handle h;
-  const char *res;
+  char *res;
   size_t n;
   int id;
 
index 8604a13948f1a81e602ea15992a87ecc15c35c29..7b73d67ea7acfd8a3b7df235ecbf4b945c40d395 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * This file is part of DisOrder.
- * Copyright (C) 2004, 2006, 2007, 2008 Richard Kettlewell
+ * Copyright (C) 2004, 2006-2009 Richard Kettlewell
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -19,8 +19,8 @@
 #ifndef AUTHHASH_H
 #define AUTHHASH_H
 
-const char *authhash(const void *challenge, size_t nchallenge,
-                    const char *user, const char *algo);
+char *authhash(const void *challenge, size_t nchallenge,
+               const char *user, const char *algo);
 int valid_authhash(const char *algo);
 
 #endif /* AUTHHASH_H */
index be2b05a45ae5a3ced48f189fb1b69167b701a330..e3c3a4eb59b560e9a6a9ce4afcd5fd714582e835 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * This file is part of DisOrder.
- * Copyright (C) 2004, 2005, 2007, 2008 Richard Kettlewell
+ * Copyright (C) 2004, 2005, 2007-2009 Richard Kettlewell
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -49,6 +49,16 @@ char *any2any(const char *from/*encoding or 0*/,
  * that iconv knows.  If FROM and TO are both 0 then ANY is returned
  * unchanged. */
 
+char *mb2utf8_f(char *mb);
+char *utf82mb_f(char *utf8);
+char *any2utf8_f(const char *from/*encoding*/,
+                 char *any/*string*/);
+char *any2mb_f(const char *from/*encoding or 0*/,
+               char *any/*string*/);
+char *any2any_f(const char *from/*encoding or 0*/,
+                const char *to/*encoding to 0*/,
+                char *any/*string*/);
+
 /** @brief Insist that @p s is not null
  * @param s Pointer to check
  * @return @p s
diff --git a/lib/charsetf.c b/lib/charsetf.c
new file mode 100644 (file)
index 0000000..cb27974
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * This file is part of DisOrder.
+ * Copyright (C) 2004, 2005, 2007, 2008 Richard Kettlewell
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+/** @file lib/charsetf.c @brief Character set conversion with free() */
+
+#include "common.h"
+
+#include "charset.h"
+#include "mem.h"
+
+char *mb2utf8_f(char *mb) {
+  char *s = mb2utf8(mb);
+  xfree(mb);
+  return s;
+}
+
+char *utf82mb_f(char *utf8) {
+  char *s = utf82mb(utf8);
+  xfree(utf8);
+  return s;
+}
+
+char *any2utf8_f(const char *from,
+                 char *any) {
+  char *s = any2utf8(from, any);
+  xfree(any);
+  return s;
+}
+
+char *any2mb_f(const char *from,
+               char *any) {
+  char *s = any2mb(from, any);
+  xfree(any);
+  return s;
+}
+
+char *any2any_f(const char *from,
+                const char *to,
+                char *any) {
+  char *s = any2any(from, to, any);
+  xfree(any);
+  return s;
+}
+
+/*
+Local Variables:
+c-basic-offset:2
+comment-column:40
+fill-column:79
+indent-tabs-mode:nil
+End:
+*/
index c55da8939fb6084e9f52e98910ef65ef5b6bfeb6..d5c61ce62f6f08ee650fc4802843a81a8c38f00b 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * This file is part of DisOrder
- * Copyright (C) 2004, 2005, 2006, 2007 Richard Kettlewell
+ * Copyright (C) 2004, 2005, 2006, 2007, 2009 Richard Kettlewell
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -63,6 +63,7 @@ socklen_t find_server(struct config *c,
     strcpy(su.sun_path, name);
     sa = (struct sockaddr *)&su;
     len = sizeof su;
+    xfree(name);
   }
   *sap = xmalloc_noptr(len);
   memcpy(*sap, sa, len);
index 00727ef010e78f62e3e6adbc0f771b2da9ba1f17..2cbcfa76201324f07dc0668975b5dd5c51a98291 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * This file is part of DisOrder.
- * Copyright (C) 2004-2008 Richard Kettlewell
+ * Copyright (C) 2004-2009 Richard Kettlewell
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -141,10 +141,12 @@ static int check_response(disorder_client *c, char **rp) {
   else if(rc / 100 == 2) {
     if(rp)
       *rp = (rc % 10 == 9) ? 0 : xstrdup(r + 4);
+    xfree(r);
     return 0;
   } else {
     if(c->verbose)
       disorder_error(0, "from %s: %s", c->ident, utf82mb(r));
+    xfree(r);
     return rc;
   }
 }
@@ -200,6 +202,7 @@ static int disorder_simple_v(disorder_client *c,
     D(("command: %s", d.vec));
     if(fputs(d.vec, c->fpout) < 0)
       goto write_error;
+    xfree(d.vec);
     if(body) {
       if(nbody < 0)
         for(nbody = 0; body[nbody]; ++nbody)
@@ -291,7 +294,9 @@ static int dequote(int rc, char **rp) {
 
   if(!rc) {
     if((rr = split(*rp, 0, SPLIT_QUOTES, 0, 0)) && *rr) {
+      xfree(*rp);
       *rp = *rr;
+      xfree(rr);
       return 0;
     }
     disorder_error(0, "invalid reply: %s", *rp);
@@ -316,13 +321,13 @@ int disorder_connect_generic(struct config *conf,
                              const char *username,
                              const char *password,
                              const char *cookie) {
-  int fd = -1, fd2 = -1, nrvec, rc;
-  unsigned char *nonce;
+  int fd = -1, fd2 = -1, nrvec = 0, rc;
+  unsigned char *nonce = NULL;
   size_t nl;
-  const char *res;
-  char *r, **rvec;
+  char *res = NULL;
+  char *r = NULL, **rvec = NULL;
   const char *protocol, *algorithm, *challenge;
-  struct sockaddr *sa;
+  struct sockaddr *sa = NULL;
   socklen_t salen;
 
   if((salen = find_server(conf, &sa, &c->ident)) == (socklen_t)-1)
@@ -364,14 +369,14 @@ int disorder_connect_generic(struct config *conf,
     disorder_error(0, "cannot parse server greeting %s", r);
     goto error;
   }
-  protocol = *rvec++;
+  protocol = rvec[0];
   if(strcmp(protocol, "2")) {
     c->last = "unknown protocol version";
     disorder_error(0, "unknown protocol version: %s", protocol);
     goto error;
   }
-  algorithm = *rvec++;
-  challenge = *rvec++;
+  algorithm = rvec[1];
+  challenge = rvec[2];
   if(!(nonce = unhex(challenge, &nl)))
     goto error;
   if(cookie) {
@@ -391,6 +396,11 @@ int disorder_connect_generic(struct config *conf,
   if((rc = disorder_simple(c, 0, "user", username, res, (char *)0)))
     goto error_rc;
   c->user = xstrdup(username);
+  xfree(res);
+  free_strings(nrvec, rvec);
+  xfree(nonce);
+  xfree(sa);
+  xfree(r);
   return 0;
 error:
   rc = -1;
@@ -505,7 +515,9 @@ int disorder_close(disorder_client *c) {
     }
     c->fpout = 0;
   }
+  xfree(c->ident);
   c->ident = 0;
+  xfree(c->user);
   c->user = 0;
   return ret;
 }
@@ -641,6 +653,7 @@ static int disorder_somequeue(disorder_client *c,
     if(!strcmp(l, ".")) {
       *qt = 0;
       *qp = qh;
+      xfree(l);
       return 0;
     }
     q = xmalloc(sizeof *q);
@@ -648,6 +661,7 @@ static int disorder_somequeue(disorder_client *c,
       *qt = q;
       qt = &q->next;
     }
+    xfree(l);
   }
   if(ferror(c->fpin)) {
     byte_xasprintf((char **)&c->last, "input error: %s", strerror(errno));
@@ -700,9 +714,11 @@ static int readlist(disorder_client *c, char ***vecp, int *nvecp) {
       if(nvecp)
        *nvecp = v.nvec;
       *vecp = v.vec;
+      xfree(l);
       return 0;
     }
-    vector_append(&v, l + (*l == '.'));
+    vector_append(&v, xstrdup(l + (*l == '.')));
+    xfree(l);
   }
   if(ferror(c->fpin)) {
     byte_xasprintf((char **)&c->last, "input error: %s", strerror(errno));
@@ -853,7 +869,9 @@ int disorder_prefs(disorder_client *c, const char *track, struct kvp **kp) {
     k->name = pvec[0];
     k->value = pvec[1];
     kp = &k->next;
+    xfree(pvec);
   }
+  free_strings(nvec, vec);
   *kp = 0;
   return 0;
 }
index 88cfbf280a6febfaca350b3492942760352247ad..53fddd5881318e4937a798e612abfc79da0771be 100644 (file)
@@ -240,6 +240,7 @@ static int set_string(const struct config_state *cs,
                   cs->path, cs->line, whoami->name);
     return -1;
   }
+  xfree(VALUE(cs->config, char *));
   VALUE(cs->config, char *) = xstrdup(vec[0]);
   return 0;
 }
@@ -520,8 +521,7 @@ static int set_rights(const struct config_state *cs,
                   cs->path, cs->line, vec[0]);
     return -1;
   }
-  *ADDRESS(cs->config, char *) = vec[0];
-  return 0;
+  return set_string(cs, whoami, nvec, vec);
 }
 
 static int set_netaddress(const struct config_state *cs,
@@ -644,7 +644,7 @@ static const struct conftype
   type_namepart = { set_namepart, free_namepartlist },
   type_transform = { set_transform, free_transformlist },
   type_netaddress = { set_netaddress, free_netaddress },
-  type_rights = { set_rights, free_none };
+  type_rights = { set_rights, free_string };
 
 /* specific validation routine */
 
@@ -1045,6 +1045,7 @@ static int validate_destaddr(const struct config_state attribute((unused)) *cs,
     disorder_error(0, "%s:%d: destination address required", cs->path, cs->line);
     return -1;
   }
+  xfree(na->address);
   return 0;
 }
 
@@ -1174,7 +1175,9 @@ static int config_set_args(const struct config_state *cs,
     vector_append(v, s);
   va_end(ap);
   vector_terminate(v);
-  return config_set(cs, v->nvec, v->vec);
+  int rc = config_set(cs, v->nvec, v->vec);
+  xfree(v->vec);
+  return rc;
 }
 
 /** @brief Error callback used by config_include()
@@ -1417,7 +1420,7 @@ static void set_configfile(void) {
  *
  * @p c is indeterminate after this function is called.
  */
-static void config_free(struct config *c) {
+void config_free(struct config *c) {
   int n;
 
   if(c) {
index 22e107d62be9b746b379b9b551317bed28095a3a..8255db2e6e7268c4c411bf71ab40847abd199118 100644 (file)
@@ -195,10 +195,10 @@ struct config {
   const char *home;
 
   /** @brief Login username */
-  const char *username;
+  char *username;
 
   /** @brief Login password */
-  const char *password;
+  char *password;
 
   /** @brief Address to connect to */
   struct netaddress connect;
@@ -328,6 +328,8 @@ char *config_private(void);
 
 int config_verify(void);
 
+void config_free(struct config *c);
+
 extern char *configfile;
 extern int config_per_user;
 
index ac0c0d813f8e070acc2df1e258403234ea53df9b..3227f12f38fd3f5af07de8b255d424257613d3dd 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * This file is part of DisOrder
- * Copyright (C) 2004, 2007, 2008 Richard Kettlewell
+ * Copyright (C) 2004, 2007-2009 Richard Kettlewell
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -26,6 +26,7 @@
 
 #include "printf.h"
 #include "sink.h"
+#include "mem.h"
 
 /** @brief vfprintf() workalike that always accepts UTF-8
  * @param fp Stream to write to
  * @return -1 on error or bytes written on success
  */
 int byte_vfprintf(FILE *fp, const char *fmt, va_list ap) {
-  return byte_vsinkprintf(sink_stdio(0, fp), fmt, ap);
+  struct sink *s = sink_stdio(0, fp);
+  int rc = byte_vsinkprintf(s, fmt, ap);
+  xfree(s);
+  return rc;
 }
 
 /** @brief fprintf() workalike that always accepts UTF-8
index 45aa03c190f3533540b95f323d473e9e95b0b594..f17cdc1edb05c9ac77ed63b3332465409b07edd6 100644 (file)
--- a/lib/kvp.c
+++ b/lib/kvp.c
@@ -287,6 +287,15 @@ struct kvp *kvp_make(const char *name, ...) {
   return kvp;
 }
 
+void kvp_free(struct kvp *k) {
+  if(k) {
+    kvp_free(k->next);
+    xfree((void *)k->name);
+    xfree((void *)k->value);
+    xfree(k);
+  }
+}
+
 /*
 Local Variables:
 c-basic-offset:2
index 0a7e4780d0af3691c25ea3a10043406f78e26c0f..732a8a68623613be96154d3a0d3c95a57baaffeb 100644 (file)
--- a/lib/kvp.h
+++ b/lib/kvp.h
@@ -71,6 +71,8 @@ char *urlencodestring(const char *s);
 char *urldecodestring(const char *s, size_t ns);
 struct kvp *kvp_make(const char *key, ...);
 
+void kvp_free(struct kvp *k);
+
 #endif /* KVP_H */
 
 /*
index 69a798696737e9f2d2efe629cffc62e3839d444b..0f39b23800fa5c31991fda8e7b21fb9ecdbc4842 100644 (file)
@@ -30,6 +30,7 @@
 #include "syscalls.h"
 #include "table.h"
 #include "printf.h"
+#include "vector.h"
 
 const char *const playing_states[] = {
   "failed",
@@ -95,11 +96,17 @@ static const char *marshall_long(const struct queue_entry *q, size_t offset) {
   return xstrdup(buffer);
 }
 
+static void free_none(struct queue_entry attribute((unused)) *q,
+                      size_t attribute((unused)) offset) {
+}
+
+#define free_long free_none
+
 static int unmarshall_string(char *data, struct queue_entry *q,
                             size_t offset,
                             void attribute((unused)) (*error_handler)(const char *, void *),
                             void attribute((unused)) *u) {
-  VALUE(q, offset, char *) = data;
+  VALUE(q, offset, char *) = xstrdup(data);
   return 0;
 }
 
@@ -107,6 +114,10 @@ static const char *marshall_string(const struct queue_entry *q, size_t offset) {
   return VALUE(q, offset, char *);
 }
 
+static void free_string(struct queue_entry *q, size_t offset) {
+  xfree(VALUE(q, offset, char *));
+}
+
 static int unmarshall_time_t(char *data, struct queue_entry *q,
                             size_t offset,
                             void (*error_handler)(const char *, void *),
@@ -134,6 +145,8 @@ static const char *marshall_time_t(const struct queue_entry *q, size_t offset) {
   return xstrdup(buffer);
 }
 
+#define free_time_t free_none
+
 static int unmarshall_state(char *data, struct queue_entry *q,
                            size_t offset,
                            void (*error_handler)(const char *, void *),
@@ -176,7 +189,10 @@ static const char *marshall_origin(const struct queue_entry *q, size_t offset) {
   return track_origins[VALUE(q, offset, enum track_origin)];
 }
 
-#define F(n, h) { #n, offsetof(struct queue_entry, n), marshall_##h, unmarshall_##h }
+#define free_state free_none
+#define free_origin free_none
+
+#define F(n, h) { #n, offsetof(struct queue_entry, n), marshall_##h, unmarshall_##h, free_##h }
 
 static const struct field {
   const char *name;
@@ -185,6 +201,7 @@ static const struct field {
   int (*unmarshall)(char *data, struct queue_entry *q, size_t offset,
                    void (*error_handler)(const char *, void *),
                    void *u);
+  void (*free)(struct queue_entry *q, size_t offset);
 } fields[] = {
   /* Keep this table sorted. */
   F(expected, time_t),
@@ -199,6 +216,7 @@ static const struct field {
   F(when, time_t),
   F(wstat, long)
 };
+#define NFIELDS (sizeof fields / sizeof *fields)
 
 int queue_unmarshall(struct queue_entry *q, const char *s,
                     void (*error_handler)(const char *, void *),
@@ -209,7 +227,9 @@ int queue_unmarshall(struct queue_entry *q, const char *s,
   q->pid = -1;                          /* =none */
   if(!(vec = split(s, &nvec, SPLIT_QUOTES, error_handler, u)))
     return -1;
-  return queue_unmarshall_vec(q, nvec, vec, error_handler, u);
+  int rc = queue_unmarshall_vec(q, nvec, vec, error_handler, u);
+  free_strings(nvec, vec);
+  return rc;
 }
 
 int queue_unmarshall_vec(struct queue_entry *q, int nvec, char **vec,
@@ -258,6 +278,16 @@ char *queue_marshall(const struct queue_entry *q) {
   return r;
 }
 
+void queue_free(struct queue_entry *q, int rest) {
+  if(!q)
+    return;
+  if(rest)
+    queue_free(q->next, rest);
+  for(unsigned n = 0; n < NFIELDS; ++n)
+    fields[n].free(q, fields[n].offset);
+  xfree(q);
+}
+
 /*
 Local Variables:
 c-basic-offset:2
index c287ebe950afd4eb9ce55e989be998c6c1713796..2219763f6539cd5da3b83b9a01979ced7ea43872 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * This file is part of DisOrder.
- * Copyright (C) 2004-2008 Richard Kettlewell
+ * Copyright (C) 2004-2009 Richard Kettlewell
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -238,6 +238,8 @@ int queue_unmarshall_vec(struct queue_entry *q, int nvec, char **vec,
 char *queue_marshall(const struct queue_entry *q);
 /* marshall @q@ into a UTF-8 string */
 
+void queue_free(struct queue_entry *q, int rest);
+
 #endif /* QUEUE_H */
 
 /*
index 4d798f1b31037554a22a466a1271e8cb1f1e8bba..fa8f9e388df6d0c90f157eacc94c7e14d6db4cd7 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * This file is part of DisOrder.
- * Copyright (C) 2004, 2007, 2008 Richard Kettlewell
+ * Copyright (C) 2004, 2007-2009 Richard Kettlewell
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -38,6 +38,19 @@ void dynstr_append_bytes(struct dynstr *v, const char *ptr, size_t n) {
   }
 }
 
+/** @brief Free a string list */
+void free_strings(int nvec, char **vec) {
+  for(int n = 0; n < nvec; ++n)
+    xfree(vec[n]);
+  xfree(vec);
+}
+
+/** @brief Free and re-initialize a vector */
+void vector_clear(struct vector *v) {
+  free_strings(v->nvec, v->vec);
+  vector_init(v);
+}
+
 /*
 Local Variables:
 c-basic-offset:2
index 31dfeda5e86ffee911719a8e901a1e927f781cdc..da84784e39ab0e45be79cff6b85a2a86b325cee1 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * This file is part of DisOrder.
- * Copyright (C) 2004, 2005, 2007, 2008 Richard Kettlewell
+ * Copyright (C) 2004, 2005, 2007-2009 Richard Kettlewell
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -94,6 +94,9 @@ static inline void dynstr_append_string(struct dynstr *v, const char *ptr) {
   dynstr_append_bytes(v, ptr, strlen(ptr));
 }
 
+void free_strings(int nvec, char **vec);
+void vector_clear(struct vector *v);
+
 #endif /* VECTOR_H */
 
 /*