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; }
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; }