/*****************************************************************************/ /* IPCtickler.c The CGI script Inter-Process Communication (IPC) tickler is designed to allow a script programmer to gain an appreciation of the way WASD interacts with VMS' record-oriented Input/Output (I/O) design, how the C Language Run-Time Library interprets U**x I/O conventions into this, how WASD attempts to accomodate both, how the mechanisms a script can use to explicitly convey exact requirements to WASD ... and finally, how these affect output (in particular the carriage-control) delivered to the client. Use http://the.host.name/cgi-bin/ipctickler to obtain an HTML form allowing control of several parameters into the script. COPYRIGHT --------- WASD VMS Hypertext Services, Copyright (C) 1996-2005 Mark G.Daniel. This package is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License, or any later version. This package is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. BUILD DETAILS ------------- $ @BUILD_ONE BUILD IPCTICKLER VERSION HISTORY --------------- 30-JAN-2007 MGD v1.2.0, modify for non-WASD but CGI compliant server (in this case to investigate Purveyor CGI) 30-AUG-2005 MGD v1.1.0, ctx=xplct (thanks JPP) 27-AUG-2005 MGD v1.0.0, initial development */ /*****************************************************************************/ #define SOFTWAREVN "1.2.0" #define SOFTWARENM "IPCTICKLER" #ifdef __ALPHA char SoftwareID [] = SOFTWARENM " AXP-" SOFTWAREVN; #endif #ifdef __ia64 char SoftwareID [] = SOFTWARENM " IA64-" SOFTWAREVN; #endif #ifdef __VAX char SoftwareID [] = SOFTWARENM " VAX-" SOFTWAREVN; #endif #define SS$_FISH 2928 #ifndef SETENV_FORM #define SETENV_FORM 0 #endif /* standard C header files */ #include #include #include #include #include /*****************************************************************************/ /* */ main () { static char fillch [] = "0123456789_abcdefghijklmnopqrstuvwxyz_ABCDEFGHIJKLMNOPQRSTUVWXYZ"; int hexch, total_chars, mrs, result, rec_size, use_fputs, use_fwrite_n1, use_fwrite_1n; char *bptr, *bufptr, *cptr, *ctxptr, *ctypeptr, *xplctptr, *modeptr, *mrsptr, *qsptr, *sptr, *zptr; char vname [256] = "WWW_FORM_", value [256]; /*********/ /* begin */ /*********/ mrsptr = getenv("WWW_GATEWAY_MRS"); if (mrsptr) mrs = atoi(mrsptr); else mrs = 0; qsptr = getenv("WWW_QUERY_STRING"); if (qsptr && !*qsptr) qsptr = NULL; if (!qsptr) { TicklerForm (mrs); exit (1); } if (!getenv("WWW_FORM_CHARS")) { #if SETENV_FORM #if __CRTL_VER >= 70000000 /* yup - only V7.0 and later */ /* no "FORM_" CGI environment variables, make some */ cptr = qsptr; while (*cptr) { sptr = vname + 9; while (*cptr && *cptr != '=') *sptr++ = toupper(*cptr++); if (!*cptr) exit (SS$_FISH); *sptr = '\0'; cptr++; sptr = value; while (*cptr && *cptr != '&') { if (*cptr == '%') { if (sscanf (cptr+1, "%2X", &hexch) != 1) exit (SS$_FISH); *sptr++ = (char)hexch; cptr += 3; } else *sptr++ = *cptr++; } *sptr = '\0'; if (*cptr) cptr++; setenv (vname, value, 1); } #endif /* __CRTL_VER >= 70000000 */ #endif /* SETENV_FORM */ if (!getenv("WWW_FORM_CHARS")) exit (SS$_FISH); } cptr = getenv("WWW_FORM_CHARS"); if (!cptr) cptr = "2048"; total_chars = atoi(cptr); cptr = getenv("WWW_FORM_SIZE"); if (!cptr) cptr = "0"; rec_size = atoi(cptr); cptr = getenv("WWW_FORM_CTX"); if (!cptr) cptr = ""; if (!strcmp (cptr, "rec")) ctxptr = "ctx=rec"; else if (!strcmp (cptr, "bin")) ctxptr = "ctx=bin"; else ctxptr = "ctx=rec"; cptr = getenv("WWW_FORM_XPLCT"); if (!cptr) cptr = ""; if (*cptr) xplctptr = "ctx=xplct"; else xplctptr = NULL; cptr = getenv("WWW_FORM_FUNC"); if (!cptr) cptr = ""; use_fputs = use_fwrite_n1 = use_fwrite_1n = 0; if (!strcmp (cptr, "fputs")) use_fputs = 1; else if (!strcmp (cptr, "fwrite_n1")) use_fwrite_n1 = 1; else if (!strcmp (cptr, "fwrite_1n")) use_fwrite_1n = 1; else use_fputs = 1; cptr = getenv("WWW_FORM_MODE"); if (!cptr) cptr = ""; if (!strcmp (cptr, "x-record-mode")) modeptr = "Script-Control: X-record-mode\n"; else if (!strcmp (cptr, "x-stream-mode")) modeptr = "Script-Control: X-stream-mode\n"; else modeptr = ""; cptr = getenv("WWW_FORM_BUFFER"); if (!cptr) cptr = ""; if (!strcmp (cptr, "x-buffer-records")) bufptr = "Script-Control: X-buffer-records\n"; else bufptr = ""; ctypeptr = getenv("WWW_FORM_CTYPE"); if (!ctypeptr) ctypeptr = "text/plain"; /* make it obvious for an observer by tuning off transfer optimisations */ fprintf (stdout, "Content-Type: %s\n\ Script-Control: X-content-encoding-gzip=0\n\ Script-Control: X-transfer-encoding-chunked=0\n\ %s%s\n", ctypeptr, modeptr, bufptr); if (xplctptr) if (!(stdout = freopen ("SYS$OUTPUT:", "w", stdout, ctxptr, xplctptr))) exit (vaxc$errno); else if (!(stdout = freopen ("SYS$OUTPUT:", "w", stdout, ctxptr))) exit (vaxc$errno); fprintf (stdout, "mailbox mrs: %d\nrecord size: %d\ntotal chars: %d\n\ fopen(%s%s%s)\n%s%s%s\n%s%s", mrs, rec_size, total_chars, ctxptr, xplctptr ? "," : "", xplctptr ? xplctptr : "", use_fputs ? "fputs()" : "", use_fwrite_n1 ? "fwrite(n,1)" : "", use_fwrite_1n ? "fwrite(1,n)" : "", modeptr, bufptr); fflush (stdout); if (!rec_size) rec_size = sizeof(fillch); bptr = sptr = calloc (1, total_chars+2); if (!bptr) exit (vaxc$errno); zptr = sptr + total_chars; while (sptr < zptr) { if (!*cptr) cptr = fillch; if (!((sptr - bptr) % rec_size)) { *sptr++ = '\n'; *sptr++ = '*'; cptr = fillch; } *sptr++ = *cptr++; } *sptr = '\n'; *sptr = '\0'; if (use_fputs) { result = fputs (bptr, stdout); if (result >= 0) result = total_chars; } else if (use_fwrite_n1) { result = fwrite (bptr, total_chars, 1, stdout); result = result * total_chars; } else result = fwrite (bptr, 1, total_chars, stdout); fflush (stdout); if (!strcmp (modeptr, "Script-Control: X-stream-mode\n")) fputs ("\n", stdout); if (result >= 0) fprintf (stdout, "\nOUTPUT: %d chars\n", result); else fprintf (stdout, "+++ OUTPUT FAILED +++\n"); } /*****************************************************************************/ /* */ TicklerForm (int mrs) { char *CgiScriptNamePtr; /*********/ /* begin */ /*********/ CgiScriptNamePtr = getenv ("WWW_SCRIPT_NAME"); if (!CgiScriptNamePtr) exit (SS$_FISH); fprintf (stdout, "Content-Type: text/html\n\ \n\ \n\ \n\ %s\n\ \n\ \n\
\n\ \n\ \n\ \n\ \ \n\ \n\ \n\ \n\ \n\ \n\ \ \n\ \n\ \ \n\ \n\ \n\
CGI Script IPC Tickler
mailbox MRS: %d
record size: \ \
total chars: \ \
fopen() ctx= \ rec\ \ bin\
\ xplct\
function: \ fputs()\ \ fwrite(n,1)\ \ fwrite(1,n)\
script-control: \ X-record-mode\ \ X-stream-mode\ \ (none)\
\ X-buffer-records\
content-type:\ \ text/plain\ \ \ application/octet-stream\
\    \ \
\n\ \n\ \n\
\n\ The CGI script Inter-Process Communication (IPC) tickler is designed to \ allow a script programmer to gain an appreciation of the way WASD interacts \ with VMS\' record-oriented Input/Output (I/O) design, how the C Language \ Run-Time Library interprets U**x I/O conventions into this, how WASD \ attempts to accomodate both, how the mechanisms a script can use to \ explicitly convey exact requirements to WASD ... and finally, how these \ affect output (in particular the carriage-control) delivered to the client.\n\

Check the WASD Scripting document \ for information on the handling of \ Script Output in \ relation to "text/.." and non-"text/.." content-type.\n\ Use this utility to manipulate the record size (number of characters between \ newlines) and total characters output against stream mode and C-RTL output \ function, to observe how (implied) carriage-control is provided to the \ client.\n\ WASD CGI response fields can be added to manipulate the desired programming \ requirement and outcome.\n\

Use the \ WATCH facility \ with CGI, DCL and Network Activity/Data items to \ directly observe the octets provided by the script and subsequently provided \ to the client.\n\

\n\ \n\ \n", SoftwareID, CgiScriptNamePtr, mrs, mrs/2); } /*****************************************************************************/