static int create_spawnproc(h2o_configurator_command_t *cmd, yoml_t *node, const char *dirname, char *const *argv, struct sockaddr_un *sa) { int listen_fd, pipe_fds[2] = {-1, -1}; /* build socket path */ sa->sun_family = AF_UNIX; strcpy(sa->sun_path, dirname); strcat(sa->sun_path, "/_"); /* create socket */ if ((listen_fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) { h2o_configurator_errprintf(cmd, node, "socket(2) failed: %s", strerror(errno)); goto Error; } if (bind(listen_fd, (void *)sa, sizeof(*sa)) != 0) { h2o_configurator_errprintf(cmd, node, "bind(2) failed: %s", strerror(errno)); goto Error; } if (listen(listen_fd, SOMAXCONN) != 0) { h2o_configurator_errprintf(cmd, node, "listen(2) failed: %s", strerror(errno)); goto Error; } /* create pipe which is used to notify the termination of the server */ if (pipe(pipe_fds) != 0) { h2o_configurator_errprintf(cmd, node, "pipe(2) failed: %s", strerror(errno)); pipe_fds[0] = -1; pipe_fds[1] = -1; goto Error; } fcntl(pipe_fds[1], F_SETFD, FD_CLOEXEC); /* spawn */ int mapped_fds[] = {listen_fd, 0, /* listen_fd to 0 */ pipe_fds[0], 5, /* pipe_fds[0] to 5 */ -1}; pid_t pid = h2o_spawnp(argv[0], argv, mapped_fds, 0); if (pid == -1) { fprintf(stderr, "[lib/handler/fastcgi.c] failed to launch helper program %s:%s\n", argv[0], strerror(errno)); goto Error; } close(listen_fd); listen_fd = -1; close(pipe_fds[0]); pipe_fds[0] = -1; return pipe_fds[1]; Error: if (pipe_fds[0] != -1) close(pipe_fds[0]); if (pipe_fds[1]) close(pipe_fds[1]); if (listen_fd != -1) close(listen_fd); unlink(sa->sun_path); return -1; }
int h2o_read_command(const char *cmd, char **argv, h2o_buffer_t **resp, int *child_status) { int respfds[2] = {-1, -1}; pid_t pid = -1; int mutex_locked = 0, ret = -1; h2o_buffer_init(resp, &h2o_socket_buffer_prototype); pthread_mutex_lock(&cloexec_mutex); mutex_locked = 1; /* create pipe for reading the result */ if (pipe(respfds) != 0) goto Exit; fcntl(respfds[0], F_SETFD, O_CLOEXEC); /* spawn */ int mapped_fds[] = {respfds[1], 1, /* stdout of the child process is read from the pipe */ -1}; if ((pid = h2o_spawnp(cmd, argv, mapped_fds, 1)) == -1) goto Exit; close(respfds[1]); respfds[1] = -1; pthread_mutex_unlock(&cloexec_mutex); mutex_locked = 0; /* read the response from pipe */ while (1) { h2o_iovec_t buf = h2o_buffer_reserve(resp, 8192); ssize_t r; while ((r = read(respfds[0], buf.base, buf.len)) == -1 && errno == EINTR) ; if (r <= 0) break; (*resp)->size += r; } Exit: if (mutex_locked) pthread_mutex_unlock(&cloexec_mutex); if (pid != -1) { /* wait for the child to complete */ pid_t r; while ((r = waitpid(pid, child_status, 0)) == -1 && errno == EINTR) ; if (r == pid) { /* success */ ret = 0; } } if (respfds[0] != -1) close(respfds[0]); if (respfds[1] != -1) close(respfds[1]); if (ret != 0) h2o_buffer_dispose(resp); return ret; }
int h2o_access_log_open_log(const char *path) { int fd; if (path[0] == '|') { int pipefds[2]; pid_t pid; char *argv[4] = {"/bin/sh", "-c", (char *)(path + 1), NULL}; /* create pipe */ if (pipe(pipefds) != 0) { perror("pipe failed"); return -1; } if (fcntl(pipefds[1], F_SETFD, FD_CLOEXEC) == -1) { perror("failed to set FD_CLOEXEC on pipefds[1]"); return -1; } /* spawn the logger */ int mapped_fds[] = {pipefds[0], 0, /* map pipefds[0] to stdin */ pipefds[0], -1, /* close pipefds[0] before exec */ -1}; if ((pid = h2o_spawnp(argv[0], argv, mapped_fds, 0)) == -1) { fprintf(stderr, "failed to open logger: %s:%s\n", path + 1, strerror(errno)); return -1; } /* close the read side of the pipefds and return the write side */ close(pipefds[0]); fd = pipefds[1]; } else { if ((fd = open(path, O_CREAT | O_WRONLY | O_APPEND | O_CLOEXEC, 0644)) == -1) { fprintf(stderr, "failed to open log file:%s:%s\n", path, strerror(errno)); return -1; } } return fd; }
int h2o_read_command(const char *cmd, char **argv, h2o_buffer_t **resp, int *child_status) { int respfds[2] = {-1, -1}; pid_t pid = -1; int mutex_locked = 0, ret = -1; h2o_buffer_init(resp, &h2o_socket_buffer_prototype); #ifndef _MSC_VER pthread_mutex_lock(&cloexec_mutex); mutex_locked = 1; #else uv_mutex_lock(&cloexec_mutex); mutex_locked = 1; #endif /* create pipe for reading the result */ #ifdef _MSC_VER if (_pipe(respfds, 4096, O_BINARY) == -1) //on fail //-- : Debug{ //printf("Pipe Failed \n"); goto Exit; #else if (pipe(respfds) != 0) //on fail goto Exit; #endif #ifndef _MSC_VER fcntl(respfds[0], F_SETFD, O_CLOEXEC); #endif /* spawn */ int mapped_fds[] = {respfds[1], 1, /* stdout of the child process is read from the pipe */ -1}; if ((pid = h2o_spawnp(cmd, argv, mapped_fds, 1)) == -1) goto Exit; close(respfds[1]); respfds[1] = -1; #ifndef _MSC_VER pthread_mutex_unlock(&cloexec_mutex); #else uv_mutex_unlock(&cloexec_mutex); #endif mutex_locked = 0; /* read the response from pipe */ while (1) { h2o_iovec_t buf = h2o_buffer_reserve(resp, 8192); ssize_t r; #ifndef _MSC_VER while ((r = read(respfds[0], buf.base, buf.len)) == -1 && errno == EINTR) ; #else while ((r = _read(respfds[0], buf.base, buf.len)) == -1 && errno == EINTR) ; #endif if (r <= 0) break; (*resp)->size += r; } Exit: if (mutex_locked) #ifndef _MSC_VER pthread_mutex_unlock(&cloexec_mutex); #else uv_mutex_unlock(&cloexec_mutex); #endif //Child _ waiting doesn't work same way in Windows so #ifndef _MSC_VER if (pid != -1) { /* wait for the child to complete */ pid_t r; while ((r = waitpid(pid, child_status, 0)) == -1 && errno == EINTR) ; if (r == pid) { /* success */ ret = 0; } } #else //If you can come up with a way to wait for a child to exist in Windows put here.s #endif #ifndef _MSC_VER if (respfds[0] != -1) close(respfds[0]); if (respfds[1] != -1) close(respfds[1]); #else if (respfds[0] != -1) _close(respfds[0]); if (respfds[1] != -1) _close(respfds[1]); #endif if (ret != 0) h2o_buffer_dispose(resp); return ret; }
int h2o_access_log_open_log(const char *path) { int fd; if (path[0] == '|') { int pipefds[2]; pid_t pid; char *argv[4] = {"/bin/sh", "-c", (char *)(path + 1), NULL}; /* create pipe */ #ifndef _MSC_VER if (pipe(pipefds) != 0) { perror("pipe failed"); return -1; } #else if (_pipe(pipefds,4096,O_BINARY) == -1) { perror("pipe failed"); return -1; } #endif #ifndef _MSC_VER if (fcntl(pipefds[1], F_SETFD, FD_CLOEXEC) == -1) { perror("failed to set FD_CLOEXEC on pipefds[1]"); return -1; } #endif /* spawn the logger */ int mapped_fds[] = {pipefds[0], 0, /* map pipefds[0] to stdin */ -1}; if ((pid = h2o_spawnp(argv[0], argv, mapped_fds, 0)) == -1) { fprintf(stderr, "failed to open logger: %s:%s\n", path + 1, strerror(errno)); return -1; } /* close the read side of the pipefds and return the write side */ close(pipefds[0]); fd = pipefds[1]; } else { #ifndef _MSC_VER if ((fd = open(path, O_CREAT | O_WRONLY | O_APPEND | O_CLOEXEC, 0644)) == -1) { //(owning) User: read & write //*Group: read //* Other : read #else if ((fd = _open(path, O_CREAT | O_WRONLY | O_APPEND, _O_RDWR)) == -1) { #endif fprintf(stderr, "failed to open log file:%s:%s\n", path, strerror(errno)); return -1; } } return fd; } h2o_access_log_filehandle_t *h2o_access_log_open_handle(const char *path, const char *fmt) { h2o_logconf_t *logconf; int fd; h2o_access_log_filehandle_t *fh; char errbuf[256]; /* default to combined log format */ if (fmt == NULL) fmt = "%h %l %u %t \"%r\" %s %b \"%{Referer}i\" \"%{User-agent}i\""; if ((logconf = h2o_logconf_compile(fmt, H2O_LOGCONF_ESCAPE_APACHE, errbuf)) == NULL) { fprintf(stderr, "%s\n", errbuf); return NULL; } /* open log file */ if ((fd = h2o_access_log_open_log(path)) == -1) { h2o_logconf_dispose(logconf); return NULL; } fh = h2o_mem_alloc_shared(NULL, sizeof(*fh), on_dispose_handle); fh->logconf = logconf; fh->fd = fd; return fh; }