nxt_conf_validation.c (394:28ec49e1e6b0) nxt_conf_validation.c (427:05ae752c6cfb)
1
2/*
3 * Copyright (C) Valentin V. Bartenev
4 * Copyright (C) NGINX, Inc.
5 */
6
7#include <nxt_main.h>
8#include <nxt_conf.h>
9#include <nxt_application.h>
10
11
12typedef struct {
13 nxt_str_t name;
14 nxt_conf_type_t type;
15 nxt_int_t (*validator)(nxt_conf_validation_t *vldt,
16 nxt_conf_value_t *value, void *data);
17 void *data;
18} nxt_conf_vldt_object_t;
19
20
21typedef nxt_int_t (*nxt_conf_vldt_member_t)(nxt_conf_validation_t *vldt,
22 nxt_str_t *name,
23 nxt_conf_value_t *value);
24
25typedef nxt_int_t (*nxt_conf_vldt_system_t)(nxt_conf_validation_t *vldt,
26 char *name);
27
28
29static nxt_int_t nxt_conf_vldt_type(nxt_conf_validation_t *vldt,
30 nxt_str_t *name, nxt_conf_value_t *value, nxt_conf_type_t type);
31static nxt_int_t nxt_conf_vldt_error(nxt_conf_validation_t *vldt,
32 const char *fmt, ...);
33
34static nxt_int_t nxt_conf_vldt_listener(nxt_conf_validation_t *vldt,
35 nxt_str_t *name, nxt_conf_value_t *value);
36static nxt_int_t nxt_conf_vldt_app_name(nxt_conf_validation_t *vldt,
37 nxt_conf_value_t *value, void *data);
38static nxt_int_t nxt_conf_vldt_app(nxt_conf_validation_t *vldt,
39 nxt_str_t *name, nxt_conf_value_t *value);
40static nxt_int_t nxt_conf_vldt_object(nxt_conf_validation_t *vldt,
41 nxt_conf_value_t *value, void *data);
42static nxt_int_t nxt_conf_vldt_object_iterator(nxt_conf_validation_t *vldt,
43 nxt_conf_value_t *value, void *data);
44static nxt_int_t nxt_conf_vldt_system(nxt_conf_validation_t *vldt,
45 nxt_conf_value_t *value, void *data);
46static nxt_int_t nxt_conf_vldt_user(nxt_conf_validation_t *vldt, char *name);
47static nxt_int_t nxt_conf_vldt_group(nxt_conf_validation_t *vldt, char *name);
48
49
50static nxt_conf_vldt_object_t nxt_conf_vldt_root_members[] = {
51 { nxt_string("listeners"),
52 NXT_CONF_OBJECT,
53 &nxt_conf_vldt_object_iterator,
54 (void *) &nxt_conf_vldt_listener },
55
56 { nxt_string("applications"),
57 NXT_CONF_OBJECT,
58 &nxt_conf_vldt_object_iterator,
59 (void *) &nxt_conf_vldt_app },
60
61 { nxt_null_string, 0, NULL, NULL }
62};
63
64
65static nxt_conf_vldt_object_t nxt_conf_vldt_listener_members[] = {
66 { nxt_string("application"),
67 NXT_CONF_STRING,
68 &nxt_conf_vldt_app_name,
69 NULL },
70
71 { nxt_null_string, 0, NULL, NULL }
72};
73
74
75static nxt_conf_vldt_object_t nxt_conf_vldt_app_limits_members[] = {
76 { nxt_string("timeout"),
77 NXT_CONF_INTEGER,
78 NULL,
79 NULL },
80
1
2/*
3 * Copyright (C) Valentin V. Bartenev
4 * Copyright (C) NGINX, Inc.
5 */
6
7#include <nxt_main.h>
8#include <nxt_conf.h>
9#include <nxt_application.h>
10
11
12typedef struct {
13 nxt_str_t name;
14 nxt_conf_type_t type;
15 nxt_int_t (*validator)(nxt_conf_validation_t *vldt,
16 nxt_conf_value_t *value, void *data);
17 void *data;
18} nxt_conf_vldt_object_t;
19
20
21typedef nxt_int_t (*nxt_conf_vldt_member_t)(nxt_conf_validation_t *vldt,
22 nxt_str_t *name,
23 nxt_conf_value_t *value);
24
25typedef nxt_int_t (*nxt_conf_vldt_system_t)(nxt_conf_validation_t *vldt,
26 char *name);
27
28
29static nxt_int_t nxt_conf_vldt_type(nxt_conf_validation_t *vldt,
30 nxt_str_t *name, nxt_conf_value_t *value, nxt_conf_type_t type);
31static nxt_int_t nxt_conf_vldt_error(nxt_conf_validation_t *vldt,
32 const char *fmt, ...);
33
34static nxt_int_t nxt_conf_vldt_listener(nxt_conf_validation_t *vldt,
35 nxt_str_t *name, nxt_conf_value_t *value);
36static nxt_int_t nxt_conf_vldt_app_name(nxt_conf_validation_t *vldt,
37 nxt_conf_value_t *value, void *data);
38static nxt_int_t nxt_conf_vldt_app(nxt_conf_validation_t *vldt,
39 nxt_str_t *name, nxt_conf_value_t *value);
40static nxt_int_t nxt_conf_vldt_object(nxt_conf_validation_t *vldt,
41 nxt_conf_value_t *value, void *data);
42static nxt_int_t nxt_conf_vldt_object_iterator(nxt_conf_validation_t *vldt,
43 nxt_conf_value_t *value, void *data);
44static nxt_int_t nxt_conf_vldt_system(nxt_conf_validation_t *vldt,
45 nxt_conf_value_t *value, void *data);
46static nxt_int_t nxt_conf_vldt_user(nxt_conf_validation_t *vldt, char *name);
47static nxt_int_t nxt_conf_vldt_group(nxt_conf_validation_t *vldt, char *name);
48
49
50static nxt_conf_vldt_object_t nxt_conf_vldt_root_members[] = {
51 { nxt_string("listeners"),
52 NXT_CONF_OBJECT,
53 &nxt_conf_vldt_object_iterator,
54 (void *) &nxt_conf_vldt_listener },
55
56 { nxt_string("applications"),
57 NXT_CONF_OBJECT,
58 &nxt_conf_vldt_object_iterator,
59 (void *) &nxt_conf_vldt_app },
60
61 { nxt_null_string, 0, NULL, NULL }
62};
63
64
65static nxt_conf_vldt_object_t nxt_conf_vldt_listener_members[] = {
66 { nxt_string("application"),
67 NXT_CONF_STRING,
68 &nxt_conf_vldt_app_name,
69 NULL },
70
71 { nxt_null_string, 0, NULL, NULL }
72};
73
74
75static nxt_conf_vldt_object_t nxt_conf_vldt_app_limits_members[] = {
76 { nxt_string("timeout"),
77 NXT_CONF_INTEGER,
78 NULL,
79 NULL },
80
81 { nxt_string("reschedule_timeout"),
82 NXT_CONF_INTEGER,
83 NULL,
84 NULL },
85
81 { nxt_string("requests"),
82 NXT_CONF_INTEGER,
83 NULL,
84 NULL },
85
86 { nxt_null_string, 0, NULL, NULL }
87};
88
89
90static nxt_conf_vldt_object_t nxt_conf_vldt_python_members[] = {
91 { nxt_string("type"),
92 NXT_CONF_STRING,
93 NULL,
94 NULL },
95
96 { nxt_string("workers"),
97 NXT_CONF_INTEGER,
98 NULL,
99 NULL },
100
101 { nxt_string("limits"),
102 NXT_CONF_OBJECT,
103 &nxt_conf_vldt_object,
104 (void *) &nxt_conf_vldt_app_limits_members },
105
106 { nxt_string("user"),
107 NXT_CONF_STRING,
108 nxt_conf_vldt_system,
109 (void *) &nxt_conf_vldt_user },
110
111 { nxt_string("group"),
112 NXT_CONF_STRING,
113 nxt_conf_vldt_system,
114 (void *) &nxt_conf_vldt_group },
115
116 { nxt_string("working_directory"),
117 NXT_CONF_STRING,
118 NULL,
119 NULL },
120
121 { nxt_string("home"),
122 NXT_CONF_STRING,
123 NULL,
124 NULL },
125
126 { nxt_string("path"),
127 NXT_CONF_STRING,
128 NULL,
129 NULL },
130
131 { nxt_string("module"),
132 NXT_CONF_STRING,
133 NULL,
134 NULL },
135
136 { nxt_null_string, 0, NULL, NULL }
137};
138
139
140static nxt_conf_vldt_object_t nxt_conf_vldt_php_members[] = {
141 { nxt_string("type"),
142 NXT_CONF_STRING,
143 NULL,
144 NULL },
145
146 { nxt_string("workers"),
147 NXT_CONF_INTEGER,
148 NULL,
149 NULL },
150
151 { nxt_string("limits"),
152 NXT_CONF_OBJECT,
153 &nxt_conf_vldt_object,
154 (void *) &nxt_conf_vldt_app_limits_members },
155
156 { nxt_string("user"),
157 NXT_CONF_STRING,
158 nxt_conf_vldt_system,
159 (void *) &nxt_conf_vldt_user },
160
161 { nxt_string("group"),
162 NXT_CONF_STRING,
163 nxt_conf_vldt_system,
164 (void *) &nxt_conf_vldt_group },
165
166 { nxt_string("working_directory"),
167 NXT_CONF_STRING,
168 NULL,
169 NULL },
170
171 { nxt_string("root"),
172 NXT_CONF_STRING,
173 NULL,
174 NULL },
175
176 { nxt_string("script"),
177 NXT_CONF_STRING,
178 NULL,
179 NULL },
180
181 { nxt_string("index"),
182 NXT_CONF_STRING,
183 NULL,
184 NULL },
185
186 { nxt_null_string, 0, NULL, NULL }
187};
188
189
190static nxt_conf_vldt_object_t nxt_conf_vldt_go_members[] = {
191 { nxt_string("type"),
192 NXT_CONF_STRING,
193 NULL,
194 NULL },
195
196 { nxt_string("workers"),
197 NXT_CONF_INTEGER,
198 NULL,
199 NULL },
200
201 { nxt_string("limits"),
202 NXT_CONF_OBJECT,
203 &nxt_conf_vldt_object,
204 (void *) &nxt_conf_vldt_app_limits_members },
205
206 { nxt_string("user"),
207 NXT_CONF_STRING,
208 nxt_conf_vldt_system,
209 (void *) &nxt_conf_vldt_user },
210
211 { nxt_string("group"),
212 NXT_CONF_STRING,
213 nxt_conf_vldt_system,
214 (void *) &nxt_conf_vldt_group },
215
216 { nxt_string("working_directory"),
217 NXT_CONF_STRING,
218 NULL,
219 NULL },
220
221 { nxt_string("executable"),
222 NXT_CONF_STRING,
223 NULL,
224 NULL },
225
226 { nxt_null_string, 0, NULL, NULL }
227};
228
229
230nxt_int_t
231nxt_conf_validate(nxt_conf_validation_t *vldt)
232{
233 nxt_int_t ret;
234
235 ret = nxt_conf_vldt_type(vldt, NULL, vldt->conf, NXT_CONF_OBJECT);
236
237 if (ret != NXT_OK) {
238 return ret;
239 }
240
241 return nxt_conf_vldt_object(vldt, vldt->conf, nxt_conf_vldt_root_members);
242}
243
244
245static nxt_int_t
246nxt_conf_vldt_type(nxt_conf_validation_t *vldt, nxt_str_t *name,
247 nxt_conf_value_t *value, nxt_conf_type_t type)
248{
249 nxt_uint_t value_type;
250
251 static const char *type_name[] = {
252 "a null",
253 "a boolean",
254 "an integer",
255 "a number",
256 "a string",
257 "an array",
258 "an object"
259 };
260
261 value_type = nxt_conf_type(value);
262
263 if (value_type == type) {
264 return NXT_OK;
265 }
266
267 if (name == NULL) {
268 return nxt_conf_vldt_error(vldt,
269 "The configuration must be %s, not %s.",
270 type_name[type], type_name[value_type]);
271 }
272
273 return nxt_conf_vldt_error(vldt,
274 "The \"%V\" value must be %s, not %s.",
275 name, type_name[type], type_name[value_type]);
276}
277
278
279static nxt_int_t
280nxt_conf_vldt_error(nxt_conf_validation_t *vldt, const char *fmt, ...)
281{
282 u_char *p, *end;
283 size_t size;
284 va_list args;
285 u_char error[NXT_MAX_ERROR_STR];
286
287 va_start(args, fmt);
288 end = nxt_vsprintf(error, error + NXT_MAX_ERROR_STR, fmt, args);
289 va_end(args);
290
291 size = end - error;
292
293 p = nxt_mp_nget(vldt->pool, size);
294 if (p == NULL) {
295 return NXT_ERROR;
296 }
297
298 nxt_memcpy(p, error, size);
299
300 vldt->error.length = size;
301 vldt->error.start = p;
302
303 return NXT_DECLINED;
304}
305
306
307static nxt_int_t
308nxt_conf_vldt_listener(nxt_conf_validation_t *vldt, nxt_str_t *name,
309 nxt_conf_value_t *value)
310{
311 nxt_int_t ret;
312
313 ret = nxt_conf_vldt_type(vldt, name, value, NXT_CONF_OBJECT);
314
315 if (ret != NXT_OK) {
316 return ret;
317 }
318
319 return nxt_conf_vldt_object(vldt, value, nxt_conf_vldt_listener_members);
320}
321
322
323static nxt_int_t
324nxt_conf_vldt_app_name(nxt_conf_validation_t *vldt, nxt_conf_value_t *value,
325 void *data)
326{
327 nxt_str_t name;
328 nxt_conf_value_t *apps, *app;
329
330 static nxt_str_t apps_str = nxt_string("applications");
331
332 nxt_conf_get_string(value, &name);
333
334 apps = nxt_conf_get_object_member(vldt->conf, &apps_str, NULL);
335
336 if (nxt_slow_path(apps == NULL)) {
337 goto error;
338 }
339
340 app = nxt_conf_get_object_member(apps, &name, NULL);
341
342 if (nxt_slow_path(app == NULL)) {
343 goto error;
344 }
345
346 return NXT_OK;
347
348error:
349
350 return nxt_conf_vldt_error(vldt, "Listening socket is assigned for "
351 "a non existing application \"%V\".",
352 &name);
353}
354
355
356static nxt_int_t
357nxt_conf_vldt_app(nxt_conf_validation_t *vldt, nxt_str_t *name,
358 nxt_conf_value_t *value)
359{
360 nxt_int_t ret;
361 nxt_str_t type;
362 nxt_thread_t *thread;
363 nxt_conf_value_t *type_value;
364 nxt_app_lang_module_t *lang;
365
366 static nxt_str_t type_str = nxt_string("type");
367
368 static void *members[] = {
369 nxt_conf_vldt_python_members,
370 nxt_conf_vldt_php_members,
371 nxt_conf_vldt_go_members,
372 };
373
374 ret = nxt_conf_vldt_type(vldt, name, value, NXT_CONF_OBJECT);
375
376 if (ret != NXT_OK) {
377 return ret;
378 }
379
380 type_value = nxt_conf_get_object_member(value, &type_str, NULL);
381
382 if (type_value == NULL) {
383 return nxt_conf_vldt_error(vldt,
384 "Application must have the \"type\" property set.");
385 }
386
387 ret = nxt_conf_vldt_type(vldt, &type_str, type_value, NXT_CONF_STRING);
388
389 if (ret != NXT_OK) {
390 return ret;
391 }
392
393 nxt_conf_get_string(type_value, &type);
394
395 thread = nxt_thread();
396
397 lang = nxt_app_lang_module(thread->runtime, &type);
398 if (lang == NULL) {
399 return nxt_conf_vldt_error(vldt,
400 "The module to run \"%V\" is not found "
401 "among the available application modules.",
402 &type);
403 }
404
405 return nxt_conf_vldt_object(vldt, value, members[lang->type]);
406}
407
408
409static nxt_int_t
410nxt_conf_vldt_object(nxt_conf_validation_t *vldt, nxt_conf_value_t *value,
411 void *data)
412{
413 uint32_t index;
414 nxt_int_t ret;
415 nxt_str_t name;
416 nxt_conf_value_t *member;
417 nxt_conf_vldt_object_t *vals;
418
419 index = 0;
420
421 for ( ;; ) {
422 member = nxt_conf_next_object_member(value, &name, &index);
423
424 if (member == NULL) {
425 return NXT_OK;
426 }
427
428 vals = data;
429
430 for ( ;; ) {
431 if (vals->name.length == 0) {
432 return nxt_conf_vldt_error(vldt, "Unknown parameter \"%V\".",
433 &name);
434 }
435
436 if (!nxt_strstr_eq(&vals->name, &name)) {
437 vals++;
438 continue;
439 }
440
441 ret = nxt_conf_vldt_type(vldt, &name, member, vals->type);
442
443 if (ret != NXT_OK) {
444 return ret;
445 }
446
447 if (vals->validator != NULL) {
448 ret = vals->validator(vldt, member, vals->data);
449
450 if (ret != NXT_OK) {
451 return ret;
452 }
453 }
454
455 break;
456 }
457 }
458}
459
460
461static nxt_int_t
462nxt_conf_vldt_object_iterator(nxt_conf_validation_t *vldt,
463 nxt_conf_value_t *value, void *data)
464{
465 uint32_t index;
466 nxt_int_t ret;
467 nxt_str_t name;
468 nxt_conf_value_t *member;
469 nxt_conf_vldt_member_t validator;
470
471 validator = (nxt_conf_vldt_member_t) data;
472 index = 0;
473
474 for ( ;; ) {
475 member = nxt_conf_next_object_member(value, &name, &index);
476
477 if (member == NULL) {
478 return NXT_OK;
479 }
480
481 ret = validator(vldt, &name, member);
482
483 if (ret != NXT_OK) {
484 return ret;
485 }
486 }
487}
488
489
490static nxt_int_t
491nxt_conf_vldt_system(nxt_conf_validation_t *vldt, nxt_conf_value_t *value,
492 void *data)
493{
494 size_t length;
495 nxt_str_t name;
496 nxt_conf_vldt_system_t validator;
497 char string[32];
498
499 /* The cast is required by Sun C. */
500 validator = (nxt_conf_vldt_system_t) data;
501
502 nxt_conf_get_string(value, &name);
503
504 length = name.length + 1;
505 length = nxt_min(length, sizeof(string));
506
507 nxt_cpystrn((u_char *) string, name.start, length);
508
509 return validator(vldt, string);
510}
511
512
513static nxt_int_t
514nxt_conf_vldt_user(nxt_conf_validation_t *vldt, char *user)
515{
516 struct passwd *pwd;
517
518 nxt_errno = 0;
519
520 pwd = getpwnam(user);
521
522 if (pwd != NULL) {
523 return NXT_OK;
524 }
525
526 if (nxt_errno == 0) {
527 return nxt_conf_vldt_error(vldt, "User \"%s\" is not found.", user);
528 }
529
530 return NXT_ERROR;
531}
532
533
534static nxt_int_t
535nxt_conf_vldt_group(nxt_conf_validation_t *vldt, char *group)
536{
537 struct group *grp;
538
539 nxt_errno = 0;
540
541 grp = getgrnam(group);
542
543 if (grp != NULL) {
544 return NXT_OK;
545 }
546
547 if (nxt_errno == 0) {
548 return nxt_conf_vldt_error(vldt, "Group \"%s\" is not found.", group);
549 }
550
551 return NXT_ERROR;
552}
553
554
86 { nxt_string("requests"),
87 NXT_CONF_INTEGER,
88 NULL,
89 NULL },
90
91 { nxt_null_string, 0, NULL, NULL }
92};
93
94
95static nxt_conf_vldt_object_t nxt_conf_vldt_python_members[] = {
96 { nxt_string("type"),
97 NXT_CONF_STRING,
98 NULL,
99 NULL },
100
101 { nxt_string("workers"),
102 NXT_CONF_INTEGER,
103 NULL,
104 NULL },
105
106 { nxt_string("limits"),
107 NXT_CONF_OBJECT,
108 &nxt_conf_vldt_object,
109 (void *) &nxt_conf_vldt_app_limits_members },
110
111 { nxt_string("user"),
112 NXT_CONF_STRING,
113 nxt_conf_vldt_system,
114 (void *) &nxt_conf_vldt_user },
115
116 { nxt_string("group"),
117 NXT_CONF_STRING,
118 nxt_conf_vldt_system,
119 (void *) &nxt_conf_vldt_group },
120
121 { nxt_string("working_directory"),
122 NXT_CONF_STRING,
123 NULL,
124 NULL },
125
126 { nxt_string("home"),
127 NXT_CONF_STRING,
128 NULL,
129 NULL },
130
131 { nxt_string("path"),
132 NXT_CONF_STRING,
133 NULL,
134 NULL },
135
136 { nxt_string("module"),
137 NXT_CONF_STRING,
138 NULL,
139 NULL },
140
141 { nxt_null_string, 0, NULL, NULL }
142};
143
144
145static nxt_conf_vldt_object_t nxt_conf_vldt_php_members[] = {
146 { nxt_string("type"),
147 NXT_CONF_STRING,
148 NULL,
149 NULL },
150
151 { nxt_string("workers"),
152 NXT_CONF_INTEGER,
153 NULL,
154 NULL },
155
156 { nxt_string("limits"),
157 NXT_CONF_OBJECT,
158 &nxt_conf_vldt_object,
159 (void *) &nxt_conf_vldt_app_limits_members },
160
161 { nxt_string("user"),
162 NXT_CONF_STRING,
163 nxt_conf_vldt_system,
164 (void *) &nxt_conf_vldt_user },
165
166 { nxt_string("group"),
167 NXT_CONF_STRING,
168 nxt_conf_vldt_system,
169 (void *) &nxt_conf_vldt_group },
170
171 { nxt_string("working_directory"),
172 NXT_CONF_STRING,
173 NULL,
174 NULL },
175
176 { nxt_string("root"),
177 NXT_CONF_STRING,
178 NULL,
179 NULL },
180
181 { nxt_string("script"),
182 NXT_CONF_STRING,
183 NULL,
184 NULL },
185
186 { nxt_string("index"),
187 NXT_CONF_STRING,
188 NULL,
189 NULL },
190
191 { nxt_null_string, 0, NULL, NULL }
192};
193
194
195static nxt_conf_vldt_object_t nxt_conf_vldt_go_members[] = {
196 { nxt_string("type"),
197 NXT_CONF_STRING,
198 NULL,
199 NULL },
200
201 { nxt_string("workers"),
202 NXT_CONF_INTEGER,
203 NULL,
204 NULL },
205
206 { nxt_string("limits"),
207 NXT_CONF_OBJECT,
208 &nxt_conf_vldt_object,
209 (void *) &nxt_conf_vldt_app_limits_members },
210
211 { nxt_string("user"),
212 NXT_CONF_STRING,
213 nxt_conf_vldt_system,
214 (void *) &nxt_conf_vldt_user },
215
216 { nxt_string("group"),
217 NXT_CONF_STRING,
218 nxt_conf_vldt_system,
219 (void *) &nxt_conf_vldt_group },
220
221 { nxt_string("working_directory"),
222 NXT_CONF_STRING,
223 NULL,
224 NULL },
225
226 { nxt_string("executable"),
227 NXT_CONF_STRING,
228 NULL,
229 NULL },
230
231 { nxt_null_string, 0, NULL, NULL }
232};
233
234
235nxt_int_t
236nxt_conf_validate(nxt_conf_validation_t *vldt)
237{
238 nxt_int_t ret;
239
240 ret = nxt_conf_vldt_type(vldt, NULL, vldt->conf, NXT_CONF_OBJECT);
241
242 if (ret != NXT_OK) {
243 return ret;
244 }
245
246 return nxt_conf_vldt_object(vldt, vldt->conf, nxt_conf_vldt_root_members);
247}
248
249
250static nxt_int_t
251nxt_conf_vldt_type(nxt_conf_validation_t *vldt, nxt_str_t *name,
252 nxt_conf_value_t *value, nxt_conf_type_t type)
253{
254 nxt_uint_t value_type;
255
256 static const char *type_name[] = {
257 "a null",
258 "a boolean",
259 "an integer",
260 "a number",
261 "a string",
262 "an array",
263 "an object"
264 };
265
266 value_type = nxt_conf_type(value);
267
268 if (value_type == type) {
269 return NXT_OK;
270 }
271
272 if (name == NULL) {
273 return nxt_conf_vldt_error(vldt,
274 "The configuration must be %s, not %s.",
275 type_name[type], type_name[value_type]);
276 }
277
278 return nxt_conf_vldt_error(vldt,
279 "The \"%V\" value must be %s, not %s.",
280 name, type_name[type], type_name[value_type]);
281}
282
283
284static nxt_int_t
285nxt_conf_vldt_error(nxt_conf_validation_t *vldt, const char *fmt, ...)
286{
287 u_char *p, *end;
288 size_t size;
289 va_list args;
290 u_char error[NXT_MAX_ERROR_STR];
291
292 va_start(args, fmt);
293 end = nxt_vsprintf(error, error + NXT_MAX_ERROR_STR, fmt, args);
294 va_end(args);
295
296 size = end - error;
297
298 p = nxt_mp_nget(vldt->pool, size);
299 if (p == NULL) {
300 return NXT_ERROR;
301 }
302
303 nxt_memcpy(p, error, size);
304
305 vldt->error.length = size;
306 vldt->error.start = p;
307
308 return NXT_DECLINED;
309}
310
311
312static nxt_int_t
313nxt_conf_vldt_listener(nxt_conf_validation_t *vldt, nxt_str_t *name,
314 nxt_conf_value_t *value)
315{
316 nxt_int_t ret;
317
318 ret = nxt_conf_vldt_type(vldt, name, value, NXT_CONF_OBJECT);
319
320 if (ret != NXT_OK) {
321 return ret;
322 }
323
324 return nxt_conf_vldt_object(vldt, value, nxt_conf_vldt_listener_members);
325}
326
327
328static nxt_int_t
329nxt_conf_vldt_app_name(nxt_conf_validation_t *vldt, nxt_conf_value_t *value,
330 void *data)
331{
332 nxt_str_t name;
333 nxt_conf_value_t *apps, *app;
334
335 static nxt_str_t apps_str = nxt_string("applications");
336
337 nxt_conf_get_string(value, &name);
338
339 apps = nxt_conf_get_object_member(vldt->conf, &apps_str, NULL);
340
341 if (nxt_slow_path(apps == NULL)) {
342 goto error;
343 }
344
345 app = nxt_conf_get_object_member(apps, &name, NULL);
346
347 if (nxt_slow_path(app == NULL)) {
348 goto error;
349 }
350
351 return NXT_OK;
352
353error:
354
355 return nxt_conf_vldt_error(vldt, "Listening socket is assigned for "
356 "a non existing application \"%V\".",
357 &name);
358}
359
360
361static nxt_int_t
362nxt_conf_vldt_app(nxt_conf_validation_t *vldt, nxt_str_t *name,
363 nxt_conf_value_t *value)
364{
365 nxt_int_t ret;
366 nxt_str_t type;
367 nxt_thread_t *thread;
368 nxt_conf_value_t *type_value;
369 nxt_app_lang_module_t *lang;
370
371 static nxt_str_t type_str = nxt_string("type");
372
373 static void *members[] = {
374 nxt_conf_vldt_python_members,
375 nxt_conf_vldt_php_members,
376 nxt_conf_vldt_go_members,
377 };
378
379 ret = nxt_conf_vldt_type(vldt, name, value, NXT_CONF_OBJECT);
380
381 if (ret != NXT_OK) {
382 return ret;
383 }
384
385 type_value = nxt_conf_get_object_member(value, &type_str, NULL);
386
387 if (type_value == NULL) {
388 return nxt_conf_vldt_error(vldt,
389 "Application must have the \"type\" property set.");
390 }
391
392 ret = nxt_conf_vldt_type(vldt, &type_str, type_value, NXT_CONF_STRING);
393
394 if (ret != NXT_OK) {
395 return ret;
396 }
397
398 nxt_conf_get_string(type_value, &type);
399
400 thread = nxt_thread();
401
402 lang = nxt_app_lang_module(thread->runtime, &type);
403 if (lang == NULL) {
404 return nxt_conf_vldt_error(vldt,
405 "The module to run \"%V\" is not found "
406 "among the available application modules.",
407 &type);
408 }
409
410 return nxt_conf_vldt_object(vldt, value, members[lang->type]);
411}
412
413
414static nxt_int_t
415nxt_conf_vldt_object(nxt_conf_validation_t *vldt, nxt_conf_value_t *value,
416 void *data)
417{
418 uint32_t index;
419 nxt_int_t ret;
420 nxt_str_t name;
421 nxt_conf_value_t *member;
422 nxt_conf_vldt_object_t *vals;
423
424 index = 0;
425
426 for ( ;; ) {
427 member = nxt_conf_next_object_member(value, &name, &index);
428
429 if (member == NULL) {
430 return NXT_OK;
431 }
432
433 vals = data;
434
435 for ( ;; ) {
436 if (vals->name.length == 0) {
437 return nxt_conf_vldt_error(vldt, "Unknown parameter \"%V\".",
438 &name);
439 }
440
441 if (!nxt_strstr_eq(&vals->name, &name)) {
442 vals++;
443 continue;
444 }
445
446 ret = nxt_conf_vldt_type(vldt, &name, member, vals->type);
447
448 if (ret != NXT_OK) {
449 return ret;
450 }
451
452 if (vals->validator != NULL) {
453 ret = vals->validator(vldt, member, vals->data);
454
455 if (ret != NXT_OK) {
456 return ret;
457 }
458 }
459
460 break;
461 }
462 }
463}
464
465
466static nxt_int_t
467nxt_conf_vldt_object_iterator(nxt_conf_validation_t *vldt,
468 nxt_conf_value_t *value, void *data)
469{
470 uint32_t index;
471 nxt_int_t ret;
472 nxt_str_t name;
473 nxt_conf_value_t *member;
474 nxt_conf_vldt_member_t validator;
475
476 validator = (nxt_conf_vldt_member_t) data;
477 index = 0;
478
479 for ( ;; ) {
480 member = nxt_conf_next_object_member(value, &name, &index);
481
482 if (member == NULL) {
483 return NXT_OK;
484 }
485
486 ret = validator(vldt, &name, member);
487
488 if (ret != NXT_OK) {
489 return ret;
490 }
491 }
492}
493
494
495static nxt_int_t
496nxt_conf_vldt_system(nxt_conf_validation_t *vldt, nxt_conf_value_t *value,
497 void *data)
498{
499 size_t length;
500 nxt_str_t name;
501 nxt_conf_vldt_system_t validator;
502 char string[32];
503
504 /* The cast is required by Sun C. */
505 validator = (nxt_conf_vldt_system_t) data;
506
507 nxt_conf_get_string(value, &name);
508
509 length = name.length + 1;
510 length = nxt_min(length, sizeof(string));
511
512 nxt_cpystrn((u_char *) string, name.start, length);
513
514 return validator(vldt, string);
515}
516
517
518static nxt_int_t
519nxt_conf_vldt_user(nxt_conf_validation_t *vldt, char *user)
520{
521 struct passwd *pwd;
522
523 nxt_errno = 0;
524
525 pwd = getpwnam(user);
526
527 if (pwd != NULL) {
528 return NXT_OK;
529 }
530
531 if (nxt_errno == 0) {
532 return nxt_conf_vldt_error(vldt, "User \"%s\" is not found.", user);
533 }
534
535 return NXT_ERROR;
536}
537
538
539static nxt_int_t
540nxt_conf_vldt_group(nxt_conf_validation_t *vldt, char *group)
541{
542 struct group *grp;
543
544 nxt_errno = 0;
545
546 grp = getgrnam(group);
547
548 if (grp != NULL) {
549 return NXT_OK;
550 }
551
552 if (nxt_errno == 0) {
553 return nxt_conf_vldt_error(vldt, "Group \"%s\" is not found.", group);
554 }
555
556 return NXT_ERROR;
557}
558
559