1804Svbart@nginx.com 2804Svbart@nginx.com /* 3804Svbart@nginx.com * Copyright (C) Max Romanov 4804Svbart@nginx.com * Copyright (C) NGINX, Inc. 5804Svbart@nginx.com */ 6804Svbart@nginx.com 7804Svbart@nginx.com #include <nxt_main.h> 8804Svbart@nginx.com #include <nxt_router.h> 9804Svbart@nginx.com #include <nxt_unit.h> 10804Svbart@nginx.com 11804Svbart@nginx.com 121488St.nateldemoura@f5.com static nxt_int_t nxt_external_start(nxt_task_t *task, nxt_process_data_t *data); 13804Svbart@nginx.com 14804Svbart@nginx.com 15804Svbart@nginx.com nxt_app_module_t nxt_external_module = { 16804Svbart@nginx.com 0, 17804Svbart@nginx.com NULL, 18804Svbart@nginx.com nxt_string("external"), 19804Svbart@nginx.com "*", 20977Smax.romanov@gmail.com NULL, 211489St.nateldemoura@f5.com 0, 221489St.nateldemoura@f5.com NULL, 231488St.nateldemoura@f5.com nxt_external_start, 24804Svbart@nginx.com }; 25804Svbart@nginx.com 26804Svbart@nginx.com 27804Svbart@nginx.com extern char **environ; 28804Svbart@nginx.com 29804Svbart@nginx.com 30804Svbart@nginx.com nxt_inline nxt_int_t 31804Svbart@nginx.com nxt_external_fd_no_cloexec(nxt_task_t *task, nxt_socket_t fd) 32804Svbart@nginx.com { 33804Svbart@nginx.com int res, flags; 34804Svbart@nginx.com 35804Svbart@nginx.com if (fd == -1) { 36804Svbart@nginx.com return NXT_OK; 37804Svbart@nginx.com } 38804Svbart@nginx.com 39804Svbart@nginx.com flags = fcntl(fd, F_GETFD); 40804Svbart@nginx.com 41804Svbart@nginx.com if (nxt_slow_path(flags == -1)) { 42804Svbart@nginx.com nxt_alert(task, "fcntl(%d, F_GETFD) failed %E", fd, nxt_errno); 43804Svbart@nginx.com return NXT_ERROR; 44804Svbart@nginx.com } 45804Svbart@nginx.com 46804Svbart@nginx.com flags &= ~FD_CLOEXEC; 47804Svbart@nginx.com 48804Svbart@nginx.com res = fcntl(fd, F_SETFD, flags); 49804Svbart@nginx.com 50804Svbart@nginx.com if (nxt_slow_path(res == -1)) { 51804Svbart@nginx.com nxt_alert(task, "fcntl(%d, F_SETFD) failed %E", fd, nxt_errno); 52804Svbart@nginx.com return NXT_ERROR; 53804Svbart@nginx.com } 54804Svbart@nginx.com 55804Svbart@nginx.com return NXT_OK; 56804Svbart@nginx.com } 57804Svbart@nginx.com 58804Svbart@nginx.com 59804Svbart@nginx.com static nxt_int_t 601488St.nateldemoura@f5.com nxt_external_start(nxt_task_t *task, nxt_process_data_t *data) 61804Svbart@nginx.com { 62804Svbart@nginx.com char **argv; 63804Svbart@nginx.com u_char buf[256]; 64804Svbart@nginx.com u_char *p, *end; 65804Svbart@nginx.com uint32_t index; 66804Svbart@nginx.com size_t size; 67804Svbart@nginx.com nxt_str_t str; 68804Svbart@nginx.com nxt_int_t rc; 69804Svbart@nginx.com nxt_uint_t i, argc; 70*1998St.nateldemoura@f5.com nxt_port_t *my_port, *proto_port, *router_port; 71804Svbart@nginx.com nxt_runtime_t *rt; 72804Svbart@nginx.com nxt_conf_value_t *value; 731488St.nateldemoura@f5.com nxt_common_app_conf_t *conf; 74804Svbart@nginx.com nxt_external_app_conf_t *c; 75804Svbart@nginx.com 76804Svbart@nginx.com rt = task->thread->runtime; 771488St.nateldemoura@f5.com conf = data->app; 78804Svbart@nginx.com 79*1998St.nateldemoura@f5.com proto_port = rt->port_by_type[NXT_PROCESS_PROTOTYPE]; 801543Smax.romanov@nginx.com router_port = rt->port_by_type[NXT_PROCESS_ROUTER]; 81804Svbart@nginx.com my_port = nxt_runtime_port_find(rt, nxt_pid, 0); 82804Svbart@nginx.com 83*1998St.nateldemoura@f5.com if (nxt_slow_path(proto_port == NULL || my_port == NULL 841543Smax.romanov@nginx.com || router_port == NULL)) 851543Smax.romanov@nginx.com { 86804Svbart@nginx.com return NXT_ERROR; 87804Svbart@nginx.com } 88804Svbart@nginx.com 89*1998St.nateldemoura@f5.com rc = nxt_external_fd_no_cloexec(task, proto_port->pair[1]); 90804Svbart@nginx.com if (nxt_slow_path(rc != NXT_OK)) { 91804Svbart@nginx.com return NXT_ERROR; 92804Svbart@nginx.com } 93804Svbart@nginx.com 941543Smax.romanov@nginx.com rc = nxt_external_fd_no_cloexec(task, router_port->pair[1]); 951543Smax.romanov@nginx.com if (nxt_slow_path(rc != NXT_OK)) { 961543Smax.romanov@nginx.com return NXT_ERROR; 971543Smax.romanov@nginx.com } 981543Smax.romanov@nginx.com 99804Svbart@nginx.com rc = nxt_external_fd_no_cloexec(task, my_port->pair[0]); 100804Svbart@nginx.com if (nxt_slow_path(rc != NXT_OK)) { 101804Svbart@nginx.com return NXT_ERROR; 102804Svbart@nginx.com } 103804Svbart@nginx.com 1041668Smax.romanov@nginx.com rc = nxt_external_fd_no_cloexec(task, my_port->pair[1]); 1051668Smax.romanov@nginx.com if (nxt_slow_path(rc != NXT_OK)) { 1061668Smax.romanov@nginx.com return NXT_ERROR; 1071668Smax.romanov@nginx.com } 1081668Smax.romanov@nginx.com 109804Svbart@nginx.com end = buf + sizeof(buf); 110804Svbart@nginx.com 111804Svbart@nginx.com p = nxt_sprintf(buf, end, 112804Svbart@nginx.com "%s;%uD;" 113804Svbart@nginx.com "%PI,%ud,%d;" 114804Svbart@nginx.com "%PI,%ud,%d;" 1151668Smax.romanov@nginx.com "%PI,%ud,%d,%d;" 1161980Smax.romanov@nginx.com "%d,%z,%uD,%Z", 1171488St.nateldemoura@f5.com NXT_VERSION, my_port->process->stream, 118*1998St.nateldemoura@f5.com proto_port->pid, proto_port->id, proto_port->pair[1], 1191543Smax.romanov@nginx.com router_port->pid, router_port->id, router_port->pair[1], 120804Svbart@nginx.com my_port->pid, my_port->id, my_port->pair[0], 1211668Smax.romanov@nginx.com my_port->pair[1], 1221980Smax.romanov@nginx.com 2, conf->shm_limit, conf->request_limit); 123804Svbart@nginx.com 124804Svbart@nginx.com if (nxt_slow_path(p == end)) { 125804Svbart@nginx.com nxt_alert(task, "internal error: buffer too small for NXT_UNIT_INIT"); 126804Svbart@nginx.com 127804Svbart@nginx.com return NXT_ERROR; 128804Svbart@nginx.com } 129804Svbart@nginx.com 130804Svbart@nginx.com nxt_debug(task, "update "NXT_UNIT_INIT_ENV"=%s", buf); 131804Svbart@nginx.com 132804Svbart@nginx.com rc = setenv(NXT_UNIT_INIT_ENV, (char *) buf, 1); 133804Svbart@nginx.com if (nxt_slow_path(rc == -1)) { 134804Svbart@nginx.com nxt_alert(task, "setenv("NXT_UNIT_INIT_ENV", %s) failed %E", buf, 135804Svbart@nginx.com nxt_errno); 136804Svbart@nginx.com 137804Svbart@nginx.com return NXT_ERROR; 138804Svbart@nginx.com } 139804Svbart@nginx.com 140804Svbart@nginx.com c = &conf->u.external; 141804Svbart@nginx.com 142804Svbart@nginx.com argc = 2; 143804Svbart@nginx.com size = 0; 144804Svbart@nginx.com 145804Svbart@nginx.com if (c->arguments != NULL) { 146804Svbart@nginx.com 147804Svbart@nginx.com for (index = 0; /* void */ ; index++) { 148804Svbart@nginx.com value = nxt_conf_get_array_element(c->arguments, index); 149804Svbart@nginx.com if (value == NULL) { 150804Svbart@nginx.com break; 151804Svbart@nginx.com } 152804Svbart@nginx.com 153804Svbart@nginx.com nxt_conf_get_string(value, &str); 154804Svbart@nginx.com 155804Svbart@nginx.com size += str.length + 1; 156804Svbart@nginx.com argc++; 157804Svbart@nginx.com } 158804Svbart@nginx.com } 159804Svbart@nginx.com 160804Svbart@nginx.com argv = nxt_malloc(argc * sizeof(argv[0]) + size); 161804Svbart@nginx.com if (nxt_slow_path(argv == NULL)) { 162804Svbart@nginx.com nxt_alert(task, "failed to allocate arguments"); 163804Svbart@nginx.com return NXT_ERROR; 164804Svbart@nginx.com } 165804Svbart@nginx.com 166804Svbart@nginx.com argv[0] = c->executable; 167804Svbart@nginx.com i = 1; 168804Svbart@nginx.com 169804Svbart@nginx.com if (c->arguments != NULL) { 170804Svbart@nginx.com p = (u_char *) &argv[argc]; 171804Svbart@nginx.com 172804Svbart@nginx.com for (index = 0; /* void */ ; index++) { 173804Svbart@nginx.com value = nxt_conf_get_array_element(c->arguments, index); 174804Svbart@nginx.com if (value == NULL) { 175804Svbart@nginx.com break; 176804Svbart@nginx.com } 177804Svbart@nginx.com 178804Svbart@nginx.com argv[i++] = (char *) p; 179804Svbart@nginx.com 180804Svbart@nginx.com nxt_conf_get_string(value, &str); 181804Svbart@nginx.com 182804Svbart@nginx.com p = nxt_cpymem(p, str.start, str.length); 183804Svbart@nginx.com *p++ = '\0'; 184804Svbart@nginx.com } 185804Svbart@nginx.com } 186804Svbart@nginx.com 187804Svbart@nginx.com argv[i] = NULL; 188804Svbart@nginx.com 189804Svbart@nginx.com (void) execve(c->executable, argv, environ); 190804Svbart@nginx.com 191804Svbart@nginx.com nxt_alert(task, "execve(%s) failed %E", c->executable, nxt_errno); 192804Svbart@nginx.com 193804Svbart@nginx.com nxt_free(argv); 194804Svbart@nginx.com 195804Svbart@nginx.com return NXT_ERROR; 196804Svbart@nginx.com } 197