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