Exemplo n.º 1
0
smcp_status_t
smcp_node_get_path(
	smcp_node_t node, char* path, coap_size_t max_path_len
) {
	smcp_status_t ret = 0;

	require(node, bail);
	require(path, bail);

	if(node->parent) {
		// using recursion here just makes this code so much more pretty,
		// but it would be ideal to avoid using recursion at all,
		// to be nice to the stack. Just a topic of future investigation...
		ret = smcp_node_get_path(node->parent, path, max_path_len);
	} else {
		path[0] = 0;
	}


	if(node->name) {
		size_t len;
		strlcat(path, "/", max_path_len);
		len = strlen(path);
		if(max_path_len>len)
			url_encode_cstr(path+len, node->name, max_path_len - len);
	}

bail:
	return ret;
}
Exemplo n.º 2
0
cgi_node_request_t
cgi_node_create_request(cgi_node_t node) {
	cgi_node_request_t ret = NULL;
	int i;
	int pipe_cmd_stdin[2];
	int pipe_cmd_stdout[2];

	for (i=0; i < CGI_NODE_MAX_REQUESTS; i++) {
		if (node->requests[i].state <= CGI_NODE_STATE_FINISHED) {
			ret = &node->requests[i];
			if (node->requests[i].state == CGI_NODE_STATE_INACTIVE) {
				break;
			}
		}
	}

	require(ret,bail);

	ret->is_active = 1;
	ret->state = CGI_NODE_STATE_ACTIVE_BLOCK1_WAIT_REQ;

	if(ret->pid != 0 && ret->pid != -1) {
		int status;
		kill(ret->pid,SIGKILL);
		waitpid(ret->pid, &status, 0);
	}

	if(ret->fd_cmd_stdin>=0) {
		close(ret->fd_cmd_stdin);
	}

	if(ret->fd_cmd_stdout>=0) {
		close(ret->fd_cmd_stdout);
	}

	ret->pid = 0;
	ret->fd_cmd_stdin = -1;
	ret->fd_cmd_stdout = -1;
	ret->block1 = BLOCK_OPTION_UNSPECIFIED;
	ret->block2 = BLOCK_OPTION_DEFAULT; // Default value, overwrite with actual block
	ret->stdin_buffer_len = 0;
	ret->stdout_buffer_len = 0;
	ret->expiration = smcp_plat_cms_to_timestamp(30 * MSEC_PER_SEC);

	free(ret->stdin_buffer);
	ret->stdin_buffer = NULL;

	free(ret->stdout_buffer);
	ret->stdout_buffer = NULL;

	smcp_start_async_response(&ret->async_response, SMCP_ASYNC_RESPONSE_FLAG_DONT_ACK);

	pipe(pipe_cmd_stdin);
	pipe(pipe_cmd_stdout);

	if(!(ret->pid=fork())) {
		// We are the child!
		char path[2048]; // todo: this max should be a preprocessor macro

		// Update stdin and stdout.
		dup2(pipe_cmd_stdin[0],STDIN_FILENO);
		dup2(pipe_cmd_stdout[1],STDOUT_FILENO);

		close(pipe_cmd_stdin[0]);
		close(pipe_cmd_stdin[1]);
		close(pipe_cmd_stdout[0]);
		close(pipe_cmd_stdout[1]);

		path[0] = 0;
		smcp_node_get_path(&node->node,path,sizeof(path));
		setenv("SCRIPT_NAME",path,1);

		setenv("SERVER_SOFTWARE","smcpd/"PACKAGE_VERSION,1);
		setenv("REQUEST_METHOD",coap_code_to_cstr(smcp_inbound_get_packet()->code),1);
		setenv("REQUEST_URI",smcp_inbound_get_path(path,2),1);
		setenv("GATEWAY_INTERFACE","CGI/1.1",1);
		setenv("SERVER_PROTOCOL","CoAP/1.0",1);

		setenv("REMOTE_ADDR","",1);
		setenv("REMOTE_PORT","",1);
		setenv("SERVER_NAME","",1);
		setenv("SERVER_ADDR","",1);
		setenv("SERVER_PORT","",1);

		if (0 == strncmp(path,getenv("SCRIPT_NAME"),strlen(getenv("SCRIPT_NAME")))) {
			setenv("PATH_INFO",path+strlen(getenv("SCRIPT_NAME")),1);
		}

		syslog(LOG_DEBUG, "cgi-node: About to execute \"%s\" using shell \"%s\"", node->cmd, node->shell);

		execl(node->shell,node->shell,"-c",node->cmd,NULL);

		syslog(LOG_ERR, "cgi-node: Failed to execute \"%s\" using shell \"%s\"", node->cmd, node->shell);

		// We should never get here...
		abort();
	}

	if (ret->pid < 0) {
		// Oh hell.

		syslog(LOG_ERR,"Unable to fork!");

		close(pipe_cmd_stdin[0]);
		close(pipe_cmd_stdin[1]);
		close(pipe_cmd_stdout[0]);
		close(pipe_cmd_stdout[1]);

		ret->is_active = 0;
		ret->state = CGI_NODE_STATE_INACTIVE;

		ret = NULL;
		goto bail;
	}

	ret->fd_cmd_stdin = pipe_cmd_stdin[1];
	ret->fd_cmd_stdout = pipe_cmd_stdout[0];

	close(pipe_cmd_stdin[0]);
	close(pipe_cmd_stdout[1]);

bail:
	return ret;
}