/*****************************************************************************/ /* 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 --------- Copyright (C) 2005-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. 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 #ifdef __x86_64 char SoftwareID [] = SOFTWARENM " X86-" SOFTWAREVN; #endif #define SS$_FISH 2928 #ifndef SETENV_FORM #define SETENV_FORM 0 #endif /* standard C header files */ #include #include #include #include #include int TicklerForm (int); /*****************************************************************************/ /* */ 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); } /*****************************************************************************/