diff options
author | Norikatsu Shigemura <nork@FreeBSD.org> | 2003-10-17 08:11:55 +0000 |
---|---|---|
committer | Norikatsu Shigemura <nork@FreeBSD.org> | 2003-10-17 08:11:55 +0000 |
commit | 148e621cf93c5996d66f69a43ed8e95e985439ff (patch) | |
tree | 3c1c6f9533ea58f6b3ec476deef054fb9d5f0d04 /www/pserv/files/patch-handlers.c | |
parent | - Fix build (diff) |
Add pserv 3.0.b1, a portable and small webserver written in C.
PR: ports/58119
Submitted by: Alex Dupre <sysadmin@alexdupre.com>
Notes
Notes:
svn path=/head/; revision=91495
Diffstat (limited to 'www/pserv/files/patch-handlers.c')
-rw-r--r-- | www/pserv/files/patch-handlers.c | 362 |
1 files changed, 362 insertions, 0 deletions
diff --git a/www/pserv/files/patch-handlers.c b/www/pserv/files/patch-handlers.c new file mode 100644 index 000000000000..2a943605a18d --- /dev/null +++ b/www/pserv/files/patch-handlers.c @@ -0,0 +1,362 @@ +--- handlers.c.orig Thu Sep 18 15:26:48 2003 ++++ handlers.c Thu Oct 16 14:16:05 2003 +@@ -24,6 +24,7 @@ + #endif + + extern char cgiRoot[MAX_PATH_LEN+1]; /* root for CGI scripts exec */ ++extern char homePath[MAX_PATH_LEN+1]; /* root for PHP scripts exec */ + extern int port; /* server port */ + extern char defaultFileName[MAX_PATH_LEN+1]; /* default name for index, default or similar file */ + +@@ -262,12 +263,33 @@ + newArgv[i] = NULL; /* we correctly terminate argv */ + + i = 0; ++ if (req.contentLength != -1) ++ { ++ sprintf(newEnvp[i++], "CONTENT_LENGTH=%ld", req.contentLength); ++ strcpy(newEnvp[i], "CONTENT_TYPE="); ++ strcat(newEnvp[i++], req.contentType); ++ } ++ strcpy(newEnvp[i], "SERVER_NAME="); ++ strcat(newEnvp[i++], DEFAULT_SERVER_NAME); + strcpy(newEnvp[i], "SERVER_SOFTWARE="); + strcat(newEnvp[i], SERVER_SOFTWARE_STR); + strcat(newEnvp[i], "/"); + strcat(newEnvp[i++], SERVER_VERSION_STR); ++ strcpy(newEnvp[i], "SERVER_PROTOCOL="); ++ strcat(newEnvp[i++], req.protocolVersion); + strcpy(newEnvp[i], "REQUEST_METHOD="); + strcat(newEnvp[i++], req.method); ++ strcpy(newEnvp[i], "REMOTE_ADDR="); ++ strcat(newEnvp[i++], req.address); ++ strcpy(newEnvp[i], "HTTP_USER_AGENT="); ++ strcat(newEnvp[i++], req.userAgent); ++ if (req.cookie[0] != '\0') ++ { ++ strcpy(newEnvp[i], "HTTP_COOKIE="); ++ strcat(newEnvp[i++], req.cookie); ++ } ++ strcpy(newEnvp[i], "SCRIPT_FILENAME="); ++ strcat(newEnvp[i++], completedPath); + strcpy(newEnvp[i], "SCRIPT_NAME="); + strcat(newEnvp[i++], req.documentAddress); + strcpy(newEnvp[i], "GATEWAY_INTERFACE="); +@@ -302,13 +324,256 @@ + execve(completedPath, newArgv, newEnvp); + /* we reach this line only if an execution error occoured */ + /* logging will happen in the father */ +- printf("\n<HTML><HEAD><TITLE>CGI Error</TITLE></HEAD><BODY><H1>Cgi Exec error</H1></BODY></HTML>\n"); ++ printf("\n<HTML><HEAD><TITLE>CGI Error</TITLE></HEAD><BODY><H1>CGI Exec error</H1></BODY></HTML>\n"); + exit(-1); + } + return 0; + } + +-int dumpHeader(sock, filePath, mimeType, req) ++ ++#ifdef PHP ++int phpHandler(port, sock, phpFileName, completedPath, req, postStr) ++int port; ++int sock; ++char *phpFileName; ++char *completedPath; ++struct request req; ++char *postStr; ++{ ++ char envPath[MAX_PATH_LEN+1]; /* where to hold the envrion PATH parameter */ ++ char *relativePath; ++ char scriptWorkingDir[MAX_PATH_LEN+1]; ++ char **newArgv; ++ char **newEnvp; ++ int i; ++ int outStdPipe[2]; /* we will redirect the script output to a pipe so we can read it */ ++ int inStdPipe[2]; /* we will redirect the script input to a pipe so we can read it */ ++ int pid; /* we fork and execute inside the child the script */ ++ char pipeReadBuf[PIPE_READ_BUF+1]; ++ int howMany; ++ int totalSentFromPipe; /* ampunt of bytes sucked from the pipe and pushed in to the socket */ ++ int fatal; ++ ++ relativePath = strrchr(completedPath, '/'); ++ strncpy(scriptWorkingDir, completedPath, strlen(completedPath) - strlen(relativePath)); ++ scriptWorkingDir[strlen(completedPath) - strlen(relativePath)] = '\0'; ++ ++ /* first we create the pipes needed for stdout redirection */ ++ if (pipe(outStdPipe)) ++ { ++#ifdef PRINTF_DEBUG ++ printf("Pipe creation error\n"); ++ return -1; ++#endif ++ } ++ if (pipe(inStdPipe)) ++ { ++#ifdef PRINTF_DEBUG ++ printf("Pipe creation error\n"); ++ return -1; ++#endif ++ } ++ ++ ++ /* now we fork to subsequently execve */ ++ pid = fork(); ++ if (pid) ++ { /* this is the parent process */ ++ if (pid < 0) ++ { /* we check for creation error */ ++ printf ("Forking error during cgi exec: %d\n", errno); ++ return -1; ++ } ++ /* we close the unused end of the pipe */ ++ close(outStdPipe[WRITE]); ++ close(inStdPipe[READ]); ++ ++ if (!strcmp(req.method, "POST")) /* we have to feed the stdin of the script */ ++ { ++ if(!strlen(postStr)) ++ { ++#ifdef PRINTF_DEBUG ++ printf("cannot post empty data\n"); ++#endif ++ return -1; ++ } ++ howMany = write(inStdPipe[WRITE], postStr, strlen(postStr)); ++ if (howMany < 0) ++ printf("Error during script pipe read.\n"); ++ } ++ totalSentFromPipe = 0; ++ fatal = NO; ++ howMany = 1; ++ while (howMany > 0 && !fatal) ++ { ++ howMany = read(outStdPipe[READ], &pipeReadBuf, PIPE_READ_BUF); ++ if (howMany < 0) ++ printf("Error during script pipe read.\n"); ++ else if (!howMany) ++ printf("Nothing read from script pipe.\n"); ++ else { ++ pipeReadBuf[howMany] = '\0'; ++ if (send(sock, pipeReadBuf, howMany, 0) < 0) ++ { ++ printf("error during CGI sock writing! %d\n", errno); ++ if (errno == EAGAIN) ++ printf("output resource temporarily not available\n"); ++ else if (errno == EPIPE) ++ { ++ printf("broken pipe during CGI out.\n"); ++ fatal = YES; ++ } else if (errno == EBADF) ++ { ++#ifdef PRINTF_DEBUG ++ printf("invalid out descriptor.\n"); ++#endif ++ fatal = YES; ++ } ++ } else ++ totalSentFromPipe += howMany; ++ } ++ } ++ /* now we finished and we clean up */ ++ wait(&i); ++ if (i) /* check if execution exited cleanly or with code */ ++ logWriter(LOG_CGI_FAILURE, NULL, 0, req, i); ++ else ++ logWriter(LOG_CGI_SUCCESS, NULL, totalSentFromPipe, req, 0); ++ close(outStdPipe[READ]); ++ close(inStdPipe[WRITE]); ++ } else ++ { /* this is the child process */ ++ /* now we do some environment setup work */ ++ newArgv = calloc(MAX_ARGV_LEN + 1, sizeof(char*)); ++ for (i = 0; i < MAX_ARGV_LEN + 1; i++) ++ { ++ newArgv[i] = calloc(MAX_PATH_LEN, sizeof(char)); ++ } ++ ++ newEnvp = calloc(MAX_ENVP_LEN + 1, sizeof(char*)); ++ for (i = 0; i < MAX_ENVP_LEN + 1; i++) ++ { ++ newEnvp[i] = calloc(MAX_PATH_LEN, sizeof(char)); ++ } ++ ++ ++ ++ /* extracting PATH env variable */ ++ i = 0; ++ while (environ && strncmp(environ[i], PATH_MATCH_STRING, strlen(PATH_MATCH_STRING))) ++ i++; ++ if(environ[i]) ++ strcpy(envPath, environ[i]); ++ else ++ envPath[0] = '\0'; /* maybe we should set some default? */ ++ ++ i = 0; ++ strcpy(newArgv[i++], phpFileName); /* here we should pass the phppath */ ++ strcpy(newArgv[i++], completedPath); /* here we should pass the scriptpath */ ++ if (strlen(req.queryString)) ++ { ++ int toParse; ++ int j, k; ++ ++ toParse = YES; ++ j = strlen(req.queryString); ++ while (toParse && j > 0) ++ { ++ if (req.queryString[j] == '=') ++ toParse = NO; ++ j--; ++ } ++ if (toParse) ++ { ++ j = 0; ++ k = 0; ++ howMany = strlen(req.queryString); ++ while (j < howMany) ++ { ++ if (req.queryString[j] == '+') ++ { ++ newArgv[i++][k] = '\0'; ++ k = 0; ++ } else ++ newArgv[i][k++] = req.queryString[j]; ++ j++; ++ } ++ i++; /* after all we will have at least one argument! */ ++ } ++ } ++ newArgv[i] = NULL; /* we correctly terminate argv */ ++ ++ i = 0; ++ if (req.contentLength != -1) ++ { ++ sprintf(newEnvp[i++], "CONTENT_LENGTH=%ld", req.contentLength); ++ strcpy(newEnvp[i], "CONTENT_TYPE="); ++ strcat(newEnvp[i++], req.contentType); ++ } ++ strcpy(newEnvp[i], "SERVER_NAME="); ++ strcat(newEnvp[i++], DEFAULT_SERVER_NAME); ++ strcpy(newEnvp[i], "SERVER_SOFTWARE="); ++ strcat(newEnvp[i], SERVER_SOFTWARE_STR); ++ strcat(newEnvp[i], "/"); ++ strcat(newEnvp[i++], SERVER_VERSION_STR); ++ strcpy(newEnvp[i], "SERVER_PROTOCOL="); ++ strcat(newEnvp[i++], req.protocolVersion); ++ strcpy(newEnvp[i], "REQUEST_METHOD="); ++ strcat(newEnvp[i++], req.method); ++ strcpy(newEnvp[i], "REMOTE_ADDR="); ++ strcat(newEnvp[i++], req.address); ++ strcpy(newEnvp[i], "HTTP_USER_AGENT="); ++ strcat(newEnvp[i++], req.userAgent); ++ if (req.cookie[0] != '\0') ++ { ++ strcpy(newEnvp[i], "HTTP_COOKIE="); ++ strcat(newEnvp[i++], req.cookie); ++ } ++ strcpy(newEnvp[i], "SCRIPT_FILENAME="); ++ strcat(newEnvp[i++], completedPath); ++ strcpy(newEnvp[i], "SCRIPT_NAME="); ++ strcat(newEnvp[i++], req.documentAddress); ++ strcpy(newEnvp[i], "GATEWAY_INTERFACE="); ++ strcat(newEnvp[i++], CGI_VERSION); ++ sprintf(newEnvp[i++], "SERVER_PORT=%d", port); ++ strcpy(newEnvp[i++], envPath); ++ strcpy(newEnvp[i], "QUERY_STRING="); ++ strcat(newEnvp[i++], req.queryString); ++ newEnvp[i] = NULL; ++ ++ /* we change the current working directory to the scripts one */ ++ if(chdir(scriptWorkingDir)) ++ { ++#ifdef PRINTF_DEBUG ++ printf("error while changing PWD in script execution: %d\n", errno); ++#endif ++ } ++ ++ close(outStdPipe[READ]); /* we close the unused end*/ ++ dup2(outStdPipe[WRITE], 1); /* we duplicate the pipe to the stdout */ ++ close(outStdPipe[WRITE]); /* we close the pipe, since we use the duplicate */ ++ ++ close(inStdPipe[WRITE]); /* we close the unused end*/ ++ dup2(inStdPipe[READ], 0); /* we duplicate the pipe to the stdin */ ++ close(inStdPipe[READ]); /* we close the pipe, since we use the duplicate */ ++ ++ ++ /* generate a reduced mimeHeader, no type, no size, etc */ ++ generateMimeHeader(sock, 200, "", NULL, req.protocolVersion, CGI_ONLY_HEADER); ++ ++ /* now we execute the script replacing the current child */ ++ execve(phpFileName, newArgv, newEnvp); ++ /* we reach this line only if an execution error occoured */ ++ /* logging will happen in the father */ ++ printf("\n<HTML><HEAD><TITLE>PHP Error</TITLE></HEAD><BODY><H1>PHP Exec error</H1></BODY></HTML>\n"); ++ exit(-1); ++ } ++ return 0; ++} ++#endif ++ ++int dumpHeader(port, sock, filePath, mimeType, req) ++int port; + int sock; + char filePath[]; + char mimeType[]; +@@ -351,11 +616,11 @@ + return -1; + } + stat(filePath, &fileStats); +- generateMimeHeader(sock, 200, mimeType, &fileStats, req.protocolVersion, FULL_HEADER); +- logWriter(LOG_GET_SUCCESS, req.documentAddress, (long int)fileStats.st_size, req, 0); + howMany = 0; + if (strncmp(mimeType, "text", 4)) /* check if it is a text type */ + { /* raw binary output routine */ ++ generateMimeHeader(sock, 200, mimeType, &fileStats, req.protocolVersion, FULL_HEADER); ++ logWriter(LOG_GET_SUCCESS, req.documentAddress, (long int)fileStats.st_size, req, 0); + fatal = NO; + retry = NO; + while(!feof(inFile) && !fatal) +@@ -399,11 +664,11 @@ + if (howMany > 0) + { + #ifdef ON_THE_FLY_CONVERSION +- { +- int i; +- for (i = 0; i < howMany; i++) +- if(outBuff[i] == '\r') outBuff[i] = '\n'; +- } ++ { ++ int i; ++ for (i = 0; i < howMany; i++) ++ if(outBuff[i] == '\r') outBuff[i] = '\n'; ++ } + #endif + if (send(sock, outBuff, howMany, 0) < 0) + { +@@ -449,7 +714,7 @@ + FILE *tempFile; + size_t generatedBytes; + char tempStr[MAX_PATH_LEN+1]; +- char linkStr[MAX_PATH_LEN+1]; ++ char linkStr[MAX_PATH_LEN+2]; + time_t currTime; + char timeStr[256]; + +@@ -497,10 +762,16 @@ + if (strcmp(dp->d_name, ".")) /* not self */ + { + if (strcmp(dp->d_name, "..")) ++ { + strcpy(linkStr, dp->d_name); +- else ++ if (dp->d_type == DT_DIR) ++ strcat(linkStr, "/"); ++ sprintf(tempStr, "<A HREF=\"%s\">%s</A><BR>\n", linkStr, linkStr); ++ } else ++ { + strcpy(linkStr, "Parent Directory"); +- sprintf(tempStr, "<A HREF=\"%s\">%s</A><BR>\n", dp->d_name, linkStr); ++ sprintf(tempStr, "<A HREF=\"%s/\">%s</A><BR>\n", dp->d_name, linkStr); ++ } + generatedBytes += strlen(tempStr); + fprintf(tempFile, "%s\n", tempStr); + } |