/*****************************************************************************/ /* CGIplusTest.c Script for testing the relative efficiencies of CGI and CGIplus. Also for scripting benchmarks between the WASD, OSU and Apache environments! This script can detect whether it is in a CGI or CGIplus environment and adjust behaviour accordingly. Call using the AB (ApcheBench) utility in both environments to test throughput and response latency performance in both. For WASD and OSU this script re-opens in binary-mode, hence the full HTTP response. For Apache it leaves it in record-mode and uses a CGI response. Requires the CGI environment variables to be available as symbols. September 2000 Note: Apache 1.3-12 seems intent on adding a to each record received, distorting the content-length and generally causing problems. This seems to lead to ApacheBench reporting errors, including length issues. January 2001 Note: The above issue seems to have been worked around. See description of ApacheFixBg(). Can also be used as example code for working in both environments (although trying to be all things to all people the code is rather cluttered). Demonstrates the alternative mechanism for accessing CGIplus variable values, reading from and parsing each line for required variables, including the starndard/historical CGIplus variable record mode and weel as the WASD V7.2 and later 'struct' mode. Define a system-wide logical CGIPLUSTEST$STRUCT to force it into this latter mode (remembering any previous instance(s) of this script should be deleted using HTTPD/DO=DCL=DELETE). See the #included general-purpose [SRC.CGIPLUS]CGIPLUS_GETVAR.C function. Also see [SRC.MISC]CGILIB.C for facilities that ease CGIplus implementation! USAGE ----- Supply a query string ("?blah-blah") of/to ... * list all CGI(plus) variables integer output number of 80 character lines before=integer sleep number of seconds before beginning output after=integer sleep number of seconds after completing output non-cgi-response upset the server by outputting a non-CGI response CGIPLUS_VAR_RECORD ------------------ To "force" the use of 'record' mode (perhaps for performance comparison purposes) assign a non-empty environment variable (symbol or logical) named CGIPLUS_VAR_RECORD. This is detected in the CGIPLUS_CGIVAR.C module. VERSION HISTORY (update SOFTWAREVN as well!) --------------- 23-DEC-2003 MGD v1.4.2, minor conditional mods to support IA64 18-JUN-2003 MGD v1.4.1, CSWS APACHE_SHARED_SOCKET to APACHE$SHARED_SOCKET, 09-APR-2001 MGD v1.4.0, facility to test/measure CGIplus 'struct' mode 11-JAN-2001 MGD v1.3.0, CSWS V1.0-1 (Apache) "fixbg" support 23-SEP-2000 MGD v1.2,0, minor mods for comparison with VMS Apache 05-MAR-1999 MGD v1.1.0, minor mods for comparison with OSU 08-JUN-1997 MGD v1.0.0, initial development */ /*****************************************************************************/ #define SOFTWAREVN "1.4.2" #define SOFTWARENM "CGIPLUSTEST" #ifdef __ALPHA # define SOFTWAREID SOFTWARENM " AXP-" SOFTWAREVN #endif #ifdef __ia64 # define SOFTWAREID SOFTWARENM " IA64-" SOFTWAREVN #endif #ifdef __VAX # define SOFTWAREID SOFTWARENM " VAX-" SOFTWAREVN #endif /* standard C headers */ #include #include #include #include #include #include /* VMS headers */ #include #include int AfterCount, ApacheEnvironment, BeforeCount, Debug, IsCgiPlus, OsuEnvironment, RequestedCount; char *CgiPlusEofPtr, *CgiPlusEotPtr, *CgiPlusEscPtr; char Utility [] = "CGIPLUSTEST", Line80Chars [] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ\ abcdefghijklmnopqrstuvwxyz\ 0123456789\ !@#$%^&*()_+-=<>,\n"; /* function prototypes */ int ApacheFixBgHandler (); void ApacheFixBg (); void AtOsuExit (); char* CgiVar (char*); /*****************************************************************************/ /* */ main () { char *cptr; char ContentLength [32]; /*********/ /* begin */ /*********/ if (getenv ("WWWEXEC_RUNDOWN_STRING") != NULL) { OsuEnvironment = 1; atexit (&AtOsuExit); } else { if (getenv ("APACHE$SHARED_SOCKET") != NULL) ApacheEnvironment = 1; } Debug = getenv ("CGIPLUSTEST$DBUG") != NULL; if (!Debug) { /* OSU spits with output > 4096 */ if (OsuEnvironment) { stdout = freopen ("SYS$OUTPUT", "w", stdout, "ctx=bin", "mrs=4096"); fprintf (stdout, ""); fflush (stdout); } else if (ApacheEnvironment) { ApacheFixBg (); stdout = freopen ("SYS$OUTPUT", "w", stdout, "ctx=bin", "mrs=4096"); } else stdout = freopen ("SYS$OUTPUT", "w", stdout, "ctx=bin"); if (stdout == NULL) exit (vaxc$errno); } IsCgiPlus = ((CgiPlusEofPtr = getenv("CGIPLUSEOF")) != NULL); CgiPlusEotPtr = getenv("CGIPLUSEOT"); CgiPlusEscPtr = getenv("CGIPLUSESC"); /* do once for standard CGI, multiple times for CGIplus */ for (;;) { RequestedCount = -1; if (IsCgiPlus) { /* synchronize and read the CGIplus variable stream */ CgiVar (""); } else if (Debug) { /* won't work for OSU! */ fprintf (stdout, "Content-Type: text/plain\n\n"); system ("show sym *"); } if ((cptr = CgiVar ("WWW_QUERY_STRING")) == NULL) if ((cptr = CgiVar ("QUERY_STRING")) == NULL) cptr = ""; AfterCount = BeforeCount = RequestedCount = 0; if (isdigit(*cptr)) RequestedCount = atoi(cptr); else if (!strncmp (cptr, "after=", 6)) { RequestedCount = 10; AfterCount = atoi(cptr+6); } else if (!strncmp (cptr, "before=", 7)) { RequestedCount = 10; BeforeCount = atoi(cptr+7); } else if (!strncmp (cptr, "non-cgi", 6)) fprintf (stdout, "Output to make it a non-CGI-compliant response\n"); if (BeforeCount) sleep (BeforeCount); if (RequestedCount > 0) sprintf (ContentLength, "Content-Length: %d\r\n", RequestedCount * (sizeof(Line80Chars)-1)); else ContentLength[0] = '\0'; fprintf (stdout, "Content-Type: text/plain\r\n\ %s\ Script-Control: X-stream-mode\r\n\ Expires: Fri, 13 Jan 1978 14:00:00 GMT\r\n\ \r\n", ContentLength); if (*cptr == '*') { /* return all CGIplus variables in successive calls */ while ((cptr = CgiVar ("*")) != NULL) fprintf (stdout, "|%s|\n", cptr); } else if (RequestedCount < 0) { fprintf (stdout, "Usage: Supply a URL with a query string containing \ an integer representing the number of 80 character lines \ to be returned during the test.\n"); } else { while (RequestedCount--) fputs (Line80Chars, stdout); } if (AfterCount) sleep (AfterCount); if (!IsCgiPlus) break; /* the CGIplus EOF must be an independant I/O record */ fflush (stdout); fputs (CgiPlusEofPtr, stdout); fflush (stdout); } exit (1); } /*****************************************************************************/ /* Script executing in OSU environment exits. */ void AtOsuExit () { if (Debug) fprintf (stdout, "\n"); else { fflush (stdout); fprintf (stdout, ""); fflush (stdout); } } /*****************************************************************************/ /* According to "Compaq Secure Web Server Version 1.0-1 for OpenVMS Alpha (based on Apache) Version 1.0-1 Release Notes" this is required to support the transfer of any binary content in excess of 32 kbytes. This is based on a code snippet in these release notes, but makes the image activation and symbol resolution dynamic to allow the object module to be linked on systems without VMS Apache and the APACHE$FIXBG.EXE shareable image available. */ void ApacheFixBg () { $DESCRIPTOR (StdOutputDsc, "SYS$OUTPUT"); $DESCRIPTOR (ApacheFixBgImageDsc, "APACHE$FIXBG"); $DESCRIPTOR (ApacheFixBgDsc, "APACHE$FIXBG"); int status; unsigned short SysOutputChannel; int (*ApacheFixBg)(unsigned short, int); /*********/ /* begin */ /*********/ if (Debug) fprintf (stdout, "ApacheFixBg()\n"); lib$establish (ApacheFixBgHandler); status = lib$find_image_symbol (&ApacheFixBgImageDsc, &ApacheFixBgDsc, &ApacheFixBg, 0); if (Debug) fprintf (stdout, "lib$find_image_symbol() %%X%08.08X\n", status); lib$revert (); if (!(status & 1)) exit (status); status = sys$assign (&StdOutputDsc, &SysOutputChannel, 0, 0); if (status & 1) status = ApacheFixBg (SysOutputChannel, 1); if (!(status & 1)) exit (status); sys$dassgn (SysOutputChannel); } /*****************************************************************************/ /* Just continue, to report an error if the image couldn't be activated or the required symbol not found. */ int ApacheFixBgHandler () { /*********/ /* begin */ /*********/ if (Debug) fprintf (stdout, "ApacheFixBgHandler()\n"); return (SS$_CONTINUE); } /*****************************************************************************/ /* Just include the code for the generic CGI/plus variable function. */ #define DEBUGIT (Debug) #include "cgiplus_cgivar.c" /*****************************************************************************/