summaryrefslogtreecommitdiffhomepage
path: root/src/nxt_external.c
diff options
context:
space:
mode:
authorValentin Bartenev <vbart@nginx.com>2018-10-09 17:53:31 +0300
committerValentin Bartenev <vbart@nginx.com>2018-10-09 17:53:31 +0300
commit029c1a9f509b2af60e02d74ef982fda1346d85e0 (patch)
treebc4265edcf0620f191393c1faa2a6610c60b1886 /src/nxt_external.c
parent6c5e5f25ef74dbf4d3dc524e293863fad7fcf524 (diff)
downloadunit-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.c178
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;
+}