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