    <rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:admin="http://webns.net/mvcb/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:content="http://purl.org/rss/1.0/modules/content/">
     <channel>
        <title>ACCU  :: Common Gateway Interface Program Testing</title>
        <link>https://members.accu.org/index.php/articles/736</link>
        <description>Professionalism in Programming</description>
        <dc:language>en-us</dc:language> 
        <dc:creator>Administrator</dc:creator> 
        <admin:generatorAgent rdf:resource="http://www.xaraya.org" /> 
        <admin:errorReportsTo rdf:resource="mailto:webeditor@accu.org" />
       <sy:updatePeriod>hourly</sy:updatePeriod>
       <sy:updateFrequency>1</sy:updateFrequency>
       <docs>http://backend.userland.com/rss</docs>




<div class="xar-mod-head"><span class="xar-mod-title">Internet Topics + CVu Journal Vol 10, #6 - Sep 1998</span></div>

<table border="0" cellpadding="1" cellspacing="0">
    <tbody>
    <tr>
        <td valign="top">
            Browse in :
       </td>
       <td valign="top">

                                            <a href="https://members.accu.org/index.php/articles/">All</a>

                     &gt;                         <a href="https://members.accu.org/index.php/articles/c13/">Topics</a>

                     &gt;                         <a href="https://members.accu.org/index.php/articles/c69/">Internet</a>
<br />

                                            <a href="https://members.accu.org/index.php/articles/">All</a>

                     &gt;                         <a href="https://members.accu.org/index.php/articles/c76/">Journals</a>

                     &gt;                         <a href="https://members.accu.org/index.php/articles/c77/">CVu</a>

                     &gt;                         <a href="https://members.accu.org/index.php/articles/c135/">106</a>
<br />

                                            <a href="https://members.accu.org/index.php/articles/c69-135/">Any of these categories</a>

                    -                        <a href="https://members.accu.org/index.php/articles/c69+135/">All of these categories</a>
<br />
</td>
   </tr>
   </tbody>
</table>




<div class="xar-error">
   <p>
 <strong>Note:</strong> when you create a new publication type,
the articles module will automatically use the templates
<em>user-display-[publicationtype].xt</em>
and <em>user-summary-[publicationtype].xt</em>.
If those templates do not exist when you try to preview or display a new article,
you'll get this warning :-)  Please place your own templates in themes/<em>yourtheme</em>/modules/articles . The templates will get the extension .xt there. </p>
</div>
<div class="xar-norm xar-standard-box-padding">
   <h1><strong>Title:</strong>&nbsp;Common Gateway Interface Program Testing</h1>
<p><strong>Author:</strong>&nbsp;</p>
<p>
<strong>Date:</strong> 03 September 1998 13:15:27 +01:00 or Thu, 03 September 1998 13:15:27 +01:00</p>
<p><strong>Summary:</strong>&nbsp;</p>
<p><strong>Body:</strong>&nbsp;<div class="section" lang="en">
<div class="titlepage">
<h2><a name="d0e18" id="d0e18"></a></h2>
</div>
<p>In the last few months I've found myself writing a lot of CGI
programs for a corporate intranet. For a number of reasons that
aren't germane to this article, I have to work on a DOS/Windows
development system, with the final implementation being on an NT
machine. The CGI programs are in C. If I actually get to finish the
work on time I may have more to say about the delights of this
undertaking.</p>
<p>In order to check my CGI programs before moving them onto the
server I wanted to simulate the GET transfer protocol. As anyone
with some DOS experience will attest, the command interpreter and
environment string handling is, well, basic. One of the things you
cannot do is incorporate '=' in an environ-ment string, which is
necessary for a GET transfer.</p>
<p>A half-remembered item in the compiler manual sent me hunting,
and I finally spied the <tt class="function">spawn()</tt> function
family, with the option to pass a custom environ-ment to the child
process. Not, I agree, a portable function, but then this isn't a
universal problem!</p>
<p>The upshot was the program <span class=
"application">RunGET2</span> (yes, there was a '1'...RIP), which
takes a file containing the desired environment key-text pairs and
the name of the program to test as arguments. The resulting output
to <tt class="classname">stdout</tt> may be captured and inspected
or viewed in a web browser.</p>
<p>It's a cheap and cheerful solution to a common problem, and, I
expect, the most re-invented of the CGI 'wheels'. The source and an
example environment file are available.</p>
<pre class="programlisting">
/* module title  : RunGET2.c
 * problems      : spawnlpe() may not be available on all systems.
 *                 It doesn't do POST transfers. But a good CGI library should handle either transaparently.
 * description   : Provides a simulated 'GET' environment for a World Wide
 *                 Web Common Gateway Interface program.
 *                 Primarily for systems such as DOS/Windows where environment support is inflexible.
 *                 Requires a definition file containing the environment to be used.   */
#include &lt;stdio.h&gt;
#include &lt;string.h&gt;
#include &lt;stdlib.h&gt;
#include &lt;process.h&gt;  /* for spawn function */
/* These values may need to be tuned. Buffersize should reflect the web  server CGI limit.  */
enum {Envsize = 200, Buffersize = 1024};
static char *envp[Envsize];             /* Why static? For something as small */
static int envcount = 0;                /* as this, why not?                  */
int load_env(const char *filename) {
  FILE *fp;
  char buffer[Buffersize];
  int result = 0;
  fp = fopen(filename, &quot;rt&quot;);
  if(NULL != fp) {
    int i;
    fgets(buffer, Buffersize - 1, fp);
    *strrchr(buffer, '\n') = '\0';
    while(!feof(fp) &amp;&amp; envcount &lt; Envsize - 3)  {
      envp[envcount] = strdup(buffer);
      envcount++;
      fgets(buffer, Buffersize - 1, fp);
      *strrchr(buffer, '\n') = '\0';
    }
/*  the program calculates the length of the query. Like a true web server the length is limited. */
    for(i = 0; i &lt; envcount; i++) {
      if(strncmp(envp[i], &quot;QUERYSTRING=&quot;, 12) == 0)  {
        char *ptr = strchr(envp[i], '=') + 1;
        int l;
        l = strlen(ptr);
        sprintf(buffer, &quot;CONTENT_LENGTH=%d&quot;, l);
        envp[envcount++] = strdup(buffer);
        break;
      }
    }
    envp[envcount] = NULL;
    fclose(fp);
    result = 1;
  }
  else result = 0;
  return(result);
}
int main(int argc, char **argv) {
  int return_status = 0;
  if(argc == 3)  {
    if(!load_env(*(argv + 1))) {
      fprintf(stderr, &quot;Fault loading environment data from %s\n&quot;, *(argv + 1));
      return_status = 1;
    }
    else {
      int result;
      char *program = *(argv + 2);
      char *path_info;
      fprintf(stderr, &quot;Executing CGI program '%s'in GET environment\n&quot;, *(argv + 2));
/* Hook to handle extra 'path' information. Need to split it from the program name and put into environment. Easier to put it into the environment definition file!                                  */
      if(NULL != (path_info = strchr(*(argv + 2), '/'))) {
        fprintf(stderr, &quot;PATH_INFO=%s\n&quot;, path_info);
      }
/* Run our CGI program with the custom  environment. If you use an interpreted CGI program you will need an argument added to the list. */
      result = spawnlpe(P_WAIT, program, program, NULL, envp);
      if(-1 == result) {
        fprintf(stderr, &quot;Unable to execute\n&quot;);
      }
      else fprintf(stderr, &quot;CGI program completed\n&quot;);
      while(--envcount &gt;= 0) {
        if(NULL != envp[envcount]) free(envp[envcount]);
      }
    }
  }
  else {
    fprintf(stderr, &quot;RunGET2\nProgram to simulate a CGI GET environment\n&quot;);
    fprintf(stderr, &quot;Graham patterson 6th August 1998\n&quot;);
    fprintf(stderr, &quot;RunGET2 &lt;environment&gt; &lt;cgi program&gt;\n&quot;);
    return_status = 1;
  }
  return return_status;
} 
</pre>
<p class="c2"><span class="remark">Graham's code is on the disk. I
made a few layout changes to get it to fit. Francis</span></p>
</div>
</p>
<p><strong>Notes:</strong>&nbsp;</p>
<p><em>More fields may be available via dynamicdata ..</em></p>
</div>
</channel>
</rss>
