[0001]
[0002]
[0003]
[0004]
[0005]
[0006]
[0007]
[0008]
[0009]
[0010]
[0011]
[0012]
[0013]
[0014]
[0015]
[0016]
[0017]
[0018]
[0019]
[0020]
[0021]
[0022]
[0023]
[0024]
[0025]
[0026]
[0027]
[0028]
[0029]
[0030]
[0031]
[0032]
[0033]
[0034]
[0035]
[0036]
[0037]
[0038]
[0039]
[0040]
[0041]
[0042]
[0043]
[0044]
[0045]
[0046]
[0047]
[0048]
[0049]
[0050]
[0051]
[0052]
[0053]
[0054]
[0055]
[0056]
[0057]
[0058]
[0059]
[0060]
[0061]
[0062]
[0063]
[0064]
[0065]
[0066]
[0067]
[0068]
[0069]
[0070]
[0071]
[0072]
[0073]
[0074]
[0075]
[0076]
[0077]
[0078]
[0079]
[0080]
[0081]
[0082]
[0083]
[0084]
[0085]
[0086]
[0087]
[0088]
[0089]
[0090]
[0091]
[0092]
[0093]
[0094]
[0095]
[0096]
[0097]
[0098]
[0099]
[0100]
[0101]
[0102]
[0103]
[0104]
[0105]
[0106]
[0107]
[0108]
[0109]
[0110]
[0111]
[0112]
[0113]
[0114]
[0115]
[0116]
[0117]
[0118]
[0119]
[0120]
[0121]
[0122]
[0123]
[0124]
[0125]
[0126]
[0127]
[0128]
[0129]
[0130]
[0131]
[0132]
[0133]
[0134]
[0135]
[0136]
[0137]
[0138]
[0139]
[0140]
[0141]
[0142]
[0143]
[0144]
[0145]
[0146]
[0147]
[0148]
[0149]
[0150]
[0151]
[0152]
[0153]
[0154]
[0155]
[0156]
[0157]
[0158]
[0159]
[0160]
[0161]
[0162]
[0163]
[0164]
[0165]
[0166]
[0167]
[0168]
[0169]
[0170]
[0171]
[0172]
[0173]
[0174]
[0175]
[0176]
[0177]
[0178]
[0179]
[0180]
[0181]
[0182]
[0183]
[0184]
[0185]
[0186]
[0187]
[0188]
[0189]
[0190]
[0191]
[0192]
[0193]
[0194]
[0195]
[0196]
[0197]
[0198]
[0199]
[0200]
[0201]
[0202]
[0203]
[0204]
[0205]
[0206]
[0207]
[0208]
[0209]
[0210]
[0211]
[0212]
[0213]
[0214]
[0215]
[0216]
[0217]
[0218]
[0219]
[0220]
[0221]
[0222]
[0223]
[0224]
[0225]
[0226]
[0227]
[0228]
[0229]
[0230]
[0231]
[0232]
[0233]
[0234]
[0235]
[0236]
[0237]
[0238]
[0239]
[0240]
[0241]
[0242]
[0243]
[0244]
[0245]
[0246]
[0247]
[0248]
[0249]
[0250]
[0251]
[0252]
[0253]
[0254]
[0255]
[0256]
[0257]
[0258]
[0259]
[0260]
[0261]
[0262]
[0263]
[0264]
[0265]
[0266]
[0267]
[0268]
[0269]
[0270]
[0271]
[0272]
[0273]
[0274]
[0275]
[0276]
[0277]
[0278]
[0279]
[0280]
[0281]
[0282]
[0283]
[0284]
[0285]
[0286]
[0287]
[0288]
[0289]
[0290]
[0291]
[0292]
[0293]
[0294]
[0295]
[0296]
[0297]
[0298]
[0299]
[0300]
[0301]
[0302]
[0303]
[0304]
[0305]
[0306]
[0307]
[0308]
[0309]
[0310]
[0311]
[0312]
[0313]
[0314]
[0315]
[0316]
[0317]
[0318]
[0319]
[0320]
[0321]
[0322]
[0323]
[0324]
[0325]
[0326]
[0327]
[0328]
[0329]
[0330]
[0331]
[0332]
[0333]
[0334]
[0335]
[0336]
[0337]
[0338]
[0339]
[0340]
[0341]
[0342]
[0343]
[0344]
[0345]
[0346]
[0347]
[0348]
[0349]
[0350]
[0351]
[0352]
[0353]
[0354]
[0355]
[0356]
[0357]
[0358]
[0359]
[0360]
[0361]
[0362]
[0363]
[0364]
[0365]
[0366]
[0367]
[0368]
[0369]
[0370]
[0371]
[0372]
[0373]
[0374]
[0375]
[0376]
[0377]
[0378]
[0379]
[0380]
[0381]
[0382]
[0383]
[0384]
[0385]
[0386]
[0387]
[0388]
[0389]
[0390]
[0391]
[0392]
[0393]
[0394]
[0395]
[0396]
[0397]
[0398]
[0399]
[0400]
[0401]
[0402]
[0403]
[0404]
[0405]
[0406]
[0407]
[0408]
[0409]
[0410]
[0411]
[0412]
[0413]
[0414]
[0415]
[0416]
[0417]
[0418]
[0419]
[0420]
[0421]
[0422]
[0423]
[0424]
[0425]
[0426]
[0427]
[0428]
[0429]
/*****************************************************************************/
/*
                              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?<integer>
WASD CGIplus     http://the.host.name/cgiplus-bin/cgiplustest?<integer> 
Apache module    http://the.host.name/cgiplustest?<integer>

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.


COPYRIGHT
---------
Copyright (C) 1997-2021 Mark G.Daniel

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.


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
#ifdef __x86_64
#  define SOFTWAREID SOFTWARENM " X86-" SOFTWAREVN
#endif

/* standard C headers */
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <errno.h>

#include <cgilib.h>

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_<arch>]MOD_CGIPLUSTEST.EXE APACHE$COMMON:[MODULES]

Activate it in Apache's httpd.conf file:

   # httpd.conf
   LoadModule cgiplustest_module modules/mod_cgiplustest.so
   <Location /cgiplustest>
      SetHandler cgiplustest
   </Location>

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

/*****************************************************************************/