MINOR: init: add -dW and "zero-warning" to reject configs with warnings

Since some systems switched to service managers which hide all warnings
by default, some users are not aware of some possibly important warnings
and get caught too late with errors that could have been detected earlier.

This patch adds a new global keyword, "zero-warning" and an equivalent
command-line option "-dW" to refuse to start in case any warning is
detected. It is recommended to use these with configurations that are
managed by humans in order to catch mistakes very early.
diff --git a/doc/configuration.txt b/doc/configuration.txt
index 8347e8a..cf52148 100644
--- a/doc/configuration.txt
+++ b/doc/configuration.txt
@@ -711,6 +711,7 @@
  * Debugging
    - debug
    - quiet
+   - zero-warning
 
 
 3.1. Process management and security
@@ -2170,6 +2171,14 @@
   Do not display any message during startup. It is equivalent to the command-
   line argument "-q".
 
+zero-warning
+  When this option is set, haproxy will refuse to start if any warning was
+  emitted while processing the configuration. It is highly recommended to set
+  this option on configurations that are not changed often, as it helps detect
+  subtle mistakes and keep the configuration clean and forward-compatible. Note
+  that "haproxy -c" will also report errors in such a case. This option is
+  equivalent to command line argument "-dW".
+
 
 3.4. Userlists
 --------------
diff --git a/doc/management.txt b/doc/management.txt
index a1d8c9c..181dcf9 100644
--- a/doc/management.txt
+++ b/doc/management.txt
@@ -228,6 +228,15 @@
     environment. Never use this in an init script as it degrades SSL security
     to the servers.
 
+  -dW : if set, haproxy will refuse to start if any warning was emitted while
+   processing the configuration. This helps detect subtle mistakes and keep the
+   configuration clean and portable across versions. It is recommended to set
+   this option in service scripts when configurations are managed by humans,
+   but it is recommended not to use it with generated configurations, which
+   tend to emit more warnings. It may be combined with "-c" to cause warnings
+   in checked configurations to fail. This is equivalent to global option
+   "zero-warning".
+
   -db : disable background mode and multi-process mode. The process remains in
     foreground. It is mainly used during development or during small tests, as
     Ctrl-C is enough to stop the process. Never use it in an init script.
diff --git a/include/types/global.h b/include/types/global.h
index 718cfd8..407fbff 100644
--- a/include/types/global.h
+++ b/include/types/global.h
@@ -48,6 +48,7 @@
 #define	MODE_FOREGROUND	0x40
 #define	MODE_MWORKER	0x80    /* Master Worker */
 #define	MODE_MWORKER_WAIT	0x100    /* Master Worker wait mode */
+#define	MODE_ZERO_WARNING       0x200    /* warnings cause a failure */
 
 /* list of last checks to perform, depending on config options */
 #define LSTCHK_CAP_BIND	0x00000001	/* check that we can bind to any port */
diff --git a/src/cfgparse-global.c b/src/cfgparse-global.c
index 0e69059..2b32497 100644
--- a/src/cfgparse-global.c
+++ b/src/cfgparse-global.c
@@ -133,6 +133,11 @@
 			goto out;
 		global.mode |= MODE_QUIET;
 	}
+	else if (!strcmp(args[0], "zero-warning")) {
+		if (alertif_too_many_args(0, file, linenum, args, &err_code))
+			goto out;
+		global.mode |= MODE_ZERO_WARNING;
+	}
 	else if (!strcmp(args[0], "tune.runqueue-depth")) {
 		if (alertif_too_many_args(1, file, linenum, args, &err_code))
 			goto out;
diff --git a/src/haproxy.c b/src/haproxy.c
index 359b970..b06a780 100644
--- a/src/haproxy.c
+++ b/src/haproxy.c
@@ -658,6 +658,7 @@
 #endif
 		"        -dr ignores server address resolution failures\n"
 		"        -dV disables SSL verify on servers side\n"
+		"        -dW fails if any warning is emitted\n"
 		"        -sf/-st [pid ]* finishes/terminates old pids.\n"
 		"        -x <unix_socket> get listening sockets from a unix socket\n"
 		"        -S <bind>[,<bind options>...] new master CLI\n"
@@ -1762,6 +1763,8 @@
 				arg_mode |= MODE_VERBOSE;
 			else if (*flag == 'd' && flag[1] == 'b')
 				arg_mode |= MODE_FOREGROUND;
+			else if (*flag == 'd' && flag[1] == 'W')
+				arg_mode |= MODE_ZERO_WARNING;
 			else if (*flag == 'd' && flag[1] == 'M')
 				mem_poison_byte = flag[2] ? strtol(flag + 2, NULL, 0) : 'P';
 			else if (*flag == 'd' && flag[1] == 'r')
@@ -1895,7 +1898,7 @@
 	}
 
 	global.mode |= (arg_mode & (MODE_DAEMON | MODE_MWORKER | MODE_FOREGROUND | MODE_VERBOSE
-				    | MODE_QUIET | MODE_CHECK | MODE_DEBUG));
+				    | MODE_QUIET | MODE_CHECK | MODE_DEBUG | MODE_ZERO_WARNING));
 
 	if (getenv("HAPROXY_MWORKER_WAIT_ONLY")) {
 		unsetenv("HAPROXY_MWORKER_WAIT_ONLY");
@@ -2097,6 +2100,11 @@
 		exit(1);
 	}
 
+	if (warned & WARN_ANY && global.mode & MODE_ZERO_WARNING) {
+		ha_alert("Some warnings were found and 'zero-warning' is set. Aborting.\n");
+		exit(1);
+	}
+
 	if (global.mode & MODE_CHECK) {
 		struct peers *pr;
 		struct proxy *px;