WIP CGI monitered by epoll
+ OK, but some errors case need to be lookup
This commit is contained in:
@@ -66,9 +66,8 @@ size_t Webserv::_cgi_pos(Client *client, std::string &path, size_t pos)
|
||||
return NPOS;
|
||||
}
|
||||
|
||||
std::string Webserv::_exec_cgi(Client *client)
|
||||
void Webserv::_exec_cgi(Client *client)
|
||||
{
|
||||
std::string script_output;
|
||||
char* env_cstr[19] = {NULL};
|
||||
std::vector<std::string> env_vector;
|
||||
env_vector.reserve(18);
|
||||
@@ -77,12 +76,11 @@ std::string Webserv::_exec_cgi(Client *client)
|
||||
_set_env_vector(client, env_vector);
|
||||
try {
|
||||
_set_env_cstr(env_cstr, env_vector);
|
||||
script_output = _exec_script(client, env_cstr);
|
||||
_exec_script(client, env_cstr);
|
||||
|
||||
while (env_cstr[i] != NULL)
|
||||
delete[] env_cstr[i++];
|
||||
|
||||
return script_output;
|
||||
return;
|
||||
}
|
||||
catch (const Webserv::ExecFail& e)
|
||||
{
|
||||
@@ -125,7 +123,7 @@ void Webserv::_set_env_vector(Client *client, std::vector<std::string> &env_vect
|
||||
env_vector.push_back(_dup_env("QUERY_STRING" , client->get_rq_query()));
|
||||
env_vector.push_back(_dup_env("REMOTE_ADDR" , client->get_cl_ip()));
|
||||
env_vector.push_back(_dup_env("REMOTE_HOST" , client->get_cl_ip())); // equal to REMOTE_ADDR or empty
|
||||
env_vector.push_back(_dup_env("REMOTE_IDENT")); // authentification not supported
|
||||
env_vector.push_back(_dup_env("REMOTE_IDENT")); // authentification not supported
|
||||
env_vector.push_back(_dup_env("REMOTE_USER")); // authentification not supported
|
||||
env_vector.push_back(_dup_env("REQUEST_METHOD" , client->get_rq_method_str()));
|
||||
env_vector.push_back(_dup_env("SCRIPT_NAME" , client->get_rq_script_path())); // LUKE: To Check
|
||||
@@ -151,43 +149,17 @@ void Webserv::_set_env_cstr(char *env_cstr[], std::vector<std::string> &env_vect
|
||||
env_cstr[i] = NULL;
|
||||
}
|
||||
|
||||
/* void Webserv::_set_env_cstr(char *env_cstr[], std::vector<std::string> &env_vector)
|
||||
{
|
||||
env_cstr[0] = const_cast<char*>(env_vector[0].c_str());
|
||||
env_cstr[1] = const_cast<char*>(env_vector[1].c_str());
|
||||
env_cstr[2] = const_cast<char*>(env_vector[2].c_str());
|
||||
env_cstr[3] = const_cast<char*>(env_vector[3].c_str());
|
||||
env_cstr[4] = const_cast<char*>(env_vector[4].c_str());
|
||||
env_cstr[5] = const_cast<char*>(env_vector[5].c_str());
|
||||
env_cstr[6] = const_cast<char*>(env_vector[6].c_str());
|
||||
env_cstr[7] = const_cast<char*>(env_vector[7].c_str());
|
||||
env_cstr[8] = const_cast<char*>(env_vector[8].c_str());
|
||||
env_cstr[9] = const_cast<char*>(env_vector[9].c_str());
|
||||
env_cstr[10] = const_cast<char*>(env_vector[10].c_str());
|
||||
env_cstr[11] = const_cast<char*>(env_vector[11].c_str());
|
||||
env_cstr[12] = const_cast<char*>(env_vector[12].c_str());
|
||||
env_cstr[13] = const_cast<char*>(env_vector[13].c_str());
|
||||
env_cstr[14] = const_cast<char*>(env_vector[14].c_str());
|
||||
env_cstr[15] = const_cast<char*>(env_vector[15].c_str());
|
||||
env_cstr[16] = const_cast<char*>(env_vector[16].c_str());
|
||||
env_cstr[17] = const_cast<char*>(env_vector[17].c_str());
|
||||
env_cstr[18] = NULL;
|
||||
} */
|
||||
|
||||
#define STATUS_500 std::string("Status: 500" CRLF CRLF);
|
||||
|
||||
std::string Webserv::_exec_script(Client *client, char *env[])
|
||||
void Webserv::_exec_script(Client *client, char *env[])
|
||||
{
|
||||
#define RD 0
|
||||
#define WR 1
|
||||
#define CGI_BUF_SIZE 10
|
||||
#define FD_WR_TO_CHLD fd_in[WR]
|
||||
#define FD_WR_TO_PRNT fd_out[WR]
|
||||
#define FD_RD_FR_CHLD fd_out[RD]
|
||||
#define FD_RD_FR_PRNT fd_in[RD]
|
||||
|
||||
pid_t pid;
|
||||
char buf[CGI_BUF_SIZE]; // WIP define buffer
|
||||
char * const nll[1] = {NULL};
|
||||
std::string script_output;
|
||||
std::string body = client->get_rq_body();
|
||||
@@ -195,12 +167,12 @@ std::string Webserv::_exec_script(Client *client, char *env[])
|
||||
int fd_out[2];
|
||||
std::string path;
|
||||
|
||||
pipe(fd_in);
|
||||
pipe(fd_out);
|
||||
::pipe(fd_in);
|
||||
::pipe(fd_out);
|
||||
|
||||
pid = fork();
|
||||
if (pid == -1)
|
||||
perror("err fork()");
|
||||
std::perror("err fork()");
|
||||
else if (pid == 0) // child
|
||||
{
|
||||
std::signal(SIGPIPE, SIG_DFL);
|
||||
@@ -212,14 +184,14 @@ std::string Webserv::_exec_script(Client *client, char *env[])
|
||||
::close(FD_RD_FR_CHLD);
|
||||
if (dup2(FD_RD_FR_PRNT, STDIN_FILENO) == -1)
|
||||
{
|
||||
perror("err dup2()");
|
||||
std::perror("err dup2()");
|
||||
::close(FD_RD_FR_PRNT); // Valgind debug, not essential
|
||||
::close(FD_WR_TO_PRNT); // Valgind debug, not essential
|
||||
throw ExecFail();
|
||||
}
|
||||
if (dup2(FD_WR_TO_PRNT, STDOUT_FILENO) == -1)
|
||||
{
|
||||
perror("err dup2()");
|
||||
std::perror("err dup2()");
|
||||
::close(FD_RD_FR_PRNT); // Valgind debug, not essential
|
||||
::close(FD_WR_TO_PRNT); // Valgind debug, not essential
|
||||
throw ExecFail();
|
||||
@@ -230,9 +202,9 @@ std::string Webserv::_exec_script(Client *client, char *env[])
|
||||
|
||||
path = "." + client->get_rq_script_path(); // Wut ? Only relative path ?
|
||||
/*DEBUG*/std::cerr << "execve:[" << path << "]\n";
|
||||
if (execve(path.c_str(), nll, env) == -1) // replace path for debug error forcing
|
||||
if (::execve(path.c_str(), nll, env) == -1) // replace path for debug error forcing
|
||||
{
|
||||
perror("err execve()");
|
||||
std::perror("err execve()");
|
||||
::close(STDIN_FILENO); // Valgind debug, not essential
|
||||
::close(STDOUT_FILENO); // Valgind debug, not essential
|
||||
throw ExecFail();
|
||||
@@ -240,37 +212,23 @@ std::string Webserv::_exec_script(Client *client, char *env[])
|
||||
}
|
||||
else //parent
|
||||
{
|
||||
close(FD_RD_FR_PRNT);
|
||||
close(FD_WR_TO_PRNT);
|
||||
write(FD_WR_TO_CHLD, body.c_str(), body.size());
|
||||
close(FD_WR_TO_CHLD);
|
||||
waitpid(-1, NULL, 0);
|
||||
// We could maybe,
|
||||
::close(FD_RD_FR_PRNT);
|
||||
::close(FD_WR_TO_PRNT);
|
||||
::write(FD_WR_TO_CHLD, body.c_str(), body.size()); // move this before the fork ?
|
||||
::close(FD_WR_TO_CHLD);
|
||||
|
||||
// add FD_RD_FR_CHLD to epoll,
|
||||
// return to the main loop,
|
||||
// read FD_RD_FR_CHLD each time epoll say its ready,
|
||||
// then try waitpid() with WNOHANG after each read.
|
||||
// when waitpid() tell us its finish (or maybe when epoll return EPOLLHUP)
|
||||
// then actually parse the script_output and send it to the client.
|
||||
_epoll_update(FD_RD_FR_CHLD, EPOLLIN, EPOLL_CTL_ADD);
|
||||
// stop monitoring client->fd until the cgi-script as done is job
|
||||
_epoll_update(client->get_cl_fd(), 0, EPOLL_CTL_DEL);
|
||||
|
||||
ssize_t ret = 1;
|
||||
while (ret > 0)
|
||||
{
|
||||
ret = read(FD_RD_FR_CHLD, buf, CGI_BUF_SIZE);
|
||||
if (ret == -1)
|
||||
{
|
||||
std::perror("err recv()");
|
||||
script_output = STATUS_500;
|
||||
break;
|
||||
}
|
||||
script_output.append(buf, ret);
|
||||
}
|
||||
close(FD_RD_FR_CHLD);
|
||||
client->cgi_pipe_rfd = FD_RD_FR_CHLD;
|
||||
struct cgi_pipe_rfd new_cgi_fd;
|
||||
new_cgi_fd.fd = FD_RD_FR_CHLD;
|
||||
new_cgi_fd.cgi_pid = pid;
|
||||
new_cgi_fd.client = client;
|
||||
_cgi_pipe_rfds.push_back(new_cgi_fd);
|
||||
}
|
||||
if (script_output.empty())
|
||||
script_output = STATUS_500;
|
||||
|
||||
return script_output;
|
||||
}
|
||||
|
||||
void Webserv::_check_script_output(Client *client, std::string & output)
|
||||
|
||||
Reference in New Issue
Block a user