diff options
author | Valentin Bartenev <vbart@nginx.com> | 2018-10-09 17:53:31 +0300 |
---|---|---|
committer | Valentin Bartenev <vbart@nginx.com> | 2018-10-09 17:53:31 +0300 |
commit | 029c1a9f509b2af60e02d74ef982fda1346d85e0 (patch) | |
tree | bc4265edcf0620f191393c1faa2a6610c60b1886 /src/nxt_external.c | |
parent | 6c5e5f25ef74dbf4d3dc524e293863fad7fcf524 (diff) | |
download | unit-029c1a9f509b2af60e02d74ef982fda1346d85e0.tar.gz unit-029c1a9f509b2af60e02d74ef982fda1346d85e0.tar.bz2 |
Renamed "go" application type to "external".
There's nothing specific to Go language. This type of application object can
be used to run any external application that utilizes libunit API.
Diffstat (limited to 'src/nxt_external.c')
-rw-r--r-- | src/nxt_external.c | 178 |
1 files changed, 178 insertions, 0 deletions
diff --git a/src/nxt_external.c b/src/nxt_external.c new file mode 100644 index 00000000..c7aacffc --- /dev/null +++ b/src/nxt_external.c @@ -0,0 +1,178 @@ + +/* + * Copyright (C) Max Romanov + * Copyright (C) NGINX, Inc. + */ + +#include <nxt_main.h> +#include <nxt_router.h> +#include <nxt_unit.h> + + +static nxt_int_t nxt_external_init(nxt_task_t *task, + nxt_common_app_conf_t *conf); + + +nxt_app_module_t nxt_external_module = { + 0, + NULL, + nxt_string("external"), + "*", + nxt_external_init, +}; + + +extern char **environ; + + +nxt_inline nxt_int_t +nxt_external_fd_no_cloexec(nxt_task_t *task, nxt_socket_t fd) +{ + int res, flags; + + if (fd == -1) { + return NXT_OK; + } + + flags = fcntl(fd, F_GETFD); + + if (nxt_slow_path(flags == -1)) { + nxt_alert(task, "fcntl(%d, F_GETFD) failed %E", fd, nxt_errno); + return NXT_ERROR; + } + + flags &= ~FD_CLOEXEC; + + res = fcntl(fd, F_SETFD, flags); + + if (nxt_slow_path(res == -1)) { + nxt_alert(task, "fcntl(%d, F_SETFD) failed %E", fd, nxt_errno); + return NXT_ERROR; + } + + nxt_fd_blocking(task, fd); + + return NXT_OK; +} + + +static nxt_int_t +nxt_external_init(nxt_task_t *task, nxt_common_app_conf_t *conf) +{ + 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_external_app_conf_t *c; + + rt = task->thread->runtime; + + main_port = rt->port_by_type[NXT_PROCESS_MAIN]; + my_port = nxt_runtime_port_find(rt, nxt_pid, 0); + + if (nxt_slow_path(main_port == NULL || my_port == NULL)) { + return NXT_ERROR; + } + + rc = nxt_external_fd_no_cloexec(task, main_port->pair[1]); + if (nxt_slow_path(rc != NXT_OK)) { + return NXT_ERROR; + } + + rc = nxt_external_fd_no_cloexec(task, my_port->pair[0]); + if (nxt_slow_path(rc != NXT_OK)) { + return NXT_ERROR; + } + + end = buf + sizeof(buf); + + p = nxt_sprintf(buf, end, + "%s;%uD;" + "%PI,%ud,%d;" + "%PI,%ud,%d;" + "%d,%Z", + NXT_VERSION, my_port->process->init->stream, + main_port->pid, main_port->id, main_port->pair[1], + my_port->pid, my_port->id, my_port->pair[0], + 2); + + if (nxt_slow_path(p == end)) { + nxt_alert(task, "internal error: buffer too small for NXT_UNIT_INIT"); + + return NXT_ERROR; + } + + nxt_debug(task, "update "NXT_UNIT_INIT_ENV"=%s", buf); + + rc = setenv(NXT_UNIT_INIT_ENV, (char *) buf, 1); + if (nxt_slow_path(rc == -1)) { + nxt_alert(task, "setenv("NXT_UNIT_INIT_ENV", %s) failed %E", buf, + nxt_errno); + + return NXT_ERROR; + } + + c = &conf->u.external; + + 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; + 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; +} |