static ret_t remove_old_socket (const char *path) { int re; struct stat info; /* It might not exist */ re = cherokee_stat (path, &info); if (re != 0) { return ret_ok; } /* If exist, it must be a socket */ if (! S_ISSOCK(info.st_mode)) { PRINT_MSG ("ERROR: Something happens; '%s' isn't a socket.\n", path); return ret_error; } /* Remove it */ re = unlink (path); if (re != 0) { PRINT_MSG ("ERROR: Couldn't remove unix socket '%s'.\n", path); return ret_error; } return ret_ok; }
ret_t cherokee_buffer_read_file (cherokee_buffer_t *buf, char *filename) { int r, f; ret_t ret; struct stat info; /* Stat() the file */ r = cherokee_stat (filename, &info); if (r != 0) return ret_error; /* Is a regular file? */ if (S_ISREG(info.st_mode) == 0) return ret_error; /* Maybe get memory */ ret = cherokee_buffer_ensure_size (buf, buf->len + info.st_size + 1); if (unlikely (ret != ret_ok)) return ret; /* Open the file */ f = cherokee_open (filename, O_RDONLY | O_BINARY, 0); if (f < 0) { LOG_ERRNO(errno, cherokee_err_error, CHEROKEE_ERROR_BUFFER_OPEN_FILE, filename); return ret_error; } cherokee_fd_set_closexec (f); /* Read the content */ r = read (f, buf->buf + buf->len, info.st_size); if (r < 0) { buf->buf[buf->len] = '\0'; cherokee_fd_close(f); return ret_error; } /* Close it and exit */ cherokee_fd_close(f); buf->len += r; buf->buf[buf->len] = '\0'; return ret_ok; }
static ret_t cherokee_bind_local (cherokee_socket_t *sock, cherokee_buffer_t *listen_to) { #ifdef HAVE_SOCKADDR_UN int re; struct stat buf; /* Sanity check */ if ((listen_to->len <= 0) || (listen_to->len >= sizeof(SOCKET_SUN_PATH(sock)))) return ret_error; /* Remove the socket if it already exists */ re = cherokee_stat (listen_to->buf, &buf); if (re == 0) { if (! S_ISSOCK(buf.st_mode)) { LOG_CRITICAL (CHEROKEE_ERROR_SOCKET_NO_SOCKET, listen_to->buf); return ret_error; } re = cherokee_unlink (listen_to->buf); if (re != 0) { LOG_ERRNO (errno, cherokee_err_error, CHEROKEE_ERROR_SOCKET_REMOVE, listen_to->buf); return ret_error; } } /* Create the socket */ memcpy (SOCKET_SUN_PATH(sock), listen_to->buf, listen_to->len + 1); sock->client_addr_len = sizeof(SOCKET_ADDR_UNIX(sock)->sun_family) + listen_to->len; re = bind (SOCKET_FD(sock), (const struct sockaddr *)SOCKET_ADDR_UNIX(sock), sock->client_addr_len); if (re != 0) return ret_error; return ret_ok; #else return ret_no_sys; #endif }
static ret_t init (cherokee_handler_ssi_t *hdl, cherokee_buffer_t *local_path) { int re; ret_t ret; cherokee_connection_t *conn = HANDLER_CONN(hdl); /* Stat the file */ re = cherokee_stat (local_path->buf, &hdl->cache_info); if (re < 0) { switch (errno) { case ENOENT: conn->error_code = http_not_found; break; case EACCES: conn->error_code = http_access_denied; break; default: conn->error_code = http_internal_error; } return ret_error; } /* Read the file */ ret = cherokee_buffer_read_file (&hdl->source, local_path->buf); if (ret != ret_ok) return ret_error; /* Render */ ret = parse (hdl, &hdl->source, &hdl->render); if (ret != ret_ok) return ret; return ret_ok; }
static ret_t parse (cherokee_handler_ssi_t *hdl, cherokee_buffer_t *in, cherokee_buffer_t *out) { ret_t ret; char *p, *q; char *begin; int re; cuint_t len; operations_t op; path_type_t path; struct stat info; cherokee_boolean_t ignore; cherokee_buffer_t key = CHEROKEE_BUF_INIT; cherokee_buffer_t val = CHEROKEE_BUF_INIT; cherokee_buffer_t pair = CHEROKEE_BUF_INIT; cherokee_buffer_t fpath = CHEROKEE_BUF_INIT; q = in->buf; while (true) { begin = q; /* Check the end */ if (q >= in->buf + in->len) break; /* Find next SSI tag */ p = strstr (q, "<!--#"); if (p == NULL) { cherokee_buffer_add (out, begin, (in->buf + in->len) - begin); ret = ret_ok; goto out; } q = strstr (p + 5, "-->"); if (q == NULL) { ret = ret_error; goto out; } len = q - p; len -= 5; cherokee_buffer_clean (&key); cherokee_buffer_add (&key, p+5, len); cherokee_buffer_trim (&key); q += 3; TRACE(ENTRIES, "Found key '%s'\n", key.buf); /* Add the previous chunk */ cherokee_buffer_add (out, begin, p - begin); /* Check element */ op = op_none; ignore = false; if (strncmp (key.buf, "include", 7) == 0) { op = op_include; len = 7; } else if (strncmp (key.buf, "fsize", 5) == 0) { op = op_size; len = 5; } else if (strncmp (key.buf, "flastmod", 8) == 0) { op = op_lastmod; len = 8; } else { LOG_ERROR (CHEROKEE_ERROR_HANDLER_SSI_PROPERTY, key.buf); } /* Deeper parsing */ path = path_none; switch (op) { case op_size: case op_include: case op_lastmod: /* Read a property key */ cherokee_buffer_move_to_begin (&key, len); cherokee_buffer_trim (&key); cherokee_buffer_clean (&pair); get_pair (&key, &pair); cherokee_buffer_drop_ending (&key, pair.len); cherokee_buffer_trim (&key); /* Parse the property */ if (strncmp (pair.buf, "file=", 5) == 0) { path = path_file; len = 5; } else if (strncmp (pair.buf, "virtual=", 8) == 0) { path = path_virtual; len = 8; } cherokee_buffer_clean (&val); get_val (pair.buf + len, &val); cherokee_buffer_clean (&fpath); switch (path) { case path_file: cherokee_buffer_add_buffer (&fpath, &hdl->dir); cherokee_buffer_add_char (&fpath, '/'); cherokee_buffer_add_buffer (&fpath, &val); TRACE(ENTRIES, "Path: file '%s'\n", fpath.buf); break; case path_virtual: cherokee_buffer_add_buffer (&fpath, &HANDLER_VSRV(hdl)->root); cherokee_buffer_add_char (&fpath, '/'); cherokee_buffer_add_buffer (&fpath, &val); TRACE(ENTRIES, "Path: virtual '%s'\n", fpath.buf); break; default: ignore = true; SHOULDNT_HAPPEN; } /* Path security check: ensure that the file * to include is inside the document root. */ if (! cherokee_buffer_is_empty (&fpath)) { cherokee_path_short (&fpath); if (fpath.len < HANDLER_VSRV(hdl)->root.len) { ignore = true; } else { re = strncmp (fpath.buf, HANDLER_VSRV(hdl)->root.buf, HANDLER_VSRV(hdl)->root.len); if (re != 0) { ignore = true; } } } /* Perform the operation */ if (! ignore) { switch (op) { case op_include: { cherokee_buffer_t file_content = CHEROKEE_BUF_INIT; ret = cherokee_buffer_read_file (&file_content, fpath.buf); if (unlikely (ret != ret_ok)) { cherokee_buffer_mrproper (&file_content); ret = ret_error; goto out; } TRACE(ENTRIES, "Including file '%s'\n", fpath.buf); ret = parse (hdl, &file_content, out); if (unlikely (ret != ret_ok)) { cherokee_buffer_mrproper (&file_content); ret = ret_error; goto out; } cherokee_buffer_mrproper (&file_content); break; } case op_size: TRACE(ENTRIES, "Including file size '%s'\n", fpath.buf); re = cherokee_stat (fpath.buf, &info); if (re >=0) { cherokee_buffer_add_ullong10 (out, info.st_size); } break; case op_lastmod: TRACE(ENTRIES, "Including file modification date '%s'\n", fpath.buf); re = cherokee_stat (fpath.buf, &info); if (re >= 0) { struct tm *ltime; struct tm ltime_buf; char tmp[50]; ltime = cherokee_localtime (&info.st_mtime, <ime_buf); if (ltime != NULL) { strftime (tmp, sizeof(tmp), "%d-%b-%Y %H:%M", ltime); cherokee_buffer_add (out, tmp, strlen(tmp)); } } break; default: SHOULDNT_HAPPEN; } } /* !ignore */ break; default: SHOULDNT_HAPPEN; } /* switch(op) */ } /* while */ ret = ret_ok; out: cherokee_buffer_mrproper (&key); cherokee_buffer_mrproper (&val); cherokee_buffer_mrproper (&pair); cherokee_buffer_mrproper (&fpath); return ret; }
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 */ 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, '/'); *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 = cherokee_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 */ 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 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); }