[MEDIUM] Fix memory freeing at exit, part 2

- free oldpids
- call free(exp->preg), not only regfree(exp->preg): req_exp, rsp_exp
- build a list of unique uri_auths and eventually free it
- prune_acl_cond/free for switching_rules
- add a callback pointer to free ptr from acl_pattern (used for regexs) and execute it

==1180== malloc/free: in use at exit: 0 bytes in 0 blocks.
==1180== malloc/free: 5,599 allocs, 5,599 frees, 4,220,556 bytes allocated.
==1180== All heap blocks were freed -- no leaks are possible.
diff --git a/include/common/uri_auth.h b/include/common/uri_auth.h
index fbbe7df..e52387c 100644
--- a/include/common/uri_auth.h
+++ b/include/common/uri_auth.h
@@ -42,6 +42,7 @@
 	int flags;			/* some flags describing the statistics page */
 	struct user_auth *users;	/* linked list of valid user:passwd couples */
 	struct stat_scope *scope;	/* linked list of authorized proxies */
+	struct uri_auth *next;		/* Used at deinit() to build a list of unique elements */
 };
 
 /* This is the default statistics URI */
diff --git a/include/types/acl.h b/include/types/acl.h
index ef5be58..53f9e70 100644
--- a/include/types/acl.h
+++ b/include/types/acl.h
@@ -101,6 +101,7 @@
 		char *str;              /* any string  */
 		regex_t *reg;           /* a compiled regex */
 	} ptr;                          /* indirect values, allocated */
+	void(*freeptrbuf)(void *ptr);	/* a destructor able to free objects from the ptr */
 	int len;                        /* data length when required  */
 	int flags;                      /* expr or pattern flags. */
 };
diff --git a/src/acl.c b/src/acl.c
index 96b21de..02678f2 100644
--- a/src/acl.c
+++ b/src/acl.c
@@ -285,6 +285,12 @@
 	return 1;
 }
 
+/* Free data allocated by acl_parse_reg */
+static void acl_free_reg(void *ptr) {
+
+	regfree((regex_t *)ptr);
+}
+
 /* Parse a regex. It is allocated. */
 int acl_parse_reg(const char **text, struct acl_pattern *pattern, int *opaque)
 {
@@ -303,6 +309,7 @@
 	}
 
 	pattern->ptr.reg = preg;
+	pattern->freeptrbuf = &acl_free_reg;
 	return 1;
 }
 
@@ -452,8 +459,14 @@
 
 static void free_pattern(struct acl_pattern *pat)
 {
-	if (pat->ptr.ptr)
+
+	if (pat->ptr.ptr) {
+		if (pat->freeptrbuf)
+			pat->freeptrbuf(pat->ptr.ptr);
+
 		free(pat->ptr.ptr);
+	}
+
 	free(pat);
 }
 
diff --git a/src/haproxy.c b/src/haproxy.c
index 4b6bdf8..d52524f 100644
--- a/src/haproxy.c
+++ b/src/haproxy.c
@@ -647,8 +647,11 @@
 	struct acl_cond *cond, *condb;
 	struct hdr_exp *exp, *expb;
 	struct acl *acl, *aclb;
+	struct switching_rule *rule, *ruleb;
+	struct uri_auth *uap, *ua = NULL;
+	struct user_auth *user;
 	int i;
-  
+
 	while (p) {
 		if (p->id)
 			free(p->id);
@@ -699,8 +702,11 @@
 		}
 
 		for (exp = p->req_exp; exp != NULL; ) {
-			if (exp->preg)
+			if (exp->preg) {
 				regfree((regex_t *)exp->preg);
+				free((regex_t *)exp->preg);
+			}
+
 			if (exp->replace && exp->action != ACT_SETBE)
 				free((char *)exp->replace);
 			expb = exp;
@@ -709,8 +715,11 @@
 		}
 
 		for (exp = p->rsp_exp; exp != NULL; ) {
-			if (exp->preg)
+			if (exp->preg) {
 				regfree((regex_t *)exp->preg);
+				free((regex_t *)exp->preg);
+			}
+
 			if (exp->replace && exp->action != ACT_SETBE)
 				free((char *)exp->replace);
 			expb = exp;
@@ -718,9 +727,21 @@
 			free(expb);
 		}
 
-		/* FIXME: this must also be freed :
-		 *  - uri_auth (but it's shared)
-		 */
+		/* build a list of unique uri_auths */
+		if (!ua)
+			ua = p->uri_auth;
+		else {
+			/* check if p->uri_auth is unique */
+			for (uap = ua; uap; uap=uap->next)
+				if (uap == p->uri_auth)
+					break;
+
+			if (!uap) {
+				/* add it, if it is */
+				p->uri_auth->next = ua;
+				ua = p->uri_auth;
+			}
+		}
 
 		list_for_each_entry_safe(acl, aclb, &p->acl, list) {
 			LIST_DEL(&acl->list);
@@ -728,6 +749,15 @@
 			free(acl);
 		}
 
+		list_for_each_entry_safe(rule, ruleb, &p->switching_rules, list) {
+			LIST_DEL(&rule->list);
+
+			prune_acl_cond(rule->cond);
+			free(rule->cond);
+
+			free(rule);
+		}
+
 		if (p->appsession_name)
 			free(p->appsession_name);
 
@@ -791,6 +821,27 @@
 		free(p0);
 	}/* end while(p) */
 
+	while (ua) {
+		uap = ua;
+		ua = ua->next;
+
+		if (uap->uri_prefix)
+			free(uap->uri_prefix);
+
+		if (uap->auth_realm)
+			free(uap->auth_realm);
+
+		while (uap->users) {
+			user = uap->users;
+			uap->users = uap->users->next;
+
+			free(user->user_pwd);
+			free(user);
+		}
+
+		free(uap);
+	}
+
 	protocol_unbind_all();
 
 	if (global.chroot)    free(global.chroot);
@@ -802,6 +853,9 @@
 	if (fdtab)            free(fdtab);
 	fdtab = NULL;
 
+	if (oldpids)
+		free(oldpids);
+
 	pool_destroy2(pool2_session);
 	pool_destroy2(pool2_buffer);
 	pool_destroy2(pool2_requri);