From de1bac616b37c8fb380f03b00c34c7b471d3a9ac Mon Sep 17 00:00:00 2001 From: Pin Date: Sun, 6 Mar 2022 23:08:18 -0500 Subject: [PATCH] moved functions around --- Dockerfile | 1 + Makefile | 3 + README.md | 30 +++++ cmd/server.c | 257 ++------------------------------------ entrypoint.sh | 4 +- include/httpStruct.h | 1 + include/requestHandlers.h | 6 + include/server.h | 5 +- include/utils.h | 2 + src/requestHandlers.c | 177 ++++++++++++++++++++++++++ src/returnRequest.c | 14 +-- src/utils.c | 105 +++++++++++++++- 12 files changed, 343 insertions(+), 262 deletions(-) create mode 100644 README.md create mode 100644 include/requestHandlers.h create mode 100644 src/requestHandlers.c diff --git a/Dockerfile b/Dockerfile index dae368c..08b675e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -16,6 +16,7 @@ COPY entrypoint.sh / COPY content/ /var/www/html RUN mkdir -p /var/log/seaweb +RUN touch /var/log/seaweb/log WORKDIR /src/ diff --git a/Makefile b/Makefile index a6acddc..6f52f4f 100644 --- a/Makefile +++ b/Makefile @@ -42,5 +42,8 @@ dockerBuild: output_dir dockerTestDeploy: dockerBuild docker run -p8080:8080 --rm -d seaweb:latest +dockerReleaseDeploy: dockerBuild + docker run -p8080:8080 --rm -d seaweb:latest --cert /src/certs/cert.pem --privkey /src/certs/key.pem + killTestDocker: docker stop -t 0 `docker ps | grep "seaweb:latest" | tail -n 1 | tr -s " " | cut -d " " -f 1` diff --git a/README.md b/README.md new file mode 100644 index 0000000..fffc349 --- /dev/null +++ b/README.md @@ -0,0 +1,30 @@ +# SeaWeb + +## Running + +It is recommended to run this application using Docker. +For a deployment running the application without HTTPS run `make dockerTestDeploy`, this will open a socket on port 8080. +For a deployment running the application with HTTPS run `make dockerReleaseDeploy`, this will also open a socket on port 8080. +Running `make killTestDocker` will kill the running instance of seaweb:latest running in Docker. +To view logs within the running container run `docker exec -it $(docker ps | grep "seaweb:latest" | grep -o '[^ ]*$') tail -f /var/log/seaweb/log`, or manually view the `/var/log/seaweb/log` file. + +If you run this application without Docker please ensure the OpenSSL development headers are installed onto your system, this will be important if running with HTTPS. + +To build this application outside of Docker run `make`, and the binary will be build into `./bin`. +Running `./bin/seaweb --help` or `./bin/seaweb -h` will show you the help message for the application showing all possible options. + +By default the application is compiled to utilize `/var/www/html` as the WEB root, and will output logs to `/var/log/seaweb/log`; if running the application outside of Docker please ensure this is setup with correct permissions to run. + +## Notes + +- All new connections will spawn a child process which is used to deal with the request + - If the process takes longer than 5 seconds to resolve the request, the child process will be killed +- php-cgi seems to randomly return empty data from scripts without throwing an error message (these are caught and a HTTP 500 response is return) + - If the request is made again it will eventually return correct data (this seems to be an issue with php-cgi and not this application) +- Running `make genCerts` will generate a root authority and generate certificates to utilize for the web server + - Certificate authority related files start with `ca` while the certificates which should be utilized for the web server omit the `ca` +- Making a request to the web server which does not match the current protocol (e.g. making a https request when it is server http) will result in the server ignoring the request + - Returning an error here is not possible since if we have a none SSL socket created we cannot respond to a SSL request + - This will cause a fork of the process to spawn which will be killed in 5 seconds after the timeout is met +- If a request to the root directory is made, `/`, it is assumed that the user was trying to navigate to `/index.html` and the request will be treated as such + diff --git a/cmd/server.c b/cmd/server.c index 7b78ff8..d497daa 100644 --- a/cmd/server.c +++ b/cmd/server.c @@ -15,6 +15,7 @@ #include "returnRequest.h" #include "server.h" #include "utils.h" +#include "requestHandlers.h" #define WEB_ROOT "/var/www/html/" //#define WEB_ROOT "content/" @@ -22,6 +23,7 @@ static int verbose_flag = 0; bool enableHTTPS = 0; +char *WEB_ROOT_DIR = NULL; static int timeout = 0; @@ -32,91 +34,6 @@ int printDebug(char message[]) { return 0; } -char *php_cgi(char *sPath, struct HTTPRequest *r) { - int phpPipe[2]; - char *buf = NULL; - size_t bufLen = 1024; - - buf = malloc(bufLen); - pipe(phpPipe); - - pid_t pid; - int status = 0; - pid = fork(); - - if (pid == 0) { // Child fork - char script[500]; - char *queryString = NULL; - close(phpPipe[0]); - dup2(phpPipe[1], STDOUT_FILENO); - strcpy(script, "SCRIPT_FILENAME="); - strcat(script, WEB_ROOT); - strcat(script, sPath); - putenv("GATEWAY_INTERFACE=CGI/1.1"); - putenv(script); - putenv("REDIRECT_STATUS=true"); - putenv("SERVER_PROTOCOL=HTTP/1.1"); - putenv("REMOTE_HOST=127.0.0.1"); - if (!strcmp(r->requestType, "POST")) { - putenv("REQUEST_METHOD=POST"); - char conLenString[256]; - sprintf(conLenString, "CONTENT_LENGTH=%zu", r->requestBodyLen); - putenv(conLenString); - putenv("CONTENT_TYPE=application/x-www-form-urlencoded"); - queryString = malloc(r->requestBodyLen + 24); - sprintf(queryString, "QUERY_STRING=%s", r->requestBody); - putenv(queryString); - - // Starting fork to pipe stdin into php-cgi - int phpPipe2[2]; - pipe(phpPipe2); - pid_t pid2; - pid2 = fork(); - - if (pid2 == 0) { // Child fork - close(phpPipe2[0]); - dup2(phpPipe2[1], STDOUT_FILENO); - printf("%s", r->requestBody); - close(phpPipe2[1]); - exit(EXIT_SUCCESS); - } else if (pid < 0) { // Error forking - printDebug("Error in stdin php frok"); - } else { // Parent fork - close(phpPipe[1]); - dup2(phpPipe2[0], STDIN_FILENO); - execlp("/usr/bin/php-cgi", "php-cgi", NULL); - } - } else { - queryString = malloc(strlen(r->requestVars) + 24); - sprintf(queryString, "QUERY_STRING=%s", r->requestVars); - putenv(queryString); - putenv("REQUEST_METHOD=GET"); - execl("/usr/bin/php-cgi", "php-cgi", NULL); - } - } else if (pid < 0) { // Error forking - printDebug("Error forking php exec"); - } else { // Parent fork - size_t buffCount; - close(phpPipe[1]); - do { - buffCount = read(phpPipe[0], buf, BUFF_READ); - if (strlen(buf) == bufLen) { - bufLen *= 2; - buf = realloc(buf, bufLen); - } - } while (buffCount == 0); - do { - waitpid(pid, &status, WUNTRACED); - } while (!WIFEXITED(status) && !WIFSIGNALED(status)); - } - - close(phpPipe[0]); - if (status != 0) { - return NULL; - } - return buf; -} - int parseHTTPRequest(unsigned char *buffer, struct HTTPRequest *r) { char temp[1]; // Used to check newlines char *token = calloc(8, sizeof(char)); @@ -219,171 +136,6 @@ int parseHTTPRequest(unsigned char *buffer, struct HTTPRequest *r) { return 0; } -int handleGetRequest(int socket, struct HTTPRequest *r, SSL *ssl) { - char errResponse[256]; - char ch; - size_t size = 8; - int i = 0; - unsigned char *fileContent = calloc(size, sizeof(unsigned char)); - FILE *fp; - char *workingReqDir; - - char *phpReturn = NULL; - char phpEnd[5] = ".php"; - bool endsWithPhp = false; - if (strlen(phpEnd) <= strlen(r->requestDir)) { - for (int i = 0; i < strlen(phpEnd); i++) { - if (r->requestDir[i + strlen(r->requestDir) - strlen(phpEnd)] != phpEnd[i]) { - endsWithPhp = false; - break; - } - endsWithPhp = true; - } - } - - if (endsWithPhp) { - phpReturn = php_cgi(r->requestDir, r); - if (phpReturn != NULL) { - return returnPHPRequest(socket, phpReturn, ssl); - } else { - return return500Request(socket, ssl); - } - } - - // If requesting root directory change to index.html - if (!strcmp(r->requestDir, "/")) { - workingReqDir = "index.html"; - } else { - workingReqDir = r->requestDir; - } - char *reqDir = calloc((strlen(WEB_ROOT) + strlen(workingReqDir) + 1), sizeof(char)); - - sprintf(reqDir, "%s%s", WEB_ROOT, workingReqDir); - - fp = fopen(reqDir, "r"); - - if (fp == NULL) { - sprintf(errResponse, "Error opening file: %s", workingReqDir); - printDebug(errResponse); - return404Request(socket, ssl); - return -1; - } - - while((ch = fgetc(fp)) != EOF) { - if (i == size) { - size *= 2; - fileContent = realloc(fileContent, size); - } - fileContent[i] = ch; - i++; - } - - return200Request(socket, fileContent, ssl); - - fclose(fp); - free(reqDir); - free(fileContent); - return 0; -} - -int handlePUTRequest(int socket, struct HTTPRequest *r, SSL *ssl) { - FILE *fp; - char *reqDir; - char * workingReqDir; - char errResponse[256]; - - if (!strcmp(r->requestDir, "/")) { - workingReqDir = "index.html"; - } else { - workingReqDir = r->requestDir; - } - - reqDir = calloc(strlen(WEB_ROOT) + strlen(workingReqDir), sizeof(char)); - sprintf(reqDir, "%s%s", WEB_ROOT, workingReqDir); - - fp = fopen(reqDir, "w"); - if (fp == NULL) { - sprintf(errResponse, "Error opening file: %s", workingReqDir); - printDebug(errResponse); - return return404Request(socket, ssl); - } - - fprintf(fp, "%s", r->requestBody); - - free(reqDir); - fclose(fp); - return return201Request(socket, r->requestBody, ssl); -} - -int handleDELETERequest(int socket, struct HTTPRequest *r, SSL *ssl) { - char *reqDir; - char * workingReqDir; - char logLine[256]; - - if (!strcmp(r->requestDir, "/")) { - workingReqDir = "index.html"; - } else { - workingReqDir = r->requestDir; - } - - reqDir = calloc(strlen(WEB_ROOT) + strlen(workingReqDir), sizeof(char)); - sprintf(reqDir, "%s%s", WEB_ROOT, workingReqDir); - - if (remove(reqDir) == 0) { - sprintf(logLine, "Deleted file"); - free(reqDir); - return return200Request(socket, NULL, ssl); - } else { - printDebug("Failed to delete file"); - free(reqDir); - if (errno == 1) { // Permission denided - return return403Request(socket, ssl); - } else { // Catch all (likely file != exist) - return return404Request(socket, ssl); - } - } - return 0; -} - -int handlePOSTRequest(int socket, struct HTTPRequest *r, SSL *ssl) { - char *phpReturn = NULL; - // Supported data types application/x-www-form-urlencoded application/json - if (r->requestConLen == NULL) { // Return 411 if length var not specified - printDebug("Content Length was not sent in POST request"); - return return411Request(socket, ssl); - } - - if (r->requestConType != NULL) { - if (!strcmp(r->requestConType, "application/x-www-form-utlencoded") == 0) { - printDebug("Application From Selected"); - } else { - printDebug("Content will likely get parsed wrong"); - } - } - - char phpEnd[5] = ".php"; - bool endsWithPhp = false; - if (strlen(phpEnd) <= strlen(r->requestDir)) { - for (int i = 0; i < strlen(phpEnd); i++) { - if (r->requestDir[i + strlen(r->requestDir) - strlen(phpEnd)] != phpEnd[i]) { - endsWithPhp = false; - break; - } - endsWithPhp = true; - } - } - - if (endsWithPhp) { - phpReturn = php_cgi(r->requestDir, r); - if (phpReturn != NULL) { - return returnPHPRequest(socket, phpReturn, ssl); - } - } else { - return return200Request(socket, NULL, ssl); - } - return return500Request(socket, ssl); -} - int handleRequest(unsigned char buffer[], int socket, SSL *ssl) { struct HTTPRequest r; // Holds relevant HTTP request information r.requestConLen = malloc(sizeof(char)); @@ -453,6 +205,10 @@ int main(int argc, char **argv) { size_t bufSize = BUFF_READ; unsigned char *buffer = calloc(bufSize, sizeof(unsigned char)); + // Copy WEB_ROOT into extern value + WEB_ROOT_DIR = malloc(strlen(WEB_ROOT)); + strcpy(WEB_ROOT_DIR, WEB_ROOT); + // Setting up options static const struct option long_options[] = { {"help", no_argument, NULL, 'h'}, @@ -625,6 +381,7 @@ int main(int argc, char **argv) { free(certFile); free(listenAddr); free(buffer); + free(WEB_ROOT_DIR); close(server_fd); exit(EXIT_SUCCESS); } diff --git a/entrypoint.sh b/entrypoint.sh index aa847b3..8e0b0f9 100644 --- a/entrypoint.sh +++ b/entrypoint.sh @@ -2,6 +2,4 @@ set -e -echo "$@" - -exec seaweb $@ +exec seaweb "$@" diff --git a/include/httpStruct.h b/include/httpStruct.h index e31097e..c47d3de 100644 --- a/include/httpStruct.h +++ b/include/httpStruct.h @@ -13,3 +13,4 @@ struct HTTPRequest { unsigned char *requestBody; size_t requestBodyLen; }; + diff --git a/include/requestHandlers.h b/include/requestHandlers.h new file mode 100644 index 0000000..2aa043e --- /dev/null +++ b/include/requestHandlers.h @@ -0,0 +1,6 @@ + +int handleGetRequest(int socket, struct HTTPRequest *r, SSL *ssl); +int handlePUTRequest(int socket, struct HTTPRequest *r, SSL *ssl); +int handleDELETERequest(int socket, struct HTTPRequest *r, SSL *ssl); +int handlePOSTRequest(int socket, struct HTTPRequest *r, SSL *ssl); + diff --git a/include/server.h b/include/server.h index d871840..8ebc773 100644 --- a/include/server.h +++ b/include/server.h @@ -1,4 +1,7 @@ #include -extern bool enableHTTPS; +int printDebug(char message[]); + +extern bool enableHTTPS; +extern char *WEB_ROOT_DIR; diff --git a/include/utils.h b/include/utils.h index d21ab81..dedd667 100644 --- a/include/utils.h +++ b/include/utils.h @@ -1,3 +1,5 @@ + int PrintLog(unsigned char *message); int checkHTTPVersion(char *version); +char *php_cgi(char *sPath, struct HTTPRequest *r); diff --git a/src/requestHandlers.c b/src/requestHandlers.c new file mode 100644 index 0000000..8d8206e --- /dev/null +++ b/src/requestHandlers.c @@ -0,0 +1,177 @@ +//#include +//#include +//#include +#include +#include +#include + +#include "httpStruct.h" +#include "returnRequest.h" +#include "server.h" +#include "utils.h" + +int handleGetRequest(int socket, struct HTTPRequest *r, SSL *ssl) { + char errResponse[256]; + char ch; + size_t size = 8; + int i = 0; + unsigned char *fileContent = calloc(size, sizeof(unsigned char)); + FILE *fp; + char *workingReqDir; + + char *phpReturn = NULL; + char phpEnd[5] = ".php"; + bool endsWithPhp = false; + if (strlen(phpEnd) <= strlen(r->requestDir)) { + for (int i = 0; i < strlen(phpEnd); i++) { + if (r->requestDir[i + strlen(r->requestDir) - strlen(phpEnd)] != phpEnd[i]) { + endsWithPhp = false; + break; + } + endsWithPhp = true; + } + } + + if (endsWithPhp) { + phpReturn = php_cgi(r->requestDir, r); + if (phpReturn != NULL) { + return returnPHPRequest(socket, phpReturn, ssl); + } else { + return return500Request(socket, ssl); + } + } + + // If requesting root directory change to index.html + if (!strcmp(r->requestDir, "/")) { + workingReqDir = "index.html"; + } else { + workingReqDir = r->requestDir; + } + char *reqDir = calloc((strlen(WEB_ROOT_DIR) + strlen(workingReqDir) + 1), sizeof(char)); + + sprintf(reqDir, "%s%s", WEB_ROOT_DIR, workingReqDir); + + fp = fopen(reqDir, "r"); + + if (fp == NULL) { + sprintf(errResponse, "Error opening file: %s", workingReqDir); + printDebug(errResponse); + return404Request(socket, ssl); + return -1; + } + + while((ch = fgetc(fp)) != EOF) { + if (i == size) { + size *= 2; + fileContent = realloc(fileContent, size); + } + fileContent[i] = ch; + i++; + } + + return200Request(socket, fileContent, ssl); + + fclose(fp); + free(reqDir); + free(fileContent); + return 0; +} + +int handlePUTRequest(int socket, struct HTTPRequest *r, SSL *ssl) { + FILE *fp; + char *reqDir; + char * workingReqDir; + char errResponse[256]; + + if (!strcmp(r->requestDir, "/")) { + workingReqDir = "index.html"; + } else { + workingReqDir = r->requestDir; + } + + reqDir = calloc(strlen(WEB_ROOT_DIR) + strlen(workingReqDir), sizeof(char)); + sprintf(reqDir, "%s%s", WEB_ROOT_DIR, workingReqDir); + + fp = fopen(reqDir, "w"); + if (fp == NULL) { + sprintf(errResponse, "Error opening file: %s", workingReqDir); + printDebug(errResponse); + return return404Request(socket, ssl); + } + + fprintf(fp, "%s", r->requestBody); + + free(reqDir); + fclose(fp); + return return201Request(socket, r->requestBody, ssl); +} + +int handleDELETERequest(int socket, struct HTTPRequest *r, SSL *ssl) { + char *reqDir; + char * workingReqDir; + char logLine[256]; + + if (!strcmp(r->requestDir, "/")) { + workingReqDir = "index.html"; + } else { + workingReqDir = r->requestDir; + } + + reqDir = calloc(strlen(WEB_ROOT_DIR) + strlen(workingReqDir), sizeof(char)); + sprintf(reqDir, "%s%s", WEB_ROOT_DIR, workingReqDir); + + if (remove(reqDir) == 0) { + sprintf(logLine, "Deleted file"); + free(reqDir); + return return200Request(socket, NULL, ssl); + } else { + printDebug("Failed to delete file"); + free(reqDir); + if (errno == 1) { // Permission denided + return return403Request(socket, ssl); + } else { // Catch all (likely file != exist) + return return404Request(socket, ssl); + } + } + return 0; +} + +int handlePOSTRequest(int socket, struct HTTPRequest *r, SSL *ssl) { + char *phpReturn = NULL; + // Supported data types application/x-www-form-urlencoded application/json + if (r->requestConLen == NULL) { // Return 411 if length var not specified + printDebug("Content Length was not sent in POST request"); + return return411Request(socket, ssl); + } + + if (r->requestConType != NULL) { + if (!strcmp(r->requestConType, "application/x-www-form-utlencoded") == 0) { + printDebug("Application From Selected"); + } else { + printDebug("Content will likely get parsed wrong"); + } + } + + char phpEnd[5] = ".php"; + bool endsWithPhp = false; + if (strlen(phpEnd) <= strlen(r->requestDir)) { + for (int i = 0; i < strlen(phpEnd); i++) { + if (r->requestDir[i + strlen(r->requestDir) - strlen(phpEnd)] != phpEnd[i]) { + endsWithPhp = false; + break; + } + endsWithPhp = true; + } + } + + if (endsWithPhp) { + phpReturn = php_cgi(r->requestDir, r); + if (phpReturn != NULL) { + return returnPHPRequest(socket, phpReturn, ssl); + } + } else { + return return200Request(socket, NULL, ssl); + } + return return500Request(socket, ssl); +} + diff --git a/src/returnRequest.c b/src/returnRequest.c index 8d7392a..11bab17 100644 --- a/src/returnRequest.c +++ b/src/returnRequest.c @@ -39,6 +39,12 @@ int return201Request(int socket, char *content, SSL *ssl) { return returnRequest(socket, message, 201, ssl); } +int return400Request(int socket, SSL *ssl) { + char *message = calloc(128, sizeof(char)); + sprintf(message, "HTTP/1.1 400 HTTP Request Not Valid\nContent-Length: 0\nConnection: close\n\n"); + return returnRequest(socket, message, 400, ssl); +} + int return403Request(int socket, SSL *ssl) { char *message = calloc(128, sizeof(char)); sprintf(message, "HTTP/1.1 403 Forbidden\nContent-Length: 0\nConnection: close\n\n"); @@ -47,16 +53,10 @@ int return403Request(int socket, SSL *ssl) { int return404Request(int socket, SSL *ssl) { char *message = calloc(128, sizeof(char)); - sprintf(message, "HTTP/1.1 404 Not Found\nContent-Length: 12\nConnection: close\n\n404 Request\n\n"); + sprintf(message, "HTTP/1.1 404 Not Found\nContent-Length: 13\nConnection: close\n\n404 Request\n\n"); return returnRequest(socket, message, 404, ssl); } -int return400Request(int socket, SSL *ssl) { - char *message = calloc(128, sizeof(char)); - sprintf(message, "HTTP/1.1 400 HTTP Request Not Valid\nContent-Length: 0\nConnection: close\n\n"); - return returnRequest(socket, message, 400, ssl); -} - int return411Request(int socket, SSL *ssl) { char *message = calloc(128, sizeof(char)); sprintf(message, "HTTP/1.1 411 Length Required\nContent-Length: 0\nConnection: close\n\n"); diff --git a/src/utils.c b/src/utils.c index a804c5e..dd3fad7 100644 --- a/src/utils.c +++ b/src/utils.c @@ -1,6 +1,14 @@ #include +#include #include #include +#include +#include + +#include "server.h" +#include "httpStruct.h" + +#define BUFF_READ 1024 #define NUM_SUPPORTED_VERSIONS 2 static char supportedHTTPVersions[NUM_SUPPORTED_VERSIONS][16] = { @@ -14,8 +22,17 @@ int PrintLog(unsigned char *message) { time(&UTCTime); struct tm *now = localtime(&UTCTime); - printf("[Log] %02d/%02d/%d %02d:%02d:%02d - %s\n", (now->tm_mon + 1), now->tm_mday, + if (!strcmp(WEB_ROOT_DIR, "/var/www/html/")) { + FILE *fp; + fp = fopen("/var/log/seaweb/log", "w"); + fprintf(fp, "[Log] %02d/%02d/%d %02d:%02d:%02d - %s\n", (now->tm_mon + 1), now->tm_mday, + (now->tm_year + 1900), now->tm_hour, now->tm_min, now->tm_sec, message); + fclose(fp); + } else { + printf("[Log] %02d/%02d/%d %02d:%02d:%02d - %s\n", (now->tm_mon + 1), now->tm_mday, (now->tm_year + 1900), now->tm_hour, now->tm_min, now->tm_sec, message); + } + return 0; } @@ -30,3 +47,89 @@ int checkHTTPVersion(char *version) { } return supported; } + +char *php_cgi(char *sPath, struct HTTPRequest *r) { + int phpPipe[2]; + char *buf = NULL; + size_t bufLen = 1024; + + buf = malloc(bufLen); + pipe(phpPipe); + + pid_t pid; + int status = 0; + pid = fork(); + + if (pid == 0) { // Child fork + char script[500]; + char *queryString = NULL; + close(phpPipe[0]); + dup2(phpPipe[1], STDOUT_FILENO); + strcpy(script, "SCRIPT_FILENAME="); + strcat(script, WEB_ROOT_DIR); + strcat(script, sPath); + putenv("GATEWAY_INTERFACE=CGI/1.1"); + putenv(script); + putenv("REDIRECT_STATUS=true"); + putenv("SERVER_PROTOCOL=HTTP/1.1"); + putenv("REMOTE_HOST=127.0.0.1"); + if (!strcmp(r->requestType, "POST")) { + putenv("REQUEST_METHOD=POST"); + char conLenString[256]; + sprintf(conLenString, "CONTENT_LENGTH=%zu", r->requestBodyLen); + putenv(conLenString); + putenv("CONTENT_TYPE=application/x-www-form-urlencoded"); + queryString = malloc(r->requestBodyLen + 24); + sprintf(queryString, "QUERY_STRING=%s", r->requestBody); + putenv(queryString); + + // Starting fork to pipe stdin into php-cgi + int phpPipe2[2]; + pipe(phpPipe2); + pid_t pid2; + pid2 = fork(); + + if (pid2 == 0) { // Child fork + close(phpPipe2[0]); + dup2(phpPipe2[1], STDOUT_FILENO); + printf("%s", r->requestBody); + close(phpPipe2[1]); + exit(EXIT_SUCCESS); + } else if (pid < 0) { // Error forking + printDebug("Error in stdin php frok"); + } else { // Parent fork + close(phpPipe[1]); + dup2(phpPipe2[0], STDIN_FILENO); + execlp("/usr/bin/php-cgi", "php-cgi", NULL); + } + } else { + queryString = malloc(strlen(r->requestVars) + 24); + sprintf(queryString, "QUERY_STRING=%s", r->requestVars); + putenv(queryString); + putenv("REQUEST_METHOD=GET"); + execl("/usr/bin/php-cgi", "php-cgi", NULL); + } + } else if (pid < 0) { // Error forking + printDebug("Error forking php exec"); + } else { // Parent fork + size_t buffCount; + close(phpPipe[1]); + do { + buffCount = read(phpPipe[0], buf, BUFF_READ); + if (strlen(buf) == bufLen) { + bufLen *= 2; + buf = realloc(buf, bufLen); + } + } while (buffCount == 0); + do { + waitpid(pid, &status, WUNTRACED); + } while (!WIFEXITED(status) && !WIFSIGNALED(status)); + } + + close(phpPipe[0]); + if (status != 0) { + return NULL; + } + return buf; +} +