summaryrefslogtreecommitdiff
path: root/www/pserv/files/patch-handlers.c
diff options
context:
space:
mode:
authorNorikatsu Shigemura <nork@FreeBSD.org>2003-10-17 08:11:55 +0000
committerNorikatsu Shigemura <nork@FreeBSD.org>2003-10-17 08:11:55 +0000
commit148e621cf93c5996d66f69a43ed8e95e985439ff (patch)
tree3c1c6f9533ea58f6b3ec476deef054fb9d5f0d04 /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.c362
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);
+ }