Annotation of libwww/LineMode/src/HTBrowse.c, revision 1.48.2.4
1.44 frystyk 1: /* HTBrowse.c
2: ** HYPERTEXT BROWSER FOR DUMB TERMINALS
3: **
4: ** (c) COPYRIGHT CERN 1994.
5: ** Please first read the full copyright statement in the file COPYRIGH.
1.1 timbl 6: **
7: ** Authors:
8: ** NP: Nicola Pellow Tech.Student CERN 1990-91
9: ** TBL: Tim Berners-Lee CERN (timbl@info.cern.ch)
10: ** JFG: Jean-Francois Groff, Cooperant CERN 1991-92 (jfg@info.cern.ch)
11: ** DR: Dudu Rashty +972-2-584848 <RASHTY@hujivms.bitnet>
1.8 duns 12: ** MD: Mark Donszelmann, DELPHI CERN, (duns@vxdeop.cern.ch)
1.34 frystyk 13: ** HFN: Henrik Frystyk Nielsen, CERN, (frystyk@dxcern.cern.ch)
1.1 timbl 14: **
15: ** History:
16: **
17: ** 4 Dec 90: Written from scratch (NP)
18: ** 11 Feb 91: Code written by TBL so that the browser could be linked with
19: ** code produced by Bernd Pollermann, enabling access to the
20: ** data on CERNVM. This involved changing the code to handle file
21: ** numbers rather than file pointers.
22: ** 18 Mar 91: The feature of history mechanism was included, enabling a
23: ** record of previous nodes visited to be kept.
24: ** 6 Apr 91: When a node is accessed, it is immediately read into a
1.40 frystyk 25: ** buffer, in an unformatted state, as soon as the connection is
1.1 timbl 26: ** made, so that the server is freed as quickly as possible.
27: ** The program now also uses the additional modules HTBufferFile.c
28: ** and HTBufferFile.h.
29: ** 17 Apr 91: Can be used on machines running ANSI C and ordinary C.
30: ** 10 May 91: Formatted text is stored in a linked list buffer which allows
31: ** scrolling and better page breaks in the middle of text.
32: ** Code incorporated by Tim BL, to enable anonymous FTP.
33: ** 21 May 91: Accepts various parameters on the command line.
34: ** 19 Aug 91: Currently available in Unix, VAX/VMS and MVS environments.
35: ** 21 Nov 91: Character grid uses new architecture. (TBL)
36: ** added -w option, new commands, print,
37: ** ... See Features.html for further details
38: ** 16 Jan 92: Put in VIOLA-compatible options - see \017 characters.
39: ** \017 and \016 bracket user-selectable input.
40: ** 27 Feb 92: New handling of user input, enhanced command syntax. (JFG)
41: ** 18 May 92: PS command see ifdef SLAVE_PRINTER (DR/TBL)
42: ** 6 Oct 92: Painful recovery from someone(?)'s attept to pretty print.(TBL)
43: ** Please see coding style guide before changing indentation etc!
44: ** Mar 93: Force on HTFile's HTDirAccess and HTDirReadme flags.
1.8 duns 45: ** 3 Nov 93: (MD) Changed vms into VMS
46: ** (MD) Assigne output in main, not at initialize (VMS only)
1.1 timbl 47: **
48: ** Compilation-time macro options
49: **
50: ** REF_MARK Printf string to be used for printing anchor numbers
51: ** END_MARK String to be used to denote the end of a document
52: ** VL Version number, quoted eg "1.2a"
53: */
54:
1.48.2.4! frystyk 55: #include "WWWLib.h"
1.11 frystyk 56: #include "HTBrowse.h" /* Things exported, short names */
57: #include "GridText.h" /* Hypertext definition */
1.1 timbl 58:
1.48.2.4! frystyk 59: #if 0
! 60: #include <ctype.h>
1.1 timbl 61: #include "HTFormat.h"
62: #include "HTTCP.h" /* TCP/IP utilities */
63: #include "HTAnchor.h" /* Anchor class */
64: #include "HTParse.h" /* WWW address manipulation */
65: #include "HTAccess.h" /* WWW document access network code */
1.48.2.4! frystyk 66: #include "HTHist.h" /* Navigational aids */
1.1 timbl 67: #include "HTML.h" /* For parser */
1.48.2.4! frystyk 68: #include "HTFWrite.h" /* For non-interactive output */
1.33 timbl 69: #include "HTMLGen.h" /* For reformatting HTML */
1.1 timbl 70: #include "HTFile.h" /* For Dir access flags */
1.3 timbl 71: #include "HTRules.h" /* For loading rule file */
1.30 frystyk 72: #include "HTError.h"
1.38 frystyk 73: #include "HTAlert.h"
1.41 frystyk 74: #include "HTTP.h"
1.40 frystyk 75: #include "HTEvent.h"
1.48.2.4! frystyk 76: #endif
1.40 frystyk 77:
78: /* HWL 18/7/94: applied patch from agl@glas2.glas.apc.org (Anton Tropashko) */
79: #ifdef CYRILLIC
80: #include "a_stdio.h"
81: #endif
1.1 timbl 82:
1.40 frystyk 83: #ifdef THINK_C /* Macintosh Think C development system */
1.1 timbl 84: #include <console.h>
85: #include <time.h>
1.40 frystyk 86: extern int socketdebug; /* Must be declared in the socket library */
87: #endif
88:
89: /* Macros and other defines */
90: #ifndef VL
91: #define VL "unspecified"
92: #endif
93:
94: /* If the guy gives the "MANUAL" command, jump to this: */
95: #ifndef MANUAL
96: #define MANUAL "http://info.cern.ch/hypertext/WWW/LineMode/Defaults/QuickGuide.html"
97: #endif
98:
99: #ifndef COM_HELP_FILE
100: #define COM_HELP_FILE "http://info.cern.ch/hypertext/WWW/LineMode/Defaults/CommandLine.html"
1.1 timbl 101: #endif
102:
1.40 frystyk 103: #ifndef DEFAULT_LOCAL_LOGFILE
104: #define DEFAULT_LOCAL_LOGFILE "WWW-log" /* Log file name for local execution */
105: #endif
1.1 timbl 106:
1.40 frystyk 107: #ifndef DEFAULT_OUTPUT_FILE
108: #define DEFAULT_OUTPUT_FILE "WWW-out" /* Output file name for non-interactive run */
1.37 howcome 109: #endif
110:
1.40 frystyk 111: #ifndef DEFAULT_REF_HEAD
112: #define DEFAULT_REF_HEAD "*** References from this document ***"
113: #endif
1.1 timbl 114:
115: #ifndef REF_MARK /* May be redefined on command line */
116: #ifdef VIOLA
117: #define REF_MARK "[\017%d\016]" /* Shift-in, shift-out around number */
118: #define PROMPT_MARK "\017%s\016"
119: #else
120: #define PROMPT_MARK "%s"
121: #ifdef VM
122: #define REF_MARK " <%d>" /* IBM terminals can't handle [] well */
123: #else
124: #define REF_MARK "[%d]"
125: #endif
126: #endif
127: #endif
128:
129: #ifndef END_MARK
130: #ifdef VM
131: #define END_MARK " <End>"
132: #else
133: #define END_MARK " [End]"
134: #endif
135: #endif
136:
137: #ifdef NEWLIB
1.13 frystyk 138: #define SCREEN_WIDTH 78
1.1 timbl 139: #endif
140:
141: #ifndef SCREEN_WIDTH
1.13 frystyk 142: #define SCREEN_WIDTH 79 /* Default width of the screen */
1.1 timbl 143: #endif
1.13 frystyk 144:
145: #ifndef MIN_SCREEN_WIDTH
146: #define MIN_SCREEN_WIDTH 10
147: #endif
148:
149: #ifndef MAX_SCREEN_WIDTH
150: #define MAX_SCREEN_WIDTH 150
151: #endif
152:
1.1 timbl 153: #ifndef SCREEN_HEIGHT
1.13 frystyk 154: #define SCREEN_HEIGHT 24 /* Default number of lines to the screen */
155: #endif
156:
157: #ifndef MIN_SCREEN_HEIGHT
158: #define MIN_SCREEN_HEIGHT 5
159: #endif
160:
161: #ifndef MAX_SCREEN_HEIGHT
1.14 frystyk 162: #define MAX_SCREEN_HEIGHT 200
1.1 timbl 163: #endif
164:
1.16 frystyk 165: #define INFINITY 1024 /*!! BUG*/
166: #define ADDRESS_LENGTH INFINITY /* Maximum address length of node */
167: #define RESPONSE_LENGTH INFINITY /* Maximum length of users response */
168:
1.40 frystyk 169: /* #define LONG_PROMPT 1 */ /* Long or short user prompt */
170:
171: #if defined(ultrix) || defined(__osf__)
172: #define GET_SCREEN_SIZE
173: #endif
174:
1.48.2.1 frystyk 175: #if defined(__svr4__)
176: #define CATCH_SIG
177: #endif
178:
1.40 frystyk 179: #define Check_User_Input(command) \
180: (!strncasecomp (command, this_word, strlen(this_word)))
1.1 timbl 181:
1.40 frystyk 182: /* Public Variables etc. */
183: /* HWL 18/7/94: applied patch from agl@glas2.glas.apc.org (Anton Tropashko) */
184: #ifdef CYRILLIC
185: struct ARc arc;
186: #endif
1.2 timbl 187:
1.40 frystyk 188: PUBLIC char * HTAppName = "CERN-LineMode"; /* Application name */
189: PUBLIC char * HTAppVersion = VL; /* Application version */
190: PUBLIC int HTScreenWidth = SCREEN_WIDTH; /* By default */
191: PUBLIC int HTScreenHeight = -1; /* -1 = Undefined */
192: PUBLIC BOOL display_anchors = YES; /* Show anchors in text? */
193: PUBLIC char * start_reference = NULL; /* Format for start anchor */
194: PUBLIC char * end_reference = REF_MARK; /* for end anchor */
195: PUBLIC char * reference_mark = "[%d] "; /* for reference lists */
196: PUBLIC char * end_mark = END_MARK; /* Format string for [End] */
1.1 timbl 197:
1.40 frystyk 198: /* Type definitions and global variables local to this module */
199: PRIVATE HTRequest * request = NULL;
200: PRIVATE HTList * reqlist = NULL; /* List of active requests */
201: PRIVATE HTParentAnchor* home_anchor = NULL; /* First document anchor */
202: PRIVATE char keywords[ADDRESS_LENGTH]; /* From command line */
203: PRIVATE char * output_file_name = NULL; /* -o xxxx */
204: PRIVATE char choice[RESPONSE_LENGTH]; /* Users response */
205: PRIVATE char * refhead = DEFAULT_REF_HEAD; /* Ref list heading */
206: PRIVATE char * logfile_root = NULL; /* Log file name */
207: PRIVATE BOOL filter = NO; /* Load from stdin? */
208: PRIVATE BOOL reformat_html = NO; /* Reformat html? */
209: PRIVATE BOOL listrefs_option = NO; /* -listrefs option used? */
210: PRIVATE BOOL OutSource = NO; /* Output source, YES/NO */
211: PRIVATE char * HTLogFileName = NULL; /* Root of log file name */
212: PRIVATE int OldTraceFlag = SHOW_ALL_TRACE;
1.47 frystyk 213: PRIVATE HTList * conversions = NULL; /* Format conversions */
1.48.2.1 frystyk 214: PRIVATE BOOL UseMulti = YES; /* Use multithreaded */
1.8 duns 215:
216: #ifdef VMS
217: PRIVATE FILE * output; /* assignment done in main */
1.17 duns 218: #ifdef __DECC
219: /* dummy declarations to make sure that LINKER will not complain */
220: PUBLIC char *HTBinDir;
221: PUBLIC int HTDiag;
222: PUBLIC char *HTPostScript;
223: PUBLIC char *HTPutScript;
224: PUBLIC char *HTSearchScript;
225: #endif /* DECC */
1.8 duns 226: #else /* not VMS */
1.4 timbl 227: PRIVATE FILE * output = stdout;
1.8 duns 228: #endif /* not VMS */
1.4 timbl 229:
1.40 frystyk 230: /* ------------------------------------------------------------------------- */
231: /* HELP FUNCTIONS */
232: /* ------------------------------------------------------------------------- */
1.7 secret 233:
234: #ifdef GET_SCREEN_SIZE
235: #include <sys/ioctl.h>
236: /*
1.40 frystyk 237: ** Get size of the output screen. Stolen from less.
238: */
239: PRIVATE void scrsize ARGS2(int *, p_height, int *, p_width)
1.7 secret 240: {
241: register char *s;
242: int ioctl();
243: struct winsize w;
244:
245: if (ioctl(2, TIOCGWINSZ, &w) == 0 && w.ws_row > 0)
246: *p_height = w.ws_row;
247: else
248: if ((s = getenv("LINES")) != NULL)
249: *p_height = atoi(s);
250: else
251: *p_height = SCREEN_HEIGHT;
252:
253: if (ioctl(2, TIOCGWINSZ, &w) == 0 && w.ws_col > 0)
254: *p_width = w.ws_col;
255: else
256: if ((s = getenv("COLUMNS")) != NULL)
257: *p_width = atoi(s);
258: else
259: *p_width = 80;
260: }
261: #endif /* GET_SCREEN_SIZE, BSN */
262:
1.48.2.1 frystyk 263: #ifdef CATCH_SIG
264: #include <signal.h>
265: /* SetSignal
266: ** This function sets up signal handlers. This might not be necessary to
267: ** call if the application has its own handlers.
268: */
269: PRIVATE void SetSignal NOARGS
270: {
271: /* On some systems (SYSV) it is necessary to catch the SIGPIPE signal
272: ** when attemting to connect to a remote host where you normally should
273: ** get `connection refused' back
274: */
275: if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) {
276: if (PROT_TRACE) fprintf(stderr, "HTSignal.... Can't catch SIGPIPE\n");
277: } else {
278: if (PROT_TRACE) fprintf(stderr, "HTSignal.... Ignoring SIGPIPE\n");
279: }
280: }
281: #endif /* CATCH_SIG */
282:
1.7 secret 283:
1.40 frystyk 284: /* Display Help screen Help_screen
285: ** -------------------
286: ** Produce a help screen, displaying the current document address and
287: ** a list of * available commands *in this context*. * ?? Perhaps this
288: ** should be a hypertext page, not included in the history list.
1.1 timbl 289: */
1.40 frystyk 290: PRIVATE void help_screen NOARGS {
291:
292: char * current_address = HTAnchor_address((HTAnchor*)HTMainAnchor);
293: CONST char * title = HTAnchor_title(HTMainAnchor);
294:
295: printf("\n\nWWW LineMode Browser version %s (WWWLib %s) COMMANDS AVAILABLE\n\n",
296: VL, HTLibraryVersion);
297: if (title) printf("You are reading\n \"%s\"\nwhose address is\n %s\n\n",
298: title, current_address);
299: else printf("You are reading a document whose address is\n '%s' \n\n",
300: current_address);
301:
302: if (HText_canScrollDown(HTMainText)) {
303: printf(
304: " <RETURN> Move down one page within the document.\n");
305: printf(
306: " BOttom Go to the last page of the document.\n");
307: };
308:
309: if (HText_canScrollUp(HTMainText)) {
310: printf(
311: " Top Return to the first page of the document.\n");
312: printf(
313: " Up Move up one page within the document\n");
314: };
315:
316: if (HText_sourceAnchors(HTMainText) != 0) {
317: printf(" List List the references from this document.\n *");
318: printf(" <number> Select a referenced document by number (from 1 to %d).\n",
319: HText_sourceAnchors(HTMainText));
320: }
321:
1.48.2.1 frystyk 322: if (UseMulti) {
323: printf(" z Interrupt a request\n");
324: }
325:
1.40 frystyk 326: if (HTAnchor_isIndex(HTMainAnchor)) {
327: printf(
328: " Find <words> Search this index for given words (separated by spaces).\n");
329: }
330:
331: if (HTHistory_canBacktrack()) {
332: printf(" Recall List visited documents.\n");
333: printf(" Recall <number> Return to a previously visited document\n");
334: printf(" as numbered in the recall list.\n");
335: printf(" HOme Return to the starting document.\n");
336: printf(" Back Move back to the last document.\n");
337: }
338:
339: if (HTHistory_canMoveBy(1))
340: printf(" Next Take next link from last document.\n");
341:
342: if (HTHistory_canMoveBy(-1))
343: printf(" Previous Take previous link from last document.\n");
1.1 timbl 344:
1.40 frystyk 345: printf(" REFresh Refresh screen with current document\n");
346: printf(" Go <address> Go to document of given [relative] address\n");
347:
348: #ifdef GOT_SYSTEM
349: if (!HTClientHost) { /* NOT for telnet guest! */
350: printf(" PRInt Print text of this document. *\n");
351: printf(" ! <command> Execute shell <command> without leaving.\n");
352: printf(" > <file> Save the text of this document in <file>. *\n");
353: printf(" If <file> exists use '>!' to overwrite it.\n");
354: printf(" >> <file> Append the text of this document to <file>. *\n");
355: printf(" | <command> Pipe this document to the shell <command>. *\n");
356: #ifdef unix
357: printf(" CD <directory> Change local working directory.\n");
358: #endif
359: printf("* Prefix these commands with \"Source \" to use raw source.\n\n");
360: }
361: #endif
362:
363: #ifdef SLAVE_PRINTER
364: printf(
365: " Ps Print text of this document to Terminal's Slave printer.\n");
1.1 timbl 366: #endif
1.40 frystyk 367:
368: printf(" Verbose Switch to %sverbose mode.\n", WWW_TraceFlag ? "non-" : "");
369:
370: printf(" Help Display this page.\n");
371: printf(" Manual Jump to the online manual for this program\n");
372: printf(" Quit Leave the www program.\n");
373: printf("\n");
374: free(current_address);
375: } /* End of help_screen */
1.1 timbl 376:
377:
1.40 frystyk 378: /* Reference_List
379: ** --------------
380: ** Print out a list of HyperText References accumulated within the text.
381: **
382: ** On entry
383: ** titles Set: if we want titles where available
384: ** Clear: we only get addresses.
385: */
1.7 secret 386:
1.40 frystyk 387: PRIVATE void Reference_List ARGS1(BOOL, titles)
388: {
1.48.2.1 frystyk 389: int cnt;
390: int refs = HText_sourceAnchors(HTMainText);
391: if (refs <= 0) {
1.40 frystyk 392: fprintf(output, "\n\nThere are no references from this document.\n\n");
393: } else {
394: fprintf(output, "\n%s\n", refhead);
1.48.2.1 frystyk 395: for (cnt=1; cnt<=refs; cnt++) {
396: HTAnchor *dest =
397: HTAnchor_followMainLink((HTAnchor *)
398: HText_childNumber(HTMainText, cnt));
399: HTParentAnchor * parent = HTAnchor_parent(dest);
400: char * address = HTAnchor_address(dest);
401: CONST char * title = titles ? HTAnchor_title(parent) : NULL;
402: fprintf(output, reference_mark, cnt);
1.40 frystyk 403: fprintf(output, "%s%s\n",
1.48.2.1 frystyk 404: ((HTAnchor*)parent!=dest) && title ? "in " : "",
1.40 frystyk 405: (char *)(title ? title : address));
406: free(address);
407: }
408: fflush(stdout);
409: }
410: }
1.1 timbl 411:
412:
1.40 frystyk 413: /* History_List
414: ** ------------
415: */
416: /* Display a history list of nodes visited during the session.
417: ** ?? This should really be a hypertext page (not itself in history!).
418: ** ?? Should have option to display address even when anchor has a title.
1.1 timbl 419: */
420:
1.40 frystyk 421: PRIVATE void History_List NOARGS {
1.38 frystyk 422:
1.40 frystyk 423: int history_number = 1;
424: printf("\n Documents you have visited:-\n\n");
1.1 timbl 425:
1.40 frystyk 426: do {
1.1 timbl 427:
1.40 frystyk 428: char * address;
429: CONST char * title;
430: HTAnchor * anchor = HTHistory_read(history_number);
431: HTParentAnchor * parent;
1.1 timbl 432:
1.40 frystyk 433: if (!anchor) break;
434: parent = HTAnchor_parent(anchor);
435: title = HTAnchor_title(parent);
436: address = HTAnchor_address(anchor);
437: #ifdef VIOLA
438: printf("\017R %2d\016) %s%s\n", /* SI user field SO */
1.1 timbl 439: #else
1.40 frystyk 440: printf("R %2d) %s%s\n",
1.1 timbl 441: #endif
1.40 frystyk 442: history_number,
443: ((HTAnchor*)parent!=anchor) && title ? "in " : "",
444: title ? title : address);
445: free(address);
446:
447: history_number++;
448:
449: } while (YES);
1.1 timbl 450:
1.40 frystyk 451: printf("\n");
1.1 timbl 452: }
453:
454:
1.40 frystyk 455: /* MakeCommandLine
1.1 timbl 456: **
1.40 frystyk 457: ** Generate the Prompt line and flush it to the user
1.1 timbl 458: */
1.40 frystyk 459: PRIVATE void MakeCommandLine ARGS1(BOOL, is_index)
460: {
461: int length_of_prompt = 0;
1.1 timbl 462:
1.40 frystyk 463: #ifndef VM /* Normal prompt */
464: if (is_index){
465: printf("FIND <keywords>, ");
466: length_of_prompt = length_of_prompt + 14;
467: }
468: if (HTAnchor_hasChildren(HTMainAnchor)!=0){
469: int refs = HText_sourceAnchors(HTMainText);
470: if (refs>1) {
471: printf("1-%d, ", refs);
472: length_of_prompt = length_of_prompt + 6; /* Roughly */
473: }
474: else {
475: printf("1, ");
476: length_of_prompt = length_of_prompt + 3;
477: }
478: }
479: if (HTHistory_canBacktrack()){
480: printf(PROMPT_MARK, "Back"); printf(", ");
481: #ifdef LONG_PROMPT
482: printf(PROMPT_MARK, "Recall"); printf(", ");
483: #endif
484: length_of_prompt = length_of_prompt + 6;
485: }
486: if (HText_canScrollUp(HTMainText)){
487: printf(PROMPT_MARK,"Up"); printf(", ");
488: length_of_prompt = length_of_prompt + 4;
489: }
490: if (HText_canScrollDown(HTMainText)) {
491: printf("<RETURN> for more, ");
492: length_of_prompt = length_of_prompt + 19;
493: }
494: if (length_of_prompt <= 47) {
495: printf(PROMPT_MARK, "Quit"); printf(", ");
496: }
1.1 timbl 497:
1.40 frystyk 498: printf("or Help: ");
499:
500: #else /* Special prompt for VM assuming PF keys set*/
501: if (is_index) {
502: printf("FIND <words>, "); /* 14 */
503: length_of_prompt = length_of_prompt + 14;
504: }
505: if (HTAnchor_hasChildren(HTMainAnchor)!=0){
506: int refs = HText_sourceAnchors(HTMainText);
507: if (refs>1) {
508: printf("1-%d, ", refs);
509: length_of_prompt = length_of_prompt + 6; /* approx 6 */
510: }
511: else {
512: printf("1, ");
513: length_of_prompt = length_of_prompt + 3;
514: }
515: }
516: if (HTHistory_canMoveBy(1)) {
517: printf("PF2=Next ");
518: length_of_prompt = length_of_prompt + 9; /* 9 */
519: }
520: printf("PF3=Quit PF4=Return, ");
521: length_of_prompt = length_of_prompt + 21; /* 21 */
1.1 timbl 522:
1.40 frystyk 523: if (HTHistory_canBacktrack()){
524: printf("Recall, ");
525: length_of_prompt = length_of_prompt + 8; /* 8 */
1.1 timbl 526: }
1.40 frystyk 527: if (HText_canScrollUp(HTMainText)){
528: printf(PROMPT_MARK,"PF7=Up "); printf(", ");
529: length_of_prompt = length_of_prompt + 7; /* 7 */
1.1 timbl 530: }
1.40 frystyk 531: if (HText_canScrollDown(HTMainText)){
532: printf("PF8=Down ");
533: length_of_prompt = length_of_prompt + 9; /* 9 */
1.1 timbl 534: }
1.40 frystyk 535: if (length_of_prompt<70) printf("PF11=Help"); /* 9 */
536: /* EQUAL 82 */
1.1 timbl 537: #endif
538:
1.44 frystyk 539: fflush(stdout); /* For use to flush out the prompt */
1.40 frystyk 540: return;
541: }
1.1 timbl 542:
1.40 frystyk 543: /* ErrMsg
544: **
545: ** General Error Message for Line Mode Browser. If verbose mode is on, then
546: ** the message is passed to stderr.
547: **
548: */
549: PRIVATE void ErrMsg ARGS2(char *, Msg, char *, Str)
550: {
1.44 frystyk 551: if (TRACE || HTInteractive)
552: fprintf(stderr, "Warning: %s (%s)\n", Msg, Str ? Str : "");
1.40 frystyk 553: }
1.1 timbl 554:
1.40 frystyk 555: /* ------------------------------------------------------------------------- */
556: /* EVENT FUNCTIONS */
557: /* ------------------------------------------------------------------------- */
1.1 timbl 558:
1.40 frystyk 559: /*
560: ** This function creates a new request structure and adds it to the global
561: ** list of active threads
1.1 timbl 562: */
1.40 frystyk 563: PRIVATE HTRequest *Thread_new ARGS1(BOOL, Interactive)
564: {
565: HTRequest *newreq = HTRequest_new(); /* Set up a new request */
566: if (!reqlist)
567: reqlist = HTList_new();
1.47 frystyk 568: if (Interactive) {
569: HTList_delete(newreq->conversions);
570: newreq->conversions = conversions; /* Take from global list */
571: } else
572: HTFormatInitNIM(newreq->conversions);
1.48.2.1 frystyk 573: if (!UseMulti)
574: request->BlockingIO = YES; /* Use blocking I/O */
1.40 frystyk 575: HTList_addObject(reqlist, (void *) newreq);
576: return newreq;
577: }
1.1 timbl 578:
579:
1.40 frystyk 580: /*
581: ** This function deletes a request structure and takes it out of the list
582: ** of active threads.
583: */
584: PRIVATE void Thread_delete ARGS1(HTRequest *, oldreq)
585: {
586: if (oldreq) {
587: if (reqlist)
588: HTList_removeObject(reqlist, (void *) oldreq);
1.48 frystyk 589: if (oldreq->conversions == conversions)
590: oldreq->conversions = NULL; /* We keep them in a global list */
1.40 frystyk 591: HTRequest_delete(oldreq);
592: }
593: }
1.1 timbl 594:
1.47 frystyk 595:
1.40 frystyk 596: /*
597: ** This function deletes the whole list of active threads.
598: */
599: PRIVATE void Thread_deleteAll NOARGS
600: {
1.47 frystyk 601: BOOL first=YES; /* We only have one global list of conversions */
1.40 frystyk 602: if (reqlist) {
603: HTList *cur = reqlist;
604: HTRequest* pres;
1.47 frystyk 605: while ((pres = (HTRequest *) HTList_nextObject(cur)) != NULL) {
606: if (first) {
607: HTRequest_delete(pres);
608: first = NO;
609: } else {
610: pres->conversions = NULL;
611: HTRequest_delete(pres);
612: }
613: }
1.40 frystyk 614: HTList_delete(reqlist);
615: reqlist = NULL;
616: }
617: }
1.1 timbl 618:
619:
620: /*
1.40 frystyk 621: ** This function puts up a stream to a file in order to save a document. This
622: ** is activated by '>', '>>' or '>!' from the prompt line.
1.47 frystyk 623: ** Returns:
624: ** YES if load terminated (either success or failure)
625: ** NO if error or operation blocked
1.1 timbl 626: **
1.40 frystyk 627: ** Henrik Frystyk 02/03-94
1.1 timbl 628: */
1.40 frystyk 629: PRIVATE BOOL SaveOutputStream ARGS2(char *, This, char *, Next)
630: {
631: FILE *fp;
632: char *fname;
633: char *fmode;
634:
635: /* Checks if file exists. Can be overruled by using '>!' */
636: if (*(This+1) == '>') { /* Append to file */
637: fmode = "a";
638: fname = *(This+2) ? (This+2) : Next;
639: } else if (*(This+1) == '!') {
640: fmode = "w"; /* Overwrite file */
641: fname = *(This+2) ? (This+2) : Next;
642: } else { /* File name follows */
643: fmode = "w";
644: fname = *(This+1) ? (This+1) : Next;
645: if (fname) { /* See if file exists */
646: if ((fp = fopen(fname, "r")) != NULL) {
647: printf("%s: File exists\n", fname);
648: fclose(fp);
649: return NO;
650: }
651: }
652: }
653: if (!fname) /* No file name given */
654: return NO;
655: if ((fp = fopen(fname, fmode)) == NULL) {
656: ErrMsg("Can't access file", fname);
657: return NO;
658: }
1.1 timbl 659:
1.40 frystyk 660: /* Now, file is open and OK: reload the text and put up a stream for it! */
1.47 frystyk 661: if (TRACE)
662: fprintf(stderr, "Saving to file %s\n", fname);
1.40 frystyk 663: {
1.47 frystyk 664: int status;
1.40 frystyk 665: HTRequest *req = Thread_new(NO); /* Set up a new request */
1.47 frystyk 666: if (OutSource)
1.40 frystyk 667: req->output_format = WWW_SOURCE;
668: req->output_stream = HTFWriter_new(fp, NO);
669: HTForceReload = YES;
1.47 frystyk 670: status = HTLoadAnchor((HTAnchor*) HTMainAnchor, req);
1.40 frystyk 671: HTForceReload = NO;
1.47 frystyk 672: return (status != HT_WOULD_BLOCK);
1.40 frystyk 673: }
674: }
1.1 timbl 675:
676:
1.40 frystyk 677: /* EventHandler
678: **
679: ** Read in the user's input, and deal with it as necessary.
680: **
681: ** Any Command which works returns from the routine. If nothing
682: ** works then a search or error message down at the bottom.
1.1 timbl 683: */
1.47 frystyk 684: PUBLIC HTEventState EventHandler ARGS1(HTRequest **, actreq)
1.1 timbl 685: {
1.40 frystyk 686: int ref_num;
1.46 frystyk 687: HTEventState status = EVENT_OK;
1.40 frystyk 688: char * the_choice = 0; /* preserved user command */
689: char * this_word = 0; /* First word of command */
690: char * this_command; /* this_word and following */
691: char * next_word; /* Second word */
692: char * other_words; /* Second word and following */
1.14 frystyk 693: BOOL is_index = HTAnchor_isIndex(HTMainAnchor);
1.48 frystyk 694: BOOL found = YES;
1.47 frystyk 695: int loadstat = HT_INTERNAL;
1.40 frystyk 696:
697: if (!fgets(choice, RESPONSE_LENGTH, stdin)) /* Read User Input */
698: return EVENT_QUIT; /* Exit if EOF */
699:
700: StrAllocCopy (the_choice, choice); /* Remember it as is, */
701: if (the_choice[strlen(the_choice)-1] == '\n') /* The final \n */
702: the_choice[strlen(the_choice)-1] = '\0';
1.14 frystyk 703:
1.40 frystyk 704: #ifdef VM /* Clear the screen (on screen-mode systems) */
705: clear_screen();
706: #endif
707: this_word = strtok (choice, " \t\n\r"); /* Tokenize user input */
708: this_command = the_choice;
709: if (this_word) {
710: next_word = strtok (NULL, " \t\n\r");
711: other_words = the_choice + (next_word - choice);
1.14 frystyk 712: }
1.40 frystyk 713: else
714: goto down; /* Empty input : scroll down */
715:
716: /* Process Command */
717: loop:
718: switch (TOUPPER(*this_word)) {
719: case '0':
720: case '1':
721: case '2':
722: case '3':
723: case '4':
724: case '5':
725: case '6':
726: case '7':
727: case '8':
728: case '9':
729: sscanf(this_word,"%d",&ref_num);
730: if (ref_num>0 && ref_num<=HText_sourceAnchors(HTMainText)) {
731: HTAnchor *destination;
732: HTChildAnchor *source = HText_childNumber(HTMainText, ref_num);
1.45 frystyk 733: if (source) {
1.47 frystyk 734: *actreq = Thread_new(YES);
1.44 frystyk 735: destination = HTAnchor_followMainLink((HTAnchor*) source);
1.47 frystyk 736: (*actreq)->parentAnchor = HTAnchor_parent((HTAnchor *) source);
737: loadstat = HTLoadAnchor(destination, *actreq);
1.45 frystyk 738: } else {
739: status = EVENT_QUIT; /* No anchor */
1.44 frystyk 740: }
741: } else {
742: if (TRACE || HTInteractive)
743: fprintf(stderr, "Warning: Invalid Reference Number: (%d)\n",
744: ref_num);
1.40 frystyk 745: }
746: break;
747:
748: case 'B':
749: if (Check_User_Input("BACK")) { /* Return to previous node */
750: if (HTHistory_canBacktrack()) {
1.47 frystyk 751: *actreq = Thread_new(YES);
752: loadstat = HTLoadAnchor(HTHistory_backtrack(), *actreq);
1.40 frystyk 753: } else {
754: printf("\n The BACK command cannot be used,");
755: printf(" as there are no previous documents\n");
756: }
1.47 frystyk 757: } else if (Check_User_Input("BOTTOM")) { /* Scroll to bottom */
1.40 frystyk 758: HText_scrollBottom(HTMainText);
1.48 frystyk 759: } else
760: found = NO;
1.40 frystyk 761: break;
762:
763: #ifdef unix
764: case 'C':
1.48 frystyk 765: if (Check_User_Input("CD")) { /* Change working directory ? */
1.40 frystyk 766: goto lcd;
1.48 frystyk 767: } else
768: found = NO;
1.40 frystyk 769: break;
770: #endif
771:
772: case 'D':
773: if (Check_User_Input("DOWN")) { /* Scroll down one page */
774: down:
775: if (HText_canScrollDown(HTMainText))
776: HText_scrollDown(HTMainText);
1.48 frystyk 777: } else
778: found = NO;
1.40 frystyk 779: break;
780:
781: case 'E': /* Quit program ? Alternative command */
1.48 frystyk 782: if (Check_User_Input("EXIT")) {
1.47 frystyk 783: status = EVENT_QUIT;
1.48 frystyk 784: } else
785: found = NO;
1.40 frystyk 786: break;
787:
788: case 'F': /* Keyword search ? */
789: if (is_index && Check_User_Input("FIND")) {
790: find:
1.47 frystyk 791: {
792: if (next_word) {
793: *actreq = Thread_new(YES);
794: loadstat = HTSearch(other_words, HTMainAnchor, *actreq);
795: }
796: }
1.48 frystyk 797: } else
798: found = NO;
1.40 frystyk 799: break;
800:
801: case 'G':
802: if (Check_User_Input("GOTO")) { /* GOTO */
803: if (next_word) {
1.47 frystyk 804: *actreq = Thread_new(YES);
805: loadstat = HTLoadRelative(next_word, HTMainAnchor, *actreq);
1.40 frystyk 806: }
1.48 frystyk 807: } else
808: found = NO;
1.40 frystyk 809: break;
810:
811: case '?':
812: help_screen();
1.47 frystyk 813: break;
1.40 frystyk 814:
815: case 'H':
1.47 frystyk 816: if (Check_User_Input("HELP")) { /* help menu, ..*/
1.40 frystyk 817: help_screen(); /*!! or a keyword search ? */
1.47 frystyk 818: } else if (Check_User_Input("HOME")) { /* back HOME */
819: if (!HTHistory_canBacktrack()) {
1.40 frystyk 820: HText_scrollTop(HTMainText);
821: } else {
1.47 frystyk 822: *actreq = Thread_new(YES);
823: loadstat = HTLoadAnchor(HTHistory_recall(1), *actreq);
1.40 frystyk 824: }
1.48 frystyk 825: } else
826: found = NO;
1.40 frystyk 827: break;
828:
829: case 'K': /* Keyword search ? */
830: if (is_index && Check_User_Input("KEYWORDS")) {
831: goto find;
1.48 frystyk 832: } else
833: found = NO;
1.40 frystyk 834: break;
835:
836: case 'L':
1.47 frystyk 837: if (Check_User_Input("LIST")) { /* List of references ? */
1.40 frystyk 838: Reference_List(!OutSource);
839: }
840: #ifdef unix
841: else if (Check_User_Input ("LCD")) { /* Local change dir ? */
842: lcd:
843: if (!next_word) { /* Missing argument */
844: printf ("\nName of the new local directory missing.\n");
1.47 frystyk 845: } else if (chdir (next_word)) { /* failed : say why */
1.40 frystyk 846: fprintf (stderr, "\n ");
847: perror (next_word);
1.47 frystyk 848: } else { /* Success : display new local directory */
1.40 frystyk 849: /* AS Sep 93 */
850: #ifdef NO_GETWD /* No getwd() on this machine */
851: #ifdef HAS_GETCWD /* System V variant SIGN CHANGED TBL 921006 !! */
852: printf ("\nLocal directory is now:\n %s\n",
853: getcwd (choice, sizeof(choice)));
854: #else /* has NO getcwd */
855: ErrMsg("This platform does not support getwd() or getcwd()",
856: NULL);
857: #endif /* has no getcwd */
858: #else /* has getwd */
859: printf("\nLocal directory is now:\n %s\n",
860: (char *) getwd (choice));
861: #endif /* has getwd */
862: /* End AS Sep 93 */
863: }
864: }
865: #endif
1.48 frystyk 866: else
867: found = NO;
1.40 frystyk 868: break;
869:
870: case 'M':
871: if (Check_User_Input("MANUAL")) { /* Read User manual */
1.47 frystyk 872: *actreq = Thread_new(YES);
873: loadstat = HTLoadRelative(MANUAL, HTMainAnchor,*actreq);
1.48 frystyk 874: } else
875: found = NO;
1.40 frystyk 876: break;
877:
878: case 'N':
879: if (Check_User_Input("NEXT")) {
880: if (!HTHistory_canMoveBy(1)) { /* No nodes to jump back to */
881: printf("\n Can't take the NEXT link from the last");
882: if (!HTHistory_canBacktrack())
883: printf(" document as there is no last");
884: printf(" document.\n");
1.47 frystyk 885: } else {
886: *actreq = Thread_new(YES);
887: loadstat = HTLoadAnchor(HTHistory_moveBy(1),*actreq);
1.40 frystyk 888: }
1.48 frystyk 889: } else
890: found = NO;
1.40 frystyk 891: break;
892:
893: case 'P':
894: if (Check_User_Input("PREVIOUS")) {
895: if (!HTHistory_canMoveBy(-1)){
896: printf("\n Can't take the PREVIOUS link from the last");
897: if (!HTHistory_canBacktrack())
898: printf(" document as there is no last");
899: printf(" document.\n");
1.47 frystyk 900: } else {
901: *actreq = Thread_new(YES);
902: loadstat = HTLoadAnchor(HTHistory_moveBy(-1), *actreq);
1.40 frystyk 903: }
904: }
905: #ifdef GOT_SYSTEM
906: else if (!HTClientHost && Check_User_Input("PRINT")) {
907: char * address = HTAnchor_address((HTAnchor *) HTMainAnchor);
908: char * command;
1.46 frystyk 909: char * tmplate = (char*)getenv("WWW_PRINT_COMMAND");
1.40 frystyk 910: int result;
911:
1.46 frystyk 912: if (!tmplate) tmplate = "www -n -na -p66 '%s' | lpr";
913: command = (char *) malloc(strlen(address)+strlen(tmplate)+20);
914: sprintf(command, tmplate, address);
1.40 frystyk 915: result = system(command);
916: free(address);
917: free(command);
918: if (result) printf(" %s\n returns %d\n", command, result);
919: }
920: #endif
921: /* this command prints the entire current text to the
922: terminal's printer; at the end it displays the top of the text */
923: #ifdef SLAVE_PRINTER
924: #define SLAVE_PRINTER_ON "\033\133\065\151"
925: #define SLAVE_PRINTER_OFF "\033\133\064\151"
926:
1.47 frystyk 927: else if (Check_User_Input("PS")) {
1.40 frystyk 928: printf ("%s",SLAVE_PRINTER_ON);
929: printf("\f"); /* Form feed for new page */
930: HText_scrollTop(HTMainText);
931: while(HText_canScrollDown(HTMainText)) {
932: HText_scrollDown(HTMainText);
933: }
934: printf("\f"); /* Form feed for new page */
935: printf ("%s",SLAVE_PRINTER_OFF);
936: HText_scrollTop(HTMainText);
937: }
938: #endif
1.48 frystyk 939: else
940: found = NO;
1.40 frystyk 941: break;
942:
943: case 'Q': /* Quit program ? */
944: if (Check_User_Input("QUIT")) {
1.47 frystyk 945:
1.40 frystyk 946: /* JFG 9/7/92, following a complaint of 'q' mis-typed for '1'.
947: JFG Then made optional because I hate it !!!
948: TBL made it only affect remote logged on users. 921122 */
949:
950: if (HTClientHost && (strcasecomp(this_word, "quit") != 0) ) {
951: printf ("\n Please type \"quit\" in full to leave www.\n");
1.47 frystyk 952: } else
953: status = EVENT_QUIT;
1.48 frystyk 954: } else
955: found = NO;
1.40 frystyk 956: break;
957:
958: case 'R':
959: #ifdef VM
960: if (Check_User_Input("RETURN")) /* Means quit program */
1.47 frystyk 961: status = EVENT_QUIT;
962: else
1.40 frystyk 963: #endif
964: if (Check_User_Input("RECALL")) {
965: int recall_node_num;
966:
967: if (!HTHistory_canBacktrack()) { /* No nodes to recall */
968: printf("\n No other documents to recall.\n");
1.47 frystyk 969: } else {
970: /* Previous node number exists, or does the user just */
971: /* require a list of nodes visited? */
972: if (next_word) {
973: if ((recall_node_num = atoi(next_word)) > 0) {
974: *actreq = Thread_new(YES);
975: loadstat =
976: HTLoadAnchor(HTHistory_recall(recall_node_num),
977: *actreq);
978: } else {
979: ErrMsg("Bad command, for list of commands type help.",
980: this_command);
981: }
982: } else {
983: History_List();
984: }
1.40 frystyk 985: }
986: } else if (Check_User_Input("REFRESH")) {
1.48.2.1 frystyk 987: HText_setStale(HTMainText); /* Force refresh */
988: HText_refresh(HTMainText); /* Refresh screen */
1.48 frystyk 989: } else
990: found = NO;
1.40 frystyk 991: break;
992:
993: case 'S': /* TBL 921009 */
994: if (Check_User_Input("SOURCE")) { /* Apply to source */
1.47 frystyk 995: if (next_word) {
996: OutSource = YES; /* Load and print as source */
997: this_word = next_word; /* Move up one word */
998: next_word = strtok (NULL, " \t\n\r");
999: this_command = the_choice + (this_word - choice);
1000: other_words = the_choice + (next_word - choice);
1001: goto loop; /* Go treat as before */
1002: }
1.40 frystyk 1003: } else if (Check_User_Input("SET")) { /* config */
1004: HTSetConfiguration(other_words);
1.48 frystyk 1005: } else
1006: found = NO;
1.40 frystyk 1007: break;
1008:
1009: case 'T':
1010: if (Check_User_Input("TOP")) { /* Return to top */
1011: HText_scrollTop(HTMainText);
1.48 frystyk 1012: } else
1013: found = NO;
1.40 frystyk 1014: break;
1015:
1016: case 'U':
1017: if (Check_User_Input("UP")) { /* Scroll up one page */
1018: HText_scrollUp(HTMainText);
1.48 frystyk 1019: } else
1020: found = NO;
1.40 frystyk 1021: break;
1022:
1023: case 'V':
1024: if (Check_User_Input("VERBOSE")) { /* Switch verbose mode */
1025: WWW_TraceFlag = WWW_TraceFlag ? 0 : OldTraceFlag;
1026: printf ("\n Verbose mode %s.\n", WWW_TraceFlag ? "ON":"OFF");
1.48 frystyk 1027: } else
1028: found = NO;
1.40 frystyk 1029: break;
1030:
1031: case 'Z':
1.48.2.1 frystyk 1032: HText_setStale(HTMainText); /* Force refresh */
1033: HText_refresh(HTMainText); /* Refresh screen */
1.44 frystyk 1034: status = EVENT_INTR_ALL;
1035: break;
1.40 frystyk 1036:
1037: case '>':
1038: if (!HTClientHost) {
1.47 frystyk 1039: if (SaveOutputStream(this_word, next_word))
1040: loadstat = HT_WOULD_BLOCK;
1.40 frystyk 1041: }
1042: break;
1.1 timbl 1043:
1.40 frystyk 1044: #ifdef GOT_PIPE
1045: case '|':
1046: if (!HTClientHost) { /* Local only!!!! */
1047: char * address = HTAnchor_address((HTAnchor *) HTMainAnchor);
1048: char * command;
1049: int result;
1050: command = (char*) malloc(strlen(address) +strlen(this_command)+30);
1051:
1052: #ifdef VM
1053: sprintf(command, "PIPE CMS WWW %s \"%s\" | %s",
1054: OutSource ? "-source" : "-n -na -p", address,this_command);
1055:
1056: #else
1057: sprintf(command, "www %s \"%s\" %s",
1058: OutSource ? "-source" : "-n -na -p", address,this_command);
1059: #endif
1060: printf("Command: %s\n", command);
1061: result = system(command);
1062: if (result)
1063: printf(" %s returns %d\n", command, result);
1064: free(command);
1065: free(address);
1.14 frystyk 1066: }
1.47 frystyk 1067: break;
1.40 frystyk 1068: #endif
1069:
1070: #ifdef GOT_SYSTEM
1071: case '!':
1072: if (!HTClientHost) { /* Local only! */
1073: int result;
1074: ErrMsg("Executing", this_command);
1075: result = system(strchr(this_command, '!') + 1);
1076: if (result) printf(" %s returns %d\n",
1077: strchr(this_command, '!') + 1, result);
1.1 timbl 1078: }
1.47 frystyk 1079: break;
1.1 timbl 1080: #endif
1.40 frystyk 1081: default:
1.48 frystyk 1082: found = NO;
1083: break;
1084: } /* Switch on 1st character */
1085:
1086: if (!found) {
1087: if (is_index && *this_word) { /* No commands, search keywords */
1.47 frystyk 1088: next_word = other_words = this_command;
1.48 frystyk 1089: found = YES;
1.47 frystyk 1090: goto find;
1091: } else {
1092: ErrMsg("Bad command, for list of commands type help.",
1093: this_command);
1094: }
1.48 frystyk 1095: }
1.47 frystyk 1096: if (loadstat != HT_INTERNAL && loadstat != HT_WOULD_BLOCK)
1097: status = EVENT_TERM;
1.48.2.4! frystyk 1098: if (loadstat != HT_LOADED && loadstat != HT_ERROR)
1.47 frystyk 1099: MakeCommandLine(is_index);
1.40 frystyk 1100: free (the_choice);
1.44 frystyk 1101: return status;
1.40 frystyk 1102: }
1103:
1104:
1105: /* HTEventRequestTerminate
1.1 timbl 1106: **
1.40 frystyk 1107: ** React to the status of the terminated request
1.1 timbl 1108: */
1.40 frystyk 1109: PUBLIC HTEventState HTEventRequestTerminate ARGS2(HTRequest *, actreq,
1110: int, status)
1111: {
1112: BOOL is_index = HTAnchor_isIndex(HTMainAnchor);
1113: if (status == HT_LOADED) {
1114: if (actreq->parentAnchor) {
1115: HTParentAnchor *parent = actreq->parentAnchor;
1116: HTParentAnchor *destination = actreq->anchor;
1117: HTHistory_leavingFrom((HTAnchor *) parent);
1118: HTHistory_record((HTAnchor *) destination);
1119: actreq->parentAnchor = NULL;
1.14 frystyk 1120: }
1.40 frystyk 1121: /* Now generate the new prompt line as a function of the result */
1122: if (!HText_canScrollDown(HTMainText) &&
1123: !HTAnchor_hasChildren(HTMainAnchor) && !is_index &&
1124: (!HTHistory_canBacktrack())) {
1125: ErrMsg("No way out of here, so I exit!", NULL);
1126: return EVENT_QUIT; /* Exit if no other options */
1127: }
1128: HText_setStale(HTMainText); /* We corrupt the display */
1129: MakeCommandLine(is_index);
1130: } else if (!HTMainText) /* If first try failed */
1131: return EVENT_QUIT;
1.48.2.2 frystyk 1132: else
1133: MakeCommandLine(is_index);
1.47 frystyk 1134: Thread_delete(actreq);
1.40 frystyk 1135: return EVENT_OK;
1136: }
1.1 timbl 1137:
1.40 frystyk 1138: /* ------------------------------------------------------------------------- */
1139: /* MAIN PROGRAM */
1140: /* ------------------------------------------------------------------------- */
1.1 timbl 1141:
1.40 frystyk 1142: int main ARGS2(int, argc, char **, argv)
1143: {
1144: int return_status = 0;
1145: int arg; /* Argument number as we scan */
1146: BOOL argument_found = NO;
1147: BOOL logfile_flag = NO;
1148: BOOL first_keyword = YES;
1149: char * default_default = HTFindRelatedName();
1150: HTFormat input_format = WWW_HTML; /* Used with filter */
1151: HTEventCallBack user; /* To register STDIN for user events */
1.1 timbl 1152:
1.40 frystyk 1153: #ifdef THINK_C /* command line from Think_C */
1154: int i;
1155: argc=ccommand(&argv);
1156: #endif
1157:
1158: /* HWL 18/7/94: applied patch from
1159: agl@glas2.glas.apc.org (Anton Tropashko) */
1160: #ifdef CYRILLIC
1161: arc.locale=0; arc.encoding=0; arc.i_encoding=0; doinull();
1.1 timbl 1162: #endif
1163:
1.40 frystyk 1164: #ifdef VMS
1165: output = stdout;
1166: #endif /* VMS */
1.1 timbl 1167:
1.40 frystyk 1168: request = HTRequest_new();
1169:
1170: /* Check for command line options */
1171: *keywords = '\0';
1172: for (arg=1; arg<argc ; arg++) {
1173: if (*argv[arg] == '-') {
1174:
1175: /* - alone => filter */
1176: if (argv[arg][1] == 0) {
1177: filter = YES;
1178: HTInteractive = NO; /* From stdin, Force non-interactive */
1179:
1180: /* -? or -help: show the command line help page */
1181: } else if (!strcmp(argv[arg], "-?") ||
1182: !strcmp(argv[arg], "-help")) {
1183: home_anchor = (HTParentAnchor *)
1184: HTAnchor_findAddress(COM_HELP_FILE);
1185: argument_found = YES; /* Don't try to find other pages */
1186:
1187: /* from -- Initial represntation (only with filter) */
1188:
1189: } else if (!strcmp(argv[arg], "-from")) {
1190: input_format = (arg+1 >= argc || *argv[arg+1] == '-') ?
1191: WWW_HTML : HTAtom_for(argv[++arg]);
1192:
1193: #ifdef CYRILLIC
1194: /* HWL 18/7/94: applied patch from agl@glas2.glas.apc.org
1195: (Anton Tropashko) */
1196: } else if (!strcmp(argv[arg], "-koi2alt")) {
1197: doia2k(); printf("Ahak2a!");
1198: #endif
1199:
1200: /* Page size */
1201: } else if (!strncmp(argv[arg], "-p", 2)) {
1202: if (*(argv[arg]+2)) {
1203: if (sscanf(argv[arg]+2, "%d", &HTScreenHeight) < 1)
1204: HTScreenHeight = -1;
1205: else {
1206: if(HTScreenHeight < MIN_SCREEN_HEIGHT)
1207: HTScreenHeight = MIN_SCREEN_HEIGHT;
1208: if(HTScreenHeight > MAX_SCREEN_HEIGHT)
1209: HTScreenHeight = MAX_SCREEN_HEIGHT;
1210: }
1211: } else if (arg+1 < argc && *argv[arg+1] != '-') {
1212: if (sscanf(argv[++arg], "%d", &HTScreenHeight) < 1)
1213: HTScreenHeight = -1;
1214: else {
1215: if(HTScreenHeight < MIN_SCREEN_HEIGHT)
1216: HTScreenHeight = MIN_SCREEN_HEIGHT;
1217: if(HTScreenHeight > MAX_SCREEN_HEIGHT)
1218: HTScreenHeight = MAX_SCREEN_HEIGHT;
1219: }
1220: }
1.1 timbl 1221:
1.40 frystyk 1222: /* Page width */
1223: } else if (!strncmp(argv[arg], "-w", 2)) {
1224: if (*(argv[arg]+2)) {
1225: if (sscanf(argv[arg]+2, "%d", &HTScreenWidth) < 1)
1226: HTScreenWidth = SCREEN_WIDTH;
1227: } else if (arg+1 < argc && *argv[arg+1] != '-') {
1228: if (sscanf(argv[++arg], "%d", &HTScreenWidth) < 1)
1229: HTScreenWidth = SCREEN_WIDTH;
1.14 frystyk 1230: }
1.40 frystyk 1231: if(HTScreenWidth < MIN_SCREEN_WIDTH)
1232: HTScreenWidth = MIN_SCREEN_WIDTH;
1233: if(HTScreenWidth > MAX_SCREEN_WIDTH)
1234: HTScreenWidth = MAX_SCREEN_WIDTH;
1235:
1236: /* reformat html */
1237: } else if (!strcmp(argv[arg], "-reformat")) {
1238: request->output_format = WWW_HTML;
1239: HTInteractive = NO;
1240: reformat_html = YES;
1.1 timbl 1241:
1.48.2.1 frystyk 1242: /* Specify a cache root (caching is otherwise disabled) */
1243: } else if (!strcmp(argv[arg], "-cacheroot")) {
1244: StrAllocCopy(HTCacheDir,
1245: (arg+1>=argc || *argv[arg+1]=='-') ?
1246: CACHE_HOME_DIR : argv[++arg]);
1247:
1248: /* to -- Final representation */
1.40 frystyk 1249: } else if (!strcmp(argv[arg], "-to")) {
1250: request->output_format =
1251: (arg+1 >= argc || *argv[arg+1] == '-') ?
1252: WWW_PRESENT :
1253: HTAtom_for(argv[++arg]);
1254: HTInteractive = NO; /* JFG */
1.1 timbl 1255:
1.40 frystyk 1256: /* Telnet from */
1257: } else if (!strcmp(argv[arg], "-h")) {
1258: if (arg+1 < argc && *argv[arg+1] != '-') {
1259: HTClientHost = argv[++arg]; /* Use host name */
1.14 frystyk 1260: }
1.40 frystyk 1261:
1262: /* Log file */
1263: } else if (!strcmp(argv[arg], "-l")) {
1264: if (arg+1 < argc && *argv[arg+1] != '-')
1265: logfile_root = argv[++arg];
1266: logfile_flag = YES;
1267:
1268: /* List References */
1269: } else if (!strcmp(argv[arg], "-listrefs")) {
1270: listrefs_option = YES;
1271: HTInteractive = NO; /* non-interactive */
1272:
1273: /* Method Used (Currently on GET and HEAD are supported) */
1274: } else if (!strcmp(argv[arg], "-m")) {
1275: HTInteractive = NO;
1276: if (++arg < argc) {
1277: if (!strcasecomp(argv[arg], "head")) {
1278: request->method = METHOD_HEAD;
1279: request->output_format = WWW_MIME;
1280: } else if (!strcasecomp(argv[arg], "get"))
1281: request->method = METHOD_GET;
1282: else
1283: request->method = METHOD_INVALID;
1.1 timbl 1284: }
1.40 frystyk 1285:
1286: /* Non-interactive */
1287: } else if (!strcmp(argv[arg], "-n")) {
1288: HTInteractive = NO;
1289:
1.48.2.1 frystyk 1290: /* Multithreaded ot not? */
1291: } else if (!strcmp(argv[arg], "-single")) {
1292: UseMulti = NO;
1293:
1.40 frystyk 1294: /* Output filename */
1295: } else if (!strcmp(argv[arg], "-o")) {
1296: output_file_name = (arg+1 < argc && *argv[arg+1] != '-') ?
1297: argv[++arg] : DEFAULT_OUTPUT_FILE;
1298: HTInteractive = NO;
1299:
1300: /* Anchor format */
1301: } else if (!strcmp(argv[arg], "-a")) {
1302: if (arg+1 < argc && *argv[arg+1] != '-')
1303: end_reference = argv[++arg]; /* New representation */
1304:
1305: /* Anchor format */
1306: } else if (!strcmp(argv[arg], "-ar")) {
1307: if (arg+1 < argc && *argv[arg+1] != '-')
1308: reference_mark = argv[++arg]; /* Change representation */
1309:
1310: /* Anchor format */
1311: } else if (!strcmp(argv[arg], "-as")) {
1312: if (arg+1 < argc && *argv[arg+1] != '-')
1313: start_reference = argv[++arg]; /* Change representation */
1314:
1315: /* No anchors */
1316: } else if (!strcmp(argv[arg], "-na")) {
1317: display_anchors = NO;
1318:
1319: #ifndef NO_RULES
1320: } else if (!strcmp(argv[arg], "-r")) {
1321: if (arg+1 < argc && *argv[arg+1] != '-') {
1322: if (HTLoadRules(argv[++arg]) < 0) {
1323: ErrMsg("Can't open rule file", argv[arg]);
1324: return_status = -1;
1325: goto endproc;
1326: }
1.14 frystyk 1327: }
1.1 timbl 1328: #endif
1.40 frystyk 1329: #ifndef NO_DIR_OPTIONS
1330: } else if (!strncmp(argv[arg], "-d", 2)) {
1331: char *p = argv[arg]+2;
1332: for(;*p;p++) {
1333: switch (argv[arg][2]) {
1334: case 'b': HTDirReadme = HT_DIR_README_BOTTOM; break;
1335: case 'n': HTDirAccess = HT_DIR_FORBID; break;
1336: case 'r': HTDirReadme = HT_DIR_README_NONE; break;
1337: case 's': HTDirAccess = HT_DIR_SELECTIVE; break;
1338: case 't': HTDirReadme = HT_DIR_README_TOP; break;
1339: case 'y': HTDirAccess = HT_DIR_OK; break;
1340: default:
1341: ErrMsg("Bad parameter for directory listing -d option",
1342: argv[arg]);
1343: return_status = -4;
1344: goto endproc;
1345: }
1346: } /* loop over characters */
1347: #endif
1348: /* Reference list heading */
1349: } else if (!strcmp(argv[arg], "-refhead")) {
1350: if (arg+1 < argc && *argv[arg+1] != '-')
1351: refhead = argv[++arg];
1.1 timbl 1352:
1.40 frystyk 1353: /* Print version and exit */
1354: } else if (!strcmp(argv[arg], "-version")) {
1355: printf("WWW LineMode Browser version %s (WWW Library %s)\n",
1356: VL, HTLibraryVersion);
1357: goto endproc;
1.1 timbl 1358:
1.40 frystyk 1359: #ifdef TRACE
1360: /* Verify: Turns on trace */
1361: } else if (!strncmp(argv[arg], "-v", 2)) {
1362: char *p = argv[arg]+2;
1363: WWW_TraceFlag = 0;
1364: for(; *p; p++) {
1365: switch (*p) {
1366: case 'a': WWW_TraceFlag += SHOW_ANCHOR_TRACE; break;
1367: case 'p': WWW_TraceFlag += SHOW_PROTOCOL_TRACE; break;
1368: case 's': WWW_TraceFlag += SHOW_SGML_TRACE; break;
1369: case 't': WWW_TraceFlag += SHOW_THREAD_TRACE; break;
1370: case 'u': WWW_TraceFlag += SHOW_URI_TRACE; break;
1371: default:
1372: ErrMsg("Bad parameter for verbose mode", argv[arg]);
1373: }
1374: }/* loop over characters */
1375: if (!WWW_TraceFlag)
1376: WWW_TraceFlag = SHOW_ALL_TRACE;
1377: OldTraceFlag = WWW_TraceFlag; /* Remember setting */
1.1 timbl 1378: #endif
1.14 frystyk 1379:
1.40 frystyk 1380: /* Source please */
1381: } else if (!strcmp(argv[arg], "-source")) {
1382: request->output_format = WWW_SOURCE;
1383: HTInteractive = NO; /* JFG */
1384:
1385: #ifdef THINK_C
1386: /* Echo to file */
1387: } else if (!strcmp(argv[arg], "-e")){
1388: struct tm *tm_now; time_t time_now;
1389: cecho2file("ThinkCconsole",FALSE,stdout);
1390: time_now=time(NULL);tm_now=localtime(&time_now);
1391: printf("\n--------------------------------------------"
1392: "\n Time: %d.%.2d.%.2d %d:%d:%d\n"
1393: "--------------------------------------------\n",
1394: (*tm_now).tm_year,
1395: (*tm_now).tm_mon+1,
1396: (*tm_now).tm_mday,
1397: (*tm_now).tm_hour,
1398: (*tm_now).tm_min,
1399: (*tm_now).tm_sec);
1400:
1401: /* debug socket library */
1402: } else if (!strcmp(argv[arg], "-s")) {
1403: socketdebug=1;
1.1 timbl 1404: #endif
1.40 frystyk 1405: /* endif long list of argument options */
1.1 timbl 1406:
1.40 frystyk 1407: } else {
1408: ErrMsg("Bad Command Line Argument", argv[arg]);
1409: }
1410: } else { /* If no leading `-' then check for main argument */
1411: if (!argument_found) {
1412: char * ref = HTParse(argv[arg], default_default, PARSE_ALL);
1413: home_anchor = (HTParentAnchor*) HTAnchor_findAddress(ref);
1414: free(ref);
1415: argument_found = YES;
1416: } else { /* Check for successive keyword arguments */
1417: if (first_keyword) { /* Collect keywords */
1418: first_keyword = NO;
1.14 frystyk 1419: } else {
1.40 frystyk 1420: strcat(keywords, " ");
1.14 frystyk 1421: }
1.40 frystyk 1422: strcat(keywords,HTStrip(argv[arg]));
1423: } /* argument already found */
1424: } /* Not an option '-'*/
1425: } /* End of argument loop */
1426:
1427: /* Initialization */
1.44 frystyk 1428: HTLibInit();
1.40 frystyk 1429: if (HTClientHost) HTSecure = YES; /* Access to local files? */
1430: HTEnableFrom = YES; /* Send `From:' in the request? */
1.48.2.1 frystyk 1431: #ifdef CATCH_SIG
1432: SetSignal();
1433: #endif
1.40 frystyk 1434: if (HTScreenHeight == -1) { /* Default page size */
1435: if (HTInteractive) {
1436: #ifdef GET_SCREEN_SIZE
1437: int scr_height, scr_width;
1438: scrsize(&scr_height, &scr_width);
1439: HTScreenHeight = scr_height;
1440: #else
1.42 frystyk 1441: HTScreenHeight = SCREEN_HEIGHT;
1.1 timbl 1442: #endif
1.40 frystyk 1443: } else
1.42 frystyk 1444: HTScreenHeight = 999999;
1.40 frystyk 1445: }
1.23 frystyk 1446:
1.48.2.3 frystyk 1447: /* Siable free directory browsing when using telnet host */
1448: if (HTClientHost && HTDirAccess==HT_DIR_OK)
1449: HTDirAccess = HT_DIR_SELECTIVE;
1.1 timbl 1450:
1.40 frystyk 1451: #ifndef NO_RULES
1452: {
1453: char * rules = getenv("WWW_CONFIG");
1454: if (rules && HTLoadRules(rules) < 0) {
1455: ErrMsg("Cant't open rule file", rules);
1456: }
1457: }
1458: #endif
1.1 timbl 1459:
1.40 frystyk 1460: /* Force predefined presentations etc to be set up */
1.47 frystyk 1461: if (HTInteractive) {
1462: conversions = HTList_new();
1463: HTFormatInit(conversions);
1464: HTList_delete(request->conversions);
1465: request->conversions = conversions;
1466: } else
1.40 frystyk 1467: HTFormatInitNIM(request->conversions);
1.4 timbl 1468:
1.40 frystyk 1469: /* Open output file */
1470: if (!HTInteractive) {
1471: if (output_file_name) {
1472: FILE * fp = fopen(output_file_name, "w");
1473: if (!fp) {
1474: ErrMsg("Can't open file for writing", output_file_name);
1475: return_status = -3;
1476: goto endproc;
1.14 frystyk 1477: }
1.40 frystyk 1478: output = fp;
1479: }
1480: request->output_stream = HTFWriter_new(output,
1481: output == stdout ? YES : NO);
1482: /* Just pump to stdout but YES: leave it open */
1483:
1484: /* To reformat HTML, just put it through a parser running
1485: ** into a regenerator tbl 940613 */
1486:
1487: if (reformat_html) {
1488: request->output_stream = SGML_new(&HTMLP_dtd,
1489: HTMLGenerator(request->output_stream));
1.1 timbl 1490:
1.40 frystyk 1491: }
1492: }
1493:
1494: /* Open Log File. Logfile via Telnet is now optional (HENRIK 11/02-94) */
1495: if (logfile_flag) {
1496: if(!logfile_root)
1497: logfile_root = HTClientHost ?
1498: DEFAULT_LOGFILE : DEFAULT_LOCAL_LOGFILE;
1499: HTLogFileName = (char*) malloc(strlen(logfile_root)+20);
1.14 frystyk 1500:
1.40 frystyk 1501: #ifdef NO_GETPID
1502: sprintf(HTLogFileName, "%s", logfile_root); /* No getpid() */
1503: #else
1504: sprintf(HTLogFileName, "%s-%d", logfile_root, (int) getpid());
1.14 frystyk 1505: #endif
1.40 frystyk 1506: HTlogfile = fopen(HTLogFileName, "a");
1507: if (!HTlogfile)
1508: ErrMsg("Can't open log file", HTLogFileName);
1509: };
1.14 frystyk 1510:
1.40 frystyk 1511: /* Make home page address */
1512: if (!home_anchor)
1513: home_anchor = HTHomeAnchor();
1.1 timbl 1514:
1.40 frystyk 1515: /* Now we are ready to start the program! If in interactive mode then start
1516: the event loop which will run until the program terminates */
1517: if (filter) { /* Just convert formats */
1518: HTBindAnchor((HTAnchor*)home_anchor, request);
1519: HTParseSocket(input_format, 0, request); /* From std UNIX input */
1520: goto endproc;
1521: }
1522: if (HTInteractive) {
1523: reqlist = HTList_new();
1524: user.sockfd = STDIN_FILENO;
1525: user.callback = EventHandler;
1526: HTList_addObject(reqlist, (void *) request);
1.45 frystyk 1527: HTEventRegister(&user); /* Register STDIN */
1528: HTHistory_record((HTAnchor *) home_anchor); /* Setup history */
1.40 frystyk 1529: return_status = HTEventLoop(request, home_anchor,
1530: (keywords && *keywords) ? keywords : NULL);
1531: } else {
1.48 frystyk 1532: request->BlockingIO = YES; /* Turn off non-blocking I/O */
1.40 frystyk 1533: if (((keywords && *keywords) ?
1534: HTSearch(keywords, home_anchor, request) :
1535: HTLoadAnchor((HTAnchor*) home_anchor, request)) != HT_LOADED) {
1536: char *addr = HTAnchor_address((HTAnchor *) home_anchor);
1537: ErrMsg("Can't access document", addr);
1538: free(addr);
1539: if (!HTMainText) {
1540: return_status = -2; /* Can't get first page */
1.14 frystyk 1541: }
1.48.2.1 frystyk 1542: } else if (listrefs_option) {
1543: Reference_List(NO); /* List without titles */
1.1 timbl 1544: }
1.34 frystyk 1545: }
1.18 frystyk 1546:
1.40 frystyk 1547: endproc:
1548: Thread_deleteAll();
1.48.2.1 frystyk 1549: if (default_default)
1.40 frystyk 1550: free(default_default);
1.48.2.4! frystyk 1551: HTLibTerminate();
1.48.2.1 frystyk 1552: printf("\n");
1553: if (!return_status) { /* Everything is working :-) */
1.40 frystyk 1554: #ifdef VMS
1555: return 1;
1556: #else
1557: return 0; /* Good */
1558: #endif
1.18 frystyk 1559: }
1.40 frystyk 1560: return return_status; /* An error occured somewhere */
1.14 frystyk 1561: }
1.1 timbl 1562:
1.18 frystyk 1563: /* End HTBrowse.c */
1.14 frystyk 1564:
Webmaster