/*****************************************************************************/ /* CGIplusTest.c Script for testing and benchmarking the relative efficiencies of CGI, CGIplus and Apache loadable modules. WASD CGI http://the.host.name/cgi-bin/cgiplustest? WASD CGIplus http://the.host.name/cgiplus-bin/cgiplustest? Apache module http://the.host.name/cgiplustest? The Apache module also provides functionality akin to WASD ResponseStream(). For loadable module configuration see below. 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!) --------------- 20-APR-2020 MGD v1.6.0, Apache loadable module for performance comparison also equivalent functionality WASD ResponseStream() 19-OCT-2009 MGD v1.5.0, use CGILIB to make the OSU test-bench more equitable and "Pragma: no-cache" - gotcha! 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.6.0" #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 #include int AfterCount, BeforeCount, Debug, IsCgiPlus, RequestedCount; char Utility [] = "CGIPLUSTEST", Line80Chars [] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ\ abcdefghijklmnopqrstuvwxyz\ 0123456789\ !@#$%^&*()_+-=<>,\n"; /*****************************************************************************/ /* */ #ifndef APACHE_MOD main (int argc, char* argv[]) { char *cptr; /*********/ /* begin */ /*********/ Debug = getenv ("CGIPLUSTEST$DBUG") != NULL; CgiLibEnvironmentInit (argc, argv, TRUE); if (Debug) CgiLibEnvironmentRecordOut (); else if (!CgiLibEnvironmentIsOsu()) if (getenv("SYS$NET")) stdout = freopen ("SYS$OUTPUT:", "w", stdout, "ctx=bin", "mrs=4096"); IsCgiPlus = CgiLibEnvironmentIsCgiPlus (); for (;;) { /* once for standard CGI, multiple times for CGIplus */ RequestedCount = -1; if (IsCgiPlus) { /* synchronize and read the CGIplus variable stream */ CgiLibVar (""); } else if (Debug) { /* won't work for OSU! */ fprintf (stdout, "Content-Type: text/plain\n\n"); system ("show sym *"); } cptr = CgiLibVar ("WWW_QUERY_STRING"); 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); fprintf (stdout, "Status: 200\r\n\ Content-Type: text/plain\r\n\ Content-Length: %d\r\n\ Script-Control: X-stream-mode\r\n\ Pragma: no-cache\r\n\ Expires: Fri, 13 Jan 1978 14:00:00 GMT\r\n\ \r\n", RequestedCount * (sizeof(Line80Chars)-1)); fflush (stdout); if (*cptr == '*') { /* return all CGIplus variables in successive calls */ while ((cptr = CgiLibVar ("*")) != NULL) fprintf (stdout, "|%s|\n", cptr); } else if (RequestedCount < 0) { fprintf (stdout, "%s\n\ 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", SOFTWAREID); } else { while (RequestedCount--) fputs (Line80Chars, stdout); } 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 (AfterCount) sleep (AfterCount); if (!IsCgiPlus) break; CgiLibCgiPlusEOF (); } exit (1); } #endif #ifdef APACHE_MOD /*****************************************************************************/ /* MOD_CGIPLUSTEST.C - VMS Apache cgiplustest module $ copy [.OBJ_]MOD_CGIPLUSTEST.EXE APACHE$COMMON:[MODULES] Activate it in Apache's httpd.conf file: # httpd.conf LoadModule cgiplustest_module modules/mod_cgiplustest.so SetHandler cgiplustest Restart Apache using: $ apachectl restart Monkey see - monkey do. Speaks volumes of my Apache sophistication. Developed for VSI AXPVMS CSWS V2.4-38C. */ /*****************************************************************************/ #include "httpd.h" #include "http_config.h" #include "http_protocol.h" #include "ap_config.h" static void cgiplustest_lines (request_rec *req, int number) { ap_set_content_type (req, "text/plain"); while (number--) { ap_rputs (Line80Chars, req); if (req->connection->aborted) break; } } static void cgiplustest_stream (request_rec *req, char flag, int number) { int cnt, octet = 0; unsigned __int64 ranum; char *cptr, *sptr, *zptr; char buf [4096+1]; if (flag == 'b' || flag == 'o') ap_set_content_type (req, "application/binary"); else ap_set_content_type (req, "text/plain"); if (flag == 'b') { while (number > 0) { zptr = (sptr = buf) + sizeof(buf)-1; SYS$GETTIM (&ranum); while (sptr < zptr) { /* cheap (no subroutine call) MTH$RANDOM() */ ranum = ranum * 69069 + 1; cptr = (char*)&ranum; for (cnt = sizeof(ranum); cnt && sptr < zptr && number > 0; cnt--) *sptr++ = *cptr++; } ap_rwrite (buf, sptr - buf, req); if (req->connection->aborted) break; } } else if (flag == 'o') { while (number > 0) { zptr = (sptr = buf) + sizeof(buf)-1; while (sptr < zptr && number-- > 0) *sptr++ = (uchar)octet++; ap_rwrite (buf, sptr - buf, req); if (req->connection->aborted) break; } } else if (flag == 't') { while (number > 0) { zptr = (sptr = buf) + sizeof(buf)-1; while (sptr < zptr && number > 0) { for (cnt = ('z'-80+1); cnt <= 'z' && sptr < zptr && number-- > 0; cnt++) *sptr++ = (char)cnt; if (cnt == 'z'+1) *sptr++ = '\n'; } /* only complete lines */ while (sptr > buf && *(sptr-1) != '\n') { sptr--; number++; } *sptr = '\0'; ap_rputs (buf, req); if (req->connection->aborted) break; } } } static int cgiplustest_handler (request_rec *req) { int number = -1, query = 0; char stream = 0; char *cptr; /** should work but doesn't **/ // if (!req->handler || strcmp (req->handler, "cgiplustest")) { // return DECLINED; // } /** so use this alternative **/ if (!req->the_request || !strstr (req->the_request, "cgiplustest")) return DECLINED; if (req->the_request) { if (!strstr (req->the_request, "cgiplustest")) return DECLINED; if (cptr = strstr (req->the_request, "/stream/")) { /* using the equivalent syntax to WASD ResponseStream() */ cptr += 8; if (isalpha (*cptr)) stream = *cptr; else { stream = 't'; if (isdigit (*cptr)) number = atoi(cptr) * 1024; } while (*cptr && *cptr != ':') cptr++; if (*cptr) number = atoi(cptr+1) * 1024; else if (number < 0) number = INT_MAX; if (!(stream == 'b' || stream != 'o' || stream != 't')) number = -1; if (strchr (req->the_request, '?')) query = 1; } else if (cptr = strchr (req->the_request, '?')) number = atoi(cptr+1); } if (query) { ap_set_content_type (req, "text/plain"); ap_rprintf (req, "%s stream:%c number:%d\n", SOFTWAREID, stream, number); return OK; } if (number < 0) { ap_set_content_type (req, "text/plain"); ap_rprintf (req, "%s\n\ 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", SOFTWAREID); } else if (stream) cgiplustest_stream (req, stream, number); else cgiplustest_lines (req, number); return OK; } static void cgiplustest_register_hooks (apr_pool_t *pool) { fprintf (stdout, "\n ** cgiplustest_register_hooks **\n\n"); ap_hook_handler (cgiplustest_handler, NULL, NULL, APR_HOOK_LAST); } /* dispatch list for API hooks */ module AP_MODULE_DECLARE_DATA cgiplustest_module = { STANDARD20_MODULE_STUFF, NULL, /* create per-dir config structures */ NULL, /* merge per-dir config structures */ NULL, /* create per-server config structures */ NULL, /* merge per-server config structures */ NULL, /* table of config file commands */ cgiplustest_register_hooks /* register hooks */ }; #endif /*****************************************************************************/