示例#1
0
ret_t
cherokee_handler_tmi_init (cherokee_handler_tmi_t *hdl)
{
    ret_t ret;
    cherokee_connection_t *conn = HANDLER_CONN(hdl);
    cherokee_buffer_t	 *tmp  = &HANDLER_THREAD(hdl)->tmp_buf1;
    cherokee_handler_tmi_props_t *props = HANDLER_TMI_PROPS(hdl);

    /* We are going to look for gzipped encoding */
    cherokee_buffer_clean (tmp);
    ret = cherokee_header_copy_known (&conn->header, header_content_encoding, tmp);
    if (ret == ret_ok && cherokee_buffer_cmp_str(tmp, "gzip") == 0) {
        TRACE(ENTRIES, "ZeroMQ: incomming header '%s'\n", tmp->buf);
        hdl->inflated = true;
    } else {
        cherokee_buffer_clean (tmp);
        ret = cherokee_header_copy_known (&conn->header, header_content_type, tmp);
        if (ret == ret_ok && (cherokee_buffer_cmp_str(tmp, "application/gzip") == 0 || cherokee_buffer_cmp_str(tmp, "application/zip") == 0)) {
            TRACE(ENTRIES, "ZeroMQ: incomming header '%s'\n", tmp->buf);
            hdl->inflated = true;
        } else {
            hdl->inflated = false;
        }
    }

#ifdef LIBXML_PUSH_ENABLED
    if (props->validate_xml) {
        hdl->validate_xml = true;
        hdl->ctxt = xmlCreatePushParserCtxt(NULL, NULL, NULL, 0, NULL);
        xmlCtxtUseOptions(hdl->ctxt, XML_PARSE_NOERROR | XML_PARSE_NOWARNING | XML_PARSE_NONET | XML_PARSE_COMPACT);

        if (hdl->inflated) {
            /* allocate inflate state */
            hdl->strm.zalloc = Z_NULL;
            hdl->strm.zfree = Z_NULL;
            hdl->strm.opaque = Z_NULL;
            hdl->strm.avail_in = 0;
            hdl->strm.next_in = Z_NULL;
            hdl->z_ret = inflateInit2(&(hdl->strm), 16+MAX_WBITS);
            if (hdl->z_ret != Z_OK)
                hdl->validate_xml = false;
        }
    }
#endif

    if (!hdl->inflated) {
        /* If we end up here that means content is plain, lets set up an encoder */
        ret = props->encoder_props->instance_func((void **)&hdl->encoder, props->encoder_props);
        if (unlikely (ret != ret_ok)) {
            return ret_error;
        }

        ret = cherokee_encoder_init (hdl->encoder, conn);
        if (unlikely (ret != ret_ok)) {
            return ret_error;
        }
    }

    return ret_ok;
}
ret_t
cherokee_handler_dbslayer_init (cherokee_handler_dbslayer_t *hdl)
{
	ret_t                              ret;
	cherokee_connection_t             *conn  = HANDLER_CONN(hdl);
	cherokee_handler_dbslayer_props_t *props = HANDLER_DBSLAYER_PROPS(hdl);

	/* Check client headers
	 */
	cherokee_client_headers (hdl);

	/* Get a reference to the target host
	 */
	if (hdl->src_ref == NULL) {
		ret = cherokee_balancer_dispatch (props->balancer, conn, &hdl->src_ref);
		if (ret != ret_ok)
			return ret;
	}

	/* Connect to the MySQL server
	 */
	ret = connect_to_database(hdl);
	if (unlikely (ret != ret_ok))
		return ret;

	/* Send query:
	 * Do not check whether it failed, ::step() will do
	 * it and send an error message if needed.
	 */
	send_query(hdl);

	return ret_ok;
}
static ret_t
send_query (cherokee_handler_dbslayer_t *hdl)
{
	int                    re;
	cuint_t                len;
	cherokee_connection_t *conn = HANDLER_CONN(hdl);
	cherokee_buffer_t     *tmp  = &HANDLER_THREAD(hdl)->tmp_buf1;

	/* Extract the SQL query
	 */
	if ((cherokee_buffer_is_empty (&conn->web_directory)) ||
	    (cherokee_buffer_is_ending (&conn->web_directory, '/')))
	{
		len = conn->web_directory.len;
	} else {
		len = conn->web_directory.len + 1;
	}

	cherokee_buffer_clean (tmp);
	cherokee_buffer_add   (tmp,
			       conn->request.buf + len,
			       conn->request.len - len);

	cherokee_buffer_unescape_uri (tmp);

	/* Send the query
	 */
	re = mysql_real_query (hdl->conn, tmp->buf, tmp->len);
	if (re != 0)
		return ret_error;

	return ret_ok;
}
示例#4
0
ret_t
cherokee_handler_ssi_init (cherokee_handler_ssi_t *hdl)
{
	ret_t                  ret;
	cherokee_connection_t *conn = HANDLER_CONN(hdl);

	/* Build the local directory
	 */
	cherokee_buffer_add_buffer (&hdl->dir, &conn->local_directory);
	cherokee_buffer_add_buffer (&hdl->dir, &conn->request);

	while (true) {
		if (cherokee_buffer_is_empty (&hdl->dir))
			return ret_error;

		if (cherokee_buffer_is_ending (&hdl->dir, '/'))
			break;

		cherokee_buffer_drop_ending (&hdl->dir, 1);
	}


	/* Real init function
	 */
	cherokee_buffer_add_buffer (&conn->local_directory, &conn->request);
	ret = init (hdl, &conn->local_directory);
	cherokee_buffer_drop_ending (&conn->local_directory, conn->request.len);

	return ret;
}
示例#5
0
static ret_t
fork_and_execute_cgi_unix (cherokee_handler_cgi_t *cgi)
{
	int                    re;
	int                    pid;
	cherokee_connection_t *conn = HANDLER_CONN(cgi);

	struct {
		int cgi[2];
		int server[2];
	} pipes;

	/* Creates the pipes ...
	 */
	re  = pipe (pipes.cgi);
	re |= pipe (pipes.server);

	if (re != 0) {
		conn->error_code = http_internal_error;
		return ret_error;
	}

	/* .. and fork the process
	 */
	pid = fork();
	if (pid == 0) {
		/* CGI process
		 */
		manage_child_cgi_process (cgi, pipes.cgi, pipes.server);

	} else if (pid < 0) {
		/* Error
		 */
		cherokee_fd_close (pipes.cgi[0]);
		cherokee_fd_close (pipes.cgi[1]);

		cherokee_fd_close (pipes.server[0]);
		cherokee_fd_close (pipes.server[1]);

		conn->error_code = http_internal_error;
		return ret_error;
	}

	TRACE (ENTRIES, "pid %d\n", pid);

	cherokee_fd_close (pipes.server[0]);
	cherokee_fd_close (pipes.cgi[1]);

	cgi->pid        = pid;
	cgi->pipeInput  = pipes.cgi[0];
	cgi->pipeOutput = pipes.server[1];

	/* Set to Input to NON-BLOCKING
	 */
	_fd_set_properties (cgi->pipeInput, O_NDELAY|O_NONBLOCK, 0);

	return ret_ok;
}
示例#6
0
ret_t
cherokee_handler_admin_add_headers (cherokee_handler_admin_t *hdl, cherokee_buffer_t *buffer)
{
    cherokee_connection_t *conn = HANDLER_CONN(hdl);

    if (cherokee_connection_should_include_length(conn)) {
        HANDLER(hdl)->support = hsupport_length;
        cherokee_buffer_add_va (buffer, "Content-Length: %lu" CRLF, hdl->reply.len);
    }

    return ret_ok;
}
示例#7
0
ret_t
cherokee_handler_cgi_read_post (cherokee_handler_cgi_t *cgi)
{
	ret_t                     ret;
	cherokee_connection_t    *conn     = HANDLER_CONN(cgi);
	cherokee_socket_status_t  blocking = socket_closed;
	cherokee_boolean_t        did_IO   = false;

	if (! conn->post.has_info) {
		return ret_ok;
	}

	ret = cherokee_post_send_to_fd (&conn->post, &conn->socket,
					cgi->pipeOutput, NULL, &blocking, &did_IO);

	if (did_IO) {
		cherokee_connection_update_timeout (conn);
	}

	switch (ret) {
	case ret_ok:
		break;
	case ret_eagain:
		if (blocking == socket_writing) {
			cherokee_thread_deactive_to_polling (HANDLER_THREAD(cgi),
							     conn, cgi->pipeOutput,
							     FDPOLL_MODE_WRITE, false);
			return ret_deny;
		}

		/* ret_eagain - Block on read
		 * ret_deny   - Block on back-end write
		 */
		if (cherokee_post_has_buffered_info (&conn->post)) {
			return ret_deny;
		}
		return ret_eagain;

	default:
		return ret;
	}

	TRACE (ENTRIES",post", "%s\n", "finished");
	cherokee_fd_close (cgi->pipeOutput);
	cgi->pipeOutput = -1;

	return ret_ok;
}
示例#8
0
ret_t
cherokee_handler_error_init (cherokee_handler_error_t *hdl)
{
	ret_t                  ret;
	cherokee_connection_t *conn = HANDLER_CONN(hdl);

	/* If needed then generate the error web page.
	 * Some HTTP response codes should not include body
	 * because it's forbidden by the RFC.
	 */
	if (http_code_with_body (conn->error_code)) {
		ret = build_hardcoded_response_page (conn, &hdl->content);
		if (unlikely(ret < ret_ok))
			return ret;
	}

	return ret_ok;
}
示例#9
0
ret_t
cherokee_handler_cgi_init (cherokee_handler_cgi_t *cgi)
{
	ret_t                        ret;
	cherokee_handler_cgi_base_t *cgi_base = HDL_CGI_BASE(cgi);
	cherokee_connection_t       *conn     = HANDLER_CONN(cgi);

	switch (cgi_base->init_phase) {
	case hcgi_phase_build_headers:

		/* Extracts PATH_INFO and filename from request uri
		 */
		if (cherokee_buffer_is_empty (&cgi_base->executable)) {
			ret = cherokee_handler_cgi_base_extract_path (cgi_base, true);
			if (unlikely (ret < ret_ok)) {
				return ret;
			}
		}

		/* It has to update the timeout of the connection,
		 * otherwhise the server will drop it for the CGI
		 * isn't fast enough
		 */
		conn->timeout = cherokee_bogonow_now + CGI_TIMEOUT;
		cgi_base->init_phase = hcgi_phase_connect;

	case hcgi_phase_connect:
		/* Launch the CGI
		 */
		ret = fork_and_execute_cgi_via_spawner(cgi);
		if (unlikely (ret != ret_ok)) {
			ret = fork_and_execute_cgi(cgi);
			if (unlikely (ret != ret_ok)) {
				return ret;
			}
		}

	default:
		break;
	}

	TRACE (ENTRIES, "finishing %s\n", "ret_ok");
	return ret_ok;
}
static void
cherokee_client_headers (cherokee_handler_dbslayer_t *hdl)
{
	ret_t                  ret;
	char                  *hdr   = NULL;
	cuint_t                len   = 0;
	cherokee_connection_t *conn  = HANDLER_CONN(hdl);

	ret = cherokee_header_get_unknown (&conn->header, "X-Beautify", 10, &hdr, &len);
	if ((ret == ret_ok) && hdr) {
		hdl->writer.pretty = !! atoi(hdr);
	}

	hdr = NULL;
	ret = cherokee_header_get_unknown (&conn->header, "X-Rollback", 10, &hdr, &len);
	if ((ret == ret_ok) && hdr) {
		hdl->rollback = !! atoi(hdr);
	}
}
示例#11
0
static ret_t
read_from_cgi (cherokee_handler_cgi_base_t *cgi_base, cherokee_buffer_t *buffer)
{
	ret_t                   ret;
 	size_t                  read_ = 0;
	cherokee_handler_cgi_t *cgi   = HDL_CGI(cgi_base);

	/* Sanity check: pipe() accessed
	 */
	if (unlikely (cgi->pipeInput < 0))
		return ret_eof;

	/* Read the data from the pipe:
	 */
	ret = cherokee_buffer_read_from_fd (buffer, cgi->pipeInput, 4096, &read_);

	TRACE (ENTRIES, "read... ret=%d %d\n", ret, read_);

	switch (ret) {
	case ret_eagain:
		cherokee_thread_deactive_to_polling (HANDLER_THREAD(cgi),
						     HANDLER_CONN(cgi), cgi->pipeInput,
						     FDPOLL_MODE_READ, false);
		return ret_eagain;

	case ret_ok:
		TRACE (ENTRIES, "%d bytes read\n", read_);
		return ret_ok;

	case ret_eof:
	case ret_error:
		cgi_base->got_eof = true;
		return ret;

	default:
		RET_UNKNOWN(ret);
	}

	SHOULDNT_HAPPEN;
	return ret_error;
}
static ret_t
read_from_fcgi (cherokee_handler_cgi_base_t *cgi, cherokee_buffer_t *buffer)
{
	ret_t                    ret;
	size_t                   read = 0;
	cherokee_handler_fcgi_t *fcgi = HDL_FCGI(cgi);

	ret = cherokee_socket_bufread (&fcgi->socket, &fcgi->write_buffer, DEFAULT_READ_SIZE, &read);

	switch (ret) {
	case ret_eagain:
		ret = cherokee_thread_deactive_to_polling (HANDLER_THREAD(cgi), HANDLER_CONN(cgi),
							   fcgi->socket.socket, FDPOLL_MODE_READ,
							   false);
		if (unlikely (ret != ret_ok)) {
			cgi->got_eof = true;
			return ret_error;
		}
		return ret_eagain;

	case ret_ok:
		ret = process_buffer (fcgi, &fcgi->write_buffer, buffer);
		TRACE (ENTRIES, "%d bytes read, buffer.len %d\n", read, buffer->len);

		if ((ret == ret_ok) && cgi->got_eof && (buffer->len > 0)) {
			return ret_eof_have_data;
		}
		return ret;

	case ret_eof:
	case ret_error:
		cgi->got_eof = true;
		return ret;

	default:
		RET_UNKNOWN(ret);
	}

	SHOULDNT_HAPPEN;
	return ret_error;
}
示例#13
0
ret_t
cherokee_handler_admin_init (cherokee_handler_admin_t *hdl)
{
    cherokee_connection_t *conn = HANDLER_CONN(hdl);

#define finishes_by(s) ((conn->request.len > sizeof(s)-1) && \
			(!strncmp (conn->request.buf + conn->request.len - (sizeof(s)-1), s, sizeof(s)-1)))

    if (finishes_by ("/py")) {
        hdl->dwriter.lang = dwriter_python;
    } else if (finishes_by ("/js")) {
        hdl->dwriter.lang = dwriter_json;
    } else if (finishes_by ("/php")) {
        hdl->dwriter.lang = dwriter_php;
    } else if (finishes_by ("/ruby")) {
        hdl->dwriter.lang = dwriter_ruby;
    }

#undef finishes_by
    return ret_ok;
}
示例#14
0
ret_t
cherokee_handler_ssi_add_headers (cherokee_handler_ssi_t *hdl,
                                  cherokee_buffer_t      *buffer)
{
	ret_t                  ret;
	char                  *ext;
	cherokee_buffer_t     *mime = NULL;
	cherokee_server_t     *srv  = HANDLER_SRV(hdl);
	cherokee_connection_t *conn = HANDLER_CONN(hdl);

	/* MIME type
	 */
	if (srv->mime != NULL) {
		ext = strrchr (conn->request.buf, '.');
		if (ext == NULL)
			return ret_ok;

		ret = cherokee_mime_get_by_suffix (srv->mime, ext+1, &hdl->mime);
		if (ret == ret_ok) {
			cherokee_mime_entry_get_type (hdl->mime, &mime);

			cherokee_buffer_add_str    (buffer, "Content-Type: ");
			cherokee_buffer_add_buffer (buffer, mime);
			cherokee_buffer_add_str    (buffer, CRLF);
		}
	}

	/* Length
	 */
	if (cherokee_connection_should_include_length(conn)) {
		HANDLER(hdl)->support = hsupport_length;

		cherokee_buffer_add_str     (buffer, "Content-Length: ");
		cherokee_buffer_add_ullong10(buffer, (cullong_t) hdl->render.len);
		cherokee_buffer_add_str     (buffer, CRLF);
	}

	return ret_ok;
}
示例#15
0
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;
}
示例#16
0
ret_t
cherokee_handler_zeromq_init (cherokee_handler_zeromq_t *hdl)
{
	ret_t							 ret;
	cherokee_buffer_t				*tmp   = &HANDLER_THREAD(hdl)->tmp_buf1;
	cherokee_connection_t			*conn  = HANDLER_CONN(hdl);
	cherokee_handler_zeromq_props_t *props = HANDLER_ZEROMQ_PROPS(hdl);

	/* We are going to look for gzipped encoding */
	cherokee_buffer_clean (tmp);
	ret = cherokee_header_copy_known (&conn->header, header_content_encoding, tmp);
	if (ret == ret_ok && cherokee_buffer_cmp_str(tmp, "gzip") == 0) {
		TRACE(ENTRIES, "ZeroMQ: incomming header '%s'\n", tmp->buf);
		return ret_ok;
	} else {
		cherokee_buffer_clean (tmp);
		ret = cherokee_header_copy_known (&conn->header, header_content_type, tmp);
		if (ret == ret_ok && cherokee_buffer_cmp_str(tmp, "application/gzip") == 0) {
			TRACE(ENTRIES, "ZeroMQ: incomming header '%s'\n", tmp->buf);
			return ret_ok;
		}
	}

	/* If we end up here that means content is plain, lets set up an encoder */
	ret = props->encoder_props->instance_func((void **)&hdl->encoder, props->encoder_props);
	if (unlikely (ret != ret_ok)) {
		return ret_error;
	}

	ret = cherokee_encoder_init (hdl->encoder, conn);
	/* TODO: this is a great idea for KV78turbo, but being able to configure
	 * the reply (KV6, 15, 17) sounds like a good idea too.
	 */
	conn->error_code = http_no_content;
	return ret_error;
}
static ret_t
connect_to_database (cherokee_handler_dbslayer_t *hdl)
{
	MYSQL                             *conn;
	cherokee_handler_dbslayer_props_t *props      = HANDLER_DBSLAYER_PROPS(hdl);
	cherokee_connection_t             *connection = HANDLER_CONN(hdl);

	conn = mysql_real_connect (hdl->conn,
				   hdl->src_ref->host.buf,
				   props->user.buf,
				   props->password.buf,
				   props->db.buf,
				   hdl->src_ref->port,
				   hdl->src_ref->unix_socket.buf,
				   CLIENT_MULTI_STATEMENTS | CLIENT_MULTI_RESULTS);
	if (conn == NULL) {
		cherokee_balancer_report_fail (props->balancer, connection, hdl->src_ref);

		connection->error_code = http_bad_gateway;
		return ret_error;
	}

	return ret_ok;
}
示例#18
0
ret_t
cherokee_handler_tmi_read_post (cherokee_handler_tmi_t *hdl)
{
    zmq_msg_t message;
    int					  re;
    ret_t					ret;
    ret_t					ret_final;
    cherokee_buffer_t	   *post = &HANDLER_THREAD(hdl)->tmp_buf1;
    cherokee_buffer_t	   *encoded = &HANDLER_THREAD(hdl)->tmp_buf2;
    cherokee_connection_t   *conn = HANDLER_CONN(hdl);

    /* Check for the post info
     */
    if (! conn->post.has_info) {
        conn->error_code = http_bad_request;
        return ret_error;
    }

    cherokee_buffer_clean (post);
    ret = cherokee_post_read (&conn->post, &conn->socket, post);
    switch (ret) {
    case ret_ok:
        cherokee_connection_update_timeout (conn);
        break;
    case ret_eagain:
        ret = cherokee_thread_deactive_to_polling (HANDLER_THREAD(hdl),
                HANDLER_CONN(hdl),
                conn->socket.socket,
                FDPOLL_MODE_READ, false);
        if (ret != ret_ok) {
            return ret_error;
        } else {
            return ret_eagain;
        }
    default:
        conn->error_code = http_bad_request;
        return ret_error;
    }

    TRACE (ENTRIES, "Post contains: '%s'\n", post->buf);

    re = cherokee_post_read_finished (&conn->post);
    ret_final = re ? ret_ok : ret_eagain;

    cherokee_buffer_clean(encoded);
    if (hdl->encoder != NULL) {
        if (ret == ret_ok) {
            cherokee_encoder_flush(hdl->encoder, post, encoded);
        } else {
            cherokee_encoder_encode(hdl->encoder, post, encoded);
        }
    } else {
        encoded = post;
    }

    cherokee_buffer_add_buffer(&hdl->output, post);

    if (ret_final == ret_ok) {
        cherokee_buffer_t	 *tmp  = &HANDLER_THREAD(hdl)->tmp_buf1;
        cherokee_handler_tmi_props_t *props = HANDLER_TMI_PROPS(hdl);
        zmq_msg_t envelope;
        zmq_msg_t message;
        cuint_t len;

        if ((cherokee_buffer_is_empty (&conn->web_directory)) ||
                (cherokee_buffer_is_ending (&conn->web_directory, '/')))
        {
            len = conn->web_directory.len;
        } else {
            len = conn->web_directory.len + 1;
        }

        cherokee_buffer_clean (tmp);
        cherokee_buffer_add   (tmp, conn->request.buf + len,
                               conn->request.len - len);

        TRACE(ENTRIES, "ZeroMQ: incomming path '%s'\n", tmp->buf);

        zmq_msg_init_size (&envelope, tmp->len);
        memcpy (zmq_msg_data (&envelope), tmp->buf, tmp->len);
        zmq_msg_init_size (&message, hdl->output.len);
        memcpy (zmq_msg_data (&message), hdl->output.buf, hdl->output.len);

        /* Atomic Section */
        CHEROKEE_MUTEX_LOCK (&props->mutex);
        zmq_msg_send (&envelope, props->socket, ZMQ_DONTWAIT | ZMQ_SNDMORE);
        zmq_msg_send (&message, props->socket, ZMQ_DONTWAIT);
        CHEROKEE_MUTEX_UNLOCK (&props->mutex);

        zmq_msg_close (&envelope);
        zmq_msg_close (&message);

#ifdef LIBXML_PUSH_ENABLED
        if (hdl->validate_xml) {
            if (hdl->inflated) {
                hdl->strm.avail_in = hdl->output.len;
                hdl->strm.next_in = hdl->output.buf;

                /* run inflate() on input until output buffer not full */
                do  {
#define CHUNK 131072
                    int have;
                    char out[CHUNK];
                    hdl->strm.avail_out = CHUNK;
                    hdl->strm.next_out = out;
                    hdl->z_ret = inflate(&(hdl->strm), Z_NO_FLUSH);
                    switch (hdl->z_ret) {
                    case Z_NEED_DICT:
                        hdl->z_ret = Z_DATA_ERROR;	 /* and fall through */
                    case Z_DATA_ERROR:
                    case Z_MEM_ERROR:
                    case Z_STREAM_ERROR:
                        hdl->z_ret = Z_STREAM_ERROR;
                        return ret_ok;
                    }
                    have = CHUNK - hdl->strm.avail_out;
                    xmlParseChunk(hdl->ctxt, out, have, 0);
                } while (hdl->strm.avail_out == 0);
            } else {
                xmlParseChunk(hdl->ctxt, hdl->output.buf, hdl->output.len, 0);
            }
        }
#endif
    }

    return ret_final;
}
示例#19
0
static ret_t
fork_and_execute_cgi_via_spawner(cherokee_handler_cgi_t *cgi)
{
	int                          re;
	int                          pid           = -1;
	cherokee_connection_t       *conn          = HANDLER_CONN(cgi);
	cherokee_handler_cgi_base_t *cgi_base      = HDL_CGI_BASE(cgi);
	ret_t                        ret;
	uid_t                        uid;
	gid_t                        gid;
	cherokee_buffer_t            empty         = CHEROKEE_BUF_INIT;
	cherokee_buffer_t            username      = CHEROKEE_BUF_INIT;
	cherokee_services_fdmap_t    fd_map;
	cherokee_buffer_t           *chdir         = NULL;
	cherokee_buffer_t            chdir_backing = CHEROKEE_BUF_INIT;
	struct passwd                ent;
	char                         ent_tmp[1024];

	struct {
		int cgi[2];
		int server[2];
	} pipes;

	TRACE (ENTRIES, "Trying to create CGI via spawner\n");

	if (! cherokee_buffer_is_empty (&conn->effective_directory)) {
		chdir = &conn->effective_directory;
	} else {
		int ofs = cgi_base->executable.len - 1;
		while (ofs >= 0 && cgi_base->executable.buf[ofs] != '/') {
			ofs--;
		}
		TRACE (ENTRIES, "While building chdir, ofs=%d\n", ofs);
		if (ofs < 0 || cherokee_buffer_add (&chdir_backing,
						    cgi_base->executable.buf,
						    ofs + 1) != ret_ok) {
			conn->error_code = http_internal_error;
			TRACE (ENTRIES, "Failed, cannot build chdir entry\n");
			cherokee_buffer_mrproper(&chdir_backing);
			return ret_error;
		}
		chdir = &chdir_backing;
	}

	/* Creates the pipes ...
	 */
	re  = cherokee_pipe (pipes.cgi);
	re |= cherokee_pipe (pipes.server);

	if (re != 0) {
		conn->error_code = http_internal_error;
		cherokee_buffer_mrproper(&chdir_backing);
		TRACE (ENTRIES, "Failed, cannot build pipes\n");
		return ret_error;
	}

	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 = cherokee_io_stat (srv->iocache, &cgi_base->executable, props->use_cache, &nocache_info, &io_entry, &info);
		if (ret != ret_ok) {
			info = &nocache_info;
			nocache_info.st_uid = getuid();
			nocache_info.st_gid = getgid();
		}

		uid = info->st_uid;
		gid = info->st_gid;

		cherokee_iocache_entry_unref(&io_entry);
	} else {
		/* Not changing, so launch as the same uid/gid as the worker */
		uid = getuid();
		gid = getgid();
	}

	/* Determine the username of the owner of the file */
	ret = cherokee_getpwuid(uid, &ent, ent_tmp, sizeof (ent_tmp));
	if (ret != ret_ok ||
	    cherokee_buffer_add(&username,
				ent.pw_name,
				strlen(ent.pw_name) != ret_ok)) {
		cherokee_fd_close(pipes.cgi[0]);
		cherokee_fd_close(pipes.cgi[1]);
		cherokee_fd_close(pipes.server[0]);
		cherokee_fd_close(pipes.server[1]);
		conn->error_code = http_internal_error;
		cherokee_buffer_mrproper(&chdir_backing);
		cherokee_buffer_mrproper(&username);
		TRACE (ENTRIES, "Failed, Unable to retrieve username for uid %d\n", uid);
		return ret_error;
	}


	/* Update the environment ready to run */
	add_environment (cgi, conn);

	/* Set up the FD map */
	fd_map.fd_in = pipes.server[0];
	fd_map.fd_out = pipes.cgi[1];

	if ((CONN_VSRV(conn)->error_writer != NULL) &&
	    (CONN_VSRV(conn)->error_writer->fd != -1)) {
		fd_map.fd_err = CONN_VSRV(conn)->error_writer->fd;
	} else {
		fd_map.fd_err = fd_map.fd_out;
	}


	TRACE (ENTRIES, "Doing Spawn\n");
	ret = cherokee_services_client_spawn (&cgi_base->executable,
					      &username,
					      uid,
					      gid,
					      &empty,
					      chdir,
					      false,
					      cgi->envp,
					      CONN_VSRV(conn)->error_writer,
					      &pid,
					      &fd_map);

	cherokee_buffer_mrproper(&chdir_backing);
	cherokee_buffer_mrproper(&username);

	/* Close the client FDs */
	cherokee_fd_close (pipes.server[0]);
	cherokee_fd_close (pipes.cgi[1]);

	/* Did we fail to try to spawn? */
	if (ret != ret_ok) {
		/* Close the server FDs too */
		cherokee_fd_close (pipes.server[1]);
		cherokee_fd_close (pipes.cgi[0]);
		TRACE (ENTRIES, "Failed to spawn\n");
		return ret;
	}

	/* Did we try, but fail, to spawn? */
	if (pid == -1) {
		/* Close the server FDs too */
		cherokee_fd_close (pipes.server[1]);
		cherokee_fd_close (pipes.cgi[0]);
		TRACE (ENTRIES, "Spawned, but failed server side\n");
		return ret_error;
	}

	/* Successfully launched */
	cgi->pid        = pid;
	cgi->pipeInput  = pipes.cgi[0];
	cgi->pipeOutput = pipes.server[1];

	/* Set to Input to NON-BLOCKING
	 */
	_fd_set_properties (cgi->pipeInput, O_NDELAY|O_NONBLOCK, 0);

	TRACE (ENTRIES, "CGI running, PID=%d\n", pid);
	return ret_ok;
}
示例#20
0
ret_t
cherokee_handler_error_add_headers (cherokee_handler_error_t *hdl, cherokee_buffer_t *buffer)
{
	cherokee_connection_t *conn = HANDLER_CONN(hdl);

	/* It has special headers on protocol upgrading
	 */
	switch (conn->upgrade) {
	case http_upgrade_nothing:
		break;
	case http_upgrade_tls10:
		cherokee_buffer_add_str (buffer, "Upgrade: TLS/1.0, HTTP/1.1"CRLF);
		break;
	case http_upgrade_http11:
		cherokee_buffer_add_str (buffer, "Upgrade: HTTP/1.1"CRLF);
		break;
	default:
		SHOULDNT_HAPPEN;
	}

	/* 1xx, 204 and 304 (Not Modified) responses have to be managed
	 * by "content" handlers, anyway this test ensures that
	 * it'll never send wrong and unrelated headers in case that
	 * a 1xx, 204 or 304 response is managed by this handler.
	 * 304 responses should only include the
	 * Last-Modified, ETag, Expires and Cache-Control headers.
	 */
	if (!http_code_with_body (conn->error_code)) {
		return ret_ok;
	}

	if (cherokee_connection_should_include_length(conn)) {

		HANDLER(hdl)->support |= hsupport_length;

		if (conn->error_code == http_range_not_satisfiable) {
			/* The handler that attended the request has put the content
			* length in conn->range_end in order to allow it to send the
			* right length to the client.
			*
			* "Content-Range: bytes *" "/" FMT_OFFSET CRLF
			*/
			cherokee_buffer_add_str     (buffer, "Content-Range: bytes */");
			cherokee_buffer_add_ullong10(buffer, (cullong_t)conn->range_end);
			cherokee_buffer_add_str     (buffer, CRLF);
		}

		cherokee_buffer_add_str     (buffer, "Content-Length: ");
		cherokee_buffer_add_ulong10 (buffer, (culong_t) hdl->content.len);
		cherokee_buffer_add_str     (buffer, CRLF);
	}

	/* Usual headers
	 */
	cherokee_buffer_add_str (buffer, "Content-Type: text/html"CRLF);

	if (http_type_400(conn->error_code) ||
	    http_type_500(conn->error_code))
	{
		cherokee_buffer_add_str (buffer, "Cache-Control: no-cache"CRLF);
		cherokee_buffer_add_str (buffer, "Pragma: no-cache"CRLF);
	}

	return ret_ok;
}
示例#21
0
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);
}
示例#22
0
static ret_t
fork_and_execute_cgi_win32 (cherokee_handler_cgi_t *cgi)
{
	int                    re;
	PROCESS_INFORMATION    pi;
	STARTUPINFO            si;
	char                  *cmd;
	cherokee_buffer_t      cmd_line = CHEROKEE_BUF_INIT;
	cherokee_buffer_t      exec_dir = CHEROKEE_BUF_INIT;
	cherokee_connection_t *conn     = HANDLER_CONN(cgi);

	SECURITY_ATTRIBUTES saSecAtr;
	HANDLE hProc;
	HANDLE hChildStdinRd  = INVALID_HANDLE_VALUE;
	HANDLE hChildStdinWr  = INVALID_HANDLE_VALUE;
	HANDLE hChildStdoutRd = INVALID_HANDLE_VALUE;
	HANDLE hChildStdoutWr = INVALID_HANDLE_VALUE;

	/* Create the environment for the process
	 */
	add_environment (cgi, conn);
	cherokee_buffer_add (&cgi->envp, "\0", 1);

	/* Command line
	 */
	cmd = HDL_CGI_BASE(cgi)->executable.buf;
	cherokee_buffer_add (&cmd_line, cmd, strlen(cmd));
//	cherokee_buffer_add_va (&cmd_line, " \"%s\"", HDL_CGI_BASE(cgi)->param.buf);

	/* Execution directory
	 */
	if (! cherokee_buffer_is_empty (&conn->effective_directory)) {
		cherokee_buffer_add_buffer (&exec_dir, &conn->effective_directory);
	} else {
		char *file = strrchr (cmd, '/');
		char *end  = HDL_CGI_BASE(cgi)->executable.buf + HDL_CGI_BASE(cgi)->executable.len;

		cherokee_buffer_add (&exec_dir, cmd,
				     HDL_CGI_BASE(cgi)->executable.len - (end - file));
	}

	/* Set the bInheritHandle flag so pipe handles are inherited.
	 */
	memset(&saSecAtr, 0, sizeof(SECURITY_ATTRIBUTES));
	saSecAtr.nLength = sizeof(SECURITY_ATTRIBUTES);
	saSecAtr.lpSecurityDescriptor = NULL;
	saSecAtr.bInheritHandle       = TRUE;

	/* Create the pipes
	 */
	hProc = GetCurrentProcess();

	re = CreatePipe (&hChildStdoutRd, &hChildStdoutWr, &saSecAtr, 0);
	if (!re) return ret_error;

	re = CreatePipe (&hChildStdinRd, &hChildStdinWr, &saSecAtr, 0);
	if (!re) return ret_error;

	/* Make them inheritable
	 */
	re = DuplicateHandle (hProc,  hChildStdoutRd,
			      hProc, &hChildStdoutRd,
			      0, TRUE,
			      DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS);
	if (!re) return ret_error;

	re = DuplicateHandle (hProc,  hChildStdinWr,
			      hProc, &hChildStdinWr,
			      0, TRUE,
			      DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS);
	if (!re) return ret_error;


	/* Starting information
	 */
	ZeroMemory (&si, sizeof(STARTUPINFO));
	si.cb         = sizeof(STARTUPINFO);
	si.hStdOutput = hChildStdoutWr;
	si.hStdError  = hChildStdoutWr;
	si.hStdInput  = hChildStdinRd;
	si.dwFlags   |= STARTF_USESTDHANDLES;

	TRACE (ENTRIES, "exec %s dir %s\n", cmd_line.buf, exec_dir.buf);

	/* Launch the child process
	 */
	re = CreateProcess (cmd,              /* ApplicationName */
			    cmd_line.buf,     /* Command line */
			    NULL,             /* Process handle not inheritable */
			    NULL,             /* Thread handle not inheritable */
			    TRUE,             /* Handle inheritance */
			    0,                /* Creation flags */
			    cgi->envp.buf,    /* Use parent's environment block */
			    exec_dir.buf,     /* Use parent's starting directory */
			    &si,              /* Pointer to STARTUPINFO structure */
			    &pi);             /* Pointer to PROCESS_INFORMATION structure */

	CloseHandle (hChildStdinRd);
	CloseHandle (hChildStdoutWr);

	if (!re) {
		LOG_ERROR (CHEROKEE_ERROR_HANDLER_CGI_CREATEPROCESS, GetLastError());

		CloseHandle (pi.hProcess);
		CloseHandle (pi.hThread);

		conn->error_code = http_internal_error;
		return ret_error;
	}

	cherokee_buffer_mrproper (&cmd_line);
	cherokee_buffer_mrproper (&exec_dir);

	cgi->thread  = pi.hThread;
	cgi->process = pi.hProcess;

	/* Wait for the CGI process to be ready
	 */
	WaitForInputIdle (pi.hProcess, INFINITE);

	/* Extract the file descriptors
	 */
	cgi->pipeInput  = _open_osfhandle((LONG)hChildStdoutRd, O_BINARY|_O_RDONLY);

	if (! conn->post.len <= 0) {
		CloseHandle (hChildStdinWr);
	} else {
		cgi->pipeOutput = _open_osfhandle((LONG)hChildStdinWr,  O_BINARY|_O_WRONLY);
	}

	TRACE (ENTRIES, "In fd %d, Out fd %d\n", cgi->pipeInput, cgi->pipeOutput);

	return ret_ok;
}
示例#23
0
ret_t
cherokee_handler_zeromq_read_post (cherokee_handler_zeromq_t *hdl)
{
	zmq_msg_t				message;
	int						re;
	ret_t					ret;
	cherokee_buffer_t	   *post = &HANDLER_THREAD(hdl)->tmp_buf1;
	cherokee_buffer_t	   *out  = &HANDLER_THREAD(hdl)->tmp_buf2;
	cherokee_connection_t  *conn = HANDLER_CONN(hdl);

	/* Check for the post info
	 */
	if (! conn->post.has_info) {
		conn->error_code = http_bad_request;
		return ret_error;
	}

	cherokee_buffer_clean (post);
	ret = cherokee_post_read (&conn->post, &conn->socket, post);
	switch (ret) {
	case ret_ok:
		cherokee_connection_update_timeout (conn);
		break;
	case ret_eagain:
		ret = cherokee_thread_deactive_to_polling (HANDLER_THREAD(hdl),
												   HANDLER_CONN(hdl),
												   conn->socket.socket,
												   FDPOLL_MODE_READ, false);
		if (ret != ret_ok) {
			return ret_error;
		} else {
			return ret_eagain;
		}
	default:
		conn->error_code = http_bad_request;
		return ret_error;
	}

	TRACE (ENTRIES, "Post contains: '%s'\n", post->buf);

	re = cherokee_post_read_finished (&conn->post);
	ret = re ? ret_ok : ret_eagain;

	if (hdl->encoder != NULL) {
		cherokee_buffer_clean(out);
		if (ret == ret_ok) {
			cherokee_encoder_flush(hdl->encoder, post, out);
		} else {
			cherokee_encoder_encode(hdl->encoder, post, out);
		}

		post = out;
	}
	
	cherokee_buffer_add_buffer(&hdl->output, post);
	
	if (ret == ret_ok) {
		cherokee_buffer_t	 			*tmp   = &HANDLER_THREAD(hdl)->tmp_buf1;
		cherokee_handler_zeromq_props_t *props = HANDLER_ZEROMQ_PROPS(hdl);
		zmq_msg_t envelope;
		zmq_msg_t message;
		cuint_t len;

		if ((cherokee_buffer_is_empty (&conn->web_directory)) ||
			(cherokee_buffer_is_ending (&conn->web_directory, '/'))) {
			len = conn->web_directory.len;
		} else {
			len = conn->web_directory.len + 1;
		}

		cherokee_buffer_clean (tmp);
		cherokee_buffer_add   (tmp, conn->request.buf + len,
									conn->request.len - len);

		TRACE(ENTRIES, "ZeroMQ: incomming path '%s'\n", tmp->buf);

		zmq_msg_init_size (&envelope, tmp->len);
		memcpy (zmq_msg_data (&envelope), tmp->buf, tmp->len);
		zmq_msg_init_size (&message, hdl->output.len);
		memcpy (zmq_msg_data (&message), hdl->output.buf, hdl->output.len);

		/* Atomic Section */
		CHEROKEE_MUTEX_LOCK (&props->mutex);
		zmq_msg_send (&envelope, props->socket, ZMQ_DONTWAIT | ZMQ_SNDMORE);
		zmq_msg_send (&message, props->socket, ZMQ_DONTWAIT);
		CHEROKEE_MUTEX_UNLOCK (&props->mutex);

		zmq_msg_close (&envelope);
		zmq_msg_close (&message);
	}

	return ret;
}
示例#24
0
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);
}
示例#25
0
ret_t
cherokee_handler_admin_read_post (cherokee_handler_admin_t *hdl)
{
    int                      re;
    ret_t                    ret;
    char                    *tmp;
    cherokee_buffer_t        post = CHEROKEE_BUF_INIT;
    cherokee_buffer_t        line = CHEROKEE_BUF_INIT;
    cherokee_connection_t   *conn = HANDLER_CONN(hdl);

    /* Check for the post info
     */
    if (! conn->post.has_info) {
        conn->error_code = http_bad_request;
        return ret_error;
    }

    /* Process line per line
     */
    ret = cherokee_post_read (&conn->post, &conn->socket, &post);
    switch (ret) {
    case ret_ok:
    case ret_eagain:
        break;
    default:
        conn->error_code = http_bad_request;
        return ret_error;
    }

    /* Parse
     */
    TRACE (ENTRIES, "Post contains: '%s'\n", post.buf);

    cherokee_dwriter_list_open (&hdl->dwriter);

    for (tmp = post.buf;;) {
        char *end1 = strchr (tmp, CHR_LF);
        char *end2 = strchr (tmp, CHR_CR);
        char *end  = cherokee_min_str (end1, end2);

        if (end == NULL) break;
        if (end - tmp < 2) break;

        /* Copy current line and go to the next one
         */
        cherokee_buffer_add (&line, tmp, end - tmp);
        while ((*end == CHR_CR) || (*end == CHR_LF)) end++;
        tmp = end;

        /* Process current line
         */
        ret = process_request_line (hdl, &line);
        if (ret == ret_error) {
            conn->error_code = http_bad_request;
            ret = ret_error;
            goto exit2;
        }

        /* Clean up for the next iteration
         */
        cherokee_buffer_clean (&line);
    }

    cherokee_dwriter_list_close (&hdl->dwriter);

    /* There might be more POST to read
     */
    re = cherokee_post_read_finished (&conn->post);
    ret = re ? ret_ok : ret_eagain;

exit2:
    cherokee_buffer_mrproper (&post);
    cherokee_buffer_mrproper (&line);
    return ret;
}