/*****************************************************************************/ /* CgiLib_example.c Simple example showing the essential elements of using the CGILIB routines. Demonstrates: * initializing the environment * alternate processing according to the environment * getting CGI variables * generating responses * processing POSTed requests Remember, the behaviours of these scripts are WATCHable. The $COUNT and $SLEEP logical names were added to allow testing of server behaviour where a CGIplus script, programmed to exit elegantly after processing a given number of requests, revealed a timing issue that, depending on the run-down speed of the script, could result in an HTTP 502 status rather than transparent reactivation as described in the April 1998 note in the [SRC.HTTPD]DCL.C module. This script used from the CGILIB_EXAMPLE.HTML document was a convenient tool to test the server fix using both GET and POST requests. LOGICAL NAMES ------------- CGILIB_EXAMPLE$COUNT an integer for exit() after this many CGIplus requests CGILIB_EXAMPLE$DBUG turns on all "if (Debug)" statements CGILIB_EXAMPLE$SLEEP an integer to sleep this many seconds before exiting BUILD DETAILS ------------- $ @BUILD_ONE BUILD CGILIB_EXAMPLE $ @BUILD_ONE LINK CGILIB_EXAMPLE COPYRIGHT --------- Copyright (C) 1999-2005 Mark G.Daniel This program, comes with ABSOLUTELY NO WARRANTY. This is free software, and you are welcome to redistribute it under the conditions of the GNU GENERAL PUBLIC LICENSE, version 2. VERSION HISTORY --------------- 15-OCT-2005 MGD v1.2.1, CGILIB_EXAMPLE$COUNT and CGILIB_EXAMPLE$SLEEP 28-OCT-2000 MGD v1.2.0, use CGILIB object module 12-APR-2000 MGD v1.1.1, minor changes for CGILIB 1.4 (Apache) 24-SEP-1999 MGD v1.0.0, initial development */ /*****************************************************************************/ /* standard C header files */ #include #include #include #include #include /* application related header file */ #include /* global storage */ int CgiPlusCount, CgiPlusSleep, CgiPlusUsage, Debug, IsCgiPlus; char *CgiContentTypePtr, *CgiQueryStringPtr, *CgiRequestMethodPtr; /*****************************************************************************/ /* */ main (int argc, char* argv[]) { char *cptr; /*********/ /* begin */ /*********/ if (Debug = (getenv ("CGILIB_EXAMPLE$DBUG") != NULL)) { CgiLibEnvironmentSetDebug (Debug); fprintf (stdout, "Content-Type: text/plain\r\n\r\n"); } if (cptr = getenv ("CGILIB_EXAMPLE$COUNT")) { CgiPlusCount = atoi(cptr); if (cptr = getenv ("CGILIB_EXAMPLE$SLEEP")) CgiPlusSleep = atoi(cptr); else CgiPlusSleep = 1; } CgiLibEnvironmentInit (argc, argv, 0); IsCgiPlus = CgiLibEnvironmentIsCgiPlus (); if (IsCgiPlus) { for (;;) { /* block waiting for the next request */ CgiLibVar (""); ProcessRequest (); CgiLibCgiPlusEOF (); if (CgiPlusCount) { CgiPlusCount--; if (!CgiPlusCount) { if (CgiPlusSleep) sleep (CgiPlusSleep); exit (1); } } } } else ProcessRequest (); } /*****************************************************************************/ /* */ ProcessRequest () { int Context; char *VariablePtr; /*********/ /* begin */ /*********/ if (Debug) fprintf (stdout, "ProcessRequest()\n"); CgiRequestMethodPtr = CgiLibVar ("WWW_REQUEST_METHOD"); if (CgiLibEnvironmentIsWasd()) { /* need this to be record-oriented for the DCL output records */ CgiLibEnvironmentRecordOut (); } /* generate an HTTP header, plain-text content-type */ CgiLibResponseHeader (200, "text/plain"); fprintf (stdout, "Current environment is \"%s\" (%s)\n\n", CgiLibEnvironmentName(), CGILIB_SOFTWAREID); if (CgiLibEnvironmentIsCgiPlus()) fprintf (stdout, "Usage count is %d.\n\n", ++CgiPlusUsage); if (CgiLibEnvironmentIsWasd() || CgiLibEnvironmentIsApache()) { fprintf (stdout, "These are the CGI variables contained in the subprocess' DCL symbols:\n\n"); /* with standard CGI the variables are all in DCL symbols */ system ("SHOW SYMBOL WWW_*"); } if (!strcmp (CgiRequestMethodPtr, "POST")) ProcessPost (); else if (CgiLibEnvironmentIsCgiPlus() || CgiLibEnvironmentIsOsu()) { fprintf (stdout, "These are the CGI variables created from the %s:\n\n", CgiLibEnvironmentIsCgiPlus() ? "CGIPLUSIN stream" : "OSU dialog phase"); while ((VariablePtr = CgiLibVarNull ("*")) != NULL) fprintf (stdout, " %s\n", VariablePtr); } CgiQueryStringPtr = CgiLibVar ("WWW_QUERY_STRING"); if (strchr (CgiQueryStringPtr, '=') != NULL) { fprintf (stdout, "\nHere are the form elements of QUERY_STRING via CgiLibFormEncodedParse():\n\n"); Context = 0; while ((VariablePtr = CgiLibFormEncodedParse (CgiQueryStringPtr, &Context)) != NULL) fprintf (stdout, " %s\n", VariablePtr); } } /*****************************************************************************/ /* */ ProcessPost () { int Context, PostBufferCount; char *VariablePtr, *PostBufferPtr; /*********/ /* begin */ /*********/ if (Debug) fprintf (stdout, "ProcessPost()\n"); /* read the POSTed request body */ CgiLibReadRequestBody (&PostBufferPtr, &PostBufferCount); if (PostBufferPtr == NULL || PostBufferCount == 0) { CgiLibResponseError (__FILE__, __LINE__, 0, "No body in the POST!"); return; } CgiContentTypePtr = CgiLibVar ("WWW_CONTENT_TYPE"); if (!strcmp (CgiContentTypePtr, "application/x-www-form-urlencoded")) { /* is URL form encoded, turn that into pseudo CGI variables */ CgiLibFormRequestBody (PostBufferPtr, PostBufferCount); fprintf (stdout, "Request was via a POSTed form.\n\n\ Here are the form elements converted to pseudo CGI variables:\n\n"); if (CgiLibEnvironmentIsCgiPlus()) fprintf (stdout, "(via CGIplus, so you'll also see the CGI environment variables)\n"); else if (CgiLibEnvironmentIsOsu()) fprintf (stdout, "(via OSU, so you'll also see the CGI environment variables)\n\n"); while ((VariablePtr = CgiLibVarNull ("*")) != NULL) fprintf (stdout, " %s\n", VariablePtr); fprintf (stdout, "\nHere are the form elements via CgiLibFormEncodedParse():\n\n"); Context = 0; while ((VariablePtr = CgiLibFormEncodedParse (PostBufferPtr, &Context)) != NULL) fprintf (stdout, " %s\n", VariablePtr); free (PostBufferPtr); } else { /* we'll just assume it's a body of displayable text */ CgiLibResponseHeader (200, "text/plain"); fputs (PostBufferPtr, stdout); free (PostBufferPtr); } } /*****************************************************************************/