Changeset a6b4c0df in rtems


Ignore:
Timestamp:
Sep 1, 2000, 10:57:21 AM (20 years ago)
Author:
Joel Sherrill <joel.sherrill@…>
Branches:
4.10, 4.11, 4.8, 4.9, 5, master
Children:
5f117e8
Parents:
757e1661
Message:

2000-08-30 Joel Sherrill <joel@…>

  • Merged version 2.1 of GoAhead? webserver. This update was submitted by Antti P Miettinen <antti.p.miettinen@…>.
  • NOTES, base64.c, ejIntrn.h, emfdb.c, emfdb.h, md5.h, md5c.c, um.c, um.h: New files.
  • wbase64.c: Removed.
  • Makefile.am, asp.c, balloc.c, default.c, ej.h, ejlex.c, ejparse.c, form.c, h.c, handler.c, mime.c, misc.c, ringq.c, rom.c, security.c, socket.c, sym.c, uemf.c, uemf.h, url.c, value.c, webcomp.c, webmain.c, webpage.c, webrom.c, webs.c, webs.h, websuemf.c, wsIntrn.h: Modified.
Files:
16 added
61 edited
2 moved

Legend:

Unmodified
Added
Removed
  • c/src/exec/libnetworking/ChangeLog

    r757e1661 ra6b4c0df  
     12000-08-31      Joel Sherrill <joel@OARcorp.com>
     2
     3        * Merged version 2.1 of GoAhead webserver.  This update
     4        was submitted by Antti P Miettinen <antti.p.miettinen@nokia.com>.
     5        * NOTES, base64.c, ejIntrn.h, emfdb.c, emfdb.h, md5.h, md5c.c,
     6        um.c, um.h: New files.
     7        * wbase64.c: Removed.
     8        * Makefile.am, asp.c, balloc.c, default.c, ej.h, ejlex.c, ejparse.c,
     9        form.c, h.c, handler.c, mime.c, misc.c, ringq.c, rom.c, security.c,
     10        socket.c, sym.c, uemf.c, uemf.h, url.c, value.c, webcomp.c, webmain.c,
     11        webpage.c, webrom.c, webs.c, webs.h, websuemf.c, wsIntrn.h: Modified.
     12
    1132000-08-31      Ralf Corsepius <corsepiu@faw.uni-ulm.de>
    214
  • c/src/libnetworking/ChangeLog

    r757e1661 ra6b4c0df  
     12000-08-31      Joel Sherrill <joel@OARcorp.com>
     2
     3        * Merged version 2.1 of GoAhead webserver.  This update
     4        was submitted by Antti P Miettinen <antti.p.miettinen@nokia.com>.
     5        * NOTES, base64.c, ejIntrn.h, emfdb.c, emfdb.h, md5.h, md5c.c,
     6        um.c, um.h: New files.
     7        * wbase64.c: Removed.
     8        * Makefile.am, asp.c, balloc.c, default.c, ej.h, ejlex.c, ejparse.c,
     9        form.c, h.c, handler.c, mime.c, misc.c, ringq.c, rom.c, security.c,
     10        socket.c, sym.c, uemf.c, uemf.h, url.c, value.c, webcomp.c, webmain.c,
     11        webpage.c, webrom.c, webs.c, webs.h, websuemf.c, wsIntrn.h: Modified.
     12
    1132000-08-31      Ralf Corsepius <corsepiu@faw.uni-ulm.de>
    214
  • c/src/libnetworking/rtems_webserver/Makefile.am

    r757e1661 ra6b4c0df  
    88LIB = $(ARCH)/$(LIBNAME)
    99
    10 C_FILES = asp.c balloc.c wbase64.c default.c ejlex.c ejparse.c form.c h.c \
    11     handler.c mime.c misc.c webpage.c ringq.c rom.c security.c socket.c \
    12     sym.c uemf.c url.c value.c webrom.c webs.c websuemf.c webmain.c
     10C_FILES = asp.c balloc.c base64.c default.c ejlex.c ejparse.c emfdb.c \
     11    form.c h.c handler.c md5c.c mime.c misc.c webpage.c ringq.c rom.c \
     12    security.c socket.c sym.c uemf.c um.c url.c value.c webrom.c webs.c \
     13    websuemf.c webmain.c
    1314C_O_FILES = $(C_FILES:%.c=$(ARCH)/%.o)
    1415
    1516OBJS = $(C_O_FILES)
    1617
    17 H_FILES = ej.h uemf.h webs.h wsIntrn.h
     18H_FILES = ej.h ejIntrn.h emfdb.h md5.h uemf.h um.h webs.h wsIntrn.h
    1819
    1920include $(RTEMS_ROOT)/make/custom/@RTEMS_BSP@.cfg
     
    5354EXTRA_DIST = asp.c balloc.c default.c ej.h ejlex.c ejparse.c form.c h.c \
    5455    handler.c mime.c misc.c ringq.c rom.c rtems_webserver.h security.c \
    55     socket.c sym.c uemf.c uemf.h url.c value.c wbase64.c webcomp.c webmain.c \
    56     webpage.c webrom.c webs.c webs.h websuemf.c wsIntrn.h
     56    socket.c sym.c uemf.c uemf.h um.h url.c value.c base64.c webcomp.c \
     57    webmain.c webpage.c webrom.c webs.c webs.h websuemf.c wsIntrn.h
    5758
    5859include $(top_srcdir)/../../../automake/local.am
  • c/src/libnetworking/rtems_webserver/asp.c

    r757e1661 ra6b4c0df  
    22 * asp.c -- Active Server Page Support
    33 *
    4  * Copyright (c) Go Ahead Software Inc., 1995-1999. All Rights Reserved.
     4 * Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved.
    55 *
    66 * See the file "license.txt" for usage and redistribution license requirements
     
    2121/********************************** Locals ************************************/
    2222
    23 static sym_fd_t  websAspFunctions = -1; /* Symbol table of functions */
     23static sym_fd_t websAspFunctions = -1;  /* Symbol table of functions */
     24static int              aspOpenCount = 0;               /* count of apps using this module */
    2425
    2526/***************************** Forward Declarations ***************************/
    2627
    27 static char_t   *strtokcmp(char_t* s1, char_t* s2);
     28static char_t   *strtokcmp(char_t *s1, char_t *s2);
    2829static char_t   *skipWhite(char_t *s);
    2930
     
    3536int websAspOpen()
    3637{
     38        if (++aspOpenCount == 1) {
    3739/*
    3840 *      Create the table for ASP functions
    3941 */
    40         websAspFunctions = symOpen(128);
     42                websAspFunctions = symOpen(WEBS_SYM_INIT * 2);
    4143
    4244/*
    4345 *      Create standard ASP commands
    4446 */
    45         websAspDefine(T("write"), websAspWrite);
     47                websAspDefine(T("write"), websAspWrite);
     48        }
    4649        return 0;
    4750}
     
    5457void websAspClose()
    5558{
    56         if (websAspFunctions != -1) {
    57                 symClose(websAspFunctions, NULL);
     59        if (--aspOpenCount <= 0) {
     60                if (websAspFunctions != -1) {
     61                        symClose(websAspFunctions);
     62                        websAspFunctions = -1;
     63                }
    5864        }
    5965}
     
    6672 */
    6773
    68 int websAspRequest(webs_t wp, char_t* lpath)
     74int websAspRequest(webs_t wp, char_t *lpath)
    6975{
    7076        websStatType    sbuf;
     
    8591
    8692/*
    87  *      Create Ejscript instance incase it is needed
     93 *      Create Ejscript instance in case it is needed
    8894 */
    8995        ejid = ejOpenEngine(wp->cgiVars, websAspFunctions);
     
    113119                goto done;
    114120        }
    115         websCloseFileHandle(wp);
     121        websPageClose(wp);
    116122
    117123/*
    118124 *      Convert to UNICODE if necessary.
    119125 */
    120         if ((buf = ballocAscToUni(rbuf)) == NULL) {
     126        if ((buf = ballocAscToUni(rbuf, len)) == NULL) {
    121127                websError(wp, 200, T("Can't get memory"));
    122128                goto done;
     
    221227done:
    222228        if (websValid(wp)) {
    223                 websCloseFileHandle(wp);
     229                websPageClose(wp);
    224230                if (ejid >= 0) {
    225231                        ejCloseEngine(ejid);
     
    253259
    254260        a_assert(websValid(wp));
    255         a_assert(argv);
    256 
     261       
    257262        for (i = 0; i < argc; ) {
     263                a_assert(argv);
    258264                if (websWriteBlock(wp, argv[i], gstrlen(argv[i])) < 0) {
    259265                        return -1;
     
    274280 */
    275281
    276 static char_t* strtokcmp(char_t* s1, char_t* s2)
     282static char_t *strtokcmp(char_t *s1, char_t *s2)
    277283{
    278284        int             len;
  • c/src/libnetworking/rtems_webserver/balloc.c

    r757e1661 ra6b4c0df  
    22 * balloc.c -- Block allocation module
    33 *
    4  * Copyright (c) GoAhead Software Inc., 1995-1999. All Rights Reserved.
     4 * Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved.
    55 *
    66 * See the file "license.txt" for usage and redistribution license requirements
     
    1212 *      This module implements a very fast block allocation scheme suitable for
    1313 *      ROMed environments. It maintains block class queues for rapid allocation
    14  *      and minimal fragmentation. This modules does not coalesce blocks. The
     14 *      and minimal fragmentation. This module does not coalesce blocks. The
    1515 *      storage space may be populated statically or via the traditional malloc
    1616 *      mechanisms. Large blocks greater than the maximum class size may be
     
    3939/********************************* Defines ************************************/
    4040
    41 typedef struct {
    42         union {
    43                 void    *next;                                                  /* Pointer to next in q */
    44                 int             size;                                                   /* Actual requested size */
    45         } u;
    46         int                     flags;                                                  /* Per block allocation flags */
    47 } bType;
    48 
    4941/*
    5042 *      Define B_STATS if you wish to track memory block and stack usage
     
    6456        long    allocated;                                                      /* Bytes currently allocated */
    6557        long    count;                                                          /* Current block count */
    66         long    allocs;                                                         /* Count of alloc attempts */
     58        long    times;                                                          /* Count of alloc attempts */
     59        long    largest;                                                        /* largest allocated here */
     60        int             q;
    6761} bStatsFileType;
    6862
     
    7872static bStatsFileType   bStatsFiles[B_MAX_FILES];/* Per file stats */
    7973static bStatsBlkType    bStatsBlks[B_MAX_BLOCKS];/* Per block stats */
    80 static int                              bStatsBlksMax;                  /* Max block entry */
    81 static int                              bStatsFilesMax;                 /* Max file entry */
    82 static int                              bStatsMemInUse;                 /* Memory currently in use */
    83 static int                              bStatsMemMax;                   /* Max memory ever used */
     74static int                              bStatsBlksMax = 0;              /* Max block entry */
     75static int                              bStatsFilesMax = 0;             /* Max file entry */
     76static int                              bStatsMemInUse = 0;             /* Memory currently in use */
     77static int                              bStatsBallocInUse = 0;  /* Memory currently balloced */
     78static int                              bStatsMemMax = 0;               /* Max memory ever used */
     79static int                              bStatsBallocMax = 0;    /* Max memory ever balloced */
    8480static void                             *bStackMin = (void*) -1;/* Miniumum stack position */
    8581static void                             *bStackStart;                   /* Starting stack position */
    86 static int                              bStatsMemMalloc;                /* Malloced memory */
     82static int                              bStatsMemMalloc = 0;    /* Malloced memory */
    8783#endif /* B_STATS */
    8884
     85/*
     86 *      ROUNDUP4(size) returns the next higher integer value of size that is
     87 *      divisible by 4, or the value of size if size is divisible by 4.
     88 *      ROUNDUP4() is used in aligning memory allocations on 4-byte boundaries.
     89 *
     90 *      Note:  ROUNDUP4() is only required on some operating systems (IRIX).
     91 */
     92
     93#define ROUNDUP4(size) ((size) % 4) ? (size) + (4 - ((size) % 4)) : (size)
    8994
    9095/********************************** Locals ************************************/
     
    99104static int                              bFreeLeft;                              /* Size of free left for use */
    100105static int                              bFlags = B_USE_MALLOC;  /* Default to auto-malloc */
     106static int                              bopenCount = 0;                 /* Num tasks using balloc */
    101107
    102108/*************************** Forward Declarations *****************************/
     
    116122static void verifyUsedBlock(bType *bp, int q);
    117123static void verifyFreeBlock(bType *bp, int q);
    118 static void verifyBallocSpace();
    119 #endif
     124void verifyBallocSpace();
     125#endif
     126
     127static int ballocGetSize(int size, int *q);
    120128
    121129/********************************** Code **************************************/
     
    134142        bFlags = flags;
    135143
     144#if BASTARD_TESTING
     145        srand(time(0L));
     146#endif /* BASTARD_TESTING */
     147
     148/*
     149 *      If bopen already called by a shared process, just increment the count
     150 *      and return;
     151 */
     152        if (++bopenCount > 1) {
     153                return 0;
     154        }
     155
    136156        if (buf == NULL) {
    137157                if (bufsize == 0) {
    138158                        bufsize = B_DEFAULT_MEM;
    139159                }
     160#ifdef IRIX
     161                bufsize = ROUNDUP4(bufsize);
     162#endif
    140163                if ((buf = malloc(bufsize)) == NULL) {
    141164                        return -1;
     
    150173        bFreeSize = bFreeLeft = bufsize;
    151174        bFreeBuf = bFreeNext = buf;
     175        memset(bQhead, 0, sizeof(bQhead));
    152176#if B_FILL || B_VERIFY_CAUSES_SEVERE_OVERHEAD
    153177        bFillBlock(buf, bufsize);
     
    172196        verifyBallocSpace();
    173197#endif
    174         if (! (bFlags & B_USER_BUF)) {
     198        if (--bopenCount <= 0 && !(bFlags & B_USER_BUF)) {
    175199                free(bFreeBuf);
     200                bopenCount = 0;
    176201        }
    177202}
     
    186211{
    187212        bType   *bp;
    188         int             q, memSize, mask;
     213        int             q, memSize;
    189214
    190215/*
     
    192217 */
    193218        if (bFreeBuf == NULL) {
    194                 if (bopen(NULL, B_DEFAULT_MEM , 0) < 0) {
     219                if (bopen(NULL, B_DEFAULT_MEM, 0) < 0) {
    195220                        return NULL;
    196221                }
     
    203228        }
    204229
    205 /*
    206  *      Determine the relevant block queue with a block big enough -- 
    207  *      include room for the block header.
    208  */
    209         mask = (size + sizeof(bType)) >> B_SHIFT;
    210         for (q = 0; mask; mask >>= 1) {
    211                 q++;
    212         }
    213 
    214         a_assert(0 <= q && q <= B_MAX_CLASS);
    215         memSize = (1 << (B_SHIFT + q));
     230#if BASTARD_TESTING
     231        if (rand() == 0x7fff) {
     232                return NULL;
     233        }
     234#endif /* BASTARD_TESTING */
     235
     236
     237        memSize = ballocGetSize(size, &q);
    216238
    217239        if (q >= B_MAX_CLASS) {
     
    222244#if B_STATS
    223245                        bstats(0, NULL);
     246#endif
     247#ifdef IRIX
     248                        memSize = ROUNDUP4(memSize);
    224249#endif
    225250                        bp = (bType*) malloc(memSize);
    226251                        if (bp == NULL) {
    227                                 goahead_trace(0, T("B: malloc failed for %s:%d, size %d\n"),
    228                                         B_ARGS, memSize);
     252                                traceRaw(T("B: malloc failed\n"));
    229253                                return NULL;
    230254                        }
     
    237261
    238262                } else {
    239                         goahead_trace(0, T("B: balloc failed for %s:%d, size %d\n"),
    240                                 B_ARGS, memSize);
     263                        traceRaw(T("B: malloc failed\n"));
    241264                        return NULL;
    242265                }
    243                 bp->u.size = size;
     266
     267/*
     268 *              the u.size is the actual size allocated for data
     269 */
     270                bp->u.size = memSize - sizeof(bType);
    244271                bp->flags = B_MALLOCED;
    245272
     
    255282                bFillBlock(bp, memSize);
    256283#endif
    257                 bp->u.size = size;
     284                bp->u.size = memSize - sizeof(bType);
    258285                bp->flags = 0;
    259286
     
    273300                        bFillBlock(bp, memSize);
    274301#endif
    275                         bp->u.size = size;
     302                        bp->u.size = memSize - sizeof(bType);
    276303                        bp->flags = 0;
    277304
    278305                } else if (bFlags & B_USE_MALLOC) {
     306#if B_STATS
    279307                        static int once = 0;
    280                         if (once++ < 20) {
    281 #if B_STATS
     308                        if (once++ == 0) {
    282309                                bstats(0, NULL);
    283 #endif
    284310                        }
     311#endif
    285312/*
    286313 *                      Nothing left on the primary free list, so malloc a new block
    287314 */
     315#ifdef IRIX
     316                        memSize = ROUNDUP4(memSize);
     317#endif
    288318                        if ((bp = (bType*) malloc(memSize)) == NULL) {
    289                                 goahead_trace(0, T("B: malloc failed for %s:%d size %d\n"),
    290                                         B_ARGS, memSize);
     319                                traceRaw(T("B: malloc failed\n"));
    291320                                return NULL;
    292321                        }
     
    297326                        bFillBlock(bp, memSize);
    298327#endif
    299                         bp->u.size = size;
     328                        bp->u.size = memSize - sizeof(bType);
    300329                        bp->flags = B_MALLOCED;
    301330
    302331                } else {
    303                         goahead_trace(0, T("B: alloc failed for %s:%d size %d\n"), B_ARGS, size);
     332                        traceRaw(T("B: malloc failed\n"));
    304333                        return NULL;
    305334                }
     
    307336
    308337#if B_STATS
    309         bStatsAlloc(B_ARGS, bp, q, size);
     338        bStatsAlloc(B_ARGS, bp, q, memSize);
    310339#endif
    311340        bp->flags |= B_INTEGRITY;
    312341
     342/*
     343 *      The following is a good place to put a breakpoint when trying to reduce
     344 *      determine and reduce maximum memory use.
     345 */
     346#if 0
     347#if B_STATS
     348        if (bStatsBallocInUse == bStatsBallocMax) {
     349                bstats(0, NULL);
     350        }
     351#endif
     352#endif
    313353        return (void*) ((char*) bp + sizeof(bType));
    314354}
     
    324364{
    325365        bType   *bp;
    326         int             mask, q;
     366        int             q, memSize;
    327367
    328368#if B_VERIFY_CAUSES_SEVERE_OVERHEAD
    329369        verifyBallocSpace();
    330370#endif
    331         a_assert(mp);
    332 
    333371        bp = (bType*) ((char*) mp - sizeof(bType));
     372
    334373        a_assert((bp->flags & B_INTEGRITY_MASK) == B_INTEGRITY);
     374
    335375        if ((bp->flags & B_INTEGRITY_MASK) != B_INTEGRITY) {
    336376                return;
    337377        }
    338378
    339 /*
    340  *      Determine the relevant block queue
    341  */
    342         mask = (bp->u.size + sizeof(bType)) >> B_SHIFT;
    343         for (q = 0; mask; mask >>= 1) {
    344                 q++;
    345         }
    346         a_assert(0 <= q && q <= B_MAX_CLASS);
     379        memSize = ballocGetSize(bp->u.size, &q);
    347380
    348381#if B_VERIFY_CAUSES_SEVERE_OVERHEAD
    349382        verifyUsedBlock(bp,q);
     383#endif
     384#if B_STATS
     385        bStatsFree(B_ARGS, bp, q, bp->u.size+sizeof(bType));
    350386#endif
    351387        if (bp->flags & B_MALLOCED) {
     
    354390        }
    355391               
    356 #if B_STATS
    357         bStatsFree(B_ARGS, bp, q, bp->u.size);
    358 #endif
    359392#if B_VERIFY_CAUSES_SEVERE_OVERHEAD
    360         bFillBlock(bp, 1 << (B_SHIFT + q));
     393        bFillBlock(bp, memSize);
    361394#endif
    362395
     
    366399        bp->u.next = bQhead[q];
    367400        bQhead[q] = bp;
     401
     402        bp->flags = B_FILL_WORD;
    368403}
    369404
     
    433468void *brealloc(B_ARGS_DEC, void *mp, int newsize)
    434469{
    435         bTypebp;
     470        bType   *bp;
    436471        void    *newbuf;
    437472
     
    441476        bp = (bType*) ((char*) mp - sizeof(bType));
    442477        a_assert((bp->flags & B_INTEGRITY_MASK) == B_INTEGRITY);
     478
     479/*
     480 *      If the allocated memory already has enough room just return the previously
     481 *      allocated address.
     482 */
     483        if (bp->u.size >= newsize) {
     484                return mp;
     485        }
    443486        if ((newbuf = balloc(B_ARGS, newsize)) != NULL) {
    444487                memcpy(newbuf, mp, bp->u.size);
     
    448491}
    449492
     493/******************************************************************************/
     494/*
     495 *      Find the size of the block to be balloc'ed.  It takes in a size, finds the
     496 *      smallest binary block it fits into, adds an overhead amount and returns.
     497 *      q is the binary size used to keep track of block sizes in use.  Called
     498 *      from both balloc and bfree.
     499 */
     500
     501static int ballocGetSize(int size, int *q)
     502{
     503        int     mask;
     504
     505        mask = (size == 0) ? 0 : (size-1) >> B_SHIFT;
     506        for (*q = 0; mask; mask >>= 1) {
     507                *q = *q + 1;
     508        }
     509        return ((1 << (B_SHIFT + *q)) + sizeof(bType));
     510}
    450511
    451512/******************************************************************************/
     
    465526/*
    466527 *      Statistics. Do output via calling the writefn callback function with
    467  *      "handle" as the output file handle.
     528 *      "handle" as the output file handle. 
    468529 */
    469530
    470531void bstats(int handle, void (*writefn)(int handle, char_t *fmt, ...))
    471532{
    472         bStatsFileType  *fp;
     533        bStatsFileType  *fp, *files;
     534        bStatsBlkType   *blkp;
    473535        bType                   *bp;
    474         int                             q, count, mem, total;
     536        char_t                  *cp;
     537        int                             q, count, mem, total, len;
    475538        static  int     recurseProtect = 0;
    476539
    477540        if (recurseProtect++ > 0) {
     541                recurseProtect--;
    478542                return;
    479543        }
     
    493557 *      dd ddddd   ddd ddddd  dddd ddddd   dddd
    494558 */
    495         (*writefn)(handle, " Q  Size  Free Bytes Inuse Bytes Allocs\n");
     559        (*writefn)(handle, " Q  Size   Free Bytes Inuse Bytes Allocs\n");
    496560
    497561        total = 0;
     
    499563                count = 0;
    500564                for (bp = bQhead[q]; bp; bp = bp->u.next) {
    501                         a_assert((bp->flags & B_INTEGRITY_MASK) == B_INTEGRITY);
    502565                        count++;
    503566                }
     
    505568                total += mem;
    506569                (*writefn)(handle,
    507                         T("%2d %5d   %3d %5d  %4d %5d   %4d\n"),
     570                        T("%2d %5d   %4d %6d  %4d %5d   %4d\n"),
    508571                        q, 1 << (q + B_SHIFT), count, mem, bStats[q].inuse,
    509572                        bStats[q].inuse * (1 << (q + B_SHIFT)), bStats[q].alloc);
     
    514577/*
    515578 *      Print summary stats
     579 *
     580 *      bFreeSize                       Initial memory reserved with bopen call
     581 *      bStatsMemMalloc         memory from calls to system MALLOC
     582 *      bStatsMemMax           
     583 *      bStatsBallocMax         largest amount of memory from balloc calls
     584 *      bStatsMemInUse
     585 *      bStatsBallocInUse       present balloced memory being used
     586 *      bStatsBlksMax);
     587 *      bStackStart
     588 *      bStackMin);
     589 *      total);
     590 *      bFreeLeft);
     591 *
    516592 */
    517593        (*writefn)(handle, T("Initial free list size    %7d\n"), bFreeSize);
    518594        (*writefn)(handle, T("Max memory malloced       %7d\n"), bStatsMemMalloc);
    519595        (*writefn)(handle, T("Max memory ever used      %7d\n"), bStatsMemMax);
     596        (*writefn)(handle, T("Max memory ever balloced  %7d\n"), bStatsBallocMax);
    520597        (*writefn)(handle, T("Memory currently in use   %7d\n"), bStatsMemInUse);
     598        (*writefn)(handle, T("Memory currently balloced %7d\n"), bStatsBallocInUse);
    521599        (*writefn)(handle, T("Max blocks allocated      %7d\n"), bStatsBlksMax);
    522600        (*writefn)(handle, T("Maximum stack used        %7d\n"),
     
    528606
    529607/*
    530  *      Print per file allocation stats
    531  */
    532         qsort(bStatsFiles, bStatsFilesMax, sizeof(bStatsFileType), bStatsFileSort);
    533         (*writefn)(handle, T("\nPer File Memory Stats\n"));
     608 *      Print per file allocation stats. Sort the copied table.
     609 */
     610        len = sizeof(bStatsFileType) * B_MAX_FILES;
     611        files = malloc(len);
     612        if (files == NULL) {
     613                (*writefn)(handle, T("Can't allocate stats memory\n"));
     614                recurseProtect--;
     615                return;
     616        }
     617        memcpy(files, bStatsFiles, len);
     618        qsort(files, bStatsFilesMax, sizeof(bStatsFileType), bStatsFileSort);
     619       
     620        (*writefn)(handle, T("\nMemory Currently Allocated\n"));
    534621        total = 0;
    535         for (fp = bStatsFiles; fp < &bStatsFiles[bStatsFilesMax]; fp++) {
     622        (*writefn)(handle,
     623                T("                      bytes, blocks in use, total times,")
     624                T("largest,   q\n"));
     625
     626        for (fp = files; fp < &files[bStatsFilesMax]; fp++) {
    536627                if (fp->file[0]) {
    537                         (*writefn)(handle,
    538                                 T("%18s, bytes %7d, blocks in use %5d, total allocs %6d\n"),
    539                                 fp->file, fp->allocated, fp->count, fp->allocs);
     628                        (*writefn)(handle, T("%18s, %7d,         %5d,      %6d, %7d,%4d\n"),
     629                                fp->file, fp->allocated, fp->count, fp->times, fp->largest,
     630                                fp->q);
    540631                        total += fp->allocated;
    541632                }
    542633        }
    543         (*writefn)(handle, T("\nTotal allocated %7d\n"), total);
     634        (*writefn)(handle, T("\nTotal allocated %7d\n\n"), total);
     635
     636/*
     637 *      Dump the actual strings
     638 */
     639        (*writefn)(handle, T("\nStrings\n"));
     640        for (blkp = &bStatsBlks[bStatsBlksMax - 1]; blkp >= bStatsBlks; blkp--) {
     641                if (blkp->ptr) {
     642                        cp = (char_t*) ((char*) blkp->ptr + sizeof(bType));
     643                        fp = blkp->who;
     644                        if (gisalnum(*cp)) {
     645                                (*writefn)(handle, T("%-50s allocated by %s\n"), cp,
     646                                        fp->file);
     647                        }
     648                }
     649        }
     650        free(files);
    544651        recurseProtect--;
    545652}
     
    566673/******************************************************************************/
    567674/*
    568  *      Default output function. Just send to trace channel.
    569  */
    570 
    571 static void bstatsWrite(int handle, char_t *fmt, ...)
    572 {
    573         va_list         args;
    574         char_t          *buf;
    575 
    576         va_start(args, fmt);
    577         buf = NULL;
    578         gvsnprintf(&buf, VALUE_MAX_STRING, fmt, args);
    579         va_end(args);
    580         goahead_trace(0, buf);
    581         if (buf) {
    582                 bfree(B_L, buf);
    583         }
    584 }
    585 
    586 /******************************************************************************/
    587 /*
    588675 *      Accumulate allocation statistics
    589676 */
     
    591678static void bStatsAlloc(B_ARGS_DEC, void *ptr, int q, int size)
    592679{
     680        int                             memSize;
    593681        bStatsFileType  *fp;
    594682        bStatsBlkType   *bp;
    595683        char_t                  name[FNAMESIZE + 10];
    596684
    597         a_assert(file && *file);
    598         a_assert(0 <= q && q <= B_MAX_CLASS);
    599         a_assert(size > 0);
    600 
    601685        gsprintf(name, T("%s:%d"), B_ARGS);
    602686
     
    604688        bStats[q].inuse++;
    605689        bStatsMemInUse += size;
    606 
    607690        if (bStatsMemInUse > bStatsMemMax) {
    608691                bStatsMemMax = bStatsMemInUse;
     692        }
     693        memSize = (1 << (B_SHIFT + q)) + sizeof(bType);
     694        bStatsBallocInUse += memSize;
     695        if (bStatsBallocInUse > bStatsBallocMax) {
     696                bStatsBallocMax = bStatsBallocInUse;
    609697        }
    610698
     
    624712                        fp->allocated += size;
    625713                        fp->count++;
    626                         fp->allocs++;
     714                        fp->times++;
     715                        if (fp->largest < size) {
     716                                fp->largest = size;
     717                                fp->q = q;
     718                        }
    627719                        break;
    628720                }
     
    630722
    631723/*
    632  *      Find the first free slot for this file and add current block size.
     724 *      New entry: find the first free slot and create a new entry
    633725 */
    634726        if (fp >= &bStatsFiles[bStatsFilesMax]) {
     
    638730                                fp->allocated += size;
    639731                                fp->count++;
    640                                 fp->allocs++;
     732                                fp->times++;
     733                                fp->largest = size;
     734                                fp->q = q;
    641735                                if ((fp - bStatsFiles) >= bStatsFilesMax) {
    642736                                        bStatsFilesMax = (fp - bStatsFiles) + 1;
     
    669763static void bStatsFree(B_ARGS_DEC, void *ptr, int q, int size)
    670764{
     765        int                             memSize;
    671766        bStatsFileType  *fp;
    672767        bStatsBlkType   *bp;
    673         char_t                  name[FNAMESIZE + 10];
    674 
    675         a_assert(file && *file);
    676         a_assert(0 <= q && q <= B_MAX_CLASS);
    677         a_assert(size > 0);
    678 
     768
     769        memSize = (1 << (B_SHIFT + q)) + sizeof(bType);
    679770        bStatsMemInUse -= size;
     771        bStatsBallocInUse -= memSize;
    680772        bStats[q].inuse--;
    681773
    682         gsprintf(name, T("%s:%d"), B_ARGS);
    683 
    684 /*
    685  *      Update the per block stats
    686  */
    687         for (bp = bStatsBlks; bp < &bStatsBlks[bStatsBlksMax]; bp++) {
     774/*
     775 *      Update the per block stats. Try from the end first
     776 */
     777        for (bp = &bStatsBlks[bStatsBlksMax - 1]; bp >= bStatsBlks; bp--) {
    688778                if (bp->ptr == ptr) {
    689779                        bp->ptr = NULL;
    690780                        fp = bp->who;
     781                        bp->who = NULL;
    691782                        fp->allocated -= size;
    692783                        fp->count--;
     
    694785                }
    695786        }
    696         a_assert(0);
    697 
    698 }
     787}
     788
     789/******************************************************************************/
     790/*
     791 *      Default output function. Just send to trace channel.
     792 */
     793
     794#undef sprintf
     795static void bstatsWrite(int handle, char_t *fmt, ...)
     796{
     797        va_list         args;
     798        char_t          buf[BUF_MAX];
     799
     800        va_start(args, fmt);
     801        vsprintf(buf, fmt, args);
     802        va_end(args);
     803        traceRaw(buf);
     804}
     805
    699806
    700807#else /* not B_STATS */
     
    713820/*
    714821 *      The following routines verify the integrity of the balloc memory space.
    715  *      These functions depend use the B_FILL feature.  Corruption is defined
     822 *      These functions use the B_FILL feature.  Corruption is defined
    716823 *      as bad integrity flags in allocated blocks or data other than B_FILL_CHAR
    717824 *      being found anywhere in the space which is unallocated and that is not a
    718  *      next pointer in the free queues.  a_assert is called if any corruption is
     825 *      next pointer in the free queues. a_assert is called if any corruption is
    719826 *      found.  CAUTION:  These functions add severe processing overhead and should
    720827 *      only be used when searching for a tough corruption problem.
     
    732839        char    *p;
    733840
    734         memSize = (1 << (B_SHIFT + q));
    735         a_assert((bp->flags & ~B_MALLOCED) == B_INTEGRITY );
     841        memSize = (1 << (B_SHIFT + q)) + sizeof(bType);
     842        a_assert((bp->flags & ~B_MALLOCED) == B_INTEGRITY);
    736843        size = bp->u.size;
    737844        for (p = ((char *)bp)+sizeof(bType)+size; p < ((char*)bp)+memSize; p++) {
     
    751858        char    *p;
    752859
    753         memSize = (1 << (B_SHIFT + q));
     860        memSize = (1 << (B_SHIFT + q)) + sizeof(bType);
    754861        for (p = ((char *)bp)+sizeof(void*); p < ((char*)bp)+memSize; p++) {
    755862                a_assert(*p == B_FILL_CHAR);
     
    757864        bp = (bType *)p;
    758865        a_assert((bp->flags & ~B_MALLOCED) == B_INTEGRITY ||
    759                                 bp->flags == B_FILL_WORD);
     866                bp->flags == B_FILL_WORD);
    760867}
    761868
     
    763870/*
    764871 *      verifyBallocSpace reads through the entire balloc memory space and
    765  *      verifies that all allocated blocks are uncorrupted and that with the
    766  *      exception of free list next pointers all other unallocated space is
     872 *      verifies that all allocated blocks are uncorrupted and that, with the
     873 *      exception of free list next pointers, all other unallocated space is
    767874 *      filled with B_FILL_CHAR.
    768875 */
    769876
    770 static void verifyBallocSpace()
    771 {
     877void verifyBallocSpace()
     878{
     879        int             q;
    772880        char    *p;
    773881        bType   *bp;
    774882
     883/*
     884 *      First verify all the free blocks.
     885 */
     886        for (q = 0; q < B_MAX_CLASS; q++) {     
     887                for (bp = bQhead[q]; bp != NULL; bp = bp->u.next) {
     888                        verifyFreeBlock(bp, q);
     889                }
     890        }
     891
     892/*
     893 *      Now verify other space
     894 */
    775895        p = bFreeBuf;
    776896        while (p < (bFreeBuf + bFreeSize)) {
     
    783903                } else {
    784904                        a_assert(((bp->flags & ~B_MALLOCED) == B_INTEGRITY) ||
    785                                                 bp->flags == B_FILL_WORD);
     905                                bp->flags == B_FILL_WORD);
    786906                        p += (sizeof(bType) + bp->u.size);
    787907                        while (p < (bFreeBuf + bFreeSize) && *p == B_FILL_CHAR) {
     
    808928
    809929/******************************************************************************/
     930
     931void bstats(int handle, void (*writefn)(int handle, char_t *fmt, ...))
     932{
     933}
     934
     935/******************************************************************************/
     936
     937char_t *bstrdupNoBalloc(char_t *s)
     938{
    810939#if UNICODE
    811 char_t* bstrdupNoBalloc(char_t* s)
    812 {
    813940        if (s) {
    814941                return wcsdup(s);
     
    816943                return wcsdup(T(""));
    817944        }
    818 }
    819 #endif /* UNICODE */
    820 
    821 /******************************************************************************/
    822 char* bstrdupANoBalloc(char* s)
     945#else
     946        return bstrdupANoBalloc(s);
     947#endif
     948}
     949
     950/******************************************************************************/
     951
     952char *bstrdupANoBalloc(char *s)
    823953{
    824954        char*   buf;
  • c/src/libnetworking/rtems_webserver/base64.c

    r757e1661 ra6b4c0df  
    22 * base64.c -- Base64 Mime encoding
    33 *
    4  * Copyright (c) Go Ahead Software Inc., 1995-1999. All Rights Reserved.
     4 * Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved.
    55 *
    66 * See the file "license.txt" for usage and redistribution license requirements
     
    6161 */
    6262
    63 int websDecode64(char_t* outbuf, char_t* string, int outlen)
     63int websDecode64(char_t *outbuf, char_t *string, int outlen)
    6464{
    6565        unsigned long   shiftbuf;
    66         char_t*                 cp;
    67         char_t*                 op;
     66        char_t                  *cp, *op;
    6867        int                             c, i, j, shift;
    6968
     
    110109 */
    111110
    112 void websEncode64(char_t* outbuf, char_t* string, int outlen)
     111void websEncode64(char_t *outbuf, char_t *string, int outlen)
    113112{
    114113        unsigned long   shiftbuf;
    115         char_t*                 cp;
    116         char_t*                 op;
     114        char_t                  *cp, *op;
    117115        int                             x, i, j, shift;
    118116
  • c/src/libnetworking/rtems_webserver/default.c

    r757e1661 ra6b4c0df  
    22 * default.c -- Default URL handler. Includes support for ASP.
    33 *
    4  * Copyright (c) Go Ahead Software Inc., 1995-1999. All Rights Reserved.
     4 * Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved.
    55 *
    66 * See the file "license.txt" for usage and redistribution license requirements
     7 *
     8 * $Id$
    79 */
    810
     
    3941
    4042int websDefaultHandler(webs_t wp, char_t *urlPrefix, char_t *webDir, int arg,
    41                                                 char_t *url, char_t *path, char_t* query)
     43                                                char_t *url, char_t *path, char_t *query)
    4244{
    4345        websStatType    sbuf;
    44         char_t                  *lpath, *tmp;
    45         char_t                  *date;
     46        char_t                  *lpath, *tmp, *date;
    4647        int                             bytes, flags, nchars;
    4748
    4849        a_assert(websValid(wp));
    4950        a_assert(url && *url);
    50         a_assert(path && *path);
     51        a_assert(path);
    5152        a_assert(query);
    5253
     
    7576                }
    7677                nchars += gstrlen(websDefaultPage) + 2;
    77                 tmp = NULL;
    78                 gsnprintf(&tmp, nchars, T("%s/%s"), path, websDefaultPage);
     78                fmtAlloc(&tmp, nchars, T("%s/%s"), path, websDefaultPage);
    7979                websRedirect(wp, tmp);
    8080                bfreeSafe(B_L, tmp);
     
    8888                                0666) < 0) {
    8989                        websError(wp, 400,
    90                                 T("Can't open document <b>%s</b><br>for URL <b>%s</b>"),
    91                                         lpath, url);
     90                                T("Cannot open URL <b>%s</b>"), url);
    9291                        return 1;
    9392                }
    9493                if (websPageStat(wp, lpath, path, &sbuf) < 0) {
    95                         websError(wp, 400, T("Can't stat page <b>%s</b><br>for URL <b>%s</b>"),
    96                                 lpath, url);
     94                        websError(wp, 400, T("Cannot stat page for URL <b>%s</b>"),
     95                                url);
     96                        return 1;
    9797                }
    9898
     
    108108                        websWrite(wp, T("HTTP/1.0 304 Use local copy\r\n"));
    109109
    110                         /* by license terms the following line of code must
    111                          * not be modified.
    112                          */
    113                         websWrite(wp, T("Server: GoAhead-Webs\r\n"));
    114 
    115                         if (flags && WEBS_KEEP_ALIVE) {
     110/*
     111 *                      by license terms the following line of code must
     112 *                      not be modified.
     113 */
     114                        websWrite(wp, T("Server: %s\r\n"), WEBS_NAME);
     115
     116                        if (flags & WEBS_KEEP_ALIVE) {
    116117                                websWrite(wp, T("Connection: keep-alive\r\n"));
    117118                        }
     
    132133/*
    133134 *              By license terms the following line of code must not be modified.
    134 */
    135                 websWrite(wp, T("Server: GoAhead-Webs\r\n"));
     135 */
     136                websWrite(wp, T("Server: %s\r\n"), WEBS_NAME);
    136137                bfree(B_L, date);
    137138        }
     
    166167
    167168/*
     169 *      All done if the browser did a HEAD request
     170 */
     171        if (flags & WEBS_HEAD_REQUEST) {
     172                websDone(wp, 200);
     173                return 1;
     174        }
     175
     176/*
    168177 *      Evaluate ASP requests
    169178 */
     
    176185        }
    177186
    178 /*
    179  *      All done if the browser did a HEAD request
    180  */
    181         if (flags & WEBS_HEAD_REQUEST) {
    182                 websDone(wp, 200);
    183                 return 1;
    184         }
     187#ifdef WEBS_SSL_SUPPORT
     188        if (wp->flags & WEBS_SECURE) {
     189                websDefaultWriteEvent(wp);
     190        } else {
     191                websSetRequestSocketHandler(wp, SOCKET_WRITABLE, websDefaultWriteEvent);
     192        }
     193#else
    185194/*
    186195 *      For normal web documents, return the data via background write
    187196 */
    188197        websSetRequestSocketHandler(wp, SOCKET_WRITABLE, websDefaultWriteEvent);
     198#endif
    189199        return 1;
    190200}
     
    241251 *      Create local path for document. Need extra space all "/" and null.
    242252 */
    243         if (npart) {
     253        if (npart || (gstrcmp(path, T("/")) == 0) || (path[0] == '\0')) {
    244254                lpath = balloc(B_L, (gstrlen(dir) + 1 + len + 1) * sizeof(char_t));
    245255                gstrcpy(lpath, dir);
     
    268278static void websDefaultWriteEvent(webs_t wp)
    269279{
    270         int                     len, wrote, flags, bytes, written;
    271         char *          buf;
     280        int             len, wrote, flags, bytes, written;
     281        char    *buf;
    272282
    273283        a_assert(websValid(wp));
     
    275285        flags = websGetRequestFlags(wp);
    276286
    277         wrote = 0;
    278         bytes = 0;
     287        websMarkTime(wp);
     288
     289        wrote = bytes = 0;
    279290        written = websGetRequestWritten(wp);
    280291
     
    285296                bytes = websGetRequestBytes(wp);
    286297/*
    287  *              Note: websWriteBlock may return less than we wanted. It will return
    288  *              -1 on a socket error
     298 *              Note: websWriteDataNonBlock may return less than we wanted. It will
     299 *              return -1 on a socket error
    289300 */
    290301                if ((buf = balloc(B_L, PAGE_READ_BUFSIZE)) == NULL) {
     
    293304                else {
    294305                        while ((len = websPageReadData(wp, buf, PAGE_READ_BUFSIZE)) > 0) {
    295                                 if ((wrote = websWriteBlockData(wp, buf, len)) < 0) {
     306                                if ((wrote = websWriteDataNonBlock(wp, buf, len)) < 0) {
    296307                                        break;
    297308                                }
    298309                                written += wrote;
    299310                                if (wrote != len) {
    300                                         websPageSeek(wp, - (wrote - len));
     311                                        websPageSeek(wp, - (len - wrote));
    301312                                        break;
    302313                                }
     
    331342        if (websDefaultPage) {
    332343                bfree(B_L, websDefaultPage);
     344                websDefaultPage = NULL;
    333345        }
    334346        if (websDefaultDir) {
    335347                bfree(B_L, websDefaultDir);
     348                websDefaultDir = NULL;
    336349        }
    337350}
  • c/src/libnetworking/rtems_webserver/ej.h

    r757e1661 ra6b4c0df  
    22 *      ej.h -- Ejscript(TM) header
    33 *
    4  *      Copyright (c) Go Ahead Software, Inc., 1992-1999
     4 * Copyright (c) GoAhead Software Inc., 1992-2000. All Rights Reserved.
    55 *
    66 *      See the file "license.txt" for information on usage and redistribution
     
    1313
    1414/*
    15  *      Go Ahead Ejscript(TM) header. This defines the Ejscript API and internal
     15 *      GoAhead Ejscript(TM) header. This defines the Ejscript API and internal
    1616 *      structures.
    1717 */
     
    1919/********************************* Includes ***********************************/
    2020
    21 #include        <ctype.h>
    22 #include        <stdarg.h>
    23 #include        <stdlib.h>
    24 #ifndef CE
    25         #include        <fcntl.h>
    26 #endif
    27 
    28 #if LYNX
    29         #include        <unistd.h>
    30 #endif
    31 
    32 #ifdef QNX4
    33         #include        <dirent.h>
    34 #endif
    35 
    36 #if UEMF
     21#if ! UEMF
     22        #include        "basic/basic.h"
     23        #include        "emf/emf.h"
     24#else
    3725        #include        "uemf.h"
    38 #else
    39         #include        <param.h>
    40         #include        <stat.h>
    41         #include        "basic/basicInternal.h"
    42         #include        "emf/emf.h"
    43         #include        "webs/webs.h"
    4426#endif
    4527
    4628/********************************** Defines ***********************************/
    47 /*
    48  *      Constants
    49  */
    50 #define EJ_INC                          110             /* Growth for tags/tokens */
    51 #define EJ_OFFSET                       1               /* hAlloc doesn't like 0 entries */
    52 #define EJ_MAX_RECURSE          100             /* Sanity for maximum recursion */
    53 
    54 /*
    55  *      Ejscript Lexical analyser tokens
    56  */
    57 #define TOK_ERR                         -1              /* Any error */
    58 #define TOK_LPAREN                      1               /* ( */
    59 #define TOK_RPAREN                      2               /* ) */
    60 #define TOK_IF                          3               /* if */
    61 #define TOK_ELSE                        4               /* else */
    62 #define TOK_LBRACE                      5               /* { */
    63 #define TOK_RBRACE                      6               /* } */
    64 #define TOK_LOGICAL                     7               /* ||, &&, ! */
    65 #define TOK_EXPR                        8               /* +, -, /, % */
    66 #define TOK_SEMI                        9               /* ; */
    67 #define TOK_LITERAL                     10              /* literal string */
    68 #define TOK_FUNCTION            11              /* function name */
    69 #define TOK_NEWLINE                     12              /* newline white space */
    70 #define TOK_ID                          13              /* function name */
    71 #define TOK_EOF                         14              /* End of script */
    72 #define TOK_COMMA                       15              /* Comma */
    73 #define TOK_VAR                         16              /* var */
    74 #define TOK_ASSIGNMENT          17              /* = */
    75 #define TOK_FOR                         18              /* for */
    76 #define TOK_INC_DEC                     19              /* ++, -- */
    77 #define TOK_RETURN                      20              /* return */
    78 
    79 /*
    80  *      Expression operators
    81  */
    82 #define EXPR_LESS                       1               /* < */
    83 #define EXPR_LESSEQ                     2               /* <= */
    84 #define EXPR_GREATER            3               /* > */
    85 #define EXPR_GREATEREQ          4               /* >= */
    86 #define EXPR_EQ                         5               /* == */
    87 #define EXPR_NOTEQ                      6               /* != */
    88 #define EXPR_PLUS                       7               /* + */
    89 #define EXPR_MINUS                      8               /* - */
    90 #define EXPR_DIV                        9               /* / */
    91 #define EXPR_MOD                        10              /* % */
    92 #define EXPR_LSHIFT                     11              /* << */
    93 #define EXPR_RSHIFT                     12              /* >> */
    94 #define EXPR_MUL                        13              /* * */
    95 #define EXPR_ASSIGNMENT         14              /* = */
    96 #define EXPR_INC                        15              /* ++ */
    97 #define EXPR_DEC                        16              /* -- */
    98 
    99 /*
    100  *      Conditional operators
    101  */
    102 #define COND_AND                        1               /* && */
    103 #define COND_OR                         2               /* || */
    104 #define COND_NOT                        3               /* ! */
    105 
    106 /*
    107  *      States
    108  */
    109 #define STATE_ERR                               -1                      /* Error state */
    110 #define STATE_EOF                               1                       /* End of file */
    111 #define STATE_COND                              2                       /* Parsing a "(conditional)" stmt */
    112 #define STATE_COND_DONE                 3
    113 #define STATE_RELEXP                    4                       /* Parsing a relational expr */
    114 #define STATE_RELEXP_DONE               5
    115 #define STATE_EXPR                              6                       /* Parsing an expression */
    116 #define STATE_EXPR_DONE                 7
    117 #define STATE_STMT                              8                       /* Parsing General statement */
    118 #define STATE_STMT_DONE                 9
    119 #define STATE_STMT_BLOCK_DONE   10                      /* End of block "}" */
    120 #define STATE_ARG_LIST                  11                      /* Function arg list */
    121 #define STATE_ARG_LIST_DONE             12
    122 #define STATE_DEC_LIST                  16                      /* Declaration list */
    123 #define STATE_DEC_LIST_DONE             17
    124 #define STATE_DEC                               18
    125 #define STATE_DEC_DONE                  19
    126 #define STATE_BEGIN                             STATE_STMT
    127 
    128 /*
    129  *      Flags. Used in ej_t and as parameter to parse()
    130  */
    131 #define FLAGS_EXE                               0x1                             /* Execute statements */
    132 #define FLAGS_VARIABLES                 0x2                             /* Allocated variables store */
    133 #define FLAGS_FUNCTIONS                 0x4                             /* Allocated function store */
    134 
    135 /*
    136  *      Function call structure
    137  */
    138 typedef struct {
    139         char_t          *fname;                                                 /* Function name */
    140         char_t          **args;                                                 /* Args for function (halloc) */
    141         int                     nArgs;                                                  /* Number of args */
    142 } ejfunc_t;
    143 
    144 /*
    145  *      EJ evaluation block structure
    146  */
    147 typedef struct ejEval {
    148         ringq_t         tokbuf;                                                 /* Current token */
    149         ringq_t         script;                                                 /* Input script for parsing */
    150         char_t          *putBackToken;                                  /* Putback token string */
    151         int                     putBackTokenId;                                 /* Putback token ID */
    152         char_t          *line;                                                  /* Current line */
    153         int                     lineLength;                                             /* Current line length */
    154         int                     lineNumber;                                             /* Parse line number */
    155         int                     lineColumn;                                             /* Column in line */
    156 } ejinput_t;
    157 
    158 /*
    159  *      Per Ejscript session structure
    160  */
    161 typedef struct ej {
    162         ejinput_t       *input;                                                 /* Input evaluation block */
    163         sym_fd_t        functions;                                              /* Symbol table for functions */
    164         sym_fd_t        *variables;                                             /* hAlloc list of variables */
    165         int                     variableMax;                                    /* Number of entries */
    166         ejfunc_t        *func;                                                  /* Current function */
    167         char_t          *result;                                                /* Current expression result */
    168         char_t          *error;                                                 /* Error message */
    169         char_t          *token;                                                 /* Pointer to token string */
    170         int                     tid;                                                    /* Current token id */
    171         int                     eid;                                                    /* Halloc handle */
    172         int                     flags;                                                  /* Flags */
    173         int                     userHandle;                                             /* User defined handle */
    174 } ej_t;
    17529
    17630/******************************** Prototypes **********************************/
    17731
     32extern int              ejArgs(int argc, char_t **argv, char_t *fmt, ...);
     33extern void             ejSetResult(int eid, char_t *s);
    17834extern int              ejOpenEngine(sym_fd_t variables, sym_fd_t functions);
    17935extern void             ejCloseEngine(int eid);
    180 extern int              ejOpenBlock(int eid);
    181 extern int              ejCloseBlock(int eid, int vid);
    182 extern char_t   *ejEval(int eid, char_t *script, char_t **emsg);
    183 extern char_t   *ejEvalBlock(int eid, char_t *script, char_t **emsg);
    184 extern char_t   *ejEvalFile(int eid, char_t *path, char_t **emsg);
    18536extern int              ejSetGlobalFunction(int eid, char_t *name,
    18637                                        int (*fn)(int eid, void *handle, int argc, char_t **argv));
    187 extern void             *ejGetGlobalFunction(int eid, char_t *name);
    188 extern int              ejSetGlobalFunctionDirect(sym_fd_t functions, char_t *name,
    189                                         int (*fn)(int eid, void *handle, int argc, char_t **argv));
    190 extern int              ejArgs(int argc, char_t **argv, char_t *fmt, ...);
    191 extern void     ejError(ej_t* ep, char_t* fmt, ...);
    192 extern void             ejSetUserHandle(int eid, int handle);
    193 extern int              ejGetUserHandle(int eid);
    194 extern int              ejGetLineNumber(int eid);
    195 extern void             ejSetResult(int eid, char_t *s);
    196 extern char_t   *ejGetResult(int eid);
    19738extern void             ejSetVar(int eid, char_t *var, char_t *value);
    198 extern void             ejSetLocalVar(int eid, char_t *var, char_t *value);
    19939extern int              ejGetVar(int eid, char_t *var, char_t **value);
    200 extern void             ejSetGlobalVar(int eid, char_t *var, char_t *value);
    201 
    202 extern int              ejLexOpen(ej_t* ep);
    203 extern void     ejLexClose(ej_t* ep);
    204 extern int              ejLexOpenScript(ej_t* ep, char_t *script);
    205 extern void     ejLexCloseScript(ej_t* ep);
    206 extern void     ejLexSaveInputState(ej_t* ep, ejinput_t* state);
    207 extern void     ejLexFreeInputState(ej_t* ep, ejinput_t* state);
    208 extern void     ejLexRestoreInputState(ej_t* ep, ejinput_t* state);
    209 extern int              ejLexGetToken(ej_t* ep, int state);
    210 extern void             ejLexPutbackToken(ej_t* ep, int tid, char_t *string);
    211 
    212 extern sym_fd_t ejGetVariableTable(int eid);
    213 extern sym_fd_t ejGetFunctionTable(int eid);
    214 
    215 extern int              ejEmfOpen(int eid);
    216 extern void             ejEmfClose(int eid);
    217 
    218 extern int ejEmfDbRead(int eid, void *handle, int argc, char_t **argv);
    219 extern int ejEmfDbReadKeyed(int eid, void *handle, int argc, char_t **argv);
    220 extern int ejEmfDbTableGetNrow(int eid, void *handle, int argc, char_t **argv);
    221 extern int ejEmfTrace(int eid, void *handle, int argc, char_t **argv);
    222 extern int ejEmfDbWrite(int eid, void *handle, int argc, char_t **argv);
     40extern char_t   *ejEval(int eid, char_t *script, char_t **emsg);
    22341
    22442#endif /* _h_EJ */
  • c/src/libnetworking/rtems_webserver/ejlex.c

    r757e1661 ra6b4c0df  
    22 * ejlex.c -- Ejscript(TM) Lexical Analyser
    33 *
    4  * Copyright (c) Go Ahead Software, Inc., 1995-1999
     4 * Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved.
    55 *
    66 * See the file "license.txt" for usage and redistribution license requirements
     
    1616/********************************** Includes **********************************/
    1717
    18 #include        "ej.h"
     18#include        "ejIntrn.h"
    1919
    2020#if UEMF
     
    2424#endif
    2525
     26/********************************** Defines ***********************************/
     27#define         OCTAL   8
     28#define         HEX             16
    2629/****************************** Forward Declarations **************************/
    2730
     
    3033static int              inputGetc(ej_t* ep);
    3134static void             inputPutback(ej_t* ep, int c);
     35static int              charConvert(ej_t* ep, int base, int maxDig);
    3236
    3337/************************************* Code ***********************************/
     
    7882                return -1;
    7983        }
    80         if (ringqOpen(&ip->script, EJ_INC, -1) < 0) {
     84        if (ringqOpen(&ip->script, EJ_SCRIPT_INC, -1) < 0) {
    8185                return -1;
    8286        }
     
    8488 *      Put the Ejscript into a ring queue for easy parsing
    8589 */
    86         ringqPutstr(&ip->script, script);
     90        ringqPutStr(&ip->script, script);
    8791
    8892        ip->lineNumber = 1;
     
    179183        if (state->putBackToken) {
    180184                bfree(B_L, state->putBackToken);
     185                state->putBackToken = NULL;
    181186        }
    182187}
     
    190195{
    191196        ep->tid = getLexicalToken(ep, state);
    192         goahead_trace(7, T("ejGetToken: %d, \"%s\"\n"), ep->tid, ep->token);
     197        trace(9, T("ejGetToken: %d, \"%s\"\n"), ep->tid, ep->token);
    193198        return ep->tid;
    194199}
     
    203208        ringq_t         *inq, *tokq;
    204209        ejinput_t*      ip;
    205         int                     done, tid, c, quote, style, back_quoted, lval, i;
     210        int                     done, tid, c, quote, style;
    206211
    207212        a_assert(ep);
     
    219224
    220225        if (ip->putBackTokenId > 0) {
    221                 ringqPutstr(tokq, ip->putBackToken);
     226                ringqPutStr(tokq, ip->putBackToken);
    222227                tid = ip->putBackTokenId;
    223228                ip->putBackTokenId = 0;
     
    386391                        return TOK_ASSIGNMENT;
    387392
    388                 case '!':                                                                       /* "!=" */
     393                case '!':                                                                       /* "!=" or "!"*/
    389394                        if ((c = inputGetc(ep)) < 0) {
    390395                                ejError(ep, T("Syntax Error"));
     
    395400                                return TOK_EXPR;
    396401                        }
    397                         tokenAddChar(ep, COND_NOT);
    398                         return TOK_LOGICAL;
     402                        inputPutback(ep, c);
     403                        tokenAddChar(ep, EXPR_BOOL_COMP);
     404                        return TOK_EXPR;
    399405
    400406                case ';':
     
    429435                                return TOK_ERR;
    430436                        }
    431                         back_quoted = 0;
     437
    432438                        while (c != quote) {
    433                                 if (c == '\\' && !back_quoted) {
    434                                         back_quoted++;
    435                                 } else if (back_quoted) {
    436                                         if (gisdigit((char_t) c)) {
    437                                                 lval = 0;
    438                                                 for (i = 0; i < 3; i++) {
    439                                                         if ('0' <= c && c <= '7') {
    440                                                                 break;
    441                                                         }
    442                                                         lval = lval * 8 + c;
    443                                                         if ((c = inputGetc(ep)) < 0) {
    444                                                                 break;
    445                                                         }
    446                                                 }
    447                                                 c = (int) lval;
    448 
    449                                         } else if (back_quoted) {
     439/*
     440 *                              check for escape sequence characters
     441 */
     442                                if (c == '\\') {
     443                                        c = inputGetc(ep);
     444
     445                                        if (gisdigit(c)) {
     446/*
     447 *                                              octal support, \101 maps to 65 = 'A'. put first char
     448 *                                              back so converter will work properly.
     449 */
     450                                                inputPutback(ep, c);
     451                                                c = charConvert(ep, OCTAL, 3);
     452
     453                                        } else {
    450454                                                switch (c) {
    451455                                                case 'n':
     
    460464                                                        c = '\t'; break;
    461465                                                case 'x':
    462                                                         lval = 0;
    463                                                         for (i = 0; i < 2; i++) {
    464                                                                 if (! gisxdigit((char_t) c)) {
    465                                                                         break;
    466                                                                 }
    467                                                                 lval = lval * 16 + c;
    468                                                                 if ((c = inputGetc(ep)) < 0) {
    469                                                                         break;
    470                                                                 }
    471                                                         }
    472                                                         c = (int) lval;
     466/*
     467 *                                                      hex support, \x41 maps to 65 = 'A'
     468 */
     469                                                        c = charConvert(ep, HEX, 2);
    473470                                                        break;
    474471                                                case 'u':
    475                                                         lval = 0;
    476                                                         for (i = 0; i < 4; i++) {
    477                                                                 if (! gisxdigit((char_t) c)) {
    478                                                                         break;
    479                                                                 }
    480                                                                 lval = lval * 16 + c;
    481                                                                 if ((c = inputGetc(ep)) < 0) {
    482                                                                         break;
    483                                                                 }
    484                                                         }
    485                                                         c = (int) lval;
     472/*
     473 *                                                      unicode support, \x0401 maps to 65 = 'A'
     474 */
     475                                                        c = charConvert(ep, HEX, 2);
     476                                                        c = c*16 + charConvert(ep, HEX, 2);
     477
    486478                                                        break;
    487479                                                case '\'':
    488480                                                case '\"':
     481                                                case '\\':
    489482                                                        break;
     483                                                default:
     484                                                        ejError(ep, T("Invalid Escape Sequence"));
     485                                                        return TOK_ERR;
    490486                                                }
    491487                                        }
    492                                         back_quoted = 0;
    493488                                        if (tokenAddChar(ep, c) < 0) {
    494489                                                return TOK_ERR;
     
    514509                                if ((c = inputGetc(ep)) < 0)
    515510                                        break;
    516                         } while (gisdigit((char_t) c));
     511                        } while (gisdigit(c));
    517512                        inputPutback(ep, c);
    518513                        return TOK_LITERAL;
     
    522517 *                      Identifiers or a function names
    523518 */
    524                         back_quoted = 0;
    525519                        while (1) {
    526                                 if (c == '\\' && !back_quoted) {
    527                                         back_quoted++;
    528                                 } else {
    529                                         back_quoted = 0;
    530                                         if (tokenAddChar(ep, c) < 0) {
     520                                if (c == '\\') {
     521/*
     522 *                                      just ignore any \ characters.
     523 */
     524                                } else if (tokenAddChar(ep, c) < 0) {
    531525                                                break;
    532                                         }
    533526                                }
    534527                                if ((c = inputGetc(ep)) < 0) {
    535528                                        break;
    536529                                }
    537                                 if (!back_quoted && (!gisalnum((char_t) c) && c != '$' &&
    538                                                 c != '_')) {
     530                                if (!gisalnum(c) && c != '$' && c != '_' &&
     531                                        c != '\\') {
    539532                                        break;
    540533                                }
     
    559552                                        return TOK_FOR;
    560553                                } else if (gstrcmp(ep->token, T("return")) == 0) {
     554                                        if ((c == ';') || (c == '(')) {
     555                                                inputPutback(ep, c);
     556                                        }
    561557                                        return TOK_RETURN;
    562558                                }
    563559                        }
    564560
    565 /*
    566  *                      skip white space after token to find out whether this is
    567  *                      a function or not.
     561/* 
     562 *                      Skip white space after token to find out whether this is
     563 *                      a function or not.
    568564 */
    569565                        while (c == ' ' || c == '\t' || c == '\r' || c == '\n') {
     
    678674
    679675/******************************************************************************/
     676/*
     677 *      Convert a hex or octal character back to binary, return original char if
     678 *      not a hex digit
     679 */
     680
     681static int charConvert(ej_t* ep, int base, int maxDig)
     682{
     683        int             i, c, lval, convChar;
     684
     685        lval = 0;
     686        for (i = 0; i < maxDig; i++) {
     687                if ((c = inputGetc(ep)) < 0) {
     688                        break;
     689                }
     690/*
     691 *              Initialize to out of range value
     692 */
     693                convChar = base;
     694                if (gisdigit(c)) {
     695                        convChar = c - '0';
     696                } else if (c >= 'a' && c <= 'f') {
     697                        convChar = c - 'a' + 10;
     698                } else if (c >= 'A' && c <= 'F') {
     699                        convChar = c - 'A' + 10;
     700                }
     701/*
     702 *              if unexpected character then return it to buffer.
     703 */
     704                if (convChar >= base) {
     705                        inputPutback(ep, c);
     706                        break;
     707                }
     708                lval = (lval * base) + convChar;
     709        }
     710        return lval;
     711}
     712
     713/******************************************************************************/
  • c/src/libnetworking/rtems_webserver/ejparse.c

    r757e1661 ra6b4c0df  
    22 * ejparse.c -- Ejscript(TM) Parser
    33 *
    4  * Copyright (c) Go Ahead Software, Inc., 1995-1999
     4 * Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved.
    55 *
    66 * See the file "license.txt" for usage and redistribution license requirements
     
    1616/********************************** Includes **********************************/
    1717
    18 #include        "ej.h"
     18#include        "ejIntrn.h"
     19
     20#if CE
     21        #include        "CE/wincompat.h"
     22#endif
    1923
    2024/********************************** Local Data ********************************/
     
    2529/****************************** Forward Declarations **************************/
    2630
     31#ifndef B_STATS
     32#define setString(a,b,c)         setstring(b,c)
     33#endif
     34
    2735static ej_t             *ejPtr(int eid);
    2836static void             clearString(char_t **ptr);
    29 static void             setString(char_t **ptr, char_t *s);
     37static void             setString(B_ARGS_DEC, char_t **ptr, char_t *s);
    3038static void             appendString(char_t **ptr, char_t *s);
    31 static void             freeVar(sym_t* sp);
    3239static int              parse(ej_t *ep, int state, int flags);
    3340static int              parseStmt(ej_t *ep, int state, int flags);
     
    4047static int              evalFunction(ej_t *ep);
    4148static void             freeFunc(ejfunc_t *func);
     49static void             ejRemoveNewlines(ej_t *ep, int state);
    4250
    4351/************************************* Code ***********************************/
     
    5866
    5967/*
    60  *      Create a top level symbol table if one is not provided for variables and 
    61  *      functions. Variables may create other symbol tables for block level 
     68 *      Create a top level symbol table if one is not provided for variables and
     69 *      functions. Variables may create other symbol tables for block level
    6270 *      declarations so we use hAlloc to manage a list of variable tables.
    6371 */
     
    7381                ep->variables[vid] = symOpen(64) + EJ_OFFSET;
    7482                ep->flags |= FLAGS_VARIABLES;
    75 
    7683        } else {
    7784                ep->variables[vid] = variables + EJ_OFFSET;
     
    123130        ejLexClose(ep);
    124131
    125         if (ep->flags & FLAGS_VARIABLES) {
    126                 for (i = ep->variableMax - 1; i >= 0; i--) {
    127                         symClose(ep->variables[i] - EJ_OFFSET, freeVar);
    128                         ep->variableMax = hFree((void***) &ep->variables, i);
    129                 }
    130         }
     132        for (i = ep->variableMax - 1; i >= 0; i--) {
     133                if (ep->flags & FLAGS_VARIABLES) {
     134                        symClose(ep->variables[i] - EJ_OFFSET);
     135                }
     136                ep->variableMax = hFree((void***) &ep->variables, i);
     137        }
     138
    131139        if (ep->flags & FLAGS_FUNCTIONS) {
    132                 symClose(ep->functions, freeVar);
     140                symClose(ep->functions);
    133141        }
    134142
     
    137145}
    138146
    139 /******************************************************************************/
    140 /*
    141  *      Callback from symClose. Free the variable.
    142  */
    143 
    144 static void freeVar(sym_t* sp)
    145 {
    146         valueFree(&sp->content);
    147 }
    148 
     147#ifndef __NO_EJ_FILE
    149148/******************************************************************************/
    150149/*
     
    152151 */
    153152
    154 #if DEV
    155153char_t *ejEvalFile(int eid, char_t *path, char_t **emsg)
    156154{
     
    166164                *emsg = NULL;
    167165        }
     166
    168167        if ((ep = ejPtr(eid)) == NULL) {
    169168                return NULL;
     
    174173                return NULL;
    175174        }
     175       
    176176        if (gstat(path, &sbuf) < 0) {
    177                 close(fd);
     177                gclose(fd);
    178178                ejError(ep, T("Cant stat %s"), path);
    179179                return NULL;
    180180        }
     181       
    181182        if ((fileBuf = balloc(B_L, sbuf.st_size + 1)) == NULL) {
    182                 close(fd);
     183                gclose(fd);
    183184                ejError(ep, T("Cant malloc %d"), sbuf.st_size);
    184185                return NULL;
    185186        }
    186         if (read(fd, fileBuf, sbuf.st_size) != (int)sbuf.st_size) {
    187                 close(fd);
     187       
     188        if (gread(fd, fileBuf, sbuf.st_size) != (int)sbuf.st_size) {
     189                gclose(fd);
    188190                bfree(B_L, fileBuf);
    189191                ejError(ep, T("Error reading %s"), path);
    190192                return NULL;
    191193        }
     194       
    192195        fileBuf[sbuf.st_size] = '\0';
    193         close(fd);
    194 
    195         if ((script = ballocAscToUni(fileBuf)) == NULL) {
     196        gclose(fd);
     197
     198        if ((script = ballocAscToUni(fileBuf, sbuf.st_size)) == NULL) {
    196199                bfree(B_L, fileBuf);
    197200                ejError(ep, T("Cant malloc %d"), sbuf.st_size + 1);
     
    205208        return rs;
    206209}
    207 #endif
     210#endif /* __NO_EJ_FILE */
    208211
    209212/******************************************************************************/
     
    211214 *      Create a new variable scope block so that consecutive ejEval calls may
    212215 *      be made with the same varible scope. This space MUST be closed with
    213  *      ejCloseBlock when the evaluations are complete.         
     216 *      ejCloseBlock when the evaluations are complete.
    214217 */
    215218
     
    217220{
    218221        ej_t    *ep;
    219         int             vid;   
     222        int             vid;
    220223
    221224        if((ep = ejPtr(eid)) == NULL) {
    222225                return -1;
    223         }       
     226        }
     227
    224228        if ((vid = hAlloc((void***) &ep->variables)) < 0) {
    225229                return -1;
    226230        }
     231
    227232        if (vid >= ep->variableMax) {
    228233                ep->variableMax = vid + 1;
    229         }       
     234        }
    230235        ep->variables[vid] = symOpen(64) + EJ_OFFSET;
    231236        return vid;
     
    242247{
    243248        ej_t    *ep;
    244        
     249
    245250        if((ep = ejPtr(eid)) == NULL) {
    246251                return -1;
    247252        }
    248         symClose(ep->variables[vid] - EJ_OFFSET, freeVar);
     253        symClose(ep->variables[vid] - EJ_OFFSET);
    249254        ep->variableMax = hFree((void***) &ep->variables, vid);
    250         return 0;       
    251 
    252 }
     255        return 0;
     256
     257}
     258
    253259/******************************************************************************/
    254260/*
     
    264270        a_assert(script);
    265271
    266         vid = ejOpenBlock(eid); 
     272        vid = ejOpenBlock(eid);
    267273        returnVal = ejEval(eid, script, emsg);
    268274        ejCloseBlock(eid, vid);
     
    273279/******************************************************************************/
    274280/*
    275  *      Parse and evaluate a Ejscript. The caller may provide a symbol table to 
     281 *      Parse and evaluate a Ejscript. The caller may provide a symbol table to
    276282 *      use for variables and function definitions. Return char_t pointer on
    277283 *      success otherwise NULL pointer is returned.
     
    283289        ejinput_t       *oldBlock;
    284290        int             state;
    285 
     291        void    *endlessLoopTest;
     292        int             loopCounter;
     293       
     294       
    286295        a_assert(script);
    287296
    288297        if (emsg) {
    289298                *emsg = NULL;
    290         }
     299        }
     300
    291301        if ((ep = ejPtr(eid)) == NULL) {
    292302                return NULL;
    293303        }
    294304
    295         setString(&ep->result, T(""));
     305        setString(B_L, &ep->result, T(""));
    296306
    297307/*
     
    304314 *      Do the actual parsing and evaluation
    305315 */
     316        loopCounter = 0;
     317        endlessLoopTest = NULL;
     318
    306319        do {
    307320                state = parse(ep, STATE_BEGIN, FLAGS_EXE);
     321
     322                if (state == STATE_RET) {
     323                        state = STATE_EOF;
     324                }
     325/*
     326 *              prevent parser from going into infinite loop.  If parsing the same
     327 *              line 10 times then fail and report Syntax error.  Most normal error
     328 *              are caught in the parser itself.
     329 */
     330                if (endlessLoopTest == ep->input->script.servp) {
     331                        if (loopCounter++ > 10) {
     332                                state = STATE_ERR;
     333                                ejError(ep, T("Syntax error"));
     334                        }
     335                } else {
     336                        endlessLoopTest = ep->input->script.servp;
     337                        loopCounter = 0;
     338                }
    308339        } while (state != STATE_EOF && state != STATE_ERR);
    309340
     
    325356                return ep->result;
    326357        }
     358
    327359        if (state == STATE_ERR) {
    328360                return NULL;
    329361        }
     362
    330363        return ep->result;
    331364}
     
    345378 */
    346379        case STATE_STMT:
     380                if ((state = parseStmt(ep, state, flags)) != STATE_STMT_DONE &&
     381                        state != STATE_EOF && state != STATE_STMT_BLOCK_DONE &&
     382                        state != STATE_RET) {
     383                        state = STATE_ERR;
     384                }
     385                break;
     386
    347387        case STATE_DEC:
    348                 state = parseStmt(ep, state, flags);
     388                if ((state = parseStmt(ep, state, flags)) != STATE_DEC_DONE &&
     389                        state != STATE_EOF) {
     390                        state = STATE_ERR;
     391                }
    349392                break;
    350393
    351394        case STATE_EXPR:
    352                 state = parseStmt(ep, state, flags);
     395                if ((state = parseStmt(ep, state, flags)) != STATE_EXPR_DONE &&
     396                        state != STATE_EOF) {
     397                        state = STATE_ERR;
     398                }
    353399                break;
    354400
     
    398444        ejfunc_t        *saveFunc;
    399445        ejinput_t       condScript, endScript, bodyScript, incrScript;
    400         char_t          *value;
    401         char_t          *identifier;
     446        char_t          *value, *identifier;
    402447        int                     done, expectSemi, thenFlags, elseFlags, tid, cond, forFlags;
     448        int                     ejVarType;
    403449
    404450        a_assert(ep);
     
    452498 */
    453499                        identifier = NULL;
    454                         setString(&identifier, ep->token);
     500                        setString(B_L, &identifier, ep->token);
    455501/*
    456502 *                      Peek ahead to see if this is an assignment
     
    459505                        if (tid == TOK_ASSIGNMENT) {
    460506                                if (parse(ep, STATE_RELEXP, flags) != STATE_RELEXP_DONE) {
     507                                        clearString(&identifier);
    461508                                        goto error;
    462509                                }
     
    464511                                        if ( state == STATE_DEC ) {
    465512                                                ejSetLocalVar(ep->eid, identifier, ep->result);
    466                                         }
    467                                         else {
    468                                                 if (ejGetVar(ep->eid, identifier, &value) > 0) {
     513                                        } else {
     514                                                ejVarType = ejGetVar(ep->eid, identifier, &value);
     515                                                if (ejVarType > 0) {
    469516                                                        ejSetLocalVar(ep->eid, identifier, ep->result);
    470517                                                } else {
     
    476523                        } else if (tid == TOK_INC_DEC ) {
    477524                                value = NULL;
    478                                 if ( flags & FLAGS_EXE ) {
    479                                         if (ejGetVar(ep->eid, identifier, &value) < 0) {
     525                                if (flags & FLAGS_EXE) {
     526                                        ejVarType = ejGetVar(ep->eid, identifier, &value);
     527                                        if (ejVarType < 0) {
    480528                                                ejError(ep, T("Undefined variable %s\n"), identifier);
    481529                                                goto error;
    482530                                        }
    483                                         setString(&ep->result, value);
     531                                        setString(B_L, &ep->result, value);
    484532                                        if (evalExpr(ep, value, (int) *ep->token, T("1")) < 0) {
    485533                                                state = STATE_ERR;
    486534                                                break;
    487535                                        }
    488                                         ejSetGlobalVar(ep->eid, identifier, ep->result);
     536
     537                                        if (ejVarType > 0) {
     538                                                ejSetLocalVar(ep->eid, identifier, ep->result);
     539                                        } else {
     540                                                ejSetGlobalVar(ep->eid, identifier, ep->result);
     541                                        }
    489542                                }
    490543
     
    496549                                if (state == STATE_DEC) {
    497550                                        if (ejGetVar(ep->eid, identifier, &value) > 0) {
    498                                                 ejError(ep, T("Variable already declared"), 
     551                                                ejError(ep, T("Variable already declared"),
    499552                                                        identifier);
    500553                                                clearString(&identifier);
     
    505558                                        if ( flags & FLAGS_EXE ) {
    506559                                                if (ejGetVar(ep->eid, identifier, &value) < 0) {
    507                                                         ejError(ep, T("Undefined variable %s\n"), 
     560                                                        ejError(ep, T("Undefined variable %s\n"),
    508561                                                                identifier);
    509562                                                        clearString(&identifier);
     
    512565                                        }
    513566                                }
    514                                 setString(&ep->result, value);
     567                                setString(B_L, &ep->result, value);
    515568                                ejLexPutbackToken(ep, tid, ep->token);
    516569                        }
     
    527580 *                      Set the result to the literal (number or string constant)
    528581 */
    529                         setString(&ep->result, ep->token);
     582                        setString(B_L, &ep->result, ep->token);
    530583                        if (state == STATE_STMT) {
    531584                                expectSemi++;
     
    542595                        }
    543596                        memset(&func, 0, sizeof(ejfunc_t));
    544                         setString(&func.fname, ep->token);
     597                        setString(B_L, &func.fname, ep->token);
    545598                        ep->func = &func;
    546599
    547                         setString(&ep->result, T(""));
     600                        setString(B_L, &ep->result, T(""));
    548601                        if (ejLexGetToken(ep, state) != TOK_LPAREN) {
    549602                                freeFunc(&func);
     
    605658                        }
    606659/*
    607  *                      Process the "then" case
    608  */
    609                         if (parse(ep, STATE_STMT, thenFlags) != STATE_STMT_DONE) {
    610                                 goto error;
    611                         }
     660 *                      Process the "then" case.  Allow for RETURN statement
     661 */
     662                        switch (parse(ep, STATE_STMT, thenFlags)) {
     663                        case STATE_RET:
     664                                return STATE_RET;
     665                        case STATE_STMT_DONE:
     666                                break;
     667                        default:
     668                                goto error;
     669                        }
     670/*
     671 *                      check to see if there is an "else" case
     672 */
     673                        ejRemoveNewlines(ep, state);
    612674                        tid = ejLexGetToken(ep, state);
    613675                        if (tid != TOK_ELSE) {
     
    617679                        }
    618680/*
    619  *                      Process the "else" case
    620  */
    621                         if (parse(ep, STATE_STMT, elseFlags) != STATE_STMT_DONE) {
     681 *                      Process the "else" case.  Allow for return.
     682 */
     683                        switch (parse(ep, STATE_STMT, elseFlags)) {
     684                        case STATE_RET:
     685                                return STATE_RET;
     686                        case STATE_STMT_DONE:
     687                                break;
     688                        default:
    622689                                goto error;
    623690                        }
     
    651718
    652719/*
    653  *                      The first time through, we save the current input context just 
     720 *                      The first time through, we save the current input context just
    654721 *                      to each step: prior to the conditional, the loop increment and the
    655722 *                      loop body.
     
    664731                                goto error;
    665732                        }
    666                        
     733
    667734/*
    668735 *                      Don't execute the loop increment statement or the body first time
     
    678745
    679746/*
    680  *                      Parse the body and remember the end of the body script 
     747 *                      Parse the body and remember the end of the body script
    681748 */
    682749                        ejLexSaveInputState(ep, &bodyScript);
     
    694761 */
    695762                                ejLexRestoreInputState(ep, &bodyScript);
    696                                 if (parse(ep, STATE_STMT, flags) != STATE_STMT_DONE) {
     763
     764                                switch (parse(ep, STATE_STMT, flags)) {
     765                                case STATE_RET:
     766                                        return STATE_RET;
     767                                case STATE_STMT_DONE:
     768                                        break;
     769                                default:
    697770                                        goto error;
    698771                                }
     
    761834                        } while (state == STATE_STMT_DONE);
    762835
     836/*
     837 *                      Allow return statement.
     838 */
     839                        if (state == STATE_RET) {
     840                                return state;
     841                        }
     842
    763843                        if (ejLexGetToken(ep, state) != TOK_RBRACE) {
    764844                                goto error;
     
    780860                                while ( ejLexGetToken(ep, state) != TOK_EOF );
    781861                                done++;
    782                                 return STATE_EOF;
     862                                return STATE_RET;
    783863                        }
    784864                        break;
     
    795875 *              Skip newline after semi-colon
    796876 */
    797                 tid = ejLexGetToken(ep, state);
    798                 if (tid != TOK_NEWLINE) {
    799                         ejLexPutbackToken(ep, tid, ep->token);
    800                 }
     877                ejRemoveNewlines(ep, state);
    801878        }
    802879
     
    811888                ejLexFreeInputState(ep, &bodyScript);
    812889        }
     890
    813891        if (state == STATE_STMT) {
    814892                return STATE_STMT_DONE;
     
    9291007        a_assert(ep);
    9301008
    931         setString(&ep->result, T(""));
     1009        setString(B_L, &ep->result, T(""));
    9321010        rhs = lhs = NULL;
    9331011        operator = 0;
     
    9431021                        break;
    9441022                }
     1023
    9451024                if (operator > 0) {
    946                         setString(&rhs, ep->result);
     1025                        setString(B_L, &rhs, ep->result);
    9471026                        if (evalCond(ep, lhs, operator, rhs) < 0) {
    9481027                                state = STATE_ERR;
     
    9501029                        }
    9511030                }
    952                 setString(&lhs, ep->result);
     1031                setString(B_L, &lhs, ep->result);
    9531032
    9541033                tid = ejLexGetToken(ep, state);
     
    9701049                bfree(B_L, lhs);
    9711050        }
     1051
    9721052        if (rhs) {
    9731053                bfree(B_L, rhs);
     
    9881068        a_assert(ep);
    9891069
    990         setString(&ep->result, T(""));
     1070        setString(B_L, &ep->result, T(""));
    9911071        rhs = lhs = NULL;
    9921072        rel = 0;
     1073        tid = 0;
    9931074
    9941075        do {
     
    9971078 *      to evalutate each term which returns the result in ep->result.
    9981079 */
    999                 state = parse(ep, STATE_EXPR, flags);
    1000                 if (state != STATE_EXPR_DONE) {
    1001                         state = STATE_ERR;
    1002                         break;
    1003                 }
    1004                 if (rel > 0) {
    1005                         setString(&rhs, ep->result);
    1006                         if (evalExpr(ep, lhs, rel, rhs) < 0) {
     1080                if (tid == TOK_LOGICAL) {
     1081                        if ((state = parse(ep, STATE_RELEXP, flags)) != STATE_RELEXP_DONE) {
    10071082                                state = STATE_ERR;
    10081083                                break;
    10091084                        }
    1010                 }
    1011                 setString(&lhs, ep->result);
    1012 
    1013                 if ((tid = ejLexGetToken(ep, state)) == TOK_EXPR) {
    1014                         rel = (int) *ep->token;
    1015 
    1016                 } else if (tid == TOK_INC_DEC) {
     1085                } else {
     1086                        if ((state = parse(ep, STATE_EXPR, flags)) != STATE_EXPR_DONE) {
     1087                                state = STATE_ERR;
     1088                                break;
     1089                        }
     1090                }
     1091
     1092                if (rel > 0) {
     1093                        setString(B_L, &rhs, ep->result);
     1094                        if (tid == TOK_LOGICAL) {
     1095                                if (evalCond(ep, lhs, rel, rhs) < 0) {
     1096                                        state = STATE_ERR;
     1097                                        break;
     1098                                }
     1099                        } else {
     1100                                if (evalExpr(ep, lhs, rel, rhs) < 0) {
     1101                                        state = STATE_ERR;
     1102                                        break;
     1103                                }
     1104                        }
     1105                }
     1106                setString(B_L, &lhs, ep->result);
     1107
     1108                if ((tid = ejLexGetToken(ep, state)) == TOK_EXPR ||
     1109                         tid == TOK_INC_DEC || tid == TOK_LOGICAL) {
    10171110                        rel = (int) *ep->token;
    10181111
     
    10241117        } while (state == STATE_EXPR_DONE);
    10251118
    1026         if (rhs)
     1119        if (rhs) {
    10271120                bfree(B_L, rhs);
    1028         if (lhs)
     1121        }
     1122
     1123        if (lhs) {
    10291124                bfree(B_L, lhs);
     1125        }
     1126
    10301127        return state;
    10311128}
     
    10461143
    10471144        lval = 0;
    1048         if (gisdigit(*lhs) && gisdigit(*rhs)) {
     1145        if (gisdigit((int)*lhs) && gisdigit((int)*rhs)) {
    10491146                l = gatoi(lhs);
    10501147                r = gatoi(rhs);
     
    10611158                }
    10621159        } else {
    1063                 if (!gisdigit(*lhs)) {
     1160                if (!gisdigit((int)*lhs)) {
    10641161                        ejError(ep, T("Conditional must be numeric"), lhs);
    10651162                } else {
     
    10671164                }
    10681165        }
    1069                
     1166
    10701167        stritoa(lval, buf, sizeof(buf));
    1071         setString(&ep->result, buf);
     1168        setString(B_L, &ep->result, buf);
    10721169        return 0;
    10731170}
     
    10921189        numeric = 1;
    10931190        for (cp = lhs; *cp; cp++) {
    1094                 if (!gisdigit(*cp)) {
     1191                if (!gisdigit((int)*cp)) {
    10951192                        numeric = 0;
    10961193                        break;
    10971194                }
    10981195        }
     1196
    10991197        if (numeric) {
    11001198                for (cp = rhs; *cp; cp++) {
    1101                         if (!gisdigit(*cp)) {
     1199                        if (!gisdigit((int)*cp)) {
    11021200                                numeric = 0;
    11031201                                break;
     
    11051203                }
    11061204        }
     1205
    11071206        if (numeric) {
    11081207                l = gatoi(lhs);
     
    11611260                case EXPR_GREATEREQ:
    11621261                        lval = (l >= r) ? 1 : 0;
     1262                        break;
     1263                case EXPR_BOOL_COMP:
     1264                        lval = (r == 0) ? 1 : 0;
    11631265                        break;
    11641266                default:
     
    12061308
    12071309        stritoa(lval, buf, sizeof(buf));
    1208         setString(&ep->result, buf);
     1310        setString(B_L, &ep->result, buf);
    12091311        return 0;
    12101312}
     
    12241326                return -1;
    12251327        }
     1328
    12261329        fn = (int (*)(int, void*, int, char_t**)) sp->content.value.integer;
    12271330        if (fn == NULL) {
     
    12301333        }
    12311334
    1232         return (*fn)(ep->eid, (void*) ep->userHandle, ep->func->nArgs, 
     1335        return (*fn)(ep->eid, (void*) ep->userHandle, ep->func->nArgs,
    12331336                ep->func->args);
    12341337}
     
    12511354        va_start(args, fmt);
    12521355        msgbuf = NULL;
    1253         gvsnprintf(&msgbuf, E_MAX_ERROR, fmt, args);
     1356        fmtValloc(&msgbuf, E_MAX_ERROR, fmt, args);
    12541357        va_end(args);
    12551358
    12561359        if (ep && ip) {
    1257                 errbuf = NULL;
    1258                 gsnprintf(&errbuf, E_MAX_ERROR, T("%s\n At line %d, line => \n\n%s\n"),
     1360                fmtAlloc(&errbuf, E_MAX_ERROR, T("%s\n At line %d, line => \n\n%s\n"),
    12591361                        msgbuf, ip->lineNumber, ip->line);
    12601362                bfreeSafe(B_L, ep->error);
     
    12841386 */
    12851387
    1286 static void setString(char_t **ptr, char_t *s)
     1388static void setString(B_ARGS_DEC, char_t **ptr, char_t *s)
    12871389{
    12881390        a_assert(ptr);
    12891391
    12901392        if (*ptr) {
    1291                 bfree(B_L, *ptr);
    1292         }
    1293         *ptr = bstrdup(B_L, s);
     1393                bfree(B_ARGS, *ptr);
     1394        }
     1395        *ptr = bstrdup(B_ARGS, s);
    12941396}
    12951397
     
    13201422 */
    13211423
    1322 int ejSetGlobalFunction(int eid, char_t *name, 
     1424int ejSetGlobalFunction(int eid, char_t *name,
    13231425        int (*fn)(int eid, void *handle, int argc, char_t **argv))
    13241426{
     
    13361438 */
    13371439
    1338 int ejSetGlobalFunctionDirect(sym_fd_t functions, char_t *name, 
     1440int ejSetGlobalFunctionDirect(sym_fd_t functions, char_t *name,
    13391441        int (*fn)(int eid, void *handle, int argc, char_t **argv))
    13401442{
     
    13471449/******************************************************************************/
    13481450/*
     1451 *      Remove ("undefine") a function
     1452 */
     1453
     1454int ejRemoveGlobalFunction(int eid, char_t *name)
     1455{
     1456        ej_t    *ep;
     1457
     1458        if ((ep = ejPtr(eid)) == NULL) {
     1459                return -1;
     1460        }
     1461        return symDelete(ep->functions, name);
     1462}
     1463
     1464/******************************************************************************/
     1465/*
    13491466 *      Get a function definition
    13501467 */
     
    13591476                return NULL;
    13601477        }
     1478
    13611479        if ((sp = symLookup(ep->functions, name)) != NULL) {
    13621480                fn = (int (*)(int, void*, int, char_t**)) sp->content.value.integer;
     
    13681486/******************************************************************************/
    13691487/*
    1370  *      Utility routine to crack Ejscript arguments. Return the number of args 
     1488 *      Utility routine to crack Ejscript arguments. Return the number of args
    13711489 *      seen. This routine only supports %s and %d type args.
    13721490 *
     
    14781596                return;
    14791597        }
    1480         setString(&ep->result, s);
     1598        setString(B_L, &ep->result, s);
    14811599}
    14821600
     
    15121630                return;
    15131631        }
     1632
    15141633        if (value == NULL) {
    15151634                v = valueString(value, 0);
     
    15361655                return;
    15371656        }
     1657
    15381658        if (value == NULL) {
    15391659                v = valueString(value, 0);
     
    15461666/******************************************************************************/
    15471667/*
    1548  *      Set a global variable. Note: a variable with a value of NULL means 
     1668 *      Set a global variable. Note: a variable with a value of NULL means
    15491669 *      declared but undefined. The value is defined in the global variable frame.
    15501670 */
     
    15601680                return;
    15611681        }
     1682
    15621683        if (value == NULL) {
    15631684                v = valueString(value, 0);
     
    15861707        }
    15871708
    1588         for (i = ep->variableMax - 1; i >= 0; i--) {
    1589                 if ((sp = symLookup(ep->variables[i] - EJ_OFFSET, var)) == NULL) {
    1590                         continue;
    1591                 }
    1592                 a_assert(sp->content.type == string);
    1593                 *value = sp->content.value.string;
    1594                 return i;
    1595         }
    1596         return -1;
    1597 }
    1598 
    1599 /******************************************************************************/
    1600 #if UNUSED
     1709        i = ep->variableMax - 1;
     1710        if ((sp = symLookup(ep->variables[i] - EJ_OFFSET, var)) == NULL) {
     1711                i = 0;
     1712                if ((sp = symLookup(ep->variables[0] - EJ_OFFSET, var)) == NULL) {
     1713                        return -1;
     1714                }
     1715        }
     1716        a_assert(sp->content.type == string);
     1717        *value = sp->content.value.string;
     1718        return i;
     1719}
     1720
     1721/******************************************************************************/
    16011722/*
    16021723 *      Get the variable symbol table
     
    16101731                return -1;
    16111732        }
    1612         return ep->variables;
    1613 }
    1614 #endif
     1733        return *ep->variables;
     1734}
     1735
    16151736/******************************************************************************/
    16161737/*
     
    16411762                func->nArgs = hFree((void***) &func->args, i);
    16421763        }
     1764
    16431765        if (func->fname) {
    16441766                bfree(B_L, func->fname);
     
    16481770
    16491771/******************************************************************************/
    1650 /* 
     1772/*
    16511773 *      Get Ejscript pointer
    16521774 */
     
    16641786
    16651787/******************************************************************************/
     1788/*
     1789 *      This function removes any new lines.  Used for else     cases, etc.
     1790 */
     1791static void ejRemoveNewlines(ej_t *ep, int state)
     1792{
     1793        int tid;
     1794
     1795        do {
     1796                tid = ejLexGetToken(ep, state);
     1797        } while (tid == TOK_NEWLINE);
     1798
     1799        ejLexPutbackToken(ep, tid, ep->token);
     1800}
     1801
     1802/******************************************************************************/
  • c/src/libnetworking/rtems_webserver/form.c

    r757e1661 ra6b4c0df  
    22 * form.c -- Form processing (in-memory CGI) for the GoAhead Web server
    33 *
    4  * Copyright (c) Go Ahead Software Inc., 1995-1999. All Rights Reserved.
     4 * Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved.
    55 *
    66 * See the file "license.txt" for usage and redistribution license requirements
     
    3030
    3131int websFormHandler(webs_t wp, char_t *urlPrefix, char_t *webDir, int arg,
    32         char_t *url, char_t *path, char_t* query)
     32        char_t *url, char_t *path, char_t *query)
    3333{
    3434        sym_t           *sp;
    3535        char_t          formBuf[FNAMESIZE];
    3636        char_t          *cp, *formName;
    37         int                     (*fn)(void *sock, char_t* path, char_t *args);
     37        int                     (*fn)(void *sock, char_t *path, char_t *args);
    3838
    3939        a_assert(websValid(wp));
     
    6464                websError(wp, 200, T("Form %s is not defined"), formName);
    6565        } else {
    66                 fn = (int (*)(void*, char_t*, char_t*)) sp->content.value.integer;
     66                fn = (int (*)(void *, char_t *, char_t *)) sp->content.value.integer;
    6767                a_assert(fn);
    6868                if (fn) {
     
    7171 */
    7272                        (*fn)((void*) wp, formName, query);
     73
     74/*
     75 *                      Remove the test to force websDone, since this prevents
     76 *                      the server "push" from a form>
     77 */
     78#if 0 /* push */
    7379                        if (websValid(wp)) {
    7480                                websError(wp, 200, T("Form didn't call websDone"));
    7581                        }
     82#endif /* push */
    7683                }
    7784        }
     
    8794        char_t *query))
    8895{
    89         static int once = 0;
    90 
    9196        a_assert(name && *name);
    9297        a_assert(fn);
     
    96101        }
    97102
    98         if (once++ == 0) {
    99                 websFormOpen();
    100         }
    101103        symEnter(formSymtab, name, valueInteger((int) fn), (int) NULL);
    102104        return 0;
     
    110112void websFormOpen()
    111113{
    112         formSymtab = symOpen(64);
     114        formSymtab = symOpen(WEBS_SYM_INIT);
    113115}
    114116
     
    121123{
    122124        if (formSymtab != -1) {
    123                 symClose(formSymtab, NULL);
     125                symClose(formSymtab);
     126                formSymtab = -1;
    124127        }
    125128}
     
    140143 *      By license terms the following line of code must not be modified
    141144 */
    142         websWrite(wp, T("Server: GoAhead-Webs\r\n"));
     145        websWrite(wp, T("Server: %s\r\n"), WEBS_NAME);
    143146
    144147        websWrite(wp, T("Pragma: no-cache\n"));
  • c/src/libnetworking/rtems_webserver/h.c

    r757e1661 ra6b4c0df  
    22 * h.c -- Handle allocation module
    33 *
    4  * Copyright (c) GoAhead Software Inc., 1995-1999. All Rights Reserved.
     4 * Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved.
    55 * See the file "license.txt" for usage and redistribution license requirements
    66 */
     
    99
    1010/*
    11  *      This module provides a simple API to allocate and free handles
    12  *      It maintains a dynamic array of pointers. These usually point to 
     11 *      This module provides a simple API to allocate and free handles
     12 *      It maintains a dynamic array of pointers. These usually point to
    1313 *      per-handle structures.
    1414 */
     
    3737/*********************************** Code *************************************/
    3838/*
    39  *      Allocate a new file handle.  On the first call, the caller must set the 
     39 *      Allocate a new file handle.  On the first call, the caller must set the
    4040 *      handle map to be a pointer to a null pointer.  *map points to the second
    4141 *      element in the handle array.
    4242 */
    4343
     44#if B_STATS
     45int HALLOC(B_ARGS_DEC, void ***map)
     46#else
    4447int hAlloc(void ***map)
     48#endif
    4549{
    4650        int             *mp;
     
    5256                incr = H_INCR;
    5357                memsize = (incr + H_OFFSET) * sizeof(void**);
     58#if B_STATS
     59                if ((mp = (int*) balloc(B_ARGS, memsize)) == NULL) {
     60#else
    5461                if ((mp = (int*) balloc(B_L, memsize)) == NULL) {
     62#endif
    5563                        return -1;
    5664                }
     
    6977 */
    7078        if (mp[H_USED] < mp[H_LEN]) {
    71                 for (handle = 0; handle < len; handle++)
     79                for (handle = 0; handle < len; handle++) {
    7280                        if (mp[handle+H_OFFSET] == 0) {
    7381                                mp[H_USED]++;
    7482                                return handle;
    7583                        }
     84                }
    7685        } else {
    7786                handle = len;
     
    140149 */
    141150
     151#if B_STATS
     152int HALLOCENTRY(B_ARGS_DEC, void ***list, int *max, int size)
     153#else
    142154int hAllocEntry(void ***list, int *max, int size)
     155#endif
    143156{
    144157        char_t  *cp;
     
    148161        a_assert(max);
    149162
     163#if B_STATS
     164        if ((id = HALLOC(B_ARGS, (void***) list)) < 0) {
     165#else
    150166        if ((id = hAlloc((void***) list)) < 0) {
     167#endif
    151168                return -1;
    152169        }
    153        
     170
    154171        if (size > 0) {
     172#if B_STATS
     173                if ((cp = balloc(B_ARGS, size)) == NULL) {
     174#else
    155175                if ((cp = balloc(B_L, size)) == NULL) {
     176#endif
    156177                        hFree(list, id);
    157178                        return -1;
     
    170191
    171192/******************************************************************************/
     193
  • c/src/libnetworking/rtems_webserver/handler.c

    r757e1661 ra6b4c0df  
    22 * handler.c -- URL handler support
    33 *
    4  * Copyright (c) Go Ahead Software Inc., 1995-1999. All Rights Reserved.
     4 * Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved.
    55 *
    66 * See the file "license.txt" for usage and redistribution license requirements
     
    2020/*********************************** Locals ***********************************/
    2121
    22 static websUrlHandlerType*      websUrlHandler;                         /* URL handler list */
     22static websUrlHandlerType       *websUrlHandler;                        /* URL handler list */
    2323static int                                      websUrlHandlerMax;                      /* Number of entries */
     24static int                                      urlHandlerOpenCount = 0;        /* count of apps */
    2425
    2526/**************************** Forward Declarations ****************************/
    2627
    27 static int      websUrlHandlerSort(const void* p1, const void* p2);
     28static int      websUrlHandlerSort(const void *p1, const void *p2);
    2829static int      websPublishHandler(webs_t wp, char_t *urlPrefix, char_t *webDir,
    2930                                int sid, char_t *url, char_t *path, char_t *query);
     31static int      websTidyUrl(webs_t wp);
    3032
    3133/*********************************** Code *************************************/
     
    3638int websUrlHandlerOpen()
    3739{
    38         websAspOpen();
     40        if (++urlHandlerOpenCount == 1) {
     41                websAspOpen();
     42                websUrlHandler = NULL;
     43                websUrlHandlerMax = 0;
     44        }
    3945        return 0;
    4046}
     
    4753void websUrlHandlerClose()
    4854{
    49         websUrlHandlerType*     sp;
    50 
    51         websAspClose();
    52         for (sp = websUrlHandler; sp < &websUrlHandler[websUrlHandlerMax]; sp++) {
    53                 bfree(B_L, sp->urlPrefix);
    54                 if (sp->webDir) {
    55                         bfree(B_L, sp->webDir);
    56                 }
    57         }
    58         bfree(B_L, websUrlHandler);
    59         websUrlHandlerMax = 0;
     55        websUrlHandlerType *sp;
     56
     57        if (--urlHandlerOpenCount <= 0) {
     58                websAspClose();
     59                for (sp = websUrlHandler; sp < &websUrlHandler[websUrlHandlerMax];
     60                        sp++) {
     61                        bfree(B_L, sp->urlPrefix);
     62                        if (sp->webDir) {
     63                                bfree(B_L, sp->webDir);
     64                        }
     65                }
     66                bfree(B_L, websUrlHandler);
     67                websUrlHandlerMax = 0;
     68        }
    6069}
    6170
     
    136145 */
    137146
    138 static int websUrlHandlerSort(const void* p1, const void* p2)
     147static int websUrlHandlerSort(const void *p1, const void *p2)
    139148{
    140149        websUrlHandlerType      *s1, *s2;
     
    247256       
    248257        websSetRequestPath(wp, websGetDefaultDir(), NULL);
     258
     259        websTidyUrl(wp);
    249260
    250261/*
     
    265276                        }
    266277                        if (!websValid(wp)) {
    267                                 goahead_trace(0,
     278                                trace(0,
    268279                                T("webs: handler %s called websDone, but didn't return 1\n"),
    269280                                        sp->urlPrefix);
     
    273284        }
    274285/*
    275  *      If no handler processed the request, then return an error. Note: It was
     286 *      If no handler processed the request, then return an error. Note: It is
    276287 *      the handlers responsibility to call websDone
    277288 */
     
    282293}
    283294
    284 /******************************************************************************/
     295
     296/******************************************************************************/
     297/*
     298 *      Tidy up the URL path. Return -1 if the URL is bad.
     299 *  Used to eliminate repeated directory delimiters ('/').
     300 */
     301
     302static int websTidyUrl(webs_t wp)
     303{
     304        char_t  *parts[64];                                     /* Array of ptr's to URL parts */
     305        char_t  *token, *url, *tidyurl;
     306        int             i, len, npart;
     307
     308        a_assert(websValid(wp));
     309
     310/*
     311 *      Copy the string so we don't destroy the original (yet)
     312 */
     313        url = bstrdup(B_L, wp->url);
     314        websDecodeUrl(url, url, gstrlen(url));
     315
     316        len = npart = 0;
     317        parts[0] = NULL;
     318        token = gstrtok(url, T("/"));
     319
     320/*
     321 *      Look at each directory segment and process "." and ".." segments
     322 *      Don't allow the browser to pop outside the root web.
     323 */
     324        while (token != NULL) {
     325                if (gstrcmp(token, T("..")) == 0) {
     326                        if (npart > 0) {
     327                                npart--;
     328                        }
     329
     330                } else if (gstrcmp(token, T(".")) != 0) {
     331                        parts[npart] = token;
     332                        len += gstrlen(token) + 1;
     333                        npart++;
     334                }
     335                token = gstrtok(NULL, T("/"));
     336        }
     337
     338/*
     339 *      Re-construct URL. Need extra space all "/" and null.
     340 */
     341        if (npart || (gstrcmp(url, T("/")) == 0) || (url[0] == '\0')) {
     342                tidyurl = balloc(B_L, (len + 2) * sizeof(char_t));
     343                *tidyurl = '\0';
     344
     345                for (i = 0; i < npart; i++) {
     346                        gstrcat(tidyurl, T("/"));
     347                        gstrcat(tidyurl, parts[i]);
     348                }
     349
     350                bfree(B_L, url);
     351
     352                bfree(B_L, wp->url);
     353                wp->url = tidyurl;
     354                return 0;
     355        } else {
     356                bfree(B_L, url);
     357                return -1;
     358        }
     359}
     360
     361/******************************************************************************/
  • c/src/libnetworking/rtems_webserver/mime.c

    r757e1661 ra6b4c0df  
    22 * mime.c -- Web server mime types
    33 *
    4  * Copyright (c) Go Ahead Software Inc., 1995-1999. All Rights Reserved.
     4 * Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved.
    55 *
    66 * See the file "license.txt" for usage and redistribution license requirements
  • c/src/libnetworking/rtems_webserver/misc.c

    r757e1661 ra6b4c0df  
    22 * misc.c -- Miscellaneous routines.
    33 *
    4  * Copyright (c) GoAhead Software Inc., 1995-1999. All Rights Reserved.
     4 * Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved.
    55 *
    66 * See the file "license.txt" for usage and redistribution license requirements
     
    1717/********************************* Defines ************************************/
    1818/*
    19  *      Sprintf buffer structure. Make the increment 8 less than 64 so that
     19 *      Sprintf buffer structure. Make the increment 64 so that
    2020 *      a balloc can use a 64 byte block.
    2121 */
    2222
    2323#define STR_REALLOC             0x1                             /* Reallocate the buffer as required */
    24 #define STR_INC                 58                              /* Growth increment */
     24#define STR_INC                 64                              /* Growth increment */
    2525
    2626typedef struct {
     
    6060/*
    6161 *      "basename" returns a pointer to the last component of a pathname
    62  *  LINUX, RTEMS, and LynxOS have their own basename function
    63  */
    64 
    65 #if ! LINUX & ! __rtems__ & ! LYNX
    66 char_t *basename(char_t* name)
     62 *  LINUX and LynxOS have their own basename function
     63 */
     64
     65#if ! LINUX && ! LYNX && ! __rtems__
     66char_t *basename(char_t *name)
    6767{
    6868        char_t  *cp;
     
    8484        }
    8585}
    86 #endif /* ! LINUX && ! __rtems__ && ! LYNX */
     86#endif /* ! LINUX & ! LYNX */
    8787
    8888/******************************************************************************/
     
    9292 */
    9393
    94 char_t *dirname(char_t* buf, char_t* name, int bufsize)
    95 {
    96         char_t* cp;
     94char_t *dirname(char_t *buf, char_t *name, int bufsize)
     95{
     96        char_t *cp;
    9797        int             len;
    9898
     
    131131}
    132132
     133
    133134/******************************************************************************/
    134135/*
    135136 *      sprintf and vsprintf are bad, ok. You can easily clobber memory. Use
    136  *      gsnprintf and gvsnprintf instead! These functions do _not_ support floating
     137 *      fmtAlloc and fmtValloc instead! These functions do _not_ support floating
    137138 *      point, like %e, %f, %g...
    138139 */
    139140
    140 int gsnprintf(char_t **s, int n, char_t *fmt, ...)
     141int fmtAlloc(char_t **s, int n, char_t *fmt, ...)
    141142{
    142143        va_list ap;
     
    148149        *s = NULL;
    149150        va_start(ap, fmt);
    150         result = gvsnprintf(s, n, fmt, ap);
     151        result = dsnprintf(s, n, fmt, ap, 0);
    151152        va_end(ap);
    152153        return result;
     
    155156/******************************************************************************/
    156157/*
     158 *      Support a static buffer version for small buffers only!
     159 */
     160
     161int fmtStatic(char_t *s, int n, char_t *fmt, ...)
     162{
     163        va_list ap;
     164        int             result;
     165
     166        a_assert(s);
     167        a_assert(fmt);
     168        a_assert(n <= 256);
     169
     170        if (n <= 0) {
     171                return -1;
     172        }
     173        va_start(ap, fmt);
     174        result = dsnprintf(&s, n, fmt, ap, 0);
     175        va_end(ap);
     176        return result;
     177}
     178
     179/******************************************************************************/
     180/*
    157181 *      This function appends the formatted string to the supplied string,
    158182 *      reallocing if required.
    159183 */
    160184
    161 int gsprintfRealloc(char_t **s, int n, int msize, char_t *fmt, ...)
     185int fmtRealloc(char_t **s, int n, int msize, char_t *fmt, ...)
    162186{
    163187        va_list ap;
     
    181205 */
    182206
    183 int gvsnprintf(char_t **s, int n, char_t *fmt, va_list arg)
     207int fmtValloc(char_t **s, int n, char_t *fmt, va_list arg)
    184208{
    185209        a_assert(s);
    186210        a_assert(fmt);
    187211
     212        *s = NULL;
    188213        return dsnprintf(s, n, fmt, arg, 0);
    189214}
     
    191216/******************************************************************************/
    192217/*
    193  *      Dynamic sprintf implementation. Supports dynamic buffer allocation also.
     218 *      Dynamic sprintf implementation. Supports dynamic buffer allocation.
    194219 *      This function can be called multiple times to grow an existing allocated
    195220 *      buffer. In this case, msize is set to the size of the previously allocated
     
    253278                                c = *fmt++;
    254279                        } else {
    255                                 for ( ; gisdigit(c); c = *fmt++) {
     280                                for ( ; gisdigit((int)c); c = *fmt++) {
    256281                                        width = width * 10 + (c - '0');
    257282                                }
     
    264289                                        c = *fmt++;
    265290                                } else {
    266                                         for (prec = 0; gisdigit(c); c = *fmt++) {
     291                                        for (prec = 0; gisdigit((int)c); c = *fmt++) {
    267292                                                prec = prec * 10 + (c - '0');
    268293                                        }
     
    403428static void put_char(strbuf_t *buf, char_t c)
    404429{
    405         if (buf->count >= buf->size) {
     430        if (buf->count >= (buf->size - 1)) {
    406431                if (! (buf->flags & STR_REALLOC)) {
    407432                        return;
     
    409434                buf->size += STR_INC;
    410435                if (buf->size > buf->max && buf->size > STR_INC) {
    411                         a_assert(buf->size <= buf->max);
     436/*
     437 *                      Caller should increase the size of the calling buffer
     438 */
    412439                        buf->size -= STR_INC;
    413440                        return;
    414441                }
    415442                if (buf->s == NULL) {
    416                         buf->s = balloc(B_L, buf->size * sizeof(char_t*));
     443                        buf->s = balloc(B_L, buf->size * sizeof(char_t));
    417444                } else {
    418                         buf->s = brealloc(B_L, buf->s, buf->size * sizeof(char_t*));
     445                        buf->s = brealloc(B_L, buf->s, buf->size * sizeof(char_t));
    419446                }
    420447        }
    421448        buf->s[buf->count] = c;
    422         ++buf->count;
     449        if (c != '\0') {
     450                ++buf->count;
     451        }
    423452}
    424453
     
    429458
    430459static void put_string(strbuf_t *buf, char_t *s, int len, int width,
    431         int prec, enum flag f)
     460                int prec, enum flag f)
    432461{
    433462        int             i;
     
    459488
    460489static void put_ulong(strbuf_t *buf, unsigned long int value, int base,
    461         int upper, char_t *prefix, int width, int prec, enum flag f)
     490                int upper, char_t *prefix, int width, int prec, enum flag f)
    462491{
    463492        unsigned long   x, x2;
     
    476505        }
    477506        if (!(f & flag_minus)) {
    478                 for (i = 0; i < width; ++i) {
    479                         put_char(buf, ' ');
     507                if (f & flag_zero) {
     508                        for (i = 0; i < width; ++i) {
     509                                put_char(buf, '0');
     510                        }
     511                } else {
     512                        for (i = 0; i < width; ++i) {
     513                                put_char(buf, ' ');
     514                        }
    480515                }
    481516        }
     
    525560 */
    526561
    527 char *uniToAsc(char *buf, char_t* ustr, int nBytes)
     562char *uniToAsc(char *buf, char_t *ustr, int nBytes)
    528563{
    529564#if UNICODE
     
    538573}
    539574
    540 
    541575/******************************************************************************/
    542576/*
    543577 *      allocate (balloc) a buffer and do ascii to unicode conversion into it.
    544  *      cp points to the ascii string which must be NULL terminated.
    545  *      Return a pointer to the unicode buffer which must be bfree'd later.
    546  *      Return NULL on failure to get buffer.
    547  */
    548 char_t *ballocAscToUni(char * cp)
    549 {
    550         char_t * unip;
     578 *      cp points to the ascii buffer.  alen is the length of the buffer to be
     579 *      converted not including a terminating NULL.  Return a pointer to the
     580 *      unicode buffer which must be bfree'd later.  Return NULL on failure to
     581 *      get buffer.  The buffer returned is NULL terminated.
     582 */
     583
     584char_t *ballocAscToUni(char *cp, int alen)
     585{
     586        char_t *unip;
    551587        int ulen;
    552588
    553         ulen = (strlen(cp) + 1) * sizeof(char_t);
     589        ulen = (alen + 1) * sizeof(char_t);
    554590        if ((unip = balloc(B_L, ulen)) == NULL) {
    555591                return NULL;
    556592        }
    557593        ascToUni(unip, cp, ulen);
     594        unip[alen] = 0;
    558595        return unip;
    559596}
     
    563600 *      allocate (balloc) a buffer and do unicode to ascii conversion into it.
    564601 *      unip points to the unicoded string. ulen is the number of characters
    565  *      in the unicode string including teminating null, if there is one.
    566  *      Return a pointer to the ascii buffer which must be bfree'd later.
    567  *      Return NULL on failure to get buffer.
    568  */
    569 char *ballocUniToAsc(char_t * unip, int ulen)
     602 *      in the unicode string not including a teminating null.  Return a pointer
     603 *      to the ascii buffer which must be bfree'd later.  Return NULL on failure
     604 *      to get buffer.  The buffer returned is NULL terminated.
     605 */
     606
     607char *ballocUniToAsc(char_t *unip, int ulen)
    570608{
    571609        char * cp;
    572610
    573         if ((cp = balloc(B_L, ulen)) == NULL) {
     611        if ((cp = balloc(B_L, ulen+1)) == NULL) {
    574612                return NULL;
    575613        }
    576614        uniToAsc(cp, unip, ulen);
     615        cp[ulen] = '\0';
    577616        return cp;
    578617}
    579618
    580619/******************************************************************************/
    581 
     620/*
     621 *      convert a hex string to an integer. The end of the string or a non-hex
     622 *      character will indicate the end of the hex specification.
     623 */
     624
     625unsigned int hextoi(char_t *hexstring)
     626{
     627        register char_t                 *h;
     628        register unsigned int   c, v;
     629
     630        v = 0;
     631        h = hexstring;
     632        if (*h == '0' && (*(h+1) == 'x' || *(h+1) == 'X')) {
     633                h += 2;
     634        }
     635        while ((c = (unsigned int)*h++) != 0) {
     636                if (c >= '0' && c <= '9') {
     637                        c -= '0';
     638                } else if (c >= 'a' && c <= 'f') {
     639                        c = (c - 'a') + 10;
     640                } else if (c >=  'A' && c <= 'F') {
     641                        c = (c - 'A') + 10;
     642                } else {
     643                        break;
     644                }
     645                v = (v * 0x10) + c;
     646        }
     647        return v;
     648}
     649
     650/******************************************************************************/
     651/*
     652 *      convert a string to an integer. If the string starts with "0x" or "0X"
     653 *      a hexidecimal conversion is done.
     654 */
     655
     656unsigned int gstrtoi(char_t *s)
     657{
     658        if (*s == '0' && (*(s+1) == 'x' || *(s+1) == 'X')) {
     659                s += 2;
     660                return hextoi(s);
     661        }
     662        return gatoi(s);
     663}
     664
     665/******************************************************************************/
     666
  • c/src/libnetworking/rtems_webserver/ringq.c

    r757e1661 ra6b4c0df  
    22 * ringq.c -- Ring queue buffering module
    33 *
    4  * Copyright (c) GoAhead Software Inc., 1995-1999. All Rights Reserved.
     4 * Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved.
    55 *
    66 * See the file "license.txt" for usage and redistribution license requirements
     
    1111/*
    1212 *      A ring queue allows maximum utilization of memory for data storage and is
    13  *      ideal for input/output buffering.  This module provides a highly effecient
     13 *      ideal for input/output buffering.  This module provides a highly efficient
    1414 *      implementation and a vehicle for dynamic strings.
    1515 *
     
    3737 *     
    3838 *      The queue is empty when servp == endp.  This means that the queue will hold
    39  *      at most rq->buflen -1 bytes.  It is the fillers responsibility to ensure
     39 *      at most rq->buflen -1 bytes.  It is the filler's responsibility to ensure
    4040 *      the ringq is never filled such that servp == endp.
    4141 *
    42  *      It is the fillers responsibility to "wrap" the endp back to point to
     42 *      It is the filler's responsibility to "wrap" the endp back to point to
    4343 *      rq->buf when the pointer steps past the end.  Correspondingly it is the
    4444 *      consumers responsibility to "wrap" the servp when it steps to rq->endbuf.
     
    6666/***************************** Forward Declarations ***************************/
    6767
    68 static int ringq_grow(ringq_t *rq);
     68static int      ringqGrow(ringq_t *rq);
     69static int      getBinBlockSize(int size);
     70
     71int                     ringqGrowCalls = 0;
    6972
    7073/*********************************** Code *************************************/
     
    7780 */
    7881
    79 int ringqOpen(ringq_t *rq, int increment, int maxsize)
    80 {
    81         a_assert(rq);
    82         a_assert(increment >= 0);
    83 
    84         if ((rq->buf = balloc(B_L, increment)) == NULL) {
     82int ringqOpen(ringq_t *rq, int initSize, int maxsize)
     83{
     84        int     increment;
     85
     86        a_assert(rq);
     87        a_assert(initSize >= 0);
     88
     89        increment = getBinBlockSize(initSize);
     90        if ((rq->buf = balloc(B_L, (increment))) == NULL) {
    8591                return -1;
    8692        }
     
    116122/******************************************************************************/
    117123/*
    118  *      Return the length of the ringq. Users must fill the queue to a high
    119  *      water mark of at most one less than the queue size.
     124 *      Return the length of the data in the ringq. Users must fill the queue to
     125 *      a high water mark of at most one less than the queue size.
    120126 */
    121127
     
    127133        if (rq->servp > rq->endp) {
    128134                return rq->buflen + rq->endp - rq->servp;
    129         }
    130         else {
     135        } else {
    131136                return rq->endp - rq->servp;
    132137        }
     
    167172int ringqPutc(ringq_t *rq, char_t c)
    168173{
    169         char_t* cp;
    170 
    171         a_assert(rq);
    172         a_assert(rq->buflen == (rq->endbuf - rq->buf));
    173 
    174         if (ringqPutBlkMax(rq) < (int) sizeof(char_t) && !ringq_grow(rq)) {
     174        char_t *cp;
     175
     176        a_assert(rq);
     177        a_assert(rq->buflen == (rq->endbuf - rq->buf));
     178
     179        if ((ringqPutBlkMax(rq) < (int) sizeof(char_t)) && !ringqGrow(rq)) {
    175180                return -1;
    176181        }
     
    192197int ringqInsertc(ringq_t *rq, char_t c)
    193198{
    194         char_t* cp;
    195 
    196         a_assert(rq);
    197         a_assert(rq->buflen == (rq->endbuf - rq->buf));
    198 
    199         if (ringqPutBlkMax(rq) < (int) sizeof(char_t) && !ringq_grow(rq)) {
     199        char_t *cp;
     200
     201        a_assert(rq);
     202        a_assert(rq->buflen == (rq->endbuf - rq->buf));
     203
     204        if (ringqPutBlkMax(rq) < (int) sizeof(char_t) && !ringqGrow(rq)) {
    200205                return -1;
    201206        }
     
    211216/******************************************************************************/
    212217/*
    213  *      Add a string to the queue. Add a trailing wide null (two nulls)
    214  */
    215 
    216 int ringqPutstr(ringq_t *rq, char_t *str)
     218 *      Add a string to the queue. Add a trailing null (maybe two nulls)
     219 */
     220
     221int ringqPutStr(ringq_t *rq, char_t *str)
    217222{
    218223        int             rc;
     
    228233
    229234/******************************************************************************/
     235/*
     236 *      Add a null terminator. This does NOT increase the size of the queue
     237 */
     238
     239void ringqAddNull(ringq_t *rq)
     240{
     241        a_assert(rq);
     242        a_assert(rq->buflen == (rq->endbuf - rq->buf));
     243
     244        *((char_t*) rq->endp) = (char_t) '\0';
     245}
     246
     247/******************************************************************************/
    230248#if UNICODE
    231249/*
     
    262280        a_assert(rq->buflen == (rq->endbuf - rq->buf));
    263281
    264         if (ringqPutBlkMax(rq) == 0 && !ringq_grow(rq)) {
     282        if (ringqPutBlkMax(rq) == 0 && !ringqGrow(rq)) {
    265283                return -1;
    266284        }
     
    283301        a_assert(rq->buflen == (rq->endbuf - rq->buf));
    284302
    285         if (ringqPutBlkMax(rq) == 0 && !ringq_grow(rq)) {
     303        if (ringqPutBlkMax(rq) == 0 && !ringqGrow(rq)) {
    286304                return -1;
    287305        }
     
    299317 */
    300318
    301 int ringqPutstrA(ringq_t *rq, char *str)
     319int ringqPutStrA(ringq_t *rq, char *str)
    302320{
    303321        int             rc;
     
    335353                this = min(ringqPutBlkMax(rq), size);
    336354                if (this <= 0) {
    337                         if (! ringq_grow(rq)) {
     355                        if (! ringqGrow(rq)) {
    338356                                break;
    339357                        }
     
    486504{
    487505        a_assert(rq);
     506        a_assert(rq->servp);
    488507
    489508        rq->servp = rq->buf;
    490509        rq->endp = rq->buf;
    491         *rq->servp = '\0';
     510        if (rq->servp) {
     511                *rq->servp = '\0';
     512        }
    492513}
    493514
     
    499520 */
    500521
    501 static int ringq_grow(ringq_t *rq)
     522static int ringqGrow(ringq_t *rq)
    502523{
    503524        unsigned char   *newbuf;
     
    532553
    533554        ringqPutBlk(rq, newbuf, len);
     555
     556/*
     557 *      Double the increment so the next grow will line up with balloc'ed memory
     558 */
     559        rq->increment = getBinBlockSize(2 * rq->increment);
     560
    534561        return 1;
    535562}
    536563
    537564/******************************************************************************/
     565/*
     566 *      Find the smallest binary memory size that "size" will fit into.  This
     567 *      makes the ringq and ringqGrow routines much more efficient.  The balloc
     568 *      routine likes powers of 2 minus 1.
     569 */
     570
     571static int      getBinBlockSize(int size)
     572{
     573        int     q;
     574
     575        size = size >> B_SHIFT;
     576        for (q = 0; size; size >>= 1) {
     577                q++;
     578        }
     579        return (1 << (B_SHIFT + q));
     580}
     581
     582/******************************************************************************/
  • c/src/libnetworking/rtems_webserver/rom.c

    r757e1661 ra6b4c0df  
    22 * rom.c -- Support for ROMed page retrieval.
    33 *
    4  * Copyright (c) Go Ahead Software Inc., 1995-1999. All Rights Reserved.
     4 * Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved.
    55 *
    66 * See the file "license.txt" for usage and redistribution license requirements
     
    2020
    2121#include        <stdlib.h>
    22 
    23 #if CE
    24 #define         EINVAL  22
    25 #define         EBADF   9
    26 #else
    27 #include        <errno.h>
    28 #endif
    2922
    3023#include        "wsIntrn.h"
     
    4740        char_t                                  name[SYM_MAX];
    4841
    49         romTab = symOpen(64);
     42        romTab = symOpen(WEBS_SYM_INIT);
    5043
    5144        for (wip = websRomPageIndex; wip->path; wip++) {
     
    6861void websRomClose()
    6962{
    70         symClose(romTab, NULL);
     63        symClose(romTab);
    7164}
    7265
     
    10699 */
    107100
    108 int websRomPageStat(char_t *path, websStatType* sbuf)
     101int websRomPageStat(char_t *path, websStatType *sbuf)
    109102{
    110103        websRomPageIndexType    *wip;
     
    194187}
    195188
    196 #endif
     189#endif /* WEBS_PAGE_ROM */
    197190
    198191/******************************************************************************/
  • c/src/libnetworking/rtems_webserver/security.c

    r757e1661 ra6b4c0df  
    22 * security.c -- Security handler
    33 *
    4  * Copyright (c) Go Ahead Software Inc., 1995-1999. All Rights Reserved.
     4 * Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved.
    55 *
    66 * See the file "license.txt" for usage and redistribution license requirements
     
    1010
    1111/*
    12  *      This module provides a basic security policy. It supports a single global
    13  *      password and ignores the username. Encoding/decoding of the password is
    14  *      -not- done.
     12 *      This module provides a basic security policy.
    1513 */
    1614
     
    1816
    1917#include        "wsIntrn.h"
     18#include        "um.h"
     19#ifdef DIGEST_ACCESS_SUPPORT
     20#include        "websda.h"
     21#endif
     22
     23/********************************** Defines ***********************************/
     24/*
     25 *      The following #defines change the behaviour of security in the absence
     26 *      of User Management.
     27 *      Note that use of User management functions require prior calling of
     28 *      umInit() to behave correctly
     29 */
     30
     31#ifndef USER_MANAGEMENT_SUPPORT
     32#define umGetAccessMethodForURL(url) AM_FULL
     33#define umUserExists(userid) 0
     34#define umUserCanAccessURL(userid, url) 1
     35#define umGetUserPassword(userid) websGetPassword()
     36#define umGetAccessLimitSecure(accessLimit) 0
     37#define umGetAccessLimit(url) NULL
     38#endif
    2039
    2140/******************************** Local Data **********************************/
    2241
    2342static char_t   websPassword[WEBS_MAX_PASS];    /* Access password (decoded) */
     43#ifdef _DEBUG
     44static int              debugSecurity = 1;
     45#else
     46static int              debugSecurity = 0;
     47#endif
    2448
    2549/*********************************** Code *************************************/
     
    3155                                                char_t *url, char_t *path, char_t *query)
    3256{
    33         char_t  *type, *password;
    34         int             flags;
     57        char_t                  *type, *userid, *password, *accessLimit;
     58        int                             flags, nRet;
     59        accessMeth_t    am;
    3560
    3661        a_assert(websValid(wp));
    3762        a_assert(url && *url);
    3863        a_assert(path && *path);
    39 
    4064/*
    4165 *      Get the critical request details
     
    4367        type = websGetRequestType(wp);
    4468        password = websGetRequestPassword(wp);
     69        userid = websGetRequestUserName(wp);
    4570        flags = websGetRequestFlags(wp);
    46 
    47 /*
    48  *      Validate the users password if required (local access is always allowed)
    49  *      We compare the decoded form of the password.
    50  */
    51         if (*websPassword && !(flags & WEBS_LOCAL_REQUEST)) {
    52 
    53                 if (password && *password) {
    54                         if (gstrcmp(password, websPassword) != 0) {
     71/*
     72 *      Get the access limit for the URL.  Exit if none found.
     73 */
     74        accessLimit = umGetAccessLimit(path);
     75        if (accessLimit == NULL) {
     76                return 0;
     77        }
     78                 
     79/*
     80 *      Check to see if URL must be encrypted
     81 */
     82#ifdef WEBS_SSL_SUPPORT
     83        nRet = umGetAccessLimitSecure(accessLimit);
     84        if (nRet && ((flags | WEBS_SECURE) == 0)) {
     85                websStats.access++;
     86                websError(wp, 200, T("Access Denied\nSecure access is required."));
     87                trace(3, T("SEC: Non-secure access attempted on <%s>\n"), path);
     88                return 1;
     89        }
     90#endif
     91
     92/*
     93 *      Get the access limit for the URL
     94 */
     95        am = umGetAccessMethodForURL(accessLimit);
     96
     97        nRet = 0;
     98        if ((flags & WEBS_LOCAL_REQUEST) && (debugSecurity == 0)) {
     99/*
     100 *              Local access is always allowed (defeat when debugging)
     101 */
     102        } else if (am == AM_NONE) {
     103/*
     104 *              URL is supposed to be hidden!  Make like it wasn't found.
     105 */
     106                websStats.access++;
     107                websError(wp, 400, T("Page Not Found"));
     108                nRet = 1;
     109        } else  if (userid && *userid) {
     110                if (!umUserExists(userid)) {
     111                        websStats.access++;
     112                        websError(wp, 200, T("Access Denied\nUnknown User"));
     113                        trace(3, T("SEC: Unknown user <%s> attempted to access <%s>\n"),
     114                                userid, path);
     115                        nRet = 1;
     116                } else if (!umUserCanAccessURL(userid, accessLimit)) {
     117                        websStats.access++;
     118                        websError(wp, 403, T("Access Denied\nProhibited User"));
     119                        nRet = 1;
     120                } else if (password && * password) {
     121                        char_t * userpass = umGetUserPassword(userid);
     122                        if (userpass) {
     123                                if (gstrcmp(password, userpass) != 0) {
     124                                        websStats.access++;
     125                                        websError(wp, 200, T("Access Denied\nWrong Password"));
     126                                        trace(3, T("SEC: Password fail for user <%s>")
     127                                                                T("attempt to access <%s>\n"), userid, path);
     128                                        nRet = 1;
     129                                } else {
     130/*
     131 *                                      User and password check out.
     132 */
     133                                }
     134
     135                                bfree (B_L, userpass);
     136                        }
     137#ifdef DIGEST_ACCESS_SUPPORT
     138                } else if (flags & WEBS_AUTH_DIGEST) {
     139
     140                        char_t *digestCalc;
     141
     142/*
     143 *                      Check digest for equivalence
     144 */
     145                        wp->password = umGetUserPassword(userid);
     146
     147                        a_assert(wp->digest);
     148                        a_assert(wp->nonce);
     149                        a_assert(wp->password);
     150                                                         
     151                        digestCalc = websCalcDigest(wp);
     152                        a_assert(digestCalc);
     153
     154                        if (gstrcmp(wp->digest, digestCalc) != 0) {
    55155                                websStats.access++;
    56156                                websError(wp, 200, T("Access Denied\nWrong Password"));
    57                                 websSetPassword(T(""));
    58                                 return 1;
     157                                nRet = 1;
    59158                        }
     159
     160                        bfree (B_L, digestCalc);
     161#endif
    60162                } else {
    61163/*
    62  *                      This will cause the browser to display a password / username
    63  *                      dialog
    64  */
     164 *                      No password has been specified
     165 */
     166#ifdef DIGEST_ACCESS_SUPPORT
     167                        if (am == AM_DIGEST) {
     168                                wp->flags |= WEBS_AUTH_DIGEST;
     169                        }
     170#endif
    65171                        websStats.errors++;
    66                         websError(wp, 401, T("<html><head>Access Denied</head><body>\r\n\
    67                                 Access to this document requires a password.</body>\
    68                                 </html>\r\n"));
    69                         return 1;
     172                        websError(wp, 401,
     173                                T("Access to this document requires a password"));
     174                        nRet = 1;
    70175                }
     176        } else if (am != AM_FULL) {
     177/*
     178 *              This will cause the browser to display a password / username
     179 *              dialog
     180 */
     181#ifdef DIGEST_ACCESS_SUPPORT
     182                if (am == AM_DIGEST) {
     183                        wp->flags |= WEBS_AUTH_DIGEST;
     184                }
     185#endif
     186                websStats.errors++;
     187                websError(wp, 401, T("Access to this document requires a User ID"));
     188                nRet = 1;
    71189        }
    72         return 0;
     190
     191        bfree(B_L, accessLimit);
     192
     193        return nRet;
    73194}
    74195
     
    103224char_t *websGetPassword()
    104225{
    105         return websPassword;
    106 }
    107 
    108 /******************************************************************************/
    109 
     226        return bstrdup(B_L, websPassword);
     227}
     228
     229/******************************************************************************/
     230
  • c/src/libnetworking/rtems_webserver/socket.c

    r757e1661 ra6b4c0df  
    1 /*
    2  * socket.c -- Socket support module for UNIX
     1
     2/*
     3 *      sockGen.c -- Posix Socket support module for general posix use
    34 *
    4  * Copyright (c) Go Ahead, 1995-1999
     5 * Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved.
    56 */
    67
     
    89
    910/*
    10  *      SCO Unix Socket Module.  This supports non-blocking buffered socket I/O.
    11  */
     11 *      Posix Socket Module.  This supports blocking and non-blocking buffered
     12 *      socket I/O.
     13 */
     14
     15#if (!WIN) || LITTLEFOOT || WEBS
    1216
    1317/********************************** Includes **********************************/
    1418
    15 #include        <errno.h>
    16 #include        <fcntl.h>
    1719#include        <string.h>
    1820#include        <stdlib.h>
    19 #include        <unistd.h>
     21
     22#if UEMF
     23        #include        "uemf.h"
     24#else
     25        #include        <socket.h>
     26        #include        <types.h>
     27        #include        <unistd.h>
     28        #include        "emfInternal.h"
     29#endif
     30
     31#if VXWORKS
     32        #include        <hostLib.h>
     33#endif
    2034
    2135#if __rtems__
    22 #include        <sys/select.h>
    23 #endif
    24 
    25 #include        "uemf.h"
    26 
    27 /*********************************** Defines **********************************/
    28 
    29 typedef struct {
    30         char                    host[64];                               /* Host name */
    31         ringq_t                 inBuf;                                  /* Input ring queue */
    32         ringq_t                 outBuf;                                 /* Output ring queue */
    33         ringq_t                 lineBuf;                                /* Line ring queue */
    34         socketAccept_t  accept;                                 /* Accept handler */
    35         socketHandler_t handler;                                /* User I/O handler */
    36         int                             handler_data;                   /* User handler data */
    37         int                             sid;                                    /* Index into socket[] */
    38         int                             port;                                   /* Port to listen on */
    39         int                             flags;                                  /* Current state flags */
    40         int                             readyMask;                              /* Events now ready */
    41         int                             interestMask;                   /* Events interest */
    42         int                             error;                                  /* Last error */
    43         int                             sock;                                   /* Actual socket handle */
    44 } socket_t;
     36        #include        <sys/select.h>
     37#endif
    4538
    4639/************************************ Locals **********************************/
    4740
    48 static socket_t**       socketList;                             /* List of open sockets */
    49 static int                      socketMax;                              /* Maximum size of socket */
    50 static int                      socketHighestFd = -1;   /* Highest socket fd opened */
     41extern socket_t         **socketList;                   /* List of open sockets */
     42extern int                      socketMax;                              /* Maximum size of socket */
     43extern int                      socketHighestFd;                /* Highest socket fd opened */
     44static int                      socketOpenCount = 0;    /* Number of task using sockets */
    5145
    5246/***************************** Forward Declarations ***************************/
    5347
    54 static int      socketAlloc(char* host, int port, socketAccept_t accept, int flags);
    55 static void socketFree(int sid);
    56 static void socketAccept(socket_t* sp);
    57 static int      socketGetInput(int sid, char* buf, int toRead, int* errCode);
    58 static int      socketDoOutput(socket_t* sp, char* buf, int toWrite, int* errCode);
     48static void socketAccept(socket_t *sp);
    5949static int      socketDoEvent(socket_t *sp);
    60 static int      socketGetError();
    61 static int      socketWaitForEvent(socket_t* sp, int events, int* errCode);
    62 static int      socketNonBlock(socket_t *sp);
    63 static socket_t* socketPtr(int sid);
     50static int      tryAlternateConnect(int sock, struct sockaddr *sockaddr);
    6451
    6552/*********************************** Code *************************************/
     
    7057int socketOpen()
    7158{
     59#if CE || WIN
     60    WSADATA     wsaData;
     61#endif
     62
     63        if (++socketOpenCount > 1) {
     64                return 0;
     65        }
     66
     67#if CE || WIN
     68        if (WSAStartup(MAKEWORD(1,1), &wsaData) != 0) {
     69                return -1;
     70        }
     71        if (wsaData.wVersion != MAKEWORD(1,1)) {
     72                WSACleanup();
     73                return -1;
     74        }
     75#endif
     76        socketList = NULL;
     77        socketMax = 0;
     78        socketHighestFd = -1;
     79
    7280        return 0;
    7381}
     
    8290        int             i;
    8391
    84         for (i = socketMax; i >= 0; i--) {
    85                 if (socketList && socketList[i]) {
    86                         socketCloseConnection(i);
    87                 }
     92        if (--socketOpenCount <= 0) {
     93                for (i = socketMax; i >= 0; i--) {
     94                        if (socketList && socketList[i]) {
     95                                socketCloseConnection(i);
     96                        }
     97                }
     98                socketOpenCount = 0;
    8899        }
    89100}
     
    94105 */
    95106
    96 int socketOpenConnection(char* host, int port, socketAccept_t accept, int flags)
    97 {
     107int socketOpenConnection(char *host, int port, socketAccept_t accept, int flags)
     108{
     109#if ! (NO_GETHOSTBYNAME || VXWORKS)
     110        struct hostent          *hostent;                                       /* Host database entry */
     111#endif /* ! (NO_GETHOSTBYNAME || VXWORKS) */
    98112        socket_t                        *sp;
    99         struct sockaddr_in      sockaddr;
    100         struct hostent          *hostent;               /* Host database entry */
    101         int                                     sid, rc;
    102 
     113        struct sockaddr_in      sockaddr;
     114        int                                     sid, bcast, dgram, rc;
     115
     116        if (port > SOCKET_PORT_MAX) {
     117                return -1;
     118        }
    103119/*
    104120 *      Allocate a socket structure
     
    122138                sockaddr.sin_addr.s_addr = inet_addr(host);
    123139                if (sockaddr.sin_addr.s_addr == INADDR_NONE) {
     140/*
     141 *                      If the OS does not support gethostbyname functionality, the macro:
     142 *                      NO_GETHOSTBYNAME should be defined to skip the use of gethostbyname.
     143 *                      Unfortunatly there is no easy way to recover, the following code
     144 *                      simply uses the basicGetHost IP for the sockaddr.
     145 */
     146
     147#if NO_GETHOSTBYNAME
     148                        if (strcmp(host, basicGetHost()) == 0) {
     149                                sockaddr.sin_addr.s_addr = inet_addr(basicGetAddress());
     150                        }
     151                        if (sockaddr.sin_addr.s_addr == INADDR_NONE) {
     152                                socketFree(sid);
     153                                return -1;
     154                        }
     155#elif VXWORKS
     156                        sockaddr.sin_addr.s_addr = (unsigned long) hostGetByName(host);
     157                        if (sockaddr.sin_addr.s_addr == NULL) {
     158                                errno = ENXIO;
     159                                socketFree(sid);
     160                                return -1;
     161                        }
     162#else
    124163                        hostent = gethostbyname(host);
    125164                        if (hostent != NULL) {
     
    128167                                        (size_t) hostent->h_length);
    129168                        } else {
    130                                 errno = ENXIO;
    131                                 socketFree(sid);
    132                                 return -1;
    133                         }
    134                 }
    135         }
    136 
    137 /*
    138  *      Create the socket. Set the close on exec flag so children don't
    139  *      inherit the socket.
    140  */
    141         sp->sock = socket(AF_INET, SOCK_STREAM, 0);
     169                                char    *asciiAddress;
     170                                char_t  *address;
     171
     172                                address = basicGetAddress();
     173                                asciiAddress = ballocUniToAsc(address, gstrlen(address));
     174                                sockaddr.sin_addr.s_addr = inet_addr(asciiAddress);
     175                                bfree(B_L, asciiAddress);
     176                                if (sockaddr.sin_addr.s_addr == INADDR_NONE) {
     177                                        errno = ENXIO;
     178                                        socketFree(sid);
     179                                        return -1;
     180                                }
     181                        }
     182#endif /* (NO_GETHOSTBYNAME || VXWORKS) */
     183                }
     184        }
     185
     186        bcast = sp->flags & SOCKET_BROADCAST;
     187        if (bcast) {
     188                sp->flags |= SOCKET_DATAGRAM;
     189        }
     190        dgram = sp->flags & SOCKET_DATAGRAM;
     191
     192/*
     193 *      Create the socket. Support for datagram sockets. Set the close on
     194 *      exec flag so children don't inherit the socket.
     195 */
     196        sp->sock = socket(AF_INET, dgram ? SOCK_DGRAM: SOCK_STREAM, 0);
    142197        if (sp->sock < 0) {
    143198                socketFree(sid);
    144199                return -1;
    145200        }
     201#ifndef __NO_FCNTL
    146202        fcntl(sp->sock, F_SETFD, FD_CLOEXEC);
     203#endif
    147204        socketHighestFd = max(socketHighestFd, sp->sock);
    148205
    149206/*
     207 *      If broadcast, we need to turn on broadcast capability.
     208 */
     209        if (bcast) {
     210                int broadcastFlag = 1;
     211                if (setsockopt(sp->sock, SOL_SOCKET, SO_BROADCAST,
     212                                (char *) &broadcastFlag, sizeof(broadcastFlag)) < 0) {
     213                        socketFree(sid);
     214                        return -1;
     215                }
     216        }
     217
     218/*
    150219 *      Host is set if we are the client
    151220 */
    152221        if (host) {
    153222/*
    154  *              Connect to the remote server
    155  */
    156                 if (connect(sp->sock, (struct sockaddr *) &sockaddr,
     223 *              Connect to the remote server in blocking mode, then go into
     224 *              non-blocking mode if desired.
     225 */
     226                if (!dgram) {
     227                        if (! (sp->flags & SOCKET_BLOCK)) {
     228/*
     229 *                              sockGen.c is only used for Windows products when blocking
     230 *                              connects are expected.  This applies to FieldUpgrader
     231 *                              agents and open source webserver connectws.  Therefore the
     232 *                              asynchronous connect code here is not compiled.
     233 */
     234#if (WIN || CE) && !(LITTLEFOOT || WEBS)
     235                                int flag;
     236
     237                                sp->flags |= SOCKET_ASYNC;
     238/*
     239 *                              Set to non-blocking for an async connect
     240 */
     241                                flag = 1;
     242                                if (ioctlsocket(sp->sock, FIONBIO, &flag) == SOCKET_ERROR) {
     243                                        socketFree(sid);
     244                                        return -1;
     245                                }
     246#else
     247                                socketSetBlock(sid, 1);
     248#endif /* #if (WIN || CE) && !(LITTLEFOOT || WEBS) */
     249
     250                        }
     251                        if ((rc = connect(sp->sock, (struct sockaddr *) &sockaddr,
     252                                sizeof(sockaddr))) < 0 &&
     253                                (rc = tryAlternateConnect(sp->sock,
     254                                (struct sockaddr *) &sockaddr)) < 0) {
     255#if WIN || CE
     256                                if (socketGetError() != EWOULDBLOCK) {
     257                                        socketFree(sid);
     258                                        return -1;
     259                                }
     260#else
     261                                socketFree(sid);
     262                                return -1;
     263
     264#endif /* WIN || CE */
     265
     266                        }
     267                }
     268        } else {
     269/*
     270 *              Bind to the socket endpoint and the call listen() to start listening
     271 */
     272                rc = 1;
     273                setsockopt(sp->sock, SOL_SOCKET, SO_REUSEADDR, (char *)&rc, sizeof(rc));
     274                if (bind(sp->sock, (struct sockaddr *) &sockaddr,
    157275                                sizeof(sockaddr)) < 0) {
    158276                        socketFree(sid);
    159277                        return -1;
    160278                }
    161                 socketNonBlock(sp);
    162 
     279
     280                if (! dgram) {
     281                        if (listen(sp->sock, SOMAXCONN) < 0) {
     282                                socketFree(sid);
     283                                return -1;
     284                        }
     285#if !UEMF
     286                        sp->fileHandle = emfCreateFileHandler(sp->sock, SOCKET_READABLE,
     287                                (emfFileProc *) socketAccept, (void *) sp);
     288#else
     289                        sp->flags |= SOCKET_LISTENING;
     290#endif
     291                }
     292                sp->handlerMask |= SOCKET_READABLE;
     293        }
     294
     295/*
     296 *      Set the blocking mode
     297 */
     298
     299        if (flags & SOCKET_BLOCK) {
     300                socketSetBlock(sid, 1);
    163301        } else {
    164 /*
    165  *              Bind to the socket endpoint with resule and the call listen() 
    166  **             to start listening
    167  */
    168                 rc = 1;
    169                 setsockopt(sp->sock, SOL_SOCKET, SO_REUSEADDR, (char *)&rc, sizeof(rc));
    170                 if (bind(sp->sock, (struct sockaddr *) &sockaddr, sizeof(sockaddr))
    171                                 < 0) {
    172                         socketFree(sid);
    173                         return -1;
    174                 }
    175                 sp->flags |= SOCKET_LISTENING;
    176 
    177                 if (listen(sp->sock, SOMAXCONN) < 0) {
    178                         socketFree(sid);
    179                         return -1;
    180                 }
    181                 sp->interestMask = SOCKET_READABLE;
     302                socketSetBlock(sid, 0);
    182303        }
    183304        return sid;
     
    186307/******************************************************************************/
    187308/*
     309 *      If the connection failed, swap the first two bytes in the
     310 *      sockaddr structure.  This is a kludge due to a change in
     311 *      VxWorks between versions 5.3 and 5.4, but we want the
     312 *      product to run on either.
     313 */
     314
     315static int tryAlternateConnect(int sock, struct sockaddr *sockaddr)
     316{
     317#if VXWORKS
     318        char *ptr;
     319
     320        ptr = (char *)sockaddr;
     321        *ptr = *(ptr+1);
     322        *(ptr+1) = 0;
     323        return connect(sock, sockaddr, sizeof(struct sockaddr));
     324#else
     325        return -1;
     326#endif /* VXWORKS */
     327}
     328
     329/******************************************************************************/
     330/*
    188331 *      Close a socket
    189332 */
     
    191334void socketCloseConnection(int sid)
    192335{
    193         socket_t*       sp;
     336        socket_t        *sp;
    194337
    195338        if ((sp = socketPtr(sid)) == NULL) {
    196339                return;
    197340        }
    198 
    199 /*
    200  *      We always flush all output before closing. Unlink from the emf event
    201  *      mechanism and then free (and close) the connection
    202  */
    203         socketFlush(sid, 1);
    204341        socketFree(sid);
    205342}
     
    207344/******************************************************************************/
    208345/*
    209  *      Accept a connection. Called by socketDoEvent
    210  */
    211 
    212 static void socketAccept(socket_t* sp)
     346 *      Accept a connection. Called as a callback on incoming connection.
     347 */
     348
     349static void socketAccept(socket_t *sp)
    213350{
    214351        struct sockaddr_in      addr;
    215352        socket_t                        *nsp;
    216         int                             len;
     353        size_t                          len;
     354        char                            *pString;
    217355        int                             newSock, nid;
    218356
     
    226364                return;
    227365        }
     366#ifndef __NO_FCNTL
    228367        fcntl(newSock, F_SETFD, FD_CLOEXEC);
     368#endif
    229369        socketHighestFd = max(socketHighestFd, newSock);
    230370
     
    232372 *      Create a socket structure and insert into the socket list
    233373 */
    234         nid = socketAlloc(sp->host, sp->port, sp->accept, 0);
     374        nid = socketAlloc(sp->host, sp->port, sp->accept, sp->flags);
    235375        nsp = socketList[nid];
    236376        a_assert(nsp);
    237377        nsp->sock = newSock;
     378        nsp->flags &= ~SOCKET_LISTENING;
    238379
    239380        if (nsp == NULL) {
     
    241382        }
    242383/*
    243  *      Call the user accept callback, the user must call socketCreateHandler
     384 *      Set the blocking mode before calling the accept callback.
     385 */
     386
     387        socketSetBlock(nid, (nsp->flags & SOCKET_BLOCK) ? 1: 0);
     388/*
     389 *      Call the user accept callback. The user must call socketCreateHandler
    244390 *      to register for further events of interest.
    245391 */
    246392        if (sp->accept != NULL) {
    247                 if ((sp->accept)(nid, inet_ntoa(addr.sin_addr),
    248                                 ntohs(addr.sin_port)) < 0) {
     393                pString = inet_ntoa(addr.sin_addr);
     394                if ((sp->accept)(nid, pString, ntohs(addr.sin_port), sp->sid) < 0) {
    249395                        socketFree(nid);
    250                         return;
    251                 }
    252         }
    253         socketNonBlock(nsp);
    254 }
    255 
    256 /******************************************************************************/
    257 /*
    258  *      Write to a socket. This may block if the underlying socket cannot
    259  *      absorb the data. Returns -1 on error, otherwise the number of bytes
    260  *      written.
    261  */
    262 
    263 int     socketWrite(int sid, char* buf, int bufsize)
    264 {
    265         socket_t*       sp;
    266         ringq_t*        rq;
    267         int                     len, bytesWritten, room;
     396                }
     397#if VXWORKS
     398                free(pString);
     399#endif
     400        }
     401}
     402
     403/******************************************************************************/
     404/*
     405 *      Get more input from the socket and return in buf.
     406 *      Returns 0 for EOF, -1 for errors and otherwise the number of bytes read.
     407 */
     408
     409int socketGetInput(int sid, char *buf, int toRead, int *errCode)
     410{
     411        struct sockaddr_in      server;
     412        socket_t                        *sp;
     413        int                             len, bytesRead;
    268414
    269415        a_assert(buf);
    270         a_assert(bufsize >= 0);
     416        a_assert(errCode);
     417
     418        *errCode = 0;
    271419
    272420        if ((sp = socketPtr(sid)) == NULL) {
    273421                return -1;
    274422        }
    275        
    276 /*
    277  *      Loop adding as much data to the output ringq as we can absorb
    278  *      Flush when the ringq is too full and continue.
    279  */
    280         rq = &sp->outBuf;
    281         for (bytesWritten = 0; bufsize > 0; ) {
    282                 if ((room = ringqPutBlkMax(rq)) == 0) {
    283                         if (socketFlush(sid, 0) < 0) {
    284                                 return -1;
    285                         }
    286                         if ((room = ringqPutBlkMax(rq)) == 0) {
    287                                 break;
    288                         }
    289                         continue;
    290                 }
    291                 len = min(room, bufsize);
    292                 ringqPutBlk(rq, (unsigned char*) buf, len);
    293                 bytesWritten += len;
    294                 bufsize -= len;
    295                 buf += len;
    296         }
    297         return bytesWritten;
    298 }
    299 
    300 /******************************************************************************/
    301 /*
    302  *      Read from a socket. Return the number of bytes read if successful. This
    303  *      may be less than the requested "bufsize" and may be zero. Return -1 for
    304  *      errors. Return 0 for EOF. Otherwise return the number of bytes read. Since
    305  *      this may be zero, callers should use socketEof() to distinguish between
    306  *      this and EOF. Note: this ignores the line buffer, so a previous socketGets
    307  *      which read a partial line may cause a subsequent socketRead to miss
    308  *      some data.
    309  */
    310 
    311 int     socketRead(int sid, char* buf, int bufsize)
    312 {
    313         socket_t*       sp;
    314         ringq_t*        rq;
    315         int                     len, room, errCode, bytesRead;
    316 
    317         a_assert(buf);
    318         a_assert(bufsize > 0);
    319 
    320         if ((sp = socketPtr(sid)) == NULL) {
    321                 return -1;
    322         }
    323 
     423
     424/*
     425 *      If we have previously seen an EOF condition, then just return
     426 */
    324427        if (sp->flags & SOCKET_EOF) {
    325428                return 0;
    326429        }
    327 
    328         rq = &sp->inBuf;
    329         for (bytesRead = 0; bufsize > 0; ) {
    330                 len = min(ringqLen(rq), bufsize);
    331                 if (len <= 0) {
    332                         room = ringqPutBlkMax(rq);
    333                         len = socketGetInput(sid, (char*) rq->endp, room, &errCode);
    334                         if (len < 0) {
    335                                 if (errCode == EWOULDBLOCK) {
    336                                         if (bytesRead >= 0) {
    337                                                 return bytesRead;
    338                                         }
    339                                 }
    340                                 return -1;
    341 
    342                         } else if (len == 0) {
    343 /*
    344  *                              This is EOF, but we may have already read some data so pass that
    345  *                              back first before notifying EOF. The next read will return 0
    346  *                              to indicate EOF.
    347  */
    348                                 return bytesRead;
    349                         }
    350                         ringqPutBlkAdj(rq, len);
    351                         len = min(len, bufsize);
    352                 }
    353                 memcpy(&buf[bytesRead], rq->servp, len);
    354                 ringqGetBlkAdj(rq, len);
    355                 bufsize -= len;
    356                 bytesRead += len;
    357         }
    358         return bytesRead;
    359 }
    360 
    361 /******************************************************************************/
    362 /*
    363  *      Get a string from a socket. This returns data in *buf in a malloced string
    364  *      after trimming the '\n'. If there is zero bytes returned, *buf will be set
    365  *      to NULL. It returns -1 for error, EOF or when no complete line yet read.
    366  *      Otherwise the length of the line is returned. If a partial line is read
    367  *      socketInputBuffered or socketEof can be used to distinguish between EOF
    368  *      and partial line still buffered. This routine eats and ignores carriage
    369  *  returns.
    370  */
    371 
    372 int     socketGets(int sid, char** buf)
    373 {
    374         socket_t*       sp;
    375         ringq_t*        lq;
    376         char            c;
    377         int                     rc, len;
    378 
    379         a_assert(buf);
    380 
    381         if ((sp = socketPtr(sid)) == NULL) {
     430#if (WIN || CE) && !(LITTLEFOOT || WEBS)
     431        if ( !(sp->flags & SOCKET_BLOCK)
     432                        && ! socketWaitForEvent(sp,  FD_CONNECT, errCode)) {
    382433                return -1;
    383434        }
    384         lq = &sp->lineBuf;
    385 
    386         while (1) {
    387 
    388                 if ((rc = socketRead(sid, &c, 1)) < 0) {
    389                         return rc;
    390 
    391                 } else if (rc == 0) {
    392 /*
    393  *                      If there is a partial line and we are at EOF, pretend we saw a '\n'
    394  */
    395                         if (ringqLen(lq) > 0 && (sp->flags & SOCKET_EOF)) {
    396                                 c = '\n';
    397                         } else {
    398                                 return -1;
    399                         }
    400                 }
    401 /*
    402  *              If a newline is seen, return the data excluding the new line to the
    403  *              caller. If carriage return is seen, just eat it.
    404  */
    405                 if (c == '\n') {
    406                         len = ringqLen(lq);
    407                         if (len > 0) {
    408                                 if ((*buf = balloc(B_L, len + 1)) == NULL) {
    409                                         return -1;
    410                                 }
    411                                 memset(*buf, 0, len + 1);
    412                                 ringqGetBlk(lq, (unsigned char*) *buf, len);
    413                         } else {
    414                                 *buf = NULL;
    415                         }
    416                         return len;
    417 
    418                 } else if (c == '\r') {
    419                         continue;
    420                 }
    421                 ringqPutc(lq, c);
    422         }
    423 }
    424 
    425 /******************************************************************************/
    426 /*
    427  *      Flush a socket. Do not wait, just initiate output and return.
    428  *      This will return -1 on errors and 0 if successful.
    429  */
    430 
    431 int socketFlush(int sid, int block)
    432 {
    433         socket_t*       sp;
    434         ringq_t*        rq;
    435         int                     len, bytesWritten, errCode;
    436 
    437         a_assert(block == 0 || block == 1);
    438 
    439         if ((sp = socketPtr(sid)) == NULL) {
    440                 return -1;
    441         }
    442         rq = &sp->outBuf;
    443 
    444 /*
    445  *      Set the background flushing flag which socketDoEvent will check to
    446  *      continue the flush.
    447  */
    448         if (!block) {
    449                 sp->flags |= SOCKET_FLUSHING;
    450         }
    451 
    452 /*
    453  *      Break from loop if not blocking after initiating output. If we are blocking
    454  *      we wait for a write event.
    455  */
    456         while (ringqLen(rq) > 0) {
    457                 len = ringqGetBlkMax(&sp->outBuf);
    458                 bytesWritten = socketDoOutput(sp, (char*) rq->servp, len, &errCode);
    459                 if (bytesWritten < 0) {
    460                         if (errCode == EINTR) {
    461                                 continue;
    462                         } else if (errCode == EWOULDBLOCK || errCode == EAGAIN) {
    463                                 if (! block) {
    464                                         return 0;
    465                                 }
    466                                 if (socketWaitForEvent(sp, SOCKET_WRITABLE | SOCKET_EXCEPTION,
    467                                                 &errCode)) {
    468                                         continue;
    469                                 }
    470                         }
    471                         return -1;
    472                 }
    473                 ringqGetBlkAdj(rq, bytesWritten);
    474                 if (! block) {
    475                         break;
    476                 }
    477         }
    478         return 0;
    479 }
    480 
    481 /******************************************************************************/
    482 /*
    483  *      Return the count of input characters buffered. We look at both the line
    484  *      buffer and the input (raw) buffer. Return -1 on error or EOF.
    485  */
    486 
    487 int socketInputBuffered(int sid)
    488 {
    489         socket_t*       sp;
    490 
    491         if ((sp = socketPtr(sid)) == NULL) {
    492                 return -1;
    493         }
    494         if (socketEof(sid)) {
    495                 return -1;
    496         }
    497         return ringqLen(&sp->lineBuf) + ringqLen(&sp->inBuf);
    498 }
    499 
    500 /******************************************************************************/
    501 /*
    502  *      Return true if EOF
    503  */
    504 
    505 int socketEof(int sid)
    506 {
    507         socket_t*       sp;
    508 
    509         if ((sp = socketPtr(sid)) == NULL) {
    510                 return -1;
    511         }
    512         return sp->flags & SOCKET_EOF;
    513 }
    514 
    515 /******************************************************************************/
    516 /*
    517  *      Create a user handler for this socket. The handler called whenever there
    518  *      is an event of interest as defined by interestMask (SOCKET_READABLE, ...)
    519  */
    520 
    521 void socketCreateHandler(int sid, int interestMask, socketHandler_t handler,
    522         int data)
    523 {
    524         socket_t*       sp;
    525 
    526         if ((sp = socketPtr(sid)) == NULL) {
    527                 return;
    528         }
    529         sp->handler = handler;
    530         sp->handler_data = data;
    531         sp->interestMask = interestMask;
    532 }
    533 
    534 /******************************************************************************/
    535 /*
    536  *      Delete a handler
    537  */
    538 
    539 void socketDeleteHandler(int sid)
    540 {
    541         socket_t*       sp;
    542 
    543         if ((sp = socketPtr(sid)) == NULL) {
    544                 return;
    545         }
    546         sp->handler = NULL;
    547         sp->interestMask = 0;
    548 }
    549 
    550 /******************************************************************************/
    551 /*
    552  *      Get more input from the socket and return in buf.
    553  *      Returns 0 for EOF, -1 for errors and otherwise the number of bytes read.
    554  */
    555 
    556 static int socketGetInput(int sid, char* buf, int toRead, int* errCode)
    557 {
    558         struct sockaddr_in      server;
    559         socket_t*                       sp;
    560         int                             len, bytesRead;
    561        
    562         a_assert(buf);
    563         a_assert(errCode);
    564 
    565         *errCode = 0;
    566 
    567         if ((sp = socketPtr(sid)) == NULL) {
    568                 return -1;
    569         }
    570 
    571 /*
    572  *      If we have previously seen an EOF condition, then just return
    573  */
    574         if (sp->flags & SOCKET_EOF) {
    575                 return 0;
    576         }
     435#endif
    577436
    578437/*
    579438 *      Read the data
    580439 */
    581         if (sp->flags & SOCKET_BROADCAST) {
    582                 server.sin_family = AF_INET;
    583                 server.sin_addr.s_addr = INADDR_BROADCAST;
    584                 server.sin_port = htons((short)(sp->port & 0xFFFF));
     440        if (sp->flags & SOCKET_DATAGRAM) {
    585441                len = sizeof(server);
    586                 bytesRead = recvfrom(sp->sock, buf, toRead, 0, 
    587                         (struct sockaddr*) &server, &len);
     442                bytesRead = recvfrom(sp->sock, buf, toRead, 0,
     443                        (struct sockaddr *) &server, &len);
    588444        } else {
    589445                bytesRead = recv(sp->sock, buf, toRead, 0);
    590446        }
    591 
    592447        if (bytesRead < 0) {
    593448                if (errno == ECONNRESET) {
     
    596451                *errCode = socketGetError();
    597452                return -1;
    598 
    599         } else if (bytesRead == 0) {
    600                 sp->flags |= SOCKET_EOF;
    601         }
     453        }
    602454        return bytesRead;
    603455}
     
    605457/******************************************************************************/
    606458/*
    607  *      Socket output procedure. Return -1 on errors otherwise return the number
    608  *      of bytes written.
    609  */
    610 
    611 static int socketDoOutput(socket_t* sp, char* buf, int toWrite, int* errCode)
    612 {
    613         struct sockaddr_in      server;
    614         int                             bytes;
    615 
     459 *      Process an event on the event queue
     460 */
     461
     462#ifndef UEMF
     463
     464static int socketEventProc(void *data, int mask)
     465{
     466        socket_t                *sp;
     467        ringq_t                 *rq;
     468        int                     sid;
     469
     470        sid = (int) data;
     471
     472        a_assert(sid >= 0 && sid < socketMax);
     473        a_assert(socketList[sid]);
     474
     475        if ((sp = socketPtr(sid)) == NULL) {
     476                return 1;
     477        }
     478
     479/*
     480 *      If now writable and flushing in the background, continue flushing
     481 */
     482        if (mask & SOCKET_WRITABLE) {
     483                if (sp->flags & SOCKET_FLUSHING) {
     484                        rq = &sp->outBuf;
     485                        if (ringqLen(rq) > 0) {
     486                                socketFlush(sp->sid);
     487                        } else {
     488                                sp->flags &= ~SOCKET_FLUSHING;
     489                        }
     490                }
     491        }
     492
     493/*
     494 *      Now invoke the users socket handler. NOTE: the handler may delete the
     495 *      socket, so we must be very careful after calling the handler.
     496 */
     497        if (sp->handler && (sp->handlerMask & mask)) {
     498                (sp->handler)(sid, mask & sp->handlerMask, sp->handler_data);
     499        }
     500        if (socketList && sid < socketMax && socketList[sid] == sp) {
     501                socketRegisterInterest(sp, sp->handlerMask);
     502        }
     503        return 1;
     504}
     505#endif /* ! UEMF */
     506
     507/******************************************************************************/
     508/*
     509 *      Define the events of interest
     510 */
     511
     512void socketRegisterInterest(socket_t *sp, int handlerMask)
     513{
    616514        a_assert(sp);
    617         a_assert(buf);
    618         a_assert(toWrite > 0);
    619         a_assert(errCode);
    620 
    621         *errCode = 0;
    622 
    623 /*
    624  *      Write the data
    625  */
    626         if (sp->flags & SOCKET_BROADCAST) {
    627                 server.sin_family = AF_INET;
    628                 server.sin_addr.s_addr = INADDR_BROADCAST;
    629                 server.sin_port = htons((short)(sp->port & 0xFFFF));
    630                 bytes = sendto(sp->sock, buf, toWrite, 0,
    631                         (struct sockaddr*) &server, sizeof(server));
     515
     516        sp->handlerMask = handlerMask;
     517#if !UEMF
     518        if (handlerMask) {
     519                sp->fileHandle = emfCreateFileHandler(sp->sock, handlerMask,
     520                        (emfFileProc *) socketEventProc, (void *) sp->sid);
    632521        } else {
    633                 bytes = send(sp->sock, buf, toWrite, 0);
    634         }
    635 
    636         if (bytes == 0 && bytes != toWrite) {
    637                 *errCode = EWOULDBLOCK;
     522                emfDeleteFileHandler(sp->fileHandle);
     523        }
     524#endif /* ! UEMF */
     525}
     526
     527/******************************************************************************/
     528/*
     529 *      Wait until an event occurs on a socket. Return 1 on success, 0 on failure.
     530 *      or -1 on exception (UEMF only)
     531 */
     532
     533int socketWaitForEvent(socket_t *sp, int handlerMask, int *errCode)
     534{
     535        int     mask;
     536
     537        a_assert(sp);
     538
     539        mask = sp->handlerMask;
     540        sp->handlerMask |= handlerMask;
     541        while (socketSelect(sp->sid, 1000)) {
     542                if (sp->currentEvents & (handlerMask | SOCKET_EXCEPTION)) {
     543                        break;
     544                }
     545        }
     546        sp->handlerMask = mask;
     547        if (sp->currentEvents & SOCKET_EXCEPTION) {
    638548                return -1;
    639         }
    640 
    641         if (bytes < 0) {
    642                 *errCode = socketGetError();
    643         }
    644         return bytes;
     549        } else if (sp->currentEvents & handlerMask) {
     550                return 1;
     551        }
     552        if (errCode) {
     553                *errCode = errno = EWOULDBLOCK;
     554        }
     555        return 0;
    645556}
    646557
     
    650561 */
    651562
    652 int socketReady()
     563int socketReady(int sid)
    653564{
    654565        socket_t        *sp;
    655         int                     i;
    656        
    657         for (i = 0; i < socketMax; i++) {
    658                 if ((sp = socketList[i]) == NULL) {
     566        int                     all;
     567
     568        all = 0;
     569        if (sid < 0) {
     570                sid = 0;
     571                all = 1;
     572        }
     573
     574        for (; sid < socketMax; sid++) {
     575                if ((sp = socketList[sid]) == NULL) {
     576                        if (! all) {
     577                                break;
     578                        } else {
     579                                continue;
     580                        }
     581                }
     582                if (sp->currentEvents & sp->handlerMask) {
     583                        return 1;
     584                }
     585/*
     586 *              If there is input data, also call select to test for new events
     587 */
     588                if (sp->handlerMask & SOCKET_READABLE && socketInputBuffered(sid)) {
     589                        socketSelect(sid, 0);
     590                        return 1;
     591                }
     592                if (! all) {
     593                        break;
     594                }
     595        }
     596        return 0;
     597}
     598
     599/******************************************************************************/
     600/*
     601 *      Wait for a handle to become readable or writable and return a number of
     602 *      noticed events. Timeout is in milliseconds.
     603 */
     604
     605#if WIN || CE
     606
     607int socketSelect(int sid, int timeout)
     608{
     609        struct timeval  tv;
     610        socket_t                *sp;
     611        fd_set                  readFds, writeFds, exceptFds;
     612        int                     nEvents;
     613        int                             all, socketHighestFd;   /* Highest socket fd opened */
     614
     615        FD_ZERO(&readFds);
     616        FD_ZERO(&writeFds);
     617        FD_ZERO(&exceptFds);
     618        socketHighestFd = -1;
     619
     620        tv.tv_sec = timeout / 1000;
     621        tv.tv_usec = (timeout % 1000) * 1000;
     622
     623/*
     624 *      Set the select event masks for events to watch
     625 */
     626        all = nEvents = 0;
     627
     628        if (sid < 0) {
     629                all++;
     630