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:
parent
59cf543804
commit
8c17e7f6d0
@ -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.
|
||||
|
@ -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 -
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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
@ -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 */
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user