blob: 1633700ae9d2b1b25b8bbee96544c99fd4a18f39 [file] [log] [blame]
Willy Tarreau36b9e222018-11-11 15:19:52 +01001#include <stdio.h>
2#include <stdlib.h>
3#include <string.h>
4#include <netdb.h>
5#include <ctype.h>
6#include <pwd.h>
7#include <grp.h>
8#include <errno.h>
9#include <sys/types.h>
10#include <sys/stat.h>
11#include <fcntl.h>
12#include <unistd.h>
13
14#include <common/cfgparse.h>
15#include <proto/compression.h>
16
17/*
18 * parse a line in a <global> section. Returns the error code, 0 if OK, or
19 * any combination of :
20 * - ERR_ABORT: must abort ASAP
21 * - ERR_FATAL: we can continue parsing but not start the service
22 * - ERR_WARN: a warning has been emitted
23 * - ERR_ALERT: an alert has been emitted
24 * Only the two first ones can stop processing, the two others are just
25 * indicators.
26 */
27int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
28{
29 int err_code = 0;
30 char *errmsg = NULL;
31
32 if (!strcmp(args[0], "global")) { /* new section */
33 /* no option, nothing special to do */
34 alertif_too_many_args(0, file, linenum, args, &err_code);
35 goto out;
36 }
37 else if (!strcmp(args[0], "daemon")) {
38 if (alertif_too_many_args(0, file, linenum, args, &err_code))
39 goto out;
40 global.mode |= MODE_DAEMON;
41 }
42 else if (!strcmp(args[0], "master-worker")) {
43 if (alertif_too_many_args(1, file, linenum, args, &err_code))
44 goto out;
45 if (*args[1]) {
46 if (!strcmp(args[1], "no-exit-on-failure")) {
47 global.tune.options |= GTUNE_NOEXIT_ONFAILURE;
48 } else {
49 ha_alert("parsing [%s:%d] : '%s' only supports 'no-exit-on-failure' option.\n", file, linenum, args[0]);
50 err_code |= ERR_ALERT | ERR_FATAL;
51 goto out;
52 }
53 }
54 global.mode |= MODE_MWORKER;
55 }
56 else if (!strcmp(args[0], "debug")) {
57 if (alertif_too_many_args(0, file, linenum, args, &err_code))
58 goto out;
59 global.mode |= MODE_DEBUG;
60 }
61 else if (!strcmp(args[0], "noepoll")) {
62 if (alertif_too_many_args(0, file, linenum, args, &err_code))
63 goto out;
64 global.tune.options &= ~GTUNE_USE_EPOLL;
65 }
66 else if (!strcmp(args[0], "nokqueue")) {
67 if (alertif_too_many_args(0, file, linenum, args, &err_code))
68 goto out;
69 global.tune.options &= ~GTUNE_USE_KQUEUE;
70 }
71 else if (!strcmp(args[0], "nopoll")) {
72 if (alertif_too_many_args(0, file, linenum, args, &err_code))
73 goto out;
74 global.tune.options &= ~GTUNE_USE_POLL;
75 }
Willy Tarreaubeb859a2018-11-22 18:07:59 +010076 else if (!strcmp(args[0], "busy-polling")) { /* "no busy-polling" or "busy-polling" */
77 if (alertif_too_many_args(0, file, linenum, args, &err_code))
78 goto out;
79 if (kwm == KWM_NO)
80 global.tune.options &= ~GTUNE_BUSY_POLLING;
81 else
82 global.tune.options |= GTUNE_BUSY_POLLING;
83 }
Willy Tarreau636848a2019-04-15 19:38:50 +020084 else if (!strcmp(args[0], "set-dumpable")) { /* "no set-dumpable" or "set-dumpable" */
85 if (alertif_too_many_args(0, file, linenum, args, &err_code))
86 goto out;
87 if (kwm == KWM_NO)
88 global.tune.options &= ~GTUNE_SET_DUMPABLE;
89 else
90 global.tune.options |= GTUNE_SET_DUMPABLE;
91 }
Willy Tarreau36b9e222018-11-11 15:19:52 +010092 else if (!strcmp(args[0], "nosplice")) {
93 if (alertif_too_many_args(0, file, linenum, args, &err_code))
94 goto out;
95 global.tune.options &= ~GTUNE_USE_SPLICE;
96 }
97 else if (!strcmp(args[0], "nogetaddrinfo")) {
98 if (alertif_too_many_args(0, file, linenum, args, &err_code))
99 goto out;
100 global.tune.options &= ~GTUNE_USE_GAI;
101 }
102 else if (!strcmp(args[0], "noreuseport")) {
103 if (alertif_too_many_args(0, file, linenum, args, &err_code))
104 goto out;
105 global.tune.options &= ~GTUNE_USE_REUSEPORT;
106 }
107 else if (!strcmp(args[0], "quiet")) {
108 if (alertif_too_many_args(0, file, linenum, args, &err_code))
109 goto out;
110 global.mode |= MODE_QUIET;
111 }
112 else if (!strcmp(args[0], "tune.runqueue-depth")) {
113 if (alertif_too_many_args(1, file, linenum, args, &err_code))
114 goto out;
115 if (global.tune.runqueue_depth != 0) {
116 ha_alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
117 err_code |= ERR_ALERT;
118 goto out;
119 }
120 if (*(args[1]) == 0) {
121 ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
122 err_code |= ERR_ALERT | ERR_FATAL;
123 goto out;
124 }
125 global.tune.runqueue_depth = atol(args[1]);
126
127 }
128 else if (!strcmp(args[0], "tune.maxpollevents")) {
129 if (alertif_too_many_args(1, file, linenum, args, &err_code))
130 goto out;
131 if (global.tune.maxpollevents != 0) {
132 ha_alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
133 err_code |= ERR_ALERT;
134 goto out;
135 }
136 if (*(args[1]) == 0) {
137 ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
138 err_code |= ERR_ALERT | ERR_FATAL;
139 goto out;
140 }
141 global.tune.maxpollevents = atol(args[1]);
142 }
143 else if (!strcmp(args[0], "tune.maxaccept")) {
Christopher Faulet6b02ab82019-04-30 14:03:56 +0200144 long max;
145
Willy Tarreau36b9e222018-11-11 15:19:52 +0100146 if (alertif_too_many_args(1, file, linenum, args, &err_code))
147 goto out;
148 if (global.tune.maxaccept != 0) {
149 ha_alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
150 err_code |= ERR_ALERT;
151 goto out;
152 }
153 if (*(args[1]) == 0) {
154 ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
155 err_code |= ERR_ALERT | ERR_FATAL;
156 goto out;
157 }
Christopher Faulet6b02ab82019-04-30 14:03:56 +0200158 max = atol(args[1]);
159 if (/*max < -1 || */max > INT_MAX) {
160 ha_alert("parsing [%s:%d] : '%s' expects -1 or an integer from 0 to INT_MAX.\n", file, linenum, args[0]);
161 err_code |= ERR_ALERT | ERR_FATAL;
162 goto out;
163 }
164 global.tune.maxaccept = max;
Willy Tarreau36b9e222018-11-11 15:19:52 +0100165 }
166 else if (!strcmp(args[0], "tune.chksize")) {
167 if (alertif_too_many_args(1, file, linenum, args, &err_code))
168 goto out;
169 if (*(args[1]) == 0) {
170 ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
171 err_code |= ERR_ALERT | ERR_FATAL;
172 goto out;
173 }
174 global.tune.chksize = atol(args[1]);
175 }
176 else if (!strcmp(args[0], "tune.recv_enough")) {
177 if (alertif_too_many_args(1, file, linenum, args, &err_code))
178 goto out;
179 if (*(args[1]) == 0) {
180 ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
181 err_code |= ERR_ALERT | ERR_FATAL;
182 goto out;
183 }
184 global.tune.recv_enough = atol(args[1]);
185 }
186 else if (!strcmp(args[0], "tune.buffers.limit")) {
187 if (alertif_too_many_args(1, file, linenum, args, &err_code))
188 goto out;
189 if (*(args[1]) == 0) {
190 ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
191 err_code |= ERR_ALERT | ERR_FATAL;
192 goto out;
193 }
194 global.tune.buf_limit = atol(args[1]);
195 if (global.tune.buf_limit) {
196 if (global.tune.buf_limit < 3)
197 global.tune.buf_limit = 3;
198 if (global.tune.buf_limit <= global.tune.reserved_bufs)
199 global.tune.buf_limit = global.tune.reserved_bufs + 1;
200 }
201 }
202 else if (!strcmp(args[0], "tune.buffers.reserve")) {
203 if (alertif_too_many_args(1, file, linenum, args, &err_code))
204 goto out;
205 if (*(args[1]) == 0) {
206 ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
207 err_code |= ERR_ALERT | ERR_FATAL;
208 goto out;
209 }
210 global.tune.reserved_bufs = atol(args[1]);
211 if (global.tune.reserved_bufs < 2)
212 global.tune.reserved_bufs = 2;
213 if (global.tune.buf_limit && global.tune.buf_limit <= global.tune.reserved_bufs)
214 global.tune.buf_limit = global.tune.reserved_bufs + 1;
215 }
216 else if (!strcmp(args[0], "tune.bufsize")) {
217 if (alertif_too_many_args(1, file, linenum, args, &err_code))
218 goto out;
219 if (*(args[1]) == 0) {
220 ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
221 err_code |= ERR_ALERT | ERR_FATAL;
222 goto out;
223 }
224 global.tune.bufsize = atol(args[1]);
Willy Tarreauc77d3642018-12-12 06:19:42 +0100225 /* round it up to support a two-pointer alignment at the end */
226 global.tune.bufsize = (global.tune.bufsize + 2 * sizeof(void *) - 1) & -(2 * sizeof(void *));
Willy Tarreau36b9e222018-11-11 15:19:52 +0100227 if (global.tune.bufsize <= 0) {
228 ha_alert("parsing [%s:%d] : '%s' expects a positive integer argument.\n", file, linenum, args[0]);
229 err_code |= ERR_ALERT | ERR_FATAL;
230 goto out;
231 }
232 }
233 else if (!strcmp(args[0], "tune.maxrewrite")) {
234 if (alertif_too_many_args(1, file, linenum, args, &err_code))
235 goto out;
236 if (*(args[1]) == 0) {
237 ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
238 err_code |= ERR_ALERT | ERR_FATAL;
239 goto out;
240 }
241 global.tune.maxrewrite = atol(args[1]);
242 if (global.tune.maxrewrite < 0) {
243 ha_alert("parsing [%s:%d] : '%s' expects a positive integer argument.\n", file, linenum, args[0]);
244 err_code |= ERR_ALERT | ERR_FATAL;
245 goto out;
246 }
247 }
248 else if (!strcmp(args[0], "tune.idletimer")) {
249 unsigned int idle;
250 const char *res;
251
252 if (alertif_too_many_args(1, file, linenum, args, &err_code))
253 goto out;
254 if (*(args[1]) == 0) {
255 ha_alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
256 err_code |= ERR_ALERT | ERR_FATAL;
257 goto out;
258 }
259
260 res = parse_time_err(args[1], &idle, TIME_UNIT_MS);
261 if (res) {
262 ha_alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
263 file, linenum, *res, args[0]);
264 err_code |= ERR_ALERT | ERR_FATAL;
265 goto out;
266 }
267
268 if (idle > 65535) {
269 ha_alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
270 err_code |= ERR_ALERT | ERR_FATAL;
271 goto out;
272 }
273 global.tune.idle_timer = idle;
274 }
275 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
276 if (alertif_too_many_args(1, file, linenum, args, &err_code))
277 goto out;
278 if (global.tune.client_rcvbuf != 0) {
279 ha_alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
280 err_code |= ERR_ALERT;
281 goto out;
282 }
283 if (*(args[1]) == 0) {
284 ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
285 err_code |= ERR_ALERT | ERR_FATAL;
286 goto out;
287 }
288 global.tune.client_rcvbuf = atol(args[1]);
289 }
290 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
291 if (alertif_too_many_args(1, file, linenum, args, &err_code))
292 goto out;
293 if (global.tune.server_rcvbuf != 0) {
294 ha_alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
295 err_code |= ERR_ALERT;
296 goto out;
297 }
298 if (*(args[1]) == 0) {
299 ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
300 err_code |= ERR_ALERT | ERR_FATAL;
301 goto out;
302 }
303 global.tune.server_rcvbuf = atol(args[1]);
304 }
305 else if (!strcmp(args[0], "tune.sndbuf.client")) {
306 if (alertif_too_many_args(1, file, linenum, args, &err_code))
307 goto out;
308 if (global.tune.client_sndbuf != 0) {
309 ha_alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
310 err_code |= ERR_ALERT;
311 goto out;
312 }
313 if (*(args[1]) == 0) {
314 ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
315 err_code |= ERR_ALERT | ERR_FATAL;
316 goto out;
317 }
318 global.tune.client_sndbuf = atol(args[1]);
319 }
320 else if (!strcmp(args[0], "tune.sndbuf.server")) {
321 if (alertif_too_many_args(1, file, linenum, args, &err_code))
322 goto out;
323 if (global.tune.server_sndbuf != 0) {
324 ha_alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
325 err_code |= ERR_ALERT;
326 goto out;
327 }
328 if (*(args[1]) == 0) {
329 ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
330 err_code |= ERR_ALERT | ERR_FATAL;
331 goto out;
332 }
333 global.tune.server_sndbuf = atol(args[1]);
334 }
335 else if (!strcmp(args[0], "tune.pipesize")) {
336 if (alertif_too_many_args(1, file, linenum, args, &err_code))
337 goto out;
338 if (*(args[1]) == 0) {
339 ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
340 err_code |= ERR_ALERT | ERR_FATAL;
341 goto out;
342 }
343 global.tune.pipesize = atol(args[1]);
344 }
345 else if (!strcmp(args[0], "tune.http.cookielen")) {
346 if (alertif_too_many_args(1, file, linenum, args, &err_code))
347 goto out;
348 if (*(args[1]) == 0) {
349 ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
350 err_code |= ERR_ALERT | ERR_FATAL;
351 goto out;
352 }
353 global.tune.cookie_len = atol(args[1]) + 1;
354 }
355 else if (!strcmp(args[0], "tune.http.logurilen")) {
356 if (alertif_too_many_args(1, file, linenum, args, &err_code))
357 goto out;
358 if (*(args[1]) == 0) {
359 ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
360 err_code |= ERR_ALERT | ERR_FATAL;
361 goto out;
362 }
363 global.tune.requri_len = atol(args[1]) + 1;
364 }
365 else if (!strcmp(args[0], "tune.http.maxhdr")) {
366 if (alertif_too_many_args(1, file, linenum, args, &err_code))
367 goto out;
368 if (*(args[1]) == 0) {
369 ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
370 err_code |= ERR_ALERT | ERR_FATAL;
371 goto out;
372 }
373 global.tune.max_http_hdr = atoi(args[1]);
374 if (global.tune.max_http_hdr < 1 || global.tune.max_http_hdr > 32767) {
375 ha_alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 32767\n",
376 file, linenum, args[0]);
377 err_code |= ERR_ALERT | ERR_FATAL;
378 goto out;
379 }
380 }
381 else if (!strcmp(args[0], "tune.comp.maxlevel")) {
382 if (alertif_too_many_args(1, file, linenum, args, &err_code))
383 goto out;
384 if (*args[1]) {
385 global.tune.comp_maxlevel = atoi(args[1]);
386 if (global.tune.comp_maxlevel < 1 || global.tune.comp_maxlevel > 9) {
387 ha_alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
388 file, linenum, args[0]);
389 err_code |= ERR_ALERT | ERR_FATAL;
390 goto out;
391 }
392 } else {
393 ha_alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
394 file, linenum, args[0]);
395 err_code |= ERR_ALERT | ERR_FATAL;
396 goto out;
397 }
398 }
399 else if (!strcmp(args[0], "tune.pattern.cache-size")) {
400 if (*args[1]) {
401 global.tune.pattern_cache = atoi(args[1]);
402 if (global.tune.pattern_cache < 0) {
403 ha_alert("parsing [%s:%d] : '%s' expects a positive numeric value\n",
404 file, linenum, args[0]);
405 err_code |= ERR_ALERT | ERR_FATAL;
406 goto out;
407 }
408 } else {
409 ha_alert("parsing [%s:%d] : '%s' expects a positive numeric value\n",
410 file, linenum, args[0]);
411 err_code |= ERR_ALERT | ERR_FATAL;
412 goto out;
413 }
414 }
415 else if (!strcmp(args[0], "uid")) {
416 if (alertif_too_many_args(1, file, linenum, args, &err_code))
417 goto out;
418 if (global.uid != 0) {
419 ha_alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
420 err_code |= ERR_ALERT;
421 goto out;
422 }
423 if (*(args[1]) == 0) {
424 ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
425 err_code |= ERR_ALERT | ERR_FATAL;
426 goto out;
427 }
428 if (strl2irc(args[1], strlen(args[1]), &global.uid) != 0) {
429 ha_warning("parsing [%s:%d] : uid: string '%s' is not a number.\n | You might want to use the 'user' parameter to use a system user name.\n", file, linenum, args[1]);
430 err_code |= ERR_WARN;
431 goto out;
432 }
433
434 }
435 else if (!strcmp(args[0], "gid")) {
436 if (alertif_too_many_args(1, file, linenum, args, &err_code))
437 goto out;
438 if (global.gid != 0) {
439 ha_alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
440 err_code |= ERR_ALERT;
441 goto out;
442 }
443 if (*(args[1]) == 0) {
444 ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
445 err_code |= ERR_ALERT | ERR_FATAL;
446 goto out;
447 }
448 if (strl2irc(args[1], strlen(args[1]), &global.gid) != 0) {
449 ha_warning("parsing [%s:%d] : gid: string '%s' is not a number.\n | You might want to use the 'group' parameter to use a system group name.\n", file, linenum, args[1]);
450 err_code |= ERR_WARN;
451 goto out;
452 }
453 }
454 else if (!strcmp(args[0], "external-check")) {
455 if (alertif_too_many_args(0, file, linenum, args, &err_code))
456 goto out;
457 global.external_check = 1;
458 }
459 /* user/group name handling */
460 else if (!strcmp(args[0], "user")) {
461 struct passwd *ha_user;
462 if (alertif_too_many_args(1, file, linenum, args, &err_code))
463 goto out;
464 if (global.uid != 0) {
465 ha_alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
466 err_code |= ERR_ALERT;
467 goto out;
468 }
469 errno = 0;
470 ha_user = getpwnam(args[1]);
471 if (ha_user != NULL) {
472 global.uid = (int)ha_user->pw_uid;
473 }
474 else {
475 ha_alert("parsing [%s:%d] : cannot find user id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
476 err_code |= ERR_ALERT | ERR_FATAL;
477 }
478 }
479 else if (!strcmp(args[0], "group")) {
480 struct group *ha_group;
481 if (alertif_too_many_args(1, file, linenum, args, &err_code))
482 goto out;
483 if (global.gid != 0) {
484 ha_alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
485 err_code |= ERR_ALERT;
486 goto out;
487 }
488 errno = 0;
489 ha_group = getgrnam(args[1]);
490 if (ha_group != NULL) {
491 global.gid = (int)ha_group->gr_gid;
492 }
493 else {
494 ha_alert("parsing [%s:%d] : cannot find group id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
495 err_code |= ERR_ALERT | ERR_FATAL;
496 }
497 }
498 /* end of user/group name handling*/
499 else if (!strcmp(args[0], "nbproc")) {
500 if (alertif_too_many_args(1, file, linenum, args, &err_code))
501 goto out;
502 if (*(args[1]) == 0) {
503 ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
504 err_code |= ERR_ALERT | ERR_FATAL;
505 goto out;
506 }
507 global.nbproc = atol(args[1]);
Willy Tarreaua38a7172019-02-02 17:11:28 +0100508 all_proc_mask = nbits(global.nbproc);
Willy Tarreauff9c9142019-02-07 10:39:36 +0100509 if (global.nbproc < 1 || global.nbproc > MAX_PROCS) {
Willy Tarreau36b9e222018-11-11 15:19:52 +0100510 ha_alert("parsing [%s:%d] : '%s' must be between 1 and %d (was %d).\n",
Willy Tarreauff9c9142019-02-07 10:39:36 +0100511 file, linenum, args[0], MAX_PROCS, global.nbproc);
Willy Tarreau36b9e222018-11-11 15:19:52 +0100512 err_code |= ERR_ALERT | ERR_FATAL;
513 goto out;
514 }
515 }
516 else if (!strcmp(args[0], "nbthread")) {
517 if (alertif_too_many_args(1, file, linenum, args, &err_code))
518 goto out;
519 if (*(args[1]) == 0) {
520 ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
521 err_code |= ERR_ALERT | ERR_FATAL;
522 goto out;
523 }
524 global.nbthread = parse_nbthread(args[1], &errmsg);
525 if (!global.nbthread) {
526 ha_alert("parsing [%s:%d] : '%s' %s.\n",
527 file, linenum, args[0], errmsg);
528 err_code |= ERR_ALERT | ERR_FATAL;
529 goto out;
530 }
531 }
532 else if (!strcmp(args[0], "maxconn")) {
533 if (alertif_too_many_args(1, file, linenum, args, &err_code))
534 goto out;
535 if (global.maxconn != 0) {
536 ha_alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
537 err_code |= ERR_ALERT;
538 goto out;
539 }
540 if (*(args[1]) == 0) {
541 ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
542 err_code |= ERR_ALERT | ERR_FATAL;
543 goto out;
544 }
545 global.maxconn = atol(args[1]);
546#ifdef SYSTEM_MAXCONN
Willy Tarreauca783d42019-03-13 10:03:07 +0100547 if (global.maxconn > SYSTEM_MAXCONN && cfg_maxconn <= SYSTEM_MAXCONN) {
548 ha_alert("parsing [%s:%d] : maxconn value %d too high for this system.\nLimiting to %d. Please use '-n' to force the value.\n", file, linenum, global.maxconn, SYSTEM_MAXCONN);
549 global.maxconn = SYSTEM_MAXCONN;
Willy Tarreau36b9e222018-11-11 15:19:52 +0100550 err_code |= ERR_ALERT;
551 }
552#endif /* SYSTEM_MAXCONN */
553 }
554 else if (!strcmp(args[0], "ssl-server-verify")) {
555 if (alertif_too_many_args(1, file, linenum, args, &err_code))
556 goto out;
557 if (*(args[1]) == 0) {
558 ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
559 err_code |= ERR_ALERT | ERR_FATAL;
560 goto out;
561 }
562 if (strcmp(args[1],"none") == 0)
563 global.ssl_server_verify = SSL_SERVER_VERIFY_NONE;
564 else if (strcmp(args[1],"required") == 0)
565 global.ssl_server_verify = SSL_SERVER_VERIFY_REQUIRED;
566 else {
567 ha_alert("parsing [%s:%d] : '%s' expects 'none' or 'required' as argument.\n", file, linenum, args[0]);
568 err_code |= ERR_ALERT | ERR_FATAL;
569 goto out;
570 }
571 }
572 else if (!strcmp(args[0], "maxconnrate")) {
573 if (alertif_too_many_args(1, file, linenum, args, &err_code))
574 goto out;
575 if (global.cps_lim != 0) {
576 ha_alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
577 err_code |= ERR_ALERT;
578 goto out;
579 }
580 if (*(args[1]) == 0) {
581 ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
582 err_code |= ERR_ALERT | ERR_FATAL;
583 goto out;
584 }
585 global.cps_lim = atol(args[1]);
586 }
587 else if (!strcmp(args[0], "maxsessrate")) {
588 if (alertif_too_many_args(1, file, linenum, args, &err_code))
589 goto out;
590 if (global.sps_lim != 0) {
591 ha_alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
592 err_code |= ERR_ALERT;
593 goto out;
594 }
595 if (*(args[1]) == 0) {
596 ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
597 err_code |= ERR_ALERT | ERR_FATAL;
598 goto out;
599 }
600 global.sps_lim = atol(args[1]);
601 }
602 else if (!strcmp(args[0], "maxsslrate")) {
603 if (alertif_too_many_args(1, file, linenum, args, &err_code))
604 goto out;
605 if (global.ssl_lim != 0) {
606 ha_alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
607 err_code |= ERR_ALERT;
608 goto out;
609 }
610 if (*(args[1]) == 0) {
611 ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
612 err_code |= ERR_ALERT | ERR_FATAL;
613 goto out;
614 }
615 global.ssl_lim = atol(args[1]);
616 }
617 else if (!strcmp(args[0], "maxcomprate")) {
618 if (alertif_too_many_args(1, file, linenum, args, &err_code))
619 goto out;
620 if (*(args[1]) == 0) {
621 ha_alert("parsing [%s:%d] : '%s' expects an integer argument in kb/s.\n", file, linenum, args[0]);
622 err_code |= ERR_ALERT | ERR_FATAL;
623 goto out;
624 }
625 global.comp_rate_lim = atoi(args[1]) * 1024;
626 }
627 else if (!strcmp(args[0], "maxpipes")) {
628 if (alertif_too_many_args(1, file, linenum, args, &err_code))
629 goto out;
630 if (global.maxpipes != 0) {
631 ha_alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
632 err_code |= ERR_ALERT;
633 goto out;
634 }
635 if (*(args[1]) == 0) {
636 ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
637 err_code |= ERR_ALERT | ERR_FATAL;
638 goto out;
639 }
640 global.maxpipes = atol(args[1]);
641 }
642 else if (!strcmp(args[0], "maxzlibmem")) {
643 if (alertif_too_many_args(1, file, linenum, args, &err_code))
644 goto out;
645 if (*(args[1]) == 0) {
646 ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
647 err_code |= ERR_ALERT | ERR_FATAL;
648 goto out;
649 }
650 global.maxzlibmem = atol(args[1]) * 1024L * 1024L;
651 }
652 else if (!strcmp(args[0], "maxcompcpuusage")) {
653 if (alertif_too_many_args(1, file, linenum, args, &err_code))
654 goto out;
655 if (*(args[1]) == 0) {
656 ha_alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
657 err_code |= ERR_ALERT | ERR_FATAL;
658 goto out;
659 }
660 compress_min_idle = 100 - atoi(args[1]);
661 if (compress_min_idle > 100) {
662 ha_alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
663 err_code |= ERR_ALERT | ERR_FATAL;
664 goto out;
665 }
666 }
667
668 else if (!strcmp(args[0], "ulimit-n")) {
669 if (alertif_too_many_args(1, file, linenum, args, &err_code))
670 goto out;
671 if (global.rlimit_nofile != 0) {
672 ha_alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
673 err_code |= ERR_ALERT;
674 goto out;
675 }
676 if (*(args[1]) == 0) {
677 ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
678 err_code |= ERR_ALERT | ERR_FATAL;
679 goto out;
680 }
681 global.rlimit_nofile = atol(args[1]);
682 }
683 else if (!strcmp(args[0], "chroot")) {
684 if (alertif_too_many_args(1, file, linenum, args, &err_code))
685 goto out;
686 if (global.chroot != NULL) {
687 ha_alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
688 err_code |= ERR_ALERT;
689 goto out;
690 }
691 if (*(args[1]) == 0) {
692 ha_alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
693 err_code |= ERR_ALERT | ERR_FATAL;
694 goto out;
695 }
696 global.chroot = strdup(args[1]);
697 }
698 else if (!strcmp(args[0], "description")) {
699 int i, len=0;
700 char *d;
701
702 if (!*args[1]) {
703 ha_alert("parsing [%s:%d]: '%s' expects a string argument.\n",
704 file, linenum, args[0]);
705 err_code |= ERR_ALERT | ERR_FATAL;
706 goto out;
707 }
708
709 for (i = 1; *args[i]; i++)
710 len += strlen(args[i]) + 1;
711
712 if (global.desc)
713 free(global.desc);
714
715 global.desc = d = calloc(1, len);
716
717 d += snprintf(d, global.desc + len - d, "%s", args[1]);
718 for (i = 2; *args[i]; i++)
719 d += snprintf(d, global.desc + len - d, " %s", args[i]);
720 }
721 else if (!strcmp(args[0], "node")) {
722 int i;
723 char c;
724
725 if (alertif_too_many_args(1, file, linenum, args, &err_code))
726 goto out;
727
728 for (i=0; args[1][i]; i++) {
729 c = args[1][i];
730 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
731 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
732 break;
733 }
734
735 if (!i || args[1][i]) {
736 ha_alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
737 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
738 file, linenum, args[0]);
739 err_code |= ERR_ALERT | ERR_FATAL;
740 goto out;
741 }
742
743 if (global.node)
744 free(global.node);
745
746 global.node = strdup(args[1]);
747 }
748 else if (!strcmp(args[0], "pidfile")) {
749 if (alertif_too_many_args(1, file, linenum, args, &err_code))
750 goto out;
751 if (global.pidfile != NULL) {
752 ha_alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
753 err_code |= ERR_ALERT;
754 goto out;
755 }
756 if (*(args[1]) == 0) {
757 ha_alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
758 err_code |= ERR_ALERT | ERR_FATAL;
759 goto out;
760 }
761 global.pidfile = strdup(args[1]);
762 }
763 else if (!strcmp(args[0], "unix-bind")) {
764 int cur_arg = 1;
765 while (*(args[cur_arg])) {
766 if (!strcmp(args[cur_arg], "prefix")) {
767 if (global.unix_bind.prefix != NULL) {
768 ha_alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
769 err_code |= ERR_ALERT;
770 cur_arg += 2;
771 continue;
772 }
773
774 if (*(args[cur_arg+1]) == 0) {
775 ha_alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
776 err_code |= ERR_ALERT | ERR_FATAL;
777 goto out;
778 }
779 global.unix_bind.prefix = strdup(args[cur_arg+1]);
780 cur_arg += 2;
781 continue;
782 }
783
784 if (!strcmp(args[cur_arg], "mode")) {
785
786 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
787 cur_arg += 2;
788 continue;
789 }
790
791 if (!strcmp(args[cur_arg], "uid")) {
792
793 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
794 cur_arg += 2;
795 continue;
796 }
797
798 if (!strcmp(args[cur_arg], "gid")) {
799
800 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
801 cur_arg += 2;
802 continue;
803 }
804
805 if (!strcmp(args[cur_arg], "user")) {
806 struct passwd *user;
807
808 user = getpwnam(args[cur_arg + 1]);
809 if (!user) {
810 ha_alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
811 file, linenum, args[0], args[cur_arg + 1 ]);
812 err_code |= ERR_ALERT | ERR_FATAL;
813 goto out;
814 }
815
816 global.unix_bind.ux.uid = user->pw_uid;
817 cur_arg += 2;
818 continue;
819 }
820
821 if (!strcmp(args[cur_arg], "group")) {
822 struct group *group;
823
824 group = getgrnam(args[cur_arg + 1]);
825 if (!group) {
826 ha_alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
827 file, linenum, args[0], args[cur_arg + 1 ]);
828 err_code |= ERR_ALERT | ERR_FATAL;
829 goto out;
830 }
831
832 global.unix_bind.ux.gid = group->gr_gid;
833 cur_arg += 2;
834 continue;
835 }
836
837 ha_alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
838 file, linenum, args[0]);
839 err_code |= ERR_ALERT | ERR_FATAL;
840 goto out;
841 }
842 }
843 else if (!strcmp(args[0], "log")) { /* "no log" or "log ..." */
844 if (!parse_logsrv(args, &global.logsrvs, (kwm == KWM_NO), &errmsg)) {
845 ha_alert("parsing [%s:%d] : %s : %s\n", file, linenum, args[0], errmsg);
846 err_code |= ERR_ALERT | ERR_FATAL;
847 goto out;
848 }
849 }
850 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
851 char *name;
852
853 if (global.log_send_hostname != NULL) {
854 ha_alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
855 err_code |= ERR_ALERT;
856 goto out;
857 }
858
859 if (*(args[1]))
860 name = args[1];
861 else
862 name = hostname;
863
864 free(global.log_send_hostname);
865 global.log_send_hostname = strdup(name);
866 }
867 else if (!strcmp(args[0], "server-state-base")) { /* path base where HAProxy can find server state files */
868 if (global.server_state_base != NULL) {
869 ha_alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
870 err_code |= ERR_ALERT;
871 goto out;
872 }
873
874 if (!*(args[1])) {
875 ha_alert("parsing [%s:%d] : '%s' expects one argument: a directory path.\n", file, linenum, args[0]);
876 err_code |= ERR_FATAL;
877 goto out;
878 }
879
880 global.server_state_base = strdup(args[1]);
881 }
882 else if (!strcmp(args[0], "server-state-file")) { /* path to the file where HAProxy can load the server states */
883 if (global.server_state_file != NULL) {
884 ha_alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
885 err_code |= ERR_ALERT;
886 goto out;
887 }
888
889 if (!*(args[1])) {
890 ha_alert("parsing [%s:%d] : '%s' expect one argument: a file path.\n", file, linenum, args[0]);
891 err_code |= ERR_FATAL;
892 goto out;
893 }
894
895 global.server_state_file = strdup(args[1]);
896 }
897 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
898 if (alertif_too_many_args(1, file, linenum, args, &err_code))
899 goto out;
900 if (*(args[1]) == 0) {
901 ha_alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
902 err_code |= ERR_ALERT | ERR_FATAL;
903 goto out;
904 }
905 chunk_destroy(&global.log_tag);
906 chunk_initstr(&global.log_tag, strdup(args[1]));
907 }
908 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
909 if (alertif_too_many_args(1, file, linenum, args, &err_code))
910 goto out;
911 if (global.spread_checks != 0) {
912 ha_alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
913 err_code |= ERR_ALERT;
914 goto out;
915 }
916 if (*(args[1]) == 0) {
917 ha_alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
918 err_code |= ERR_ALERT | ERR_FATAL;
919 goto out;
920 }
921 global.spread_checks = atol(args[1]);
922 if (global.spread_checks < 0 || global.spread_checks > 50) {
923 ha_alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
924 err_code |= ERR_ALERT | ERR_FATAL;
925 }
926 }
927 else if (!strcmp(args[0], "max-spread-checks")) { /* maximum time between first and last check */
928 const char *err;
929 unsigned int val;
930
931 if (alertif_too_many_args(1, file, linenum, args, &err_code))
932 goto out;
933 if (*(args[1]) == 0) {
934 ha_alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
935 err_code |= ERR_ALERT | ERR_FATAL;
936 goto out;
937 }
938
939 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
940 if (err) {
941 ha_alert("parsing [%s:%d]: unsupported character '%c' in '%s' (wants an integer delay).\n", file, linenum, *err, args[0]);
942 err_code |= ERR_ALERT | ERR_FATAL;
943 }
944 global.max_spread_checks = val;
945 if (global.max_spread_checks < 0) {
946 ha_alert("parsing [%s:%d]: '%s' needs a positive delay in milliseconds.\n",file, linenum, args[0]);
947 err_code |= ERR_ALERT | ERR_FATAL;
948 }
949 }
950 else if (strcmp(args[0], "cpu-map") == 0) {
951 /* map a process list to a CPU set */
952#ifdef USE_CPU_AFFINITY
953 char *slash;
954 unsigned long proc = 0, thread = 0, cpus;
955 int i, j, n, autoinc;
956
957 if (!*args[1] || !*args[2]) {
958 ha_alert("parsing [%s:%d] : %s expects a process number "
959 " ('all', 'odd', 'even', a number from 1 to %d or a range), "
960 " followed by a list of CPU ranges with numbers from 0 to %d.\n",
Willy Tarreau5799e9c2019-03-05 18:14:03 +0100961 file, linenum, args[0], LONGBITS, LONGBITS - 1);
Willy Tarreau36b9e222018-11-11 15:19:52 +0100962 err_code |= ERR_ALERT | ERR_FATAL;
963 goto out;
964 }
965
966 if ((slash = strchr(args[1], '/')) != NULL)
967 *slash = 0;
968
Willy Tarreau5799e9c2019-03-05 18:14:03 +0100969 /* note: we silently ignore processes over MAX_PROCS and
970 * threads over MAX_THREADS so as not to make configurations a
971 * pain to maintain.
972 */
973 if (parse_process_number(args[1], &proc, LONGBITS, &autoinc, &errmsg)) {
Willy Tarreau36b9e222018-11-11 15:19:52 +0100974 ha_alert("parsing [%s:%d] : %s : %s\n", file, linenum, args[0], errmsg);
975 err_code |= ERR_ALERT | ERR_FATAL;
976 goto out;
977 }
978
979 if (slash) {
Willy Tarreau5799e9c2019-03-05 18:14:03 +0100980 if (parse_process_number(slash+1, &thread, LONGBITS, NULL, &errmsg)) {
Willy Tarreau36b9e222018-11-11 15:19:52 +0100981 ha_alert("parsing [%s:%d] : %s : %s\n", file, linenum, args[0], errmsg);
982 err_code |= ERR_ALERT | ERR_FATAL;
983 goto out;
984 }
985 *slash = '/';
986
987 if (autoinc && atleast2(proc) && atleast2(thread)) {
988 ha_alert("parsing [%s:%d] : %s : '%s' : unable to automatically bind "
989 "a process range _AND_ a thread range\n",
990 file, linenum, args[0], args[1]);
991 err_code |= ERR_ALERT | ERR_FATAL;
992 goto out;
993 }
994 }
995
996 if (parse_cpu_set((const char **)args+2, &cpus, &errmsg)) {
997 ha_alert("parsing [%s:%d] : %s : %s\n", file, linenum, args[0], errmsg);
998 err_code |= ERR_ALERT | ERR_FATAL;
999 goto out;
1000 }
1001
1002 if (autoinc &&
1003 my_popcountl(proc) != my_popcountl(cpus) &&
1004 my_popcountl(thread) != my_popcountl(cpus)) {
1005 ha_alert("parsing [%s:%d] : %s : PROC/THREAD range and CPU sets "
1006 "must have the same size to be automatically bound\n",
1007 file, linenum, args[0]);
1008 err_code |= ERR_ALERT | ERR_FATAL;
1009 goto out;
1010 }
1011
Willy Tarreauff9c9142019-02-07 10:39:36 +01001012 for (i = n = 0; i < MAX_PROCS; i++) {
Willy Tarreau36b9e222018-11-11 15:19:52 +01001013 /* No mapping for this process */
1014 if (!(proc & (1UL << i)))
1015 continue;
1016
1017 /* Mapping at the process level */
1018 if (!thread) {
1019 if (!autoinc)
1020 global.cpu_map.proc[i] = cpus;
1021 else {
1022 n += my_ffsl(cpus >> n);
1023 global.cpu_map.proc[i] = (1UL << (n-1));
1024 }
1025 continue;
1026 }
1027
1028 /* Mapping at the thread level */
1029 for (j = 0; j < MAX_THREADS; j++) {
1030 /* Np mapping for this thread */
1031 if (!(thread & (1UL << j)))
1032 continue;
1033
1034 if (!autoinc)
1035 global.cpu_map.thread[i][j] = cpus;
1036 else {
1037 n += my_ffsl(cpus >> n);
1038 global.cpu_map.thread[i][j] = (1UL << (n-1));
1039 }
1040 }
1041 }
1042#else
1043 ha_alert("parsing [%s:%d] : '%s' is not enabled, please check build options for USE_CPU_AFFINITY.\n",
1044 file, linenum, args[0]);
1045 err_code |= ERR_ALERT | ERR_FATAL;
1046 goto out;
1047#endif /* ! USE_CPU_AFFINITY */
1048 }
1049 else if (strcmp(args[0], "setenv") == 0 || strcmp(args[0], "presetenv") == 0) {
1050 if (alertif_too_many_args(3, file, linenum, args, &err_code))
1051 goto out;
1052
1053 if (*(args[2]) == 0) {
1054 ha_alert("parsing [%s:%d]: '%s' expects a name and a value.\n", file, linenum, args[0]);
1055 err_code |= ERR_ALERT | ERR_FATAL;
1056 goto out;
1057 }
1058
1059 /* "setenv" overwrites, "presetenv" only sets if not yet set */
1060 if (setenv(args[1], args[2], (args[0][0] == 's')) != 0) {
1061 ha_alert("parsing [%s:%d]: '%s' failed on variable '%s' : %s.\n", file, linenum, args[0], args[1], strerror(errno));
1062 err_code |= ERR_ALERT | ERR_FATAL;
1063 goto out;
1064 }
1065 }
1066 else if (!strcmp(args[0], "unsetenv")) {
1067 int arg;
1068
1069 if (*(args[1]) == 0) {
1070 ha_alert("parsing [%s:%d]: '%s' expects at least one variable name.\n", file, linenum, args[0]);
1071 err_code |= ERR_ALERT | ERR_FATAL;
1072 goto out;
1073 }
1074
1075 for (arg = 1; *args[arg]; arg++) {
1076 if (unsetenv(args[arg]) != 0) {
1077 ha_alert("parsing [%s:%d]: '%s' failed on variable '%s' : %s.\n", file, linenum, args[0], args[arg], strerror(errno));
1078 err_code |= ERR_ALERT | ERR_FATAL;
1079 goto out;
1080 }
1081 }
1082 }
1083 else if (!strcmp(args[0], "resetenv")) {
1084 extern char **environ;
1085 char **env = environ;
1086
1087 /* args contain variable names to keep, one per argument */
1088 while (*env) {
1089 int arg;
1090
1091 /* look for current variable in among all those we want to keep */
1092 for (arg = 1; *args[arg]; arg++) {
1093 if (strncmp(*env, args[arg], strlen(args[arg])) == 0 &&
1094 (*env)[strlen(args[arg])] == '=')
1095 break;
1096 }
1097
1098 /* delete this variable */
1099 if (!*args[arg]) {
1100 char *delim = strchr(*env, '=');
1101
1102 if (!delim || delim - *env >= trash.size) {
1103 ha_alert("parsing [%s:%d]: '%s' failed to unset invalid variable '%s'.\n", file, linenum, args[0], *env);
1104 err_code |= ERR_ALERT | ERR_FATAL;
1105 goto out;
1106 }
1107
1108 memcpy(trash.area, *env, delim - *env);
1109 trash.area[delim - *env] = 0;
1110
1111 if (unsetenv(trash.area) != 0) {
1112 ha_alert("parsing [%s:%d]: '%s' failed to unset variable '%s' : %s.\n", file, linenum, args[0], *env, strerror(errno));
1113 err_code |= ERR_ALERT | ERR_FATAL;
1114 goto out;
1115 }
1116 }
1117 else
1118 env++;
1119 }
1120 }
1121 else {
1122 struct cfg_kw_list *kwl;
1123 int index;
1124 int rc;
1125
1126 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1127 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1128 if (kwl->kw[index].section != CFG_GLOBAL)
1129 continue;
1130 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
1131 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, file, linenum, &errmsg);
1132 if (rc < 0) {
1133 ha_alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
1134 err_code |= ERR_ALERT | ERR_FATAL;
1135 }
1136 else if (rc > 0) {
1137 ha_warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
1138 err_code |= ERR_WARN;
1139 goto out;
1140 }
1141 goto out;
1142 }
1143 }
1144 }
1145
1146 ha_alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
1147 err_code |= ERR_ALERT | ERR_FATAL;
1148 }
1149
1150 out:
1151 free(errmsg);
1152 return err_code;
1153}
1154