ret_t cherokee_error_errno_log (int errnumber, cherokee_error_type_t type, const char *filename, int line, int error_num, ...) { va_list ap; const char *errstr; char err_tmp[ERROR_MAX_BUFSIZE]; cherokee_buffer_t error_str = CHEROKEE_BUF_INIT; /* Render the error message */ va_start (ap, error_num); render (type, filename, line, error_num, ap, &error_str); va_end (ap); /* Replace ${errno} */ errstr = cherokee_strerror_r (errnumber, err_tmp, sizeof(err_tmp)); if (errstr == NULL) { errstr = "unknwon error (?)"; } cherokee_buffer_replace_string (&error_str, (char *)"${errno}", 8, (char *) errstr, strlen(errstr)); /* Report it */ report_error (&error_str); /* Clean up */ cherokee_buffer_mrproper (&error_str); return ret_ok; }
static NORETURN void manage_child_cgi_process (cherokee_handler_cgi_t *cgi, int pipe_cgi[2], int pipe_server[2]) { /* Child process */ int re; char *script; cherokee_connection_t *conn = HANDLER_CONN(cgi); cherokee_handler_cgi_base_t *cgi_base = HDL_CGI_BASE(cgi); char *absolute_path = cgi_base->executable.buf; char *argv[2] = { NULL, NULL }; #ifdef TRACE_ENABLED TRACE(ENTRIES, "About to execute: '%s'\n", absolute_path); if (! cherokee_buffer_is_empty (&conn->effective_directory)) TRACE(ENTRIES, "Effective directory: '%s'\n", conn->effective_directory.buf); else TRACE(ENTRIES, "No Effective directory %s", "\n"); #endif /* Close useless sides */ cherokee_fd_close (pipe_cgi[0]); cherokee_fd_close (pipe_server[1]); /* Change stdin and out */ re = dup2 (pipe_server[0], STDIN_FILENO); cherokee_fd_close (pipe_server[0]); if (unlikely (re != 0)) { printf ("Status: 500" CRLF_CRLF); printf ("X-Debug: file=%s line=%d" CRLF_CRLF, __FILE__, __LINE__); exit(1); } re |= dup2 (pipe_cgi[1], STDOUT_FILENO); cherokee_fd_close (pipe_cgi[1]); /* Redirect the stderr */ if ((CONN_VSRV(conn)->error_writer != NULL) && (CONN_VSRV(conn)->error_writer->fd != -1)) { dup2 (CONN_VSRV(conn)->error_writer->fd, STDERR_FILENO); } # if 0 /* Set unbuffered */ setvbuf (stdin, NULL, _IONBF, 0); setvbuf (stdout, NULL, _IONBF, 0); # endif /* Enable blocking mode */ _fd_set_properties (STDIN_FILENO, 0, O_NONBLOCK); _fd_set_properties (STDOUT_FILENO, 0, O_NONBLOCK); _fd_set_properties (STDERR_FILENO, 0, O_NONBLOCK); /* Sets the new environ. */ add_environment (cgi, conn); /* Change the directory */ if (! cherokee_buffer_is_empty (&conn->effective_directory)) { re = chdir (conn->effective_directory.buf); } else { char *file = strrchr (absolute_path, '/'); *file = '\0'; re = chdir (absolute_path); *file = '/'; } if (re < 0) { printf ("Status: 500" CRLF_CRLF); printf ("X-Debug: file=%s line=%d" CRLF_CRLF, __FILE__, __LINE__); exit(1); } /* Build de argv array */ script = absolute_path; argv[0] = absolute_path; /* Change the execution user? */ if (HANDLER_CGI_PROPS(cgi_base)->change_user) { struct stat info; re = stat (script, &info); if (re >= 0) { re = setuid (info.st_uid); if (re != 0) { LOG_ERROR (CHEROKEE_ERROR_HANDLER_CGI_SETID, script, info.st_uid); } } } /* Reset the server-wide signal handlers */ #ifdef SIGPIPE signal (SIGPIPE, SIG_DFL); #endif #ifdef SIGHUP signal (SIGHUP, SIG_DFL); #endif #ifdef SIGSEGV signal (SIGSEGV, SIG_DFL); #endif #ifdef SIGBUS signal (SIGBUS, SIG_DFL); #endif #ifdef SIGTERM signal (SIGTERM, SIG_DFL); #endif /* Lets go.. execute it! */ re = execve (absolute_path, argv, cgi->envp); if (re < 0) { int err = errno; char buferr[ERROR_MAX_BUFSIZE]; switch (err) { case ENOENT: printf ("Status: 404" CRLF_CRLF); break; default: printf ("Status: 500" CRLF_CRLF); printf ("X-Debug: file=%s line=%d cmd=%s: %s" CRLF_CRLF, __FILE__, __LINE__, absolute_path, strerror(err)); } /* Don't use the logging system (concurrency issues) */ LOG_ERROR (CHEROKEE_ERROR_HANDLER_CGI_EXECUTE, absolute_path, cherokee_strerror_r(err, buferr, sizeof(buferr))); exit(1); } /* There is no way, it could reach this point. */ SHOULDNT_HAPPEN; exit(2); }
static NORETURN void manage_child_cgi_process (cherokee_handler_cgi_t *cgi, int pipe_cgi[2], int pipe_server[2]) { /* Child process */ int re; cherokee_connection_t *conn = HANDLER_CONN(cgi); cherokee_handler_cgi_base_t *cgi_base = HDL_CGI_BASE(cgi); char *absolute_path = cgi_base->executable.buf; char *argv[2] = { NULL, NULL }; #ifdef TRACE_ENABLED TRACE(ENTRIES, "About to execute: '%s'\n", absolute_path); if (! cherokee_buffer_is_empty (&conn->effective_directory)) TRACE(ENTRIES, "Effective directory: '%s'\n", conn->effective_directory.buf); else TRACE(ENTRIES, "No Effective directory %s", "\n"); #endif /* Close useless sides */ cherokee_fd_close (pipe_cgi[0]); cherokee_fd_close (pipe_server[1]); /* Change stdin and out */ cherokee_fd_close (STDIN_FILENO); re = dup2 (pipe_server[0], STDIN_FILENO); cherokee_fd_close (pipe_server[0]); if (unlikely (re != 0)) { printf ("Status: 500" CRLF_CRLF); printf ("X-Debug: file=%s line=%d" CRLF_CRLF, __FILE__, __LINE__); exit(1); } cherokee_fd_close (STDOUT_FILENO); re |= dup2 (pipe_cgi[1], STDOUT_FILENO); cherokee_fd_close (pipe_cgi[1]); /* Redirect the stderr */ if ((CONN_VSRV(conn)->error_writer != NULL) && (CONN_VSRV(conn)->error_writer->fd != -1)) { cherokee_fd_close (STDERR_FILENO); dup2 (CONN_VSRV(conn)->error_writer->fd, STDERR_FILENO); } # if 0 /* Set unbuffered */ setvbuf (stdin, NULL, _IONBF, 0); setvbuf (stdout, NULL, _IONBF, 0); # endif /* Enable blocking mode */ _fd_set_properties (STDIN_FILENO, 0, O_NONBLOCK); _fd_set_properties (STDOUT_FILENO, 0, O_NONBLOCK); _fd_set_properties (STDERR_FILENO, 0, O_NONBLOCK); /* Sets the new environ. */ add_environment (cgi, conn); /* Change the directory */ if (! cherokee_buffer_is_empty (&conn->effective_directory)) { re = chdir (conn->effective_directory.buf); } else { char *file = strrchr (absolute_path, '/'); if (file != NULL) { *file = '\0'; re = chdir (absolute_path); *file = '/'; } else { re = -1; } } if (re < 0) { printf ("Status: 500" CRLF_CRLF); printf ("X-Debug: file=%s line=%d" CRLF_CRLF, __FILE__, __LINE__); exit(1); } /* Build de argv array */ argv[0] = absolute_path; /* Change the execution user? */ if (HANDLER_CGI_PROPS(cgi_base)->change_user) { struct stat nocache_info; struct stat *info; cherokee_iocache_entry_t *io_entry = NULL; cherokee_server_t *srv = CONN_SRV(conn); cherokee_handler_cgi_base_props_t *props = HANDLER_CGI_BASE_PROPS(cgi); ret_t ret = cherokee_io_stat (srv->iocache, &cgi_base->executable, props->use_cache, &nocache_info, &io_entry, &info); if (ret != ret_ok) { info = &nocache_info; } re = setuid (info->st_uid); if (re != 0) { LOG_ERROR (CHEROKEE_ERROR_HANDLER_CGI_SETID, absolute_path, info->st_uid); } cherokee_iocache_entry_unref(&io_entry); } /* Reset the server-wide signal handlers */ cherokee_reset_signals(); /* Lets go.. execute it! */ do { re = execve (absolute_path, argv, cgi->envp); } while ((re == -1) && (errno == EINTR)); if (re < 0) { int err = errno; char buferr[ERROR_MAX_BUFSIZE]; switch (err) { case ENODEV: case ENOTDIR: case ENOENT: printf ("Status: 404" CRLF_CRLF); exit(0); case EPERM: case EACCES: case ENOEXEC: printf ("Status: 403" CRLF_CRLF); exit(0); default: printf ("Status: 500" CRLF_CRLF); printf ("X-Debug: file=%s line=%d cmd=%s errno=%d: %s" CRLF_CRLF, __FILE__, __LINE__, absolute_path, err, strerror(err)); } /* Don't use the logging system (concurrency issues) */ LOG_ERROR (CHEROKEE_ERROR_HANDLER_CGI_EXECUTE, absolute_path, cherokee_strerror_r(err, buferr, sizeof(buferr))); exit(1); } /* There is no way, it could reach this point. */ SHOULDNT_HAPPEN; exit(2); }