]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
[MINOR] config: improve error reporting in listen sections
authorWilly Tarreau <w@1wt.eu>
Thu, 23 Jul 2009 11:19:11 +0000 (13:19 +0200)
committerWilly Tarreau <w@1wt.eu>
Sun, 26 Jul 2009 15:40:35 +0000 (17:40 +0200)
Try not to immediately exit on non-fatal errors while parsing a
listen section, so that the user has a chance to get most of the
errors at once, which is quite convenient especially during config
checks with the -c argument.
(cherry picked from commit 9389379f608d0776988125e52cbac12a2a2ad165)

src/cfgparse.c

index 14b40066b16f4087f6147440639125f4ca583162..2ab51ec302bd0e9664914b74ea6447c5c8887391 100644 (file)
@@ -721,7 +721,13 @@ void init_default_instance()
 
 /*
  * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
- * Returns 0 if OK, -1 if error.
+ * Returns the error code, 0 if OK, or any combination of :
+ *  - ERR_ABORT: must abort ASAP
+ *  - ERR_FATAL: we can continue parsing but not start the service
+ *  - ERR_WARN: a warning has been emitted
+ *  - ERR_ALERT: an alert has been emitted
+ * Only the two first ones can stop processing, the two others are just
+ * indicators.
  */
 int cfg_parse_listen(const char *file, int linenum, char **args, int inv)
 {
@@ -730,6 +736,7 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int inv)
        const char *err;
        int rc;
        unsigned val;
+       int err_code = 0;
 
        if (!strcmp(args[0], "listen"))
                rc = PR_CAP_LISTEN;
@@ -747,14 +754,15 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int inv)
                        Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
                              "  optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
                              file, linenum, args[0]);
-                       return -1;
+                       err_code |= ERR_ALERT | ERR_ABORT;
+                       goto out;
                }
 
                err = invalid_char(args[1]);
                if (err) {
                        Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
                              file, linenum, *err, args[0], args[1]);
-                       return -1;
+                       err_code |= ERR_ALERT | ERR_FATAL;
                }
 
                for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
@@ -774,12 +782,14 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int inv)
                                (rc!=(PR_CAP_BE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_FE|PR_CAP_RS))) {
                                Warning("Parsing [%s:%d]: %s '%s' has same name as another %s.\n",
                                        file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy));
+                               err_code |= ERR_WARN;
                        }
                }
 
                if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
                        Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
-                       return -1;
+                       err_code |= ERR_ALERT | ERR_ABORT;
+                       goto out;
                }
 
                curproxy->next = proxy;
@@ -804,8 +814,10 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int inv)
                /* parse the listener address if any */
                if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
                        curproxy->listen = str2listener(args[2], curproxy->listen);
-                       if (!curproxy->listen)
-                               return -1;
+                       if (!curproxy->listen) {
+                               err_code |= ERR_FATAL;
+                               goto out;
+                       }
                        global.maxsock++;
                }
 
@@ -908,7 +920,7 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int inv)
                curproxy->uuid = next_pxid++;   /* generate a uuid for this proxy */
                curproxy->next_svid = 1;        /* server id 0 is reserved */
 
-               return 0;
+               goto out;
        }
        else if (!strcmp(args[0], "defaults")) {  /* use this one to assign default values */
                /* some variables may have already been initialized earlier */
@@ -933,11 +945,12 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int inv)
                init_default_instance();
                curproxy = &defproxy;
                defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
-               return 0;
+               goto out;
        }
        else if (curproxy == NULL) {
                Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
-               return -1;
+               err_code |= ERR_ALERT | ERR_FATAL;
+               goto out;
        }
     
 
@@ -948,21 +961,25 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int inv)
 
                if (curproxy == &defproxy) {
                        Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
-                       return -1;
+                       err_code |= ERR_ALERT | ERR_FATAL;
+                       goto out;
                }
                if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
-                       return 0;
+                       err_code |= ERR_WARN;
 
                if (strchr(args[1], ':') == NULL) {
                        Alert("parsing [%s:%d] : '%s' expects [addr1]:port1[-end1]{,[addr]:port[-end]}... as arguments.\n",
                              file, linenum, args[0]);
-                       return -1;
+                       err_code |= ERR_ALERT | ERR_FATAL;
+                       goto out;
                }
 
                last_listen = curproxy->listen;
                curproxy->listen = str2listener(args[1], last_listen);
-               if (!curproxy->listen)
-                       return -1;
+               if (!curproxy->listen) {
+                       err_code |= ERR_ALERT | ERR_FATAL;
+                       goto out;
+               }
 
                cur_arg = 2;
                while (*(args[cur_arg])) {
@@ -973,7 +990,8 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int inv)
                                if (!*args[cur_arg + 1]) {
                                        Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
                                              file, linenum, args[0]);
-                                       return -1;
+                                       err_code |= ERR_ALERT | ERR_FATAL;
+                                       goto out;
                                }
                                
                                for (l = curproxy->listen; l != last_listen; l = l->next)
@@ -986,7 +1004,8 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int inv)
 #else
                                Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
                                      file, linenum, args[0], args[cur_arg]);
-                               return -1;
+                               err_code |= ERR_ALERT | ERR_FATAL;
+                               goto out;
 #endif
                        }
                        if (!strcmp(args[cur_arg], "transparent")) { /* transparently bind to these addresses */
@@ -1001,37 +1020,41 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int inv)
 #else
                                Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
                                      file, linenum, args[0], args[cur_arg]);
-                               return -1;
+                               err_code |= ERR_ALERT | ERR_FATAL;
+                               goto out;
 #endif
                        }
                        Alert("parsing [%s:%d] : '%s' only supports the 'transparent' and 'interface' options.\n",
                              file, linenum, args[0]);
-                       return -1;
+                       err_code |= ERR_ALERT | ERR_FATAL;
+                       goto out;
                }
                global.maxsock++;
-               return 0;
+               goto out;
        }
        else if (!strcmp(args[0], "monitor-net")) {  /* set the range of IPs to ignore */
                if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
                        Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
                              file, linenum, args[0]);
-                       return -1;
+                       err_code |= ERR_ALERT | ERR_FATAL;
+                       goto out;
                }
                if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
-                       return 0;
+                       err_code |= ERR_WARN;
 
                /* flush useless bits */
                curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
-               return 0;
+               goto out;
        }
        else if (!strcmp(args[0], "monitor-uri")) {  /* set the URI to intercept */
                if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
-                       return 0;
+                       err_code |= ERR_WARN;
 
                if (!*args[1]) {
                        Alert("parsing [%s:%d] : '%s' expects an URI.\n",
                              file, linenum, args[0]);
-                       return -1;
+                       err_code |= ERR_ALERT | ERR_FATAL;
+                       goto out;
                }
 
                free(curproxy->monitor_uri);
@@ -1040,7 +1063,7 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int inv)
                memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
                curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
 
-               return 0;
+               goto out;
        }
        else if (!strcmp(args[0], "mode")) {  /* sets the proxy mode */
                if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
@@ -1048,7 +1071,8 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int inv)
                else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
                else {
                        Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
-                       return -1;
+                       err_code |= ERR_ALERT | ERR_FATAL;
+                       goto out;
                }
        }
        else if (!strcmp(args[0], "id")) {
@@ -1057,13 +1081,15 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int inv)
                if (curproxy == &defproxy) {
                        Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
                                 file, linenum, args[0]);
-                       return -1;
+                       err_code |= ERR_ALERT | ERR_FATAL;
+                       goto out;
                }
 
                if (!*args[1]) {
                        Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
                                file, linenum, args[0]);
-                       return -1;
+                       err_code |= ERR_ALERT | ERR_FATAL;
+                       goto out;
                }
 
                curproxy->uuid = atol(args[1]);
@@ -1071,14 +1097,16 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int inv)
                if (curproxy->uuid < 1001) {
                        Alert("parsing [%s:%d]: custom id has to be > 1000",
                                file, linenum);
-                       return -1;
+                       err_code |= ERR_ALERT | ERR_FATAL;
+                       goto out;
                }
 
                for (target = proxy; target; target = target->next)
                        if (curproxy != target && curproxy->uuid == target->uuid) {
                                Alert("parsing [%s:%d]: custom id has to be unique but is duplicated in %s and %s.\n",
                                        file, linenum, curproxy->id, target->id);
-                               return -1;
+                               err_code |= ERR_ALERT | ERR_FATAL;
+                               goto out;
                        }
        }
        else if (!strcmp(args[0], "disabled")) {  /* disables this proxy */
@@ -1108,11 +1136,13 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int inv)
                                if (u < 1 || u > 32) {
                                        Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or process numbers from 1 to 32.\n",
                                              file, linenum, args[0]);
-                                       return -1;
+                                       err_code |= ERR_ALERT | ERR_FATAL;
+                                       goto out;
                                }
                                if (u > global.nbproc) {
                                        Warning("parsing [%s:%d]: %s references process number higher than global.nbproc.\n",
                                                file, linenum, args[0]);
+                                       err_code |= ERR_WARN;
                                }
                                set |= 1 << (u - 1);
                        }
@@ -1123,32 +1153,35 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int inv)
        else if (!strcmp(args[0], "acl")) {  /* add an ACL */
                if (curproxy == &defproxy) {
                        Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
-                       return -1;
+                       err_code |= ERR_ALERT | ERR_FATAL;
+                       goto out;
                }
 
                err = invalid_char(args[1]);
                if (err) {
                        Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
                              file, linenum, *err, args[1]);
-                       return -1;
+                       err_code |= ERR_ALERT | ERR_FATAL;
                }
 
                if (parse_acl((const char **)args + 1, &curproxy->acl) == NULL) {
                        Alert("parsing [%s:%d] : error detected while parsing ACL '%s'.\n",
                              file, linenum, args[1]);
-                       return -1;
+                       err_code |= ERR_ALERT | ERR_FATAL;
+                       goto out;
                }
        }
        else if (!strcmp(args[0], "cookie")) {  /* cookie name */
                int cur_arg;
 
                if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
-                       return 0;
+                       err_code |= ERR_WARN;
 
                if (*(args[1]) == 0) {
                        Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
                              file, linenum, args[0]);
-                       return -1;
+                       err_code |= ERR_ALERT | ERR_FATAL;
+                       goto out;
                }
 
                free(curproxy->cookie_name);
@@ -1179,7 +1212,8 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int inv)
                                if (!*args[cur_arg + 1]) {
                                        Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
                                                file, linenum, args[cur_arg]);
-                                       return -1;
+                                       err_code |= ERR_ALERT | ERR_FATAL;
+                                       goto out;
                                }
 
                                if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
@@ -1187,14 +1221,16 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int inv)
                                        Alert("parsing [%s:%d]: domain '%s' contains no embedded"
                                                " dots or does not start with a dot.\n",
                                                file, linenum, args[cur_arg + 1]);
-                                       return -1;
+                                       err_code |= ERR_ALERT | ERR_FATAL;
+                                       goto out;
                                }
 
                                err = invalid_domainchar(args[cur_arg + 1]);
                                if (err) {
                                        Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
                                                file, linenum, *err, args[cur_arg + 1]);
-                                       return -1;
+                                       err_code |= ERR_ALERT | ERR_FATAL;
+                                       goto out;
                                }
 
                                curproxy->cookie_domain = strdup(args[cur_arg + 1]);
@@ -1203,31 +1239,33 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int inv)
                        else {
                                Alert("parsing [%s:%d] : '%s' supports 'rewrite', 'insert', 'prefix', 'indirect', 'nocache' and 'postonly', 'domain' options.\n",
                                      file, linenum, args[0]);
-                               return -1;
+                               err_code |= ERR_ALERT | ERR_FATAL;
+                               goto out;
                        }
                        cur_arg++;
                }
                if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_IND))) {
                        Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
                              file, linenum);
-                       return -1;
+                       err_code |= ERR_ALERT | ERR_FATAL;
                }
 
                if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_INS|PR_O_COOK_PFX))) {
                        Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
                              file, linenum);
-                       return -1;
+                       err_code |= ERR_ALERT | ERR_FATAL;
                }
        }/* end else if (!strcmp(args[0], "cookie"))  */
        else if (!strcmp(args[0], "appsession")) {  /* cookie name */
 
                if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
-                       return 0;
+                       err_code |= ERR_WARN;
 
                if (*(args[5]) == 0) {
                        Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout>.\n",
                              file, linenum, args[0]);
-                       return -1;
+                       err_code |= ERR_ALERT | ERR_FATAL;
+                       goto out;
                }
                have_appsession = 1;
                free(curproxy->appsession_name);
@@ -1238,24 +1276,27 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int inv)
                if (err) {
                        Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
                              file, linenum, *err, args[0]);
-                       return -1;
+                       err_code |= ERR_ALERT | ERR_FATAL;
+                       goto out;
                }
                curproxy->timeout.appsession = val;
 
                if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
                        Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
-                       return -1;
+                       err_code |= ERR_ALERT | ERR_ABORT;
+                       goto out;
                }
        } /* Url App Session */
        else if (!strcmp(args[0], "capture")) {
                if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
-                       return 0;
+                       err_code |= ERR_WARN;
 
                if (!strcmp(args[1], "cookie")) {  /* name of a cookie to capture */
                        if (*(args[4]) == 0) {
                                Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
                                      file, linenum, args[0]);
-                               return -1;
+                               err_code |= ERR_ALERT | ERR_FATAL;
+                               goto out;
                        }
                        free(curproxy->capture_name);
                        curproxy->capture_name = strdup(args[2]);
@@ -1264,6 +1305,7 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int inv)
                        if (curproxy->capture_len >= CAPTURE_LEN) {
                                Warning("parsing [%s:%d] : truncating capture length to %d bytes.\n",
                                        file, linenum, CAPTURE_LEN - 1);
+                               err_code |= ERR_WARN;
                                curproxy->capture_len = CAPTURE_LEN - 1;
                        }
                        curproxy->to_log |= LW_COOKIE;
@@ -1273,13 +1315,15 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int inv)
 
                        if (curproxy == &defproxy) {
                                Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
-                               return -1;
+                               err_code |= ERR_ALERT | ERR_FATAL;
+                               goto out;
                        }
 
                        if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
                                Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
                                      file, linenum, args[0], args[1]);
-                               return -1;
+                               err_code |= ERR_ALERT | ERR_FATAL;
+                               goto out;
                        }
 
                        hdr = calloc(sizeof(struct cap_hdr), 1);
@@ -1297,13 +1341,15 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int inv)
 
                        if (curproxy == &defproxy) {
                                Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
-                               return -1;
+                               err_code |= ERR_ALERT | ERR_FATAL;
+                               goto out;
                        }
 
                        if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
                                Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
                                      file, linenum, args[0], args[1]);
-                               return -1;
+                               err_code |= ERR_ALERT | ERR_FATAL;
+                               goto out;
                        }
                        hdr = calloc(sizeof(struct cap_hdr), 1);
                        hdr->next = curproxy->rsp_cap;
@@ -1318,17 +1364,19 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int inv)
                else {
                        Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
                              file, linenum, args[0]);
-                       return -1;
+                       err_code |= ERR_ALERT | ERR_FATAL;
+                       goto out;
                }
        }
        else if (!strcmp(args[0], "retries")) {  /* connection retries */
                if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
-                       return 0;
+                       err_code |= ERR_WARN;
 
                if (*(args[1]) == 0) {
                        Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
                              file, linenum, args[0]);
-                       return -1;
+                       err_code |= ERR_ALERT | ERR_FATAL;
+                       goto out;
                }
                curproxy->conn_retries = atol(args[1]);
        }
@@ -1338,7 +1386,8 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int inv)
 
                if (curproxy == &defproxy) {
                        Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
-                       return -1;
+                       err_code |= ERR_ALERT | ERR_FATAL;
+                       goto out;
                }
 
                if (!strcmp(args[1], "if"))
@@ -1349,13 +1398,15 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int inv)
                if (pol == ACL_COND_NONE) {
                        Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
                              file, linenum, args[0]);
-                       return -1;
+                       err_code |= ERR_ALERT | ERR_FATAL;
+                       goto out;
                }
 
                if ((cond = parse_acl_cond((const char **)args + 2, &curproxy->acl, pol)) == NULL) {
                        Alert("parsing [%s:%d] : error detected while parsing blocking condition.\n",
                              file, linenum);
-                       return -1;
+                       err_code |= ERR_ALERT | ERR_FATAL;
+                       goto out;
                }
                cond->line = linenum;
                LIST_ADDQ(&curproxy->block_cond, &cond->list);
@@ -1379,7 +1430,8 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int inv)
                                if (!*args[cur_arg + 1]) {
                                        Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
                                              file, linenum, args[0], args[cur_arg]);
-                                       return -1;
+                                       err_code |= ERR_ALERT | ERR_FATAL;
+                                       goto out;
                                }
 
                                type = REDIRECT_TYPE_LOCATION;
@@ -1390,7 +1442,8 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int inv)
                                if (!*args[cur_arg + 1]) {
                                        Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
                                              file, linenum, args[0], args[cur_arg]);
-                                       return -1;
+                                       err_code |= ERR_ALERT | ERR_FATAL;
+                                       goto out;
                                }
 
                                type = REDIRECT_TYPE_PREFIX;
@@ -1401,7 +1454,8 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int inv)
                                if (!*args[cur_arg + 1]) {
                                        Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
                                              file, linenum, args[0], args[cur_arg]);
-                                       return -1;
+                                       err_code |= ERR_ALERT | ERR_FATAL;
+                                       goto out;
                                }
 
                                cur_arg++;
@@ -1412,7 +1466,8 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int inv)
                                if (!*args[cur_arg + 1]) {
                                        Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
                                              file, linenum, args[0], args[cur_arg]);
-                                       return -1;
+                                       err_code |= ERR_ALERT | ERR_FATAL;
+                                       goto out;
                                }
 
                                cur_arg++;
@@ -1423,14 +1478,16 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int inv)
                                if (!*args[cur_arg + 1]) {
                                        Alert("parsing [%s:%d] : '%s': missing HTTP code.\n",
                                              file, linenum, args[0]);
-                                       return -1;
+                                       err_code |= ERR_ALERT | ERR_FATAL;
+                                       goto out;
                                }
                                cur_arg++;
                                code = atol(args[cur_arg]);
                                if (code < 301 || code > 303) {
                                        Alert("parsing [%s:%d] : '%s': unsupported HTTP code '%d'.\n",
                                              file, linenum, args[0], code);
-                                       return -1;
+                                       err_code |= ERR_ALERT | ERR_FATAL;
+                                       goto out;
                                }
                        }
                        else if (!strcmp(args[cur_arg],"drop-query")) {
@@ -1449,7 +1506,8 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int inv)
                        else {
                                Alert("parsing [%s:%d] : '%s' expects 'code', 'prefix' or 'location' (was '%s').\n",
                                      file, linenum, args[0], args[cur_arg]);
-                               return -1;
+                               err_code |= ERR_ALERT | ERR_FATAL;
+                               goto out;
                        }
                        cur_arg++;
                }
@@ -1457,19 +1515,22 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int inv)
                if (type == REDIRECT_TYPE_NONE) {
                        Alert("parsing [%s:%d] : '%s' expects a redirection type ('prefix' or 'location').\n",
                              file, linenum, args[0]);
-                       return -1;
+                       err_code |= ERR_ALERT | ERR_FATAL;
+                       goto out;
                }
 
                if (pol == ACL_COND_NONE) {
                        Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
                              file, linenum, args[0]);
-                       return -1;
+                       err_code |= ERR_ALERT | ERR_FATAL;
+                       goto out;
                }
 
                if ((cond = parse_acl_cond((const char **)args + cur_arg, &curproxy->acl, pol)) == NULL) {
                        Alert("parsing [%s:%d] : '%s': error detected while parsing redirect condition.\n",
                              file, linenum, args[0]);
-                       return -1;
+                       err_code |= ERR_ALERT | ERR_FATAL;
+                       goto out;
                }
 
                cond->line = linenum;
@@ -1505,15 +1566,17 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int inv)
 
                if (curproxy == &defproxy) {
                        Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
-                       return -1;
+                       err_code |= ERR_ALERT | ERR_FATAL;
+                       goto out;
                }
 
                if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
-                       return 0;
+                       err_code |= ERR_WARN;
 
                if (*(args[1]) == 0) {
                        Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
-                       return -1;
+                       err_code |= ERR_ALERT | ERR_FATAL;
+                       goto out;
                }
 
                if (!strcmp(args[2], "if"))
@@ -1524,13 +1587,15 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int inv)
                if (pol == ACL_COND_NONE) {
                        Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
                              file, linenum, args[0]);
-                       return -1;
+                       err_code |= ERR_ALERT | ERR_FATAL;
+                       goto out;
                }
 
                if ((cond = parse_acl_cond((const char **)args + 3, &curproxy->acl, pol)) == NULL) {
                        Alert("parsing [%s:%d] : error detected while parsing switching rule.\n",
                              file, linenum);
-                       return -1;
+                       err_code |= ERR_ALERT | ERR_FATAL;
+                       goto out;
                }
 
                cond->line = linenum;
@@ -1542,6 +1607,7 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int inv)
                        name = acl ? acl->name : "(unknown)";
                        Warning("parsing [%s:%d] : acl '%s' involves some response-only criteria which will be ignored.\n",
                                file, linenum, name);
+                       err_code |= ERR_WARN;
                }
 
                rule = (struct switching_rule *)calloc(1, sizeof(*rule));
@@ -1552,29 +1618,34 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int inv)
        }
        else if (!strcmp(args[0], "stats")) {
                if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
-                       return 0;
+                       err_code |= ERR_WARN;
 
                if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
                        curproxy->uri_auth = NULL; /* we must detach from the default config */
 
                if (*(args[1]) == 0) {
                        Alert("parsing [%s:%d] : '%s' expects 'uri', 'realm', 'auth', 'scope' or 'enable'.\n", file, linenum, args[0]);
-                       return -1;
+                       err_code |= ERR_ALERT | ERR_FATAL;
+                       goto out;
                } else if (!strcmp(args[1], "uri")) {
                        if (*(args[2]) == 0) {
                                Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
-                               return -1;
+                               err_code |= ERR_ALERT | ERR_FATAL;
+                               goto out;
                        } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
                                Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
-                               return -1;
+                               err_code |= ERR_ALERT | ERR_ABORT;
+                               goto out;
                        }
                } else if (!strcmp(args[1], "realm")) {
                        if (*(args[2]) == 0) {
                                Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
-                               return -1;
+                               err_code |= ERR_ALERT | ERR_FATAL;
+                               goto out;
                        } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
                                Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
-                               return -1;
+                               err_code |= ERR_ALERT | ERR_ABORT;
+                               goto out;
                        }
                } else if (!strcmp(args[1], "refresh")) {
                        unsigned interval;
@@ -1583,41 +1654,50 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int inv)
                        if (err) {
                                Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
                                      file, linenum, *err);
-                               return -1;
+                               err_code |= ERR_ALERT | ERR_FATAL;
+                               goto out;
                        } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
                                Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
-                               return -1;
+                               err_code |= ERR_ALERT | ERR_ABORT;
+                               goto out;
                        }
                } else if (!strcmp(args[1], "auth")) {
                        if (*(args[2]) == 0) {
                                Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
-                               return -1;
+                               err_code |= ERR_ALERT | ERR_FATAL;
+                               goto out;
                        } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
                                Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
-                               return -1;
+                               err_code |= ERR_ALERT | ERR_ABORT;
+                               goto out;
                        }
                } else if (!strcmp(args[1], "scope")) {
                        if (*(args[2]) == 0) {
                                Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
-                               return -1;
+                               err_code |= ERR_ALERT | ERR_FATAL;
+                               goto out;
                        } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
                                Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
-                               return -1;
+                               err_code |= ERR_ALERT | ERR_ABORT;
+                               goto out;
                        }
                } else if (!strcmp(args[1], "enable")) {
                        if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
                                Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
-                               return -1;
+                               err_code |= ERR_ALERT | ERR_ABORT;
+                               goto out;
                        }
                } else if (!strcmp(args[1], "hide-version")) {
                        if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
                                Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
-                               return -1;
+                               err_code |= ERR_ALERT | ERR_ABORT;
+                               goto out;
                        }
                } else {
                        Alert("parsing [%s:%d] : unknown stats parameter '%s' (expects 'hide-version', 'uri', 'realm', 'auth' or 'enable').\n",
                              file, linenum, args[0]);
-                       return -1;
+                       err_code |= ERR_ALERT | ERR_FATAL;
+                       goto out;
                }
        }
        else if (!strcmp(args[0], "option")) {
@@ -1626,41 +1706,47 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int inv)
                if (*(args[1]) == '\0') {
                        Alert("parsing [%s:%d]: '%s' expects an option name.\n",
                              file, linenum, args[0]);
-                       return -1;
+                       err_code |= ERR_ALERT | ERR_FATAL;
+                       goto out;
                }
 
                for (optnum = 0; cfg_opts[optnum].name; optnum++) {
                        if (!strcmp(args[1], cfg_opts[optnum].name)) {
-                               if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL))
-                                       return 0;
+                               if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
+                                       err_code |= ERR_WARN;
+                                       goto out;
+                               }
 
                                if (!inv)
                                        curproxy->options |= cfg_opts[optnum].val;
                                else
                                        curproxy->options &= ~cfg_opts[optnum].val;
 
-                               return 0;
+                               goto out;
                        }
                }
 
                for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
                        if (!strcmp(args[1], cfg_opts2[optnum].name)) {
-                               if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL))
-                                       return 0;
+                               if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
+                                       err_code |= ERR_WARN;
+                                       goto out;
+                               }
 
                                if (!inv)
                                        curproxy->options2 |= cfg_opts2[optnum].val;
                                else
                                        curproxy->options2 &= ~cfg_opts2[optnum].val;
 
-                               return 0;
+                               goto out;
                        }
                }
 
                if (inv) {
                        Alert("parsing [%s:%d]: negation is not supported for option '%s'.\n",
                                file, linenum, args[1]);
-                       return -1;
+                       err_code |= ERR_ALERT | ERR_FATAL;
+                       goto out;
                }
 
                if (!strcmp(args[1], "httplog"))
@@ -1672,7 +1758,7 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int inv)
                else if (!strcmp(args[1], "tcpka")) {
                        /* enable TCP keep-alives on client and server sessions */
                        if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
-                               return 0;
+                               err_code |= ERR_WARN;
 
                        if (curproxy->cap & PR_CAP_FE)
                                curproxy->options |= PR_O_TCP_CLI_KA;
@@ -1681,7 +1767,8 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int inv)
                }
                else if (!strcmp(args[1], "httpchk")) {
                        if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
-                               return 0;
+                               err_code |= ERR_WARN;
+
                        /* use HTTP request to check servers' health */
                        free(curproxy->check_req);
                        curproxy->options &= ~PR_O_SSL3_CHK;
@@ -1710,7 +1797,7 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int inv)
                else if (!strcmp(args[1], "ssl-hello-chk")) {
                        /* use SSLv3 CLIENT HELLO to check servers' health */
                        if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
-                               return 0;
+                               err_code |= ERR_WARN;
 
                        free(curproxy->check_req);
                        curproxy->options &= ~PR_O_HTTP_CHK;
@@ -1762,7 +1849,8 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int inv)
                                        if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
                                                Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
                                                      file, linenum, args[0], args[1], args[cur_arg]);
-                                               return -1;
+                                               err_code |= ERR_ALERT | ERR_FATAL;
+                                               goto out;
                                        }
                                        /* flush useless bits */
                                        curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
@@ -1772,7 +1860,8 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int inv)
                                        if (*(args[cur_arg+1]) == 0) {
                                                Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
                                                      file, linenum, args[0], args[1], args[cur_arg]);
-                                               return -1;
+                                               err_code |= ERR_ALERT | ERR_FATAL;
+                                               goto out;
                                        }
                                        free(curproxy->fwdfor_hdr_name);
                                        curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
@@ -1782,7 +1871,8 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int inv)
                                        /* unknown suboption - catchall */
                                        Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
                                              file, linenum, args[0], args[1]);
-                                       return -1;
+                                       err_code |= ERR_ALERT | ERR_FATAL;
+                                       goto out;
                                }
                        } /* end while loop */
                }
@@ -1807,7 +1897,8 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int inv)
                                        if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_to, &curproxy->except_mask_to)) {
                                                Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
                                                      file, linenum, args[0], args[1], args[cur_arg]);
-                                               return -1;
+                                               err_code |= ERR_ALERT | ERR_FATAL;
+                                               goto out;
                                        }
                                        /* flush useless bits */
                                        curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
@@ -1817,7 +1908,8 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int inv)
                                        if (*(args[cur_arg+1]) == 0) {
                                                Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
                                                      file, linenum, args[0], args[1], args[cur_arg]);
-                                               return -1;
+                                               err_code |= ERR_ALERT | ERR_FATAL;
+                                               goto out;
                                        }
                                        free(curproxy->orgto_hdr_name);
                                        curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
@@ -1827,40 +1919,43 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int inv)
                                        /* unknown suboption - catchall */
                                        Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
                                              file, linenum, args[0], args[1]);
-                                       return -1;
+                                       err_code |= ERR_ALERT | ERR_FATAL;
+                                       goto out;
                                }
                        } /* end while loop */
                }
                else {
                        Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
-                       return -1;
+                       err_code |= ERR_ALERT | ERR_FATAL;
+                       goto out;
                }
-               return 0;
+               goto out;
        }
        else if (!strcmp(args[0], "default_backend")) {
                if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
-                       return 0;
+                       err_code |= ERR_WARN;
 
                if (*(args[1]) == 0) {
                        Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
-                       return -1;
+                       err_code |= ERR_ALERT | ERR_FATAL;
+                       goto out;
                }
                free(curproxy->defbe.name);
                curproxy->defbe.name = strdup(args[1]);
        }
        else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
                if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
-                       return 0;
+                       err_code |= ERR_WARN;
 
                Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
                                file, linenum, args[0]);
-
+               err_code |= ERR_WARN;
                /* enable reconnections to dispatch */
                curproxy->options |= PR_O_REDISP;
        }
        else if (!strcmp(args[0], "http-check")) {
                if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
-                       return 0;
+                       err_code |= ERR_WARN;
 
                if (strcmp(args[1], "disable-on-404") == 0) {
                        /* enable a graceful server shutdown on an HTTP 404 response */
@@ -1868,17 +1963,19 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int inv)
                }
                else {
                        Alert("parsing [%s:%d] : '%s' only supports 'disable-on-404'.\n", file, linenum, args[0]);
-                       return -1;
+                       err_code |= ERR_ALERT | ERR_FATAL;
+                       goto out;
                }
        }
        else if (!strcmp(args[0], "monitor")) {
                if (curproxy == &defproxy) {
                        Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
-                       return -1;
+                       err_code |= ERR_ALERT | ERR_FATAL;
+                       goto out;
                }
 
                if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
-                       return 0;
+                       err_code |= ERR_WARN;
 
                if (strcmp(args[1], "fail") == 0) {
                        /* add a condition to fail monitor requests */
@@ -1893,20 +1990,23 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int inv)
                        if (pol == ACL_COND_NONE) {
                                Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
                                      file, linenum, args[0], args[1]);
-                               return -1;
+                               err_code |= ERR_ALERT | ERR_FATAL;
+                               goto out;
                        }
 
                        if ((cond = parse_acl_cond((const char **)args + 3, &curproxy->acl, pol)) == NULL) {
                                Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition.\n",
                                      file, linenum, args[0], args[1]);
-                               return -1;
+                               err_code |= ERR_ALERT | ERR_FATAL;
+                               goto out;
                        }
                        cond->line = linenum;
                        LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
                }
                else {
                        Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
-                       return -1;
+                       err_code |= ERR_ALERT | ERR_FATAL;
+                       goto out;
                }
        }
 #ifdef TPROXY
@@ -1917,69 +2017,77 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int inv)
 #endif
        else if (!strcmp(args[0], "maxconn")) {  /* maxconn */
                if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
-                       return 0;
+                       err_code |= ERR_WARN;
 
                if (*(args[1]) == 0) {
                        Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
-                       return -1;
+                       err_code |= ERR_ALERT | ERR_FATAL;
+                       goto out;
                }
                curproxy->maxconn = atol(args[1]);
        }
        else if (!strcmp(args[0], "backlog")) {  /* backlog */
                if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
-                       return 0;
+                       err_code |= ERR_WARN;
 
                if (*(args[1]) == 0) {
                        Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
-                       return -1;
+                       err_code |= ERR_ALERT | ERR_FATAL;
+                       goto out;
                }
                curproxy->backlog = atol(args[1]);
        }
        else if (!strcmp(args[0], "fullconn")) {  /* fullconn */
                if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
-                       return 0;
+                       err_code |= ERR_WARN;
 
                if (*(args[1]) == 0) {
                        Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
-                       return -1;
+                       err_code |= ERR_ALERT | ERR_FATAL;
+                       goto out;
                }
                curproxy->fullconn = atol(args[1]);
        }
        else if (!strcmp(args[0], "grace")) {  /* grace time (ms) */
                if (*(args[1]) == 0) {
                        Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
-                       return -1;
+                       err_code |= ERR_ALERT | ERR_FATAL;
+                       goto out;
                }
                err = parse_time_err(args[1], &val, TIME_UNIT_MS);
                if (err) {
                        Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
                              file, linenum, *err);
-                       return -1;
+                       err_code |= ERR_ALERT | ERR_FATAL;
+                       goto out;
                }
                curproxy->grace = val;
        }
        else if (!strcmp(args[0], "dispatch")) {  /* dispatch address */
                if (curproxy == &defproxy) {
                        Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
-                       return -1;
+                       err_code |= ERR_ALERT | ERR_FATAL;
+                       goto out;
                }
                else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
-                       return 0;
+                       err_code |= ERR_WARN;
 
                if (strchr(args[1], ':') == NULL) {
                        Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
-                       return -1;
+                       err_code |= ERR_ALERT | ERR_FATAL;
+                       goto out;
                }
                curproxy->dispatch_addr = *str2sa(args[1]);
        }
        else if (!strcmp(args[0], "balance")) {  /* set balancing with optional algorithm */
                if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
-                       return 0;
+                       err_code |= ERR_WARN;
 
                memcpy(trash, "error near 'balance'", 21);
                if (backend_parse_balance((const char **)args + 1, trash, sizeof(trash), curproxy) < 0) {
                        Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
-                       return -1;
+                       err_code |= ERR_ALERT | ERR_FATAL;
+                       goto out;
                }
        }
        else if (!strcmp(args[0], "server")) {  /* server address */
@@ -1991,27 +2099,31 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int inv)
 
                if (curproxy == &defproxy) {
                        Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
-                       return -1;
+                       err_code |= ERR_ALERT | ERR_FATAL;
+                       goto out;
                }
                else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
-                       return 0;
+                       err_code |= ERR_ALERT | ERR_FATAL;
 
                if (!*args[2]) {
                        Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
                              file, linenum, args[0]);
-                       return -1;
+                       err_code |= ERR_ALERT | ERR_FATAL;
+                       goto out;
                }
 
                err = invalid_char(args[1]);
                if (err) {
                        Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
                              file, linenum, *err, args[1]);
-                       return -1;
+                       err_code |= ERR_ALERT | ERR_FATAL;
+                       goto out;
                }
 
                if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
                        Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
-                       return -1;
+                       err_code |= ERR_ALERT | ERR_ABORT;
+                       goto out;
                }
 
                /* the servers are linked backwards first */
@@ -2068,7 +2180,8 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int inv)
                                if (!*args[cur_arg + 1]) {
                                        Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
                                                file, linenum, args[cur_arg]);
-                                       return -1;
+                                       err_code |= ERR_ALERT | ERR_FATAL;
+                                       goto out;
                                }
 
                                newsrv->puid = atol(args[cur_arg + 1]);
@@ -2076,14 +2189,16 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int inv)
                                if (newsrv->puid< 1001) {
                                        Alert("parsing [%s:%d]: custom id has to be > 1000",
                                                file, linenum);
-                                       return -1;
+                                       err_code |= ERR_ALERT | ERR_FATAL;
+                                       goto out;
                                }
 
                                for (target = proxy->srv; target; target = target->next)
                                        if (newsrv != target && newsrv->puid == target->puid) {
                                                Alert("parsing [%s:%d]: custom id has to be unique but is duplicated in %s and %s.\n",
                                                        file, linenum, newsrv->id, target->id);
-                                               return -1;
+                                               err_code |= ERR_ALERT | ERR_FATAL;
+                                               goto out;
                                        }
                                cur_arg += 2;
                        }
@@ -2111,12 +2226,14 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int inv)
                                if (err) {
                                        Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
                                              file, linenum, *err, newsrv->id);
-                                       return -1;
+                                       err_code |= ERR_ALERT | ERR_FATAL;
+                                       goto out;
                                }
                                if (val <= 0) {
                                        Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
                                              file, linenum, val, args[cur_arg], newsrv->id);
-                                       return -1;
+                                       err_code |= ERR_ALERT | ERR_FATAL;
+                                       goto out;
                                }
                                newsrv->inter = val;
                                cur_arg += 2;
@@ -2126,12 +2243,14 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int inv)
                                if (err) {
                                        Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
                                              file, linenum, *err, newsrv->id);
-                                       return -1;
+                                       err_code |= ERR_ALERT | ERR_FATAL;
+                                       goto out;
                                }
                                if (val <= 0) {
                                        Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
                                              file, linenum, val, args[cur_arg], newsrv->id);
-                                       return -1;
+                                       err_code |= ERR_ALERT | ERR_FATAL;
+                                       goto out;
                                }
                                newsrv->fastinter = val;
                                cur_arg += 2;
@@ -2141,12 +2260,14 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int inv)
                                if (err) {
                                        Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
                                              file, linenum, *err, newsrv->id);
-                                       return -1;
+                                       err_code |= ERR_ALERT | ERR_FATAL;
+                                       goto out;
                                }
                                if (val <= 0) {
                                        Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
                                              file, linenum, val, args[cur_arg], newsrv->id);
-                                       return -1;
+                                       err_code |= ERR_ALERT | ERR_FATAL;
+                                       goto out;
                                }
                                newsrv->downinter = val;
                                cur_arg += 2;
@@ -2169,7 +2290,8 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int inv)
                                if (w < 0 || w > 256) {
                                        Alert("parsing [%s:%d] : weight of server %s is not within 0 and 256 (%d).\n",
                                              file, linenum, newsrv->id, w);
-                                       return -1;
+                                       err_code |= ERR_ALERT | ERR_FATAL;
+                                       goto out;
                                }
                                newsrv->uweight = w;
                                cur_arg += 2;
@@ -2192,12 +2314,14 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int inv)
                                if (err) {
                                        Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
                                              file, linenum, *err, newsrv->id);
-                                       return -1;
+                                       err_code |= ERR_ALERT | ERR_FATAL;
+                                       goto out;
                                }
                                if (val <= 0) {
                                        Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
                                              file, linenum, val, args[cur_arg], newsrv->id);
-                                       return -1;
+                                       err_code |= ERR_ALERT | ERR_FATAL;
+                                       goto out;
                                }
                                newsrv->slowstart = (val + 999) / 1000;
                                cur_arg += 2;
@@ -2207,7 +2331,8 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int inv)
                                if (!*args[cur_arg + 1]) {
                                        Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
                                                file, linenum);
-                                       return -1;
+                                       err_code |= ERR_ALERT | ERR_FATAL;
+                                       goto out;
                                }
 
                                newsrv->trackit = strdup(args[cur_arg + 1]);
@@ -2229,7 +2354,8 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int inv)
                                        Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]] as argument.\n",
                                              file, linenum, "source");
 #endif
-                                       return -1;
+                                       err_code |= ERR_ALERT | ERR_FATAL;
+                                       goto out;
                                }
                                newsrv->state |= SRV_BIND_SRC;
                                newsrv->source_addr = *str2sa_range(args[cur_arg + 1], &port_low, &port_high);
@@ -2241,7 +2367,8 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int inv)
                                            port_low > port_high) {
                                                Alert("parsing [%s:%d] : invalid source port range %d-%d.\n",
                                                      file, linenum, port_low, port_high);
-                                               return -1;
+                                               err_code |= ERR_ALERT | ERR_FATAL;
+                                               goto out;
                                        }
                                        newsrv->sport_range = port_range_alloc_range(port_high - port_low + 1);
                                        for (i = 0; i < newsrv->sport_range->size; i++)
@@ -2256,13 +2383,15 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int inv)
                                                if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
                                                        Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
                                                              file, linenum, "usesrc", "source");
-                                                       return -1;
+                                                       err_code |= ERR_ALERT | ERR_FATAL;
+                                                       goto out;
                                                }
 #endif
                                                if (!*args[cur_arg + 1]) {
                                                        Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
                                                              file, linenum, "usesrc");
-                                                       return -1;
+                                                       err_code |= ERR_ALERT | ERR_FATAL;
+                                                       goto out;
                                                }
                                                if (!strcmp(args[cur_arg + 1], "client")) {
                                                        newsrv->state |= SRV_TPROXY_CLI;
@@ -2281,7 +2410,8 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int inv)
 #else  /* no TPROXY support */
                                                Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
                                                      file, linenum, "usesrc");
-                                               return -1;
+                                               err_code |= ERR_ALERT | ERR_FATAL;
+                                               goto out;
 #endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY) */
                                        } /* "usesrc" */
 
@@ -2290,7 +2420,8 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int inv)
                                                if (!*args[cur_arg + 1]) {
                                                        Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
                                                              file, linenum, args[0]);
-                                                       return -1;
+                                                       err_code |= ERR_ALERT | ERR_FATAL;
+                                                       goto out;
                                                }
                                                if (newsrv->iface_name)
                                                        free(newsrv->iface_name);
@@ -2301,7 +2432,8 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int inv)
 #else
                                                Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
                                                      file, linenum, args[0], args[cur_arg]);
-                                               return -1;
+                                               err_code |= ERR_ALERT | ERR_FATAL;
+                                               goto out;
 #endif
                                                cur_arg += 2;
                                                continue;
@@ -2313,12 +2445,14 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int inv)
                        else if (!strcmp(args[cur_arg], "usesrc")) {  /* address to use outside: needs "source" first */
                                Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
                                      file, linenum, "usesrc", "source");
-                               return -1;
+                               err_code |= ERR_ALERT | ERR_FATAL;
+                               goto out;
                        }
                        else {
                                Alert("parsing [%s:%d] : server %s only supports options 'backup', 'cookie', 'redir', 'check', 'track', 'id', 'inter', 'fastinter', 'downinter', 'rise', 'fall', 'addr', 'port', 'source', 'minconn', 'maxconn', 'maxqueue', 'slowstart' and 'weight'.\n",
                                      file, linenum, newsrv->id);
-                               return -1;
+                               err_code |= ERR_ALERT | ERR_FATAL;
+                               goto out;
                        }
                }
 
@@ -2326,7 +2460,8 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int inv)
                        if (newsrv->trackit) {
                                Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
                                        file, linenum);
-                               return -1;
+                               err_code |= ERR_ALERT | ERR_FATAL;
+                               goto out;
                        }
 
                        if (!newsrv->check_port && newsrv->check_addr.sin_port)
@@ -2352,7 +2487,8 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int inv)
                        if (!newsrv->check_port) {
                                Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
                                      file, linenum, newsrv->id);
-                               return -1;
+                               err_code |= ERR_ALERT | ERR_FATAL;
+                               goto out;
                        }
                        newsrv->state |= SRV_CHECKED;
                }
@@ -2431,25 +2567,28 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int inv)
                        }
                        else {
                                Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
-                               return -1;
+                               err_code |= ERR_ALERT | ERR_FATAL;
+                               goto out;
                        }
                }
                else {
                        Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
                              file, linenum);
-                       return -1;
+                       err_code |= ERR_ALERT | ERR_FATAL;
+                       goto out;
                }
        }
        else if (!strcmp(args[0], "source")) {  /* address to which we bind when connecting */
                int cur_arg;
 
                if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
-                       return 0;
+                       err_code |= ERR_WARN;
 
                if (!*args[1]) {
                        Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
                              file, linenum, "source", "usesrc", "interface");
-                       return -1;
+                       err_code |= ERR_ALERT | ERR_FATAL;
+                       goto out;
                }
 
                /* we must first clear any optional default setting */  
@@ -2469,13 +2608,15 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int inv)
                                if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
                                        Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
                                              file, linenum, "usesrc");
-                                       return -1;
+                                       err_code |= ERR_ALERT | ERR_FATAL;
+                                       goto out;
                                }
 #endif
                                if (!*args[cur_arg + 1]) {
                                        Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
                                              file, linenum, "usesrc");
-                                       return -1;
+                                       err_code |= ERR_ALERT | ERR_FATAL;
+                                       goto out;
                                }
 
                                if (!strcmp(args[cur_arg + 1], "client")) {
@@ -2493,7 +2634,8 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int inv)
 #else  /* no TPROXY support */
                                Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
                                      file, linenum, "usesrc");
-                               return -1;
+                               err_code |= ERR_ALERT | ERR_FATAL;
+                               goto out;
 #endif
                                cur_arg += 2;
                                continue;
@@ -2504,7 +2646,8 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int inv)
                                if (!*args[cur_arg + 1]) {
                                        Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
                                              file, linenum, args[0]);
-                                       return -1;
+                                       err_code |= ERR_ALERT | ERR_FATAL;
+                                       goto out;
                                }
                                if (curproxy->iface_name)
                                        free(curproxy->iface_name);
@@ -2515,47 +2658,53 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int inv)
 #else
                                Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
                                      file, linenum, args[0], args[cur_arg]);
-                               return -1;
+                               err_code |= ERR_ALERT | ERR_FATAL;
+                               goto out;
 #endif
                                cur_arg += 2;
                                continue;
                        }
                        Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
                              file, linenum, args[0], "inteface", "usesrc");
-                       return -1;
+                       err_code |= ERR_ALERT | ERR_FATAL;
+                       goto out;
                }
        }
        else if (!strcmp(args[0], "usesrc")) {  /* address to use outside: needs "source" first */
                Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
                      file, linenum, "usesrc", "source");
-               return -1;
+               err_code |= ERR_ALERT | ERR_FATAL;
+               goto out;
        }
        else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) {  /* replace request header from a regex */
                regex_t *preg;
                if (curproxy == &defproxy) {
                        Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
-                       return -1;
+                       err_code |= ERR_ALERT | ERR_FATAL;
+                       goto out;
                }
                else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
-                       return 0;
+                       err_code |= ERR_WARN;
 
                if (*(args[1]) == 0 || *(args[2]) == 0) {
                        Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
                              file, linenum, args[0]);
-                       return -1;
+                       err_code |= ERR_ALERT | ERR_FATAL;
+                       goto out;
                }
        
                preg = calloc(1, sizeof(regex_t));
                if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
                        Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
-                       return -1;
+                       err_code |= ERR_ALERT | ERR_FATAL;
+                       goto out;
                }
        
                err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
                if (err) {
                        Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
                              file, linenum, *err);
-                       return -1;
+                       err_code |= ERR_ALERT | ERR_FATAL;
                }
                warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
        }
@@ -2563,20 +2712,23 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int inv)
                regex_t *preg;
                if (curproxy == &defproxy) {
                        Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
-                       return -1;
+                       err_code |= ERR_ALERT | ERR_FATAL;
+                       goto out;
                }
                else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
-                       return 0;
+                       err_code |= ERR_WARN;
 
                if (*(args[1]) == 0) {
                        Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
-                       return -1;
+                       err_code |= ERR_ALERT | ERR_FATAL;
+                       goto out;
                }
        
                preg = calloc(1, sizeof(regex_t));
                if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
                        Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
-                       return -1;
+                       err_code |= ERR_ALERT | ERR_FATAL;
+                       goto out;
                }
        
                chain_regex(&curproxy->req_exp, preg, ACT_REMOVE, NULL);
@@ -2586,20 +2738,23 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int inv)
                regex_t *preg;
                if (curproxy == &defproxy) {
                        Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
-                       return -1;
+                       err_code |= ERR_ALERT | ERR_FATAL;
+                       goto out;
                }
                else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
-                       return 0;
+                       err_code |= ERR_WARN;
 
                if (*(args[1]) == 0) {
                        Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
-                       return -1;
+                       err_code |= ERR_ALERT | ERR_FATAL;
+                       goto out;
                }
        
                preg = calloc(1, sizeof(regex_t));
                if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
                        Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
-                       return -1;
+                       err_code |= ERR_ALERT | ERR_FATAL;
+                       goto out;
                }
        
                chain_regex(&curproxy->req_exp, preg, ACT_DENY, NULL);
@@ -2609,20 +2764,23 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int inv)
                regex_t *preg;
                if (curproxy == &defproxy) {
                        Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
-                       return -1;
+                       err_code |= ERR_ALERT | ERR_FATAL;
+                       goto out;
                }
                else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
-                       return 0;
+                       err_code |= ERR_WARN;
 
                if (*(args[1]) == 0) {
                        Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
-                       return -1;
+                       err_code |= ERR_ALERT | ERR_FATAL;
+                       goto out;
                }
        
                preg = calloc(1, sizeof(regex_t));
                if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
                        Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
-                       return -1;
+                       err_code |= ERR_ALERT | ERR_FATAL;
+                       goto out;
                }
        
                chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
@@ -2632,20 +2790,23 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int inv)
                regex_t *preg;
                if (curproxy == &defproxy) {
                        Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
-                       return -1;
+                       err_code |= ERR_ALERT | ERR_FATAL;
+                       goto out;
                }
                else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
-                       return 0;
+                       err_code |= ERR_WARN;
 
                if (*(args[1]) == 0) {
                        Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
-                       return -1;
+                       err_code |= ERR_ALERT | ERR_FATAL;
+                       goto out;
                }
        
                preg = calloc(1, sizeof(regex_t));
                if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
                        Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
-                       return -1;
+                       err_code |= ERR_ALERT | ERR_FATAL;
+                       goto out;
                }
        
                chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
@@ -2655,20 +2816,23 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int inv)
                regex_t *preg;
                if (curproxy == &defproxy) {
                        Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
-                       return -1;
+                       err_code |= ERR_ALERT | ERR_FATAL;
+                       goto out;
                }
                else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
-                       return 0;
+                       err_code |= ERR_WARN;
 
                if (*(args[1]) == 0) {
                        Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
-                       return -1;
+                       err_code |= ERR_ALERT | ERR_FATAL;
+                       goto out;
                }
        
                preg = calloc(1, sizeof(regex_t));
                if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
                        Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
-                       return -1;
+                       err_code |= ERR_ALERT | ERR_FATAL;
+                       goto out;
                }
        
                chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
@@ -2678,20 +2842,24 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int inv)
                regex_t *preg;
                if (curproxy == &defproxy) {
                        Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
-                       return -1;
+                       err_code |= ERR_ALERT | ERR_FATAL;
+                       goto out;
                }
                else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
-                       return 0;
+                       err_code |= ERR_WARN;
 
                if (*(args[1]) == 0 || *(args[2]) == 0) {
                        Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n", 
                                file, linenum, args[0]);
-                       return -1;      
+                       err_code |= ERR_ALERT | ERR_FATAL;
+                       goto out;
                }
                
                preg = calloc(1, sizeof(regex_t));
                if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
                        Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
+                       err_code |= ERR_ALERT | ERR_FATAL;
+                       goto out;
                }
 
                chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
@@ -2701,20 +2869,24 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int inv)
                regex_t *preg;
                if (curproxy == &defproxy) {
                        Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
-                       return -1;
+                       err_code |= ERR_ALERT | ERR_FATAL;
+                       goto out;
                }
                else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
-                       return 0;
+                       err_code |= ERR_WARN;
 
                if (*(args[1]) == 0 || *(args[2]) == 0) {
                        Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n", 
                              file, linenum, args[0]);
-                       return -1;      
+                       err_code |= ERR_ALERT | ERR_FATAL;
+                       goto out;
                }
                
                preg = calloc(1, sizeof(regex_t));
                if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
                        Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
+                       err_code |= ERR_ALERT | ERR_FATAL;
+                       goto out;
                }
 
                chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
@@ -2724,28 +2896,32 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int inv)
                regex_t *preg;
                if (curproxy == &defproxy) {
                        Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
-                       return -1;
+                       err_code |= ERR_ALERT | ERR_FATAL;
+                       goto out;
                }
                else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
-                       return 0;
+                       err_code |= ERR_WARN;
 
                if (*(args[1]) == 0 || *(args[2]) == 0) {
                        Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
                              file, linenum, args[0]);
-                       return -1;
+                       err_code |= ERR_ALERT | ERR_FATAL;
+                       goto out;
                }
        
                preg = calloc(1, sizeof(regex_t));
                if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
                        Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
-                       return -1;
+                       err_code |= ERR_ALERT | ERR_FATAL;
+                       goto out;
                }
        
                err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
                if (err) {
                        Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
                              file, linenum, *err);
-                       return -1;
+                       err_code |= ERR_ALERT | ERR_FATAL;
+                       goto out;
                }
                warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
        }
@@ -2753,20 +2929,23 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int inv)
                regex_t *preg;
                if (curproxy == &defproxy) {
                        Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
-                       return -1;
+                       err_code |= ERR_ALERT | ERR_FATAL;
+                       goto out;
                }
                else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
-                       return 0;
+                       err_code |= ERR_WARN;
 
                if (*(args[1]) == 0) {
                        Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
-                       return -1;
+                       err_code |= ERR_ALERT | ERR_FATAL;
+                       goto out;
                }
        
                preg = calloc(1, sizeof(regex_t));
                if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
                        Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
-                       return -1;
+                       err_code |= ERR_ALERT | ERR_FATAL;
+                       goto out;
                }
        
                chain_regex(&curproxy->req_exp, preg, ACT_REMOVE, NULL);
@@ -2776,20 +2955,23 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int inv)
                regex_t *preg;
                if (curproxy == &defproxy) {
                        Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
-                       return -1;
+                       err_code |= ERR_ALERT | ERR_FATAL;
+                       goto out;
                }
                else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
-                       return 0;
+                       err_code |= ERR_WARN;
 
                if (*(args[1]) == 0) {
                        Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
-                       return -1;
+                       err_code |= ERR_ALERT | ERR_FATAL;
+                       goto out;
                }
        
                preg = calloc(1, sizeof(regex_t));
                if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
                        Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
-                       return -1;
+                       err_code |= ERR_ALERT | ERR_FATAL;
+                       goto out;
                }
        
                chain_regex(&curproxy->req_exp, preg, ACT_DENY, NULL);
@@ -2799,20 +2981,23 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int inv)
                regex_t *preg;
                if (curproxy == &defproxy) {
                        Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
-                       return -1;
+                       err_code |= ERR_ALERT | ERR_FATAL;
+                       goto out;
                }
                else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
-                       return 0;
+                       err_code |= ERR_WARN;
 
                if (*(args[1]) == 0) {
                        Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
-                       return -1;
+                       err_code |= ERR_ALERT | ERR_FATAL;
+                       goto out;
                }
        
                preg = calloc(1, sizeof(regex_t));
                if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
                        Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
-                       return -1;
+                       err_code |= ERR_ALERT | ERR_FATAL;
+                       goto out;
                }
        
                chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
@@ -2822,20 +3007,23 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int inv)
                regex_t *preg;
                if (curproxy == &defproxy) {
                        Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
-                       return -1;
+                       err_code |= ERR_ALERT | ERR_FATAL;
+                       goto out;
                }
                else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
-                       return 0;
+                       err_code |= ERR_WARN;
 
                if (*(args[1]) == 0) {
                        Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
-                       return -1;
+                       err_code |= ERR_ALERT | ERR_FATAL;
+                       goto out;
                }
        
                preg = calloc(1, sizeof(regex_t));
                if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
                        Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
-                       return -1;
+                       err_code |= ERR_ALERT | ERR_FATAL;
+                       goto out;
                }
        
                chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
@@ -2845,20 +3033,23 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int inv)
                regex_t *preg;
                if (curproxy == &defproxy) {
                        Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
-                       return -1;
+                       err_code |= ERR_ALERT | ERR_FATAL;
+                       goto out;
                }
                else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
-                       return 0;
+                       err_code |= ERR_WARN;
 
                if (*(args[1]) == 0) {
                        Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
-                       return -1;
+                       err_code |= ERR_ALERT | ERR_FATAL;
+                       goto out;
                }
        
                preg = calloc(1, sizeof(regex_t));
                if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
                        Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
-                       return -1;
+                       err_code |= ERR_ALERT | ERR_FATAL;
+                       goto out;
                }
        
                chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
@@ -2867,19 +3058,22 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int inv)
        else if (!strcmp(args[0], "reqadd")) {  /* add request header */
                if (curproxy == &defproxy) {
                        Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
-                       return -1;
+                       err_code |= ERR_ALERT | ERR_FATAL;
+                       goto out;
                }
                else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
-                       return 0;
+                       err_code |= ERR_WARN;
 
                if (curproxy->nb_reqadd >= MAX_NEWHDR) {
                        Alert("parsing [%s:%d] : too many '%s'. Continuing.\n", file, linenum, args[0]);
-                       return 0;
+                       err_code |= ERR_ALERT | ERR_FATAL;
+                       goto out;
                }
        
                if (*(args[1]) == 0) {
                        Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
-                       return -1;
+                       err_code |= ERR_ALERT | ERR_FATAL;
+                       goto out;
                }
        
                curproxy->req_add[curproxy->nb_reqadd++] = strdup(args[1]);
@@ -2891,22 +3085,25 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int inv)
                if (*(args[1]) == 0 || *(args[2]) == 0) {
                        Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
                              file, linenum, args[0]);
-                       return -1;
+                       err_code |= ERR_ALERT | ERR_FATAL;
+                       goto out;
                }
                else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
-                       return 0;
+                       err_code |= ERR_WARN;
 
                preg = calloc(1, sizeof(regex_t));
                if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
                        Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
-                       return -1;
+                       err_code |= ERR_ALERT | ERR_FATAL;
+                       goto out;
                }
        
                err = chain_regex(&curproxy->rsp_exp, preg, ACT_REPLACE, strdup(args[2]));
                if (err) {
                        Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
                              file, linenum, *err);
-                       return -1;
+                       err_code |= ERR_ALERT | ERR_FATAL;
+                       goto out;
                }
                warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
        }
@@ -2914,154 +3111,177 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int inv)
                regex_t *preg;
                if (curproxy == &defproxy) {
                        Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
-                       return -1;
+                       err_code |= ERR_ALERT | ERR_FATAL;
+                       goto out;
                }
                else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
-                       return 0;
+                       err_code |= ERR_WARN;
 
                if (*(args[1]) == 0) {
                        Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
-                       return -1;
+                       err_code |= ERR_ALERT | ERR_FATAL;
+                       goto out;
                }
 
                preg = calloc(1, sizeof(regex_t));
                if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
                        Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
-                       return -1;
+                       err_code |= ERR_ALERT | ERR_FATAL;
+                       goto out;
                }
        
                err = chain_regex(&curproxy->rsp_exp, preg, ACT_REMOVE, strdup(args[2]));
                if (err) {
                        Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
                              file, linenum, *err);
-                       return -1;
+                       err_code |= ERR_ALERT | ERR_FATAL;
+                       goto out;
                }
        }
        else if (!strcmp(args[0], "rspdeny")) {  /* block response header from a regex */
                regex_t *preg;
                if (curproxy == &defproxy) {
                        Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
-                       return -1;
+                       err_code |= ERR_ALERT | ERR_FATAL;
+                       goto out;
                }
                else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
-                       return 0;
+                       err_code |= ERR_WARN;
 
                if (*(args[1]) == 0) {
                        Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
-                       return -1;
+                       err_code |= ERR_ALERT | ERR_FATAL;
+                       goto out;
                }
 
                preg = calloc(1, sizeof(regex_t));
                if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
                        Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
-                       return -1;
+                       err_code |= ERR_ALERT | ERR_FATAL;
+                       goto out;
                }
        
                err = chain_regex(&curproxy->rsp_exp, preg, ACT_DENY, strdup(args[2]));
                if (err) {
                        Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
                              file, linenum, *err);
-                       return -1;
+                       err_code |= ERR_ALERT | ERR_FATAL;
+                       goto out;
                }
        }
        else if (!strcmp(args[0], "rspirep")) {  /* replace response header from a regex ignoring case */
                regex_t *preg;
                if (curproxy == &defproxy) {
                        Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
-                       return -1;
+                       err_code |= ERR_ALERT | ERR_FATAL;
+                       goto out;
                }
                else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
-                       return 0;
+                       err_code |= ERR_WARN;
 
                if (*(args[1]) == 0 || *(args[2]) == 0) {
                        Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
                              file, linenum, args[0]);
-                       return -1;
+                       err_code |= ERR_ALERT | ERR_FATAL;
+                       goto out;
                }
 
                preg = calloc(1, sizeof(regex_t));
                if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
                        Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
-                       return -1;
+                       err_code |= ERR_ALERT | ERR_FATAL;
+                       goto out;
                }
            
                err = chain_regex(&curproxy->rsp_exp, preg, ACT_REPLACE, strdup(args[2]));
                if (err) {
                        Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
                              file, linenum, *err);
-                       return -1;
+                       err_code |= ERR_ALERT | ERR_FATAL;
+                       goto out;
                }
        }
        else if (!strcmp(args[0], "rspidel")) {  /* delete response header from a regex ignoring case */
                regex_t *preg;
                if (curproxy == &defproxy) {
                        Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
-                       return -1;
+                       err_code |= ERR_ALERT | ERR_FATAL;
+                       goto out;
                }
                else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
-                       return 0;
+                       err_code |= ERR_WARN;
 
                if (*(args[1]) == 0) {
                        Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
-                       return -1;
+                       err_code |= ERR_ALERT | ERR_FATAL;
+                       goto out;
                }
 
                preg = calloc(1, sizeof(regex_t));
                if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
                        Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
-                       return -1;
+                       err_code |= ERR_ALERT | ERR_FATAL;
+                       goto out;
                }
        
                err = chain_regex(&curproxy->rsp_exp, preg, ACT_REMOVE, strdup(args[2]));
                if (err) {
                        Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
                              file, linenum, *err);
-                       return -1;
+                       err_code |= ERR_ALERT | ERR_FATAL;
+                       goto out;
                }
        }
        else if (!strcmp(args[0], "rspideny")) {  /* block response header from a regex ignoring case */
                regex_t *preg;
                if (curproxy == &defproxy) {
                        Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
-                       return -1;
+                       err_code |= ERR_ALERT | ERR_FATAL;
+                       goto out;
                }
                else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
-                       return 0;
+                       err_code |= ERR_WARN;
 
                if (*(args[1]) == 0) {
                        Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
-                       return -1;
+                       err_code |= ERR_ALERT | ERR_FATAL;
+                       goto out;
                }
 
                preg = calloc(1, sizeof(regex_t));
                if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
                        Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
-                       return -1;
+                       err_code |= ERR_ALERT | ERR_FATAL;
+                       goto out;
                }
        
                err = chain_regex(&curproxy->rsp_exp, preg, ACT_DENY, strdup(args[2]));
                if (err) {
                        Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
                              file, linenum, *err);
-                       return -1;
+                       err_code |= ERR_ALERT | ERR_FATAL;
+                       goto out;
                }
        }
        else if (!strcmp(args[0], "rspadd")) {  /* add response header */
                if (curproxy == &defproxy) {
                        Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
-                       return -1;
+                       err_code |= ERR_ALERT | ERR_FATAL;
+                       goto out;
                }
                else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
-                       return 0;
+                       err_code |= ERR_WARN;
 
                if (curproxy->nb_rspadd >= MAX_NEWHDR) {
                        Alert("parsing [%s:%d] : too many '%s'. Continuing.\n", file, linenum, args[0]);
-                       return 0;
+                       err_code |= ERR_ALERT | ERR_FATAL;
+                       goto out;
                }
        
                if (*(args[1]) == 0) {
                        Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
-                       return -1;
+                       err_code |= ERR_ALERT | ERR_FATAL;
+                       goto out;
                }
        
                curproxy->rsp_add[curproxy->nb_rspadd++] = strdup(args[1]);
@@ -3073,11 +3293,12 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int inv)
                char *err;
 
                if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
-                       return 0;
+                       err_code |= ERR_WARN;
 
                if (*(args[2]) == 0) {
                        Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
-                       return -1;
+                       err_code |= ERR_ALERT | ERR_FATAL;
+                       goto out;
                }
 
                errnum = atol(args[1]);
@@ -3110,11 +3331,12 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int inv)
                struct stat stat;
 
                if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
-                       return 0;
+                       err_code |= ERR_WARN;
 
                if (*(args[2]) == 0) {
                        Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
-                       return -1;
+                       err_code |= ERR_ALERT | ERR_FATAL;
+                       goto out;
                }
 
                fd = open(args[2], O_RDONLY);
@@ -3123,7 +3345,8 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int inv)
                              file, linenum, args[2], args[1]);
                        if (fd >= 0)
                                close(fd);
-                       return -1;
+                       err_code |= ERR_ALERT | ERR_FATAL;
+                       goto out;
                }
 
                if (stat.st_size <= BUFSIZE) {
@@ -3131,6 +3354,7 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int inv)
                } else {
                        Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
                                file, linenum, args[2], BUFSIZE);
+                       err_code |= ERR_WARN;
                        errlen = BUFSIZE;
                }
 
@@ -3141,7 +3365,8 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int inv)
                              file, linenum, args[2], args[1]);
                        close(fd);
                        free(err);
-                       return -1;
+                       err_code |= ERR_ALERT | ERR_FATAL;
+                       goto out;
                }
                close(fd);
 
@@ -3158,6 +3383,7 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int inv)
                if (rc >= HTTP_ERR_SIZE) {
                        Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
                                file, linenum, errnum);
+                       err_code |= ERR_WARN;
                        free(err);
                }
        }
@@ -3176,21 +3402,25 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int inv)
                                        rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, trash, sizeof(trash));
                                        if (rc < 0) {
                                                Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
-                                               return -1;
+                                               err_code |= ERR_ALERT | ERR_FATAL;
+                                               goto out;
                                        }
                                        else if (rc > 0) {
                                                Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
-                                               return 0;
+                                               err_code |= ERR_WARN;
+                                               goto out;
                                        }
-                                       return 0;
+                                       goto out;
                                }
                        }
                }
                
                Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
-               return -1;
+               err_code |= ERR_ALERT | ERR_FATAL;
+               goto out;
        }
-       return 0;
+ out:
+       return err_code;
 }
 
 
@@ -3341,8 +3571,7 @@ int readcfgfile(const char *file)
 
                switch (confsect) {
                case CFG_LISTEN:
-                       if (cfg_parse_listen(file, linenum, args, inv) < 0)
-                               err_code |= ERR_ABORT;
+                       err_code |= cfg_parse_listen(file, linenum, args, inv);
                        break;
                case CFG_GLOBAL:
                        err_code |= cfg_parse_global(file, linenum, args, inv);