diff options
author | Ralf Corsepius <ralf.corsepius@rtems.org> | 2010-06-09 05:46:03 +0000 |
---|---|---|
committer | Ralf Corsepius <ralf.corsepius@rtems.org> | 2010-06-09 05:46:03 +0000 |
commit | 44b7bcd59c6042aecef864cd45bc79508ff67d71 (patch) | |
tree | 14c9f01314d0c454030d0c87e9d11e7e6f5f4f59 | |
parent | 2010-06-08 Sebastian Huber <sebastian.huber@embedded-brains.de> (diff) | |
download | rtems-44b7bcd59c6042aecef864cd45bc79508ff67d71.tar.bz2 |
Remove (discontinued).
Diffstat (limited to '')
50 files changed, 0 insertions, 23608 deletions
diff --git a/cpukit/httpd/.cvsignore b/cpukit/httpd/.cvsignore deleted file mode 100644 index 282522db03..0000000000 --- a/cpukit/httpd/.cvsignore +++ /dev/null @@ -1,2 +0,0 @@ -Makefile -Makefile.in diff --git a/cpukit/httpd/Makefile.am b/cpukit/httpd/Makefile.am deleted file mode 100644 index 94e3d60019..0000000000 --- a/cpukit/httpd/Makefile.am +++ /dev/null @@ -1,33 +0,0 @@ -## -## $Id$ -## - -## DEPRECATED, don't use. - -include $(top_srcdir)/automake/compile.am - -AM_CPPFLAGS += -DWEBS -DUEMF - -if LIBHTTPD -## Always install this header file. Both webservers use it. -include_HEADERS = rtems_webserver.h - -if HAS_PTHREADS -include_goaheaddir = $(includedir)/goahead - -include_goahead_HEADERS = ej.h ejIntrn.h emfdb.h md5.h uemf.h um.h webs.h \ - wsIntrn.h - -project_lib_LIBRARIES = libhttpd.a -libhttpd_a_SOURCES = asp.c balloc.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 sock.c socket.c sym.c uemf.c um.c url.c value.c wbase64.c \ - webrom.c webs.c websuemf.c webmain.c -libhttpd_a_CPPFLAGS = $(AM_CPPFLAGS) -endif -endif - -EXTRA_DIST = webcomp.c webpage.c - -include $(srcdir)/preinstall.am -include $(top_srcdir)/automake/local.am diff --git a/cpukit/httpd/NOTES b/cpukit/httpd/NOTES deleted file mode 100644 index e2ef07eb34..0000000000 --- a/cpukit/httpd/NOTES +++ /dev/null @@ -1,36 +0,0 @@ -# -# $Id$ -# - -Notes on merging GoAhead Webs 2.1.4. 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. - -Porting -======= - - added rtems complier flags to uemf.h and misc.c - - following source files are distributed with the web server - but not currently used by RTEMS - [cgi.c, sockGen.c, umui.c, websSSL.c, websda.c] - -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 - diff --git a/cpukit/httpd/asp.c b/cpukit/httpd/asp.c deleted file mode 100644 index b31236fbfe..0000000000 --- a/cpukit/httpd/asp.c +++ /dev/null @@ -1,321 +0,0 @@ -/* - * asp.c -- Active Server Page Support - * - * Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved. - * - * See the file "license.txt" for usage and redistribution license requirements - * - * $Id$ - */ - -/******************************** Description *********************************/ - -/* - * The ASP module processes ASP pages and executes embedded scripts. It - * support an open scripting architecture with in-built support for - * Ejscript(TM). - */ - -/********************************* Includes ***********************************/ - -#include "wsIntrn.h" - -/********************************** Locals ************************************/ - -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 *skipWhite(char_t *s); - -/************************************* Code ***********************************/ -/* - * Create script spaces and commands - */ - -int websAspOpen(void) -{ - if (++aspOpenCount == 1) { -/* - * Create the table for ASP functions - */ - websAspFunctions = symOpen(WEBS_SYM_INIT * 2); - -/* - * Create standard ASP commands - */ - websAspDefine(T("write"), websAspWrite); - } - return 0; -} - -/************************************* Code ***********************************/ -/* - * Close Asp symbol table. - */ - -void websAspClose(void) -{ - if (--aspOpenCount <= 0) { - if (websAspFunctions != -1) { - symClose(websAspFunctions); - websAspFunctions = -1; - } - } -} - -/******************************************************************************/ -/* - * Process ASP requests and expand all scripting commands. We read the - * entire ASP page into memory and then process. If you have really big - * documents, it is better to make them plain HTML files rather than ASPs. - */ - -int websAspRequest(webs_t wp, char_t *lpath) -{ - websStatType sbuf; - char *rbuf; - char_t *token, *lang, *result, *path, *ep, *cp, *buf, *nextp; - char_t *last; - int rc, engine, len, ejid; - - a_assert(websValid(wp)); - a_assert(lpath && *lpath); - - rc = -1; - buf = NULL; - rbuf = NULL; - engine = EMF_SCRIPT_EJSCRIPT; - wp->flags |= WEBS_HEADER_DONE; - path = websGetRequestPath(wp); - -/* - * Create Ejscript instance in case it is needed - */ - ejid = ejOpenEngine(wp->cgiVars, websAspFunctions); - if (ejid < 0) { - websError(wp, 200, T("Can't create Ejscript engine")); - goto done; - } - ejSetUserHandle(ejid, (int) wp); - - if (websPageStat(wp, lpath, path, &sbuf) < 0) { - websError(wp, 200, T("Can't stat %s"), lpath); - goto done; - } - -/* - * Create a buffer to hold the ASP file in-memory - */ - len = sbuf.size * sizeof(char); - if ((rbuf = balloc(B_L, len + 1)) == NULL) { - websError(wp, 200, T("Can't get memory")); - goto done; - } - rbuf[len] = '\0'; - - if (websPageReadData(wp, rbuf, len) != len) { - websError(wp, 200, T("Cant read %s"), lpath); - goto done; - } - websPageClose(wp); - -/* - * Convert to UNICODE if necessary. - */ - if ((buf = ballocAscToUni(rbuf, len)) == NULL) { - websError(wp, 200, T("Can't get memory")); - goto done; - } - -/* - * Scan for the next "<%" - */ - last = buf; - rc = 0; - while (rc == 0 && *last && ((nextp = gstrstr(last, T("<%"))) != NULL)) { - websWriteBlock(wp, last, (nextp - last)); - nextp = skipWhite(nextp + 2); - -/* - * Decode the language - */ - token = T("language"); - - if ((lang = strtokcmp(nextp, token)) != NULL) { - if ((cp = strtokcmp(lang, T("=javascript"))) != NULL) { - engine = EMF_SCRIPT_EJSCRIPT; - } else { - cp = nextp; - } - nextp = cp; - } - -/* - * Find tailing bracket and then evaluate the script - */ - if ((ep = gstrstr(nextp, T("%>"))) != NULL) { - - *ep = '\0'; - last = ep + 2; - nextp = skipWhite(nextp); -/* - * Handle backquoted newlines - */ - for (cp = nextp; *cp; ) { - if (*cp == '\\' && (cp[1] == '\r' || cp[1] == '\n')) { - *cp++ = ' '; - while (*cp == '\r' || *cp == '\n') { - *cp++ = ' '; - } - } else { - cp++; - } - } - -/* - * Now call the relevant script engine. Output is done directly - * by the ASP script procedure by calling websWrite() - */ - if (*nextp) { - result = NULL; - if (engine == EMF_SCRIPT_EJSCRIPT) { - rc = scriptEval(engine, nextp, &result, ejid); - } else { - rc = scriptEval(engine, nextp, &result, (int) wp); - } - if (rc < 0) { -/* - * On an error, discard all output accumulated so far - * and store the error in the result buffer. Be careful if the - * user has called websError() already. - */ - if (websValid(wp)) { - if (result) { - websWrite(wp, T("<h2><b>ASP Error: %s</b></h2>\n"), - result); - websWrite(wp, T("<pre>%s</pre>"), nextp); - bfree(B_L, result); - } else { - websWrite(wp, T("<h2><b>ASP Error</b></h2>\n%s\n"), - nextp); - } - websWrite(wp, T("</body></html>\n")); - rc = 0; - } - goto done; - } - } - - } else { - websError(wp, 200, T("Unterminated script in %s: \n"), lpath); - rc = -1; - goto done; - } - } -/* - * Output any trailing HTML page text - */ - if (last && *last && rc == 0) { - websWriteBlock(wp, last, gstrlen(last)); - } - rc = 0; - -/* - * Common exit and cleanup - */ -done: - if (websValid(wp)) { - websPageClose(wp); - if (ejid >= 0) { - ejCloseEngine(ejid); - } - } - bfreeSafe(B_L, buf); - bfreeSafe(B_L, rbuf); - return rc; -} - -/******************************************************************************/ -/* - * Define an ASP Ejscript function. Bind an ASP name to a C procedure. - */ - -int websAspDefine(char_t *name, - int (*fn)(int ejid, webs_t wp, int argc, char_t **argv)) -{ - return ejSetGlobalFunctionDirect(websAspFunctions, name, - (int (*)(int, void*, int, char_t**)) fn); -} - -/******************************************************************************/ -/* - * Asp write command. This implemements <% write("text"); %> command - */ - -int websAspWrite(int ejid, webs_t wp, int argc, char_t **argv) -{ - int i; - - a_assert(websValid(wp)); - - for (i = 0; i < argc; ) { - a_assert(argv); - if (websWriteBlock(wp, argv[i], gstrlen(argv[i])) < 0) { - return -1; - } - if (++i < argc) { - if (websWriteBlock(wp, T(" "), 2) < 0) { - return -1; - } - } - } - return 0; -} - -/******************************************************************************/ -/* - * strtokcmp -- Find s2 in s1. We skip leading white space in s1. - * Return a pointer to the location in s1 after s2 ends. - */ - -static char_t *strtokcmp(char_t *s1, char_t *s2) -{ - int len; - - s1 = skipWhite(s1); - len = gstrlen(s2); - for (len = gstrlen(s2); len > 0 && (tolower((unsigned char)*s1) == tolower((unsigned char)*s2)); len--) { - if (*s2 == '\0') { - return s1; - } - s1++; - s2++; - } - if (len == 0) { - return s1; - } - return NULL; -} - -/******************************************************************************/ -/* - * Skip white space - */ - -static char_t *skipWhite(char_t *s) -{ - a_assert(s); - - if (s == NULL) { - return s; - } - while (*s && gisspace((unsigned char)*s)) { - s++; - } - return s; -} - -/******************************************************************************/ diff --git a/cpukit/httpd/balloc.c b/cpukit/httpd/balloc.c deleted file mode 100644 index 49710ee9ec..0000000000 --- a/cpukit/httpd/balloc.c +++ /dev/null @@ -1,967 +0,0 @@ -/* - * balloc.c -- Block allocation module - * - * Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved. - * - * See the file "license.txt" for usage and redistribution license requirements - * - * $Id$ - */ - -/******************************** Description *********************************/ - -/* - * 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 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 - * of malloc, call bopen with flags set to B_USE_MALLOC (this is the default). - * It is recommended that bopen be called first thing in the application. - * If it is not, it will be called with default values on the first call to - * balloc(). Note that this code is not designed for multi-threading purposes - * and it depends on newly declared variables being initialized to zero. - */ - -/********************************* Includes ***********************************/ - -#define IN_BALLOC - -#ifdef UEMF - #include "uemf.h" -#else - #include "basic/basicInternal.h" -#endif - -#include <stdarg.h> -#include <stdlib.h> - -#ifndef NO_BALLOC -/********************************* Defines ************************************/ - -/* - * Define B_STATS if you wish to track memory block and stack usage - */ -#ifdef B_STATS -/* - * Optional statistics - */ - -typedef struct { - long alloc; /* Block allocation calls */ - long inuse; /* Blocks in use */ -} bStatsType; - -typedef struct { - char_t file[FNAMESIZE]; - long allocated; /* Bytes currently allocated */ - long count; /* Current block count */ - long times; /* Count of alloc attempts */ - long largest; /* largest allocated here */ - int q; -} bStatsFileType; - -/* - * This one is very expensive but great stats - */ -typedef struct { - void *ptr; /* Pointer to memory */ - bStatsFileType *who; /* Who allocated the memory */ -} bStatsBlkType; - -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 = 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 = 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 ************************************/ -/* - * bQhead blocks are created as the original memory allocation is freed up. - * See bfree. - */ -static bType *bQhead[B_MAX_CLASS]; /* Per class block q head */ -static char *bFreeBuf; /* Pointer to free memory */ -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 *****************************/ - -#ifdef B_STATS -static void bStatsAlloc(B_ARGS_DEC, void *ptr, int q, int size); -static void bStatsFree(B_ARGS_DEC, void *ptr, int q, int size); -static void bstatsWrite(int handle, char_t *fmt, ...); -static int bStatsFileSort(const void *cp1, const void *cp2); -#endif /* B_STATS */ - -#if (defined (B_FILL) || defined (B_VERIFY_CAUSES_SEVERE_OVERHEAD)) -static void bFillBlock(void *buf, int bufsize); -#endif - -#ifdef B_VERIFY_CAUSES_SEVERE_OVERHEAD -static void verifyUsedBlock(bType *bp, int q); -static void verifyFreeBlock(bType *bp, int q); -void verifyBallocSpace(); -#endif - -static int ballocGetSize(int size, int *q); - -/********************************** Code **************************************/ -/* - * Initialize the balloc module. bopen should be called the very first thing - * after the application starts and bclose should be called the last thing - * before exiting. If bopen is not called, it will be called on the first - * allocation with default values. "buf" points to memory to use of size - * "bufsize". If buf is NULL, memory is allocated using malloc. flags may - * be set to B_USE_MALLOC if using malloc is okay. This routine will allocate - * an initial buffer of size bufsize for use by the application. - */ - -int bopen(void *buf, int bufsize, int flags) -{ - bFlags = flags; - -#ifdef 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; - } -#ifdef B_STATS - bStatsMemMalloc += bufsize; -#endif - } else { - bFlags |= B_USER_BUF; - } - - bFreeSize = bFreeLeft = bufsize; - bFreeBuf = bFreeNext = buf; - memset(bQhead, 0, sizeof(bQhead)); -#if (defined (B_FILL) || defined (B_VERIFY_CAUSES_SEVERE_OVERHEAD)) - bFillBlock(buf, bufsize); -#endif -#ifdef B_STATS - bStackStart = &buf; -#endif -#ifdef B_VERIFY_CAUSES_SEVERE_OVERHEAD - verifyFreeBlock(buf, bufsize); -#endif - return 0; -} - -/******************************************************************************/ -/* - * Close down the balloc module and free all malloced memory. - */ - -void bclose(void) -{ -#ifdef B_VERIFY_CAUSES_SEVERE_OVERHEAD - verifyBallocSpace(); -#endif - if (--bopenCount <= 0 && !(bFlags & B_USER_BUF)) { - free(bFreeBuf); - bopenCount = 0; - } -} - -/******************************************************************************/ -/* - * Allocate a block of the requested size. First check the block - * queues for a suitable one. - */ - -void *balloc(B_ARGS_DEC, int size) -{ - bType *bp; - 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) { - return NULL; - } - } -#ifdef B_VERIFY_CAUSES_SEVERE_OVERHEAD - verifyBallocSpace(); -#endif - if (size < 0) { - return NULL; - } - -#ifdef BASTARD_TESTING - if (rand() == 0x7fff) { - return NULL; - } -#endif /* BASTARD_TESTING */ - - - memSize = ballocGetSize(size, &q); - - if (q >= B_MAX_CLASS) { -/* - * Size if bigger than the maximum class. Malloc if use has been okayed - */ - if (bFlags & B_USE_MALLOC) { -#ifdef B_STATS - bstats(0, NULL); -#endif -#ifdef IRIX - memSize = ROUNDUP4(memSize); -#endif - bp = (bType*) malloc(memSize); - if (bp == NULL) { - traceRaw(T("B: malloc failed\n")); - return NULL; - } -#ifdef B_STATS - bStatsMemMalloc += memSize; -#endif -#if (defined (B_FILL) || defined (B_VERIFY_CAUSES_SEVERE_OVERHEAD)) - bFillBlock(bp, memSize); -#endif - - } else { - traceRaw(T("B: malloc failed\n")); - return NULL; - } - -/* - * 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) { -/* - * Take first block off the relevant q if non-empty - */ - bQhead[q] = bp->u.next; -#ifdef B_VERIFY_CAUSES_SEVERE_OVERHEAD - verifyFreeBlock(bp, q); -#endif -#if (defined (B_FILL) || defined (B_VERIFY_CAUSES_SEVERE_OVERHEAD)) - bFillBlock(bp, memSize); -#endif - bp->u.size = memSize - sizeof(bType); - bp->flags = 0; - - } else { - if (bFreeLeft > memSize) { -/* - * The q was empty, and the free list has spare memory so - * create a new block out of the primary free block - */ - bp = (bType*) bFreeNext; -#ifdef B_VERIFY_CAUSES_SEVERE_OVERHEAD - verifyFreeBlock(bp, q); -#endif - bFreeNext += memSize; - bFreeLeft -= memSize; -#if (defined (B_FILL) || defined (B_VERIFY_CAUSES_SEVERE_OVERHEAD)) - bFillBlock(bp, memSize); -#endif - bp->u.size = memSize - sizeof(bType); - bp->flags = 0; - - } else if (bFlags & B_USE_MALLOC) { -#ifdef B_STATS - static int once = 0; - if (once++ == 0) { - bstats(0, NULL); - } -#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) { - traceRaw(T("B: malloc failed\n")); - return NULL; - } -#ifdef B_STATS - bStatsMemMalloc += memSize; -#endif -#if (defined (B_FILL) || defined (B_VERIFY_CAUSES_SEVERE_OVERHEAD)) - bFillBlock(bp, memSize); -#endif - bp->u.size = memSize - sizeof(bType); - bp->flags = B_MALLOCED; - - } else { - traceRaw(T("B: malloc failed\n")); - return NULL; - } - } - -#ifdef B_STATS - 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 -#ifdef B_STATS - if (bStatsBallocInUse == bStatsBallocMax) { - bstats(0, NULL); - } -#endif -#endif - return (void*) ((char*) bp + sizeof(bType)); -} - -/******************************************************************************/ -/* - * Free a block back to the relevant free q. We don't free back to the O/S - * or run time system unless the block is greater than the maximum class size. - * We also do not coalesce blocks. - */ - -void bfree(B_ARGS_DEC, void *mp) -{ - bType *bp; - int q, memSize; - -#ifdef B_VERIFY_CAUSES_SEVERE_OVERHEAD - verifyBallocSpace(); -#endif - bp = (bType*) ((char*) mp - sizeof(bType)); - - a_assert((bp->flags & B_INTEGRITY_MASK) == B_INTEGRITY); - - if ((bp->flags & B_INTEGRITY_MASK) != B_INTEGRITY) { - return; - } - - memSize = ballocGetSize(bp->u.size, &q); - -#ifdef B_VERIFY_CAUSES_SEVERE_OVERHEAD - verifyUsedBlock(bp,q); -#endif -#ifdef B_STATS - bStatsFree(B_ARGS, bp, q, bp->u.size+sizeof(bType)); -#endif - if (bp->flags & B_MALLOCED) { - free(bp); - return; - } - -#ifdef B_VERIFY_CAUSES_SEVERE_OVERHEAD - bFillBlock(bp, memSize); -#endif - -/* - * Simply link onto the head of the relevant q - */ - bp->u.next = bQhead[q]; - bQhead[q] = bp; - - bp->flags = B_FILL_WORD; -} - -/******************************************************************************/ -/* - * Safe free - */ - -void bfreeSafe(B_ARGS_DEC, void *mp) -{ - if (mp) { - bfree(B_ARGS, mp); - } -} - -/******************************************************************************/ -#ifdef UNICODE -/* - * Duplicate a string, allow NULL pointers and then dup an empty string. - */ - -char *bstrdupA(B_ARGS_DEC, char *s) -{ - char *cp; - int len; - - if (s == NULL) { - s = ""; - } - len = strlen(s) + 1; - if (cp = balloc(B_ARGS, len)) { - strcpy(cp, s); - } - return cp; -} - -#endif /* UNICODE */ -/******************************************************************************/ -/* - * Duplicate an ascii string, allow NULL pointers and then dup an empty string. - * If UNICODE, bstrdup above works with wide chars, so we need this routine - * for ascii strings. - */ - -char_t *bstrdup(B_ARGS_DEC, char_t *s) -{ - char_t *cp; - int len; - - if (s == NULL) { - s = T(""); - } - len = gstrlen(s) + 1; - if ((cp = balloc(B_ARGS, len * sizeof(char_t))) != NULL) { - gstrcpy(cp, s); - } - return cp; -} - -/******************************************************************************/ -/* - * Reallocate a block. Allow NULL pointers and just do a malloc. - * Note: if the realloc fails, we return NULL and the previous buffer is - * preserved. - */ - -void *brealloc(B_ARGS_DEC, void *mp, int newsize) -{ - bType *bp; - void *newbuf; - - if (mp == NULL) { - return balloc(B_ARGS, 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); - } - 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 (defined (B_FILL) || defined (B_VERIFY_CAUSES_SEVERE_OVERHEAD)) -/* - * Fill the block (useful during development to catch zero fill assumptions) - */ - -static void bFillBlock(void *buf, int bufsize) -{ - memset(buf, B_FILL_CHAR, bufsize); -} -#endif - -/******************************************************************************/ -#ifdef B_STATS -/* - * Statistics. Do output via calling the writefn callback function with - * "handle" as the output file handle. - */ - -void bstats(int handle, void (*writefn)(int handle, char_t *fmt, ...)) -{ - bStatsFileType *fp, *files; - bStatsBlkType *blkp; - bType *bp; - char_t *cp; - int q, count, mem, total, len; - static int recurseProtect = 0; - - if (recurseProtect++ > 0) { - recurseProtect--; - return; - } - - if (writefn == NULL) { - writefn = bstatsWrite; - } - -/* - * Print stats for each memory block - */ - (*writefn)(handle, T("\nMemory Stats\n")); - -/* - * The following tabular format is now used for the output. - * Q Size Free Bytes Inuse Bytes Allocs - * dd ddddd ddd ddddd dddd ddddd dddd - */ - (*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) { - count++; - } - mem = count * (1 << (q + B_SHIFT)); - total += mem; - (*writefn)(handle, - 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); - } - - (*writefn)(handle, T("\n")); - -/* - * 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); - - (*writefn)(handle, T("Free memory on all queues %7d\n"), total); - (*writefn)(handle, T("Free list buffer left %7d\n"), bFreeLeft); - (*writefn)(handle, T("Total free memory %7d\n"), bFreeLeft + total); - -/* - * Print per file allocation stats. Sort the copied table. - */ - 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; - (*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, %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\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--; -} - -/******************************************************************************/ -/* - * File sort function. Used to sort per file stats - */ - -static int bStatsFileSort(const void *cp1, const void *cp2) -{ - bStatsFileType *s1, *s2; - - s1 = (bStatsFileType*) cp1; - s2 = (bStatsFileType*) cp2; - - if (s1->allocated < s2->allocated) - return -1; - else if (s1->allocated == s2->allocated) - return 0; - return 1; -} - -/******************************************************************************/ -/* - * Accumulate allocation statistics - */ - -static void bStatsAlloc(B_ARGS_DEC, void *ptr, int q, int size) -{ - int memSize; - bStatsFileType *fp; - bStatsBlkType *bp; - char_t name[FNAMESIZE + 10]; - - 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 - * we only measure this on block allocation. - */ - if ((void*) &file < bStackMin) { - bStackMin = (void*) &file; - } - -/* - * Find the file and adjust the stats for this file - */ - for (fp = bStatsFiles; fp < &bStatsFiles[bStatsFilesMax]; fp++) { - if (fp->file[0] == file[0] && gstrcmp(fp->file, name) == 0) { - fp->allocated += size; - fp->count++; - fp->times++; - if (fp->largest < size) { - fp->largest = size; - fp->q = q; - } - break; - } - } - -/* - * 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++) { - if (fp->file[0] == '\0') { - gstrncpy(fp->file, name, TSZ(fp->file)); - fp->allocated += size; - fp->count++; - fp->times++; - fp->largest = size; - fp->q = q; - if ((fp - bStatsFiles) >= bStatsFilesMax) { - bStatsFilesMax = (fp - bStatsFiles) + 1; - } - break; - } - } - } - -/* - * Update the per block stats. Allocate a new slot. - */ - for (bp = bStatsBlks; bp < &bStatsBlks[B_MAX_BLOCKS]; bp++) { - if (bp->ptr == NULL) { - bp->ptr = ptr; - bp->who = fp; - if ((bp - bStatsBlks) >= bStatsBlksMax) { - bStatsBlksMax = (bp - bStatsBlks) + 1; - } - break; - } - } -} - -/******************************************************************************/ -/* - * Free statistics - */ - -static void bStatsFree(B_ARGS_DEC, void *ptr, int q, int size) -{ - int memSize; - bStatsFileType *fp; - bStatsBlkType *bp; - - memSize = (1 << (B_SHIFT + q)) + sizeof(bType); - bStatsMemInUse -= size; - bStatsBallocInUse -= memSize; - bStats[q].inuse--; - -/* - * Update the per block stats. Try from the end first - */ - 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; - } - } -} - -/******************************************************************************/ -/* - * 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 */ -/******************************************************************************/ -/* - * Dummy bstats for external calls that aren't protected by #if B_STATS. - */ - -void bstats(int handle, void (*writefn)(int handle, char_t *fmt, ...)) -{ -} -#endif /* B_STATS */ - -/******************************************************************************/ -#ifdef B_VERIFY_CAUSES_SEVERE_OVERHEAD -/* - * The following routines verify the integrity of the balloc memory space. - * 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 - * found. CAUTION: These functions add severe processing overhead and should - * only be used when searching for a tough corruption problem. - */ - -/******************************************************************************/ -/* - * verifyUsedBlock verifies that a block which was previously allocated is - * still uncorrupted. - */ - -static void verifyUsedBlock(bType *bp, int q) -{ - int memSize, size; - char *p; - - 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); - } -} - -/******************************************************************************/ -/* - * verifyFreeBlock verifies that a previously free'd block in one of the queues - * is still uncorrupted. - */ - -static void verifyFreeBlock(bType *bp, int q) -{ - int memSize; - char *p; - - 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); -} - -/******************************************************************************/ -/* - * 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 - * filled with B_FILL_CHAR. - */ - -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; - if (bp->u.size > 0xFFFFF) { - p += sizeof(bp->u); - while (p < (bFreeBuf + bFreeSize) && *p == B_FILL_CHAR) { - p++; - } - } else { - a_assert(((bp->flags & ~B_MALLOCED) == B_INTEGRITY) || - bp->flags == B_FILL_WORD); - p += (sizeof(bType) + bp->u.size); - while (p < (bFreeBuf + bFreeSize) && *p == B_FILL_CHAR) { - p++; - } - } - } -} -#endif /* B_VERIFY_CAUSES_SEVERE_OVERHEAD */ - -/******************************************************************************/ - -#else /* NO_BALLOC */ -int bopen(void *buf, int bufsize, int flags) -{ - return 0; -} - -/******************************************************************************/ - -void bclose() -{ -} - -/******************************************************************************/ - -void bstats(int handle, void (*writefn)(int handle, char_t *fmt, ...)) -{ -} - -/******************************************************************************/ - -char_t *bstrdupNoBalloc(char_t *s) -{ -#ifdef UNICODE - if (s) { - return wcsdup(s); - } else { - return wcsdup(T("")); - } -#else - return bstrdupANoBalloc(s); -#endif -} - -/******************************************************************************/ - -char *bstrdupANoBalloc(char *s) -{ - char* buf; - - if (s == NULL) { - s = ""; - } - buf = malloc(strlen(s)+1); - strcpy(buf, s); - return buf; -} - -#endif /* NO_BALLOC */ -/******************************************************************************/ diff --git a/cpukit/httpd/cgi.c b/cpukit/httpd/cgi.c deleted file mode 100644 index f349e27015..0000000000 --- a/cpukit/httpd/cgi.c +++ /dev/null @@ -1,331 +0,0 @@ -/* - * cgi.c -- CGI processing (for the GoAhead Web server - * - * Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved. - * - * See the file "license.txt" for usage and redistribution license requirements - * - * $Id$ - */ - -/********************************** Description *******************************/ -/* - * This module implements the /cgi-bin handler. CGI processing differs from - * goforms processing in that each CGI request is executed as a separate - * process, rather than within the webserver process. For each CGI request the - * environment of the new process must be set to include all the CGI variables - * and its standard input and output must be directed to the socket. This - * is done using temporary files. - */ - -/*********************************** Includes *********************************/ -#include "wsIntrn.h" -#ifdef UEMF - #include "uemf.h" -#else - #include "basic/basicInternal.h" -#endif - -/************************************ Locals **********************************/ -typedef struct { /* Struct for CGI tasks which have completed */ - webs_t wp; /* pointer to session websRec */ - char_t *stdIn; /* file desc. for task's temp input fd */ - char_t *stdOut; /* file desc. for task's temp output fd */ - char_t *cgiPath; /* path to executable process file */ - char_t **argp; /* pointer to buf containing argv tokens */ - char_t **envp; /* pointer to array of environment strings */ - int handle; /* process handle of the task */ - long fplacemark; /* seek location for CGI output file */ -} cgiRec; -static cgiRec **cgiList; /* hAlloc chain list of wp's to be closed */ -static int cgiMax; /* Size of hAlloc list */ - -/************************************* Code ***********************************/ - -/* - * Process a form request. Returns 1 always to indicate it handled the URL - */ -int websCgiHandler(webs_t wp, char_t *urlPrefix, char_t *webDir, int arg, - char_t *url, char_t *path, char_t* query) -{ - cgiRec *cgip; - sym_t *s; - char_t cgiBuf[FNAMESIZE], *stdIn, *stdOut, cwd[FNAMESIZE]; - char_t *cp, *cgiName, *cgiPath, **argp, **envp, **ep; - int n, envpsize, argpsize, pHandle, cid; - a_assert(websValid(wp)); - a_assert(url && *url); - a_assert(path && *path == '/'); - websStats.cgiHits++; -/* - * Extract the form name and then build the full path name. The form - * name will follow the first '/' in path. - */ - gstrncpy(cgiBuf, path, TSZ(cgiBuf)); - if ((cgiName = gstrchr(&cgiBuf[1], '/')) == NULL) { - websError(wp, 200, T("Missing CGI name")); - return 1; - } - cgiName++; - if ((cp = gstrchr(cgiName, '/')) != NULL) { - *cp = '\0'; - } - fmtAlloc(&cgiPath, FNAMESIZE, T("%s/%s/%s"), websGetDefaultDir(), - CGI_BIN, cgiName); -#ifndef VXWORKS -/* - * See if the file exists and is executable. If not error out. - * Don't do this step for VxWorks, since the module may already - * be part of the OS image, rather than in the file system. - */ - { - gstat_t sbuf; - if (gstat(cgiPath, &sbuf) != 0 || (sbuf.st_mode & S_IFREG) == 0) { - websError(wp, 200, T("CGI process file does not exist")); - bfree(B_L, cgiPath); - return 1; - } -#if (defined (WIN) || defined (CE)) - if (gstrstr(cgiPath, T(".exe")) == NULL && - gstrstr(cgiPath, T(".bat")) == NULL) { -#elif (defined (NW)) - if (gstrstr(cgiPath, T(".nlm")) == NULL) { -#else - if (gaccess(cgiPath, X_OK) != 0) { -#endif /* WIN || CE */ - websError(wp, 200, T("CGI process file is not executable")); - bfree(B_L, cgiPath); - return 1; - } - } -#endif /* ! VXWORKS */ - - -/* - * Get the CWD for resetting after launching the child process CGI - */ - ggetcwd(cwd, FNAMESIZE); -/* - * Retrieve the directory of the child process CGI - */ - if ((cp = gstrrchr(cgiPath, '/')) != NULL) { - *cp = '\0'; - gchdir(cgiPath); - *cp = '/'; - } -/* - * Build command line arguments. Only used if there is no non-encoded - * = character. This is indicative of a ISINDEX query. POST separators - * are & and others are +. argp will point to a balloc'd array of - * pointers. Each pointer will point to substring within the - * query string. This array of string pointers is how the spawn or - * exec routines expect command line arguments to be passed. Since - * we don't know ahead of time how many individual items there are in - * the query string, the for loop includes logic to grow the array - * size via brealloc. - */ - argpsize = 10; - argp = balloc(B_L, argpsize * sizeof(char_t *)); - *argp = cgiPath; - n = 1; - if (gstrchr(query, '=') == NULL) { - websDecodeUrl(query, query, gstrlen(query)); - for (cp = gstrtok(query, T(" ")); cp != NULL; ) { - *(argp+n) = cp; - n++; - if (n >= argpsize) { - argpsize *= 2; - argp = brealloc(B_L, argp, argpsize * sizeof(char_t *)); - } - cp = gstrtok(NULL, T(" ")); - } - } - *(argp+n) = NULL; -/* - * Add all CGI variables to the environment strings to be passed - * to the spawned CGI process. This includes a few we don't - * already have in the symbol table, plus all those that are in - * the cgiVars symbol table. envp will point to a balloc'd array of - * pointers. Each pointer will point to a balloc'd string containing - * the keyword value pair in the form keyword=value. Since we don't - * know ahead of time how many environment strings there will be the - * for loop includes logic to grow the array size via brealloc. - */ - envpsize = WEBS_SYM_INIT; - envp = balloc(B_L, envpsize * sizeof(char_t *)); - n = 0; - fmtAlloc(envp+n, FNAMESIZE, T("%s=%s"),T("PATH_TRANSLATED"), cgiPath); - n++; - fmtAlloc(envp+n, FNAMESIZE, T("%s=%s/%s"),T("SCRIPT_NAME"), - CGI_BIN, cgiName); - n++; - fmtAlloc(envp+n, FNAMESIZE, T("%s=%s"),T("REMOTE_USER"), wp->userName); - n++; - fmtAlloc(envp+n, FNAMESIZE, T("%s=%s"),T("AUTH_TYPE"), wp->authType); - n++; - for (s = symFirst(wp->cgiVars); s != NULL; s = symNext(wp->cgiVars)) { - if (s->content.valid && s->content.type == string && - gstrcmp(s->name.value.string, T("REMOTE_HOST")) != 0 && - gstrcmp(s->name.value.string, T("HTTP_AUTHORIZATION")) != 0) { - fmtAlloc(envp+n, FNAMESIZE, T("%s=%s"), s->name.value.string, - s->content.value.string); - n++; - if (n >= envpsize) { - envpsize *= 2; - envp = brealloc(B_L, envp, envpsize * sizeof(char_t *)); - } - } - } - *(envp+n) = NULL; -/* - * Create temporary file name(s) for the child's stdin and stdout. - * For POST data the stdin temp file (and name) should already exist. - */ - if (wp->cgiStdin == NULL) { - wp->cgiStdin = websGetCgiCommName(); - } - stdIn = wp->cgiStdin; - stdOut = websGetCgiCommName(); -/* - * Now launch the process. If not successful, do the cleanup of resources. - * If successful, the cleanup will be done after the process completes. - */ - if ((pHandle = websLaunchCgiProc(cgiPath, argp, envp, stdIn, stdOut)) - == -1) { - websError(wp, 200, T("failed to spawn CGI task")); - for (ep = envp; *ep != NULL; ep++) { - bfreeSafe(B_L, *ep); - } - bfreeSafe(B_L, cgiPath); - bfreeSafe(B_L, argp); - bfreeSafe(B_L, envp); - bfreeSafe(B_L, stdOut); - } else { -/* - * If the spawn was successful, put this wp on a queue to be - * checked for completion. - */ - cid = hAllocEntry((void***) &cgiList, &cgiMax, sizeof(cgiRec)); - cgip = cgiList[cid]; - cgip->handle = pHandle; - cgip->stdIn = stdIn; - cgip->stdOut = stdOut; - cgip->cgiPath = cgiPath; - cgip->argp = argp; - cgip->envp = envp; - cgip->wp = wp; - cgip->fplacemark = 0; - websTimeoutCancel(wp); - } -/* - * Restore the current working directory after spawning child CGI - */ - gchdir(cwd); - return 1; -} - - - -/******************************************************************************/ -/* - * Any entry in the cgiList need to be checked to see if it has - */ -void websCgiGatherOutput (cgiRec *cgip) -{ - gstat_t sbuf; - char_t cgiBuf[FNAMESIZE]; - if ((gstat(cgip->stdOut, &sbuf) == 0) && - (sbuf.st_size > cgip->fplacemark)) { - int fdout; - fdout = gopen(cgip->stdOut, O_RDONLY | O_BINARY, 0444 ); -/* - * Check to see if any data is available in the - * output file and send its contents to the socket. - */ - if (fdout >= 0) { - webs_t wp = cgip->wp; - int nRead; -/* - * Write the HTTP header on our first pass - */ - if (cgip->fplacemark == 0) { - websWrite(wp, T("HTTP/1.0 200 OK\r\n")); - } - glseek(fdout, cgip->fplacemark, SEEK_SET); - while ((nRead = gread(fdout, cgiBuf, FNAMESIZE)) > 0) { - websWriteBlock(wp, cgiBuf, nRead); - cgip->fplacemark += nRead; - } - gclose(fdout); - } - } -} - - - -/******************************************************************************/ -/* - * Any entry in the cgiList need to be checked to see if it has - * completed, and if so, process its output and clean up. - */ -void websCgiCleanup() -{ - cgiRec *cgip; - webs_t wp; - char_t **ep; - int cid, nTries; - for (cid = 0; cid < cgiMax; cid++) { - if ((cgip = cgiList[cid]) != NULL) { - wp = cgip->wp; - websCgiGatherOutput (cgip); - if (websCheckCgiProc(cgip->handle) == 0) { -/* - * We get here if the CGI process has terminated. Clean up. - */ - nTries = 0; -/* - * Make sure we didn't miss something during a task switch. - * Maximum wait is 100 times 10 msecs (1 second). - */ - while ((cgip->fplacemark == 0) && (nTries < 100)) { - websCgiGatherOutput(cgip); -/* - * There are some cases when we detect app exit - * before the file is ready. - */ - if (cgip->fplacemark == 0) { -#ifdef WIN - Sleep(10); -#endif /* WIN*/ - } - nTries++; - } - if (cgip->fplacemark == 0) { - websError(wp, 200, T("CGI generated no output")); - } else { - websDone(wp, 200); - } -/* - * Remove the temporary re-direction files - */ - gunlink(cgip->stdIn); - gunlink(cgip->stdOut); -/* - * Free all the memory buffers pointed to by cgip. - * The stdin file name (wp->cgiStdin) gets freed as - * part of websFree(). - */ - cgiMax = hFree((void***) &cgiList, cid); - for (ep = cgip->envp; ep != NULL && *ep != NULL; ep++) { - bfreeSafe(B_L, *ep); - } - bfreeSafe(B_L, cgip->cgiPath); - bfreeSafe(B_L, cgip->argp); - bfreeSafe(B_L, cgip->envp); - bfreeSafe(B_L, cgip->stdOut); - bfreeSafe(B_L, cgip); - } - } - } -} -/******************************************************************************/ diff --git a/cpukit/httpd/default.c b/cpukit/httpd/default.c deleted file mode 100644 index e0f9c54b9b..0000000000 --- a/cpukit/httpd/default.c +++ /dev/null @@ -1,431 +0,0 @@ -/* - * default.c -- Default URL handler. Includes support for ASP. - * - * Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved. - * - * See the file "license.txt" for usage and redistribution license requirements - * - * $Id$ - */ - -/******************************** Description *********************************/ - -/* - * This module provides default URL handling and Active Server Page support. - * - * In many cases we don't check the return code of calls to websWrite as - * it is easier, smaller and non-fatal to continue even when the requesting - * browser has gone away. - */ - -/********************************* Includes ***********************************/ - -#include "wsIntrn.h" - -/*********************************** Locals ***********************************/ - -static char_t *websDefaultPage; /* Default page name */ -static char_t *websDefaultDir; /* Default Web page directory */ - -/**************************** Forward Declarations ****************************/ - -static void websDefaultWriteEvent(webs_t wp); - -/*********************************** Code *************************************/ -/* - * Process a default URL request. This will validate the URL and handle "../" - * and will provide support for Active Server Pages. As the handler is the - * last handler to run, it always indicates that it has handled the URL - * by returning 1. - */ - -int websDefaultHandler(webs_t wp, char_t *urlPrefix, char_t *webDir, int arg, - char_t *url, char_t *path, char_t *query) -{ - websStatType sbuf; - char_t *lpath, *tmp, *date; - int bytes, flags, nchars; - - a_assert(websValid(wp)); - a_assert(url && *url); - a_assert(path); - a_assert(query); - -/* - * Validate the URL and ensure that ".."s don't give access to unwanted files - */ - flags = websGetRequestFlags(wp); - - if (websValidateUrl(wp, path) < 0) { - websError(wp, 500, T("Invalid URL %s"), url); - return 1; - } - lpath = websGetRequestLpath(wp); - nchars = gstrlen(lpath) - 1; - if (lpath[nchars] == '/' || lpath[nchars] == '\\') { - lpath[nchars] = '\0'; - } - -/* - * If the file is a directory, redirect using the nominated default page - */ - if (websPageIsDirectory(lpath)) { - nchars = gstrlen(path); - if (path[nchars-1] == '/' || path[nchars-1] == '\\') { - path[--nchars] = '\0'; - } - nchars += gstrlen(websDefaultPage) + 2; - fmtAlloc(&tmp, nchars, T("%s/%s"), path, websDefaultPage); - websRedirect(wp, tmp); - bfreeSafe(B_L, tmp); - return 1; - } - -/* - * Open the document. Stat for later use. - */ - if (websPageOpen(wp, lpath, path, SOCKET_RDONLY | SOCKET_BINARY, - 0666) < 0) { - websError(wp, 400, T("Cannot open URL <b>%s</b>"), url); - return 1; - } - - if (websPageStat(wp, lpath, path, &sbuf) < 0) { - websError(wp, 400, T("Cannot stat page for URL <b>%s</b>"), url); - return 1; - } - -/* - * If the page has not been modified since the user last received it and it - * is not dynamically generated each time (ASP), then optimize request by - * sending a 304 Use local copy response - */ - websStats.localHits++; -#ifdef WEBS_IF_MODIFIED_SUPPORT - if (flags & WEBS_IF_MODIFIED && !(flags & WEBS_ASP)) { - 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: %s\r\n"), WEBS_NAME); - - if (flags & WEBS_KEEP_ALIVE) { - websWrite(wp, T("Connection: keep-alive\r\n")); - } - websWrite(wp, T("\r\n")); - websSetRequestFlags(wp, flags |= WEBS_HEADER_DONE); - websDone(wp, 304); - return 1; - } - } -#endif - -/* - * Output the normal HTTP response header - */ - if ((date = websGetDateString(NULL)) != NULL) { - websWrite(wp, T("HTTP/1.0 200 OK\r\nDate: %s\r\n"), date); - -/* - * By license terms the following line of code must not be modified. - */ - websWrite(wp, T("Server: %s\r\n"), WEBS_NAME); - bfree(B_L, date); - } - flags |= WEBS_HEADER_DONE; - -/* - * If this is an ASP request, ensure the remote browser doesn't cache it. - * Send back both HTTP/1.0 and HTTP/1.1 cache control directives - */ - if (flags & WEBS_ASP) { - bytes = 0; - websWrite(wp, T("Pragma: no-cache\r\nCache-Control: no-cache\r\n")); - - } else { - if ((date = websGetDateString(&sbuf)) != NULL) { - websWrite(wp, T("Last-modified: %s\r\n"), date); - bfree(B_L, date); - } - bytes = sbuf.size; - } - - if (bytes) { - websWrite(wp, T("Content-length: %d\r\n"), bytes); - websSetRequestBytes(wp, bytes); - } - websWrite(wp, T("Content-type: %s\r\n"), websGetRequestType(wp)); - - if ((flags & WEBS_KEEP_ALIVE) && !(flags & WEBS_ASP)) { - websWrite(wp, T("Connection: keep-alive\r\n")); - } - 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 - */ - if (flags & WEBS_ASP) { - if (websAspRequest(wp, lpath) < 0) { - return 1; - } - 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; -} - -/******************************************************************************/ -/* - * Validate the URL path and process ".." path segments. Return -1 if the URL - * is bad. - */ - -int websValidateUrl(webs_t wp, char_t *path) -{ - char_t *parts[64]; /* Array of ptr's to URL parts */ - char_t *token, *dir, *lpath; - int i, len, npart; - - a_assert(websValid(wp)); - a_assert(path); - - dir = websGetRequestDir(wp); - if (dir == NULL || *dir == '\0') { - return -1; - } - -/* - * Copy the string so we don't destroy the original - */ - path = bstrdup(B_L, path); - websDecodeUrl(path, path, gstrlen(path)); - - len = npart = 0; - parts[0] = NULL; - - /* - * 22 Jul 02 -- there were reports that a directory traversal exploit was - * possible in the WebServer running under Windows if directory paths - * outside the server's specified root web were given by URL-encoding the - * backslash character, like: - * - * GoAhead is vulnerable to a directory traversal bug. A request such as - * - * GoAhead-server/../../../../../../../ results in an error message - * 'Cannot open URL'. - - * However, by encoding the '/' character, it is possible to break out of - * the - * web root and read arbitrary files from the server. - * Hence a request like: - * - * GoAhead-server/..%5C..%5C..%5C..%5C..%5C..%5C/winnt/win.ini returns the - * contents of the win.ini file. - * (Note that the description uses forward slashes (0x2F), but the example - * uses backslashes (0x5C). In my tests, forward slashes are correctly - * trapped, but backslashes are not. The code below substitutes forward - * slashes for backslashes before attempting to validate that there are no - * unauthorized paths being accessed. - */ - token = gstrchr(path, '\\'); - while (token != NULL) - { - *token = '/'; - token = gstrchr(token, '\\'); - } - - token = gstrtok(path, 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("/")); - } - -/* - * Create local path for document. Need extra space all "/" and null. - */ - if (npart || (gstrcmp(path, T("/")) == 0) || (path[0] == '\0')) { - lpath = balloc(B_L, (gstrlen(dir) + 1 + len + 1) * sizeof(char_t)); - gstrcpy(lpath, dir); - - for (i = 0; i < npart; i++) { - gstrcat(lpath, T("/")); - gstrcat(lpath, parts[i]); - } - websSetRequestLpath(wp, lpath); - bfree(B_L, path); - bfree(B_L, lpath); - - } else { - bfree(B_L, path); - return -1; - } - return 0; -} - -/******************************************************************************/ -/* - * Do output back to the browser in the background. This is a socket - * write handler. - */ - -static void websDefaultWriteEvent(webs_t wp) -{ - int len, wrote, flags, bytes, written; - char *buf; - - a_assert(websValid(wp)); - - flags = websGetRequestFlags(wp); - - websSetTimeMark(wp); - - wrote = bytes = 0; - written = websGetRequestWritten(wp); - -/* - * We only do this for non-ASP documents - */ - if ( !(flags & WEBS_ASP)) { - bytes = websGetRequestBytes(wp); -/* - * 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 = websWriteDataNonBlock(wp, buf, len)) < 0) { - break; - } - written += wrote; - if (wrote != len) { - websPageSeek(wp, - (len - wrote)); - break; - } - } -/* - * Safety. If we are at EOF, we must be done - */ - if (len == 0) { - a_assert(written >= bytes); - written = bytes; - } - bfree(B_L, buf); - } - } - -/* - * We're done if an error, or all bytes output - */ - websSetRequestWritten(wp, written); - if (wrote < 0 || written >= bytes) { - websDone(wp, 200); - } -} - -/******************************************************************************/ -/* - * Closing down. Free resources. - */ - -void websDefaultClose(void) -{ - if (websDefaultPage) { - bfree(B_L, websDefaultPage); - websDefaultPage = NULL; - } - if (websDefaultDir) { - bfree(B_L, websDefaultDir); - websDefaultDir = NULL; - } -} - -/******************************************************************************/ -/* - * Get the default page for URL requests ending in "/" - */ - -char_t *websGetDefaultPage(void) -{ - return websDefaultPage; -} - -/******************************************************************************/ -/* - * Get the default web directory - */ - -char_t *websGetDefaultDir(void) -{ - return websDefaultDir; -} - -/******************************************************************************/ -/* - * Set the default page for URL requests ending in "/" - */ - -void websSetDefaultPage(char_t *page) -{ - a_assert(page && *page); - - if (websDefaultPage) { - bfree(B_L, websDefaultPage); - } - websDefaultPage = bstrdup(B_L, page); -} - -/******************************************************************************/ -/* - * Set the default web directory - */ - -void websSetDefaultDir(char_t *dir) -{ - a_assert(dir && *dir); - if (websDefaultDir) { - bfree(B_L, websDefaultDir); - } - websDefaultDir = bstrdup(B_L, dir); -} - -/******************************************************************************/ diff --git a/cpukit/httpd/ej.h b/cpukit/httpd/ej.h deleted file mode 100644 index c60fdc1682..0000000000 --- a/cpukit/httpd/ej.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * ej.h -- Ejscript(TM) 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_EJ -#define _h_EJ 1 - -/******************************** Description *********************************/ - -/* - * GoAhead Ejscript(TM) header. This defines the Ejscript API and internal - * structures. - */ - -/********************************* Includes ***********************************/ - -#ifndef UEMF - #include "basic/basic.h" - #include "emf/emf.h" -#else - #include "uemf.h" -#endif - -/********************************** Defines ***********************************/ - -/******************************** 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 ejSetGlobalFunction(int eid, char_t *name, - int (*fn)(int eid, void *handle, int argc, char_t **argv)); -extern void ejSetVar(int eid, char_t *var, char_t *value); -extern int ejGetVar(int eid, char_t *var, char_t **value); -extern char_t *ejEval(int eid, char_t *script, char_t **emsg); - -#endif /* _h_EJ */ - -/*****************************************************************************/ diff --git a/cpukit/httpd/ejIntrn.h b/cpukit/httpd/ejIntrn.h deleted file mode 100644 index 0cf74fcde6..0000000000 --- a/cpukit/httpd/ejIntrn.h +++ /dev/null @@ -1,230 +0,0 @@ -/* - * ejIntrn.h -- Ejscript(TM) header - * - * Copyright (c) GoAhead Software, Inc., 1992-2000 - * - * See the file "license.txt" for information on usage and redistribution - * - * $Id$ - */ - -#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> - -#ifdef CE -#ifndef UEMF - #include <io.h> -#endif -#endif - -#ifdef LYNX - #include <unistd.h> -#endif - -#ifdef QNX4 - #include <dirent.h> -#endif - -#ifdef 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 */ diff --git a/cpukit/httpd/ejlex.c b/cpukit/httpd/ejlex.c deleted file mode 100644 index 137643475a..0000000000 --- a/cpukit/httpd/ejlex.c +++ /dev/null @@ -1,721 +0,0 @@ -/* - * ejlex.c -- Ejscript(TM) Lexical Analyser - * - * Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved. - * - * See the file "license.txt" for usage and redistribution license requirements - * - * $Id$ - */ - -/******************************** Description *********************************/ - -/* - * Ejscript lexical analyser. This implementes a lexical analyser for a - * a subset of the JavaScript language. - */ - -/********************************** Includes **********************************/ - -#include "ejIntrn.h" - -#ifdef UEMF - #include "uemf.h" -#else - #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 ***********************************/ -/* - * Setup the lexical analyser - */ - -int ejLexOpen(ej_t* ep) -{ - return 0; -} - -/******************************************************************************/ -/* - * Close the lexicial analyser - */ - -void ejLexClose(ej_t* ep) -{ -} - -/******************************************************************************/ -/* - * Open a new input script - */ - -int ejLexOpenScript(ej_t* ep, char_t *script) -{ - ejinput_t *ip; - - a_assert(ep); - a_assert(script); - - if ((ep->input = balloc(B_L, sizeof(ejinput_t))) == NULL) { - return -1; - } - ip = ep->input; - memset(ip, 0, sizeof(*ip)); - - a_assert(ip); - a_assert(ip->putBackToken == NULL); - a_assert(ip->putBackTokenId == 0); - -/* - * Create the parse token buffer and script buffer - */ - if (ringqOpen(&ip->tokbuf, EJ_INC, -1) < 0) { - return -1; - } - 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); - - ip->lineNumber = 1; - ip->lineLength = 0; - ip->lineColumn = 0; - ip->line = NULL; - - return 0; -} - -/******************************************************************************/ -/* - * Close the input script - */ - -void ejLexCloseScript(ej_t* ep) -{ - ejinput_t *ip; - - a_assert(ep); - - ip = ep->input; - a_assert(ip); - - if (ip->putBackToken) { - bfree(B_L, ip->putBackToken); - ip->putBackToken = NULL; - } - ip->putBackTokenId = 0; - - if (ip->line) { - bfree(B_L, ip->line); - ip->line = NULL; - } - - ringqClose(&ip->tokbuf); - ringqClose(&ip->script); - - bfree(B_L, ip); -} - -/******************************************************************************/ -/* - * Save the input state - */ - -void ejLexSaveInputState(ej_t* ep, ejinput_t* state) -{ - ejinput_t *ip; - - a_assert(ep); - - ip = ep->input; - a_assert(ip); - - *state = *ip; - if (ip->putBackToken) { - state->putBackToken = bstrdup(B_L, ip->putBackToken); - } -} - -/******************************************************************************/ -/* - * Restore the input state - */ - -void ejLexRestoreInputState(ej_t* ep, ejinput_t* state) -{ - ejinput_t *ip; - - a_assert(ep); - - ip = ep->input; - a_assert(ip); - - ip->tokbuf = state->tokbuf; - ip->script = state->script; - ip->putBackTokenId = state->putBackTokenId; - if (ip->putBackToken) { - bfree(B_L, ip->putBackToken); - } - if (state->putBackToken) { - ip->putBackToken = bstrdup(B_L, state->putBackToken); - } -} - -/******************************************************************************/ -/* - * Free a saved input state - */ - -void ejLexFreeInputState(ej_t* ep, ejinput_t* state) -{ - if (state->putBackToken) { - bfree(B_L, state->putBackToken); - state->putBackToken = NULL; - } -} - -/******************************************************************************/ -/* - * Get the next Ejscript token - */ - -int ejLexGetToken(ej_t* ep, int state) -{ - ep->tid = getLexicalToken(ep, state); - /* - * commented out 04 Apr 02 Bg Porter -- we found a case where very long - * arguments to write() were being corrupted downstream in the trace call - * (the ep->token pointer was being overwritten with the trace message. - * restore this if it's useful for your debugging. - trace(9, T("ejGetToken: %d, \"%s\"\n"), ep->tid, ep->token); - */ - return ep->tid; -} - -/******************************************************************************/ -/* - * Get the next Ejscript token - */ - -static int getLexicalToken(ej_t* ep, int state) -{ - ringq_t *inq, *tokq; - ejinput_t* ip; - int done, tid, c, quote, style; - - a_assert(ep); - ip = ep->input; - a_assert(ip); - - inq = &ip->script; - tokq = &ip->tokbuf; - - ep->tid = -1; - tid = -1; - ep->token = T(""); - - ringqFlush(tokq); - - if (ip->putBackTokenId > 0) { - ringqPutStr(tokq, ip->putBackToken); - tid = ip->putBackTokenId; - ip->putBackTokenId = 0; - ep->token = (char_t*) tokq->servp; - return tid; - } - - if ((c = inputGetc(ep)) < 0) { - return TOK_EOF; - } - - for (done = 0; !done; ) { - switch (c) { - case -1: - return TOK_EOF; - - case ' ': - case '\t': - case '\r': - do { - if ((c = inputGetc(ep)) < 0) - break; - } while (c == ' ' || c == '\t' || c == '\r'); - break; - - case '\n': - return TOK_NEWLINE; - - case '(': - tokenAddChar(ep, c); - return TOK_LPAREN; - - case ')': - tokenAddChar(ep, c); - return TOK_RPAREN; - - case '{': - tokenAddChar(ep, c); - return TOK_LBRACE; - - case '}': - tokenAddChar(ep, c); - return TOK_RBRACE; - - case '+': - if ((c = inputGetc(ep)) < 0) { - ejError(ep, T("Syntax Error")); - return TOK_ERR; - } - if (c != '+' ) { - inputPutback(ep, c); - tokenAddChar(ep, EXPR_PLUS); - return TOK_EXPR; - } - tokenAddChar(ep, EXPR_INC); - return TOK_INC_DEC; - - case '-': - if ((c = inputGetc(ep)) < 0) { - ejError(ep, T("Syntax Error")); - return TOK_ERR; - } - if (c != '-' ) { - inputPutback(ep, c); - tokenAddChar(ep, EXPR_MINUS); - return TOK_EXPR; - } - tokenAddChar(ep, EXPR_DEC); - return TOK_INC_DEC; - - case '*': - tokenAddChar(ep, EXPR_MUL); - return TOK_EXPR; - - case '%': - tokenAddChar(ep, EXPR_MOD); - return TOK_EXPR; - - case '/': -/* - * Handle the division operator and comments - */ - if ((c = inputGetc(ep)) < 0) { - ejError(ep, T("Syntax Error")); - return TOK_ERR; - } - if (c != '*' && c != '/') { - inputPutback(ep, c); - tokenAddChar(ep, EXPR_DIV); - return TOK_EXPR; - } - style = c; -/* - * Eat comments. Both C and C++ comment styles are supported. - */ - while (1) { - if ((c = inputGetc(ep)) < 0) { - ejError(ep, T("Syntax Error")); - return TOK_ERR; - } - if (c == '\n' && style == '/') { - break; - } else if (c == '*') { - c = inputGetc(ep); - if (style == '/') { - if (c == '\n') { - break; - } - } else { - if (c == '/') { - break; - } - } - } - } -/* - * Continue looking for a token, so get the next character - */ - if ((c = inputGetc(ep)) < 0) { - return TOK_EOF; - } - break; - - case '<': /* < and <= */ - if ((c = inputGetc(ep)) < 0) { - ejError(ep, T("Syntax Error")); - return TOK_ERR; - } - if (c == '<') { - tokenAddChar(ep, EXPR_LSHIFT); - return TOK_EXPR; - } else if (c == '=') { - tokenAddChar(ep, EXPR_LESSEQ); - return TOK_EXPR; - } - tokenAddChar(ep, EXPR_LESS); - inputPutback(ep, c); - return TOK_EXPR; - - case '>': /* > and >= */ - if ((c = inputGetc(ep)) < 0) { - ejError(ep, T("Syntax Error")); - return TOK_ERR; - } - if (c == '>') { - tokenAddChar(ep, EXPR_RSHIFT); - return TOK_EXPR; - } else if (c == '=') { - tokenAddChar(ep, EXPR_GREATEREQ); - return TOK_EXPR; - } - tokenAddChar(ep, EXPR_GREATER); - inputPutback(ep, c); - return TOK_EXPR; - - case '=': /* "==" */ - if ((c = inputGetc(ep)) < 0) { - ejError(ep, T("Syntax Error")); - return TOK_ERR; - } - if (c == '=') { - tokenAddChar(ep, EXPR_EQ); - return TOK_EXPR; - } - inputPutback(ep, c); - return TOK_ASSIGNMENT; - - case '!': /* "!=" or "!"*/ - if ((c = inputGetc(ep)) < 0) { - ejError(ep, T("Syntax Error")); - return TOK_ERR; - } - if (c == '=') { - tokenAddChar(ep, EXPR_NOTEQ); - return TOK_EXPR; - } - inputPutback(ep, c); - tokenAddChar(ep, EXPR_BOOL_COMP); - return TOK_EXPR; - - case ';': - tokenAddChar(ep, c); - return TOK_SEMI; - - case ',': - tokenAddChar(ep, c); - return TOK_COMMA; - - case '|': /* "||" */ - if ((c = inputGetc(ep)) < 0 || c != '|') { - ejError(ep, T("Syntax Error")); - return TOK_ERR; - } - tokenAddChar(ep, COND_OR); - return TOK_LOGICAL; - - case '&': /* "&&" */ - if ((c = inputGetc(ep)) < 0 || c != '&') { - ejError(ep, T("Syntax Error")); - return TOK_ERR; - } - tokenAddChar(ep, COND_AND); - return TOK_LOGICAL; - - case '\"': /* String quote */ - case '\'': - quote = c; - if ((c = inputGetc(ep)) < 0) { - ejError(ep, T("Syntax Error")); - return TOK_ERR; - } - - 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; - case 'b': - c = '\b'; break; - case 'f': - c = '\f'; break; - case 'r': - c = '\r'; break; - case 't': - c = '\t'; break; - case 'x': -/* - * hex support, \x41 maps to 65 = 'A' - */ - c = charConvert(ep, HEX, 2); - break; - case 'u': -/* - * 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; - } - } - if (tokenAddChar(ep, c) < 0) { - return TOK_ERR; - } - } else { - if (tokenAddChar(ep, c) < 0) { - return TOK_ERR; - } - } - if ((c = inputGetc(ep)) < 0) { - ejError(ep, T("Unmatched Quote")); - return TOK_ERR; - } - } - return TOK_LITERAL; - - case '0': case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': - do { - if (tokenAddChar(ep, c) < 0) { - return TOK_ERR; - } - if ((c = inputGetc(ep)) < 0) - break; - } while (gisdigit(c)); - inputPutback(ep, c); - return TOK_LITERAL; - - default: -/* - * Identifiers or a function names - */ - while (1) { - if (c == '\\') { -/* - * just ignore any \ characters. - */ - } else if (tokenAddChar(ep, c) < 0) { - break; - } - if ((c = inputGetc(ep)) < 0) { - break; - } - if (!gisalnum(c) && c != '$' && c != '_' && - c != '\\') { - break; - } - } - if (! gisalpha(*tokq->servp) && *tokq->servp != '$' && - *tokq->servp != '_') { - ejError(ep, T("Invalid identifier %s"), tokq->servp); - return TOK_ERR; - } -/* - * Check for reserved words (only "if", "else", "var", "for" - * and "return" at the moment) - */ - if (state == STATE_STMT) { - if (gstrcmp(ep->token, T("if")) == 0) { - return TOK_IF; - } else if (gstrcmp(ep->token, T("else")) == 0) { - return TOK_ELSE; - } else if (gstrcmp(ep->token, T("var")) == 0) { - return TOK_VAR; - } 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. - */ - while (c == ' ' || c == '\t' || c == '\r' || c == '\n') { - if ((c = inputGetc(ep)) < 0) - break; - } - - tid = (c == '(') ? TOK_FUNCTION : TOK_ID; - done++; - } - } - -/* - * Putback the last extra character for next time - */ - inputPutback(ep, c); - return tid; -} - -/******************************************************************************/ -/* - * Putback the last token read - */ - -void ejLexPutbackToken(ej_t* ep, int tid, char_t *string) -{ - ejinput_t* ip; - - a_assert(ep); - ip = ep->input; - a_assert(ip); - - if (ip->putBackToken) { - bfree(B_L, ip->putBackToken); - } - ip->putBackTokenId = tid; - ip->putBackToken = bstrdup(B_L, string); -} - -/******************************************************************************/ -/* - * Add a character to the token ringq buffer - */ - -static int tokenAddChar(ej_t *ep, int c) -{ - ejinput_t* ip; - - a_assert(ep); - ip = ep->input; - a_assert(ip); - - if (ringqPutc(&ip->tokbuf, (char_t) c) < 0) { - ejError(ep, T("Token too big")); - return -1; - } - * ((char_t*) ip->tokbuf.endp) = '\0'; - ep->token = (char_t*) ip->tokbuf.servp; - - return 0; -} - -/******************************************************************************/ -/* - * Get another input character - */ - -static int inputGetc(ej_t* ep) -{ - ejinput_t *ip; - int c, len; - - a_assert(ep); - ip = ep->input; - - if ((len = ringqLen(&ip->script)) == 0) { - return -1; - } - - c = ringqGetc(&ip->script); - - if (c == '\n') { - ip->lineNumber++; - ip->lineColumn = 0; - } else { - if ((ip->lineColumn + 2) >= ip->lineLength) { - ip->lineLength += EJ_INC; - ip->line = brealloc(B_L, ip->line, ip->lineLength * sizeof(char_t)); - } - ip->line[ip->lineColumn++] = c; - ip->line[ip->lineColumn] = '\0'; - } - return c; -} - -/******************************************************************************/ -/* - * Putback a character onto the input queue - */ - -static void inputPutback(ej_t* ep, int c) -{ - ejinput_t *ip; - - a_assert(ep); - - ip = ep->input; - ringqInsertc(&ip->script, (char_t) c); - ip->lineColumn--; - ip->line[ip->lineColumn] = '\0'; -} - -/******************************************************************************/ -/* - * 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; -} - -/******************************************************************************/ diff --git a/cpukit/httpd/ejparse.c b/cpukit/httpd/ejparse.c deleted file mode 100644 index f2e97a221b..0000000000 --- a/cpukit/httpd/ejparse.c +++ /dev/null @@ -1,1804 +0,0 @@ -/* - * ejparse.c -- Ejscript(TM) Parser - * - * Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved. - * - * See the file "license.txt" for usage and redistribution license requirements - * - * $Id$ - */ - -/******************************** Description *********************************/ - -/* - * Ejscript parser. This implementes a subset of the JavaScript language. - * Multiple Ejscript parsers can be opened at a time. - */ - -/********************************** Includes **********************************/ - -#include "ejIntrn.h" - -#ifdef CE - #include "CE/wincompat.h" -#endif - -/********************************** Local Data ********************************/ - -ej_t **ejHandles; /* List of ej handles */ -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(B_ARGS_DEC, char_t **ptr, char_t *s); -static void appendString(char_t **ptr, char_t *s); -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); -static int parseArgs(ej_t *ep, int state, int flags); -static int parseCond(ej_t *ep, int state, int flags); -static int parseExpr(ej_t *ep, int state, int flags); -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 ***********************************/ -/* - * Initialize a Ejscript engine - */ - -int ejOpenEngine(sym_fd_t variables, sym_fd_t functions) -{ - ej_t *ep; - int eid, vid; - - if ((eid = hAllocEntry((void*) &ejHandles, &ejMax, sizeof(ej_t))) < 0) { - return -1; - } - ep = ejHandles[eid]; - 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 - * declarations so we use hAlloc to manage a list of variable tables. - */ - if ((vid = hAlloc((void***) &ep->variables)) < 0) { - ejMax = hFree((void*) &ejHandles, ep->eid); - return -1; - } - if (vid >= ep->variableMax) { - ep->variableMax = vid + 1; - } - - if (variables == -1) { - ep->variables[vid] = symOpen(64) + EJ_OFFSET; - ep->flags |= FLAGS_VARIABLES; - } else { - ep->variables[vid] = variables + EJ_OFFSET; - } - - if (functions == -1) { - ep->functions = symOpen(64); - ep->flags |= FLAGS_FUNCTIONS; - } else { - ep->functions = functions; - } - - ejLexOpen(ep); - -/* - * Define standard constants - */ - ejSetGlobalVar(ep->eid, T("null"), NULL); - -#ifdef EMF - ejEmfOpen(ep->eid); -#endif - return ep->eid; -} - -/******************************************************************************/ -/* - * Close - */ - -void ejCloseEngine(int eid) -{ - ej_t *ep; - int i; - - if ((ep = ejPtr(eid)) == NULL) { - return; - } - -#ifdef EMF - ejEmfClose(eid); -#endif - - bfreeSafe(B_L, ep->error); - ep->error = NULL; - bfreeSafe(B_L, ep->result); - ep->result = NULL; - - ejLexClose(ep); - - 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); - } - - ejMax = hFree((void*) &ejHandles, ep->eid); - bfree(B_L, ep); -} - -#ifndef __NO_EJ_FILE -/******************************************************************************/ -/* - * Evaluate a Ejscript file - */ - -char_t *ejEvalFile(int eid, char_t *path, char_t **emsg) -{ - gstat_t sbuf; - ej_t *ep; - char_t *script, *rs; - char *fileBuf; - int fd; - - a_assert(path && *path); - - if (emsg) { - *emsg = NULL; - } - - if ((ep = ejPtr(eid)) == NULL) { - return NULL; - } - - if ((fd = gopen(path, O_RDONLY | O_BINARY, 0666)) < 0) { - ejError(ep, T("Bad handle %d"), eid); - return NULL; - } - - if (gstat(path, &sbuf) < 0) { - gclose(fd); - ejError(ep, T("Cant stat %s"), path); - return NULL; - } - - if ((fileBuf = balloc(B_L, sbuf.st_size + 1)) == NULL) { - gclose(fd); - ejError(ep, T("Cant malloc %d"), sbuf.st_size); - return NULL; - } - - 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'; - gclose(fd); - - if ((script = ballocAscToUni(fileBuf, sbuf.st_size)) == NULL) { - bfree(B_L, fileBuf); - ejError(ep, T("Cant malloc %d"), sbuf.st_size + 1); - return NULL; - } - bfree(B_L, fileBuf); - - rs = ejEvalBlock(eid, script, emsg); - - bfree(B_L, script); - return rs; -} -#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. - */ - -int ejOpenBlock(int eid) -{ - ej_t *ep; - 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; - -} - -/******************************************************************************/ -/* - * Close a variable scope block. The vid parameter is the return value from - * the call to ejOpenBlock - */ - -int ejCloseBlock(int eid, int vid) -{ - ej_t *ep; - - if((ep = ejPtr(eid)) == NULL) { - return -1; - } - symClose(ep->variables[vid] - EJ_OFFSET); - ep->variableMax = hFree((void***) &ep->variables, vid); - return 0; - -} - -/******************************************************************************/ -/* - * Create a new variable scope block and evaluate a script. All variables - * created during this context will be automatically deleted when complete. - */ - -char_t *ejEvalBlock(int eid, char_t *script, char_t **emsg) -{ - char_t* returnVal; - int vid; - - a_assert(script); - - vid = ejOpenBlock(eid); - returnVal = ejEval(eid, script, emsg); - ejCloseBlock(eid, vid); - - return returnVal; -} - -/******************************************************************************/ -/* - * 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. - */ - -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(B_L, &ep->result, T("")); - -/* - * Allocate a new evaluation block, and save the old one - */ - oldBlock = ep->input; - ejLexOpenScript(ep, script); - -/* - * 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); - -/* - * Return any error string to the user - */ - if (state == STATE_ERR && emsg) { - *emsg = bstrdup(B_L, ep->error); - } - -/* - * Restore the old evaluation block - */ - ep->input = oldBlock; - - if (state == STATE_EOF) { - return ep->result; - } - - if (state == STATE_ERR) { - return NULL; - } - - return ep->result; -} - -/******************************************************************************/ -/* - * Recursive descent parser for Ejscript - */ - -static int parse(ej_t *ep, int state, int flags) -{ - a_assert(ep); - - switch (state) { -/* - * 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: - if ((state = parseStmt(ep, state, flags)) != STATE_DEC_DONE && - state != STATE_EOF) { - state = STATE_ERR; - } - break; - - case STATE_EXPR: - if ((state = parseStmt(ep, state, flags)) != STATE_EXPR_DONE && - state != STATE_EOF) { - state = STATE_ERR; - } - break; - -/* - * Variable declaration list - */ - case STATE_DEC_LIST: - state = parseDeclaration(ep, state, flags); - break; - -/* - * Function argument string - */ - case STATE_ARG_LIST: - state = parseArgs(ep, state, flags); - break; - -/* - * Logical condition list (relational operations separated by &&, ||) - */ - case STATE_COND: - state = parseCond(ep, state, flags); - break; - -/* - * Expression list - */ - case STATE_RELEXP: - state = parseExpr(ep, state, flags); - break; - } - - if (state == STATE_ERR && ep->error == NULL) { - ejError(ep, T("Syntax error")); - } - return state; -} - -/******************************************************************************/ -/* - * Parse any statement including functions and simple relational operations - */ - -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, *identifier; - int done, expectSemi, thenFlags, elseFlags, tid, cond, forFlags; - int ejVarType; - - a_assert(ep); - -/* - * Set these to NULL, else we try to free them if an error occurs. - */ - endScript.putBackToken = NULL; - bodyScript.putBackToken = NULL; - incrScript.putBackToken = NULL; - condScript.putBackToken = NULL; - - expectSemi = 0; - saveFunc = NULL; - - for (done = 0; !done; ) { - tid = ejLexGetToken(ep, state); - - switch (tid) { - default: - ejLexPutbackToken(ep, TOK_EXPR, ep->token); - done++; - break; - - case TOK_ERR: - state = STATE_ERR; - done++; - break; - - case TOK_EOF: - state = STATE_EOF; - done++; - break; - - case TOK_NEWLINE: - break; - - case TOK_SEMI: -/* - * This case is when we discover no statement and just a lone ';' - */ - if (state != STATE_STMT) { - ejLexPutbackToken(ep, tid, ep->token); - } - done++; - break; - - case TOK_ID: -/* - * This could either be a reference to a variable or an assignment - */ - identifier = NULL; - 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 { - ejVarType = ejGetVar(ep->eid, identifier, &value); - if (ejVarType > 0) { - ejSetLocalVar(ep->eid, identifier, ep->result); - } else { - ejSetGlobalVar(ep->eid, identifier, ep->result); - } - } - } - - } else if (tid == TOK_INC_DEC ) { - value = NULL; - if (flags & FLAGS_EXE) { - ejVarType = ejGetVar(ep->eid, identifier, &value); - if (ejVarType < 0) { - ejError(ep, T("Undefined variable %s\n"), identifier); - goto error; - } - setString(B_L, &ep->result, value); - if (evalExpr(ep, value, (int) *ep->token, T("1")) < 0) { - state = STATE_ERR; - break; - } - - if (ejVarType > 0) { - ejSetLocalVar(ep->eid, identifier, ep->result); - } else { - ejSetGlobalVar(ep->eid, identifier, ep->result); - } - } - - } else { -/* - * If we are processing a declaration, allow undefined vars - */ - value = NULL; - if (state == STATE_DEC) { - if (ejGetVar(ep->eid, identifier, &value) > 0) { - ejError(ep, T("Variable already declared"), - identifier); - clearString(&identifier); - goto error; - } - ejSetLocalVar(ep->eid, identifier, NULL); - } else { - if ( flags & FLAGS_EXE ) { - if (ejGetVar(ep->eid, identifier, &value) < 0) { - ejError(ep, T("Undefined variable %s\n"), - identifier); - clearString(&identifier); - goto error; - } - } - } - setString(B_L, &ep->result, value); - ejLexPutbackToken(ep, tid, ep->token); - } - clearString(&identifier); - - if (state == STATE_STMT) { - expectSemi++; - } - done++; - break; - - case TOK_LITERAL: -/* - * Set the result to the literal (number or string constant) - */ - setString(B_L, &ep->result, ep->token); - if (state == STATE_STMT) { - expectSemi++; - } - done++; - break; - - case TOK_FUNCTION: -/* - * We must save any current ep->func value for the current stack frame - */ - if (ep->func) { - saveFunc = ep->func; - } - memset(&func, 0, sizeof(ejfunc_t)); - setString(B_L, &func.fname, ep->token); - ep->func = &func; - - setString(B_L, &ep->result, T("")); - if (ejLexGetToken(ep, state) != TOK_LPAREN) { - freeFunc(&func); - goto error; - } - - if (parse(ep, STATE_ARG_LIST, flags) != STATE_ARG_LIST_DONE) { - freeFunc(&func); - ep->func = saveFunc; - goto error; - } -/* - * Evaluate the function if required - */ - if (flags & FLAGS_EXE && evalFunction(ep) < 0) { - freeFunc(&func); - ep->func = saveFunc; - goto error; - } - - freeFunc(&func); - ep->func = saveFunc; - - if (ejLexGetToken(ep, state) != TOK_RPAREN) { - goto error; - } - if (state == STATE_STMT) { - expectSemi++; - } - done++; - break; - - case TOK_IF: - if (state != STATE_STMT) { - goto error; - } - if (ejLexGetToken(ep, state) != TOK_LPAREN) { - goto error; - } -/* - * Evaluate the entire condition list "(condition)" - */ - if (parse(ep, STATE_COND, flags) != STATE_COND_DONE) { - goto error; - } - if (ejLexGetToken(ep, state) != TOK_RPAREN) { - goto error; - } -/* - * This is the "then" case. We need to always parse both cases and - * execute only the relevant case. - */ - if (*ep->result == '1') { - thenFlags = flags; - elseFlags = flags & ~FLAGS_EXE; - } else { - thenFlags = flags & ~FLAGS_EXE; - elseFlags = flags; - } -/* - * Process the "then" case. Allow for RETURN statement - */ - 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); - done++; - break; - } -/* - * Process the "else" case. Allow for return. - */ - switch (parse(ep, STATE_STMT, elseFlags)) { - case STATE_RET: - return STATE_RET; - case STATE_STMT_DONE: - break; - default: - goto error; - } - done++; - break; - - case TOK_FOR: -/* - * Format for the expression is: - * - * for (initial; condition; incr) { - * body; - * } - */ - if (state != STATE_STMT) { - goto error; - } - if (ejLexGetToken(ep, state) != TOK_LPAREN) { - goto error; - } - -/* - * Evaluate the for loop initialization statement - */ - if (parse(ep, STATE_EXPR, flags) != STATE_EXPR_DONE) { - goto error; - } - if (ejLexGetToken(ep, state) != TOK_SEMI) { - goto error; - } - -/* - * 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. - */ - ejLexSaveInputState(ep, &condScript); - if (parse(ep, STATE_COND, flags) != STATE_COND_DONE) { - goto error; - } - cond = (*ep->result != '0'); - - if (ejLexGetToken(ep, state) != TOK_SEMI) { - goto error; - } - -/* - * Don't execute the loop increment statement or the body first time - */ - forFlags = flags & ~FLAGS_EXE; - ejLexSaveInputState(ep, &incrScript); - if (parse(ep, STATE_EXPR, forFlags) != STATE_EXPR_DONE) { - goto error; - } - if (ejLexGetToken(ep, state) != TOK_RPAREN) { - goto error; - } - -/* - * Parse the body and remember the end of the body script - */ - ejLexSaveInputState(ep, &bodyScript); - if (parse(ep, STATE_STMT, forFlags) != STATE_STMT_DONE) { - goto error; - } - ejLexSaveInputState(ep, &endScript); - -/* - * Now actually do the for loop. Note loop has been rotated - */ - while (cond && (flags & FLAGS_EXE) ) { -/* - * Evaluate the body - */ - ejLexRestoreInputState(ep, &bodyScript); - - switch (parse(ep, STATE_STMT, flags)) { - case STATE_RET: - return STATE_RET; - case STATE_STMT_DONE: - break; - default: - goto error; - } -/* - * Evaluate the increment script - */ - ejLexRestoreInputState(ep, &incrScript); - if (parse(ep, STATE_EXPR, flags) != STATE_EXPR_DONE) { - goto error; - } -/* - * Evaluate the condition - */ - ejLexRestoreInputState(ep, &condScript); - if (parse(ep, STATE_COND, flags) != STATE_COND_DONE) { - goto error; - } - cond = (*ep->result != '0'); - } - ejLexRestoreInputState(ep, &endScript); - done++; - break; - - case TOK_VAR: - if (parse(ep, STATE_DEC_LIST, flags) != STATE_DEC_LIST_DONE) { - goto error; - } - done++; - break; - - case TOK_COMMA: - ejLexPutbackToken(ep, TOK_EXPR, ep->token); - done++; - break; - - case TOK_LPAREN: - if (state == STATE_EXPR) { - if (parse(ep, STATE_RELEXP, flags) != STATE_RELEXP_DONE) { - goto error; - } - if (ejLexGetToken(ep, state) != TOK_RPAREN) { - goto error; - } - return STATE_EXPR_DONE; - } - done++; - break; - - case TOK_RPAREN: - ejLexPutbackToken(ep, tid, ep->token); - return STATE_EXPR_DONE; - - case TOK_LBRACE: -/* - * This handles any code in braces except "if () {} else {}" - */ - if (state != STATE_STMT) { - goto error; - } - -/* - * Parse will return STATE_STMT_BLOCK_DONE when the RBRACE is seen - */ - do { - 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; - } - return STATE_STMT_DONE; - - case TOK_RBRACE: - if (state == STATE_STMT) { - ejLexPutbackToken(ep, tid, ep->token); - return STATE_STMT_BLOCK_DONE; - } - goto error; - - case TOK_RETURN: - if (parse(ep, STATE_RELEXP, flags) != STATE_RELEXP_DONE) { - goto error; - } - if (flags & FLAGS_EXE) { - while ( ejLexGetToken(ep, state) != TOK_EOF ); - done++; - return STATE_RET; - } - break; - } - } - - if (expectSemi) { - tid = ejLexGetToken(ep, state); - if (tid != TOK_SEMI && tid != TOK_NEWLINE) { - goto error; - } - -/* - * Skip newline after semi-colon - */ - ejRemoveNewlines(ep, state); - } - -/* - * Free resources and return the correct status - */ -doneParse: - if (tid == TOK_FOR) { - ejLexFreeInputState(ep, &condScript); - ejLexFreeInputState(ep, &incrScript); - ejLexFreeInputState(ep, &endScript); - ejLexFreeInputState(ep, &bodyScript); - } - - if (state == STATE_STMT) { - return STATE_STMT_DONE; - } else if (state == STATE_DEC) { - return STATE_DEC_DONE; - } else if (state == STATE_EXPR) { - return STATE_EXPR_DONE; - } else if (state == STATE_EOF) { - return state; - } else { - return STATE_ERR; - } - -/* - * Common error exit - */ -error: - state = STATE_ERR; - goto doneParse; -} - -/******************************************************************************/ -/* - * Parse variable declaration list - */ - -static int parseDeclaration(ej_t *ep, int state, int flags) -{ - int tid; - - a_assert(ep); - -/* - * Declarations can be of the following forms: - * var x; - * var x, y, z; - * var x = 1 + 2 / 3, y = 2 + 4; - * - * We set the variable to NULL if there is no associated assignment. - */ - - do { - if ((tid = ejLexGetToken(ep, state)) != TOK_ID) { - return STATE_ERR; - } - ejLexPutbackToken(ep, tid, ep->token); - -/* - * Parse the entire assignment or simple identifier declaration - */ - if (parse(ep, STATE_DEC, flags) != STATE_DEC_DONE) { - return STATE_ERR; - } - -/* - * Peek at the next token, continue if comma seen - */ - tid = ejLexGetToken(ep, state); - if (tid == TOK_SEMI) { - return STATE_DEC_LIST_DONE; - } else if (tid != TOK_COMMA) { - return STATE_ERR; - } - } while (tid == TOK_COMMA); - - if (tid != TOK_SEMI) { - return STATE_ERR; - } - return STATE_DEC_LIST_DONE; -} - -/******************************************************************************/ -/* - * Parse function arguments - */ - -static int parseArgs(ej_t *ep, int state, int flags) -{ - int tid, aid; - - a_assert(ep); - - do { - state = parse(ep, STATE_RELEXP, flags); - if (state == STATE_EOF || state == STATE_ERR) { - return state; - } - if (state == STATE_RELEXP_DONE) { - aid = hAlloc((void***) &ep->func->args); - ep->func->args[aid] = bstrdup(B_L, ep->result); - ep->func->nArgs++; - } -/* - * Peek at the next token, continue if more args (ie. comma seen) - */ - tid = ejLexGetToken(ep, state); - if (tid != TOK_COMMA) { - ejLexPutbackToken(ep, tid, ep->token); - } - } while (tid == TOK_COMMA); - - if (tid != TOK_RPAREN && state != STATE_RELEXP_DONE) { - return STATE_ERR; - } - return STATE_ARG_LIST_DONE; -} - -/******************************************************************************/ -/* - * Parse conditional expression (relational ops separated by ||, &&) - */ - -static int parseCond(ej_t *ep, int state, int flags) -{ - char_t *lhs, *rhs; - int tid, operator; - - a_assert(ep); - - setString(B_L, &ep->result, T("")); - rhs = lhs = NULL; - operator = 0; - - do { -/* - * Recurse to handle one side of a conditional. Accumulate the - * left hand side and the final result in ep->result. - */ - state = parse(ep, STATE_RELEXP, flags); - if (state != STATE_RELEXP_DONE) { - state = STATE_ERR; - break; - } - - if (operator > 0) { - setString(B_L, &rhs, ep->result); - if (evalCond(ep, lhs, operator, rhs) < 0) { - state = STATE_ERR; - break; - } - } - setString(B_L, &lhs, ep->result); - - tid = ejLexGetToken(ep, state); - if (tid == TOK_LOGICAL) { - operator = (int) *ep->token; - - } else if (tid == TOK_RPAREN || tid == TOK_SEMI) { - ejLexPutbackToken(ep, tid, ep->token); - state = STATE_COND_DONE; - break; - - } else { - ejLexPutbackToken(ep, tid, ep->token); - } - - } while (state == STATE_RELEXP_DONE); - - if (lhs) { - bfree(B_L, lhs); - } - - if (rhs) { - bfree(B_L, rhs); - } - return state; -} - -/******************************************************************************/ -/* - * Parse expression (leftHandSide operator rightHandSide) - */ - -static int parseExpr(ej_t *ep, int state, int flags) -{ - char_t *lhs, *rhs; - int rel, tid; - - a_assert(ep); - - 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. - */ - 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; - } - } - - 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); - - if ((tid = ejLexGetToken(ep, state)) == TOK_EXPR || - tid == TOK_INC_DEC || tid == TOK_LOGICAL) { - rel = (int) *ep->token; - - } else { - ejLexPutbackToken(ep, tid, ep->token); - state = STATE_RELEXP_DONE; - } - - } while (state == STATE_EXPR_DONE); - - if (rhs) { - bfree(B_L, rhs); - } - - if (lhs) { - bfree(B_L, lhs); - } - - return state; -} - -/******************************************************************************/ -/* - * Evaluate a condition. Implements &&, ||, ! - */ - -static int evalCond(ej_t *ep, char_t *lhs, int rel, char_t *rhs) -{ - char_t buf[16]; - int l, r, lval; - - a_assert(lhs); - a_assert(rhs); - a_assert(rel > 0); - - lval = 0; - if (gisdigit((unsigned char)*lhs) && gisdigit((unsigned char)*rhs)) { - l = gatoi(lhs); - r = gatoi(rhs); - switch (rel) { - case COND_AND: - lval = l && r; - break; - case COND_OR: - lval = l || r; - break; - default: - ejError(ep, T("Bad operator %d"), rel); - return -1; - } - } else { - if (!gisdigit((unsigned char)*lhs)) { - ejError(ep, T("Conditional must be numeric"), lhs); - } else { - ejError(ep, T("Conditional must be numeric"), rhs); - } - } - - stritoa(lval, buf, sizeof(buf)); - setString(B_L, &ep->result, buf); - return 0; -} - -/******************************************************************************/ -/* - * Evaluate an operation - */ - -static int evalExpr(ej_t *ep, char_t *lhs, int rel, char_t *rhs) -{ - char_t *cp, buf[16]; - int numeric, l, r, lval; - - a_assert(lhs); - a_assert(rhs); - a_assert(rel > 0); - -/* - * All of the characters in the lhs and rhs must be numeric - */ - numeric = 1; - for (cp = lhs; *cp; cp++) { - if (!gisdigit((unsigned char)*cp)) { - numeric = 0; - break; - } - } - - if (numeric) { - for (cp = rhs; *cp; cp++) { - if (!gisdigit((unsigned char)*cp)) { - numeric = 0; - break; - } - } - } - - if (numeric) { - l = gatoi(lhs); - r = gatoi(rhs); - switch (rel) { - case EXPR_PLUS: - lval = l + r; - break; - case EXPR_INC: - lval = l + 1; - break; - case EXPR_MINUS: - lval = l - r; - break; - case EXPR_DEC: - lval = l - 1; - break; - case EXPR_MUL: - lval = l * r; - break; - case EXPR_DIV: - if (r != 0) { - lval = l / r; - } else { - lval = 0; - } - break; - case EXPR_MOD: - if (r != 0) { - lval = l % r; - } else { - lval = 0; - } - break; - case EXPR_LSHIFT: - lval = l << r; - break; - case EXPR_RSHIFT: - lval = l >> r; - break; - case EXPR_EQ: - lval = l == r; - break; - case EXPR_NOTEQ: - lval = l != r; - break; - case EXPR_LESS: - lval = (l < r) ? 1 : 0; - break; - case EXPR_LESSEQ: - lval = (l <= r) ? 1 : 0; - break; - case EXPR_GREATER: - lval = (l > r) ? 1 : 0; - break; - 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; - } - - } else { - switch (rel) { - case EXPR_PLUS: - clearString(&ep->result); - appendString(&ep->result, lhs); - appendString(&ep->result, rhs); - return 0; - case EXPR_LESS: - lval = gstrcmp(lhs, rhs) < 0; - break; - case EXPR_LESSEQ: - lval = gstrcmp(lhs, rhs) <= 0; - break; - case EXPR_GREATER: - lval = gstrcmp(lhs, rhs) > 0; - break; - case EXPR_GREATEREQ: - lval = gstrcmp(lhs, rhs) >= 0; - break; - case EXPR_EQ: - lval = gstrcmp(lhs, rhs) == 0; - break; - case EXPR_NOTEQ: - lval = gstrcmp(lhs, rhs) != 0; - break; - case EXPR_INC: - case EXPR_DEC: - case EXPR_MINUS: - case EXPR_DIV: - case EXPR_MOD: - case EXPR_LSHIFT: - case EXPR_RSHIFT: - default: - ejError(ep, T("Bad operator")); - return -1; - } - } - - stritoa(lval, buf, sizeof(buf)); - setString(B_L, &ep->result, buf); - return 0; -} - -/******************************************************************************/ -/* - * Evaluate a function - */ - -static int evalFunction(ej_t *ep) -{ - sym_t *sp; - int (*fn)(int eid, void *handle, int argc, char_t **argv); - - if ((sp = symLookup(ep->functions, ep->func->fname)) == NULL) { - 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, - ep->func->args); -} - -/******************************************************************************/ -/* - * Output a parse ej_error message - */ - -void ejError(ej_t* ep, char_t* fmt, ...) -{ - va_list args; - ejinput_t *ip; - char_t *errbuf, *msgbuf; - - a_assert(ep); - a_assert(fmt); - ip = ep->input; - - va_start(args, fmt); - msgbuf = NULL; - fmtValloc(&msgbuf, E_MAX_ERROR, fmt, args); - va_end(args); - - if (ep && ip) { - 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; - } - bfreeSafe(B_L, msgbuf); -} - -/******************************************************************************/ -/* - * Clear a string value - */ - -static void clearString(char_t **ptr) -{ - a_assert(ptr); - - if (*ptr) { - bfree(B_L, *ptr); - } - *ptr = NULL; -} - -/******************************************************************************/ -/* - * Set a string value - */ - -static void setString(B_ARGS_DEC, char_t **ptr, char_t *s) -{ - a_assert(ptr); - - if (*ptr) { - bfree(B_ARGS, *ptr); - } - *ptr = bstrdup(B_ARGS, s); -} - -/******************************************************************************/ -/* - * Append to the pointer value - */ - -static void appendString(char_t **ptr, char_t *s) -{ - int len, oldlen; - - a_assert(ptr); - - if (*ptr) { - len = gstrlen(s); - oldlen = gstrlen(*ptr); - *ptr = brealloc(B_L, *ptr, (len + oldlen + 1) * sizeof(char_t)); - gstrcpy(&(*ptr)[oldlen], s); - } else { - *ptr = bstrdup(B_L, s); - } -} - -/******************************************************************************/ -/* - * Define a function - */ - -int ejSetGlobalFunction(int eid, char_t *name, - int (*fn)(int eid, void *handle, int argc, char_t **argv)) -{ - ej_t *ep; - - if ((ep = ejPtr(eid)) == NULL) { - return -1; - } - return ejSetGlobalFunctionDirect(ep->functions, name, fn); -} - -/******************************************************************************/ -/* - * Define a function directly into the function symbol table. - */ - -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) { - return -1; - } - 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 - */ - -void *ejGetGlobalFunction(int eid, char_t *name) -{ - ej_t *ep; - sym_t *sp; - int (*fn)(int eid, void *handle, int argc, char_t **argv); - - 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; - } - return NULL; -} - -/******************************************************************************/ -/* - * Utility routine to crack Ejscript arguments. Return the number of args - * seen. This routine only supports %s and %d type args. - * - * Typical usage: - * - * if (ejArgs(argc, argv, "%s %d", &name, &age) < 2) { - * error("Insufficient args\n"); - * return -1; - * } - */ - -int ejArgs(int argc, char_t **argv, char_t *fmt, ...) -{ - va_list vargs; - char_t *cp, **sp; - int *ip; - int argn; - - va_start(vargs, fmt); - - if (argv == NULL) { - return 0; - } - - for (argn = 0, cp = fmt; cp && *cp && argv[argn]; ) { - if (*cp++ != '%') { - continue; - } - - switch (*cp) { - case 'd': - ip = va_arg(vargs, int*); - *ip = gatoi(argv[argn]); - break; - - case 's': - sp = va_arg(vargs, char_t**); - *sp = argv[argn]; - break; - - default: -/* - * Unsupported - */ - a_assert(0); - } - argn++; - } - - va_end(vargs); - return argn; -} - -/******************************************************************************/ -/* - * Define the user handle - */ - -void ejSetUserHandle(int eid, int handle) -{ - ej_t *ep; - - if ((ep = ejPtr(eid)) == NULL) { - return; - } - ep->userHandle = handle; -} - -/******************************************************************************/ -/* - * Get the user handle - */ - -int ejGetUserHandle(int eid) -{ - ej_t *ep; - - if ((ep = ejPtr(eid)) == NULL) { - return -1; - } - return ep->userHandle; -} - -/******************************************************************************/ -/* - * Get the current line number - */ - -int ejGetLineNumber(int eid) -{ - ej_t *ep; - - if ((ep = ejPtr(eid)) == NULL) { - return -1; - } - return ep->input->lineNumber; -} - -/******************************************************************************/ -/* - * Set the result - */ - -void ejSetResult(int eid, char_t *s) -{ - ej_t *ep; - - if ((ep = ejPtr(eid)) == NULL) { - return; - } - setString(B_L, &ep->result, s); -} - -/******************************************************************************/ -/* - * Get the result - */ - -char_t *ejGetResult(int eid) -{ - ej_t *ep; - - if ((ep = ejPtr(eid)) == NULL) { - return NULL; - } - return ep->result; -} - -/******************************************************************************/ -/* - * Set a variable. Note: a variable with a value of NULL means declared but - * undefined. The value is defined in the top-most variable frame. - */ - -void ejSetVar(int eid, char_t *var, char_t *value) -{ - ej_t *ep; - value_t v; - - a_assert(var && *var); - - if ((ep = ejPtr(eid)) == NULL) { - return; - } - - if (value == NULL) { - v = valueString(value, 0); - } else { - v = valueString(value, VALUE_ALLOCATE); - } - symEnter(ep->variables[ep->variableMax - 1] - EJ_OFFSET, var, v, 0); -} - -/******************************************************************************/ -/* - * Set a local variable. Note: a variable with a value of NULL means - * declared but undefined. The value is defined in the top-most variable frame. - */ - -void ejSetLocalVar(int eid, char_t *var, char_t *value) -{ - ej_t *ep; - value_t v; - - a_assert(var && *var); - - if ((ep = ejPtr(eid)) == NULL) { - return; - } - - if (value == NULL) { - v = valueString(value, 0); - } else { - v = valueString(value, VALUE_ALLOCATE); - } - symEnter(ep->variables[ep->variableMax - 1] - EJ_OFFSET, var, v, 0); -} - -/******************************************************************************/ -/* - * 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. - */ - -void ejSetGlobalVar(int eid, char_t *var, char_t *value) -{ - ej_t *ep; - value_t v; - - a_assert(var && *var); - - if ((ep = ejPtr(eid)) == NULL) { - return; - } - - if (value == NULL) { - v = valueString(value, 0); - } else { - v = valueString(value, VALUE_ALLOCATE); - } - symEnter(ep->variables[0] - EJ_OFFSET, var, v, 0); -} - -/******************************************************************************/ -/* - * Get a variable - */ - -int ejGetVar(int eid, char_t *var, char_t **value) -{ - ej_t *ep; - sym_t *sp; - int i; - - a_assert(var && *var); - a_assert(value); - - if ((ep = ejPtr(eid)) == NULL) { - return -1; - } - - 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; -} - -/******************************************************************************/ -/* - * Get the variable symbol table - */ - -sym_fd_t ejGetVariableTable(int eid) -{ - ej_t *ep; - - if ((ep = ejPtr(eid)) == NULL) { - return -1; - } - return *ep->variables; -} - -/******************************************************************************/ -/* - * Get the functions symbol table - */ - -sym_fd_t ejGetFunctionTable(int eid) -{ - ej_t *ep; - - if ((ep = ejPtr(eid)) == NULL) { - return -1; - } - return ep->functions; -} - -/******************************************************************************/ -/* - * Free an argument list - */ - -static void freeFunc(ejfunc_t *func) -{ - int i; - - for (i = func->nArgs - 1; i >= 0; i--) { - bfree(B_L, func->args[i]); - func->nArgs = hFree((void***) &func->args, i); - } - - if (func->fname) { - bfree(B_L, func->fname); - func->fname = NULL; - } -} - -/******************************************************************************/ -/* - * Get Ejscript pointer - */ - -static ej_t *ejPtr(int eid) -{ - a_assert(0 <= eid && eid < ejMax); - - if (eid < 0 || eid >= ejMax || ejHandles[eid] == NULL) { - ejError(NULL, T("Bad handle %d"), eid); - return NULL; - } - return ejHandles[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); -} - -/******************************************************************************/ diff --git a/cpukit/httpd/emfdb.c b/cpukit/httpd/emfdb.c deleted file mode 100644 index e3a8072d0f..0000000000 --- a/cpukit/httpd/emfdb.c +++ /dev/null @@ -1,1050 +0,0 @@ -/* - * emfdb.c -- 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 *********************************/ -/* - * Textfile-based database support for WebServer 2.1. - */ - -/********************************* Includes ***********************************/ - -#include "emfdb.h" -#include "wsIntrn.h" - -/********************************* Defines ************************************/ - -#define KEYWORD_TABLE T("TABLE") -#define KEYWORD_ROW T("ROW") - -/*********************************** Locals ***********************************/ - -/* - * Variable to support the basicSet and basicGet functions. - */ - -static char_t *basicProdDir = NULL; -static char_t *basicDefaultDir = T("."); /* Default set to current */ - -/* - * hAlloc chain list of table schemas to be closed - */ - -static int dbMaxTables = 0; -static dbTable_t **dbListTables = NULL; - -/****************************** Forward Declarations **************************/ - -static int crack(char_t *buf, char_t **key, char_t **val); -static char_t *trim(char_t *str); -static int GetColumnIndex(int tid, char_t *colName); - -/******************************************************************************/ -/* - * Add a schema to the module-internal schema database - */ - -int dbRegisterDBSchema(dbTable_t *pTableRegister) -{ - dbTable_t *pTable; - int tid; - - a_assert(pTableRegister); - - trace(4, T("DB: Registering database table <%s>\n"), - pTableRegister->name); - -/* - * Bump up the size of the table array - */ - tid = hAllocEntry((void*) &dbListTables, - &dbMaxTables, sizeof(dbTable_t)); - -/* - * Copy the table schema to the last spot in schema array - */ - a_assert(dbListTables); - pTable = dbListTables[tid]; - a_assert(pTable); - -/* - * Copy the name of the table - */ - pTable->name = bstrdup(B_L, pTableRegister->name); - -/* - * Copy the number of columns - */ - pTable->nColumns = pTableRegister->nColumns; - -/* - * Copy the column definitions - */ - if (pTable->nColumns > 0) { - int i; - pTable->columnNames = balloc(B_L, sizeof(char_t *) * pTable->nColumns); - pTable->columnTypes = balloc(B_L, sizeof(int *) * pTable->nColumns); - - for (i = 0; (i < pTableRegister->nColumns); i++) { - pTable->columnNames[i] = - bstrdup(B_L, pTableRegister->columnNames[i]); - pTable->columnTypes[i] = pTableRegister->columnTypes[i]; - } - - } else { - pTable->columnNames = NULL; - pTable->columnTypes = NULL; - } - -/* - * Zero out the table's data (very important!) - */ - pTable->nRows = 0; - pTable->rows = NULL; - - return 0; -} - -/******************************************************************************/ -/* - * This is provided for compatibility with EMF. Tables are "registered" - * with staticly defined schemas. There is only one did in this package: 0. - */ - -int dbOpen(char_t *tablename, char_t *filename, - int (*gettime)(int did), int flags) -{ - basicProdDir = NULL; - basicDefaultDir = T("."); - dbMaxTables = 0; - dbListTables = NULL; - return 0; -} - -/******************************************************************************/ -/* - * Delete all the rows of the tables, and all of the tables - */ - -void dbClose(int did) -{ - int table, column; - dbTable_t *pTable; - -/* - * Before doing anything, delete all the contents of the database - */ - dbZero(did); - -/* - * Now delete the tables - */ - for (table = 0; table < dbMaxTables; table++) { - pTable = dbListTables[table]; - - if (pTable != NULL) { -/* - * Delete the table schema - */ - if (pTable->nColumns) { - for (column = 0; column < pTable->nColumns; column++) { - bfreeSafe(B_L, pTable->columnNames[column]); - } - bfreeSafe(B_L, pTable->columnNames); - bfreeSafe(B_L, pTable->columnTypes); - } -/* - * Delete the table name - */ - bfreeSafe(B_L, pTable->name); -/* - * Free the table - */ - bfreeSafe(B_L, pTable); - hFree((void *) &dbListTables, table); - } - } - - if (dbListTables) { - bfree(B_L, dbListTables); - } - -/* - * Set the global table list to a safe value - */ - dbListTables = NULL; - dbMaxTables = 0; -} - - -/******************************************************************************/ -/* - * Delete all the data records in all tables - */ - -void dbZero(int did) -{ - int table, row, column, nRows, nColumns; - int *pRow; - dbTable_t *pTable; - -/* - * Delete all data from all tables - */ - for (table = 0; table < dbMaxTables; table++) { - pTable = dbListTables[table]; -/* - * Delete the row data contained within the schema - */ - if (pTable) { - nColumns = pTable->nColumns; - nRows = pTable->nRows; - for (row = 0; row < nRows; row++) { - pRow = pTable->rows[row]; - if (pRow) { -/* - * Only delete the contents of rows not previously deleted! - */ - for (column = 0; column < nColumns; column++) { - if (pTable->columnTypes[column] == T_STRING) { - bfreeSafe(B_L, (char_t *)(pRow[column])); - pRow[column] = (int)NULL; - } - } - - bfreeSafe(B_L, pRow); - hFree((void ***) &pTable->rows, row); - } - } - - pTable->rows = NULL; - pTable->nRows = 0; - } - } -} - -/******************************************************************************/ -/* - * Find the a row in the table with the given string in the given column - */ - -int dbSearchStr(int did, char_t *tablename, - char_t *colName, char_t *value, int flags) -{ - int tid, nRows, nColumns, column; - dbTable_t *pTable; - - a_assert(tablename); - a_assert(colName); - a_assert(value); - - tid = dbGetTableId(0, tablename); - a_assert(tid >= 0); - - if ((tid >= 0) && (tid < dbMaxTables) && (dbListTables[tid] != NULL)) { - pTable = dbListTables[tid]; - } else { - return DB_ERR_TABLE_NOT_FOUND; - } - - nColumns = pTable->nColumns; - nRows = pTable->nRows; - column = GetColumnIndex(tid, colName); - a_assert (column >= 0); - - if (column >= 0) { - char_t *compareVal; - int row, *pRow; -/* - * Scan through rows until we find a match. - * Note that some of these rows may be deleted! - */ - row = 0; - while (row < nRows) { - pRow = pTable->rows[row]; - if (pRow) { - compareVal = (char_t *)(pRow[column]); - if (compareVal && (gstrcmp(compareVal, value) == 0)) { - return row; - } - } - row++; - } - } else { -/* - * Return -2 if search column was not found - */ - trace(3, T("DB: Unable to find column <%s> in table <%s>\n"), - colName, tablename); - return DB_ERR_COL_NOT_FOUND; - } - - return -1; -} - -/******************************************************************************/ -/* - * Add a new row to the given table. Return the new row ID. - */ - -int dbAddRow(int did, char_t *tablename) -{ - int tid, size; - dbTable_t *pTable; - - a_assert(tablename); - - tid = dbGetTableId(0, tablename); - a_assert(tid >= 0); - - if ((tid >= 0) && (tid < dbMaxTables) && (dbListTables[tid] != NULL)) { - pTable = dbListTables[tid]; - } else { - return DB_ERR_TABLE_NOT_FOUND; - } - - a_assert(pTable); - - if (pTable) { - trace(5, T("DB: Adding a row to table <%s>\n"), tablename); - - size = pTable->nColumns * max(sizeof(int), sizeof(char_t *)); - return hAllocEntry((void***) &(pTable->rows), &(pTable->nRows), size); - } - - return -1; -} - -/******************************************************************************/ -/* - * Delete a row in the table. - */ - -int dbDeleteRow(int did, char_t *tablename, int row) -{ - int tid, nColumns, nRows; - dbTable_t *pTable; - - a_assert(tablename); - tid = dbGetTableId(0, tablename); - a_assert(tid >= 0); - - if ((tid >= 0) && (tid < dbMaxTables) && (dbListTables[tid] != NULL)) { - pTable = dbListTables[tid]; - } else { - return DB_ERR_TABLE_NOT_FOUND; - } - - nColumns = pTable->nColumns; - nRows = pTable->nRows; - - if ((row >= 0) && (row < nRows)) { - int *pRow = pTable->rows[row]; - - if (pRow) { - int column = 0; -/* - * Free up any allocated strings - */ - while (column < nColumns) { - if (pRow[column] && - (pTable->columnTypes[column] == T_STRING)) { - bfree(B_L, (char_t *)pRow[column]); - } - - column++; - } -/* - * Zero out the row for safety - */ - memset(pRow, 0, nColumns * max(sizeof(int), sizeof(char_t *))); - - bfreeSafe(B_L, pRow); - pTable->nRows = hFree((void ***)&pTable->rows, row); - trace(5, T("DB: Deleted row <%d> from table <%s>\n"), - row, tablename); - } - return 0; - } else { - trace(3, T("DB: Unable to delete row <%d> from table <%s>\n"), - row, tablename); - } - - return -1; -} - -/*****************************************************************************/ -/* - * Grow the rows in the table to the nominated size. - */ - -int dbSetTableNrow(int did, char_t *tablename, int nNewRows) -{ - int nRet, tid, nRows, nColumns; - dbTable_t *pTable; - - a_assert(tablename); - tid = dbGetTableId(0, tablename); - a_assert(tid >= 0) ; - - if ((tid >= 0) && (tid < dbMaxTables) && (dbListTables[tid] != NULL)) { - pTable = dbListTables[tid]; - } else { - return DB_ERR_TABLE_NOT_FOUND; - } - - nRet = -1; - - a_assert(pTable); - if (pTable) { - nColumns = pTable->nColumns; - nRows = pTable->nRows; - nRet = 0; - - if (nRows >= nNewRows) { -/* - * If number of rows already allocated exceeds requested number, do nothing - */ - trace(4, T("DB: Ignoring row set to <%d> in table <%s>\n"), - nNewRows, tablename); - } else { - trace(4, T("DB: Setting rows to <%d> in table <%s>\n"), - nNewRows, tablename); - while (pTable->nRows < nNewRows) { - if (dbAddRow(did, tablename) < 0) { - return -1; - } - } - } - } - - return nRet; -} - -/******************************************************************************/ -/* - * Return the number of rows in the given table - */ - -int dbGetTableNrow(int did, char_t *tablename) -{ - int tid; - - a_assert(tablename); - tid = dbGetTableId(did, tablename); - - if ((tid >= 0) && (tid < dbMaxTables) && (dbListTables[tid] != NULL)) { - return (dbListTables[tid])->nRows; - } else { - return -1; - } -} - -/******************************************************************************/ -/* - * Do table driven read of the database - */ - -int dbReadInt(int did, char_t *table, char_t *column, int row, int *returnValue) -{ - int colIndex, *pRow, tid; - dbTable_t *pTable; - - a_assert(table); - a_assert(column); - a_assert(returnValue); - - tid = dbGetTableId(0, table); - a_assert(tid >= 0); - -/* - * Return -6 if table is not found - */ - if (tid < 0) { - return DB_ERR_TABLE_NOT_FOUND; - } - -/* - * Return -7 if table id has been deleted - */ - pTable = dbListTables[tid]; - if (pTable == NULL) { - return DB_ERR_TABLE_DELETED; - } - - a_assert(row >= 0); - - if ((row >= 0) && (row < pTable->nRows)) { - colIndex = GetColumnIndex(tid, column); - a_assert(colIndex >= 0); - - if (colIndex >= 0) { - pRow = pTable->rows[row]; - if (pRow) { - *returnValue = pRow[colIndex]; - return 0; - } - return DB_ERR_ROW_DELETED; - } - return DB_ERR_COL_NOT_FOUND; - } - - return DB_ERR_ROW_NOT_FOUND; -} - -/******************************************************************************/ -/* - * dbReadStr calls dbReadInt to do table driven read of database - */ - -int dbReadStr(int did, char_t *table, char_t *column, int row, - char_t **returnValue) -{ - return dbReadInt(did, table, column, row, (int *)returnValue); -} - -/******************************************************************************/ -/* - * The dbWriteInt function writes a value into a table at a given row and - * column. The existence of the row and column is verified before the - * write. 0 is returned on succes, -1 is returned on error. - */ - -int dbWriteInt(int did, char_t *table, char_t *column, int row, int iData) -{ - int tid, colIndex, *pRow; - dbTable_t *pTable; - - a_assert(table); - a_assert(column); - -/* - * Make sure that this table exists - */ - tid = dbGetTableId(0, table); - a_assert(tid >= 0); - - if (tid < 0) { - return DB_ERR_TABLE_NOT_FOUND; - } - - pTable = dbListTables[tid]; - - if (pTable) { -/* - * Make sure that the column exists - */ - colIndex = GetColumnIndex(tid, column); - a_assert(colIndex >= 0); - if (colIndex >= 0) { -/* - * Make sure that the row exists - */ - a_assert((row >= 0) && (row < pTable->nRows)); - if ((row >= 0) && (row < pTable->nRows)) { - pRow = pTable->rows[row]; - if (pRow) { - pRow[colIndex] = iData; - return 0; - } - return DB_ERR_ROW_DELETED; - } - return DB_ERR_ROW_NOT_FOUND; - } - return DB_ERR_COL_NOT_FOUND; - } - - return DB_ERR_TABLE_DELETED; -} - -/******************************************************************************/ -/* - * The dbWriteStr function writes a string value into a table at a given row - * and column. The existence of the row and column is verified before the - * write. The column is also checked to confirm it is a string field. - * 0 is returned on succes, -1 is returned on error. - */ - -int dbWriteStr(int did, char_t *table, char_t *column, int row, char_t *s) -{ - int tid, colIndex; - int *pRow; - char_t *ptr; - dbTable_t *pTable; - - a_assert(table); - a_assert(column); - - tid = dbGetTableId(0, table); - a_assert(tid >= 0); - - if (tid < 0) { - return DB_ERR_TABLE_NOT_FOUND; - } - -/* - * Make sure that this table exists - */ - pTable = dbListTables[tid]; - a_assert(pTable); - if (!pTable) { - return DB_ERR_TABLE_DELETED; - } - -/* - * Make sure that this column exists - */ - colIndex = GetColumnIndex(tid, column); - if (colIndex < 0) { - return DB_ERR_COL_NOT_FOUND; - } - -/* - * Make sure that this column is a string column - */ - if (pTable->columnTypes[colIndex] != T_STRING) { - return DB_ERR_BAD_FORMAT; - } - -/* - * Make sure that the row exists - */ - a_assert((row >= 0) && (row < pTable->nRows)); - if ((row >= 0) && (row < pTable->nRows)) { - pRow = pTable->rows[row]; - } else { - return DB_ERR_ROW_NOT_FOUND; - } - - if (!pRow) { - return DB_ERR_ROW_DELETED; - } - -/* - * If the column already has a value, be sure to delete it to prevent - * memory leaks. - */ - if (pRow[colIndex]) { - bfree(B_L, (char_t *) pRow[colIndex]); - } - -/* - * Make sure we make a copy of the string to write into the column. - * This allocated string will be deleted when the row is deleted. - */ - ptr = bstrdup(B_L, s); - pRow[colIndex] = (int)ptr; - - return 0; -} - -/******************************************************************************/ -/* - * Print a key-value pair to a file - */ - -static int dbWriteKeyValue(int fd, char_t *key, char_t *value) -{ - int rc; - int len; - char_t *pLineOut; - - a_assert(key && *key); - a_assert(value); - - fmtAlloc(&pLineOut, BUF_MAX, T("%s=%s\n"), key, value); - - if (pLineOut) { - len = gstrlen(pLineOut); -#ifdef CE - rc = writeUniToAsc(fd, pLineOut, len); -#else - rc = gwrite(fd, pLineOut, len); -#endif - bfree(B_L, pLineOut); - } else { - rc = -1; - } - - return rc; -} - -/******************************************************************************/ -/* - * Persist a database to a file - */ - -int dbSave(int did, char_t *filename, int flags) -{ - int row, column, nColumns, nRows, fd, rc; - int *colTypes, *pRow, nRet, tid; - char_t *path, *tmpFile, *tmpNum; - char_t **colNames; - dbTable_t *pTable; - - trace(5, T("DB: About to save database to file\n")); - - a_assert(dbMaxTables > 0); - -/* - * First write to a temporary file, then switch around later. - */ - fmtAlloc(&tmpFile, FNAMESIZE, T("%s/data.tmp"), basicGetProductDir()); - if ((fd = gopen(tmpFile, - O_CREAT | O_TRUNC | O_WRONLY | O_BINARY, 0666)) < 0) { - trace(1, T("WARNING: Failed to open file %s\n"), tmpFile); - bfree(B_L, tmpFile); - return -1; - } - - nRet = 0; - - for (tid = 0; (tid < dbMaxTables) && (nRet != -1); tid++) { - pTable = dbListTables[tid]; - - if (pTable) { -/* - * Print the TABLE=tableName directive to the file - */ - rc = dbWriteKeyValue(fd, KEYWORD_TABLE, pTable->name); - - nColumns = pTable->nColumns; - nRows = pTable->nRows; - - for (row = 0; (row < nRows) && (nRet == 0); row++) { - pRow = pTable->rows[row]; -/* - * if row is NULL, the row has been deleted, so don't - * write it out. - */ - if ((pRow == NULL) || (pRow[0] == '\0') || - (*(char_t *)(pRow[0]) == '\0')) { - continue; - } -/* - * Print the ROW=rowNumber directive to the file - */ - fmtAlloc(&tmpNum, 20, T("%d"), row); - rc = dbWriteKeyValue(fd, KEYWORD_ROW, tmpNum); - bfreeSafe(B_L, tmpNum); - - colNames = pTable->columnNames; - colTypes = pTable->columnTypes; -/* - * Print the key-value pairs (COLUMN=value) for data cells - */ - for (column = 0; (column < nColumns) && (rc >= 0); - column++, colNames++, colTypes++) { - if (*colTypes == T_STRING) { - rc = dbWriteKeyValue(fd, *colNames, - (char_t *)(pRow[column])); - } else { - fmtAlloc(&tmpNum, 20, T("%d"), pRow[column]); - rc = dbWriteKeyValue(fd, *colNames, tmpNum); - bfreeSafe(B_L, tmpNum); - } - } - - if (rc < 0) { - trace(1, T("WARNING: Failed to write to file %s\n"), - tmpFile); - nRet = -1; - } - } - } - } - - gclose(fd); - -/* - * Replace the existing file with the temporary file, if no errors - */ - if (nRet == 0) { - fmtAlloc(&path, FNAMESIZE, T("%s/%s"), basicGetProductDir(), filename); - - gunlink(path); - if (grename(tmpFile, path) != 0) { - trace(1, T("WARNING: Failed to rename %s to %s\n"), tmpFile, path); - nRet = -1; - } - - bfree(B_L, path); - } - - bfree(B_L, tmpFile); - - return nRet; -} - -/******************************************************************************/ -/* - * Crack a keyword=value string into keyword and value. We can change buf. - */ - -static int crack(char_t *buf, char_t **key, char_t **val) -{ - char_t *ptr; - - if ((ptr = gstrrchr(buf, '\n')) != NULL || - (ptr = gstrrchr(buf, '\r')) != NULL) { - *ptr = '\0'; - } - -/* - * Find the = sign. It must exist. - */ - if ((ptr = gstrstr(buf, T("="))) == NULL) { - return -1; - } - - *ptr++ = '\0'; - *key = trim(buf); - *val = trim(ptr); - - return 0; -} - -/******************************************************************************/ -/* - * Parse the file. These files consist of key-value pairs, separated by the - * "=" sign. Parsing of tables starts with the "TABLE=value" pair, and rows - * are parsed starting with the "ROW=value" pair. - */ - -int dbLoad(int did, char_t *filename, int flags) -{ - gstat_t sbuf; - char_t *buf, *keyword, *value, *path, *ptr; - char_t *tablename; - int fd, tid, row; - dbTable_t *pTable; - - a_assert(did >= 0); - - fmtAlloc(&path, FNAMESIZE, T("%s/%s"), basicGetProductDir(), filename); - trace(4, T("DB: About to read data file <%s>\n"), path); - - if (gstat(path, &sbuf) < 0) { - trace(3, T("DB: Failed to stat persistent data file.\n")); - bfree(B_L, path); - return -1; - } - - fd = gopen(path, O_RDONLY | O_BINARY, 0666); - bfree(B_L, path); - - if (fd < 0) { - trace(3, T("DB: No persistent data file present.\n")); - return -1; - } - - if (sbuf.st_size <= 0) { - trace(3, T("DB: Persistent data file is empty.\n")); - gclose(fd); - return -1; - } -/* - * Read entire file into temporary buffer - */ - buf = balloc(B_L, sbuf.st_size + 1); -#ifdef CE - if (readAscToUni(fd, &buf, sbuf.st_size) != (int)sbuf.st_size) { -#else - if (gread(fd, buf, sbuf.st_size) != (int)sbuf.st_size) { -#endif - trace(3, T("DB: Persistent data read failed.\n")); - bfree(B_L, buf); - gclose(fd); - return -1; - } - - gclose(fd); - *(buf + sbuf.st_size) = '\0'; - - row = -1; - tid = -1; - pTable = NULL; - ptr = gstrtok(buf, T("\n")); - tablename = NULL; - - do { - if (crack(ptr, &keyword, &value) < 0) { - trace(5, T("DB: Failed to crack line %s\n"), ptr); - continue; - } - - a_assert(keyword && *keyword); - - if (gstrcmp(keyword, KEYWORD_TABLE) == 0) { -/* - * Table name found, check to see if it's registered - */ - if (tablename) { - bfree(B_L, tablename); - } - - tablename = bstrdup(B_L, value); - tid = dbGetTableId(did, tablename); - - if (tid >= 0) { - pTable = dbListTables[tid]; - } else { - pTable = NULL; - } - - } else if (gstrcmp(keyword, KEYWORD_ROW) == 0) { -/* - * Row/Record indicator found, add a new row to table - */ - if (tid >= 0) { - int nRows = dbGetTableNrow(did, tablename); - - if (dbSetTableNrow(did, tablename, nRows + 1) == 0) { - row = nRows; - } - } - - } else if (row != -1) { -/* - * some other data found, assume it's a COLUMN=value - */ - int nColumn = GetColumnIndex(tid, keyword); - - if ((nColumn >= 0) && (pTable != NULL)) { - int nColumnType = pTable->columnTypes[nColumn]; - if (nColumnType == T_STRING) { - dbWriteStr(did, tablename, keyword, row, value); - } else { - dbWriteInt(did, tablename, keyword, row, gstrtoi(value)); - } - } - } - } while ((ptr = gstrtok(NULL, T("\n"))) != NULL); - - if (tablename) { - bfree(B_L, tablename); - } - - bfree(B_L, buf); - - return 0; -} - -/******************************************************************************/ -/* - * Return a table id given the table name - */ - -int dbGetTableId(int did, char_t *tablename) -{ - int tid; - dbTable_t *pTable; - - a_assert(tablename); - - for (tid = 0; (tid < dbMaxTables); tid++) { - if ((pTable = dbListTables[tid]) != NULL) { - if (gstrcmp(tablename, pTable->name) == 0) { - return tid; - } - } - } - - return -1; -} - -/******************************************************************************/ -/* - * Return a pointer to the table name, given its ID - */ - -char_t *dbGetTableName(int did, int tid) -{ - if ((tid >= 0) && (tid < dbMaxTables) && (dbListTables[tid] != NULL)) { - return (dbListTables[tid])->name; - } - - return NULL; -} - -/******************************************************************************/ -/* - * Trim leading white space. - */ - -static char_t *trim(char_t *str) -{ - while (isspace((unsigned char)*str)) { - str++; - } - return str; -} - -/******************************************************************************/ -/* - * Return a column index given the column name - */ - -static int GetColumnIndex(int tid, char_t *colName) -{ - int column; - dbTable_t *pTable; - - a_assert(colName); - - if ((tid >= 0) && (tid < dbMaxTables) && (dbListTables[tid] != NULL)) { - pTable = dbListTables[tid]; - - for (column = 0; (column < pTable->nColumns); column++) { - if (gstrcmp(colName, pTable->columnNames[column]) == 0) - return column; - } - } - - return -1; -} - -/******************************************************************************/ -/* - * Set the prefix-directory - */ - -void basicSetProductDir(char_t *proddir) -{ - int len; - - if (basicProdDir != NULL) { - bfree(B_L, basicProdDir); - } - - basicProdDir = bstrdup(B_L, proddir); -/* - * Make sure that prefix-directory doesn't end with a '/' - */ - len = gstrlen(basicProdDir); - if ((len > 0) && *(basicProdDir + len - 1) == '/') { - *(basicProdDir+len-1) = '\0'; - } -} - -/******************************************************************************/ -/* - * Return the prefix-directory - */ - -char_t *basicGetProductDir(void) -{ - if (basicProdDir) { - return basicProdDir; - } else { - return basicDefaultDir; - } -} - -/******************************************************************************/ diff --git a/cpukit/httpd/emfdb.h b/cpukit/httpd/emfdb.h deleted file mode 100644 index 5fd6e5a2d4..0000000000 --- a/cpukit/httpd/emfdb.h +++ /dev/null @@ -1,101 +0,0 @@ -/* - * 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 - -#ifndef 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(void); -extern void basicSetProductDir(char_t *proddir); - -#endif /* _h_EMFDB */ - -/******************************************************************************/ diff --git a/cpukit/httpd/form.c b/cpukit/httpd/form.c deleted file mode 100644 index fa163dbed7..0000000000 --- a/cpukit/httpd/form.c +++ /dev/null @@ -1,168 +0,0 @@ -/* - * form.c -- Form processing (in-memory CGI) for the GoAhead Web server - * - * Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved. - * - * See the file "license.txt" for usage and redistribution license requirements - * - * $Id$ - */ - -/********************************** Description *******************************/ - -/* - * This module implements the /goform handler. It emulates CGI processing - * but performs this in-process and not as an external process. This enables - * a very high performance implementation with easy parsing and decoding - * of query strings and posted data. - */ - -/*********************************** Includes *********************************/ - -#include "wsIntrn.h" - -/************************************ Locals **********************************/ - -static sym_fd_t formSymtab = -1; /* Symbol table for form handlers */ - -/************************************* Code ***********************************/ -/* - * Process a form request. Returns 1 always to indicate it handled the URL - */ - -int websFormHandler(webs_t wp, char_t *urlPrefix, char_t *webDir, int arg, - 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); - - a_assert(websValid(wp)); - a_assert(url && *url); - a_assert(path && *path == '/'); - - websStats.formHits++; - -/* - * Extract the form name - */ - gstrncpy(formBuf, path, TSZ(formBuf)); - if ((formName = gstrchr(&formBuf[1], '/')) == NULL) { - websError(wp, 200, T("Missing form name")); - return 1; - } - formName++; - if ((cp = gstrchr(formName, '/')) != NULL) { - *cp = '\0'; - } - -/* - * Lookup the C form function first and then try tcl (no javascript support - * yet). - */ - sp = symLookup(formSymtab, formName); - 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; - 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; -} - -/******************************************************************************/ -/* - * Define a form function in the "form" map space. - */ - -int websFormDefine(char_t *name, void (*fn)(webs_t wp, char_t *path, - char_t *query)) -{ - a_assert(name && *name); - a_assert(fn); - - if (fn == NULL) { - return -1; - } - - symEnter(formSymtab, name, valueInteger((int) fn), (int) NULL); - return 0; -} - -/******************************************************************************/ -/* - * Open the symbol table for forms. - */ - -void websFormOpen(void) -{ - formSymtab = symOpen(WEBS_SYM_INIT); -} - -/******************************************************************************/ -/* - * Close the symbol table for forms. - */ - -void websFormClose(void) -{ - if (formSymtab != -1) { - symClose(formSymtab); - formSymtab = -1; - } -} - -/******************************************************************************/ -/* - * Write a webs header. This is a convenience routine to write a common - * header for a form back to the browser. - */ - -void websHeader(webs_t wp) -{ - a_assert(websValid(wp)); - - websWrite(wp, T("HTTP/1.0 200 OK\n")); - -/* - * By license terms the following line of code must not be modified - */ - websWrite(wp, T("Server: %s\r\n"), WEBS_NAME); - - websWrite(wp, T("Pragma: no-cache\n")); - websWrite(wp, T("Cache-control: no-cache\n")); - websWrite(wp, T("Content-Type: text/html\n")); - websWrite(wp, T("\n")); - websWrite(wp, T("<html>\n")); -} - -/******************************************************************************/ -/* - * Write a webs footer - */ - -void websFooter(webs_t wp) -{ - a_assert(websValid(wp)); - - websWrite(wp, T("</html>\n")); -} - -/******************************************************************************/ diff --git a/cpukit/httpd/h.c b/cpukit/httpd/h.c deleted file mode 100644 index 35b0bbbae6..0000000000 --- a/cpukit/httpd/h.c +++ /dev/null @@ -1,194 +0,0 @@ -/* - * h.c -- Handle allocation module - * - * Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved. - * See the file "license.txt" for usage and redistribution license requirements - * - * $Id$ - */ - -/******************************** Description *********************************/ - -/* - * 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. - */ - -/********************************* Includes ***********************************/ - -#ifdef UEMF - #include "uemf.h" -#else - #include "basic/basicInternal.h" -#endif - -/********************************** Defines ***********************************/ -/* - * The handle list stores the length of the list and the number of used - * handles in the first two words. These are hidden from the caller by - * returning a pointer to the third word to the caller - */ - -#define H_LEN 0 /* First entry holds length of list */ -#define H_USED 1 /* Second entry holds number of used */ -#define H_OFFSET 2 /* Offset to real start of list */ - -#define H_INCR 16 /* Grow handle list in chunks this size */ - -/*********************************** Code *************************************/ -/* - * 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. - */ - -#ifdef B_STATS -int HALLOC(B_ARGS_DEC, void ***map) -#else -int hAlloc(void ***map) -#endif -{ - int *mp; - int handle, len, memsize, incr; - - a_assert(map); - - if (*map == NULL) { - incr = H_INCR; - memsize = (incr + H_OFFSET) * sizeof(void**); -#ifdef 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); - mp[H_LEN] = incr; - mp[H_USED] = 0; - *map = (void**) &mp[H_OFFSET]; - } else { - mp = &((*(int**)map)[-H_OFFSET]); - } - - len = mp[H_LEN]; - -/* - * Find the first null handle - */ - if (mp[H_USED] < mp[H_LEN]) { - for (handle = 0; handle < len; handle++) { - if (mp[handle+H_OFFSET] == 0) { - mp[H_USED]++; - return handle; - } - } - } else { - handle = len; - } - -/* - * No free handle so grow the handle list. Grow list in chunks of H_INCR. - */ - len += H_INCR; - memsize = (len + H_OFFSET) * sizeof(void**); - if ((mp = (int*) brealloc(B_L, (void*) mp, memsize)) == NULL) { - return -1; - } - *map = (void**) &mp[H_OFFSET]; - mp[H_LEN] = len; - memset(&mp[H_OFFSET + len - H_INCR], 0, sizeof(int*) * H_INCR); - mp[H_USED]++; - return handle; -} - -/******************************************************************************/ -/* - * Free a handle. This function returns the value of the largest - * handle in use plus 1, to be saved as a max value. - */ - -int hFree(void ***map, int handle) -{ - int *mp; - int len; - - a_assert(map); - mp = &((*(int**)map)[-H_OFFSET]); - a_assert(mp[H_LEN] >= H_INCR); - - a_assert(mp[handle + H_OFFSET]); - a_assert(mp[H_USED]); - mp[handle + H_OFFSET] = 0; - if (--(mp[H_USED]) == 0) { - bfree(B_L, (void*) mp); - *map = NULL; - } - -/* - * Find the greatest handle number in use. - */ - if (*map == NULL) { - handle = -1; - } else { - len = mp[H_LEN]; - if (mp[H_USED] < mp[H_LEN]) { - for (handle = len - 1; handle >= 0; handle--) { - if (mp[handle + H_OFFSET]) - break; - } - } else { - handle = len; - } - } - return handle + 1; -} - -/******************************************************************************/ -/* - * Allocate an entry in the halloc array. - */ - -#ifdef 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; - - a_assert(list); - a_assert(max); - -#ifdef B_STATS - if ((id = HALLOC(B_ARGS, (void***) list)) < 0) { -#else - if ((id = hAlloc((void***) list)) < 0) { -#endif - return -1; - } - - if (size > 0) { -#ifdef B_STATS - if ((cp = balloc(B_ARGS, size)) == NULL) { -#else - if ((cp = balloc(B_L, size)) == NULL) { -#endif - hFree(list, id); - return -1; - } - a_assert(cp); - memset(cp, 0, size); - - (*list)[id] = (void*) cp; - } - - if (id >= *max) { - *max = id + 1; - } - return id; -} - -/******************************************************************************/ diff --git a/cpukit/httpd/handler.c b/cpukit/httpd/handler.c deleted file mode 100644 index 51781a4845..0000000000 --- a/cpukit/httpd/handler.c +++ /dev/null @@ -1,411 +0,0 @@ -/* - * handler.c -- URL handler support - * - * Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved. - * - * See the file "license.txt" for usage and redistribution license requirements - * - * $Id$ - */ - -/******************************** Description *********************************/ - -/* - * This module implements a URL handler interface and API to permit - * the addition of user definable URL processors. - */ - -/********************************* Includes ***********************************/ - -#include "wsIntrn.h" - -/*********************************** Locals ***********************************/ - -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 websPublishHandler(webs_t wp, char_t *urlPrefix, char_t *webDir, - int sid, char_t *url, char_t *path, char_t *query); -static char_t *websCondenseMultipleChars(char_t *strToCondense, char_t cCondense); - -/*********************************** Code *************************************/ -/* - * Initialize the URL handler module - */ - -int websUrlHandlerOpen(void) -{ - if (++urlHandlerOpenCount == 1) { - websAspOpen(); - websUrlHandler = NULL; - websUrlHandlerMax = 0; - } - return 0; -} - -/******************************************************************************/ -/* - * Close the URL handler module - */ - -void websUrlHandlerClose(void) -{ - websUrlHandlerType *sp; - - 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; - } -} - -/******************************************************************************/ -/* - * Define a new URL handler. urlPrefix is the URL prefix to match. webDir is - * an optional root directory path for a web directory. arg is an optional - * arg to pass to the URL handler. flags defines the matching order. Valid - * flags include WEBS_HANDLER_LAST, WEBS_HANDLER_FIRST. If multiple users - * specify last or first, their order is defined alphabetically by the - * urlPrefix. - */ - -int websUrlHandlerDefine(char_t *urlPrefix, char_t *webDir, int arg, - int (*handler)(webs_t wp, char_t *urlPrefix, char_t *webdir, int arg, - char_t *url, char_t *path, char_t *query), int flags) -{ - websUrlHandlerType *sp; - int len; - - a_assert(urlPrefix); - a_assert(handler); - -/* - * Grow the URL handler array to create a new slot - */ - len = (websUrlHandlerMax + 1) * sizeof(websUrlHandlerType); - if ((websUrlHandler = brealloc(B_L, websUrlHandler, len)) == NULL) { - return -1; - } - sp = &websUrlHandler[websUrlHandlerMax++]; - memset(sp, 0, sizeof(websUrlHandlerType)); - - sp->urlPrefix = bstrdup(B_L, urlPrefix); - sp->len = gstrlen(sp->urlPrefix); - if (webDir) { - sp->webDir = bstrdup(B_L, webDir); - } else { - sp->webDir = bstrdup(B_L, T("")); - } - sp->handler = handler; - sp->arg = arg; - sp->flags = flags; - -/* - * Sort in decreasing URL length order observing the flags for first and last - */ - qsort(websUrlHandler, websUrlHandlerMax, sizeof(websUrlHandlerType), - websUrlHandlerSort); - return 0; -} - -/******************************************************************************/ -/* - * Delete an existing URL handler. We don't reclaim the space of the old - * handler, just NULL the entry. Return -1 if handler is not found. - */ - -int websUrlHandlerDelete(int (*handler)(webs_t wp, char_t *urlPrefix, - char_t *webDir, int arg, char_t *url, char_t *path, char_t *query)) -{ - websUrlHandlerType *sp; - int i; - - for (i = 0; i < websUrlHandlerMax; i++) { - sp = &websUrlHandler[i]; - if (sp->handler == handler) { - sp->handler = NULL; - return 0; - } - } - return -1; -} - -/******************************************************************************/ -/* - * Sort in decreasing URL length order observing the flags for first and last - */ - -static int websUrlHandlerSort(const void *p1, const void *p2) -{ - websUrlHandlerType *s1, *s2; - int rc; - - a_assert(p1); - a_assert(p2); - - s1 = (websUrlHandlerType*) p1; - s2 = (websUrlHandlerType*) p2; - - if ((s1->flags & WEBS_HANDLER_FIRST) || (s2->flags & WEBS_HANDLER_LAST)) { - return -1; - } - - if ((s2->flags & WEBS_HANDLER_FIRST) || (s1->flags & WEBS_HANDLER_LAST)) { - return 1; - } - - if ((rc = gstrcmp(s1->urlPrefix, s2->urlPrefix)) == 0) { - if (s1->len < s2->len) { - return 1; - } else if (s1->len > s2->len) { - return -1; - } - } - return -rc; -} - -/******************************************************************************/ -/* - * Publish a new web directory (Use the default URL handler) - */ - -int websPublish(char_t *urlPrefix, char_t *path) -{ - return websUrlHandlerDefine(urlPrefix, path, 0, websPublishHandler, 0); -} - -/******************************************************************************/ -/* - * Return the directory for a given prefix. Ignore empty prefixes - */ - -char_t *websGetPublishDir(char_t *path, char_t **urlPrefix) -{ - websUrlHandlerType *sp; - int i; - - for (i = 0; i < websUrlHandlerMax; i++) { - sp = &websUrlHandler[i]; - if (sp->urlPrefix[0] == '\0') { - continue; - } - if (sp->handler && gstrncmp(sp->urlPrefix, path, sp->len) == 0) { - if (urlPrefix) { - *urlPrefix = sp->urlPrefix; - } - return sp->webDir; - } - } - return NULL; -} - -/******************************************************************************/ -/* - * Publish URL handler. We just patch the web page Directory and let the - * default handler do the rest. - */ - -static int websPublishHandler(webs_t wp, char_t *urlPrefix, char_t *webDir, - int sid, char_t *url, char_t *path, char_t *query) -{ - int len; - - a_assert(websValid(wp)); - a_assert(path); - -/* - * Trim the urlPrefix off the path and set the webdirectory. Add one to step - * over the trailing '/' - */ - len = gstrlen(urlPrefix) + 1; - websSetRequestPath(wp, webDir, &path[len]); - return 0; -} - -/******************************************************************************/ -/* - * See if any valid handlers are defined for this request. If so, call them - * and continue calling valid handlers until one accepts the request. - * Return true if a handler was invoked, else return FALSE. - */ - -int websUrlHandlerRequest(webs_t wp) -{ - websUrlHandlerType *sp; - int i, first; - - a_assert(websValid(wp)); - -/* - * Delete the socket handler as we don't want to start reading any - * data on the connection as it may be for the next pipelined HTTP/1.1 - * request if using Keep Alive - */ - socketDeleteHandler(wp->sid); - wp->state = WEBS_PROCESSING; - websStats.handlerHits++; - - websSetRequestPath(wp, websGetDefaultDir(), NULL); - -/* - * Eliminate security hole - */ - websCondenseMultipleChars(wp->path, '/'); - websCondenseMultipleChars(wp->url, '/'); - -/* - * We loop over each handler in order till one accepts the request. - * The security handler will handle the request if access is NOT allowed. - */ - first = 1; - for (i = 0; i < websUrlHandlerMax; i++) { - sp = &websUrlHandler[i]; - if (sp->handler && gstrncmp(sp->urlPrefix, wp->path, sp->len) == 0) { - if (first) { - websSetEnv(wp); - first = 0; - } - if ((*sp->handler)(wp, sp->urlPrefix, sp->webDir, sp->arg, - wp->url, wp->path, wp->query)) { - return 1; - } - if (!websValid(wp)) { - trace(0, - T("webs: handler %s called websDone, but didn't return 1\n"), - sp->urlPrefix); - return 1; - } - } - } -/* - * If no handler processed the request, then return an error. Note: It is - * the handlers responsibility to call websDone - */ - if (i >= websUrlHandlerMax) { - websError(wp, 200, T("No handler for this URL %s"), wp->url); - } - return 0; -} - -#ifdef OBSOLETE_CODE - -/******************************************************************************/ -/* - * 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; - } -} - -#endif - -/******************************************************************************/ -/* - * Convert multiple adjacent occurrences of a given character to a single - * instance. - */ - -static char_t *websCondenseMultipleChars(char_t *strToCondense, char_t cCondense) -{ - if (strToCondense != NULL) { - char_t *pStr, *pScan; - - pStr = pScan = strToCondense; - - while (*pScan && *pStr) { -/* - * Advance scan pointer over multiple occurences of condense character - */ - while ((*pScan == cCondense) && (*(pScan + 1) == cCondense)) { - pScan++; - } -/* - * Copy character if an advance of the scan pointer has occurred - */ - if (pStr != pScan) { - *pStr = *pScan; - } - - pScan++; - pStr++; - } -/* - * Zero terminate string if multiple adjacent characters were found and condensed - */ - if (pStr != pScan) { - *pStr = 0; - } - } - - return strToCondense; -} - -/******************************************************************************/ diff --git a/cpukit/httpd/license.txt b/cpukit/httpd/license.txt deleted file mode 100644 index 1fa9e67e79..0000000000 --- a/cpukit/httpd/license.txt +++ /dev/null @@ -1,282 +0,0 @@ -License Agreement - -THIS LICENSE ALLOWS ONLY THE LIMITED USE OF GO AHEAD SOFTWARE, -INC. PROPRIETARY CODE. PLEASE CAREFULLY READ THIS AGREEMENT AS IT -PERTAINS TO THIS LICENSE, YOU CERTIFY THAT YOU WILL USE THE SOFTWARE -ONLY IN THE MANNER PERMITTED HEREIN. - -1. Definitions. - -1.1 "Documentation" means any documentation GoAhead includes with the -Original Code. - -1.2 "GoAhead" means Go Ahead Software, Inc. - -1.3 "Intellectual Property Rights" means all rights, whether now existing -or hereinafter acquired, in and to trade secrets, patents, copyrights, -trademarks, know-how, as well as moral rights and similar rights of any -type under the laws of any governmental authority, domestic or foreign, -including rights in and to all applications and registrations relating -to any of the foregoing. - -1.4 "License" or "Agreement" means this document. - -1.5 "Modifications" means any addition to or deletion from the substance -or structure of either the Original Code or any previous Modifications. - -1.6 "Original Code" means the Source Code to GoAhead’s proprietary -computer software entitled GoAhead WebServer. - -1.7 "Response Header" means the first portion of the response message -output by the GoAhead WebServer, containing but not limited to, header -fields for date, content-type, server identification and cache control. - -1.8 "Server Identification Field" means the field in the Response Header -which contains the text "Server: GoAhead-Webs". - -1.9 "You" means an individual or a legal entity exercising rights under, -and complying with all of the terms of, this license or a future version -of this license. For legal entities, "You" includes any entity which -controls, is controlled by, or is under common control with You. For -purposes of this definition, "control" means (a) the power, direct or -indirect, to cause the direction or management of such entity, whether -by contract or otherwise, or (b) ownership of fifty percent (50%) or -more of the outstanding shares or beneficial ownership of such entity. - -2. Source Code License. - -2.1 Limited Source Code Grant. - -GoAhead hereby grants You a world-wide, royalty-free, non-exclusive -license, subject to third party intellectual property claims, to use, -reproduce, modify, copy and distribute the Original Code. - -2.2 Binary Code. - -GoAhead hereby grants You a world-wide, royalty-free, non-exclusive -license to copy and distribute the binary code versions of the Original -Code together with Your Modifications. - -2.3 License Back to GoAhead. - -You hereby grant in both source code and binary code to GoAhead a -world-wide, royalty-free, non-exclusive license to copy, modify, display, -use and sublicense any Modifications You make that are distributed or -planned for distribution. Within 30 days of either such event, You -agree to ship to GoAhead a file containing the Modifications (in a media -to be determined by the parties), including any programmers’ notes and -other programmers’ materials. Additionally, You will provide to GoAhead -a complete description of the product, the product code or model number, -the date on which the product is initially shipped, and a contact name, -phone number and e-mail address for future correspondence. GoAhead will -keep confidential all data specifically marked as such. - -2.4 Restrictions on Use. - -You may sublicense Modifications to third parties such as subcontractors -or OEM's provided that You enter into license agreements with such third -parties that bind such third parties to all the obligations under this -Agreement applicable to you and that are otherwise substantially similar -in scope and application to this Agreement. - -3. Term. - -This Agreement and license are effective from the time You accept the -terms of this Agreement until this Agreement is terminated. You may -terminate this Agreement at any time by uninstalling or destroying -all copies of the Original Code including any and all binary versions -and removing any Modifications to the Original Code existing in any -products. This Agreement will terminate immediately and without further -notice if You fail to comply with any provision of this Agreement. All -restrictions on use, and all other provisions that may reasonably -be interpreted to survive termination of this Agreement, will survive -termination of this Agreement for any reason. Upon termination, You agree -to uninstall or destroy all copies of the Original Code, Modifications, -and Documentation. - -4. Trademarks and Brand. - -4.1 License and Use. - -GoAhead hereby grants to You a limited world-wide, royalty-free, -non-exclusive license to use the GoAhead trade names, trademarks, logos, -service marks and product designations posted in Exhibit A (collectively, -the "GoAhead Marks") in connection with the activities by You under this -Agreement. Additionally, GoAhead grants You a license under the terms -above to such GoAhead trademarks as shall be identified at a URL (the -"URL") provided by GoAhead. The use by You of GoAhead Marks shall be in -accordance with GoAhead’s trademark policies regarding trademark usage -as established at the web site designated by the URL, or as otherwise -communicated to You by GoAhead at its sole discretion. You understand and -agree that any use of GoAhead Marks in connection with this Agreement -shall not create any right, title or interest in or to such GoAhead -Marks and that all such use and goodwill associated with GoAhead Marks -will inure to the benefit of GoAhead. - -4.2 Promotion by You of GoAhead WebServer Mark. - -In consideration for the licenses granted by GoAhead to You herein, You -agree to notify GoAhead when You incorporate the GoAhead WebServer in -Your product and to inform GoAhead when such product begins to ship. You -agree to promote the Original Code by prominently and visibly displaying -a graphic of the GoAhead WebServer mark on the initial web page of Your -product that is displayed each time a user connects to it. You also agree -that GoAhead may identify your company as a user of the GoAhead WebServer -in conjunction with its own marketing efforts. You may further promote -the Original Code by displaying the GoAhead WebServer mark in marketing -and promotional materials such as the home page of your web site or web -pages promoting the product. - -4.3 Placement of Copyright Notice by You. - -You agree to include copies of the following notice (the "Notice") -regarding proprietary rights in all copies of the products that You -distribute, as follows: (i) embedded in the object code; and (ii) on -the title pages of all documentation. Furthermore, You agree to use -commercially reasonable efforts to cause any licensees of your products -to embed the Notice in object code and on the title pages or relevant -documentation. The Notice is as follows: Copyright (c) 20xx GoAhead -Software, Inc. All Rights Reserved. Unless GoAhead otherwise instructs, -the year 20xx is to be replaced with the year during which the release of -the Original Code containing the notice is issued by GoAhead. If this year -is not supplied with Documentation, GoAhead will supply it upon request. - -4.4 No Modifications to Server Identification Field. - -You agree not to remove or modify the Server identification Field -contained in the Response Header as defined in Section 1.6 and 1.7. - -5. Warranty Disclaimers. - -THE ORIGINAL CODE, THE DOCUMENTATION AND THE MEDIA UPON WHICH THE ORIGINAL -CODE IS RECORDED (IF ANY) ARE PROVIDED "AS IS" AND WITHOUT WARRANTIES OF -ANY KIND, EXPRESS, STATUTORY OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. - -The entire risk as to the quality and performance of the Original Code -(including any Modifications You make) and the Documentation is with -You. Should the Original Code or the Documentation prove defective, -You (and not GoAhead or its distributors, licensors or dealers) assume -the entire cost of all necessary servicing or repair. GoAhead does not -warrant that the functions contained in the Original Code will meet your -requirements or operate in the combination that You may select for use, -that the operation of the Original Code will be uninterrupted or error -free, or that defects in the Original Code will be corrected. No oral -or written statement by GoAhead or by a representative of GoAhead shall -create a warranty or increase the scope of this warranty. - -GOAHEAD DOES NOT WARRANT THE ORIGINAL CODE AGAINST INFRINGEMENT OR THE -LIKE WITH RESPECT TO ANY COPYRIGHT, PATENT, TRADE SECRET, TRADEMARK -OR OTHER PROPRIETARY RIGHT OF ANY THIRD PARTY AND DOES NOT WARRANT -THAT THE ORIGINAL CODE DOES NOT INCLUDE ANY VIRUS, SOFTWARE ROUTINE -OR OTHER SOFTWARE DESIGNED TO PERMIT UNAUTHORIZED ACCESS, TO DISABLE, -ERASE OR OTHERWISE HARM SOFTWARE, HARDWARE OR DATA, OR TO PERFORM ANY -OTHER SUCH ACTIONS. - -Any warranties that by law survive the foregoing disclaimers shall -terminate ninety (90) days from the date You received the Original Code. - -6. Limitation of Liability. - -YOUR SOLE REMEDIES AND GOAHEAD'S ENTIRE LIABILITY ARE SET FORTH ABOVE. IN -NO EVENT WILL GOAHEAD OR ITS DISTRIBUTORS OR DEALERS BE LIABLE FOR -DIRECT, INDIRECT, INCIDENTAL OR CONSEQUENTIAL DAMAGES RESULTING FROM -THE USE OF THE ORIGINAL CODE, THE INABILITY TO USE THE ORIGINAL CODE, -OR ANY DEFECT IN THE ORIGINAL CODE, INCLUDING ANY LOST PROFITS, EVEN IF -THEY HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -You agree that GoAhead and its distributors and dealers will not be -LIABLE for defense or indemnity with respect to any claim against You -by any third party arising from your possession or use of the Original -Code or the Documentation. - -In no event will GoAhead’s total liability to You for all damages, losses, -and causes of action (whether in contract, tort, including negligence, -or otherwise) exceed the amount You paid for this product. - -SOME STATES DO NOT ALLOW LIMITATIONS ON HOW LONG AN IMPLIED WARRANTY -LASTS, AND SOME STATES DO NOT ALLOW THE EXCLUSION OR LIMITATION -OF INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO THE ABOVE LIMITATIONS OR -EXCLUSIONS MAY NOT APPLY TO YOU. THIS WARRANTY GIVES YOU SPECIFIC LEGAL -RIGHTS AND YOU MAY ALSO HAVE OTHER RIGHTS WHICH VARY FROM STATE TO STATE. - -7. Indemnification by You. - -You agree to indemnify and hold GoAhead harmless against any and all -claims, losses, damages and costs (including legal expenses and reasonable -counsel fees) arising out of any claim of a third party with respect to -the contents of the Your products, and any intellectual property rights -or other rights or interests related thereto. - -8. High Risk Activities. - -The Original Code is not fault-tolerant and is not designed , manufactured -or intended for use or resale as online control equipment in hazardous -environments requiring fail-safe performance, such as in the operation -of nuclear facilities, aircraft navigation or communication systems, -air traffic control, direct life support machines or weapons systems, -in which the failure of the Original Code could lead directly to death, -personal injury, or severe physical or environmental damage. GoAhead and -its suppliers specifically disclaim any express or implied warranty of -fitness for any high risk uses listed above. - -9. Government Restricted Rights. - -For units of the Department of Defense, use, duplication, or disclosure -by the Government is subject to restrictions as set forth in subparagraph -(c)(1)(ii) of the Rights in Technical Data and Computer Software clause -at DFARS 252.227-7013. Contractor/manufacturer is GoAhead Software, -Inc., 10900 N.E. 8th Street, Suite 750, Bellevue, Washington 98004. - -If the Commercial Computer Software Restricted rights clause at FAR -52.227-19 or its successors apply, the Software and Documentation -constitute restricted computer software as defined in that clause and -the Government shall not have the license for published software set -forth in subparagraph (c)(3) of that clause. - -The Original Code (i) was developed at private expense, and no part of it -was developed with governmental funds; (ii) is a trade secret of GoAhead -(or its licensor(s)) for all purposes of the Freedom of Information Act; -(iii) is "restricted computer software" subject to limited utilization as -provided in the contract between the vendor and the governmental entity; -and (iv) in all respects is proprietary data belonging solely to GoAhead -(or its licensor(s)). - -10. Governing Law and Interpretation. - -This Agreement shall be interpreted under and governed by the laws of the -State of Washington, without regard to its rules governing the conflict of -laws. If any provision of this Agreement is held illegal or unenforceable -by a court or tribunal of competent jurisdiction, the remaining provisions -of this Agreement shall remain in effect and the invalid provision deemed -modified to the least degree necessary to remedy such invalidity. - -11. Entire Agreement. - -This Agreement is the complete agreement between GoAhead and You and -supersedes all prior agreements, oral or written, with respect to the -subject matter hereof. - -If You have any questions concerning this Agreement, You may write to -GoAhead Software, Inc., 10900 N.E. 8th Street, Suite 750, Bellevue, -Washington 98004 or send e-mail to info@goahead.com. - -BY CLICKING ON THE "Register" BUTTON ON THE REGISTRATION FORM, YOU -ACCEPT AND AGREE TO BE BOUND BY ALL OF THE TERMS AND CONDITIONS SET -FORTH IN THIS AGREEMENT. IF YOU DO NOT WISH TO ACCEPT THIS LICENSE OR -YOU DO NOT QUALIFY FOR A LICENSE BASED ON THE TERMS SET FORTH ABOVE, -YOU MUST NOT CLICK THE "Register" BUTTON. - -Exhibit A - -GoAhead Trademarks, Logos, and Product Designation Information - - - - -01/28/00 - - - - diff --git a/cpukit/httpd/md5.h b/cpukit/httpd/md5.h deleted file mode 100644 index 99df4eb735..0000000000 --- a/cpukit/httpd/md5.h +++ /dev/null @@ -1,50 +0,0 @@ -/* MD5.H - header file for MD5C.C - * - * $Id$ - */ - -/* 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 */ diff --git a/cpukit/httpd/md5c.c b/cpukit/httpd/md5c.c deleted file mode 100644 index 6118caf5ff..0000000000 --- a/cpukit/httpd/md5c.c +++ /dev/null @@ -1,337 +0,0 @@ -/* MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm - * - * $Id$ - */ - -/* 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 ( -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 ( -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 ( -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 ( -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 ( -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 ( -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 ( -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 ( -POINTER output, -int value, -unsigned int len) -{ - unsigned int i; - - for (i = 0; i < len; i++) - ((char *)output)[i] = (char)value; -} diff --git a/cpukit/httpd/mime.c b/cpukit/httpd/mime.c deleted file mode 100644 index 689360ea68..0000000000 --- a/cpukit/httpd/mime.c +++ /dev/null @@ -1,116 +0,0 @@ -/* - * mime.c -- Web server mime types - * - * Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved. - * - * See the file "license.txt" for usage and redistribution license requirements - * - * $Id$ - */ - -/******************************** Description *********************************/ - -/* - * Mime types and file extensions. This module maps URL extensions to - * content types. - */ - -/********************************* Includes ***********************************/ - -#include "wsIntrn.h" - -/******************************** Global Data *********************************/ -/* - * Addd entries to the MimeList as required for your content - */ - - -websMimeType websMimeList[] = { - { T("application/java"), T(".class") }, - { T("application/java"), T(".jar") }, - { T("text/html"), T(".asp") }, - { T("text/html"), T(".htm") }, - { T("text/html"), T(".html") }, - { T("image/gif"), T(".gif") }, - { T("image/jpeg"), T(".jpg") }, - { T("text/css"), T(".css") }, - { T("text/plain"), T(".txt") }, - { T("application/x-javascript"), T(".js") }, - -#ifdef MORE_MIME_TYPES - { T("application/binary"), T(".exe") }, - { T("application/compress"), T(".z") }, - { T("application/gzip"), T(".gz") }, - { T("application/octet-stream"), T(".bin") }, - { T("application/oda"), T(".oda") }, - { T("application/pdf"), T(".pdf") }, - { T("application/postscript"), T(".ai") }, - { T("application/postscript"), T(".eps") }, - { T("application/postscript"), T(".ps") }, - { T("application/rtf"), T(".rtf") }, - { T("application/x-bcpio"), T(".bcpio") }, - { T("application/x-cpio"), T(".cpio") }, - { T("application/x-csh"), T(".csh") }, - { T("application/x-dvi"), T(".dvi") }, - { T("application/x-gtar"), T(".gtar") }, - { T("application/x-hdf"), T(".hdf") }, - { T("application/x-latex"), T(".latex") }, - { T("application/x-mif"), T(".mif") }, - { T("application/x-netcdf"), T(".nc") }, - { T("application/x-netcdf"), T(".cdf") }, - { T("application/x-ns-proxy-autoconfig"), T(".pac") }, - { T("application/x-patch"), T(".patch") }, - { T("application/x-sh"), T(".sh") }, - { T("application/x-shar"), T(".shar") }, - { T("application/x-sv4cpio"), T(".sv4cpio") }, - { T("application/x-sv4crc"), T(".sv4crc") }, - { T("application/x-tar"), T(".tar") }, - { T("application/x-tcl"), T(".tcl") }, - { T("application/x-tex"), T(".tex") }, - { T("application/x-texinfo"), T(".texinfo") }, - { T("application/x-texinfo"), T(".texi") }, - { T("application/x-troff"), T(".t") }, - { T("application/x-troff"), T(".tr") }, - { T("application/x-troff"), T(".roff") }, - { T("application/x-troff-man"), T(".man") }, - { T("application/x-troff-me"), T(".me") }, - { T("application/x-troff-ms"), T(".ms") }, - { T("application/x-ustar"), T(".ustar") }, - { T("application/x-wais-source"), T(".src") }, - { T("application/zip"), T(".zip") }, - { T("audio/basic"), T(".au snd") }, - { T("audio/x-aiff"), T(".aif") }, - { T("audio/x-aiff"), T(".aiff") }, - { T("audio/x-aiff"), T(".aifc") }, - { T("audio/x-wav"), T(".wav") }, - { T("audio/x-wav"), T(".ram") }, - { T("image/ief"), T(".ief") }, - { T("image/jpeg"), T(".jpeg") }, - { T("image/jpeg"), T(".jpe") }, - { T("image/tiff"), T(".tiff") }, - { T("image/tiff"), T(".tif") }, - { T("image/x-cmu-raster"), T(".ras") }, - { T("image/x-portable-anymap"), T(".pnm") }, - { T("image/x-portable-bitmap"), T(".pbm") }, - { T("image/x-portable-graymap"), T(".pgm") }, - { T("image/x-portable-pixmap"), T(".ppm") }, - { T("image/x-rgb"), T(".rgb") }, - { T("image/x-xbitmap"), T(".xbm") }, - { T("image/x-xpixmap"), T(".xpm") }, - { T("image/x-xwindowdump"), T(".xwd") }, - { T("text/html"), T(".cfm") }, - { T("text/html"), T(".shtm") }, - { T("text/html"), T(".shtml") }, - { T("text/richtext"), T(".rtx") }, - { T("text/tab-separated-values"), T(".tsv") }, - { T("text/x-setext"), T(".etx") }, - { T("video/mpeg"), T(".mpeg mpg mpe") }, - { T("video/quicktime"), T(".qt") }, - { T("video/quicktime"), T(".mov") }, - { T("video/x-msvideo"), T(".avi") }, - { T("video/x-sgi-movie"), T(".movie") }, -#endif - { NULL, NULL}, -}; - -/*****************************************************************************/ diff --git a/cpukit/httpd/misc.c b/cpukit/httpd/misc.c deleted file mode 100644 index f9f4aac144..0000000000 --- a/cpukit/httpd/misc.c +++ /dev/null @@ -1,675 +0,0 @@ -/* - * misc.c -- Miscellaneous routines. - * - * Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved. - * - * See the file "license.txt" for usage and redistribution license requirements - * - * $Id$ - */ - -/********************************* Includes ***********************************/ - -#ifdef UEMF - #include "uemf.h" -#else - #include "basic/basicInternal.h" -#endif - -/********************************* Defines ************************************/ -/* - * 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 64 /* Growth increment */ - -typedef struct { - char_t *s; /* Pointer to buffer */ - int size; /* Current buffer size */ - int max; /* Maximum buffer size */ - int count; /* Buffer count */ - int flags; /* Allocation flags */ -} strbuf_t; - -/* - * Sprintf formatting flags - */ -enum flag { - flag_none = 0, - flag_minus = 1, - flag_plus = 2, - flag_space = 4, - flag_hash = 8, - flag_zero = 16, - flag_short = 32, - flag_long = 64 -}; - -/************************** Forward Declarations ******************************/ - -static int dsnprintf(char_t **s, int size, char_t *fmt, va_list arg, - int msize); -#if !defined(__rtems__) -static int strnlen(char_t *s, unsigned int n); -#endif -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); -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); - -/************************************ Code ************************************/ -/* - * "basename" returns a pointer to the last component of a pathname - * LINUX, LynxOS and Mac OS X have their own basename function - */ - -#if (!defined (LINUX) && !defined (LYNX) && !defined (MACOSX)) -char_t *basename(char_t *name) -{ - char_t *cp; - -#if (defined (NW) || defined (WIN)) - if (((cp = gstrrchr(name, '\\')) == NULL) && - ((cp = gstrrchr(name, '/')) == NULL)) { - return name; -#else - if ((cp = gstrrchr(name, '/')) == NULL) { - return name; -#endif - } else if (*(cp + 1) == '\0' && cp == name) { - return name; - } else if (*(cp + 1) == '\0' && cp != name) { - return T(""); - } else { - return ++cp; - } -} -#endif /* ! LINUX & ! LYNX & ! MACOSX */ - -/******************************************************************************/ -/* - * Returns a pointer to the directory component of a pathname. bufsize is - * the size of the buffer in BYTES! - */ - -char_t *dirname(char_t *buf, char_t *name, int bufsize) -{ - char_t *cp; - int len; - - a_assert(name); - a_assert(buf); - a_assert(bufsize > 0); - -#if (defined (WIN) || defined (NW)) - if ((cp = gstrrchr(name, '/')) == NULL && - (cp = gstrrchr(name, '\\')) == NULL) -#else - if ((cp = gstrrchr(name, '/')) == NULL) -#endif - { - gstrcpy(buf, T(".")); - return buf; - } - - if ((*(cp + 1) == '\0' && cp == name)) { - gstrncpy(buf, T("."), TSZ(bufsize)); - gstrcpy(buf, T(".")); - return buf; - } - - len = cp - name; - - if (len < bufsize) { - gstrncpy(buf, name, len); - buf[len] = '\0'; - } else { - gstrncpy(buf, name, TSZ(bufsize)); - buf[bufsize - 1] = '\0'; - } - - return buf; -} - - -/******************************************************************************/ -/* - * sprintf and vsprintf are bad, ok. You can easily clobber memory. Use - * fmtAlloc and fmtValloc instead! These functions do _not_ support floating - * point, like %e, %f, %g... - */ - -int fmtAlloc(char_t **s, int n, char_t *fmt, ...) -{ - va_list ap; - int result; - - a_assert(s); - a_assert(fmt); - - *s = NULL; - va_start(ap, fmt); - 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; -} - -/******************************************************************************/ -/* - * This function appends the formatted string to the supplied string, - * reallocing if required. - */ - -int fmtRealloc(char_t **s, int n, int msize, char_t *fmt, ...) -{ - va_list ap; - int result; - - a_assert(s); - a_assert(fmt); - - if (msize == -1) { - *s = NULL; - } - va_start(ap, fmt); - result = dsnprintf(s, n, fmt, ap, msize); - va_end(ap); - return result; -} - -/******************************************************************************/ -/* - * A vsprintf replacement. - */ - -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. - * 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 - * return the size of the allocated buffer for use with the next call. For - * the first call, msize can be set to -1. - */ - -static int dsnprintf(char_t **s, int size, char_t *fmt, va_list arg, int msize) -{ - strbuf_t buf; - char_t c; - - a_assert(s); - a_assert(fmt); - - memset(&buf, 0, sizeof(buf)); - buf.s = *s; - - if (*s == NULL || msize != 0) { - buf.max = size; - buf.flags |= STR_REALLOC; - if (msize != 0) { - buf.size = max(msize, 0); - } - if (*s != NULL && msize != 0) { - buf.count = gstrlen(*s); - } - } else { - buf.size = size; - } - - while ((c = *fmt++) != '\0') { - if (c != '%' || (c = *fmt++) == '%') { - put_char(&buf, c); - } else { - enum flag f = flag_none; - int width = 0; - int prec = -1; - for ( ; c != '\0'; c = *fmt++) { - if (c == '-') { - f |= flag_minus; - } else if (c == '+') { - f |= flag_plus; - } else if (c == ' ') { - f |= flag_space; - } else if (c == '#') { - f |= flag_hash; - } else if (c == '0') { - f |= flag_zero; - } else { - break; - } - } - if (c == '*') { - width = va_arg(arg, int); - if (width < 0) { - f |= flag_minus; - width = -width; - } - c = *fmt++; - } else { - for ( ; gisdigit((unsigned char)c); c = *fmt++) { - width = width * 10 + (c - '0'); - } - } - if (c == '.') { - f &= ~flag_zero; - c = *fmt++; - if (c == '*') { - prec = va_arg(arg, int); - c = *fmt++; - } else { - for (prec = 0; gisdigit((unsigned char)c); c = *fmt++) { - prec = prec * 10 + (c - '0'); - } - } - } - if (c == 'h' || c == 'l') { - f |= (c == 'h' ? flag_short : flag_long); - c = *fmt++; - } - if (c == 'd' || c == 'i') { - long int value; - if (f & flag_short) { - value = (short int) va_arg(arg, int); - } else if (f & flag_long) { - value = va_arg(arg, long int); - } else { - value = va_arg(arg, int); - } - if (value >= 0) { - if (f & flag_plus) { - put_ulong(&buf, value, 10, 0, T("+"), width, prec, f); - } else if (f & flag_space) { - put_ulong(&buf, value, 10, 0, T(" "), width, prec, f); - } else { - put_ulong(&buf, value, 10, 0, NULL, width, prec, f); - } - } else { - put_ulong(&buf, -value, 10, 0, T("-"), width, prec, f); - } - } else if (c == 'o' || c == 'u' || c == 'x' || c == 'X') { - unsigned long int value; - if (f & flag_short) { - value = (unsigned short int) va_arg(arg, unsigned int); - } else if (f & flag_long) { - value = va_arg(arg, unsigned long int); - } else { - value = va_arg(arg, unsigned int); - } - if (c == 'o') { - if (f & flag_hash && value != 0) { - put_ulong(&buf, value, 8, 0, T("0"), width, prec, f); - } else { - put_ulong(&buf, value, 8, 0, NULL, width, prec, f); - } - } else if (c == 'u') { - put_ulong(&buf, value, 10, 0, NULL, width, prec, f); - } else { - if (f & flag_hash && value != 0) { - if (c == 'x') { - put_ulong(&buf, value, 16, 0, T("0x"), width, - prec, f); - } else { - put_ulong(&buf, value, 16, 1, T("0X"), width, - prec, f); - } - } else { - /* 04 Apr 02 BgP -- changed so that %X correctly outputs - * uppercase hex digits when requested. - put_ulong(&buf, value, 16, 0, NULL, width, prec, f); - */ - put_ulong(&buf, value, 16, ('X' == c) , NULL, width, prec, f); - } - } - - } else if (c == 'c') { - char_t value = va_arg(arg, int); - put_char(&buf, value); - - } else if (c == 's' || c == 'S') { - char_t *value = va_arg(arg, char_t *); - if (value == NULL) { - put_string(&buf, T("(null)"), -1, width, prec, f); - } else if (f & flag_hash) { - put_string(&buf, - value + 1, (char_t) *value, width, prec, f); - } else { - put_string(&buf, value, -1, width, prec, f); - } - } else if (c == 'p') { - void *value = va_arg(arg, void *); - put_ulong(&buf, - (unsigned long int) value, 16, 0, T("0x"), width, prec, f); - } else if (c == 'n') { - if (f & flag_short) { - short int *value = va_arg(arg, short int *); - *value = buf.count; - } else if (f & flag_long) { - long int *value = va_arg(arg, long int *); - *value = buf.count; - } else { - int *value = va_arg(arg, int *); - *value = buf.count; - } - } else { - put_char(&buf, c); - } - } - } - if (buf.s == NULL) { - put_char(&buf, '\0'); - } - -/* - * If the user requested a dynamic buffer (*s == NULL), ensure it is returned. - */ - if (*s == NULL || msize != 0) { - *s = buf.s; - } - - if (*s != NULL && size > 0) { - if (buf.count < size) { - (*s)[buf.count] = '\0'; - } else { - (*s)[buf.size - 1] = '\0'; - } - } - - if (msize != 0) { - return buf.size; - } - return buf.count; -} - -/******************************************************************************/ -/* - * Return the length of a string limited by a given length - */ - -#if !defined(__rtems__) -static int strnlen(char_t *s, unsigned int n) -{ - unsigned int len; - - len = gstrlen(s); - return min(len, n); -} -#endif - -/******************************************************************************/ -/* - * Add a character to a string buffer - */ - -static void put_char(strbuf_t *buf, char_t c) -{ - 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) { -/* - * 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)); - } else { - buf->s = brealloc(B_L, buf->s, buf->size * sizeof(char_t)); - } - } - buf->s[buf->count] = c; - if (c != '\0') { - ++buf->count; - } -} - -/******************************************************************************/ -/* - * Add a string to a string buffer - */ - -static void put_string(strbuf_t *buf, char_t *s, int len, int width, - int prec, enum flag f) -{ - int i; - - if (len < 0) { - len = strnlen(s, prec >= 0 ? prec : ULONG_MAX); - } else if (prec >= 0 && prec < len) { - len = prec; - } - if (width > len && !(f & flag_minus)) { - for (i = len; i < width; ++i) { - put_char(buf, ' '); - } - } - for (i = 0; i < len; ++i) { - put_char(buf, s[i]); - } - if (width > len && f & flag_minus) { - for (i = len; i < width; ++i) { - put_char(buf, ' '); - } - } -} - -/******************************************************************************/ -/* - * Add a long to a string buffer - */ - -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) -{ - unsigned long x, x2; - int len, zeros, i; - - for (len = 1, x = 1; x < ULONG_MAX / base; ++len, x = x2) { - x2 = x * base; - if (x2 > value) { - break; - } - } - zeros = (prec > len) ? prec - len : 0; - width -= zeros + len; - if (prefix != NULL) { - width -= strnlen(prefix, ULONG_MAX); - } - if (!(f & flag_minus)) { - 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) { - put_string(buf, prefix, -1, 0, -1, flag_none); - } - for (i = 0; i < zeros; ++i) { - put_char(buf, '0'); - } - for ( ; x > 0; x /= base) { - int digit = (value / x) % base; - put_char(buf, (char) ((digit < 10 ? '0' : (upper ? 'A' : 'a') - 10) + - digit)); - } - if (f & flag_minus) { - for (i = 0; i < width; ++i) { - put_char(buf, ' '); - } - } -} - -/******************************************************************************/ -/* - * Convert an ansi string to a unicode string. On an error, we return the - * original ansi string which is better than returning NULL. nBytes is the - * size of the destination buffer (ubuf) in _bytes_. - */ - -char_t *ascToUni(char_t *ubuf, char *str, int nBytes) -{ -#ifdef UNICODE - if (MultiByteToWideChar(CP_ACP, 0, str, nBytes / sizeof(char_t), ubuf, - nBytes / sizeof(char_t)) < 0) { - return (char_t*) str; - } -#else - strncpy(ubuf, str, nBytes); -#endif - return ubuf; -} - -/******************************************************************************/ -/* - * Convert a unicode string to an ansi string. On an error, return the - * original unicode string which is better than returning NULL. - * N.B. nBytes is the number of _bytes_ in the destination buffer, buf. - */ - -char *uniToAsc(char *buf, char_t *ustr, int nBytes) -{ -#ifdef UNICODE - if (WideCharToMultiByte(CP_ACP, 0, ustr, nBytes, buf, nBytes, NULL, - NULL) < 0) { - return (char*) ustr; - } -#else - strncpy(buf, ustr, nBytes); -#endif - return (char*) buf; -} - -/******************************************************************************/ -/* - * allocate (balloc) a buffer and do ascii to unicode conversion into it. - * 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, int alen) -{ - char_t *unip; - int ulen; - - ulen = (alen + 1) * sizeof(char_t); - if ((unip = balloc(B_L, ulen)) == NULL) { - return NULL; - } - ascToUni(unip, cp, ulen); - unip[alen] = 0; - return unip; -} - -/******************************************************************************/ -/* - * 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 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 * cp; - - 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); -} - -/******************************************************************************/ diff --git a/cpukit/httpd/preinstall.am b/cpukit/httpd/preinstall.am deleted file mode 100644 index 7fe32d7d10..0000000000 --- a/cpukit/httpd/preinstall.am +++ /dev/null @@ -1,78 +0,0 @@ -## Automatically generated by ampolish3 - Do not edit - -if AMPOLISH3 -$(srcdir)/preinstall.am: Makefile.am - $(AMPOLISH3) $(srcdir)/Makefile.am > $(srcdir)/preinstall.am -endif - -PREINSTALL_DIRS = -DISTCLEANFILES = $(PREINSTALL_DIRS) - -all-local: $(TMPINSTALL_FILES) - -TMPINSTALL_FILES = -CLEANFILES = $(TMPINSTALL_FILES) - -all-am: $(PREINSTALL_FILES) - -PREINSTALL_FILES = -CLEANFILES += $(PREINSTALL_FILES) - -$(PROJECT_LIB)/$(dirstamp): - @$(MKDIR_P) $(PROJECT_LIB) - @: > $(PROJECT_LIB)/$(dirstamp) -PREINSTALL_DIRS += $(PROJECT_LIB)/$(dirstamp) - -$(PROJECT_INCLUDE)/$(dirstamp): - @$(MKDIR_P) $(PROJECT_INCLUDE) - @: > $(PROJECT_INCLUDE)/$(dirstamp) -PREINSTALL_DIRS += $(PROJECT_INCLUDE)/$(dirstamp) - -if LIBHTTPD -$(PROJECT_INCLUDE)/rtems_webserver.h: rtems_webserver.h $(PROJECT_INCLUDE)/$(dirstamp) - $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems_webserver.h -PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems_webserver.h - -if HAS_PTHREADS -$(PROJECT_INCLUDE)/goahead/$(dirstamp): - @$(MKDIR_P) $(PROJECT_INCLUDE)/goahead - @: > $(PROJECT_INCLUDE)/goahead/$(dirstamp) -PREINSTALL_DIRS += $(PROJECT_INCLUDE)/goahead/$(dirstamp) - -$(PROJECT_INCLUDE)/goahead/ej.h: ej.h $(PROJECT_INCLUDE)/goahead/$(dirstamp) - $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/goahead/ej.h -PREINSTALL_FILES += $(PROJECT_INCLUDE)/goahead/ej.h - -$(PROJECT_INCLUDE)/goahead/ejIntrn.h: ejIntrn.h $(PROJECT_INCLUDE)/goahead/$(dirstamp) - $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/goahead/ejIntrn.h -PREINSTALL_FILES += $(PROJECT_INCLUDE)/goahead/ejIntrn.h - -$(PROJECT_INCLUDE)/goahead/emfdb.h: emfdb.h $(PROJECT_INCLUDE)/goahead/$(dirstamp) - $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/goahead/emfdb.h -PREINSTALL_FILES += $(PROJECT_INCLUDE)/goahead/emfdb.h - -$(PROJECT_INCLUDE)/goahead/md5.h: md5.h $(PROJECT_INCLUDE)/goahead/$(dirstamp) - $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/goahead/md5.h -PREINSTALL_FILES += $(PROJECT_INCLUDE)/goahead/md5.h - -$(PROJECT_INCLUDE)/goahead/uemf.h: uemf.h $(PROJECT_INCLUDE)/goahead/$(dirstamp) - $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/goahead/uemf.h -PREINSTALL_FILES += $(PROJECT_INCLUDE)/goahead/uemf.h - -$(PROJECT_INCLUDE)/goahead/um.h: um.h $(PROJECT_INCLUDE)/goahead/$(dirstamp) - $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/goahead/um.h -PREINSTALL_FILES += $(PROJECT_INCLUDE)/goahead/um.h - -$(PROJECT_INCLUDE)/goahead/webs.h: webs.h $(PROJECT_INCLUDE)/goahead/$(dirstamp) - $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/goahead/webs.h -PREINSTALL_FILES += $(PROJECT_INCLUDE)/goahead/webs.h - -$(PROJECT_INCLUDE)/goahead/wsIntrn.h: wsIntrn.h $(PROJECT_INCLUDE)/goahead/$(dirstamp) - $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/goahead/wsIntrn.h -PREINSTALL_FILES += $(PROJECT_INCLUDE)/goahead/wsIntrn.h - -$(PROJECT_LIB)/libhttpd.a: libhttpd.a $(PROJECT_LIB)/$(dirstamp) - $(INSTALL_DATA) $< $(PROJECT_LIB)/libhttpd.a -TMPINSTALL_FILES += $(PROJECT_LIB)/libhttpd.a -endif -endif diff --git a/cpukit/httpd/ringq.c b/cpukit/httpd/ringq.c deleted file mode 100644 index 5ee1af0f4b..0000000000 --- a/cpukit/httpd/ringq.c +++ /dev/null @@ -1,584 +0,0 @@ -/* - * ringq.c -- Ring queue buffering module - * - * Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved. - * - * See the file "license.txt" for usage and redistribution license requirements - * - * $Id$ - */ - -/******************************** Description *********************************/ - -/* - * A ring queue allows maximum utilization of memory for data storage and is - * 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 - * the queue structure and pointers. Change this module very carefully. - * - * This module follows the open/close model. - * - * Operation of a ringq where rq is a pointer to a ringq : - * - * rq->buflen contains the size of the buffer. - * rq->buf will point to the start of the buffer. - * rq->servp will point to the first (un-consumed) data byte. - * rq->endp will point to the next free location to which new data is added - * rq->endbuf will point to one past the end of the buffer. - * - * Eg. If the ringq contains the data "abcdef", it might look like : - * - * +-------------------------------------------------------------------+ - * | | | | | | | | a | b | c | d | e | f | | | | | - * +-------------------------------------------------------------------+ - * ^ ^ ^ ^ - * | | | | - * 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 filler's responsibility to ensure - * the ringq is never filled such that servp == endp. - * - * 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. - */ - -/********************************* Includes ***********************************/ - -#ifdef UEMF - #include "uemf.h" -#else - #include "basic/basicInternal.h" -#endif - -/*********************************** Defines **********************************/ -/* - * Faster than a function call - */ - -#define RINGQ_LEN(rq) \ - ((rq->servp > rq->endp) ? \ - (rq->buflen + (rq->endp - rq->servp)) : \ - (rq->endp - rq->servp)) - -/***************************** Forward Declarations ***************************/ - -static int ringqGrow(ringq_t *rq); -static int getBinBlockSize(int size); - -int ringqGrowCalls = 0; - -/*********************************** Code *************************************/ -/* - * Create a new ringq. "increment" is the amount to increase the size of the - * ringq should it need to grow to accomodate data being added. "maxsize" is - * an upper limit (sanity level) beyond which the q must not grow. Set maxsize - * to -1 to imply no upper limit. The buffer for the ringq is always - * dynamically allocated. Set maxsize - */ - -int ringqOpen(ringq_t *rq, int initSize, int maxsize) -{ - int increment; - - a_assert(rq); - a_assert(initSize >= 0); - - increment = getBinBlockSize(initSize); - if ((rq->buf = balloc(B_L, (increment))) == NULL) { - return -1; - } - rq->maxsize = maxsize; - rq->buflen = increment; - rq->increment = increment; - rq->endbuf = &rq->buf[rq->buflen]; - rq->servp = rq->buf; - rq->endp = rq->buf; - *rq->servp = '\0'; - return 0; -} - -/******************************************************************************/ -/* - * Delete a ringq and free the ringq buffer. - */ - -void ringqClose(ringq_t *rq) -{ - a_assert(rq); - a_assert(rq->buflen == (rq->endbuf - rq->buf)); - - if (rq == NULL) { - return; - } - - ringqFlush(rq); - bfree(B_L, (char*) rq->buf); - rq->buf = NULL; -} - -/******************************************************************************/ -/* - * 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) -{ - a_assert(rq); - a_assert(rq->buflen == (rq->endbuf - rq->buf)); - - if (rq->servp > rq->endp) { - return rq->buflen + rq->endp - rq->servp; - } else { - return rq->endp - rq->servp; - } -} - -/******************************************************************************/ -/* - * Get a byte from the queue - */ - -int ringqGetc(ringq_t *rq) -{ - char_t c; - char_t* cp; - - a_assert(rq); - a_assert(rq->buflen == (rq->endbuf - rq->buf)); - - if (rq->servp == rq->endp) { - return -1; - } - - cp = (char_t*) rq->servp; - c = *cp++; - rq->servp = (unsigned char *) cp; - if (rq->servp >= rq->endbuf) { - rq->servp = rq->buf; - } - return c; -} - -/******************************************************************************/ -/* - * Add a char to the queue. Note if being used to store wide strings - * this does not add a trailing '\0'. Grow the q as required. - */ - -int ringqPutc(ringq_t *rq, char_t c) -{ - char_t *cp; - - a_assert(rq); - a_assert(rq->buflen == (rq->endbuf - rq->buf)); - - if ((ringqPutBlkMax(rq) < (int) sizeof(char_t)) && !ringqGrow(rq)) { - return -1; - } - - cp = (char_t*) rq->endp; - *cp++ = (char_t) c; - rq->endp = (unsigned char *) cp; - if (rq->endp >= rq->endbuf) { - rq->endp = rq->buf; - } - return 0; -} - -/******************************************************************************/ -/* - * Insert a wide character at the front of the queue - */ - -int ringqInsertc(ringq_t *rq, char_t c) -{ - char_t *cp; - - a_assert(rq); - a_assert(rq->buflen == (rq->endbuf - rq->buf)); - - if (ringqPutBlkMax(rq) < (int) sizeof(char_t) && !ringqGrow(rq)) { - return -1; - } - if (rq->servp <= rq->buf) { - rq->servp = rq->endbuf; - } - cp = (char_t*) rq->servp; - *--cp = (char_t) c; - rq->servp = (unsigned char *) cp; - return 0; -} - -/******************************************************************************/ -/* - * Add a string to the queue. Add a trailing null (maybe two nulls) - */ - -int ringqPutStr(ringq_t *rq, char_t *str) -{ - int rc; - - a_assert(rq); - a_assert(str); - a_assert(rq->buflen == (rq->endbuf - rq->buf)); - - rc = ringqPutBlk(rq, (unsigned char*) str, gstrlen(str) * sizeof(char_t)); - *((char_t*) rq->endp) = (char_t) '\0'; - 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'; -} - -/******************************************************************************/ -#ifdef UNICODE -/* - * Get a byte from the queue - */ - -int ringqGetcA(ringq_t *rq) -{ - unsigned char c; - - a_assert(rq); - a_assert(rq->buflen == (rq->endbuf - rq->buf)); - - if (rq->servp == rq->endp) { - return -1; - } - - c = *rq->servp++; - if (rq->servp >= rq->endbuf) { - rq->servp = rq->buf; - } - return c; -} - -/******************************************************************************/ -/* - * Add a byte to the queue. Note if being used to store strings this does not - * add a trailing '\0'. Grow the q as required. - */ - -int ringqPutcA(ringq_t *rq, char c) -{ - a_assert(rq); - a_assert(rq->buflen == (rq->endbuf - rq->buf)); - - if (ringqPutBlkMax(rq) == 0 && !ringqGrow(rq)) { - return -1; - } - - *rq->endp++ = (unsigned char) c; - if (rq->endp >= rq->endbuf) { - rq->endp = rq->buf; - } - return 0; -} - -/******************************************************************************/ -/* - * Insert a byte at the front of the queue - */ - -int ringqInsertcA(ringq_t *rq, char c) -{ - a_assert(rq); - a_assert(rq->buflen == (rq->endbuf - rq->buf)); - - if (ringqPutBlkMax(rq) == 0 && !ringqGrow(rq)) { - return -1; - } - if (rq->servp <= rq->buf) { - rq->servp = rq->endbuf; - } - *--rq->servp = (unsigned char) c; - return 0; -} - -/******************************************************************************/ -/* - * Add a string to the queue. Add a trailing null (not really in the q). - * ie. beyond the last valid byte. - */ - -int ringqPutStrA(ringq_t *rq, char *str) -{ - int rc; - - a_assert(rq); - a_assert(str); - a_assert(rq->buflen == (rq->endbuf - rq->buf)); - - rc = ringqPutBlk(rq, (unsigned char*) str, strlen(str)); - rq->endp[0] = '\0'; - return rc; -} - -#endif /* UNICODE */ -/******************************************************************************/ -/* - * Add a block of data to the ringq. Return the number of bytes added. - * Grow the q as required. - */ - -int ringqPutBlk(ringq_t *rq, unsigned char *buf, int size) -{ - int this, bytes_put; - - a_assert(rq); - a_assert(rq->buflen == (rq->endbuf - rq->buf)); - a_assert(buf); - a_assert(0 <= size); - -/* - * Loop adding the maximum bytes we can add in a single straight line copy - */ - bytes_put = 0; - while (size > 0) { - this = min(ringqPutBlkMax(rq), size); - if (this <= 0) { - if (! ringqGrow(rq)) { - break; - } - this = min(ringqPutBlkMax(rq), size); - } - - memcpy(rq->endp, buf, this); - buf += this; - rq->endp += this; - size -= this; - bytes_put += this; - - if (rq->endp >= rq->endbuf) { - rq->endp = rq->buf; - } - } - return bytes_put; -} - -/******************************************************************************/ -/* - * Get a block of data from the ringq. Return the number of bytes returned. - */ - -int ringqGetBlk(ringq_t *rq, unsigned char *buf, int size) -{ - int this, bytes_read; - - a_assert(rq); - a_assert(rq->buflen == (rq->endbuf - rq->buf)); - a_assert(buf); - a_assert(0 <= size && size < rq->buflen); - -/* - * Loop getting the maximum bytes we can get in a single straight line copy - */ - bytes_read = 0; - while (size > 0) { - this = ringqGetBlkMax(rq); - this = min(this, size); - if (this <= 0) { - break; - } - - memcpy(buf, rq->servp, this); - buf += this; - rq->servp += this; - size -= this; - bytes_read += this; - - if (rq->servp >= rq->endbuf) { - rq->servp = rq->buf; - } - } - return bytes_read; -} - -/******************************************************************************/ -/* - * Return the maximum number of bytes the ring q can accept via a single - * block copy. Useful if the user is doing their own data insertion. - */ - -int ringqPutBlkMax(ringq_t *rq) -{ - int space, in_a_line; - - a_assert(rq); - a_assert(rq->buflen == (rq->endbuf - rq->buf)); - - space = rq->buflen - RINGQ_LEN(rq) - 1; - in_a_line = rq->endbuf - rq->endp; - - return min(in_a_line, space); -} - -/******************************************************************************/ -/* - * Return the maximum number of bytes the ring q can provide via a single - * block copy. Useful if the user is doing their own data retrieval. - */ - -int ringqGetBlkMax(ringq_t *rq) -{ - int len, in_a_line; - - a_assert(rq); - a_assert(rq->buflen == (rq->endbuf - rq->buf)); - - len = RINGQ_LEN(rq); - in_a_line = rq->endbuf - rq->servp; - - return min(in_a_line, len); -} - -/******************************************************************************/ -/* - * Adjust the endp pointer after the user has copied data into the queue. - */ - -void ringqPutBlkAdj(ringq_t *rq, int size) -{ - a_assert(rq); - a_assert(rq->buflen == (rq->endbuf - rq->buf)); - a_assert(0 <= size && size < rq->buflen); - - rq->endp += size; - if (rq->endp >= rq->endbuf) { - rq->endp -= rq->buflen; - } -/* - * Flush the queue if the endp pointer is corrupted via a bad size - */ - if (rq->endp >= rq->endbuf) { - error(E_L, E_LOG, T("Bad end pointer")); - ringqFlush(rq); - } -} - -/******************************************************************************/ -/* - * Adjust the servp pointer after the user has copied data from the queue. - */ - -void ringqGetBlkAdj(ringq_t *rq, int size) -{ - a_assert(rq); - a_assert(rq->buflen == (rq->endbuf - rq->buf)); - a_assert(0 < size && size < rq->buflen); - - rq->servp += size; - if (rq->servp >= rq->endbuf) { - rq->servp -= rq->buflen; - } -/* - * Flush the queue if the servp pointer is corrupted via a bad size - */ - if (rq->servp >= rq->endbuf) { - error(E_L, E_LOG, T("Bad serv pointer")); - ringqFlush(rq); - } -} - -/******************************************************************************/ -/* - * Flush all data in a ring q. Reset the pointers. - */ - -void ringqFlush(ringq_t *rq) -{ - a_assert(rq); - a_assert(rq->servp); - - rq->servp = rq->buf; - rq->endp = rq->buf; - if (rq->servp) { - *rq->servp = '\0'; - } -} - -/******************************************************************************/ -/* - * Grow the buffer. Return true if the buffer can be grown. Grow using - * the increment size specified when opening the ringq. Don't grow beyond - * the maximum possible size. - */ - -static int ringqGrow(ringq_t *rq) -{ - unsigned char *newbuf; - int len; - - a_assert(rq); - - if (rq->maxsize >= 0 && rq->buflen >= rq->maxsize) { - return 0; - } - - len = ringqLen(rq); - - if ((newbuf = balloc(B_L, rq->buflen + rq->increment)) == NULL) { - return 0; - } - ringqGetBlk(rq, newbuf, ringqLen(rq)); - bfree(B_L, (char*) rq->buf); - -#ifdef OLD - rq->endp = &newbuf[endp]; - rq->servp = &newbuf[servp]; - rq->endbuf = &newbuf[rq->buflen]; - rq->buf = newbuf; -#endif - - rq->buflen += rq->increment; - rq->endp = newbuf; - rq->servp = newbuf; - rq->buf = newbuf; - 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)); -} - -/******************************************************************************/ diff --git a/cpukit/httpd/rom.c b/cpukit/httpd/rom.c deleted file mode 100644 index f9ff5312ac..0000000000 --- a/cpukit/httpd/rom.c +++ /dev/null @@ -1,193 +0,0 @@ -/* - * rom.c -- Support for ROMed page retrieval. - * - * Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved. - * - * See the file "license.txt" for usage and redistribution license requirements - * - * $Id$ - */ - -/******************************** Description *********************************/ - -/* - * This module provides web page retrieval from compiled web pages. Use the - * webcomp program to compile web pages and link into the GoAhead WebServer. - * This module uses a hashed symbol table for fast page lookup. - * - * Usage: webcomp -f webPageFileList -p Prefix >webrom.c - */ - -/********************************* Includes ***********************************/ - -#include <stdlib.h> - -#include "wsIntrn.h" - -/******************************** Local Data **********************************/ - -#ifdef WEBS_PAGE_ROM - -sym_fd_t romTab; /* Symbol table for web pages */ - -/*********************************** Code *************************************/ -/* - * Open the ROM module - */ - -int websRomOpen() -{ - websRomPageIndexType *wip; - int nchars; - char_t name[SYM_MAX]; - - romTab = symOpen(WEBS_SYM_INIT); - - for (wip = websRomPageIndex; wip->path; wip++) { - gstrncpy(name, wip->path, SYM_MAX); - nchars = gstrlen(name) - 1; - if (nchars > 0 && - (name[nchars] == '/' || name[nchars] == '\\')) { - name[nchars] = '\0'; - } - symEnter(romTab, name, valueInteger((int) wip), 0); - } - return 0; -} - -/******************************************************************************/ -/* - * Close the ROM module - */ - -void websRomClose() -{ - symClose(romTab); -} - -/******************************************************************************/ -/* - * Open a web page - */ - -int websRomPageOpen(webs_t wp, char_t *path, int mode, int perm) -{ - websRomPageIndexType *wip; - sym_t *sp; - - a_assert(websValid(wp)); - a_assert(path && *path); - - if ((sp = symLookup(romTab, path)) == NULL) { - return -1; - } - wip = (websRomPageIndexType*) sp->content.value.integer; - wip->pos = 0; - return (wp->docfd = wip - websRomPageIndex); -} - -/******************************************************************************/ -/* - * Close a web page - */ - -void websRomPageClose(int fd) -{ -} - -/******************************************************************************/ -/* - * Stat a web page - */ - -int websRomPageStat(char_t *path, websStatType *sbuf) -{ - websRomPageIndexType *wip; - sym_t *sp; - - a_assert(path && *path); - - if ((sp = symLookup(romTab, path)) == NULL) { - return -1; - } - wip = (websRomPageIndexType*) sp->content.value.integer; - - memset(sbuf, 0, sizeof(websStatType)); - sbuf->size = wip->size; - if (wip->page == NULL) { - sbuf->isDir = 1; - } - return 0; -} - -/******************************************************************************/ -/* - * Read a web page - */ - -int websRomPageReadData(webs_t wp, char *buf, int nBytes) -{ - websRomPageIndexType *wip; - int len; - - a_assert(websValid(wp)); - a_assert(buf); - a_assert(wp->docfd >= 0); - - wip = &websRomPageIndex[wp->docfd]; - - len = min(wip->size - wip->pos, nBytes); - memcpy(buf, &wip->page[wip->pos], len); - wip->pos += len; - return len; -} - -/******************************************************************************/ -/* - * Position a web page - */ - -long websRomPageSeek(webs_t wp, long offset, int origin) -{ - websRomPageIndexType *wip; - long pos; - - a_assert(websValid(wp)); - a_assert(origin == SEEK_SET || origin == SEEK_CUR || origin == SEEK_END); - a_assert(wp->docfd >= 0); - - wip = &websRomPageIndex[wp->docfd]; - - if (origin != SEEK_SET && origin != SEEK_CUR && origin != SEEK_END) { - errno = EINVAL; - return -1; - } - - if (wp->docfd < 0) { - errno = EBADF; - return -1; - } - - pos = offset; - switch (origin) { - case SEEK_CUR: - pos = wip->pos + offset; - break; - case SEEK_END: - pos = wip->size + offset; - break; - default: - break; - } - - if (pos < 0) { - errno = EBADF; - return -1; - } - - return (wip->pos = pos); -} - -#endif /* WEBS_PAGE_ROM */ - -/******************************************************************************/ diff --git a/cpukit/httpd/rtems_webserver.h b/cpukit/httpd/rtems_webserver.h deleted file mode 100644 index d2e1362865..0000000000 --- a/cpukit/httpd/rtems_webserver.h +++ /dev/null @@ -1,17 +0,0 @@ -/** - * @file rtems/rtems_webserver.h - */ - -#ifndef _rtems_rtems_webserver_h -#define _rtems_rtems_webserver_h - -#ifdef __cplusplus -extern "C" { -#endif - -int rtems_initialize_webserver(); - -#ifdef __cplusplus -} -#endif -#endif diff --git a/cpukit/httpd/security.c b/cpukit/httpd/security.c deleted file mode 100644 index be8bf812f2..0000000000 --- a/cpukit/httpd/security.c +++ /dev/null @@ -1,235 +0,0 @@ -/* - * security.c -- Security handler - * - * Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved. - * - * See the file "license.txt" for usage and redistribution license requirements - * - * $Id$ - */ - -/******************************** Description *********************************/ - -/* - * 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 *************************************/ -/* - * Determine if this request should be honored - */ - -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, *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, 405, T("Access Denied\nSecure access is required.")); - trace(3, T("SEC: Non-secure access attempted on <%s>\n"), path); - /* bugfix 5/24/02 -- we were leaking the memory pointed to by - * 'accessLimit'. Thanks to Simon Byholm. - */ - bfree(B_L, accessLimit); - return 1; - } -#endif - -/* - * Get the access limit for the URL - */ - am = umGetAccessMethodForURL(accessLimit); - - 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, 401, 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, 401, 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, 405, T("Access Denied\nWrong Password")); - nRet = 1; - } - - bfree (B_L, digestCalc); -#endif - } else { -/* - * 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("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; - } - - bfree(B_L, accessLimit); - - return nRet; -} - -/******************************************************************************/ -/* - * Delete the default security handler - */ - -void websSecurityDelete(void) -{ - websUrlHandlerDelete(websSecurityHandler); -} - -/******************************************************************************/ -/* - * Store the new password, expect a decoded password. Store in websPassword in - * the decoded form. - */ - -void websSetPassword(char_t *password) -{ - a_assert(password); - - gstrncpy(websPassword, password, TSZ(websPassword)); -} - -/******************************************************************************/ -/* - * Get password, return the decoded form - */ - -char_t *websGetPassword(void) -{ - return bstrdup(B_L, websPassword); -} - -/******************************************************************************/ diff --git a/cpukit/httpd/sock.c b/cpukit/httpd/sock.c deleted file mode 100644 index d962697773..0000000000 --- a/cpukit/httpd/sock.c +++ /dev/null @@ -1,791 +0,0 @@ -/* - * sock.c -- Posix Socket upper layer support module for general posix use - * - * Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved. - * - * $Id$ - */ - -/******************************** Description *********************************/ - -/* - * Posix Socket Module. This supports blocking and non-blocking buffered - * socket I/O. - */ - -/********************************** Includes **********************************/ - -#include <string.h> -#include <stdlib.h> - -#ifdef UEMF - #include "uemf.h" -#else - #include <socket.h> - #include <types.h> - #include <unistd.h> - #include "emfInternal.h" -#endif - -/************************************ Locals **********************************/ - -socket_t **socketList; /* List of open sockets */ -int socketMax; /* Maximum size of socket */ -int socketHighestFd = -1; /* Highest socket fd opened */ - -/***************************** Forward Declarations ***************************/ - -static int socketDoOutput(socket_t *sp, char *buf, int toWrite, int *errCode); -static int tryAlternateSendTo(int sock, char *buf, int toWrite, int i, - struct sockaddr *server); - -/*********************************** Code *************************************/ -/* - * Write to a socket. Absorb as much data as the socket can buffer. Block if - * the socket is in blocking mode. Returns -1 on error, otherwise the number - * of bytes written. - */ - -int socketWrite(int sid, char *buf, int bufsize) -{ - socket_t *sp; - ringq_t *rq; - int len, bytesWritten, room; - - a_assert(buf); - a_assert(bufsize >= 0); - - if ((sp = socketPtr(sid)) == NULL) { - return -1; - } - -/* - * Loop adding as much data to the output ringq as we can absorb. Initiate a - * flush when the ringq is too full and continue. Block in socketFlush if the - * socket is in blocking mode. - */ - rq = &sp->outBuf; - for (bytesWritten = 0; bufsize > 0; ) { - if ((room = ringqPutBlkMax(rq)) == 0) { - if (socketFlush(sid) < 0) { - return -1; - } - if ((room = ringqPutBlkMax(rq)) == 0) { - if (sp->flags & SOCKET_BLOCK) { -#if (defined (WIN) || defined (CE)) - int errCode; - if (! socketWaitForEvent(sp, FD_WRITE | SOCKET_WRITABLE, - &errCode)) { - return -1; - } -#endif - continue; - } - break; - } - continue; - } - len = min(room, bufsize); - ringqPutBlk(rq, (unsigned char *) buf, len); - bytesWritten += len; - bufsize -= len; - buf += len; - } - return bytesWritten; -} - -/******************************************************************************/ -/* - * Write a string to a socket - */ - -int socketWriteString(int sid, char_t *buf) -{ - #ifdef UNICODE - char *byteBuf; - int r, len; - - len = gstrlen(buf); - byteBuf = ballocUniToAsc(buf, len); - r = socketWrite(sid, byteBuf, len); - bfreeSafe(B_L, byteBuf); - return r; - #else - return socketWrite(sid, buf, strlen(buf)); - #endif /* UNICODE */ -} - -/******************************************************************************/ -/* - * Read from a socket. Return the number of bytes read if successful. This - * may be less than the requested "bufsize" and may be zero. Return -1 for - * errors. Return 0 for EOF. Otherwise return the number of bytes read. - * If this routine returns zero it indicates an EOF condition. - * which can be verified with socketEof() - - * Note: this ignores the line buffer, so a previous socketGets - * which read a partial line may cause a subsequent socketRead to miss some - * data. This routine may block if the socket is in blocking mode. - * - */ - -int socketRead(int sid, char *buf, int bufsize) -{ - socket_t *sp; - ringq_t *rq; - int len, room, errCode, bytesRead; - - a_assert(buf); - a_assert(bufsize > 0); - - if ((sp = socketPtr(sid)) == NULL) { - return -1; - } - - if (sp->flags & SOCKET_EOF) { - return 0; - } - - rq = &sp->inBuf; - for (bytesRead = 0; bufsize > 0; ) { - len = min(ringqLen(rq), bufsize); - if (len <= 0) { -/* - * if blocking mode and already have data, exit now or it may block - * forever. - */ - if ((sp->flags & SOCKET_BLOCK) && - (bytesRead > 0)) { - break; - } -/* - * This flush is critical for readers of datagram packets. If the - * buffer is not big enough to read the whole datagram in one hit, - * the recvfrom call will fail. - */ - ringqFlush(rq); - room = ringqPutBlkMax(rq); - len = socketGetInput(sid, (char *) rq->endp, room, &errCode); - if (len < 0) { - if (errCode == EWOULDBLOCK) { - if ((sp->flags & SOCKET_BLOCK) && - (bytesRead == 0)) { - continue; - } - if (bytesRead >= 0) { - return bytesRead; - } - } - return -1; - - } else if (len == 0) { -/* - * If bytesRead is 0, this is EOF since socketRead should never - * be called unless there is data yet to be read. Set the flag. - * Then pass back the number of bytes read. - */ - if (bytesRead == 0) { - sp->flags |= SOCKET_EOF; - } - return bytesRead; - } - ringqPutBlkAdj(rq, len); - len = min(len, bufsize); - } - memcpy(&buf[bytesRead], rq->servp, len); - ringqGetBlkAdj(rq, len); - bufsize -= len; - bytesRead += len; - } - return bytesRead; -} - -/******************************************************************************/ -/* - * Get a string from a socket. This returns data in *buf in a malloced string - * after trimming the '\n'. If there is zero bytes returned, *buf will be set - * to NULL. If doing non-blocking I/O, it returns -1 for error, EOF or when - * no complete line yet read. If doing blocking I/O, it will block until an - * entire line is read. If a partial line is read socketInputBuffered or - * socketEof can be used to distinguish between EOF and partial line still - * buffered. This routine eats and ignores carriage returns. - */ - -int socketGets(int sid, char_t **buf) -{ - socket_t *sp; - ringq_t *lq; - char c; - int rc, len; - - a_assert(buf); - *buf = NULL; - - if ((sp = socketPtr(sid)) == NULL) { - return -1; - } - lq = &sp->lineBuf; - - while (1) { - - if ((rc = socketRead(sid, &c, 1)) < 0) { - return rc; - } - - if (rc == 0) { -/* - * If there is a partial line and we are at EOF, pretend we saw a '\n' - */ - if (ringqLen(lq) > 0 && (sp->flags & SOCKET_EOF)) { - c = '\n'; - } else { - return -1; - } - } -/* - * If a newline is seen, return the data excluding the new line to the - * caller. If carriage return is seen, just eat it. - */ - if (c == '\n') { - len = ringqLen(lq); - if (len > 0) { - *buf = ballocAscToUni((char *)lq->servp, len); - } else { - *buf = NULL; - } - ringqFlush(lq); - return len; - - } else if (c == '\r') { - continue; - } - ringqPutcA(lq, c); - } - return 0; -} - -/******************************************************************************/ -/* - * Flush the socket. Block if the socket is in blocking mode. - * This will return -1 on errors and 0 if successful. - */ - -int socketFlush(int sid) -{ - socket_t *sp; - ringq_t *rq; - int len, bytesWritten, errCode; - - if ((sp = socketPtr(sid)) == NULL) { - return -1; - } - rq = &sp->outBuf; - -/* - * Set the background flushing flag which socketEventProc will check to - * continue the flush. - */ - if (! (sp->flags & SOCKET_BLOCK)) { - sp->flags |= SOCKET_FLUSHING; - } - -/* - * Break from loop if not blocking after initiating output. If we are blocking - * we wait for a write event. - */ - while (ringqLen(rq) > 0) { - len = ringqGetBlkMax(&sp->outBuf); - bytesWritten = socketDoOutput(sp, (char*) rq->servp, len, &errCode); - if (bytesWritten < 0) { - if (errCode == EINTR) { - continue; - } else if (errCode == EWOULDBLOCK || errCode == EAGAIN) { -#if (defined (WIN) || defined (CE)) - if (sp->flags & SOCKET_BLOCK) { - int errCode; - if (! socketWaitForEvent(sp, FD_WRITE | SOCKET_WRITABLE, - &errCode)) { - return -1; - } - continue; - } -#endif -/* - * Ensure we get a FD_WRITE message when the socket can absorb - * more data (non-blocking only.) Store the user's mask if we - * haven't done it already. - */ - if (sp->saveMask < 0 ) { - sp->saveMask = sp->handlerMask; - socketRegisterInterest(sp, - sp->handlerMask | SOCKET_WRITABLE); - } - return 0; - } - return -1; - } - ringqGetBlkAdj(rq, bytesWritten); - } -/* - * If the buffer is empty, reset the ringq pointers to point to the start - * of the buffer. This is essential to ensure that datagrams get written - * in one single I/O operation. - */ - if (ringqLen(rq) == 0) { - ringqFlush(rq); - } -/* - * Restore the users mask if it was saved by the non-blocking code above. - * Note: saveMask = -1 if empty. socketRegisterInterest will set handlerMask - */ - if (sp->saveMask >= 0) { - socketRegisterInterest(sp, sp->saveMask); - sp->saveMask = -1; - } - sp->flags &= ~SOCKET_FLUSHING; - return 0; -} - -/******************************************************************************/ -/* - * Return the count of input characters buffered. We look at both the line - * buffer and the input (raw) buffer. Return -1 on error or EOF. - */ - -int socketInputBuffered(int sid) -{ - socket_t *sp; - - if ((sp = socketPtr(sid)) == NULL) { - return -1; - } - if (socketEof(sid)) { - return -1; - } - return ringqLen(&sp->lineBuf) + ringqLen(&sp->inBuf); -} - -/******************************************************************************/ -/* - * Return true if EOF - */ - -int socketEof(int sid) -{ - socket_t *sp; - - if ((sp = socketPtr(sid)) == NULL) { - return -1; - } - return sp->flags & SOCKET_EOF; -} - -/******************************************************************************/ -/* - * Return the number of bytes the socket can absorb without blocking - */ - -int socketCanWrite(int sid) -{ - socket_t *sp; - - if ((sp = socketPtr(sid)) == NULL) { - return -1; - } - return sp->outBuf.buflen - ringqLen(&sp->outBuf) - 1; -} - -/******************************************************************************/ -/* - * Add one to allow the user to write exactly SOCKET_BUFSIZ - */ - -void socketSetBufferSize(int sid, int in, int line, int out) -{ - socket_t *sp; - - if ((sp = socketPtr(sid)) == NULL) { - return; - } - - if (in >= 0) { - ringqClose(&sp->inBuf); - in++; - ringqOpen(&sp->inBuf, in, in); - } - - if (line >= 0) { - ringqClose(&sp->lineBuf); - line++; - ringqOpen(&sp->lineBuf, line, line); - } - - if (out >= 0) { - ringqClose(&sp->outBuf); - out++; - ringqOpen(&sp->outBuf, out, out); - } -} - -/******************************************************************************/ -/* - * Create a user handler for this socket. The handler called whenever there - * is an event of interest as defined by handlerMask (SOCKET_READABLE, ...) - */ - -void socketCreateHandler(int sid, int handlerMask, socketHandler_t handler, - int data) -{ - socket_t *sp; - - if ((sp = socketPtr(sid)) == NULL) { - return; - } - sp->handler = handler; - sp->handler_data = data; - socketRegisterInterest(sp, handlerMask); -} - -/******************************************************************************/ -/* - * Delete a handler - */ - -void socketDeleteHandler(int sid) -{ - socket_t *sp; - - if ((sp = socketPtr(sid)) == NULL) { - return; - } - sp->handler = NULL; - socketRegisterInterest(sp, 0); -} - -/******************************************************************************/ -/* - * Socket output procedure. Return -1 on errors otherwise return the number - * of bytes written. - */ - -static int socketDoOutput(socket_t *sp, char *buf, int toWrite, int *errCode) -{ - struct sockaddr_in server; - int bytes; - - a_assert(sp); - a_assert(buf); - a_assert(toWrite > 0); - a_assert(errCode); - - *errCode = 0; - -#if (defined (WIN) || defined (CE)) - if ((sp->flags & SOCKET_ASYNC) - && ! socketWaitForEvent(sp, FD_CONNECT, errCode)) { - return -1; - } -#endif - -/* - * Write the data - */ - if (sp->flags & SOCKET_BROADCAST) { - server.sin_family = AF_INET; -#if (defined (UEMF) || defined (LITTLEFOOT)) - server.sin_addr.s_addr = INADDR_BROADCAST; -#else - server.sin_addr.s_addr = inet_addr(basicGetBroadcastAddress()); -#endif - server.sin_port = htons((short)(sp->port & 0xFFFF)); - if ((bytes = sendto(sp->sock, buf, toWrite, 0, - (struct sockaddr *) &server, sizeof(server))) < 0) { - bytes = tryAlternateSendTo(sp->sock, buf, toWrite, 0, - (struct sockaddr *) &server); - } - } else if (sp->flags & SOCKET_DATAGRAM) { - server.sin_family = AF_INET; - server.sin_addr.s_addr = inet_addr(sp->host); - server.sin_port = htons((short)(sp->port & 0xFFFF)); - bytes = sendto(sp->sock, buf, toWrite, 0, - (struct sockaddr *) &server, sizeof(server)); - - } else { - bytes = send(sp->sock, buf, toWrite, 0); - } - - if (bytes < 0) { - *errCode = socketGetError(); -#if (defined (WIN) || defined (CE)) - sp->currentEvents &= ~FD_WRITE; -#endif - - return -1; - - } else if (bytes == 0 && bytes != toWrite) { - *errCode = EWOULDBLOCK; -#if (defined (WIN) || defined (CE)) - sp->currentEvents &= ~FD_WRITE; -#endif - return -1; - } - -/* - * Ensure we get to write some more data real soon if the socket can absorb - * more data - */ -#ifndef UEMF -#ifdef WIN - if (sp->interestEvents & FD_WRITE) { - emfTime_t blockTime = { 0, 0 }; - emfSetMaxBlockTime(&blockTime); - } -#endif /* WIN */ -#endif - return bytes; -} - -/******************************************************************************/ -/* - * If the sendto failed, swap the first two bytes in the - * sockaddr structure. This is a kludge due to a change in - * VxWorks between versions 5.3 and 5.4, but we want the - * product to run on either. - */ -static int tryAlternateSendTo(int sock, char *buf, int toWrite, int i, - struct sockaddr *server) -{ -#ifdef VXWORKS - char *ptr; - - ptr = (char *)server; - *ptr = *(ptr+1); - *(ptr+1) = 0; - return sendto(sock, buf, toWrite, i, server, sizeof(struct sockaddr)); -#else - return -1; -#endif /* VXWORKS */ -} - -/******************************************************************************/ -/* - * Allocate a new socket structure - */ - -int socketAlloc(char *host, int port, socketAccept_t accept, int flags) -{ - socket_t *sp; - int sid; - - if ((sid = hAllocEntry((void*) &socketList, &socketMax, - sizeof(socket_t))) < 0) { - return -1; - } - sp = socketList[sid]; - - sp->sid = sid; - sp->accept = accept; - sp->port = port; - sp->fileHandle = -1; - sp->saveMask = -1; - - if (host) { - strncpy(sp->host, host, sizeof(sp->host)); - } - -/* - * Preserve only specified flags from the callers open - */ - a_assert((flags & ~(SOCKET_BROADCAST|SOCKET_DATAGRAM|SOCKET_BLOCK| - SOCKET_LISTENING)) == 0); - sp->flags = flags & (SOCKET_BROADCAST | SOCKET_DATAGRAM | SOCKET_BLOCK| - SOCKET_LISTENING); - -/* - * Add one to allow the user to write exactly SOCKET_BUFSIZ - */ - ringqOpen(&sp->inBuf, SOCKET_BUFSIZ, SOCKET_BUFSIZ); - ringqOpen(&sp->outBuf, SOCKET_BUFSIZ + 1, SOCKET_BUFSIZ + 1); - ringqOpen(&sp->lineBuf, SOCKET_BUFSIZ, -1); - - return sid; -} - -/******************************************************************************/ -/* - * Free a socket structure - */ - -void socketFree(int sid) -{ - socket_t *sp; - char_t buf[256]; - int i; - - if ((sp = socketPtr(sid)) == NULL) { - return; - } - -/* - * To close a socket, remove any registered interests, set it to - * non-blocking so that the recv which follows won't block, do a - * shutdown on it so peers on the other end will receive a FIN, - * then read any data not yet retrieved from the receive buffer, - * and finally close it. If these steps are not all performed - * RESETs may be sent to the other end causing problems. - */ - socketRegisterInterest(sp, 0); - if (sp->sock >= 0) { - socketSetBlock(sid, 0); - if (shutdown(sp->sock, 1) >= 0) { - recv(sp->sock, buf, sizeof(buf), 0); - } -#if (defined (WIN) || defined (CE)) - closesocket(sp->sock); -#else - close(sp->sock); -#endif - } - - ringqClose(&sp->inBuf); - ringqClose(&sp->outBuf); - ringqClose(&sp->lineBuf); - - bfree(B_L, sp); - socketMax = hFree((void*) &socketList, sid); - -/* - * Calculate the new highest socket number - */ - socketHighestFd = -1; - for (i = 0; i < socketMax; i++) { - if ((sp = socketList[i]) == NULL) { - continue; - } - socketHighestFd = max(socketHighestFd, sp->sock); - } -} - -/******************************************************************************/ -/* - * Validate a socket handle - */ - -socket_t *socketPtr(int sid) -{ - if (sid < 0 || sid >= socketMax || socketList[sid] == NULL) { - a_assert(NULL); - errno = EBADF; - return NULL; - } - - a_assert(socketList[sid]); - return socketList[sid]; -} - -/******************************************************************************/ -/* - * Get the operating system error code - */ - -int socketGetError(void) -{ -#if (defined (WIN) || defined (CE)) - switch (WSAGetLastError()) { - case WSAEWOULDBLOCK: - return EWOULDBLOCK; - case WSAECONNRESET: - return ECONNRESET; - case WSAENETDOWN: - return ENETDOWN; - case WSAEPROCLIM: - return EAGAIN; - case WSAEINTR: - return EINTR; - default: - return EINVAL; - } -#else - return errno; -#endif -} - -/******************************************************************************/ -/* - * Return the underlying socket handle - */ - -int socketGetHandle(int sid) -{ - socket_t *sp; - - if ((sp = socketPtr(sid)) == NULL) { - return -1; - } - return sp->sock; -} - -/******************************************************************************/ -/* - * Get blocking mode - */ - -int socketGetBlock(int sid) -{ - socket_t *sp; - - if ((sp = socketPtr(sid)) == NULL) { - a_assert(0); - return 0; - } - return (sp->flags & SOCKET_BLOCK); -} - -/******************************************************************************/ -/* - * Get mode - */ - -int socketGetMode(int sid) -{ - socket_t *sp; - - if ((sp = socketPtr(sid)) == NULL) { - a_assert(0); - return 0; - } - return sp->flags; -} - -/******************************************************************************/ -/* - * Set mode - */ - -void socketSetMode(int sid, int mode) -{ - socket_t *sp; - - if ((sp = socketPtr(sid)) == NULL) { - a_assert(0); - return; - } - sp->flags = mode; -} - -/******************************************************************************/ -/* - * Get port. - */ - -int socketGetPort(int sid) -{ - socket_t *sp; - - if ((sp = socketPtr(sid)) == NULL) { - return -1; - } - return sp->port; -} - -/******************************************************************************/ diff --git a/cpukit/httpd/sockGen.c b/cpukit/httpd/sockGen.c deleted file mode 100644 index e3319f3a92..0000000000 --- a/cpukit/httpd/sockGen.c +++ /dev/null @@ -1,1043 +0,0 @@ - -/* - * sockGen.c -- Posix Socket support module for general posix use - * - * Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved. - * - * $Id$ - */ - -/******************************** Description *********************************/ - -/* - * Posix Socket Module. This supports blocking and non-blocking buffered - * socket I/O. - */ - -#if (!defined (WIN) || defined (LITTLEFOOT) || defined (WEBS)) - -/********************************** Includes **********************************/ - -#include <errno.h> -#include <fcntl.h> -#include <string.h> -#include <stdlib.h> - -#ifdef UEMF - #include "uemf.h" -#else - #include <socket.h> - #include <types.h> - #include <unistd.h> - #include "emfInternal.h" -#endif - -#ifdef VXWORKS - #include <hostLib.h> -#endif - -/************************************ Locals **********************************/ - -extern socket_t **socketList; /* List of open sockets */ -extern int socketMax; /* Maximum size of socket */ -extern int socketHighestFd; /* Highest socket fd opened */ -static int socketOpenCount = 0; /* Number of task using sockets */ - -/***************************** Forward Declarations ***************************/ - -static void socketAccept(socket_t *sp); -static int socketDoEvent(socket_t *sp); -static int tryAlternateConnect(int sock, struct sockaddr *sockaddr); - -/*********************************** Code *************************************/ -/* - * Open socket module - */ - -int socketOpen() -{ -#if (defined (CE) || defined (WIN)) - WSADATA wsaData; -#endif - - if (++socketOpenCount > 1) { - return 0; - } - -#if (defined (CE) || defined (WIN)) - if (WSAStartup(MAKEWORD(1,1), &wsaData) != 0) { - return -1; - } - if (wsaData.wVersion != MAKEWORD(1,1)) { - WSACleanup(); - return -1; - } -#endif - - socketList = NULL; - socketMax = 0; - socketHighestFd = -1; - - return 0; -} - -/******************************************************************************/ -/* - * Close the socket module, by closing all open connections - */ - -void socketClose() -{ - int i; - - if (--socketOpenCount <= 0) { - for (i = socketMax; i >= 0; i--) { - if (socketList && socketList[i]) { - socketCloseConnection(i); - } - } - socketOpenCount = 0; - } -} - -/******************************************************************************/ -/* - * Open a client or server socket. Host is NULL if we want server capability. - */ - -int socketOpenConnection(char *host, int port, socketAccept_t accept, int flags) -{ -#if (!defined (NO_GETHOSTBYNAME) && !defined (VXWORKS)) - struct hostent *hostent; /* Host database entry */ -#endif /* ! (NO_GETHOSTBYNAME || VXWORKS) */ - socket_t *sp; - struct sockaddr_in sockaddr; - int sid, bcast, dgram, rc; - - if (port > SOCKET_PORT_MAX) { - return -1; - } -/* - * Allocate a socket structure - */ - if ((sid = socketAlloc(host, port, accept, flags)) < 0) { - return -1; - } - sp = socketList[sid]; - a_assert(sp); - -/* - * Create the socket address structure - */ - memset((char *) &sockaddr, '\0', sizeof(struct sockaddr_in)); - sockaddr.sin_family = AF_INET; - sockaddr.sin_port = htons((short) (port & 0xFFFF)); - - if (host == NULL) { - sockaddr.sin_addr.s_addr = INADDR_ANY; - } else { - sockaddr.sin_addr.s_addr = inet_addr(host); - if (sockaddr.sin_addr.s_addr == INADDR_NONE) { -/* - * If the OS does not support gethostbyname functionality, the macro: - * NO_GETHOSTBYNAME should be defined to skip the use of gethostbyname. - * Unfortunatly there is no easy way to recover, the following code - * simply uses the basicGetHost IP for the sockaddr. - */ - -#ifdef NO_GETHOSTBYNAME - if (strcmp(host, basicGetHost()) == 0) { - sockaddr.sin_addr.s_addr = inet_addr(basicGetAddress()); - } - if (sockaddr.sin_addr.s_addr == INADDR_NONE) { - socketFree(sid); - return -1; - } -#elif (defined (VXWORKS)) - sockaddr.sin_addr.s_addr = (unsigned long) hostGetByName(host); - if (sockaddr.sin_addr.s_addr == NULL) { - errno = ENXIO; - socketFree(sid); - return -1; - } -#else - hostent = gethostbyname(host); - if (hostent != NULL) { - memcpy((char *) &sockaddr.sin_addr, - (char *) hostent->h_addr_list[0], - (size_t) hostent->h_length); - } else { - char *asciiAddress; - char_t *address; - - address = basicGetAddress(); - asciiAddress = ballocUniToAsc(address, gstrlen(address)); - sockaddr.sin_addr.s_addr = inet_addr(asciiAddress); - bfree(B_L, asciiAddress); - if (sockaddr.sin_addr.s_addr == INADDR_NONE) { - errno = ENXIO; - socketFree(sid); - return -1; - } - } -#endif /* (NO_GETHOSTBYNAME || VXWORKS) */ - } - } - - bcast = sp->flags & SOCKET_BROADCAST; - if (bcast) { - sp->flags |= SOCKET_DATAGRAM; - } - dgram = sp->flags & SOCKET_DATAGRAM; - -/* - * Create the socket. Support for datagram sockets. Set the close on - * exec flag so children don't inherit the socket. - */ - sp->sock = socket(AF_INET, dgram ? SOCK_DGRAM: SOCK_STREAM, 0); - if (sp->sock < 0) { - socketFree(sid); - return -1; - } -#ifndef __NO_FCNTL - fcntl(sp->sock, F_SETFD, FD_CLOEXEC); -#endif - socketHighestFd = max(socketHighestFd, sp->sock); - -/* - * If broadcast, we need to turn on broadcast capability. - */ - if (bcast) { - int broadcastFlag = 1; - if (setsockopt(sp->sock, SOL_SOCKET, SO_BROADCAST, - (char *) &broadcastFlag, sizeof(broadcastFlag)) < 0) { - socketFree(sid); - return -1; - } - } - -/* - * Host is set if we are the client - */ - if (host) { -/* - * Connect to the remote server in blocking mode, then go into - * non-blocking mode if desired. - */ - if (!dgram) { - if (! (sp->flags & SOCKET_BLOCK)) { -/* - * sockGen.c is only used for Windows products when blocking - * connects are expected. This applies to FieldUpgrader - * agents and open source webserver connectws. Therefore the - * asynchronous connect code here is not compiled. - */ -#if (defined (WIN) || defined (CE)) && (!defined (LITTLEFOOT) && !defined (WEBS)) - int flag; - - sp->flags |= SOCKET_ASYNC; -/* - * Set to non-blocking for an async connect - */ - flag = 1; - if (ioctlsocket(sp->sock, FIONBIO, &flag) == SOCKET_ERROR) { - socketFree(sid); - return -1; - } -#else - socketSetBlock(sid, 1); -#endif /* #if (WIN || CE) && !(LITTLEFOOT || WEBS) */ - - } - if ((rc = connect(sp->sock, (struct sockaddr *) &sockaddr, - sizeof(sockaddr))) < 0 && - (rc = tryAlternateConnect(sp->sock, - (struct sockaddr *) &sockaddr)) < 0) { -#if (defined (WIN) || defined (CE)) - if (socketGetError() != EWOULDBLOCK) { - socketFree(sid); - return -1; - } -#else - socketFree(sid); - return -1; - -#endif /* WIN || CE */ - - } - } - } else { -/* - * Bind to the socket endpoint and the call listen() to start listening - */ - rc = 1; - setsockopt(sp->sock, SOL_SOCKET, SO_REUSEADDR, (char *)&rc, sizeof(rc)); - if (bind(sp->sock, (struct sockaddr *) &sockaddr, - sizeof(sockaddr)) < 0) { - socketFree(sid); - return -1; - } - - if (! dgram) { - if (listen(sp->sock, SOMAXCONN) < 0) { - socketFree(sid); - return -1; - } -#ifndef UEMF - sp->fileHandle = emfCreateFileHandler(sp->sock, SOCKET_READABLE, - (emfFileProc *) socketAccept, (void *) sp); -#else - sp->flags |= SOCKET_LISTENING; -#endif - } - sp->handlerMask |= SOCKET_READABLE; - } - -/* - * Set the blocking mode - */ - - if (flags & SOCKET_BLOCK) { - socketSetBlock(sid, 1); - } else { - socketSetBlock(sid, 0); - } - return sid; -} - - -/******************************************************************************/ -/* - * If the connection failed, swap the first two bytes in the - * sockaddr structure. This is a kludge due to a change in - * VxWorks between versions 5.3 and 5.4, but we want the - * product to run on either. - */ - -static int tryAlternateConnect(int sock, struct sockaddr *sockaddr) -{ -#ifdef VXWORKS - char *ptr; - - ptr = (char *)sockaddr; - *ptr = *(ptr+1); - *(ptr+1) = 0; - return connect(sock, sockaddr, sizeof(struct sockaddr)); -#else - return -1; -#endif /* VXWORKS */ -} - -/******************************************************************************/ -/* - * Close a socket - */ - -void socketCloseConnection(int sid) -{ - socket_t *sp; - - if ((sp = socketPtr(sid)) == NULL) { - return; - } - socketFree(sid); -} - -/******************************************************************************/ -/* - * Accept a connection. Called as a callback on incoming connection. - */ - -static void socketAccept(socket_t *sp) -{ - struct sockaddr_in addr; - socket_t *nsp; - size_t len; - char *pString; - int newSock, nid; - - -#ifdef NW - NETINET_DEFINE_CONTEXT; -#endif - - a_assert(sp); - -/* - * Accept the connection and prevent inheriting by children (F_SETFD) - */ - len = sizeof(struct sockaddr_in); - if ((newSock = accept(sp->sock, (struct sockaddr *) &addr, (int *) &len)) < 0) { - return; - } -#ifndef __NO_FCNTL - fcntl(newSock, F_SETFD, FD_CLOEXEC); -#endif - socketHighestFd = max(socketHighestFd, newSock); - -/* - * Create a socket structure and insert into the socket list - */ - nid = socketAlloc(sp->host, sp->port, sp->accept, sp->flags); - nsp = socketList[nid]; - a_assert(nsp); - nsp->sock = newSock; - nsp->flags &= ~SOCKET_LISTENING; - - if (nsp == NULL) { - return; - } -/* - * Set the blocking mode before calling the accept callback. - */ - - socketSetBlock(nid, (nsp->flags & SOCKET_BLOCK) ? 1: 0); -/* - * Call the user accept callback. The user must call socketCreateHandler - * to register for further events of interest. - */ - if (sp->accept != NULL) { - pString = inet_ntoa(addr.sin_addr); - if ((sp->accept)(nid, pString, ntohs(addr.sin_port), sp->sid) < 0) { - socketFree(nid); - } -#ifdef VXWORKS - free(pString); -#endif - } -} - -/******************************************************************************/ -/* - * Get more input from the socket and return in buf. - * Returns 0 for EOF, -1 for errors and otherwise the number of bytes read. - */ - -int socketGetInput(int sid, char *buf, int toRead, int *errCode) -{ - struct sockaddr_in server; - socket_t *sp; - int len, bytesRead; - - a_assert(buf); - a_assert(errCode); - - *errCode = 0; - - if ((sp = socketPtr(sid)) == NULL) { - return -1; - } - -/* - * If we have previously seen an EOF condition, then just return - */ - if (sp->flags & SOCKET_EOF) { - return 0; - } -#if ((defined (WIN) || defined (CE)) && (!defined (LITTLEFOOT) && !defined (WEBS))) - if ( !(sp->flags & SOCKET_BLOCK) - && ! socketWaitForEvent(sp, FD_CONNECT, errCode)) { - return -1; - } -#endif - -/* - * Read the data - */ - if (sp->flags & SOCKET_DATAGRAM) { - len = sizeof(server); - bytesRead = recvfrom(sp->sock, buf, toRead, 0, - (struct sockaddr *) &server, &len); - } else { - bytesRead = recv(sp->sock, buf, toRead, 0); - } - - /* - * BUG 01865 -- CPU utilization hangs on Windows. The original code used - * the 'errno' global variable, which is not set by the winsock functions - * as it is under *nix platforms. We use the platform independent - * socketGetError() function instead, which does handle Windows correctly. - * Other, *nix compatible platforms should work as well, since on those - * platforms, socketGetError() just returns the value of errno. - * Thanks to Jonathan Burgoyne for the fix. - */ - if (bytesRead < 0) - { - *errCode = socketGetError(); - if (*errCode == ECONNRESET) - { - sp->flags |= SOCKET_CONNRESET; - return 0; - } - return -1; - } - return bytesRead; -} - -/******************************************************************************/ -/* - * Process an event on the event queue - */ - -#ifndef UEMF - -static int socketEventProc(void *data, int mask) -{ - socket_t *sp; - ringq_t *rq; - int sid; - - sid = (int) data; - - a_assert(sid >= 0 && sid < socketMax); - a_assert(socketList[sid]); - - if ((sp = socketPtr(sid)) == NULL) { - return 1; - } - -/* - * If now writable and flushing in the background, continue flushing - */ - if (mask & SOCKET_WRITABLE) { - if (sp->flags & SOCKET_FLUSHING) { - rq = &sp->outBuf; - if (ringqLen(rq) > 0) { - socketFlush(sp->sid); - } else { - sp->flags &= ~SOCKET_FLUSHING; - } - } - } - -/* - * Now invoke the users socket handler. NOTE: the handler may delete the - * socket, so we must be very careful after calling the handler. - */ - if (sp->handler && (sp->handlerMask & mask)) { - (sp->handler)(sid, mask & sp->handlerMask, sp->handler_data); - } - if (socketList && sid < socketMax && socketList[sid] == sp) { - socketRegisterInterest(sp, sp->handlerMask); - } - return 1; -} -#endif /* ! UEMF */ - -/******************************************************************************/ -/* - * Define the events of interest - */ - -void socketRegisterInterest(socket_t *sp, int handlerMask) -{ - a_assert(sp); - - sp->handlerMask = handlerMask; -#ifndef UEMF - if (handlerMask) { - sp->fileHandle = emfCreateFileHandler(sp->sock, handlerMask, - (emfFileProc *) socketEventProc, (void *) sp->sid); - } else { - emfDeleteFileHandler(sp->fileHandle); - sp->fileHandle = -1; - } -#endif /* ! UEMF */ -} - -/******************************************************************************/ -/* - * Wait until an event occurs on a socket. Return 1 on success, 0 on failure. - * or -1 on exception (UEMF only) - */ - -int socketWaitForEvent(socket_t *sp, int handlerMask, int *errCode) -{ - int mask; - - a_assert(sp); - - mask = sp->handlerMask; - sp->handlerMask |= handlerMask; - while (socketSelect(sp->sid, 1000)) { - if (sp->currentEvents & (handlerMask | SOCKET_EXCEPTION)) { - break; - } - } - sp->handlerMask = mask; - if (sp->currentEvents & SOCKET_EXCEPTION) { - return -1; - } else if (sp->currentEvents & handlerMask) { - return 1; - } - if (errCode) { - *errCode = errno = EWOULDBLOCK; - } - return 0; -} - -/******************************************************************************/ -/* - * Return TRUE if there is a socket with an event ready to process, - */ - -int socketReady(int sid) -{ - socket_t *sp; - int all; - - all = 0; - if (sid < 0) { - sid = 0; - all = 1; - } - - for (; sid < socketMax; sid++) { - if ((sp = socketList[sid]) == NULL) { - if (! all) { - break; - } else { - continue; - } - } - if (sp->flags & SOCKET_CONNRESET) { - socketCloseConnection(sid); - return 0; - } - if (sp->currentEvents & sp->handlerMask) { - return 1; - } -/* - * If there is input data, also call select to test for new events - */ - if (sp->handlerMask & SOCKET_READABLE && socketInputBuffered(sid) > 0) { - socketSelect(sid, 0); - return 1; - } - if (! all) { - break; - } - } - return 0; -} - -/******************************************************************************/ -/* - * Wait for a handle to become readable or writable and return a number of - * noticed events. Timeout is in milliseconds. - */ - -#if (defined (WIN) || defined (CE) || defined (NW)) - -int socketSelect(int sid, int timeout) -{ - struct timeval tv; - socket_t *sp; - fd_set readFds, writeFds, exceptFds; - int nEvents; - int all, socketHighestFd; /* Highest socket fd opened */ - - FD_ZERO(&readFds); - FD_ZERO(&writeFds); - FD_ZERO(&exceptFds); - socketHighestFd = -1; - - tv.tv_sec = timeout / 1000; - tv.tv_usec = (timeout % 1000) * 1000; - -/* - * Set the select event masks for events to watch - */ - all = nEvents = 0; - - if (sid < 0) { - all++; - sid = 0; - } - - for (; sid < socketMax; sid++) { - if ((sp = socketList[sid]) == NULL) { - continue; - } - a_assert(sp); -/* - * Set the appropriate bit in the ready masks for the sp->sock. - */ - if (sp->handlerMask & SOCKET_READABLE) { - FD_SET(sp->sock, &readFds); - nEvents++; - if (socketInputBuffered(sid) > 0) { - tv.tv_sec = 0; - tv.tv_usec = 0; - } - } - if (sp->handlerMask & SOCKET_WRITABLE) { - FD_SET(sp->sock, &writeFds); - nEvents++; - } - if (sp->handlerMask & SOCKET_EXCEPTION) { - FD_SET(sp->sock, &exceptFds); - nEvents++; - } - if (! all) { - break; - } - } - -/* - * Windows select() fails if no descriptors are set, instead of just sleeping - * like other, nice select() calls. So, if WIN, sleep. - */ - if (nEvents == 0) { - Sleep(timeout); - return 0; - } - -/* - * Wait for the event or a timeout. - */ - nEvents = select(socketHighestFd+1, &readFds, &writeFds, &exceptFds, &tv); - - if (all) { - sid = 0; - } - for (; sid < socketMax; sid++) { - if ((sp = socketList[sid]) == NULL) { - continue; - } - - if (FD_ISSET(sp->sock, &readFds) || socketInputBuffered(sid) > 0) { - sp->currentEvents |= SOCKET_READABLE; - } - if (FD_ISSET(sp->sock, &writeFds)) { - sp->currentEvents |= SOCKET_WRITABLE; - } - if (FD_ISSET(sp->sock, &exceptFds)) { - sp->currentEvents |= SOCKET_EXCEPTION; - } - if (! all) { - break; - } - } - - return nEvents; -} - -#else /* not WIN || CE || NW */ - -int socketSelect(int sid, int timeout) -{ - socket_t *sp; - struct timeval tv; - fd_mask *readFds, *writeFds, *exceptFds; - int all, len, nwords, index, bit, nEvents; - -/* - * Allocate and zero the select masks - */ - nwords = (socketHighestFd + NFDBITS) / NFDBITS; - len = nwords * sizeof(int); - - readFds = balloc(B_L, len); - memset(readFds, 0, len); - writeFds = balloc(B_L, len); - memset(writeFds, 0, len); - exceptFds = balloc(B_L, len); - memset(exceptFds, 0, len); - - tv.tv_sec = timeout / 1000; - tv.tv_usec = (timeout % 1000) * 1000; - -/* - * Set the select event masks for events to watch - */ - all = nEvents = 0; - - if (sid < 0) { - all++; - sid = 0; - } - - for (; sid < socketMax; sid++) { - if ((sp = socketList[sid]) == NULL) { - if (all == 0) { - break; - } else { - continue; - } - } - a_assert(sp); - -/* - * Initialize the ready masks and compute the mask offsets. - */ - index = sp->sock / (NBBY * sizeof(fd_mask)); - bit = 1 << (sp->sock % (NBBY * sizeof(fd_mask))); - -/* - * Set the appropriate bit in the ready masks for the sp->sock. - */ - if (sp->handlerMask & SOCKET_READABLE) { - readFds[index] |= bit; - nEvents++; - if (socketInputBuffered(sid) > 0) { - tv.tv_sec = 0; - tv.tv_usec = 0; - } - } - if (sp->handlerMask & SOCKET_WRITABLE) { - writeFds[index] |= bit; - nEvents++; - } - if (sp->handlerMask & SOCKET_EXCEPTION) { - exceptFds[index] |= bit; - nEvents++; - } - if (! all) { - break; - } - } - -/* - * Wait for the event or a timeout. Reset nEvents to be the number of actual - * events now. - */ - nEvents = select(socketHighestFd + 1, (fd_set *) readFds, - (fd_set *) writeFds, (fd_set *) exceptFds, &tv); - - if (nEvents > 0) { - if (all) { - sid = 0; - } - for (; sid < socketMax; sid++) { - if ((sp = socketList[sid]) == NULL) { - if (all == 0) { - break; - } else { - continue; - } - } - - index = sp->sock / (NBBY * sizeof(fd_mask)); - bit = 1 << (sp->sock % (NBBY * sizeof(fd_mask))); - - if (readFds[index] & bit || socketInputBuffered(sid) > 0) { - sp->currentEvents |= SOCKET_READABLE; - } - if (writeFds[index] & bit) { - sp->currentEvents |= SOCKET_WRITABLE; - } - if (exceptFds[index] & bit) { - sp->currentEvents |= SOCKET_EXCEPTION; - } - if (! all) { - break; - } - } - } - - bfree(B_L, readFds); - bfree(B_L, writeFds); - bfree(B_L, exceptFds); - - return nEvents; -} -#endif /* WIN || CE */ - -/******************************************************************************/ -/* - * Process socket events - */ - -void socketProcess(int sid) -{ - socket_t *sp; - int all; - - all = 0; - if (sid < 0) { - all = 1; - sid = 0; - } -/* - * Process each socket - */ - for (; sid < socketMax; sid++) { - if ((sp = socketList[sid]) == NULL) { - if (! all) { - break; - } else { - continue; - } - } - if (socketReady(sid)) { - socketDoEvent(sp); - } - if (! all) { - break; - } - } -} - -/******************************************************************************/ -/* - * Process an event on the event queue - */ - -static int socketDoEvent(socket_t *sp) -{ - ringq_t *rq; - int sid; - - a_assert(sp); - - sid = sp->sid; - if (sp->currentEvents & SOCKET_READABLE) { - if (sp->flags & SOCKET_LISTENING) { - socketAccept(sp); - sp->currentEvents = 0; - return 1; - } - - } else { -/* - * If there is still read data in the buffers, trigger the read handler - * NOTE: this may busy spin if the read handler doesn't read the data - */ - if (sp->handlerMask & SOCKET_READABLE && socketInputBuffered(sid) > 0) { - sp->currentEvents |= SOCKET_READABLE; - } - } - - -/* - * If now writable and flushing in the background, continue flushing - */ - if (sp->currentEvents & SOCKET_WRITABLE) { - if (sp->flags & SOCKET_FLUSHING) { - rq = &sp->outBuf; - if (ringqLen(rq) > 0) { - socketFlush(sp->sid); - } else { - sp->flags &= ~SOCKET_FLUSHING; - } - } - } - -/* - * Now invoke the users socket handler. NOTE: the handler may delete the - * socket, so we must be very careful after calling the handler. - */ - if (sp->handler && (sp->handlerMask & sp->currentEvents)) { - (sp->handler)(sid, sp->handlerMask & sp->currentEvents, - sp->handler_data); -/* - * Make sure socket pointer is still valid, then reset the currentEvents. - */ - if (socketList && sid < socketMax && socketList[sid] == sp) { - sp->currentEvents = 0; - } - } - return 1; -} - -/******************************************************************************/ -/* - * Set the socket blocking mode - */ - -int socketSetBlock(int sid, int on) -{ - socket_t *sp; - unsigned long flag; - int iflag; - int oldBlock; - - flag = iflag = !on; - - if ((sp = socketPtr(sid)) == NULL) { - a_assert(0); - return 0; - } - oldBlock = (sp->flags & SOCKET_BLOCK); - sp->flags &= ~(SOCKET_BLOCK); - if (on) { - sp->flags |= SOCKET_BLOCK; - } - -/* - * Put the socket into block / non-blocking mode - */ - if (sp->flags & SOCKET_BLOCK) { -#if (defined (CE) || defined (WIN)) - ioctlsocket(sp->sock, FIONBIO, &flag); -#elif (defined (ECOS)) - int off; - off = 0; - ioctl(sp->sock, FIONBIO, &off); -#elif (defined (VXWORKS) || defined (NW)) - ioctl(sp->sock, FIONBIO, (int)&iflag); -#else - fcntl(sp->sock, F_SETFL, fcntl(sp->sock, F_GETFL) & ~O_NONBLOCK); -#endif - - } else { -#if (defined (CE) || defined (WIN)) - ioctlsocket(sp->sock, FIONBIO, &flag); -#elif (defined (ECOS)) - int on; - on = 1; - ioctl(sp->sock, FIONBIO, &on); -#elif (defined (VXWORKS) || defined (NW)) - ioctl(sp->sock, FIONBIO, (int)&iflag); -#else - fcntl(sp->sock, F_SETFL, fcntl(sp->sock, F_GETFL) | O_NONBLOCK); -#endif - } - return oldBlock; -} - -/******************************************************************************/ -/* - * Return true if a readable socket has buffered data. - not public - */ - -int socketDontBlock() -{ - socket_t *sp; - int i; - - for (i = 0; i < socketMax; i++) { - if ((sp = socketList[i]) == NULL || - (sp->handlerMask & SOCKET_READABLE) == 0) { - continue; - } - if (socketInputBuffered(i) > 0) { - return 1; - } - } - return 0; -} - -/******************************************************************************/ -/* - * Return true if a particular socket buffered data. - not public - */ - -int socketSockBuffered(int sock) -{ - socket_t *sp; - int i; - - for (i = 0; i < socketMax; i++) { - if ((sp = socketList[i]) == NULL || sp->sock != sock) { - continue; - } - return socketInputBuffered(i); - } - return 0; -} - -#endif /* (!WIN) | LITTLEFOOT | WEBS */ - -/******************************************************************************/ diff --git a/cpukit/httpd/socket.c b/cpukit/httpd/socket.c deleted file mode 100644 index 5d121fda20..0000000000 --- a/cpukit/httpd/socket.c +++ /dev/null @@ -1,1024 +0,0 @@ - -/* - * sockGen.c -- Posix Socket support module for general posix use - * - * Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved. - */ - -/******************************** Description *********************************/ - -/* - * Posix Socket Module. This supports blocking and non-blocking buffered - * socket I/O. - */ - -#if (!WIN) || LITTLEFOOT || WEBS - -/********************************** Includes **********************************/ - -#include <string.h> -#include <stdlib.h> - -#if UEMF - #include "uemf.h" -#else - #include <socket.h> - #include <types.h> - #include <unistd.h> - #include "emfInternal.h" -#endif - -#if VXWORKS - #include <hostLib.h> -#endif - -#if __rtems__ - #include <sys/select.h> -#endif - -/************************************ Locals **********************************/ - -extern socket_t **socketList; /* List of open sockets */ -extern int socketMax; /* Maximum size of socket */ -extern int socketHighestFd; /* Highest socket fd opened */ -static int socketOpenCount = 0; /* Number of task using sockets */ - -/***************************** Forward Declarations ***************************/ - -static void socketAccept(socket_t *sp); -static int socketDoEvent(socket_t *sp); -static int tryAlternateConnect(int sock, struct sockaddr *sockaddr); - -/*********************************** Code *************************************/ -/* - * Open socket module - */ - -int socketOpen(void) -{ -#if CE || WIN - WSADATA wsaData; -#endif - - if (++socketOpenCount > 1) { - return 0; - } - -#if CE || WIN - if (WSAStartup(MAKEWORD(1,1), &wsaData) != 0) { - return -1; - } - if (wsaData.wVersion != MAKEWORD(1,1)) { - WSACleanup(); - return -1; - } -#endif - socketList = NULL; - socketMax = 0; - socketHighestFd = -1; - - return 0; -} - -/******************************************************************************/ -/* - * Close the socket module, by closing all open connections - */ - -void socketClose(void) -{ - int i; - - if (--socketOpenCount <= 0) { - for (i = socketMax; i >= 0; i--) { - if (socketList && socketList[i]) { - socketCloseConnection(i); - } - } - socketOpenCount = 0; - } -} - -/******************************************************************************/ -/* - * Open a client or server socket. Host is NULL if we want server capability. - */ - -int socketOpenConnection(char *host, int port, socketAccept_t accept, int flags) -{ -#if ! (NO_GETHOSTBYNAME || VXWORKS) - struct hostent *hostent; /* Host database entry */ -#endif /* ! (NO_GETHOSTBYNAME || VXWORKS) */ - socket_t *sp; - struct sockaddr_in sockaddr; - int sid, bcast, dgram, rc; - - if (port > SOCKET_PORT_MAX) { - return -1; - } -/* - * Allocate a socket structure - */ - if ((sid = socketAlloc(host, port, accept, flags)) < 0) { - return -1; - } - sp = socketList[sid]; - a_assert(sp); - -/* - * Create the socket address structure - */ - memset((char *) &sockaddr, '\0', sizeof(struct sockaddr_in)); - sockaddr.sin_family = AF_INET; - sockaddr.sin_port = htons((short) (port & 0xFFFF)); - - if (host == NULL) { - sockaddr.sin_addr.s_addr = INADDR_ANY; - } else { - sockaddr.sin_addr.s_addr = inet_addr(host); - if (sockaddr.sin_addr.s_addr == INADDR_NONE) { -/* - * If the OS does not support gethostbyname functionality, the macro: - * NO_GETHOSTBYNAME should be defined to skip the use of gethostbyname. - * Unfortunatly there is no easy way to recover, the following code - * simply uses the basicGetHost IP for the sockaddr. - */ - -#if NO_GETHOSTBYNAME - if (strcmp(host, basicGetHost()) == 0) { - sockaddr.sin_addr.s_addr = inet_addr(basicGetAddress()); - } - if (sockaddr.sin_addr.s_addr == INADDR_NONE) { - socketFree(sid); - return -1; - } -#elif VXWORKS - sockaddr.sin_addr.s_addr = (unsigned long) hostGetByName(host); - if (sockaddr.sin_addr.s_addr == NULL) { - errno = ENXIO; - socketFree(sid); - return -1; - } -#else - hostent = gethostbyname(host); - if (hostent != NULL) { - memcpy((char *) &sockaddr.sin_addr, - (char *) hostent->h_addr_list[0], - (size_t) hostent->h_length); - } else { - char *asciiAddress; - char_t *address; - - address = basicGetAddress(); - asciiAddress = ballocUniToAsc(address, gstrlen(address)); - sockaddr.sin_addr.s_addr = inet_addr(asciiAddress); - bfree(B_L, asciiAddress); - if (sockaddr.sin_addr.s_addr == INADDR_NONE) { - errno = ENXIO; - socketFree(sid); - return -1; - } - } -#endif /* (NO_GETHOSTBYNAME || VXWORKS) */ - } - } - - bcast = sp->flags & SOCKET_BROADCAST; - if (bcast) { - sp->flags |= SOCKET_DATAGRAM; - } - dgram = sp->flags & SOCKET_DATAGRAM; - -/* - * Create the socket. Support for datagram sockets. Set the close on - * exec flag so children don't inherit the socket. - */ - sp->sock = socket(AF_INET, dgram ? SOCK_DGRAM: SOCK_STREAM, 0); - if (sp->sock < 0) { - socketFree(sid); - return -1; - } -#ifndef __NO_FCNTL - fcntl(sp->sock, F_SETFD, FD_CLOEXEC); -#endif - socketHighestFd = max(socketHighestFd, sp->sock); - -/* - * If broadcast, we need to turn on broadcast capability. - */ - if (bcast) { - int broadcastFlag = 1; - if (setsockopt(sp->sock, SOL_SOCKET, SO_BROADCAST, - (char *) &broadcastFlag, sizeof(broadcastFlag)) < 0) { - socketFree(sid); - return -1; - } - } - -/* - * Host is set if we are the client - */ - if (host) { -/* - * Connect to the remote server in blocking mode, then go into - * non-blocking mode if desired. - */ - if (!dgram) { - if (! (sp->flags & SOCKET_BLOCK)) { -/* - * sockGen.c is only used for Windows products when blocking - * connects are expected. This applies to FieldUpgrader - * agents and open source webserver connectws. Therefore the - * asynchronous connect code here is not compiled. - */ -#if (WIN || CE) && !(LITTLEFOOT || WEBS) - int flag; - - sp->flags |= SOCKET_ASYNC; -/* - * Set to non-blocking for an async connect - */ - flag = 1; - if (ioctlsocket(sp->sock, FIONBIO, &flag) == SOCKET_ERROR) { - socketFree(sid); - return -1; - } -#else - socketSetBlock(sid, 1); -#endif /* #if (WIN || CE) && !(LITTLEFOOT || WEBS) */ - - } - if ((rc = connect(sp->sock, (struct sockaddr *) &sockaddr, - sizeof(sockaddr))) < 0 && - (rc = tryAlternateConnect(sp->sock, - (struct sockaddr *) &sockaddr)) < 0) { -#if WIN || CE - if (socketGetError() != EWOULDBLOCK) { - socketFree(sid); - return -1; - } -#else - socketFree(sid); - return -1; - -#endif /* WIN || CE */ - - } - } - } else { -/* - * Bind to the socket endpoint and the call listen() to start listening - */ - rc = 1; - setsockopt(sp->sock, SOL_SOCKET, SO_REUSEADDR, (char *)&rc, sizeof(rc)); - if (bind(sp->sock, (struct sockaddr *) &sockaddr, - sizeof(sockaddr)) < 0) { - socketFree(sid); - return -1; - } - - if (! dgram) { - if (listen(sp->sock, SOMAXCONN) < 0) { - socketFree(sid); - return -1; - } -#if !UEMF - sp->fileHandle = emfCreateFileHandler(sp->sock, SOCKET_READABLE, - (emfFileProc *) socketAccept, (void *) sp); -#else - sp->flags |= SOCKET_LISTENING; -#endif - } - sp->handlerMask |= SOCKET_READABLE; - } - -/* - * Set the blocking mode - */ - - if (flags & SOCKET_BLOCK) { - socketSetBlock(sid, 1); - } else { - socketSetBlock(sid, 0); - } - return sid; -} - -/******************************************************************************/ -/* - * If the connection failed, swap the first two bytes in the - * sockaddr structure. This is a kludge due to a change in - * VxWorks between versions 5.3 and 5.4, but we want the - * product to run on either. - */ - -static int tryAlternateConnect(int sock, struct sockaddr *sockaddr) -{ -#if VXWORKS - char *ptr; - - ptr = (char *)sockaddr; - *ptr = *(ptr+1); - *(ptr+1) = 0; - return connect(sock, sockaddr, sizeof(struct sockaddr)); -#else - return -1; -#endif /* VXWORKS */ -} - -/******************************************************************************/ -/* - * Close a socket - */ - -void socketCloseConnection(int sid) -{ - socket_t *sp; - - if ((sp = socketPtr(sid)) == NULL) { - return; - } - socketFree(sid); -} - -/******************************************************************************/ -/* - * Accept a connection. Called as a callback on incoming connection. - */ - -static void socketAccept(socket_t *sp) -{ - union { - struct sockaddr addr; - struct sockaddr_in addr_in; - } overlay; - struct sockaddr_in *addr; - socket_t *nsp; - socklen_t len; - char *pString; - int newSock, nid; - - a_assert(sp); - addr = &overlay.addr_in; - -/* - * Accept the connection and prevent inheriting by children (F_SETFD) - */ - len = sizeof(struct sockaddr_in); - if ((newSock = accept(sp->sock, &overlay.addr, &len)) < 0) { - return; - } -#ifndef __NO_FCNTL - fcntl(newSock, F_SETFD, FD_CLOEXEC); -#endif - socketHighestFd = max(socketHighestFd, newSock); - -/* - * Create a socket structure and insert into the socket list - */ - nid = socketAlloc(sp->host, sp->port, sp->accept, sp->flags); - nsp = socketList[nid]; - a_assert(nsp); - nsp->sock = newSock; - nsp->flags &= ~SOCKET_LISTENING; - - if (nsp == NULL) { - return; - } -/* - * Set the blocking mode before calling the accept callback. - */ - - socketSetBlock(nid, (nsp->flags & SOCKET_BLOCK) ? 1: 0); -/* - * Call the user accept callback. The user must call socketCreateHandler - * to register for further events of interest. - */ - if (sp->accept != NULL) { - pString = inet_ntoa(addr->sin_addr); - if ((sp->accept)(nid, pString, ntohs(addr->sin_port), sp->sid) < 0) { - socketFree(nid); - } -#if VXWORKS - free(pString); -#endif - } -} - -/******************************************************************************/ -/* - * Get more input from the socket and return in buf. - * Returns 0 for EOF, -1 for errors and otherwise the number of bytes read. - */ - -int socketGetInput(int sid, char *buf, int toRead, int *errCode) -{ - struct sockaddr_in server; - socket_t *sp; - socklen_t len; - int bytesRead; - - a_assert(buf); - a_assert(errCode); - - *errCode = 0; - - if ((sp = socketPtr(sid)) == NULL) { - return -1; - } - -/* - * If we have previously seen an EOF condition, then just return - */ - if (sp->flags & SOCKET_EOF) { - return 0; - } -#if (WIN || CE) && !(LITTLEFOOT || WEBS) - if ( !(sp->flags & SOCKET_BLOCK) - && ! socketWaitForEvent(sp, FD_CONNECT, errCode)) { - return -1; - } -#endif - -/* - * Read the data - */ - if (sp->flags & SOCKET_DATAGRAM) { - len = sizeof(server); - bytesRead = recvfrom(sp->sock, buf, toRead, 0, - (struct sockaddr *) &server, &len); - } else { - bytesRead = recv(sp->sock, buf, toRead, 0); - } - if (bytesRead < 0) { - if (errno == ECONNRESET) { - return 0; - } - *errCode = socketGetError(); - return -1; - } - return bytesRead; -} - -/******************************************************************************/ -/* - * Process an event on the event queue - */ - -#ifndef UEMF - -static int socketEventProc(void *data, int mask) -{ - socket_t *sp; - ringq_t *rq; - int sid; - - sid = (int) data; - - a_assert(sid >= 0 && sid < socketMax); - a_assert(socketList[sid]); - - if ((sp = socketPtr(sid)) == NULL) { - return 1; - } - -/* - * If now writable and flushing in the background, continue flushing - */ - if (mask & SOCKET_WRITABLE) { - if (sp->flags & SOCKET_FLUSHING) { - rq = &sp->outBuf; - if (ringqLen(rq) > 0) { - socketFlush(sp->sid); - } else { - sp->flags &= ~SOCKET_FLUSHING; - } - } - } - -/* - * Now invoke the users socket handler. NOTE: the handler may delete the - * socket, so we must be very careful after calling the handler. - */ - if (sp->handler && (sp->handlerMask & mask)) { - (sp->handler)(sid, mask & sp->handlerMask, sp->handler_data); - } - if (socketList && sid < socketMax && socketList[sid] == sp) { - socketRegisterInterest(sp, sp->handlerMask); - } - return 1; -} -#endif /* ! UEMF */ - -/******************************************************************************/ -/* - * Define the events of interest - */ - -void socketRegisterInterest(socket_t *sp, int handlerMask) -{ - a_assert(sp); - - sp->handlerMask = handlerMask; -#if !UEMF - if (handlerMask) { - sp->fileHandle = emfCreateFileHandler(sp->sock, handlerMask, - (emfFileProc *) socketEventProc, (void *) sp->sid); - } else { - emfDeleteFileHandler(sp->fileHandle); - } -#endif /* ! UEMF */ -} - -/******************************************************************************/ -/* - * Wait until an event occurs on a socket. Return 1 on success, 0 on failure. - * or -1 on exception (UEMF only) - */ - -int socketWaitForEvent(socket_t *sp, int handlerMask, int *errCode) -{ - int mask; - - a_assert(sp); - - mask = sp->handlerMask; - sp->handlerMask |= handlerMask; - while (socketSelect(sp->sid, 1000)) { - if (sp->currentEvents & (handlerMask | SOCKET_EXCEPTION)) { - break; - } - } - sp->handlerMask = mask; - if (sp->currentEvents & SOCKET_EXCEPTION) { - return -1; - } else if (sp->currentEvents & handlerMask) { - return 1; - } - if (errCode) { - *errCode = errno = EWOULDBLOCK; - } - return 0; -} - -/******************************************************************************/ -/* - * Return TRUE if there is a socket with an event ready to process, - */ - -int socketReady(int sid) -{ - socket_t *sp; - int all; - - all = 0; - if (sid < 0) { - sid = 0; - all = 1; - } - - for (; sid < socketMax; sid++) { - if ((sp = socketList[sid]) == NULL) { - if (! all) { - break; - } else { - continue; - } - } - if (sp->currentEvents & sp->handlerMask) { - return 1; - } -/* - * If there is input data, also call select to test for new events - */ - if (sp->handlerMask & SOCKET_READABLE && socketInputBuffered(sid)) { - socketSelect(sid, 0); - return 1; - } - if (! all) { - break; - } - } - return 0; -} - -/******************************************************************************/ -/* - * Wait for a handle to become readable or writable and return a number of - * noticed events. Timeout is in milliseconds. - */ - -#if WIN || CE - -int socketSelect(int sid, int timeout) -{ - struct timeval tv; - socket_t *sp; - fd_set readFds, writeFds, exceptFds; - int nEvents; - int all, socketHighestFd; /* Highest socket fd opened */ - - FD_ZERO(&readFds); - FD_ZERO(&writeFds); - FD_ZERO(&exceptFds); - socketHighestFd = -1; - - tv.tv_sec = timeout / 1000; - tv.tv_usec = (timeout % 1000) * 1000; - -/* - * Set the select event masks for events to watch - */ - all = nEvents = 0; - - if (sid < 0) { - all++; - sid = 0; - } - - for (; sid < socketMax; sid++) { - if ((sp = socketList[sid]) == NULL) { - continue; - } - a_assert(sp); -/* - * Set the appropriate bit in the ready masks for the sp->sock. - */ - if (sp->handlerMask & SOCKET_READABLE) { - FD_SET(sp->sock, &readFds); - nEvents++; - if (socketInputBuffered(sid) > 0) { - tv.tv_sec = 0; - tv.tv_usec = 0; - } - } - if (sp->handlerMask & SOCKET_WRITABLE) { - FD_SET(sp->sock, &writeFds); - nEvents++; - } - if (sp->handlerMask & SOCKET_EXCEPTION) { - FD_SET(sp->sock, &exceptFds); - nEvents++; - } - if (! all) { - break; - } - } - -/* - * Windows select() fails if no descriptors are set, instead of just sleeping - * like other, nice select() calls. So, if WIN, sleep. - */ - if (nEvents == 0) { - Sleep(timeout); - return 0; - } - -/* - * Wait for the event or a timeout. - */ - nEvents = select(socketHighestFd+1, &readFds, &writeFds, &exceptFds, &tv); - - if (all) { - sid = 0; - } - for (; sid < socketMax; sid++) { - if ((sp = socketList[sid]) == NULL) { - continue; - } - - if (FD_ISSET(sp->sock, &readFds) || socketInputBuffered(sid) > 0) { - sp->currentEvents |= SOCKET_READABLE; - } - if (FD_ISSET(sp->sock, &writeFds)) { - sp->currentEvents |= SOCKET_WRITABLE; - } - if (FD_ISSET(sp->sock, &exceptFds)) { - sp->currentEvents |= SOCKET_EXCEPTION; - } - if (! all) { - break; - } - } - - return nEvents; -} - -#else /* not WIN || CE */ - -int socketSelect(int sid, int timeout) -{ - socket_t *sp; - struct timeval tv; - fd_mask *readFds, *writeFds, *exceptFds; - int all, len, nwords, index, bit, nEvents; - -/* - * Allocate and zero the select masks - */ - nwords = (socketHighestFd + NFDBITS) / NFDBITS; - len = nwords * sizeof(int); - - readFds = balloc(B_L, len); - memset(readFds, 0, len); - writeFds = balloc(B_L, len); - memset(writeFds, 0, len); - exceptFds = balloc(B_L, len); - memset(exceptFds, 0, len); - - tv.tv_sec = timeout / 1000; - tv.tv_usec = (timeout % 1000) * 1000; - -/* - * Set the select event masks for events to watch - */ - all = nEvents = 0; - - if (sid < 0) { - all++; - sid = 0; - } - - for (; sid < socketMax; sid++) { - if ((sp = socketList[sid]) == NULL) { - if (all == 0) { - break; - } else { - continue; - } - } - a_assert(sp); - -/* - * Initialize the ready masks and compute the mask offsets. - */ - index = sp->sock / (NBBY * sizeof(fd_mask)); - bit = 1 << (sp->sock % (NBBY * sizeof(fd_mask))); - -/* - * Set the appropriate bit in the ready masks for the sp->sock. - */ - if (sp->handlerMask & SOCKET_READABLE) { - readFds[index] |= bit; - nEvents++; - if (socketInputBuffered(sid) > 0) { - tv.tv_sec = 0; - tv.tv_usec = 0; - } - } - if (sp->handlerMask & SOCKET_WRITABLE) { - writeFds[index] |= bit; - nEvents++; - } - if (sp->handlerMask & SOCKET_EXCEPTION) { - exceptFds[index] |= bit; - nEvents++; - } - if (! all) { - break; - } - } - -/* - * Wait for the event or a timeout. Reset nEvents to be the number of actual - * events now. - */ - nEvents = select(socketHighestFd + 1, (fd_set *) readFds, - (fd_set *) writeFds, (fd_set *) exceptFds, &tv); - - if (nEvents > 0) { - if (all) { - sid = 0; - } - for (; sid < socketMax; sid++) { - if ((sp = socketList[sid]) == NULL) { - if (all == 0) { - break; - } else { - continue; - } - } - - index = sp->sock / (NBBY * sizeof(fd_mask)); - bit = 1 << (sp->sock % (NBBY * sizeof(fd_mask))); - - if (readFds[index] & bit || socketInputBuffered(sid) > 0) { - sp->currentEvents |= SOCKET_READABLE; - } - if (writeFds[index] & bit) { - sp->currentEvents |= SOCKET_WRITABLE; - } - if (exceptFds[index] & bit) { - sp->currentEvents |= SOCKET_EXCEPTION; - } - if (! all) { - break; - } - } - } - - bfree(B_L, readFds); - bfree(B_L, writeFds); - bfree(B_L, exceptFds); - - return nEvents; -} -#endif /* WIN || CE */ - -/******************************************************************************/ -/* - * Process socket events - */ - -void socketProcess(int sid) -{ - socket_t *sp; - int all; - - all = 0; - if (sid < 0) { - all = 1; - sid = 0; - } -/* - * Process each socket - */ - for (; sid < socketMax; sid++) { - if ((sp = socketList[sid]) == NULL) { - if (! all) { - break; - } else { - continue; - } - } - if (socketReady(sid)) { - socketDoEvent(sp); - } - if (! all) { - break; - } - } -} - -/******************************************************************************/ -/* - * Process an event on the event queue - */ - -static int socketDoEvent(socket_t *sp) -{ - ringq_t *rq; - int sid; - - a_assert(sp); - - sid = sp->sid; - if (sp->currentEvents & SOCKET_READABLE) { - if (sp->flags & SOCKET_LISTENING) { - socketAccept(sp); - sp->currentEvents = 0; - return 1; - } - - } else { -/* - * If there is still read data in the buffers, trigger the read handler - * NOTE: this may busy spin if the read handler doesn't read the data - */ - if (sp->handlerMask & SOCKET_READABLE && socketInputBuffered(sid)) { - sp->currentEvents |= SOCKET_READABLE; - } - } - - -/* - * If now writable and flushing in the background, continue flushing - */ - if (sp->currentEvents & SOCKET_WRITABLE) { - if (sp->flags & SOCKET_FLUSHING) { - rq = &sp->outBuf; - if (ringqLen(rq) > 0) { - socketFlush(sp->sid); - } else { - sp->flags &= ~SOCKET_FLUSHING; - } - } - } - -/* - * Now invoke the users socket handler. NOTE: the handler may delete the - * socket, so we must be very careful after calling the handler. - */ - if (sp->handler && (sp->handlerMask & sp->currentEvents)) { - (sp->handler)(sid, sp->handlerMask & sp->currentEvents, - sp->handler_data); -/* - * Make sure socket pointer is still valid, then reset the currentEvents. - */ - if (socketList && sid < socketMax && socketList[sid] == sp) { - sp->currentEvents = 0; - } - } - return 1; -} - -/******************************************************************************/ -/* - * Set the socket blocking mode - */ - -int socketSetBlock(int sid, int on) -{ - socket_t *sp; - unsigned long flag; - int iflag; - int oldBlock; - - flag = iflag = !on; - - if ((sp = socketPtr(sid)) == NULL) { - a_assert(0); - return 0; - } - oldBlock = (sp->flags & SOCKET_BLOCK); - sp->flags &= ~(SOCKET_BLOCK); - if (on) { - sp->flags |= SOCKET_BLOCK; - } - -/* - * Put the socket into block / non-blocking mode - */ - if (sp->flags & SOCKET_BLOCK) { -#if CE || WIN - ioctlsocket(sp->sock, FIONBIO, &flag); -#elif ECOS - int off; - off = 0; - ioctl(sp->sock, FIONBIO, &off); -#elif VXWORKS - ioctl(sp->sock, FIONBIO, (int)&iflag); -#else - fcntl(sp->sock, F_SETFL, fcntl(sp->sock, F_GETFL) & ~O_NONBLOCK); -#endif - - } else { -#if CE || WIN - ioctlsocket(sp->sock, FIONBIO, &flag); -#elif ECOS - int on; - on = 1; - ioctl(sp->sock, FIONBIO, &on); -#elif VXWORKS - ioctl(sp->sock, FIONBIO, (int)&iflag); -#else - fcntl(sp->sock, F_SETFL, fcntl(sp->sock, F_GETFL) | O_NONBLOCK); -#endif - } - return oldBlock; -} - -/******************************************************************************/ -/* - * Return true if a readable socket has buffered data. - not public - */ - -int socketDontBlock(void) -{ - socket_t *sp; - int i; - - for (i = 0; i < socketMax; i++) { - if ((sp = socketList[i]) == NULL || - (sp->handlerMask & SOCKET_READABLE) == 0) { - continue; - } - if (socketInputBuffered(i) > 0) { - return 1; - } - } - return 0; -} - -/******************************************************************************/ -/* - * Return true if a particular socket buffered data. - not public - */ - -int socketSockBuffered(int sock) -{ - socket_t *sp; - int i; - - for (i = 0; i < socketMax; i++) { - if ((sp = socketList[i]) == NULL || sp->sock != sock) { - continue; - } - return socketInputBuffered(i); - } - return 0; -} - -#endif /* (!WIN) | LITTLEFOOT | WEBS */ - -/******************************************************************************/ diff --git a/cpukit/httpd/sym.c b/cpukit/httpd/sym.c deleted file mode 100644 index 2d7aadbc27..0000000000 --- a/cpukit/httpd/sym.c +++ /dev/null @@ -1,474 +0,0 @@ -/* - * sym.c -- Symbol Table module - * - * Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved. - * - * See the file "license.txt" for usage and redistribution license requirements - * - * $Id$ - */ - -/******************************** Description *********************************/ -/* - * 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. - */ - -/********************************* Includes ***********************************/ - -#ifdef UEMF - #include "uemf.h" -#else - #include "basic/basicInternal.h" -#endif - -/********************************* Defines ************************************/ - -typedef struct { /* Symbol table descriptor */ - int inuse; /* Is this entry in use */ - int hash_size; /* Size of the table below */ - sym_t **hash_table; /* Allocated at run time */ -} sym_tabent_t; - -/********************************* Globals ************************************/ - -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 */ - -/**************************** 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 calcPrime(int size); - -/*********************************** Code *************************************/ -/* - * Open the symbol table subSystem. - */ - -int symSubOpen(void) -{ - if (++symOpenCount == 1) { - symMax = 0; - sym = NULL; - } - return 0; -} - -/******************************************************************************/ -/* - * Close the symbol table subSystem. - */ - -void symSubClose(void) -{ - if (--symOpenCount <= 0) { - symOpenCount = 0; - } -} - -/******************************************************************************/ -/* - * Create a symbol table. - */ - -sym_fd_t symOpen(int hash_size) -{ - sym_fd_t sd; - sym_tabent_t *tp; - - a_assert(hash_size > 2); - -/* - * Create a new handle for this symbol table - */ - if ((sd = hAlloc((void*) &sym)) < 0) { - return -1; - } - -/* - * Create a new symbol table structure and zero - */ - if ((tp = (sym_tabent_t*) balloc(B_L, sizeof(sym_tabent_t))) == NULL) { - symMax = hFree((void*) &sym, sd); - return -1; - } - memset(tp, 0, sizeof(sym_tabent_t)); - if (sd >= symMax) { - symMax = sd + 1; - } - a_assert(0 <= sd && sd < symMax); - sym[sd] = tp; - -/* - * Now create the hash table for fast indexing. - */ - 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*)); - - return sd; -} - -/******************************************************************************/ -/* - * Close this symbol table. Call a cleanup function to allow the caller - * to free resources associated with each symbol table entry. - */ - -void symClose(sym_fd_t sd) -{ - sym_tabent_t *tp; - sym_t *sp, *forw; - int i; - - a_assert(0 <= sd && sd < symMax); - tp = sym[sd]; - a_assert(tp); - -/* - * Free all symbols in the hash table, then the hash table itself. - */ - for (i = 0; i < tp->hash_size; i++) { - for (sp = tp->hash_table[i]; sp; sp = forw) { - forw = sp->forw; - valueFree(&sp->name); - valueFree(&sp->content); - bfree(B_L, (void*) sp); - sp = forw; - } - } - bfree(B_L, (void*) tp->hash_table); - - symMax = hFree((void*) &sym, sd); - bfree(B_L, (void*) tp); -} - -/******************************************************************************/ -/* - * Return the first symbol in the hashtable if there is one. This call is used - * as the first step in traversing the table. A call to symFirst should be - * followed by calls to symNext to get all the rest of the entries. - */ - -sym_t* symFirst(sym_fd_t sd) -{ - sym_tabent_t *tp; - sym_t *sp, *forw; - int i; - - a_assert(0 <= sd && sd < symMax); - tp = sym[sd]; - a_assert(tp); - -/* - * Find the first symbol in the hashtable and return a pointer to it. - */ - for (i = 0; i < tp->hash_size; i++) { - for (sp = tp->hash_table[i]; sp; sp = forw) { - forw = sp->forw; - - if (forw == NULL) { - htIndex = i + 1; - next = tp->hash_table[htIndex]; - } else { - htIndex = i; - next = forw; - } - return sp; - } - } - return NULL; -} - -/******************************************************************************/ -/* - * Return the next symbol in the hashtable if there is one. See symFirst. - */ - -sym_t* symNext(sym_fd_t sd) -{ - sym_tabent_t *tp; - sym_t *sp, *forw; - int i; - - a_assert(0 <= sd && sd < symMax); - tp = sym[sd]; - a_assert(tp); - -/* - * Find the first symbol in the hashtable and return a pointer to it. - */ - for (i = htIndex; i < tp->hash_size; i++) { - for (sp = next; sp; sp = forw) { - forw = sp->forw; - - if (forw == NULL) { - htIndex = i + 1; - next = tp->hash_table[htIndex]; - } else { - htIndex = i; - next = forw; - } - return sp; - } - next = tp->hash_table[i + 1]; - } - return NULL; -} - -/******************************************************************************/ -/* - * Lookup a symbol and return a pointer to the symbol entry. If not present - * then return a NULL. - */ - -sym_t *symLookup(sym_fd_t sd, char_t *name) -{ - sym_tabent_t *tp; - sym_t *sp; - char_t *cp; - - a_assert(0 <= sd && sd < symMax); - if ((tp = sym[sd]) == NULL) { - return NULL; - } - - if (name == NULL || *name == '\0') { - return NULL; - } - -/* - * Do an initial hash and then follow the link chain to find the right entry - */ - for (sp = hash(tp, name); sp; sp = sp->forw) { - cp = sp->name.value.string; - if (cp[0] == name[0] && gstrcmp(cp, name) == 0) { - break; - } - } - return sp; -} - -/******************************************************************************/ -/* - * 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) -{ - sym_tabent_t *tp; - sym_t *sp, *last; - char_t *cp; - int hindex; - - 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 - * we have daisy-chain, so scan it and look for the symbol. - */ - last = NULL; - hindex = hashIndex(tp, name); - if ((sp = tp->hash_table[hindex]) != NULL) { - for (; sp; sp = sp->forw) { - cp = sp->name.value.string; - if (cp[0] == name[0] && gstrcmp(cp, name) == 0) { - break; - } - last = sp; - } - if (sp) { -/* - * Found, so update the value - * If the caller stores handles which require freeing, they - * will be lost here. It is the callers responsibility to free - * resources before overwriting existing contents. We will here - * free allocated strings which occur due to value_instring(). - * We should consider providing the cleanup function on the open rather - * than the close and then we could call it here and solve the problem. - */ - if (sp->content.valid) { - valueFree(&sp->content); - } - sp->content = v; - sp->arg = arg; - return sp; - } -/* - * Not found so allocate and append to the daisy-chain - */ - sp = (sym_t*) balloc(B_L, sizeof(sym_t)); - if (sp == NULL) { - return NULL; - } - sp->name = valueString(name, VALUE_ALLOCATE); - sp->content = v; - sp->forw = (sym_t*) NULL; - sp->arg = arg; - last->forw = sp; - - } else { -/* - * Daisy chain is empty so we need to start the chain - */ - sp = (sym_t*) balloc(B_L, sizeof(sym_t)); - if (sp == NULL) { - return NULL; - } - tp->hash_table[hindex] = sp; - tp->hash_table[hashIndex(tp, name)] = sp; - - sp->forw = (sym_t*) NULL; - sp->content = v; - sp->arg = arg; - sp->name = valueString(name, VALUE_ALLOCATE); - } - return sp; -} - -/******************************************************************************/ -/* - * Delete a symbol from a table - */ - -int symDelete(sym_fd_t sd, char_t *name) -{ - sym_tabent_t *tp; - sym_t *sp, *last; - char_t *cp; - int hindex; - - a_assert(name && *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 - * we have daisy-chain, so scan it and look for the symbol. - */ - last = NULL; - hindex = hashIndex(tp, name); - if ((sp = tp->hash_table[hindex]) != NULL) { - for ( ; sp; sp = sp->forw) { - cp = sp->name.value.string; - if (cp[0] == name[0] && gstrcmp(cp, name) == 0) { - break; - } - last = sp; - } - } - 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. - */ - if (last) { - last->forw = sp->forw; - } else { - tp->hash_table[hindex] = sp->forw; - } - valueFree(&sp->name); - valueFree(&sp->content); - bfree(B_L, (void*) sp); - - return 0; -} - -/******************************************************************************/ -/* - * Hash a symbol and return a pointer to the hash daisy-chain list - * All symbols reside on the chain (ie. none stored in the hash table itself) - */ - -static sym_t *hash(sym_tabent_t *tp, char_t *name) -{ - a_assert(tp); - - return tp->hash_table[hashIndex(tp, name)]; -} - -/******************************************************************************/ -/* - * Compute the hash function and return an index into the hash table - * We use a basic additive function that is then made modulo the size of the - * table. - */ - -static int hashIndex(sym_tabent_t *tp, char_t *name) -{ - 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 - * new cycle placing character shifted up by one bit. - */ - i = 0; - sum = 0; - while (*name) { - sum += (((int) *name++) << i); - i = (i + 7) % (BITS(int) - BITSPERBYTE); - } - return sum % tp->hash_size; -} - -/******************************************************************************/ -/* - * Check if this number is a prime - */ - -static int isPrime(int n) -{ - int i, max; - - a_assert(n > 0); - - max = n / 2; - for (i = 2; i <= max; i++) { - if (n % i == 0) { - return 0; - } - } - return 1; -} - -/******************************************************************************/ -/* - * Calculate the largest prime smaller than size. - */ - -static int calcPrime(int size) -{ - int count; - - a_assert(size > 0); - - for (count = size; count > 0; count--) { - if (isPrime(count)) { - return count; - } - } - return 1; -} - -/******************************************************************************/ diff --git a/cpukit/httpd/uemf.c b/cpukit/httpd/uemf.c deleted file mode 100644 index 862a1451de..0000000000 --- a/cpukit/httpd/uemf.c +++ /dev/null @@ -1,293 +0,0 @@ -/* - * uemf.c -- GoAhead Micro Embedded Management Framework - * - * Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved. - * - * See the file "license.txt" for usage and redistribution license requirements - * - * $Id$ - */ - -/********************************** Description *******************************/ - -/* - * This module provides compatibility with the full GoAhead EMF. - * It is a collection of routines which permits the GoAhead WebServer to - * run stand-alone and to also load as a solution pack under the GoAhead EMF. - */ - -/*********************************** Includes *********************************/ - -#include "uemf.h" - -/********************************** Local Data ********************************/ - -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 wherever the developer wishes - */ - -void error(E_ARGS_DEC, int etype, char_t *fmt, ...) -{ - va_list args; - char_t *fmtBuf, *buf; - - va_start(args, fmt); - fmtValloc(&fmtBuf, E_MAX_ERROR, fmt, args); - - if (etype == E_LOG) { - fmtAlloc(&buf, E_MAX_ERROR, T("%s\n"), fmtBuf); -/*#ifdef 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); - } - /* - * bugfix -- if etype is not E_LOG, E_ASSERT, or E_USER, the call to - * bfreeSafe(B_L, buf) below will fail, because 'buf' is randomly - * initialized. To be nice, we format a message saying that this is an - * unknown message type, and in doing so give buf a valid value. Thanks - * to Simon Byholm. - */ - else { - fmtAlloc(&buf, E_MAX_ERROR, T("Unknown error")); - } - va_end(args); - - bfree(B_L, fmtBuf); - - if (errorHandler) { - errorHandler(etype, buf); - } - - 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; -} - -/******************************************************************************/ -/* - * Trace log. Customize this function to log trace output - */ - -void trace(int level, char_t *fmt, ...) -{ - va_list args; - char_t *buf; - - va_start(args, fmt); - fmtValloc(&buf, VALUE_MAX_STRING, fmt, args); - - if (traceHandler) { - traceHandler(level, buf); - } - bfreeSafe(B_L, buf); - va_end(args); -} - -/******************************************************************************/ -/* - * 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; -} - -/******************************************************************************/ -/* - * Save the instance handle - */ - -void emfInstSet(int inst) -{ - emfInst = inst; -} - -/******************************************************************************/ -/* - * Get the instance handle - */ - -int emfInstGet(void) -{ - return emfInst; -} - -/******************************************************************************/ -/* - * Convert a string to lower case - */ - -char_t *strlower(char_t *string) -{ - unsigned char *s; - - a_assert(string); - - if (string == NULL) { - return NULL; - } - - s = (unsigned char *)string; - while (*s) { - if (gisupper(*s)) { - *s = (char_t) gtolower(*s); - } - s++; - } - *s = '\0'; - return string; -} - -/******************************************************************************/ -/* - * Convert a string to upper case - */ - -char_t *strupper(char_t *string) -{ - unsigned char *s; - - a_assert(string); - if (string == NULL) { - return NULL; - } - - s = (unsigned char *)string; - while (*s) { - if (gislower(*s)) { - *s = (char_t) gtoupper(*s); - } - s++; - } - *s = '\0'; - return string; -} - -/******************************************************************************/ -/* - * Convert integer to ascii string. Allow a NULL string in which case we - * allocate a dynamic buffer. - */ - -char_t *stritoa(int n, char_t *string, int width) -{ - char_t *cp, *lim, *s; - char_t buf[16]; /* Just temp to hold number */ - int next, minus; - - a_assert(string && width > 0); - - if (string == NULL) { - if (width == 0) { - width = 10; - } - if ((string = balloc(B_L, width + 1)) == NULL) { - return NULL; - } - } - if (n < 0) { - minus = 1; - n = -n; - width--; - } else { - minus = 0; - } - - cp = buf; - lim = &buf[width - 1]; - while (n > 9 && cp < lim) { - next = n; - n /= 10; - *cp++ = (char_t) (next - n * 10 + '0'); - } - if (cp < lim) { - *cp++ = (char_t) (n + '0'); - } - - s = string; - if (minus) { - *s++ = '-'; - } - - while (cp > buf) { - *s++ = *--cp; - } - - *s++ = '\0'; - return string; -} - -/******************************************************************************/ -/* - * Stubs - */ - -char_t *basicGetProduct(void) -{ - return T("uemf"); -} - -char_t *basicGetAddress(void) -{ - return T("localhost"); -} - -int errorOpen(char_t *pname) -{ - return 0; -} - -void errorClose(void) -{ -} - -/******************************************************************************/ diff --git a/cpukit/httpd/uemf.h b/cpukit/httpd/uemf.h deleted file mode 100644 index c286ecccc2..0000000000 --- a/cpukit/httpd/uemf.h +++ /dev/null @@ -1,1110 +0,0 @@ -/* - * uemf.h -- GoAhead Micro Embedded Management Framework Header - * - * Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved. - * - * See the file "license.txt" for usage and redistribution license requirements - * - * $Id$ - */ - -#ifndef _h_UEMF -#define _h_UEMF 1 - -/******************************** Description *********************************/ - -/* - * GoAhead Web Server header. This defines the Web public APIs - */ - -/******************************* Per O/S Includes *****************************/ - -#ifdef WIN - #include <direct.h> - #include <io.h> - #include <sys/stat.h> - #include <limits.h> - #include <tchar.h> - #include <windows.h> - #include <winnls.h> - #include <time.h> - #include <sys/types.h> - #include <stdio.h> - #include <stdlib.h> - #include <fcntl.h> - #include <errno.h> -#endif /* WIN */ - -#ifdef CE - #include <errno.h> - #include <limits.h> - #include <tchar.h> - #include <windows.h> - #include <winsock.h> - #include <winnls.h> - #include "CE/wincompat.h" - #include <winsock.h> -#endif /* CE */ - -#ifdef NW - #include <direct.h> - #include <io.h> - #include <sys/stat.h> - #include <time.h> - #include <sys/types.h> - #include <stdio.h> - #include <stdlib.h> - #include <fcntl.h> - #include <errno.h> - #include <niterror.h> - #define EINTR EINUSE - #define WEBS 1 - #include <limits.h> - #include <netdb.h> - #include <process.h> - #include <tiuser.h> - #include <sys/time.h> - #include <arpa/inet.h> - #include <sys/types.h> - #include <sys/socket.h> - #include <sys/filio.h> - #include <netinet/in.h> -#endif /* NW */ - -#ifdef SCOV5 - #include <sys/types.h> - #include <stdio.h> - #include "sys/socket.h" - #include "sys/select.h" - #include "netinet/in.h" - #include "arpa/inet.h" - #include "netdb.h" -#endif /* SCOV5 */ - -#ifdef UNIX - #include <stdio.h> -#endif /* UNIX */ - -#if LINUX || __rtems__ - #include <sys/types.h> - #include <sys/stat.h> - #include <sys/param.h> - #include <limits.h> - #include <stdio.h> - #include <stdlib.h> - #include <unistd.h> - #include <sys/socket.h> - #include <sys/select.h> - #include <netinet/in.h> - #include <arpa/inet.h> - #include <netdb.h> - #include <time.h> - #include <fcntl.h> - #include <errno.h> -#endif /* LINUX */ - -#ifdef LYNX - #include <limits.h> - #include <stdarg.h> - #include <stdio.h> - #include <stdlib.h> - #include <unistd.h> - #include <socket.h> - #include <netinet/in.h> - #include <arpa/inet.h> - #include <netdb.h> - #include <time.h> - #include <fcntl.h> - #include <errno.h> -#endif /* LYNX */ - -#ifdef MACOSX - #include <sys/stat.h> - #include <stdio.h> - #include <stdlib.h> - #include <unistd.h> - #include <sys/socket.h> - #include <netinet/in.h> - #include <arpa/inet.h> - #include <netdb.h> - #include <fcntl.h> - #include <errno.h> -#endif /* MACOSX */ - -#ifdef UW - #include <stdio.h> -#endif /* UW */ - -#ifdef VXWORKS - #include <vxWorks.h> - #include <sockLib.h> - #include <selectLib.h> - #include <inetLib.h> - #include <ioLib.h> - #include <stdio.h> - #include <stat.h> - #include <time.h> - #include <usrLib.h> - #include <fcntl.h> - #include <errno.h> -#endif /* VXWORKS */ - -#ifdef SOLARIS - #include <sys/types.h> - #include <limits.h> - #include <stdio.h> - #include <stdlib.h> - #include <unistd.h> - #include <socket.h> - #include <sys/select.h> - #include <netinet/in.h> - #include <arpa/inet.h> - #include <netdb.h> - #include <time.h> - #include <fcntl.h> - #include <errno.h> -#endif /* SOLARIS */ - -#ifdef QNX4 - #include <sys/types.h> - #include <stdio.h> - #include <sys/socket.h> - #include <sys/select.h> - #include <netinet/in.h> - #include <arpa/inet.h> - #include <netdb.h> - #include <stdlib.h> - #include <unistd.h> - #include <sys/uio.h> - #include <sys/wait.h> -#endif /* QNX4 */ - -#ifdef ECOS - #include <limits.h> - #include <cyg/infra/cyg_type.h> - #include <cyg/kernel/kapi.h> - #include <time.h> - #include <network.h> - #include <errno.h> -#endif /* ECOS */ - -/********************************** Includes **********************************/ - -#include <ctype.h> -#include <stdarg.h> -#include <string.h> - -#ifndef WEBS -#include "messages.h" -#endif /* ! WEBS */ - -/******************************* Per O/S Defines *****************************/ - -#if defined(__rtems__) -#define __NO_PACK 1 -#endif - -#ifdef UW - #define __NO_PACK 1 -#endif /* UW */ - -#if (defined (SCOV5) || defined (VXWORKS) || defined (LINUX) || defined (LYNX) || defined (MACOSX) || defined (__rtems__)) -#ifndef O_BINARY -#define O_BINARY 0 -#endif /* O_BINARY */ -#define SOCKET_ERROR -1 -#endif /* SCOV5 || VXWORKS || LINUX || LYNX || MACOSX */ - -#if (defined (WIN) || defined (CE)) -/* - * __NO_FCNTL means can't access fcntl function. Fcntl.h is still available. - */ -#define __NO_FCNTL 1 - -#undef R_OK -#define R_OK 4 -#undef W_OK -#define W_OK 2 -#undef X_OK -#define X_OK 1 -#undef F_OK -#define F_OK 0 -#endif /* WIN || CE */ - -#if (defined (LINUX) && !defined(__rtems__) && !defined (_STRUCT_TIMEVAL)) -struct timeval -{ - time_t tv_sec; /* Seconds. */ - time_t tv_usec; /* Microseconds. */ -}; -#define _STRUCT_TIMEVAL 1 -#endif /* LINUX && ! _STRUCT_TIMEVAL */ - -#ifdef ECOS - #define O_RDONLY 1 - #define O_BINARY 2 - - #define __NO_PACK 1 - #define __NO_EJ_FILE 1 - #define __NO_CGI_BIN 1 - #define __NO_FCNTL 1 - -/* - * #define LIBKERN_INLINE to avoid kernel inline functions - */ - #define LIBKERN_INLINE - -#endif /* ECOS */ - -#ifdef QNX4 - typedef long fd_mask; - #define NFDBITS (sizeof (fd_mask) * NBBY) /* bits per mask */ -#endif /* QNX4 */ - -#ifdef NW - #define fd_mask fd_set - #define INADDR_NONE -1l - #define Sleep delay - - #define __NO_FCNTL 1 - - #undef R_OK - #define R_OK 4 - #undef W_OK - #define W_OK 2 - #undef X_OK - #define X_OK 1 - #undef F_OK - #define F_OK 0 -#endif /* NW */ - -/********************************** Unicode ***********************************/ -/* - * Constants and limits. Also FNAMESIZE and PATHSIZE are currently defined - * in param.h to be 128 and 512 - */ -#define TRACE_MAX (4096 - 48) -#define VALUE_MAX_STRING (4096 - 48) -#define SYM_MAX (512) -#define XML_MAX 4096 /* Maximum size for tags/tokens */ -#define BUF_MAX 4096 /* General sanity check for bufs */ -#define FMT_STATIC_MAX 256 /* Maximum for fmtStatic calls */ - -#if (defined (LITTLEFOOT) || defined (WEBS)) -#define LF_BUF_MAX (510) -#define LF_PATHSIZE LF_BUF_MAX -#else -#define LF_BUF_MAX BUF_MAX -#define LF_PATHSIZE PATHSIZE -#define UPPATHSIZE PATHSIZE -#endif /* LITTLEFOOT || WEBS */ - -#ifndef CHAR_T_DEFINED -#define CHAR_T_DEFINED 1 -#ifdef UNICODE -/* - * To convert strings to UNICODE. We have a level of indirection so things - * like T(__FILE__) will expand properly. - */ -#define T(x) __TXT(x) -#define __TXT(s) L ## s -typedef unsigned short char_t; -typedef unsigned short uchar_t; - -/* - * Text size of buffer macro. A buffer bytes will hold (size / char size) - * characters. - */ -#define TSZ(x) (sizeof(x) / sizeof(char_t)) - -/* - * How many ASCII bytes are required to represent this UNICODE string? - */ -#define TASTRL(x) ((wcslen(x) + 1) * sizeof(char_t)) - -#else -#define T(s) s -typedef char char_t; -#define TSZ(x) (sizeof(x)) -#define TASTRL(x) (strlen(x) + 1) -#ifdef WIN -typedef unsigned char uchar_t; -#endif /* WIN */ - -#endif /* UNICODE */ - -#endif /* ! CHAR_T_DEFINED */ - -/* - * "Boolean" constants - */ - -#ifndef TRUE -#define TRUE 1 -#endif - -#ifndef FALSE -#define FALSE 0 -#endif - -/* - * GoAhead Copyright. - */ -#define GOAHEAD_COPYRIGHT \ - T("Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved.") - -/* - * The following include has to be after the unicode defines. By putting it - * here, many modules in various parts of the tree are cleaner. - */ -#if (defined (LITTLEFOOT) && defined (INMEM)) - #include "lf/inmem.h" -#endif /* LITTLEFOOT && INMEM */ - -/* - * Type for unicode systems - */ -#ifdef UNICODE - -#define gmain wmain - -#define gasctime _wasctime -#define gsprintf swprintf -#define gprintf wprintf -#define gfprintf fwprintf -#define gsscanf swscanf -#define gvsprintf vswprintf - -#define gstrcpy wcscpy -#define gstrncpy wcsncpy -#define gstrncat wcsncat -#define gstrlen wcslen -#define gstrcat wcscat -#define gstrcmp wcscmp -#define gstrncmp wcsncmp -#define gstricmp wcsicmp -#define gstrchr wcschr -#define gstrrchr wcsrchr -#define gstrtok wcstok -#define gstrnset wcsnset -#define gstrrchr wcsrchr -#define gstrstr wcsstr -#define gstrtol wcstol - -#define gfopen _wfopen -#define gopen _wopen -#define gclose close -#define gcreat _wcreat -#define gfgets fgetws -#define gfputs fputws -#define gfscanf fwscanf -#define ggets _getws -#define glseek lseek -#define gunlink _wunlink -#define gread read -#define grename _wrename -#define gwrite write -#define gtmpnam _wtmpnam -#define gtempnam _wtempnam -#define gfindfirst _wfindfirst -#define gfinddata_t _wfinddata_t -#define gfindnext _wfindnext -#define gfindclose _findclose -#define gstat _wstat -#define gaccess _waccess -#define gchmod _wchmod - -typedef struct _stat gstat_t; - -#define gmkdir _wmkdir -#define gchdir _wchdir -#define grmdir _wrmdir -#define ggetcwd _wgetcwd - -#define gtolower towlower -#define gtoupper towupper -#ifdef CE -#define gisspace isspace -#define gisdigit isdigit -#define gisxdigit isxdigit -#define gisupper isupper -#define gislower islower -#define gisprint isprint -#else -#define gremove _wremove -#define gisspace iswspace -#define gisdigit iswdigit -#define gisxdigit iswxdigit -#define gisupper iswupper -#define gislower iswlower -#endif /* if CE */ -#define gisalnum iswalnum -#define gisalpha iswalpha -#define gatoi(s) wcstol(s, NULL, 10) - -#define gctime _wctime -#define ggetenv _wgetenv -#define gexecvp _wexecvp - -#else /* ! UNICODE */ - -#ifndef gopen -#if INMEM -#define gchdir imChdir -#define gmkdir imMkdir -#define grmdir imRmdir -#define gclose imClose -#define gclosedir imClosedir -#define gchmod imChmod -#define ggetcwd imGetcwd -#define glseek imLseek -#define gloadModule imLoadModule -#define gopen imOpen -#define gopendir imOpendir -#define gread imRead -#define greaddir imReaddir -#define grename imRename -#define gstat imStat -#define gunlink imUnlink -#define gwrite imWrite -#else -#if VXWORKS -#define gchdir vxchdir -#define gmkdir vxmkdir -#define grmdir vxrmdir -#elif (defined (LYNX) || defined (LINUX) || defined (MACOSX) || defined (SOLARIS)) -#define gchdir chdir -#define gmkdir(s) mkdir(s,0755) -#define grmdir rmdir -#else -#define gchdir chdir -#define gmkdir mkdir -#define grmdir rmdir -#endif /* VXWORKS #elif LYNX || LINUX || MACOSX || SOLARIS*/ -#define gclose close -#define gclosedir closedir -#define gchmod chmod -#define ggetcwd getcwd -#define glseek lseek -#define gloadModule loadModule -#define gopen open -#define gopendir opendir -#define gread read -#define greaddir readdir -#define grename rename -#define gstat stat -#define gunlink unlink -#define gwrite write -#endif /* INMEM */ -#endif /* ! gopen */ - -#define gasctime asctime -#define gsprintf sprintf -#define gprintf printf -#define gfprintf fprintf -#define gsscanf sscanf -#define gvsprintf vsprintf - -#define gstrcpy strcpy -#define gstrncpy strncpy -#define gstrncat strncat -#define gstrlen strlen -#define gstrcat strcat -#define gstrcmp strcmp -#define gstrncmp strncmp -#define gstricmp strcmpci -#define gstrchr strchr -#define gstrrchr strrchr -#define gstrtok strtok -#define gstrnset strnset -#define gstrrchr strrchr -#define gstrstr strstr -#define gstrtol strtol - -#define gfopen fopen -#define gcreat creat -#define gfgets fgets -#define gfputs fputs -#define gfscanf fscanf -#define ggets gets -#define gtmpnam tmpnam -#define gtempnam tempnam -#define gfindfirst _findfirst -#define gfinddata_t _finddata_t -#define gfindnext _findnext -#define gfindclose _findclose -#define gaccess access - -typedef struct stat gstat_t; - -#define gremove remove - -#define gtolower tolower -#define gtoupper toupper -#define gisspace isspace -#define gisdigit isdigit -#define gisxdigit isxdigit -#define gisalnum isalnum -#define gisalpha isalpha -#define gisupper isupper -#define gislower islower -#define gatoi atoi - -#define gctime ctime -#define ggetenv getenv -#define gexecvp execvp -#ifndef VXWORKS -#define gmain main -#endif /* ! VXWORKS */ -#ifdef VXWORKS -#define fcntl(a, b, c) -#endif /* VXWORKS */ -#endif /* ! UNICODE */ - -/* - * Include inmem.h here because it redefines many of the file access fucntions. - * Otherwise there would be lots more #if-#elif-#else-#endif ugliness. - */ -#ifdef INMEM - #include "lf/inmem.h" -#endif - -/********************************** Defines ***********************************/ - -#ifndef FNAMESIZE -#define FNAMESIZE 254 /* Max length of file names */ -#endif /* FNAMESIZE */ - -#define E_MAX_ERROR 4096 -#define URL_MAX 4096 - -/* - * Error types - */ -#define E_ASSERT 0x1 /* Assertion error */ -#define E_LOG 0x2 /* Log error to log file */ -#define E_USER 0x3 /* Error that must be displayed */ - -#define E_L T(__FILE__), __LINE__ -#define E_ARGS_DEC char_t *file, int line -#define E_ARGS file, line - -#if (defined (ASSERT) || defined (ASSERT_CE)) - #define a_assert(C) if (C) ; else error(E_L, E_ASSERT, T("%s"), T(#C)) -#else - #define a_assert(C) if (1) ; else {} -#endif /* ASSERT || ASSERT_CE */ - -/******************************************************************************/ -/* VALUE */ -/******************************************************************************/ -/* - * These values are not prefixed so as to aid code readability - */ - -typedef enum { - undefined = 0, - byteint = 1, - shortint = 2, - integer = 3, - hex = 4, - percent = 5, - octal = 6, - big = 7, - flag = 8, - floating = 9, - string = 10, - bytes = 11, - symbol = 12, - errmsg = 13 -} vtype_t; - -#ifndef __NO_PACK -#pragma pack(2) -#endif /* _NO_PACK */ - -typedef struct { - - union { - char flag; - char byteint; - short shortint; - char percent; - long integer; - long hex; - long octal; - long big[2]; -#ifdef FLOATING_POINT_SUPPORT - double floating; -#endif /* FLOATING_POINT_SUPPORT */ - char_t *string; - char *bytes; - char_t *errmsg; - void *symbol; - } value; - - vtype_t type; - unsigned int valid : 8; - unsigned int allocated : 8; /* String was balloced */ -} value_t; - -#ifndef __NO_PACK -#pragma pack() -#endif /* __NO_PACK */ - -/* - * Allocation flags - */ -#define VALUE_ALLOCATE 0x1 - -#define value_numeric(t) (t >= byteint && t <= big) -#define value_str(t) (t >= string && t <= bytes) -#define value_ok(t) (t > undefined && t <= symbol) - -#define VALUE_VALID { {0}, integer, 1 } -#define VALUE_INVALID { {0}, undefined, 0 } - -/******************************************************************************/ -/* - * A ring queue allows maximum utilization of memory for data storage and is - * ideal for input/output buffering. This module provides a highly effecient - * implementation and a vehicle for dynamic strings. - * - * WARNING: This is a public implementation and callers have full access to - * the queue structure and pointers. Change this module very carefully. - * - * This module follows the open/close model. - * - * Operation of a ringq where rq is a pointer to a ringq : - * - * rq->buflen contains the size of the buffer. - * rq->buf will point to the start of the buffer. - * rq->servp will point to the first (un-consumed) data byte. - * rq->endp will point to the next free location to which new data is added - * rq->endbuf will point to one past the end of the buffer. - * - * Eg. If the ringq contains the data "abcdef", it might look like : - * - * +-------------------------------------------------------------------+ - * | | | | | | | | a | b | c | d | e | f | | | | | - * +-------------------------------------------------------------------+ - * ^ ^ ^ ^ - * | | | | - * 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 - * the ringq is never filled such that servp == endp. - * - * It is the fillers 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. - */ - -/* - * Ring queue buffer structure - */ -typedef struct { - unsigned char *buf; /* Holding buffer for data */ - unsigned char *servp; /* Pointer to start of data */ - unsigned char *endp; /* Pointer to end of data */ - unsigned char *endbuf; /* Pointer to end of buffer */ - int buflen; /* Length of ring queue */ - int maxsize; /* Maximum size */ - int increment; /* Growth increment */ -} ringq_t; - -/* - * Block allocation (balloc) definitions - */ -#ifdef B_STATS -#ifndef B_L -#define B_L T(__FILE__), __LINE__ -#define B_ARGS_DEC char_t *file, int line -#define B_ARGS file, line -#endif /* B_L */ -#endif /* B_STATS */ - -/* - * Block classes are: 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, - * 16384, 32768, 65536 - */ -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_SHIFT 4 /* Convert size to class */ -#define B_ROUND ((1 << (B_SHIFT)) - 1) -#define B_MAX_CLASS 13 /* Maximum class number + 1 */ -#define B_MALLOCED 0x80000000 /* Block was malloced */ -#define B_DEFAULT_MEM (64 * 1024) /* Default memory allocation */ -#define B_MAX_FILES (512) /* Maximum number of files */ -#define B_FILL_CHAR (0x77) /* Fill byte for buffers */ -#define B_FILL_WORD (0x77777777) /* Fill word for buffers */ -#define B_MAX_BLOCKS (64 * 1024) /* Maximum allocated blocks */ - -/* - * Flags. The integrity value is used as an arbitrary value to fill the flags. - */ -#define B_INTEGRITY 0x8124000 /* Integrity value */ -#define B_INTEGRITY_MASK 0xFFFF000 /* Integrity mask */ -#define B_USE_MALLOC 0x1 /* Okay to use malloc if required */ -#define B_USER_BUF 0x2 /* User supplied buffer for mem */ - -/* - * The symbol table record for each symbol entry - */ - -typedef struct sym_t { - struct sym_t *forw; /* Pointer to next hash list */ - value_t name; /* Name of symbol */ - value_t content; /* Value of symbol */ - int arg; /* Parameter value */ -} sym_t; - -typedef int sym_fd_t; /* Returned by symOpen */ - -/* - * Script engines - */ -#define EMF_SCRIPT_JSCRIPT 0 /* javascript */ -#define EMF_SCRIPT_TCL 1 /* tcl */ -#define EMF_SCRIPT_EJSCRIPT 2 /* Ejscript */ -#define EMF_SCRIPT_MAX 3 - -#define MAXINT INT_MAX -#define BITSPERBYTE CHAR_BIT -#define BITS(type) (BITSPERBYTE * (int) sizeof(type)) -#define STRSPACE T("\t \n\r\t") - -#ifndef max -#define max(a,b) (((a) > (b)) ? (a) : (b)) -#endif /* max */ - -#ifndef min -#define min(a,b) (((a) < (b)) ? (a) : (b)) -#endif /* min */ - -/******************************************************************************/ -/* CRON */ -/******************************************************************************/ - -typedef struct { - char_t *minute; - char_t *hour; - char_t *day; - char_t *month; - char_t *dayofweek; -} cron_t; - -extern long cronUntil(cron_t *cp, int period, time_t testTime); -extern int cronAlloc(cron_t *cp, char_t *str); -extern int cronFree(cron_t *cp); - -/******************************************************************************/ -/* SOCKET */ -/******************************************************************************/ -/* - * Socket flags - */ - -#if ((defined (WIN) || defined (CE)) && defined (WEBS)) -#define EWOULDBLOCK WSAEWOULDBLOCK -#define ENETDOWN WSAENETDOWN -#define ECONNRESET WSAECONNRESET -#endif /* (WIN || CE) && WEBS) */ - -#define SOCKET_EOF 0x1 /* Seen end of file */ -#define SOCKET_CONNECTING 0x2 /* Connect in progress */ -#define SOCKET_BROADCAST 0x4 /* Broadcast mode */ -#define SOCKET_PENDING 0x8 /* Message pending on this socket */ -#define SOCKET_FLUSHING 0x10 /* Background flushing */ -#define SOCKET_DATAGRAM 0x20 /* Use datagrams */ -#define SOCKET_ASYNC 0x40 /* Use async connect */ -#define SOCKET_BLOCK 0x80 /* Use blocking I/O */ -#define SOCKET_LISTENING 0x100 /* Socket is server listener */ -#define SOCKET_CLOSING 0x200 /* Socket is closing */ -#define SOCKET_CONNRESET 0x400 /* Socket connection was reset */ - -#define SOCKET_PORT_MAX 0xffff /* Max Port size */ - -/* - * Socket error values - */ -#define SOCKET_WOULDBLOCK 1 /* Socket would block on I/O */ -#define SOCKET_RESET 2 /* Socket has been reset */ -#define SOCKET_NETDOWN 3 /* Network is down */ -#define SOCKET_AGAIN 4 /* Issue the request again */ -#define SOCKET_INTR 5 /* Call was interrupted */ -#define SOCKET_INVAL 6 /* Invalid */ - -/* - * Handler event masks - */ -#define SOCKET_READABLE 0x2 /* Make socket readable */ -#define SOCKET_WRITABLE 0x4 /* Make socket writable */ -#define SOCKET_EXCEPTION 0x8 /* Interested in exceptions */ -#define EMF_SOCKET_MESSAGE (WM_USER+13) - -#ifdef LITTLEFOOT -#define SOCKET_BUFSIZ 510 /* Underlying buffer size */ -#else -#define SOCKET_BUFSIZ 1024 /* Underlying buffer size */ -#endif /* LITTLEFOOT */ - -typedef void (*socketHandler_t)(int sid, int mask, int data); -typedef int (*socketAccept_t)(int sid, char *ipaddr, int port, - int listenSid); -typedef struct { - char host[64]; /* Host name */ - ringq_t inBuf; /* Input ring queue */ - ringq_t outBuf; /* Output ring queue */ - ringq_t lineBuf; /* Line ring queue */ - socketAccept_t accept; /* Accept handler */ - socketHandler_t handler; /* User I/O handler */ - int handler_data; /* User handler data */ - int handlerMask; /* Handler events of interest */ - int sid; /* Index into socket[] */ - int port; /* Port to listen on */ - int flags; /* Current state flags */ - int sock; /* Actual socket handle */ - int fileHandle; /* ID of the file handler */ - int interestEvents; /* Mask of events to watch for */ - int currentEvents; /* Mask of ready events (FD_xx) */ - int selectEvents; /* Events being selected */ - int saveMask; /* saved Mask for socketFlush */ - int error; /* Last error */ -} socket_t; - -/********************************* Prototypes *********************************/ -/* - * Balloc module - * - */ - -extern void bclose(void); -extern int bopen(void *buf, int bufsize, int flags); - -/* - * Define NO_BALLOC to turn off our balloc module altogether - * #define NO_BALLOC 1 - */ - -#ifdef NO_BALLOC -#define balloc(B_ARGS, num) malloc(num) -#define bfree(B_ARGS, p) free(p) -#define bfreeSafe(B_ARGS, p) \ - if (p) { free(p); } else -#define brealloc(B_ARGS, p, num) realloc(p, num) -extern char_t *bstrdupNoBalloc(char_t *s); -extern char *bstrdupANoBalloc(char *s); -#define bstrdup(B_ARGS, s) bstrdupNoBalloc(s) -#define bstrdupA(B_ARGS, s) bstrdupANoBalloc(s) -#define gstrdup(B_ARGS, s) bstrdupNoBalloc(s) - -#else /* BALLOC */ - -#ifndef B_STATS -#define balloc(B_ARGS, num) balloc(num) -#define bfree(B_ARGS, p) bfree(p) -#define bfreeSafe(B_ARGS, p) bfreeSafe(p) -#define brealloc(B_ARGS, p, size) brealloc(p, size) -#define bstrdup(B_ARGS, p) bstrdup(p) - -#ifdef UNICODE -#define bstrdupA(B_ARGS, p) bstrdupA(p) -#else /* UNICODE */ -#define bstrdupA bstrdup -#endif /* UNICODE */ - -#endif /* B_STATS */ - -#define gstrdup bstrdup -extern void *balloc(B_ARGS_DEC, int size); -extern void bfree(B_ARGS_DEC, void *mp); -extern void bfreeSafe(B_ARGS_DEC, void *mp); -extern void *brealloc(B_ARGS_DEC, void *buf, int newsize); -extern char_t *bstrdup(B_ARGS_DEC, char_t *s); - -#ifdef UNICODE -extern char *bstrdupA(B_ARGS_DEC, char *s); -#else /* UNICODE */ -#define bstrdupA bstrdup -#endif /* UNICODE */ -#endif /* BALLOC */ - -extern void bstats(int handle, void (*writefn)(int handle, char_t *fmt, ...)); - -/* - * Flags. The integrity value is used as an arbitrary value to fill the flags. - */ -#define B_USE_MALLOC 0x1 /* Okay to use malloc if required */ -#define B_USER_BUF 0x2 /* User supplied buffer for mem */ - - -#if !LINUX && !__rtems__ -extern char_t *basename(char_t *name); -#endif /* !LINUX */ - -#if (defined (UEMF) && defined (WEBS)) -/* - * The open source webserver uses a different callback/timer mechanism - * than other emf derivative products such as FieldUpgrader agents - * so redefine those API for webserver so that they can coexist in the - * same address space as the others. - */ -#define emfSchedCallback websSchedCallBack -#define emfUnschedCallback websUnschedCallBack -#define emfReschedCallback websReschedCallBack -#endif /* UEMF && WEBS */ - -typedef void (emfSchedProc)(void *data, int id); -extern int emfSchedCallback(int delay, emfSchedProc *proc, void *arg); -extern void emfUnschedCallback(int id); -extern void emfReschedCallback(int id, int delay); -extern void emfSchedProcess(void); -extern int emfInstGet(void); -extern void emfInstSet(int inst); -extern void error(E_ARGS_DEC, int flags, char_t *fmt, ...); -extern void (*errorSetHandler(void (*function)(int etype, char_t *msg))) \ - (int etype, char_t *msg); - -#ifdef B_STATS -#define hAlloc(x) HALLOC(B_L, x) -#define hAllocEntry(x, y, z) HALLOCENTRY(B_L, x, y, z) -extern int HALLOC(B_ARGS_DEC, void ***map); -extern int HALLOCENTRY(B_ARGS_DEC, void ***list, int *max, int size); -#else -extern int hAlloc(void ***map); -extern int hAllocEntry(void ***list, int *max, int size); -#endif /* B_STATS */ - -extern int hFree(void ***map, int handle); - -extern int ringqOpen(ringq_t *rq, int increment, int maxsize); -extern void ringqClose(ringq_t *rq); -extern int ringqLen(ringq_t *rq); - -extern int ringqPutc(ringq_t *rq, char_t c); -extern int ringqInsertc(ringq_t *rq, char_t c); -extern int ringqPutStr(ringq_t *rq, char_t *str); -extern int ringqGetc(ringq_t *rq); - -extern int fmtValloc(char_t **s, int n, char_t *fmt, va_list arg); -extern int fmtAlloc(char_t **s, int n, char_t *fmt, ...); -extern int fmtStatic(char_t *s, int n, char_t *fmt, ...); - -#ifdef UNICODE -extern int ringqPutcA(ringq_t *rq, char c); -extern int ringqInsertcA(ringq_t *rq, char c); -extern int ringqPutStrA(ringq_t *rq, char *str); -extern int ringqGetcA(ringq_t *rq); -#else -#define ringqPutcA ringqPutc -#define ringqInsertcA ringqInsertc -#define ringqPutStrA ringqPutStr -#define ringqGetcA ringqGetc -#endif /* UNICODE */ - -extern int ringqPutBlk(ringq_t *rq, unsigned char *buf, int len); -extern int ringqPutBlkMax(ringq_t *rq); -extern void ringqPutBlkAdj(ringq_t *rq, int size); -extern int ringqGetBlk(ringq_t *rq, unsigned char *buf, int len); -extern int ringqGetBlkMax(ringq_t *rq); -extern void ringqGetBlkAdj(ringq_t *rq, int size); -extern void ringqFlush(ringq_t *rq); -extern void ringqAddNull(ringq_t *rq); - -extern int scriptSetVar(int engine, char_t *var, char_t *value); -extern int scriptEval(int engine, char_t *cmd, char_t **rslt, int chan); - -extern void socketClose(void); -extern void socketCloseConnection(int sid); -extern void socketCreateHandler(int sid, int mask, socketHandler_t - handler, int arg); -extern void socketDeleteHandler(int sid); -extern int socketEof(int sid); -extern int socketCanWrite(int sid); -extern void socketSetBufferSize(int sid, int in, int line, int out); -extern int socketFlush(int sid); -extern int socketGets(int sid, char_t **buf); -extern int socketGetPort(int sid); -extern int socketInputBuffered(int sid); -extern int socketOpen(void); -extern int socketOpenConnection(char *host, int port, - socketAccept_t accept, int flags); -extern void socketProcess(int hid); -extern int socketRead(int sid, char *buf, int len); -extern int socketReady(int hid); -extern int socketWrite(int sid, char *buf, int len); -extern int socketWriteString(int sid, char_t *buf); -extern int socketSelect(int hid, int timeout); -extern int socketGetHandle(int sid); -extern int socketSetBlock(int sid, int flags); -extern int socketGetBlock(int sid); -extern int socketAlloc(char *host, int port, socketAccept_t accept, - int flags); -extern void socketFree(int sid); -extern int socketGetError(void); -extern socket_t *socketPtr(int sid); -extern int socketWaitForEvent(socket_t *sp, int events, int *errCode); -extern void socketRegisterInterest(socket_t *sp, int handlerMask); -extern int socketGetInput(int sid, char *buf, int toRead, int *errCode); - -extern char_t *strlower(char_t *string); -extern char_t *strupper(char_t *string); - -extern char_t *stritoa(int n, char_t *string, int width); - -extern sym_fd_t symOpen(int hash_size); -extern void symClose(sym_fd_t sd); -extern sym_t *symLookup(sym_fd_t sd, char_t *name); -extern sym_t *symEnter(sym_fd_t sd, char_t *name, value_t v, int arg); -extern int symDelete(sym_fd_t sd, char_t *name); -extern void symWalk(sym_fd_t sd, void (*fn)(sym_t *symp)); -extern sym_t *symFirst(sym_fd_t sd); -extern sym_t *symNext(sym_fd_t sd); -extern int symSubOpen(void); -extern void symSubClose(void); - -extern void trace(int lev, char_t *fmt, ...); -extern void traceRaw(char_t *buf); -extern void (*traceSetHandler(void (*function)(int level, char_t *buf))) - (int level, char_t *buf); - -extern value_t valueInteger(long value); -extern value_t valueString(char_t *value, int flags); -extern value_t valueErrmsg(char_t *value); -extern void valueFree(value_t *v); -extern int vxchdir(char *dirname); - -extern unsigned int hextoi(char_t *hexstring); -extern unsigned int gstrtoi(char_t *s); -extern time_t timeMsec(void); - -extern char_t *ascToUni(char_t *ubuf, char *str, int nBytes); -extern char *uniToAsc(char *buf, char_t *ustr, int nBytes); -extern char_t *ballocAscToUni(char *cp, int alen); -extern char *ballocUniToAsc(char_t *unip, int ulen); - -extern char_t *basicGetHost(void); -extern char_t *basicGetAddress(void); -extern char_t *basicGetProduct(void); -extern void basicSetHost(char_t *host); -extern void basicSetAddress(char_t *addr); - -extern int harnessOpen(char_t **argv); -extern void harnessClose(int status); -extern void harnessTesting(char_t *msg, ...); -extern void harnessPassed(void); -extern void harnessFailed(int line); -extern int harnessLevel(void); - -#endif /* _h_UEMF */ - -/******************************************************************************/ diff --git a/cpukit/httpd/um.c b/cpukit/httpd/um.c deleted file mode 100644 index 58e288affb..0000000000 --- a/cpukit/httpd/um.c +++ /dev/null @@ -1,1435 +0,0 @@ -/* - * um.c -- User Management - * - * Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved. - * - * See the file "license.txt" for usage and redistribution license requirements - * - * $Id$ - */ - -/******************************** Description *********************************/ -/* - * User Management routines for adding/deleting/changing users and groups - * Also, routines for determining user access - */ - -/********************************* Includes ***********************************/ - -#include "um.h" -#include "emfdb.h" -#include "webs.h" - -/********************************** Defines ***********************************/ - -#define UM_DB_FILENAME T("um.xml") -#define UM_TXT_FILENAME T("umconfig.txt") - -/* - * Table names - */ -#define UM_USER_TABLENAME T("users") -#define UM_GROUP_TABLENAME T("groups") -#define UM_ACCESS_TABLENAME T("access") - -/* - * Column names - */ -#define UM_NAME T("name") -#define UM_PASS T("password") -#define UM_GROUP T("group") -#define UM_PROT T("prot") -#define UM_DISABLE T("disable") -#define UM_METHOD T("method") -#define UM_PRIVILEGE T("priv") -#define UM_SECURE T("secure") - -/* - * XOR encryption mask - * Note: This string should be modified for individual sites - * in order to enhance user password security. - */ -#define UM_XOR_ENCRYPT T("*j7a(L#yZ98sSd5HfSgGjMj8;Ss;d)(*&^#@$a2s0i3g") - -/******************************** Local Data **********************************/ - -#ifdef qHierarchicalAccess -/* - * user-provided function to allow hierarchical access protection. See below. - * for details. - */ -extern bool_t dmfCanAccess(const char_t* usergroup, const char_t* group); -#endif -#ifdef UEMF -/* - * User table definition - */ -#define NUMBER_OF_USER_COLUMNS 5 - -char_t *userColumnNames[NUMBER_OF_USER_COLUMNS] = { - UM_NAME, UM_PASS, UM_GROUP, UM_PROT, UM_DISABLE -}; - -int userColumnTypes[NUMBER_OF_USER_COLUMNS] = { - T_STRING, T_STRING, T_STRING, T_INT, T_INT -}; - -dbTable_t userTable = { - UM_USER_TABLENAME, - NUMBER_OF_USER_COLUMNS, - userColumnNames, - userColumnTypes, - 0, - NULL -}; - -/* - * Group table definition - */ -#define NUMBER_OF_GROUP_COLUMNS 5 - -char_t *groupColumnNames[NUMBER_OF_GROUP_COLUMNS] = { - UM_NAME, UM_PRIVILEGE, UM_METHOD, UM_PROT, UM_DISABLE -}; - -int groupColumnTypes[NUMBER_OF_GROUP_COLUMNS] = { - T_STRING, T_INT, T_INT, T_INT, T_INT -}; - -dbTable_t groupTable = { - UM_GROUP_TABLENAME, - NUMBER_OF_GROUP_COLUMNS, - groupColumnNames, - groupColumnTypes, - 0, - NULL -}; - -/* - * Access Limit table definition - */ -#define NUMBER_OF_ACCESS_COLUMNS 4 - -char_t *accessColumnNames[NUMBER_OF_ACCESS_COLUMNS] = { - UM_NAME, UM_METHOD, UM_SECURE, UM_GROUP -}; - -int accessColumnTypes[NUMBER_OF_ACCESS_COLUMNS] = { - T_STRING, T_INT, T_INT, T_STRING -}; - -dbTable_t accessTable = { - UM_ACCESS_TABLENAME, - NUMBER_OF_ACCESS_COLUMNS, - accessColumnNames, - accessColumnTypes, - 0, - NULL -}; -#endif /* #ifdef UEMF */ - -/* - * Database Identifier returned from dbOpen() - */ -static int didUM = -1; - -/* - * Configuration database persist filename - */ -static char_t *saveFilename = NULL; - -static int umOpenCount = 0; /* count of apps using this module */ - -/*************************** Forward Declarations *****************************/ - -static bool_t umCheckName(char_t *name); - -/*********************************** Code *************************************/ -/* - * umOpen() registers the UM tables in the fake emf-database - */ - -int umOpen(void) -{ - if (++umOpenCount != 1) { - return didUM; - } -/* - * Do not initialize if intialization has already taken place - */ - if (didUM == -1) { - didUM = dbOpen(UM_USER_TABLENAME, UM_DB_FILENAME, NULL, 0); -#ifdef UEMF - dbRegisterDBSchema(&userTable); - dbRegisterDBSchema(&groupTable); - dbRegisterDBSchema(&accessTable); -#endif - } - - if (saveFilename == NULL) { - saveFilename = bstrdup(B_L, UM_TXT_FILENAME); - } - - return didUM; -} - -/******************************************************************************/ -/* - * umClose() frees up the UM tables in the fake emf-database - */ - -void umClose(void) -{ - if (--umOpenCount > 0) { - return; - } -/* - * Do not close if intialization has not taken place - */ - if (didUM != -1) { - dbClose(didUM); - didUM = -1; - } - - if (saveFilename != NULL) { - bfree(B_L, saveFilename); - saveFilename = NULL; - } -} - -/******************************************************************************/ -/* - * umCommit() persists all of the UM tables - */ - -int umCommit(char_t *filename) -{ - if (filename && *filename) { - if (saveFilename != NULL) { - bfree(B_L, saveFilename); - } - - saveFilename = bstrdup(B_L, filename); - } - - a_assert (saveFilename && *saveFilename); - trace(3, T("UM: Writing User Configuration to file <%s>\n"), - saveFilename); - - return dbSave(didUM, saveFilename, 0); -} - -/******************************************************************************/ -/* - * umRestore() loads up the UM tables with persisted data - */ - -int umRestore(char_t *filename) -{ - if (filename && *filename) { - if (saveFilename != NULL) { - bfree(B_L, saveFilename); - } - - saveFilename = bstrdup(B_L, filename); - } - - a_assert(saveFilename && *saveFilename); - - trace(3, T("UM: Loading User Configuration from file <%s>\n"), - saveFilename); - -/* - * First empty the database, otherwise we wind up with duplicates! - */ - dbZero(didUM); - return dbLoad(didUM, saveFilename, 0); -} - -/******************************************************************************/ -/* - * Encrypt/Decrypt a text string. - * Returns the number of characters encrypted. - */ - -static int umEncryptString(char_t *textString) -{ - char_t *enMask; - unsigned char enChar; - int numChars; - - a_assert(textString); - - enMask = UM_XOR_ENCRYPT; - numChars = 0; - - while (*textString) { - enChar = *textString ^ *enMask; -/* - * Do not produce encrypted text with embedded linefeeds or tabs. - * Simply use existing character. - */ - if (enChar && !gisspace(enChar)) - *textString = enChar; -/* - * Increment all pointers. - */ - enMask++; - textString++; - numChars++; -/* - * Wrap encryption mask pointer if at end of length. - */ - if (*enMask == '\0') { - enMask = UM_XOR_ENCRYPT; - } - } - - return numChars; -} - -/******************************************************************************/ -/* - * umGetFirstRowData() - return a pointer to the first non-blank key value - * in the given column for the given table. - */ - -static char_t *umGetFirstRowData(char_t *tableName, char_t *columnName) -{ - char_t *columnData; - int row; - int check; - - a_assert(tableName && *tableName); - a_assert(columnName && *columnName); - - row = 0; -/* - * Move through table until we retrieve the first row with non-null - * column data. - */ - columnData = NULL; - while ((check = dbReadStr(didUM, tableName, columnName, row++, - &columnData)) == 0 || (check == DB_ERR_ROW_DELETED)) { - if (columnData && *columnData) { - return columnData; - } - } - - return NULL; -} - -/******************************************************************************/ -/* - * umGetNextRowData() - return a pointer to the first non-blank - * key value following the given one. - */ - -static char_t *umGetNextRowData(char_t *tableName, char_t *columnName, - char_t *keyLast) -{ - char_t *key; - int row; - int check; - - a_assert(tableName && *tableName); - a_assert(columnName && *columnName); - a_assert(keyLast && *keyLast); -/* - * Position row counter to row where the given key value was found - */ - row = 0; - key = NULL; - - while ((((check = dbReadStr(didUM, tableName, columnName, row++, - &key)) == 0) || (check == DB_ERR_ROW_DELETED)) && - ((key == NULL) || (gstrcmp(key, keyLast) != 0))) { - } -/* - * If the last key value was not found, return NULL - */ - if (!key || gstrcmp(key, keyLast) != 0) { - return NULL; - } -/* - * Move through table until we retrieve the next row with a non-null key - */ - while (((check = dbReadStr(didUM, tableName, columnName, row++, &key)) - == 0) || (check == DB_ERR_ROW_DELETED)) { - if (key && *key && (gstrcmp(key, keyLast) != 0)) { - return key; - } - } - - return NULL; -} - -/******************************************************************************/ -/* - * umAddUser() - Adds a user to the "users" table. - */ - -int umAddUser(char_t *user, char_t *pass, char_t *group, - bool_t prot, bool_t disabled) -{ - int row; - char_t *password; - - a_assert(user && *user); - a_assert(pass && *pass); - a_assert(group && *group); - - trace(3, T("UM: Adding User <%s>\n"), user); - -/* - * Do not allow duplicates - */ - if (umUserExists(user)) { - return UM_ERR_DUPLICATE; - } - -/* - * Make sure user name and password contain valid characters - */ - if (!umCheckName(user)) { - return UM_ERR_BAD_NAME; - } - - if (!umCheckName(pass)) { - return UM_ERR_BAD_PASSWORD; - } - -/* - * Make sure group exists - */ - if (!umGroupExists(group)) { - return UM_ERR_NOT_FOUND; - } - -/* - * Now create the user record - */ - row = dbAddRow(didUM, UM_USER_TABLENAME); - - if (row < 0) { - return UM_ERR_GENERAL; - } - - if (dbWriteStr(didUM, UM_USER_TABLENAME, UM_NAME, row, user) != 0) { - return UM_ERR_GENERAL; - } - - password = bstrdup(B_L, pass); - umEncryptString(password); - dbWriteStr(didUM, UM_USER_TABLENAME, UM_PASS, row, password); - bfree(B_L, password); - dbWriteStr(didUM, UM_USER_TABLENAME, UM_GROUP, row, group); - dbWriteInt(didUM, UM_USER_TABLENAME, UM_PROT, row, prot); - dbWriteInt(didUM, UM_USER_TABLENAME, UM_DISABLE, row, disabled); - - return 0; -} - -/******************************************************************************/ -/* - * umDeleteUser() - remove a user from the "users" table - */ - -int umDeleteUser(char_t *user) -{ - int row; - - a_assert(user && *user); - trace(3, T("UM: Deleting User <%s>\n"), user); -/* - * Check to see if user is delete-protected - */ - if (umGetUserProtected(user)) { - return UM_ERR_PROTECTED; - } - -/* - * If found, delete the user from the database - */ - if ((row = dbSearchStr(didUM, UM_USER_TABLENAME, UM_NAME, user, 0)) >= 0) { - return dbDeleteRow(didUM, UM_USER_TABLENAME, row); - } - - return UM_ERR_NOT_FOUND; -} - -/******************************************************************************/ -/* - * umGetFirstUser() - Returns the user ID of the first user found in the - * "users" table. - */ - -char_t *umGetFirstUser(void) -{ - return umGetFirstRowData(UM_USER_TABLENAME, UM_NAME); -} - -/******************************************************************************/ -/* - * umGetNextUser() Returns the next user found in the "users" table after - * the given user. - */ - -char_t *umGetNextUser(char_t *userLast) -{ - return umGetNextRowData(UM_USER_TABLENAME, UM_NAME, userLast); -} - -/******************************************************************************/ -/* - * umUserExists() Returns TRUE if userid exists. - */ - -bool_t umUserExists(char_t *user) -{ - a_assert(user && *user); - - if (dbSearchStr(didUM, UM_USER_TABLENAME, UM_NAME, user, 0) >= 0) { - return TRUE; - } else { - return FALSE; - } -} - -/******************************************************************************/ -/* - * umGetUserPassword() returns a de-crypted copy of the user password - */ - -char_t *umGetUserPassword(char_t *user) -{ - char_t *password; - int row; - - a_assert(user && *user); - - password = NULL; - row = dbSearchStr(didUM, UM_USER_TABLENAME, UM_NAME, user, 0); - - if (row >= 0) { - char_t *pass = NULL; - dbReadStr(didUM, UM_USER_TABLENAME, UM_PASS, row, &pass); -/* - * Decrypt password - * Note, this function returns a copy of the password, which must - * be deleted at some time in the future. - */ - password = bstrdup(B_L, pass); - umEncryptString(password); - } - - return password; -} - -/******************************************************************************/ -/* - * umSetUserPassword() updates the user password in the user "table" after - * encrypting the given password - */ - -int umSetUserPassword(char_t *user, char_t *pass) -{ - int row, nRet; - char_t *password; - - a_assert(user && *user); - a_assert(pass && *pass); - trace(3, T("UM: Attempting to change the password for user <%s>\n"), user); -/* - * Find the row of the user - */ - if ((row = dbSearchStr(didUM, UM_USER_TABLENAME, UM_NAME, user, 0)) < 0) { - return UM_ERR_NOT_FOUND; - } - - password = bstrdup(B_L, pass); - umEncryptString(password); - nRet = dbWriteStr(didUM, UM_USER_TABLENAME, UM_PASS, row, password); - bfree(B_L, password); - - return nRet; -} - -/******************************************************************************/ -/* - * umGetUserGroup() returns the name of the user group - */ - -char_t *umGetUserGroup(char_t *user) -{ - char_t *group; - int row; - - a_assert(user && *user); - group = NULL; -/* - * Find the row of the user - */ - row = dbSearchStr(didUM, UM_USER_TABLENAME, UM_NAME, user, 0); - - if (row >= 0) { - dbReadStr(didUM, UM_USER_TABLENAME, UM_GROUP, row, &group); - } - - return group; -} - -/******************************************************************************/ -/* - * umSetUserGroup() Sets the name of the user group for the user - */ - -int umSetUserGroup(char_t *user, char_t *group) -{ - int row; - - a_assert(user && *user); - a_assert(group && *group); -/* - * Find the row of the user - */ - row = dbSearchStr(didUM, UM_USER_TABLENAME, UM_NAME, user, 0); - - if (row >= 0) { - return dbWriteStr(didUM, UM_USER_TABLENAME, UM_GROUP, row, group); - } else { - return UM_ERR_NOT_FOUND; - } -} - -/******************************************************************************/ -/* - * umGetUserEnabled() - returns if the user is enabled - * Returns FALSE if the user is not found. - */ - -bool_t umGetUserEnabled(char_t *user) -{ - int disabled, row; - - a_assert(user && *user); - - disabled = 1; -/* - * Find the row of the user - */ - row = dbSearchStr(didUM, UM_USER_TABLENAME, UM_NAME, user, 0); - - if (row >= 0) { - dbReadInt(didUM, UM_USER_TABLENAME, UM_DISABLE, row, &disabled); - } - - return (bool_t)!disabled; -} - -/******************************************************************************/ -/* - * umSetUserEnabled() Enables/disables the user - */ -int umSetUserEnabled(char_t *user, bool_t enabled) -{ - int row; - - a_assert(user && *user); -/* - * Find the row of the user - */ - row = dbSearchStr(didUM, UM_USER_TABLENAME, UM_NAME, user, 0); - if (row >= 0) { - return dbWriteInt(didUM, UM_USER_TABLENAME, UM_DISABLE, row, !enabled); - } else { - return UM_ERR_NOT_FOUND; - } -} - -/******************************************************************************/ -/* - * umGetUserProtected() - determine deletability of user - */ - -bool_t umGetUserProtected(char_t *user) -{ - int protect, row; - - a_assert(user && *user); -/* - * Find the row of the user - */ - row = dbSearchStr(didUM, UM_USER_TABLENAME, UM_NAME, user, 0); - protect = FALSE; - - if (row >= 0) { - dbReadInt(didUM, UM_USER_TABLENAME, UM_PROT, row, &protect); - } - - return (bool_t)protect; -} - -/******************************************************************************/ -/* - * umSetUserProtected() sets the delete protection for the user - */ -int umSetUserProtected(char_t *user, bool_t protect) -{ - int row; - - a_assert(user && *user); -/* - * Find the row of the user - */ - row = dbSearchStr(didUM, UM_USER_TABLENAME, UM_NAME, user, 0); - - if (row >= 0) { - return dbWriteInt(didUM, UM_USER_TABLENAME, UM_PROT, row, protect); - } else { - return UM_ERR_NOT_FOUND; - } -} - - -/******************************************************************************/ -/* - * umAddGroup() adds a group to the "Group" table - */ - -int umAddGroup(char_t *group, short priv, accessMeth_t am, - bool_t prot, bool_t disabled) -{ - int row; - - a_assert(group && *group); - trace(3, T("UM: Adding group <%s>\n"), group); - -/* - * Do not allow duplicates - */ - if (umGroupExists(group)) { - return UM_ERR_DUPLICATE; - } - -/* - * Only allow valid characters in key field - */ - if (!umCheckName(group)) { - return UM_ERR_BAD_NAME; - } - -/* - * Add a new row to the table - */ - if ((row = dbAddRow(didUM, UM_GROUP_TABLENAME)) < 0) { - return UM_ERR_GENERAL; - } - -/* - * Write the key field - */ - if (dbWriteStr(didUM, UM_GROUP_TABLENAME, UM_NAME, row, group) != 0) { - return UM_ERR_GENERAL; - } - -/* - * Write the remaining fields - */ - dbWriteInt(didUM, UM_GROUP_TABLENAME, UM_PRIVILEGE, row, priv); - dbWriteInt(didUM, UM_GROUP_TABLENAME, UM_METHOD, row, (int) am); - dbWriteInt(didUM, UM_GROUP_TABLENAME, UM_PROT, row, prot); - dbWriteInt(didUM, UM_GROUP_TABLENAME, UM_DISABLE, row, disabled); - - return 0; -} - -/******************************************************************************/ -/* - * umDeleteGroup() - Delete a user group, if not protected - */ - -int umDeleteGroup(char_t *group) -{ - int row; - - a_assert(group && *group); - trace(3, T("UM: Deleting Group <%s>\n"), group); - -/* - * Check to see if the group is in use - */ - if (umGetGroupInUse(group)) { - return UM_ERR_IN_USE; - } - -/* - * Check to see if the group is delete-protected - */ - if (umGetGroupProtected(group)) { - return UM_ERR_PROTECTED; - } - -/* - * Find the row of the group to delete - */ - if ((row = dbSearchStr(didUM, UM_GROUP_TABLENAME, UM_NAME, group, 0)) < 0) { - return UM_ERR_NOT_FOUND; - } - - return dbDeleteRow(didUM, UM_GROUP_TABLENAME, row); -} - -/******************************************************************************/ -/* - * umGroupExists() returns TRUE if group exists, FALSE otherwise - */ - -bool_t umGroupExists(char_t *group) -{ - a_assert(group && *group); - - if (dbSearchStr(didUM, UM_GROUP_TABLENAME, UM_NAME, group, 0) >= 0) { - return TRUE; - } else { - return FALSE; - } -} - - -/******************************************************************************/ -/* - * umGetGroupInUse() returns TRUE if the group is referenced by a user or by - * an access limit. - */ - -bool_t umGetGroupInUse(char_t *group) -{ - a_assert(group && *group); - -/* - * First, check the user table - */ - if (dbSearchStr(didUM, UM_USER_TABLENAME, UM_GROUP, group, 0) >= 0) { - return TRUE; - } - -/* - * Second, check the access limit table - */ - if (dbSearchStr(didUM, UM_ACCESS_TABLENAME, UM_GROUP, group, 0) >= 0) { - return TRUE; - } - - return FALSE; -} - - -/******************************************************************************/ -/* - * umGetFirstGroup() - return a pointer to the first non-blank group name - */ - -char_t *umGetFirstGroup(void) -{ - return umGetFirstRowData(UM_GROUP_TABLENAME, UM_NAME); -} - -/******************************************************************************/ -/* - * umGetNextGroup() - return a pointer to the first non-blank group name - * following the given group name - */ - -char_t *umGetNextGroup(char_t *groupLast) -{ - return umGetNextRowData(UM_GROUP_TABLENAME, UM_NAME, groupLast); -} - -/******************************************************************************/ -/* - * Returns the default access method to use for a given group - */ - -accessMeth_t umGetGroupAccessMethod(char_t *group) -{ - int am, row; - - a_assert(group && *group); - row = dbSearchStr(didUM, UM_GROUP_TABLENAME, UM_NAME, group, 0); - - if (row >= 0) { - dbReadInt(didUM, UM_GROUP_TABLENAME, UM_METHOD, row, (int *)&am); - } else { - am = AM_INVALID; - } - - return (accessMeth_t) am; -} - -/******************************************************************************/ -/* - * Set the default access method to use for a given group - */ - -int umSetGroupAccessMethod(char_t *group, accessMeth_t am) -{ - int row; - - a_assert(group && *group); - row = dbSearchStr(didUM, UM_GROUP_TABLENAME, UM_NAME, group, 0); - - if (row >= 0) { - return dbWriteInt(didUM, UM_GROUP_TABLENAME, UM_METHOD, row, (int) am); - } else { - return UM_ERR_NOT_FOUND; - } -} - -/******************************************************************************/ -/* - * Returns the privilege mask for a given group - */ - -short umGetGroupPrivilege(char_t *group) -{ - int privilege, row; - - a_assert(group && *group); - privilege = -1; - row = dbSearchStr(didUM, UM_GROUP_TABLENAME, UM_NAME, group, 0); - - if (row >= 0) { - dbReadInt(didUM, UM_GROUP_TABLENAME, UM_PRIVILEGE, row, &privilege); - } - - return (short) privilege; -} - -/******************************************************************************/ -/* - * Set the privilege mask for a given group - */ - -int umSetGroupPrivilege(char_t *group, short privilege) -{ - int row; - - a_assert(group && *group); - row = dbSearchStr(didUM, UM_GROUP_TABLENAME, UM_NAME, group, 0); - - if (row >= 0) { - return dbWriteInt(didUM, UM_GROUP_TABLENAME, UM_PRIVILEGE, row, - (int)privilege); - } else { - return UM_ERR_NOT_FOUND; - } -} - -/******************************************************************************/ -/* - * Returns the enabled setting for a given group. - * Returns FALSE if group is not found. - */ - -bool_t umGetGroupEnabled(char_t *group) -{ - int disabled, row; - - a_assert(group && *group); - row = dbSearchStr(didUM, UM_GROUP_TABLENAME, UM_NAME, group, 0); - disabled = 1; - - if (row >= 0) { - dbReadInt(didUM, UM_GROUP_TABLENAME, UM_DISABLE, row, &disabled); - } - - return (bool_t) !disabled; -} - -/******************************************************************************/ -/* - * Sets the enabled setting for a given group. - */ - -int umSetGroupEnabled(char_t *group, bool_t enabled) -{ - int row; - - a_assert(group && *group); - row = dbSearchStr(didUM, UM_GROUP_TABLENAME, UM_NAME, group, 0); - - if (row >= 0) { - return dbWriteInt(didUM, UM_GROUP_TABLENAME, UM_DISABLE, row, - (int) !enabled); - } else { - return UM_ERR_NOT_FOUND; - } -} - -/******************************************************************************/ -/* - * Returns the protected setting for a given group - * Returns FALSE if user is not found - */ - -bool_t umGetGroupProtected(char_t *group) -{ - int protect, row; - - a_assert(group && *group); - - protect = 0; - row = dbSearchStr(didUM, UM_GROUP_TABLENAME, UM_NAME, group, 0); - if (row >= 0) { - dbReadInt(didUM, UM_GROUP_TABLENAME, UM_PROT, row, &protect); - } - - return (bool_t) protect; -} - -/******************************************************************************/ -/* - * Sets the protected setting for a given group - */ - -int umSetGroupProtected(char_t *group, bool_t protect) -{ - int row; - - a_assert(group && *group); - row = dbSearchStr(didUM, UM_GROUP_TABLENAME, UM_NAME, group, 0); - - if (row >= 0) { - return dbWriteInt(didUM, UM_GROUP_TABLENAME, UM_PROT, row, - (int) protect); - } else { - return UM_ERR_NOT_FOUND; - } -} - - -/******************************************************************************/ -/* - * umAddAccessLimit() adds an access limit to the "access" table - */ - -int umAddAccessLimit(char_t *url, accessMeth_t am, short secure, char_t *group) -{ - int row; - - a_assert(url && *url); - trace(3, T("UM: Adding Access Limit for <%s>\n"), url); - -/* - * Do not allow duplicates - */ - if (umAccessLimitExists(url)) { - return UM_ERR_DUPLICATE; - } - -/* - * Add a new row to the table - */ - if ((row = dbAddRow(didUM, UM_ACCESS_TABLENAME)) < 0) { - return UM_ERR_GENERAL; - } - -/* - * Write the key field - */ - if(dbWriteStr(didUM, UM_ACCESS_TABLENAME, UM_NAME, row, url) < 0) { - return UM_ERR_GENERAL; - } - -/* - * Write the remaining fields - */ - dbWriteInt(didUM, UM_ACCESS_TABLENAME, UM_METHOD, row, (int)am); - dbWriteInt(didUM, UM_ACCESS_TABLENAME, UM_SECURE, row, (int)secure); - dbWriteStr(didUM, UM_ACCESS_TABLENAME, UM_GROUP, row, group); - - return 0; -} - -/******************************************************************************/ -/* - * umDeleteAccessLimit() - */ - -int umDeleteAccessLimit(char_t *url) -{ - int row; - - a_assert(url && *url); - trace(3, T("UM: Deleting Access Limit for <%s>\n"), url); -/* - * Find the row of the access limit to delete - */ - if ((row = dbSearchStr(didUM, UM_ACCESS_TABLENAME, UM_NAME, url, 0)) < 0) { - return UM_ERR_NOT_FOUND; - } - - return dbDeleteRow(didUM, UM_ACCESS_TABLENAME, row); -} - -/******************************************************************************/ -/* - * umGetFirstGroup() - return a pointer to the first non-blank access limit - */ - -char_t *umGetFirstAccessLimit(void) -{ - return umGetFirstRowData(UM_ACCESS_TABLENAME, UM_NAME); -} - -/******************************************************************************/ -/* - * umGetNextAccessLimit() - return a pointer to the first non-blank - * access limit following the given one - */ - -char_t *umGetNextAccessLimit(char_t *urlLast) -{ - return umGetNextRowData(UM_ACCESS_TABLENAME, UM_NAME, urlLast); -} - -/******************************************************************************/ -/* - * umAccessLimitExists() returns TRUE if this access limit exists - */ - -bool_t umAccessLimitExists(char_t *url) -{ - a_assert(url && *url); - - if (dbSearchStr(didUM, UM_ACCESS_TABLENAME, UM_NAME, url, 0) < 0) { - return FALSE; - } else { - return TRUE; - } -} - -/******************************************************************************/ -/* - * umGetAccessLimit() returns the Access Method for the URL - */ - -accessMeth_t umGetAccessLimitMethod(char_t *url) -{ - int am, row; - - am = (int) AM_INVALID; - row = dbSearchStr(didUM, UM_ACCESS_TABLENAME, UM_NAME, url, 0); - - if (row >= 0) { - dbReadInt(didUM, UM_ACCESS_TABLENAME, UM_METHOD, row, &am); - } - - return (accessMeth_t) am; -} - -/******************************************************************************/ -/* - * umSetAccessLimitMethod() - set Access Method for Access Limit - */ - -int umSetAccessLimitMethod(char_t *url, accessMeth_t am) -{ - int row; - - a_assert(url && *url); - row = dbSearchStr(didUM, UM_ACCESS_TABLENAME, UM_NAME, url, 0); - - if (row >= 0) { - return dbWriteInt(didUM, UM_ACCESS_TABLENAME, UM_METHOD, row, (int) am); - } else { - return UM_ERR_NOT_FOUND; - } -} - -/******************************************************************************/ -/* - * umGetAccessLimitSecure() - returns secure switch for access limit - */ - -short umGetAccessLimitSecure(char_t *url) -{ - int secure, row; - - a_assert(url && *url); - secure = -1; - row = dbSearchStr(didUM, UM_ACCESS_TABLENAME, UM_NAME, url, 0); - - if (row >= 0) { - dbReadInt(didUM, UM_ACCESS_TABLENAME, UM_SECURE, row, &secure); - } - - return (short)secure; -} - -/******************************************************************************/ -/* - * umSetAccessLimitSecure() - sets the secure flag for the URL - */ - -int umSetAccessLimitSecure(char_t *url, short secure) -{ - int row; - - a_assert(url && *url); - row = dbSearchStr(didUM, UM_ACCESS_TABLENAME, UM_NAME, url, 0); - - if (row >= 0) { - return dbWriteInt(didUM, UM_ACCESS_TABLENAME, UM_SECURE, row, - (int)secure); - } else { - return UM_ERR_NOT_FOUND; - } -} - -/******************************************************************************/ -/* - * umGetAccessLimitGroup() - returns the user group of the access limit - */ - -char_t *umGetAccessLimitGroup(char_t *url) -{ - char_t *group; - int row; - - a_assert(url && *url); - group = NULL; - row = dbSearchStr(didUM, UM_ACCESS_TABLENAME, UM_NAME, url, 0); - - if (row >= 0) { - dbReadStr(didUM, UM_ACCESS_TABLENAME, UM_GROUP, row, &group); - } - - return group; -} - -/******************************************************************************/ -/* - * umSetAccessLimitGroup() - sets the user group for the access limit. - */ - -int umSetAccessLimitGroup(char_t *url, char_t *group) -{ - int row; - - a_assert(url && *url); - row = dbSearchStr(didUM, UM_ACCESS_TABLENAME, UM_NAME, url, 0); - - if (row >= 0) { - return dbWriteStr(didUM, UM_ACCESS_TABLENAME, UM_GROUP, row, group); - } else { - return UM_ERR_NOT_FOUND; - } -} - -/******************************************************************************/ -/* - * Returns the access limit to use for a given URL, by checking for URLs up - * the directory tree. Creates a new string that must be deleted. - */ - -char_t *umGetAccessLimit(char_t *url) -{ - char_t *urlRet, *urlCheck, *lastChar; - int len; - - a_assert(url && *url); - urlRet = NULL; - urlCheck = bstrdup(B_L, url); - a_assert(urlCheck); - len = gstrlen(urlCheck); -/* - * Scan back through URL to see if there is a "parent" access limit - */ - while (len && !urlRet) { - if (umAccessLimitExists(urlCheck)) { - urlRet = bstrdup(B_L, urlCheck); - } else { -/* - * Trim the end portion of the URL to the previous directory marker - */ - lastChar = urlCheck + len; - lastChar--; - - while ((lastChar >= urlCheck) && ((*lastChar == '/') || - (*lastChar == '\\'))) { - *lastChar = 0; - lastChar--; - } - - while ((lastChar >= urlCheck) && (*lastChar != '/') && - (*lastChar != '\\')) { - *lastChar = 0; - lastChar--; - } - - len = gstrlen(urlCheck); - } - } - bfree (B_L, urlCheck); - - return urlRet; -} - -/******************************************************************************/ -/* - * Returns the access method to use for a given URL - */ - -accessMeth_t umGetAccessMethodForURL(char_t *url) -{ - accessMeth_t amRet; - char_t *urlHavingLimit, *group; - - urlHavingLimit = umGetAccessLimit(url); - if (urlHavingLimit) { - group = umGetAccessLimitGroup(urlHavingLimit); - - if (group && *group) { - amRet = umGetGroupAccessMethod(group); - } else { - amRet = umGetAccessLimitMethod(urlHavingLimit); - } - - bfree(B_L, urlHavingLimit); - } else { - amRet = AM_FULL; - } - - return amRet; -} - -/******************************************************************************/ -/* - * Returns TRUE if user can access URL - */ - -bool_t umUserCanAccessURL(char_t *user, char_t *url) -{ - accessMeth_t amURL; - char_t *group, *usergroup, *urlHavingLimit; - short priv; - - a_assert(user && *user); - a_assert(url && *url); - -/* - * Make sure user exists - */ - if (!umUserExists(user)) { - return FALSE; - } - -/* - * Make sure user is enabled - */ - if (!umGetUserEnabled(user)) { - return FALSE; - } - -/* - * Make sure user has sufficient privileges (any will do) - */ - usergroup = umGetUserGroup(user); - priv = umGetGroupPrivilege(usergroup); - if (priv == 0) { - return FALSE; - } - -/* - * Make sure user's group is enabled - */ - if (!umGetGroupEnabled(usergroup)) { - return FALSE; - } - -/* - * The access method of the user group must not be AM_NONE - */ - if (umGetGroupAccessMethod(usergroup) == AM_NONE) { - return FALSE; - } - -/* - * Check to see if there is an Access Limit for this URL - */ - urlHavingLimit = umGetAccessLimit(url); - if (urlHavingLimit) { - amURL = umGetAccessLimitMethod(urlHavingLimit); - group = umGetAccessLimitGroup(urlHavingLimit); - bfree(B_L, urlHavingLimit); - } else { -/* - * If there isn't an access limit for the URL, user has full access - */ - return TRUE; - } - -/* - * If the access method for the URL is AM_NONE then - * the file "doesn't exist". - */ - if (amURL == AM_NONE) { - return FALSE; - } - -/* - * If Access Limit has a group specified, then the user must be a - * member of that group - */ - if (group && *group) { -#ifdef qHierarchicalAccess - /* - * If we are compiling with the hierarchical access extensions, we - * instead call the user-provided function that checks to see whether - * the current user's access level is greater than or equal to the - * access level required for this URL. - */ - return dmfCanAccess(usergroup, group); - -#else - if (usergroup && (gstrcmp(group, usergroup) != 0)) { - return FALSE; - - } -#endif - } - -/* - * Otherwise, user can access the URL - */ - return TRUE; - -} - -/******************************************************************************/ -/* - * Returns TRUE if given name has only valid chars - */ - -static bool_t umCheckName(char_t *name) -{ - a_assert(name && *name); - - if (name && *name) { - while (*name) { - if (gisspace((unsigned char)*name)) { - return FALSE; - } - - name++; - } - - return TRUE; - } - - return FALSE; -} - -/******************************************************************************/ diff --git a/cpukit/httpd/um.h b/cpukit/httpd/um.h deleted file mode 100644 index 3bf6cf1758..0000000000 --- a/cpukit/httpd/um.h +++ /dev/null @@ -1,183 +0,0 @@ -/* - * 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 ***********************************/ - -#ifndef 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(void); - -/* - * umClose() should be called before shutdown to free memory - */ -extern void umClose(void); - -/* - * 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(void); -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(void); -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(void); -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 */ - -/******************************************************************************/ diff --git a/cpukit/httpd/umui.c b/cpukit/httpd/umui.c deleted file mode 100644 index 329a76adff..0000000000 --- a/cpukit/httpd/umui.c +++ /dev/null @@ -1,641 +0,0 @@ -/* - * umui.c -- User Management GoForm Processing - * - * Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved. - * - * See the file "license.txt" for usage and redistribution license requirements - * - * $Id$ - */ - -/******************************** Description *********************************/ - -/* - * This module provides GoForm functions for User management - */ - -/********************************* Includes ***********************************/ - -#include "wsIntrn.h" -#include "um.h" - -/********************************* Defines ************************************/ - -#define NONE_OPTION T("<NONE>") -#define MSG_START T("<body><h2>") -#define MSG_END T("</h2></body>") - -/**************************** Forward Declarations ****************************/ - -static void formAddUser(webs_t wp, char_t *path, char_t *query); -static void formDeleteUser(webs_t wp, char_t *path, char_t *query); -static void formDisplayUser(webs_t wp, char_t *path, char_t *query); -static int aspGenerateUserList(int eid, webs_t wp, - int argc, char_t **argv); - -static void formAddGroup(webs_t wp, char_t *path, char_t *query); -static void formDeleteGroup(webs_t wp, char_t *path, char_t *query); -static int aspGenerateGroupList(int eid, webs_t wp, - int argc, char_t **argv); - -static void formAddAccessLimit(webs_t wp, char_t *path, char_t *query); -static void formDeleteAccessLimit(webs_t wp, char_t *path, char_t *query); -static int aspGenerateAccessLimitList(int eid, webs_t wp, - int argc, char_t **argv); - -static int aspGenerateAccessMethodList(int eid, webs_t wp, - int argc, char_t **argv); -static int aspGeneratePrivilegeList(int eid, webs_t wp, - int argc, char_t **argv); - -static void formSaveUserManagement(webs_t wp, char_t *path, char_t *query); -static void formLoadUserManagement(webs_t wp, char_t *path, char_t *query); - -static void websMsgStart(webs_t wp); -static void websMsgEnd(webs_t wp); - -/*********************************** Code *************************************/ -/* - * Set up the User Management form handlers - */ - -void formDefineUserMgmt(void) -{ - websAspDefine(T("MakeGroupList"), aspGenerateGroupList); - websAspDefine(T("MakeUserList"), aspGenerateUserList); - websAspDefine(T("MakeAccessLimitList"), aspGenerateAccessLimitList); - websAspDefine(T("MakeAccessMethodList"), aspGenerateAccessMethodList); - websAspDefine(T("MakePrivilegeList"), aspGeneratePrivilegeList); - - websFormDefine(T("AddUser"), formAddUser); - websFormDefine(T("DeleteUser"), formDeleteUser); - websFormDefine(T("DisplayUser"), formDisplayUser); - websFormDefine(T("AddGroup"), formAddGroup); - websFormDefine(T("DeleteGroup"), formDeleteGroup); - websFormDefine(T("AddAccessLimit"), formAddAccessLimit); - websFormDefine(T("DeleteAccessLimit"), formDeleteAccessLimit); - - websFormDefine(T("SaveUserManagement"), formSaveUserManagement); - websFormDefine(T("LoadUserManagement"), formLoadUserManagement); -} - -/******************************************************************************/ -/* - * Add a user - */ - -static void formAddUser(webs_t wp, char_t *path, char_t *query) -{ - char_t *userid, *pass1, *pass2, *group, *enabled, *ok; - bool_t bDisable; - int nCheck; - - a_assert(wp); - - userid = websGetVar(wp, T("user"), T("")); - pass1 = websGetVar(wp, T("password"), T("")); - pass2 = websGetVar(wp, T("passconf"), T("")); - group = websGetVar(wp, T("group"), T("")); - enabled = websGetVar(wp, T("enabled"), T("")); - ok = websGetVar(wp, T("ok"), T("")); - - websHeader(wp); - websMsgStart(wp); - - if (gstricmp(ok, T("ok")) != 0) { - websWrite(wp, T("Add User Cancelled")); - } else if (gstrcmp(pass1, pass2) != 0) { - websWrite(wp, T("Confirmation Password did not match.")); - } else { - if (enabled && *enabled && (gstrcmp(enabled, T("on")) == 0)) { - bDisable = FALSE; - } else { - bDisable = TRUE; - } - - nCheck = umAddUser(userid, pass1, group, 0, bDisable); - if (nCheck != 0) { - char_t * strError; - - switch (nCheck) { - case UM_ERR_DUPLICATE: - strError = T("User already exists."); - break; - - case UM_ERR_BAD_NAME: - strError = T("Invalid user name."); - break; - - case UM_ERR_BAD_PASSWORD: - strError = T("Invalid password."); - break; - - case UM_ERR_NOT_FOUND: - strError = T("Invalid or unselected group."); - break; - - default: - strError = T("Error writing user record."); - break; - } - - websWrite(wp, T("Unable to add user, \"%s\". %s"), - userid, strError); - } else { - websWrite(wp, T("User, \"%s\" was successfully added."), - userid); - } - } - - websMsgEnd(wp); - websFooter(wp); - websDone(wp, 200); -} - -/******************************************************************************/ -/* - * Delete a user - */ - -static void formDeleteUser(webs_t wp, char_t *path, char_t *query) -{ - char_t *userid, *ok; - - a_assert(wp); - - userid = websGetVar(wp, T("user"), T("")); - ok = websGetVar(wp, T("ok"), T("")); - - websHeader(wp); - websMsgStart(wp); - - if (gstricmp(ok, T("ok")) != 0) { - websWrite(wp, T("Delete User Cancelled")); - } else if (umUserExists(userid) == FALSE) { - websWrite(wp, T("ERROR: User \"%s\" not found"), userid); - } else if (umGetUserProtected(userid)) { - websWrite(wp, T("ERROR: User, \"%s\" is delete-protected."), userid); - } else if (umDeleteUser(userid) != 0) { - websWrite(wp, T("ERROR: Unable to delete user, \"%s\" "), userid); - } else { - websWrite(wp, T("User, \"%s\" was successfully deleted."), userid); - } - - websMsgEnd(wp); - websFooter(wp); - websDone(wp, 200); -} - -/******************************************************************************/ -/* - * Display the user info - */ - -static void formDisplayUser(webs_t wp, char_t *path, char_t *query) -{ - char_t *userid, *ok, *temp; - bool_t enabled; - - a_assert(wp); - - userid = websGetVar(wp, T("user"), T("")); - ok = websGetVar(wp, T("ok"), T("")); - - websHeader(wp); - websWrite(wp, T("<body>")); - - if (gstricmp(ok, T("ok")) != 0) { - websWrite(wp, T("Display User Cancelled")); - } else if (umUserExists(userid) == FALSE) { - websWrite(wp, T("ERROR: User <b>%s</b> not found.\n"), userid); - } else { - websWrite(wp, T("<h2>User ID: <b>%s</b></h2>\n"), userid); - temp = umGetUserGroup(userid); - websWrite(wp, T("<h3>User Group: <b>%s</b></h3>\n"), temp); - enabled = umGetUserEnabled(userid); - websWrite(wp, T("<h3>Enabled: <b>%d</b></h3>\n"), enabled); - } - - websWrite(wp, T("</body>\n")); - websFooter(wp); - websDone(wp, 200); -} - - -/******************************************************************************/ -/* - * Generate HTML to create a list box containing the users - */ - -static int aspGenerateUserList(int eid, webs_t wp, int argc, char_t **argv) -{ - char_t *userid; - int row, nBytesSent, nBytes; - - a_assert(wp); - - nBytes = websWrite(wp, - T("<SELECT NAME=\"user\" SIZE=\"3\" TITLE=\"Select a User\">")); - row = 0; - userid = umGetFirstUser(); - nBytesSent = 0; - - while (userid && (nBytes > 0)) { - nBytes = websWrite(wp, T("<OPTION VALUE=\"%s\">%s\n"), - userid, userid); - userid = umGetNextUser(userid); - nBytesSent += nBytes; - } - - nBytesSent += websWrite(wp, T("</SELECT>")); - - return nBytesSent; -} - -/******************************************************************************/ -/* - * Add a group - */ - -static void formAddGroup(webs_t wp, char_t *path, char_t *query) -{ - char_t *group, *enabled, *privilege, *method, *ok, *pChar; - int nCheck; - short priv; - accessMeth_t am; - bool_t bDisable; - - a_assert(wp); - - group = websGetVar(wp, T("group"), T("")); - method = websGetVar(wp, T("method"), T("")); - enabled = websGetVar(wp, T("enabled"), T("")); - privilege = websGetVar(wp, T("privilege"), T("")); - ok = websGetVar(wp, T("ok"), T("")); - - websHeader(wp); - websMsgStart(wp); - - if (gstricmp(ok, T("ok")) != 0) { - websWrite(wp, T("Add Group Cancelled.")); - } else if ((group == NULL) || (*group == 0)) { - websWrite(wp, T("No Group Name was entered.")); - } else if (umGroupExists(group)) { - websWrite(wp, T("ERROR: Group, \"%s\" already exists."), group); - } else { - if (privilege && *privilege) { -/* - * privilege is a mulitple <SELECT> var, and must be parsed. - * Values for these variables are space delimited. - */ - priv = 0; - for (pChar = privilege; *pChar; pChar++) { - if (*pChar == ' ') { - *pChar = '\0'; - priv |= gatoi(privilege); - *pChar = ' '; - privilege = pChar + 1; - } - } - priv |= gatoi(privilege); - } else { - priv = 0; - } - - if (method && *method) { - am = (accessMeth_t) gatoi(method); - } else { - am = AM_FULL; - } - - if (enabled && *enabled && (gstrcmp(enabled, T("on")) == 0)) { - bDisable = FALSE; - } else { - bDisable = TRUE; - } - - nCheck = umAddGroup(group, priv, am, 0, bDisable); - if (nCheck != 0) { - websWrite(wp, T("Unable to add group, \"%s\", code: %d "), - group, nCheck); - } else { - websWrite(wp, T("Group, \"%s\" was successfully added."), - group); - } - } - - websMsgEnd(wp); - websFooter(wp); - websDone(wp, 200); -} - -/******************************************************************************/ -/* - * Delete a group - */ - -static void formDeleteGroup(webs_t wp, char_t *path, char_t *query) -{ - char_t *group, *ok; - - a_assert(wp); - - group = websGetVar(wp, T("group"), T("")); - ok = websGetVar(wp, T("ok"), T("")); - - websHeader(wp); - websMsgStart(wp); - - if (gstricmp(ok, T("ok")) != 0) { - websWrite(wp, T("Delete Group Cancelled.")); - } else if ((group == NULL) || (*group == '\0')) { - websWrite(wp, T("ERROR: No group was selected.")); - } else if (umGetGroupProtected(group)) { - websWrite(wp, T("ERROR: Group, \"%s\" is delete-protected."), group); - } else if (umGetGroupInUse(group)) { - websWrite(wp, T("ERROR: Group, \"%s\" is being used."), group); - } else if (umDeleteGroup(group) != 0) { - websWrite(wp, T("ERROR: Unable to delete group, \"%s\" "), group); - } else { - websWrite(wp, T("Group, \"%s\" was successfully deleted."), group); - } - - websMsgEnd(wp); - websFooter(wp); - websDone(wp, 200); -} - -/******************************************************************************/ -/* - * Generate HTML to create a list box containing the groups - */ - -static int aspGenerateGroupList(int eid, webs_t wp, int argc, char_t **argv) -{ - char_t *group; - int row, nBytesSent, nBytes; - - a_assert(wp); - - row = 0; - nBytesSent = 0; - nBytes = websWrite(wp, - T("<SELECT NAME=\"group\" SIZE=\"3\" TITLE=\"Select a Group\">")); -/* - * Add a special "<NONE>" element to allow de-selection - */ - nBytes = websWrite(wp, T("<OPTION VALUE=\"\">[NONE]\n")); - - group = umGetFirstGroup(); - while (group && (nBytes > 0)) { - nBytes = websWrite(wp, T("<OPTION VALUE=\"%s\">%s\n"), group, group); - group = umGetNextGroup(group); - nBytesSent += nBytes; - } - - nBytesSent += websWrite(wp, T("</SELECT>")); - - return nBytesSent; -} - -/******************************************************************************/ -/* - * Add an access limit - */ - -static void formAddAccessLimit(webs_t wp, char_t *path, char_t *query) -{ - char_t *url, *method, *group, *secure, *ok; - int nCheck; - accessMeth_t am; - short nSecure; - - a_assert(wp); - - url = websGetVar(wp, T("url"), T("")); - group = websGetVar(wp, T("group"), T("")); - method = websGetVar(wp, T("method"), T("")); - secure = websGetVar(wp, T("secure"), T("")); - ok = websGetVar(wp, T("ok"), T("")); - - websHeader(wp); - websMsgStart(wp); - - if (gstricmp(ok, T("ok")) != 0) { - websWrite(wp, T("Add Access Limit Cancelled.")); - } else if ((url == NULL) || (*url == 0)) { - websWrite(wp, T("ERROR: No URL was entered.")); - } else if (umAccessLimitExists(url)) { - websWrite(wp, T("ERROR: An Access Limit for [%s] already exists."), - url); - } else { - if (method && *method) { - am = (accessMeth_t) gatoi(method); - } else { - am = AM_FULL; - } - - if (secure && *secure) { - nSecure = (short) gatoi(secure); - } else { - nSecure = 0; - } - - nCheck = umAddAccessLimit(url, am, nSecure, group); - if (nCheck != 0) { - websWrite(wp, T("Unable to add Access Limit for [%s]"), url); - } else { - websWrite(wp, T("Access limit for [%s], was successfully added."), - url); - } - } - - websMsgEnd(wp); - websFooter(wp); - websDone(wp, 200); -} - -/******************************************************************************/ -/* - * Delete an Access Limit - */ - -static void formDeleteAccessLimit(webs_t wp, char_t *path, char_t *query) -{ - char_t *url, *ok; - - a_assert(wp); - - url = websGetVar(wp, T("url"), T("")); - ok = websGetVar(wp, T("ok"), T("")); - - websHeader(wp); - websMsgStart(wp); - - if (gstricmp(ok, T("ok")) != 0) { - websWrite(wp, T("Delete Access Limit Cancelled")); - } else if (umDeleteAccessLimit(url) != 0) { - websWrite(wp, T("ERROR: Unable to delete Access Limit for [%s]"), - url); - } else { - websWrite(wp, T("Access Limit for [%s], was successfully deleted."), - url); - } - - websMsgEnd(wp); - websFooter(wp); - websDone(wp, 200); -} - -/******************************************************************************/ -/* - * Generate HTML to create a list box containing the access limits - */ - -static int aspGenerateAccessLimitList(int eid, webs_t wp, - int argc, char_t **argv) -{ - char_t *url; - int row, nBytesSent, nBytes; - - a_assert(wp); - - row = nBytesSent = 0; - url = umGetFirstAccessLimit(); - nBytes = websWrite(wp, - T("<SELECT NAME=\"url\" SIZE=\"3\" TITLE=\"Select a URL\">")); - - while (url && (nBytes > 0)) { - nBytes = websWrite(wp, T("<OPTION VALUE=\"%s\">%s\n"), url, url); - url = umGetNextAccessLimit(url); - nBytesSent += nBytes; - } - - nBytesSent += websWrite(wp, T("</SELECT>")); - - return nBytesSent; -} - -/******************************************************************************/ -/* - * Generate HTML to create a list box containing the access methods - */ - -static int aspGenerateAccessMethodList(int eid, webs_t wp, - int argc, char_t **argv) -{ - int nBytes; - - a_assert(wp); - - nBytes = websWrite(wp, - T("<SELECT NAME=\"method\" SIZE=\"3\" TITLE=\"Select a Method\">")); - nBytes += websWrite(wp, T("<OPTION VALUE=\"%d\">FULL ACCESS\n"), - AM_FULL); - nBytes += websWrite(wp, T("<OPTION VALUE=\"%d\">BASIC ACCESS\n"), - AM_BASIC); - nBytes += websWrite(wp, T("<OPTION VALUE=\"%d\" SELECTED>DIGEST ACCESS\n"), - AM_DIGEST); - nBytes += websWrite(wp, T("<OPTION VALUE=\"%d\">NO ACCESS\n"), - AM_NONE); - nBytes += websWrite(wp, T("</SELECT>")); - - return nBytes; -} -/******************************************************************************/ -/* - * Generate HTML to create a list box containing privileges - */ - -static int aspGeneratePrivilegeList(int eid, webs_t wp, - int argc, char_t **argv) -{ - int nBytes; - - a_assert(wp); - - nBytes = websWrite(wp, T("<SELECT NAME=\"privilege\" SIZE=\"3\" ")); - nBytes += websWrite(wp, T("MULTIPLE TITLE=\"Choose Privileges\">")); - nBytes += websWrite(wp, T("<OPTION VALUE=\"%d\">READ\n"), PRIV_READ); - nBytes += websWrite(wp, T("<OPTION VALUE=\"%d\">EXECUTE\n"), PRIV_WRITE); - nBytes += websWrite(wp, T("<OPTION VALUE=\"%d\">ADMINISTRATE\n"), - PRIV_ADMIN); - nBytes += websWrite(wp, T("</SELECT>")); - - return nBytes; -} - -/******************************************************************************/ -/* - * Save the user management configuration to a file - */ - -static void formSaveUserManagement(webs_t wp, char_t *path, char_t *query) -{ - char_t *ok; - - a_assert(wp); - - ok = websGetVar(wp, T("ok"), T("")); - - websHeader(wp); - websMsgStart(wp); - - if (gstricmp(ok, T("ok")) != 0) { - websWrite(wp, T("Save Cancelled.")); - } else if (umCommit(NULL) != 0) { - websWrite(wp, T("ERROR: Unable to save user configuration.")); - } else { - websWrite(wp, T("User configuration was saved successfully.")); - } - - websMsgEnd(wp); - websFooter(wp); - websDone(wp, 200); -} - -/******************************************************************************/ -/* - * Load the user management configuration from a file - */ - -static void formLoadUserManagement(webs_t wp, char_t *path, char_t *query) -{ - char_t *ok; - - a_assert(wp); - - ok = websGetVar(wp, T("ok"), T("")); - - websHeader(wp); - websMsgStart(wp); - - if (gstricmp(ok, T("ok")) != 0) { - websWrite(wp, T("Load Cancelled.")); - } else if (umRestore(NULL) != 0) { - websWrite(wp, T("ERROR: Unable to load user configuration.")); - } else { - websWrite(wp, T("User configuration was re-loaded successfully.")); - } - - websMsgEnd(wp); - websFooter(wp); - websDone(wp, 200); -} - -/******************************************************************************/ -/* - * Message start and end convenience functions - */ - -static void websMsgStart(webs_t wp) -{ - websWrite(wp, MSG_START); -} - -static void websMsgEnd(webs_t wp) -{ - websWrite(wp, MSG_END); -} - -/******************************************************************************/ diff --git a/cpukit/httpd/url.c b/cpukit/httpd/url.c deleted file mode 100644 index da99f3f78a..0000000000 --- a/cpukit/httpd/url.c +++ /dev/null @@ -1,212 +0,0 @@ -/* - * url.c -- Parse URLs - * - * Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved. - * - * See the file "license.txt" for usage and redistribution license requirements - * - * $Id$ - */ - -/******************************** Description *********************************/ - -/* - * This module parses URLs into their components. - */ - -/********************************* Includes ***********************************/ - -#include "wsIntrn.h" - -/********************************* Statics ************************************/ -/* - * htmExt is declared in this way to avoid a Linux and Solaris segmentation - * fault when a constant string is passed to strlower which could change its - * argument. - */ - -char_t htmExt[] = T(".htm"); - - -/*********************************** Code *************************************/ -/* - * Return the mime type for the given URL given a URL. - * The caller supplies the buffer to hold the result. - * charCnt is the number of characters the buffer will hold, ascii or UNICODE. - */ - -char_t *websUrlType(char_t *url, char_t *buf, int charCnt) -{ - sym_t *sp; - char_t *ext, *parsebuf; - - a_assert(url && *url); - a_assert(buf && charCnt > 0); - - if (url == NULL || *url == '\0') { - gstrcpy(buf, T("text/plain")); - return buf; - } - if (websUrlParse(url, &parsebuf, NULL, NULL, NULL, NULL, NULL, - NULL, &ext) < 0) { - gstrcpy(buf, T("text/plain")); - return buf; - } - strlower(ext); - -/* - * Lookup the mime type symbol table to find the relevant content type - */ - if ((sp = symLookup(websMime, ext)) != NULL) { - gstrncpy(buf, sp->content.value.string, charCnt); - } else { - gstrcpy(buf, T("text/plain")); - } - bfree(B_L, parsebuf); - return buf; -} - -/******************************************************************************/ -/* - * Parse the URL. A buffer is allocated to store the parsed URL in *pbuf. - * This must be freed by the caller. NOTE: tag is not yet fully supported. - */ - -int websUrlParse(char_t *url, char_t **pbuf, char_t **phost, char_t **ppath, - char_t **pport, char_t **pquery, char_t **pproto, char_t **ptag, - char_t **pext) -{ - char_t *tok, *cp, *host, *path, *port, *proto, *tag, *query, *ext; - char_t *last_delim, *hostbuf, *portbuf, *buf; - int c, len, ulen; - - a_assert(url); - a_assert(pbuf); - - ulen = gstrlen(url); -/* - * 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. - */ - len = ulen * 2 + MAX_PORT_LEN + 3; - if ((buf = balloc(B_L, len * sizeof(char_t))) == NULL) { - return -1; - } - portbuf = &buf[len - MAX_PORT_LEN - 1]; - hostbuf = &buf[ulen+1]; - gstrcpy(buf, url); - url = buf; - -/* - * Convert the current listen port to a string. We use this if the URL has - * no explicit port setting - */ - stritoa(websGetPort(), portbuf, MAX_PORT_LEN); - port = portbuf; - path = T("/"); - proto = T("http"); - host = T("localhost"); - query = T(""); - ext = htmExt; - tag = T(""); - - if (gstrncmp(url, T("http://"), 7) == 0) { - tok = &url[7]; - tok[-3] = '\0'; - proto = url; - host = tok; - for (cp = tok; *cp; cp++) { - if (*cp == '/') { - break; - } - if (*cp == ':') { - *cp++ = '\0'; - port = cp; - tok = cp; - } - } - if ((cp = gstrchr(tok, '/')) != NULL) { -/* - * If a full URL is supplied, we need to copy the host and port - * portions into static buffers. - */ - c = *cp; - *cp = '\0'; - gstrncpy(hostbuf, host, ulen); - gstrncpy(portbuf, port, MAX_PORT_LEN); - *cp = c; - host = hostbuf; - port = portbuf; - path = cp; - tok = cp; - } - - } else { - path = url; - tok = url; - } - -/* - * Parse the query string - */ - 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; - } - } - -/* - * Only do the following if asked for the extension - */ - if (pext) { - if ((cp = gstrrchr(path, '.')) != NULL) { - if ((last_delim = gstrrchr(path, '/')) != NULL) { - if (last_delim > cp) { - ext = htmExt; - } else { - ext = cp; - } - } else { - ext = cp; - } - } else { - if (path[gstrlen(path) - 1] == '/') { - ext = htmExt; - } - } - } - -/* - * Pass back the fields requested (if not NULL) - */ - if (phost) - *phost = host; - if (ppath) - *ppath = path; - if (pport) - *pport = port; - if (pproto) - *pproto = proto; - if (pquery) - *pquery = query; - if (ptag) - *ptag = tag; - if (pext) - *pext = ext; - *pbuf = buf; - return 0; -} - -/******************************************************************************/ diff --git a/cpukit/httpd/value.c b/cpukit/httpd/value.c deleted file mode 100644 index ac21ec6afe..0000000000 --- a/cpukit/httpd/value.c +++ /dev/null @@ -1,1213 +0,0 @@ -/* - * value.c -- Generic type (holds all types) - * - * Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved. - * - * $Id$ - */ - -/******************************** Description *********************************/ - -/* - * This module provides a generic type that can hold all possible types. - * It is designed to provide maximum effeciency. - */ - -/********************************* Includes ***********************************/ - -#ifdef UEMF - #include "uemf.h" -#else - #include "basic/basicInternal.h" -#endif - -/*********************************** Locals ***********************************/ -#ifndef UEMF -static value_t value_null; /* All zeros */ - -/***************************** Forward Declarations ***************************/ - -static void coerce_types(value_t* v1, value_t* v2); -static int value_to_integer(value_t* vp); -#endif /*!UEMF*/ -/*********************************** Code *************************************/ -/* - * Initialize a integer value. - */ - -value_t valueInteger(long value) -{ - value_t v; - - memset(&v, 0x0, sizeof(v)); - v.valid = 1; - v.type = integer; - v.value.integer = value; - return v; -} - -/******************************************************************************/ -/* - * Initialize a string value. - */ - -value_t valueString(char_t* value, int flags) -{ - value_t v; - - memset(&v, 0x0, sizeof(v)); - v.valid = 1; - v.type = string; - if (flags & VALUE_ALLOCATE) { - v.allocated = 1; - v.value.string = gstrdup(B_L, value); - } else { - v.allocated = 0; - v.value.string = value; - } - return v; -} - -/******************************************************************************/ -/* - * Free any storage allocated for a value. - */ - -void valueFree(value_t* v) -{ - if (v->valid && v->allocated && v->type == string && - v->value.string != NULL) { - bfree(B_L, v->value.string); - } -#ifndef UEMF - if (v->valid && v->type == symbol && v->value.symbol.data != NULL && - v->value.symbol.freeCb !=NULL) { - v->value.symbol.freeCb(v->value.symbol.data); - } -#endif - v->type = undefined; - v->valid = 0; - v->allocated = 0; -} - -#ifndef UEMF - -/******************************************************************************/ -/* - * Initialize an invalid value. - */ - -value_t valueInvalid() -{ - value_t v; - v.valid = 0; - v.type = undefined; - return v; -} - -/******************************************************************************/ -/* - * Initialize a flag value. - */ - -value_t valueBool(int value) -{ - value_t v; - - memset(&v, 0x0, sizeof(v)); - v.type = flag; - v.valid = 1; - v.value.flag = (char) value; - return v; -} - -/******************************************************************************/ -/* - * Initialize a byteint value. - */ - -value_t valueByteint(char value) -{ - value_t v; - - memset(&v, 0x0, sizeof(v)); - v.valid = 1; - v.type = byteint; - v.value.byteint = value; - return v; -} - -/******************************************************************************/ -/* - * Initialize a shortint value. - */ - -value_t valueShortint(short value) -{ - value_t v; - - memset(&v, 0x0, sizeof(v)); - v.valid = 1; - v.type = shortint; - v.value.shortint = value; - return v; -} - -#ifdef FLOATING_POINT_SUPPORT -/******************************************************************************/ -/* - * Initialize a floating value. - */ - -value_t valueFloating(double value) -{ - value_t v; - - memset(&v, 0x0, sizeof(v)); - v.valid = 1; - v.type = floating; - v.value.floating = value; - return v; -} -#endif /* FLOATING_POINT_SUPPORT */ - -/******************************************************************************/ -/* - * Initialize a big value. - */ - -value_t valueBig(long high_word, long low_word) -{ - value_t v; - - memset(&v, 0x0, sizeof(v)); - v.valid = 1; - v.type = big; - v.value.big[BLOW] = low_word; - v.value.big[BHIGH] = high_word; - return v; -} - -/******************************************************************************/ -/* - * Initialize a hex value. - */ - -value_t valueHex(int value) -{ - value_t v; - - memset(&v, 0x0, sizeof(v)); - v.valid = 1; - v.type = hex; - v.value.integer = value; - return v; -} - -/******************************************************************************/ -/* - * Initialize a octal value. - */ - -value_t valueOctal(int value) -{ - value_t v; - - memset(&v, 0x0, sizeof(v)); - v.valid = 1; - v.type = octal; - v.value.integer = value; - return v; -} - -/******************************************************************************/ -/* - * Initialize a percent value. - */ - -value_t valuePercent(int value) -{ - value_t v; - - memset(&v, 0x0, sizeof(v)); - v.valid = 1; - v.type = percent; - v.value.percent = (char) value; - return v; -} - -/******************************************************************************/ -/* - * Initialize an byte array. Note: no allocation, just store the ptr - */ - -value_t valueBytes(char* value, int flags) -{ - value_t v; - - memset(&v, 0x0, sizeof(v)); - v.valid = 1; - v.type = bytes; - if (flags & VALUE_ALLOCATE) { - v.allocated = 1; - v.value.bytes = bstrdupA(B_L, value); - } else { - v.allocated = 0; - v.value.bytes = value; - } - return v; -} - -/******************************************************************************/ -/* - * Initialize a symbol value. - * Value parameter can hold a pointer to any type of value - * Free parameter can be NULL, or a function pointer to a function that will - * free the value - */ - -value_t valueSymbol(void *value, freeCallback freeCb) -{ - value_t v; - - memset(&v, 0x0, sizeof(v)); - v.valid = 1; - v.type = symbol; - v.value.symbol.data = value; - v.value.symbol.freeCb = freeCb; - return v; -} - -/******************************************************************************/ -/* - * Initialize an error message value. - */ - -value_t valueErrmsg(char_t* value) -{ - value_t v; - - memset(&v, 0x0, sizeof(v)); - v.valid = 1; - v.type = errmsg; - v.value.errmsg = value; - return v; -} - -/******************************************************************************/ -/* - * Copy a value. If the type is 'string' then allocate another string. - * Note: we allow the copy of a null value. - */ - -value_t valueCopy(value_t v2) -{ - value_t v1; - - v1 = v2; - if (v2.valid && v2.type == string && v2.value.string != NULL) { - v1.value.string = gstrdup(B_L, v2.value.string); - v1.allocated = 1; - } - return v1; -} - - -/******************************************************************************/ -/* - * Add a value. - */ - -value_t valueAdd(value_t v1, value_t v2) -{ - value_t v; - - a_assert(v1.valid); - a_assert(v2.valid); - - memset(&v, 0x0, sizeof(v)); - v.valid = 1; - - if (v1.type != v2.type) - coerce_types(&v1, &v2); - - switch (v1.type) { - default: - case string: - case bytes: - a_assert(0); - break; - -#ifdef FLOATING_POINT_SUPPORT - case floating: - v1.value.floating += v2.value.floating; - return v1; -#endif - - case flag: - v1.value.bool |= v2.value.flag; - return v1; - - case byteint: - case percent: - v1.value.byteint += v2.value.byteint; - return v1; - - case shortint: - v1.value.shortint += v2.value.shortint; - return v1; - - case hex: - case integer: - case octal: - v1.value.integer += v2.value.integer; - return v1; - - case big: - v.type = big; - badd(v.value.big, v1.value.big, v2.value.big); - return v; - } - - return v1; -} - - -/******************************************************************************/ -/* - * Subtract a value. - */ - -value_t valueSub(value_t v1, value_t v2) -{ - value_t v; - - a_assert(v1.valid); - a_assert(v2.valid); - - memset(&v, 0x0, sizeof(v)); - v.valid = 1; - - if (v1.type != v2.type) - coerce_types(&v1, &v2); - switch (v1.type) { - default: - a_assert(0); - break; - -#ifdef FLOATING_POINT_SUPPORT - case floating: - v1.value.floating -= v2.value.floating; - return v1; -#endif - - case flag: - v1.value.flag &= v2.value.flag; - return v1; - - case byteint: - case percent: - v1.value.byteint -= v2.value.byteint; - return v1; - - case shortint: - v1.value.shortint -= v2.value.shortint; - return v1; - - case hex: - case integer: - case octal: - v1.value.integer -= v2.value.integer; - return v1; - - case big: - v.type = big; - bsub(v.value.big, v1.value.big, v2.value.big); - return v; - } - - return v1; -} - - -/******************************************************************************/ -/* - * Multiply a value. - */ - -value_t valueMul(value_t v1, value_t v2) -{ - value_t v; - - a_assert(v1.valid); - a_assert(v2.valid); - - memset(&v, 0x0, sizeof(v)); - v.valid = 1; - - if (v1.type != v2.type) - coerce_types(&v1, &v2); - switch (v1.type) { - default: - a_assert(0); - break; - - case flag: - a_assert(v1.type != flag); - break; - -#ifdef FLOATING_POINT_SUPPORT - case floating: - v1.value.floating *= v2.value.floating; - return v1; -#endif - - case byteint: - case percent: - v1.value.byteint *= v2.value.byteint; - return v1; - - case shortint: - v1.value.shortint *= v2.value.shortint; - return v1; - - case hex: - case integer: - case octal: - v1.value.integer *= v2.value.integer; - return v1; - - case big: - v.type = big; - bmul(v.value.big, v1.value.big, v2.value.big); - return v; - } - - return v1; -} - - -/******************************************************************************/ -/* - * Divide a value. - */ - -value_t valueDiv(value_t v1, value_t v2) -{ - value_t v; - - a_assert(v1.valid); - a_assert(v2.valid); - - memset(&v, 0x0, sizeof(v)); - v.valid = 1; - - if (v1.type != v2.type) - coerce_types(&v1, &v2); - switch (v1.type) { - default: - a_assert(0); - break; - - case flag: - a_assert(v1.type != flag); - break; - -#ifdef FLOATING_POINT_SUPPORT - case floating: - v1.value.floating /= v2.value.floating; - return v1; -#endif - - case byteint: - case percent: - v1.value.byteint /= v2.value.byteint; - return v1; - - case shortint: - v1.value.shortint /= v2.value.shortint; - return v1; - - case hex: - case integer: - case octal: - v1.value.integer /= v2.value.integer; - return v1; - - case big: - v.type = big; - bdiv(v.value.big, v1.value.big, v2.value.big); - return v; - } - - return v1; -} - - -/******************************************************************************/ -/* - * Compare a value. - */ - -int valueCmp(value_t v1, value_t v2) -{ - a_assert(v1.valid); - a_assert(v2.valid); - - if (v1.type != v2.type) - coerce_types(&v1, &v2); - if (v1.type != v2.type) { -/* - * Make v2 == v1 - */ - a_assert(v1.type == v2.type); - v2 = v1; - return 0; - } - switch (v1.type) { - case string: - if (v1.value.string == NULL && v2.value.string == NULL) { - return 0; - } else if (v1.value.string == NULL) { - return -1; - } else if (v2.value.string == NULL) { - return 1; - } else { - return gstrcmp(v1.value.string, v2.value.string); - } - /* Nobody here */ - - case flag: - if (v1.value.flag < v2.value.flag) - return -1; - else if (v1.value.flag == v2.value.flag) - return 0; - else return 1; - -#ifdef FLOATING_POINT_SUPPORT - case floating: - if (v1.value.floating < v2.value.floating) - return -1; - else if (v1.value.floating == v2.value.floating) - return 0; - else return 1; -#endif - - case byteint: - case percent: - if (v1.value.byteint < v2.value.byteint) - return -1; - else if (v1.value.byteint == v2.value.byteint) - return 0; - else return 1; - - case shortint: - if (v1.value.shortint < v2.value.shortint) - return -1; - else if (v1.value.shortint == v2.value.shortint) - return 0; - else return 1; - - case hex: - case integer: - case octal: - if (v1.value.integer < v2.value.integer) - return -1; - else if (v1.value.integer == v2.value.integer) - return 0; - else return 1; - - case big: - return bcompare(v1.value.big, v2.value.big); - - default: - a_assert(0); - return 0; - } -} - - -/******************************************************************************/ -/* - * If type mismatch, then coerce types to big. - * Note: Known bug, casting of negative bigs to floats doesn't work. - */ - -static void coerce_types(register value_t* v1, register value_t* v2) -{ -#ifdef FLOATING_POINT_SUPPORT - if (v1->type == floating) { - v2->type = floating; - v2->value.floating = (double) v2->value.integer; - if (v2->type == big) - v2->value.floating = (double) v2->value.big[BLOW] + - (double) v2->value.big[BHIGH] * (double) MAXINT; - - } else if (v2->type == floating) { - v1->type = floating; - v1->value.floating = (double) v1->value.integer; - if (v1->type == big) - v1->value.floating = (double) v1->value.big[BLOW] + - (double) v1->value.big[BHIGH] * (double) MAXINT; - - } else if (v1->type == big) { -#else - if (v1->type == big) { -#endif /* FLOATING_POINT_SUPPORT */ - v2->value.big[BLOW] = value_to_integer(v2); - if (valueNegative(v2)) - v2->value.big[BHIGH] = -1; - else - v2->value.big[BHIGH] = 0; - v2->type = big; - - } else if (v2->type == big) { - if (valueNegative(v1)) - v1->value.big[BHIGH] = -1; - else - v1->value.big[BHIGH] = 0; - v1->value.big[BLOW] = value_to_integer(v1); - v1->type = big; - - - } else if (v1->type == integer) { - v2->value.integer = value_to_integer(v2); - v2->type = integer; - - } else if (v2->type == integer) { - v1->value.integer = value_to_integer(v1); - v1->type = integer; - - } else if (v1->type != integer) { - v2->type = v1->type; - - } else if (v2->type != integer) { - v1->type = v2->type; - - } - a_assert(v1->type == v2->type); -} - - -/******************************************************************************/ -/* - * Return true if the value is numeric and negative. Otherwise return 0. - */ - -int valueNegative(value_t* vp) -{ - switch (vp->type) { - default: - case string: - case bytes: - return 0; - -#ifdef FLOATING_POINT_SUPPORT - case floating: - if (vp->value.floating < 0) - return 1; - return 0; -#endif - - case flag: - if ((signed char)vp->value.flag < 0) - return 1; - return 0; - - case byteint: - case percent: - if ((signed char)vp->value.byteint < 0) - return 1; - return 0; - - case shortint: - if (vp->value.shortint < 0) - return 1; - return 0; - - case hex: - case integer: - case octal: - if (vp->value.integer < 0) - return 1; - return 0; - - case big: - if (vp->value.big[BHIGH] < 0) - return 1; - return 0; - } -} - -/******************************************************************************/ -/* - * Return true if the value is numeric and zero. Otherwise return 0. - */ - -int valueZero(value_t* vp) -{ - switch (vp->type) { - default: - case string: - case bytes: - return 0; - -#ifdef FLOATING_POINT_SUPPORT - case floating: - if (vp->value.floating == 0) - return 1; - return 0; -#endif - - case flag: - if (vp->value.flag == 0) - return 1; - return 0; - - case byteint: - case percent: - if (vp->value.byteint == 0) - return 1; - return 0; - - case shortint: - if (vp->value.shortint == 0) - return 1; - return 0; - - case hex: - case integer: - case octal: - if (vp->value.integer == 0) - return 1; - return 0; - - case big: - if (vp->value.big[BHIGH] == 0 && vp->value.big[BLOW] == 0) - return 1; - return 0; - } -} - - -/******************************************************************************/ -/* - * Cast a value to an integer. Cannot be called for floating, non-numerics - * or bigs. - */ - -static int value_to_integer(value_t* vp) -{ - switch (vp->type) { - default: - case string: - case bytes: - case big: -#ifdef FLOATING_POINT_SUPPORT - case floating: - a_assert(0); - return -1; -#endif - - case flag: - return (int) vp->value.flag; - - case byteint: - case percent: - return (int) vp->value.byteint; - - case shortint: - return (int) vp->value.shortint; - - case hex: - case integer: - case octal: - return (int) vp->value.integer; - } -} - - -/******************************************************************************/ -/* - * Convert a value to a text based representation of its value - */ - -void valueSprintf(char_t** out, int size, char_t* fmt, value_t vp) -{ - char_t *src, *dst, *tmp, *dst_start; - - a_assert(out); - - *out = NULL; - - if (! vp.valid) { - *out = bstrdup(B_L, T("Invalid")); - return; - } - - switch (vp.type) { - case flag: - if (fmt == NULL || *fmt == '\0') { - *out = bstrdup(B_L, (vp.value.flag) ? T("true") : T("false")); - } else { - fmtAlloc(out, size, fmt, (vp.value.flag) ? T("true") : T("false")); - } - break; - -#ifdef FLOATING_POINT_SUPPORT - case floating: - if (fmt == NULL || *fmt == '\0') { - fmtAlloc(out, size, T("%f"), vp.value.floating); - } else { - fmtAlloc(out, size, fmt, vp.value.floating); - } - break; -#endif - - case hex: - if (fmt == NULL || *fmt == '\0') { - fmtAlloc(out, size, T("0x%lx"), vp.value.hex); - } else { - fmtAlloc(out, size, fmt, vp.value.hex); - } - break; - - case big: - if (*out == NULL) { - *out = btoa(vp.value.big, NULL, 0); - } else { - btoa(vp.value.big, *out, size); - } - break; - - case integer: - if (fmt == NULL || *fmt == '\0') { - fmtAlloc(out, size, T("%ld"), vp.value.integer); - } else { - fmtAlloc(out, size, fmt, vp.value.integer); - } - break; - - case octal: - if (fmt == NULL || *fmt == '\0') { - fmtAlloc(out, size, T("0%lo"), vp.value.octal); - } else { - fmtAlloc(out, size, fmt, vp.value.octal); - } - break; - - case percent: - if (fmt == NULL || *fmt == '\0') { - fmtAlloc(out, size, T("%d%%"), vp.value.percent); - } else { - fmtAlloc(out, size, fmt, vp.value.percent); - } - break; - - case byteint: - if (fmt == NULL || *fmt == '\0') { - fmtAlloc(out, size, T("%d"), (int) vp.value.byteint); - } else { - fmtAlloc(out, size, fmt, (int) vp.value.byteint); - } - break; - - case shortint: - if (fmt == NULL || *fmt == '\0') { - fmtAlloc(out, size, T("%d"), (int) vp.value.shortint); - } else { - fmtAlloc(out, size, fmt, (int) vp.value.shortint); - } - break; - - case string: - case errmsg: - src = vp.value.string; - - if (src == NULL) { - *out = bstrdup(B_L, T("NULL")); - } else if (fmt && *fmt) { - fmtAlloc(out, size, fmt, src); - - } else { - - *out = balloc(B_L, size); - dst_start = dst = *out; - for (; *src != '\0'; src++) { - if (dst >= &dst_start[VALUE_MAX_STRING - 5]) - break; - switch (*src) { - case '\a': *dst++ = '\\'; *dst++ = 'a'; break; - case '\b': *dst++ = '\\'; *dst++ = 'b'; break; - case '\f': *dst++ = '\\'; *dst++ = 'f'; break; - case '\n': *dst++ = '\\'; *dst++ = 'n'; break; - case '\r': *dst++ = '\\'; *dst++ = 'r'; break; - case '\t': *dst++ = '\\'; *dst++ = 't'; break; - case '\v': *dst++ = '\\'; *dst++ = 'v'; break; - case '\\': *dst++ = '\\'; *dst++ = '\\'; break; - case '"': *dst++ = '\\'; *dst++ = '\"'; break; - default: - if (gisprint(*src)) { - *dst++ = *src; - } else { - fmtAlloc(&tmp, size, T("\\x%02x"), - (unsigned int) *src); - gstrcpy(dst, tmp); - bfreeSafe(B_L, tmp); - dst += 4; - } - break; - } - } - *dst++ = '\0'; - } - break; - -#ifdef UNUSED - case bytes: - asrc = vp.value.bytes; - - if (asrc == NULL) { - *out = bstrdup(B_L, T("NULL")); - - } else if (fmt && *fmt) { - fmtAlloc(out, size, fmt, asrc); - - } else { - - dst_start = dst; - for (; *asrc != '\0'; asrc++) { - if (dst >= &dst_start[VALUE_MAX_STRING - 5]) - break; - switch (*asrc) { - case '\a': *dst++ = '\\'; *dst++ = 'a'; break; - case '\b': *dst++ = '\\'; *dst++ = 'b'; break; - case '\f': *dst++ = '\\'; *dst++ = 'f'; break; - case '\n': *dst++ = '\\'; *dst++ = 'n'; break; - case '\r': *dst++ = '\\'; *dst++ = 'r'; break; - case '\t': *dst++ = '\\'; *dst++ = 't'; break; - case '\v': *dst++ = '\\'; *dst++ = 'v'; break; - case '\\': *dst++ = '\\'; *dst++ = '\\'; break; - case '"': *dst++ = '\\'; *dst++ = '\"'; break; - default: - if (gisprint(*asrc)) { - *dst++ = *asrc; - } else { - fmtAlloc(dst, size, - T("\\x%02x"), (unsigned int) *asrc); - dst += 4; - } - break; - } - } - *dst++ = '\0'; - } - break; -#endif - - default: - a_assert(0); - } -} - -/******************************************************************************/ -/* - * Print a value to the named file descriptor - */ - -void valueFprintf(FILE* fp, char_t* fmt, value_t vp) -{ - char_t *buf; - - buf = NULL; - valueSprintf(&buf, VALUE_MAX_STRING, fmt, vp); - gfputs(buf, fp); - bfreeSafe(B_L, buf); - fflush(fp); -} - -/******************************************************************************/ -/* - * Ascii to value conversion - */ - -value_t valueAtov(char_t* s, int pref_type) -{ - vtype_t type; - value_t v; - long tmp[2], tmp2[2], base[2]; - int i, len, num; - - a_assert(0 <= pref_type && pref_type < 99); /* Sanity check */ - a_assert(s); - - v = value_null; - if (s == NULL) { - return value_null; - } - - base[BLOW] = 10; - base[BHIGH] = 0; - len = gstrlen(s); - -/* - * Determine the value type - */ - type = undefined; - if (pref_type <= 0) { - if (gisdigit(*s)) { - base[BHIGH] = 0; - if (s[len - 1] == '%') { - type = percent; - len --; - base[BLOW] = 10; - } else if (*s == '0') { - if (s[1] == 'x') { - type = hex; - s += 2; - len -= 2; - base[BLOW] = 16; - } else if (s[1] == '\0') { - type = integer; - base[BLOW] = 10; - } else { - type = octal; - s++; - len--; - base[BLOW] = 8; - } - } else { - type = integer; - base[BLOW] = 10; - } - - } else { - if (gstrcmp(s, T("true")) == 0 || gstrcmp(s, T("false")) == 0) { - type = flag; - } else if (*s == '\'' && s[len - 1] == '\'') { - type = string; - s++; - len -= 2; - } else if (*s == '\"' && s[len - 1] == '\"') { - type = string; - s++; - len -= 2; - } else { - type = string; - } - } - v.type = type; - - } else - v.type = pref_type; - v.valid = 1; - -/* - * Do the conversion. Always use big arithmetic - */ - switch (v.type) { - case hex: - if (!isdigit(s[0])) { - if (gtolower(s[0]) >= 'a' || gtolower(s[0]) <= 'f') { - v.value.big[BLOW] = 10 + gtolower(s[0]) - 'a'; - } else { - v.value.big[BLOW] = 0; - } - } else { - v.value.big[BLOW] = s[0] - '0'; - } - v.value.big[BHIGH] = 0; - for (i = 1; i < len; i++) { - if (!isdigit(s[i])) { - if (gtolower(s[i]) < 'a' || gtolower(s[i]) > 'f') { - break; - } - num = 10 + gtolower(s[i]) - 'a'; - } else { - num = s[i] - '0'; - } - bmul(tmp, v.value.big, base); - binit(tmp2, 0, num); - badd(v.value.big, tmp, tmp2); - } - v.value.hex = v.value.big[BLOW]; - break; - - case shortint: - case byteint: - case integer: - case percent: - case octal: - case big: - v.value.big[BHIGH] = 0; - if (gisdigit(s[0])) - v.value.big[BLOW] = s[0] - '0'; - else - v.value.big[BLOW] = 0; - for (i = 1; i < len && gisdigit(s[i]); i++) { - bmul(tmp, v.value.big, base); - binit(tmp2, 0, s[i] - '0'); - badd(v.value.big, tmp, tmp2); - } - switch (v.type) { - case shortint: - v.value.shortint = (short) v.value.big[BLOW]; - break; - case byteint: - v.value.byteint = (char) v.value.big[BLOW]; - break; - case integer: - v.value.integer = (int) v.value.big[BLOW]; - break; - case percent: - v.value.percent = (char) v.value.big[BLOW]; - break; - case octal: - v.value.octal = (int) v.value.big[BLOW]; - break; - default: - break; - } - break; - -#ifdef FLOATING_POINT_SUPPORT - case floating: - gsscanf(s, T("%f"), &v.value.floating); - break; -#endif - - case flag: - if (*s == 't') - v.value.flag = 1; - else v.value.flag = 0; - break; - - case string: -/* - * Note this always ballocs a string - */ - v = valueString(s, VALUE_ALLOCATE); - break; - - case bytes: - v = valueBytes((char*) s, VALUE_ALLOCATE); - break; - -#ifdef UNUSED - case literal: - v = value_literal(bstrdup(B_L, s)); - v.value.literal[len] = '\0'; - break; -#endif - - case undefined: - case symbol: - default: - v.valid = 0; - a_assert(0); - } - return v; -} - -#endif /* !UEMF */ -/******************************************************************************/ diff --git a/cpukit/httpd/wbase64.c b/cpukit/httpd/wbase64.c deleted file mode 100644 index 5cf8c8b0b5..0000000000 --- a/cpukit/httpd/wbase64.c +++ /dev/null @@ -1,149 +0,0 @@ -/* - * base64.c -- Base64 Mime encoding - * - * Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved. - * - * See the file "license.txt" for usage and redistribution license requirements - * - * $Id$ - */ - -/******************************** Description *********************************/ - -/* - * The base64 command encodes and decodes a string in mime base64 format - */ - -/********************************* Includes ***********************************/ - -#include "wsIntrn.h" - -/******************************** Local Data **********************************/ -/* - * Mapping of ANSI chars to base64 Mime encoding alphabet (see below) - */ - -static char_t map64[] = { - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, - -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, - 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, - -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, - 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -}; - -static char_t alphabet64[] = { - 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', - 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', - 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', - 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', - 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', - 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', - 'w', 'x', 'y', 'z', '0', '1', '2', '3', - '4', '5', '6', '7', '8', '9', '+', '/', -}; - -/*********************************** Code *************************************/ -/* - * Decode a buffer from "string" and into "outbuf" - */ - -int websDecode64(char_t *outbuf, char_t *string, int outlen) -{ - unsigned long shiftbuf; - char_t *cp, *op; - int c, i, j, shift; - - op = outbuf; - *op = '\0'; - cp = string; - while (*cp && *cp != '=') { -/* - * Map 4 (6bit) input bytes and store in a single long (shiftbuf) - */ - shiftbuf = 0; - shift = 18; - for (i = 0; i < 4 && *cp && *cp != '='; i++, cp++) { - c = map64[*cp & 0xff]; - if (c == -1) { - error(E_L, E_LOG, T("Bad string: %s at %c index %d"), string, - c, i); - return -1; - } - shiftbuf = shiftbuf | (c << shift); - shift -= 6; - } -/* - * Interpret as 3 normal 8 bit bytes (fill in reverse order). - * Check for potential buffer overflow before filling. - */ - --i; - if ((op + i) >= &outbuf[outlen]) { - gstrcpy(outbuf, T("String too big")); - return -1; - } - for (j = 0; j < i; j++) { - *op++ = (char_t) ((shiftbuf >> (8 * (2 - j))) & 0xff); - } - *op = '\0'; - } - return 0; -} - - -/******************************************************************************/ -/* - * Encode a buffer from "string" into "outbuf" - */ - -void websEncode64(char_t *outbuf, char_t *string, int outlen) -{ - unsigned long shiftbuf; - char_t *cp, *op; - int x, i, j, shift; - - op = outbuf; - *op = '\0'; - cp = string; - while (*cp) { -/* - * Take three characters and create a 24 bit number in shiftbuf - */ - shiftbuf = 0; - for (j = 2; j >= 0 && *cp; j--, cp++) { - shiftbuf |= ((*cp & 0xff) << (j * 8)); - } -/* - * Now convert shiftbuf to 4 base64 letters. The i,j magic calculates - * how many letters need to be output. - */ - shift = 18; - for (i = ++j; i < 4 && op < &outbuf[outlen] ; i++) { - x = (shiftbuf >> shift) & 0x3f; - *op++ = alphabet64[(shiftbuf >> shift) & 0x3f]; - shift -= 6; - } -/* - * Pad at the end with '=' - */ - while (j-- > 0) { - *op++ = '='; - } - *op = '\0'; - } -} -/******************************************************************************/ diff --git a/cpukit/httpd/webcomp.c b/cpukit/httpd/webcomp.c deleted file mode 100644 index f19063f5b3..0000000000 --- a/cpukit/httpd/webcomp.c +++ /dev/null @@ -1,188 +0,0 @@ -/* - * webcomp -- Compile web pages into C source - * - * Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved. - * - * See the file "license.txt" for usage and redistribution license requirements - * - * $Id$ - */ - -/******************************** Description *********************************/ - -/* - * Usage: webcomp prefix filelist >webrom.c - * - * filelist is a file containing the pathnames of all web pages - * prefix is a path prefix to remove from all the web page pathnames - * webrom.c is the resulting C source file to compile and link. - */ - -/********************************* Includes ***********************************/ - -#include "wsIntrn.h" - -/**************************** Forward Declarations ****************************/ - -static int compile(char_t *fileList, char_t *prefix); -static void usage(); - -/*********************************** Code *************************************/ -/* - * Main program for webpack test harness - */ - -int gmain(int argc, char_t* argv[]) -{ - char_t *fileList, *prefix; - - fileList = NULL; - - if (argc != 3) { - usage(); - } - - prefix = argv[1]; - fileList = argv[2]; - - if (compile(fileList, prefix) < 0) { - return -1; - } - return 0; -} - -/******************************************************************************/ -/* - * Output usage message - */ - -static void usage() -{ - fprintf(stderr, "usage: webcomp prefix filelist >output.c\n"); - exit(2); -} - -/******************************************************************************/ -/* - * Compile the web pages - */ - -static int compile(char_t *fileList, char_t *prefix) -{ - gstat_t sbuf; - FILE *lp; - time_t now; - char_t file[FNAMESIZE]; - char_t *cp, *sl; - char buf[512]; - unsigned char *p; - int j, i, len, fd, nFile; - -/* - * Open list of files - */ - if ((lp = fopen(fileList, "r")) == NULL) { - fprintf(stderr, "Can't open file list %s\n", fileList); - return -1; - } - - time(&now); - fprintf(stdout, "/*\n * webrom.c -- Compiled Web Pages\n *\n"); - fprintf(stdout, " * Compiled by GoAhead WebCompile: %s */\n\n", - gctime(&now)); - fprintf(stdout, "#include \"wsIntrn.h\"\n\n"); - fprintf(stdout, "#ifndef WEBS_PAGE_ROM\n"); - fprintf(stdout, "websRomPageIndexType websRomPageIndex[] = {\n"); - fprintf(stdout, " { 0, 0, 0 },\n};\n"); - fprintf(stdout, "#else\n"); - -/* - * Open each input file and compile each web page - */ - nFile = 0; - while (fgets(file, sizeof(file), lp) != NULL) { - 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; - } - if ((fd = gopen(file, O_RDONLY | O_BINARY)) < 0) { - fprintf(stderr, "Can't open file %s\n", file); - return -1; - } - fprintf(stdout, "static unsigned char page_%d[] = {\n", nFile); - - while ((len = read(fd, buf, sizeof(buf))) > 0) { - p = buf; - for (i = 0; i < len; ) { - fprintf(stdout, " "); - for (j = 0; p < &buf[len] && j < 16; j++, p++) { - fprintf(stdout, "%3d,", *p); - } - i += j; - fprintf(stdout, "\n"); - } - } - fprintf(stdout, " 0 };\n\n"); - - close(fd); - nFile++; - } - fclose(lp); - -/* - * Now output the page index - */ - fprintf(stdout, "websRomPageIndexType websRomPageIndex[] = {\n"); - - if ((lp = fopen(fileList, "r")) == NULL) { - fprintf(stderr, "Can't open file list %s\n", fileList); - return -1; - } - nFile = 0; - while (fgets(file, sizeof(file), lp) != NULL) { - 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 - */ - if (strncmp(file, prefix, gstrlen(prefix)) == 0) { - cp = &file[gstrlen(prefix)]; - } else { - cp = file; - } - while((sl = strchr(file, '\\')) != NULL) { - *sl = '/'; - } - if (*cp == '/') { - cp++; - } - - if (gstat(file, &sbuf) == 0 && sbuf.st_mode & S_IFDIR) { - fprintf(stdout, " { T(\"/%s\"), 0, 0 },\n", cp); - continue; - } - fprintf(stdout, " { T(\"/%s\"), page_%d, %d },\n", cp, nFile, - sbuf.st_size); - nFile++; - } - fclose(lp); - - fprintf(stdout, " { 0, 0, 0 },\n"); - fprintf(stdout, "};\n"); - fprintf(stdout, "#endif /* WEBS_PAGE_ROM */\n"); - - fclose(lp); - fflush(stdout); - return 0; -} - -/******************************************************************************/ diff --git a/cpukit/httpd/webmain.c b/cpukit/httpd/webmain.c deleted file mode 100644 index eca5735cef..0000000000 --- a/cpukit/httpd/webmain.c +++ /dev/null @@ -1,499 +0,0 @@ -/* - * main.c -- Main program for the GoAhead WebServer (RTEMS version) - * - * Copyright (c) Go Ahead Software Inc., 1995-1999. All Rights Reserved. - * - * See the file "license.txt" for usage and redistribution license requirements - * - * $Id$ - */ - -/******************************** Description *********************************/ - -/* - * Main program for for the GoAhead WebServer. This is a demonstration - * main program to initialize and configure the web server. - */ - -/********************************* Includes ***********************************/ - -#include "uemf.h" -#include "wsIntrn.h" -#include <signal.h> -#include <sys/time.h> -#include <pthread.h> - -#include <rtems.h> -#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 - */ - -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 */ -static int finished; /* Finished flag */ - -/* - * Structure to hold timer events - */ -typedef struct { - void (*routine)(long arg); /* Timer routine */ - long arg; /* Argument to routine */ -} websTimer_t; - -/* The following holds the pointer to an allocated websTimer_t structure . - * Using this method only one timer can be active at a time, but - * for the WebServer, this should be OK. - */ -websTimer_t *tp; - -/****************************** Forward Declarations **************************/ - -static int initWebs(void); -static int aspTest(int eid, webs_t wp, int argc, char_t **argv); -static void formTest(webs_t wp, char_t *path, char_t *query); -static int websHomePageHandler(webs_t wp, char_t *urlPrefix, char_t *webDir, - int arg, char_t* url, char_t* path, char_t* query); -static void timerProc(int signo); -#if B_STATS -static void printMemStats(int handle, char_t *fmt, ...); -static void memLeaks(void); -#endif -static timer_t timer_id; -static void rtems_httpd_daemon(rtems_task_argument args); - -/*********************************** Code *************************************/ -/* - * Main -- entry point from RTEMS - */ -int rtems_initialize_webserver(void) -{ - rtems_status_code sc; - rtems_id tid; - int priority; - - /*********************************************************************** - * Default HTTPD priority. - **********************************************************************/ - priority = 40; - - sc = rtems_task_create(rtems_build_name('H', 'T', 'P', 'D'), - priority, 8*1024, - RTEMS_PREEMPT | RTEMS_NO_TIMESLICE | RTEMS_NO_ASR | - RTEMS_INTERRUPT_LEVEL(0), - RTEMS_NO_FLOATING_POINT | RTEMS_LOCAL, - &tid); - if (sc != RTEMS_SUCCESSFUL) - { - return(RTEMS_UNSATISFIED); - } - - sc = rtems_task_start(tid, rtems_httpd_daemon, 0); - if (sc != RTEMS_SUCCESSFUL) - { - return(RTEMS_UNSATISFIED); - } - - return(RTEMS_SUCCESSFUL); - -} - -static void -rtems_httpd_daemon(rtems_task_argument args) -{ -/* - * Initialize the memory allocator. Allow use of malloc and start with a - * 10K heap. - */ - bopen(NULL, (10 * 1024), B_USE_MALLOC); - -/* - * Initialize the web server - */ - 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(-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 ); -} - -/******************************************************************************/ -/* - * Initialize the web server. - */ - -static int initWebs(void) -{ - struct hostent* hp; - struct in_addr intaddr; - char host[128], webdir[128]; - char_t wbuf[128]; - -/* - * Initialize the socket subsystem - */ - socketOpen(); - -/* - * Define the local Ip address, host name, default home page and the - * root web directory. - */ - if (gethostname(host, sizeof(host)) < 0) { - error(E_L, E_LOG, T("Can't get hostname")); - return -1; - } - -/* intaddr.s_addr = (unsigned long) hostGetByName(host); */ - if ((hp = gethostbyname(host)) == NULL) { - error(E_L, E_LOG, T("Can't get host address")); - return -1; - } - memcpy((char *) &intaddr, (char *) hp->h_addr_list[0], - (size_t) hp->h_length); - -#if 0 -/* - * Set /TFTP/x.y.z.w/goahead as the root web. Modify to suit your needs - */ - sprintf(webdir, "/TFTP/%s/%s", tftpServer, rootWeb); -#else - sprintf(webdir, "/"); -#endif -/* - * Configure the web server options before opening the web server - */ - websSetDefaultDir(webdir); - ascToUni(wbuf, inet_ntoa(intaddr), sizeof(wbuf)); - websSetIpaddr(wbuf); - ascToUni(wbuf, host, sizeof(wbuf)); - websSetHost(wbuf); - -/* - * Configure the web server options before opening the web server - */ -#if 0 - websSetDefaultPage(T("default.asp")); -#else - websSetDefaultPage(T("index.html")); -#endif - websSetPassword(password); - -/* - * Open the web server on the given port. If that port is taken, try - * the next sequential port for up to "retries" attempts. - */ - websOpenServer(port, retries); - -/* - * First create the URL handlers. Note: handlers are called in sorted order - * with the longest path handler examined first. Here we define the security - * handler, forms handler and the default web page handler. - */ - websUrlHandlerDefine(T(""), NULL, 0, websSecurityHandler, - WEBS_HANDLER_FIRST); - websUrlHandlerDefine(T("/goform"), NULL, 0, websFormHandler, 0); - websUrlHandlerDefine(T(""), NULL, 0, websDefaultHandler, - WEBS_HANDLER_LAST); - -/* - * Now define two test procedures. Replace these with your application - * relevant ASP script procedures and form functions. - */ - websAspDefine(T("aspTest"), aspTest); - websFormDefine(T("formTest"), formTest); - -/* - * Create a handler for the default home page - */ - websUrlHandlerDefine(T("/"), NULL, 0, websHomePageHandler, 0); - return 0; -} - -/******************************************************************************/ -/* - * Test Javascript binding for ASP. This will be invoked when "aspTest" is - * embedded in an ASP page. See web/asp.asp for usage. Set browser to - * "localhost/asp.asp" to test. - */ - -static int aspTest(int eid, webs_t wp, int argc, char_t **argv) -{ - char_t *name, *address; - - if (ejArgs(argc, argv, T("%s %s"), &name, &address) < 2) { - websError(wp, 400, T("Insufficient args\n")); - return -1; - } - return websWrite(wp, T("Name: %s, Address %s"), name, address); -} -/******************************************************************************/ -/* - * Test form for posted data (in-memory CGI). This will be called when the - * form in web/asp.asp is invoked. Set browser to "localhost/asp.asp" to test. - */ - -static void formTest(webs_t wp, char_t *path, char_t *query) -{ - char_t *name, *address; - - name = websGetVar(wp, T("name"), T("Joe Smith")); - address = websGetVar(wp, T("address"), T("1212 Milky Way Ave.")); - - websHeader(wp); - websWrite(wp, T("<body><h2>Name: %s, Address: %s</h2>\n"), name, address); - websFooter(wp); - websDone(wp, 200); -} - -/******************************************************************************/ -/* - * Create a timer to invoke the routine in "delay" milliseconds. - */ - -void *emfCreateTimer(int delay, void (*routine)(long arg), long arg) -{ -/* this variable is only used in the if'ed 0 section below */ -#if 0 - struct sigaction act; -#endif - struct itimerspec its = { {0,0}, {0,0} }; - struct sigevent se; - int status; - - if ((tp = balloc(B_L, sizeof(websTimer_t)))) { - tp->routine = routine; - tp->arg = arg; - } - else { - return NULL; - } - - se.sigev_notify = SIGEV_THREAD; - se.sigev_value.sival_ptr = tp; - se.sigev_notify_function = (void (*)(union sigval)) timerProc; - - /* - * NOT POSIX? - * se.sigev_notify_attributes = NULL; - */ - - - status = timer_create(CLOCK_REALTIME, &se, &timer_id); - if (status != 0) { - bfree(B_L, tp); - return NULL; - } - /* convert delay millisecs to secs and usecs required by struct */ - its.it_value.tv_sec = delay / 1000; - its.it_value.tv_nsec = (delay % 1000) * 1000000; - - status = timer_settime(timer_id, 0, &its, 0); - if (status != 0) { - bfree(B_L, tp); - return NULL; - } - -#if 0 - act.sa_flags = 0; - sigemptyset(&act.sa_mask); - act.sa_handler = timerProc; - sigaction(SIGALRM, &act, NULL); - - /* convert delay millisecs to secs and usecs required by struct */ - its.it_value.tv_sec = delay / 1000; - its.it_value.tv_usec = (delay % 1000) * 1000; - - if (setitimer(ITIMER_REAL, &its, NULL) == -1) { - bfree(B_L, tp); - return NULL; - } -#endif - return tp; -} - -/******************************************************************************/ -/* - * Delete a timer - */ - -void emfDeleteTimer(void * id) -{ - websTimer_t *wtp; - /*struct itimerval its = { {0,0}, {0,0} };*/ - - wtp = (websTimer_t *)id; - /* setitimer(ITIMER_REAL, &its, NULL);*/ - timer_delete(timer_id); - bfree(B_L, wtp); -} - -/******************************************************************************/ -/* - * Timer handler - */ - -static void timerProc(int signo) -{ - websTimer_t wtp = *tp; - -/* Copy the timer structure to a local first and delete it before calling - * the function, since the function could create another timer. In this - * implementation, only one timer can be allocated at a time. - */ - - bfree(B_L, tp); - (wtp.routine)(wtp.arg); -} - -/******************************************************************************/ -/* - * Home page handler - */ - -static int websHomePageHandler(webs_t wp, char_t *urlPrefix, char_t *webDir, - int arg, char_t* url, char_t* path, char_t* query) -{ -/* - * 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; -} - -/******************************************************************************/ - -#if B_STATS -static void memLeaks() -{ - int fd=1; - - /* if ((fd = gopen(T("leak.txt"), O_CREAT | O_TRUNC | O_WRONLY)) >= 0) { */ - bstats(fd, printMemStats); - /* - close(fd); - } - */ -} - -/******************************************************************************/ -/* - * Print memory usage / leaks - */ - -static void printMemStats(int handle, char_t *fmt, ...) -{ - va_list args; - char_t buf[256]; - - va_start(args, fmt); - vsprintf(buf, fmt, args); - va_end(args); - write(handle, buf, strlen(buf)); -} -#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(void) -{ - char_t *pname1, *pname2; - - pname1 = tempnam(NULL, T("cgi")); - pname2 = bstrdup(B_L, pname1); - free(pname1); - return pname2; -} diff --git a/cpukit/httpd/webpage.c b/cpukit/httpd/webpage.c deleted file mode 100644 index a42a8b45c9..0000000000 --- a/cpukit/httpd/webpage.c +++ /dev/null @@ -1,141 +0,0 @@ -/* - * Page.c -- Support for page retrieval. - * - * Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved. - * - * See the file "license.txt" for usage and redistribution license requirements - * - * $Id$ - */ - -/******************************** Description *********************************/ - -/* - * This module provides page retrieval handling. It provides support for - * reading web pages from file systems and has expansion for ROMed web - * pages. - */ - -/********************************* Includes ***********************************/ - -#include "wsIntrn.h" - -/*********************************** Code *************************************/ -/* - * Open a web page. lpath is the local filename. path is the URL path name. - */ - -int websPageOpen(webs_t wp, char_t *lpath, char_t *path, int mode, int perm) -{ - a_assert(websValid(wp)); - -#ifdef WEBS_PAGE_ROM - return websRomPageOpen(wp, path, mode, perm); -#else - return (wp->docfd = gopen(lpath, mode, perm)); -#endif /* WEBS_PAGE_ROM */ -} - -/******************************************************************************/ -/* - * Close a web page - */ - -void websPageClose(webs_t wp) -{ - a_assert(websValid(wp)); - -#ifdef WEBS_PAGE_ROM - websRomPageClose(wp->docfd); -#else - if (wp->docfd >= 0) { - close(wp->docfd); - wp->docfd = -1; - } -#endif -} - -/******************************************************************************/ -/* - * Stat a web page lpath is the local filename. path is the URL path name. - */ - -int websPageStat(webs_t wp, char_t *lpath, char_t *path, websStatType* sbuf) -{ -#ifdef WEBS_PAGE_ROM - return websRomPageStat(path, sbuf); -#else - gstat_t s; - - if (gstat(lpath, &s) < 0) { - return -1; - } - sbuf->size = s.st_size; - sbuf->mtime = s.st_mtime; - sbuf->isDir = s.st_mode & S_IFDIR; - return 0; -#endif -} - -/******************************************************************************/ -/* - * Is this file a directory? - */ - -int websPageIsDirectory(char_t *lpath) -{ -#ifdef WEBS_PAGE_ROM - websStatType sbuf; - - if (websRomPageStat(lpath, &sbuf) >= 0) { - return(sbuf.isDir); - } else { - return 0; - } -#else - gstat_t sbuf; - - if (gstat(lpath, &sbuf) >= 0) { - return(sbuf.st_mode & S_IFDIR); - } else { - return 0; - } -#endif -} - - -/******************************************************************************/ -/* - * Read a web page. Returns the number of _bytes_ read. - * len is the size of buf, in bytes. - */ - -int websPageReadData(webs_t wp, char *buf, int nBytes) -{ - -#ifdef WEBS_PAGE_ROM - a_assert(websValid(wp)); - return websRomPageReadData(wp, buf, nBytes); -#else - a_assert(websValid(wp)); - return read(wp->docfd, buf, nBytes); -#endif -} - -/******************************************************************************/ -/* - * Move file pointer offset bytes. - */ - -void websPageSeek(webs_t wp, long offset) -{ - a_assert(websValid(wp)); - -#ifdef WEBS_PAGE_ROM - websRomPageSeek(wp, offset, SEEK_CUR); -#else - lseek(wp->docfd, offset, SEEK_CUR); -#endif -} - -/******************************************************************************/ diff --git a/cpukit/httpd/webrom.c b/cpukit/httpd/webrom.c deleted file mode 100644 index 3efc0a9588..0000000000 --- a/cpukit/httpd/webrom.c +++ /dev/null @@ -1,15 +0,0 @@ -/* - * webrom.c -- Compiled Web Pages - * - * Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved. - * - * See the file "license.txt" for usage and redistribution license requirements - * - * $Id$ - */ - -#include "wsIntrn.h" - -websRomPageIndexType websRomPageIndex[] = { - { NULL, NULL, 0, 0 }, -}; diff --git a/cpukit/httpd/webs.c b/cpukit/httpd/webs.c deleted file mode 100644 index 509e7061d8..0000000000 --- a/cpukit/httpd/webs.c +++ /dev/null @@ -1,2967 +0,0 @@ -/* - * webs.c -- GoAhead Embedded HTTP webs server - * - * Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved. - * - * See the file "license.txt" for usage and redistribution license requirements - * - * $Id$ - */ - -/******************************** Description *********************************/ - -/* - * This module implements an embedded HTTP/1.1 web server. It supports - * loadable URL handlers that define the nature of URL processing performed. - */ - -/********************************* Includes ***********************************/ - -#include "wsIntrn.h" -#ifdef DIGEST_ACCESS_SUPPORT - #include "websda.h" -#endif - -/******************************** Global Data *********************************/ - -websStatsType websStats; /* Web access stats */ -webs_t *webs; /* Open connection list head */ -sym_fd_t websMime; /* Set of mime types */ -int websMax; /* List size */ -int websPort; /* Listen port for server */ -char_t websHost[64]; /* Host name for the server */ -char_t websIpaddr[64]; /* IP address for the server */ -char_t *websHostUrl = NULL; /* URL to access server */ -char_t *websIpaddrUrl = NULL; /* URL to access server */ - -/*********************************** Locals ***********************************/ -/* - * Standard HTTP error codes - */ - -websErrorType websErrors[] = { - { 200, T("Data follows") }, - { 204, T("No Content") }, - { 301, T("Redirect") }, - { 302, T("Redirect") }, - { 304, T("Use local copy") }, - { 400, T("Page not found") }, - { 401, T("Unauthorized") }, - { 403, T("Forbidden") }, - { 404, T("Site or Page Not Found") }, - { 405, T("Access Denied") }, - { 500, T("Web Error") }, - { 501, T("Not Implemented") }, - { 503, T("Site Temporarily Unavailable. Try again.") }, - { 0, NULL } -}; - -#ifdef WEBS_LOG_SUPPORT -static char_t websLogname[64] = T("log.txt"); /* Log filename */ -static int websLogFd; /* Log file handle */ -#endif - -static int websListenSock; /* Listen socket */ -static char_t websRealm[64] = T("GoAhead"); /* Realm name */ - -static int websOpenCount = 0; /* count of apps using this module */ - -/**************************** Forward Declarations ****************************/ - - -/*static char_t *websErrorMsg(int code);*/ -static int websGetInput(webs_t wp, char_t **ptext, int *nbytes); -static int websParseFirst(webs_t wp, char_t *text); -static void websParseRequest(webs_t wp); -static void websSocketEvent(int sid, int mask, int data); -static int websGetTimeSinceMark(webs_t wp); - -#ifdef WEBS_LOG_SUPPORT -static void websLog(webs_t wp, int code); -#endif -#ifdef WEBS_IF_MODIFIED_SUPPORT -static time_t dateParse(time_t tip, char_t *cmd); -#endif - -/*********************************** Code *************************************/ -/* - * Open the GoAhead WebServer - */ - -int websOpenServer(int port, int retries) -{ - websMimeType *mt; - - if (++websOpenCount != 1) { - return websPort; - } - - a_assert(port > 0); - a_assert(retries >= 0); - -#ifdef WEBS_PAGE_ROM - websRomOpen(); -#endif - - webs = NULL; - websMax = 0; -/* - * Create a mime type lookup table for quickly determining the content type - */ - websMime = symOpen(WEBS_SYM_INIT * 4); - a_assert(websMime >= 0); - for (mt = websMimeList; mt->type; mt++) { - symEnter(websMime, mt->ext, valueString(mt->type, 0), 0); - } - -/* - * Open the URL handler module. The caller should create the required - * URL handlers after calling this function. - */ - if (websUrlHandlerOpen() < 0) { - return -1; - } - websFormOpen(); - -#ifdef WEBS_LOG_SUPPORT -/* - * Optional request log support - */ - websLogFd = gopen(websLogname, O_CREAT | O_TRUNC | O_APPEND | O_WRONLY, - 0666); - a_assert(websLogFd >= 0); -#endif - - return websOpenListen(port, retries); -} - -/******************************************************************************/ -/* - * Close the GoAhead WebServer - */ - -void websCloseServer(void) -{ - webs_t wp; - int wid; - - if (--websOpenCount > 0) { - return; - } - -/* - * Close the listen handle first then all open connections. - */ - websCloseListen(); - -/* - * Close each open browser connection and free all resources - */ - for (wid = websMax; webs && wid >= 0; wid--) { - if ((wp = webs[wid]) == NULL) { - continue; - } - socketCloseConnection(wp->sid); - websFree(wp); - } - -#ifdef WEBS_LOG_SUPPORT - if (websLogFd >= 0) { - close(websLogFd); - websLogFd = -1; - } -#endif - -#ifdef WEBS_PAGE_ROM - websRomClose(); -#endif - symClose(websMime); - websFormClose(); - websUrlHandlerClose(); -} - -/******************************************************************************/ -/* - * Open the GoAhead WebServer listen port - */ - -int websOpenListen(int port, int retries) -{ - int i, orig; - - a_assert(port > 0); - a_assert(retries >= 0); - - orig = port; -/* - * Open the webs webs listen port. If we fail, try the next port. - */ - for (i = 0; i <= retries; i++) { - websListenSock = socketOpenConnection(NULL, port, websAccept, 0); - if (websListenSock >= 0) { - break; - } - port++; - } - if (i > retries) { - error(E_L, E_USER, T("Couldn't open a socket on ports %d - %d"), - orig, port - 1); - return -1; - } - -/* - * Determine the full URL address to access the home page for this web server - */ - websPort = port; - bfreeSafe(B_L, websHostUrl); - bfreeSafe(B_L, websIpaddrUrl); - websIpaddrUrl = websHostUrl = NULL; - - if (port == 80) { - websHostUrl = bstrdup(B_L, websHost); - websIpaddrUrl = bstrdup(B_L, websIpaddr); - } else { - fmtAlloc(&websHostUrl, WEBS_MAX_URL + 80, T("%s:%d"), websHost, port); - fmtAlloc(&websIpaddrUrl, WEBS_MAX_URL + 80, T("%s:%d"), - websIpaddr, port); - } - trace(0, T("webs: Listening for HTTP requests at address %s\n"), - websIpaddrUrl); - - return port; -} - -/******************************************************************************/ -/* - * Close webs listen port - */ - -void websCloseListen(void) -{ - if (websListenSock >= 0) { - socketCloseConnection(websListenSock); - websListenSock = -1; - } - bfreeSafe(B_L, websHostUrl); - bfreeSafe(B_L, websIpaddrUrl); - websIpaddrUrl = websHostUrl = NULL; -} - -/******************************************************************************/ -/* - * Accept a connection - */ - -int websAccept(int sid, char *ipaddr, int port, int listenSid) -{ - webs_t wp; - int wid; - - a_assert(ipaddr && *ipaddr); - a_assert(sid >= 0); - a_assert(port >= 0); - -/* - * Allocate a new handle for this accepted connection. This will allocate - * a webs_t structure in the webs[] list - */ - if ((wid = websAlloc(sid)) < 0) { - return -1; - } - wp = webs[wid]; - a_assert(wp); - wp->listenSid = listenSid; - - ascToUni(wp->ipaddr, ipaddr, min(sizeof(wp->ipaddr), strlen(ipaddr) + 1)); - -/* - * Check if this is a request from a browser on this system. This is useful - * to know for permitting administrative operations only for local access - */ - if (gstrcmp(wp->ipaddr, T("127.0.0.1")) == 0 || - gstrcmp(wp->ipaddr, websIpaddr) == 0 || - gstrcmp(wp->ipaddr, websHost) == 0) { - wp->flags |= WEBS_LOCAL_REQUEST; - } - -/* - * Arrange for websSocketEvent to be called when read data is available - */ - socketCreateHandler(sid, SOCKET_READABLE, websSocketEvent, (int) wp); - -/* - * Arrange for a timeout to kill hung requests - */ - wp->timeout = emfSchedCallback(WEBS_TIMEOUT, websTimeout, (void *) wp); - trace(8, T("webs: accept request\n")); - return 0; -} - -/******************************************************************************/ -/* - * The webs socket handler. Called in response to I/O. We just pass control - * to the relevant read or write handler. A pointer to the webs structure - * is passed as an (int) in iwp. - */ - -static void websSocketEvent(int sid, int mask, int iwp) -{ - webs_t wp; - - wp = (webs_t) iwp; - a_assert(wp); - - if (! websValid(wp)) { - return; - } - - if (mask & SOCKET_READABLE) { - websReadEvent(wp); - } - if (mask & SOCKET_WRITABLE) { - if (websValid(wp) && wp->writeSocket) { - (*wp->writeSocket)(wp); - } - } -} - -/******************************************************************************/ -/* - * The webs read handler. This is the primary read event loop. It uses a - * state machine to track progress while parsing the HTTP request. - * Note: we never block as the socket is always in non-blocking mode. - */ - -void websReadEvent(webs_t wp) -{ - char_t *text; - int rc, nbytes, len, done, fd; - - a_assert(wp); - a_assert(websValid(wp)); - - websSetTimeMark(wp); - -/* - * Read as many lines as possible. socketGets is called to read the header - * and socketRead is called to read posted data. - */ - text = NULL; - fd = -1; - for (done = 0; !done; ) { - if (text) { - bfree(B_L, text); - text = NULL; - } - -/* - * Get more input into "text". Returns 0, if more data is needed - * to continue, -1 if finished with the request, or 1 if all - * required data is available for current state. - */ - while ((rc = websGetInput(wp, &text, &nbytes)) == 0) { - ; - } - -/* - * websGetInput returns -1 if it finishes with the request - */ - if (rc < 0) { - break; - } - -/* - * This is the state machine for the web server. - */ - switch(wp->state) { - case WEBS_BEGIN: -/* - * Parse the first line of the Http header - */ - if (websParseFirst(wp, text) < 0) { - done++; - break; - } - wp->state = WEBS_HEADER; - break; - - case WEBS_HEADER: -/* - * Store more of the HTTP header. As we are doing line reads, we - * need to separate the lines with '\n' - */ - if (ringqLen(&wp->header) > 0) { - ringqPutStr(&wp->header, T("\n")); - } - ringqPutStr(&wp->header, text); - break; - - case WEBS_POST_CLEN: -/* - * POST request with content specified by a content length. - * If this is a CGI request, write the data to the cgi stdin. - * socketGets was used to get the data and it strips \n's so - * add them back in here. - */ -#ifndef __NO_CGI_BIN - if (wp->flags & WEBS_CGI_REQUEST) { - if (fd == -1) { - fd = gopen(wp->cgiStdin, O_CREAT | O_WRONLY | O_BINARY, - 0666); - } - gwrite(fd, text, gstrlen(text)); - /* - * NOTE that the above comment is wrong -- if the content length - * is set, websGetInput() does NOT use socketGets(), it uses - * socketRead(), so the line below that adds an additional newline - * is destructive. - */ - /*gwrite(fd, T("\n"), sizeof(char_t));*/ -/* - * Line removed as per BUG02488 - * - nbytes += 1; - */ - } else -#endif - if (wp->query) { - if (wp->query[0] && !(wp->flags & WEBS_POST_DATA)) { -/* - * Special case where the POST request also had query data - * specified in the URL, ie. url?query_data. In this case - * the URL query data is separated by a '&' from the posted - * query data. - */ - len = gstrlen(wp->query); - wp->query = brealloc(B_L, wp->query, (len + gstrlen(text) + - 2) * sizeof(char_t)); - wp->query[len++] = '&'; - gstrcpy(&wp->query[len], text); - - } else { -/* - * The existing query data came from the POST request so just - * append it. - */ - if (text != NULL) - { - len = gstrlen(wp->query); - wp->query = brealloc(B_L, wp->query, (len + gstrlen(text) + - 1) * sizeof(char_t)); - if (wp->query) { - gstrcpy(&wp->query[len], text); - } - } - } - - } else { - wp->query = bstrdup(B_L, text); - } -/* - * Calculate how much more post data is to be read. - */ - wp->flags |= WEBS_POST_DATA; - wp->clen -= nbytes; - if (wp->clen > 0) { - if (nbytes > 0) { - break; - } - done++; - break; - } -/* - * No more data so process the request, (but be sure to close - * the input file first!). - */ - if (fd != -1) { - gclose (fd); - fd = -1; - } - websUrlHandlerRequest(wp); - done++; - break; - - case WEBS_POST: -/* - * POST without content-length specification - * If this is a CGI request, write the data to the cgi stdin. - * socketGets was used to get the data and it strips \n's so - * add them back in here. - */ - -#ifndef __NO_CGI_BIN - if (wp->flags & WEBS_CGI_REQUEST) { - if (fd == -1) { - fd = gopen(wp->cgiStdin, O_CREAT | O_WRONLY | O_BINARY, - 0666); - } - gwrite(fd, text, gstrlen(text)); - gwrite(fd, T("\n"), sizeof(char_t)); - } else -#endif - if (wp->query && *wp->query && !(wp->flags & WEBS_POST_DATA)) { - len = gstrlen(wp->query); - wp->query = brealloc(B_L, wp->query, (len + gstrlen(text) + - 2) * sizeof(char_t)); - if (wp->query) { - wp->query[len++] = '&'; - gstrcpy(&wp->query[len], text); - } - - } else { - wp->query = bstrdup(B_L, text); - } - wp->flags |= WEBS_POST_DATA; - done++; - break; - - default: - websError(wp, 404, T("Bad state")); - done++; - break; - } - } - - if (fd != -1) { - fd = gclose (fd); - } - - if (text) { - bfree(B_L, text); - } -} - -/******************************************************************************/ -/* - * Get input from the browser. Return TRUE (!0) if the request has been - * handled. Return -1 on errors or if the request has been processed, - * 1 if input read, and 0 to instruct the caller to call again for more input. - * - * Note: socketRead will Return the number of bytes read if successful. This - * may be less than the requested "bufsize" and may be zero. It returns -1 for - * errors. It returns 0 for EOF. Otherwise it returns the number of bytes - * read. Since this may be zero, callers should use socketEof() to - * distinguish between this and EOF. - */ - -static int websGetInput(webs_t wp, char_t **ptext, int *pnbytes) -{ - char_t *text; - char buf[WEBS_SOCKET_BUFSIZ+1]; - int nbytes, len, clen; - - a_assert(websValid(wp)); - a_assert(ptext); - a_assert(pnbytes); - - *ptext = text = NULL; - *pnbytes = 0; - -/* - * If this request is a POST with a content length, we know the number - * of bytes to read so we use socketRead(). - */ - if (wp->state == WEBS_POST_CLEN) { - len = (wp->clen > WEBS_SOCKET_BUFSIZ) ? WEBS_SOCKET_BUFSIZ : wp->clen; - } else { - len = 0; - } - - if (len > 0) { - -#ifdef WEBS_SSL_SUPPORT - if (wp->flags & WEBS_SECURE) { - nbytes = websSSLRead(wp->wsp, buf, len); - } else { - nbytes = socketRead(wp->sid, buf, len); - } -#else - nbytes = socketRead(wp->sid, buf, len); -#endif - if (nbytes < 0) { /* Error */ - websDone(wp, 0); - return -1; - - } else if (nbytes == 0) { /* EOF or No data available */ - /* Bugfix for POST DoS attack with invalid content length */ - if (socketEof(wp->sid)) { - websDone(wp, 0); - } - /* End of bugfix */ - return -1; - - } else { /* Valid data */ -/* - * Convert to UNICODE if necessary. First be sure the string - * is NULL terminated. - */ - buf[nbytes] = '\0'; - if ((text = ballocAscToUni(buf, nbytes)) == NULL) { - websError(wp, 503, T("Insufficient memory")); - return -1; - } - } - - } else { -#ifdef WEBS_SSL_SUPPORT - if (wp->flags & WEBS_SECURE) { - nbytes = websSSLGets(wp->wsp, &text); - } else { - nbytes = socketGets(wp->sid, &text); - } -#else - nbytes = socketGets(wp->sid, &text); -#endif - - if (nbytes < 0) { - int eof; -/* - * Error, EOF or incomplete - */ -#ifdef WEBS_SSL_SUPPORT - if (wp->flags & WEBS_SECURE) { -/* - * If state is WEBS_BEGIN and the request is secure, a -1 will - * usually indicate SSL negotiation - */ - if (wp->state == WEBS_BEGIN) { - eof = 1; - } else { - eof = websSSLEof(wp->wsp); - } - } else { - eof = socketEof(wp->sid); - } -#else - eof = socketEof(wp->sid); -#endif - - if (eof) { -/* - * If this is a post request without content length, process - * the request as we now have all the data. Otherwise just - * close the connection. - */ - if (wp->state == WEBS_POST) { - websUrlHandlerRequest(wp); - } else { - websDone(wp, 0); - } - } else { -/* - * If an error occurred and it wasn't an eof, close the connection - */ -#ifdef HP_FIX - websDone(wp, 0); -#endif /*HP_FIX*/ - - } -/* - * If state is WEBS_HEADER and the ringq is empty, then this is a - * simple request with no additional header fields to process and - * no empty line terminator. - */ -/* - * NOTE: this fix for earlier versions of browsers is troublesome - * because if we don't receive the entire header in the first pass - * this code assumes we were only expecting a one line header, which - * is not necessarily the case. So we weren't processing the whole - * header and weren't fufilling requests properly. - */ -#ifdef UNUSED - if (wp->state == WEBS_HEADER && ringqLen(&wp->header) <= 0) { - websParseRequest(wp); - websUrlHandlerRequest(wp); - } -#endif - return -1; - - } else if (nbytes == 0) { - if (wp->state == WEBS_HEADER) { -/* - * Valid empty line, now finished with header - */ - websParseRequest(wp); - if (wp->flags & WEBS_POST_REQUEST) { - if (wp->flags & WEBS_CLEN) { - wp->state = WEBS_POST_CLEN; - clen = wp->clen; - } else { - wp->state = WEBS_POST; - clen = 1; - } - if (clen > 0) { -/* - * Return 0 to get more data. - */ - return 0; - } - return 1; - } -/* - * We've read the header so go and handle the request - */ - websUrlHandlerRequest(wp); - } - return -1; - } - } - a_assert(text); - a_assert(nbytes > 0); - *ptext = text; - *pnbytes = nbytes; - return 1; -} - -/******************************************************************************/ -/* - * Parse the first line of a HTTP request - */ - -static int websParseFirst(webs_t wp, char_t *text) -{ - char_t *op, *proto, *protoVer, *url, *host, *query, *path, *port, *ext; - char_t *buf; - int testPort; - - a_assert(websValid(wp)); - a_assert(text && *text); - -/* - * Determine the request type: GET, HEAD or POST - */ - op = gstrtok(text, T(" \t")); - if (op == NULL || *op == '\0') { - websError(wp, 400, T("Bad HTTP request")); - return -1; - } - if (gstrcmp(op, T("GET")) != 0) { - if (gstrcmp(op, T("POST")) == 0) { - wp->flags |= WEBS_POST_REQUEST; - } else if (gstrcmp(op, T("HEAD")) == 0) { - wp->flags |= WEBS_HEAD_REQUEST; - } else { - websError(wp, 400, T("Bad request type")); - return -1; - } - } - -/* - * Store result in the form (CGI) variable store - */ - websSetVar(wp, T("REQUEST_METHOD"), op); - - url = gstrtok(NULL, T(" \t\n")); - if (url == NULL || *url == '\0') { - websError(wp, 400, T("Bad HTTP request")); - return -1; - } - protoVer = gstrtok(NULL, T(" \t\n")); - -/* - * Parse the URL and store all the various URL components. websUrlParse - * returns an allocated buffer in buf which we must free. We support both - * proxied and non-proxied requests. Proxied requests will have http://host/ - * at the start of the URL. Non-proxied will just be local path names. - */ - host = path = port = proto = query = ext = NULL; - if (websUrlParse(url, &buf, &host, &path, &port, &query, &proto, - NULL, &ext) < 0) { - websError(wp, 400, T("Bad URL format")); - return -1; - } - - wp->url = bstrdup(B_L, url); - -#ifndef __NO_CGI_BIN - if (gstrstr(url, CGI_BIN) != NULL) { - wp->flags |= WEBS_CGI_REQUEST; - if (wp->flags & WEBS_POST_REQUEST) { - wp->cgiStdin = websGetCgiCommName(); - } - } -#endif - - wp->query = bstrdup(B_L, query); - wp->host = bstrdup(B_L, host); - wp->path = bstrdup(B_L, path); - wp->protocol = bstrdup(B_L, proto); - wp->protoVersion = bstrdup(B_L, protoVer); - - if ((testPort = socketGetPort(wp->listenSid)) >= 0) { - wp->port = testPort; - } else { - wp->port = gatoi(port); - } - - if (gstrcmp(ext, T(".asp")) == 0) { - wp->flags |= WEBS_ASP; - } - bfree(B_L, buf); - - websUrlType(url, wp->type, TSZ(wp->type)); - -#ifdef WEBS_PROXY_SUPPORT -/* - * Determine if this is a request for local webs data. If it is not a proxied - * request from the browser, we won't see the "http://" or the system name, so - * we assume it must be talking to us directly for local webs data. - * Note: not fully implemented yet. - */ - if (gstrstr(wp->url, T("http://")) == NULL || - ((gstrcmp(wp->host, T("localhost")) == 0 || - gstrcmp(wp->host, websHost) == 0) && (wp->port == websPort))) { - wp->flags |= WEBS_LOCAL_PAGE; - if (gstrcmp(wp->path, T("/")) == 0) { - wp->flags |= WEBS_HOME_PAGE; - } - } -#endif - - ringqFlush(&wp->header); - return 0; -} - -/******************************************************************************/ -/* - * Parse a full request - */ - -#define isgoodchar(s) (gisalnum((s)) || ((s) == '/') || ((s) == '_') || \ - ((s) == '.') || ((s) == '-') ) - -static void websParseRequest(webs_t wp) -{ - char_t *authType, *upperKey, *cp, *browser, *lp, *key, *value; - - a_assert(websValid(wp)); - -/* - * Define default CGI values - */ - websSetVar(wp, T("HTTP_AUTHORIZATION"), T("")); - -/* - * Parse the header and create the Http header keyword variables - * We rewrite the header as we go for non-local requests. NOTE: this - * modifies the header string directly and tokenizes each line with '\0'. - */ - browser = NULL; - for (lp = (char_t*) wp->header.servp; lp && *lp; ) { - cp = lp; - if ((lp = gstrchr(lp, '\n')) != NULL) { - lp++; - } - - if ((key = gstrtok(cp, T(": \t\n"))) == NULL) { - continue; - } - - if ((value = gstrtok(NULL, T("\n"))) == NULL) { - value = T(""); - } - - while (gisspace((unsigned char)*value)) { - value++; - } - strlower(key); - -/* - * Create a variable (CGI) for each line in the header - */ - fmtAlloc(&upperKey, (gstrlen(key) + 6), T("HTTP_%s"), key); - for (cp = upperKey; *cp; cp++) { - if (*cp == '-') - *cp = '_'; - } - strupper(upperKey); - websSetVar(wp, upperKey, value); - bfree(B_L, upperKey); - -/* - * Track the requesting agent (browser) type - */ - if (gstrcmp(key, T("user-agent")) == 0) { - wp->userAgent = bstrdup(B_L, value); - -/* - * Parse the user authorization. ie. password - */ - } else if (gstricmp(key, T("authorization")) == 0) { -/* - * Determine the type of Authorization Request - */ - authType = bstrdup (B_L, value); - a_assert (authType); -/* - * Truncate authType at the next non-alpha character - */ - cp = authType; - while (gisalpha((unsigned char)*cp)) { - cp++; - } - *cp = '\0'; - - wp->authType = bstrdup(B_L, authType); - bfree(B_L, authType); - - if (gstricmp(wp->authType, T("basic")) == 0) { - char_t userAuth[FNAMESIZE]; -/* - * The incoming value is username:password (Basic authentication) - */ - if ((cp = gstrchr(value, ' ')) != NULL) { - *cp = '\0'; - /* - * bugfix 5/24/02 -- we were leaking the memory pointed to by - * wp->authType that was allocated just before the if() - * statement that we are currently in. Thanks to Simon Byholm. - */ - bfree(B_L, wp->authType); - wp->authType = bstrdup(B_L, value); - websDecode64(userAuth, ++cp, sizeof(userAuth)); - } else { - websDecode64(userAuth, value, sizeof(userAuth)); - } -/* - * Split userAuth into userid and password - */ - if ((cp = gstrchr(userAuth, ':')) != NULL) { - *cp++ = '\0'; - } - if (cp) { - wp->userName = bstrdup(B_L, userAuth); - wp->password = bstrdup(B_L, cp); - } else { - wp->userName = bstrdup(B_L, T("")); - wp->password = bstrdup(B_L, T("")); - } -/* - * Set the flags to indicate digest authentication - */ - wp->flags |= WEBS_AUTH_BASIC; - } else { -#ifdef DIGEST_ACCESS_SUPPORT -/* - * The incoming value is slightly more complicated (Digest) - */ - char_t *np; /* pointer to end of tag name */ - char_t tp; /* temporary character holding space */ - char_t *vp; /* pointer to value */ - char_t *npv; /* pointer to end of value, "next" pointer */ - char_t tpv; /* temporary character holding space */ -/* - * Set the flags to indicate digest authentication - */ - wp->flags |= WEBS_AUTH_DIGEST; -/* - * Move cp to Next word beyond "Digest", - * vp to first char after '='. - */ - cp = value; - while (isgoodchar(*cp)) { - cp++; - } - while (!isgoodchar(*cp)) { - cp++; - } - -/* - * Find beginning of value - */ - vp = gstrchr(cp, '='); - while (vp) { -/* - * Zero-terminate tag name - */ - np = cp; - while (isgoodchar(*np)) { - np++; - } - tp = *np; - *np = 0; -/* - * Advance value pointer to first legit character - */ - vp++; - while (!isgoodchar(*vp)) { - vp++; - } -/* - * Zero-terminate value - */ - npv = vp; - while (isgoodchar(*npv)) { - npv++; - } - tpv = *npv; - *npv = 0; -/* - * Extract the fields - */ - if (gstricmp(cp, T("username")) == 0) { - wp->userName = bstrdup(B_L, vp); - } else if (gstricmp(cp, T("response")) == 0) { - wp->digest = bstrdup(B_L, vp); - } else if (gstricmp(cp, T("opaque")) == 0) { - wp->opaque = bstrdup(B_L, vp); - } else if (gstricmp(cp, T("uri")) == 0) { - wp->uri = bstrdup(B_L, vp); - } else if (gstricmp(cp, T("realm")) == 0) { - wp->realm = bstrdup(B_L, vp); - } else if (gstricmp(cp, T("nonce")) == 0) { - wp->nonce = bstrdup(B_L, vp); - } else if (gstricmp(cp, T("nc")) == 0) { - wp->nc = bstrdup(B_L, vp); - } else if (gstricmp(cp, T("cnonce")) == 0) { - wp->cnonce = bstrdup(B_L, vp); - } else if (gstricmp(cp, T("qop")) == 0) { - wp->qop = bstrdup(B_L, vp); - } -/* - * Restore tag name and value zero-terminations - */ - *np = tp; - *npv = tpv; -/* - * Advance tag name and value pointers - */ - cp = npv; - while (*cp && isgoodchar(*cp)) { - cp++; - } - while (*cp && !isgoodchar(*cp)) { - cp++; - } - - if (*cp) { - vp = gstrchr(cp, '='); - } else { - vp = NULL; - } - } -#endif /* DIGEST_ACCESS_SUPPORT */ - } /* if (gstrcmp(wp->authType)) */ -/* - * Parse the content length - */ - } else if (gstrcmp(key, T("content-length")) == 0) { - /* - * 11 Oct 02 BgP -- The server would crash if an attacker sent a POST - * message with a content-length value <= 0. We assume that anyone - * sending this is malicious, and the POST is read from the socket, - * but it is ignored, and the socket is closed. - */ - wp->clen = gatoi(value); - if (wp->clen > 0) - { - wp->flags |= WEBS_CLEN; - websSetVar(wp, T("CONTENT_LENGTH"), value); - } - else - { - wp->clen = 0; - } - -/* - * Parse the content type - */ - } else if (gstrcmp(key, T("content-type")) == 0) { - websSetVar(wp, T("CONTENT_TYPE"), value); - -#ifdef WEBS_KEEP_ALIVE_SUPPORT - } else if (gstrcmp(key, T("connection")) == 0) { - strlower(value); - if (gstrcmp(value, T("keep-alive")) == 0) { - wp->flags |= WEBS_KEEP_ALIVE; - } -#endif - -#ifdef WEBS_PROXY_SUPPORT -/* - * This may be useful if you wish to keep a local cache of web pages - * for proxied requests. - */ - } else if (gstrcmp(key, T("pragma")) == 0) { - char_t tmp[256]; - gstrncpy(tmp, value, TSZ(tmp)); - strlower(tmp); - if (gstrstr(tmp, T("no-cache"))) { - wp->flags |= WEBS_DONT_USE_CACHE; - } -#endif /* WEBS_PROXY_SUPPORT */ - -/* - * Store the cookie - */ - } else if (gstrcmp(key, T("cookie")) == 0) { - wp->flags |= WEBS_COOKIE; - wp->cookie = bstrdup(B_L, value); - -#ifdef WEBS_IF_MODIFIED_SUPPORT -/* - * See if the local page has been modified since the browser last - * requested this document. If not, just return a 302 - */ - } else if (gstrcmp(key, T("if-modified-since")) == 0) { - char_t *cmd; - time_t tip = 0; - - if ((cp = gstrchr(value, ';')) != NULL) { - *cp = '\0'; - } - - fmtAlloc(&cmd, 64, T("%s"), value); - - if ((wp->since = dateParse(tip, cmd)) != 0) { - wp->flags |= WEBS_IF_MODIFIED; - } - - bfreeSafe(B_L, cmd); -#endif /* WEBS_IF_MODIFIED_SUPPORT */ - } - } -} - -/******************************************************************************/ -/* - * Set the variable (CGI) environment for this request. Create variables - * for all standard CGI variables. Also decode the query string and create - * a variable for each name=value pair. - */ - -void websSetEnv(webs_t wp) -{ - char_t portBuf[8]; - char_t *keyword, *value, *valCheck, *valNew; - - a_assert(websValid(wp)); - - websSetVar(wp, T("QUERY_STRING"), wp->query); - websSetVar(wp, T("GATEWAY_INTERFACE"), T("CGI/1.1")); - websSetVar(wp, T("SERVER_HOST"), websHost); - websSetVar(wp, T("SERVER_NAME"), websHost); - websSetVar(wp, T("SERVER_URL"), websHostUrl); - websSetVar(wp, T("REMOTE_HOST"), wp->ipaddr); - websSetVar(wp, T("REMOTE_ADDR"), wp->ipaddr); - websSetVar(wp, T("PATH_INFO"), wp->path); - stritoa(websPort, portBuf, sizeof(portBuf)); - websSetVar(wp, T("SERVER_PORT"), portBuf); - websSetVar(wp, T("SERVER_ADDR"), websIpaddr); - fmtAlloc(&value, FNAMESIZE, T("%s/%s"), WEBS_NAME, WEBS_VERSION); - websSetVar(wp, T("SERVER_SOFTWARE"), value); - bfreeSafe(B_L, value); - websSetVar(wp, T("SERVER_PROTOCOL"), wp->protoVersion); - -/* - * Decode and create an environment query variable for each query keyword. - * We split into pairs at each '&', then split pairs at the '='. - * Note: we rely on wp->decodedQuery preserving the decoded values in the - * symbol table. - */ - wp->decodedQuery = bstrdup(B_L, wp->query); - keyword = gstrtok(wp->decodedQuery, T("&")); - while (keyword != NULL) { - if ((value = gstrchr(keyword, '=')) != NULL) { - *value++ = '\0'; - websDecodeUrl(keyword, keyword, gstrlen(keyword)); - websDecodeUrl(value, value, gstrlen(value)); - } else { - value = T(""); - } - - if (*keyword) { -/* - * If keyword has already been set, append the new value to what has - * been stored. - */ - if ((valCheck = websGetVar(wp, keyword, NULL)) != 0) { - fmtAlloc(&valNew, 256, T("%s %s"), valCheck, value); - websSetVar(wp, keyword, valNew); - bfreeSafe(B_L, valNew); - } else { - websSetVar(wp, keyword, value); - } - } - keyword = gstrtok(NULL, T("&")); - } - -#ifdef EMF -/* - * Add GoAhead Embedded Management Framework defines - */ - websSetEmfEnvironment(wp); -#endif -} - -/******************************************************************************/ -/* - * Define a webs (CGI) variable for this connection. Also create in relevant - * scripting engines. Note: the incoming value may be volatile. - */ - -void websSetVar(webs_t wp, char_t *var, char_t *value) -{ - value_t v; - - a_assert(websValid(wp)); - -/* - * value_instring will allocate the string if required. - */ - if (value) { - v = valueString(value, VALUE_ALLOCATE); - } else { - v = valueString(T(""), VALUE_ALLOCATE); - } - symEnter(wp->cgiVars, var, v, 0); -} - -/******************************************************************************/ -/* - * Return TRUE if a webs variable exists for this connection. - */ - -int websTestVar(webs_t wp, char_t *var) -{ - sym_t *sp; - - a_assert(websValid(wp)); - - if (var == NULL || *var == '\0') { - return 0; - } - - if ((sp = symLookup(wp->cgiVars, var)) == NULL) { - return 0; - } - return 1; -} - -/******************************************************************************/ -/* - * Get a webs variable but return a default value if string not found. - * Note, defaultGetValue can be NULL to permit testing existence. - */ - -char_t *websGetVar(webs_t wp, char_t *var, char_t *defaultGetValue) -{ - sym_t *sp; - - a_assert(websValid(wp)); - a_assert(var && *var); - - if ((sp = symLookup(wp->cgiVars, var)) != NULL) { - a_assert(sp->content.type == string); - if (sp->content.value.string) { - return sp->content.value.string; - } else { - return T(""); - } - } - return defaultGetValue; -} - -/******************************************************************************/ -/* - * Return TRUE if a webs variable is set to a given value - */ - -int websCompareVar(webs_t wp, char_t *var, char_t *value) -{ - a_assert(websValid(wp)); - a_assert(var && *var); - - if (gstrcmp(value, websGetVar(wp, var, T(" __UNDEF__ "))) == 0) { - return 1; - } - return 0; -} - -/******************************************************************************/ -/* - * Cancel the request timeout. Note may be called multiple times. - */ - -void websTimeoutCancel(webs_t wp) -{ - a_assert(websValid(wp)); - - if (wp->timeout >= 0) { - emfUnschedCallback(wp->timeout); - wp->timeout = -1; - } -} - -/******************************************************************************/ -/* - * Output a HTTP response back to the browser. If redirect is set to a - * URL, the browser will be sent to this location. - */ - -void websResponse(webs_t wp, int code, char_t *message, char_t *redirect) -{ - char_t *date; - - a_assert(websValid(wp)); - -/* - * IE3.0 needs no Keep Alive for some return codes. - */ - wp->flags &= ~WEBS_KEEP_ALIVE; - -/* - * Only output the header if a header has not already been output. - */ - if ( !(wp->flags & WEBS_HEADER_DONE)) { - wp->flags |= WEBS_HEADER_DONE; -/* - * Redirect behaves much better when sent with HTTP/1.0 - */ - if (redirect != NULL) { - websWrite(wp, T("HTTP/1.0 %d %s\r\n"), code, websErrorMsg(code)); - } else { - websWrite(wp, T("HTTP/1.1 %d %s\r\n"), code, websErrorMsg(code)); - } - -/* - * By license terms the following line of code must not be modified. - */ - websWrite(wp, T("Server: %s\r\n"), WEBS_NAME); - -/* - * Timestamp/Date is usually the next to go - */ - if ((date = websGetDateString(NULL)) != NULL) { - websWrite(wp, T("Date: %s\r\n"), date); - bfree(B_L, date); - } -/* - * If authentication is required, send the auth header info - */ - if (code == 401) { - if (!(wp->flags & WEBS_AUTH_DIGEST)) { - websWrite(wp, T("WWW-Authenticate: Basic realm=\"%s\"\r\n"), - websGetRealm()); -#ifdef DIGEST_ACCESS_SUPPORT - } else { - char_t *nonce, *opaque; - - /* $$$ before... (note commas instead of semicolons...) - nonce = websCalcNonce(wp), - opaque = websCalcOpaque(wp), - $$$ after */ - nonce = websCalcNonce(wp); - opaque = websCalcOpaque(wp); - /* ...$$$ end */ - websWrite(wp, - T("WWW-Authenticate: Digest realm=\"%s\", domain=\"%s\",") - T("qop=\"%s\", nonce=\"%s\", opaque=\"%s\",") - T("algorithm=\"%s\", stale=\"%s\"\r\n"), - websGetRealm(), - websGetHostUrl(), - T("auth"), - nonce, - opaque, T("MD5"), T("FALSE")); - bfree(B_L, nonce); - bfree(B_L, opaque); -#endif - } - } - - if (wp->flags & WEBS_KEEP_ALIVE) { - websWrite(wp, T("Connection: keep-alive\r\n")); - } - - websWrite(wp, T("Pragma: no-cache\r\nCache-Control: no-cache\r\n")); - websWrite(wp, T("Content-Type: text/html\r\n")); -/* - * We don't do a string length here as the message may be multi-line. - * Ie. <CR><LF> will count as only one and we will have a content-length - * that is too short. - * - * websWrite(wp, T("Content-Length: %s\r\n"), message); - */ - if (redirect) { - websWrite(wp, T("Location: %s\r\n"), redirect); - } - websWrite(wp, T("\r\n")); - } - -/* - * If the browser didn't do a HEAD only request, send the message as well. - */ - if ((wp->flags & WEBS_HEAD_REQUEST) == 0 && message && *message) { - websWrite(wp, T("%s\r\n"), message); - } - websDone(wp, code); -} - -/******************************************************************************/ -/* - * Redirect the user to another webs page - */ - -void websRedirect(webs_t wp, char_t *url) -{ - char_t *msgbuf, *urlbuf, *redirectFmt; - - a_assert(websValid(wp)); - a_assert(url); - - websStats.redirects++; - msgbuf = urlbuf = NULL; - -/* - * Some browsers require a http://host qualified URL for redirection - */ - if (gstrstr(url, T("http://")) == NULL) { - if (*url == '/') { - url++; - } - - redirectFmt = T("http://%s/%s"); - -#ifdef WEBS_SSL_SUPPORT - if (wp->flags & WEBS_SECURE) { - redirectFmt = T("https://%s/%s"); - } -#endif - - fmtAlloc(&urlbuf, WEBS_MAX_URL + 80, redirectFmt, - websGetVar(wp, T("HTTP_HOST"), websHostUrl), url); - url = urlbuf; - } - -/* - * Add human readable message for completeness. Should not be required. - */ - fmtAlloc(&msgbuf, WEBS_MAX_URL + 80, - T("<html><head></head><body>\r\n\ - This document has moved to a new <a href=\"%s\">location</a>.\r\n\ - Please update your documents to reflect the new location.\r\n\ - </body></html>\r\n"), url); - - websResponse(wp, 302, msgbuf, url); - - bfreeSafe(B_L, msgbuf); - bfreeSafe(B_L, urlbuf); -} - -/******************************************************************************/ -/* - * Output an error message and cleanup - */ - -#ifdef qRichErrorPage -extern int dmfRichError(webs_t wp, int code, char_t* userMsg); -#endif -void websError(webs_t wp, int code, char_t *fmt, ...) -{ - va_list args; - char_t *msg, *userMsg, *buf; -#ifdef qRichErrorPage - static int reEntry = 0; - int errorOk; -#endif - - a_assert(websValid(wp)); - a_assert(fmt); - - websStats.errors++; - - va_start(args, fmt); - userMsg = NULL; - fmtValloc(&userMsg, WEBS_BUFSIZE, fmt, args); - va_end(args); - -#ifdef qRichErrorPage - if (!reEntry) - { - /* - * The dmfRichError function that we're about to call may very well call - * websError() as part of its work. If that happens, we do NOT want to - * get into a never-ending recursive call chain. When we get back here - * in a call from inside dmfRichError(), we check to see if we're - * already trying to call dmfRichError. If we are, we just revert to the - * old non-rich behavior and display a black on white error page. - */ - - reEntry = 1; - errorOk = dmfRichError(wp, code, userMsg); - reEntry = 0; - if (errorOk) - { - return; - } - /* ...else we need to fall through and execute the simple error page. */ - } - /* implicit else... */ -#endif - - msg = T("<html><head><title>Document Error: %s</title></head>\r\n\ - <body><h2>Access Error: %s</h2>\r\n\ - when trying to obtain <b>%s</b><br><p>%s</p></body></html>\r\n"); -/* - * Ensure we have plenty of room - */ - buf = NULL; - fmtAlloc(&buf, WEBS_BUFSIZE, msg, websErrorMsg(code), - websErrorMsg(code), wp->url, userMsg); - - websResponse(wp, code, buf, NULL); - bfreeSafe(B_L, buf); - bfreeSafe(B_L, userMsg); -} - -/******************************************************************************/ -/* - * Return the error message for a given code - */ - -/*static char_t *websErrorMsg(int code)*/ -char_t *websErrorMsg(int code) -{ - websErrorType *ep; - - for (ep = websErrors; ep->code; ep++) { - if (code == ep->code) { - return ep->msg; - } - } - a_assert(0); - return T(""); -} - -/******************************************************************************/ -/* - * Do formatted output to the browser. This is the public ASP and form - * write procedure. - */ - -int websWrite(webs_t wp, char_t *fmt, ...) -{ - va_list vargs; - char_t *buf; - int rc; - - a_assert(websValid(wp)); - - va_start(vargs, fmt); - - buf = NULL; - rc = 0; - - if (fmtValloc(&buf, WEBS_BUFSIZE, fmt, vargs) >= WEBS_BUFSIZE) { - trace(0, T("webs: websWrite lost data, buffer overflow\n")); - } - - va_end(vargs); - a_assert(buf); - if (buf) { - rc = websWriteBlock(wp, buf, gstrlen(buf)); - bfree(B_L, buf); - } - return rc; -} - -/******************************************************************************/ -/* - * Write a block of data of length "nChars" to the user's browser. Public - * write block procedure. If unicode is turned on this function expects - * buf to be a unicode string and it converts it to ASCII before writing. - * See websWriteDataNonBlock to always write binary or ASCII data with no - * unicode conversion. This returns the number of char_t's processed. - * It spins until nChars are flushed to the socket. For non-blocking - * behavior, use websWriteDataNonBlock. - */ - -int websWriteBlock(webs_t wp, char_t *buf, int nChars) -{ - int len, done; - char *asciiBuf, *pBuf; - - a_assert(wp); - a_assert(websValid(wp)); - a_assert(buf); - a_assert(nChars >= 0); - - done = len = 0; - -/* - * ballocUniToAsc will convert Unicode to strings to Ascii. If Unicode is - * not turned on then ballocUniToAsc will not do the conversion. - */ - pBuf = asciiBuf = ballocUniToAsc(buf, nChars); - - while (nChars > 0) { -#ifdef WEBS_SSL_SUPPORT - if (wp->flags & WEBS_SECURE) { - if ((len = websSSLWrite(wp->wsp, pBuf, nChars)) < 0) { - bfree(B_L, asciiBuf); - return -1; - } - websSSLFlush(wp->wsp); - } else { - if ((len = socketWrite(wp->sid, pBuf, nChars)) < 0) { - bfree(B_L, asciiBuf); - return -1; - } - socketFlush(wp->sid); - } -#else /* ! WEBS_SSL_SUPPORT */ - if ((len = socketWrite(wp->sid, pBuf, nChars)) < 0) { - bfree(B_L, asciiBuf); - return -1; - } - socketFlush(wp->sid); -#endif /* WEBS_SSL_SUPPORT */ - nChars -= len; - pBuf += len; - done += len; - } - - bfree(B_L, asciiBuf); - return done; -} - -/******************************************************************************/ -/* - * Write a block of data of length "nChars" to the user's browser. Same as - * websWriteBlock except that it expects straight ASCII or binary and does no - * unicode conversion before writing the data. If the socket cannot hold all - * the data, it will return the number of bytes flushed to the socket before - * it would have blocked. This returns the number of chars processed or -1 - * if socketWrite fails. - */ - -int websWriteDataNonBlock(webs_t wp, char *buf, int nChars) -{ - int r; - - a_assert(wp); - a_assert(websValid(wp)); - a_assert(buf); - a_assert(nChars >= 0); - -#ifdef WEBS_SSL_SUPPORT - if (wp->flags & WEBS_SECURE) { - r = websSSLWrite(wp->wsp, buf, nChars); - websSSLFlush(wp->wsp); - } else { - r = socketWrite(wp->sid, buf, nChars); - socketFlush(wp->sid); - } -#else - r = socketWrite(wp->sid, buf, nChars); - socketFlush(wp->sid); -#endif - - return r; -} - -/******************************************************************************/ -/* - * Decode a URL (or part thereof). Allows insitu decoding. - */ - -void websDecodeUrl(char_t *decoded, char_t *token, int len) -{ - unsigned char *ip; - char_t *op; - int num, i, c; - - a_assert(decoded); - a_assert(token); - - op = decoded; - for (ip = (unsigned char *)token; *ip && len > 0; ip++, op++) { - if (*ip == '+') { - *op = ' '; - } else if (*ip == '%' && gisxdigit(ip[1]) && gisxdigit(ip[2])) { - -/* - * Convert %nn to a single character - */ - ip++; - for (i = 0, num = 0; i < 2; i++, ip++) { - c = tolower(*ip); - if (c >= 'a' && c <= 'f') { - num = (num * 16) + 10 + c - 'a'; - } else { - num = (num * 16) + c - '0'; - } - } - *op = (char_t) num; - ip--; - - } else { - *op = *ip; - } - len--; - } - *op = '\0'; -} - -/******************************************************************************/ -#ifdef WEBS_LOG_SUPPORT -/* - * Output a log message - */ - -static void websLog(webs_t wp, int code) -{ - char_t *buf; - char *abuf; - int len; -#define qAnlLog 1 -#ifdef qAnlLog - time_t timer; - char_t* newLine = NULL; - char_t* timeStr = NULL; -#endif - a_assert(websValid(wp)); - - buf = NULL; - -#ifdef qAnlLog - time(&timer); - timeStr = ctime(&timer); - newLine = gstrchr(timeStr, '\n'); - if (newLine) - { - *newLine = '\0'; - } - fmtAlloc(&buf, WEBS_MAX_URL + 80, T("%s\t%s\t%s\tcode = %d\n"), - timeStr, wp->ipaddr, wp->url, code); -#else - fmtAlloc(&buf, WEBS_MAX_URL + 80, T("%d %s %d %d\n"), time(0), - wp->url, code, wp->written); -#endif - len = gstrlen(buf); - abuf = ballocUniToAsc(buf, len+1); - write(websLogFd, abuf, len); - bfreeSafe(B_L, buf); - bfreeSafe(B_L, abuf); -} - -#endif /* WEBS_LOG_SUPPORT */ - -/******************************************************************************/ -/* - * Request timeout. The timeout triggers if we have not read any data from - * the users browser in the last WEBS_TIMEOUT period. If we have heard from - * the browser, simply re-issue the timeout. - */ - -void websTimeout(void *arg, int id) -{ - webs_t wp; - int delay, tm; - - wp = (webs_t) arg; - a_assert(websValid(wp)); - - tm = websGetTimeSinceMark(wp) * 1000; - if (tm >= WEBS_TIMEOUT) { - websStats.timeouts++; - emfUnschedCallback(id); - -/* - * Clear the timeout id - */ - wp->timeout = -1; - websDone(wp, 404); - } else { - delay = WEBS_TIMEOUT - tm; - a_assert(delay > 0); - emfReschedCallback(id, delay); - } -} - -/******************************************************************************/ -/* - * Called when the request is done. - */ - -void websDone(webs_t wp, int code) -{ - a_assert(websValid(wp)); - -/* - * Disable socket handler in case keep alive set. - */ - socketDeleteHandler(wp->sid); - - if (code != 200) { - wp->flags &= ~WEBS_KEEP_ALIVE; - } - -#ifdef WEBS_PROXY_SUPPORT - if (! (wp->flags & WEBS_LOCAL_PAGE)) { - websStats.activeNetRequests--; - } -#endif - -#ifdef WEBS_LOG_SUPPORT - if (! (wp->flags & WEBS_REQUEST_DONE)) { - websLog(wp, code); - } -#endif - -/* - * Close any opened document by a handler - */ - websPageClose(wp); - -/* - * Exit if secure. - */ -#ifdef WEBS_SSL_SUPPORT - if (wp->flags & WEBS_SECURE) { - websTimeoutCancel(wp); - websSSLFlush(wp->wsp); - socketCloseConnection(wp->sid); - websFree(wp); - return; - } -#endif - -/* - * If using Keep Alive (HTTP/1.1) we keep the socket open for a period - * while waiting for another request on the socket. - */ - if (wp->flags & WEBS_KEEP_ALIVE) { - if (socketFlush(wp->sid) == 0) { - wp->state = WEBS_BEGIN; - wp->flags |= WEBS_REQUEST_DONE; - if (wp->header.buf) { - ringqFlush(&wp->header); - } - socketCreateHandler(wp->sid, SOCKET_READABLE, websSocketEvent, - (int) wp); - websTimeoutCancel(wp); - wp->timeout = emfSchedCallback(WEBS_TIMEOUT, websTimeout, - (void *) wp); - return; - } - } else { - websTimeoutCancel(wp); - socketSetBlock(wp->sid, 1); - socketFlush(wp->sid); - socketCloseConnection(wp->sid); - } - websFree(wp); -} - -/******************************************************************************/ -/* - * Allocate a new webs structure - */ - -int websAlloc(int sid) -{ - webs_t wp; - int wid; - -/* - * Allocate a new handle for this connection - */ - if ((wid = hAllocEntry((void*) &webs, &websMax, - sizeof(struct websRec))) < 0) { - return -1; - } - wp = webs[wid]; - - wp->wid = wid; - wp->sid = sid; - wp->state = WEBS_BEGIN; - wp->docfd = -1; - wp->timeout = -1; - wp->dir = NULL; - wp->authType = NULL; - wp->protocol = NULL; - wp->protoVersion = NULL; - wp->password = NULL; - wp->userName = NULL; -#ifdef DIGEST_ACCESS_SUPPORT - wp->realm = NULL; - wp->nonce = NULL; - wp->digest = NULL; - wp->uri = NULL; - wp->opaque = NULL; - wp->nc = NULL; - wp->cnonce = NULL; - wp->qop = NULL; -#endif -#ifdef WEBS_SSL_SUPPORT - wp->wsp = NULL; -#endif - - ringqOpen(&wp->header, WEBS_HEADER_BUFINC, WEBS_MAX_HEADER); - -/* - * Create storage for the CGI variables. We supply the symbol tables for - * both the CGI variables and for the global functions. The function table - * is common to all webs instances (ie. all browsers) - */ - wp->cgiVars = symOpen(WEBS_SYM_INIT); - - return wid; -} - -/******************************************************************************/ -/* - * Free a webs structure - */ - -void websFree(webs_t wp) -{ - a_assert(websValid(wp)); - - if (wp->path) - bfree(B_L, wp->path); - if (wp->url) - bfree(B_L, wp->url); - if (wp->host) - bfree(B_L, wp->host); - if (wp->lpath) - bfree(B_L, wp->lpath); - if (wp->query) - bfree(B_L, wp->query); - if (wp->decodedQuery) - bfree(B_L, wp->decodedQuery); - if (wp->authType) - bfree(B_L, wp->authType); - if (wp->password) - bfree(B_L, wp->password); - if (wp->userName) - bfree(B_L, wp->userName); - if (wp->cookie) - bfree(B_L, wp->cookie); - if (wp->userAgent) - bfree(B_L, wp->userAgent); - if (wp->dir) - bfree(B_L, wp->dir); - if (wp->protocol) - bfree(B_L, wp->protocol); - if (wp->protoVersion) - bfree(B_L, wp->protoVersion); - if (wp->cgiStdin) - bfree(B_L, wp->cgiStdin); - - -#ifdef DIGEST_ACCESS_SUPPORT - if (wp->realm) - bfree(B_L, wp->realm); - if (wp->uri) - bfree(B_L, wp->uri); - if (wp->digest) - bfree(B_L, wp->digest); - if (wp->opaque) - bfree(B_L, wp->opaque); - if (wp->nonce) - bfree(B_L, wp->nonce); - if (wp->nc) - bfree(B_L, wp->nc); - if (wp->cnonce) - bfree(B_L, wp->cnonce); - if (wp->qop) - bfree(B_L, wp->qop); -#endif -#ifdef WEBS_SSL_SUPPORT - websSSLFree(wp->wsp); -#endif - symClose(wp->cgiVars); - - if (wp->header.buf) { - ringqClose(&wp->header); - } - - websMax = hFree((void*) &webs, wp->wid); - bfree(B_L, wp); - a_assert(websMax >= 0); -} - -/******************************************************************************/ -/* - * Return the server address - */ - -char_t *websGetHost(void) -{ - return websHost; -} - -/******************************************************************************/ -/* - * Return the the url to access the server. (ip address) - */ - -char_t *websGetIpaddrUrl(void) -{ - return websIpaddrUrl; -} - -/******************************************************************************/ -/* - * Return the server address - */ - -char_t *websGetHostUrl(void) -{ - return websHostUrl; -} - -/******************************************************************************/ -/* - * Return the listen port - */ - -int websGetPort(void) -{ - return websPort; -} - -/******************************************************************************/ -/* - * Get the number of bytes to write - */ - -int websGetRequestBytes(webs_t wp) -{ - a_assert(websValid(wp)); - - return wp->numbytes; -} - -/******************************************************************************/ -/* - * Get the directory for this request - */ - -char_t *websGetRequestDir(webs_t wp) -{ - a_assert(websValid(wp)); - - if (wp->dir == NULL) { - return T(""); - } - - return wp->dir; -} - -/******************************************************************************/ -/* - * Get the flags for this request - */ - -int websGetRequestFlags(webs_t wp) -{ - a_assert(websValid(wp)); - - return wp->flags; -} - -/******************************************************************************/ -/* - * Return the IP address - */ - -char_t *websGetRequestIpaddr(webs_t wp) -{ - a_assert(websValid(wp)); - - return wp->ipaddr; -} - -/******************************************************************************/ -/* - * Set the local path for the request - */ - -char_t *websGetRequestLpath(webs_t wp) -{ - a_assert(websValid(wp)); - -#ifdef WEBS_PAGE_ROM - return wp->path; -#else - return wp->lpath; -#endif -} - -/******************************************************************************/ -/* - * Get the path for this request - */ - -char_t *websGetRequestPath(webs_t wp) -{ - a_assert(websValid(wp)); - - if (wp->path == NULL) { - return T(""); - } - - return wp->path; -} - -/******************************************************************************/ -/* - * Return the password - */ - -char_t *websGetRequestPassword(webs_t wp) -{ - a_assert(websValid(wp)); - - return wp->password; -} - -/******************************************************************************/ -/* - * Return the request type - */ - -char_t *websGetRequestType(webs_t wp) -{ - a_assert(websValid(wp)); - - return wp->type; -} - -/******************************************************************************/ -/* - * Return the username - */ - -char_t *websGetRequestUserName(webs_t wp) -{ - a_assert(websValid(wp)); - - return wp->userName; -} - -/******************************************************************************/ -/* - * Get the number of bytes written - */ - -int websGetRequestWritten(webs_t wp) -{ - a_assert(websValid(wp)); - - return wp->written; -} - -/******************************************************************************/ -/* - * Set the hostname - */ - -void websSetHost(char_t *host) -{ - gstrncpy(websHost, host, TSZ(websHost)); -} - -/******************************************************************************/ -/* - * Set the host URL - */ - -void websSetHostUrl(char_t *url) -{ - a_assert(url && *url); - - bfreeSafe(B_L, websHostUrl); - websHostUrl = gstrdup(B_L, url); -} - -/******************************************************************************/ -/* - * Set the IP address - */ - -void websSetIpaddr(char_t *ipaddr) -{ - a_assert(ipaddr && *ipaddr); - - gstrncpy(websIpaddr, ipaddr, TSZ(websIpaddr)); -} - -/******************************************************************************/ -/* - * Set the number of bytes to write - */ - -void websSetRequestBytes(webs_t wp, int bytes) -{ - a_assert(websValid(wp)); - a_assert(bytes >= 0); - - wp->numbytes = bytes; -} - -/******************************************************************************/ -/* - * Set the flags for this request - */ - -void websSetRequestFlags(webs_t wp, int flags) -{ - a_assert(websValid(wp)); - - wp->flags = flags; -} - -/******************************************************************************/ -/* - * Set the local path for the request - */ - -void websSetRequestLpath(webs_t wp, char_t *lpath) -{ - a_assert(websValid(wp)); - a_assert(lpath && *lpath); - - if (wp->lpath) { - bfree(B_L, wp->lpath); - } - wp->lpath = bstrdup(B_L, lpath); - websSetVar(wp, T("PATH_TRANSLATED"), wp->lpath); -} - -/******************************************************************************/ -/* - * Update the URL path and the directory containing the web page - */ - -void websSetRequestPath(webs_t wp, char_t *dir, char_t *path) -{ - char_t *tmp; - - a_assert(websValid(wp)); - - if (dir) { - tmp = wp->dir; - wp->dir = bstrdup(B_L, dir); - if (tmp) { - bfree(B_L, tmp); - } - } - if (path) { - tmp = wp->path; - wp->path = bstrdup(B_L, path); - websSetVar(wp, T("PATH_INFO"), wp->path); - if (tmp) { - bfree(B_L, tmp); - } - } -} - -/******************************************************************************/ -/* - * Set the Write handler for this socket - */ - -void websSetRequestSocketHandler(webs_t wp, int mask, void (*fn)(webs_t wp)) -{ - a_assert(websValid(wp)); - - wp->writeSocket = fn; - socketCreateHandler(wp->sid, SOCKET_WRITABLE, websSocketEvent, (int) wp); -} - -/******************************************************************************/ -/* - * Set the number of bytes written - */ - -void websSetRequestWritten(webs_t wp, int written) -{ - a_assert(websValid(wp)); - - wp->written = written; -} - -/******************************************************************************/ -/* - * Reurn true if the webs handle is valid - */ - -int websValid(webs_t wp) -{ - int wid; - - for (wid = 0; wid < websMax; wid++) { - if (wp == webs[wid]) { - return 1; - } - } - return 0; -} - -/******************************************************************************/ -/* - * Build an ASCII time string. If sbuf is NULL we use the current time, - * else we use the last modified time of sbuf; - */ - -char_t *websGetDateString(websStatType *sbuf) -{ - char_t* cp, *r; - time_t now; - - if (sbuf == NULL) { - time(&now); - } else { - now = sbuf->mtime; - } - if ((cp = gctime(&now)) != NULL) { - cp[gstrlen(cp) - 1] = '\0'; - r = bstrdup(B_L, cp); - return r; - } - return NULL; -} - -/******************************************************************************/ -/* - * Mark time. Set a timestamp so that, later, we can return the number of - * seconds since we made the mark. Note that the mark my not be a - * "real" time, but rather a relative marker. - */ - -void websSetTimeMark(webs_t wp) -{ - wp->timestamp = time(0); -} - -/******************************************************************************/ -/* - * Get the number of seconds since the last mark. - */ - -static int websGetTimeSinceMark(webs_t wp) -{ - return time(0) - wp->timestamp; -} - -/******************************************************************************/ -/* - * Store the new realm name - */ - -void websSetRealm(char_t *realmName) -{ - a_assert(realmName); - - gstrncpy(websRealm, realmName, TSZ(websRealm)); -} - -/******************************************************************************/ -/* - * Return the realm name (used for authorization) - */ - -char_t *websGetRealm(void) -{ - return websRealm; -} - - -#ifdef WEBS_IF_MODIFIED_SUPPORT -/******************************************************************************/ -/* - * These functions are intended to closely mirror the syntax for HTTP-date - * from RFC 2616 (HTTP/1.1 spec). This code was submitted by Pete Bergstrom. - */ - -/* - * RFC1123Date = wkday "," SP date1 SP time SP "GMT" - * RFC850Date = weekday "," SP date2 SP time SP "GMT" - * ASCTimeDate = wkday SP date3 SP time SP 4DIGIT - * - * Each of these functions tries to parse the value and update the index to - * the point it leaves off parsing. - */ - -typedef enum { JAN, FEB, MAR, APR, MAY, JUN, JUL, AUG, SEP, OCT, NOV, DEC } MonthEnumeration; -typedef enum { SUN, MON, TUE, WED, THU, FRI, SAT } WeekdayEnumeration; - -/******************************************************************************/ -/* - * Parse an N-digit value - */ - -static int parseNDIGIT(char_t *buf, int digits, int *index) -{ - int tmpIndex, returnValue; - - returnValue = 0; - - for (tmpIndex = *index; tmpIndex < *index+digits; tmpIndex++) { - if (gisdigit(buf[tmpIndex])) { - returnValue = returnValue * 10 + (buf[tmpIndex] - T('0')); - } - } - *index = tmpIndex; - - return returnValue; -} - -/******************************************************************************/ -/* - * Return an index into the month array - */ - -static int parseMonth(char_t *buf, int *index) -{ -/* - * "Jan" | "Feb" | "Mar" | "Apr" | "May" | "Jun" | - * "Jul" | "Aug" | "Sep" | "Oct" | "Nov" | "Dec" - */ - int tmpIndex, returnValue; - - returnValue = -1; - tmpIndex = *index; - - switch (buf[tmpIndex]) { - case 'A': - switch (buf[tmpIndex+1]) { - case 'p': - returnValue = APR; - break; - case 'u': - returnValue = AUG; - break; - } - break; - case 'D': - returnValue = DEC; - break; - case 'F': - returnValue = FEB; - break; - case 'J': - switch (buf[tmpIndex+1]) { - case 'a': - returnValue = JAN; - break; - case 'u': - switch (buf[tmpIndex+2]) { - case 'l': - returnValue = JUL; - break; - case 'n': - returnValue = JUN; - break; - } - break; - } - break; - case 'M': - switch (buf[tmpIndex+1]) { - case 'a': - switch (buf[tmpIndex+2]) { - case 'r': - returnValue = MAR; - break; - case 'y': - returnValue = MAY; - break; - } - break; - } - break; - case 'N': - returnValue = NOV; - break; - case 'O': - returnValue = OCT; - break; - case 'S': - returnValue = SEP; - break; - } - - if (returnValue >= 0) { - *index += 3; - } - - return returnValue; -} - -/******************************************************************************/ -/* - * Parse a year value (either 2 or 4 digits) - */ - -static int parseYear(char_t *buf, int *index) -{ - int tmpIndex, returnValue; - - tmpIndex = *index; - returnValue = parseNDIGIT(buf, 4, &tmpIndex); - - if (returnValue >= 0) { - *index = tmpIndex; - } else { - returnValue = parseNDIGIT(buf, 2, &tmpIndex); - if (returnValue >= 0) { -/* - * Assume that any year earlier than the start of the - * epoch for time_t (1970) specifies 20xx - */ - if (returnValue < 70) { - returnValue += 2000; - } else { - returnValue += 1900; - } - - *index = tmpIndex; - } - } - - return returnValue; -} - -/******************************************************************************/ -/* - * The formulas used to build these functions are from "Calendrical Calculations", - * by Nachum Dershowitz, Edward M. Reingold, Cambridge University Press, 1997. - */ - -#include <math.h> - -const int GregorianEpoch = 1; - -/******************************************************************************/ -/* - * Determine if year is a leap year - */ - -int GregorianLeapYearP(long year) -{ - int result; - long tmp; - - tmp = year % 400; - - if ((year % 4 == 0) && - (tmp != 100) && - (tmp != 200) && - (tmp != 300)) { - result = TRUE; - } else { - result = FALSE; - } - - return result; -} - -/******************************************************************************/ -/* - * Return the fixed date from the gregorian date - */ - -long FixedFromGregorian(long month, long day, long year) -{ - long fixedDate; - - fixedDate = (long)(GregorianEpoch - 1 + 365 * (year - 1) + - floor((year - 1) / 4.0) - - floor((double)(year - 1) / 100.0) + - floor((double)(year - 1) / 400.0) + - floor((367.0 * ((double)month) - 362.0) / 12.0)); - - if (month <= 2) { - fixedDate += 0; - } else if (TRUE == GregorianLeapYearP(year)) { - fixedDate += -1; - } else { - fixedDate += -2; - } - - fixedDate += day; - - return fixedDate; -} - -/******************************************************************************/ -/* - * Return the gregorian year from a fixed date - */ - -long GregorianYearFromFixed(long fixedDate) -{ - long result, d0, n400, d1, n100, d2, n4, d3, n1, d4, year; - - d0 = fixedDate - GregorianEpoch; - n400 = (long)(floor((double)d0 / (double)146097)); - d1 = d0 % 146097; - n100 = (long)(floor((double)d1 / (double)36524)); - d2 = d1 % 36524; - n4 = (long)(floor((double)d2 / (double)1461)); - d3 = d2 % 1461; - n1 = (long)(floor((double)d3 / (double)365)); - d4 = (d3 % 365) + 1; - year = 400 * n400 + 100 * n100 + 4 * n4 + n1; - - if ((n100 == 4) || (n1 == 4)) { - result = year; - } else { - result = year + 1; - } - - return result; -} - -/******************************************************************************/ -/* - * Returns the Gregorian date from a fixed date - * (not needed for this use, but included for completeness - */ - -#if 0 -GregorianFromFixed(long fixedDate, long *month, long *day, long *year) -{ - long priorDays, correction; - - *year = GregorianYearFromFixed(fixedDate); - priorDays = fixedDate - FixedFromGregorian(1, 1, *year); - - if (fixedDate < FixedFromGregorian(3,1,*year)) { - correction = 0; - } else if (true == GregorianLeapYearP(*year)) { - correction = 1; - } else { - correction = 2; - } - - *month = (long)(floor((12.0 * (double)(priorDays + correction) + 373.0) / 367.0)); - *day = fixedDate - FixedFromGregorian(*month, 1, *year); -} -#endif - -/******************************************************************************/ -/* - * Returns the difference between two Gregorian dates - */ - -long GregorianDateDifference( long month1, long day1, long year1, - long month2, long day2, long year2) -{ - return FixedFromGregorian(month2, day2, year2) - - FixedFromGregorian(month1, day1, year1); -} - - -/******************************************************************************/ -/* - * Return the number of seconds into the current day - */ - -#define SECONDS_PER_DAY 24*60*60 - -static int parseTime(char_t *buf, int *index) -{ -/* - * Format of buf is - 2DIGIT ":" 2DIGIT ":" 2DIGIT - */ - int returnValue, tmpIndex, hourValue, minuteValue, secondValue; - - hourValue = minuteValue = secondValue = -1; - returnValue = -1; - tmpIndex = *index; - - hourValue = parseNDIGIT(buf, 2, &tmpIndex); - - if (hourValue >= 0) { - tmpIndex++; - minuteValue = parseNDIGIT(buf, 2, &tmpIndex); - if (minuteValue >= 0) { - tmpIndex++; - secondValue = parseNDIGIT(buf, 2, &tmpIndex); - } - } - - if ((hourValue >= 0) && - (minuteValue >= 0) && - (secondValue >= 0)) { - returnValue = (((hourValue * 60) + minuteValue) * 60) + secondValue; - *index = tmpIndex; - } - - return returnValue; -} - -/******************************************************************************/ -/* - * Return the equivalent of time() given a gregorian date - */ - -static time_t dateToTimet(int year, int month, int day) -{ - long dayDifference; - - /* - * Bug fix by Jeff Reeder (Jun 14, 2002): The 'month' parameter is - * numbered from 0 (Jan == 0), but FixedFromGregorian() takes - * months numbered from 1 (January == 1). We need to add 1 - * to the month - */ - dayDifference = FixedFromGregorian(month + 1, day, year) - - FixedFromGregorian(1, 1, 1970); - - return dayDifference * SECONDS_PER_DAY; -} - -/******************************************************************************/ -/* - * Return the number of seconds between Jan 1, 1970 and the parsed date - * (corresponds to documentation for time() function) - */ - -static time_t parseDate1or2(char_t *buf, int *index) -{ -/* - * Format of buf is either - * 2DIGIT SP month SP 4DIGIT - * or - * 2DIGIT "-" month "-" 2DIGIT - */ - int dayValue, monthValue, yearValue, tmpIndex; - time_t returnValue; - - returnValue = (time_t) -1; - tmpIndex = *index; - - dayValue = monthValue = yearValue = -1; - - if (buf[tmpIndex] == T(',')) { -/* - * Skip over the ", " - */ - tmpIndex += 2; - - dayValue = parseNDIGIT(buf, 2, &tmpIndex); - if (dayValue >= 0) { -/* - * Skip over the space or hyphen - */ - tmpIndex++; - monthValue = parseMonth(buf, &tmpIndex); - if (monthValue >= 0) { -/* - * Skip over the space or hyphen - */ - tmpIndex++; - yearValue = parseYear(buf, &tmpIndex); - } - } - - if ((dayValue >= 0) && - (monthValue >= 0) && - (yearValue >= 0)) { - if (yearValue < 1970) { -/* - * Allow for Microsoft IE's year 1601 dates - */ - returnValue = 0; - } else { - returnValue = dateToTimet(yearValue, monthValue, dayValue); - } - *index = tmpIndex; - } - } - - return returnValue; -} - -/******************************************************************************/ -/* - * Return the number of seconds between Jan 1, 1970 and the parsed date - */ - -static time_t parseDate3Time(char_t *buf, int *index) -{ -/* - * Format of buf is month SP ( 2DIGIT | ( SP 1DIGIT )) - */ - int dayValue, monthValue, yearValue, timeValue, tmpIndex; - time_t returnValue; - - returnValue = (time_t) -1; - tmpIndex = *index; - - dayValue = monthValue = yearValue = timeValue = -1; - - monthValue = parseMonth(buf, &tmpIndex); - if (monthValue >= 0) { -/* - * Skip over the space - */ - tmpIndex++; - if (buf[tmpIndex] == T(' ')) { -/* - * Skip over this space too - */ - tmpIndex++; - dayValue = parseNDIGIT(buf, 1, &tmpIndex); - } else { - dayValue = parseNDIGIT(buf, 2, &tmpIndex); - } -/* - * Now get the time and time SP 4DIGIT - */ - timeValue = parseTime(buf, &tmpIndex); - if (timeValue >= 0) { -/* - * Now grab the 4DIGIT year value - */ - yearValue = parseYear(buf, &tmpIndex); - } - } - - if ((dayValue >= 0) && - (monthValue >= 0) && - (yearValue >= 0)) { - returnValue = dateToTimet(yearValue, monthValue, dayValue); - returnValue += timeValue; - *index = tmpIndex; - } - - return returnValue; -} - - -/******************************************************************************/ -/* - * Although this looks like a trivial function, I found I was replicating the implementation - * seven times in the parseWeekday function. In the interests of minimizing code size - * and redundancy, it is broken out into a separate function. The cost of an extra - * function call I can live with given that it should only be called once per HTTP request. - */ - -static int bufferIndexIncrementGivenNTest(char_t *buf, int testIndex, char_t testChar, - int foundIncrement, int notfoundIncrement) -{ - if (buf[testIndex] == testChar) { - return foundIncrement; - } - - return notfoundIncrement; -} - -/******************************************************************************/ -/* - * Return an index into a logical weekday array - */ - -static int parseWeekday(char_t *buf, int *index) -{ -/* - * Format of buf is either - * "Mon" | "Tue" | "Wed" | "Thu" | "Fri" | "Sat" | "Sun" - * or - * "Monday" | "Tuesday" | "Wednesday" | "Thursday" | "Friday" | "Saturday" | "Sunday" - */ - int tmpIndex, returnValue; - - returnValue = -1; - tmpIndex = *index; - - switch (buf[tmpIndex]) { - case 'F': - returnValue = FRI; - *index += bufferIndexIncrementGivenNTest(buf, tmpIndex+3, 'd', sizeof("Friday"), 3); - break; - case 'M': - returnValue = MON; - *index += bufferIndexIncrementGivenNTest(buf, tmpIndex+3, 'd', sizeof("Monday"), 3); - break; - case 'S': - switch (buf[tmpIndex+1]) { - case 'a': - returnValue = SAT; - *index += bufferIndexIncrementGivenNTest(buf, tmpIndex+3, 'u', sizeof("Saturday"), 3); - break; - case 'u': - returnValue = SUN; - *index += bufferIndexIncrementGivenNTest(buf, tmpIndex+3, 'd', sizeof("Sunday"), 3); - break; - } - break; - case 'T': - switch (buf[tmpIndex+1]) { - case 'h': - returnValue = THU; - *index += bufferIndexIncrementGivenNTest(buf, tmpIndex+3, 'r', sizeof("Thursday"), 3); - break; - case 'u': - returnValue = TUE; - *index += bufferIndexIncrementGivenNTest(buf, tmpIndex+3, 's', sizeof("Tuesday"), 3); - break; - } - break; - case 'W': - returnValue = WED; - *index += bufferIndexIncrementGivenNTest(buf, tmpIndex+3, 'n', sizeof("Wednesday"), 3); - break; - } - return returnValue; -} - -/******************************************************************************/ -/* - * Parse the date and time string. - */ - -static time_t dateParse(time_t tip, char_t *cmd) -{ - int index, tmpIndex, weekday, timeValue; - time_t parsedValue, dateValue; - - parsedValue = (time_t) 0; - index = timeValue = 0; - weekday = parseWeekday(cmd, &index); - - if (weekday >= 0) { - tmpIndex = index; - dateValue = parseDate1or2(cmd, &tmpIndex); - if (dateValue >= 0) { - index = tmpIndex + 1; -/* - * One of these two forms is being used - * wkday "," SP date1 SP time SP "GMT" - * weekday "," SP date2 SP time SP "GMT" - */ - timeValue = parseTime(cmd, &index); - if (timeValue >= 0) { -/* - * Now match up that "GMT" string for completeness - * Compute the final value if there were no problems in the parse - */ - if ((weekday >= 0) && - (dateValue >= 0) && - (timeValue >= 0)) { - parsedValue = dateValue + timeValue; - } - } - } else { -/* - * Try the other form - wkday SP date3 SP time SP 4DIGIT - */ - tmpIndex = index; - parsedValue = parseDate3Time(cmd, &tmpIndex); - } - } - - return parsedValue; -} - -#endif /* WEBS_IF_MODIFIED_SUPPORT */ - -/******************************************************************************/ diff --git a/cpukit/httpd/webs.h b/cpukit/httpd/webs.h deleted file mode 100644 index 1bf96f8256..0000000000 --- a/cpukit/httpd/webs.h +++ /dev/null @@ -1,233 +0,0 @@ -/* - * webs.h -- GoAhead Web 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_WEBS -#define _h_WEBS 1 - -/******************************** Description *********************************/ - -/* - * 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. - */ - -/********************************* 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.3") - -#define WEBS_HEADER_BUFINC 512 /* Header buffer size */ -#define WEBS_ASP_BUFINC 512 /* Asp expansion increment */ -#define WEBS_MAX_PASS 32 /* Size of password */ -#define WEBS_BUFSIZE 1000 /* websWrite max output string */ -#define WEBS_MAX_HEADER (5 * 1024) /* Sanity check header */ -#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(). - */ -#define WEBS_LOCAL_PAGE 0x1 /* Request for local webs page */ -#define WEBS_KEEP_ALIVE 0x2 /* HTTP/1.1 keep alive */ -#define WEBS_DONT_USE_CACHE 0x4 /* Not implemented cache support */ -#define WEBS_COOKIE 0x8 /* Cookie supplied in request */ -#define WEBS_IF_MODIFIED 0x10 /* If-modified-since in request */ -#define WEBS_POST_REQUEST 0x20 /* Post request operation */ -#define WEBS_LOCAL_REQUEST 0x40 /* Request from this system */ -#define WEBS_HOME_PAGE 0x80 /* Request for the home page */ -#define WEBS_ASP 0x100 /* ASP request */ -#define WEBS_HEAD_REQUEST 0x200 /* Head request */ -#define WEBS_CLEN 0x400 /* Request had a content length */ -#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 */ - -/* - * URL handler flags - */ -#define WEBS_HANDLER_FIRST 0x1 /* Process this handler first */ -#define WEBS_HANDLER_LAST 0x2 /* Process this handler last */ - -/* - * Per socket connection webs structure - */ -typedef struct websRec { - ringq_t header; /* Header dynamic string */ - time_t since; /* Parsed if-modified-since time */ - sym_fd_t cgiVars; /* CGI standard variables */ - sym_fd_t cgiQuery; /* CGI decoded query string */ - time_t timestamp; /* Last transaction with browser */ - 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 *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 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); -extern void websCloseListen(void); -extern int websDecode64(char_t *outbuf, char_t *string, int buflen); -extern void websDecodeUrl(char_t *token, char_t *decoded, int len); -extern void websDone(webs_t wp, int code); -extern void websEncode64(char_t *outbuf, char_t *string, int buflen); -extern void websError(webs_t wp, int code, char_t *msg, ...); -/* function websErrorMsg() made extern 03 Jun 02 BgP */ -extern char_t *websErrorMsg(int code); -extern void websFooter(webs_t wp); -extern int websFormDefine(char_t *name, void (*fn)(webs_t wp, - char_t *path, char_t *query)); -extern char_t *websGetDefaultDir(void); -extern char_t *websGetDefaultPage(void); -extern char_t *websGetHostUrl(void); -extern char_t *websGetIpaddrUrl(void); -extern char_t *websGetPassword(void); -extern int websGetPort(void); -extern char_t *websGetPublishDir(char_t *path, char_t **urlPrefix); -extern char_t *websGetRealm(void); -extern int websGetRequestBytes(webs_t wp); -extern char_t *websGetRequestDir(webs_t wp); -extern int websGetRequestFlags(webs_t wp); -extern char_t *websGetRequestIpaddr(webs_t wp); -extern char_t *websGetRequestLpath(webs_t wp); -extern char_t *websGetRequestPath(webs_t wp); -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, - int mode, int perm); -extern void websPageClose(webs_t wp); -extern int websPublish(char_t *urlPrefix, char_t *path); -extern void websRedirect(webs_t wp, char_t *url); -extern void websSecurityDelete(void); -extern int websSecurityHandler(webs_t wp, char_t *urlPrefix, - char_t *webDir, int arg, char_t *url, char_t *path, - char_t *query); -extern void websSetDefaultDir(char_t *dir); -extern void websSetDefaultPage(char_t *page); -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); -extern void websSetRequestPath(webs_t wp, char_t *dir, char_t *path); -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, - char_t *query), int flags); -extern int websUrlHandlerDelete(int (*fn)(webs_t wp, char_t *urlPrefix, - char_t *webDir, int arg, char_t *url, char_t *path, - char_t *query)); -extern int websUrlHandlerRequest(webs_t wp); -extern int websUrlParse(char_t *url, char_t **buf, char_t **host, - char_t **path, char_t **port, char_t **query, - char_t **proto, char_t **tag, char_t **ext); -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 websWriteDataNonBlock(webs_t wp, char *buf, int nChars); -extern int websValid(webs_t wp); -extern int websValidateUrl(webs_t wp, char_t *path); -extern void websSetTimeMark(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 - * GoAhead Embedded Management Framework (EMF) - */ -#ifdef EMF -extern void websFormExplain(webs_t wp, char_t *path, char_t *query); -#endif - -#endif /* _h_WEBS */ - -/******************************************************************************/ diff --git a/cpukit/httpd/websSSL.c b/cpukit/httpd/websSSL.c deleted file mode 100644 index a3c3fdc232..0000000000 --- a/cpukit/httpd/websSSL.c +++ /dev/null @@ -1,706 +0,0 @@ -/* - * websSSL.c -- SSL envrionment creation - * - * Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved. - * - * See the file "license.txt" for usage and redistribution license requirements - * - * $Id$ - */ - -/******************************** Description *********************************/ - -/* - * This module implements a patch into SSL implementations for the webs - * module. - */ - -/********************************* Includes ***********************************/ - -#include "wsIntrn.h" -#include "webs.h" -#include "websSSL.h" - -/******************************* Definitions **********************************/ - -#define DEFAULT_CERT_FILE "./server.pem" -#define DEFAULT_KEY_FILE "./certs/cakey.pem" -#define DEFAULT_CA_FILE "./certs/cacert.pem" -#define DEFAULT_CA_PATH "./certs/" -#define SSL_PORT 443 - -/* - * Define the components of the apps_startup() macro - */ - -#ifdef SIGPIPE -#define do_pipe_sig() signal(SIGPIPE,SIG_IGN) -#else -#define do_pipe_sig() -#endif - -#ifdef OPENSSL -#define SSLC_add_all_algorithms() SSLeay_add_all_algorithms() -#else -extern void SSLC_add_all_algorithms(void); -#endif - -/* - * Define the apps_startup() macro - */ - -# if defined(MSDOS) || defined(WIN16) || defined(WIN32) -# ifdef _O_BINARY -# define apps_startup() \ - _fmode=_O_BINARY; do_pipe_sig(); CRYPTO_malloc_init(); \ - SSLC_add_all_algorithms() -# else -# define apps_startup() \ - _fmode=O_BINARY; do_pipe_sig(); CRYPTO_malloc_init(); \ - SSLC_add_all_algorithms() -# endif -# else -# define apps_startup() do_pipe_sig(); SSLC_add_all_algorithms(); -# endif - -/*************************** Forward Declarations *****************************/ - -static int websSSLSetCertStuff(SSL_CTX *ctx, - char *cert_file, - char *key_file); -static int websSSLVerifyCallback(int ok, X509_STORE_CTX *ctx); -static RSA *websSSLTempRSACallback(SSL *s, int is_export, int keylength); - -static int websSSLReadEvent (webs_t wp); -static int websSSLAccept(int sid, char *ipaddr, int port, int listenSid); -static void websSSLSocketEvent(int sid, int mask, int data); - -/*********************************** Locals ***********************************/ - -static int sslListenSock = -1; /* Listen socket */ -static SSL_CTX *sslctx = NULL; - -/******************************************************************************/ -/* - * Start up the SSL Context for the application, and start a listen on the - * SSL port (usually 443, and defined by SSL_PORT) - * Return 0 on success, -1 on failure. - */ - -int websSSLOpen() -{ - char *certFile, *keyFile, *CApath, *CAfile; - SSL_METHOD *meth; - -/* - * Install and initialize the SSL library - */ - apps_startup(); - trace(7, T("SSL: Initializing SSL\n")); - -#ifdef SSLC - SSL_library_init(); -#endif - - SSL_load_error_strings(); - -#ifdef OPENSSL - SSLeay_add_ssl_algorithms(); -#endif - -/* - * Important! Enable both SSL versions 2 and 3 - */ - meth = SSLv23_server_method(); - sslctx = SSL_CTX_new(meth); - - a_assert(sslctx); - - if (sslctx == NULL) { - trace(2, T("SSL: Unable to create SSL context!\n")); - return -1; - } - -/* - * Adjust some SSL Context variables - */ - SSL_CTX_set_quiet_shutdown(sslctx, 1); - SSL_CTX_set_options(sslctx, 0); - SSL_CTX_sess_set_cache_size(sslctx, 128); - -/* - * Set the certificate verification locations - */ - CApath = DEFAULT_CA_PATH; - CAfile = DEFAULT_CA_FILE; - if ((!SSL_CTX_load_verify_locations(sslctx, CAfile, CApath)) || - (!SSL_CTX_set_default_verify_paths(sslctx))) { - trace(2, T("SSL: Unable to set cert verification locations!\n")); - websSSLClose(); - return -1; - } - -/* - * Set the certificate and key files for the SSL context - */ - certFile = DEFAULT_CERT_FILE; - keyFile = NULL; - if (websSSLSetCertStuff(sslctx, certFile, keyFile) != 0) { - websSSLClose(); - return -1; - } - -/* - * Set the RSA callback for the SSL context - */ - SSL_CTX_set_tmp_rsa_callback(sslctx, websSSLTempRSACallback); - -/* - * Set the verification callback for the SSL context - */ - SSL_CTX_set_verify(sslctx, SSL_VERIFY_NONE, websSSLVerifyCallback); - -/* - * Set the certificate authority list for the client - */ - SSL_CTX_set_client_CA_list(sslctx, SSL_load_client_CA_file(CAfile)); - -/* - * Open the socket - */ - sslListenSock = socketOpenConnection(NULL, SSL_PORT, - websSSLAccept, SOCKET_BLOCK); - - if (sslListenSock < 0) { - trace(2, T("SSL: Unable to open SSL socket on port <%d>!\n"), - SSL_PORT); - return -1; - } - - return 0; -} - -/******************************************************************************/ -/* - * Return TRUE if websSSL has been opened - */ - -int websSSLIsOpen() -{ - return (sslListenSock != -1); -} - -/******************************************************************************/ -/* - * Stops the SSL - */ - -void websSSLClose() -{ - trace(7, T("SSL: Closing SSL\n")); - - if (sslctx != NULL) { - SSL_CTX_free(sslctx); - sslctx = NULL; - } - - if (sslListenSock != -1) { - socketCloseConnection(sslListenSock); - sslListenSock = -1; - } - -#ifdef SSLC - SSL_library_cleanup(); -#endif -} - -/******************************************************************************/ -/* - * Accept a connection - */ - -int websSSLAccept(int sid, char *ipaddr, int port, int listenSid) -{ - webs_t wp; - int wid; - - a_assert(ipaddr && *ipaddr); - a_assert(sid >= 0); - a_assert(port >= 0); - -/* - * Allocate a new handle for this accepted connection. This will allocate - * a webs_t structure in the webs[] list - */ - if ((wid = websAlloc(sid)) < 0) { - return -1; - } - wp = webs[wid]; - a_assert(wp); - wp->listenSid = listenSid; - - ascToUni(wp->ipaddr, ipaddr, min(sizeof(wp->ipaddr), strlen(ipaddr)+1)); - -/* - * Check if this is a request from a browser on this system. This is useful - * to know for permitting administrative operations only for local access - */ - if (gstrcmp(wp->ipaddr, T("127.0.0.1")) == 0 || - gstrcmp(wp->ipaddr, websIpaddr) == 0 || - gstrcmp(wp->ipaddr, websHost) == 0) { - wp->flags |= WEBS_LOCAL_REQUEST; - } -/* - * Since the acceptance came in on this channel, it must be secure - */ - wp->flags |= WEBS_SECURE; - -/* - * Arrange for websSocketEvent to be called when read data is available - */ - socketCreateHandler(sid, SOCKET_READABLE, websSSLSocketEvent, (int) wp); - -/* - * Arrange for a timeout to kill hung requests - */ - wp->timeout = emfSchedCallback(WEBS_TIMEOUT, websTimeout, (void *) wp); - trace(8, T("webs: accept request\n")); - return 0; -} - -/******************************************************************************/ -/* - * The webs socket handler. Called in response to I/O. We just pass control - * to the relevant read or write handler. A pointer to the webs structure - * is passed as an (int) in iwp. - */ - -static void websSSLSocketEvent(int sid, int mask, int iwp) -{ - webs_t wp; - - wp = (webs_t) iwp; - a_assert(wp); - - if (! websValid(wp)) { - return; - } - - if (mask & SOCKET_READABLE) { - websSSLReadEvent(wp); - } - if (mask & SOCKET_WRITABLE) { - if (wp->writeSocket) { - (*wp->writeSocket)(wp); - } - } -} - -/******************************************************************************/ -/* - * Handler for SSL Read Events - */ - -static int websSSLReadEvent (webs_t wp) -{ - int ret, sock; - socket_t *sptr; - SSL *ssl; - BIO *bio, *bioSSL, *bioSock; -#ifdef DEV - const char *ciphers; -#endif - - a_assert (wp); - a_assert(websValid(wp)); - - sptr = socketPtr(wp->sid); - a_assert(sptr); - - sock = sptr->sock; - -/* - * Create a new BIO and SSL session for this web request - */ - bio = BIO_new(BIO_f_buffer()); - a_assert(bio); - - if (!BIO_set_write_buffer_size(bio, 128)) { - return -1; - } - - ssl = (SSL *) SSL_new(sslctx); - a_assert(ssl); - - if (ssl == NULL) { - return -1; - } - - SSL_set_session(ssl, NULL); - - bioSSL = BIO_new(BIO_f_ssl()); - a_assert(bioSSL); - - bioSock = BIO_new_socket(sock, BIO_NOCLOSE); - a_assert(bioSock); - - SSL_set_bio(ssl, bioSock, bioSock); - SSL_set_accept_state(ssl); - - ret = BIO_set_ssl(bioSSL, ssl, BIO_CLOSE); - BIO_push(bio, bioSSL); - -#ifdef DEV - ciphers = SSL_get_cipher_list(ssl, 10); -#endif - -/* - * Create the SSL data structure in the wp. - */ -#ifdef WEBS_SSL_SUPPORT - wp->wsp = balloc(B_L, sizeof(websSSL_t)); - a_assert (wp->wsp); - (wp->wsp)->bio = bio; - (wp->wsp)->ssl = ssl; -#endif - -/* - * Call the default Read Event - */ - websReadEvent(wp); - - return ret; -} - - -/******************************************************************************/ -/* - * SSL Verification Callback - */ - -static int sslVerifyDepth = 0; -static int sslVerifyError = X509_V_OK; - -int websSSLVerifyCallback(int ok, X509_STORE_CTX *ctx) -{ - char buf[256]; - X509 *errCert; - int err; - int depth; - - errCert = X509_STORE_CTX_get_current_cert(ctx); - err = X509_STORE_CTX_get_error(ctx); - depth = X509_STORE_CTX_get_error_depth(ctx); - - X509_NAME_oneline(X509_get_subject_name(errCert), buf, 256); - - if (!ok) { - if (sslVerifyDepth >= depth) { - ok = 1; - sslVerifyError = X509_V_OK; - } else { - ok=0; - sslVerifyError = X509_V_ERR_CERT_CHAIN_TOO_LONG; - } - } - - switch (err) { - case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT: -#ifdef OPENSSL - X509_NAME_oneline(X509_get_issuer_name(ctx->current_cert), buf, 256); -#endif - break; - - case X509_V_ERR_CERT_NOT_YET_VALID: - case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD: - case X509_V_ERR_CERT_HAS_EXPIRED: - case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD: - break; - } - - return ok; -} - -/******************************************************************************/ -/* - * Set the SSL certificate and key for the SSL context - */ - -int websSSLSetCertStuff(SSL_CTX *ctx, char *certFile, char *keyFile) -{ - a_assert (ctx); - a_assert (certFile); - - if (certFile != NULL) { - if (SSL_CTX_use_certificate_file(ctx, certFile, - SSL_FILETYPE_PEM) <= 0) { - trace(2, T("SSL: Unable to set certificate file <%s>\n"), - certFile); - return -1; - } - - if (keyFile == NULL) { - keyFile = certFile; - } - - if (SSL_CTX_use_PrivateKey_file(ctx, keyFile, SSL_FILETYPE_PEM) <= 0) { - trace(2, T("SSL: Unable to set private key file <%s>\n"), - keyFile); - return -1; - } - -/* - * Now we know that a key and cert have been set against - * the SSL context - */ - if (!SSL_CTX_check_private_key(ctx)) { - trace(2, T("SSL: Check of private key file <%s> FAILED!\n"), - keyFile); - return -1; - } - } - - return 0; -} - -/******************************************************************************/ -/* - * Set certificate file for SSL context - */ - -int websSSLSetCertFile(char_t *certFile) -{ - a_assert (sslctx); - a_assert (certFile); - - if (sslctx == NULL) { - return -1; - } - - if (SSL_CTX_use_certificate_file(sslctx, certFile, - SSL_FILETYPE_PEM) <= 0) { - return -1; - } -/* - * Confirm that the certificate and the private key jive. - */ - if (!SSL_CTX_check_private_key(sslctx)) { - return -1; - } - - return 0; -} - -/******************************************************************************/ -/* - * Set key file for SSL context - */ - -int websSSLSetKeyFile(char_t *keyFile) -{ - a_assert (sslctx); - a_assert (keyFile); - - if (sslctx == NULL) { - return -1; - } - - if (SSL_CTX_use_PrivateKey_file(sslctx, keyFile, SSL_FILETYPE_PEM) <= 0) { - return -1; - } -/* - * Confirm that the certificate and the private key jive. - */ - if (!SSL_CTX_check_private_key(sslctx)) { - return -1; - } - - return 0; -} - -#ifdef SSLC -extern RSA *RSA_new(void); -#endif - -/******************************************************************************/ -/* - * the Temporary RSA callback - */ - -static RSA *websSSLTempRSACallback(SSL *ssl, int isExport, int keyLength) -{ - static RSA *rsaTemp = NULL; - - if (rsaTemp == NULL) { - -#ifdef OPENSSL - rsaTemp = RSA_generate_key(keyLength, RSA_F4, NULL, NULL); -#endif - -#ifdef SSLC - rsaTemp = RSA_new(); -#endif - - } - - return rsaTemp; -} - -/******************************************************************************/ -/* - * Free SSL resources - */ - -int websSSLFree(websSSL_t *wsp) -{ - if (wsp == NULL) { - return -1; - } - -/* - * Make sure we re-use sessions - */ - if (wsp->ssl != NULL) { - SSL_set_shutdown(wsp->ssl, SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN); - } - - if (wsp->bio != NULL) { - BIO_free_all(wsp->bio); - } - - bfree(B_L, wsp); - - return 0; -} - -/******************************************************************************/ -/* - * Return Eof for the SSL BIO - */ - -int websSSLEof(websSSL_t *wsp) -{ - a_assert(wsp); - - if ((wsp == NULL) || (wsp->bio == NULL)) { - return -1; - } - - return BIO_eof(wsp->bio); -} - -/******************************************************************************/ -/* - * Perform a read of the SSL BIO - */ - -int websSSLRead(websSSL_t *wsp, char_t *buf, int len) -{ - a_assert(wsp); - a_assert(buf); - - if ((wsp == NULL) || (wsp->bio == NULL)) { - return -1; - } - - return BIO_read(wsp->bio, buf, len); -} - -/******************************************************************************/ -/* - * Perform a gets of the SSL BIO, returning an balloc'ed string - */ - -#define BUF_BLOCK 256 - -int websSSLGets(websSSL_t *wsp, char_t **buf) -{ - int rc, len, lenBuf; - char c; - - a_assert(wsp); - a_assert(buf); - - lenBuf = 0; - len = 0; - - if ((wsp == NULL) || (wsp->bio == NULL)) { - return -1; - } - - while (1) { - - if ((rc = BIO_read(wsp->bio, &c, 1)) < 0) { - return rc; - } - - if (rc == 0) { -/* - * If there is a partial line and we are at EOF, pretend we saw a '\n' - */ - if (len > 0 && BIO_eof(wsp->bio)) { - c = '\n'; - } else { - return -1; - } - } -/* - * If a newline is seen, return the data excluding the new line to the - * caller. If carriage return is seen, just eat it. - */ - if (c == '\n') { - if ((len > 0) && (len < lenBuf)) { - (*buf)[len] = 0; - } - return len; - } else if (c == '\r') { - continue; - } -/* - * Append character to buf - */ - if (len >= lenBuf) { - lenBuf += BUF_BLOCK; - *buf = brealloc(B_L, *buf, lenBuf); - } - - a_assert(*buf); - (*buf)[len] = c; - len++; - } -} - -/******************************************************************************/ -/* - * Perform a write to the SSL BIO - */ - -int websSSLWrite(websSSL_t *wsp, char_t *buf, int len) -{ - a_assert(wsp); - a_assert(buf); - - if ((wsp == NULL) || (wsp->bio == NULL)) { - return -1; - } - - return BIO_write(wsp->bio, buf, len); -} - -/******************************************************************************/ -/* - * Perform a flush of the SSL BIO - */ - -int websSSLFlush(websSSL_t *wsp) -{ - a_assert(wsp); - - if ((wsp == NULL) || (wsp->bio == NULL)) { - return -1; - } - - return BIO_flush(wsp->bio); -} - -/******************************************************************************/ diff --git a/cpukit/httpd/websSSL.h b/cpukit/httpd/websSSL.h deleted file mode 100644 index 8e09703476..0000000000 --- a/cpukit/httpd/websSSL.h +++ /dev/null @@ -1,67 +0,0 @@ -/* - * websSSL.h -- SSL Patch 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_websSSL -#define _h_websSSL 1 - -/******************************** Description *********************************/ - -/* - * Header file for the GoAhead Patch for SSL. This defines the interface to - * integrate SSL into the GoAhead Webserver. - */ - -/********************************* Includes ***********************************/ - - -#ifdef OPENSSL -#define SSLEAY /* turn off a few special case MONOLITH macros */ -#define USE_SOCKETS /* needed for the _O_BINARY defs in the MS world */ -#include <openssl/ssl.h> -#else -#include <sslc.h> -#endif - -#ifndef UEMF - #include "basic/basic.h" - #include "emf/emf.h" -#else - #include "uemf.h" -#endif - -/********************************** Defines ***********************************/ - -typedef struct { - SSL *ssl; - BIO *bio; -} websSSL_t; - - -/******************************** Prototypes **********************************/ - -extern int websSSLOpen(); -extern int websSSLIsOpen(); -extern void websSSLClose(); - -extern int websSSLWrite(websSSL_t *wsp, char_t *buf, int nChars); -extern int websSSLGets(websSSL_t *wsp, char_t **buf); -extern int websSSLRead(websSSL_t *wsp, char_t *buf, int nChars); -extern int websSSLEof(websSSL_t *wsp); - -extern int websSSLFree(websSSL_t *wsp); -extern int websSSLFlush(websSSL_t *wsp); - -extern int websSSLSetKeyFile(char_t *keyFile); -extern int websSSLSetCertFile(char_t *certFile); - - -#endif /* _h_websSSL */ - -/*****************************************************************************/ diff --git a/cpukit/httpd/websda.c b/cpukit/httpd/websda.c deleted file mode 100644 index 21d8ac6921..0000000000 --- a/cpukit/httpd/websda.c +++ /dev/null @@ -1,244 +0,0 @@ -/* - * websda.c -- Digest Access Authentication routines - * - * Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved. - * - * See the file "license.txt" for usage and redistribution license requirements - * - * $Id$ - */ - -/******************************** Description *********************************/ - -/* - * Routines for generating DAA data. The module uses the - * "RSA Data Security, Inc. MD5 Message-Digest Algorithm" found in md5c.c - */ - -/********************************* Includes ***********************************/ - -#ifndef CE -#include <time.h> -#endif -#include "websda.h" -#include "md5.h" - -/******************************** Local Data **********************************/ - -#define RANDOMKEY T("onceuponatimeinparadise") -#define NONCE_SIZE 34 -#define HASH_SIZE 16 - -/*********************************** Code *************************************/ -/* - * websMD5binary returns the MD5 hash - */ - -char *websMD5binary(unsigned char *buf, int length) -{ - const char *hex = "0123456789abcdef"; - MD5_CONTEXT md5ctx; - unsigned char hash[HASH_SIZE]; - char *r, *strReturn; - char result[(HASH_SIZE * 2) + 1]; - int i; - -/* - * Take the MD5 hash of the string argument. - */ - MD5Init(&md5ctx); - MD5Update(&md5ctx, buf, (unsigned int)length); - MD5Final(hash, &md5ctx); - -/* - * Prepare the resulting hash string - */ - for (i = 0, r = result; i < 16; i++) { - *r++ = hex[hash[i] >> 4]; - *r++ = hex[hash[i] & 0xF]; - } - -/* - * Zero terminate the hash string - */ - *r = '\0'; - -/* - * Allocate a new copy of the hash string - */ - strReturn = balloc(B_L, sizeof(result)); - strcpy(strReturn, result); - - return strReturn; -} - -/*****************************************************************************/ -/* - * Convenience call to websMD5binary - * (Performs char_t to char conversion and back) - */ - -char_t *websMD5(char_t *string) -{ - char_t *strReturn; - - a_assert(string && *string); - - if (string && *string) { - char *strTemp, *strHash; - int nLen; -/* - * Convert input char_t string to char string - */ - nLen = gstrlen(string); - strTemp = ballocUniToAsc(string, nLen + 1); -/* - * Execute the digest calculation - */ - strHash = websMD5binary((unsigned char *)strTemp, nLen); -/* - * Convert the returned char string digest to a char_t string - */ - nLen = strlen(strHash); - strReturn = ballocAscToUni(strHash, nLen); -/* - * Free up the temporary allocated resources - */ - bfree(B_L, strTemp); - bfree(B_L, strHash); - } else { - strReturn = NULL; - } - - return strReturn; -} - -/******************************************************************************/ -/* - * Get a Nonce value for passing along to the client. This function - * composes the string "RANDOMKEY:timestamp:myrealm" and - * calculates the MD5 digest placing it in output. - */ - -char_t *websCalcNonce(webs_t wp) -{ - char_t *nonce, *prenonce; - struct tm *newtime; - time_t longTime; - - a_assert(wp); -/* - * Get time as long integer. - */ - time(&longTime); -/* - * Convert to local time. - */ - newtime = localtime(&longTime); -/* - * Create prenonce string. - */ - prenonce = NULL; -#ifdef DIGEST_ACCESS_SUPPORT - fmtAlloc(&prenonce, 256, T("%s:%s:%s"), RANDOMKEY, gasctime(newtime), - wp->realm); -#else - fmtAlloc(&prenonce, 256, T("%s:%s:%s"), RANDOMKEY, gasctime(newtime), - RANDOMKEY); -#endif - a_assert(prenonce); -/* - * Create the nonce - */ - nonce = websMD5(prenonce); -/* - * Cleanup - */ - bfreeSafe(B_L, prenonce); - - return nonce; -} - -/******************************************************************************/ -/* - * Get an Opaque value for passing along to the client - */ - -char_t *websCalcOpaque(webs_t wp) -{ - char_t *opaque; - a_assert(wp); -/* - * Temporary stub! - */ - opaque = bstrdup(B_L, T("5ccc069c403ebaf9f0171e9517f40e41")); - - return opaque; -} - -/******************************************************************************/ -/* - * Get a Digest value using the MD5 algorithm - */ - -char_t *websCalcDigest(webs_t wp) -{ -#ifdef DIGEST_ACCESS_SUPPORT - char_t *digest, *a1, *a1prime, *a2, *a2prime, *preDigest, *method; - - a_assert(wp); - digest = NULL; - -/* - * Calculate first portion of digest H(A1) - */ - a1 = NULL; - fmtAlloc(&a1, 255, T("%s:%s:%s"), wp->userName, wp->realm, wp->password); - a_assert(a1); - a1prime = websMD5(a1); - bfreeSafe(B_L, a1); -/* - * Calculate second portion of digest H(A2) - */ - method = websGetVar(wp, T("REQUEST_METHOD"), NULL); - a_assert(method); - a2 = NULL; - fmtAlloc(&a2, 255, T("%s:%s"), method, wp->uri); - a_assert(a2); - a2prime = websMD5(a2); - bfreeSafe(B_L, a2); -/* - * Construct final digest KD(H(A1):nonce:H(A2)) - */ - a_assert(a1prime); - a_assert(a2prime); - a_assert(wp->nonce); - - preDigest = NULL; - if (!wp->qop) { - fmtAlloc(&preDigest, 255, T("%s:%s:%s"), a1prime, wp->nonce, a2prime); - } else { - fmtAlloc(&preDigest, 255, T("%s:%s:%s:%s:%s:%s"), - a1prime, - wp->nonce, - wp->nc, - wp->cnonce, - wp->qop, - a2prime); - } - - a_assert(preDigest); - digest = websMD5(preDigest); -/* - * Now clean up - */ - bfreeSafe(B_L, a1prime); - bfreeSafe(B_L, a2prime); - bfreeSafe(B_L, preDigest); - return digest; -#else - return NULL; -#endif /* DIGEST_ACCESS_SUPPORT */ -} - -/******************************************************************************/ diff --git a/cpukit/httpd/websda.h b/cpukit/httpd/websda.h deleted file mode 100644 index 1bb5424d90..0000000000 --- a/cpukit/httpd/websda.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * websda.h -- GoAhead Digest Access Authentication 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_WEBSDA -#define _h_WEBSDA 1 - -/******************************** Description *********************************/ - -/* - * GoAhead Digest Access Authentication header. This defines the Digest - * access authentication public APIs. Include this header for files that - * use DAA functions - */ - -/********************************* Includes ***********************************/ - -#ifndef UEMF - #include "basic/basic.h" - #include "emf/emf.h" -#else - #include "uemf.h" -#endif - -#include "webs.h" - -/****************************** Definitions ***********************************/ - -extern char_t *websCalcNonce(webs_t wp); -extern char_t *websCalcOpaque(webs_t wp); -extern char_t *websCalcDigest(webs_t wp); - -#endif /* _h_WEBSDA */ - -/******************************************************************************/ diff --git a/cpukit/httpd/websuemf.c b/cpukit/httpd/websuemf.c deleted file mode 100644 index 2a2cb19ea4..0000000000 --- a/cpukit/httpd/websuemf.c +++ /dev/null @@ -1,217 +0,0 @@ -/* - * websuemf.c -- GoAhead Micro Embedded Management Framework - * - * Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved. - * - * See the file "license.txt" for usage and redistribution license requirements - * - * $Id$ - */ - -/********************************** Description *******************************/ - -/* - * This modules provides compatibility with the full GoAhead EMF. - */ - -/*********************************** 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 ejid; - - if (engine == EMF_SCRIPT_EJSCRIPT) { - ejid = (int) chan; - /* - * NOTE -- to disable better reporting of ASP errors, change the - * following line of code to - * if (ejEval(ejid, cmd, NULL) ) { - */ - if (ejEval(ejid, cmd, result) ) { - return 0; - } else { - return -1; - } - } - return -1; -} - -/******************************************************************************/ -/* - * 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((unsigned char)*s1) - gtolower((unsigned char)*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(void) -{ - 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; - } - } -} - -/******************************************************************************/ diff --git a/cpukit/httpd/wsIntrn.h b/cpukit/httpd/wsIntrn.h deleted file mode 100644 index b6e89d5571..0000000000 --- a/cpukit/httpd/wsIntrn.h +++ /dev/null @@ -1,309 +0,0 @@ -/* - * wsIntrn.h -- Internal GoAhead Web server 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_WEBS_INTERNAL -#define _h_WEBS_INTERNAL 1 - -/******************************** Description *********************************/ - -/* - * Internal GoAhead Web Server header. This defines the Web private APIs - * Include this header when you want to create URL handlers. - */ - -/*********************************** Defines **********************************/ - -/* - * Define this to enable logging of web accesses to a file - * #define WEBS_LOG_SUPPORT 1 - * - * Define this to enable HTTP/1.1 keep alive support - * #define WEBS_KEEP_ALIVE_SUPPORT 1 - * - * Define this to enable if-modified-since support - * #define WEBS_IF_MODIFIED_SUPPORT 1 - * - * Define this to support proxy capability and track local vs remote request - * Note: this is not yet fully implemented. - * #define WEBS_PROXY_SUPPORT 1 - * - * Define this to support reading pages from ROM - * #define WEBS_PAGE_ROM 1 - * - * Define this to enable memory allocation and stack usage tracking - * #define B_STATS 1 - */ - -/********************************** Includes **********************************/ - -#include <ctype.h> -#include <stdlib.h> -#include <string.h> -#include <stdarg.h> - -#ifdef NETWARE - #include <fcntl.h> - #include <sys/stat.h> - #include <signal.h> - #include <io.h> -#endif - -#ifdef WIN - #include <fcntl.h> - #include <sys/stat.h> - #include <io.h> -#endif - -#ifdef CE -#ifndef UEMF - #include <io.h> -#endif -#endif - -#ifdef NW - #include <fcntl.h> - #include <sys/stat.h> -#endif - -#ifdef SCOV5 - #include <fcntl.h> - #include <sys/stat.h> - #include <signal.h> - #include <unistd.h> -#endif - -#ifdef LYNX - #include <fcntl.h> - #include <sys/stat.h> - #include <signal.h> - #include <unistd.h> -#endif - -#ifdef UNIX - #include <fcntl.h> - #include <sys/stat.h> - #include <signal.h> - #include <unistd.h> -#endif - -#ifdef QNX4 - #include <fcntl.h> - #include <sys/stat.h> - #include <signal.h> - #include <unistd.h> - #include <unix.h> -#endif - -#ifdef UW - #include <fcntl.h> - #include <sys/stat.h> -#endif - -#ifdef VXWORKS - #include <vxWorks.h> - #include <fcntl.h> - #include <sys/stat.h> -#endif - -#ifdef SOLARIS - #include <macros.h> - #include <fcntl.h> - #include <sys/stat.h> -#endif - -#ifdef UEMF - #include "uemf.h" - #include "ejIntrn.h" -#else - #include "emf/emfInternal.h" - #include "ej/ejIntrn.h" -#endif - -#include "webs.h" - -/********************************** Defines ***********************************/ -/* - * 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 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 */ - -/* - * URL handler structure. Stores the leading URL path and the handler - * function to call when the URL path is seen. - */ -typedef struct { - int (*handler)(webs_t wp, char_t *urlPrefix, char_t *webDir, int arg, - char_t *url, char_t *path, - char_t *query); /* Callback URL handler function */ - char_t *webDir; /* Web directory if required */ - char_t *urlPrefix; /* URL leading prefix */ - int len; /* Length of urlPrefix for speed */ - int arg; /* Argument to provide to handler */ - int flags; /* Flags */ -} websUrlHandlerType; - -/* - * Webs statistics - */ -typedef struct { - long errors; /* General errors */ - long redirects; - long net_requests; - long activeNetRequests; - long activeBrowserRequests; - long timeouts; - long access; /* Access violations */ - long localHits; - long remoteHits; - long formHits; - long cgiHits; - long handlerHits; -} websStatsType; - -extern websStatsType websStats; /* Web access stats */ - -/* - * Error code list - */ -typedef struct { - int code; /* HTTP error code */ - char_t *msg; /* HTTP error message */ -} websErrorType; - -/* - * Mime type list - */ -typedef struct { - char_t *type; /* Mime type */ - char_t *ext; /* File extension */ -} websMimeType; - -/* - * File information structure. - */ -typedef struct { - unsigned long size; /* File length */ - int isDir; /* Set if directory */ - time_t mtime; /* Modified time */ -} websStatType; - -/* - * Compiled Rom Page Index - */ -typedef struct { - char_t *path; /* Web page URL path */ - unsigned char *page; /* Web page data */ - int size; /* Size of web page in bytes */ - int pos; /* Current read position */ -} websRomPageIndexType; - -/* - * Defines for file open. - */ -#ifndef CE -#define SOCKET_RDONLY O_RDONLY -#define SOCKET_BINARY O_BINARY -#else /* CE */ -#define SOCKET_RDONLY 0x1 -#define SOCKET_BINARY 0x2 -#endif /* CE */ - -extern websRomPageIndexType websRomPageIndex[]; -extern websMimeType websMimeList[]; /* List of mime types */ -extern sym_fd_t websMime; /* Set of mime types */ -extern webs_t* webs; /* Session list head */ -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 **********************************/ - -extern int websAspOpen(void); -extern void websAspClose(void); -extern void websFormOpen(void); -extern void websFormClose(void); -extern int websAspWrite(int ejid, webs_t wp, int argc, char_t **argv); -extern void websDefaultClose(void); -extern int websDefaultHandler(webs_t wp, char_t *urlPrefix, - char_t *webDir, int arg, char_t *url, char_t *path, - 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(void); -extern int websCheckCgiProc(int handle); -extern char_t *websGetCgiCommName(void); - -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 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, - websStatType *sbuf); -extern int websPageIsDirectory(char_t *lpath); -extern int websRomOpen(void); -extern void websRomClose(void); -extern int websRomPageOpen(webs_t wp, char_t *path, int mode, int perm); -extern void websRomPageClose(int fd); -extern int websRomPageReadData(webs_t wp, char *buf, int len); -extern int websRomPageStat(char_t *path, websStatType *sbuf); -extern long websRomPageSeek(webs_t wp, long offset, int origin); -extern void websSetRequestSocketHandler(webs_t wp, int mask, - void (*fn)(webs_t wp)); -extern int websSolutionHandler(webs_t wp, char_t *urlPrefix, - char_t *webDir, int arg, char_t *url, char_t *path, - char_t *query); -extern void websUrlHandlerClose(void); -extern int websUrlHandlerOpen(void); -extern int websOpenServer(int port, int retries); -extern void websCloseServer(void); -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) - */ -#ifdef EMF -extern int websEmfOpen(); -extern void websEmfClose(); -extern void websSetEmfEnvironment(webs_t wp); -#endif - -#ifdef 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 */ - -/******************************************************************************/ |