[MEDIUM] make it possible to change the buffer size in the configuration

The new tune.bufsize and tune.maxrewrite global directives allow one to
change the buffer size and the maxrewrite size. Right now, setting bufsize
too low will block stats sockets which will not be able to write at all.
An error checking must be added to buffer_write_chunk() so that if it
cannot write its message to an empty buffer, it causes the caller to abort.
diff --git a/src/buffers.c b/src/buffers.c
index 55b7963..a20f3f4 100644
--- a/src/buffers.c
+++ b/src/buffers.c
@@ -17,6 +17,7 @@
 #include <common/config.h>
 #include <common/memory.h>
 #include <proto/buffers.h>
+#include <types/global.h>
 
 struct pool_head *pool2_buffer;
 
@@ -24,7 +25,7 @@
 /* perform minimal intializations, report 0 in case of error, 1 if OK. */
 int init_buffer()
 {
-	pool2_buffer = create_pool("buffer", sizeof(struct buffer) + BUFSIZE, MEM_F_SHARED);
+	pool2_buffer = create_pool("buffer", sizeof(struct buffer) + global.tune.bufsize, MEM_F_SHARED);
 	return pool2_buffer != NULL;
 }
 
diff --git a/src/cfgparse.c b/src/cfgparse.c
index a6b9f07..3828812 100644
--- a/src/cfgparse.c
+++ b/src/cfgparse.c
@@ -445,6 +445,26 @@
 		}
 		global.tune.maxaccept = atol(args[1]);
 	}
+	else if (!strcmp(args[0], "tune.bufsize")) {
+		if (*(args[1]) == 0) {
+			Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
+			err_code |= ERR_ALERT | ERR_FATAL;
+			goto out;
+		}
+		global.tune.bufsize = atol(args[1]);
+		if (global.tune.maxrewrite >= global.tune.bufsize / 2)
+			global.tune.maxrewrite = global.tune.bufsize / 2;
+	}
+	else if (!strcmp(args[0], "tune.maxrewrite")) {
+		if (*(args[1]) == 0) {
+			Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
+			err_code |= ERR_ALERT | ERR_FATAL;
+			goto out;
+		}
+		global.tune.maxrewrite = atol(args[1]);
+		if (global.tune.maxrewrite >= global.tune.bufsize / 2)
+			global.tune.maxrewrite = global.tune.bufsize / 2;
+	}
 	else if (!strcmp(args[0], "uid")) {
 		if (global.uid != 0) {
 			Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
@@ -3482,13 +3502,13 @@
 			goto out;
 		}
 
-		if (stat.st_size <= BUFSIZE) {
+		if (stat.st_size <= global.tune.bufsize) {
 			errlen = stat.st_size;
 		} else {
 			Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
-				file, linenum, args[2], BUFSIZE);
+				file, linenum, args[2], global.tune.bufsize);
 			err_code |= ERR_WARN;
-			errlen = BUFSIZE;
+			errlen = global.tune.bufsize;
 		}
 
 		err = malloc(errlen); /* malloc() must succeed during parsing */
diff --git a/src/client.c b/src/client.c
index 92baefc..76ea122 100644
--- a/src/client.c
+++ b/src/client.c
@@ -384,7 +384,7 @@
 		if ((s->req = pool_alloc2(pool2_buffer)) == NULL)
 			goto out_fail_req; /* no memory */
 
-		s->req->size = BUFSIZE;
+		s->req->size = global.tune.bufsize;
 		buffer_init(s->req);
 		s->req->prod = &s->si[0];
 		s->req->cons = &s->si[1];
@@ -393,7 +393,7 @@
 		s->req->flags |= BF_READ_ATTACHED; /* the producer is already connected */
 
 		if (p->mode == PR_MODE_HTTP) { /* reserve some space for header rewriting */
-			s->req->max_len -= MAXREWRITE;
+			s->req->max_len -= global.tune.maxrewrite;
 			s->req->flags |= BF_READ_DONTWAIT; /* one read is usually enough */
 		}
 
@@ -411,7 +411,7 @@
 		if ((s->rep = pool_alloc2(pool2_buffer)) == NULL)
 			goto out_fail_rep; /* no memory */
 
-		s->rep->size = BUFSIZE;
+		s->rep->size = global.tune.bufsize;
 		buffer_init(s->rep);
 		s->rep->prod = &s->si[1];
 		s->rep->cons = &s->si[0];
diff --git a/src/haproxy.c b/src/haproxy.c
index 09f8288..dd03e32 100644
--- a/src/haproxy.c
+++ b/src/haproxy.c
@@ -122,7 +122,11 @@
 				 .mode = 0,
 			 }
 		 }
-	}
+	},
+	.tune = {
+		.bufsize = BUFSIZE,
+		.maxrewrite = MAXREWRITE,
+	},
 	/* others NULL OK */
 };
 
@@ -177,7 +181,10 @@
 #ifdef BUILD_OPTIONS
 	       "\n  OPTIONS = " BUILD_OPTIONS
 #endif
-	       "\n\n");
+	       "\n\nDefault settings :"
+	       "\n  maxconn = %d, bufsize = %d, maxrewrite = %d, maxpollevents = %d"
+	       "\n\n",
+	       DEFAULT_MAXCONN, BUFSIZE, MAXREWRITE, MAX_POLL_EVENTS);
 }
 
 /*
@@ -604,6 +611,9 @@
 	if (global.tune.recv_enough == 0)
 		global.tune.recv_enough = MIN_RECV_AT_ONCE_ENOUGH;
 
+	if (global.tune.maxrewrite >= global.tune.bufsize / 2)
+		global.tune.maxrewrite = global.tune.bufsize / 2;
+
 	if (arg_mode & (MODE_DEBUG | MODE_FOREGROUND)) {
 		/* command line debug mode inhibits configuration mode */
 		global.mode &= ~(MODE_DAEMON | MODE_QUIET);
diff --git a/src/proto_uxst.c b/src/proto_uxst.c
index 0cd6a35..c811f64 100644
--- a/src/proto_uxst.c
+++ b/src/proto_uxst.c
@@ -482,7 +482,7 @@
 		if ((s->req = pool_alloc2(pool2_buffer)) == NULL)
 			goto out_free_task;
 
-		s->req->size = BUFSIZE;
+		s->req->size = global.tune.bufsize;
 		buffer_init(s->req);
 		s->req->prod = &s->si[0];
 		s->req->cons = &s->si[1];
@@ -499,7 +499,7 @@
 		if ((s->rep = pool_alloc2(pool2_buffer)) == NULL)
 			goto out_free_req;
 
-		s->rep->size = BUFSIZE;
+		s->rep->size = global.tune.bufsize;
 		buffer_init(s->rep);
 
 		s->rep->prod = &s->si[1];
diff --git a/src/session.c b/src/session.c
index 23c4409..f0c2d86 100644
--- a/src/session.c
+++ b/src/session.c
@@ -330,7 +330,7 @@
 		}
 	}
 	else {
-		buffer_set_rlim(rep, req->size - MAXREWRITE); /* rewrite needed */
+		buffer_set_rlim(rep, req->size - global.tune.maxrewrite); /* rewrite needed */
 		s->txn.rsp.msg_state = HTTP_MSG_RPBEFORE;
 		/* reset hdr_idx which was already initialized by the request.
 		 * right now, the http parser does it.