/*****************************************************************************/
/*
                               CGIcallout.c


Very simple, "standard" CGI script illustrating the use of callouts.

Also see CGICALLOUTPROC.COM which is a similar example in DCL.

Remember, the behaviour of these scripts can be WATCHed to gain further insight
into how this is implemented.


BUILD DETAILS
-------------
See BUILD_ONE.COM procedure.

  $ @BUILD_ONE BUILD CGICALLOUT
  $ @BUILD_ONE LINK CGICALLOUT


COPYRIGHT
---------
Copyright (C) 1999-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
---------------
06-SEP-1999  MGD  v1.0.0, initial development
*/

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

/* standard C header files */
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

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

main ()
       
{
   int  status;
   char  *CgiPlusEscPtr,
         *CgiPlusEotPtr,
         *CgiPathInfoPtr,
         *FileNamePtr;
   char  CalloutResponse [256];
   FILE  *CgiPlusIn;

   /*********/
   /* begin */
   /*********/

   /* get the callout escape sequences */
   CgiPlusEscPtr = getenv ("CGIPLUSESC");
   CgiPlusEotPtr = getenv ("CGIPLUSEOT");
   if (CgiPlusEscPtr == NULL || CgiPlusEotPtr == NULL)
   {
      puts ("Error: callout environment not detected!\n");
      exit (1);
   }
   /* open the stream that provides the server callout response */
   if ((CgiPlusIn = fopen ("CGIPLUSIN:", "r")) == NULL)
   {
      status = vaxc$errno;
      puts ("Error: opening CGIPLUSIN stream!\n");
      exit (status);
   }

   /***************/
   /* page output */
   /***************/

   /* "standard" CGI response header (plus start of page) */
   puts (
"Content-Type: text/plain\n\
\n\
CGI variable symbols:\n");

   /* just show the CGI variables (DCL symbols) */
   system ("SHOW SYMBOL WWW_*");

   CgiPathInfoPtr = getenv ("WWW_PATH_INFO");
   if (CgiPathInfoPtr == NULL) CgiPathInfoPtr = "";

   printf (
"\n\
\n\
Map path \"%s\"%s to a file specification.\n\
\n\
  This will be done using a callout of \"MAP-PATH: %s\"\n\
\n",
      CgiPathInfoPtr,
      CgiPathInfoPtr[0] ? "" : " (empty path, will be an error)",
      CgiPathInfoPtr);

   /****************************************************/
   /* here's the actual callout (expanded for clarity) */
   /****************************************************/

   /* first, the "escape" sequence record */
   printf ("%s\n", CgiPlusEscPtr);

   /* next, write the callout request to the server */
   fprintf (stdout, "MAP-PATH: %s\n", CgiPathInfoPtr);

   /* last, the "end-of-text" sequence record */
   printf ("%s\n", CgiPlusEotPtr);

   /* read the callout response sent by the server */
   fgets (CalloutResponse, sizeof(CalloutResponse), CgiPlusIn);
   /* just trim the trailing newline from the response record */
   *(strchr (CalloutResponse, '\n')) = '\0';

   /***************/
   /* page output */
   /***************/

   printf (
"  The server responded with: \"%s\"\n\
\n\
  %c%c%c is a %s code, hence the %s is \"%s\"\n",
      CalloutResponse,
      CalloutResponse[0], CalloutResponse[1], CalloutResponse[2],
      CalloutResponse[0] == '2' ? "success" : "error",
      CalloutResponse[0] == '2' ? "file specification" : "error message",
      CalloutResponse+4);

   if (CalloutResponse[0] == '2')
   {
      FileNamePtr = CalloutResponse + 4;
      printf (
"\n\
\n\
Now map this file specification back to a path.\n\
\n\
  This will be done using a callout of \"MAP-FILE: %s\"\n\
\n",
         FileNamePtr);

      /*************************************************/
      /* here's the second callout (more concise form) */
      /*************************************************/

      /* this works with record-oriented <stdout> (the default) */ 
      printf ("%s\n%s: %s\n%s\n",
              CgiPlusEscPtr,
              "MAP-FILE", FileNamePtr,
              CgiPlusEotPtr);

      fgets (CalloutResponse, sizeof(CalloutResponse), CgiPlusIn);
      /* just trim the trailing newline from the record */
      *(strchr (CalloutResponse, '\n')) = '\0';

      /***************/
      /* page output */
      /***************/

      printf (
"  The server responded with: \"%s\"\n\
\n\
  %c%c%c is a %s code, hence the %s is \"%s\"\n\
\n",
         CalloutResponse,
         CalloutResponse[0], CalloutResponse[1], CalloutResponse[2],
         CalloutResponse[0] == '2' ? "success" : "error",
         CalloutResponse[0] == '2' ? "path" : "error message",
         CalloutResponse+4);
   }
   else
   {
      printf (
"\n\
\n\
As an error occured in the first callout, the second, to map it back to a\n\
path, will not be done.  \
Append a path to the script URL and see what happens!\n");
   }

   /***************************************/
   /* explicit records for binary streams */
   /***************************************/

   /*
      Callouts may still be used even if the output stream has
      been made binary (not record-oriented, in C a "ctx=bin").
      Explicit fflush()es are required to provide the "records".
      (note: this may be WATCHed but produces no page output!)
   */

   fflush (stdout);
   puts (CgiPlusEscPtr);
   fflush (stdout);

   puts ("NOOP:");
   fflush (stdout);

   puts (CgiPlusEotPtr);
   fflush (stdout);

   fgets (CalloutResponse, sizeof(CalloutResponse), CgiPlusIn);
}

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

