forked from Imagelibrary/rtems
2000-08-30 Joel Sherrill <joel@OARcorp.com>
* Merged version 2.1 of GoAhead webserver. This update was submitted by Antti P Miettinen <antti.p.miettinen@nokia.com>. * NOTES, base64.c, ejIntrn.h, emfdb.c, emfdb.h, md5.h, md5c.c, um.c, um.h: New files. * wbase64.c: Removed. * Makefile.am, asp.c, balloc.c, default.c, ej.h, ejlex.c, ejparse.c, form.c, h.c, handler.c, mime.c, misc.c, ringq.c, rom.c, security.c, socket.c, sym.c, uemf.c, uemf.h, url.c, value.c, webcomp.c, webmain.c, webpage.c, webrom.c, webs.c, webs.h, websuemf.c, wsIntrn.h: Modified.
This commit is contained in:
@@ -1,3 +1,15 @@
|
||||
2000-08-31 Joel Sherrill <joel@OARcorp.com>
|
||||
|
||||
* Merged version 2.1 of GoAhead webserver. This update
|
||||
was submitted by Antti P Miettinen <antti.p.miettinen@nokia.com>.
|
||||
* NOTES, base64.c, ejIntrn.h, emfdb.c, emfdb.h, md5.h, md5c.c,
|
||||
um.c, um.h: New files.
|
||||
* wbase64.c: Removed.
|
||||
* Makefile.am, asp.c, balloc.c, default.c, ej.h, ejlex.c, ejparse.c,
|
||||
form.c, h.c, handler.c, mime.c, misc.c, ringq.c, rom.c, security.c,
|
||||
socket.c, sym.c, uemf.c, uemf.h, url.c, value.c, webcomp.c, webmain.c,
|
||||
webpage.c, webrom.c, webs.c, webs.h, websuemf.c, wsIntrn.h: Modified.
|
||||
|
||||
2000-08-31 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
|
||||
|
||||
* netinet/tcp_input.c: Spelling corrections.
|
||||
|
||||
@@ -1,3 +1,15 @@
|
||||
2000-08-31 Joel Sherrill <joel@OARcorp.com>
|
||||
|
||||
* Merged version 2.1 of GoAhead webserver. This update
|
||||
was submitted by Antti P Miettinen <antti.p.miettinen@nokia.com>.
|
||||
* NOTES, base64.c, ejIntrn.h, emfdb.c, emfdb.h, md5.h, md5c.c,
|
||||
um.c, um.h: New files.
|
||||
* wbase64.c: Removed.
|
||||
* Makefile.am, asp.c, balloc.c, default.c, ej.h, ejlex.c, ejparse.c,
|
||||
form.c, h.c, handler.c, mime.c, misc.c, ringq.c, rom.c, security.c,
|
||||
socket.c, sym.c, uemf.c, uemf.h, url.c, value.c, webcomp.c, webmain.c,
|
||||
webpage.c, webrom.c, webs.c, webs.h, websuemf.c, wsIntrn.h: Modified.
|
||||
|
||||
2000-08-31 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
|
||||
|
||||
* netinet/tcp_input.c: Spelling corrections.
|
||||
|
||||
@@ -7,14 +7,15 @@ AUTOMAKE_OPTIONS = foreign 1.4
|
||||
LIBNAME = lib.a
|
||||
LIB = $(ARCH)/$(LIBNAME)
|
||||
|
||||
C_FILES = asp.c balloc.c wbase64.c default.c ejlex.c ejparse.c form.c h.c \
|
||||
handler.c mime.c misc.c webpage.c ringq.c rom.c security.c socket.c \
|
||||
sym.c uemf.c url.c value.c webrom.c webs.c websuemf.c webmain.c
|
||||
C_FILES = asp.c balloc.c base64.c default.c ejlex.c ejparse.c emfdb.c \
|
||||
form.c h.c handler.c md5c.c mime.c misc.c webpage.c ringq.c rom.c \
|
||||
security.c socket.c sym.c uemf.c um.c url.c value.c webrom.c webs.c \
|
||||
websuemf.c webmain.c
|
||||
C_O_FILES = $(C_FILES:%.c=$(ARCH)/%.o)
|
||||
|
||||
OBJS = $(C_O_FILES)
|
||||
|
||||
H_FILES = ej.h uemf.h webs.h wsIntrn.h
|
||||
H_FILES = ej.h ejIntrn.h emfdb.h md5.h uemf.h um.h webs.h wsIntrn.h
|
||||
|
||||
include $(RTEMS_ROOT)/make/custom/@RTEMS_BSP@.cfg
|
||||
include $(top_srcdir)/../../../automake/lib.am
|
||||
@@ -52,7 +53,7 @@ endif
|
||||
|
||||
EXTRA_DIST = asp.c balloc.c default.c ej.h ejlex.c ejparse.c form.c h.c \
|
||||
handler.c mime.c misc.c ringq.c rom.c rtems_webserver.h security.c \
|
||||
socket.c sym.c uemf.c uemf.h url.c value.c wbase64.c webcomp.c webmain.c \
|
||||
webpage.c webrom.c webs.c webs.h websuemf.c wsIntrn.h
|
||||
socket.c sym.c uemf.c uemf.h um.h url.c value.c base64.c webcomp.c \
|
||||
webmain.c webpage.c webrom.c webs.c webs.h websuemf.c wsIntrn.h
|
||||
|
||||
include $(top_srcdir)/../../../automake/local.am
|
||||
|
||||
29
c/src/libnetworking/rtems_webserver/NOTES
Normal file
29
c/src/libnetworking/rtems_webserver/NOTES
Normal file
@@ -0,0 +1,29 @@
|
||||
#
|
||||
# $Id$
|
||||
#
|
||||
|
||||
Notes on merging GoAhead Webs 2.1. Eventually RTEMS should be supported
|
||||
in their distributions and this directory removed.
|
||||
|
||||
Applied patch from Antti P Miettinen <antti.p.miettinen@nokia.com>.
|
||||
|
||||
Obtain the original distribution from http://www.goahead.com for
|
||||
documentation.
|
||||
|
||||
Tailoring
|
||||
=========
|
||||
socket.c is RTEMS specific
|
||||
|
||||
Renames
|
||||
=======
|
||||
|
||||
Distributed as This Directory
|
||||
============== ================
|
||||
base64.c wbase64.c
|
||||
page.c webpage.c
|
||||
|
||||
RTEMS Specific Additions
|
||||
========================
|
||||
webmain.c
|
||||
rtems_webserver.h
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* asp.c -- Active Server Page Support
|
||||
*
|
||||
* Copyright (c) Go Ahead Software Inc., 1995-1999. All Rights Reserved.
|
||||
* Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved.
|
||||
*
|
||||
* See the file "license.txt" for usage and redistribution license requirements
|
||||
*/
|
||||
@@ -20,11 +20,12 @@
|
||||
|
||||
/********************************** Locals ************************************/
|
||||
|
||||
static sym_fd_t websAspFunctions = -1; /* Symbol table of functions */
|
||||
static sym_fd_t websAspFunctions = -1; /* Symbol table of functions */
|
||||
static int aspOpenCount = 0; /* count of apps using this module */
|
||||
|
||||
/***************************** Forward Declarations ***************************/
|
||||
|
||||
static char_t *strtokcmp(char_t* s1, char_t* s2);
|
||||
static char_t *strtokcmp(char_t *s1, char_t *s2);
|
||||
static char_t *skipWhite(char_t *s);
|
||||
|
||||
/************************************* Code ***********************************/
|
||||
@@ -34,15 +35,17 @@ static char_t *skipWhite(char_t *s);
|
||||
|
||||
int websAspOpen()
|
||||
{
|
||||
if (++aspOpenCount == 1) {
|
||||
/*
|
||||
* Create the table for ASP functions
|
||||
*/
|
||||
websAspFunctions = symOpen(128);
|
||||
websAspFunctions = symOpen(WEBS_SYM_INIT * 2);
|
||||
|
||||
/*
|
||||
* Create standard ASP commands
|
||||
*/
|
||||
websAspDefine(T("write"), websAspWrite);
|
||||
websAspDefine(T("write"), websAspWrite);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -53,8 +56,11 @@ int websAspOpen()
|
||||
|
||||
void websAspClose()
|
||||
{
|
||||
if (websAspFunctions != -1) {
|
||||
symClose(websAspFunctions, NULL);
|
||||
if (--aspOpenCount <= 0) {
|
||||
if (websAspFunctions != -1) {
|
||||
symClose(websAspFunctions);
|
||||
websAspFunctions = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,7 +71,7 @@ void websAspClose()
|
||||
* documents, it is better to make them plain HTML files rather than ASPs.
|
||||
*/
|
||||
|
||||
int websAspRequest(webs_t wp, char_t* lpath)
|
||||
int websAspRequest(webs_t wp, char_t *lpath)
|
||||
{
|
||||
websStatType sbuf;
|
||||
char *rbuf;
|
||||
@@ -84,7 +90,7 @@ int websAspRequest(webs_t wp, char_t* lpath)
|
||||
path = websGetRequestPath(wp);
|
||||
|
||||
/*
|
||||
* Create Ejscript instance incase it is needed
|
||||
* Create Ejscript instance in case it is needed
|
||||
*/
|
||||
ejid = ejOpenEngine(wp->cgiVars, websAspFunctions);
|
||||
if (ejid < 0) {
|
||||
@@ -112,12 +118,12 @@ int websAspRequest(webs_t wp, char_t* lpath)
|
||||
websError(wp, 200, T("Cant read %s"), lpath);
|
||||
goto done;
|
||||
}
|
||||
websCloseFileHandle(wp);
|
||||
websPageClose(wp);
|
||||
|
||||
/*
|
||||
* Convert to UNICODE if necessary.
|
||||
*/
|
||||
if ((buf = ballocAscToUni(rbuf)) == NULL) {
|
||||
if ((buf = ballocAscToUni(rbuf, len)) == NULL) {
|
||||
websError(wp, 200, T("Can't get memory"));
|
||||
goto done;
|
||||
}
|
||||
@@ -220,7 +226,7 @@ int websAspRequest(webs_t wp, char_t* lpath)
|
||||
*/
|
||||
done:
|
||||
if (websValid(wp)) {
|
||||
websCloseFileHandle(wp);
|
||||
websPageClose(wp);
|
||||
if (ejid >= 0) {
|
||||
ejCloseEngine(ejid);
|
||||
}
|
||||
@@ -252,9 +258,9 @@ int websAspWrite(int ejid, webs_t wp, int argc, char_t **argv)
|
||||
int i;
|
||||
|
||||
a_assert(websValid(wp));
|
||||
a_assert(argv);
|
||||
|
||||
|
||||
for (i = 0; i < argc; ) {
|
||||
a_assert(argv);
|
||||
if (websWriteBlock(wp, argv[i], gstrlen(argv[i])) < 0) {
|
||||
return -1;
|
||||
}
|
||||
@@ -273,7 +279,7 @@ int websAspWrite(int ejid, webs_t wp, int argc, char_t **argv)
|
||||
* Return a pointer to the location in s1 after s2 ends.
|
||||
*/
|
||||
|
||||
static char_t* strtokcmp(char_t* s1, char_t* s2)
|
||||
static char_t *strtokcmp(char_t *s1, char_t *s2)
|
||||
{
|
||||
int len;
|
||||
|
||||
@@ -310,4 +316,4 @@ static char_t *skipWhite(char_t *s)
|
||||
return s;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/******************************************************************************/
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* balloc.c -- Block allocation module
|
||||
*
|
||||
* Copyright (c) GoAhead Software Inc., 1995-1999. All Rights Reserved.
|
||||
* Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved.
|
||||
*
|
||||
* See the file "license.txt" for usage and redistribution license requirements
|
||||
*/
|
||||
@@ -11,7 +11,7 @@
|
||||
/*
|
||||
* This module implements a very fast block allocation scheme suitable for
|
||||
* ROMed environments. It maintains block class queues for rapid allocation
|
||||
* and minimal fragmentation. This modules does not coalesce blocks. The
|
||||
* and minimal fragmentation. This module does not coalesce blocks. The
|
||||
* storage space may be populated statically or via the traditional malloc
|
||||
* mechanisms. Large blocks greater than the maximum class size may be
|
||||
* allocated from the O/S or run-time system via malloc. To permit the use
|
||||
@@ -38,14 +38,6 @@
|
||||
#if !NO_BALLOC
|
||||
/********************************* Defines ************************************/
|
||||
|
||||
typedef struct {
|
||||
union {
|
||||
void *next; /* Pointer to next in q */
|
||||
int size; /* Actual requested size */
|
||||
} u;
|
||||
int flags; /* Per block allocation flags */
|
||||
} bType;
|
||||
|
||||
/*
|
||||
* Define B_STATS if you wish to track memory block and stack usage
|
||||
*/
|
||||
@@ -63,7 +55,9 @@ typedef struct {
|
||||
char_t file[FNAMESIZE];
|
||||
long allocated; /* Bytes currently allocated */
|
||||
long count; /* Current block count */
|
||||
long allocs; /* Count of alloc attempts */
|
||||
long times; /* Count of alloc attempts */
|
||||
long largest; /* largest allocated here */
|
||||
int q;
|
||||
} bStatsFileType;
|
||||
|
||||
/*
|
||||
@@ -77,15 +71,26 @@ typedef struct {
|
||||
static bStatsType bStats[B_MAX_CLASS]; /* Per class stats */
|
||||
static bStatsFileType bStatsFiles[B_MAX_FILES];/* Per file stats */
|
||||
static bStatsBlkType bStatsBlks[B_MAX_BLOCKS];/* Per block stats */
|
||||
static int bStatsBlksMax; /* Max block entry */
|
||||
static int bStatsFilesMax; /* Max file entry */
|
||||
static int bStatsMemInUse; /* Memory currently in use */
|
||||
static int bStatsMemMax; /* Max memory ever used */
|
||||
static int bStatsBlksMax = 0; /* Max block entry */
|
||||
static int bStatsFilesMax = 0; /* Max file entry */
|
||||
static int bStatsMemInUse = 0; /* Memory currently in use */
|
||||
static int bStatsBallocInUse = 0; /* Memory currently balloced */
|
||||
static int bStatsMemMax = 0; /* Max memory ever used */
|
||||
static int bStatsBallocMax = 0; /* Max memory ever balloced */
|
||||
static void *bStackMin = (void*) -1;/* Miniumum stack position */
|
||||
static void *bStackStart; /* Starting stack position */
|
||||
static int bStatsMemMalloc; /* Malloced memory */
|
||||
static int bStatsMemMalloc = 0; /* Malloced memory */
|
||||
#endif /* B_STATS */
|
||||
|
||||
/*
|
||||
* ROUNDUP4(size) returns the next higher integer value of size that is
|
||||
* divisible by 4, or the value of size if size is divisible by 4.
|
||||
* ROUNDUP4() is used in aligning memory allocations on 4-byte boundaries.
|
||||
*
|
||||
* Note: ROUNDUP4() is only required on some operating systems (IRIX).
|
||||
*/
|
||||
|
||||
#define ROUNDUP4(size) ((size) % 4) ? (size) + (4 - ((size) % 4)) : (size)
|
||||
|
||||
/********************************** Locals ************************************/
|
||||
/*
|
||||
@@ -98,6 +103,7 @@ static char *bFreeNext; /* Pointer to next free mem */
|
||||
static int bFreeSize; /* Size of free memory */
|
||||
static int bFreeLeft; /* Size of free left for use */
|
||||
static int bFlags = B_USE_MALLOC; /* Default to auto-malloc */
|
||||
static int bopenCount = 0; /* Num tasks using balloc */
|
||||
|
||||
/*************************** Forward Declarations *****************************/
|
||||
|
||||
@@ -115,9 +121,11 @@ static void bFillBlock(void *buf, int bufsize);
|
||||
#if B_VERIFY_CAUSES_SEVERE_OVERHEAD
|
||||
static void verifyUsedBlock(bType *bp, int q);
|
||||
static void verifyFreeBlock(bType *bp, int q);
|
||||
static void verifyBallocSpace();
|
||||
void verifyBallocSpace();
|
||||
#endif
|
||||
|
||||
static int ballocGetSize(int size, int *q);
|
||||
|
||||
/********************************** Code **************************************/
|
||||
/*
|
||||
* Initialize the balloc module. bopen should be called the very first thing
|
||||
@@ -133,10 +141,25 @@ int bopen(void *buf, int bufsize, int flags)
|
||||
{
|
||||
bFlags = flags;
|
||||
|
||||
#if BASTARD_TESTING
|
||||
srand(time(0L));
|
||||
#endif /* BASTARD_TESTING */
|
||||
|
||||
/*
|
||||
* If bopen already called by a shared process, just increment the count
|
||||
* and return;
|
||||
*/
|
||||
if (++bopenCount > 1) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (buf == NULL) {
|
||||
if (bufsize == 0) {
|
||||
bufsize = B_DEFAULT_MEM;
|
||||
}
|
||||
#ifdef IRIX
|
||||
bufsize = ROUNDUP4(bufsize);
|
||||
#endif
|
||||
if ((buf = malloc(bufsize)) == NULL) {
|
||||
return -1;
|
||||
}
|
||||
@@ -149,6 +172,7 @@ int bopen(void *buf, int bufsize, int flags)
|
||||
|
||||
bFreeSize = bFreeLeft = bufsize;
|
||||
bFreeBuf = bFreeNext = buf;
|
||||
memset(bQhead, 0, sizeof(bQhead));
|
||||
#if B_FILL || B_VERIFY_CAUSES_SEVERE_OVERHEAD
|
||||
bFillBlock(buf, bufsize);
|
||||
#endif
|
||||
@@ -171,8 +195,9 @@ void bclose()
|
||||
#if B_VERIFY_CAUSES_SEVERE_OVERHEAD
|
||||
verifyBallocSpace();
|
||||
#endif
|
||||
if (! (bFlags & B_USER_BUF)) {
|
||||
if (--bopenCount <= 0 && !(bFlags & B_USER_BUF)) {
|
||||
free(bFreeBuf);
|
||||
bopenCount = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -185,13 +210,13 @@ void bclose()
|
||||
void *balloc(B_ARGS_DEC, int size)
|
||||
{
|
||||
bType *bp;
|
||||
int q, memSize, mask;
|
||||
int q, memSize;
|
||||
|
||||
/*
|
||||
* Call bopen with default values if the application has not yet done so
|
||||
*/
|
||||
if (bFreeBuf == NULL) {
|
||||
if (bopen(NULL, B_DEFAULT_MEM , 0) < 0) {
|
||||
if (bopen(NULL, B_DEFAULT_MEM, 0) < 0) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
@@ -202,17 +227,14 @@ void *balloc(B_ARGS_DEC, int size)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Determine the relevant block queue with a block big enough --
|
||||
* include room for the block header.
|
||||
*/
|
||||
mask = (size + sizeof(bType)) >> B_SHIFT;
|
||||
for (q = 0; mask; mask >>= 1) {
|
||||
q++;
|
||||
#if BASTARD_TESTING
|
||||
if (rand() == 0x7fff) {
|
||||
return NULL;
|
||||
}
|
||||
#endif /* BASTARD_TESTING */
|
||||
|
||||
a_assert(0 <= q && q <= B_MAX_CLASS);
|
||||
memSize = (1 << (B_SHIFT + q));
|
||||
|
||||
memSize = ballocGetSize(size, &q);
|
||||
|
||||
if (q >= B_MAX_CLASS) {
|
||||
/*
|
||||
@@ -221,11 +243,13 @@ void *balloc(B_ARGS_DEC, int size)
|
||||
if (bFlags & B_USE_MALLOC) {
|
||||
#if B_STATS
|
||||
bstats(0, NULL);
|
||||
#endif
|
||||
#ifdef IRIX
|
||||
memSize = ROUNDUP4(memSize);
|
||||
#endif
|
||||
bp = (bType*) malloc(memSize);
|
||||
if (bp == NULL) {
|
||||
goahead_trace(0, T("B: malloc failed for %s:%d, size %d\n"),
|
||||
B_ARGS, memSize);
|
||||
traceRaw(T("B: malloc failed\n"));
|
||||
return NULL;
|
||||
}
|
||||
#if B_STATS
|
||||
@@ -236,11 +260,14 @@ void *balloc(B_ARGS_DEC, int size)
|
||||
#endif
|
||||
|
||||
} else {
|
||||
goahead_trace(0, T("B: balloc failed for %s:%d, size %d\n"),
|
||||
B_ARGS, memSize);
|
||||
traceRaw(T("B: malloc failed\n"));
|
||||
return NULL;
|
||||
}
|
||||
bp->u.size = size;
|
||||
|
||||
/*
|
||||
* the u.size is the actual size allocated for data
|
||||
*/
|
||||
bp->u.size = memSize - sizeof(bType);
|
||||
bp->flags = B_MALLOCED;
|
||||
|
||||
} else if ((bp = bQhead[q]) != NULL) {
|
||||
@@ -254,7 +281,7 @@ void *balloc(B_ARGS_DEC, int size)
|
||||
#if B_FILL || B_VERIFY_CAUSES_SEVERE_OVERHEAD
|
||||
bFillBlock(bp, memSize);
|
||||
#endif
|
||||
bp->u.size = size;
|
||||
bp->u.size = memSize - sizeof(bType);
|
||||
bp->flags = 0;
|
||||
|
||||
} else {
|
||||
@@ -272,22 +299,24 @@ void *balloc(B_ARGS_DEC, int size)
|
||||
#if B_FILL || B_VERIFY_CAUSES_SEVERE_OVERHEAD
|
||||
bFillBlock(bp, memSize);
|
||||
#endif
|
||||
bp->u.size = size;
|
||||
bp->u.size = memSize - sizeof(bType);
|
||||
bp->flags = 0;
|
||||
|
||||
} else if (bFlags & B_USE_MALLOC) {
|
||||
static int once = 0;
|
||||
if (once++ < 20) {
|
||||
#if B_STATS
|
||||
static int once = 0;
|
||||
if (once++ == 0) {
|
||||
bstats(0, NULL);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
/*
|
||||
* Nothing left on the primary free list, so malloc a new block
|
||||
*/
|
||||
#ifdef IRIX
|
||||
memSize = ROUNDUP4(memSize);
|
||||
#endif
|
||||
if ((bp = (bType*) malloc(memSize)) == NULL) {
|
||||
goahead_trace(0, T("B: malloc failed for %s:%d size %d\n"),
|
||||
B_ARGS, memSize);
|
||||
traceRaw(T("B: malloc failed\n"));
|
||||
return NULL;
|
||||
}
|
||||
#if B_STATS
|
||||
@@ -296,20 +325,31 @@ void *balloc(B_ARGS_DEC, int size)
|
||||
#if B_FILL || B_VERIFY_CAUSES_SEVERE_OVERHEAD
|
||||
bFillBlock(bp, memSize);
|
||||
#endif
|
||||
bp->u.size = size;
|
||||
bp->u.size = memSize - sizeof(bType);
|
||||
bp->flags = B_MALLOCED;
|
||||
|
||||
} else {
|
||||
goahead_trace(0, T("B: alloc failed for %s:%d size %d\n"), B_ARGS, size);
|
||||
traceRaw(T("B: malloc failed\n"));
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
#if B_STATS
|
||||
bStatsAlloc(B_ARGS, bp, q, size);
|
||||
bStatsAlloc(B_ARGS, bp, q, memSize);
|
||||
#endif
|
||||
bp->flags |= B_INTEGRITY;
|
||||
|
||||
/*
|
||||
* The following is a good place to put a breakpoint when trying to reduce
|
||||
* determine and reduce maximum memory use.
|
||||
*/
|
||||
#if 0
|
||||
#if B_STATS
|
||||
if (bStatsBallocInUse == bStatsBallocMax) {
|
||||
bstats(0, NULL);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
return (void*) ((char*) bp + sizeof(bType));
|
||||
}
|
||||
|
||||
@@ -323,41 +363,34 @@ void *balloc(B_ARGS_DEC, int size)
|
||||
void bfree(B_ARGS_DEC, void *mp)
|
||||
{
|
||||
bType *bp;
|
||||
int mask, q;
|
||||
int q, memSize;
|
||||
|
||||
#if B_VERIFY_CAUSES_SEVERE_OVERHEAD
|
||||
verifyBallocSpace();
|
||||
#endif
|
||||
a_assert(mp);
|
||||
|
||||
bp = (bType*) ((char*) mp - sizeof(bType));
|
||||
|
||||
a_assert((bp->flags & B_INTEGRITY_MASK) == B_INTEGRITY);
|
||||
|
||||
if ((bp->flags & B_INTEGRITY_MASK) != B_INTEGRITY) {
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Determine the relevant block queue
|
||||
*/
|
||||
mask = (bp->u.size + sizeof(bType)) >> B_SHIFT;
|
||||
for (q = 0; mask; mask >>= 1) {
|
||||
q++;
|
||||
}
|
||||
a_assert(0 <= q && q <= B_MAX_CLASS);
|
||||
memSize = ballocGetSize(bp->u.size, &q);
|
||||
|
||||
#if B_VERIFY_CAUSES_SEVERE_OVERHEAD
|
||||
verifyUsedBlock(bp,q);
|
||||
#endif
|
||||
#if B_STATS
|
||||
bStatsFree(B_ARGS, bp, q, bp->u.size+sizeof(bType));
|
||||
#endif
|
||||
if (bp->flags & B_MALLOCED) {
|
||||
free(bp);
|
||||
return;
|
||||
}
|
||||
|
||||
#if B_STATS
|
||||
bStatsFree(B_ARGS, bp, q, bp->u.size);
|
||||
#endif
|
||||
#if B_VERIFY_CAUSES_SEVERE_OVERHEAD
|
||||
bFillBlock(bp, 1 << (B_SHIFT + q));
|
||||
bFillBlock(bp, memSize);
|
||||
#endif
|
||||
|
||||
/*
|
||||
@@ -365,6 +398,8 @@ void bfree(B_ARGS_DEC, void *mp)
|
||||
*/
|
||||
bp->u.next = bQhead[q];
|
||||
bQhead[q] = bp;
|
||||
|
||||
bp->flags = B_FILL_WORD;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
@@ -432,7 +467,7 @@ char_t *bstrdup(B_ARGS_DEC, char_t *s)
|
||||
|
||||
void *brealloc(B_ARGS_DEC, void *mp, int newsize)
|
||||
{
|
||||
bType* bp;
|
||||
bType *bp;
|
||||
void *newbuf;
|
||||
|
||||
if (mp == NULL) {
|
||||
@@ -440,6 +475,14 @@ void *brealloc(B_ARGS_DEC, void *mp, int newsize)
|
||||
}
|
||||
bp = (bType*) ((char*) mp - sizeof(bType));
|
||||
a_assert((bp->flags & B_INTEGRITY_MASK) == B_INTEGRITY);
|
||||
|
||||
/*
|
||||
* If the allocated memory already has enough room just return the previously
|
||||
* allocated address.
|
||||
*/
|
||||
if (bp->u.size >= newsize) {
|
||||
return mp;
|
||||
}
|
||||
if ((newbuf = balloc(B_ARGS, newsize)) != NULL) {
|
||||
memcpy(newbuf, mp, bp->u.size);
|
||||
bfree(B_ARGS, mp);
|
||||
@@ -447,6 +490,24 @@ void *brealloc(B_ARGS_DEC, void *mp, int newsize)
|
||||
return newbuf;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/*
|
||||
* Find the size of the block to be balloc'ed. It takes in a size, finds the
|
||||
* smallest binary block it fits into, adds an overhead amount and returns.
|
||||
* q is the binary size used to keep track of block sizes in use. Called
|
||||
* from both balloc and bfree.
|
||||
*/
|
||||
|
||||
static int ballocGetSize(int size, int *q)
|
||||
{
|
||||
int mask;
|
||||
|
||||
mask = (size == 0) ? 0 : (size-1) >> B_SHIFT;
|
||||
for (*q = 0; mask; mask >>= 1) {
|
||||
*q = *q + 1;
|
||||
}
|
||||
return ((1 << (B_SHIFT + *q)) + sizeof(bType));
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
#if B_FILL || B_VERIFY_CAUSES_SEVERE_OVERHEAD
|
||||
@@ -464,17 +525,20 @@ static void bFillBlock(void *buf, int bufsize)
|
||||
#if B_STATS
|
||||
/*
|
||||
* Statistics. Do output via calling the writefn callback function with
|
||||
* "handle" as the output file handle.
|
||||
* "handle" as the output file handle.
|
||||
*/
|
||||
|
||||
void bstats(int handle, void (*writefn)(int handle, char_t *fmt, ...))
|
||||
{
|
||||
bStatsFileType *fp;
|
||||
bStatsFileType *fp, *files;
|
||||
bStatsBlkType *blkp;
|
||||
bType *bp;
|
||||
int q, count, mem, total;
|
||||
char_t *cp;
|
||||
int q, count, mem, total, len;
|
||||
static int recurseProtect = 0;
|
||||
|
||||
if (recurseProtect++ > 0) {
|
||||
recurseProtect--;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -492,19 +556,18 @@ void bstats(int handle, void (*writefn)(int handle, char_t *fmt, ...))
|
||||
* Q Size Free Bytes Inuse Bytes Allocs
|
||||
* dd ddddd ddd ddddd dddd ddddd dddd
|
||||
*/
|
||||
(*writefn)(handle, " Q Size Free Bytes Inuse Bytes Allocs\n");
|
||||
(*writefn)(handle, " Q Size Free Bytes Inuse Bytes Allocs\n");
|
||||
|
||||
total = 0;
|
||||
for (q = 0; q < B_MAX_CLASS; q++) {
|
||||
count = 0;
|
||||
for (bp = bQhead[q]; bp; bp = bp->u.next) {
|
||||
a_assert((bp->flags & B_INTEGRITY_MASK) == B_INTEGRITY);
|
||||
count++;
|
||||
}
|
||||
mem = count * (1 << (q + B_SHIFT));
|
||||
total += mem;
|
||||
(*writefn)(handle,
|
||||
T("%2d %5d %3d %5d %4d %5d %4d\n"),
|
||||
T("%2d %5d %4d %6d %4d %5d %4d\n"),
|
||||
q, 1 << (q + B_SHIFT), count, mem, bStats[q].inuse,
|
||||
bStats[q].inuse * (1 << (q + B_SHIFT)), bStats[q].alloc);
|
||||
}
|
||||
@@ -513,11 +576,26 @@ void bstats(int handle, void (*writefn)(int handle, char_t *fmt, ...))
|
||||
|
||||
/*
|
||||
* Print summary stats
|
||||
*
|
||||
* bFreeSize Initial memory reserved with bopen call
|
||||
* bStatsMemMalloc memory from calls to system MALLOC
|
||||
* bStatsMemMax
|
||||
* bStatsBallocMax largest amount of memory from balloc calls
|
||||
* bStatsMemInUse
|
||||
* bStatsBallocInUse present balloced memory being used
|
||||
* bStatsBlksMax);
|
||||
* bStackStart
|
||||
* bStackMin);
|
||||
* total);
|
||||
* bFreeLeft);
|
||||
*
|
||||
*/
|
||||
(*writefn)(handle, T("Initial free list size %7d\n"), bFreeSize);
|
||||
(*writefn)(handle, T("Max memory malloced %7d\n"), bStatsMemMalloc);
|
||||
(*writefn)(handle, T("Max memory ever used %7d\n"), bStatsMemMax);
|
||||
(*writefn)(handle, T("Max memory ever balloced %7d\n"), bStatsBallocMax);
|
||||
(*writefn)(handle, T("Memory currently in use %7d\n"), bStatsMemInUse);
|
||||
(*writefn)(handle, T("Memory currently balloced %7d\n"), bStatsBallocInUse);
|
||||
(*writefn)(handle, T("Max blocks allocated %7d\n"), bStatsBlksMax);
|
||||
(*writefn)(handle, T("Maximum stack used %7d\n"),
|
||||
(int) bStackStart - (int) bStackMin);
|
||||
@@ -527,20 +605,49 @@ void bstats(int handle, void (*writefn)(int handle, char_t *fmt, ...))
|
||||
(*writefn)(handle, T("Total free memory %7d\n"), bFreeLeft + total);
|
||||
|
||||
/*
|
||||
* Print per file allocation stats
|
||||
* Print per file allocation stats. Sort the copied table.
|
||||
*/
|
||||
qsort(bStatsFiles, bStatsFilesMax, sizeof(bStatsFileType), bStatsFileSort);
|
||||
(*writefn)(handle, T("\nPer File Memory Stats\n"));
|
||||
len = sizeof(bStatsFileType) * B_MAX_FILES;
|
||||
files = malloc(len);
|
||||
if (files == NULL) {
|
||||
(*writefn)(handle, T("Can't allocate stats memory\n"));
|
||||
recurseProtect--;
|
||||
return;
|
||||
}
|
||||
memcpy(files, bStatsFiles, len);
|
||||
qsort(files, bStatsFilesMax, sizeof(bStatsFileType), bStatsFileSort);
|
||||
|
||||
(*writefn)(handle, T("\nMemory Currently Allocated\n"));
|
||||
total = 0;
|
||||
for (fp = bStatsFiles; fp < &bStatsFiles[bStatsFilesMax]; fp++) {
|
||||
(*writefn)(handle,
|
||||
T(" bytes, blocks in use, total times,")
|
||||
T("largest, q\n"));
|
||||
|
||||
for (fp = files; fp < &files[bStatsFilesMax]; fp++) {
|
||||
if (fp->file[0]) {
|
||||
(*writefn)(handle,
|
||||
T("%18s, bytes %7d, blocks in use %5d, total allocs %6d\n"),
|
||||
fp->file, fp->allocated, fp->count, fp->allocs);
|
||||
(*writefn)(handle, T("%18s, %7d, %5d, %6d, %7d,%4d\n"),
|
||||
fp->file, fp->allocated, fp->count, fp->times, fp->largest,
|
||||
fp->q);
|
||||
total += fp->allocated;
|
||||
}
|
||||
}
|
||||
(*writefn)(handle, T("\nTotal allocated %7d\n"), total);
|
||||
(*writefn)(handle, T("\nTotal allocated %7d\n\n"), total);
|
||||
|
||||
/*
|
||||
* Dump the actual strings
|
||||
*/
|
||||
(*writefn)(handle, T("\nStrings\n"));
|
||||
for (blkp = &bStatsBlks[bStatsBlksMax - 1]; blkp >= bStatsBlks; blkp--) {
|
||||
if (blkp->ptr) {
|
||||
cp = (char_t*) ((char*) blkp->ptr + sizeof(bType));
|
||||
fp = blkp->who;
|
||||
if (gisalnum(*cp)) {
|
||||
(*writefn)(handle, T("%-50s allocated by %s\n"), cp,
|
||||
fp->file);
|
||||
}
|
||||
}
|
||||
}
|
||||
free(files);
|
||||
recurseProtect--;
|
||||
}
|
||||
|
||||
@@ -563,26 +670,6 @@ static int bStatsFileSort(const void *cp1, const void *cp2)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/*
|
||||
* Default output function. Just send to trace channel.
|
||||
*/
|
||||
|
||||
static void bstatsWrite(int handle, char_t *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
char_t *buf;
|
||||
|
||||
va_start(args, fmt);
|
||||
buf = NULL;
|
||||
gvsnprintf(&buf, VALUE_MAX_STRING, fmt, args);
|
||||
va_end(args);
|
||||
goahead_trace(0, buf);
|
||||
if (buf) {
|
||||
bfree(B_L, buf);
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/*
|
||||
* Accumulate allocation statistics
|
||||
@@ -590,23 +677,24 @@ static void bstatsWrite(int handle, char_t *fmt, ...)
|
||||
|
||||
static void bStatsAlloc(B_ARGS_DEC, void *ptr, int q, int size)
|
||||
{
|
||||
int memSize;
|
||||
bStatsFileType *fp;
|
||||
bStatsBlkType *bp;
|
||||
char_t name[FNAMESIZE + 10];
|
||||
|
||||
a_assert(file && *file);
|
||||
a_assert(0 <= q && q <= B_MAX_CLASS);
|
||||
a_assert(size > 0);
|
||||
|
||||
gsprintf(name, T("%s:%d"), B_ARGS);
|
||||
|
||||
bStats[q].alloc++;
|
||||
bStats[q].inuse++;
|
||||
bStatsMemInUse += size;
|
||||
|
||||
if (bStatsMemInUse > bStatsMemMax) {
|
||||
bStatsMemMax = bStatsMemInUse;
|
||||
}
|
||||
memSize = (1 << (B_SHIFT + q)) + sizeof(bType);
|
||||
bStatsBallocInUse += memSize;
|
||||
if (bStatsBallocInUse > bStatsBallocMax) {
|
||||
bStatsBallocMax = bStatsBallocInUse;
|
||||
}
|
||||
|
||||
/*
|
||||
* Track maximum stack usage. Assumes a stack growth down. Approximate as
|
||||
@@ -623,13 +711,17 @@ static void bStatsAlloc(B_ARGS_DEC, void *ptr, int q, int size)
|
||||
if (fp->file[0] == file[0] && gstrcmp(fp->file, name) == 0) {
|
||||
fp->allocated += size;
|
||||
fp->count++;
|
||||
fp->allocs++;
|
||||
fp->times++;
|
||||
if (fp->largest < size) {
|
||||
fp->largest = size;
|
||||
fp->q = q;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Find the first free slot for this file and add current block size.
|
||||
* New entry: find the first free slot and create a new entry
|
||||
*/
|
||||
if (fp >= &bStatsFiles[bStatsFilesMax]) {
|
||||
for (fp = bStatsFiles; fp < &bStatsFiles[B_MAX_FILES]; fp++) {
|
||||
@@ -637,7 +729,9 @@ static void bStatsAlloc(B_ARGS_DEC, void *ptr, int q, int size)
|
||||
gstrncpy(fp->file, name, TSZ(fp->file));
|
||||
fp->allocated += size;
|
||||
fp->count++;
|
||||
fp->allocs++;
|
||||
fp->times++;
|
||||
fp->largest = size;
|
||||
fp->q = q;
|
||||
if ((fp - bStatsFiles) >= bStatsFilesMax) {
|
||||
bStatsFilesMax = (fp - bStatsFiles) + 1;
|
||||
}
|
||||
@@ -668,35 +762,48 @@ static void bStatsAlloc(B_ARGS_DEC, void *ptr, int q, int size)
|
||||
|
||||
static void bStatsFree(B_ARGS_DEC, void *ptr, int q, int size)
|
||||
{
|
||||
int memSize;
|
||||
bStatsFileType *fp;
|
||||
bStatsBlkType *bp;
|
||||
char_t name[FNAMESIZE + 10];
|
||||
|
||||
a_assert(file && *file);
|
||||
a_assert(0 <= q && q <= B_MAX_CLASS);
|
||||
a_assert(size > 0);
|
||||
|
||||
memSize = (1 << (B_SHIFT + q)) + sizeof(bType);
|
||||
bStatsMemInUse -= size;
|
||||
bStatsBallocInUse -= memSize;
|
||||
bStats[q].inuse--;
|
||||
|
||||
gsprintf(name, T("%s:%d"), B_ARGS);
|
||||
|
||||
/*
|
||||
* Update the per block stats
|
||||
* Update the per block stats. Try from the end first
|
||||
*/
|
||||
for (bp = bStatsBlks; bp < &bStatsBlks[bStatsBlksMax]; bp++) {
|
||||
for (bp = &bStatsBlks[bStatsBlksMax - 1]; bp >= bStatsBlks; bp--) {
|
||||
if (bp->ptr == ptr) {
|
||||
bp->ptr = NULL;
|
||||
fp = bp->who;
|
||||
bp->who = NULL;
|
||||
fp->allocated -= size;
|
||||
fp->count--;
|
||||
return;
|
||||
}
|
||||
}
|
||||
a_assert(0);
|
||||
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/*
|
||||
* Default output function. Just send to trace channel.
|
||||
*/
|
||||
|
||||
#undef sprintf
|
||||
static void bstatsWrite(int handle, char_t *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
char_t buf[BUF_MAX];
|
||||
|
||||
va_start(args, fmt);
|
||||
vsprintf(buf, fmt, args);
|
||||
va_end(args);
|
||||
traceRaw(buf);
|
||||
}
|
||||
|
||||
|
||||
#else /* not B_STATS */
|
||||
/******************************************************************************/
|
||||
/*
|
||||
@@ -712,10 +819,10 @@ void bstats(int handle, void (*writefn)(int handle, char_t *fmt, ...))
|
||||
#if B_VERIFY_CAUSES_SEVERE_OVERHEAD
|
||||
/*
|
||||
* The following routines verify the integrity of the balloc memory space.
|
||||
* These functions depend use the B_FILL feature. Corruption is defined
|
||||
* These functions use the B_FILL feature. Corruption is defined
|
||||
* as bad integrity flags in allocated blocks or data other than B_FILL_CHAR
|
||||
* being found anywhere in the space which is unallocated and that is not a
|
||||
* next pointer in the free queues. a_assert is called if any corruption is
|
||||
* next pointer in the free queues. a_assert is called if any corruption is
|
||||
* found. CAUTION: These functions add severe processing overhead and should
|
||||
* only be used when searching for a tough corruption problem.
|
||||
*/
|
||||
@@ -731,8 +838,8 @@ static void verifyUsedBlock(bType *bp, int q)
|
||||
int memSize, size;
|
||||
char *p;
|
||||
|
||||
memSize = (1 << (B_SHIFT + q));
|
||||
a_assert((bp->flags & ~B_MALLOCED) == B_INTEGRITY );
|
||||
memSize = (1 << (B_SHIFT + q)) + sizeof(bType);
|
||||
a_assert((bp->flags & ~B_MALLOCED) == B_INTEGRITY);
|
||||
size = bp->u.size;
|
||||
for (p = ((char *)bp)+sizeof(bType)+size; p < ((char*)bp)+memSize; p++) {
|
||||
a_assert(*p == B_FILL_CHAR);
|
||||
@@ -750,28 +857,41 @@ static void verifyFreeBlock(bType *bp, int q)
|
||||
int memSize;
|
||||
char *p;
|
||||
|
||||
memSize = (1 << (B_SHIFT + q));
|
||||
memSize = (1 << (B_SHIFT + q)) + sizeof(bType);
|
||||
for (p = ((char *)bp)+sizeof(void*); p < ((char*)bp)+memSize; p++) {
|
||||
a_assert(*p == B_FILL_CHAR);
|
||||
}
|
||||
bp = (bType *)p;
|
||||
a_assert((bp->flags & ~B_MALLOCED) == B_INTEGRITY ||
|
||||
bp->flags == B_FILL_WORD);
|
||||
bp->flags == B_FILL_WORD);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/*
|
||||
* verifyBallocSpace reads through the entire balloc memory space and
|
||||
* verifies that all allocated blocks are uncorrupted and that with the
|
||||
* exception of free list next pointers all other unallocated space is
|
||||
* verifies that all allocated blocks are uncorrupted and that, with the
|
||||
* exception of free list next pointers, all other unallocated space is
|
||||
* filled with B_FILL_CHAR.
|
||||
*/
|
||||
|
||||
static void verifyBallocSpace()
|
||||
void verifyBallocSpace()
|
||||
{
|
||||
int q;
|
||||
char *p;
|
||||
bType *bp;
|
||||
|
||||
/*
|
||||
* First verify all the free blocks.
|
||||
*/
|
||||
for (q = 0; q < B_MAX_CLASS; q++) {
|
||||
for (bp = bQhead[q]; bp != NULL; bp = bp->u.next) {
|
||||
verifyFreeBlock(bp, q);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Now verify other space
|
||||
*/
|
||||
p = bFreeBuf;
|
||||
while (p < (bFreeBuf + bFreeSize)) {
|
||||
bp = (bType *)p;
|
||||
@@ -782,7 +902,7 @@ static void verifyBallocSpace()
|
||||
}
|
||||
} else {
|
||||
a_assert(((bp->flags & ~B_MALLOCED) == B_INTEGRITY) ||
|
||||
bp->flags == B_FILL_WORD);
|
||||
bp->flags == B_FILL_WORD);
|
||||
p += (sizeof(bType) + bp->u.size);
|
||||
while (p < (bFreeBuf + bFreeSize) && *p == B_FILL_CHAR) {
|
||||
p++;
|
||||
@@ -807,19 +927,29 @@ void bclose()
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
#if UNICODE
|
||||
char_t* bstrdupNoBalloc(char_t* s)
|
||||
|
||||
void bstats(int handle, void (*writefn)(int handle, char_t *fmt, ...))
|
||||
{
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
char_t *bstrdupNoBalloc(char_t *s)
|
||||
{
|
||||
#if UNICODE
|
||||
if (s) {
|
||||
return wcsdup(s);
|
||||
} else {
|
||||
return wcsdup(T(""));
|
||||
}
|
||||
#else
|
||||
return bstrdupANoBalloc(s);
|
||||
#endif
|
||||
}
|
||||
#endif /* UNICODE */
|
||||
|
||||
/******************************************************************************/
|
||||
char* bstrdupANoBalloc(char* s)
|
||||
|
||||
char *bstrdupANoBalloc(char *s)
|
||||
{
|
||||
char* buf;
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* base64.c -- Base64 Mime encoding
|
||||
*
|
||||
* Copyright (c) Go Ahead Software Inc., 1995-1999. All Rights Reserved.
|
||||
* Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved.
|
||||
*
|
||||
* See the file "license.txt" for usage and redistribution license requirements
|
||||
*/
|
||||
@@ -60,11 +60,10 @@ static char_t alphabet64[] = {
|
||||
* Decode a buffer from "string" and into "outbuf"
|
||||
*/
|
||||
|
||||
int websDecode64(char_t* outbuf, char_t* string, int outlen)
|
||||
int websDecode64(char_t *outbuf, char_t *string, int outlen)
|
||||
{
|
||||
unsigned long shiftbuf;
|
||||
char_t* cp;
|
||||
char_t* op;
|
||||
char_t *cp, *op;
|
||||
int c, i, j, shift;
|
||||
|
||||
op = outbuf;
|
||||
@@ -109,11 +108,10 @@ int websDecode64(char_t* outbuf, char_t* string, int outlen)
|
||||
* Encode a buffer from "string" into "outbuf"
|
||||
*/
|
||||
|
||||
void websEncode64(char_t* outbuf, char_t* string, int outlen)
|
||||
void websEncode64(char_t *outbuf, char_t *string, int outlen)
|
||||
{
|
||||
unsigned long shiftbuf;
|
||||
char_t* cp;
|
||||
char_t* op;
|
||||
char_t *cp, *op;
|
||||
int x, i, j, shift;
|
||||
|
||||
op = outbuf;
|
||||
@@ -1,9 +1,11 @@
|
||||
/*
|
||||
* default.c -- Default URL handler. Includes support for ASP.
|
||||
*
|
||||
* Copyright (c) Go Ahead Software Inc., 1995-1999. All Rights Reserved.
|
||||
* Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved.
|
||||
*
|
||||
* See the file "license.txt" for usage and redistribution license requirements
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
/******************************** Description *********************************/
|
||||
@@ -38,16 +40,15 @@ static void websDefaultWriteEvent(webs_t wp);
|
||||
*/
|
||||
|
||||
int websDefaultHandler(webs_t wp, char_t *urlPrefix, char_t *webDir, int arg,
|
||||
char_t *url, char_t *path, char_t* query)
|
||||
char_t *url, char_t *path, char_t *query)
|
||||
{
|
||||
websStatType sbuf;
|
||||
char_t *lpath, *tmp;
|
||||
char_t *date;
|
||||
char_t *lpath, *tmp, *date;
|
||||
int bytes, flags, nchars;
|
||||
|
||||
a_assert(websValid(wp));
|
||||
a_assert(url && *url);
|
||||
a_assert(path && *path);
|
||||
a_assert(path);
|
||||
a_assert(query);
|
||||
|
||||
/*
|
||||
@@ -74,8 +75,7 @@ int websDefaultHandler(webs_t wp, char_t *urlPrefix, char_t *webDir, int arg,
|
||||
path[--nchars] = '\0';
|
||||
}
|
||||
nchars += gstrlen(websDefaultPage) + 2;
|
||||
tmp = NULL;
|
||||
gsnprintf(&tmp, nchars, T("%s/%s"), path, websDefaultPage);
|
||||
fmtAlloc(&tmp, nchars, T("%s/%s"), path, websDefaultPage);
|
||||
websRedirect(wp, tmp);
|
||||
bfreeSafe(B_L, tmp);
|
||||
return 1;
|
||||
@@ -87,13 +87,13 @@ int websDefaultHandler(webs_t wp, char_t *urlPrefix, char_t *webDir, int arg,
|
||||
if (websPageOpen(wp, lpath, path, SOCKET_RDONLY | SOCKET_BINARY,
|
||||
0666) < 0) {
|
||||
websError(wp, 400,
|
||||
T("Can't open document <b>%s</b><br>for URL <b>%s</b>"),
|
||||
lpath, url);
|
||||
T("Cannot open URL <b>%s</b>"), url);
|
||||
return 1;
|
||||
}
|
||||
if (websPageStat(wp, lpath, path, &sbuf) < 0) {
|
||||
websError(wp, 400, T("Can't stat page <b>%s</b><br>for URL <b>%s</b>"),
|
||||
lpath, url);
|
||||
websError(wp, 400, T("Cannot stat page for URL <b>%s</b>"),
|
||||
url);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -107,12 +107,13 @@ int websDefaultHandler(webs_t wp, char_t *urlPrefix, char_t *webDir, int arg,
|
||||
if (sbuf.mtime <= wp->since) {
|
||||
websWrite(wp, T("HTTP/1.0 304 Use local copy\r\n"));
|
||||
|
||||
/* by license terms the following line of code must
|
||||
* not be modified.
|
||||
*/
|
||||
websWrite(wp, T("Server: GoAhead-Webs\r\n"));
|
||||
/*
|
||||
* by license terms the following line of code must
|
||||
* not be modified.
|
||||
*/
|
||||
websWrite(wp, T("Server: %s\r\n"), WEBS_NAME);
|
||||
|
||||
if (flags && WEBS_KEEP_ALIVE) {
|
||||
if (flags & WEBS_KEEP_ALIVE) {
|
||||
websWrite(wp, T("Connection: keep-alive\r\n"));
|
||||
}
|
||||
websWrite(wp, T("\r\n"));
|
||||
@@ -131,8 +132,8 @@ int websDefaultHandler(webs_t wp, char_t *urlPrefix, char_t *webDir, int arg,
|
||||
|
||||
/*
|
||||
* By license terms the following line of code must not be modified.
|
||||
*/
|
||||
websWrite(wp, T("Server: GoAhead-Webs\r\n"));
|
||||
*/
|
||||
websWrite(wp, T("Server: %s\r\n"), WEBS_NAME);
|
||||
bfree(B_L, date);
|
||||
}
|
||||
flags |= WEBS_HEADER_DONE;
|
||||
@@ -164,6 +165,14 @@ int websDefaultHandler(webs_t wp, char_t *urlPrefix, char_t *webDir, int arg,
|
||||
}
|
||||
websWrite(wp, T("\r\n"));
|
||||
|
||||
/*
|
||||
* All done if the browser did a HEAD request
|
||||
*/
|
||||
if (flags & WEBS_HEAD_REQUEST) {
|
||||
websDone(wp, 200);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Evaluate ASP requests
|
||||
*/
|
||||
@@ -175,17 +184,18 @@ int websDefaultHandler(webs_t wp, char_t *urlPrefix, char_t *webDir, int arg,
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* All done if the browser did a HEAD request
|
||||
*/
|
||||
if (flags & WEBS_HEAD_REQUEST) {
|
||||
websDone(wp, 200);
|
||||
return 1;
|
||||
#ifdef WEBS_SSL_SUPPORT
|
||||
if (wp->flags & WEBS_SECURE) {
|
||||
websDefaultWriteEvent(wp);
|
||||
} else {
|
||||
websSetRequestSocketHandler(wp, SOCKET_WRITABLE, websDefaultWriteEvent);
|
||||
}
|
||||
#else
|
||||
/*
|
||||
* For normal web documents, return the data via background write
|
||||
*/
|
||||
websSetRequestSocketHandler(wp, SOCKET_WRITABLE, websDefaultWriteEvent);
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -240,7 +250,7 @@ int websValidateUrl(webs_t wp, char_t *path)
|
||||
/*
|
||||
* Create local path for document. Need extra space all "/" and null.
|
||||
*/
|
||||
if (npart) {
|
||||
if (npart || (gstrcmp(path, T("/")) == 0) || (path[0] == '\0')) {
|
||||
lpath = balloc(B_L, (gstrlen(dir) + 1 + len + 1) * sizeof(char_t));
|
||||
gstrcpy(lpath, dir);
|
||||
|
||||
@@ -267,15 +277,16 @@ int websValidateUrl(webs_t wp, char_t *path)
|
||||
|
||||
static void websDefaultWriteEvent(webs_t wp)
|
||||
{
|
||||
int len, wrote, flags, bytes, written;
|
||||
char * buf;
|
||||
int len, wrote, flags, bytes, written;
|
||||
char *buf;
|
||||
|
||||
a_assert(websValid(wp));
|
||||
|
||||
flags = websGetRequestFlags(wp);
|
||||
|
||||
wrote = 0;
|
||||
bytes = 0;
|
||||
websMarkTime(wp);
|
||||
|
||||
wrote = bytes = 0;
|
||||
written = websGetRequestWritten(wp);
|
||||
|
||||
/*
|
||||
@@ -284,20 +295,20 @@ static void websDefaultWriteEvent(webs_t wp)
|
||||
if ( !(flags & WEBS_ASP)) {
|
||||
bytes = websGetRequestBytes(wp);
|
||||
/*
|
||||
* Note: websWriteBlock may return less than we wanted. It will return
|
||||
* -1 on a socket error
|
||||
* Note: websWriteDataNonBlock may return less than we wanted. It will
|
||||
* return -1 on a socket error
|
||||
*/
|
||||
if ((buf = balloc(B_L, PAGE_READ_BUFSIZE)) == NULL) {
|
||||
websError(wp, 200, T("Can't get memory"));
|
||||
}
|
||||
else {
|
||||
while ((len = websPageReadData(wp, buf, PAGE_READ_BUFSIZE)) > 0) {
|
||||
if ((wrote = websWriteBlockData(wp, buf, len)) < 0) {
|
||||
if ((wrote = websWriteDataNonBlock(wp, buf, len)) < 0) {
|
||||
break;
|
||||
}
|
||||
written += wrote;
|
||||
if (wrote != len) {
|
||||
websPageSeek(wp, - (wrote - len));
|
||||
websPageSeek(wp, - (len - wrote));
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -330,9 +341,11 @@ void websDefaultClose()
|
||||
{
|
||||
if (websDefaultPage) {
|
||||
bfree(B_L, websDefaultPage);
|
||||
websDefaultPage = NULL;
|
||||
}
|
||||
if (websDefaultDir) {
|
||||
bfree(B_L, websDefaultDir);
|
||||
websDefaultDir = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* ej.h -- Ejscript(TM) header
|
||||
*
|
||||
* Copyright (c) Go Ahead Software, Inc., 1992-1999
|
||||
* Copyright (c) GoAhead Software Inc., 1992-2000. All Rights Reserved.
|
||||
*
|
||||
* See the file "license.txt" for information on usage and redistribution
|
||||
*/
|
||||
@@ -12,214 +12,32 @@
|
||||
/******************************** Description *********************************/
|
||||
|
||||
/*
|
||||
* Go Ahead Ejscript(TM) header. This defines the Ejscript API and internal
|
||||
* GoAhead Ejscript(TM) header. This defines the Ejscript API and internal
|
||||
* structures.
|
||||
*/
|
||||
|
||||
/********************************* Includes ***********************************/
|
||||
|
||||
#include <ctype.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
#ifndef CE
|
||||
#include <fcntl.h>
|
||||
#endif
|
||||
|
||||
#if LYNX
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#ifdef QNX4
|
||||
#include <dirent.h>
|
||||
#endif
|
||||
|
||||
#if UEMF
|
||||
#include "uemf.h"
|
||||
#else
|
||||
#include <param.h>
|
||||
#include <stat.h>
|
||||
#include "basic/basicInternal.h"
|
||||
#if ! UEMF
|
||||
#include "basic/basic.h"
|
||||
#include "emf/emf.h"
|
||||
#include "webs/webs.h"
|
||||
#else
|
||||
#include "uemf.h"
|
||||
#endif
|
||||
|
||||
/********************************** Defines ***********************************/
|
||||
/*
|
||||
* Constants
|
||||
*/
|
||||
#define EJ_INC 110 /* Growth for tags/tokens */
|
||||
#define EJ_OFFSET 1 /* hAlloc doesn't like 0 entries */
|
||||
#define EJ_MAX_RECURSE 100 /* Sanity for maximum recursion */
|
||||
|
||||
/*
|
||||
* Ejscript Lexical analyser tokens
|
||||
*/
|
||||
#define TOK_ERR -1 /* Any error */
|
||||
#define TOK_LPAREN 1 /* ( */
|
||||
#define TOK_RPAREN 2 /* ) */
|
||||
#define TOK_IF 3 /* if */
|
||||
#define TOK_ELSE 4 /* else */
|
||||
#define TOK_LBRACE 5 /* { */
|
||||
#define TOK_RBRACE 6 /* } */
|
||||
#define TOK_LOGICAL 7 /* ||, &&, ! */
|
||||
#define TOK_EXPR 8 /* +, -, /, % */
|
||||
#define TOK_SEMI 9 /* ; */
|
||||
#define TOK_LITERAL 10 /* literal string */
|
||||
#define TOK_FUNCTION 11 /* function name */
|
||||
#define TOK_NEWLINE 12 /* newline white space */
|
||||
#define TOK_ID 13 /* function name */
|
||||
#define TOK_EOF 14 /* End of script */
|
||||
#define TOK_COMMA 15 /* Comma */
|
||||
#define TOK_VAR 16 /* var */
|
||||
#define TOK_ASSIGNMENT 17 /* = */
|
||||
#define TOK_FOR 18 /* for */
|
||||
#define TOK_INC_DEC 19 /* ++, -- */
|
||||
#define TOK_RETURN 20 /* return */
|
||||
|
||||
/*
|
||||
* Expression operators
|
||||
*/
|
||||
#define EXPR_LESS 1 /* < */
|
||||
#define EXPR_LESSEQ 2 /* <= */
|
||||
#define EXPR_GREATER 3 /* > */
|
||||
#define EXPR_GREATEREQ 4 /* >= */
|
||||
#define EXPR_EQ 5 /* == */
|
||||
#define EXPR_NOTEQ 6 /* != */
|
||||
#define EXPR_PLUS 7 /* + */
|
||||
#define EXPR_MINUS 8 /* - */
|
||||
#define EXPR_DIV 9 /* / */
|
||||
#define EXPR_MOD 10 /* % */
|
||||
#define EXPR_LSHIFT 11 /* << */
|
||||
#define EXPR_RSHIFT 12 /* >> */
|
||||
#define EXPR_MUL 13 /* * */
|
||||
#define EXPR_ASSIGNMENT 14 /* = */
|
||||
#define EXPR_INC 15 /* ++ */
|
||||
#define EXPR_DEC 16 /* -- */
|
||||
|
||||
/*
|
||||
* Conditional operators
|
||||
*/
|
||||
#define COND_AND 1 /* && */
|
||||
#define COND_OR 2 /* || */
|
||||
#define COND_NOT 3 /* ! */
|
||||
|
||||
/*
|
||||
* States
|
||||
*/
|
||||
#define STATE_ERR -1 /* Error state */
|
||||
#define STATE_EOF 1 /* End of file */
|
||||
#define STATE_COND 2 /* Parsing a "(conditional)" stmt */
|
||||
#define STATE_COND_DONE 3
|
||||
#define STATE_RELEXP 4 /* Parsing a relational expr */
|
||||
#define STATE_RELEXP_DONE 5
|
||||
#define STATE_EXPR 6 /* Parsing an expression */
|
||||
#define STATE_EXPR_DONE 7
|
||||
#define STATE_STMT 8 /* Parsing General statement */
|
||||
#define STATE_STMT_DONE 9
|
||||
#define STATE_STMT_BLOCK_DONE 10 /* End of block "}" */
|
||||
#define STATE_ARG_LIST 11 /* Function arg list */
|
||||
#define STATE_ARG_LIST_DONE 12
|
||||
#define STATE_DEC_LIST 16 /* Declaration list */
|
||||
#define STATE_DEC_LIST_DONE 17
|
||||
#define STATE_DEC 18
|
||||
#define STATE_DEC_DONE 19
|
||||
#define STATE_BEGIN STATE_STMT
|
||||
|
||||
/*
|
||||
* Flags. Used in ej_t and as parameter to parse()
|
||||
*/
|
||||
#define FLAGS_EXE 0x1 /* Execute statements */
|
||||
#define FLAGS_VARIABLES 0x2 /* Allocated variables store */
|
||||
#define FLAGS_FUNCTIONS 0x4 /* Allocated function store */
|
||||
|
||||
/*
|
||||
* Function call structure
|
||||
*/
|
||||
typedef struct {
|
||||
char_t *fname; /* Function name */
|
||||
char_t **args; /* Args for function (halloc) */
|
||||
int nArgs; /* Number of args */
|
||||
} ejfunc_t;
|
||||
|
||||
/*
|
||||
* EJ evaluation block structure
|
||||
*/
|
||||
typedef struct ejEval {
|
||||
ringq_t tokbuf; /* Current token */
|
||||
ringq_t script; /* Input script for parsing */
|
||||
char_t *putBackToken; /* Putback token string */
|
||||
int putBackTokenId; /* Putback token ID */
|
||||
char_t *line; /* Current line */
|
||||
int lineLength; /* Current line length */
|
||||
int lineNumber; /* Parse line number */
|
||||
int lineColumn; /* Column in line */
|
||||
} ejinput_t;
|
||||
|
||||
/*
|
||||
* Per Ejscript session structure
|
||||
*/
|
||||
typedef struct ej {
|
||||
ejinput_t *input; /* Input evaluation block */
|
||||
sym_fd_t functions; /* Symbol table for functions */
|
||||
sym_fd_t *variables; /* hAlloc list of variables */
|
||||
int variableMax; /* Number of entries */
|
||||
ejfunc_t *func; /* Current function */
|
||||
char_t *result; /* Current expression result */
|
||||
char_t *error; /* Error message */
|
||||
char_t *token; /* Pointer to token string */
|
||||
int tid; /* Current token id */
|
||||
int eid; /* Halloc handle */
|
||||
int flags; /* Flags */
|
||||
int userHandle; /* User defined handle */
|
||||
} ej_t;
|
||||
|
||||
/******************************** Prototypes **********************************/
|
||||
|
||||
extern int ejArgs(int argc, char_t **argv, char_t *fmt, ...);
|
||||
extern void ejSetResult(int eid, char_t *s);
|
||||
extern int ejOpenEngine(sym_fd_t variables, sym_fd_t functions);
|
||||
extern void ejCloseEngine(int eid);
|
||||
extern int ejOpenBlock(int eid);
|
||||
extern int ejCloseBlock(int eid, int vid);
|
||||
extern char_t *ejEval(int eid, char_t *script, char_t **emsg);
|
||||
extern char_t *ejEvalBlock(int eid, char_t *script, char_t **emsg);
|
||||
extern char_t *ejEvalFile(int eid, char_t *path, char_t **emsg);
|
||||
extern int ejSetGlobalFunction(int eid, char_t *name,
|
||||
int (*fn)(int eid, void *handle, int argc, char_t **argv));
|
||||
extern void *ejGetGlobalFunction(int eid, char_t *name);
|
||||
extern int ejSetGlobalFunctionDirect(sym_fd_t functions, char_t *name,
|
||||
int (*fn)(int eid, void *handle, int argc, char_t **argv));
|
||||
extern int ejArgs(int argc, char_t **argv, char_t *fmt, ...);
|
||||
extern void ejError(ej_t* ep, char_t* fmt, ...);
|
||||
extern void ejSetUserHandle(int eid, int handle);
|
||||
extern int ejGetUserHandle(int eid);
|
||||
extern int ejGetLineNumber(int eid);
|
||||
extern void ejSetResult(int eid, char_t *s);
|
||||
extern char_t *ejGetResult(int eid);
|
||||
extern void ejSetVar(int eid, char_t *var, char_t *value);
|
||||
extern void ejSetLocalVar(int eid, char_t *var, char_t *value);
|
||||
extern int ejGetVar(int eid, char_t *var, char_t **value);
|
||||
extern void ejSetGlobalVar(int eid, char_t *var, char_t *value);
|
||||
|
||||
extern int ejLexOpen(ej_t* ep);
|
||||
extern void ejLexClose(ej_t* ep);
|
||||
extern int ejLexOpenScript(ej_t* ep, char_t *script);
|
||||
extern void ejLexCloseScript(ej_t* ep);
|
||||
extern void ejLexSaveInputState(ej_t* ep, ejinput_t* state);
|
||||
extern void ejLexFreeInputState(ej_t* ep, ejinput_t* state);
|
||||
extern void ejLexRestoreInputState(ej_t* ep, ejinput_t* state);
|
||||
extern int ejLexGetToken(ej_t* ep, int state);
|
||||
extern void ejLexPutbackToken(ej_t* ep, int tid, char_t *string);
|
||||
|
||||
extern sym_fd_t ejGetVariableTable(int eid);
|
||||
extern sym_fd_t ejGetFunctionTable(int eid);
|
||||
|
||||
extern int ejEmfOpen(int eid);
|
||||
extern void ejEmfClose(int eid);
|
||||
|
||||
extern int ejEmfDbRead(int eid, void *handle, int argc, char_t **argv);
|
||||
extern int ejEmfDbReadKeyed(int eid, void *handle, int argc, char_t **argv);
|
||||
extern int ejEmfDbTableGetNrow(int eid, void *handle, int argc, char_t **argv);
|
||||
extern int ejEmfTrace(int eid, void *handle, int argc, char_t **argv);
|
||||
extern int ejEmfDbWrite(int eid, void *handle, int argc, char_t **argv);
|
||||
extern char_t *ejEval(int eid, char_t *script, char_t **emsg);
|
||||
|
||||
#endif /* _h_EJ */
|
||||
|
||||
|
||||
228
c/src/libnetworking/rtems_webserver/ejIntrn.h
Normal file
228
c/src/libnetworking/rtems_webserver/ejIntrn.h
Normal file
@@ -0,0 +1,228 @@
|
||||
/*
|
||||
* ejIntrn.h -- Ejscript(TM) header
|
||||
*
|
||||
* Copyright (c) GoAhead Software, Inc., 1992-2000
|
||||
*
|
||||
* See the file "license.txt" for information on usage and redistribution
|
||||
*/
|
||||
|
||||
#ifndef _h_EJINTERNAL
|
||||
#define _h_EJINTERNAL 1
|
||||
|
||||
/******************************** Description *********************************/
|
||||
|
||||
/*
|
||||
* GoAhead Ejscript(TM) header. This defines the Ejscript API and internal
|
||||
* structures.
|
||||
*/
|
||||
|
||||
/********************************* Includes ***********************************/
|
||||
|
||||
#include <ctype.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#if CE
|
||||
#if ! UEMF
|
||||
#include <io.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if LYNX
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#ifdef QNX4
|
||||
#include <dirent.h>
|
||||
#endif
|
||||
|
||||
#if UEMF
|
||||
#include "uemf.h"
|
||||
#else
|
||||
#include <param.h>
|
||||
#include <stat.h>
|
||||
#include "basic/basicInternal.h"
|
||||
#include "emf/emfInternal.h"
|
||||
#endif
|
||||
|
||||
#include "ej.h"
|
||||
|
||||
/********************************** Defines ***********************************/
|
||||
/*
|
||||
* Constants
|
||||
*/
|
||||
#define EJ_INC 110 /* Growth for tags/tokens */
|
||||
#define EJ_SCRIPT_INC 1023 /* Growth for ej scripts */
|
||||
#define EJ_OFFSET 1 /* hAlloc doesn't like 0 entries */
|
||||
#define EJ_MAX_RECURSE 100 /* Sanity for maximum recursion */
|
||||
|
||||
/*
|
||||
* Ejscript Lexical analyser tokens
|
||||
*/
|
||||
#define TOK_ERR -1 /* Any error */
|
||||
#define TOK_LPAREN 1 /* ( */
|
||||
#define TOK_RPAREN 2 /* ) */
|
||||
#define TOK_IF 3 /* if */
|
||||
#define TOK_ELSE 4 /* else */
|
||||
#define TOK_LBRACE 5 /* { */
|
||||
#define TOK_RBRACE 6 /* } */
|
||||
#define TOK_LOGICAL 7 /* ||, &&, ! */
|
||||
#define TOK_EXPR 8 /* +, -, /, % */
|
||||
#define TOK_SEMI 9 /* ; */
|
||||
#define TOK_LITERAL 10 /* literal string */
|
||||
#define TOK_FUNCTION 11 /* function name */
|
||||
#define TOK_NEWLINE 12 /* newline white space */
|
||||
#define TOK_ID 13 /* function name */
|
||||
#define TOK_EOF 14 /* End of script */
|
||||
#define TOK_COMMA 15 /* Comma */
|
||||
#define TOK_VAR 16 /* var */
|
||||
#define TOK_ASSIGNMENT 17 /* = */
|
||||
#define TOK_FOR 18 /* for */
|
||||
#define TOK_INC_DEC 19 /* ++, -- */
|
||||
#define TOK_RETURN 20 /* return */
|
||||
|
||||
/*
|
||||
* Expression operators
|
||||
*/
|
||||
#define EXPR_LESS 1 /* < */
|
||||
#define EXPR_LESSEQ 2 /* <= */
|
||||
#define EXPR_GREATER 3 /* > */
|
||||
#define EXPR_GREATEREQ 4 /* >= */
|
||||
#define EXPR_EQ 5 /* == */
|
||||
#define EXPR_NOTEQ 6 /* != */
|
||||
#define EXPR_PLUS 7 /* + */
|
||||
#define EXPR_MINUS 8 /* - */
|
||||
#define EXPR_DIV 9 /* / */
|
||||
#define EXPR_MOD 10 /* % */
|
||||
#define EXPR_LSHIFT 11 /* << */
|
||||
#define EXPR_RSHIFT 12 /* >> */
|
||||
#define EXPR_MUL 13 /* * */
|
||||
#define EXPR_ASSIGNMENT 14 /* = */
|
||||
#define EXPR_INC 15 /* ++ */
|
||||
#define EXPR_DEC 16 /* -- */
|
||||
#define EXPR_BOOL_COMP 17 /* ! */
|
||||
/*
|
||||
* Conditional operators
|
||||
*/
|
||||
#define COND_AND 1 /* && */
|
||||
#define COND_OR 2 /* || */
|
||||
#define COND_NOT 3 /* ! */
|
||||
|
||||
/*
|
||||
* States
|
||||
*/
|
||||
#define STATE_ERR -1 /* Error state */
|
||||
#define STATE_EOF 1 /* End of file */
|
||||
#define STATE_COND 2 /* Parsing a "(conditional)" stmt */
|
||||
#define STATE_COND_DONE 3
|
||||
#define STATE_RELEXP 4 /* Parsing a relational expr */
|
||||
#define STATE_RELEXP_DONE 5
|
||||
#define STATE_EXPR 6 /* Parsing an expression */
|
||||
#define STATE_EXPR_DONE 7
|
||||
#define STATE_STMT 8 /* Parsing General statement */
|
||||
#define STATE_STMT_DONE 9
|
||||
#define STATE_STMT_BLOCK_DONE 10 /* End of block "}" */
|
||||
#define STATE_ARG_LIST 11 /* Function arg list */
|
||||
#define STATE_ARG_LIST_DONE 12
|
||||
#define STATE_DEC_LIST 16 /* Declaration list */
|
||||
#define STATE_DEC_LIST_DONE 17
|
||||
#define STATE_DEC 18
|
||||
#define STATE_DEC_DONE 19
|
||||
|
||||
#define STATE_RET 20 /* Return statement */
|
||||
|
||||
#define STATE_BEGIN STATE_STMT
|
||||
|
||||
/*
|
||||
* Flags. Used in ej_t and as parameter to parse()
|
||||
*/
|
||||
#define FLAGS_EXE 0x1 /* Execute statements */
|
||||
#define FLAGS_VARIABLES 0x2 /* Allocated variables store */
|
||||
#define FLAGS_FUNCTIONS 0x4 /* Allocated function store */
|
||||
|
||||
/*
|
||||
* Function call structure
|
||||
*/
|
||||
typedef struct {
|
||||
char_t *fname; /* Function name */
|
||||
char_t **args; /* Args for function (halloc) */
|
||||
int nArgs; /* Number of args */
|
||||
} ejfunc_t;
|
||||
|
||||
/*
|
||||
* EJ evaluation block structure
|
||||
*/
|
||||
typedef struct ejEval {
|
||||
ringq_t tokbuf; /* Current token */
|
||||
ringq_t script; /* Input script for parsing */
|
||||
char_t *putBackToken; /* Putback token string */
|
||||
int putBackTokenId; /* Putback token ID */
|
||||
char_t *line; /* Current line */
|
||||
int lineLength; /* Current line length */
|
||||
int lineNumber; /* Parse line number */
|
||||
int lineColumn; /* Column in line */
|
||||
} ejinput_t;
|
||||
|
||||
/*
|
||||
* Per Ejscript session structure
|
||||
*/
|
||||
typedef struct ej {
|
||||
ejinput_t *input; /* Input evaluation block */
|
||||
sym_fd_t functions; /* Symbol table for functions */
|
||||
sym_fd_t *variables; /* hAlloc list of variables */
|
||||
int variableMax; /* Number of entries */
|
||||
ejfunc_t *func; /* Current function */
|
||||
char_t *result; /* Current expression result */
|
||||
char_t *error; /* Error message */
|
||||
char_t *token; /* Pointer to token string */
|
||||
int tid; /* Current token id */
|
||||
int eid; /* Halloc handle */
|
||||
int flags; /* Flags */
|
||||
int userHandle; /* User defined handle */
|
||||
} ej_t;
|
||||
|
||||
/******************************** Prototypes **********************************/
|
||||
|
||||
extern int ejOpenBlock(int eid);
|
||||
extern int ejCloseBlock(int eid, int vid);
|
||||
extern char_t *ejEvalBlock(int eid, char_t *script, char_t **emsg);
|
||||
#ifndef __NO_EJ_FILE
|
||||
extern char_t *ejEvalFile(int eid, char_t *path, char_t **emsg);
|
||||
#endif
|
||||
extern int ejRemoveGlobalFunction(int eid, char_t *name);
|
||||
extern void *ejGetGlobalFunction(int eid, char_t *name);
|
||||
extern int ejSetGlobalFunctionDirect(sym_fd_t functions, char_t *name,
|
||||
int (*fn)(int eid, void *handle, int argc, char_t **argv));
|
||||
extern void ejError(ej_t* ep, char_t* fmt, ...);
|
||||
extern void ejSetUserHandle(int eid, int handle);
|
||||
extern int ejGetUserHandle(int eid);
|
||||
extern int ejGetLineNumber(int eid);
|
||||
extern char_t *ejGetResult(int eid);
|
||||
extern void ejSetLocalVar(int eid, char_t *var, char_t *value);
|
||||
extern void ejSetGlobalVar(int eid, char_t *var, char_t *value);
|
||||
|
||||
extern int ejLexOpen(ej_t* ep);
|
||||
extern void ejLexClose(ej_t* ep);
|
||||
extern int ejLexOpenScript(ej_t* ep, char_t *script);
|
||||
extern void ejLexCloseScript(ej_t* ep);
|
||||
extern void ejLexSaveInputState(ej_t* ep, ejinput_t* state);
|
||||
extern void ejLexFreeInputState(ej_t* ep, ejinput_t* state);
|
||||
extern void ejLexRestoreInputState(ej_t* ep, ejinput_t* state);
|
||||
extern int ejLexGetToken(ej_t* ep, int state);
|
||||
extern void ejLexPutbackToken(ej_t* ep, int tid, char_t *string);
|
||||
|
||||
extern sym_fd_t ejGetVariableTable(int eid);
|
||||
extern sym_fd_t ejGetFunctionTable(int eid);
|
||||
|
||||
extern int ejEmfOpen(int eid);
|
||||
extern void ejEmfClose(int eid);
|
||||
|
||||
extern int ejEmfDbRead(int eid, void *handle, int argc, char_t **argv);
|
||||
extern int ejEmfDbReadKeyed(int eid, void *handle, int argc, char_t **argv);
|
||||
extern int ejEmfDbTableGetNrow(int eid, void *handle, int argc, char_t **argv);
|
||||
extern int ejEmfDbDeleteRow(int eid, void *handle, int argc, char_t **argv);
|
||||
extern int ejEmfTrace(int eid, void *handle, int argc, char_t **argv);
|
||||
extern int ejEmfDbWrite(int eid, void *handle, int argc, char_t **argv);
|
||||
extern int ejEmfDbCollectTable(int eid, void *handle, int argc, char_t **argv);
|
||||
|
||||
#endif /* _h_EJINTERNAL */
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* ejlex.c -- Ejscript(TM) Lexical Analyser
|
||||
*
|
||||
* Copyright (c) Go Ahead Software, Inc., 1995-1999
|
||||
* Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved.
|
||||
*
|
||||
* See the file "license.txt" for usage and redistribution license requirements
|
||||
*/
|
||||
@@ -15,7 +15,7 @@
|
||||
|
||||
/********************************** Includes **********************************/
|
||||
|
||||
#include "ej.h"
|
||||
#include "ejIntrn.h"
|
||||
|
||||
#if UEMF
|
||||
#include "uemf.h"
|
||||
@@ -23,12 +23,16 @@
|
||||
#include "basic/basicInternal.h"
|
||||
#endif
|
||||
|
||||
/********************************** Defines ***********************************/
|
||||
#define OCTAL 8
|
||||
#define HEX 16
|
||||
/****************************** Forward Declarations **************************/
|
||||
|
||||
static int getLexicalToken(ej_t* ep, int state);
|
||||
static int tokenAddChar(ej_t *ep, int c);
|
||||
static int inputGetc(ej_t* ep);
|
||||
static void inputPutback(ej_t* ep, int c);
|
||||
static int charConvert(ej_t* ep, int base, int maxDig);
|
||||
|
||||
/************************************* Code ***********************************/
|
||||
/*
|
||||
@@ -77,13 +81,13 @@ int ejLexOpenScript(ej_t* ep, char_t *script)
|
||||
if (ringqOpen(&ip->tokbuf, EJ_INC, -1) < 0) {
|
||||
return -1;
|
||||
}
|
||||
if (ringqOpen(&ip->script, EJ_INC, -1) < 0) {
|
||||
if (ringqOpen(&ip->script, EJ_SCRIPT_INC, -1) < 0) {
|
||||
return -1;
|
||||
}
|
||||
/*
|
||||
* Put the Ejscript into a ring queue for easy parsing
|
||||
*/
|
||||
ringqPutstr(&ip->script, script);
|
||||
ringqPutStr(&ip->script, script);
|
||||
|
||||
ip->lineNumber = 1;
|
||||
ip->lineLength = 0;
|
||||
@@ -178,6 +182,7 @@ void ejLexFreeInputState(ej_t* ep, ejinput_t* state)
|
||||
{
|
||||
if (state->putBackToken) {
|
||||
bfree(B_L, state->putBackToken);
|
||||
state->putBackToken = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -189,7 +194,7 @@ void ejLexFreeInputState(ej_t* ep, ejinput_t* state)
|
||||
int ejLexGetToken(ej_t* ep, int state)
|
||||
{
|
||||
ep->tid = getLexicalToken(ep, state);
|
||||
goahead_trace(7, T("ejGetToken: %d, \"%s\"\n"), ep->tid, ep->token);
|
||||
trace(9, T("ejGetToken: %d, \"%s\"\n"), ep->tid, ep->token);
|
||||
return ep->tid;
|
||||
}
|
||||
|
||||
@@ -202,7 +207,7 @@ static int getLexicalToken(ej_t* ep, int state)
|
||||
{
|
||||
ringq_t *inq, *tokq;
|
||||
ejinput_t* ip;
|
||||
int done, tid, c, quote, style, back_quoted, lval, i;
|
||||
int done, tid, c, quote, style;
|
||||
|
||||
a_assert(ep);
|
||||
ip = ep->input;
|
||||
@@ -218,7 +223,7 @@ static int getLexicalToken(ej_t* ep, int state)
|
||||
ringqFlush(tokq);
|
||||
|
||||
if (ip->putBackTokenId > 0) {
|
||||
ringqPutstr(tokq, ip->putBackToken);
|
||||
ringqPutStr(tokq, ip->putBackToken);
|
||||
tid = ip->putBackTokenId;
|
||||
ip->putBackTokenId = 0;
|
||||
ep->token = (char_t*) tokq->servp;
|
||||
@@ -385,7 +390,7 @@ static int getLexicalToken(ej_t* ep, int state)
|
||||
inputPutback(ep, c);
|
||||
return TOK_ASSIGNMENT;
|
||||
|
||||
case '!': /* "!=" */
|
||||
case '!': /* "!=" or "!"*/
|
||||
if ((c = inputGetc(ep)) < 0) {
|
||||
ejError(ep, T("Syntax Error"));
|
||||
return TOK_ERR;
|
||||
@@ -394,8 +399,9 @@ static int getLexicalToken(ej_t* ep, int state)
|
||||
tokenAddChar(ep, EXPR_NOTEQ);
|
||||
return TOK_EXPR;
|
||||
}
|
||||
tokenAddChar(ep, COND_NOT);
|
||||
return TOK_LOGICAL;
|
||||
inputPutback(ep, c);
|
||||
tokenAddChar(ep, EXPR_BOOL_COMP);
|
||||
return TOK_EXPR;
|
||||
|
||||
case ';':
|
||||
tokenAddChar(ep, c);
|
||||
@@ -428,25 +434,23 @@ static int getLexicalToken(ej_t* ep, int state)
|
||||
ejError(ep, T("Syntax Error"));
|
||||
return TOK_ERR;
|
||||
}
|
||||
back_quoted = 0;
|
||||
while (c != quote) {
|
||||
if (c == '\\' && !back_quoted) {
|
||||
back_quoted++;
|
||||
} else if (back_quoted) {
|
||||
if (gisdigit((char_t) c)) {
|
||||
lval = 0;
|
||||
for (i = 0; i < 3; i++) {
|
||||
if ('0' <= c && c <= '7') {
|
||||
break;
|
||||
}
|
||||
lval = lval * 8 + c;
|
||||
if ((c = inputGetc(ep)) < 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
c = (int) lval;
|
||||
|
||||
} else if (back_quoted) {
|
||||
while (c != quote) {
|
||||
/*
|
||||
* check for escape sequence characters
|
||||
*/
|
||||
if (c == '\\') {
|
||||
c = inputGetc(ep);
|
||||
|
||||
if (gisdigit(c)) {
|
||||
/*
|
||||
* octal support, \101 maps to 65 = 'A'. put first char
|
||||
* back so converter will work properly.
|
||||
*/
|
||||
inputPutback(ep, c);
|
||||
c = charConvert(ep, OCTAL, 3);
|
||||
|
||||
} else {
|
||||
switch (c) {
|
||||
case 'n':
|
||||
c = '\n'; break;
|
||||
@@ -459,37 +463,28 @@ static int getLexicalToken(ej_t* ep, int state)
|
||||
case 't':
|
||||
c = '\t'; break;
|
||||
case 'x':
|
||||
lval = 0;
|
||||
for (i = 0; i < 2; i++) {
|
||||
if (! gisxdigit((char_t) c)) {
|
||||
break;
|
||||
}
|
||||
lval = lval * 16 + c;
|
||||
if ((c = inputGetc(ep)) < 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
c = (int) lval;
|
||||
/*
|
||||
* hex support, \x41 maps to 65 = 'A'
|
||||
*/
|
||||
c = charConvert(ep, HEX, 2);
|
||||
break;
|
||||
case 'u':
|
||||
lval = 0;
|
||||
for (i = 0; i < 4; i++) {
|
||||
if (! gisxdigit((char_t) c)) {
|
||||
break;
|
||||
}
|
||||
lval = lval * 16 + c;
|
||||
if ((c = inputGetc(ep)) < 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
c = (int) lval;
|
||||
/*
|
||||
* unicode support, \x0401 maps to 65 = 'A'
|
||||
*/
|
||||
c = charConvert(ep, HEX, 2);
|
||||
c = c*16 + charConvert(ep, HEX, 2);
|
||||
|
||||
break;
|
||||
case '\'':
|
||||
case '\"':
|
||||
case '\\':
|
||||
break;
|
||||
default:
|
||||
ejError(ep, T("Invalid Escape Sequence"));
|
||||
return TOK_ERR;
|
||||
}
|
||||
}
|
||||
back_quoted = 0;
|
||||
if (tokenAddChar(ep, c) < 0) {
|
||||
return TOK_ERR;
|
||||
}
|
||||
@@ -513,7 +508,7 @@ static int getLexicalToken(ej_t* ep, int state)
|
||||
}
|
||||
if ((c = inputGetc(ep)) < 0)
|
||||
break;
|
||||
} while (gisdigit((char_t) c));
|
||||
} while (gisdigit(c));
|
||||
inputPutback(ep, c);
|
||||
return TOK_LITERAL;
|
||||
|
||||
@@ -521,21 +516,19 @@ static int getLexicalToken(ej_t* ep, int state)
|
||||
/*
|
||||
* Identifiers or a function names
|
||||
*/
|
||||
back_quoted = 0;
|
||||
while (1) {
|
||||
if (c == '\\' && !back_quoted) {
|
||||
back_quoted++;
|
||||
} else {
|
||||
back_quoted = 0;
|
||||
if (tokenAddChar(ep, c) < 0) {
|
||||
if (c == '\\') {
|
||||
/*
|
||||
* just ignore any \ characters.
|
||||
*/
|
||||
} else if (tokenAddChar(ep, c) < 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ((c = inputGetc(ep)) < 0) {
|
||||
break;
|
||||
}
|
||||
if (!back_quoted && (!gisalnum((char_t) c) && c != '$' &&
|
||||
c != '_')) {
|
||||
if (!gisalnum(c) && c != '$' && c != '_' &&
|
||||
c != '\\') {
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -558,13 +551,16 @@ static int getLexicalToken(ej_t* ep, int state)
|
||||
} else if (gstrcmp(ep->token, T("for")) == 0) {
|
||||
return TOK_FOR;
|
||||
} else if (gstrcmp(ep->token, T("return")) == 0) {
|
||||
if ((c == ';') || (c == '(')) {
|
||||
inputPutback(ep, c);
|
||||
}
|
||||
return TOK_RETURN;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* skip white space after token to find out whether this is
|
||||
* a function or not.
|
||||
/*
|
||||
* Skip white space after token to find out whether this is
|
||||
* a function or not.
|
||||
*/
|
||||
while (c == ' ' || c == '\t' || c == '\r' || c == '\n') {
|
||||
if ((c = inputGetc(ep)) < 0)
|
||||
@@ -677,3 +673,41 @@ static void inputPutback(ej_t* ep, int c)
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/*
|
||||
* Convert a hex or octal character back to binary, return original char if
|
||||
* not a hex digit
|
||||
*/
|
||||
|
||||
static int charConvert(ej_t* ep, int base, int maxDig)
|
||||
{
|
||||
int i, c, lval, convChar;
|
||||
|
||||
lval = 0;
|
||||
for (i = 0; i < maxDig; i++) {
|
||||
if ((c = inputGetc(ep)) < 0) {
|
||||
break;
|
||||
}
|
||||
/*
|
||||
* Initialize to out of range value
|
||||
*/
|
||||
convChar = base;
|
||||
if (gisdigit(c)) {
|
||||
convChar = c - '0';
|
||||
} else if (c >= 'a' && c <= 'f') {
|
||||
convChar = c - 'a' + 10;
|
||||
} else if (c >= 'A' && c <= 'F') {
|
||||
convChar = c - 'A' + 10;
|
||||
}
|
||||
/*
|
||||
* if unexpected character then return it to buffer.
|
||||
*/
|
||||
if (convChar >= base) {
|
||||
inputPutback(ep, c);
|
||||
break;
|
||||
}
|
||||
lval = (lval * base) + convChar;
|
||||
}
|
||||
return lval;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* ejparse.c -- Ejscript(TM) Parser
|
||||
*
|
||||
* Copyright (c) Go Ahead Software, Inc., 1995-1999
|
||||
* Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved.
|
||||
*
|
||||
* See the file "license.txt" for usage and redistribution license requirements
|
||||
*/
|
||||
@@ -15,7 +15,11 @@
|
||||
|
||||
/********************************** Includes **********************************/
|
||||
|
||||
#include "ej.h"
|
||||
#include "ejIntrn.h"
|
||||
|
||||
#if CE
|
||||
#include "CE/wincompat.h"
|
||||
#endif
|
||||
|
||||
/********************************** Local Data ********************************/
|
||||
|
||||
@@ -24,11 +28,14 @@ int ejMax = -1; /* Maximum size of */
|
||||
|
||||
/****************************** Forward Declarations **************************/
|
||||
|
||||
#ifndef B_STATS
|
||||
#define setString(a,b,c) setstring(b,c)
|
||||
#endif
|
||||
|
||||
static ej_t *ejPtr(int eid);
|
||||
static void clearString(char_t **ptr);
|
||||
static void setString(char_t **ptr, char_t *s);
|
||||
static void setString(B_ARGS_DEC, char_t **ptr, char_t *s);
|
||||
static void appendString(char_t **ptr, char_t *s);
|
||||
static void freeVar(sym_t* sp);
|
||||
static int parse(ej_t *ep, int state, int flags);
|
||||
static int parseStmt(ej_t *ep, int state, int flags);
|
||||
static int parseDeclaration(ej_t *ep, int state, int flags);
|
||||
@@ -39,6 +46,7 @@ static int evalExpr(ej_t *ep, char_t *lhs, int rel, char_t *rhs);
|
||||
static int evalCond(ej_t *ep, char_t *lhs, int rel, char_t *rhs);
|
||||
static int evalFunction(ej_t *ep);
|
||||
static void freeFunc(ejfunc_t *func);
|
||||
static void ejRemoveNewlines(ej_t *ep, int state);
|
||||
|
||||
/************************************* Code ***********************************/
|
||||
/*
|
||||
@@ -57,8 +65,8 @@ int ejOpenEngine(sym_fd_t variables, sym_fd_t functions)
|
||||
ep->eid = eid;
|
||||
|
||||
/*
|
||||
* Create a top level symbol table if one is not provided for variables and
|
||||
* functions. Variables may create other symbol tables for block level
|
||||
* Create a top level symbol table if one is not provided for variables and
|
||||
* functions. Variables may create other symbol tables for block level
|
||||
* declarations so we use hAlloc to manage a list of variable tables.
|
||||
*/
|
||||
if ((vid = hAlloc((void***) &ep->variables)) < 0) {
|
||||
@@ -72,7 +80,6 @@ int ejOpenEngine(sym_fd_t variables, sym_fd_t functions)
|
||||
if (variables == -1) {
|
||||
ep->variables[vid] = symOpen(64) + EJ_OFFSET;
|
||||
ep->flags |= FLAGS_VARIABLES;
|
||||
|
||||
} else {
|
||||
ep->variables[vid] = variables + EJ_OFFSET;
|
||||
}
|
||||
@@ -122,36 +129,27 @@ void ejCloseEngine(int eid)
|
||||
|
||||
ejLexClose(ep);
|
||||
|
||||
if (ep->flags & FLAGS_VARIABLES) {
|
||||
for (i = ep->variableMax - 1; i >= 0; i--) {
|
||||
symClose(ep->variables[i] - EJ_OFFSET, freeVar);
|
||||
ep->variableMax = hFree((void***) &ep->variables, i);
|
||||
for (i = ep->variableMax - 1; i >= 0; i--) {
|
||||
if (ep->flags & FLAGS_VARIABLES) {
|
||||
symClose(ep->variables[i] - EJ_OFFSET);
|
||||
}
|
||||
ep->variableMax = hFree((void***) &ep->variables, i);
|
||||
}
|
||||
|
||||
if (ep->flags & FLAGS_FUNCTIONS) {
|
||||
symClose(ep->functions, freeVar);
|
||||
symClose(ep->functions);
|
||||
}
|
||||
|
||||
ejMax = hFree((void***) &ejHandles, ep->eid);
|
||||
bfree(B_L, ep);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/*
|
||||
* Callback from symClose. Free the variable.
|
||||
*/
|
||||
|
||||
static void freeVar(sym_t* sp)
|
||||
{
|
||||
valueFree(&sp->content);
|
||||
}
|
||||
|
||||
#ifndef __NO_EJ_FILE
|
||||
/******************************************************************************/
|
||||
/*
|
||||
* Evaluate a Ejscript file
|
||||
*/
|
||||
|
||||
#if DEV
|
||||
char_t *ejEvalFile(int eid, char_t *path, char_t **emsg)
|
||||
{
|
||||
gstat_t sbuf;
|
||||
@@ -165,6 +163,7 @@ char_t *ejEvalFile(int eid, char_t *path, char_t **emsg)
|
||||
if (emsg) {
|
||||
*emsg = NULL;
|
||||
}
|
||||
|
||||
if ((ep = ejPtr(eid)) == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
@@ -173,26 +172,30 @@ char_t *ejEvalFile(int eid, char_t *path, char_t **emsg)
|
||||
ejError(ep, T("Bad handle %d"), eid);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (gstat(path, &sbuf) < 0) {
|
||||
close(fd);
|
||||
gclose(fd);
|
||||
ejError(ep, T("Cant stat %s"), path);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ((fileBuf = balloc(B_L, sbuf.st_size + 1)) == NULL) {
|
||||
close(fd);
|
||||
gclose(fd);
|
||||
ejError(ep, T("Cant malloc %d"), sbuf.st_size);
|
||||
return NULL;
|
||||
}
|
||||
if (read(fd, fileBuf, sbuf.st_size) != (int)sbuf.st_size) {
|
||||
close(fd);
|
||||
|
||||
if (gread(fd, fileBuf, sbuf.st_size) != (int)sbuf.st_size) {
|
||||
gclose(fd);
|
||||
bfree(B_L, fileBuf);
|
||||
ejError(ep, T("Error reading %s"), path);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
fileBuf[sbuf.st_size] = '\0';
|
||||
close(fd);
|
||||
gclose(fd);
|
||||
|
||||
if ((script = ballocAscToUni(fileBuf)) == NULL) {
|
||||
if ((script = ballocAscToUni(fileBuf, sbuf.st_size)) == NULL) {
|
||||
bfree(B_L, fileBuf);
|
||||
ejError(ep, T("Cant malloc %d"), sbuf.st_size + 1);
|
||||
return NULL;
|
||||
@@ -204,29 +207,31 @@ char_t *ejEvalFile(int eid, char_t *path, char_t **emsg)
|
||||
bfree(B_L, script);
|
||||
return rs;
|
||||
}
|
||||
#endif
|
||||
#endif /* __NO_EJ_FILE */
|
||||
|
||||
/******************************************************************************/
|
||||
/*
|
||||
* Create a new variable scope block so that consecutive ejEval calls may
|
||||
* be made with the same varible scope. This space MUST be closed with
|
||||
* ejCloseBlock when the evaluations are complete.
|
||||
* ejCloseBlock when the evaluations are complete.
|
||||
*/
|
||||
|
||||
int ejOpenBlock(int eid)
|
||||
{
|
||||
ej_t *ep;
|
||||
int vid;
|
||||
int vid;
|
||||
|
||||
if((ep = ejPtr(eid)) == NULL) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if ((vid = hAlloc((void***) &ep->variables)) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (vid >= ep->variableMax) {
|
||||
ep->variableMax = vid + 1;
|
||||
}
|
||||
}
|
||||
ep->variables[vid] = symOpen(64) + EJ_OFFSET;
|
||||
return vid;
|
||||
|
||||
@@ -241,15 +246,16 @@ int ejOpenBlock(int eid)
|
||||
int ejCloseBlock(int eid, int vid)
|
||||
{
|
||||
ej_t *ep;
|
||||
|
||||
|
||||
if((ep = ejPtr(eid)) == NULL) {
|
||||
return -1;
|
||||
}
|
||||
symClose(ep->variables[vid] - EJ_OFFSET, freeVar);
|
||||
symClose(ep->variables[vid] - EJ_OFFSET);
|
||||
ep->variableMax = hFree((void***) &ep->variables, vid);
|
||||
return 0;
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/*
|
||||
* Create a new variable scope block and evaluate a script. All variables
|
||||
@@ -263,7 +269,7 @@ char_t *ejEvalBlock(int eid, char_t *script, char_t **emsg)
|
||||
|
||||
a_assert(script);
|
||||
|
||||
vid = ejOpenBlock(eid);
|
||||
vid = ejOpenBlock(eid);
|
||||
returnVal = ejEval(eid, script, emsg);
|
||||
ejCloseBlock(eid, vid);
|
||||
|
||||
@@ -272,7 +278,7 @@ char_t *ejEvalBlock(int eid, char_t *script, char_t **emsg)
|
||||
|
||||
/******************************************************************************/
|
||||
/*
|
||||
* Parse and evaluate a Ejscript. The caller may provide a symbol table to
|
||||
* Parse and evaluate a Ejscript. The caller may provide a symbol table to
|
||||
* use for variables and function definitions. Return char_t pointer on
|
||||
* success otherwise NULL pointer is returned.
|
||||
*/
|
||||
@@ -282,17 +288,21 @@ char_t *ejEval(int eid, char_t *script, char_t **emsg)
|
||||
ej_t *ep;
|
||||
ejinput_t *oldBlock;
|
||||
int state;
|
||||
|
||||
void *endlessLoopTest;
|
||||
int loopCounter;
|
||||
|
||||
|
||||
a_assert(script);
|
||||
|
||||
if (emsg) {
|
||||
*emsg = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if ((ep = ejPtr(eid)) == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
setString(&ep->result, T(""));
|
||||
setString(B_L, &ep->result, T(""));
|
||||
|
||||
/*
|
||||
* Allocate a new evaluation block, and save the old one
|
||||
@@ -303,8 +313,29 @@ char_t *ejEval(int eid, char_t *script, char_t **emsg)
|
||||
/*
|
||||
* Do the actual parsing and evaluation
|
||||
*/
|
||||
loopCounter = 0;
|
||||
endlessLoopTest = NULL;
|
||||
|
||||
do {
|
||||
state = parse(ep, STATE_BEGIN, FLAGS_EXE);
|
||||
|
||||
if (state == STATE_RET) {
|
||||
state = STATE_EOF;
|
||||
}
|
||||
/*
|
||||
* prevent parser from going into infinite loop. If parsing the same
|
||||
* line 10 times then fail and report Syntax error. Most normal error
|
||||
* are caught in the parser itself.
|
||||
*/
|
||||
if (endlessLoopTest == ep->input->script.servp) {
|
||||
if (loopCounter++ > 10) {
|
||||
state = STATE_ERR;
|
||||
ejError(ep, T("Syntax error"));
|
||||
}
|
||||
} else {
|
||||
endlessLoopTest = ep->input->script.servp;
|
||||
loopCounter = 0;
|
||||
}
|
||||
} while (state != STATE_EOF && state != STATE_ERR);
|
||||
|
||||
ejLexCloseScript(ep);
|
||||
@@ -324,9 +355,11 @@ char_t *ejEval(int eid, char_t *script, char_t **emsg)
|
||||
if (state == STATE_EOF) {
|
||||
return ep->result;
|
||||
}
|
||||
|
||||
if (state == STATE_ERR) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return ep->result;
|
||||
}
|
||||
|
||||
@@ -344,12 +377,25 @@ static int parse(ej_t *ep, int state, int flags)
|
||||
* Any statement, function arguments or conditional expressions
|
||||
*/
|
||||
case STATE_STMT:
|
||||
if ((state = parseStmt(ep, state, flags)) != STATE_STMT_DONE &&
|
||||
state != STATE_EOF && state != STATE_STMT_BLOCK_DONE &&
|
||||
state != STATE_RET) {
|
||||
state = STATE_ERR;
|
||||
}
|
||||
break;
|
||||
|
||||
case STATE_DEC:
|
||||
state = parseStmt(ep, state, flags);
|
||||
if ((state = parseStmt(ep, state, flags)) != STATE_DEC_DONE &&
|
||||
state != STATE_EOF) {
|
||||
state = STATE_ERR;
|
||||
}
|
||||
break;
|
||||
|
||||
case STATE_EXPR:
|
||||
state = parseStmt(ep, state, flags);
|
||||
if ((state = parseStmt(ep, state, flags)) != STATE_EXPR_DONE &&
|
||||
state != STATE_EOF) {
|
||||
state = STATE_ERR;
|
||||
}
|
||||
break;
|
||||
|
||||
/*
|
||||
@@ -397,9 +443,9 @@ static int parseStmt(ej_t *ep, int state, int flags)
|
||||
ejfunc_t func;
|
||||
ejfunc_t *saveFunc;
|
||||
ejinput_t condScript, endScript, bodyScript, incrScript;
|
||||
char_t *value;
|
||||
char_t *identifier;
|
||||
char_t *value, *identifier;
|
||||
int done, expectSemi, thenFlags, elseFlags, tid, cond, forFlags;
|
||||
int ejVarType;
|
||||
|
||||
a_assert(ep);
|
||||
|
||||
@@ -451,21 +497,22 @@ static int parseStmt(ej_t *ep, int state, int flags)
|
||||
* This could either be a reference to a variable or an assignment
|
||||
*/
|
||||
identifier = NULL;
|
||||
setString(&identifier, ep->token);
|
||||
setString(B_L, &identifier, ep->token);
|
||||
/*
|
||||
* Peek ahead to see if this is an assignment
|
||||
*/
|
||||
tid = ejLexGetToken(ep, state);
|
||||
if (tid == TOK_ASSIGNMENT) {
|
||||
if (parse(ep, STATE_RELEXP, flags) != STATE_RELEXP_DONE) {
|
||||
clearString(&identifier);
|
||||
goto error;
|
||||
}
|
||||
if (flags & FLAGS_EXE) {
|
||||
if ( state == STATE_DEC ) {
|
||||
ejSetLocalVar(ep->eid, identifier, ep->result);
|
||||
}
|
||||
else {
|
||||
if (ejGetVar(ep->eid, identifier, &value) > 0) {
|
||||
} else {
|
||||
ejVarType = ejGetVar(ep->eid, identifier, &value);
|
||||
if (ejVarType > 0) {
|
||||
ejSetLocalVar(ep->eid, identifier, ep->result);
|
||||
} else {
|
||||
ejSetGlobalVar(ep->eid, identifier, ep->result);
|
||||
@@ -475,17 +522,23 @@ static int parseStmt(ej_t *ep, int state, int flags)
|
||||
|
||||
} else if (tid == TOK_INC_DEC ) {
|
||||
value = NULL;
|
||||
if ( flags & FLAGS_EXE ) {
|
||||
if (ejGetVar(ep->eid, identifier, &value) < 0) {
|
||||
if (flags & FLAGS_EXE) {
|
||||
ejVarType = ejGetVar(ep->eid, identifier, &value);
|
||||
if (ejVarType < 0) {
|
||||
ejError(ep, T("Undefined variable %s\n"), identifier);
|
||||
goto error;
|
||||
}
|
||||
setString(&ep->result, value);
|
||||
setString(B_L, &ep->result, value);
|
||||
if (evalExpr(ep, value, (int) *ep->token, T("1")) < 0) {
|
||||
state = STATE_ERR;
|
||||
break;
|
||||
}
|
||||
ejSetGlobalVar(ep->eid, identifier, ep->result);
|
||||
|
||||
if (ejVarType > 0) {
|
||||
ejSetLocalVar(ep->eid, identifier, ep->result);
|
||||
} else {
|
||||
ejSetGlobalVar(ep->eid, identifier, ep->result);
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
@@ -495,7 +548,7 @@ static int parseStmt(ej_t *ep, int state, int flags)
|
||||
value = NULL;
|
||||
if (state == STATE_DEC) {
|
||||
if (ejGetVar(ep->eid, identifier, &value) > 0) {
|
||||
ejError(ep, T("Variable already declared"),
|
||||
ejError(ep, T("Variable already declared"),
|
||||
identifier);
|
||||
clearString(&identifier);
|
||||
goto error;
|
||||
@@ -504,14 +557,14 @@ static int parseStmt(ej_t *ep, int state, int flags)
|
||||
} else {
|
||||
if ( flags & FLAGS_EXE ) {
|
||||
if (ejGetVar(ep->eid, identifier, &value) < 0) {
|
||||
ejError(ep, T("Undefined variable %s\n"),
|
||||
ejError(ep, T("Undefined variable %s\n"),
|
||||
identifier);
|
||||
clearString(&identifier);
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
}
|
||||
setString(&ep->result, value);
|
||||
setString(B_L, &ep->result, value);
|
||||
ejLexPutbackToken(ep, tid, ep->token);
|
||||
}
|
||||
clearString(&identifier);
|
||||
@@ -526,7 +579,7 @@ static int parseStmt(ej_t *ep, int state, int flags)
|
||||
/*
|
||||
* Set the result to the literal (number or string constant)
|
||||
*/
|
||||
setString(&ep->result, ep->token);
|
||||
setString(B_L, &ep->result, ep->token);
|
||||
if (state == STATE_STMT) {
|
||||
expectSemi++;
|
||||
}
|
||||
@@ -541,10 +594,10 @@ static int parseStmt(ej_t *ep, int state, int flags)
|
||||
saveFunc = ep->func;
|
||||
}
|
||||
memset(&func, 0, sizeof(ejfunc_t));
|
||||
setString(&func.fname, ep->token);
|
||||
setString(B_L, &func.fname, ep->token);
|
||||
ep->func = &func;
|
||||
|
||||
setString(&ep->result, T(""));
|
||||
setString(B_L, &ep->result, T(""));
|
||||
if (ejLexGetToken(ep, state) != TOK_LPAREN) {
|
||||
freeFunc(&func);
|
||||
goto error;
|
||||
@@ -604,11 +657,20 @@ static int parseStmt(ej_t *ep, int state, int flags)
|
||||
elseFlags = flags;
|
||||
}
|
||||
/*
|
||||
* Process the "then" case
|
||||
* Process the "then" case. Allow for RETURN statement
|
||||
*/
|
||||
if (parse(ep, STATE_STMT, thenFlags) != STATE_STMT_DONE) {
|
||||
switch (parse(ep, STATE_STMT, thenFlags)) {
|
||||
case STATE_RET:
|
||||
return STATE_RET;
|
||||
case STATE_STMT_DONE:
|
||||
break;
|
||||
default:
|
||||
goto error;
|
||||
}
|
||||
/*
|
||||
* check to see if there is an "else" case
|
||||
*/
|
||||
ejRemoveNewlines(ep, state);
|
||||
tid = ejLexGetToken(ep, state);
|
||||
if (tid != TOK_ELSE) {
|
||||
ejLexPutbackToken(ep, tid, ep->token);
|
||||
@@ -616,9 +678,14 @@ static int parseStmt(ej_t *ep, int state, int flags)
|
||||
break;
|
||||
}
|
||||
/*
|
||||
* Process the "else" case
|
||||
* Process the "else" case. Allow for return.
|
||||
*/
|
||||
if (parse(ep, STATE_STMT, elseFlags) != STATE_STMT_DONE) {
|
||||
switch (parse(ep, STATE_STMT, elseFlags)) {
|
||||
case STATE_RET:
|
||||
return STATE_RET;
|
||||
case STATE_STMT_DONE:
|
||||
break;
|
||||
default:
|
||||
goto error;
|
||||
}
|
||||
done++;
|
||||
@@ -650,7 +717,7 @@ static int parseStmt(ej_t *ep, int state, int flags)
|
||||
}
|
||||
|
||||
/*
|
||||
* The first time through, we save the current input context just
|
||||
* The first time through, we save the current input context just
|
||||
* to each step: prior to the conditional, the loop increment and the
|
||||
* loop body.
|
||||
*/
|
||||
@@ -663,7 +730,7 @@ static int parseStmt(ej_t *ep, int state, int flags)
|
||||
if (ejLexGetToken(ep, state) != TOK_SEMI) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Don't execute the loop increment statement or the body first time
|
||||
*/
|
||||
@@ -677,7 +744,7 @@ static int parseStmt(ej_t *ep, int state, int flags)
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse the body and remember the end of the body script
|
||||
* Parse the body and remember the end of the body script
|
||||
*/
|
||||
ejLexSaveInputState(ep, &bodyScript);
|
||||
if (parse(ep, STATE_STMT, forFlags) != STATE_STMT_DONE) {
|
||||
@@ -693,7 +760,13 @@ static int parseStmt(ej_t *ep, int state, int flags)
|
||||
* Evaluate the body
|
||||
*/
|
||||
ejLexRestoreInputState(ep, &bodyScript);
|
||||
if (parse(ep, STATE_STMT, flags) != STATE_STMT_DONE) {
|
||||
|
||||
switch (parse(ep, STATE_STMT, flags)) {
|
||||
case STATE_RET:
|
||||
return STATE_RET;
|
||||
case STATE_STMT_DONE:
|
||||
break;
|
||||
default:
|
||||
goto error;
|
||||
}
|
||||
/*
|
||||
@@ -760,6 +833,13 @@ static int parseStmt(ej_t *ep, int state, int flags)
|
||||
state = parse(ep, STATE_STMT, flags);
|
||||
} while (state == STATE_STMT_DONE);
|
||||
|
||||
/*
|
||||
* Allow return statement.
|
||||
*/
|
||||
if (state == STATE_RET) {
|
||||
return state;
|
||||
}
|
||||
|
||||
if (ejLexGetToken(ep, state) != TOK_RBRACE) {
|
||||
goto error;
|
||||
}
|
||||
@@ -779,7 +859,7 @@ static int parseStmt(ej_t *ep, int state, int flags)
|
||||
if (flags & FLAGS_EXE) {
|
||||
while ( ejLexGetToken(ep, state) != TOK_EOF );
|
||||
done++;
|
||||
return STATE_EOF;
|
||||
return STATE_RET;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -794,10 +874,7 @@ static int parseStmt(ej_t *ep, int state, int flags)
|
||||
/*
|
||||
* Skip newline after semi-colon
|
||||
*/
|
||||
tid = ejLexGetToken(ep, state);
|
||||
if (tid != TOK_NEWLINE) {
|
||||
ejLexPutbackToken(ep, tid, ep->token);
|
||||
}
|
||||
ejRemoveNewlines(ep, state);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -810,6 +887,7 @@ doneParse:
|
||||
ejLexFreeInputState(ep, &endScript);
|
||||
ejLexFreeInputState(ep, &bodyScript);
|
||||
}
|
||||
|
||||
if (state == STATE_STMT) {
|
||||
return STATE_STMT_DONE;
|
||||
} else if (state == STATE_DEC) {
|
||||
@@ -928,7 +1006,7 @@ static int parseCond(ej_t *ep, int state, int flags)
|
||||
|
||||
a_assert(ep);
|
||||
|
||||
setString(&ep->result, T(""));
|
||||
setString(B_L, &ep->result, T(""));
|
||||
rhs = lhs = NULL;
|
||||
operator = 0;
|
||||
|
||||
@@ -942,14 +1020,15 @@ static int parseCond(ej_t *ep, int state, int flags)
|
||||
state = STATE_ERR;
|
||||
break;
|
||||
}
|
||||
|
||||
if (operator > 0) {
|
||||
setString(&rhs, ep->result);
|
||||
setString(B_L, &rhs, ep->result);
|
||||
if (evalCond(ep, lhs, operator, rhs) < 0) {
|
||||
state = STATE_ERR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
setString(&lhs, ep->result);
|
||||
setString(B_L, &lhs, ep->result);
|
||||
|
||||
tid = ejLexGetToken(ep, state);
|
||||
if (tid == TOK_LOGICAL) {
|
||||
@@ -969,6 +1048,7 @@ static int parseCond(ej_t *ep, int state, int flags)
|
||||
if (lhs) {
|
||||
bfree(B_L, lhs);
|
||||
}
|
||||
|
||||
if (rhs) {
|
||||
bfree(B_L, rhs);
|
||||
}
|
||||
@@ -987,33 +1067,46 @@ static int parseExpr(ej_t *ep, int state, int flags)
|
||||
|
||||
a_assert(ep);
|
||||
|
||||
setString(&ep->result, T(""));
|
||||
setString(B_L, &ep->result, T(""));
|
||||
rhs = lhs = NULL;
|
||||
rel = 0;
|
||||
tid = 0;
|
||||
|
||||
do {
|
||||
/*
|
||||
* This loop will handle an entire expression list. We call parse
|
||||
* to evalutate each term which returns the result in ep->result.
|
||||
*/
|
||||
state = parse(ep, STATE_EXPR, flags);
|
||||
if (state != STATE_EXPR_DONE) {
|
||||
state = STATE_ERR;
|
||||
break;
|
||||
}
|
||||
if (rel > 0) {
|
||||
setString(&rhs, ep->result);
|
||||
if (evalExpr(ep, lhs, rel, rhs) < 0) {
|
||||
if (tid == TOK_LOGICAL) {
|
||||
if ((state = parse(ep, STATE_RELEXP, flags)) != STATE_RELEXP_DONE) {
|
||||
state = STATE_ERR;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if ((state = parse(ep, STATE_EXPR, flags)) != STATE_EXPR_DONE) {
|
||||
state = STATE_ERR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
setString(&lhs, ep->result);
|
||||
|
||||
if ((tid = ejLexGetToken(ep, state)) == TOK_EXPR) {
|
||||
rel = (int) *ep->token;
|
||||
if (rel > 0) {
|
||||
setString(B_L, &rhs, ep->result);
|
||||
if (tid == TOK_LOGICAL) {
|
||||
if (evalCond(ep, lhs, rel, rhs) < 0) {
|
||||
state = STATE_ERR;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if (evalExpr(ep, lhs, rel, rhs) < 0) {
|
||||
state = STATE_ERR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
setString(B_L, &lhs, ep->result);
|
||||
|
||||
} else if (tid == TOK_INC_DEC) {
|
||||
if ((tid = ejLexGetToken(ep, state)) == TOK_EXPR ||
|
||||
tid == TOK_INC_DEC || tid == TOK_LOGICAL) {
|
||||
rel = (int) *ep->token;
|
||||
|
||||
} else {
|
||||
@@ -1023,10 +1116,14 @@ static int parseExpr(ej_t *ep, int state, int flags)
|
||||
|
||||
} while (state == STATE_EXPR_DONE);
|
||||
|
||||
if (rhs)
|
||||
if (rhs) {
|
||||
bfree(B_L, rhs);
|
||||
if (lhs)
|
||||
}
|
||||
|
||||
if (lhs) {
|
||||
bfree(B_L, lhs);
|
||||
}
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
@@ -1045,7 +1142,7 @@ static int evalCond(ej_t *ep, char_t *lhs, int rel, char_t *rhs)
|
||||
a_assert(rel > 0);
|
||||
|
||||
lval = 0;
|
||||
if (gisdigit(*lhs) && gisdigit(*rhs)) {
|
||||
if (gisdigit((int)*lhs) && gisdigit((int)*rhs)) {
|
||||
l = gatoi(lhs);
|
||||
r = gatoi(rhs);
|
||||
switch (rel) {
|
||||
@@ -1060,15 +1157,15 @@ static int evalCond(ej_t *ep, char_t *lhs, int rel, char_t *rhs)
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
if (!gisdigit(*lhs)) {
|
||||
if (!gisdigit((int)*lhs)) {
|
||||
ejError(ep, T("Conditional must be numeric"), lhs);
|
||||
} else {
|
||||
ejError(ep, T("Conditional must be numeric"), rhs);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
stritoa(lval, buf, sizeof(buf));
|
||||
setString(&ep->result, buf);
|
||||
setString(B_L, &ep->result, buf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1091,19 +1188,21 @@ static int evalExpr(ej_t *ep, char_t *lhs, int rel, char_t *rhs)
|
||||
*/
|
||||
numeric = 1;
|
||||
for (cp = lhs; *cp; cp++) {
|
||||
if (!gisdigit(*cp)) {
|
||||
if (!gisdigit((int)*cp)) {
|
||||
numeric = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (numeric) {
|
||||
for (cp = rhs; *cp; cp++) {
|
||||
if (!gisdigit(*cp)) {
|
||||
if (!gisdigit((int)*cp)) {
|
||||
numeric = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (numeric) {
|
||||
l = gatoi(lhs);
|
||||
r = gatoi(rhs);
|
||||
@@ -1161,6 +1260,9 @@ static int evalExpr(ej_t *ep, char_t *lhs, int rel, char_t *rhs)
|
||||
case EXPR_GREATEREQ:
|
||||
lval = (l >= r) ? 1 : 0;
|
||||
break;
|
||||
case EXPR_BOOL_COMP:
|
||||
lval = (r == 0) ? 1 : 0;
|
||||
break;
|
||||
default:
|
||||
ejError(ep, T("Bad operator %d"), rel);
|
||||
return -1;
|
||||
@@ -1205,7 +1307,7 @@ static int evalExpr(ej_t *ep, char_t *lhs, int rel, char_t *rhs)
|
||||
}
|
||||
|
||||
stritoa(lval, buf, sizeof(buf));
|
||||
setString(&ep->result, buf);
|
||||
setString(B_L, &ep->result, buf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1223,13 +1325,14 @@ static int evalFunction(ej_t *ep)
|
||||
ejError(ep, T("Undefined procedure %s"), ep->func->fname);
|
||||
return -1;
|
||||
}
|
||||
|
||||
fn = (int (*)(int, void*, int, char_t**)) sp->content.value.integer;
|
||||
if (fn == NULL) {
|
||||
ejError(ep, T("Undefined procedure %s"), ep->func->fname);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return (*fn)(ep->eid, (void*) ep->userHandle, ep->func->nArgs,
|
||||
return (*fn)(ep->eid, (void*) ep->userHandle, ep->func->nArgs,
|
||||
ep->func->args);
|
||||
}
|
||||
|
||||
@@ -1250,12 +1353,11 @@ void ejError(ej_t* ep, char_t* fmt, ...)
|
||||
|
||||
va_start(args, fmt);
|
||||
msgbuf = NULL;
|
||||
gvsnprintf(&msgbuf, E_MAX_ERROR, fmt, args);
|
||||
fmtValloc(&msgbuf, E_MAX_ERROR, fmt, args);
|
||||
va_end(args);
|
||||
|
||||
if (ep && ip) {
|
||||
errbuf = NULL;
|
||||
gsnprintf(&errbuf, E_MAX_ERROR, T("%s\n At line %d, line => \n\n%s\n"),
|
||||
fmtAlloc(&errbuf, E_MAX_ERROR, T("%s\n At line %d, line => \n\n%s\n"),
|
||||
msgbuf, ip->lineNumber, ip->line);
|
||||
bfreeSafe(B_L, ep->error);
|
||||
ep->error = errbuf;
|
||||
@@ -1283,14 +1385,14 @@ static void clearString(char_t **ptr)
|
||||
* Set a string value
|
||||
*/
|
||||
|
||||
static void setString(char_t **ptr, char_t *s)
|
||||
static void setString(B_ARGS_DEC, char_t **ptr, char_t *s)
|
||||
{
|
||||
a_assert(ptr);
|
||||
|
||||
if (*ptr) {
|
||||
bfree(B_L, *ptr);
|
||||
bfree(B_ARGS, *ptr);
|
||||
}
|
||||
*ptr = bstrdup(B_L, s);
|
||||
*ptr = bstrdup(B_ARGS, s);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
@@ -1319,7 +1421,7 @@ static void appendString(char_t **ptr, char_t *s)
|
||||
* Define a function
|
||||
*/
|
||||
|
||||
int ejSetGlobalFunction(int eid, char_t *name,
|
||||
int ejSetGlobalFunction(int eid, char_t *name,
|
||||
int (*fn)(int eid, void *handle, int argc, char_t **argv))
|
||||
{
|
||||
ej_t *ep;
|
||||
@@ -1335,7 +1437,7 @@ int ejSetGlobalFunction(int eid, char_t *name,
|
||||
* Define a function directly into the function symbol table.
|
||||
*/
|
||||
|
||||
int ejSetGlobalFunctionDirect(sym_fd_t functions, char_t *name,
|
||||
int ejSetGlobalFunctionDirect(sym_fd_t functions, char_t *name,
|
||||
int (*fn)(int eid, void *handle, int argc, char_t **argv))
|
||||
{
|
||||
if (symEnter(functions, name, valueInteger((long) fn), 0) == NULL) {
|
||||
@@ -1344,6 +1446,21 @@ int ejSetGlobalFunctionDirect(sym_fd_t functions, char_t *name,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/*
|
||||
* Remove ("undefine") a function
|
||||
*/
|
||||
|
||||
int ejRemoveGlobalFunction(int eid, char_t *name)
|
||||
{
|
||||
ej_t *ep;
|
||||
|
||||
if ((ep = ejPtr(eid)) == NULL) {
|
||||
return -1;
|
||||
}
|
||||
return symDelete(ep->functions, name);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/*
|
||||
* Get a function definition
|
||||
@@ -1358,6 +1475,7 @@ void *ejGetGlobalFunction(int eid, char_t *name)
|
||||
if ((ep = ejPtr(eid)) == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ((sp = symLookup(ep->functions, name)) != NULL) {
|
||||
fn = (int (*)(int, void*, int, char_t**)) sp->content.value.integer;
|
||||
return (void*) fn;
|
||||
@@ -1367,7 +1485,7 @@ void *ejGetGlobalFunction(int eid, char_t *name)
|
||||
|
||||
/******************************************************************************/
|
||||
/*
|
||||
* Utility routine to crack Ejscript arguments. Return the number of args
|
||||
* Utility routine to crack Ejscript arguments. Return the number of args
|
||||
* seen. This routine only supports %s and %d type args.
|
||||
*
|
||||
* Typical usage:
|
||||
@@ -1477,7 +1595,7 @@ void ejSetResult(int eid, char_t *s)
|
||||
if ((ep = ejPtr(eid)) == NULL) {
|
||||
return;
|
||||
}
|
||||
setString(&ep->result, s);
|
||||
setString(B_L, &ep->result, s);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
@@ -1511,6 +1629,7 @@ void ejSetVar(int eid, char_t *var, char_t *value)
|
||||
if ((ep = ejPtr(eid)) == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (value == NULL) {
|
||||
v = valueString(value, 0);
|
||||
} else {
|
||||
@@ -1535,6 +1654,7 @@ void ejSetLocalVar(int eid, char_t *var, char_t *value)
|
||||
if ((ep = ejPtr(eid)) == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (value == NULL) {
|
||||
v = valueString(value, 0);
|
||||
} else {
|
||||
@@ -1545,7 +1665,7 @@ void ejSetLocalVar(int eid, char_t *var, char_t *value)
|
||||
|
||||
/******************************************************************************/
|
||||
/*
|
||||
* Set a global variable. Note: a variable with a value of NULL means
|
||||
* Set a global variable. Note: a variable with a value of NULL means
|
||||
* declared but undefined. The value is defined in the global variable frame.
|
||||
*/
|
||||
|
||||
@@ -1559,6 +1679,7 @@ void ejSetGlobalVar(int eid, char_t *var, char_t *value)
|
||||
if ((ep = ejPtr(eid)) == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (value == NULL) {
|
||||
v = valueString(value, 0);
|
||||
} else {
|
||||
@@ -1585,19 +1706,19 @@ int ejGetVar(int eid, char_t *var, char_t **value)
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (i = ep->variableMax - 1; i >= 0; i--) {
|
||||
if ((sp = symLookup(ep->variables[i] - EJ_OFFSET, var)) == NULL) {
|
||||
continue;
|
||||
i = ep->variableMax - 1;
|
||||
if ((sp = symLookup(ep->variables[i] - EJ_OFFSET, var)) == NULL) {
|
||||
i = 0;
|
||||
if ((sp = symLookup(ep->variables[0] - EJ_OFFSET, var)) == NULL) {
|
||||
return -1;
|
||||
}
|
||||
a_assert(sp->content.type == string);
|
||||
*value = sp->content.value.string;
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
a_assert(sp->content.type == string);
|
||||
*value = sp->content.value.string;
|
||||
return i;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
#if UNUSED
|
||||
/*
|
||||
* Get the variable symbol table
|
||||
*/
|
||||
@@ -1609,9 +1730,9 @@ sym_fd_t ejGetVariableTable(int eid)
|
||||
if ((ep = ejPtr(eid)) == NULL) {
|
||||
return -1;
|
||||
}
|
||||
return ep->variables;
|
||||
return *ep->variables;
|
||||
}
|
||||
#endif
|
||||
|
||||
/******************************************************************************/
|
||||
/*
|
||||
* Get the functions symbol table
|
||||
@@ -1640,6 +1761,7 @@ static void freeFunc(ejfunc_t *func)
|
||||
bfree(B_L, func->args[i]);
|
||||
func->nArgs = hFree((void***) &func->args, i);
|
||||
}
|
||||
|
||||
if (func->fname) {
|
||||
bfree(B_L, func->fname);
|
||||
func->fname = NULL;
|
||||
@@ -1647,7 +1769,7 @@ static void freeFunc(ejfunc_t *func)
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/*
|
||||
/*
|
||||
* Get Ejscript pointer
|
||||
*/
|
||||
|
||||
@@ -1663,3 +1785,18 @@ static ej_t *ejPtr(int eid)
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/*
|
||||
* This function removes any new lines. Used for else cases, etc.
|
||||
*/
|
||||
static void ejRemoveNewlines(ej_t *ep, int state)
|
||||
{
|
||||
int tid;
|
||||
|
||||
do {
|
||||
tid = ejLexGetToken(ep, state);
|
||||
} while (tid == TOK_NEWLINE);
|
||||
|
||||
ejLexPutbackToken(ep, tid, ep->token);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
1050
c/src/libnetworking/rtems_webserver/emfdb.c
Normal file
1050
c/src/libnetworking/rtems_webserver/emfdb.c
Normal file
File diff suppressed because it is too large
Load Diff
102
c/src/libnetworking/rtems_webserver/emfdb.h
Normal file
102
c/src/libnetworking/rtems_webserver/emfdb.h
Normal file
@@ -0,0 +1,102 @@
|
||||
/*
|
||||
* emfdb.h -- EMF database compatability functions for GoAhead WebServer.
|
||||
*
|
||||
* Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved.
|
||||
*
|
||||
* See the file "license.txt" for usage and redistribution license requirements
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
/******************************** Description *********************************/
|
||||
/*
|
||||
* Emf-like textfile database support for WebServer 2.1.
|
||||
*/
|
||||
|
||||
/********************************* Includes ***********************************/
|
||||
|
||||
#ifndef _h_EMFDB
|
||||
#define _h_EMFDB 1
|
||||
|
||||
#if ! UEMF
|
||||
#include "basic/basic.h"
|
||||
#include "emf/emf.h"
|
||||
#else
|
||||
#include "uemf.h"
|
||||
#endif
|
||||
|
||||
|
||||
/********************************* Defines ************************************/
|
||||
|
||||
#define T_INT 0
|
||||
#define T_STRING 1
|
||||
|
||||
#define DB_OK 0
|
||||
#define DB_ERR_GENERAL -1
|
||||
#define DB_ERR_COL_NOT_FOUND -2
|
||||
#define DB_ERR_COL_DELETED -3
|
||||
#define DB_ERR_ROW_NOT_FOUND -4
|
||||
#define DB_ERR_ROW_DELETED -5
|
||||
#define DB_ERR_TABLE_NOT_FOUND -6
|
||||
#define DB_ERR_TABLE_DELETED -7
|
||||
#define DB_ERR_BAD_FORMAT -8
|
||||
|
||||
typedef struct dbTable_s {
|
||||
char_t *name;
|
||||
int nColumns;
|
||||
char_t **columnNames;
|
||||
int *columnTypes;
|
||||
int nRows;
|
||||
int **rows;
|
||||
} dbTable_t;
|
||||
|
||||
/********************************** Prototypes ********************************/
|
||||
|
||||
/*
|
||||
* Add a schema to the module-internal schema database
|
||||
*/
|
||||
extern int dbRegisterDBSchema(dbTable_t *sTable);
|
||||
|
||||
extern int dbOpen(char_t *databasename, char_t *filename,
|
||||
int (*gettime)(int did), int flags);
|
||||
extern void dbClose(int did);
|
||||
extern int dbGetTableId(int did, char_t *tname);
|
||||
extern char_t *dbGetTableName(int did, int tid);
|
||||
extern int dbReadInt(int did, char_t *table, char_t *column, int row,
|
||||
int *returnValue);
|
||||
extern int dbReadStr(int did, char_t *table, char_t *column, int row,
|
||||
char_t **returnValue);
|
||||
extern int dbWriteInt(int did, char_t *table, char_t *column, int row,
|
||||
int idata);
|
||||
extern int dbWriteStr(int did, char_t *table, char_t *column, int row,
|
||||
char_t *s);
|
||||
extern int dbAddRow(int did, char_t *table);
|
||||
extern int dbDeleteRow(int did, char_t *table, int rid);
|
||||
extern int dbSetTableNrow(int did, char_t *table, int nNewRows);
|
||||
extern int dbGetTableNrow(int did, char_t *table);
|
||||
|
||||
/*
|
||||
* Dump the contents of a database to file
|
||||
*/
|
||||
extern int dbSave(int did, char_t *filename, int flags);
|
||||
|
||||
/*
|
||||
* Load the contents of a database to file
|
||||
*/
|
||||
extern int dbLoad(int did, char_t *filename, int flags);
|
||||
|
||||
/*
|
||||
* Search for a data in a given column
|
||||
*/
|
||||
extern int dbSearchStr(int did, char_t *table, char_t *column,
|
||||
char_t *value, int flags);
|
||||
|
||||
extern void dbZero(int did);
|
||||
|
||||
extern char_t *basicGetProductDir();
|
||||
extern void basicSetProductDir(char_t *proddir);
|
||||
|
||||
#endif /* _h_EMFDB */
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* form.c -- Form processing (in-memory CGI) for the GoAhead Web server
|
||||
*
|
||||
* Copyright (c) Go Ahead Software Inc., 1995-1999. All Rights Reserved.
|
||||
* Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved.
|
||||
*
|
||||
* See the file "license.txt" for usage and redistribution license requirements
|
||||
*/
|
||||
@@ -29,12 +29,12 @@ static sym_fd_t formSymtab = -1; /* Symbol table for form handlers */
|
||||
*/
|
||||
|
||||
int websFormHandler(webs_t wp, char_t *urlPrefix, char_t *webDir, int arg,
|
||||
char_t *url, char_t *path, char_t* query)
|
||||
char_t *url, char_t *path, char_t *query)
|
||||
{
|
||||
sym_t *sp;
|
||||
char_t formBuf[FNAMESIZE];
|
||||
char_t *cp, *formName;
|
||||
int (*fn)(void *sock, char_t* path, char_t *args);
|
||||
int (*fn)(void *sock, char_t *path, char_t *args);
|
||||
|
||||
a_assert(websValid(wp));
|
||||
a_assert(url && *url);
|
||||
@@ -63,16 +63,23 @@ int websFormHandler(webs_t wp, char_t *urlPrefix, char_t *webDir, int arg,
|
||||
if (sp == NULL) {
|
||||
websError(wp, 200, T("Form %s is not defined"), formName);
|
||||
} else {
|
||||
fn = (int (*)(void*, char_t*, char_t*)) sp->content.value.integer;
|
||||
fn = (int (*)(void *, char_t *, char_t *)) sp->content.value.integer;
|
||||
a_assert(fn);
|
||||
if (fn) {
|
||||
/*
|
||||
* For good practice, forms must call websDone()
|
||||
*/
|
||||
(*fn)((void*) wp, formName, query);
|
||||
|
||||
/*
|
||||
* Remove the test to force websDone, since this prevents
|
||||
* the server "push" from a form>
|
||||
*/
|
||||
#if 0 /* push */
|
||||
if (websValid(wp)) {
|
||||
websError(wp, 200, T("Form didn't call websDone"));
|
||||
}
|
||||
#endif /* push */
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
@@ -86,8 +93,6 @@ int websFormHandler(webs_t wp, char_t *urlPrefix, char_t *webDir, int arg,
|
||||
int websFormDefine(char_t *name, void (*fn)(webs_t wp, char_t *path,
|
||||
char_t *query))
|
||||
{
|
||||
static int once = 0;
|
||||
|
||||
a_assert(name && *name);
|
||||
a_assert(fn);
|
||||
|
||||
@@ -95,9 +100,6 @@ int websFormDefine(char_t *name, void (*fn)(webs_t wp, char_t *path,
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (once++ == 0) {
|
||||
websFormOpen();
|
||||
}
|
||||
symEnter(formSymtab, name, valueInteger((int) fn), (int) NULL);
|
||||
return 0;
|
||||
}
|
||||
@@ -109,7 +111,7 @@ int websFormDefine(char_t *name, void (*fn)(webs_t wp, char_t *path,
|
||||
|
||||
void websFormOpen()
|
||||
{
|
||||
formSymtab = symOpen(64);
|
||||
formSymtab = symOpen(WEBS_SYM_INIT);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
@@ -120,7 +122,8 @@ void websFormOpen()
|
||||
void websFormClose()
|
||||
{
|
||||
if (formSymtab != -1) {
|
||||
symClose(formSymtab, NULL);
|
||||
symClose(formSymtab);
|
||||
formSymtab = -1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -139,7 +142,7 @@ void websHeader(webs_t wp)
|
||||
/*
|
||||
* By license terms the following line of code must not be modified
|
||||
*/
|
||||
websWrite(wp, T("Server: GoAhead-Webs\r\n"));
|
||||
websWrite(wp, T("Server: %s\r\n"), WEBS_NAME);
|
||||
|
||||
websWrite(wp, T("Pragma: no-cache\n"));
|
||||
websWrite(wp, T("Cache-control: no-cache\n"));
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
/*
|
||||
* h.c -- Handle allocation module
|
||||
*
|
||||
* Copyright (c) GoAhead Software Inc., 1995-1999. All Rights Reserved.
|
||||
* Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved.
|
||||
* See the file "license.txt" for usage and redistribution license requirements
|
||||
*/
|
||||
|
||||
/******************************** Description *********************************/
|
||||
|
||||
/*
|
||||
* This module provides a simple API to allocate and free handles
|
||||
* It maintains a dynamic array of pointers. These usually point to
|
||||
* This module provides a simple API to allocate and free handles
|
||||
* It maintains a dynamic array of pointers. These usually point to
|
||||
* per-handle structures.
|
||||
*/
|
||||
|
||||
@@ -36,12 +36,16 @@
|
||||
|
||||
/*********************************** Code *************************************/
|
||||
/*
|
||||
* Allocate a new file handle. On the first call, the caller must set the
|
||||
* Allocate a new file handle. On the first call, the caller must set the
|
||||
* handle map to be a pointer to a null pointer. *map points to the second
|
||||
* element in the handle array.
|
||||
*/
|
||||
|
||||
#if B_STATS
|
||||
int HALLOC(B_ARGS_DEC, void ***map)
|
||||
#else
|
||||
int hAlloc(void ***map)
|
||||
#endif
|
||||
{
|
||||
int *mp;
|
||||
int handle, len, memsize, incr;
|
||||
@@ -51,7 +55,11 @@ int hAlloc(void ***map)
|
||||
if (*map == NULL) {
|
||||
incr = H_INCR;
|
||||
memsize = (incr + H_OFFSET) * sizeof(void**);
|
||||
#if B_STATS
|
||||
if ((mp = (int*) balloc(B_ARGS, memsize)) == NULL) {
|
||||
#else
|
||||
if ((mp = (int*) balloc(B_L, memsize)) == NULL) {
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
memset(mp, 0, memsize);
|
||||
@@ -68,11 +76,12 @@ int hAlloc(void ***map)
|
||||
* Find the first null handle
|
||||
*/
|
||||
if (mp[H_USED] < mp[H_LEN]) {
|
||||
for (handle = 0; handle < len; handle++)
|
||||
for (handle = 0; handle < len; handle++) {
|
||||
if (mp[handle+H_OFFSET] == 0) {
|
||||
mp[H_USED]++;
|
||||
return handle;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
handle = len;
|
||||
}
|
||||
@@ -139,7 +148,11 @@ int hFree(void ***map, int handle)
|
||||
* Allocate an entry in the halloc array.
|
||||
*/
|
||||
|
||||
#if B_STATS
|
||||
int HALLOCENTRY(B_ARGS_DEC, void ***list, int *max, int size)
|
||||
#else
|
||||
int hAllocEntry(void ***list, int *max, int size)
|
||||
#endif
|
||||
{
|
||||
char_t *cp;
|
||||
int id;
|
||||
@@ -147,12 +160,20 @@ int hAllocEntry(void ***list, int *max, int size)
|
||||
a_assert(list);
|
||||
a_assert(max);
|
||||
|
||||
#if B_STATS
|
||||
if ((id = HALLOC(B_ARGS, (void***) list)) < 0) {
|
||||
#else
|
||||
if ((id = hAlloc((void***) list)) < 0) {
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
if (size > 0) {
|
||||
#if B_STATS
|
||||
if ((cp = balloc(B_ARGS, size)) == NULL) {
|
||||
#else
|
||||
if ((cp = balloc(B_L, size)) == NULL) {
|
||||
#endif
|
||||
hFree(list, id);
|
||||
return -1;
|
||||
}
|
||||
@@ -169,3 +190,4 @@ int hAllocEntry(void ***list, int *max, int size)
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* handler.c -- URL handler support
|
||||
*
|
||||
* Copyright (c) Go Ahead Software Inc., 1995-1999. All Rights Reserved.
|
||||
* Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved.
|
||||
*
|
||||
* See the file "license.txt" for usage and redistribution license requirements
|
||||
*/
|
||||
@@ -19,14 +19,16 @@
|
||||
|
||||
/*********************************** Locals ***********************************/
|
||||
|
||||
static websUrlHandlerType* websUrlHandler; /* URL handler list */
|
||||
static websUrlHandlerType *websUrlHandler; /* URL handler list */
|
||||
static int websUrlHandlerMax; /* Number of entries */
|
||||
static int urlHandlerOpenCount = 0; /* count of apps */
|
||||
|
||||
/**************************** Forward Declarations ****************************/
|
||||
|
||||
static int websUrlHandlerSort(const void* p1, const void* p2);
|
||||
static int websUrlHandlerSort(const void *p1, const void *p2);
|
||||
static int websPublishHandler(webs_t wp, char_t *urlPrefix, char_t *webDir,
|
||||
int sid, char_t *url, char_t *path, char_t *query);
|
||||
static int websTidyUrl(webs_t wp);
|
||||
|
||||
/*********************************** Code *************************************/
|
||||
/*
|
||||
@@ -35,7 +37,11 @@ static int websPublishHandler(webs_t wp, char_t *urlPrefix, char_t *webDir,
|
||||
|
||||
int websUrlHandlerOpen()
|
||||
{
|
||||
websAspOpen();
|
||||
if (++urlHandlerOpenCount == 1) {
|
||||
websAspOpen();
|
||||
websUrlHandler = NULL;
|
||||
websUrlHandlerMax = 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -46,17 +52,20 @@ int websUrlHandlerOpen()
|
||||
|
||||
void websUrlHandlerClose()
|
||||
{
|
||||
websUrlHandlerType* sp;
|
||||
websUrlHandlerType *sp;
|
||||
|
||||
websAspClose();
|
||||
for (sp = websUrlHandler; sp < &websUrlHandler[websUrlHandlerMax]; sp++) {
|
||||
bfree(B_L, sp->urlPrefix);
|
||||
if (sp->webDir) {
|
||||
bfree(B_L, sp->webDir);
|
||||
if (--urlHandlerOpenCount <= 0) {
|
||||
websAspClose();
|
||||
for (sp = websUrlHandler; sp < &websUrlHandler[websUrlHandlerMax];
|
||||
sp++) {
|
||||
bfree(B_L, sp->urlPrefix);
|
||||
if (sp->webDir) {
|
||||
bfree(B_L, sp->webDir);
|
||||
}
|
||||
}
|
||||
bfree(B_L, websUrlHandler);
|
||||
websUrlHandlerMax = 0;
|
||||
}
|
||||
bfree(B_L, websUrlHandler);
|
||||
websUrlHandlerMax = 0;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
@@ -135,7 +144,7 @@ int websUrlHandlerDelete(int (*handler)(webs_t wp, char_t *urlPrefix,
|
||||
* Sort in decreasing URL length order observing the flags for first and last
|
||||
*/
|
||||
|
||||
static int websUrlHandlerSort(const void* p1, const void* p2)
|
||||
static int websUrlHandlerSort(const void *p1, const void *p2)
|
||||
{
|
||||
websUrlHandlerType *s1, *s2;
|
||||
int rc;
|
||||
@@ -247,6 +256,8 @@ int websUrlHandlerRequest(webs_t wp)
|
||||
|
||||
websSetRequestPath(wp, websGetDefaultDir(), NULL);
|
||||
|
||||
websTidyUrl(wp);
|
||||
|
||||
/*
|
||||
* We loop over each handler in order till one accepts the request.
|
||||
* The security handler will handle the request if access is NOT allowed.
|
||||
@@ -264,7 +275,7 @@ int websUrlHandlerRequest(webs_t wp)
|
||||
return 1;
|
||||
}
|
||||
if (!websValid(wp)) {
|
||||
goahead_trace(0,
|
||||
trace(0,
|
||||
T("webs: handler %s called websDone, but didn't return 1\n"),
|
||||
sp->urlPrefix);
|
||||
return 1;
|
||||
@@ -272,7 +283,7 @@ int websUrlHandlerRequest(webs_t wp)
|
||||
}
|
||||
}
|
||||
/*
|
||||
* If no handler processed the request, then return an error. Note: It was
|
||||
* If no handler processed the request, then return an error. Note: It is
|
||||
* the handlers responsibility to call websDone
|
||||
*/
|
||||
if (i >= websUrlHandlerMax) {
|
||||
@@ -281,4 +292,70 @@ int websUrlHandlerRequest(webs_t wp)
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************/
|
||||
/*
|
||||
* Tidy up the URL path. Return -1 if the URL is bad.
|
||||
* Used to eliminate repeated directory delimiters ('/').
|
||||
*/
|
||||
|
||||
static int websTidyUrl(webs_t wp)
|
||||
{
|
||||
char_t *parts[64]; /* Array of ptr's to URL parts */
|
||||
char_t *token, *url, *tidyurl;
|
||||
int i, len, npart;
|
||||
|
||||
a_assert(websValid(wp));
|
||||
|
||||
/*
|
||||
* Copy the string so we don't destroy the original (yet)
|
||||
*/
|
||||
url = bstrdup(B_L, wp->url);
|
||||
websDecodeUrl(url, url, gstrlen(url));
|
||||
|
||||
len = npart = 0;
|
||||
parts[0] = NULL;
|
||||
token = gstrtok(url, T("/"));
|
||||
|
||||
/*
|
||||
* Look at each directory segment and process "." and ".." segments
|
||||
* Don't allow the browser to pop outside the root web.
|
||||
*/
|
||||
while (token != NULL) {
|
||||
if (gstrcmp(token, T("..")) == 0) {
|
||||
if (npart > 0) {
|
||||
npart--;
|
||||
}
|
||||
|
||||
} else if (gstrcmp(token, T(".")) != 0) {
|
||||
parts[npart] = token;
|
||||
len += gstrlen(token) + 1;
|
||||
npart++;
|
||||
}
|
||||
token = gstrtok(NULL, T("/"));
|
||||
}
|
||||
|
||||
/*
|
||||
* Re-construct URL. Need extra space all "/" and null.
|
||||
*/
|
||||
if (npart || (gstrcmp(url, T("/")) == 0) || (url[0] == '\0')) {
|
||||
tidyurl = balloc(B_L, (len + 2) * sizeof(char_t));
|
||||
*tidyurl = '\0';
|
||||
|
||||
for (i = 0; i < npart; i++) {
|
||||
gstrcat(tidyurl, T("/"));
|
||||
gstrcat(tidyurl, parts[i]);
|
||||
}
|
||||
|
||||
bfree(B_L, url);
|
||||
|
||||
bfree(B_L, wp->url);
|
||||
wp->url = tidyurl;
|
||||
return 0;
|
||||
} else {
|
||||
bfree(B_L, url);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
48
c/src/libnetworking/rtems_webserver/md5.h
Normal file
48
c/src/libnetworking/rtems_webserver/md5.h
Normal file
@@ -0,0 +1,48 @@
|
||||
/* MD5.H - header file for MD5C.C
|
||||
*/
|
||||
|
||||
/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
|
||||
rights reserved.
|
||||
|
||||
License to copy and use this software is granted provided that it
|
||||
is identified as the "RSA Data Security, Inc. MD5 Message-Digest
|
||||
Algorithm" in all material mentioning or referencing this software
|
||||
or this function.
|
||||
|
||||
License is also granted to make and use derivative works provided
|
||||
that such works are identified as "derived from the RSA Data
|
||||
Security, Inc. MD5 Message-Digest Algorithm" in all material
|
||||
mentioning or referencing the derived work.
|
||||
|
||||
RSA Data Security, Inc. makes no representations concerning either
|
||||
the merchantability of this software or the suitability of this
|
||||
software for any particular purpose. It is provided "as is"
|
||||
without express or implied warranty of any kind.
|
||||
|
||||
These notices must be retained in any copies of any part of this
|
||||
documentation and/or software.
|
||||
*/
|
||||
|
||||
#ifndef _h_MD5
|
||||
#define _h_MD5 1
|
||||
|
||||
#ifndef UINT4
|
||||
#define UINT4 unsigned long
|
||||
#endif
|
||||
|
||||
#ifndef POINTER
|
||||
#define POINTER unsigned char *
|
||||
#endif
|
||||
|
||||
/* MD5 context. */
|
||||
typedef struct {
|
||||
UINT4 state[4]; /* state (ABCD) */
|
||||
UINT4 count[2]; /* number of bits, modulo 2^64 (lsb first) */
|
||||
unsigned char buffer[64]; /* input buffer */
|
||||
} MD5_CONTEXT;
|
||||
|
||||
extern void MD5Init (MD5_CONTEXT *);
|
||||
extern void MD5Update (MD5_CONTEXT *, unsigned char *, unsigned int);
|
||||
extern void MD5Final (unsigned char [16], MD5_CONTEXT *);
|
||||
|
||||
#endif /* _h_MD5 */
|
||||
335
c/src/libnetworking/rtems_webserver/md5c.c
Normal file
335
c/src/libnetworking/rtems_webserver/md5c.c
Normal file
@@ -0,0 +1,335 @@
|
||||
/* MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm
|
||||
*/
|
||||
|
||||
/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
|
||||
rights reserved.
|
||||
|
||||
License to copy and use this software is granted provided that it
|
||||
is identified as the "RSA Data Security, Inc. MD5 Message-Digest
|
||||
Algorithm" in all material mentioning or referencing this software
|
||||
or this function.
|
||||
|
||||
License is also granted to make and use derivative works provided
|
||||
that such works are identified as "derived from the RSA Data
|
||||
Security, Inc. MD5 Message-Digest Algorithm" in all material
|
||||
mentioning or referencing the derived work.
|
||||
|
||||
RSA Data Security, Inc. makes no representations concerning either
|
||||
the merchantability of this software or the suitability of this
|
||||
software for any particular purpose. It is provided "as is"
|
||||
without express or implied warranty of any kind.
|
||||
|
||||
These notices must be retained in any copies of any part of this
|
||||
documentation and/or software.
|
||||
*/
|
||||
|
||||
#include "md5.h"
|
||||
|
||||
/* Constants for MD5Transform routine.
|
||||
*/
|
||||
#define S11 7
|
||||
#define S12 12
|
||||
#define S13 17
|
||||
#define S14 22
|
||||
#define S21 5
|
||||
#define S22 9
|
||||
#define S23 14
|
||||
#define S24 20
|
||||
#define S31 4
|
||||
#define S32 11
|
||||
#define S33 16
|
||||
#define S34 23
|
||||
#define S41 6
|
||||
#define S42 10
|
||||
#define S43 15
|
||||
#define S44 21
|
||||
|
||||
static void MD5Transform (UINT4 [4], unsigned char [64]);
|
||||
static void Encode (unsigned char *, UINT4 *, unsigned int);
|
||||
static void Decode (UINT4 *, unsigned char *, unsigned int);
|
||||
static void MD5_memcpy (POINTER, POINTER, unsigned int);
|
||||
static void MD5_memset (POINTER, int, unsigned int);
|
||||
|
||||
static unsigned char PADDING[64] = {
|
||||
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
};
|
||||
|
||||
/*
|
||||
* Note: The following MD5 macros can be implemented as functions
|
||||
* for code compactness, (at the expense of execution speed).
|
||||
*/
|
||||
|
||||
/* F, G, H and I are basic MD5 functions.
|
||||
*/
|
||||
#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
|
||||
#define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
|
||||
#define H(x, y, z) ((x) ^ (y) ^ (z))
|
||||
#define I(x, y, z) ((y) ^ ((x) | (~z)))
|
||||
|
||||
/* ROTATE_LEFT rotates x left n bits.
|
||||
*/
|
||||
#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
|
||||
|
||||
/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
|
||||
Rotation is separate from addition to prevent recomputation.
|
||||
*/
|
||||
#define FF(a, b, c, d, x, s, ac) { \
|
||||
(a) += F ((b), (c), (d)) + (x) + (UINT4)(ac); \
|
||||
(a) = ROTATE_LEFT ((a), (s)); \
|
||||
(a) += (b); \
|
||||
}
|
||||
#define GG(a, b, c, d, x, s, ac) { \
|
||||
(a) += G ((b), (c), (d)) + (x) + (UINT4)(ac); \
|
||||
(a) = ROTATE_LEFT ((a), (s)); \
|
||||
(a) += (b); \
|
||||
}
|
||||
#define HH(a, b, c, d, x, s, ac) { \
|
||||
(a) += H ((b), (c), (d)) + (x) + (UINT4)(ac); \
|
||||
(a) = ROTATE_LEFT ((a), (s)); \
|
||||
(a) += (b); \
|
||||
}
|
||||
#define II(a, b, c, d, x, s, ac) { \
|
||||
(a) += I ((b), (c), (d)) + (x) + (UINT4)(ac); \
|
||||
(a) = ROTATE_LEFT ((a), (s)); \
|
||||
(a) += (b); \
|
||||
}
|
||||
|
||||
/* MD5 initialization. Begins an MD5 operation, writing a new context.
|
||||
*/
|
||||
void MD5Init (context)
|
||||
MD5_CONTEXT *context; /* context */
|
||||
{
|
||||
context->count[0] = context->count[1] = 0;
|
||||
/* Load magic initialization constants.
|
||||
*/
|
||||
context->state[0] = 0x67452301;
|
||||
context->state[1] = 0xefcdab89;
|
||||
context->state[2] = 0x98badcfe;
|
||||
context->state[3] = 0x10325476;
|
||||
}
|
||||
|
||||
/* MD5 block update operation. Continues an MD5 message-digest
|
||||
operation, processing another message block, and updating the
|
||||
context.
|
||||
*/
|
||||
void MD5Update (context, input, inputLen)
|
||||
MD5_CONTEXT *context; /* context */
|
||||
unsigned char *input; /* input block */
|
||||
unsigned int inputLen; /* length of input block */
|
||||
{
|
||||
unsigned int i, index, partLen;
|
||||
|
||||
/* Compute number of bytes mod 64 */
|
||||
index = (unsigned int)((context->count[0] >> 3) & 0x3F);
|
||||
|
||||
/* Update number of bits */
|
||||
if ((context->count[0] += ((UINT4)inputLen << 3))
|
||||
< ((UINT4)inputLen << 3))
|
||||
context->count[1]++;
|
||||
context->count[1] += ((UINT4)inputLen >> 29);
|
||||
|
||||
partLen = 64 - index;
|
||||
|
||||
/* Transform as many times as possible.
|
||||
*/
|
||||
if (inputLen >= partLen) {
|
||||
MD5_memcpy
|
||||
((POINTER)&context->buffer[index], (POINTER)input, partLen);
|
||||
MD5Transform (context->state, context->buffer);
|
||||
|
||||
for (i = partLen; i + 63 < inputLen; i += 64)
|
||||
MD5Transform (context->state, &input[i]);
|
||||
|
||||
index = 0;
|
||||
}
|
||||
else
|
||||
i = 0;
|
||||
|
||||
/* Buffer remaining input */
|
||||
MD5_memcpy
|
||||
((POINTER)&context->buffer[index], (POINTER)&input[i],
|
||||
inputLen-i);
|
||||
}
|
||||
|
||||
/* MD5 finalization. Ends an MD5 message-digest operation, writing the
|
||||
the message digest and zeroizing the context.
|
||||
*/
|
||||
void MD5Final (digest, context)
|
||||
unsigned char digest[16]; /* message digest */
|
||||
MD5_CONTEXT *context; /* context */
|
||||
{
|
||||
unsigned char bits[8];
|
||||
unsigned int index, padLen;
|
||||
|
||||
/* Save number of bits */
|
||||
Encode (bits, context->count, 8);
|
||||
|
||||
/* Pad out to 56 mod 64.
|
||||
*/
|
||||
index = (unsigned int)((context->count[0] >> 3) & 0x3f);
|
||||
padLen = (index < 56) ? (56 - index) : (120 - index);
|
||||
MD5Update (context, PADDING, padLen);
|
||||
|
||||
/* Append length (before padding) */
|
||||
MD5Update (context, bits, 8);
|
||||
/* Store state in digest */
|
||||
Encode (digest, context->state, 16);
|
||||
|
||||
/* Zeroize sensitive information.
|
||||
*/
|
||||
MD5_memset ((POINTER)context, 0, sizeof (*context));
|
||||
}
|
||||
|
||||
/* MD5 basic transformation. Transforms state based on block.
|
||||
*/
|
||||
static void MD5Transform (state, block)
|
||||
UINT4 state[4];
|
||||
unsigned char block[64];
|
||||
{
|
||||
UINT4 a = state[0], b = state[1], c = state[2], d = state[3], x[16];
|
||||
|
||||
Decode (x, block, 64);
|
||||
|
||||
/* Round 1 */
|
||||
FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */
|
||||
FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */
|
||||
FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */
|
||||
FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */
|
||||
FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */
|
||||
FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */
|
||||
FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */
|
||||
FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */
|
||||
FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */
|
||||
FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */
|
||||
FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
|
||||
FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
|
||||
FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
|
||||
FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
|
||||
FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
|
||||
FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
|
||||
|
||||
/* Round 2 */
|
||||
GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */
|
||||
GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */
|
||||
GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
|
||||
GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */
|
||||
GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */
|
||||
GG (d, a, b, c, x[10], S22, 0x2441453); /* 22 */
|
||||
GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
|
||||
GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */
|
||||
GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */
|
||||
GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
|
||||
GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */
|
||||
GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */
|
||||
GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
|
||||
GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */
|
||||
GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */
|
||||
GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
|
||||
|
||||
/* Round 3 */
|
||||
HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */
|
||||
HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */
|
||||
HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
|
||||
HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
|
||||
HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */
|
||||
HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */
|
||||
HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */
|
||||
HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
|
||||
HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
|
||||
HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */
|
||||
HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */
|
||||
HH (b, c, d, a, x[ 6], S34, 0x4881d05); /* 44 */
|
||||
HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */
|
||||
HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
|
||||
HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
|
||||
HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */
|
||||
|
||||
/* Round 4 */
|
||||
II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */
|
||||
II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */
|
||||
II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
|
||||
II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */
|
||||
II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
|
||||
II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */
|
||||
II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
|
||||
II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */
|
||||
II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */
|
||||
II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
|
||||
II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */
|
||||
II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
|
||||
II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */
|
||||
II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
|
||||
II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */
|
||||
II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */
|
||||
|
||||
state[0] += a;
|
||||
state[1] += b;
|
||||
state[2] += c;
|
||||
state[3] += d;
|
||||
|
||||
/* Zeroize sensitive information.
|
||||
*/
|
||||
MD5_memset ((POINTER)x, 0, sizeof (x));
|
||||
}
|
||||
|
||||
/* Encodes input (UINT4) into output (unsigned char). Assumes len is
|
||||
a multiple of 4.
|
||||
*/
|
||||
static void Encode (output, input, len)
|
||||
unsigned char *output;
|
||||
UINT4 *input;
|
||||
unsigned int len;
|
||||
{
|
||||
unsigned int i, j;
|
||||
|
||||
for (i = 0, j = 0; j < len; i++, j += 4) {
|
||||
output[j] = (unsigned char)(input[i] & 0xff);
|
||||
output[j+1] = (unsigned char)((input[i] >> 8) & 0xff);
|
||||
output[j+2] = (unsigned char)((input[i] >> 16) & 0xff);
|
||||
output[j+3] = (unsigned char)((input[i] >> 24) & 0xff);
|
||||
}
|
||||
}
|
||||
|
||||
/* Decodes input (unsigned char) into output (UINT4). Assumes len is
|
||||
a multiple of 4.
|
||||
*/
|
||||
static void Decode (output, input, len)
|
||||
UINT4 *output;
|
||||
unsigned char *input;
|
||||
unsigned int len;
|
||||
{
|
||||
unsigned int i, j;
|
||||
|
||||
for (i = 0, j = 0; j < len; i++, j += 4)
|
||||
output[i] = ((UINT4)input[j]) | (((UINT4)input[j+1]) << 8) |
|
||||
(((UINT4)input[j+2]) << 16) | (((UINT4)input[j+3]) << 24);
|
||||
}
|
||||
|
||||
/* Note: Replace "for loop" with standard memcpy if possible.
|
||||
*/
|
||||
|
||||
static void MD5_memcpy (output, input, len)
|
||||
POINTER output;
|
||||
POINTER input;
|
||||
unsigned int len;
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < len; i++)
|
||||
output[i] = input[i];
|
||||
}
|
||||
|
||||
/* Note: Replace "for loop" with standard memset if possible.
|
||||
*/
|
||||
static void MD5_memset (output, value, len)
|
||||
POINTER output;
|
||||
int value;
|
||||
unsigned int len;
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < len; i++)
|
||||
((char *)output)[i] = (char)value;
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* mime.c -- Web server mime types
|
||||
*
|
||||
* Copyright (c) Go Ahead Software Inc., 1995-1999. All Rights Reserved.
|
||||
* Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved.
|
||||
*
|
||||
* See the file "license.txt" for usage and redistribution license requirements
|
||||
*/
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* misc.c -- Miscellaneous routines.
|
||||
*
|
||||
* Copyright (c) GoAhead Software Inc., 1995-1999. All Rights Reserved.
|
||||
* Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved.
|
||||
*
|
||||
* See the file "license.txt" for usage and redistribution license requirements
|
||||
*/
|
||||
@@ -16,12 +16,12 @@
|
||||
|
||||
/********************************* Defines ************************************/
|
||||
/*
|
||||
* Sprintf buffer structure. Make the increment 8 less than 64 so that
|
||||
* Sprintf buffer structure. Make the increment 64 so that
|
||||
* a balloc can use a 64 byte block.
|
||||
*/
|
||||
|
||||
#define STR_REALLOC 0x1 /* Reallocate the buffer as required */
|
||||
#define STR_INC 58 /* Growth increment */
|
||||
#define STR_INC 64 /* Growth increment */
|
||||
|
||||
typedef struct {
|
||||
char_t *s; /* Pointer to buffer */
|
||||
@@ -59,11 +59,11 @@ static void put_ulong(strbuf_t *buf, unsigned long int value, int base,
|
||||
/************************************ Code ************************************/
|
||||
/*
|
||||
* "basename" returns a pointer to the last component of a pathname
|
||||
* LINUX, RTEMS, and LynxOS have their own basename function
|
||||
* LINUX and LynxOS have their own basename function
|
||||
*/
|
||||
|
||||
#if ! LINUX & ! __rtems__ & ! LYNX
|
||||
char_t *basename(char_t* name)
|
||||
#if ! LINUX && ! LYNX && ! __rtems__
|
||||
char_t *basename(char_t *name)
|
||||
{
|
||||
char_t *cp;
|
||||
|
||||
@@ -83,7 +83,7 @@ char_t *basename(char_t* name)
|
||||
return ++cp;
|
||||
}
|
||||
}
|
||||
#endif /* ! LINUX && ! __rtems__ && ! LYNX */
|
||||
#endif /* ! LINUX & ! LYNX */
|
||||
|
||||
/******************************************************************************/
|
||||
/*
|
||||
@@ -91,9 +91,9 @@ char_t *basename(char_t* name)
|
||||
* the size of the buffer in BYTES!
|
||||
*/
|
||||
|
||||
char_t *dirname(char_t* buf, char_t* name, int bufsize)
|
||||
char_t *dirname(char_t *buf, char_t *name, int bufsize)
|
||||
{
|
||||
char_t* cp;
|
||||
char_t *cp;
|
||||
int len;
|
||||
|
||||
a_assert(name);
|
||||
@@ -130,14 +130,15 @@ char_t *dirname(char_t* buf, char_t* name, int bufsize)
|
||||
return buf;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************/
|
||||
/*
|
||||
* sprintf and vsprintf are bad, ok. You can easily clobber memory. Use
|
||||
* gsnprintf and gvsnprintf instead! These functions do _not_ support floating
|
||||
* fmtAlloc and fmtValloc instead! These functions do _not_ support floating
|
||||
* point, like %e, %f, %g...
|
||||
*/
|
||||
|
||||
int gsnprintf(char_t **s, int n, char_t *fmt, ...)
|
||||
int fmtAlloc(char_t **s, int n, char_t *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
int result;
|
||||
@@ -147,7 +148,30 @@ int gsnprintf(char_t **s, int n, char_t *fmt, ...)
|
||||
|
||||
*s = NULL;
|
||||
va_start(ap, fmt);
|
||||
result = gvsnprintf(s, n, fmt, ap);
|
||||
result = dsnprintf(s, n, fmt, ap, 0);
|
||||
va_end(ap);
|
||||
return result;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/*
|
||||
* Support a static buffer version for small buffers only!
|
||||
*/
|
||||
|
||||
int fmtStatic(char_t *s, int n, char_t *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
int result;
|
||||
|
||||
a_assert(s);
|
||||
a_assert(fmt);
|
||||
a_assert(n <= 256);
|
||||
|
||||
if (n <= 0) {
|
||||
return -1;
|
||||
}
|
||||
va_start(ap, fmt);
|
||||
result = dsnprintf(&s, n, fmt, ap, 0);
|
||||
va_end(ap);
|
||||
return result;
|
||||
}
|
||||
@@ -158,7 +182,7 @@ int gsnprintf(char_t **s, int n, char_t *fmt, ...)
|
||||
* reallocing if required.
|
||||
*/
|
||||
|
||||
int gsprintfRealloc(char_t **s, int n, int msize, char_t *fmt, ...)
|
||||
int fmtRealloc(char_t **s, int n, int msize, char_t *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
int result;
|
||||
@@ -180,17 +204,18 @@ int gsprintfRealloc(char_t **s, int n, int msize, char_t *fmt, ...)
|
||||
* A vsprintf replacement.
|
||||
*/
|
||||
|
||||
int gvsnprintf(char_t **s, int n, char_t *fmt, va_list arg)
|
||||
int fmtValloc(char_t **s, int n, char_t *fmt, va_list arg)
|
||||
{
|
||||
a_assert(s);
|
||||
a_assert(fmt);
|
||||
|
||||
*s = NULL;
|
||||
return dsnprintf(s, n, fmt, arg, 0);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/*
|
||||
* Dynamic sprintf implementation. Supports dynamic buffer allocation also.
|
||||
* Dynamic sprintf implementation. Supports dynamic buffer allocation.
|
||||
* This function can be called multiple times to grow an existing allocated
|
||||
* buffer. In this case, msize is set to the size of the previously allocated
|
||||
* buffer. The buffer will be realloced, as required. If msize is set, we
|
||||
@@ -252,7 +277,7 @@ static int dsnprintf(char_t **s, int size, char_t *fmt, va_list arg, int msize)
|
||||
}
|
||||
c = *fmt++;
|
||||
} else {
|
||||
for ( ; gisdigit(c); c = *fmt++) {
|
||||
for ( ; gisdigit((int)c); c = *fmt++) {
|
||||
width = width * 10 + (c - '0');
|
||||
}
|
||||
}
|
||||
@@ -263,7 +288,7 @@ static int dsnprintf(char_t **s, int size, char_t *fmt, va_list arg, int msize)
|
||||
prec = va_arg(arg, int);
|
||||
c = *fmt++;
|
||||
} else {
|
||||
for (prec = 0; gisdigit(c); c = *fmt++) {
|
||||
for (prec = 0; gisdigit((int)c); c = *fmt++) {
|
||||
prec = prec * 10 + (c - '0');
|
||||
}
|
||||
}
|
||||
@@ -402,24 +427,28 @@ static int strnlen(char_t *s, unsigned int n)
|
||||
|
||||
static void put_char(strbuf_t *buf, char_t c)
|
||||
{
|
||||
if (buf->count >= buf->size) {
|
||||
if (buf->count >= (buf->size - 1)) {
|
||||
if (! (buf->flags & STR_REALLOC)) {
|
||||
return;
|
||||
}
|
||||
buf->size += STR_INC;
|
||||
if (buf->size > buf->max && buf->size > STR_INC) {
|
||||
a_assert(buf->size <= buf->max);
|
||||
/*
|
||||
* Caller should increase the size of the calling buffer
|
||||
*/
|
||||
buf->size -= STR_INC;
|
||||
return;
|
||||
}
|
||||
if (buf->s == NULL) {
|
||||
buf->s = balloc(B_L, buf->size * sizeof(char_t*));
|
||||
buf->s = balloc(B_L, buf->size * sizeof(char_t));
|
||||
} else {
|
||||
buf->s = brealloc(B_L, buf->s, buf->size * sizeof(char_t*));
|
||||
buf->s = brealloc(B_L, buf->s, buf->size * sizeof(char_t));
|
||||
}
|
||||
}
|
||||
buf->s[buf->count] = c;
|
||||
++buf->count;
|
||||
if (c != '\0') {
|
||||
++buf->count;
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
@@ -428,7 +457,7 @@ static void put_char(strbuf_t *buf, char_t c)
|
||||
*/
|
||||
|
||||
static void put_string(strbuf_t *buf, char_t *s, int len, int width,
|
||||
int prec, enum flag f)
|
||||
int prec, enum flag f)
|
||||
{
|
||||
int i;
|
||||
|
||||
@@ -458,7 +487,7 @@ static void put_string(strbuf_t *buf, char_t *s, int len, int width,
|
||||
*/
|
||||
|
||||
static void put_ulong(strbuf_t *buf, unsigned long int value, int base,
|
||||
int upper, char_t *prefix, int width, int prec, enum flag f)
|
||||
int upper, char_t *prefix, int width, int prec, enum flag f)
|
||||
{
|
||||
unsigned long x, x2;
|
||||
int len, zeros, i;
|
||||
@@ -475,8 +504,14 @@ static void put_ulong(strbuf_t *buf, unsigned long int value, int base,
|
||||
width -= strnlen(prefix, ULONG_MAX);
|
||||
}
|
||||
if (!(f & flag_minus)) {
|
||||
for (i = 0; i < width; ++i) {
|
||||
put_char(buf, ' ');
|
||||
if (f & flag_zero) {
|
||||
for (i = 0; i < width; ++i) {
|
||||
put_char(buf, '0');
|
||||
}
|
||||
} else {
|
||||
for (i = 0; i < width; ++i) {
|
||||
put_char(buf, ' ');
|
||||
}
|
||||
}
|
||||
}
|
||||
if (prefix != NULL) {
|
||||
@@ -524,7 +559,7 @@ char_t *ascToUni(char_t *ubuf, char *str, int nBytes)
|
||||
* N.B. nBytes is the number of _bytes_ in the destination buffer, buf.
|
||||
*/
|
||||
|
||||
char *uniToAsc(char *buf, char_t* ustr, int nBytes)
|
||||
char *uniToAsc(char *buf, char_t *ustr, int nBytes)
|
||||
{
|
||||
#if UNICODE
|
||||
if (WideCharToMultiByte(CP_ACP, 0, ustr, nBytes, buf, nBytes, NULL,
|
||||
@@ -537,24 +572,26 @@ char *uniToAsc(char *buf, char_t* ustr, int nBytes)
|
||||
return (char*) buf;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************/
|
||||
/*
|
||||
* allocate (balloc) a buffer and do ascii to unicode conversion into it.
|
||||
* cp points to the ascii string which must be NULL terminated.
|
||||
* Return a pointer to the unicode buffer which must be bfree'd later.
|
||||
* Return NULL on failure to get buffer.
|
||||
* cp points to the ascii buffer. alen is the length of the buffer to be
|
||||
* converted not including a terminating NULL. Return a pointer to the
|
||||
* unicode buffer which must be bfree'd later. Return NULL on failure to
|
||||
* get buffer. The buffer returned is NULL terminated.
|
||||
*/
|
||||
char_t *ballocAscToUni(char * cp)
|
||||
|
||||
char_t *ballocAscToUni(char *cp, int alen)
|
||||
{
|
||||
char_t * unip;
|
||||
char_t *unip;
|
||||
int ulen;
|
||||
|
||||
ulen = (strlen(cp) + 1) * sizeof(char_t);
|
||||
ulen = (alen + 1) * sizeof(char_t);
|
||||
if ((unip = balloc(B_L, ulen)) == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
ascToUni(unip, cp, ulen);
|
||||
unip[alen] = 0;
|
||||
return unip;
|
||||
}
|
||||
|
||||
@@ -562,20 +599,68 @@ char_t *ballocAscToUni(char * cp)
|
||||
/*
|
||||
* allocate (balloc) a buffer and do unicode to ascii conversion into it.
|
||||
* unip points to the unicoded string. ulen is the number of characters
|
||||
* in the unicode string including teminating null, if there is one.
|
||||
* Return a pointer to the ascii buffer which must be bfree'd later.
|
||||
* Return NULL on failure to get buffer.
|
||||
* in the unicode string not including a teminating null. Return a pointer
|
||||
* to the ascii buffer which must be bfree'd later. Return NULL on failure
|
||||
* to get buffer. The buffer returned is NULL terminated.
|
||||
*/
|
||||
char *ballocUniToAsc(char_t * unip, int ulen)
|
||||
|
||||
char *ballocUniToAsc(char_t *unip, int ulen)
|
||||
{
|
||||
char * cp;
|
||||
|
||||
if ((cp = balloc(B_L, ulen)) == NULL) {
|
||||
if ((cp = balloc(B_L, ulen+1)) == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
uniToAsc(cp, unip, ulen);
|
||||
cp[ulen] = '\0';
|
||||
return cp;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/*
|
||||
* convert a hex string to an integer. The end of the string or a non-hex
|
||||
* character will indicate the end of the hex specification.
|
||||
*/
|
||||
|
||||
unsigned int hextoi(char_t *hexstring)
|
||||
{
|
||||
register char_t *h;
|
||||
register unsigned int c, v;
|
||||
|
||||
v = 0;
|
||||
h = hexstring;
|
||||
if (*h == '0' && (*(h+1) == 'x' || *(h+1) == 'X')) {
|
||||
h += 2;
|
||||
}
|
||||
while ((c = (unsigned int)*h++) != 0) {
|
||||
if (c >= '0' && c <= '9') {
|
||||
c -= '0';
|
||||
} else if (c >= 'a' && c <= 'f') {
|
||||
c = (c - 'a') + 10;
|
||||
} else if (c >= 'A' && c <= 'F') {
|
||||
c = (c - 'A') + 10;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
v = (v * 0x10) + c;
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/*
|
||||
* convert a string to an integer. If the string starts with "0x" or "0X"
|
||||
* a hexidecimal conversion is done.
|
||||
*/
|
||||
|
||||
unsigned int gstrtoi(char_t *s)
|
||||
{
|
||||
if (*s == '0' && (*(s+1) == 'x' || *(s+1) == 'X')) {
|
||||
s += 2;
|
||||
return hextoi(s);
|
||||
}
|
||||
return gatoi(s);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* ringq.c -- Ring queue buffering module
|
||||
*
|
||||
* Copyright (c) GoAhead Software Inc., 1995-1999. All Rights Reserved.
|
||||
* Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved.
|
||||
*
|
||||
* See the file "license.txt" for usage and redistribution license requirements
|
||||
*/
|
||||
@@ -10,7 +10,7 @@
|
||||
|
||||
/*
|
||||
* A ring queue allows maximum utilization of memory for data storage and is
|
||||
* ideal for input/output buffering. This module provides a highly effecient
|
||||
* ideal for input/output buffering. This module provides a highly efficient
|
||||
* implementation and a vehicle for dynamic strings.
|
||||
*
|
||||
* WARNING: This is a public implementation and callers have full access to
|
||||
@@ -36,10 +36,10 @@
|
||||
* rq->buf rq->servp rq->endp rq->enduf
|
||||
*
|
||||
* The queue is empty when servp == endp. This means that the queue will hold
|
||||
* at most rq->buflen -1 bytes. It is the fillers responsibility to ensure
|
||||
* at most rq->buflen -1 bytes. It is the filler's responsibility to ensure
|
||||
* the ringq is never filled such that servp == endp.
|
||||
*
|
||||
* It is the fillers responsibility to "wrap" the endp back to point to
|
||||
* It is the filler's responsibility to "wrap" the endp back to point to
|
||||
* rq->buf when the pointer steps past the end. Correspondingly it is the
|
||||
* consumers responsibility to "wrap" the servp when it steps to rq->endbuf.
|
||||
* The ringqPutc and ringqGetc routines will do this automatically.
|
||||
@@ -65,7 +65,10 @@
|
||||
|
||||
/***************************** Forward Declarations ***************************/
|
||||
|
||||
static int ringq_grow(ringq_t *rq);
|
||||
static int ringqGrow(ringq_t *rq);
|
||||
static int getBinBlockSize(int size);
|
||||
|
||||
int ringqGrowCalls = 0;
|
||||
|
||||
/*********************************** Code *************************************/
|
||||
/*
|
||||
@@ -76,12 +79,15 @@ static int ringq_grow(ringq_t *rq);
|
||||
* dynamically allocated. Set maxsize
|
||||
*/
|
||||
|
||||
int ringqOpen(ringq_t *rq, int increment, int maxsize)
|
||||
int ringqOpen(ringq_t *rq, int initSize, int maxsize)
|
||||
{
|
||||
a_assert(rq);
|
||||
a_assert(increment >= 0);
|
||||
int increment;
|
||||
|
||||
if ((rq->buf = balloc(B_L, increment)) == NULL) {
|
||||
a_assert(rq);
|
||||
a_assert(initSize >= 0);
|
||||
|
||||
increment = getBinBlockSize(initSize);
|
||||
if ((rq->buf = balloc(B_L, (increment))) == NULL) {
|
||||
return -1;
|
||||
}
|
||||
rq->maxsize = maxsize;
|
||||
@@ -115,8 +121,8 @@ void ringqClose(ringq_t *rq)
|
||||
|
||||
/******************************************************************************/
|
||||
/*
|
||||
* Return the length of the ringq. Users must fill the queue to a high
|
||||
* water mark of at most one less than the queue size.
|
||||
* Return the length of the data in the ringq. Users must fill the queue to
|
||||
* a high water mark of at most one less than the queue size.
|
||||
*/
|
||||
|
||||
int ringqLen(ringq_t *rq)
|
||||
@@ -126,8 +132,7 @@ int ringqLen(ringq_t *rq)
|
||||
|
||||
if (rq->servp > rq->endp) {
|
||||
return rq->buflen + rq->endp - rq->servp;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
return rq->endp - rq->servp;
|
||||
}
|
||||
}
|
||||
@@ -166,12 +171,12 @@ int ringqGetc(ringq_t *rq)
|
||||
|
||||
int ringqPutc(ringq_t *rq, char_t c)
|
||||
{
|
||||
char_t* cp;
|
||||
char_t *cp;
|
||||
|
||||
a_assert(rq);
|
||||
a_assert(rq->buflen == (rq->endbuf - rq->buf));
|
||||
|
||||
if (ringqPutBlkMax(rq) < (int) sizeof(char_t) && !ringq_grow(rq)) {
|
||||
if ((ringqPutBlkMax(rq) < (int) sizeof(char_t)) && !ringqGrow(rq)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -191,12 +196,12 @@ int ringqPutc(ringq_t *rq, char_t c)
|
||||
|
||||
int ringqInsertc(ringq_t *rq, char_t c)
|
||||
{
|
||||
char_t* cp;
|
||||
char_t *cp;
|
||||
|
||||
a_assert(rq);
|
||||
a_assert(rq->buflen == (rq->endbuf - rq->buf));
|
||||
|
||||
if (ringqPutBlkMax(rq) < (int) sizeof(char_t) && !ringq_grow(rq)) {
|
||||
if (ringqPutBlkMax(rq) < (int) sizeof(char_t) && !ringqGrow(rq)) {
|
||||
return -1;
|
||||
}
|
||||
if (rq->servp <= rq->buf) {
|
||||
@@ -210,10 +215,10 @@ int ringqInsertc(ringq_t *rq, char_t c)
|
||||
|
||||
/******************************************************************************/
|
||||
/*
|
||||
* Add a string to the queue. Add a trailing wide null (two nulls)
|
||||
* Add a string to the queue. Add a trailing null (maybe two nulls)
|
||||
*/
|
||||
|
||||
int ringqPutstr(ringq_t *rq, char_t *str)
|
||||
int ringqPutStr(ringq_t *rq, char_t *str)
|
||||
{
|
||||
int rc;
|
||||
|
||||
@@ -226,6 +231,19 @@ int ringqPutstr(ringq_t *rq, char_t *str)
|
||||
return rc;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/*
|
||||
* Add a null terminator. This does NOT increase the size of the queue
|
||||
*/
|
||||
|
||||
void ringqAddNull(ringq_t *rq)
|
||||
{
|
||||
a_assert(rq);
|
||||
a_assert(rq->buflen == (rq->endbuf - rq->buf));
|
||||
|
||||
*((char_t*) rq->endp) = (char_t) '\0';
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
#if UNICODE
|
||||
/*
|
||||
@@ -261,7 +279,7 @@ int ringqPutcA(ringq_t *rq, char c)
|
||||
a_assert(rq);
|
||||
a_assert(rq->buflen == (rq->endbuf - rq->buf));
|
||||
|
||||
if (ringqPutBlkMax(rq) == 0 && !ringq_grow(rq)) {
|
||||
if (ringqPutBlkMax(rq) == 0 && !ringqGrow(rq)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -282,7 +300,7 @@ int ringqInsertcA(ringq_t *rq, char c)
|
||||
a_assert(rq);
|
||||
a_assert(rq->buflen == (rq->endbuf - rq->buf));
|
||||
|
||||
if (ringqPutBlkMax(rq) == 0 && !ringq_grow(rq)) {
|
||||
if (ringqPutBlkMax(rq) == 0 && !ringqGrow(rq)) {
|
||||
return -1;
|
||||
}
|
||||
if (rq->servp <= rq->buf) {
|
||||
@@ -298,7 +316,7 @@ int ringqInsertcA(ringq_t *rq, char c)
|
||||
* ie. beyond the last valid byte.
|
||||
*/
|
||||
|
||||
int ringqPutstrA(ringq_t *rq, char *str)
|
||||
int ringqPutStrA(ringq_t *rq, char *str)
|
||||
{
|
||||
int rc;
|
||||
|
||||
@@ -334,7 +352,7 @@ int ringqPutBlk(ringq_t *rq, unsigned char *buf, int size)
|
||||
while (size > 0) {
|
||||
this = min(ringqPutBlkMax(rq), size);
|
||||
if (this <= 0) {
|
||||
if (! ringq_grow(rq)) {
|
||||
if (! ringqGrow(rq)) {
|
||||
break;
|
||||
}
|
||||
this = min(ringqPutBlkMax(rq), size);
|
||||
@@ -485,10 +503,13 @@ void ringqGetBlkAdj(ringq_t *rq, int size)
|
||||
void ringqFlush(ringq_t *rq)
|
||||
{
|
||||
a_assert(rq);
|
||||
a_assert(rq->servp);
|
||||
|
||||
rq->servp = rq->buf;
|
||||
rq->endp = rq->buf;
|
||||
*rq->servp = '\0';
|
||||
if (rq->servp) {
|
||||
*rq->servp = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
@@ -498,7 +519,7 @@ void ringqFlush(ringq_t *rq)
|
||||
* the maximum possible size.
|
||||
*/
|
||||
|
||||
static int ringq_grow(ringq_t *rq)
|
||||
static int ringqGrow(ringq_t *rq)
|
||||
{
|
||||
unsigned char *newbuf;
|
||||
int len;
|
||||
@@ -531,7 +552,31 @@ static int ringq_grow(ringq_t *rq)
|
||||
rq->endbuf = &rq->buf[rq->buflen];
|
||||
|
||||
ringqPutBlk(rq, newbuf, len);
|
||||
|
||||
/*
|
||||
* Double the increment so the next grow will line up with balloc'ed memory
|
||||
*/
|
||||
rq->increment = getBinBlockSize(2 * rq->increment);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/*
|
||||
* Find the smallest binary memory size that "size" will fit into. This
|
||||
* makes the ringq and ringqGrow routines much more efficient. The balloc
|
||||
* routine likes powers of 2 minus 1.
|
||||
*/
|
||||
|
||||
static int getBinBlockSize(int size)
|
||||
{
|
||||
int q;
|
||||
|
||||
size = size >> B_SHIFT;
|
||||
for (q = 0; size; size >>= 1) {
|
||||
q++;
|
||||
}
|
||||
return (1 << (B_SHIFT + q));
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* rom.c -- Support for ROMed page retrieval.
|
||||
*
|
||||
* Copyright (c) Go Ahead Software Inc., 1995-1999. All Rights Reserved.
|
||||
* Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved.
|
||||
*
|
||||
* See the file "license.txt" for usage and redistribution license requirements
|
||||
*/
|
||||
@@ -20,13 +20,6 @@
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#if CE
|
||||
#define EINVAL 22
|
||||
#define EBADF 9
|
||||
#else
|
||||
#include <errno.h>
|
||||
#endif
|
||||
|
||||
#include "wsIntrn.h"
|
||||
|
||||
/******************************** Local Data **********************************/
|
||||
@@ -46,7 +39,7 @@ int websRomOpen()
|
||||
int nchars;
|
||||
char_t name[SYM_MAX];
|
||||
|
||||
romTab = symOpen(64);
|
||||
romTab = symOpen(WEBS_SYM_INIT);
|
||||
|
||||
for (wip = websRomPageIndex; wip->path; wip++) {
|
||||
gstrncpy(name, wip->path, SYM_MAX);
|
||||
@@ -67,7 +60,7 @@ int websRomOpen()
|
||||
|
||||
void websRomClose()
|
||||
{
|
||||
symClose(romTab, NULL);
|
||||
symClose(romTab);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
@@ -105,7 +98,7 @@ void websRomPageClose(int fd)
|
||||
* Stat a web page
|
||||
*/
|
||||
|
||||
int websRomPageStat(char_t *path, websStatType* sbuf)
|
||||
int websRomPageStat(char_t *path, websStatType *sbuf)
|
||||
{
|
||||
websRomPageIndexType *wip;
|
||||
sym_t *sp;
|
||||
@@ -193,6 +186,6 @@ long websRomPageSeek(webs_t wp, long offset, int origin)
|
||||
return (wip->pos = pos);
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif /* WEBS_PAGE_ROM */
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* security.c -- Security handler
|
||||
*
|
||||
* Copyright (c) Go Ahead Software Inc., 1995-1999. All Rights Reserved.
|
||||
* Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved.
|
||||
*
|
||||
* See the file "license.txt" for usage and redistribution license requirements
|
||||
*/
|
||||
@@ -9,18 +9,42 @@
|
||||
/******************************** Description *********************************/
|
||||
|
||||
/*
|
||||
* This module provides a basic security policy. It supports a single global
|
||||
* password and ignores the username. Encoding/decoding of the password is
|
||||
* -not- done.
|
||||
* This module provides a basic security policy.
|
||||
*/
|
||||
|
||||
/********************************* Includes ***********************************/
|
||||
|
||||
#include "wsIntrn.h"
|
||||
#include "um.h"
|
||||
#ifdef DIGEST_ACCESS_SUPPORT
|
||||
#include "websda.h"
|
||||
#endif
|
||||
|
||||
/********************************** Defines ***********************************/
|
||||
/*
|
||||
* The following #defines change the behaviour of security in the absence
|
||||
* of User Management.
|
||||
* Note that use of User management functions require prior calling of
|
||||
* umInit() to behave correctly
|
||||
*/
|
||||
|
||||
#ifndef USER_MANAGEMENT_SUPPORT
|
||||
#define umGetAccessMethodForURL(url) AM_FULL
|
||||
#define umUserExists(userid) 0
|
||||
#define umUserCanAccessURL(userid, url) 1
|
||||
#define umGetUserPassword(userid) websGetPassword()
|
||||
#define umGetAccessLimitSecure(accessLimit) 0
|
||||
#define umGetAccessLimit(url) NULL
|
||||
#endif
|
||||
|
||||
/******************************** Local Data **********************************/
|
||||
|
||||
static char_t websPassword[WEBS_MAX_PASS]; /* Access password (decoded) */
|
||||
#ifdef _DEBUG
|
||||
static int debugSecurity = 1;
|
||||
#else
|
||||
static int debugSecurity = 0;
|
||||
#endif
|
||||
|
||||
/*********************************** Code *************************************/
|
||||
/*
|
||||
@@ -30,46 +54,143 @@ static char_t websPassword[WEBS_MAX_PASS]; /* Access password (decoded) */
|
||||
int websSecurityHandler(webs_t wp, char_t *urlPrefix, char_t *webDir, int arg,
|
||||
char_t *url, char_t *path, char_t *query)
|
||||
{
|
||||
char_t *type, *password;
|
||||
int flags;
|
||||
char_t *type, *userid, *password, *accessLimit;
|
||||
int flags, nRet;
|
||||
accessMeth_t am;
|
||||
|
||||
a_assert(websValid(wp));
|
||||
a_assert(url && *url);
|
||||
a_assert(path && *path);
|
||||
|
||||
/*
|
||||
* Get the critical request details
|
||||
*/
|
||||
type = websGetRequestType(wp);
|
||||
password = websGetRequestPassword(wp);
|
||||
userid = websGetRequestUserName(wp);
|
||||
flags = websGetRequestFlags(wp);
|
||||
/*
|
||||
* Get the access limit for the URL. Exit if none found.
|
||||
*/
|
||||
accessLimit = umGetAccessLimit(path);
|
||||
if (accessLimit == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check to see if URL must be encrypted
|
||||
*/
|
||||
#ifdef WEBS_SSL_SUPPORT
|
||||
nRet = umGetAccessLimitSecure(accessLimit);
|
||||
if (nRet && ((flags | WEBS_SECURE) == 0)) {
|
||||
websStats.access++;
|
||||
websError(wp, 200, T("Access Denied\nSecure access is required."));
|
||||
trace(3, T("SEC: Non-secure access attempted on <%s>\n"), path);
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Validate the users password if required (local access is always allowed)
|
||||
* We compare the decoded form of the password.
|
||||
* Get the access limit for the URL
|
||||
*/
|
||||
if (*websPassword && !(flags & WEBS_LOCAL_REQUEST)) {
|
||||
am = umGetAccessMethodForURL(accessLimit);
|
||||
|
||||
if (password && *password) {
|
||||
if (gstrcmp(password, websPassword) != 0) {
|
||||
nRet = 0;
|
||||
if ((flags & WEBS_LOCAL_REQUEST) && (debugSecurity == 0)) {
|
||||
/*
|
||||
* Local access is always allowed (defeat when debugging)
|
||||
*/
|
||||
} else if (am == AM_NONE) {
|
||||
/*
|
||||
* URL is supposed to be hidden! Make like it wasn't found.
|
||||
*/
|
||||
websStats.access++;
|
||||
websError(wp, 400, T("Page Not Found"));
|
||||
nRet = 1;
|
||||
} else if (userid && *userid) {
|
||||
if (!umUserExists(userid)) {
|
||||
websStats.access++;
|
||||
websError(wp, 200, T("Access Denied\nUnknown User"));
|
||||
trace(3, T("SEC: Unknown user <%s> attempted to access <%s>\n"),
|
||||
userid, path);
|
||||
nRet = 1;
|
||||
} else if (!umUserCanAccessURL(userid, accessLimit)) {
|
||||
websStats.access++;
|
||||
websError(wp, 403, T("Access Denied\nProhibited User"));
|
||||
nRet = 1;
|
||||
} else if (password && * password) {
|
||||
char_t * userpass = umGetUserPassword(userid);
|
||||
if (userpass) {
|
||||
if (gstrcmp(password, userpass) != 0) {
|
||||
websStats.access++;
|
||||
websError(wp, 200, T("Access Denied\nWrong Password"));
|
||||
trace(3, T("SEC: Password fail for user <%s>")
|
||||
T("attempt to access <%s>\n"), userid, path);
|
||||
nRet = 1;
|
||||
} else {
|
||||
/*
|
||||
* User and password check out.
|
||||
*/
|
||||
}
|
||||
|
||||
bfree (B_L, userpass);
|
||||
}
|
||||
#ifdef DIGEST_ACCESS_SUPPORT
|
||||
} else if (flags & WEBS_AUTH_DIGEST) {
|
||||
|
||||
char_t *digestCalc;
|
||||
|
||||
/*
|
||||
* Check digest for equivalence
|
||||
*/
|
||||
wp->password = umGetUserPassword(userid);
|
||||
|
||||
a_assert(wp->digest);
|
||||
a_assert(wp->nonce);
|
||||
a_assert(wp->password);
|
||||
|
||||
digestCalc = websCalcDigest(wp);
|
||||
a_assert(digestCalc);
|
||||
|
||||
if (gstrcmp(wp->digest, digestCalc) != 0) {
|
||||
websStats.access++;
|
||||
websError(wp, 200, T("Access Denied\nWrong Password"));
|
||||
websSetPassword(T(""));
|
||||
return 1;
|
||||
nRet = 1;
|
||||
}
|
||||
|
||||
bfree (B_L, digestCalc);
|
||||
#endif
|
||||
} else {
|
||||
/*
|
||||
* This will cause the browser to display a password / username
|
||||
* dialog
|
||||
* No password has been specified
|
||||
*/
|
||||
#ifdef DIGEST_ACCESS_SUPPORT
|
||||
if (am == AM_DIGEST) {
|
||||
wp->flags |= WEBS_AUTH_DIGEST;
|
||||
}
|
||||
#endif
|
||||
websStats.errors++;
|
||||
websError(wp, 401, T("<html><head>Access Denied</head><body>\r\n\
|
||||
Access to this document requires a password.</body>\
|
||||
</html>\r\n"));
|
||||
return 1;
|
||||
websError(wp, 401,
|
||||
T("Access to this document requires a password"));
|
||||
nRet = 1;
|
||||
}
|
||||
} else if (am != AM_FULL) {
|
||||
/*
|
||||
* This will cause the browser to display a password / username
|
||||
* dialog
|
||||
*/
|
||||
#ifdef DIGEST_ACCESS_SUPPORT
|
||||
if (am == AM_DIGEST) {
|
||||
wp->flags |= WEBS_AUTH_DIGEST;
|
||||
}
|
||||
#endif
|
||||
websStats.errors++;
|
||||
websError(wp, 401, T("Access to this document requires a User ID"));
|
||||
nRet = 1;
|
||||
}
|
||||
return 0;
|
||||
|
||||
bfree(B_L, accessLimit);
|
||||
|
||||
return nRet;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
@@ -102,7 +223,7 @@ void websSetPassword(char_t *password)
|
||||
|
||||
char_t *websGetPassword()
|
||||
{
|
||||
return websPassword;
|
||||
return bstrdup(B_L, websPassword);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,15 +1,15 @@
|
||||
/*
|
||||
* sym.c -- Symbol Table module
|
||||
*
|
||||
* Copyright (c) GoAhead Software Inc., 1995-1999. All Rights Reserved.
|
||||
* Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved.
|
||||
*
|
||||
* See the file "license.txt" for usage and redistribution license requirements
|
||||
*/
|
||||
|
||||
/******************************** Description *********************************/
|
||||
/*
|
||||
* This module implements a highly efficient generic symbol table with
|
||||
* update and access routines. Symbols are simple character strings and
|
||||
* This module implements a highly efficient generic symbol table with
|
||||
* update and access routines. Symbols are simple character strings and
|
||||
* the values they take can be flexible types as defined by value_t.
|
||||
* This modules allows multiple symbol tables to be created.
|
||||
*/
|
||||
@@ -32,24 +32,51 @@ typedef struct { /* Symbol table descriptor */
|
||||
|
||||
/********************************* Globals ************************************/
|
||||
|
||||
static sym_tabent_t **sym; /* List of symbol tables */
|
||||
static int sym_max; /* One past the max symbol table */
|
||||
static sym_tabent_t **sym; /* List of symbol tables */
|
||||
static int symMax; /* One past the max symbol table */
|
||||
static int symOpenCount = 0; /* Count of apps using sym */
|
||||
|
||||
static int htIndex; /* Current location in table */
|
||||
static sym_t* next; /* Next symbol in iteration */
|
||||
static int htIndex; /* Current location in table */
|
||||
static sym_t* next; /* Next symbol in iteration */
|
||||
|
||||
/**************************** Forward Declarations ****************************/
|
||||
|
||||
static int hashIndex(sym_tabent_t *tp, char_t *name);
|
||||
static sym_t *hash(sym_tabent_t *tp, char_t *name);
|
||||
static int calc_prime(int size);
|
||||
static int hashIndex(sym_tabent_t *tp, char_t *name);
|
||||
static sym_t *hash(sym_tabent_t *tp, char_t *name);
|
||||
static int calcPrime(int size);
|
||||
|
||||
/*********************************** Code *************************************/
|
||||
/*
|
||||
* Open the symbol table subSystem.
|
||||
*/
|
||||
|
||||
int symSubOpen()
|
||||
{
|
||||
if (++symOpenCount == 1) {
|
||||
symMax = 0;
|
||||
sym = NULL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/*
|
||||
* Close the symbol table subSystem.
|
||||
*/
|
||||
|
||||
void symSubClose()
|
||||
{
|
||||
if (--symOpenCount <= 0) {
|
||||
symOpenCount = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/*
|
||||
* Create a symbol table.
|
||||
*/
|
||||
|
||||
sym_fd_t symOpen(int hash_size)
|
||||
sym_fd_t symOpen(int hash_size)
|
||||
{
|
||||
sym_fd_t sd;
|
||||
sym_tabent_t *tp;
|
||||
@@ -67,20 +94,20 @@ sym_fd_t symOpen(int hash_size)
|
||||
* Create a new symbol table structure and zero
|
||||
*/
|
||||
if ((tp = (sym_tabent_t*) balloc(B_L, sizeof(sym_tabent_t))) == NULL) {
|
||||
sym_max = hFree((void***) &sym, sd);
|
||||
symMax = hFree((void***) &sym, sd);
|
||||
return -1;
|
||||
}
|
||||
memset(tp, 0, sizeof(sym_tabent_t));
|
||||
if (sd >= sym_max) {
|
||||
sym_max = sd + 1;
|
||||
if (sd >= symMax) {
|
||||
symMax = sd + 1;
|
||||
}
|
||||
a_assert(0 <= sd && sd < sym_max);
|
||||
a_assert(0 <= sd && sd < symMax);
|
||||
sym[sd] = tp;
|
||||
|
||||
/*
|
||||
* Now create the hash table for fast indexing.
|
||||
*/
|
||||
tp->hash_size = calc_prime(hash_size);
|
||||
tp->hash_size = calcPrime(hash_size);
|
||||
tp->hash_table = (sym_t**) balloc(B_L, tp->hash_size * sizeof(sym_t*));
|
||||
a_assert(tp->hash_table);
|
||||
memset(tp->hash_table, 0, tp->hash_size * sizeof(sym_t*));
|
||||
@@ -94,13 +121,13 @@ sym_fd_t symOpen(int hash_size)
|
||||
* to free resources associated with each symbol table entry.
|
||||
*/
|
||||
|
||||
void symClose(sym_fd_t sd, void (*cleanup)(sym_t *symp))
|
||||
void symClose(sym_fd_t sd)
|
||||
{
|
||||
sym_tabent_t *tp;
|
||||
sym_t *sp, *forw;
|
||||
int i;
|
||||
int i;
|
||||
|
||||
a_assert(0 <= sd && sd < sym_max);
|
||||
a_assert(0 <= sd && sd < symMax);
|
||||
tp = sym[sd];
|
||||
a_assert(tp);
|
||||
|
||||
@@ -110,30 +137,18 @@ void symClose(sym_fd_t sd, void (*cleanup)(sym_t *symp))
|
||||
for (i = 0; i < tp->hash_size; i++) {
|
||||
for (sp = tp->hash_table[i]; sp; sp = forw) {
|
||||
forw = sp->forw;
|
||||
if (cleanup) {
|
||||
(*cleanup)(sp);
|
||||
}
|
||||
valueFree(&sp->name);
|
||||
valueFree(&sp->content);
|
||||
bfree(B_L, (void*) sp);
|
||||
sp = forw;
|
||||
}
|
||||
}
|
||||
bfree(B_L, (void*) tp->hash_table);
|
||||
|
||||
sym_max = hFree((void***) &sym, sd);
|
||||
symMax = hFree((void***) &sym, sd);
|
||||
bfree(B_L, (void*) tp);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/*
|
||||
* Default callback for freeing the value.
|
||||
*/
|
||||
|
||||
void symFreeVar(sym_t* sp)
|
||||
{
|
||||
valueFree(&sp->content);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/*
|
||||
* Return the first symbol in the hashtable if there is one. This call is used
|
||||
@@ -145,9 +160,9 @@ sym_t* symFirst(sym_fd_t sd)
|
||||
{
|
||||
sym_tabent_t *tp;
|
||||
sym_t *sp, *forw;
|
||||
int i;
|
||||
int i;
|
||||
|
||||
a_assert(0 <= sd && sd < sym_max);
|
||||
a_assert(0 <= sd && sd < symMax);
|
||||
tp = sym[sd];
|
||||
a_assert(tp);
|
||||
|
||||
@@ -180,9 +195,9 @@ sym_t* symNext(sym_fd_t sd)
|
||||
{
|
||||
sym_tabent_t *tp;
|
||||
sym_t *sp, *forw;
|
||||
int i;
|
||||
int i;
|
||||
|
||||
a_assert(0 <= sd && sd < sym_max);
|
||||
a_assert(0 <= sd && sd < symMax);
|
||||
tp = sym[sd];
|
||||
a_assert(tp);
|
||||
|
||||
@@ -219,9 +234,10 @@ sym_t *symLookup(sym_fd_t sd, char_t *name)
|
||||
sym_t *sp;
|
||||
char_t *cp;
|
||||
|
||||
a_assert(0 <= sd && sd < sym_max);
|
||||
tp = sym[sd];
|
||||
a_assert(tp);
|
||||
a_assert(0 <= sd && sd < symMax);
|
||||
if ((tp = sym[sd]) == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (name == NULL || *name == '\0') {
|
||||
return NULL;
|
||||
@@ -241,8 +257,10 @@ sym_t *symLookup(sym_fd_t sd, char_t *name)
|
||||
|
||||
/******************************************************************************/
|
||||
/*
|
||||
* Enter a symbol into the table. If already there, update its value.
|
||||
* Always succeeds if memory available.
|
||||
* Enter a symbol into the table. If already there, update its value.
|
||||
* Always succeeds if memory available. We allocate a copy of "name" here
|
||||
* so it can be a volatile variable. The value "v" is just a copy of the
|
||||
* passed in value, so it MUST be persistent.
|
||||
*/
|
||||
|
||||
sym_t *symEnter(sym_fd_t sd, char_t *name, value_t v, int arg)
|
||||
@@ -252,13 +270,13 @@ sym_t *symEnter(sym_fd_t sd, char_t *name, value_t v, int arg)
|
||||
char_t *cp;
|
||||
int hindex;
|
||||
|
||||
a_assert(name && *name);
|
||||
a_assert(0 <= sd && sd < sym_max);
|
||||
a_assert(name);
|
||||
a_assert(0 <= sd && sd < symMax);
|
||||
tp = sym[sd];
|
||||
a_assert(tp);
|
||||
|
||||
/*
|
||||
* Calculate the first daisy-chain from the hash table. If non-zero, then
|
||||
* Calculate the first daisy-chain from the hash table. If non-zero, then
|
||||
* we have daisy-chain, so scan it and look for the symbol.
|
||||
*/
|
||||
last = NULL;
|
||||
@@ -333,12 +351,12 @@ int symDelete(sym_fd_t sd, char_t *name)
|
||||
int hindex;
|
||||
|
||||
a_assert(name && *name);
|
||||
a_assert(0 <= sd && sd < sym_max);
|
||||
a_assert(0 <= sd && sd < symMax);
|
||||
tp = sym[sd];
|
||||
a_assert(tp);
|
||||
|
||||
/*
|
||||
* Calculate the first daisy-chain from the hash table. If non-zero, then
|
||||
* Calculate the first daisy-chain from the hash table. If non-zero, then
|
||||
* we have daisy-chain, so scan it and look for the symbol.
|
||||
*/
|
||||
last = NULL;
|
||||
@@ -355,7 +373,7 @@ int symDelete(sym_fd_t sd, char_t *name)
|
||||
if (sp == (sym_t*) NULL) { /* Not Found */
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Unlink and free the symbol. Last will be set if the element to be deleted
|
||||
* is not first in the chain.
|
||||
@@ -366,6 +384,7 @@ int symDelete(sym_fd_t sd, char_t *name)
|
||||
tp->hash_table[hindex] = sp->forw;
|
||||
}
|
||||
valueFree(&sp->name);
|
||||
valueFree(&sp->content);
|
||||
bfree(B_L, (void*) sp);
|
||||
|
||||
return 0;
|
||||
@@ -393,13 +412,13 @@ static sym_t *hash(sym_tabent_t *tp, char_t *name)
|
||||
|
||||
static int hashIndex(sym_tabent_t *tp, char_t *name)
|
||||
{
|
||||
unsigned int sum;
|
||||
int i;
|
||||
unsigned int sum;
|
||||
int i;
|
||||
|
||||
a_assert(tp);
|
||||
/*
|
||||
* Add in each character shifted up progressively by 7 bits. The shift
|
||||
* amount is rounded so as to not shift too far. It thus cycles with each
|
||||
* amount is rounded so as to not shift too far. It thus cycles with each
|
||||
* new cycle placing character shifted up by one bit.
|
||||
*/
|
||||
i = 0;
|
||||
@@ -416,13 +435,14 @@ static int hashIndex(sym_tabent_t *tp, char_t *name)
|
||||
* Check if this number is a prime
|
||||
*/
|
||||
|
||||
static int is_prime(int n)
|
||||
static int isPrime(int n)
|
||||
{
|
||||
int i;
|
||||
int i, max;
|
||||
|
||||
a_assert(n > 0);
|
||||
|
||||
for (i = 2; i < n; i++) {
|
||||
max = n / 2;
|
||||
for (i = 2; i <= max; i++) {
|
||||
if (n % i == 0) {
|
||||
return 0;
|
||||
}
|
||||
@@ -435,14 +455,14 @@ static int is_prime(int n)
|
||||
* Calculate the largest prime smaller than size.
|
||||
*/
|
||||
|
||||
static int calc_prime(int size)
|
||||
static int calcPrime(int size)
|
||||
{
|
||||
int count;
|
||||
|
||||
a_assert(size > 0);
|
||||
|
||||
for (count = size; count > 0; count--) {
|
||||
if (is_prime(count)) {
|
||||
if (isPrime(count)) {
|
||||
return count;
|
||||
}
|
||||
}
|
||||
@@ -450,3 +470,4 @@ static int calc_prime(int size)
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* uemf.c -- GoAhead Micro Embedded Management Framework
|
||||
*
|
||||
* Copyright (c) Go Ahead Software, Inc., 1995-1999
|
||||
* Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved.
|
||||
*
|
||||
* See the file "license.txt" for usage and redistribution license requirements
|
||||
*/
|
||||
@@ -22,31 +22,62 @@
|
||||
|
||||
int emfInst; /* Application instance handle */
|
||||
|
||||
/****************************** Forward Declarations **************************/
|
||||
|
||||
extern void defaultErrorHandler(int etype, char_t *buf);
|
||||
static void (*errorHandler)(int etype, char_t *msg) = defaultErrorHandler;
|
||||
|
||||
extern void defaultTraceHandler(int level, char_t *buf);
|
||||
static void (*traceHandler)(int level, char_t *buf) = defaultTraceHandler;
|
||||
|
||||
/************************************* Code ***********************************/
|
||||
/*
|
||||
* Error message that doesn't need user attention. Customize this code
|
||||
* to direct error messages to whereever the developer wishes
|
||||
* to direct error messages to wherever the developer wishes
|
||||
*/
|
||||
|
||||
void error(E_ARGS_DEC, int flags, char_t *fmt, ...)
|
||||
void error(E_ARGS_DEC, int etype, char_t *fmt, ...)
|
||||
{
|
||||
va_list arglist;
|
||||
|
||||
va_start(arglist, fmt);
|
||||
|
||||
if (flags & E_LOG) {
|
||||
/* Log error message */
|
||||
va_list args;
|
||||
char_t *fmtBuf, *buf;
|
||||
|
||||
} else if (flags & E_ASSERT) {
|
||||
/* Assert message */
|
||||
va_start(args, fmt);
|
||||
fmtValloc(&fmtBuf, E_MAX_ERROR, fmt, args);
|
||||
|
||||
} else if (flags & E_USER) {
|
||||
/* Display message to the user */
|
||||
if (etype == E_LOG) {
|
||||
fmtAlloc(&buf, E_MAX_ERROR, T("%s\n"), fmtBuf);
|
||||
#if DEV
|
||||
} else if (etype == E_ASSERT) {
|
||||
fmtAlloc(&buf, E_MAX_ERROR,
|
||||
T("Assertion %s, failed at %s %d\n"), fmtBuf, E_ARGS);
|
||||
#endif
|
||||
} else if (etype == E_USER) {
|
||||
fmtAlloc(&buf, E_MAX_ERROR, T("%s\n"), fmtBuf);
|
||||
}
|
||||
va_end(args);
|
||||
|
||||
bfree(B_L, fmtBuf);
|
||||
|
||||
if (errorHandler) {
|
||||
errorHandler(etype, buf);
|
||||
}
|
||||
|
||||
vprintf (fmt, arglist);
|
||||
va_end(arglist);
|
||||
bfreeSafe(B_L, buf);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/*
|
||||
* Replace the default error handler. Return pointer to old error handler.
|
||||
*/
|
||||
|
||||
void (*errorSetHandler(void (*function)(int etype, char_t *msg))) \
|
||||
(int etype, char_t *msg)
|
||||
{
|
||||
void (*oldHandler)(int etype, char_t *buf);
|
||||
|
||||
oldHandler = errorHandler;
|
||||
errorHandler = function;
|
||||
return oldHandler;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
@@ -54,21 +85,48 @@ void error(E_ARGS_DEC, int flags, char_t *fmt, ...)
|
||||
* Trace log. Customize this function to log trace output
|
||||
*/
|
||||
|
||||
void goahead_trace(int level, char_t *afmt, ...)
|
||||
void trace(int level, char_t *fmt, ...)
|
||||
{
|
||||
#if DEBUG
|
||||
va_list args;
|
||||
char_t *buf;
|
||||
|
||||
va_start(args, afmt);
|
||||
buf = NULL;
|
||||
gvsnprintf(&buf, VALUE_MAX_STRING, afmt, args);
|
||||
if (buf) {
|
||||
gprintf(buf);
|
||||
bfree(B_L, buf);
|
||||
va_start(args, fmt);
|
||||
fmtValloc(&buf, VALUE_MAX_STRING, fmt, args);
|
||||
|
||||
if (traceHandler) {
|
||||
traceHandler(level, buf);
|
||||
}
|
||||
bfreeSafe(B_L, buf);
|
||||
va_end(args);
|
||||
#endif
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/*
|
||||
* Trace log. Customize this function to log trace output
|
||||
*/
|
||||
|
||||
void traceRaw(char_t *buf)
|
||||
{
|
||||
if (traceHandler) {
|
||||
traceHandler(0, buf);
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/*
|
||||
* Replace the default trace handler. Return a pointer to the old handler.
|
||||
*/
|
||||
|
||||
void (*traceSetHandler(void (*function)(int level, char_t *buf)))
|
||||
(int level, char *buf)
|
||||
{
|
||||
void (*oldHandler)(int level, char_t *buf);
|
||||
|
||||
oldHandler = traceHandler;
|
||||
if (function) {
|
||||
traceHandler = function;
|
||||
}
|
||||
return oldHandler;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
@@ -197,4 +255,27 @@ char_t *stritoa(int n, char_t *string, int width)
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/*
|
||||
* Stubs
|
||||
*/
|
||||
|
||||
char_t *basicGetProduct()
|
||||
{
|
||||
return T("uemf");
|
||||
}
|
||||
|
||||
char_t *basicGetAddress()
|
||||
{
|
||||
return T("localhost");
|
||||
}
|
||||
|
||||
int errorOpen(char_t *pname)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void errorClose()
|
||||
{
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
1415
c/src/libnetworking/rtems_webserver/um.c
Normal file
1415
c/src/libnetworking/rtems_webserver/um.c
Normal file
File diff suppressed because it is too large
Load Diff
184
c/src/libnetworking/rtems_webserver/um.h
Normal file
184
c/src/libnetworking/rtems_webserver/um.h
Normal file
@@ -0,0 +1,184 @@
|
||||
/*
|
||||
* um.h -- GoAhead User Management public header
|
||||
*
|
||||
* Copyright (c) GoAhead Software Inc., 1992-2000. All Rights Reserved.
|
||||
*
|
||||
* See the file "license.txt" for information on usage and redistribution
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#ifndef _h_UM
|
||||
#define _h_UM 1
|
||||
|
||||
/******************************** Description *********************************/
|
||||
|
||||
/*
|
||||
* GoAhead User Management header. This defines the User Management
|
||||
* public APIs. Include this header for files that contain access to
|
||||
* user inquiry or management.
|
||||
*/
|
||||
|
||||
/********************************* Includes ***********************************/
|
||||
|
||||
#if ! UEMF
|
||||
#include "basic/basic.h"
|
||||
#include "emf/emf.h"
|
||||
#else
|
||||
#include "uemf.h"
|
||||
#endif
|
||||
|
||||
/********************************** Defines ***********************************/
|
||||
|
||||
/*
|
||||
* Error Return Flags
|
||||
*/
|
||||
#define UM_OK 0
|
||||
#define UM_ERR_GENERAL -1
|
||||
#define UM_ERR_NOT_FOUND -2
|
||||
#define UM_ERR_PROTECTED -3
|
||||
#define UM_ERR_DUPLICATE -4
|
||||
#define UM_ERR_IN_USE -5
|
||||
#define UM_ERR_BAD_NAME -6
|
||||
#define UM_ERR_BAD_PASSWORD -7
|
||||
|
||||
/*
|
||||
* Privilege Masks
|
||||
*/
|
||||
#define PRIV_NONE 0x00
|
||||
#define PRIV_READ 0x01
|
||||
#define PRIV_WRITE 0x02
|
||||
#define PRIV_ADMIN 0x04
|
||||
|
||||
/*
|
||||
* User classes
|
||||
*/
|
||||
typedef short bool_t;
|
||||
|
||||
#ifndef TRUE
|
||||
#define TRUE 1
|
||||
#endif
|
||||
|
||||
#ifndef FALSE
|
||||
#define FALSE 0
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
AM_NONE = 0,
|
||||
AM_FULL,
|
||||
AM_BASIC,
|
||||
AM_DIGEST,
|
||||
AM_INVALID
|
||||
} accessMeth_t;
|
||||
|
||||
/********************************** Prototypes ********************************/
|
||||
|
||||
/*
|
||||
* umOpen() must be called before accessing User Management functions
|
||||
*/
|
||||
extern int umOpen();
|
||||
|
||||
/*
|
||||
* umClose() should be called before shutdown to free memory
|
||||
*/
|
||||
extern void umClose();
|
||||
|
||||
/*
|
||||
* umCommit() persists the user management database
|
||||
*/
|
||||
extern int umCommit(char_t *filename);
|
||||
|
||||
/*
|
||||
* umRestore() loads the user management database
|
||||
*/
|
||||
extern int umRestore(char_t *filename);
|
||||
|
||||
/*
|
||||
* umUser functions use a user ID for a key
|
||||
*/
|
||||
extern int umAddUser(char_t *user, char_t *password,
|
||||
char_t *group, bool_t protect, bool_t disabled);
|
||||
|
||||
extern int umDeleteUser(char_t *user);
|
||||
|
||||
extern char_t *umGetFirstUser();
|
||||
extern char_t *umGetNextUser(char_t *lastUser);
|
||||
|
||||
extern bool_t umUserExists(char_t *user);
|
||||
|
||||
extern char_t *umGetUserPassword(char_t *user);
|
||||
extern int umSetUserPassword(char_t *user, char_t *password);
|
||||
|
||||
extern char_t *umGetUserGroup(char_t *user);
|
||||
extern int umSetUserGroup(char_t *user, char_t *password);
|
||||
|
||||
extern bool_t umGetUserEnabled(char_t *user);
|
||||
extern int umSetUserEnabled(char_t *user, bool_t enabled);
|
||||
|
||||
extern bool_t umGetUserProtected(char_t *user);
|
||||
extern int umSetUserProtected(char_t *user, bool_t protect);
|
||||
|
||||
/*
|
||||
* umGroup functions use a group name for a key
|
||||
*/
|
||||
extern int umAddGroup(char_t *group, short privilege,
|
||||
accessMeth_t am, bool_t protect, bool_t disabled);
|
||||
|
||||
extern int umDeleteGroup(char_t *group);
|
||||
|
||||
extern char_t *umGetFirstGroup();
|
||||
extern char_t *umGetNextGroup(char_t *lastUser);
|
||||
|
||||
extern bool_t umGroupExists(char_t *group);
|
||||
extern bool_t umGetGroupInUse(char_t *group);
|
||||
|
||||
extern accessMeth_t umGetGroupAccessMethod(char_t *group);
|
||||
extern int umSetGroupAccessMethod(char_t *group, accessMeth_t am);
|
||||
|
||||
extern bool_t umGetGroupEnabled(char_t *group);
|
||||
extern int umSetGroupEnabled(char_t *group, bool_t enabled);
|
||||
|
||||
extern short umGetGroupPrivilege(char_t *group);
|
||||
extern int umSetGroupPrivilege(char_t *group, short privileges);
|
||||
|
||||
extern bool_t umGetGroupProtected(char_t *group);
|
||||
extern int umSetGroupProtected(char_t *group, bool_t protect);
|
||||
|
||||
/*
|
||||
* umAccessLimit functions use a URL as a key
|
||||
*/
|
||||
extern int umAddAccessLimit(char_t *url, accessMeth_t am,
|
||||
short secure, char_t *group);
|
||||
|
||||
extern int umDeleteAccessLimit(char_t *url);
|
||||
|
||||
extern char_t *umGetFirstAccessLimit();
|
||||
extern char_t *umGetNextAccessLimit(char_t *lastUser);
|
||||
|
||||
/*
|
||||
* Returns the name of an ancestor access limit if
|
||||
*/
|
||||
extern char_t *umGetAccessLimit(char_t *url);
|
||||
|
||||
extern bool_t umAccessLimitExists(char_t *url);
|
||||
|
||||
extern accessMeth_t umGetAccessLimitMethod(char_t *url);
|
||||
extern int umSetAccessLimitMethod(char_t *url, accessMeth_t am);
|
||||
|
||||
extern short umGetAccessLimitSecure(char_t *url);
|
||||
extern int umSetAccessLimitSecure(char_t *url, short secure);
|
||||
|
||||
extern char_t *umGetAccessLimitGroup(char_t *url);
|
||||
extern int umSetAccessLimitGroup(char_t *url, char_t *group);
|
||||
|
||||
/*
|
||||
* Convenience Functions
|
||||
*/
|
||||
|
||||
extern accessMeth_t umGetAccessMethodForURL(char_t *url);
|
||||
extern bool_t umUserCanAccessURL(char_t *user, char_t *url);
|
||||
|
||||
#endif /* _h_UM */
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* url.c -- Parse URLs
|
||||
*
|
||||
* Copyright (c) Go Ahead Software Inc., 1995-1999. All Rights Reserved.
|
||||
* Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved.
|
||||
*
|
||||
* See the file "license.txt" for usage and redistribution license requirements
|
||||
*/
|
||||
@@ -83,7 +83,7 @@ int websUrlParse(char_t *url, char_t **pbuf, char_t **phost, char_t **ppath,
|
||||
|
||||
ulen = gstrlen(url);
|
||||
/*
|
||||
* We allocate enough to store a separate hostname and port number fields.
|
||||
* We allocate enough to store separate hostname and port number fields.
|
||||
* As there are 3 strings in the one buffer, we need room for 3 null chars.
|
||||
* We allocate MAX_PORT_LEN char_t's for the port number.
|
||||
*/
|
||||
@@ -146,16 +146,23 @@ int websUrlParse(char_t *url, char_t **pbuf, char_t **phost, char_t **ppath,
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse the tag and the query
|
||||
* Parse the query string
|
||||
*/
|
||||
if ((cp = gstrchr(tok, '#')) != NULL) {
|
||||
*cp++ = '\0';
|
||||
path = tok;
|
||||
tok = cp;
|
||||
}
|
||||
if ((cp = gstrchr(tok, '?')) != NULL) {
|
||||
*cp++ = '\0';
|
||||
query = cp;
|
||||
path = tok;
|
||||
tok = query;
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse the fragment identifier
|
||||
*/
|
||||
if ((cp = gstrchr(tok, '#')) != NULL) {
|
||||
*cp++ = '\0';
|
||||
if (*query == 0) {
|
||||
path = tok;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* webcomp -- Compile web pages into C source
|
||||
*
|
||||
* Copyright (c) Go Ahead Software Inc., 1995-1999. All Rights Reserved.
|
||||
* Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved.
|
||||
*
|
||||
* See the file "license.txt" for usage and redistribution license requirements
|
||||
*/
|
||||
@@ -71,10 +71,10 @@ static int compile(char_t *fileList, char_t *prefix)
|
||||
FILE *lp;
|
||||
time_t now;
|
||||
char_t file[FNAMESIZE];
|
||||
char_t *cp;
|
||||
char_t *cp, *sl;
|
||||
char buf[512];
|
||||
char *p;
|
||||
int j, i, len, fd, nFile;
|
||||
unsigned char *p;
|
||||
int j, i, len, fd, nFile;
|
||||
|
||||
/*
|
||||
* Open list of files
|
||||
@@ -87,7 +87,7 @@ static int compile(char_t *fileList, char_t *prefix)
|
||||
time(&now);
|
||||
fprintf(stdout, "/*\n * webrom.c -- Compiled Web Pages\n *\n");
|
||||
fprintf(stdout, " * Compiled by GoAhead WebCompile: %s */\n\n",
|
||||
ctime(&now));
|
||||
gctime(&now));
|
||||
fprintf(stdout, "#include \"wsIntrn.h\"\n\n");
|
||||
fprintf(stdout, "#ifndef WEBS_PAGE_ROM\n");
|
||||
fprintf(stdout, "websRomPageIndexType websRomPageIndex[] = {\n");
|
||||
@@ -102,6 +102,9 @@ static int compile(char_t *fileList, char_t *prefix)
|
||||
if ((p = strchr(file, '\n')) || (p = strchr(file, '\r'))) {
|
||||
*p = '\0';
|
||||
}
|
||||
if (*file == '\0') {
|
||||
continue;
|
||||
}
|
||||
if (gstat(file, &sbuf) == 0 && sbuf.st_mode & S_IFDIR) {
|
||||
continue;
|
||||
}
|
||||
@@ -109,7 +112,7 @@ static int compile(char_t *fileList, char_t *prefix)
|
||||
fprintf(stderr, "Can't open file %s\n", file);
|
||||
return -1;
|
||||
}
|
||||
fprintf(stdout, "static unsigned char page_%d[] = {\n", nFile);
|
||||
fprintf(stdout, "static const unsigned char page_%d[] = {\n", nFile);
|
||||
|
||||
while ((len = read(fd, buf, sizeof(buf))) > 0) {
|
||||
p = buf;
|
||||
@@ -143,6 +146,9 @@ static int compile(char_t *fileList, char_t *prefix)
|
||||
if ((p = strchr(file, '\n')) || (p = strchr(file, '\r'))) {
|
||||
*p = '\0';
|
||||
}
|
||||
if (*file == '\0') {
|
||||
continue;
|
||||
}
|
||||
/*
|
||||
* Remove the prefix and add a leading "/" when we print the path
|
||||
*/
|
||||
@@ -151,6 +157,9 @@ static int compile(char_t *fileList, char_t *prefix)
|
||||
} else {
|
||||
cp = file;
|
||||
}
|
||||
while((sl = strchr(file, '\\')) != NULL) {
|
||||
*sl = '/';
|
||||
}
|
||||
if (*cp == '/') {
|
||||
cp++;
|
||||
}
|
||||
@@ -159,8 +168,8 @@ static int compile(char_t *fileList, char_t *prefix)
|
||||
fprintf(stdout, " { T(\"/%s\"), 0, 0 },\n", cp);
|
||||
continue;
|
||||
}
|
||||
fprintf(stdout, " { T(\"/%s\"), page_%d, %ld },\n", cp, nFile,
|
||||
(long) sbuf.st_size);
|
||||
fprintf(stdout, " { T(\"/%s\"), page_%d, %d },\n", cp, nFile,
|
||||
sbuf.st_size);
|
||||
nFile++;
|
||||
}
|
||||
fclose(lp);
|
||||
|
||||
@@ -25,12 +25,22 @@
|
||||
|
||||
#include <rtems/error.h>
|
||||
|
||||
#ifdef WEBS_SSL_SUPPORT
|
||||
#include "websSSL.h"
|
||||
#endif
|
||||
|
||||
#ifdef USER_MANAGEMENT_SUPPORT
|
||||
#include "um.h"
|
||||
void formDefineUserMgmt(void);
|
||||
#endif
|
||||
|
||||
/*********************************** Locals ***********************************/
|
||||
/*
|
||||
* Change configuration here
|
||||
*/
|
||||
|
||||
static char_t *rootWeb = T("web"); /* Root web directory */
|
||||
extern const char *tftpServer;
|
||||
static char_t *rootWeb = T("goahead"); /* Root web directory */
|
||||
static char_t *password = T(""); /* Security password */
|
||||
static int port = 80; /* Server port */
|
||||
static int retries = 5; /* Server port retries */
|
||||
@@ -113,33 +123,47 @@ rtems_httpd_daemon()
|
||||
/*
|
||||
* Initialize the web server
|
||||
*/
|
||||
while (initWebs() < 0) {
|
||||
printf("\nUnable to initialize Web server !!\n"
|
||||
" Suspending the task. Resume to try again.\n");
|
||||
rtems_task_suspend( RTEMS_SELF);
|
||||
if (initWebs() < 0) {
|
||||
rtems_panic("Unable to initialize Web server !!\n");
|
||||
}
|
||||
|
||||
#ifdef WEBS_SSL_SUPPORT
|
||||
websSSLOpen();
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Basic event loop. SocketReady returns true when a socket is ready for
|
||||
* service. SocketSelect will block until an event occurs. SocketProcess
|
||||
* will actually do the servicing.
|
||||
*/
|
||||
while (!finished) {
|
||||
if (socketReady() || socketSelect()) {
|
||||
socketProcess();
|
||||
if (socketReady(-1) || socketSelect(-1, 2000)) {
|
||||
socketProcess(-1);
|
||||
}
|
||||
/*websCgiCleanup();*/
|
||||
emfSchedProcess();
|
||||
}
|
||||
|
||||
#ifdef WEBS_SSL_SUPPORT
|
||||
websSSLClose();
|
||||
#endif
|
||||
|
||||
#ifdef USER_MANAGEMENT_SUPPORT
|
||||
umClose();
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Close the socket module, report memory leaks and close the memory allocator
|
||||
*/
|
||||
websCloseServer();
|
||||
websDefaultClose();
|
||||
socketClose();
|
||||
symSubClose();
|
||||
#if B_STATS
|
||||
memLeaks();
|
||||
#endif
|
||||
bclose();
|
||||
rtems_task_delete( RTEMS_SELF );
|
||||
rtems_task_delete( RTEMS_SELF );
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
@@ -177,15 +201,14 @@ static int initWebs()
|
||||
memcpy((char *) &intaddr, (char *) hp->h_addr_list[0],
|
||||
(size_t) hp->h_length);
|
||||
|
||||
#if 0
|
||||
/*
|
||||
* Set ../web as the root web. Modify this to suit your needs
|
||||
* Set /TFTP/x.y.z.w/goahead as the root web. Modify to suit your needs
|
||||
*/
|
||||
getcwd(dir, sizeof(dir));
|
||||
if ((cp = strrchr(dir, '/'))) {
|
||||
*cp = '\0';
|
||||
}
|
||||
sprintf(webdir, "%s/%s", dir, rootWeb);
|
||||
|
||||
sprintf(webdir, "/TFTP/%s/%s", tftpServer, rootWeb);
|
||||
#else
|
||||
sprintf(webdir, "/");
|
||||
#endif
|
||||
/*
|
||||
* Configure the web server options before opening the web server
|
||||
*/
|
||||
@@ -198,7 +221,11 @@ static int initWebs()
|
||||
/*
|
||||
* Configure the web server options before opening the web server
|
||||
*/
|
||||
#if 0
|
||||
websSetDefaultPage(T("default.asp"));
|
||||
#else
|
||||
websSetDefaultPage(T("index.html"));
|
||||
#endif
|
||||
websSetPassword(password);
|
||||
|
||||
/*
|
||||
@@ -380,7 +407,11 @@ static int websHomePageHandler(webs_t wp, char_t *urlPrefix, char_t *webDir,
|
||||
* If the empty or "/" URL is invoked, redirect default URLs to the home page
|
||||
*/
|
||||
if (*url == '\0' || gstrcmp(url, T("/")) == 0) {
|
||||
#if 0
|
||||
websRedirect(wp, T("home.asp"));
|
||||
#else
|
||||
websRedirect(wp, T("index.html"));
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
@@ -391,12 +422,14 @@ static int websHomePageHandler(webs_t wp, char_t *urlPrefix, char_t *webDir,
|
||||
#if B_STATS
|
||||
static void memLeaks()
|
||||
{
|
||||
int fd;
|
||||
int fd=1;
|
||||
|
||||
if ((fd = gopen(T("leak.txt"), O_CREAT | O_TRUNC | O_WRONLY)) >= 0) {
|
||||
/* if ((fd = gopen(T("leak.txt"), O_CREAT | O_TRUNC | O_WRONLY)) >= 0) { */
|
||||
bstats(fd, printMemStats);
|
||||
/*
|
||||
close(fd);
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
@@ -416,4 +449,51 @@ static void printMemStats(int handle, char_t *fmt, ...)
|
||||
}
|
||||
#endif
|
||||
|
||||
/******************************************************************************/
|
||||
/*****************************************************************************/
|
||||
|
||||
/*****************************************************************************/
|
||||
/*
|
||||
* Default error handler. The developer should insert code to handle
|
||||
* error messages in the desired manner.
|
||||
*/
|
||||
|
||||
void defaultErrorHandler(int etype, char_t *msg)
|
||||
{
|
||||
#if 1
|
||||
write(1, msg, gstrlen(msg));
|
||||
#endif
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/*
|
||||
* Trace log. Customize this function to log trace output
|
||||
*/
|
||||
|
||||
void defaultTraceHandler(int level, char_t *buf)
|
||||
{
|
||||
/*
|
||||
* The following code would write all trace regardless of level
|
||||
* to stdout.
|
||||
*/
|
||||
#if 1
|
||||
if (buf) {
|
||||
write(1, buf, gstrlen(buf));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/*
|
||||
* Returns a pointer to an allocated qualified unique temporary file name.
|
||||
* This filename must eventually be deleted with bfree();
|
||||
*/
|
||||
|
||||
char_t *websGetCgiCommName()
|
||||
{
|
||||
char_t *pname1, *pname2;
|
||||
|
||||
pname1 = tempnam(NULL, T("cgi"));
|
||||
pname2 = bstrdup(B_L, pname1);
|
||||
free(pname1);
|
||||
return pname2;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Page.c -- Support for page retrieval.
|
||||
*
|
||||
* Copyright (c) Go Ahead Software Inc., 1995-1999. All Rights Reserved.
|
||||
* Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved.
|
||||
*
|
||||
* See the file "license.txt" for usage and redistribution license requirements
|
||||
*/
|
||||
@@ -41,6 +41,8 @@ int websPageOpen(webs_t wp, char_t *lpath, char_t *path, int mode, int perm)
|
||||
|
||||
void websPageClose(webs_t wp)
|
||||
{
|
||||
a_assert(websValid(wp));
|
||||
|
||||
#if WEBS_PAGE_ROM
|
||||
websRomPageClose(wp->docfd);
|
||||
#else
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
/*
|
||||
* webrom.c -- Compiled Web Pages
|
||||
*
|
||||
* Copyright (c) Go Ahead Software Inc., 1995-1999. All Rights Reserved.
|
||||
* Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved.
|
||||
*
|
||||
* See the file "license.txt" for usage and redistribution license requirements
|
||||
*/
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* webs.h -- Go Ahead Web public header
|
||||
* webs.h -- GoAhead Web public header
|
||||
*
|
||||
* Copyright (c) Go Ahead Software Inc., 1992-1999. All Rights Reserved.
|
||||
* Copyright (c) GoAhead Software Inc., 1992-2000. All Rights Reserved.
|
||||
*
|
||||
* See the file "license.txt" for information on usage and redistribution
|
||||
*/
|
||||
@@ -12,7 +12,7 @@
|
||||
/******************************** Description *********************************/
|
||||
|
||||
/*
|
||||
* Go Ahead Web Server header. This defines the Web public APIs.
|
||||
* GoAhead Web Server header. This defines the Web public APIs.
|
||||
* Include this header for files that contain ASP or Form procedures.
|
||||
* Include wsIntrn.h when creating URL handlers.
|
||||
*/
|
||||
@@ -20,8 +20,17 @@
|
||||
/********************************* Includes ***********************************/
|
||||
|
||||
#include "ej.h"
|
||||
#ifdef WEBS_SSL_SUPPORT
|
||||
#include "websSSL.h"
|
||||
#endif
|
||||
|
||||
/********************************** Defines ***********************************/
|
||||
/*
|
||||
* By license terms the server software name defined in the following line of
|
||||
* code must not be modified.
|
||||
*/
|
||||
#define WEBS_NAME T("GoAhead-Webs")
|
||||
#define WEBS_VERSION T("2.1")
|
||||
|
||||
#define WEBS_HEADER_BUFINC 512 /* Header buffer size */
|
||||
#define WEBS_ASP_BUFINC 512 /* Asp expansion increment */
|
||||
@@ -31,6 +40,9 @@
|
||||
#define WEBS_MAX_URL 4096 /* Maximum URL size for sanity */
|
||||
#define WEBS_SOCKET_BUFSIZ 256 /* Bytes read from socket */
|
||||
|
||||
#define WEBS_HTTP_PORT T("httpPort")
|
||||
#define CGI_BIN T("cgi-bin")
|
||||
|
||||
/*
|
||||
* Request flags. Also returned by websGetRequestFlags().
|
||||
*/
|
||||
@@ -48,6 +60,10 @@
|
||||
#define WEBS_FORM 0x800 /* Request is a form */
|
||||
#define WEBS_REQUEST_DONE 0x1000 /* Request complete */
|
||||
#define WEBS_POST_DATA 0x2000 /* Already appended post data */
|
||||
#define WEBS_CGI_REQUEST 0x4000 /* cgi-bin request */
|
||||
#define WEBS_SECURE 0x8000 /* connection uses SSL */
|
||||
#define WEBS_AUTH_BASIC 0x10000 /* Basic authentication request */
|
||||
#define WEBS_AUTH_DIGEST 0x20000 /* Digest authentication request */
|
||||
#define WEBS_HEADER_DONE 0x40000 /* Already output the HTTP header */
|
||||
|
||||
/*
|
||||
@@ -65,38 +81,56 @@ typedef struct websRec {
|
||||
sym_fd_t cgiVars; /* CGI standard variables */
|
||||
sym_fd_t cgiQuery; /* CGI decoded query string */
|
||||
time_t timestamp; /* Last transaction with browser */
|
||||
void* timeout; /* Timeout handle */
|
||||
int timeout; /* Timeout handle */
|
||||
char_t ipaddr[32]; /* Connecting ipaddress */
|
||||
char_t type[64]; /* Mime type */
|
||||
char_t* dir; /* Directory containing the page */
|
||||
char_t* path; /* Path name without query */
|
||||
char_t* url; /* Full request url */
|
||||
char_t* host; /* Requested host */
|
||||
char_t* lpath; /* Cache local path name */
|
||||
char_t* query; /* Request query */
|
||||
char_t* decodedQuery; /* Decoded request query */
|
||||
char_t* password; /* Authorization password */
|
||||
char_t* userName; /* Authorization username */
|
||||
char_t* cookie; /* Cookie string */
|
||||
char_t* userAgent; /* User agent (browser) */
|
||||
char_t *dir; /* Directory containing the page */
|
||||
char_t *path; /* Path name without query */
|
||||
char_t *url; /* Full request url */
|
||||
char_t *host; /* Requested host */
|
||||
char_t *lpath; /* Cache local path name */
|
||||
char_t *query; /* Request query */
|
||||
char_t *decodedQuery; /* Decoded request query */
|
||||
char_t *authType; /* Authorization type (Basic/DAA) */
|
||||
char_t *password; /* Authorization password */
|
||||
char_t *userName; /* Authorization username */
|
||||
char_t *cookie; /* Cookie string */
|
||||
char_t *userAgent; /* User agent (browser) */
|
||||
char_t *protocol; /* Protocol (normally HTTP) */
|
||||
char_t *protoVersion; /* Protocol version */
|
||||
int sid; /* Socket id (handler) */
|
||||
int listenSid; /* Listen Socket id */
|
||||
int port; /* Request port number */
|
||||
int state; /* Current state */
|
||||
int flags; /* Current flags -- see above */
|
||||
int code; /* Request result code */
|
||||
int clen; /* Content length */
|
||||
int wid; /* Index into webs */
|
||||
char_t *cgiStdin; /* filename for CGI stdin */
|
||||
int docfd; /* Document file descriptor */
|
||||
int numbytes; /* Bytes to transfer to browser */
|
||||
int numbytes; /* Bytes to transfer to browser */
|
||||
int written; /* Bytes actually transferred */
|
||||
void (*writeSocket)(struct websRec *wp);
|
||||
#ifdef DIGEST_ACCESS_SUPPORT
|
||||
char_t *realm; /* usually the same as "host" from websRec */
|
||||
char_t *nonce; /* opaque-to-client string sent by server */
|
||||
char_t *digest; /* digest form of user password */
|
||||
char_t *uri; /* URI found in DAA header */
|
||||
char_t *opaque; /* opaque value passed from server */
|
||||
char_t *nc; /* nonce count */
|
||||
char_t *cnonce; /* check nonce */
|
||||
char_t *qop; /* quality operator */
|
||||
#endif
|
||||
#ifdef WEBS_SSL_SUPPORT
|
||||
websSSL_t *wsp; /* SSL data structure */
|
||||
#endif
|
||||
} websRec;
|
||||
|
||||
typedef websRec *webs_t;
|
||||
typedef websRec websType;
|
||||
|
||||
/******************************** Prototypes **********************************/
|
||||
|
||||
extern int websAccept(int sid, char *ipaddr, int port, int listenSid);
|
||||
extern int websAspDefine(char_t *name,
|
||||
int (*fn)(int ejid, webs_t wp, int argc, char_t **argv));
|
||||
extern int websAspRequest(webs_t wp, char_t *lpath);
|
||||
@@ -112,9 +146,11 @@ extern int websFormDefine(char_t *name, void (*fn)(webs_t wp,
|
||||
extern char_t *websGetDefaultDir();
|
||||
extern char_t *websGetDefaultPage();
|
||||
extern char_t *websGetHostUrl();
|
||||
extern char_t *websGetIpaddrUrl();
|
||||
extern char_t *websGetPassword();
|
||||
extern int websGetPort();
|
||||
extern char_t *websGetPublishDir(char_t *path, char_t **urlPrefix);
|
||||
extern char_t *websGetRealm();
|
||||
extern int websGetRequestBytes(webs_t wp);
|
||||
extern char_t *websGetRequestDir(webs_t wp);
|
||||
extern int websGetRequestFlags(webs_t wp);
|
||||
@@ -125,6 +161,7 @@ extern char_t *websGetRequestPassword(webs_t wp);
|
||||
extern char_t *websGetRequestType(webs_t wp);
|
||||
extern int websGetRequestWritten(webs_t wp);
|
||||
extern char_t *websGetVar(webs_t wp, char_t *var, char_t *def);
|
||||
extern int websCompareVar(webs_t wp, char_t *var, char_t *value);
|
||||
extern void websHeader(webs_t wp);
|
||||
extern int websOpenListen(int port, int retries);
|
||||
extern int websPageOpen(webs_t wp, char_t *lpath, char_t *path,
|
||||
@@ -142,6 +179,7 @@ extern void websSetEnv(webs_t wp);
|
||||
extern void websSetHost(char_t *host);
|
||||
extern void websSetIpaddr(char_t *ipaddr);
|
||||
extern void websSetPassword(char_t *password);
|
||||
extern void websSetRealm(char_t *realmName);
|
||||
extern void websSetRequestBytes(webs_t wp, int bytes);
|
||||
extern void websSetRequestFlags(webs_t wp, int flags);
|
||||
extern void websSetRequestLpath(webs_t wp, char_t *lpath);
|
||||
@@ -150,6 +188,7 @@ extern char_t *websGetRequestUserName(webs_t wp);
|
||||
extern void websSetRequestWritten(webs_t wp, int written);
|
||||
extern void websSetVar(webs_t wp, char_t *var, char_t *value);
|
||||
extern int websTestVar(webs_t wp, char_t *var);
|
||||
extern void websTimeoutCancel(webs_t wp);
|
||||
extern int websUrlHandlerDefine(char_t *urlPrefix, char_t *webDir,
|
||||
int arg, int (*fn)(webs_t wp, char_t *urlPrefix,
|
||||
char_t *webDir, int arg, char_t *url, char_t *path,
|
||||
@@ -164,10 +203,18 @@ extern int websUrlParse(char_t *url, char_t **buf, char_t **host,
|
||||
extern char_t *websUrlType(char_t *webs, char_t *buf, int charCnt);
|
||||
extern int websWrite(webs_t wp, char_t* fmt, ...);
|
||||
extern int websWriteBlock(webs_t wp, char_t *buf, int nChars);
|
||||
extern int websWriteBlockData(webs_t wp, char *buf, int nChars);
|
||||
extern int websWriteDataNonBlock(webs_t wp, char *buf, int nChars);
|
||||
extern int websValid(webs_t wp);
|
||||
extern int websValidateUrl(webs_t wp, char_t *path);
|
||||
extern int websCloseFileHandle(webs_t wp);
|
||||
extern void websMarkTime(webs_t wp);
|
||||
|
||||
/*
|
||||
* The following prototypes are used by the SSL patch found in websSSL.c
|
||||
*/
|
||||
extern int websAlloc(int sid);
|
||||
extern void websFree(webs_t wp);
|
||||
extern void websTimeout(void *arg, int id);
|
||||
extern void websReadEvent(webs_t wp);
|
||||
|
||||
/*
|
||||
* Prototypes for functions available when running as part of the
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* websuemf.c -- GoAhead Micro Embedded Management Framework
|
||||
*
|
||||
* Copyright (c) Go Ahead Software Inc., 1995-1999. All Rights Reserved.
|
||||
* Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved.
|
||||
*
|
||||
* See the file "license.txt" for usage and redistribution license requirements
|
||||
*/
|
||||
@@ -14,14 +14,32 @@
|
||||
|
||||
/*********************************** Includes *********************************/
|
||||
|
||||
#include "ejIntrn.h"
|
||||
#include "wsIntrn.h"
|
||||
|
||||
/*********************************** Defines **********************************/
|
||||
|
||||
/*
|
||||
* This structure stores scheduled events.
|
||||
*/
|
||||
typedef struct {
|
||||
void (*routine)(void *arg, int id);
|
||||
void *arg;
|
||||
time_t at;
|
||||
int schedid;
|
||||
} sched_t;
|
||||
|
||||
/*********************************** Locals ***********************************/
|
||||
|
||||
static sched_t **sched;
|
||||
static int schedMax;
|
||||
|
||||
/************************************* Code ***********************************/
|
||||
/*
|
||||
* Evaluate a script
|
||||
*/
|
||||
|
||||
int scriptEval(int engine, char_t* cmd, char_t** result, int chan)
|
||||
int scriptEval(int engine, char_t *cmd, char_t **result, int chan)
|
||||
{
|
||||
int ejid;
|
||||
|
||||
@@ -37,3 +55,156 @@ int scriptEval(int engine, char_t* cmd, char_t** result, int chan)
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/*
|
||||
* Compare strings, ignoring case: normal strcmp return codes.
|
||||
*
|
||||
* WARNING: It is not good form to increment or decrement pointers inside a
|
||||
* "call" to tolower et al. These can be MACROS, and have undesired side
|
||||
* effects.
|
||||
*/
|
||||
|
||||
int strcmpci(char_t *s1, char_t *s2)
|
||||
{
|
||||
int rc;
|
||||
|
||||
a_assert(s1 && s2);
|
||||
if (s1 == NULL || s2 == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (s1 == s2) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
do {
|
||||
rc = gtolower(*s1) - gtolower(*s2);
|
||||
if (*s1 == '\0') {
|
||||
break;
|
||||
}
|
||||
s1++;
|
||||
s2++;
|
||||
} while (rc == 0);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/*
|
||||
* This function is called when a scheduled process time has come.
|
||||
*/
|
||||
|
||||
void TimerProc(int schedid)
|
||||
{
|
||||
sched_t *s;
|
||||
|
||||
a_assert(0 <= schedid && schedid < schedMax);
|
||||
s = sched[schedid];
|
||||
a_assert(s);
|
||||
|
||||
(s->routine)(s->arg, s->schedid);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/*
|
||||
* Schedule an event in delay milliseconds time. We will use 1 second
|
||||
* granularity for webServer.
|
||||
*/
|
||||
|
||||
int emfSchedCallback(int delay, emfSchedProc *proc, void *arg)
|
||||
{
|
||||
sched_t *s;
|
||||
int schedid;
|
||||
|
||||
if ((schedid = hAllocEntry((void***) &sched, &schedMax,
|
||||
sizeof(sched_t))) < 0) {
|
||||
return -1;
|
||||
}
|
||||
s = sched[schedid];
|
||||
s->routine = proc;
|
||||
s->arg = arg;
|
||||
s->schedid = schedid;
|
||||
|
||||
/*
|
||||
* Round the delay up to seconds.
|
||||
*/
|
||||
s->at = ((delay + 500) / 1000) + time(0);
|
||||
|
||||
return schedid;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/*
|
||||
* Reschedule to a new delay.
|
||||
*/
|
||||
|
||||
void emfReschedCallback(int schedid, int delay)
|
||||
{
|
||||
sched_t *s;
|
||||
|
||||
if (sched == NULL || schedid == -1 || schedid >= schedMax ||
|
||||
(s = sched[schedid]) == NULL) {
|
||||
return;
|
||||
}
|
||||
s->at = ((delay + 500) / 1000) + time(0);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
void emfUnschedCallback(int schedid)
|
||||
{
|
||||
sched_t *s;
|
||||
|
||||
if (sched == NULL || schedid == -1 || schedid >= schedMax ||
|
||||
(s = sched[schedid]) == NULL) {
|
||||
return;
|
||||
}
|
||||
bfree(B_L, s);
|
||||
schedMax = hFree((void***) &sched, schedid);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/*
|
||||
* Take the tasks off the queue in a round robin fashion.
|
||||
*/
|
||||
|
||||
void emfSchedProcess()
|
||||
{
|
||||
sched_t *s;
|
||||
int schedid;
|
||||
static int next = 0;
|
||||
|
||||
/*
|
||||
* If schedMax is 0, there are no tasks scheduled, so just return.
|
||||
*/
|
||||
if (schedMax <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* If next >= schedMax, the schedule queue was reduced in our absence
|
||||
* so reset next to 0 to start from the begining of the queue again.
|
||||
*/
|
||||
if (next >= schedMax) {
|
||||
next = 0;
|
||||
}
|
||||
|
||||
schedid = next;
|
||||
for (;;) {
|
||||
if ((s = sched[schedid]) != NULL && (int)s->at <= (int)time(0)) {
|
||||
TimerProc(schedid);
|
||||
next = schedid + 1;
|
||||
return;
|
||||
}
|
||||
if (++schedid >= schedMax) {
|
||||
schedid = 0;
|
||||
}
|
||||
if (schedid == next) {
|
||||
/*
|
||||
* We've gone all the way through the queue without finding
|
||||
* anything to do so just return.
|
||||
*/
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
/*
|
||||
* wsIntrn.h -- Internal Go Ahead Web server header
|
||||
* wsIntrn.h -- Internal GoAhead Web server header
|
||||
*
|
||||
* Copyright (c) Go Ahead Software Inc., 1992-1999. All Rights Reserved.
|
||||
* Copyright (c) GoAhead Software Inc., 1992-2000. All Rights Reserved.
|
||||
*
|
||||
* See the file "license.txt" for information on usage and redistribution
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _h_WEBS_INTERNAL
|
||||
#define _h_WEBS_INTERNAL 1
|
||||
|
||||
/******************************** Description *********************************/
|
||||
|
||||
/*
|
||||
* Internal Go Ahead Web Server header. This defines the Web private APIs
|
||||
* Internal GoAhead Web Server header. This defines the Web private APIs
|
||||
* Include this header when you want to create URL handlers.
|
||||
*/
|
||||
|
||||
@@ -33,7 +33,6 @@
|
||||
* #define WEBS_PROXY_SUPPORT 1
|
||||
*
|
||||
* Define this to support reading pages from ROM
|
||||
* Note: this is not yet fully implemented.
|
||||
* #define WEBS_PAGE_ROM 1
|
||||
*
|
||||
* Define this to enable memory allocation and stack usage tracking
|
||||
@@ -64,6 +63,13 @@
|
||||
#include <sys/stat.h>
|
||||
#endif
|
||||
|
||||
#if SCOV5
|
||||
#include <fcntl.h>
|
||||
#include <sys/stat.h>
|
||||
#include <signal.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#if LYNX
|
||||
#include <fcntl.h>
|
||||
#include <sys/stat.h>
|
||||
@@ -91,17 +97,24 @@
|
||||
#include <sys/stat.h>
|
||||
#endif
|
||||
|
||||
#if VXW486
|
||||
#if VXWORKS
|
||||
#include <vxWorks.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/stat.h>
|
||||
#endif
|
||||
|
||||
#if SOLARIS
|
||||
#include <macros.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/stat.h>
|
||||
#endif
|
||||
|
||||
#if UEMF
|
||||
#include "uemf.h"
|
||||
#include "ej.h"
|
||||
#include "ejIntrn.h"
|
||||
#else
|
||||
#include "emf/emfInternal.h"
|
||||
#include "ej/ejIntrn.h"
|
||||
#endif
|
||||
|
||||
#include "webs.h"
|
||||
@@ -110,16 +123,18 @@
|
||||
/*
|
||||
* Read handler flags and state
|
||||
*/
|
||||
#define WEBS_BEGIN 0x1 /* Beginning state */
|
||||
#define WEBS_HEADER 0x2 /* Ready to read first line */
|
||||
#define WEBS_POST 0x4 /* POST without content */
|
||||
#define WEBS_POST_CLEN 0x8 /* Ready to read content for POST */
|
||||
#define WEBS_PROCESSING 0x10 /* Processing request */
|
||||
#define WEBS_KEEP_TIMEOUT 15000 /* Keep-alive timeout (15 secs) */
|
||||
#define WEBS_TIMEOUT 60000 /* General request timeout (60) */
|
||||
#define WEBS_BEGIN 0x1 /* Beginning state */
|
||||
#define WEBS_HEADER 0x2 /* Ready to read first line */
|
||||
#define WEBS_POST 0x4 /* POST without content */
|
||||
#define WEBS_POST_CLEN 0x8 /* Ready to read content for POST */
|
||||
#define WEBS_PROCESSING 0x10 /* Processing request */
|
||||
#define WEBS_KEEP_TIMEOUT 15000 /* Keep-alive timeout (15 secs) */
|
||||
#define WEBS_TIMEOUT 60000 /* General request timeout (60) */
|
||||
|
||||
#define PAGE_READ_BUFSIZE 512 /* bytes read from page files */
|
||||
#define MAX_PORT_LEN 10 /* max digits in port number */
|
||||
#define PAGE_READ_BUFSIZE 512 /* bytes read from page files */
|
||||
#define MAX_PORT_LEN 10 /* max digits in port number */
|
||||
#define WEBS_SYM_INIT 64 /* initial # of sym table entries */
|
||||
#define WEBS_VERSION_STR T("2.1.3") /* version of web server s/w */
|
||||
|
||||
/*
|
||||
* URL handler structure. Stores the leading URL path and the handler
|
||||
@@ -150,6 +165,7 @@ typedef struct {
|
||||
long localHits;
|
||||
long remoteHits;
|
||||
long formHits;
|
||||
long cgiHits;
|
||||
long handlerHits;
|
||||
} websStatsType;
|
||||
|
||||
@@ -185,7 +201,7 @@ typedef struct {
|
||||
*/
|
||||
typedef struct {
|
||||
char_t *path; /* Web page URL path */
|
||||
unsigned char *page; /* Web page data */
|
||||
const unsigned char *page; /* Web page data */
|
||||
int size; /* Size of web page in bytes */
|
||||
int pos; /* Current read position */
|
||||
} websRomPageIndexType;
|
||||
@@ -209,6 +225,7 @@ extern int websMax; /* List size */
|
||||
extern char_t websHost[64]; /* Name of this host */
|
||||
extern char_t websIpaddr[64]; /* IP address of this host */
|
||||
extern char_t *websHostUrl; /* URL for this host */
|
||||
extern char_t *websIpaddrUrl; /* URL for this host */
|
||||
extern int websPort; /* Port number */
|
||||
|
||||
/******************************** Prototypes **********************************/
|
||||
@@ -224,12 +241,21 @@ extern int websDefaultHandler(webs_t wp, char_t *urlPrefix,
|
||||
char_t *query);
|
||||
extern int websFormHandler(webs_t wp, char_t *urlPrefix, char_t *webDir,
|
||||
int arg, char_t *url, char_t *path, char_t *query);
|
||||
extern int websCgiHandler(webs_t wp, char_t *urlPrefix, char_t *webDir,
|
||||
int arg, char_t *url, char_t *path, char_t *query);
|
||||
extern void websCgiCleanup();
|
||||
extern int websCheckCgiProc(int handle);
|
||||
extern char_t *websGetCgiCommName();
|
||||
|
||||
extern int websLaunchCgiProc(char_t *cgiPath, char_t **argp,
|
||||
char_t **envp, char_t *stdIn, char_t *stdOut);
|
||||
extern int websOpen(int sid);
|
||||
extern void websResponse(webs_t wp, int code, char_t *msg,
|
||||
char_t *redirect);
|
||||
extern int websJavaScriptEval(webs_t wp, char_t *script);
|
||||
extern int websPageReadData(webs_t wp, char *buf, int nBytes);
|
||||
extern int websPageOpen(webs_t wp, char_t *lpath, char_t *path, int mode, int perm);
|
||||
extern int websPageOpen(webs_t wp, char_t *lpath, char_t *path, int mode,
|
||||
int perm);
|
||||
extern void websPageClose(webs_t wp);
|
||||
extern void websPageSeek(webs_t wp, long offset);
|
||||
extern int websPageStat(webs_t wp, char_t *lpath, char_t *path,
|
||||
@@ -253,6 +279,8 @@ extern int websOpenServer(int port, int retries);
|
||||
extern void websCloseServer();
|
||||
extern char_t* websGetDateString(websStatType* sbuf);
|
||||
|
||||
extern int strcmpci(char_t* s1, char_t* s2);
|
||||
|
||||
/*
|
||||
* Prototypes for functions available when running as part of the
|
||||
* GoAhead Embedded Management Framework (EMF)
|
||||
@@ -263,6 +291,11 @@ extern void websEmfClose();
|
||||
extern void websSetEmfEnvironment(webs_t wp);
|
||||
#endif
|
||||
|
||||
#if CE
|
||||
extern int writeUniToAsc(int fid, void *buf, unsigned int len);
|
||||
extern int readAscToUni(int fid, void **buf, unsigned int len);
|
||||
#endif
|
||||
|
||||
#endif /* _h_WEBS_INTERNAL */
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
Reference in New Issue
Block a user