From ceeb30188152426d76eac1f40ca8ceb24ddb5d0a Mon Sep 17 00:00:00 2001 From: Valentin Bartenev Date: Wed, 6 Jun 2018 16:53:35 +0300 Subject: Go: specifying command line arguments to the executable. This closes #110 issue on GitHub. --- src/nxt_application.h | 3 ++- src/nxt_conf_validation.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++- src/nxt_go.c | 55 +++++++++++++++++++++++++++++++++++++++++-- src/nxt_main_process.c | 7 ++++++ 4 files changed, 121 insertions(+), 4 deletions(-) diff --git a/src/nxt_application.h b/src/nxt_application.h index 6ac7fbd3..96af1d67 100644 --- a/src/nxt_application.h +++ b/src/nxt_application.h @@ -53,7 +53,8 @@ typedef struct { typedef struct { - char *executable; + char *executable; + nxt_conf_value_t *arguments; } nxt_go_app_conf_t; diff --git a/src/nxt_conf_validation.c b/src/nxt_conf_validation.c index f31f3f15..cd5b576f 100644 --- a/src/nxt_conf_validation.c +++ b/src/nxt_conf_validation.c @@ -36,7 +36,8 @@ typedef struct { typedef nxt_int_t (*nxt_conf_vldt_member_t)(nxt_conf_validation_t *vldt, nxt_str_t *name, nxt_conf_value_t *value); - +typedef nxt_int_t (*nxt_conf_vldt_element_t)(nxt_conf_validation_t *vldt, + nxt_conf_value_t *value); typedef nxt_int_t (*nxt_conf_vldt_system_t)(nxt_conf_validation_t *vldt, char *name); @@ -58,12 +59,16 @@ static nxt_int_t nxt_conf_vldt_processes(nxt_conf_validation_t *vldt, nxt_conf_value_t *value, void *data); static nxt_int_t nxt_conf_vldt_object_iterator(nxt_conf_validation_t *vldt, nxt_conf_value_t *value, void *data); +static nxt_int_t nxt_conf_vldt_array_iterator(nxt_conf_validation_t *vldt, + nxt_conf_value_t *value, void *data); static nxt_int_t nxt_conf_vldt_system(nxt_conf_validation_t *vldt, nxt_conf_value_t *value, void *data); static nxt_int_t nxt_conf_vldt_user(nxt_conf_validation_t *vldt, char *name); static nxt_int_t nxt_conf_vldt_group(nxt_conf_validation_t *vldt, char *name); static nxt_int_t nxt_conf_vldt_environment(nxt_conf_validation_t *vldt, nxt_str_t *name, nxt_conf_value_t *value); +static nxt_int_t nxt_conf_vldt_argument(nxt_conf_validation_t *vldt, + nxt_conf_value_t *value); static nxt_conf_vldt_object_t nxt_conf_vldt_root_members[] = { @@ -222,6 +227,11 @@ static nxt_conf_vldt_object_t nxt_conf_vldt_go_members[] = { NULL, NULL }, + { nxt_string("arguments"), + NXT_CONF_VLDT_ARRAY, + &nxt_conf_vldt_array_iterator, + (void *) &nxt_conf_vldt_argument }, + NXT_CONF_VLDT_NEXT(&nxt_conf_vldt_common_members) }; @@ -668,6 +678,33 @@ nxt_conf_vldt_object_iterator(nxt_conf_validation_t *vldt, } +static nxt_int_t +nxt_conf_vldt_array_iterator(nxt_conf_validation_t *vldt, + nxt_conf_value_t *value, void *data) +{ + uint32_t index; + nxt_int_t ret; + nxt_conf_value_t *element; + nxt_conf_vldt_element_t validator; + + validator = (nxt_conf_vldt_element_t) data; + + for (index = 0; /* void */ ; index++) { + element = nxt_conf_get_array_element(value, index); + + if (element == NULL) { + return NXT_OK; + } + + ret = validator(vldt, element); + + if (ret != NXT_OK) { + return ret; + } + } +} + + static nxt_int_t nxt_conf_vldt_system(nxt_conf_validation_t *vldt, nxt_conf_value_t *value, void *data) @@ -768,3 +805,24 @@ nxt_conf_vldt_environment(nxt_conf_validation_t *vldt, nxt_str_t *name, return NXT_OK; } + + +static nxt_int_t +nxt_conf_vldt_argument(nxt_conf_validation_t *vldt, nxt_conf_value_t *value) +{ + nxt_str_t str; + + if (nxt_conf_type(value) != NXT_CONF_STRING) { + return nxt_conf_vldt_error(vldt, "The \"arguments\" array " + "must contain only string values."); + } + + nxt_conf_get_string(value, &str); + + if (nxt_memchr(str.start, '\0', str.length) != NULL) { + return nxt_conf_vldt_error(vldt, "The \"arguments\" array must not " + "contain strings with null character."); + } + + return NXT_OK; +} diff --git a/src/nxt_go.c b/src/nxt_go.c index edcd5eff..67a5afb6 100644 --- a/src/nxt_go.c +++ b/src/nxt_go.c @@ -58,12 +58,17 @@ nxt_go_fd_no_cloexec(nxt_task_t *task, nxt_socket_t fd) static nxt_int_t nxt_go_init(nxt_task_t *task, nxt_common_app_conf_t *conf) { - char *argv[2]; + char **argv; u_char buf[256]; u_char *p, *end; + uint32_t index; + size_t size; + nxt_str_t str; nxt_int_t rc; + nxt_uint_t i, argc; nxt_port_t *my_port, *main_port; nxt_runtime_t *rt; + nxt_conf_value_t *value; nxt_go_app_conf_t *c; rt = task->thread->runtime; @@ -114,13 +119,59 @@ nxt_go_init(nxt_task_t *task, nxt_common_app_conf_t *conf) c = &conf->u.go; + argc = 2; + size = 0; + + if (c->arguments != NULL) { + + for (index = 0; /* void */ ; index++) { + value = nxt_conf_get_array_element(c->arguments, index); + if (value == NULL) { + break; + } + + nxt_conf_get_string(value, &str); + + size += str.length + 1; + argc++; + } + } + + argv = nxt_malloc(argc * sizeof(argv[0]) + size); + if (nxt_slow_path(argv == NULL)) { + nxt_alert(task, "failed to allocate arguments"); + return NXT_ERROR; + } + argv[0] = c->executable; - argv[1] = NULL; + i = 1; + + if (c->arguments != NULL) { + p = (u_char *) &argv[argc]; + + for (index = 0; /* void */ ; index++) { + value = nxt_conf_get_array_element(c->arguments, index); + if (value == NULL) { + break; + } + + argv[i++] = (char *) p; + + nxt_conf_get_string(value, &str); + + p = nxt_cpymem(p, str.start, str.length); + *p++ = '\0'; + } + } + + argv[i] = NULL; (void) execve(c->executable, argv, environ); nxt_alert(task, "execve(%s) failed %E", c->executable, nxt_errno); + nxt_free(argv); + return NXT_ERROR; } diff --git a/src/nxt_main_process.c b/src/nxt_main_process.c index b5037635..032c05cd 100644 --- a/src/nxt_main_process.c +++ b/src/nxt_main_process.c @@ -178,6 +178,13 @@ static nxt_conf_map_t nxt_go_app_conf[] = { NXT_CONF_MAP_CSTRZ, offsetof(nxt_common_app_conf_t, u.go.executable), }, + + { + nxt_string("arguments"), + NXT_CONF_MAP_PTR, + offsetof(nxt_common_app_conf_t, u.go.arguments), + }, + }; -- cgit