Fix CGI I/O redirection and interposer tasks

git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@1988 42af7a65-404d-4744-a932-0658087f49c3
This commit is contained in:
patacongo 2009-07-18 18:04:05 +00:00
parent 59cf543804
commit 8c17e7f6d0
11 changed files with 788 additions and 714 deletions

View File

@ -12,7 +12,7 @@
<h1><big><font color="#3c34ec">
<i>NuttX RTOS Porting Guide</i>
</font></big></h1>
<p>Last Updated: July 12, 2009</p>
<p>Last Updated: July 18, 2009</p>
</td>
</tr>
</table>
@ -2384,10 +2384,6 @@ extern void up_ledoff(int led);
<code>CONFIG_THTTPD_CGI_TIMELIMIT</code>: How many seconds to allow CGI programs
to run before killing them.
</li>
<li>
<code>CONFIG_THTTPD_CGI_OUTFD</code>: In NuttX, CGI cannot use stdout for output.
Rather, it must use this file descriptor number.
</li>
<li>
<code>CONFIG_THTTPD_CHARSET- The default character set name to use with
text MIME types.

View File

@ -369,8 +369,6 @@ defconfig -- This is a configuration file similar to the Linux
CONFIG_THTTPD_CGI_BYTECOUNT - Byte output limit for CGI tasks.
CONFIG_THTTPD_CGI_TIMELIMIT - How many seconds to allow CGI programs
to run before killing them.
CONFIG_THTTPD_CGI_OUTFD - In NuttX, CGI cannot use stdout for output.
Rather, it must use this file descriptor number.
CONFIG_THTTPD_CHARSET- The default character set name to use with
text MIME types.
CONFIG_THTTPD_IOBUFFERSIZE -

View File

@ -494,8 +494,6 @@ CONFIG_NET_RESOLV_ENTRIES=4
# CONFIG_THTTPD_CGI_BYTECOUNT - Byte output limit for CGI tasks.
# CONFIG_THTTPD_CGI_TIMELIMIT - How many seconds to allow CGI programs
# to run before killing them.
# CONFIG_THTTPD_CGI_OUTFD - In NuttX, CGI cannot use stdout for output.
# Rather, it must use this file descriptor number.
# CONFIG_THTTPD_CHARSET- The default character set name to use with
# text MIME types.
# CONFIG_THTTPD_IOBUFFERSIZE -
@ -544,7 +542,6 @@ CONFIG_THTTPD_CGI_PRIORITY=50
CONFIG_THTTPD_CGI_STACKSIZE=1024
CONFIG_THTTPD_CGI_BYTECOUNT=20000
CONFIG_THTTPD_CGI_TIMELIMIT=0
#CONFIG_THTTPD_CGI_OUTFD
CONFIG_THTTPD_CHARSET="iso-8859-1"
CONFIG_THTTPD_IOBUFFERSIZE=256
#CONFIG_THTTPD_INDEX_NAMES

View File

@ -61,15 +61,9 @@
int main(int argc, char *argv[])
{
FILE *outstream;
fprintf(stderr, "phf CGI probe from %s\n", getenv("REMOTE_ADDR"));
outstream = fdopen(CONFIG_THTTPD_CGI_OUTFD, "w");
if (outstream)
{
(void)fprintf(outstream,
"\
(void)printf("\
Content-type: text/html\n\
Status: 404/html\n\
\n\
@ -79,7 +73,6 @@ The requested object does not exist on this server.\n\
The link you followed is either outdated, inaccurate,\n\
or the server has been instructed not to let you have it.\n\
</BODY></HTML>\n");
fclose(outstream);
return 0;
}
return 1;

View File

@ -98,12 +98,11 @@ static char g_url[LINE_SIZE];
* Private Functions
****************************************************************************/
static void internal_error(FILE *outstream, char *reason)
static void internal_error(char *reason)
{
char *title = "500 Internal Error";
(void)fprintf(outstream,
"\
(void)printf("\
Status: %s\n\
Content-type: text/html\n\
\n\
@ -116,12 +115,11 @@ Something unusual went wrong during a redirection request:\n\
</BODY></HTML>\n", title, title, title, reason);
}
static void not_found(FILE *outstream, char *script_name)
static void not_found(char *script_name)
{
char *title = "404 Not Found";
(void)fprintf(outstream,
"\
(void)printf("\
Status: %s\n\
Content-type: text/html\n\
\n\
@ -132,12 +130,11 @@ however, the new URL has not yet been specified.\n\
</BODY></HTML>\n", title, title, title, script_name);
}
static void moved(FILE *outstream, char *script_name, char *url)
static void moved(char *script_name, char *url)
{
char *title = "Moved";
(void)fprintf(outstream,
"\
(void)printf("\
Location: %s\n\
Content-type: text/html\n\
\n\
@ -154,7 +151,6 @@ The requested filename, %s, has moved to a new URL:\n\
int main(int argc, char **argv)
{
FILE *outstream;
char *script_name;
char *path_info;
char *cp = 0;
@ -162,14 +158,6 @@ int main(int argc, char **argv)
char *star;
int err = 0;
outstream = fdopen(CONFIG_THTTPD_CGI_OUTFD, "w");
if (!outstream)
{
fprintf(stderr, "fdopen failed: %d\n", errno);
err = 1;
goto errout;
}
/* Get the name that we were run as, which is the filename being **
* redirected.
*/
@ -177,9 +165,8 @@ int main(int argc, char **argv)
script_name = getenv("SCRIPT_NAME");
if (!script_name)
{
internal_error(outstream, "Couldn't get SCRIPT_NAME environment variable.");
err = 2;
goto errout_with_outstream;
internal_error("Couldn't get SCRIPT_NAME environment variable.");
return 1;
}
/* Append the PATH_INFO, if any. This allows redirection of whole **
@ -192,9 +179,8 @@ int main(int argc, char **argv)
cp = (char *)malloc(strlen(script_name) + strlen(path_info) + 1);
if (!cp)
{
internal_error(outstream, "Out of memory.");
err = 3;
goto errout_with_outstream;
internal_error("Out of memory.");
return 2;
}
(void)sprintf(cp, "%s%s", script_name, path_info);
@ -206,8 +192,8 @@ int main(int argc, char **argv)
fp = fopen(".redirects", "r");
if (fp == (FILE *) 0)
{
internal_error(outstream, "Couldn't open .redirects file.");
err = 4;
internal_error("Couldn't open .redirects file.");
err = 3;
goto errout_with_cp;
}
@ -251,7 +237,7 @@ int main(int argc, char **argv)
/* XXX Whack the script_name, too? */
moved(outstream, script_name, g_url);
moved(script_name, g_url);
goto success_out;
}
}
@ -262,7 +248,7 @@ int main(int argc, char **argv)
{
/* Got it. */
moved(outstream, script_name, g_url);
moved(script_name, g_url);
goto success_out;
}
}
@ -271,8 +257,8 @@ int main(int argc, char **argv)
/* No match found. */
not_found(outstream, script_name);
err = 5;
not_found(script_name);
err = 4;
success_out:
fclose(fp);
@ -281,8 +267,5 @@ errout_with_cp:
{
free(cp);
}
errout_with_outstream:
fclose(outstream);
errout:
return err;
}

View File

@ -78,7 +78,7 @@
* Private Function Prototypes
****************************************************************************/
static void read_file(FILE *outstream, FILE *instream, char *vfilename, char *filename);
static void read_file(FILE *instream, char *vfilename, char *filename);
/****************************************************************************
* Private Data
@ -96,12 +96,11 @@ static struct stat g_sb;
* Private Functions
****************************************************************************/
static void internal_error(FILE *outstream, char *reason)
static void internal_error(char *reason)
{
char *title = "500 Internal Error";
(void)fprintf(outstream,
"\
(void)printf("\
<HTML><HEAD><TITLE>%s</TITLE></HEAD>\n\
<BODY><H2>%s</H2>\n\
Something unusual went wrong during a server-side-includes request:\n\
@ -111,12 +110,11 @@ Something unusual went wrong during a server-side-includes request:\n\
</BODY></HTML>\n", title, title, reason);
}
static void not_found(FILE *outstream, char *filename)
static void not_found(char *filename)
{
char *title = "404 Not Found";
(void)fprintf(outstream,
"\
(void)printf("\
<HTML><HEAD><TITLE>%s</TITLE></HEAD>\n\
<BODY><H2>%s</H2>\n\
The requested server-side-includes filename, %s,\n\
@ -124,67 +122,62 @@ does not seem to exist.\n\
</BODY></HTML>\n", title, title, filename);
}
static void not_found2(FILE *outstream, char *directive, char *tag, char *filename)
static void not_found2(char *directive, char *tag, char *filename)
{
char *title = "Not Found";
(void)fprintf(outstream,
"\
(void)printf("\
<HR><H2>%s</H2>\n\
The filename requested in a %s %s directive, %s,\n\
does not seem to exist.\n\
<HR>\n", title, directive, tag, filename);
}
static void not_permitted(FILE *outstream, char *directive, char *tag, char *val)
static void not_permitted(char *directive, char *tag, char *val)
{
char *title = "Not Permitted";
(void)fprintf(outstream,
"\
(void)printf("\
<HR><H2>%s</H2>\n\
The filename requested in the %s %s=%s directive\n\
may not be fetched.\n\
<HR>\n", title, directive, tag, val);
}
static void unknown_directive(FILE *outstream, char *filename, char *directive)
static void unknown_directive(char *filename, char *directive)
{
char *title = "Unknown Directive";
(void)fprintf(outstream,
"\
(void)printf("\
<HR><H2>%s</H2>\n\
The requested server-side-includes filename, %s,\n\
tried to use an unknown directive, %s.\n\
<HR>\n", title, filename, directive);
}
static void unknown_tag(FILE *outstream, char *filename, char *directive, char *tag)
static void unknown_tag(char *filename, char *directive, char *tag)
{
char *title = "Unknown Tag";
(void)fprintf(outstream,
"\
(void)printf("\
<HR><H2>%s</H2>\n\
The requested server-side-includes filename, %s,\n\
tried to use the directive %s with an unknown tag, %s.\n\
<HR>\n", title, filename, directive, tag);
}
static void unknown_value(FILE *outstream, char *filename, char *directive, char *tag, char *val)
static void unknown_value(char *filename, char *directive, char *tag, char *val)
{
char *title = "Unknown Value";
(void)fprintf(outstream,
"\
(void)printf("\
<HR><H2>%s</H2>\n\
The requested server-side-includes filename, %s,\n\
tried to use the directive %s %s with an unknown value, %s.\n\
<HR>\n", title, filename, directive, tag, val);
}
static int get_filename(FILE *outstream, char *vfilename, char *filename,
static int get_filename(char *vfilename, char *filename,
char *directive, char *tag, char *val, char *fn,
int fnsize)
{
@ -205,7 +198,7 @@ static int get_filename(FILE *outstream, char *vfilename, char *filename,
{
if (strstr(val, "../") != (char *)0)
{
not_permitted(outstream, directive, tag, val);
not_permitted(directive, tag, val);
return -1;
}
@ -228,7 +221,7 @@ static int get_filename(FILE *outstream, char *vfilename, char *filename,
{
if (val[0] == '/' || strstr(val, "../") != (char *)0)
{
not_permitted(outstream, directive, tag, val);
not_permitted(directive, tag, val);
return -1;
}
if (fl + 1 + strlen(val) >= fnsize)
@ -247,7 +240,7 @@ static int get_filename(FILE *outstream, char *vfilename, char *filename,
}
else
{
unknown_tag(outstream, filename, directive, tag);
unknown_tag(filename, directive, tag);
return -1;
}
return 0;
@ -353,7 +346,7 @@ static int check_filename(char *filename)
return 1;
}
static void show_time(FILE *outstream, time_t t, int gmt)
static void show_time(time_t t, int gmt)
{
struct tm *tmP;
@ -368,40 +361,40 @@ static void show_time(FILE *outstream, time_t t, int gmt)
if (strftime(g_iobuffer2, BUFFER_SIZE, g_timeformat, tmP) > 0)
{
(void)fputs(g_iobuffer2, outstream);
(void)puts(g_iobuffer2);
}
}
static void show_size(FILE *outstream, off_t size)
static void show_size(off_t size)
{
switch (g_sizefmt)
{
case SF_BYTES:
(void)fprintf(outstream, "%ld", (long)size); /* spec says should have commas */
(void)printf("%ld", (long)size); /* spec says should have commas */
break;
case SF_ABBREV:
if (size < 1024)
{
(void)fprintf(outstream, "%ld", (long)size);
(void)printf("%ld", (long)size);
}
else if (size < 1024)
{
(void)fprintf(outstream, "%ldK", (long)size / 1024L);
(void)printf("%ldK", (long)size / 1024L);
}
else if (size < 1024 * 1024)
{
(void)fprintf(outstream, "%ldM", (long)size / (1024L * 1024L));
(void)printf("%ldM", (long)size / (1024L * 1024L));
}
else
{
(void)fprintf(outstream, "%ldG", (long)size / (1024L * 1024L * 1024L));
(void)printf("%ldG", (long)size / (1024L * 1024L * 1024L));
}
break;
}
}
static void do_config(FILE *outstream, FILE *instream, char *vfilename, char *filename,
static void do_config(FILE *instream, char *vfilename, char *filename,
char *directive, char *tag, char *val)
{
/* The config directive controls various aspects of the file parsing. **
@ -431,16 +424,16 @@ static void do_config(FILE *outstream, FILE *instream, char *vfilename, char *fi
}
else
{
unknown_value(outstream, filename, directive, tag, val);
unknown_value(filename, directive, tag, val);
}
}
else
{
unknown_tag(outstream, filename, directive, tag);
unknown_tag(filename, directive, tag);
}
}
static void do_include(FILE *outstream, FILE *instream, char *vfilename, char *filename,
static void do_include(FILE *instream, char *vfilename, char *filename,
char *directive, char *tag, char *val)
{
FILE *instream2;
@ -448,7 +441,7 @@ static void do_include(FILE *outstream, FILE *instream, char *vfilename, char *f
/* Inserts the text of another document into the parsed document. */
ret = get_filename(outstream, vfilename, filename, directive, tag, val, g_iobuffer1, BUFFER_SIZE);
ret = get_filename(vfilename, filename, directive, tag, val, g_iobuffer1, BUFFER_SIZE);
if (ret < 0)
{
return;
@ -456,14 +449,14 @@ static void do_include(FILE *outstream, FILE *instream, char *vfilename, char *f
if (!check_filename(g_iobuffer1))
{
not_permitted(outstream, directive, tag, g_iobuffer1);
not_permitted(directive, tag, g_iobuffer1);
return;
}
instream2 = fopen(g_iobuffer1, "r");
if (instream2 == (FILE *) 0)
{
not_found2(outstream, directive, tag, g_iobuffer1);
not_found2(directive, tag, g_iobuffer1);
return;
}
@ -498,11 +491,11 @@ static void do_include(FILE *outstream, FILE *instream, char *vfilename, char *f
}
}
read_file(outstream, instream2, g_iobuffer2, g_iobuffer1);
read_file(instream2, g_iobuffer2, g_iobuffer1);
(void)fclose(instream2);
}
static void do_echo(FILE *outstream, FILE *instream, char *vfilename, char *filename,
static void do_echo(FILE *instream, char *vfilename, char *filename,
char *directive, char *tag, char *val)
{
char *cp;
@ -515,7 +508,7 @@ static void do_echo(FILE *outstream, FILE *instream, char *vfilename, char *file
if (strcmp(tag, "var") != 0)
{
unknown_tag(outstream, filename, directive, tag);
unknown_tag(filename, directive, tag);
}
else
{
@ -523,13 +516,13 @@ static void do_echo(FILE *outstream, FILE *instream, char *vfilename, char *file
{
/* The current filename. */
(void)fputs(filename, outstream);
(void)puts(filename);
}
else if (strcmp(val, "DOCUMENT_URI") == 0)
{
/* The virtual path to this file (such as /~robm/foo.shtml). */
(void)fputs(vfilename, outstream);
(void)puts(vfilename);
}
else if (strcmp(val, "QUERY_STRING_UNESCAPED") == 0)
{
@ -538,7 +531,7 @@ static void do_echo(FILE *outstream, FILE *instream, char *vfilename, char *file
cp = getenv("QUERY_STRING");
if (cp != (char *)0)
{
(void)fputs(cp, outstream);
(void)puts(cp);
}
}
else if (strcmp(val, "DATE_LOCAL") == 0)
@ -548,7 +541,7 @@ static void do_echo(FILE *outstream, FILE *instream, char *vfilename, char *file
/* The current date, local time zone. */
gettimeofday(&tm, NULL);
show_time(outstream, tm.tv_sec, 0);
show_time(tm.tv_sec, 0);
}
else if (strcmp(val, "DATE_GMT") == 0)
{
@ -557,7 +550,7 @@ static void do_echo(FILE *outstream, FILE *instream, char *vfilename, char *file
/* Same as DATE_LOCAL but in Greenwich mean time. */
gettimeofday(&tm, NULL);
show_time(outstream, t, 1);
show_time(t, 1);
}
else if (strcmp(val, "LAST_MODIFIED") == 0)
{
@ -565,7 +558,7 @@ static void do_echo(FILE *outstream, FILE *instream, char *vfilename, char *file
if (fstat(fileno(instream), &g_sb) >= 0)
{
show_time(outstream, g_sb.st_mtime, 0);
show_time(g_sb.st_mtime, 0);
}
}
else
@ -575,24 +568,24 @@ static void do_echo(FILE *outstream, FILE *instream, char *vfilename, char *file
cp = getenv(val);
if (cp == (char *)0)
{
unknown_value(outstream, filename, directive, tag, val);
unknown_value(filename, directive, tag, val);
}
else
{
(void)fputs(cp, outstream);
(void)puts(cp);
}
}
}
}
static void do_fsize(FILE *outstream, FILE *instream, char *vfilename, char *filename,
static void do_fsize(FILE *instream, char *vfilename, char *filename,
char *directive, char *tag, char *val)
{
int ret;
/* Prints the size of the specified file. */
ret = get_filename(outstream, vfilename, filename, directive, tag, val, g_iobuffer1, BUFFER_SIZE);
ret = get_filename(vfilename, filename, directive, tag, val, g_iobuffer1, BUFFER_SIZE);
if (ret < 0)
{
return;
@ -600,21 +593,21 @@ static void do_fsize(FILE *outstream, FILE *instream, char *vfilename, char *fil
if (stat(g_iobuffer1, &g_sb) < 0)
{
not_found2(outstream, directive, tag, g_iobuffer1);
not_found2(directive, tag, g_iobuffer1);
return;
}
show_size(outstream, g_sb.st_size);
show_size(g_sb.st_size);
}
static void do_flastmod(FILE *outstream, FILE *instream, char *vfilename, char *filename,
static void do_flastmod(FILE *instream, char *vfilename, char *filename,
char *directive, char *tag, char *val)
{
int ret;
/* Prints the last modification date of the specified file. */
ret = get_filename(outstream, vfilename, filename, directive, tag, val, g_iobuffer1, BUFFER_SIZE);
ret = get_filename(vfilename, filename, directive, tag, val, g_iobuffer1, BUFFER_SIZE);
if (ret < 0)
{
return;
@ -622,13 +615,13 @@ static void do_flastmod(FILE *outstream, FILE *instream, char *vfilename, char *
if (stat(g_iobuffer1, &g_sb) < 0)
{
not_found2(outstream, directive, tag, g_iobuffer1);
not_found2(directive, tag, g_iobuffer1);
return;
}
show_time(outstream, g_sb.st_mtime, 0);
show_time(g_sb.st_mtime, 0);
}
static void parse(FILE *outstream, FILE *instream, char *vfilename, char *filename, char *str)
static void parse(FILE *instream, char *vfilename, char *filename, char *str)
{
char *directive;
char *cp;
@ -695,7 +688,7 @@ static void parse(FILE *outstream, FILE *instream, char *vfilename, char *filena
}
else
{
unknown_directive(outstream, filename, directive);
unknown_directive(filename, directive);
return;
}
@ -703,7 +696,7 @@ static void parse(FILE *outstream, FILE *instream, char *vfilename, char *filena
{
if (i > 0)
{
putc(' ', outstream);
putchar(' ');
}
val = strchr(g_tags[i], '=');
@ -725,29 +718,29 @@ static void parse(FILE *outstream, FILE *instream, char *vfilename, char *filena
switch (dirn)
{
case DI_CONFIG:
do_config(outstream, instream, vfilename, filename, directive, g_tags[i], val);
do_config(instream, vfilename, filename, directive, g_tags[i], val);
break;
case DI_INCLUDE:
do_include(outstream, instream, vfilename, filename, directive, g_tags[i], val);
do_include(instream, vfilename, filename, directive, g_tags[i], val);
break;
case DI_ECHO:
do_echo(outstream, instream, vfilename, filename, directive, g_tags[i], val);
do_echo(instream, vfilename, filename, directive, g_tags[i], val);
break;
case DI_FSIZE:
do_fsize(outstream, instream, vfilename, filename, directive, g_tags[i], val);
do_fsize(instream, vfilename, filename, directive, g_tags[i], val);
break;
case DI_FLASTMOD:
do_flastmod(outstream, instream, vfilename, filename, directive, g_tags[i], val);
do_flastmod(instream, vfilename, filename, directive, g_tags[i], val);
break;
}
}
}
static void slurp(FILE *outstream, FILE *instream, char *vfilename, char *filename)
static void slurp(FILE *instream, char *vfilename, char *filename)
{
int state;
int ich;
@ -783,7 +776,7 @@ static void slurp(FILE *outstream, FILE *instream, char *vfilename, char *filena
if (ich == '>')
{
g_iobuffer1[i - 2] = '\0';
parse(outstream, instream, vfilename, filename, g_iobuffer1);
parse(instream, vfilename, filename, g_iobuffer1);
return;
}
else if (ich != '-')
@ -800,7 +793,7 @@ static void slurp(FILE *outstream, FILE *instream, char *vfilename, char *filena
}
}
static void read_file(FILE *outstream, FILE *instream, char *vfilename, char *filename)
static void read_file(FILE *instream, char *vfilename, char *filename)
{
int ich;
int state;
@ -831,7 +824,7 @@ static void read_file(FILE *outstream, FILE *instream, char *vfilename, char *fi
else
{
state = ST_GROUND;
putc('<', outstream);
putchar('<');
}
break;
@ -844,7 +837,7 @@ static void read_file(FILE *outstream, FILE *instream, char *vfilename, char *fi
else
{
state = ST_GROUND;
(void)fputs("<!", outstream);
(void)puts("<!");
}
break;
@ -857,26 +850,26 @@ static void read_file(FILE *outstream, FILE *instream, char *vfilename, char *fi
else
{
state = ST_GROUND;
(void)fputs("<!-", outstream);
(void)puts("<!-");
}
break;
case ST_MINUS2:
if (ich == '#')
{
slurp(outstream, instream, vfilename, filename);
slurp(instream, vfilename, filename);
state = ST_GROUND;
continue;
}
else
{
state = ST_GROUND;
(void)fputs("<!--", outstream);
(void)puts("<!--");
}
break;
}
putc((char)ich, outstream);
putcchar((char)ich);
}
}
@ -886,21 +879,12 @@ static void read_file(FILE *outstream, FILE *instream, char *vfilename, char *fi
int main(int argc, char **argv)
{
FILE *outstream;
FILE *instream;
char *script_name;
char *path_info;
char *path_translated;
int err = 0;
outstream = fdopen(CONFIG_THTTPD_CGI_OUTFD, "w");
if (!outstream)
{
fprintf(stderr, "fdopen failed: %d\n", errno);
err = 1;
goto errout;
}
/* Default formats. */
(void)strcpy(g_timeformat, "%a %b %e %T %Z %Y");
@ -908,16 +892,15 @@ int main(int argc, char **argv)
/* The MIME type has to be text/html. */
(void)fputs("Content-type: text/html\n\n", outstream);
(voidfputs("Content-type: text/html\n\n");
/* Get the name that we were run as. */
script_name = getenv("SCRIPT_NAME");
if (!script_name)
{
internal_error(outstream, "Couldn't get SCRIPT_NAME environment variable.");
err = 2;
goto errout_with_outstream;
internal_error("Couldn't get SCRIPT_NAME environment variable.");
return 1;
}
/* Append the PATH_INFO, if any, to get the full URL. */
@ -931,9 +914,8 @@ int main(int argc, char **argv)
g_url = (char*)malloc(strlen(script_name) + strlen(path_info) + 1);
if (!g_url)
{
internal_error(outstream, "Out of memory.");
err = 3;
goto errout_with_outstream;
internal_error("Out of memory.");
return 2;
}
(void)sprintf(g_url, "%s%s", script_name, path_info);
@ -942,15 +924,15 @@ int main(int argc, char **argv)
path_translated = getenv("PATH_TRANSLATED");
if (!path_translated)
{
internal_error(outstream, "Couldn't get PATH_TRANSLATED environment variable.");
err = 4;
internal_error("Couldn't get PATH_TRANSLATED environment variable.");
err = 3;
goto errout_with_g_url;
}
if (!check_filename(path_translated))
{
not_permitted(outstream, "initial", "PATH_TRANSLATED", path_translated);
err = 5;
not_permitted("initial", "PATH_TRANSLATED", path_translated);
err = 4;
goto errout_with_g_url;
}
@ -959,21 +941,18 @@ int main(int argc, char **argv)
instream = fopen(path_translated, "r");
if (!instream)
{
not_found(outstream, path_translated);
err = 6;
not_found(path_translated);
err = 5;
goto errout_with_g_url;
}
/* Read and handle the file. */
read_file(outstream, instream, path_info, path_translated);
read_file(instream, path_info, path_translated);
(void)fclose(instream);
errout_with_g_url:
free(g_url);
errout_with_outstream:
fclose(outstream);
errout:
return err;
}

View File

@ -119,14 +119,6 @@
# define CONFIG_THTTPD_CGI_TIMELIMIT 0 /* No time limit */
#endif
/* In NuttX, CGI cannot use stdout for output. Rather, it must use
* the following file descriptor number.
*/
#ifndef CONFIG_THTTPD_CGI_OUTFD
# define CONFIG_THTTPD_CGI_OUTFD CONFIG_NFILE_DESCRIPTORS
#endif
/* The default character set name to use with text MIME types. */
#ifndef CONFIG_THTTPD_CHARSET

View File

@ -71,18 +71,9 @@
****************************************************************************/
#if defined(CONFIG_DEBUG) && defined(CONFIG_DEBUG_NET)
static long nwatches;
static long nwatches = 0;
#endif
static int *fd_rw;
static void **fd_data;
static struct pollfd *pollfds;
static int *poll_pollndx;
static int *poll_rfdidx;
static int npoll_fds;
static int nreturned;
static int next_rfndx;
/****************************************************************************
* Private Function Prototypes
****************************************************************************/
@ -97,87 +88,123 @@ static int next_rfndx;
/* Initialize the fdwatch data structures. Returns -1 on failure. */
int fdwatch_initialize(void)
struct fdwatch_s *fdwatch_initialize(int nfds)
{
struct fdwatch_s *fw;
int i;
/* Allocate the fdwatch data structure */
fw = (struct fdwatch_s*)zalloc(sizeof(struct fdwatch_s));
if (!fw)
{
ndbg("Failed to allocate fdwatch\n");
return NULL;
}
/* Initialize the fdwatch data structures. */
#if defined(CONFIG_DEBUG) && defined(CONFIG_DEBUG_NET)
nwatches = 0;
#endif
fw->nfds = nfds;
fd_rw = (int *)malloc(sizeof(int) * CONFIG_NSOCKET_DESCRIPTORS);
if (!fd_rw)
fw->fd_rw = (int*)malloc(sizeof(int) * nfds);
if (!fw->fd_rw)
{
goto errout;
goto errout_with_allocations;
}
fd_data = (void **)malloc(sizeof(void*) * CONFIG_NSOCKET_DESCRIPTORS);
if (!fd_data)
fw->fd_data = (void**)malloc(sizeof(void*) * nfds);
if (!fw->fd_data)
{
goto errout_with_fd_rw;
goto errout_with_allocations;
}
for (i = 0; i < CONFIG_NSOCKET_DESCRIPTORS; ++i)
for (i = 0; i < nfds; ++i)
{
fd_rw[i] = -1;
fw->fd_rw[i] = -1;
}
pollfds = (struct pollfd *)malloc(sizeof(struct pollfd) * CONFIG_NSOCKET_DESCRIPTORS);
if (!pollfds)
fw->pollfds = (struct pollfd*)malloc(sizeof(struct pollfd) * nfds);
if (!fw->pollfds)
{
goto errout_with_fd_data;
goto errout_with_allocations;
}
poll_pollndx = (int *)malloc(sizeof(int) * CONFIG_NSOCKET_DESCRIPTORS);
if (!poll_pollndx)
fw->poll_pollndx = (int*)malloc(sizeof(int) * nfds);
if (!fw->poll_pollndx)
{
goto errout_with_pollfds;
goto errout_with_allocations;
}
poll_rfdidx = (int *)malloc(sizeof(int) * CONFIG_NSOCKET_DESCRIPTORS);
if (!poll_rfdidx)
fw->poll_rfdidx = (int*)malloc(sizeof(int) * nfds);
if (!fw->poll_rfdidx)
{
goto errout_with_poll_pollndx;
goto errout_with_allocations;
}
for (i = 0; i < CONFIG_NSOCKET_DESCRIPTORS; i++)
for (i = 0; i < nfds; i++)
{
pollfds[i].fd = poll_pollndx[i] = -1;
fw->pollfds[i].fd = fw->poll_pollndx[i] = -1;
}
return OK;
return fw;
errout_with_poll_pollndx:
free(poll_pollndx);
errout_with_pollfds:
free(pollfds);
errout_with_fd_data:
free(fd_data);
errout_with_fd_rw:
free(fd_rw);
errout:
return ERROR;
errout_with_allocations:
fdwatch_uninitialize(fw);
return NULL;
}
/* Uninitialize the fwdatch data structure */
void fdwatch_uninitialize(struct fdwatch_s *fw)
{
if (fw)
{
if (fw->fd_rw)
{
free(fw->fd_rw);
}
if (fw->fd_data)
{
free(fw->fd_data);
}
if (fw->pollfds)
{
free(fw->pollfds);
}
if (fw->poll_pollndx)
{
free(fw->poll_pollndx);
}
if (fw->poll_rfdidx)
{
free(fw->poll_rfdidx);
}
free(fw);
}
}
/* Add a descriptor to the watch list. rw is either FDW_READ or FDW_WRITE. */
void fdwatch_add_fd(int fd, void *client_data, int rw)
void fdwatch_add_fd(struct fdwatch_s *fw, int fd, void *client_data, int rw)
{
int fdndx;
#ifdef CONFIG_DEBUG
if (fd < CONFIG_NFILE_DESCRIPTORS ||
fd >= CONFIG_NFILE_DESCRIPTORS+CONFIG_NSOCKET_DESCRIPTORS ||
fd_rw[fd-CONFIG_NFILE_DESCRIPTORS] != -1)
fd >= CONFIG_NFILE_DESCRIPTORS+fw->nfds ||
fw->fd_rw[fd-CONFIG_NFILE_DESCRIPTORS] != -1)
{
ndbg("Received bad fd (%d)\n", fd);
return;
}
#endif
if (npoll_fds >= CONFIG_NSOCKET_DESCRIPTORS)
if (fw->npoll_fds >= fw->nfds)
{
ndbg("too many fds\n");
return;
@ -189,31 +216,31 @@ void fdwatch_add_fd(int fd, void *client_data, int rw)
/* Save the new fd at the end of the list */
pollfds[npoll_fds].fd = fd;
fw->pollfds[fw->npoll_fds].fd = fd;
switch (rw)
{
default:
case FDW_READ:
pollfds[npoll_fds].events = POLLIN;
fw->pollfds[fw->npoll_fds].events = POLLIN;
break;
case FDW_WRITE:
pollfds[npoll_fds].events = POLLOUT;
fw->pollfds[fw->npoll_fds].events = POLLOUT;
break;
}
/* Save the new index and increment the cound of watched descriptors */
poll_pollndx[fdndx] = npoll_fds;
npoll_fds++;
fw->poll_pollndx[fdndx] = fw->npoll_fds;
fw->npoll_fds++;
fd_rw[fdndx] = rw;
fd_data[fdndx] = client_data;
fw->fd_rw[fdndx] = rw;
fw->fd_data[fdndx] = client_data;
}
/* Remove a descriptor from the watch list. */
void fdwatch_del_fd(int fd)
void fdwatch_del_fd(struct fdwatch_s *fw, int fd)
{
int fdndx;
int pollndx;
@ -221,8 +248,8 @@ void fdwatch_del_fd(int fd)
#ifdef CONFIG_DEBUG
if (fd < CONFIG_NFILE_DESCRIPTORS ||
fd >= CONFIG_NFILE_DESCRIPTORS+CONFIG_NSOCKET_DESCRIPTORS ||
fd_rw[fd-CONFIG_NFILE_DESCRIPTORS] == -1)
fd >= CONFIG_NFILE_DESCRIPTORS+fw->nfds ||
fw->fd_rw[fd-CONFIG_NFILE_DESCRIPTORS] == -1)
{
ndbg("Received bad fd: %d\n", fd);
return;
@ -234,10 +261,10 @@ void fdwatch_del_fd(int fd)
*/
fdndx = fd-CONFIG_NFILE_DESCRIPTORS;
pollndx = poll_pollndx[fdndx];
pollndx = fw->poll_pollndx[fdndx];
#ifdef CONFIG_DEBUG
if (pollndx < 0 || pollndx >= CONFIG_NSOCKET_DESCRIPTORS)
if (pollndx < 0 || pollndx >= fw->nfds)
{
ndbg("Bad poll index: %d\n", pollndx);
return;
@ -246,20 +273,20 @@ void fdwatch_del_fd(int fd)
/* Decrement the number of fds in the poll table */
npoll_fds--;
fw->npoll_fds--;
/* Replace the deleted one with the one at the the end
* of the list.
*/
tmpndx = pollfds[pollndx].fd - CONFIG_NFILE_DESCRIPTORS;
pollfds[pollndx] = pollfds[npoll_fds];
poll_pollndx[tmpndx] = poll_pollndx[fdndx];;
pollfds[npoll_fds].fd = -1;
poll_pollndx[fdndx] = -1;
tmpndx = fw->pollfds[pollndx].fd - CONFIG_NFILE_DESCRIPTORS;
fw->pollfds[pollndx] = fw->pollfds[fw->npoll_fds];
fw->poll_pollndx[tmpndx] = fw->poll_pollndx[fdndx];;
fw->pollfds[fw->npoll_fds].fd = -1;
fw->poll_pollndx[fdndx] = -1;
fd_rw[fdndx] = -1;
fd_data[fdndx] = NULL;
fw->fd_rw[fdndx] = -1;
fw->fd_data[fdndx] = NULL;
}
/* Do the watch. Return value is the number of descriptors that are ready,
@ -267,7 +294,7 @@ void fdwatch_del_fd(int fd)
* wait indefinitely.
*/
int fdwatch(long timeout_msecs)
int fdwatch(struct fdwatch_s *fw, long timeout_msecs)
{
int rfndx;
int ret;
@ -277,18 +304,18 @@ int fdwatch(long timeout_msecs)
nwatches++;
#endif
ret = poll(pollfds, npoll_fds, (int)timeout_msecs);
ret = poll(fw->pollfds, fw->npoll_fds, (int)timeout_msecs);
if (ret <= 0)
{
return ret;
}
rfndx = 0;
for (i = 0; i < npoll_fds; i++)
for (i = 0; i < fw->npoll_fds; i++)
{
if (pollfds[i].revents & (POLLIN | POLLOUT | POLLERR | POLLHUP | POLLNVAL))
if (fw->pollfds[i].revents & (POLLIN | POLLOUT | POLLERR | POLLHUP | POLLNVAL))
{
poll_rfdidx[rfndx++] = pollfds[i].fd;
fw->poll_rfdidx[rfndx++] = fw->pollfds[i].fd;
if (rfndx == ret)
{
break;
@ -296,21 +323,20 @@ int fdwatch(long timeout_msecs)
}
}
next_rfndx = 0;
return rfndx;
}
/* Check if a descriptor was ready. */
int fdwatch_check_fd(int fd)
int fdwatch_check_fd(struct fdwatch_s *fw, int fd)
{
int fdndx;
int pollndx;
#ifdef CONFIG_DEBUG
if (fd < CONFIG_NFILE_DESCRIPTORS ||
fd >= CONFIG_NFILE_DESCRIPTORS+CONFIG_NSOCKET_DESCRIPTORS ||
fd_rw[fd-CONFIG_NFILE_DESCRIPTORS] == -1)
fd >= CONFIG_NFILE_DESCRIPTORS+fw->nfds ||
fw->fd_rw[fd-CONFIG_NFILE_DESCRIPTORS] == -1)
{
ndbg("Bad fd: %d\n", fd);
return 0;
@ -322,28 +348,28 @@ int fdwatch_check_fd(int fd)
*/
fdndx = fd-CONFIG_NFILE_DESCRIPTORS;
pollndx = poll_pollndx[fdndx];
pollndx = fw->poll_pollndx[fdndx];
#ifdef CONFIG_DEBUG
if (pollndx < 0 || pollndx >= CONFIG_NSOCKET_DESCRIPTORS)
if (pollndx < 0 || pollndx >= fw->nfds)
{
ndbg("Bad poll index: %d\n", pollndx);
return 0;
}
#endif
if (pollfds[pollndx].revents & POLLERR)
if (fw->pollfds[pollndx].revents & POLLERR)
{
return 0;
}
switch (fd_rw[fdndx])
switch (fw->fd_rw[fdndx])
{
case FDW_READ:
return pollfds[pollndx].revents & (POLLIN | POLLHUP | POLLNVAL);
return fw->pollfds[pollndx].revents & (POLLIN | POLLHUP | POLLNVAL);
case FDW_WRITE:
return pollfds[pollndx].revents & (POLLOUT | POLLHUP | POLLNVAL);
return fw->pollfds[pollndx].revents & (POLLOUT | POLLHUP | POLLNVAL);
default:
break;
@ -351,40 +377,33 @@ int fdwatch_check_fd(int fd)
return 0;
}
void *fdwatch_get_next_client_data(void)
void *fdwatch_get_next_client_data(struct fdwatch_s *fw)
{
int rfndx;
int fdndx;
int fd;
if (next_rfndx >= nreturned)
{
return (void*)-1;
}
rfndx = next_rfndx++;
#ifdef CONFIG_DEBUG
if (rfndx < 0 || rfndx >= CONFIG_NSOCKET_DESCRIPTORS)
if (rfndx < 0 || rfndx >= fw->nfds)
{
ndbg("Bad rfndx: %d\n", rfndx);
return NULL;
}
#endif
fd = poll_rfdidx[rfndx];
fd = fw->poll_rfdidx[rfndx];
fdndx = fd-CONFIG_NFILE_DESCRIPTORS;
if (fdndx < 0 || fdndx >= CONFIG_NSOCKET_DESCRIPTORS)
if (fdndx < 0 || fdndx >= fw->nfds)
{
return NULL;
}
return fd_data[fdndx];
return fw->fd_data[fdndx];
}
/* Generate debugging statistics ndbg message. */
#if defined(CONFIG_DEBUG) && defined(CONFIG_DEBUG_NET)
void fdwatch_logstats(long secs)
void fdwatch_logstats(struct fdwatch_s *fw, long secs)
{
if (secs > 0)
ndbg("fdwatch - %ld polls (%g/sec)\n", nwatches, (float)nwatches / secs);

View File

@ -40,6 +40,10 @@
#ifndef __NETUTILS_THTTPD_FDWATCH_H
#define __NETUTILS_THTTPD_FDWATCH_H
/****************************************************************************
* Pre-Processor Definitions
****************************************************************************/
#define FDW_READ 0
#define FDW_WRITE 1
@ -47,39 +51,62 @@
# define INFTIM -1
#endif
/* initialize the fdwatch data structures. Returns -1 on failure. */
/****************************************************************************
* Private Types
****************************************************************************/
extern int fdwatch_initialize(void);
struct fdwatch_s
{
int *fd_rw;
void **fd_data;
struct pollfd *pollfds;
int *poll_pollndx;
int *poll_rfdidx;
int nfds;
int npoll_fds;
};
/****************************************************************************
* Public Function Prototypes
****************************************************************************/
/* Initialize the fdwatch data structures. Returns NULL on failure. */
extern struct fdwatch_s *fdwatch_initialize(int nfds);
/* Uninitialize the fwdatch data structure */
extern void fdwatch_uninitialize(struct fdwatch_s *fw);
/* Add a descriptor to the watch list. rw is either FDW_READ or FDW_WRITE. */
extern void fdwatch_add_fd(int fd, void *client_data, int rw);
extern void fdwatch_add_fd(struct fdwatch_s *fw, int fd, void *client_data, int rw);
/* Delete a descriptor from the watch list. */
extern void fdwatch_del_fd(int fd);
extern void fdwatch_del_fd(struct fdwatch_s *fw, int fd);
/* Do the watch. Return value is the number of descriptors that are ready,
* or 0 if the timeout expired, or -1 on errors. A timeout of INFTIM means
* wait indefinitely.
*/
extern int fdwatch(long timeout_msecs);
extern int fdwatch(struct fdwatch_s *fw, long timeout_msecs);
/* Check if a descriptor was ready. */
extern int fdwatch_check_fd(int fd);
extern int fdwatch_check_fd(struct fdwatch_s *fw, int fd);
/* Get the client data for the next returned event. Returns -1 when there
* are no more events.
*/
extern void *fdwatch_get_next_client_data(void);
extern void *fdwatch_get_next_client_data(struct fdwatch_s *fw);
/* Generate debugging statistics syslog message. */
#if defined(CONFIG_DEBUG) && defined(CONFIG_DEBUG_NET)
extern void fdwatch_logstats(long secs);
extern void fdwatch_logstats(struct fdwatch_s *fw, long secs);
#endif
#endif /* __NETUTILS_THTTPD_FDWATCH_H */

File diff suppressed because it is too large Load Diff

View File

@ -108,6 +108,7 @@ static struct connect_s *connects;
static int num_connects;
static int first_free_connect;
static int httpd_conn_count;
static struct fdwatch_s *fw;
/****************************************************************************
* Public Data
@ -180,7 +181,7 @@ static void shut_down(void)
hs = (httpd_server *) 0;
if (ths->listen_fd != -1)
{
fdwatch_del_fd(ths->listen_fd);
fdwatch_del_fd(fw, ths->listen_fd);
}
httpd_terminate(ths);
}
@ -271,7 +272,7 @@ static int handle_newconnect(struct timeval *tv, int listen_fd)
httpd_set_ndelay(conn->hc->conn_fd);
fdwatch_add_fd(conn->hc->conn_fd, conn, FDW_READ);
fdwatch_add_fd(fw, conn->hc->conn_fd, conn, FDW_READ);
#if defined(CONFIG_DEBUG) && defined(CONFIG_DEBUG_NET)
++stats_connections;
@ -403,8 +404,8 @@ static void handle_read(struct connect_s *conn, struct timeval *tv)
conn->conn_state = CNST_SENDING;
client_data.p = conn;
fdwatch_del_fd(hc->conn_fd);
fdwatch_add_fd(hc->conn_fd, conn, FDW_WRITE);
fdwatch_del_fd(fw, hc->conn_fd);
fdwatch_add_fd(fw, hc->conn_fd, conn, FDW_WRITE);
return;
errout_with_400:
@ -560,12 +561,12 @@ static void clear_connection(struct connect_s *conn, struct timeval *tv)
{
if (conn->conn_state != CNST_PAUSING)
{
fdwatch_del_fd(conn->hc->conn_fd);
fdwatch_del_fd(fw, conn->hc->conn_fd);
}
conn->conn_state = CNST_LINGERING;
close(conn->hc->conn_fd);
fdwatch_add_fd(conn->hc->conn_fd, conn, FDW_READ);
fdwatch_add_fd(fw, conn->hc->conn_fd, conn, FDW_READ);
client_data.p = conn;
if (conn->linger_timer != (Timer *) 0)
@ -594,7 +595,7 @@ static void really_clear_connection(struct connect_s *conn, struct timeval *tv)
#endif
if (conn->conn_state != CNST_PAUSING)
{
fdwatch_del_fd(conn->hc->conn_fd);
fdwatch_del_fd(fw, conn->hc->conn_fd);
}
httpd_close_conn(conn->hc, tv);
@ -685,7 +686,7 @@ static void logstats(struct timeval *nowP)
thttpd_logstats(stats_secs);
httpd_logstats(stats_secs);
fdwatch_logstats(stats_secs);
fdwatch_logstats(fw, stats_secs);
tmr_logstats(stats_secs);
}
#endif
@ -742,7 +743,6 @@ int thttpd_main(int argc, char **argv)
struct sockaddr_in sa;
#endif
struct timeval tv;
int ret;
/* Setup host address */
@ -773,10 +773,12 @@ int thttpd_main(int argc, char **argv)
(void)strcat(cwd, "/");
}
/* Initialize the fdwatch package */
/* Initialize the fdwatch package to handle all of the configured
* socket descriptors
*/
ret = fdwatch_initialize();
if (ret < 0)
fw = fdwatch_initialize(CONFIG_NSOCKET_DESCRIPTORS);
if (!fw)
{
ndbg("fdwatch initialization failure\n");
exit(1);
@ -860,7 +862,7 @@ int thttpd_main(int argc, char **argv)
if (hs != (httpd_server *) 0)
{
if (hs->listen_fd != -1)
fdwatch_add_fd(hs->listen_fd, (void *)0, FDW_READ);
fdwatch_add_fd(fw, hs->listen_fd, (void *)0, FDW_READ);
}
/* Main loop */
@ -870,7 +872,7 @@ int thttpd_main(int argc, char **argv)
{
/* Do the fd watch */
num_ready = fdwatch(tmr_mstimeout(&tv));
num_ready = fdwatch(fw, tmr_mstimeout(&tv));
if (num_ready < 0)
{
if (errno == EINTR || errno == EAGAIN)
@ -892,7 +894,7 @@ int thttpd_main(int argc, char **argv)
/* Is it a new connection? */
if (hs != (httpd_server *) 0 && hs->listen_fd != -1 &&
fdwatch_check_fd(hs->listen_fd))
fdwatch_check_fd(fw, hs->listen_fd))
{
if (handle_newconnect(&tv, hs->listen_fd))
{
@ -908,14 +910,14 @@ int thttpd_main(int argc, char **argv)
/* Find the connections that need servicing */
while ((conn =
(struct connect_s *) fdwatch_get_next_client_data()) !=
(struct connect_s *) - 1)
(struct connect_s*)fdwatch_get_next_client_data(fw)) !=
(struct connect_s*)- 1)
{
if (conn == (struct connect_s *) 0)
continue;
hc = conn->hc;
if (!fdwatch_check_fd(hc->conn_fd))
if (!fdwatch_check_fd(fw, hc->conn_fd))
{
/* Something went wrong */