[0001] [0002] [0003] [0004] [0005] [0006] [0007] [0008] [0009] [0010] [0011] [0012] [0013] [0014] [0015] [0016] [0017] [0018] [0019] [0020] [0021] [0022] [0023] [0024] [0025] [0026] [0027] [0028] [0029] [0030] [0031] [0032] [0033] [0034] [0035] [0036] [0037] [0038] [0039] [0040] [0041] [0042] [0043] [0044] [0045] [0046] [0047] [0048] [0049] [0050] [0051] [0052] [0053] [0054] [0055] [0056] [0057] [0058] [0059] [0060] [0061] [0062] [0063] [0064] [0065] [0066] [0067] [0068] [0069] [0070] [0071] [0072] [0073] [0074] [0075] [0076] [0077] [0078] [0079] [0080] [0081] [0082] [0083] [0084] [0085] [0086] [0087] [0088] [0089] [0090] [0091] [0092] [0093] [0094] [0095] [0096] [0097] [0098] [0099] [0100] [0101] [0102] [0103] [0104] [0105] [0106] [0107] [0108] [0109] [0110] [0111] [0112] [0113] [0114] [0115] [0116] [0117] [0118] [0119] [0120] [0121] [0122] [0123] [0124] [0125] [0126] [0127] [0128] [0129] [0130] [0131] [0132] [0133] [0134] [0135] [0136] [0137] [0138] [0139] [0140] [0141] [0142] [0143] [0144] [0145] [0146] [0147] [0148] [0149] [0150] [0151] [0152] [0153] [0154] [0155] [0156] [0157] [0158] [0159] [0160] [0161] [0162] [0163] [0164] [0165] [0166] [0167] [0168] [0169] [0170] [0171] [0172] [0173] [0174] [0175] [0176] [0177] [0178] [0179] [0180] [0181] [0182] [0183] [0184] [0185] [0186] [0187] [0188] [0189] [0190] [0191] [0192] [0193] [0194] [0195] [0196] [0197] [0198] [0199] [0200] [0201] [0202] [0203] [0204] [0205] [0206] [0207] [0208] [0209] [0210] [0211] [0212] [0213] [0214] [0215] [0216] [0217] [0218] [0219] [0220] [0221] [0222] [0223] [0224] [0225] [0226] [0227] [0228] [0229] [0230] [0231] [0232] [0233] [0234] [0235] [0236] [0237] [0238] [0239] [0240] [0241] [0242] [0243] [0244] [0245] [0246] [0247] [0248] [0249] [0250] [0251] [0252] [0253] [0254] [0255] [0256] [0257] [0258] [0259] [0260] [0261] [0262] [0263] [0264] [0265] [0266] [0267] [0268] [0269] [0270] [0271] [0272] [0273] [0274] [0275] [0276] [0277] [0278] [0279] [0280] [0281] [0282] [0283] [0284] [0285] [0286] [0287] [0288] [0289] [0290] [0291] [0292] [0293] [0294] [0295] [0296] [0297] [0298] [0299] [0300] [0301] [0302] [0303] [0304] [0305] [0306] [0307] [0308] [0309] [0310] [0311] [0312] [0313] [0314] [0315] [0316] [0317] [0318] [0319] [0320] [0321] [0322] [0323] [0324] [0325] [0326] [0327] [0328] [0329] [0330] [0331] [0332] [0333] [0334] [0335] [0336] [0337] [0338] [0339] [0340] [0341] [0342] [0343] [0344] [0345] [0346] [0347] [0348] [0349] [0350] [0351] [0352] [0353] [0354] [0355] [0356] [0357] [0358] [0359] [0360] [0361] [0362] [0363] [0364] [0365] [0366] [0367] [0368] [0369] [0370] [0371] [0372] [0373] [0374] [0375] [0376] [0377] [0378] [0379] [0380] [0381] [0382] [0383] [0384] [0385] [0386] [0387] [0388] [0389] [0390] [0391] [0392] [0393] [0394] [0395] [0396] [0397] [0398] [0399] [0400] [0401] [0402] [0403] [0404] [0405] [0406] [0407] [0408] [0409] [0410] [0411] [0412] [0413] [0414] [0415] [0416] [0417] [0418] [0419] [0420] [0421] [0422] [0423] [0424] [0425] [0426] [0427] [0428] [0429] [0430] [0431] [0432] [0433] [0434] [0435] [0436] [0437] [0438] [0439] [0440] [0441] [0442] [0443] [0444] [0445] [0446] [0447] [0448] [0449] [0450] [0451] [0452] [0453] [0454] [0455] [0456] [0457] [0458] [0459] [0460] [0461] [0462] [0463] [0464] [0465] [0466] [0467] [0468] [0469] [0470] [0471] [0472] [0473] [0474] [0475] [0476] [0477] [0478] [0479] [0480] [0481] [0482] [0483] [0484] [0485] [0486] [0487] [0488] [0489] [0490] [0491] [0492] [0493] [0494] [0495] [0496] [0497] [0498] [0499] [0500] [0501] [0502] [0503] [0504] [0505] [0506] [0507] [0508] [0509] [0510] [0511] [0512] [0513] [0514] [0515] [0516] [0517] [0518] [0519] [0520] [0521] [0522] [0523] [0524] [0525] [0526] [0527] [0528] [0529] [0530] [0531] [0532] [0533] [0534] [0535] [0536] [0537] [0538] [0539] [0540] [0541] [0542] [0543] [0544] [0545] [0546] [0547] [0548] [0549] [0550] [0551] [0552] [0553] [0554] [0555] [0556] [0557] [0558] [0559] [0560] [0561] [0562] [0563] [0564] [0565] [0566] [0567] [0568] [0569] [0570] [0571] [0572] [0573] [0574] [0575] [0576] [0577] [0578] [0579] [0580] [0581] [0582] [0583] [0584] [0585] [0586] [0587] [0588] [0589] [0590] [0591] [0592] [0593] [0594] [0595] [0596] [0597] [0598] [0599] [0600] [0601] [0602] [0603] [0604] [0605] [0606] [0607] [0608] [0609] [0610] [0611] [0612] [0613] [0614] [0615] [0616] [0617] [0618] [0619] [0620] [0621] [0622] [0623] [0624] [0625] [0626] [0627] [0628] [0629] [0630] [0631] [0632] [0633] [0634] [0635] [0636] [0637] [0638] [0639] [0640] [0641] [0642] [0643] [0644] [0645] [0646] [0647] [0648] [0649] [0650] [0651] [0652] [0653] [0654] [0655] [0656] [0657] [0658] [0659] [0660] [0661] [0662] [0663] [0664] [0665] [0666] [0667]
<!DOCTYPE html> <!-- WASDOC AXP-2.0.0 (CGILIB AXP-1.9.9) --> <!-- wasDOC Copyright (C) 2019,2020 Mark G.Daniel - Apache-2.0 licenced --> <!-- 3-NOV-2021 02:57 --> <noscript>NOTE: SOME FUNCTIONALITY EMPLOYS JAVASCRIPT</noscript> <div id="erreport1" style="display:none;"></div> <script> function errorReport(string) { for (var cnt = 1; cnt <= 2; cnt++) { var err = document.getElementById('erreport'+cnt); err.style.display = 'block'; err.innerHTML += string; } } </script> <style type="text/css"> html { font-family: arial, verdana, sans-serif; font-size:12pt; margin:1em; } h1 { font-size:124%; font-style:bold; margin-top:1em; margin-bottom:0.5em; } h2 { font-size:120%; font-style:bold; margin-top:1.1em; margin-bottom:0.4em; } h3 { font-size:116%; font-style:bold; margin-top:1.0em; margin-bottom:0.3em; } h4 { font-size:112%; font-style:bold; margin-top:1.1em; margin-bottom:0.3em; } h5 { font-size:112%; font-style:bold; margin-top:1.1em; margin-bottom:0.3em; } h6 { font-size:112%; font-style:bold; padding:0; margin:0; } h1 .text { text-decoration:underline; } h1 .numb { padding-right:0.8em; } h1 .numb:empty { display:none; padding-right:0; } h2 .numb { padding-right:0.8em; } h2 .numb:empty { display:none; padding-right:0; } h3 .numb { padding-right:0.8em; } h3 .numb:empty { display:none; padding-right:0; } h4 .numb { padding-right:0.8em; } h4 .numb:empty { display:none; padding-right:0; } h5 .numb { display:none; padding-right:0; } h6 .numb { display:none; padding-right:0; } kbd { font-family:monospace; } noscript { font-size:1.2em; } p { line-height:1.1em; margin-top:1em; margin-bottom:1em; } .chunk { font-size:130%; text-decoration:underline; } .head {} .high {} .bold { font-weight:bold; } .center { text-align:center; } .italic { font-style:italic; } .left { text-align:left; } .nowrap { white-space:nowrap; } .prewrap { white-space:pre; } .right { text-align:right; } .strike { text-decoration:line-through; } .under { text-decoration:underline; } .backlight { background-color:#f2f2f2; } .display0 { display:none; } img { max-width:100%; } .imglink { } .link { } .blank { } .list { margin-bottom:1em; } .list li { margin-top:0.5em; } .list0 li { margin-top:0; } .item {} .tabl { border-collapse:collapse; text-align:left; margin:0.4em 2em 0.5em 2em; } .tabu { border-collapse:collapse; text-align:right; margin:0.4em 2em 0.5em 2em; } .tabr { vertical-align:top; } .tabh { padding:0.2em 0 0 2em; margin:0; } .tabd { padding:0.1em 0 0 2em; margin:0; } .tabh:first-of-type, td:first-of-type { padding-left:0; } .tabu .tabh, .tabu .tabd { border:1px solid gray; padding:0.2em 0.3em 0.2em 0.3em; } .tab0 { border:none; visibility:hidden; max-width:1em; white-space:nowrap; overflow:hidden; } .tabauto { margin-left:auto; margin-right:auto; } .tabr:empty { height:0.2em; } .tabu .tabh:empty, .tabu .tabd:empty { border:none; visibility:hidden; } .error { font-size:110%; color:black; background-color:yellow; font-family:sans-serif; font-weight:bold; font-style:normal; width:95%; border:solid 1px gray; padding:0.5em 1em 0.5em 1em; } .error::before { content:'\026a0\00a0'; } .image { } .page { width:98%; border:1px dashed gray; margin:1.5em 0 1.8em 0; } .epage { width:98%; border:1px dashed black; margin:1.5em 0 1.8em 0; } .monosp { font-family:monospace; } .ppage { display:none; } .simple { list-style-type:none; } .valtop { vertical-align:top; } .valmid { vertical-align:middle; } .valbot { vertical-align:bottom; } .code { border-style:solid; border-width:0 0 0 1px; padding-left:1em; font-family:monospace; white-space:pre; } .block { } .blockof { margin:0.4em 2em 0.5em 2em; } .example { border-style:dashed; border-width:0 0 0 1px; padding-left:1em; margin-top:0.5em; margin-bottom:0.5em; white-space:pre; } .indent { margin-left:2em; margin-right:2em; } .noindent { margin-left:0; margin-right:0; } .inblock { display:inline-block; } .mono { white-space:pre; font-family:monospace; } .note { margin:0.4em 2em 0.5em 2em; page-break-inside:avoid; } .note h5 { margin-top:0 } .note_hr { width:80%; border:1px solid gray; } .prop { padding-left:1em; margin-top:0.5em; margin-bottom:0.5em; } .quote { border-style:dashed; border-width:0 0 0 1px; padding-left:1em; margin-top:0.5em; margin-bottom:0.5em; } .this { display:none; } a:link,a:visited { color:black; text-decoration:none; } a:hover,a:active { text-decoration:underline; } a:focus { outline:0; } :target:before { content:''; display:block; height:0.1em; margin:-0.1em; } a.link:link, a.link:visited,a.link:active { color:midnightBlue; text-decoration:underline; text-decoration-style:solid; } .TOC1cols1 { width:80%; max-width:80%; } .TOC1cols2 { column-count:2; width:80%; max-width:80%; } .TOC1cols3 { column-count:3; max-width:90%; max-width:90%; } .TOC1cols4 { column-count:4; max-width:100%; max-width:100%; } .TOC1table { margin-left:2em; white-space:nowrap; break-inside:auto; } .TOC1table tr { vertical-align:top; text-align:left; break-inside:avoid; break-after:auto; } .TOC1table td+td { padding:0 0 0 0.5em; } .TOC1table .numb { width:3em; max-width:3em; } .TOC1table .sepr { width:5em; max-width:6em; overflow:hidden; } .TOC1table .majr { font-weight:bold; } .TOC1table .text { white-space:normal; } /* These are due to Firefox (at least <= 76) recalcitrant multi-column handling. Web search "Split table into css columns, issue in Firefox" (stackoverflow). "Good grief, Charlie Brown!" */ .TOC1cols2 table, .TOC1cols2 tbody, .TOC1cols2 tr, .TOC1cols3 table, .TOC1cols3 tbody, .TOC1cols3 tr, .TOC1cols4 table, .TOC1cols4 tbody, .TOC1cols4 tr { display:block; padding:0; } .TOC2cols1 { width:60%; max-width:60%; } .TOC2cols2 { column-count:2; width:70%; max-width:70%; } .TOC2cols3 { column-count:3; width:80%; max-width:80%; } .TOC2cols4 { column-count:4; width:90%; max-width:90%; } .TOC2table { margin-left:2em; white-space:nowrap; break-inside:auto; } .TOC2table tr { vertical-align:top; text-align:left; break-inside:avoid; break-after:auto; } .TOC2table .numb { font-weight:bold; padding-right:0.5em; } .TOC2table .text { width:100%; white-space:normal; } /* see "recalcitrant" above */ .TOC2cols2 table, .TOC2cols2 tbody, .TOC2cols2 tr, .TOC2cols3 table, .TOC2cols3 tbody, .TOC2cols3 tr, .TOC2cols4 table, .TOC2cols4 tbody, .TOC2cols4 tr { display:block; padding:0; } .NAVtable { margin:0.1em 0 0 2em; } .NAVtable td { font-size:110%; font-weight:bold; padding:0; margin:0; } .NAVtable a { padding:0 0.5em 0 0.5em; text-decoration:none; } .IDXcols1 { width:80%; max-width:80%; } .IDXcols2 { column-count:2; width:90%; max-width:90%; } .IDXcols3 { column-count:3; width:95%; max-width:95%; } .IDXcols4 { column-count:4; width:100%; max-width:100%; } .IDXtable { margin:1em 0 1em 2em; white-space:nowrap; break-inside:auto; } .IDXtable tr { vertical-align:top; text-align:left; break-inside:avoid; break-after:auto; } .IDXtable .alpha { font-weight:bold; min-width:2em; } .IDXtable .text { width:100%; white-space:normal; } .IDXtable .para:before { content:'\00b6\00a0'; } /* see "recalcitrant" above */ .IDXcols2 table, .IDXcols2 tbody, .IDXcols2 tr, .IDXcols3 table, .IDXcols3 tbody, .IDXcols3 tr, .IDXcols4 table, .IDXcols4 tbody, .IDXcols4 tr { display:block; padding:0; } .insight { background-color:cyan; font-family:monospace; padding:0 0.2em 0 0.2em; margin:0 0.2em 0 0.2em; font-size:100%; font-style:normal; font-weight:normal; text-decoration:none; } .wasdoc { font-family: "Lucida Console", Monaco, monospace; letter-spacing:-0.07em; } @media screen { .blank::after { content:"\2924"; } .print { display:none; } } @media print { table { page-break-inside:avoid; } .noprint { display:none; } .page { border:none; page-break-after: always; } .epage { display:none; } .ppage { page-break-after:always; } .NAVtable { display:none; } .NAVprint { display:block!important; } } @page { margin:2cm 1cm 2cm 1cm; } </style> <!-- source:0000_SCRIPTING.WASDOC --> <style type="text/css">._smiley::after { font-size:150%; vertical-align:middle; content:'\263a' }</style> <style type="text/css">._frowny::after { font-size:150%; vertical-align:middle; content:'\2639' }</style> <a id="0." href="#"></a> <title>WASD Scripting Environment – CGIplus</title> <a id="3." href="#"></a> <a id="3.cgiplus" href="#"></a> <a id="cgiplus" href="#"></a> <h1 class="head chunk">WASD Scripting Environment</h1> <h1 class="head"><span class="numb">3.</span><span class="text">CGIplus</span></h1> <table class="TOC2table"> <tr><td><a href="scripting003.html#3.1.cgiplusprogramming"><span class="numb">3.1</span><span class="text">CGIplus Programming</span></a> <tr><td><a href="scripting003.html#3.2.codeexamples"><span class="numb">3.2</span><span class="text">Code Examples</span></a> <tr><td><a href="scripting003.html#3.3.otherconsiderations"><span class="numb">3.3</span><span class="text">Other Considerations</span></a> </table> </div> <table class="NAVtable NAVprint"><tr> <td><a href="javascript:window.history.back();">↩︎</a> <td><a href="scripting002.html#2.">↖︎</a> <td><a href="scripting000.html#0.">↑︎</a> <td><a href="scripting004.html#4.">↘︎</a> <td><a href="javascript:window.history.forward();">↪︎</a> </table> <style type="text/css">._cgipplus th { padding:0 0.3em 0 0.3em; font-size:1.1em; } </style> <table class="tabl noindent _cgipplus"> <tr class="tabr"> <th class="tabh">Common Gateway Interface <th class="tabh">… <th class="tabh">plus lower latency, <tr class="tabr"> <th class="tabh"> <th class="tabh"> <th class="tabh">plus greater throughput, <tr class="tabr"> <th class="tabh"> <th class="tabh"> <th class="tabh">plus far less system impact! </table> <p> <span class="high" style="font-size:1.1em;">I know, I know! The term <span class="high under">CGIplus</span> is a bit <span class="high under">too cute</span> but I had to call it something!</span> <p> CGIplus attempts to eliminate the overhead associated with creating the script process and then executing the image of a CGI script. It does this by allowing the script process and any associated image/application to continue executing between uses, eliminating startup overheads. This reduces both the load on the system and the request latency. In this sense these advantages parallel those offered by commercial HTTP server-integration APIs, such as Netscape NSAPI and Microsoft ISAPI, without the disadvantages of such proprietory interfaces, the API complexity, language dependency and server process integration. <p> Existing CGI scripts can rapidly and elegantly be modified to additionally support CGIplus. The capability of scripts to easily differentiate between and operate in both standard CGI and CGIplus environments with a minimum of code revision offers great versatility. Many WASD scripts operate in both environments. <a id="3.0.0.0.1" href="#"></a> <a id="3.cgiplusperformance" href="#"></a> <a id="cgiplusperformance" href="#"></a> <h5 class="head"><span class="text">CGIplus Performance</span></h5> <p> A simple performance evaluation indicates the advantage of CGIplus. See "Techncial Overview, Performance" for some test results comparing the CGI and CGIplus environments. <p> Without a doubt, the subjective difference in activating the same script within the standard CGI and CGIplus environments is quite startling! <a id="3.1" href="#"></a> <a id="3.1.cgiplusprogramming" href="#"></a> <a id="cgiplusprogramming" href="#"></a> <h2 class="head"><span class="numb">3.1</span><span class="text">CGIplus Programming</span></h2> <p> <span class="high bold">The script interface is still CGI</span>, with all the usual environment variables and input/output streams available, which means a new API does not need to be learned and existing CGI scripts are simple to modify. <p> See examples in <a class="link blank" target="_blank" href="/wasd_root/src/CGIplus/*.*">WASD_ROOT:[SRC.CGIPLUS]</a> <p> Instead of having the CGI variables available from the environment (generally accessed via the C Language <span class="high italic">getenv()</span> standard library call, or via DCL symbols) a CGIplus script must read the CGI variables from an I/O stream named CGIPLUSIN. The variables can be supplied in one of two modes. <ul class="list"> <li class="item"> <span class="high bold">Record Mode – </span> Each CGI variable is supplied as an individual record (line). This is the default, and simplest method. Each contains a CGI variable name (in upper-case), an equate symbol and then the variable value. The format may be easily parsed and as the value contains no encoded characters may be directly used. The quantity of characters in each record depends on the size of the variable name and the length of the associated value. The value can vary from zero, to tens, hundreds, even thousands of characters. It is limited by the size of the CGIPLUSIN mailbox, which is in turn set by the [BufferSizeDclCgiPlusIn] configuration directive. <li class="item"> <span class="high bold">Struct Mode – </span> All variables are supplied in a binary structure which must be parsed by the receiving script. This is the most efficient method for providing the CGIplus script with its CGI environment. Performance improvements in the order of 50-100% have been measured. This size of this structure is limited by the size of the CGIPLUSIN mailbox, which is in turn set as described above. </ul> <a id="3.1.0.0.1" href="#"></a> <a id="3.1.recordmodecgiplus" href="#"></a> <a id="recordmodecgiplus" href="#"></a> <h5 class="head"><span class="text">Record-Mode CGIplus</span></h5> <p> This default and simple record-oriented mode allows any environment that can read records from an input source to process CGIplus variables. This of course includes DCL (examples referenced below). <ul class="list"> <li class="item"> The read will block between subsequent requests and so may be used to coordinate the application. <li class="item"> The first record read in any request can always be discarded. This is provided so that a script may be synchronized outside of the general CGIplus variable read loop. Record-mode can always be recognised by the single exclamation symbol comprising this record. <li class="item"> The CGIplus variable stream <span class="high bold">must always be completely read</span>, record-by-record up until the the first empty record (blank line, see below) before beginning any request processing. <li class="item"> An empty record (blank line) indicates the end of a single request's CGIplus variable stream. Reading MUST be halted at this stage. Request processing may then commence. </ul> <a id="3.1.0.0.2" href="#"></a> <a id="3.1.structmodecgiplus" href="#"></a> <a id="structmodecgiplus" href="#"></a> <h5 class="head"><span class="text">Struct-Mode CGIplus</span></h5> <p> This mode offers significantly lower system overheads and improves latency and performance at the cost of the additional complexity of recovering the variables from a binary structure. Code examples and CGILIB functions make this relatively trivial at the application level. <ul class="list"> <li class="item"> The read will block between subsequent requests and so may be used to coordinate the application. <li class="item"> The first record read in any request contains the size of the following binary record. It is also provided so that a script may be synchronized outside of the general CGIplus variable read loop. Struct-mode can always be recognised by the two, successive, leading exclamation marks preceding the variable structure record size integer. <li class="item"> The CGIplus variables are read as a single, binary I/O. <li class="item"> The contents of the binary structure must be parsed to obtain the individual CGI variables. Request processing may then commence. </ul> <a id="3.1.0.0.3" href="#"></a> <a id="3.1.requirementswhenusingcgiplus" href="#"></a> <a id="requirementswhenusingcgiplus" href="#"></a> <h5 class="head"><span class="text">Requirements when using CGIplus</span></h5> <p> After processing, the CGIplus script can loop, waiting to read the details of the next request from CGIPLUSIN. <p> Request output (to the client) is written to SYS$OUTPUT (<stdout>) as per normal CGI behaviour. <span class="high bold">End of output MUST be indicated by writing a special EOF record to the output stream.</span> A unique EOF sequence is generated for each use of DCL via a zombie or CGIplus script process. A non-repeating series of bits most unlikely to occur in normal output is employed … but there is still a very, very, very small chance of premature termination of output (one in 2^<sup>224</sup> I think!) See <a class="link blank" target="_blank" href="/wasd_root/src/httpd/cgi.c">WASD_ROOT:[SRC.HTTPD]CGI.C</a> for how the value is generated. <p> The CGIplus EOF string is obtained by the script from the logical name CGIPLUSEOF, defined in the script process' process table, using the scripting language's equivalent of F$TRNLNM(), SYS$TRNLNM(), or a getenv() call (in the C standard library). This string will always contain less than 64 characters and comprise only printable characters. It must be written at the conclusion of a request's output to the output stream as a single record (line) but may also contain a <CR><LF> or just <LF> trailing carriage-control (to allow for programming language requirements). It only has to be evaluated once, as the processing begins, remaining the same for all requests over the life-time of that instance of the script. <p> HTTP input (raw request body stream) is still available to a CGIplus script. <a id="3.1.0.0.4" href="#"></a> <a id="3.1.cgifunctionlibrary" href="#"></a> <a id="cgifunctionlibrary" href="#"></a> <h5 class="head"><span class="text">CGI Function Library</span></h5> <p> A source code collection of C language functions useful for processing the more vexing aspects of CGI/CGIplus/RTE programming (<a class="link" href="scripting001.html#1.12.scriptingfunctionlibrary">1.12 Scripting Function Library</a>). <a id="3.2" href="#"></a> <a id="3.2.codeexamples" href="#"></a> <a id="codeexamples" href="#"></a> <h2 class="head"><span class="numb">3.2</span><span class="text">Code Examples</span></h2> <p> Of course a CGIplus script should only have a single exit point and should explicitly close files, free allocated memory, etc., after processing a request (i.e. not rely on image run-down to clean-up after itself). It is particularly important when modifying existing scripts to work in the CGIplus environment to ensure this requirement is met (who of us hasn't thought "well, this file will close when the image exits anyway"?) <p> It is a simple task to design a script to modify its behaviour according to the environment it is executing in. Detecting the presence or absence of the CGIPLUSEOF logical is sufficient indication. The following C code fragment shows simultaneously determining whether it is a standard or CGIplus environment (and setting an appropriate boolean), and getting the CGIplus EOF sequence (if it exists). <div class="blockof code">int IsCgiPlus; char *CgiPlusEofPtr; IsCgiPlus = ((CgiPlusEofPtr = getenv("CGIPLUSEOF")) != NULL); </div> <a id="3.2.0.0.1" href="#"></a> <a id="3.2.recordmodecode" href="#"></a> <a id="recordmodecode" href="#"></a> <h5 class="head"><span class="text">Record-Mode Code</span></h5> <p> The following C code fragment shows a basic CGIplus record-mode request loop, reading lines from CGIPLUSIN, and some basic processing to select required CGI variables for request processing. Generally this level of coding is not required as it is recommended to employ the functionality of something like the CGILIB functiona library. <div class="blockof code">if (IsCgiPlus) { char *cptr; char Line [1024], RemoteHost [128]; FILE *CgiPlusIn; if ((CgiPlusIn = fopen (getenv("CGIPLUSIN"), "r")) == NULL) { perror ("CGIplus: fopen"); exit (0); } for (;;) { /* will block waiting for subsequent requests */ for (;;) { /* should never have a problem reading CGIPLUSIN, but */ if (fgets (Line, sizeof(Line), CgiPlusIn) == NULL) { perror ("CGIplus: fgets"); exit (0); } /* first empty line signals the end of CGIplus variables */ if (Line[0] == '\n') break; /* remove the trailing newline */ if ((cptr = strchr(Line, '\n')) != NULL) *cptr = '\0'; /* process the CGI variable(s) we are interested in */ if (!strncmp (Line, "WWW_REMOTE_HOST=", 16)) strcpy (RemoteHost, Line+16); } <span class="high italic">process request, signal end-of-output)</span> } } </div> <a id="3.2.0.0.2" href="#"></a> <a id="3.2.structmodecode" href="#"></a> <a id="structmodecode" href="#"></a> <h5 class="head"><span class="text">Struct-Mode Code</span></h5> <p> This mode requires significantly more code than record-mode. A self-contained C language function, allowing CGI variable processing in standard CGI, CGIplus record-mode and CGIplus struct-mode, is available for inclusion in user applications. It automatically detects the environment and changes behaviour to suit. This or CGILIB is strongly recommended. <p> See source in <a class="link blank" target="_blank" href="/wasd_root/src/CGIplus/CGIplus_cgivar.c">WASD_ROOT:[SRC.CGIPLUS]CGIPLUS_CGIVAR.C</a> <a id="3.2.0.0.3" href="#"></a> <a id="3.2.cgiplusoutput" href="#"></a> <a id="cgiplusoutput" href="#"></a> <h5 class="head"><span class="text">CGIplus Output</span></h5> <p> CGI scripts can write output in record (line-by-line) or binary mode (more efficient because of buffering by the C RTL). When in binary mode the output stream must be flushed immediately before and after writing the CGIplus EOF sequence (note that in binary a full HTTP stream must also be used). This code fragment shows placing a script output stream into binary mode and the flushing steps. <div class="blockof code">/* reopen output stream so that the '\r' and '\n' are not filtered */ if ((stdout = freopen ("SYS$OUTPUT", "w", stdout, "ctx=bin")) == NULL) exit (vaxc$errno); do { <span class="high italic">read request ...)</span> /* CGI response header */ fprintf (stdout, "Content-Type: text/html\n\n"); <span class="high italic">other output ...)</span> if (IsCgiPlus) { /* the CGIplus EOF must be an independant I/O record */ fflush (stdout); fprintf (stdout, "%s", CgiPlusEofPtr); fflush (stdout); } } while (IsCgiPlus); </div> If the script output is not binary (using default <stdout>) it is only necessary to ensure the EOF string has a record-delimiting new-line. <div class="blockof code">fprintf (stdout, "%s\n", CgiPlusEofPtr); </div> Other languages may not have this same requirement. DCL procedures are quite capable of being used as CGIplus scripts. <p> See examples in <a class="link blank" target="_blank" href="/wasd_root/src/CGIplus/*.*">WASD_ROOT:[SRC.CGIPLUS]</a> <div class="note"> <a id="3.2.0.0.4" href="#"></a> <a id="3.2.hint" href="#"></a> <a id="hint" href="#"></a> <h5 class="head center"><span class="text">Hint!</span></h5> <hr class="note_hr"> Whenever developing CGIplus scripts/applications (unlike standard CGI) don't forget that after compiling, the old image must be purged from the server before trying out the new!!! (I've been caught a number of times <span class="high monosp">:^)</span> <p> Scripting processes may be purged or deleted using (see <a class="link blank" target="_blank" href="../features/#httpdcommandline">HTTPd Command Line</a> in <a class="link blank" target="_blank" href="../features/#0.">WASD Features</a>). <div class="blockof code">$ HTTPD /DO=DCL=DELETE $ HTTPD /DO=DCL=PURGE </div> <hr class="note_hr"> </div> <a id="3.3" href="#"></a> <a id="3.3.otherconsiderations" href="#"></a> <a id="otherconsiderations" href="#"></a> <h2 class="head"><span class="numb">3.3</span><span class="text">Other Considerations</span></h2> <p> Multiple CGIplus scripts may be executing in multiple processes at any one time. This includes multiple instances of any particular script. It is the server's task to track these, distributing appropriate requests to idle processes, monitoring those currently processing requests, creating new instances if and when necessary, and deleting the least-used, idle CGIplus processes when configurable thresholds are reached. Of course it is the script's job to maintain coherency if multiple instances may result in resource conflicts or race conditions, etc., between the scripts. <p> The CGIplus script process can be given a finite life-time set by configuration parameter (see "Features and Facilities, Server Configuration"). If this life-time is not set then the CGIplus will persist indefinitely (i.e. until purged due to soft-limits being reached, or explicitly purged/deleted). When a life-time has been set the CGIplus process is automatically deleted after being idle for the specified period (i.e. not having processed a request). This can be useful in preventing sporadically used scripts from cluttering up the system indefinitely. <p> In addition, an idle CGIplus script can be run-down by the server at any time the script process soft-limit is reached, so resources should be largely quiescent when not actually processing (<a class="link" href="scripting001.html#1.2.6.scriptprocessrundown">1.2.6 Script Process Run-Down</a>). Of course, in extreme situations, a CGIplus process may also be manually terminated from the command line (e.g. STOP/ID=). <p> Some CGIplus scripting information and management is available via the server administration menu, see "Features and Facilities, Server Reports". <a id="3.3.0.0.1" href="#"></a> <a id="3.3.cgiplusrulemapping" href="#"></a> <a id="cgiplusrulemapping" href="#"></a> <h5 class="head"><span class="text">CGIplus Rule Mapping</span></h5> <p> CGIplus scripts are differentiated from standard CGI scripts in the mapping rule configuration file using the "script+" and "exec+" directives (see <a class="link blank" target="_blank" href="../config/#requestprocessingconfiguration">Request Processing Configuration</a> in <a class="link blank" target="_blank" href="../config/#0.">WASD Configuration</a>). <p> Scripts capable of operating in both standard CGI and CGIplus environments may simply be accessed in either via rules such as <div class="blockof code">exec /cgi-bin/* /cgi-bin/* exec+ /cgiplus-bin/* /cgi-bin/* </div> while specific scripts can be individually designated as CGIplus using <div class="blockof code">script+ /cgiplus_example* /cgi-bin/cgiplus_example* </div> <div class="note"> <a id="3.3.0.0.2" href="#"></a> <a id="3.3.hint" href="#"></a> <a id="hint" href="#"></a> <h5 class="head center"><span class="text">Hint!</span></h5> <hr class="note_hr"> When changing CGIplus script mapping it is advised to purge execution of existing scripts then reloading the mapping rules. Some conflict is possible when using new rules while existing CGIplus scripts are executing. <div class="blockof code">$ HTTPD /DO=DCL=PURGE $ HTTPD /DO=MAP </div> <hr class="note_hr"> </div> <!-- source:0400_RTE.WASDOC --> <table class="NAVtable NAVprint"><tr> <td><a href="javascript:window.history.back();">↩︎</a> <td><a href="scripting002.html#2.">↖︎</a> <td><a href="scripting000.html#0.">↑︎</a> <td><a href="scripting004.html#4.">↘︎</a> <td><a href="javascript:window.history.forward();">↪︎</a> </table>