[MINOR] implement per-logger log level limitation

Some people are using haproxy in a shared environment where the
system logger by default sends alert and emerg messages to all
consoles, which happens when all servers go down on a backend for
instance. These people can not always change the system configuration
and would like to limit the outgoing messages level in order not to
disturb the local users.

The addition of an optional 4th field on the "log" line permits
exactly this. The minimal log level ensures that all outgoing logs
will have at least this level. So the logs are not filtered out,
just set to this level.
diff --git a/doc/configuration.txt b/doc/configuration.txt
index 454bbd3..43627b5 100644
--- a/doc/configuration.txt
+++ b/doc/configuration.txt
@@ -415,7 +415,7 @@
   Similar to "gid" but uses the GID of group name <group name> from /etc/group.
   See also "gid" and "user".
   
-log <address> <facility> [max level]
+log <address> <facility> [max level [min level]]
   Adds a global syslog server. Up to two global servers can be defined. They
   will receive logs for startups and exits, as well as all logs from proxies
   configured with "log global".
@@ -438,8 +438,12 @@
           local0 local1 local2 local3 local4 local5 local6 local7
 
   An optional level can be specified to filter outgoing messages. By default,
-  all messages are sent. If a level is specified, only messages with a severity
-  at least as important as this level will be sent. 8 levels are known :
+  all messages are sent. If a maximum level is specified, only messages with a
+  severity at least as important as this level will be sent. An optional minimum
+  level can be specified. If it is set, logs emitted with a more severe level
+  than this one will be capped to this level. This is used to avoid sending
+  "emerg" messages on all terminals on some default syslog configurations.
+  Eight levels are known :
 
 	  emerg  alert  crit   err    warning notice info  debug
 
@@ -1640,7 +1644,7 @@
 
 
 log global
-log <address> <facility> [<level>]
+log <address> <facility> [<level> [<minlevel>]]
   Enable per-instance logging of events and traffic.
   May be used in sections :   defaults | frontend | listen | backend
                                  yes   |    yes   |   yes  |   yes
@@ -1673,7 +1677,11 @@
     <level>    is optional and can be specified to filter outgoing messages. By
                default, all messages are sent. If a level is specified, only
                messages with a severity at least as important as this level
-               will be sent. 8 levels are known :
+               will be sent. An optional minimum level can be specified. If it
+               is set, logs emitted with a more severe level than this one will
+               be capped to this level. This is used to avoid sending "emerg"
+               messages on all terminals on some default syslog configurations.
+               Eight levels are known :
 
                  emerg  alert  crit   err    warning notice info  debug
 
@@ -1696,7 +1704,8 @@
 
   Example :
     log global
-    log 127.0.0.1:514 local0 notice
+    log 127.0.0.1:514 local0 notice         # only send important events
+    log 127.0.0.1:514 local0 notice notice  # same but limit output level
 
 
 maxconn <conns>
diff --git a/include/types/global.h b/include/types/global.h
index d0c22bc..1ba0b11 100644
--- a/include/types/global.h
+++ b/include/types/global.h
@@ -72,6 +72,7 @@
 	char *pidfile;
 	int logfac1, logfac2;
 	int loglev1, loglev2;
+	int minlvl1, minlvl2;
 	struct logsrv logsrv1, logsrv2;
 	struct {
 		int maxpollevents; /* max number of poll events at once */
diff --git a/include/types/proxy.h b/include/types/proxy.h
index 3cb60c0..7ef5fc8 100644
--- a/include/types/proxy.h
+++ b/include/types/proxy.h
@@ -266,6 +266,7 @@
 	struct logsrv logsrv1, logsrv2;		/* 2 syslog servers */
 	signed char logfac1, logfac2;		/* log facility for both servers. -1 = disabled */
 	int loglev1, loglev2;			/* log level for each server, 7 by default */
+	int minlvl1, minlvl2;			/* minimum log level for each server, 0 by default */
 	int to_log;				/* things to be logged (LW_*) */
 	int stop_time;                          /* date to stop listening, when stopping != 0 (int ticks) */
 	int nb_reqadd, nb_rspadd;
diff --git a/src/cfgparse.c b/src/cfgparse.c
index 3a71df2..e3c8b62 100644
--- a/src/cfgparse.c
+++ b/src/cfgparse.c
@@ -553,7 +553,7 @@
 	}
 	else if (!strcmp(args[0], "log")) {  /* syslog server address */
 		struct logsrv logsrv;
-		int facility, level;
+		int facility, level, minlvl;
 	
 		if (*(args[1]) == 0 || *(args[2]) == 0) {
 			Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
@@ -575,6 +575,15 @@
 			}
 		}
 
+		minlvl = 0; /* limit syslog level to this level (emerg) */
+		if (*(args[4])) {
+			minlvl = get_log_level(args[4]);
+			if (level < 0) {
+				Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
+				exit(1);
+			}
+		}
+
 		if (args[1][0] == '/') {
 			logsrv.u.addr.sa_family = AF_UNIX;
 			logsrv.u.un = *str2sun(args[1]);
@@ -589,11 +598,13 @@
 			global.logsrv1 = logsrv;
 			global.logfac1 = facility;
 			global.loglev1 = level;
+			global.minlvl1 = minlvl;
 		}
 		else if (global.logfac2 == -1) {
 			global.logsrv2 = logsrv;
 			global.logfac2 = facility;
 			global.loglev2 = level;
+			global.minlvl2 = minlvl;
 		}
 		else {
 			Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
@@ -847,9 +858,11 @@
 		curproxy->logfac1 = defproxy.logfac1;
 		curproxy->logsrv1 = defproxy.logsrv1;
 		curproxy->loglev1 = defproxy.loglev1;
+		curproxy->minlvl1 = defproxy.minlvl1;
 		curproxy->logfac2 = defproxy.logfac2;
 		curproxy->logsrv2 = defproxy.logsrv2;
 		curproxy->loglev2 = defproxy.loglev2;
+		curproxy->minlvl2 = defproxy.minlvl2;
 		curproxy->grace  = defproxy.grace;
 		curproxy->uuid = next_pxid++;   /* generate a uuid for this proxy */
 		curproxy->next_svid = 1;        /* server id 0 is reserved */
@@ -2302,12 +2315,14 @@
 			curproxy->logfac1 = global.logfac1;
 			curproxy->logsrv1 = global.logsrv1;
 			curproxy->loglev1 = global.loglev1;
+			curproxy->minlvl1 = global.minlvl1;
 			curproxy->logfac2 = global.logfac2;
 			curproxy->logsrv2 = global.logsrv2;
 			curproxy->loglev2 = global.loglev2;
+			curproxy->minlvl2 = global.minlvl2;
 		}
 		else if (*(args[1]) && *(args[2])) {
-			int level;
+			int level, minlvl;
 
 			facility = get_log_facility(args[2]);
 			if (facility < 0) {
@@ -2324,6 +2339,15 @@
 				}
 			}
 
+			minlvl = 0; /* limit syslog level to this level (emerg) */
+			if (*(args[4])) {
+				minlvl = get_log_level(args[4]);
+				if (level < 0) {
+					Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
+					exit(1);
+				}
+			}
+
 			if (args[1][0] == '/') {
 				logsrv.u.addr.sa_family = AF_UNIX;
 				logsrv.u.un = *str2sun(args[1]);
@@ -2340,11 +2364,13 @@
 				curproxy->logsrv1 = logsrv;
 				curproxy->logfac1 = facility;
 				curproxy->loglev1 = level;
+				curproxy->minlvl1 = minlvl;
 			}
 			else if (curproxy->logfac2 == -1) {
 				curproxy->logsrv2 = logsrv;
 				curproxy->logfac2 = facility;
 				curproxy->loglev2 = level;
+				curproxy->minlvl2 = minlvl;
 			}
 			else {
 				Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
diff --git a/src/log.c b/src/log.c
index bc9fd0a..093accb 100644
--- a/src/log.c
+++ b/src/log.c
@@ -176,7 +176,7 @@
 	int fac_level;
 	int hdr_len, data_len;
 	struct logsrv *logsrvs[2];
-	int facilities[2], loglevel[2];
+	int facilities[2], loglevel[2], minlvl[2];
 	int nblogger;
 	int nbloggers = 0;
 	char *log_ptr;
@@ -222,12 +222,14 @@
 			logsrvs[nbloggers] = &global.logsrv1;
 			facilities[nbloggers] = global.logfac1;
 			loglevel[nbloggers] = global.loglev1;
+			minlvl[nbloggers] = global.minlvl1;
 			nbloggers++;
 		}
 		if (global.logfac2 >= 0) {
 			logsrvs[nbloggers] = &global.logsrv2;
 			facilities[nbloggers] = global.logfac2;
 			loglevel[nbloggers] = global.loglev2;
+			minlvl[nbloggers] = global.minlvl2;
 			nbloggers++;
 		}
 	} else {
@@ -235,12 +237,14 @@
 			logsrvs[nbloggers] = &p->logsrv1;
 			facilities[nbloggers] = p->logfac1;
 			loglevel[nbloggers] = p->loglev1;
+			minlvl[nbloggers] = p->minlvl1;
 			nbloggers++;
 		}
 		if (p->logfac2 >= 0) {
 			logsrvs[nbloggers] = &p->logsrv2;
 			facilities[nbloggers] = p->logfac2;
 			loglevel[nbloggers] = p->loglev2;
+			minlvl[nbloggers] = p->minlvl2;
 			nbloggers++;
 		}
 	}
@@ -292,7 +296,7 @@
 		 * time, we only change the facility in the pre-computed header,
 		 * and we change the pointer to the header accordingly.
 		 */
-		fac_level = (facilities[nblogger] << 3) + level;
+		fac_level = (facilities[nblogger] << 3) + MAX(level, minlvl[nblogger]);
 		log_ptr = logmsg + 3; /* last digit of the log level */
 		do {
 			*log_ptr = '0' + fac_level % 10;