Changeset a6b4c0df in rtems
- Timestamp:
- 09/01/00 10:57:21 (23 years ago)
- Branches:
- 4.10, 4.11, 4.8, 4.9, 5, master
- Children:
- 5f117e8
- Parents:
- 757e1661
- Files:
-
- 16 added
- 61 edited
- 2 moved
Legend:
- Unmodified
- Added
- Removed
-
c/src/exec/libnetworking/ChangeLog
r757e1661 ra6b4c0df 1 2000-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 1 13 2000-08-31 Ralf Corsepius <corsepiu@faw.uni-ulm.de> 2 14 -
c/src/libnetworking/ChangeLog
r757e1661 ra6b4c0df 1 2000-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 1 13 2000-08-31 Ralf Corsepius <corsepiu@faw.uni-ulm.de> 2 14 -
c/src/libnetworking/rtems_webserver/Makefile.am
r757e1661 ra6b4c0df 8 8 LIB = $(ARCH)/$(LIBNAME) 9 9 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 10 C_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 13 14 C_O_FILES = $(C_FILES:%.c=$(ARCH)/%.o) 14 15 15 16 OBJS = $(C_O_FILES) 16 17 17 H_FILES = ej.h uemf.h webs.h wsIntrn.h18 H_FILES = ej.h ejIntrn.h emfdb.h md5.h uemf.h um.h webs.h wsIntrn.h 18 19 19 20 include $(RTEMS_ROOT)/make/custom/@RTEMS_BSP@.cfg … … 53 54 EXTRA_DIST = asp.c balloc.c default.c ej.h ejlex.c ejparse.c form.c h.c \ 54 55 handler.c mime.c misc.c ringq.c rom.c rtems_webserver.h security.c \ 55 socket.c sym.c uemf.c uemf.h u rl.c value.c wbase64.c webcomp.c webmain.c \56 web page.c webrom.c webs.c webs.h websuemf.c wsIntrn.h56 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 57 58 58 59 include $(top_srcdir)/../../../automake/local.am -
c/src/libnetworking/rtems_webserver/asp.c
r757e1661 ra6b4c0df 2 2 * asp.c -- Active Server Page Support 3 3 * 4 * Copyright (c) Go Ahead Software Inc., 1995-1999. All Rights Reserved.4 * Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved. 5 5 * 6 6 * See the file "license.txt" for usage and redistribution license requirements … … 21 21 /********************************** Locals ************************************/ 22 22 23 static sym_fd_t websAspFunctions = -1; /* Symbol table of functions */ 23 static sym_fd_t websAspFunctions = -1; /* Symbol table of functions */ 24 static int aspOpenCount = 0; /* count of apps using this module */ 24 25 25 26 /***************************** Forward Declarations ***************************/ 26 27 27 static char_t *strtokcmp(char_t * s1, char_t*s2);28 static char_t *strtokcmp(char_t *s1, char_t *s2); 28 29 static char_t *skipWhite(char_t *s); 29 30 … … 35 36 int websAspOpen() 36 37 { 38 if (++aspOpenCount == 1) { 37 39 /* 38 40 * Create the table for ASP functions 39 41 */ 40 websAspFunctions = symOpen(128);42 websAspFunctions = symOpen(WEBS_SYM_INIT * 2); 41 43 42 44 /* 43 45 * Create standard ASP commands 44 46 */ 45 websAspDefine(T("write"), websAspWrite); 47 websAspDefine(T("write"), websAspWrite); 48 } 46 49 return 0; 47 50 } … … 54 57 void websAspClose() 55 58 { 56 if (websAspFunctions != -1) { 57 symClose(websAspFunctions, NULL); 59 if (--aspOpenCount <= 0) { 60 if (websAspFunctions != -1) { 61 symClose(websAspFunctions); 62 websAspFunctions = -1; 63 } 58 64 } 59 65 } … … 66 72 */ 67 73 68 int websAspRequest(webs_t wp, char_t *lpath)74 int websAspRequest(webs_t wp, char_t *lpath) 69 75 { 70 76 websStatType sbuf; … … 85 91 86 92 /* 87 * Create Ejscript instance in case it is needed93 * Create Ejscript instance in case it is needed 88 94 */ 89 95 ejid = ejOpenEngine(wp->cgiVars, websAspFunctions); … … 113 119 goto done; 114 120 } 115 webs CloseFileHandle(wp);121 websPageClose(wp); 116 122 117 123 /* 118 124 * Convert to UNICODE if necessary. 119 125 */ 120 if ((buf = ballocAscToUni(rbuf )) == NULL) {126 if ((buf = ballocAscToUni(rbuf, len)) == NULL) { 121 127 websError(wp, 200, T("Can't get memory")); 122 128 goto done; … … 221 227 done: 222 228 if (websValid(wp)) { 223 webs CloseFileHandle(wp);229 websPageClose(wp); 224 230 if (ejid >= 0) { 225 231 ejCloseEngine(ejid); … … 253 259 254 260 a_assert(websValid(wp)); 255 a_assert(argv); 256 261 257 262 for (i = 0; i < argc; ) { 263 a_assert(argv); 258 264 if (websWriteBlock(wp, argv[i], gstrlen(argv[i])) < 0) { 259 265 return -1; … … 274 280 */ 275 281 276 static char_t * strtokcmp(char_t* s1, char_t*s2)282 static char_t *strtokcmp(char_t *s1, char_t *s2) 277 283 { 278 284 int len; -
c/src/libnetworking/rtems_webserver/balloc.c
r757e1661 ra6b4c0df 2 2 * balloc.c -- Block allocation module 3 3 * 4 * Copyright (c) GoAhead Software Inc., 1995- 1999. All Rights Reserved.4 * Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved. 5 5 * 6 6 * See the file "license.txt" for usage and redistribution license requirements … … 12 12 * This module implements a very fast block allocation scheme suitable for 13 13 * ROMed environments. It maintains block class queues for rapid allocation 14 * and minimal fragmentation. This module sdoes not coalesce blocks. The14 * and minimal fragmentation. This module does not coalesce blocks. The 15 15 * storage space may be populated statically or via the traditional malloc 16 16 * mechanisms. Large blocks greater than the maximum class size may be … … 39 39 /********************************* Defines ************************************/ 40 40 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 49 41 /* 50 42 * Define B_STATS if you wish to track memory block and stack usage … … 64 56 long allocated; /* Bytes currently allocated */ 65 57 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; 67 61 } bStatsFileType; 68 62 … … 78 72 static bStatsFileType bStatsFiles[B_MAX_FILES];/* Per file stats */ 79 73 static 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 */ 74 static int bStatsBlksMax = 0; /* Max block entry */ 75 static int bStatsFilesMax = 0; /* Max file entry */ 76 static int bStatsMemInUse = 0; /* Memory currently in use */ 77 static int bStatsBallocInUse = 0; /* Memory currently balloced */ 78 static int bStatsMemMax = 0; /* Max memory ever used */ 79 static int bStatsBallocMax = 0; /* Max memory ever balloced */ 84 80 static void *bStackMin = (void*) -1;/* Miniumum stack position */ 85 81 static void *bStackStart; /* Starting stack position */ 86 static int bStatsMemMalloc ;/* Malloced memory */82 static int bStatsMemMalloc = 0; /* Malloced memory */ 87 83 #endif /* B_STATS */ 88 84 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) 89 94 90 95 /********************************** Locals ************************************/ … … 99 104 static int bFreeLeft; /* Size of free left for use */ 100 105 static int bFlags = B_USE_MALLOC; /* Default to auto-malloc */ 106 static int bopenCount = 0; /* Num tasks using balloc */ 101 107 102 108 /*************************** Forward Declarations *****************************/ … … 116 122 static void verifyUsedBlock(bType *bp, int q); 117 123 static void verifyFreeBlock(bType *bp, int q); 118 static void verifyBallocSpace(); 119 #endif 124 void verifyBallocSpace(); 125 #endif 126 127 static int ballocGetSize(int size, int *q); 120 128 121 129 /********************************** Code **************************************/ … … 134 142 bFlags = flags; 135 143 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 136 156 if (buf == NULL) { 137 157 if (bufsize == 0) { 138 158 bufsize = B_DEFAULT_MEM; 139 159 } 160 #ifdef IRIX 161 bufsize = ROUNDUP4(bufsize); 162 #endif 140 163 if ((buf = malloc(bufsize)) == NULL) { 141 164 return -1; … … 150 173 bFreeSize = bFreeLeft = bufsize; 151 174 bFreeBuf = bFreeNext = buf; 175 memset(bQhead, 0, sizeof(bQhead)); 152 176 #if B_FILL || B_VERIFY_CAUSES_SEVERE_OVERHEAD 153 177 bFillBlock(buf, bufsize); … … 172 196 verifyBallocSpace(); 173 197 #endif 174 if ( !(bFlags & B_USER_BUF)) {198 if (--bopenCount <= 0 && !(bFlags & B_USER_BUF)) { 175 199 free(bFreeBuf); 200 bopenCount = 0; 176 201 } 177 202 } … … 186 211 { 187 212 bType *bp; 188 int q, memSize , mask;213 int q, memSize; 189 214 190 215 /* … … 192 217 */ 193 218 if (bFreeBuf == NULL) { 194 if (bopen(NULL, B_DEFAULT_MEM 219 if (bopen(NULL, B_DEFAULT_MEM, 0) < 0) { 195 220 return NULL; 196 221 } … … 203 228 } 204 229 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); 216 238 217 239 if (q >= B_MAX_CLASS) { … … 222 244 #if B_STATS 223 245 bstats(0, NULL); 246 #endif 247 #ifdef IRIX 248 memSize = ROUNDUP4(memSize); 224 249 #endif 225 250 bp = (bType*) malloc(memSize); 226 251 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")); 229 253 return NULL; 230 254 } … … 237 261 238 262 } 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")); 241 264 return NULL; 242 265 } 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); 244 271 bp->flags = B_MALLOCED; 245 272 … … 255 282 bFillBlock(bp, memSize); 256 283 #endif 257 bp->u.size = size;284 bp->u.size = memSize - sizeof(bType); 258 285 bp->flags = 0; 259 286 … … 273 300 bFillBlock(bp, memSize); 274 301 #endif 275 bp->u.size = size;302 bp->u.size = memSize - sizeof(bType); 276 303 bp->flags = 0; 277 304 278 305 } else if (bFlags & B_USE_MALLOC) { 306 #if B_STATS 279 307 static int once = 0; 280 if (once++ < 20) { 281 #if B_STATS 308 if (once++ == 0) { 282 309 bstats(0, NULL); 283 #endif284 310 } 311 #endif 285 312 /* 286 313 * Nothing left on the primary free list, so malloc a new block 287 314 */ 315 #ifdef IRIX 316 memSize = ROUNDUP4(memSize); 317 #endif 288 318 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")); 291 320 return NULL; 292 321 } … … 297 326 bFillBlock(bp, memSize); 298 327 #endif 299 bp->u.size = size;328 bp->u.size = memSize - sizeof(bType); 300 329 bp->flags = B_MALLOCED; 301 330 302 331 } 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")); 304 333 return NULL; 305 334 } … … 307 336 308 337 #if B_STATS 309 bStatsAlloc(B_ARGS, bp, q, size);338 bStatsAlloc(B_ARGS, bp, q, memSize); 310 339 #endif 311 340 bp->flags |= B_INTEGRITY; 312 341 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 313 353 return (void*) ((char*) bp + sizeof(bType)); 314 354 } … … 324 364 { 325 365 bType *bp; 326 int mask, q;366 int q, memSize; 327 367 328 368 #if B_VERIFY_CAUSES_SEVERE_OVERHEAD 329 369 verifyBallocSpace(); 330 370 #endif 331 a_assert(mp);332 333 371 bp = (bType*) ((char*) mp - sizeof(bType)); 372 334 373 a_assert((bp->flags & B_INTEGRITY_MASK) == B_INTEGRITY); 374 335 375 if ((bp->flags & B_INTEGRITY_MASK) != B_INTEGRITY) { 336 376 return; 337 377 } 338 378 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); 347 380 348 381 #if B_VERIFY_CAUSES_SEVERE_OVERHEAD 349 382 verifyUsedBlock(bp,q); 383 #endif 384 #if B_STATS 385 bStatsFree(B_ARGS, bp, q, bp->u.size+sizeof(bType)); 350 386 #endif 351 387 if (bp->flags & B_MALLOCED) { … … 354 390 } 355 391 356 #if B_STATS357 bStatsFree(B_ARGS, bp, q, bp->u.size);358 #endif359 392 #if B_VERIFY_CAUSES_SEVERE_OVERHEAD 360 bFillBlock(bp, 1 << (B_SHIFT + q));393 bFillBlock(bp, memSize); 361 394 #endif 362 395 … … 366 399 bp->u.next = bQhead[q]; 367 400 bQhead[q] = bp; 401 402 bp->flags = B_FILL_WORD; 368 403 } 369 404 … … 433 468 void *brealloc(B_ARGS_DEC, void *mp, int newsize) 434 469 { 435 bType *bp;470 bType *bp; 436 471 void *newbuf; 437 472 … … 441 476 bp = (bType*) ((char*) mp - sizeof(bType)); 442 477 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 } 443 486 if ((newbuf = balloc(B_ARGS, newsize)) != NULL) { 444 487 memcpy(newbuf, mp, bp->u.size); … … 448 491 } 449 492 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 501 static 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 } 450 511 451 512 /******************************************************************************/ … … 465 526 /* 466 527 * Statistics. Do output via calling the writefn callback function with 467 * "handle" as the output file handle. 528 * "handle" as the output file handle. 468 529 */ 469 530 470 531 void bstats(int handle, void (*writefn)(int handle, char_t *fmt, ...)) 471 532 { 472 bStatsFileType *fp; 533 bStatsFileType *fp, *files; 534 bStatsBlkType *blkp; 473 535 bType *bp; 474 int q, count, mem, total; 536 char_t *cp; 537 int q, count, mem, total, len; 475 538 static int recurseProtect = 0; 476 539 477 540 if (recurseProtect++ > 0) { 541 recurseProtect--; 478 542 return; 479 543 } … … 493 557 * dd ddddd ddd ddddd dddd ddddd dddd 494 558 */ 495 (*writefn)(handle, " Q Size FreeBytes Inuse Bytes Allocs\n");559 (*writefn)(handle, " Q Size Free Bytes Inuse Bytes Allocs\n"); 496 560 497 561 total = 0; … … 499 563 count = 0; 500 564 for (bp = bQhead[q]; bp; bp = bp->u.next) { 501 a_assert((bp->flags & B_INTEGRITY_MASK) == B_INTEGRITY);502 565 count++; 503 566 } … … 505 568 total += mem; 506 569 (*writefn)(handle, 507 T("%2d %5d % 3d %5d %4d %5d %4d\n"),570 T("%2d %5d %4d %6d %4d %5d %4d\n"), 508 571 q, 1 << (q + B_SHIFT), count, mem, bStats[q].inuse, 509 572 bStats[q].inuse * (1 << (q + B_SHIFT)), bStats[q].alloc); … … 514 577 /* 515 578 * 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 * 516 592 */ 517 593 (*writefn)(handle, T("Initial free list size %7d\n"), bFreeSize); 518 594 (*writefn)(handle, T("Max memory malloced %7d\n"), bStatsMemMalloc); 519 595 (*writefn)(handle, T("Max memory ever used %7d\n"), bStatsMemMax); 596 (*writefn)(handle, T("Max memory ever balloced %7d\n"), bStatsBallocMax); 520 597 (*writefn)(handle, T("Memory currently in use %7d\n"), bStatsMemInUse); 598 (*writefn)(handle, T("Memory currently balloced %7d\n"), bStatsBallocInUse); 521 599 (*writefn)(handle, T("Max blocks allocated %7d\n"), bStatsBlksMax); 522 600 (*writefn)(handle, T("Maximum stack used %7d\n"), … … 528 606 529 607 /* 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")); 534 621 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++) { 536 627 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); 540 631 total += fp->allocated; 541 632 } 542 633 } 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); 544 651 recurseProtect--; 545 652 } … … 566 673 /******************************************************************************/ 567 674 /* 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 /*588 675 * Accumulate allocation statistics 589 676 */ … … 591 678 static void bStatsAlloc(B_ARGS_DEC, void *ptr, int q, int size) 592 679 { 680 int memSize; 593 681 bStatsFileType *fp; 594 682 bStatsBlkType *bp; 595 683 char_t name[FNAMESIZE + 10]; 596 684 597 a_assert(file && *file);598 a_assert(0 <= q && q <= B_MAX_CLASS);599 a_assert(size > 0);600 601 685 gsprintf(name, T("%s:%d"), B_ARGS); 602 686 … … 604 688 bStats[q].inuse++; 605 689 bStatsMemInUse += size; 606 607 690 if (bStatsMemInUse > bStatsMemMax) { 608 691 bStatsMemMax = bStatsMemInUse; 692 } 693 memSize = (1 << (B_SHIFT + q)) + sizeof(bType); 694 bStatsBallocInUse += memSize; 695 if (bStatsBallocInUse > bStatsBallocMax) { 696 bStatsBallocMax = bStatsBallocInUse; 609 697 } 610 698 … … 624 712 fp->allocated += size; 625 713 fp->count++; 626 fp->allocs++; 714 fp->times++; 715 if (fp->largest < size) { 716 fp->largest = size; 717 fp->q = q; 718 } 627 719 break; 628 720 } … … 630 722 631 723 /* 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 633 725 */ 634 726 if (fp >= &bStatsFiles[bStatsFilesMax]) { … … 638 730 fp->allocated += size; 639 731 fp->count++; 640 fp->allocs++; 732 fp->times++; 733 fp->largest = size; 734 fp->q = q; 641 735 if ((fp - bStatsFiles) >= bStatsFilesMax) { 642 736 bStatsFilesMax = (fp - bStatsFiles) + 1; … … 669 763 static void bStatsFree(B_ARGS_DEC, void *ptr, int q, int size) 670 764 { 765 int memSize; 671 766 bStatsFileType *fp; 672 767 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); 679 770 bStatsMemInUse -= size; 771 bStatsBallocInUse -= memSize; 680 772 bStats[q].inuse--; 681 773 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--) { 688 778 if (bp->ptr == ptr) { 689 779 bp->ptr = NULL; 690 780 fp = bp->who; 781 bp->who = NULL; 691 782 fp->allocated -= size; 692 783 fp->count--; … … 694 785 } 695 786 } 696 a_assert(0); 697 698 } 787 } 788 789 /******************************************************************************/ 790 /* 791 * Default output function. Just send to trace channel. 792 */ 793 794 #undef sprintf 795 static 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 699 806 700 807 #else /* not B_STATS */ … … 713 820 /* 714 821 * The following routines verify the integrity of the balloc memory space. 715 * These functions dependuse the B_FILL feature. Corruption is defined822 * These functions use the B_FILL feature. Corruption is defined 716 823 * as bad integrity flags in allocated blocks or data other than B_FILL_CHAR 717 824 * being found anywhere in the space which is unallocated and that is not a 718 * next pointer in the free queues. 825 * next pointer in the free queues. a_assert is called if any corruption is 719 826 * found. CAUTION: These functions add severe processing overhead and should 720 827 * only be used when searching for a tough corruption problem. … … 732 839 char *p; 733 840 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); 736 843 size = bp->u.size; 737 844 for (p = ((char *)bp)+sizeof(bType)+size; p < ((char*)bp)+memSize; p++) { … … 751 858 char *p; 752 859 753 memSize = (1 << (B_SHIFT + q)) ;860 memSize = (1 << (B_SHIFT + q)) + sizeof(bType); 754 861 for (p = ((char *)bp)+sizeof(void*); p < ((char*)bp)+memSize; p++) { 755 862 a_assert(*p == B_FILL_CHAR); … … 757 864 bp = (bType *)p; 758 865 a_assert((bp->flags & ~B_MALLOCED) == B_INTEGRITY || 759 866 bp->flags == B_FILL_WORD); 760 867 } 761 868 … … 763 870 /* 764 871 * verifyBallocSpace reads through the entire balloc memory space and 765 * verifies that all allocated blocks are uncorrupted and that with the766 * exception of free list next pointers all other unallocated space is872 * verifies that all allocated blocks are uncorrupted and that, with the 873 * exception of free list next pointers, all other unallocated space is 767 874 * filled with B_FILL_CHAR. 768 875 */ 769 876 770 static void verifyBallocSpace() 771 { 877 void verifyBallocSpace() 878 { 879 int q; 772 880 char *p; 773 881 bType *bp; 774 882 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 */ 775 895 p = bFreeBuf; 776 896 while (p < (bFreeBuf + bFreeSize)) { … … 783 903 } else { 784 904 a_assert(((bp->flags & ~B_MALLOCED) == B_INTEGRITY) || 785 905 bp->flags == B_FILL_WORD); 786 906 p += (sizeof(bType) + bp->u.size); 787 907 while (p < (bFreeBuf + bFreeSize) && *p == B_FILL_CHAR) { … … 808 928 809 929 /******************************************************************************/ 930 931 void bstats(int handle, void (*writefn)(int handle, char_t *fmt, ...)) 932 { 933 } 934 935 /******************************************************************************/ 936 937 char_t *bstrdupNoBalloc(char_t *s) 938 { 810 939 #if UNICODE 811 char_t* bstrdupNoBalloc(char_t* s)812 {813 940 if (s) { 814 941 return wcsdup(s); … … 816 943 return wcsdup(T("")); 817 944 } 818 } 819 #endif /* UNICODE */ 820 821 /******************************************************************************/ 822 char* bstrdupANoBalloc(char* s) 945 #else 946 return bstrdupANoBalloc(s); 947 #endif 948 } 949 950 /******************************************************************************/ 951 952 char *bstrdupANoBalloc(char *s) 823 953 { 824 954 char* buf; -
c/src/libnetworking/rtems_webserver/base64.c
r757e1661 ra6b4c0df 2 2 * base64.c -- Base64 Mime encoding 3 3 * 4 * Copyright (c) Go Ahead Software Inc., 1995-1999. All Rights Reserved.4 * Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved. 5 5 * 6 6 * See the file "license.txt" for usage and redistribution license requirements … … 61 61 */ 62 62 63 int websDecode64(char_t * outbuf, char_t*string, int outlen)63 int websDecode64(char_t *outbuf, char_t *string, int outlen) 64 64 { 65 65 unsigned long shiftbuf; 66 char_t* cp; 67 char_t* op; 66 char_t *cp, *op; 68 67 int c, i, j, shift; 69 68 … … 110 109 */ 111 110 112 void websEncode64(char_t * outbuf, char_t*string, int outlen)111 void websEncode64(char_t *outbuf, char_t *string, int outlen) 113 112 { 114 113 unsigned long shiftbuf; 115 char_t* cp; 116 char_t* op; 114 char_t *cp, *op; 117 115 int x, i, j, shift; 118 116 -
c/src/libnetworking/rtems_webserver/default.c
r757e1661 ra6b4c0df 2 2 * default.c -- Default URL handler. Includes support for ASP. 3 3 * 4 * Copyright (c) Go Ahead Software Inc., 1995-1999. All Rights Reserved.4 * Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved. 5 5 * 6 6 * See the file "license.txt" for usage and redistribution license requirements 7 * 8 * $Id$ 7 9 */ 8 10 … … 39 41 40 42 int 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) 42 44 { 43 45 websStatType sbuf; 44 char_t *lpath, *tmp; 45 char_t *date; 46 char_t *lpath, *tmp, *date; 46 47 int bytes, flags, nchars; 47 48 48 49 a_assert(websValid(wp)); 49 50 a_assert(url && *url); 50 a_assert(path && *path);51 a_assert(path); 51 52 a_assert(query); 52 53 … … 75 76 } 76 77 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); 79 79 websRedirect(wp, tmp); 80 80 bfreeSafe(B_L, tmp); … … 88 88 0666) < 0) { 89 89 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); 92 91 return 1; 93 92 } 94 93 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; 97 97 } 98 98 … … 108 108 websWrite(wp, T("HTTP/1.0 304 Use local copy\r\n")); 109 109 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) { 116 117 websWrite(wp, T("Connection: keep-alive\r\n")); 117 118 } … … 132 133 /* 133 134 * 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); 136 137 bfree(B_L, date); 137 138 } … … 166 167 167 168 /* 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 /* 168 177 * Evaluate ASP requests 169 178 */ … … 176 185 } 177 186 178 /* 179 * All done if the browser did a HEAD request 180 */ 181 if (flags & WEBS_HEAD_REQUEST){182 webs Done(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 185 194 /* 186 195 * For normal web documents, return the data via background write 187 196 */ 188 197 websSetRequestSocketHandler(wp, SOCKET_WRITABLE, websDefaultWriteEvent); 198 #endif 189 199 return 1; 190 200 } … … 241 251 * Create local path for document. Need extra space all "/" and null. 242 252 */ 243 if (npart ) {253 if (npart || (gstrcmp(path, T("/")) == 0) || (path[0] == '\0')) { 244 254 lpath = balloc(B_L, (gstrlen(dir) + 1 + len + 1) * sizeof(char_t)); 245 255 gstrcpy(lpath, dir); … … 268 278 static void websDefaultWriteEvent(webs_t wp) 269 279 { 270 int 271 char *buf;280 int len, wrote, flags, bytes, written; 281 char *buf; 272 282 273 283 a_assert(websValid(wp)); … … 275 285 flags = websGetRequestFlags(wp); 276 286 277 wrote = 0; 278 bytes = 0; 287 websMarkTime(wp); 288 289 wrote = bytes = 0; 279 290 written = websGetRequestWritten(wp); 280 291 … … 285 296 bytes = websGetRequestBytes(wp); 286 297 /* 287 * Note: websWrite Block may return less than we wanted. It will return288 * -1 on a socket error298 * Note: websWriteDataNonBlock may return less than we wanted. It will 299 * return -1 on a socket error 289 300 */ 290 301 if ((buf = balloc(B_L, PAGE_READ_BUFSIZE)) == NULL) { … … 293 304 else { 294 305 while ((len = websPageReadData(wp, buf, PAGE_READ_BUFSIZE)) > 0) { 295 if ((wrote = websWrite BlockData(wp, buf, len)) < 0) {306 if ((wrote = websWriteDataNonBlock(wp, buf, len)) < 0) { 296 307 break; 297 308 } 298 309 written += wrote; 299 310 if (wrote != len) { 300 websPageSeek(wp, - ( wrote - len));311 websPageSeek(wp, - (len - wrote)); 301 312 break; 302 313 } … … 331 342 if (websDefaultPage) { 332 343 bfree(B_L, websDefaultPage); 344 websDefaultPage = NULL; 333 345 } 334 346 if (websDefaultDir) { 335 347 bfree(B_L, websDefaultDir); 348 websDefaultDir = NULL; 336 349 } 337 350 } -
c/src/libnetworking/rtems_webserver/ej.h
r757e1661 ra6b4c0df 2 2 * ej.h -- Ejscript(TM) header 3 3 * 4 * Copyright (c) Go Ahead Software, Inc., 1992-19994 * Copyright (c) GoAhead Software Inc., 1992-2000. All Rights Reserved. 5 5 * 6 6 * See the file "license.txt" for information on usage and redistribution … … 13 13 14 14 /* 15 * Go 15 * GoAhead Ejscript(TM) header. This defines the Ejscript API and internal 16 16 * structures. 17 17 */ … … 19 19 /********************************* Includes ***********************************/ 20 20 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 37 25 #include "uemf.h" 38 #else39 #include <param.h>40 #include <stat.h>41 #include "basic/basicInternal.h"42 #include "emf/emf.h"43 #include "webs/webs.h"44 26 #endif 45 27 46 28 /********************************** Defines ***********************************/ 47 /*48 * Constants49 */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 tokens56 */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 operators81 */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 operators101 */102 #define COND_AND 1 /* && */103 #define COND_OR 2 /* || */104 #define COND_NOT 3 /* ! */105 106 /*107 * States108 */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 3113 #define STATE_RELEXP 4 /* Parsing a relational expr */114 #define STATE_RELEXP_DONE 5115 #define STATE_EXPR 6 /* Parsing an expression */116 #define STATE_EXPR_DONE 7117 #define STATE_STMT 8 /* Parsing General statement */118 #define STATE_STMT_DONE 9119 #define STATE_STMT_BLOCK_DONE 10 /* End of block "}" */120 #define STATE_ARG_LIST 11 /* Function arg list */121 #define STATE_ARG_LIST_DONE 12122 #define STATE_DEC_LIST 16 /* Declaration list */123 #define STATE_DEC_LIST_DONE 17124 #define STATE_DEC 18125 #define STATE_DEC_DONE 19126 #define STATE_BEGIN STATE_STMT127 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 structure137 */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 structure146 */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 structure160 */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;175 29 176 30 /******************************** Prototypes **********************************/ 177 31 32 extern int ejArgs(int argc, char_t **argv, char_t *fmt, ...); 33 extern void ejSetResult(int eid, char_t *s); 178 34 extern int ejOpenEngine(sym_fd_t variables, sym_fd_t functions); 179 35 extern 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);185 36 extern int ejSetGlobalFunction(int eid, char_t *name, 186 37 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);197 38 extern void ejSetVar(int eid, char_t *var, char_t *value); 198 extern void ejSetLocalVar(int eid, char_t *var, char_t *value);199 39 extern 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); 40 extern char_t *ejEval(int eid, char_t *script, char_t **emsg); 223 41 224 42 #endif /* _h_EJ */ -
c/src/libnetworking/rtems_webserver/ejlex.c
r757e1661 ra6b4c0df 2 2 * ejlex.c -- Ejscript(TM) Lexical Analyser 3 3 * 4 * Copyright (c) Go Ahead Software, Inc., 1995-19994 * Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved. 5 5 * 6 6 * See the file "license.txt" for usage and redistribution license requirements … … 16 16 /********************************** Includes **********************************/ 17 17 18 #include "ej .h"18 #include "ejIntrn.h" 19 19 20 20 #if UEMF … … 24 24 #endif 25 25 26 /********************************** Defines ***********************************/ 27 #define OCTAL 8 28 #define HEX 16 26 29 /****************************** Forward Declarations **************************/ 27 30 … … 30 33 static int inputGetc(ej_t* ep); 31 34 static void inputPutback(ej_t* ep, int c); 35 static int charConvert(ej_t* ep, int base, int maxDig); 32 36 33 37 /************************************* Code ***********************************/ … … 78 82 return -1; 79 83 } 80 if (ringqOpen(&ip->script, EJ_ INC, -1) < 0) {84 if (ringqOpen(&ip->script, EJ_SCRIPT_INC, -1) < 0) { 81 85 return -1; 82 86 } … … 84 88 * Put the Ejscript into a ring queue for easy parsing 85 89 */ 86 ringqPut str(&ip->script, script);90 ringqPutStr(&ip->script, script); 87 91 88 92 ip->lineNumber = 1; … … 179 183 if (state->putBackToken) { 180 184 bfree(B_L, state->putBackToken); 185 state->putBackToken = NULL; 181 186 } 182 187 } … … 190 195 { 191 196 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); 193 198 return ep->tid; 194 199 } … … 203 208 ringq_t *inq, *tokq; 204 209 ejinput_t* ip; 205 int done, tid, c, quote, style , back_quoted, lval, i;210 int done, tid, c, quote, style; 206 211 207 212 a_assert(ep); … … 219 224 220 225 if (ip->putBackTokenId > 0) { 221 ringqPut str(tokq, ip->putBackToken);226 ringqPutStr(tokq, ip->putBackToken); 222 227 tid = ip->putBackTokenId; 223 228 ip->putBackTokenId = 0; … … 386 391 return TOK_ASSIGNMENT; 387 392 388 case '!': /* "!=" */393 case '!': /* "!=" or "!"*/ 389 394 if ((c = inputGetc(ep)) < 0) { 390 395 ejError(ep, T("Syntax Error")); … … 395 400 return TOK_EXPR; 396 401 } 397 tokenAddChar(ep, COND_NOT); 398 return TOK_LOGICAL; 402 inputPutback(ep, c); 403 tokenAddChar(ep, EXPR_BOOL_COMP); 404 return TOK_EXPR; 399 405 400 406 case ';': … … 429 435 return TOK_ERR; 430 436 } 431 back_quoted = 0; 437 432 438 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 { 450 454 switch (c) { 451 455 case 'n': … … 460 464 c = '\t'; break; 461 465 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); 473 470 break; 474 471 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 486 478 break; 487 479 case '\'': 488 480 case '\"': 481 case '\\': 489 482 break; 483 default: 484 ejError(ep, T("Invalid Escape Sequence")); 485 return TOK_ERR; 490 486 } 491 487 } 492 back_quoted = 0;493 488 if (tokenAddChar(ep, c) < 0) { 494 489 return TOK_ERR; … … 514 509 if ((c = inputGetc(ep)) < 0) 515 510 break; 516 } while (gisdigit( (char_t)c));511 } while (gisdigit(c)); 517 512 inputPutback(ep, c); 518 513 return TOK_LITERAL; … … 522 517 * Identifiers or a function names 523 518 */ 524 back_quoted = 0;525 519 while (1) { 526 if (c == '\\' && !back_quoted) {527 back_quoted++; 528 } else { 529 back_quoted = 0; 530 520 if (c == '\\') { 521 /* 522 * just ignore any \ characters. 523 */ 524 } else if (tokenAddChar(ep, c) < 0) { 531 525 break; 532 }533 526 } 534 527 if ((c = inputGetc(ep)) < 0) { 535 528 break; 536 529 } 537 if (! back_quoted && (!gisalnum((char_t) c) && c != '$' &&538 c != '_')) {530 if (!gisalnum(c) && c != '$' && c != '_' && 531 c != '\\') { 539 532 break; 540 533 } … … 559 552 return TOK_FOR; 560 553 } else if (gstrcmp(ep->token, T("return")) == 0) { 554 if ((c == ';') || (c == '(')) { 555 inputPutback(ep, c); 556 } 561 557 return TOK_RETURN; 562 558 } 563 559 } 564 560 565 /* 566 * skip white space after token to find out whether this is567 * a function or not.561 /* 562 * Skip white space after token to find out whether this is 563 * a function or not. 568 564 */ 569 565 while (c == ' ' || c == '\t' || c == '\r' || c == '\n') { … … 678 674 679 675 /******************************************************************************/ 676 /* 677 * Convert a hex or octal character back to binary, return original char if 678 * not a hex digit 679 */ 680 681 static 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 2 2 * ejparse.c -- Ejscript(TM) Parser 3 3 * 4 * Copyright (c) Go Ahead Software, Inc., 1995-19994 * Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved. 5 5 * 6 6 * See the file "license.txt" for usage and redistribution license requirements … … 16 16 /********************************** Includes **********************************/ 17 17 18 #include "ej.h" 18 #include "ejIntrn.h" 19 20 #if CE 21 #include "CE/wincompat.h" 22 #endif 19 23 20 24 /********************************** Local Data ********************************/ … … 25 29 /****************************** Forward Declarations **************************/ 26 30 31 #ifndef B_STATS 32 #define setString(a,b,c) setstring(b,c) 33 #endif 34 27 35 static ej_t *ejPtr(int eid); 28 36 static void clearString(char_t **ptr); 29 static void setString( char_t **ptr, char_t *s);37 static void setString(B_ARGS_DEC, char_t **ptr, char_t *s); 30 38 static void appendString(char_t **ptr, char_t *s); 31 static void freeVar(sym_t* sp);32 39 static int parse(ej_t *ep, int state, int flags); 33 40 static int parseStmt(ej_t *ep, int state, int flags); … … 40 47 static int evalFunction(ej_t *ep); 41 48 static void freeFunc(ejfunc_t *func); 49 static void ejRemoveNewlines(ej_t *ep, int state); 42 50 43 51 /************************************* Code ***********************************/ … … 58 66 59 67 /* 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 62 70 * declarations so we use hAlloc to manage a list of variable tables. 63 71 */ … … 73 81 ep->variables[vid] = symOpen(64) + EJ_OFFSET; 74 82 ep->flags |= FLAGS_VARIABLES; 75 76 83 } else { 77 84 ep->variables[vid] = variables + EJ_OFFSET; … … 123 130 ejLexClose(ep); 124 131 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 131 139 if (ep->flags & FLAGS_FUNCTIONS) { 132 symClose(ep->functions , freeVar);140 symClose(ep->functions); 133 141 } 134 142 … … 137 145 } 138 146 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 149 148 /******************************************************************************/ 150 149 /* … … 152 151 */ 153 152 154 #if DEV155 153 char_t *ejEvalFile(int eid, char_t *path, char_t **emsg) 156 154 { … … 166 164 *emsg = NULL; 167 165 } 166 168 167 if ((ep = ejPtr(eid)) == NULL) { 169 168 return NULL; … … 174 173 return NULL; 175 174 } 175 176 176 if (gstat(path, &sbuf) < 0) { 177 close(fd);177 gclose(fd); 178 178 ejError(ep, T("Cant stat %s"), path); 179 179 return NULL; 180 180 } 181 181 182 if ((fileBuf = balloc(B_L, sbuf.st_size + 1)) == NULL) { 182 close(fd);183 gclose(fd); 183 184 ejError(ep, T("Cant malloc %d"), sbuf.st_size); 184 185 return NULL; 185 186 } 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); 188 190 bfree(B_L, fileBuf); 189 191 ejError(ep, T("Error reading %s"), path); 190 192 return NULL; 191 193 } 194 192 195 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) { 196 199 bfree(B_L, fileBuf); 197 200 ejError(ep, T("Cant malloc %d"), sbuf.st_size + 1); … … 205 208 return rs; 206 209 } 207 #endif 210 #endif /* __NO_EJ_FILE */ 208 211 209 212 /******************************************************************************/ … … 211 214 * Create a new variable scope block so that consecutive ejEval calls may 212 215 * 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. 214 217 */ 215 218 … … 217 220 { 218 221 ej_t *ep; 219 int vid; 222 int vid; 220 223 221 224 if((ep = ejPtr(eid)) == NULL) { 222 225 return -1; 223 } 226 } 227 224 228 if ((vid = hAlloc((void***) &ep->variables)) < 0) { 225 229 return -1; 226 230 } 231 227 232 if (vid >= ep->variableMax) { 228 233 ep->variableMax = vid + 1; 229 } 234 } 230 235 ep->variables[vid] = symOpen(64) + EJ_OFFSET; 231 236 return vid; … … 242 247 { 243 248 ej_t *ep; 244 249 245 250 if((ep = ejPtr(eid)) == NULL) { 246 251 return -1; 247 252 } 248 symClose(ep->variables[vid] - EJ_OFFSET , freeVar);253 symClose(ep->variables[vid] - EJ_OFFSET); 249 254 ep->variableMax = hFree((void***) &ep->variables, vid); 250 return 0; 251 252 } 255 return 0; 256 257 } 258 253 259 /******************************************************************************/ 254 260 /* … … 264 270 a_assert(script); 265 271 266 vid = ejOpenBlock(eid); 272 vid = ejOpenBlock(eid); 267 273 returnVal = ejEval(eid, script, emsg); 268 274 ejCloseBlock(eid, vid); … … 273 279 /******************************************************************************/ 274 280 /* 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 276 282 * use for variables and function definitions. Return char_t pointer on 277 283 * success otherwise NULL pointer is returned. … … 283 289 ejinput_t *oldBlock; 284 290 int state; 285 291 void *endlessLoopTest; 292 int loopCounter; 293 294 286 295 a_assert(script); 287 296 288 297 if (emsg) { 289 298 *emsg = NULL; 290 } 299 } 300 291 301 if ((ep = ejPtr(eid)) == NULL) { 292 302 return NULL; 293 303 } 294 304 295 setString( &ep->result, T(""));305 setString(B_L, &ep->result, T("")); 296 306 297 307 /* … … 304 314 * Do the actual parsing and evaluation 305 315 */ 316 loopCounter = 0; 317 endlessLoopTest = NULL; 318 306 319 do { 307 320 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 } 308 339 } while (state != STATE_EOF && state != STATE_ERR); 309 340 … … 325 356 return ep->result; 326 357 } 358 327 359 if (state == STATE_ERR) { 328 360 return NULL; 329 361 } 362 330 363 return ep->result; 331 364 } … … 345 378 */ 346 379 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 347 387 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 } 349 392 break; 350 393 351 394 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 } 353 399 break; 354 400 … … 398 444 ejfunc_t *saveFunc; 399 445 ejinput_t condScript, endScript, bodyScript, incrScript; 400 char_t *value; 401 char_t *identifier; 446 char_t *value, *identifier; 402 447 int done, expectSemi, thenFlags, elseFlags, tid, cond, forFlags; 448 int ejVarType; 403 449 404 450 a_assert(ep); … … 452 498 */ 453 499 identifier = NULL; 454 setString( &identifier, ep->token);500 setString(B_L, &identifier, ep->token); 455 501 /* 456 502 * Peek ahead to see if this is an assignment … … 459 505 if (tid == TOK_ASSIGNMENT) { 460 506 if (parse(ep, STATE_RELEXP, flags) != STATE_RELEXP_DONE) { 507 clearString(&identifier); 461 508 goto error; 462 509 } … … 464 511 if ( state == STATE_DEC ) { 465 512 ejSetLocalVar(ep->eid, identifier, ep->result); 466 } 467 else {468 if (ej GetVar(ep->eid, identifier, &value)> 0) {513 } else { 514 ejVarType = ejGetVar(ep->eid, identifier, &value); 515 if (ejVarType > 0) { 469 516 ejSetLocalVar(ep->eid, identifier, ep->result); 470 517 } else { … … 476 523 } else if (tid == TOK_INC_DEC ) { 477 524 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) { 480 528 ejError(ep, T("Undefined variable %s\n"), identifier); 481 529 goto error; 482 530 } 483 setString( &ep->result, value);531 setString(B_L, &ep->result, value); 484 532 if (evalExpr(ep, value, (int) *ep->token, T("1")) < 0) { 485 533 state = STATE_ERR; 486 534 break; 487 535 } 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 } 489 542 } 490 543 … … 496 549 if (state == STATE_DEC) { 497 550 if (ejGetVar(ep->eid, identifier, &value) > 0) { 498 ejError(ep, T("Variable already declared"), 551 ejError(ep, T("Variable already declared"), 499 552 identifier); 500 553 clearString(&identifier); … … 505 558 if ( flags & FLAGS_EXE ) { 506 559 if (ejGetVar(ep->eid, identifier, &value) < 0) { 507 ejError(ep, T("Undefined variable %s\n"), 560 ejError(ep, T("Undefined variable %s\n"), 508 561 identifier); 509 562 clearString(&identifier); … … 512 565 } 513 566 } 514 setString( &ep->result, value);567 setString(B_L, &ep->result, value); 515 568 ejLexPutbackToken(ep, tid, ep->token); 516 569 } … … 527 580 * Set the result to the literal (number or string constant) 528 581 */ 529 setString( &ep->result, ep->token);582 setString(B_L, &ep->result, ep->token); 530 583 if (state == STATE_STMT) { 531 584 expectSemi++; … … 542 595 } 543 596 memset(&func, 0, sizeof(ejfunc_t)); 544 setString( &func.fname, ep->token);597 setString(B_L, &func.fname, ep->token); 545 598 ep->func = &func; 546 599 547 setString( &ep->result, T(""));600 setString(B_L, &ep->result, T("")); 548 601 if (ejLexGetToken(ep, state) != TOK_LPAREN) { 549 602 freeFunc(&func); … … 605 658 } 606 659 /* 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); 612 674 tid = ejLexGetToken(ep, state); 613 675 if (tid != TOK_ELSE) { … … 617 679 } 618 680 /* 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: 622 689 goto error; 623 690 } … … 651 718 652 719 /* 653 * The first time through, we save the current input context just 720 * The first time through, we save the current input context just 654 721 * to each step: prior to the conditional, the loop increment and the 655 722 * loop body. … … 664 731 goto error; 665 732 } 666 733 667 734 /* 668 735 * Don't execute the loop increment statement or the body first time … … 678 745 679 746 /* 680 * Parse the body and remember the end of the body script 747 * Parse the body and remember the end of the body script 681 748 */ 682 749 ejLexSaveInputState(ep, &bodyScript); … … 694 761 */ 695 762 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: 697 770 goto error; 698 771 } … … 761 834 } while (state == STATE_STMT_DONE); 762 835 836 /* 837 * Allow return statement. 838 */ 839 if (state == STATE_RET) { 840 return state; 841 } 842 763 843 if (ejLexGetToken(ep, state) != TOK_RBRACE) { 764 844 goto error; … … 780 860 while ( ejLexGetToken(ep, state) != TOK_EOF ); 781 861 done++; 782 return STATE_ EOF;862 return STATE_RET; 783 863 } 784 864 break; … … 795 875 * Skip newline after semi-colon 796 876 */ 797 tid = ejLexGetToken(ep, state); 798 if (tid != TOK_NEWLINE) { 799 ejLexPutbackToken(ep, tid, ep->token); 800 } 877 ejRemoveNewlines(ep, state); 801 878 } 802 879 … … 811 888 ejLexFreeInputState(ep, &bodyScript); 812 889 } 890 813 891 if (state == STATE_STMT) { 814 892 return STATE_STMT_DONE; … … 929 1007 a_assert(ep); 930 1008 931 setString( &ep->result, T(""));1009 setString(B_L, &ep->result, T("")); 932 1010 rhs = lhs = NULL; 933 1011 operator = 0; … … 943 1021 break; 944 1022 } 1023 945 1024 if (operator > 0) { 946 setString( &rhs, ep->result);1025 setString(B_L, &rhs, ep->result); 947 1026 if (evalCond(ep, lhs, operator, rhs) < 0) { 948 1027 state = STATE_ERR; … … 950 1029 } 951 1030 } 952 setString( &lhs, ep->result);1031 setString(B_L, &lhs, ep->result); 953 1032 954 1033 tid = ejLexGetToken(ep, state); … … 970 1049 bfree(B_L, lhs); 971 1050 } 1051 972 1052 if (rhs) { 973 1053 bfree(B_L, rhs); … … 988 1068 a_assert(ep); 989 1069 990 setString( &ep->result, T(""));1070 setString(B_L, &ep->result, T("")); 991 1071 rhs = lhs = NULL; 992 1072 rel = 0; 1073 tid = 0; 993 1074 994 1075 do { … … 997 1078 * to evalutate each term which returns the result in ep->result. 998 1079 */ 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) { 1007 1082 state = STATE_ERR; 1008 1083 break; 1009 1084 } 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) { 1017 1110 rel = (int) *ep->token; 1018 1111 … … 1024 1117 } while (state == STATE_EXPR_DONE); 1025 1118 1026 if (rhs) 1119 if (rhs) { 1027 1120 bfree(B_L, rhs); 1028 if (lhs) 1121 } 1122 1123 if (lhs) { 1029 1124 bfree(B_L, lhs); 1125 } 1126 1030 1127 return state; 1031 1128 } … … 1046 1143 1047 1144 lval = 0; 1048 if (gisdigit( *lhs) && gisdigit(*rhs)) {1145 if (gisdigit((int)*lhs) && gisdigit((int)*rhs)) { 1049 1146 l = gatoi(lhs); 1050 1147 r = gatoi(rhs); … … 1061 1158 } 1062 1159 } else { 1063 if (!gisdigit( *lhs)) {1160 if (!gisdigit((int)*lhs)) { 1064 1161 ejError(ep, T("Conditional must be numeric"), lhs); 1065 1162 } else { … … 1067 1164 } 1068 1165 } 1069 1166 1070 1167 stritoa(lval, buf, sizeof(buf)); 1071 setString( &ep->result, buf);1168 setString(B_L, &ep->result, buf); 1072 1169 return 0; 1073 1170 } … … 1092 1189 numeric = 1; 1093 1190 for (cp = lhs; *cp; cp++) { 1094 if (!gisdigit( *cp)) {1191 if (!gisdigit((int)*cp)) { 1095 1192 numeric = 0; 1096 1193 break; 1097 1194 } 1098 1195 } 1196 1099 1197 if (numeric) { 1100 1198 for (cp = rhs; *cp; cp++) { 1101 if (!gisdigit( *cp)) {1199 if (!gisdigit((int)*cp)) { 1102 1200 numeric = 0; 1103 1201 break; … … 1105 1203 } 1106 1204 } 1205 1107 1206 if (numeric) { 1108 1207 l = gatoi(lhs); … … 1161 1260 case EXPR_GREATEREQ: 1162 1261 lval = (l >= r) ? 1 : 0; 1262 break; 1263 case EXPR_BOOL_COMP: 1264 lval = (r == 0) ? 1 : 0; 1163 1265 break; 1164 1266 default: … … 1206 1308 1207 1309 stritoa(lval, buf, sizeof(buf)); 1208 setString( &ep->result, buf);1310 setString(B_L, &ep->result, buf); 1209 1311 return 0; 1210 1312 } … … 1224 1326 return -1; 1225 1327 } 1328 1226 1329 fn = (int (*)(int, void*, int, char_t**)) sp->content.value.integer; 1227 1330 if (fn == NULL) { … … 1230 1333 } 1231 1334 1232 return (*fn)(ep->eid, (void*) ep->userHandle, ep->func->nArgs, 1335 return (*fn)(ep->eid, (void*) ep->userHandle, ep->func->nArgs, 1233 1336 ep->func->args); 1234 1337 } … … 1251 1354 va_start(args, fmt); 1252 1355 msgbuf = NULL; 1253 gvsnprintf(&msgbuf, E_MAX_ERROR, fmt, args);1356 fmtValloc(&msgbuf, E_MAX_ERROR, fmt, args); 1254 1357 va_end(args); 1255 1358 1256 1359 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"), 1259 1361 msgbuf, ip->lineNumber, ip->line); 1260 1362 bfreeSafe(B_L, ep->error); … … 1284 1386 */ 1285 1387 1286 static void setString( char_t **ptr, char_t *s)1388 static void setString(B_ARGS_DEC, char_t **ptr, char_t *s) 1287 1389 { 1288 1390 a_assert(ptr); 1289 1391 1290 1392 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); 1294 1396 } 1295 1397 … … 1320 1422 */ 1321 1423 1322 int ejSetGlobalFunction(int eid, char_t *name, 1424 int ejSetGlobalFunction(int eid, char_t *name, 1323 1425 int (*fn)(int eid, void *handle, int argc, char_t **argv)) 1324 1426 { … … 1336 1438 */ 1337 1439 1338 int ejSetGlobalFunctionDirect(sym_fd_t functions, char_t *name, 1440 int ejSetGlobalFunctionDirect(sym_fd_t functions, char_t *name, 1339 1441 int (*fn)(int eid, void *handle, int argc, char_t **argv)) 1340 1442 { … … 1347 1449 /******************************************************************************/ 1348 1450 /* 1451 * Remove ("undefine") a function 1452 */ 1453 1454 int 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 /* 1349 1466 * Get a function definition 1350 1467 */ … … 1359 1476 return NULL; 1360 1477 } 1478 1361 1479 if ((sp = symLookup(ep->functions, name)) != NULL) { 1362 1480 fn = (int (*)(int, void*, int, char_t**)) sp->content.value.integer; … … 1368 1486 /******************************************************************************/ 1369 1487 /* 1370 * Utility routine to crack Ejscript arguments. Return the number of args 1488 * Utility routine to crack Ejscript arguments. Return the number of args 1371 1489 * seen. This routine only supports %s and %d type args. 1372 1490 * … … 1478 1596 return; 1479 1597 } 1480 setString( &ep->result, s);1598 setString(B_L, &ep->result, s); 1481 1599 } 1482 1600 … … 1512 1630 return; 1513 1631 } 1632 1514 1633 if (value == NULL) { 1515 1634 v = valueString(value, 0); … … 1536 1655 return; 1537 1656 } 1657 1538 1658 if (value == NULL) { 1539 1659 v = valueString(value, 0); … … 1546 1666 /******************************************************************************/ 1547 1667 /* 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 1549 1669 * declared but undefined. The value is defined in the global variable frame. 1550 1670 */ … … 1560 1680 return; 1561 1681 } 1682 1562 1683 if (value == NULL) { 1563 1684 v = valueString(value, 0); … … 1586 1707 } 1587 1708 1588 for (i = ep->variableMax - 1; i >= 0; i--) {1589 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 /******************************************************************************/ 1601 1722 /* 1602 1723 * Get the variable symbol table … … 1610 1731 return -1; 1611 1732 } 1612 return ep->variables;1613 } 1614 #endif 1733 return *ep->variables; 1734 } 1735 1615 1736 /******************************************************************************/ 1616 1737 /* … … 1641 1762 func->nArgs = hFree((void***) &func->args, i); 1642 1763 } 1764 1643 1765 if (func->fname) { 1644 1766 bfree(B_L, func->fname); … … 1648 1770 1649 1771 /******************************************************************************/ 1650 /* 1772 /* 1651 1773 * Get Ejscript pointer 1652 1774 */ … … 1664 1786 1665 1787 /******************************************************************************/ 1788 /* 1789 * This function removes any new lines. Used for else cases, etc. 1790 */ 1791 static 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 2 2 * form.c -- Form processing (in-memory CGI) for the GoAhead Web server 3 3 * 4 * Copyright (c) Go Ahead Software Inc., 1995-1999. All Rights Reserved.4 * Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved. 5 5 * 6 6 * See the file "license.txt" for usage and redistribution license requirements … … 30 30 31 31 int 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) 33 33 { 34 34 sym_t *sp; 35 35 char_t formBuf[FNAMESIZE]; 36 36 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); 38 38 39 39 a_assert(websValid(wp)); … … 64 64 websError(wp, 200, T("Form %s is not defined"), formName); 65 65 } 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; 67 67 a_assert(fn); 68 68 if (fn) { … … 71 71 */ 72 72 (*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 */ 73 79 if (websValid(wp)) { 74 80 websError(wp, 200, T("Form didn't call websDone")); 75 81 } 82 #endif /* push */ 76 83 } 77 84 } … … 87 94 char_t *query)) 88 95 { 89 static int once = 0;90 91 96 a_assert(name && *name); 92 97 a_assert(fn); … … 96 101 } 97 102 98 if (once++ == 0) {99 websFormOpen();100 }101 103 symEnter(formSymtab, name, valueInteger((int) fn), (int) NULL); 102 104 return 0; … … 110 112 void websFormOpen() 111 113 { 112 formSymtab = symOpen( 64);114 formSymtab = symOpen(WEBS_SYM_INIT); 113 115 } 114 116 … … 121 123 { 122 124 if (formSymtab != -1) { 123 symClose(formSymtab, NULL); 125 symClose(formSymtab); 126 formSymtab = -1; 124 127 } 125 128 } … … 140 143 * By license terms the following line of code must not be modified 141 144 */ 142 websWrite(wp, T("Server: GoAhead-Webs\r\n"));145 websWrite(wp, T("Server: %s\r\n"), WEBS_NAME); 143 146 144 147 websWrite(wp, T("Pragma: no-cache\n")); -
c/src/libnetworking/rtems_webserver/h.c
r757e1661 ra6b4c0df 2 2 * h.c -- Handle allocation module 3 3 * 4 * Copyright (c) GoAhead Software Inc., 1995- 1999. All Rights Reserved.4 * Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved. 5 5 * See the file "license.txt" for usage and redistribution license requirements 6 6 */ … … 9 9 10 10 /* 11 * 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 13 13 * per-handle structures. 14 14 */ … … 37 37 /*********************************** Code *************************************/ 38 38 /* 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 40 40 * handle map to be a pointer to a null pointer. *map points to the second 41 41 * element in the handle array. 42 42 */ 43 43 44 #if B_STATS 45 int HALLOC(B_ARGS_DEC, void ***map) 46 #else 44 47 int hAlloc(void ***map) 48 #endif 45 49 { 46 50 int *mp; … … 52 56 incr = H_INCR; 53 57 memsize = (incr + H_OFFSET) * sizeof(void**); 58 #if B_STATS 59 if ((mp = (int*) balloc(B_ARGS, memsize)) == NULL) { 60 #else 54 61 if ((mp = (int*) balloc(B_L, memsize)) == NULL) { 62 #endif 55 63 return -1; 56 64 } … … 69 77 */ 70 78 if (mp[H_USED] < mp[H_LEN]) { 71 for (handle = 0; handle < len; handle++) 79 for (handle = 0; handle < len; handle++) { 72 80 if (mp[handle+H_OFFSET] == 0) { 73 81 mp[H_USED]++; 74 82 return handle; 75 83 } 84 } 76 85 } else { 77 86 handle = len; … … 140 149 */ 141 150 151 #if B_STATS 152 int HALLOCENTRY(B_ARGS_DEC, void ***list, int *max, int size) 153 #else 142 154 int hAllocEntry(void ***list, int *max, int size) 155 #endif 143 156 { 144 157 char_t *cp; … … 148 161 a_assert(max); 149 162 163 #if B_STATS 164 if ((id = HALLOC(B_ARGS, (void***) list)) < 0) { 165 #else 150 166 if ((id = hAlloc((void***) list)) < 0) { 167 #endif 151 168 return -1; 152 169 } 153 170 154 171 if (size > 0) { 172 #if B_STATS 173 if ((cp = balloc(B_ARGS, size)) == NULL) { 174 #else 155 175 if ((cp = balloc(B_L, size)) == NULL) { 176 #endif 156 177 hFree(list, id); 157 178 return -1; … … 170 191 171 192 /******************************************************************************/ 193 -
c/src/libnetworking/rtems_webserver/handler.c
r757e1661 ra6b4c0df 2 2 * handler.c -- URL handler support 3 3 * 4 * Copyright (c) Go Ahead Software Inc., 1995-1999. All Rights Reserved.4 * Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved. 5 5 * 6 6 * See the file "license.txt" for usage and redistribution license requirements … … 20 20 /*********************************** Locals ***********************************/ 21 21 22 static websUrlHandlerType * websUrlHandler;/* URL handler list */22 static websUrlHandlerType *websUrlHandler; /* URL handler list */ 23 23 static int websUrlHandlerMax; /* Number of entries */ 24 static int urlHandlerOpenCount = 0; /* count of apps */ 24 25 25 26 /**************************** Forward Declarations ****************************/ 26 27 27 static int websUrlHandlerSort(const void * p1, const void*p2);28 static int websUrlHandlerSort(const void *p1, const void *p2); 28 29 static int websPublishHandler(webs_t wp, char_t *urlPrefix, char_t *webDir, 29 30 int sid, char_t *url, char_t *path, char_t *query); 31 static int websTidyUrl(webs_t wp); 30 32 31 33 /*********************************** Code *************************************/ … … 36 38 int websUrlHandlerOpen() 37 39 { 38 websAspOpen(); 40 if (++urlHandlerOpenCount == 1) { 41 websAspOpen(); 42 websUrlHandler = NULL; 43 websUrlHandlerMax = 0; 44 } 39 45 return 0; 40 46 } … … 47 53 void websUrlHandlerClose() 48 54 { 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 } 60 69 } 61 70 … … 136 145 */ 137 146 138 static int websUrlHandlerSort(const void * p1, const void*p2)147 static int websUrlHandlerSort(const void *p1, const void *p2) 139 148 { 140 149 websUrlHandlerType *s1, *s2; … … 247 256 248 257 websSetRequestPath(wp, websGetDefaultDir(), NULL); 258 259 websTidyUrl(wp); 249 260 250 261 /* … … 265 276 } 266 277 if (!websValid(wp)) { 267 goahead_trace(0,278 trace(0, 268 279 T("webs: handler %s called websDone, but didn't return 1\n"), 269 280 sp->urlPrefix); … … 273 284 } 274 285 /* 275 * If no handler processed the request, then return an error. Note: It was286 * If no handler processed the request, then return an error. Note: It is 276 287 * the handlers responsibility to call websDone 277 288 */ … … 282 293 } 283 294 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 302 static 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 2 2 * mime.c -- Web server mime types 3 3 * 4 * Copyright (c) Go Ahead Software Inc., 1995-1999. All Rights Reserved.4 * Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved. 5 5 * 6 6 * See the file "license.txt" for usage and redistribution license requirements -
c/src/libnetworking/rtems_webserver/misc.c
r757e1661 ra6b4c0df 2 2 * misc.c -- Miscellaneous routines. 3 3 * 4 * Copyright (c) GoAhead Software Inc., 1995- 1999. All Rights Reserved.4 * Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved. 5 5 * 6 6 * See the file "license.txt" for usage and redistribution license requirements … … 17 17 /********************************* Defines ************************************/ 18 18 /* 19 * Sprintf buffer structure. Make the increment 8 less than64 so that19 * Sprintf buffer structure. Make the increment 64 so that 20 20 * a balloc can use a 64 byte block. 21 21 */ 22 22 23 23 #define STR_REALLOC 0x1 /* Reallocate the buffer as required */ 24 #define STR_INC 58/* Growth increment */24 #define STR_INC 64 /* Growth increment */ 25 25 26 26 typedef struct { … … 60 60 /* 61 61 * "basename" returns a pointer to the last component of a pathname 62 * LINUX , RTEMS,and LynxOS have their own basename function63 */ 64 65 #if ! LINUX & ! __rtems__ & ! LYNX66 char_t *basename(char_t *name)62 * LINUX and LynxOS have their own basename function 63 */ 64 65 #if ! LINUX && ! LYNX && ! __rtems__ 66 char_t *basename(char_t *name) 67 67 { 68 68 char_t *cp; … … 84 84 } 85 85 } 86 #endif /* ! LINUX & & ! __rtems__ &&! LYNX */86 #endif /* ! LINUX & ! LYNX */ 87 87 88 88 /******************************************************************************/ … … 92 92 */ 93 93 94 char_t *dirname(char_t * buf, char_t*name, int bufsize)95 { 96 char_t *cp;94 char_t *dirname(char_t *buf, char_t *name, int bufsize) 95 { 96 char_t *cp; 97 97 int len; 98 98 … … 131 131 } 132 132 133 133 134 /******************************************************************************/ 134 135 /* 135 136 * sprintf and vsprintf are bad, ok. You can easily clobber memory. Use 136 * gsnprintf and gvsnprintfinstead! These functions do _not_ support floating137 * fmtAlloc and fmtValloc instead! These functions do _not_ support floating 137 138 * point, like %e, %f, %g... 138 139 */ 139 140 140 int gsnprintf(char_t **s, int n, char_t *fmt, ...)141 int fmtAlloc(char_t **s, int n, char_t *fmt, ...) 141 142 { 142 143 va_list ap; … … 148 149 *s = NULL; 149 150 va_start(ap, fmt); 150 result = gvsnprintf(s, n, fmt, ap);151 result = dsnprintf(s, n, fmt, ap, 0); 151 152 va_end(ap); 152 153 return result; … … 155 156 /******************************************************************************/ 156 157 /* 158 * Support a static buffer version for small buffers only! 159 */ 160 161 int 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 /* 157 181 * This function appends the formatted string to the supplied string, 158 182 * reallocing if required. 159 183 */ 160 184 161 int gsprintfRealloc(char_t **s, int n, int msize, char_t *fmt, ...)185 int fmtRealloc(char_t **s, int n, int msize, char_t *fmt, ...) 162 186 { 163 187 va_list ap; … … 181 205 */ 182 206 183 int gvsnprintf(char_t **s, int n, char_t *fmt, va_list arg)207 int fmtValloc(char_t **s, int n, char_t *fmt, va_list arg) 184 208 { 185 209 a_assert(s); 186 210 a_assert(fmt); 187 211 212 *s = NULL; 188 213 return dsnprintf(s, n, fmt, arg, 0); 189 214 } … … 191 216 /******************************************************************************/ 192 217 /* 193 * Dynamic sprintf implementation. Supports dynamic buffer allocation also.218 * Dynamic sprintf implementation. Supports dynamic buffer allocation. 194 219 * This function can be called multiple times to grow an existing allocated 195 220 * buffer. In this case, msize is set to the size of the previously allocated … … 253 278 c = *fmt++; 254 279 } else { 255 for ( ; gisdigit( c); c = *fmt++) {280 for ( ; gisdigit((int)c); c = *fmt++) { 256 281 width = width * 10 + (c - '0'); 257 282 } … … 264 289 c = *fmt++; 265 290 } else { 266 for (prec = 0; gisdigit( c); c = *fmt++) {291 for (prec = 0; gisdigit((int)c); c = *fmt++) { 267 292 prec = prec * 10 + (c - '0'); 268 293 } … … 403 428 static void put_char(strbuf_t *buf, char_t c) 404 429 { 405 if (buf->count >= buf->size) {430 if (buf->count >= (buf->size - 1)) { 406 431 if (! (buf->flags & STR_REALLOC)) { 407 432 return; … … 409 434 buf->size += STR_INC; 410 435 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 */ 412 439 buf->size -= STR_INC; 413 440 return; 414 441 } 415 442 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)); 417 444 } 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)); 419 446 } 420 447 } 421 448 buf->s[buf->count] = c; 422 ++buf->count; 449 if (c != '\0') { 450 ++buf->count; 451 } 423 452 } 424 453 … … 429 458 430 459 static 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) 432 461 { 433 462 int i; … … 459 488 460 489 static 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) 462 491 { 463 492 unsigned long x, x2; … … 476 505 } 477 506 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 } 480 515 } 481 516 } … … 525 560 */ 526 561 527 char *uniToAsc(char *buf, char_t *ustr, int nBytes)562 char *uniToAsc(char *buf, char_t *ustr, int nBytes) 528 563 { 529 564 #if UNICODE … … 538 573 } 539 574 540 541 575 /******************************************************************************/ 542 576 /* 543 577 * 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 584 char_t *ballocAscToUni(char *cp, int alen) 585 { 586 char_t *unip; 551 587 int ulen; 552 588 553 ulen = ( strlen(cp)+ 1) * sizeof(char_t);589 ulen = (alen + 1) * sizeof(char_t); 554 590 if ((unip = balloc(B_L, ulen)) == NULL) { 555 591 return NULL; 556 592 } 557 593 ascToUni(unip, cp, ulen); 594 unip[alen] = 0; 558 595 return unip; 559 596 } … … 563 600 * allocate (balloc) a buffer and do unicode to ascii conversion into it. 564 601 * 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 607 char *ballocUniToAsc(char_t *unip, int ulen) 570 608 { 571 609 char * cp; 572 610 573 if ((cp = balloc(B_L, ulen )) == NULL) {611 if ((cp = balloc(B_L, ulen+1)) == NULL) { 574 612 return NULL; 575 613 } 576 614 uniToAsc(cp, unip, ulen); 615 cp[ulen] = '\0'; 577 616 return cp; 578 617 } 579 618 580 619 /******************************************************************************/ 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 625 unsigned 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 656 unsigned 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 2 2 * ringq.c -- Ring queue buffering module 3 3 * 4 * Copyright (c) GoAhead Software Inc., 1995- 1999. All Rights Reserved.4 * Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved. 5 5 * 6 6 * See the file "license.txt" for usage and redistribution license requirements … … 11 11 /* 12 12 * A ring queue allows maximum utilization of memory for data storage and is 13 * ideal for input/output buffering. This module provides a highly eff ecient13 * ideal for input/output buffering. This module provides a highly efficient 14 14 * implementation and a vehicle for dynamic strings. 15 15 * … … 37 37 * 38 38 * The queue is empty when servp == endp. This means that the queue will hold 39 * at most rq->buflen -1 bytes. It is the filler s responsibility to ensure39 * at most rq->buflen -1 bytes. It is the filler's responsibility to ensure 40 40 * the ringq is never filled such that servp == endp. 41 41 * 42 * It is the filler s responsibility to "wrap" the endp back to point to42 * It is the filler's responsibility to "wrap" the endp back to point to 43 43 * rq->buf when the pointer steps past the end. Correspondingly it is the 44 44 * consumers responsibility to "wrap" the servp when it steps to rq->endbuf. … … 66 66 /***************************** Forward Declarations ***************************/ 67 67 68 static int ringq_grow(ringq_t *rq); 68 static int ringqGrow(ringq_t *rq); 69 static int getBinBlockSize(int size); 70 71 int ringqGrowCalls = 0; 69 72 70 73 /*********************************** Code *************************************/ … … 77 80 */ 78 81 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) { 82 int 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) { 85 91 return -1; 86 92 } … … 116 122 /******************************************************************************/ 117 123 /* 118 * Return the length of the ringq. Users must fill the queue to a high119 * 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. 120 126 */ 121 127 … … 127 133 if (rq->servp > rq->endp) { 128 134 return rq->buflen + rq->endp - rq->servp; 129 } 130 else { 135 } else { 131 136 return rq->endp - rq->servp; 132 137 } … … 167 172 int ringqPutc(ringq_t *rq, char_t c) 168 173 { 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)) { 175 180 return -1; 176 181 } … … 192 197 int ringqInsertc(ringq_t *rq, char_t c) 193 198 { 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)) { 200 205 return -1; 201 206 } … … 211 216 /******************************************************************************/ 212 217 /* 213 * Add a string to the queue. Add a trailing wide null (two nulls)214 */ 215 216 int ringqPut str(ringq_t *rq, char_t *str)218 * Add a string to the queue. Add a trailing null (maybe two nulls) 219 */ 220 221 int ringqPutStr(ringq_t *rq, char_t *str) 217 222 { 218 223 int rc; … … 228 233 229 234 /******************************************************************************/ 235 /* 236 * Add a null terminator. This does NOT increase the size of the queue 237 */ 238 239 void 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 /******************************************************************************/ 230 248 #if UNICODE 231 249 /* … … 262 280 a_assert(rq->buflen == (rq->endbuf - rq->buf)); 263 281 264 if (ringqPutBlkMax(rq) == 0 && !ringq _grow(rq)) {282 if (ringqPutBlkMax(rq) == 0 && !ringqGrow(rq)) { 265 283 return -1; 266 284 } … … 283 301 a_assert(rq->buflen == (rq->endbuf - rq->buf)); 284 302 285 if (ringqPutBlkMax(rq) == 0 && !ringq _grow(rq)) {303 if (ringqPutBlkMax(rq) == 0 && !ringqGrow(rq)) { 286 304 return -1; 287 305 } … … 299 317 */ 300 318 301 int ringqPut strA(ringq_t *rq, char *str)319 int ringqPutStrA(ringq_t *rq, char *str) 302 320 { 303 321 int rc; … … 335 353 this = min(ringqPutBlkMax(rq), size); 336 354 if (this <= 0) { 337 if (! ringq _grow(rq)) {355 if (! ringqGrow(rq)) { 338 356 break; 339 357 } … … 486 504 { 487 505 a_assert(rq); 506 a_assert(rq->servp); 488 507 489 508 rq->servp = rq->buf; 490 509 rq->endp = rq->buf; 491 *rq->servp = '\0'; 510 if (rq->servp) { 511 *rq->servp = '\0'; 512 } 492 513 } 493 514 … … 499 520 */ 500 521 501 static int ringq _grow(ringq_t *rq)522 static int ringqGrow(ringq_t *rq) 502 523 { 503 524 unsigned char *newbuf; … … 532 553 533 554 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 534 561 return 1; 535 562 } 536 563 537 564 /******************************************************************************/ 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 571 static 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 2 2 * rom.c -- Support for ROMed page retrieval. 3 3 * 4 * Copyright (c) Go Ahead Software Inc., 1995-1999. All Rights Reserved.4 * Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved. 5 5 * 6 6 * See the file "license.txt" for usage and redistribution license requirements … … 20 20 21 21 #include <stdlib.h> 22 23 #if CE24 #define EINVAL 2225 #define EBADF 926 #else27 #include <errno.h>28 #endif29 22 30 23 #include "wsIntrn.h" … … 47 40 char_t name[SYM_MAX]; 48 41 49 romTab = symOpen( 64);42 romTab = symOpen(WEBS_SYM_INIT); 50 43 51 44 for (wip = websRomPageIndex; wip->path; wip++) { … … 68 61 void websRomClose() 69 62 { 70 symClose(romTab , NULL);63 symClose(romTab); 71 64 } 72 65 … … 106 99 */ 107 100 108 int websRomPageStat(char_t *path, websStatType *sbuf)101 int websRomPageStat(char_t *path, websStatType *sbuf) 109 102 { 110 103 websRomPageIndexType *wip; … … 194 187 } 195 188 196 #endif 189 #endif /* WEBS_PAGE_ROM */ 197 190 198 191 /******************************************************************************/ -
c/src/libnetworking/rtems_webserver/security.c
r757e1661 ra6b4c0df 2 2 * security.c -- Security handler 3 3 * 4 * Copyright (c) Go Ahead Software Inc., 1995-1999. All Rights Reserved.4 * Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved. 5 5 * 6 6 * See the file "license.txt" for usage and redistribution license requirements … … 10 10 11 11 /* 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. 15 13 */ 16 14 … … 18 16 19 17 #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 20 39 21 40 /******************************** Local Data **********************************/ 22 41 23 42 static char_t websPassword[WEBS_MAX_PASS]; /* Access password (decoded) */ 43 #ifdef _DEBUG 44 static int debugSecurity = 1; 45 #else 46 static int debugSecurity = 0; 47 #endif 24 48 25 49 /*********************************** Code *************************************/ … … 31 55 char_t *url, char_t *path, char_t *query) 32 56 { 33 char_t *type, *password; 34 int flags; 57 char_t *type, *userid, *password, *accessLimit; 58 int flags, nRet; 59 accessMeth_t am; 35 60 36 61 a_assert(websValid(wp)); 37 62 a_assert(url && *url); 38 63 a_assert(path && *path); 39 40 64 /* 41 65 * Get the critical request details … … 43 67 type = websGetRequestType(wp); 44 68 password = websGetRequestPassword(wp); 69 userid = websGetRequestUserName(wp); 45 70 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) { 55 155 websStats.access++; 56 156 websError(wp, 200, T("Access Denied\nWrong Password")); 57 websSetPassword(T("")); 58 return 1; 157 nRet = 1; 59 158 } 159 160 bfree (B_L, digestCalc); 161 #endif 60 162 } else { 61 163 /* 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 65 171 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; 70 175 } 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; 71 189 } 72 return 0; 190 191 bfree(B_L, accessLimit); 192 193 return nRet; 73 194 } 74 195 … … 103 224 char_t *websGetPassword() 104 225 { 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 3 4 * 4 * Copyright (c) Go Ahead, 1995-19995 * Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved. 5 6 */ 6 7 … … 8 9 9 10 /* 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 12 16 13 17 /********************************** Includes **********************************/ 14 18 15 #include <errno.h>16 #include <fcntl.h>17 19 #include <string.h> 18 20 #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 20 34 21 35 #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 45 38 46 39 /************************************ Locals **********************************/ 47 40 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 */ 41 extern socket_t **socketList; /* List of open sockets */ 42 extern int socketMax; /* Maximum size of socket */ 43 extern int socketHighestFd; /* Highest socket fd opened */ 44 static int socketOpenCount = 0; /* Number of task using sockets */ 51 45 52 46 /***************************** Forward Declarations ***************************/ 53 47 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); 48 static void socketAccept(socket_t *sp); 59 49 static 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); 50 static int tryAlternateConnect(int sock, struct sockaddr *sockaddr); 64 51 65 52 /*********************************** Code *************************************/ … … 70 57 int socketOpen() 71 58 { 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 72 80 return 0; 73 81 } … … 82 90 int i; 83 91 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; 88 99 } 89 100 } … … 94 105 */ 95 106 96 int socketOpenConnection(char* host, int port, socketAccept_t accept, int flags) 97 { 107 int 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) */ 98 112 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 } 103 119 /* 104 120 * Allocate a socket structure … … 122 138 sockaddr.sin_addr.s_addr = inet_addr(host); 123 139 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 124 163 hostent = gethostbyname(host); 125 164 if (hostent != NULL) { … … 128 167 (size_t) hostent->h_length); 129 168 } 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); 142 197 if (sp->sock < 0) { 143 198 socketFree(sid); 144 199 return -1; 145 200 } 201 #ifndef __NO_FCNTL 146 202 fcntl(sp->sock, F_SETFD, FD_CLOEXEC); 203 #endif 147 204 socketHighestFd = max(socketHighestFd, sp->sock); 148 205 149 206 /* 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 /* 150 219 * Host is set if we are the client 151 220 */ 152 221 if (host) { 153 222 /* 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, 157 275 sizeof(sockaddr)) < 0) { 158 276 socketFree(sid); 159 277 return -1; 160 278 } 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); 163 301 } 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); 182 303 } 183 304 return sid; … … 186 307 /******************************************************************************/ 187 308 /* 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 315 static 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 /* 188 331 * Close a socket 189 332 */ … … 191 334 void socketCloseConnection(int sid) 192 335 { 193 socket_t *sp;336 socket_t *sp; 194 337 195 338 if ((sp = socketPtr(sid)) == NULL) { 196 339 return; 197 340 } 198 199 /*200 * We always flush all output before closing. Unlink from the emf event201 * mechanism and then free (and close) the connection202 */203 socketFlush(sid, 1);204 341 socketFree(sid); 205 342 } … … 207 344 /******************************************************************************/ 208 345 /* 209 * Accept a connection. Called by socketDoEvent210 */ 211 212 static void socketAccept(socket_t *sp)346 * Accept a connection. Called as a callback on incoming connection. 347 */ 348 349 static void socketAccept(socket_t *sp) 213 350 { 214 351 struct sockaddr_in addr; 215 352 socket_t *nsp; 216 int len; 353 size_t len; 354 char *pString; 217 355 int newSock, nid; 218 356 … … 226 364 return; 227 365 } 366 #ifndef __NO_FCNTL 228 367 fcntl(newSock, F_SETFD, FD_CLOEXEC); 368 #endif 229 369 socketHighestFd = max(socketHighestFd, newSock); 230 370 … … 232 372 * Create a socket structure and insert into the socket list 233 373 */ 234 nid = socketAlloc(sp->host, sp->port, sp->accept, 0);374 nid = socketAlloc(sp->host, sp->port, sp->accept, sp->flags); 235 375 nsp = socketList[nid]; 236 376 a_assert(nsp); 237 377 nsp->sock = newSock; 378 nsp->flags &= ~SOCKET_LISTENING; 238 379 239 380 if (nsp == NULL) { … … 241 382 } 242 383 /* 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 244 390 * to register for further events of interest. 245 391 */ 246 392 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) { 249 395 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 bytes260 * written.261 */ 262 263 int socketWrite(int sid, char* buf, int bufsize)264 { 265 s ocket_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 409 int socketGetInput(int sid, char *buf, int toRead, int *errCode) 410 { 411 struct sockaddr_in server; 412 socket_t *sp; 413 int len, bytesRead; 268 414 269 415 a_assert(buf); 270 a_assert(bufsize >= 0); 416 a_assert(errCode); 417 418 *errCode = 0; 271 419 272 420 if ((sp = socketPtr(sid)) == NULL) { 273 421 return -1; 274 422 } 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 */ 324 427 if (sp->flags & SOCKET_EOF) { 325 428 return 0; 326 429 } 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)) { 382 433 return -1; 383 434 } 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 577 436 578 437 /* 579 438 * Read the data 580 439 */ 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) { 585 441 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); 588 444 } else { 589 445 bytesRead = recv(sp->sock, buf, toRead, 0); 590 446 } 591 592 447 if (bytesRead < 0) { 593 448 if (errno == ECONNRESET) { … … 596 451 *errCode = socketGetError(); 597 452 return -1; 598 599 } else if (bytesRead == 0) { 600 sp->flags |= SOCKET_EOF; 601 } 453 } 602 454 return bytesRead; 603 455 } … … 605 457 /******************************************************************************/ 606 458 /* 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 464 static 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 512 void socketRegisterInterest(socket_t *sp, int handlerMask) 513 { 616 514 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); 632 521 } 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 533 int 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) { 638 548 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; 645 556 } 646 557 … … 650 561 */ 651 562 652 int socketReady( )563 int socketReady(int sid) 653 564 { 654 565 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 607 int 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 sid = 0;