* released 1.2.1-pre1
* send an EMERG log when no server is available for a given proxy
* added the '-c' command line option to syntactically check the
  configuration file without starting the service.
diff --git a/CHANGELOG b/CHANGELOG
index b8ae2ac..2a65fa4 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,6 +1,11 @@
 ChangeLog :
 ===========
 
+2004/04/18 : 1.2.1 (1.1.28)
+  - send an EMERG log when no server is available for a given proxy
+  - added the '-c' command line option to syntactically check the
+    configuration file without starting the service.
+
 2003/11/09 : 1.2.0
   - the same as 1.1.27 + IPv6 support on the client side
 
diff --git a/TODO b/TODO
index c11c82f..d54fbd1 100644
--- a/TODO
+++ b/TODO
@@ -80,17 +80,25 @@
 5) implémenter "balance source" pour faire un hash sur la source.
    permettre de spécifier un masque sur lequel s'applique le hachage,
    ainsi qu'une option pour hacher en fonction de l'adresse dans le
-   champ "x-forwarded-for".
+   champ "x-forwarded-for". Problème pour le support des pannes: ce
+   type de hash est utile là où la persistence par cookie ne peut pas
+   s'appliquer, donc comment faire pour assurer un maximum de persistence
+   en cas de panne ?
 
 6) possibilité d'un process séparé par listen :
    listen XXX
       fork [ group_id ]
 
-le fait de spécifier group_id fera que toutes les instances utilisant le même
-identifiant de groupe seront gérées par un même processus.
+   le fait de spécifier group_id fera que toutes les instances utilisant le
+   même identifiant de groupe seront gérées par un même processus.
 
    -> plus souple et plus compréhensible de faire des sections par processus,
-      ce qui résoud également le cas ci-dessous
+      ce qui résoud également le cas ci-dessous. Ex:
+   process_group X
+      nbproc X
+      uid X
+      chroot X
+      listen ...
 
 7) gérer un chroot/uid/gid différents par process :
    listen XXX
@@ -111,3 +119,23 @@
 ok>    ex: option httpchk        -> OPTIONS / HTTP/1.0
 ok> 	   option httpchk /test  -> OPTIONS /test HTTP/1.0
 ok> 	   option httpchk HEAD / HTTP/1.0\nHost:\ www   -> tel quel
+
+Todo for 1.1
+============
+* "no more server" alert
+* config check
+- anti-flapping
+
+Todo for 1.2
+============
+- direct <server> <regex> <match>
+- new config syntax allowing braces to be able to shorten lines
+- insert/learn/check/log unique request ID, and add the ability
+  to block bad responses.
+- IPv6 :
+* listen [ip4.ip4.ip4.ip4]:port[-port]
+* listen [ip6::...ip6]/port[-port]
+- server xxx ipv4 | ipv4: | ipv4:port[-port] | ipv6/ | ipv6/port[-port]
+
+- weighted round robin
+
diff --git a/haproxy.c b/haproxy.c
index 10bb3e0..91d597e 100644
--- a/haproxy.c
+++ b/haproxy.c
@@ -1,6 +1,6 @@
 /*
  * HA-Proxy : High Availability-enabled HTTP/TCP proxy
- * 2000-2003 - Willy Tarreau - willy AT meta-x DOT org.
+ * 2000-2004 - Willy Tarreau - willy AT meta-x DOT org.
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -53,8 +53,8 @@
 #include <linux/netfilter_ipv4.h>
 #endif
 
-#define HAPROXY_VERSION "1.1.27-ipv6"
-#define HAPROXY_DATE	"2003/11/09"
+#define HAPROXY_VERSION "1.2.1"
+#define HAPROXY_DATE	"2004/04/18"
 
 /* this is for libc5 for example */
 #ifndef TCP_NODELAY
@@ -293,6 +293,7 @@
 #define	MODE_LOG	4
 #define	MODE_DAEMON	8
 #define	MODE_QUIET	16
+#define	MODE_CHECK	32
 
 /* server flags */
 #define SRV_RUNNING	1	/* the server is UP */
@@ -537,6 +538,9 @@
 /* this is used to drain data, and as a temporary buffer for sprintf()... */
 static char trash[BUFSIZE];
 
+const int zero = 0;
+const int one = 1;
+
 /*
  * Syslog facilities and levels. Conforming to RFC3164.
  */
@@ -665,7 +669,7 @@
 
 void display_version() {
     printf("HA-Proxy version " HAPROXY_VERSION " " HAPROXY_DATE"\n");
-    printf("Copyright 2000-2003 Willy Tarreau <willy AT meta-x DOT org>\n\n");
+    printf("Copyright 2000-2004 Willy Tarreau <w@w.ods.org>\n\n");
 }
 
 /*
@@ -687,6 +691,7 @@
 #endif
 	    "        -D goes daemon ; implies -q\n"
 	    "        -q quiet mode : don't display messages\n"
+	    "        -c check mode : only check config file and exit\n"
 	    "        -n sets the maximum total # of connections (%d)\n"
 	    "        -N sets the default, per-proxy maximum # of connections (%d)\n"
 	    "        -p writes pids of all children to this file\n\n",
@@ -1446,7 +1451,6 @@
  * it's OK, -1 if it's impossible.
  */
 int connect_server(struct session *s) {
-    int one = 1;
     int fd;
 
     //    fprintf(stderr,"connect_server : s=%p\n",s);
@@ -2033,7 +2037,6 @@
     struct session *s;
     struct task *t;
     int cfd;
-    int one = 1;
 
     while (p->nbconn < p->maxconn) {
 	struct sockaddr_storage addr;
@@ -3833,7 +3836,6 @@
     struct server *s = t->context;
     struct sockaddr_in sa;
     int fd = s->curfd;
-    int one = 1;
 
     //fprintf(stderr, "process_chk: task=%p\n", t);
 
@@ -3899,15 +3901,17 @@
 	if (s->health > s->rise)
 	    s->health--; /* still good */
 	else {
+	    s->state &= ~SRV_RUNNING;
 	    if (s->health == s->rise) {
-		if (!(global.mode & MODE_QUIET))
-		    Warning("server %s/%s DOWN.\n", s->proxy->id, s->id);
-
+		Warning("Server %s/%s DOWN.\n", s->proxy->id, s->id);
 		send_log(s->proxy, LOG_ALERT, "Server %s/%s is DOWN.\n", s->proxy->id, s->id);
-	    }
 
+		if (find_server(s->proxy) == NULL) {
+		    Alert("Proxy %s has no server available !\n", s->proxy->id);
+		    send_log(s->proxy, LOG_EMERG, "Proxy %s has no server available !\n", s->proxy->id);
+		}
+	    }
 	    s->health = 0; /* failure */
-	    s->state &= ~SRV_RUNNING;
 	}
 
 	//fprintf(stderr, "process_chk: 7\n");
@@ -3922,8 +3926,7 @@
 	    s->health++; /* was bad, stays for a while */
 	    if (s->health >= s->rise) {
 		if (s->health == s->rise) {
-		    if (!(global.mode & MODE_QUIET))
-			Warning("server %s/%s UP.\n", s->proxy->id, s->id);
+		    Warning("server %s/%s UP.\n", s->proxy->id, s->id);
 		    send_log(s->proxy, LOG_NOTICE, "Server %s/%s is UP.\n", s->proxy->id, s->id);
 		}
 
@@ -3941,15 +3944,19 @@
 	    if (s->health > s->rise)
 		s->health--; /* still good */
 	    else {
-		if (s->health == s->rise) {
-		    if (!(global.mode & MODE_QUIET))
-			Warning("server %s/%s DOWN.\n", s->proxy->id, s->id);
+		s->state &= ~SRV_RUNNING;
 
+		if (s->health == s->rise) {
+		    Warning("Server %s/%s DOWN.\n", s->proxy->id, s->id);
 		    send_log(s->proxy, LOG_ALERT, "Server %s/%s is DOWN.\n", s->proxy->id, s->id);
+
+		    if (find_server(s->proxy) == NULL) {
+			Alert("Proxy %s has no server available !\n", s->proxy->id);
+			send_log(s->proxy, LOG_EMERG, "Proxy %s has no server available !\n", s->proxy->id);
+		    }
 		}
 
 		s->health = 0; /* failure */
-		s->state &= ~SRV_RUNNING;
 	    }
 	    s->curfd = -1;
 	    //FD_CLR(fd, StaticWriteEvent);
@@ -4280,6 +4287,12 @@
 	    }
 	    s = s->next;
 	}
+
+	if (find_server(p) == NULL) {
+	    Warning("SIGHUP: proxy %s has no server available !\n", p);
+	    send_log(p, LOG_NOTICE, "SIGHUP: proxy %s has no server available !\n", p);
+	}
+
 	p = p->next;
     }
     signal(sig, sig_dump_state);
@@ -5691,7 +5704,7 @@
     int cfg_maxconn = 0;	/* # of simultaneous connections, (-n) */
 
     if (1<<INTBITS != sizeof(int)*8) {
-	qfprintf(stderr,
+	fprintf(stderr,
 		"Error: wrong architecture. Recompile so that sizeof(int)=%d\n",
 		sizeof(int)*8);
 	exit(1);
@@ -5716,6 +5729,8 @@
 	    }
 	    else if (*flag == 'd')
 		arg_mode |= MODE_DEBUG;
+	    else if (*flag == 'c')
+		arg_mode |= MODE_CHECK;
 	    else if (*flag == 'D')
 		arg_mode |= MODE_DAEMON | MODE_QUIET;
 	    else if (*flag == 'q')
@@ -5745,6 +5760,8 @@
 	    argv++; argc--;
     }
 
+    global.mode = (arg_mode & (MODE_DAEMON | MODE_QUIET | MODE_DEBUG));
+
     if (!cfg_cfgfile)
 	usage(old_argv);
 
@@ -5755,6 +5772,11 @@
 	exit(1);
     }
 
+    if (arg_mode & MODE_CHECK) {
+	qfprintf(stdout, "Configuration file is valid : %s\n", cfg_cfgfile);
+	exit(0);
+    }
+
     if (cfg_maxconn > 0)
 	global.maxconn = cfg_maxconn;
 
@@ -5814,7 +5836,6 @@
 int start_proxies() {
     struct proxy *curproxy;
     struct listener *listener;
-    int one = 1;
     int fd;
 
     for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {