[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] [0668] [0669] [0670] [0671] [0672] [0673] [0674] [0675] [0676] [0677] [0678] [0679] [0680] [0681] [0682] [0683] [0684] [0685] [0686] [0687] [0688] [0689] [0690] [0691] [0692] [0693] [0694] [0695] [0696] [0697] [0698] [0699] [0700] [0701] [0702] [0703] [0704] [0705] [0706] [0707] [0708] [0709] [0710] [0711] [0712] [0713] [0714] [0715] [0716] [0717] [0718] [0719] [0720] [0721] [0722] [0723] [0724] [0725] [0726] [0727] [0728] [0729] [0730] [0731] [0732] [0733] [0734] [0735] [0736] [0737] [0738] [0739] [0740] [0741] [0742] [0743] [0744] [0745] [0746] [0747] [0748] [0749] [0750] [0751] [0752] [0753] [0754] [0755] [0756] [0757] [0758] [0759] [0760] [0761] [0762] [0763] [0764] [0765] [0766] [0767] [0768] [0769] [0770] [0771] [0772] [0773] [0774] [0775] [0776] [0777] [0778] [0779] [0780] [0781] [0782] [0783] [0784] [0785] [0786] [0787] [0788] [0789] [0790] [0791] [0792] [0793] [0794] [0795] [0796] [0797] [0798] [0799] [0800] [0801] [0802] [0803] [0804] [0805] [0806] [0807] [0808] [0809] [0810] [0811] [0812] [0813] [0814] [0815] [0816] [0817] [0818] [0819] [0820] [0821] [0822] [0823] [0824] [0825] [0826] [0827] [0828]
/* PROGRAM Handle a VMS Help request from a WWW client VMSHelpGate.c ** =========================================== ** PROGRAM FOR CGI/1.0 SCRIPTS TO GENERATE HTML ** RENDITIONS OF VMS HELP LIBRARY CONTENTS. ** Note that in the present absence of table ** support, PRE formatting is used to create ** multicolumn displays. The tab expansion ** functions cannot take into account any ** numbering of anchors performed by the client, ** so the displays will not be as intented when ** this gateway is used by the WWW LineMode ** browser, or by Lynx when set to "Numbered ** Links" mode. The PRE formatting assumes ** the client has an 80 column (or greater) ** display window in effect. ** FOR USE ON VMS. ** ** USAGE (called from a script, e.g., HelpGate.com): ** ** $ VMSHelpGate :== $device:[directory]VMSHelpGate.exe ** $ VMSHelpGate ! cern server ** $ VMSHelpGate method url protocol ! decthreads server. ** ** The symbol WWW_PATH_INFO is set by the httpd and holds ** the argument for the help library and module to be ** returned to the client as HTML. It should be of the ** form: /HELP[/@library][/topic[/subtopic...]] ** with the following in the httpd configuration file to ** set it up: ** ** map /help /htbin/helpgate/HELP ** map /help/* /htbin/helpgate/HELP/* ** exec /htbin/* /HTTPD_Dir/* ** ** If no "/@library" is specified, "/@SYS$HELP:HELPLIB" ** is assumed. ** ** The symbols WWW_HOST_ACRONYM for indicating the ** host (e.g., WFEB) in the TITLE, and WWW_COPYRIGHT_STRING ** for showing a copyright notice at the tops of displays, ** should be set by the script. ** ** The script should also set the following two symbols ** to "TRUE" or "FALSE" as desired. They default to "FALSE" ** if undefined. ** WWW_CREATE_REAL_LINKS determines if we create real links ** from links simply listed in HELP text. ** WWW_CREATE_HELP_LINKS determines if we create links to other ** HELP topics that are referenced. ** ** A couple of notes if you use the WWW_CREATE_HELP_LINKS code: ** * Just one space is allowed between HELP words. ** * Qualifiers are not supported (yet). ** * Hyphenated HELP topics (like HELP E-MAIL) where the ** hyphen is the last character on a line are unsupported. ** And if you use the WWW_CREATE_REAL_LINKS code, note that the ** URL is assumed to be contained all on one line. ** ** AUTHORS: ** JFG Jean-Francois Groff, CERN, Geneva jfg@info.cern.ch ** FM Foteos Macrides macrides@sci.wfeb.edu ** DLJ David L. Jones, Ohio State Univ. vman+@osu.edu ** JW Jim Winkle, Univ of Wisconsin-Madison jwinkle@doit.wisc.edu ** ** HISTORY: ** Originally written by JFG as a standalone gateway. ** Extensively modified by FM for use with HTTP/1.0 and ** CGI scripts. ** ** JFG's HISTORY: ** -------------- ** 1.1 26 Feb 92 (JFG) Enabled strange topics ** 1.0 7 Oct 91 (JFG) First release ** 0.4 2 Oct 91 (JFG) Handle help summary. Definitive address format : ** //node[:port]/HELP[/@library][/topic[/subtopic...]] ** 0.3 27 Sep 91 (JFG) Created from h2h.c ** ** (c) CERN WorldWideWeb project 1990-1992. See Copyright.html for details ** ** Current HISTORY: ** ---------------- ** 2.0 1 May 94 (FM) Polishing up my modifications, for general release. ** ** DLJ mods: ** -------------------- ** 5 May 95 Convert to support DECthreads scripting system ** (cgilib). Replace printfs with cgi_printf. ** 7 May 94 Replace WWW_HELP_DIR 'caching' with direct library ** access via VMS Librarian utility routines. ** ** 2.1 8 May 94 (FM) Adopted DLJ's mods for CERN server too, with minor ** fixes for spacing in PRE formatted sections, and bug ** fix in lbr_close() of lbrio.c which caused ACCIO due ** to bad argument in free() call. ** 11 May 94 (FM) Added fixes from DLJ for Alphas. ** 27 Jun 94 (FM) Fixes in anchor_strcpy() for current HELP library ** rules and escaping of any lead colon. Unescape ** it in main() if still present. ** DLJ mods: ** -------------------- ** 2 Jul 94 Make qualifers within a level anchors and include ** in them with hrefs in generated menus. This more ** more closely mimics DCL HELP. Use cleaner algorithm ** to determine line-breaks in menus. ** ** 3 Jul 94 Add hack to deal with bugs in mac-mosaicB6 and ** <PRE> operations. ** ** 31 Oct 94 Escape '<', '>', and '&' in help text as per HTML spec. ** (No checks being done within anchors) ** ** 2 Aug 99 Make finickier check for module boundary. ** ** JW mods: ** -------------------- ** 2.2 13 Nov 96 Create real links to links simply listed in HELP text, ** and create links to other HELP topics referenced. */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <ctype.h> #include <unixlib.h> #include "lbrio.h" /* direct library access *DLJ* */ #define TAB_SIZE 16 /* 11 is what DCL HELP uses. */ #define LINE_WIDTH 80 /* * For DECthreads, include the cgilib.h */ #ifdef NOCGILIB #define cgi_init(a,b) 1 #define cgi_info(a) getenv(strcpy(&cgi_info_buf[4], a)-4) static char cgi_info_buf[64] = { 'W', 'W', 'W', '_' }; #define cgi_printf printf #else #include "cgilib.h" #endif /** Headers taken from h2h.c **/ /* Maximum line size for buffers */ #define LSIZE 256 /* Maximum command line size for VMS */ #define CSIZE 256 /* Maximum VMS file name size (note that it's actually 49.49) */ #define FSIZE 80 /* Maximum anchor size */ #define ASIZE 80 /** Function declarations **/ int strcasecomp(char *, char *); int strncasecomp(char *, char *, int); char *anchor_strcpy(char *, char *); void show_copyright(void); int hlp_to_html(lbr_index, char *); int lis_to_html(lbr_index, char *); lbr_index open_hlp(char *, char *); static char *pre_start; /* either "/n<PRE>" or "<PRE>/n" (macmosaic) */ /***************************************************************************** main : Retrieve information from VMS help libraries or cached modules and convert to HTML "on the fly". Input : symbol WWW_PATH_INFO set by httpd : HT address ------------------------------------------------------------------------------*/ int main(int argc, char *argv[]) { char *arg; lbr_index hlp; /* lbr control structure *DLJ* */ char *help_file; char *query; char *s; char *cp; char *browser; /* User-agent field, DLJ */ int status; /* Initialize CGI library. */ status = cgi_init ( argc, argv ); if ( (status&1) == 0 ) exit ( status ); s = cgi_info ( "HTTP_USER_AGENT" ); /* * Hack to accomodate MacMosaic bug. Mosaic 1.0.3 ignores the first * LF it sees after going into <PRE> mode while other browsers need the * line break before going into <PRE>. Check for the faulty browser and * do the right thing. */ pre_start = "\n<PRE>"; if ( s ) { browser = malloc ( strlen(s) + 1 ); strcpy ( browser, s ); for ( cp = browser; *cp; cp++ ) if (isspace(*cp) ) { *cp = '\0'; break; } /* fprintf(stderr,"browser: '%s'\n", browser ); */ if ( strcmp ( browser, "MacMosaicB6" ) == 0 ) pre_start = "<PRE>\n"; } /* output the content type */ cgi_printf("Content-Type: text/html\n\n<HTML>\n"); /* address must be of the form /HELP[/@library][/topic[/subtopic...]] */ if ((arg=cgi_info("PATH_INFO")) == NULL || (s = strtok (arg + 1, "/")) == NULL) { cgi_printf("Address should begin with /HELP arg=%d\n</HTML>\n", arg); exit(0); } if (strcasecomp (s, "HELP")) { cgi_printf("Address should begin with /HELP : /%s\n</HTML>\n", s ? s : ""); exit(0); } help_file = strtok (NULL, "/"); if (help_file && *help_file == '@' && help_file[1] ) { /* Explicit help library specified */ help_file++; /* Skip @ */ query = strtok (NULL, "/+"); } else { /* This was not a help library, but the beginning of the query */ query = help_file; help_file = NULL; } /* Unescape lead colon, if present in query */ if (query && strncasecomp(query, "%3a", 3) == 0) { query += 2; *query = ':'; } /* The first word from the query is the module name (perhaps empty) */ if (! (hlp = open_hlp (help_file, query))) { cgi_printf("Help library or module not found : %s/%s\n", help_file ? help_file : "", query ? query : ""); cgi_printf("</HTML>"); return 2160; } if (query) { /* Parse rest of address and process help file */ while (s = strtok (NULL, "/+")) *(s - 1) = ' '; status = hlp_to_html(hlp, query); } else /* Process library directory */ status = lis_to_html(hlp, help_file); cgi_printf("</HTML>"); exit(0); return(status); } /***************************************************************************** strcasecomp : Case-insensitive comparison for strings of any length. strncasecomp : Case-insensitive comparison for strings with count limit. Return -1, 0, 1 equivalently to strcmp and strncmp -----------------------------------------------------------------------------*/ /* Strings of any length ** --------------------- */ int strcasecomp(char *a, char *b) { char *p = a; char *q = b; for(p=a, q=b; *p && *q; p++, q++) { int diff = tolower(*p) - tolower(*q); if (diff) return diff; } if (*p) return 1; /* p was longer than q */ if (*q) return -1; /* p was shorter than q */ return 0; /* Exact match */ } /* With count limit ** ---------------- */ int strncasecomp(char *a, char *b, int n) { char *p = a; char *q = b; for(p=a, q=b;; p++, q++) { int diff; if (p == a+n) return 0; /* Match up to n characters */ if (!(*p && *q)) return *p - *q; diff = tolower(*p) - tolower(*q); if (diff) return diff; } } /***************************************************************************** anchor_strcpy : Converts a string to a name suitable for use as an anchor and for comparisons, i.e. trim to its first word (consisting of alphanumeric characters plus '_', '=', '@', '-', '$', '/' and '.'), make the letters uppercase, and convert each '$' '/' and '.' to '_'. If string begins with ':', escape it. Inputs : char *dest : destination string char *src : source string Returns the end position of the destination string. -----------------------------------------------------------------------------*/ char *anchor_strcpy(char *dest, char *src) { char *end = dest; /* Trim to first word */ for ( ; *end = isalnum (*src) || *src == '_' || *src == '=' || *src == '@' || *src == '-' ? _toupper(*src) : *src == '/' || *src == '$' || *src == '.' ? '_' : '\0' ; ++end, ++src); if (end == dest) { /* src doesn't begin with a word or _=@-/$. */ if (*src == ':') { /* If it begins with a colon, escape it */ *end++ = '%'; *end++ = '3'; *end++ = 'a'; src++; } for ( ; *src ; ++src) { *end++ = _toupper (*src); } *end = 0; /* Terminate the string */ } return end; } /**************************************************************************** show_copyright : Outputs a copyright notice if the script has set the symbol WWW_COPYRIGHT_STRING. ----------------------------------------------------------------------------*/ void show_copyright() { char *cp; if ((cp=getenv("WWW_COPYRIGHT_STRING")) != NULL) cgi_printf("%s\n", cp); return; } /***************************************************************************** hlp_to_html : Reads in help library module and outputs desired info in HTML format. Inputs : lbr_index hlp : pointer to the .HLP file to be scanned char *query : data to be found, as blank-separated keywords NOTE : this string is altered (tokenized) by the function Optional symbols set by script : WWW_HOST_ACRONYM : Acronym for host. Prefixed to HTML title. WWW_CREATE_REAL_LINKS : Create real links to links listed in HELP text. WWW_CREATE_HELP_LINKS : Create links to other HELP topics referenced. Status returned : 0 : Success Unused -1 : Help file not found -2 : Query not found Unused -3 : Empty query -4 : Structure error in help file (may create some text before that) Unused -5 : Write error to HTML file (may create some text before that) Unused -6 : Can't open HTML output file -----------------------------------------------------------------------------*/ int hlp_to_html(lbr_index hlp, char *query) { int subqual; /* True if level defines qualifiers (DLJ) */ int dlen; /* 'Display' length, chars on current display line */ char carcon[TAB_SIZE*2]; char *sep = " "; /* Authorized keyword separators in the query */ char line[LSIZE]; /* Input buffer */ char out[LSIZE]; /* Output buffer */ /* Possible states of the scanning algorithm */ enum { PARSE, TEXT, MENU, DONE } state; int depth; /* Current depth in the help tree */ char *key; /* Currently searched keyword from the query */ int prefix; /* Prefix number on a line of the help file, indicating depth */ char *title; /* Pointer to the rest of a title line after depth prefix */ char anchor[ASIZE]; /* Anchor name built from menu title and item */ char *menu_item; /* Pointer to menu item within anchor name */ int multi_line_HELP; /* Flag indicating "HELP [topic]..." is > 1 line long */ char help_topic_saved[256]; /* Place to save first line(s) from multi-line HELP */ char *cp, *s, *t; /* Temporary string pointers */ int i = 1, len; int create_real_links; /* Flag equivalent to WWW_CREATE_REAL_LINKS */ int create_help_links; /* Flag equivalent to WWW_CREATE_REAL_LINKS */ /* Initial things to send out */ state = PARSE; /* Searching for the query's keywords */ multi_line_HELP = 0; depth = 1; subqual = 0; key = strtok (query, sep); /* Read first keyword from the query */ anchor_strcpy (key, key); /* Normalise key to help matches */ /* If TRUE, then TRUE. If undefined, FALSE, or other, then FALSE. */ if (create_real_links = (cp=getenv("WWW_CREATE_REAL_LINKS")) != NULL) create_real_links = strcmp (cp, "TRUE") == 0; if (create_help_links = (cp=getenv("WWW_CREATE_HELP_LINKS")) != NULL) create_help_links = strcmp (cp, "TRUE") == 0; while (1==(1&lbr_fgets (line, LSIZE, hlp)) ) { if (isdigit (*line) && isspace(line[1]) ) { /* This is a title line */ prefix = strtol (line, &title, 10); while (isspace (*title)) /* Find the real beginning of the title */ title++; s = title; while (*(++s) != '\n'); /* Find the real end of the title */ while (isspace (*(--s))); *(++s) = '\0'; /* Trim title to a clean string */ switch (state) { case PARSE: /* Check title against query */ menu_item = anchor_strcpy (anchor, title); /* Is this a match ? */ if (prefix == depth && !strncmp(anchor, key, strlen(key))) { if (depth == 1) { /* Root match */ /* Start the HTML title with the first word of 'title' */ cgi_printf ("<TITLE>%s Help %.*s", (cp=getenv("WWW_HOST_ACRONYM")) ? cp : "", menu_item - anchor, title); } else { /* Deep match : continue HTML title in the same way */ cgi_printf(" %.*s", menu_item - anchor, title); } if (key = strtok (NULL, sep)) { /* More levels to descend */ depth++; anchor_strcpy (key, key); /* Normalise key to help matches */ } else { /* Query fully parsed */ cgi_printf("</TITLE>\n"); /* End the HTML title */ show_copyright(); /* show copyright notice if set by script */ cgi_printf("<H1>%s</H1>", title); /* Print full heading */ *menu_item++ = '/'; /* Append field separator to anchor */ *menu_item = '\0'; /* Ready for anchor completion */ state = TEXT; cgi_printf(pre_start); /* Will copy help text verbatim */ } } break; case TEXT: cgi_printf("\n</PRE>\n"); /* Help text is finished, folks ! */ if (prefix <= depth) { /* We reached the next item at this depth or it was the last one */ /* That's all, folks ! */ state = DONE; break; } else if (prefix == depth + 1) { /* This item has a menu */ state = MENU; depth++; cgi_printf("<H3>Additional information available:</H3>%s",pre_start); i = 1; dlen = 0; } else { /* The help file skipped the next depth */ lbr_close (hlp); cgi_printf("Help file corrupted.\n"); return(-4); } /* No break here : flow through case MENU if state transition */ /* (Yeah, you may find this ugly...) */ case MENU: if (prefix < depth) { /* Seen all menu items */ cgi_printf("\n</PRE>\n"); /* That's all, folks ! */ state = DONE; } else if (prefix == depth) { /* Next menu item */ anchor_strcpy (menu_item, title); /* Append item to anchor prefix */ len = strlen(title); /* printable chars */ if ( 0 == dlen ) strcpy ( carcon, "" ); else { int j = 0; carcon[j++] = ' '; for ( dlen++; dlen%TAB_SIZE; dlen++ ) carcon[j++] = ' '; carcon[j] = '\0'; if ( subqual || ( (dlen + len) >= LINE_WIDTH ) ) { strcpy ( carcon, "\n" ); dlen = 0; i = 1; } } dlen += len; subqual = 0; /* new level started */ cgi_printf("%s<A HREF=\"%s\">%s</A\n>", carcon, anchor, title ); } /* if prefix > depth, there's a submenu : ignore it. */ break; case DONE: /* Shouldn't happen here */ fprintf (stderr, "Internal error : invalid state DONE.\n"); break; } /* End of switch(state) */ } /* End of title line processing */ else { /* This is a text line */ if (state == TEXT && *line != '!') { /* It's not a comment ('!') */ if (*line == '/') { /* Make qualifier header bold and make it an anchor. Anchor * name is only the qualifier name itself. */ char tag[80]; int j; strncpy ( tag, line+1, sizeof(tag)-2 ); tag[sizeof(tag)-1] = '\0'; for ( j = 0; tag[j]; j++ ) if ( isspace(tag[j]) || ( tag[j] == '\n' ) ) { tag[j] = '\0'; break; } for ( j = 0; line[j] && (line[j] != '\n'); j++); line[j] = '\0'; cgi_printf("<b><A NAME=\"%s\">%s</A></b>", tag, line); } else { /* Copy text line to HTML file: */ /* - escaping '<', '>', and '&' */ /* - creating real links to links simply listed in HELP text */ /* - creating links to other HELP topics referenced */ char *start, *curp, testc; int url_length, token_length; char *help_start; /* start of the H"ELP [topic...]" string */ char url[256]; /* the url we're forming */ char curc_saved; /* we need to overwrite a character to terminate a string, so save it */ for ( start = curp = line; (testc=(*curp)); curp++ ) { if ( (testc == '<') || (testc == '>') || (testc == '&') ) { *curp = '\0'; /* terminate the start string */ cgi_printf( (testc=='<') ? "%s<" : ((testc=='>') ? "%s>" : "%s&"), start ); start = curp+1; } else if (create_real_links && ( (testc == 'h' && strncmp (curp, "http://", strlen ("http://")) == 0) || (testc == 'g' && strncmp (curp, "gopher://", strlen ("gopher://")) == 0) || (testc == 't' && strncmp (curp, "telnet://", strlen ("telnet://")) == 0) || (testc == 'f' && strncmp (curp, "ftp://", strlen ("ftp://")) == 0) || (testc == 'm' && strncmp (curp, "mailto:", strlen ("mailto:")) == 0) || (testc == 'n' && strncmp (curp, "news:", strlen ("news:")) == 0) )) { url_length = strcspn (curp, " \t\n,?;!)"); strncpy (url, curp, url_length); url[url_length] = '\0'; *curp = '\0'; /* terminate the start string */ cgi_printf("%s<A HREF=\"%s\">%s</A>", start, url, url); start = curp+url_length; } else if (create_help_links && ( (testc == 'H' && strncmp (curp, "HELP", strlen ("HELP")) == 0) && (curp == line || *(curp-1) == '(' || *(curp-1) == ' ') )) { /* avoid SYS$HELP, 264-HELP, etc. */ int j; char token[64]; strcpy (url, ""); while (isupper (*curp)) { token_length = strcspn (curp, " \t\n,?;!)."); strncpy (token, curp, token_length); token[token_length] = '\0'; if ( strcmp (token, "HELP") == 0 ) { *curp = '\0'; /* terminate the start string */ help_start = curp+1; } else strcat (url, "/"); strcat (url, token); curp = curp + token_length; if (*curp == ' ') curp++; } multi_line_HELP = ( *curp == '\n' ); if ( *(curp - 1) == ' ' ) --curp; curc_saved = *curp; *curp = '\0'; /* terminate the help_start string */ if (!multi_line_HELP) if (strlen (url) > strlen ("HELP")) cgi_printf("%s<A HREF=\"/%s\">%c%s</A>%c", start, url, testc, help_start, curc_saved); else cgi_printf("%s%c%s%c", start, testc, help_start, curc_saved); else { cgi_printf("%s<A HREF=\"/%s", start, url); /* save the help_topic for later */ strcpy (help_topic_saved, " "); help_topic_saved[0] = testc; strcat (help_topic_saved, help_start); *(curp + 1) = '\0'; /* terminate the for loop, way above */ } start = curp+1; } else if (multi_line_HELP) { int j; char token[64]; strcpy (url, ""); while (*curp == ' ' || *curp == '\t') curp++; /* skip white space at beginning of line */ while (isupper (*curp)) { token_length = strcspn (curp, " \t\n,?;!)."); strncpy (token, curp, token_length); token[token_length] = '\0'; strcat (url, token); strcat (url, "/"); curp = curp + token_length; if (*curp == ' ') curp++; } multi_line_HELP = ( *curp == '\n' && strlen (url) > 0 ); if ( *(curp - 1) == ' ' ) --curp; curc_saved = *curp; *curp = '\0'; /* terminate the start string */ if (!multi_line_HELP) if (strlen (url) > 0) { url[strlen (url) - 1] = '\0'; /* delete the trailing '/' */ cgi_printf("/%s\">%s\n%s</A>%c", url, help_topic_saved, start, curc_saved); } else if (strcmp (help_topic_saved, "HELP") == 0) /* don't create link for just "HELP" */ cgi_printf("\"></A>%s\n%s%c", help_topic_saved, start, curc_saved); else cgi_printf("\">%s\n</A>%s%c", help_topic_saved, start, curc_saved); else { /* third and subsequent lines */ url[strlen (url) - 1] = '\0'; /* delete the trailing '/' */ cgi_printf("/%s", url); strcat (help_topic_saved, "\n"); strcat (help_topic_saved, start); *(curp + 1) = '\0'; /* terminate the for loop, way above */ } start = curp+1; } } cgi_printf("%s", start); } } else if ( (state == MENU) && (*line == '/') && (prefix == depth) ) { /* * The help module has qualifier definitions that don't go to the * next level. Add these to the menu, starting them on a fresh * line. Reference will be using intra-module syntax. */ char tag[80]; int j; strncpy ( tag, line+1, sizeof(tag)-2 ); tag[sizeof(tag)-1] = '\0'; for ( j = 0; tag[j]; j++ ) if ( isspace(tag[j]) || ( tag[j] == '\n' ) ) { tag[j] = '\0'; break; } for ( j = 0; line[j] && (line[j] != '\n'); j++); line[j] = '\0'; len = strlen ( line ); if ( 0 == dlen ) strcpy ( carcon, "" ); else { j = 0; carcon[j++] = ' '; for ( dlen++; dlen%TAB_SIZE; dlen++ ) carcon[j++] = ' '; carcon[j] = '\0'; if ( (subqual==0) || ( dlen + len >= LINE_WIDTH ) ) { strcpy ( carcon, "\n" ); dlen = 0; } } subqual = 1; dlen += len; cgi_printf ( "%s<A HREF=\"%s#%s\">%s</A\n>", carcon, anchor, tag, line ); } } /* End of text line processing */ if (state == DONE) { /* Have we finished yet ? */ lbr_close (hlp); cgi_printf("\n"); return 0; /* success */ } } /* EOF reached on help file */ lbr_close (hlp); if (state != PARSE) { /* EOF reached while outputting HTML */ cgi_printf("\n</PRE>\n"); return 0; /* success */ } else { /* key not found */ if (depth > 1) /* Partial match : end the title cleanly */ cgi_printf("</TITLE>\n"); cgi_printf("\"%s\" not found in help file.\n", key ? key : ""); return(-2); } } /***************************************************************************** lis_to_html : Reads current library module index and outputs menu in HTML format. Inputs : lbr_index dir : pointer to the library to be scanned char *lib_name : name of the help library (for HTML title) Optional symbols set by script : WWW_HOST_ACRONYM : Acronym for host. Prefixed to HTML title. Status returned : 0 : Success -2 : Structure error in .LIS file -----------------------------------------------------------------------------*/ int lis_to_html(lbr_index dir, char *lib_name) { char line[LSIZE]; /* Input buffer */ char spacing[24]; /* Holds output chars that move cursoro to next col */ char *entry; /* Pointer to current directory entry */ char *cp, *at_prefix; int dlen; int i = 1, len, j, extra_cols, fill; if (lib_name) /* Help library specified */ at_prefix = "HELP/../@"; /* Use a relative path trick */ else { /* Plain HELP request */ at_prefix = ""; lib_name = "HELP"; /* Root level help */ } /* Initial things to send out */ cgi_printf("<TITLE>%s Help Library ", (cp=getenv("WWW_HOST_ACRONYM")) ? cp : ""); cgi_printf("%s", lib_name); cgi_printf(" Contents</TITLE>\n"); show_copyright(); /* show copyright notice if set by script */ cgi_printf("<H1>%s</H1>%s", lib_name, pre_start); /* Now scan the entries */ i = 1; /* Current column, 1..5 */ entry = line; extra_cols = 0; dlen = 0; fill = 0; while ( 1==(1&lbr_read_directory (entry, LSIZE, dir)) ) { len = strlen(entry); /* length of entry */ if ( 0 == dlen ) strcpy ( spacing, "" ); else { j = 0; spacing[j++] = ' '; for ( dlen++; dlen%TAB_SIZE; dlen++ ) spacing[j++] = ' '; spacing[j] = '\0'; if ( dlen + len >= LINE_WIDTH ) { strcpy ( spacing, "\n" ); dlen = 0; } } dlen += len; cgi_printf ( "%s<A HREF=\"%s%s/%s\">%s</A\n>", spacing, at_prefix, lib_name, entry, entry ); } /* End of entry processing */ lbr_close (dir); cgi_printf("\n</PRE>\n"); /* End the pseudo-table cleanly */ return 0; /* success */ } /***************************************************************************** open_hlp : Opens desired module from specified library. Extracts it from .HLB help library if necessary. If no module is specified, opens (and perhaps creates) .LIS library directory file. Inputs : char *help_lib : library name char *module : name of the module to extract Returns lbr_index pointing to control stucture. ----------------------------------------------------------------------------*/ lbr_index open_hlp(char *help_lib, char *module) { lbr_index lptr; int status, searching; char *lib_name; char fallback[256]; /* First, create the relevant (unique) file name */ if ( help_lib ) { lib_name = help_lib; strcpy ( fallback, "HELPLIB" ); if ( strcmp(help_lib,"HELPLIB") == 0 ) strcpy ( fallback, "HLP$LIBRARY"); } else { /* Try helplib first */ lib_name = "HELPLIB"; strcpy ( fallback, "HLP$LIBRARY" ); } /* * Search specified library plus default libraries. */ for ( searching = 1; searching; ) { status = lbr_open ( lib_name, "SYS$HELP:.HLB", &lptr ); if ( 1 == (status&1) ) { /* See if module in library */ if ( module ) { status = lbr_set_module ( lptr, module ); if ( 1 == (status&1) ) searching = 0; /* Found a match */ else lbr_close ( lptr ); /* not this library */ } else searching = 0; /* Assume directory scan */ } if ( searching ) { /* * Library open failed, set up libname for next try. */ if ( strcmp(fallback,"HELPLIB") == 0 ) { strcpy ( fallback, "HLP$LIBRARY" ); lib_name = "HELPLIB"; } else { lib_name = getenv(fallback); if ( !lib_name ) break; /* no more fallbacks */ sprintf(fallback,"HLP$LIBRARY_%d", searching++ ); } } } /* * Breaking out of loop (searching non-zero) means module not found. */ return searching ? (lbr_index) 0 : lptr; /* DLJ */ }