Annotation of libwww/LineMode/src/HTBrowse.c, revision 1.103
1.44 frystyk 1: /* HTBrowse.c
2: ** HYPERTEXT BROWSER FOR DUMB TERMINALS
3: **
1.62 frystyk 4: ** (c) COPRIGHT MIT 1995.
1.44 frystyk 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
1.61 frystyk 9: ** TBL: Tim Berners-Lee CERN (timbl@w3.org)
10: ** JFG: Jean-Francois Groff, Cooperant CERN 1991-92 (jfg@dxcern.cern.ch)
1.1 timbl 11: ** DR: Dudu Rashty +972-2-584848 <RASHTY@hujivms.bitnet>
1.8 duns 12: ** MD: Mark Donszelmann, DELPHI CERN, (duns@vxdeop.cern.ch)
1.96 frystyk 13: ** HFN: Henrik Frystyk Nielsen, MIT, (frystyk@w3.org)
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
1.99 frystyk 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.96 frystyk 55: #include "WWWLib.h"
56: #include "WWWMIME.h"
57: #include "WWWApp.h"
1.92 frystyk 58:
1.96 frystyk 59: #include "GridText.h" /* Hypertext definition */
1.68 frystyk 60: #include "HTBrowse.h" /* Things exported, short names */
1.40 frystyk 61:
62: #ifndef VL
63: #define VL "unspecified"
64: #endif
65:
1.96 frystyk 66: #define APP_NAME "W3CLineMode"
67: #define APP_VERSION VL
1.86 frystyk 68:
1.68 frystyk 69: /* Default page for "Manual" command */
1.96 frystyk 70: #define MANUAL "http://www.w3.org/pub/WWW/LineMode/Defaults/QuickGuide.html"
1.40 frystyk 71:
1.68 frystyk 72: /* Default page for "help" command */
1.96 frystyk 73: #define C_HELP "http://www.w3.org/pub/WWW/LineMode/Defaults/Commands.html"
1.1 timbl 74:
1.68 frystyk 75: /* Default page for "-help" command line option */
1.96 frystyk 76: #define L_HELP "http://www.w3.org/pub/WWW/LineMode/Defaults/CommandLine.html"
1.37 howcome 77:
1.68 frystyk 78: #define DEFAULT_OUTPUT_FILE "www.out"
79: #define DEFAULT_RULE_FILE "www.conf"
80: #define DEFAULT_LOG_FILE "www.log"
81:
82: #define PROMPT "%s"
83: #define REF_MARK "[%d]"
84: #define END_MARK "[END]"
1.1 timbl 85:
1.72 frystyk 86: #define SCREEN_WIDTH 79 /* Default width of the screen */
1.13 frystyk 87: #define MIN_SCREEN_WIDTH 10
88: #define MAX_SCREEN_WIDTH 150
1.72 frystyk 89: #define SCREEN_HEIGHT 24 /* Default number of lines */
1.13 frystyk 90: #define MIN_SCREEN_HEIGHT 5
1.14 frystyk 91: #define MAX_SCREEN_HEIGHT 200
1.72 frystyk 92:
93: #define MAX_HISTORY 20 /* Don't list more than this in list */
1.1 timbl 94:
1.68 frystyk 95: #define RESPONSE_LENGTH 1024 /* Maximum length of users response */
1.16 frystyk 96:
1.94 frystyk 97: #define SHOW_MSG (WWWTRACE || HTAlert_interactive())
1.68 frystyk 98: #define CHECK_INPUT(a, b) (!strncasecomp ((a), (b), strlen((b))))
1.50 frystyk 99:
1.96 frystyk 100: #define DEFAULT_I_TIMEOUT 1 /* Interactive timeout in seconds */
101: #define DEFAULT_NI_TIMEOUT 10 /* Non-interactive timeout in seconds */
102:
103: #define DEFAULT_FORMAT WWW_PRESENT
1.81 frystyk 104:
1.50 frystyk 105: #if defined(ultrix) || defined(__osf__)
106: #define GET_SCREEN_SIZE
1.16 frystyk 107: #endif
1.1 timbl 108:
1.50 frystyk 109: #if defined(__svr4__)
110: #define CATCH_SIG
111: #endif
1.40 frystyk 112:
113: /* HWL 18/7/94: applied patch from agl@glas2.glas.apc.org (Anton Tropashko) */
114: #ifdef CYRILLIC
1.68 frystyk 115: #include "a_stdio.h"
1.40 frystyk 116: struct ARc arc;
117: #endif
1.2 timbl 118:
1.68 frystyk 119: /* Screen size parameters */
1.40 frystyk 120: PUBLIC int HTScreenWidth = SCREEN_WIDTH; /* By default */
121: PUBLIC int HTScreenHeight = -1; /* -1 = Undefined */
1.68 frystyk 122:
123: /* Anchor specific information */
1.40 frystyk 124: PUBLIC BOOL display_anchors = YES; /* Show anchors in text? */
125: PUBLIC char * start_reference = NULL; /* Format for start anchor */
126: PUBLIC char * end_reference = REF_MARK; /* for end anchor */
127: PUBLIC char * reference_mark = "[%d] "; /* for reference lists */
128: PUBLIC char * end_mark = END_MARK; /* Format string for [End] */
1.8 duns 129:
1.96 frystyk 130: typedef enum _LMFlags {
131: LM_FILTER = 0x1,
132: LM_REFS = 0x2,
133: LM_REFORMAT = 0x4,
134: LM_PREEMTIVE= 0x8
135: } LMFlags;
136:
137: typedef struct _LineMode {
138: HTRequest * request;
1.98 frystyk 139: HTRequest * tty;
1.96 frystyk 140: HTParentAnchor * anchor;
141: HTParentAnchor * dest; /* Destination for PUT etc. */
142: struct timeval * tv; /* Timeout on socket */
143: HTList * active; /* List of acitve contexts */
144: HTList * converters;
145: HTList * presenters;
146: HTHistory * history; /* History list */
147: char * cwd; /* Current dir URL */
148: char * rules;
149: char * logfile;
150: char * outputfile;
151: char * host;
152: int trace;
153: HTFormat format; /* Input format from console */
154: LMFlags flags;
155: } LineMode;
156:
157: typedef enum _LMState {
158: LM_UPDATE = 0x1,
159: LM_NO_UPDATE= 0x2,
160: LM_DONE = 0x4,
161: LM_INACTIVE = 0x8
162: } LMState;
163:
164: typedef struct _Context {
165: LMState state;
166: HTRequest * request;
167: LineMode * lm;
168: } Context;
1.4 timbl 169:
1.99 frystyk 170: #ifndef _WINDOWS
1.96 frystyk 171: PRIVATE FILE * output = STDOUT;
1.99 frystyk 172: #endif
1.96 frystyk 173:
1.62 frystyk 174: /* ------------------------------------------------------------------------- */
175:
1.96 frystyk 176: /* Create a Context Object
177: ** -----------------------
178: */
179: PRIVATE Context * Context_new (LineMode * lm, HTRequest * request)
180: {
181: Context * me = (Context *) calloc(1, sizeof (Context));
182: if (!me) outofmem(__FILE__, "Context_new");
183: me->state = LM_UPDATE;
184: me->request = request;
185: me->lm = lm;
186: HTRequest_setContext(request, (void *) me);
1.72 frystyk 187: return me;
188: }
189:
1.96 frystyk 190: /* Delete a Context Object
191: ** -----------------------
1.72 frystyk 192: */
1.96 frystyk 193: PRIVATE BOOL Context_delete (Context * old)
1.72 frystyk 194: {
195: FREE(old);
196: return YES;
197: }
198:
1.62 frystyk 199: /*
1.96 frystyk 200: ** This function creates a new request object and adds it to the global
1.62 frystyk 201: ** list of active threads
202: */
1.96 frystyk 203: PRIVATE HTRequest * Thread_new (LineMode * lm, BOOL Interactive)
1.62 frystyk 204: {
1.96 frystyk 205: HTRequest * newreq = HTRequest_new();
206: Context * context = Context_new(lm, newreq);
207: if (!lm) return NULL;
208: if (!lm->active) lm->active = HTList_new();
209: if (Interactive) HTRequest_setConversion(newreq, lm->presenters, NO);
210: if (lm->flags & LM_PREEMTIVE) HTRequest_setPreemtive(newreq, YES);
211: HTList_addObject(lm->active, (void *) context);
1.80 frystyk 212: HTRequest_addRqHd(newreq, HT_HOST);
1.62 frystyk 213: return newreq;
214: }
215:
216: /*
1.96 frystyk 217: ** This function deletes all unused request objects
1.62 frystyk 218: */
1.96 frystyk 219: PRIVATE void Thread_cleanup (LineMode * lm)
1.62 frystyk 220: {
1.96 frystyk 221: if (lm && lm->active) {
222: HTList * cur = lm->active;
223: Context * pres;
224: while ((pres = (Context *) HTList_nextObject(cur))) {
225: if (pres->state & (LM_DONE | LM_INACTIVE)) {
226: HTList_removeObject(lm->active, pres);
227: HTRequest_delete(pres->request);
228: Context_delete(pres);
229: cur = lm->active;
230: }
231: }
1.62 frystyk 232: }
233: }
234:
235: /*
236: ** This function deletes the whole list of active threads.
237: */
1.96 frystyk 238: PRIVATE void Thread_deleteAll (LineMode * lm)
1.62 frystyk 239: {
1.96 frystyk 240: if (lm && lm->active) {
241: HTList * cur = lm->active;
242: Context * pres;
243: while ((pres = (Context *) HTList_nextObject(cur))) {
244: if (pres->request) HTRequest_delete(pres->request);
1.62 frystyk 245: }
1.96 frystyk 246: HTList_delete(lm->active);
247: lm->active = NULL;
1.62 frystyk 248: }
249: }
250:
1.96 frystyk 251: /* Create a Line Mode Object
252: ** -------------------------
253: */
1.101 frystyk 254: #ifdef _WINDOWS
255: HTRequest * TTYReq = 0; /* The windowed version doesn't get the HTRequest* when
256: it gets key events so save it in a global here */
257: #endif
258:
1.96 frystyk 259: PRIVATE LineMode * LineMode_new (void)
260: {
261: LineMode * me;
262: if ((me = (LineMode *) calloc(1, sizeof(LineMode))) == NULL ||
263: (me->tv = (struct timeval*) calloc(1, sizeof(struct timeval))) == NULL)
264: outofmem(__FILE__, "LineMode_new");
265: me->tv->tv_sec = -1;
266: me->cwd = HTFindRelatedName();
267: me->active = HTList_new();
268: me->request = HTRequest_new();
1.98 frystyk 269: me->tty = HTRequest_new();
1.101 frystyk 270: #ifdef _WINDOWS
271: TTYReq = me->tty;
272: #endif
1.96 frystyk 273: Context_new(me, me->request);
1.101 frystyk 274: Context_new(me, me->tty);
1.96 frystyk 275: return me;
276: }
277:
278: /* Delete a Line Mode Object
279: ** -------------------------
280: */
281: PRIVATE BOOL LineMode_delete (LineMode * lm)
282: {
283: if (lm) {
284: Context * context = (Context *) HTRequest_context(lm->request);
285: HTRequest_delete(lm->request);
1.98 frystyk 286: HTRequest_delete(lm->tty);
1.96 frystyk 287: Context_delete(context);
288: free(lm->tv);
289: Thread_deleteAll(lm);
290: HTConversion_deleteAll(lm->converters);
291: HTPresentation_deleteAll(lm->presenters);
292: HTHistory_delete(lm->history);
293: FREE(lm->cwd);
294: if (lm->logfile) HTLog_close();
1.99 frystyk 295: #ifndef _WINDOWS
296: if (OUTPUT && OUTPUT != STDOUT) fclose(OUTPUT);
297: #endif
1.96 frystyk 298: free(lm);
299: return YES;
300: }
301: return NO;
302: }
303:
304: PRIVATE void Cleanup (LineMode * me, int status)
305: {
306: if (HTAlert_interactive()) /* Terminate with a LF if not interactive */
307: TTYPrint(OUTPUT, "\n");
308: LineMode_delete(me);
309: HTLibTerminate();
310: #ifdef VMS
311: exit(status ? status : 1);
312: #else
313: exit(status ? status : 0);
314: #endif
315: }
1.7 secret 316:
317: #ifdef GET_SCREEN_SIZE
1.50 frystyk 318: #include <sys/ioctl.h>
1.7 secret 319: /*
1.100 frystyk 320: ** Get size of the output screen. Stolen from less.
1.40 frystyk 321: */
1.90 frystyk 322: PRIVATE void scrsize (int * p_height, int * p_width)
1.7 secret 323: {
1.96 frystyk 324: register char *s;
325: int ioctl();
326: struct winsize w;
327: if (ioctl(2, TIOCGWINSZ, &w) == 0 && w.ws_row > 0)
328: *p_height = w.ws_row;
329: else if ((s = getenv("LINES")) != NULL)
330: *p_height = atoi(s);
331: else
332: *p_height = SCREEN_HEIGHT;
333:
334: if (ioctl(2, TIOCGWINSZ, &w) == 0 && w.ws_col > 0)
335: *p_width = w.ws_col;
336: else if ((s = getenv("COLUMNS")) != NULL)
337: *p_width = atoi(s);
338: else
339: *p_width = 80;
1.7 secret 340: }
341: #endif /* GET_SCREEN_SIZE, BSN */
342:
1.50 frystyk 343: #ifdef CATCH_SIG
344: #include <signal.h>
345: /* SetSignal
346: ** This function sets up signal handlers. This might not be necessary to
347: ** call if the application has its own handlers.
348: */
1.90 frystyk 349: PRIVATE void SetSignal (void)
1.50 frystyk 350: {
351: /* On some systems (SYSV) it is necessary to catch the SIGPIPE signal
352: ** when attemting to connect to a remote host where you normally should
353: ** get `connection refused' back
354: */
355: if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) {
1.89 frystyk 356: if (PROT_TRACE) TTYPrint(TDEST, "HTSignal.... Can't catch SIGPIPE\n");
1.50 frystyk 357: } else {
1.89 frystyk 358: if (PROT_TRACE) TTYPrint(TDEST, "HTSignal.... Ignoring SIGPIPE\n");
1.50 frystyk 359: }
360: }
361: #endif /* CATCH_SIG */
362:
1.96 frystyk 363: /* Print version information
364: ** -------------------------
365: */
366: PRIVATE void VersionInfo (void)
367: {
368: TTYPrint(OUTPUT,"\n\nW3C Reference Software\n\n");
369: TTYPrint(OUTPUT,"\tW3C Line Mode Browser version %s.\n", APP_VERSION);
370: TTYPrint(OUTPUT,"\tW3C Reference Library version %s.\n\n",HTLib_version());
371: TTYPrint(OUTPUT,"Please send feedback to <www-bug@w3.org>\n");
372: }
1.7 secret 373:
1.40 frystyk 374: /* Reference_List
375: ** --------------
1.96 frystyk 376: ** Print out a list of HyperText References from current document
1.40 frystyk 377: */
1.96 frystyk 378: PRIVATE void Reference_List (LineMode * lm, BOOL titles)
1.40 frystyk 379: {
1.50 frystyk 380: int refs = HText_sourceAnchors(HTMainText);
381: if (refs <= 0) {
1.99 frystyk 382: TTYPrint(OUTPUT,"\n\nThere are no references from this document.\n\n");
1.40 frystyk 383: } else {
1.68 frystyk 384: int cnt;
1.99 frystyk 385: TTYPrint(OUTPUT, "\n*** References from this document ***\n");
1.50 frystyk 386: for (cnt=1; cnt<=refs; cnt++) {
387: HTAnchor *dest =
388: HTAnchor_followMainLink((HTAnchor *)
389: HText_childNumber(HTMainText, cnt));
390: HTParentAnchor * parent = HTAnchor_parent(dest);
391: char * address = HTAnchor_address(dest);
392: CONST char * title = titles ? HTAnchor_title(parent) : NULL;
1.99 frystyk 393: TTYPrint(OUTPUT, reference_mark, cnt);
394: TTYPrint(OUTPUT, "%s%s\n",
1.50 frystyk 395: ((HTAnchor*)parent!=dest) && title ? "in " : "",
1.40 frystyk 396: (char *)(title ? title : address));
397: free(address);
398: }
1.99 frystyk 399: #ifndef _WINDOWS
400: fflush(OUTPUT);
401: #endif
1.40 frystyk 402: }
403: }
1.1 timbl 404:
1.96 frystyk 405: /* History_List
406: ** ------------
1.68 frystyk 407: ** Display a history list of nodes visited during the session.
1.1 timbl 408: */
1.96 frystyk 409: PRIVATE void History_List (LineMode * lm)
410: {
411: int current = HTHistory_position(lm->history);
412: int max = HTHistory_count(lm->history);
1.70 frystyk 413: int cnt;
1.99 frystyk 414: TTYPrint(OUTPUT, "\n Documents you have visited: ");
1.70 frystyk 415: if (max > MAX_HISTORY) {
416: max = MAX_HISTORY;
1.99 frystyk 417: TTYPrint(OUTPUT, "(truncated)\n");
1.70 frystyk 418: } else
1.99 frystyk 419: TTYPrint(OUTPUT, "\n");
1.70 frystyk 420: for (cnt=1; cnt<=max; cnt++) {
1.96 frystyk 421: HTAnchor *anchor = HTHistory_list(lm->history, cnt);
1.70 frystyk 422: char *address = HTAnchor_address(anchor);
423: HTParentAnchor *parent = HTAnchor_parent(anchor);
424: CONST char *title = HTAnchor_title(parent);
1.99 frystyk 425: TTYPrint(OUTPUT, "%s R %d\t%s%s\n",
1.70 frystyk 426: (cnt==current) ? "*" : " ",
427: cnt,
1.68 frystyk 428: ((HTAnchor*)parent!=anchor) && title ? "in " : "",
429: title ? title : address);
1.40 frystyk 430: free(address);
1.70 frystyk 431: }
1.99 frystyk 432: TTYPrint(OUTPUT, "\n");
1.1 timbl 433: }
434:
1.94 frystyk 435: /* Prompt for answer and get text back. Reply text is either NULL on
436: ** error or a dynamic string which the caller must free.
437: */
438: PRIVATE char * AskUser (HTRequest * request, CONST char * Msg,
1.96 frystyk 439: CONST char * deflt)
1.94 frystyk 440: {
441: char buffer[200];
442: char *reply = NULL;
443: TTYPrint(TDEST, "%s ", Msg ? Msg : "UNKNOWN");
444: if (deflt)
445: TTYPrint(TDEST, "(RETURN for [%s]) ", deflt);
446:
447: #ifndef NO_STDIO
448: if (!fgets(buffer, 200, stdin))
449: return NULL; /* NULL string on error, Henrik */
450: buffer[strlen(buffer)-1] = '\0'; /* Overwrite newline */
451: if (*buffer)
452: StrAllocCopy(reply, buffer);
453: else if (deflt)
454: StrAllocCopy(reply, deflt);
455: #endif
456: return reply;
457: }
458:
459: PRIVATE BOOL confirm (HTRequest * request, CONST char * Msg)
460: {
1.96 frystyk 461: char response[4];
462: TTYPrint(TDEST, "%s (y/n) ", Msg ? Msg : "UNKNOWN");
1.94 frystyk 463: #ifndef NO_STDIO
1.96 frystyk 464: if (fgets(response, 4, stdin)) /* get reply, max 3 chars */
1.94 frystyk 465: #endif
1.96 frystyk 466: {
467: char *ptr = response;
468: while (*ptr) {
469: if (*ptr == '\n') {
470: *ptr = '\0';
471: break;
472: }
473: *ptr = TOUPPER(*ptr);
474: ptr++;
475: }
476: return (!strcmp(response, "YES") || !strcmp(response, "Y")) ? YES : NO;
1.94 frystyk 477: }
1.96 frystyk 478: return NO;
1.94 frystyk 479: }
1.1 timbl 480:
1.96 frystyk 481: /* MakeCommandLine
482: ** ---------------
1.40 frystyk 483: ** Generate the Prompt line and flush it to the user
1.1 timbl 484: */
1.96 frystyk 485: PRIVATE void MakeCommandLine (LineMode * lm, BOOL is_index)
1.40 frystyk 486: {
1.70 frystyk 487: /* First Line */
1.69 frystyk 488: if (HTAnchor_hasChildren(HTMainAnchor)) {
1.40 frystyk 489: int refs = HText_sourceAnchors(HTMainText);
1.69 frystyk 490: if (refs>1)
1.99 frystyk 491: TTYPrint(OUTPUT, "1-%d, ", refs);
1.69 frystyk 492: else
1.99 frystyk 493: TTYPrint(OUTPUT, "1, ");
1.40 frystyk 494: }
1.70 frystyk 495: if (HText_canScrollUp(HTMainText)) {
1.99 frystyk 496: TTYPrint(OUTPUT, "Top, ");
497: TTYPrint(OUTPUT, "Up, ");
1.70 frystyk 498: }
499: if (HText_canScrollDown(HTMainText)) {
1.99 frystyk 500: TTYPrint(OUTPUT, "BOttom, ");
501: TTYPrint(OUTPUT, "Down or <RETURN> for more,");
1.70 frystyk 502: }
1.69 frystyk 503:
1.70 frystyk 504: /* Second Line */
1.99 frystyk 505: TTYPrint(OUTPUT, "\n");
1.96 frystyk 506: if (HTHistory_canBacktrack(lm->history))
1.99 frystyk 507: TTYPrint(OUTPUT, "Back, ");
1.96 frystyk 508: if (HTHistory_canForward(lm->history))
1.99 frystyk 509: TTYPrint(OUTPUT, "Forward, ");
1.70 frystyk 510: if (is_index)
1.99 frystyk 511: TTYPrint(OUTPUT, "FIND <keywords>, ");
512: TTYPrint(OUTPUT, "Quit, or Help: ");
1.44 frystyk 513: fflush(stdout); /* For use to flush out the prompt */
1.40 frystyk 514: return;
515: }
1.1 timbl 516:
1.40 frystyk 517: /*
1.62 frystyk 518: ** Upload a document either from local file or from a HTTP server
519: ** to a HTTP server. The method can be either PUT or POST.
520: ** Returns the result of the load function.
1.1 timbl 521: */
1.96 frystyk 522: PRIVATE int Upload (LineMode * lm, HTRequest * req, HTMethod method)
1.40 frystyk 523: {
1.96 frystyk 524: char * base = HTAnchor_address((HTAnchor*) HTMainAnchor);
525: char * scr_url = NULL;
526: char * dest_url = NULL;
1.62 frystyk 527: int status = HT_INTERNAL;
1.96 frystyk 528: if ((scr_url = AskUser(req, "Source:", base)) != NULL &&
529: (dest_url = AskUser(req, "Destination:", NULL)) != NULL) {
1.94 frystyk 530: BOOL doit = YES;
1.96 frystyk 531: char * fd = HTParse(HTStrip(dest_url), base, PARSE_ALL);
532: char * fs = HTParse(HTStrip(scr_url), base, PARSE_ALL);
533: HTParentAnchor * dest = (HTParentAnchor *) HTAnchor_findAddress(fd);
534: HTParentAnchor * src = (HTParentAnchor *) HTAnchor_findAddress(fs);
535: HTLink * link = HTAnchor_findLink((HTAnchor *) src, (HTAnchor *) dest);
1.62 frystyk 536:
537: /* Now link the two anchors together if not already done */
1.68 frystyk 538: if (link) {
539: char *msg = (char *) malloc(128);
1.62 frystyk 540: if (!msg) outofmem(__FILE__, "Upload");
1.68 frystyk 541: sprintf(msg, "The destination is already related to the source with a %s method - result %d, continue?",
1.103 ! frystyk 542: HTMethod_name(HTLink_method(link)), HTLink_result(link));
1.96 frystyk 543: doit = confirm(req, msg);
1.62 frystyk 544: free(msg);
545: } else
546: HTAnchor_link((HTAnchor *) src, (HTAnchor *) dest, NULL, method);
1.94 frystyk 547: if (doit) {
1.96 frystyk 548: req = Thread_new(lm, YES);
1.68 frystyk 549: status = HTCopyAnchor((HTAnchor *) src, req);
1.62 frystyk 550: }
551: free(fd);
552: free(fs);
1.40 frystyk 553: }
1.96 frystyk 554: FREE(scr_url);
555: FREE(dest_url);
556: FREE(base);
1.62 frystyk 557: return status;
1.40 frystyk 558: }
1.1 timbl 559:
560: /*
1.40 frystyk 561: ** This function puts up a stream to a file in order to save a document. This
562: ** is activated by '>', '>>' or '>!' from the prompt line.
1.1 timbl 563: */
1.90 frystyk 564: PRIVATE BOOL SaveOutputStream (HTRequest * req, char * This, char * Next)
1.40 frystyk 565: {
566: FILE *fp;
567: char *fname;
568: char *fmode;
569:
570: /* Checks if file exists. Can be overruled by using '>!' */
571: if (*(This+1) == '>') { /* Append to file */
1.74 frystyk 572: fmode = "ab";
1.40 frystyk 573: fname = *(This+2) ? (This+2) : Next;
574: } else if (*(This+1) == '!') {
1.74 frystyk 575: fmode = "wb"; /* Overwrite file */
1.40 frystyk 576: fname = *(This+2) ? (This+2) : Next;
577: } else { /* File name follows */
1.74 frystyk 578: fmode = "wb";
1.40 frystyk 579: fname = *(This+1) ? (This+1) : Next;
580: if (fname) { /* See if file exists */
581: if ((fp = fopen(fname, "r")) != NULL) {
582: fclose(fp);
1.94 frystyk 583: if (!confirm(req, "File exists - overwrite?"))
1.92 frystyk 584: return NO;
1.40 frystyk 585: }
586: }
587: }
588: if (!fname) /* No file name given */
589: return NO;
590: if ((fp = fopen(fname, fmode)) == NULL) {
1.89 frystyk 591: if (SHOW_MSG) TTYPrint(TDEST, "Can't access file (%s)\n", fname);
1.40 frystyk 592: return NO;
593: }
1.90 frystyk 594: HTRequest_setOutputStream(req, HTFWriter_new(fp, NO));
1.92 frystyk 595: if (SHOW_MSG) TTYPrint(TDEST, "Saving to file `%s\'\n", fname);
1.58 frystyk 596: return (HTLoadAnchor((HTAnchor*) HTMainAnchor, req) != HT_WOULD_BLOCK);
1.40 frystyk 597: }
1.1 timbl 598:
1.62 frystyk 599: /* ------------------------------------------------------------------------- */
600: /* EVENT FUNCTIONS */
601: /* ------------------------------------------------------------------------- */
1.1 timbl 602:
1.89 frystyk 603: /* parse_command
1.76 frystyk 604: ** ------------
1.89 frystyk 605: ** Given the user's input, deal with it as necessary.
1.40 frystyk 606: ** Any Command which works returns from the routine. If nothing
607: ** works then a search or error message down at the bottom.
1.76 frystyk 608: **
609: ** Returns HT_ERROR Error has occured or we quit
610: ** HT_OK Call back was OK
1.1 timbl 611: */
1.91 frystyk 612: PRIVATE int parse_command (char* choice, SOCKET s, HTRequest *req, SockOps ops)
1.101 frystyk 613: {
1.68 frystyk 614: char * the_choice=NULL; /* preserved user command */
615: char * token=NULL; /* First word of command */
616: char * this_command; /* token and following */
1.40 frystyk 617: char * next_word; /* Second word */
618: char * other_words; /* Second word and following */
1.14 frystyk 619: BOOL is_index = HTAnchor_isIndex(HTMainAnchor);
1.48 frystyk 620: BOOL found = YES;
1.68 frystyk 621: BOOL OutSource = NO; /* Output source, YES/NO */
1.76 frystyk 622: int status = YES;
1.101 frystyk 623: Context * context;
624: LineMode * lm;
625:
626: #ifdef _WINDOWS
627: req = TTYReq;
628: #endif
629: context = (Context *) HTRequest_context(req);
630: lm = context->lm;
1.40 frystyk 631:
632: StrAllocCopy (the_choice, choice); /* Remember it as is, */
1.91 frystyk 633: if (*the_choice && the_choice[strlen(the_choice)-1] == '\n') /* final \n */
1.40 frystyk 634: the_choice[strlen(the_choice)-1] = '\0';
1.14 frystyk 635:
1.68 frystyk 636: token = strtok (choice, " \t\n\r"); /* Tokenize user input */
1.40 frystyk 637: this_command = the_choice;
1.68 frystyk 638: if (token) {
1.40 frystyk 639: next_word = strtok (NULL, " \t\n\r");
640: other_words = the_choice + (next_word - choice);
1.14 frystyk 641: }
1.40 frystyk 642: else
643: goto down; /* Empty input : scroll down */
644:
645: /* Process Command */
646: loop:
1.68 frystyk 647: switch (TOUPPER(*token)) {
1.40 frystyk 648: case '0':
649: case '1':
650: case '2':
651: case '3':
652: case '4':
653: case '5':
654: case '6':
655: case '7':
656: case '8':
657: case '9':
1.68 frystyk 658: {
659: int ref_num;
660: sscanf(token,"%d",&ref_num);
661: if (ref_num>0 && ref_num<=HText_sourceAnchors(HTMainText)) {
662: HTAnchor *destination;
663: HTChildAnchor *source = HText_childNumber(HTMainText, ref_num);
664: if (source) {
1.96 frystyk 665: req = Thread_new(lm, YES);
1.68 frystyk 666: destination = HTAnchor_followMainLink((HTAnchor*) source);
1.69 frystyk 667:
668: /* Continous browsing, so we want Referer field */
1.90 frystyk 669: HTRequest_setParent(req,
670: HTAnchor_parent((HTAnchor*)source));
1.76 frystyk 671: status = HTLoadAnchor(destination, req);
1.68 frystyk 672: } else {
1.76 frystyk 673: status = NO; /* No anchor */
1.68 frystyk 674: }
1.45 frystyk 675: } else {
1.68 frystyk 676: if (SHOW_MSG)
1.89 frystyk 677: TTYPrint(TDEST,"Warning: Invalid Reference Number: (%d)\n",
1.68 frystyk 678: ref_num);
1.44 frystyk 679: }
1.40 frystyk 680: }
681: break;
682:
683: case 'B':
1.68 frystyk 684: if (CHECK_INPUT("BACK", token)) { /* Return to previous node */
1.96 frystyk 685: if (HTHistory_canBacktrack(lm->history)) {
686: req = Thread_new(lm, YES);
687: context->state = LM_NO_UPDATE;
688: status = HTLoadAnchor(HTHistory_back(lm->history), req);
1.40 frystyk 689: } else {
1.89 frystyk 690: TTYPrint(OUTPUT, "\nThis is the first document in history list\n");
1.40 frystyk 691: }
1.68 frystyk 692: } else if (CHECK_INPUT("BOTTOM", token)) { /* Scroll to bottom */
1.40 frystyk 693: HText_scrollBottom(HTMainText);
1.48 frystyk 694: } else
695: found = NO;
1.40 frystyk 696: break;
697:
1.51 frystyk 698: case 'C':
1.50 frystyk 699: #ifdef unix
1.68 frystyk 700: if (CHECK_INPUT("CD", token)) { /* Change working directory ? */
1.40 frystyk 701: goto lcd;
1.64 frystyk 702: } else
1.51 frystyk 703: #endif
1.69 frystyk 704: if (CHECK_INPUT("CLEAR", token)) { /* Clear History list */
1.96 frystyk 705: HTHistory_removeFrom(lm->history, 1);
1.69 frystyk 706: } else
1.48 frystyk 707: found = NO;
1.40 frystyk 708: break;
709:
710: case 'D':
1.68 frystyk 711: if (CHECK_INPUT("DOWN", token)) { /* Scroll down one page */
1.40 frystyk 712: down:
713: if (HText_canScrollDown(HTMainText))
714: HText_scrollDown(HTMainText);
1.48 frystyk 715: } else
716: found = NO;
1.40 frystyk 717: break;
718:
1.51 frystyk 719: case 'E':
1.68 frystyk 720: if (CHECK_INPUT("EDIT", token)) {
1.51 frystyk 721:
722: /* @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ */
723:
1.68 frystyk 724: } else if (CHECK_INPUT("EXIT", token)) { /* Quit program? */
1.76 frystyk 725: status = NO;
1.48 frystyk 726: } else
727: found = NO;
1.40 frystyk 728: break;
729:
730: case 'F': /* Keyword search ? */
1.68 frystyk 731: if (is_index && CHECK_INPUT("FIND", token)) {
1.40 frystyk 732: find:
1.47 frystyk 733: {
734: if (next_word) {
1.96 frystyk 735: req = Thread_new(lm, YES);
1.76 frystyk 736: status = HTSearch(other_words, HTMainAnchor, req);
1.47 frystyk 737: }
738: }
1.69 frystyk 739: } else if (CHECK_INPUT("FORWARD", token)) {
1.96 frystyk 740: if (HTHistory_canForward(lm->history)) {
741: req = Thread_new(lm, YES);
742: context->state = LM_NO_UPDATE;
743: status = HTLoadAnchor(HTHistory_forward(lm->history), req);
1.69 frystyk 744: } else {
1.89 frystyk 745: TTYPrint(OUTPUT, "\nThis is the last document in history list.\n");
1.69 frystyk 746: }
1.48 frystyk 747: } else
748: found = NO;
1.40 frystyk 749: break;
750:
751: case 'G':
1.68 frystyk 752: if (CHECK_INPUT("GOTO", token)) { /* GOTO */
1.40 frystyk 753: if (next_word) {
1.96 frystyk 754: req = Thread_new(lm, YES);
1.76 frystyk 755: status = HTLoadRelative(next_word, HTMainAnchor, req);
1.40 frystyk 756: }
1.48 frystyk 757: } else
758: found = NO;
1.40 frystyk 759: break;
760:
761: case '?':
1.96 frystyk 762: req = Thread_new(lm, YES);
1.81 frystyk 763: HTRequest_setPreemtive(req, YES);
1.76 frystyk 764: status = HTLoadRelative(C_HELP, HTMainAnchor, req);
1.47 frystyk 765: break;
1.40 frystyk 766:
767: case 'H':
1.68 frystyk 768: if (CHECK_INPUT("HELP", token)) { /* help menu, ..*/
1.96 frystyk 769: req = Thread_new(lm, YES);
1.81 frystyk 770: HTRequest_setPreemtive(req, YES);
1.76 frystyk 771: status = HTLoadRelative(C_HELP, HTMainAnchor, req);
1.68 frystyk 772: } else if (CHECK_INPUT("HOME", token)) { /* back HOME */
1.96 frystyk 773: if (!HTHistory_canBacktrack(lm->history)) {
1.40 frystyk 774: HText_scrollTop(HTMainText);
775: } else {
1.96 frystyk 776: req = Thread_new(lm, YES);
777: context->state = LM_NO_UPDATE;
778: status = HTLoadAnchor(HTHistory_find(lm->history, 1), req);
1.40 frystyk 779: }
1.48 frystyk 780: } else
781: found = NO;
1.40 frystyk 782: break;
783:
784: case 'K': /* Keyword search ? */
1.68 frystyk 785: if (is_index && CHECK_INPUT("KEYWORDS", token)) {
1.40 frystyk 786: goto find;
1.48 frystyk 787: } else
788: found = NO;
1.40 frystyk 789: break;
790:
791: case 'L':
1.68 frystyk 792: if (CHECK_INPUT("LIST", token)) { /* List of references ? */
1.96 frystyk 793: Reference_List(lm, !OutSource);
1.40 frystyk 794: }
1.50 frystyk 795: #ifdef unix
1.68 frystyk 796: else if (CHECK_INPUT ("LCD", token)) { /* Local change dir ? */
1.40 frystyk 797: lcd:
798: if (!next_word) { /* Missing argument */
1.89 frystyk 799: TTYPrint(OUTPUT, "\nName of the new local directory missing.\n");
1.47 frystyk 800: } else if (chdir (next_word)) { /* failed : say why */
1.89 frystyk 801: TTYPrint(OUTPUT, "\n ");
1.40 frystyk 802: perror (next_word);
1.47 frystyk 803: } else { /* Success : display new local directory */
1.40 frystyk 804: /* AS Sep 93 */
1.50 frystyk 805: #ifdef NO_GETWD /* No getwd() on this machine */
806: #ifdef HAS_GETCWD /* System V variant SIGN CHANGED TBL 921006 !! */
1.89 frystyk 807: TTYPrint(OUTPUT, "\nLocal directory is now:\n %s\n",
1.40 frystyk 808: getcwd (choice, sizeof(choice)));
1.50 frystyk 809: #else /* has NO getcwd */
1.68 frystyk 810: if (SHOW_MSG)
1.89 frystyk 811: TTYPrint(TDEST, "This platform does not support getwd() or getcwd()\n");
1.50 frystyk 812: #endif /* has no getcwd */
813: #else /* has getwd */
1.89 frystyk 814: TTYPrint(OUTPUT, "\nLocal directory is now:\n %s\n",
1.50 frystyk 815: (char *) getwd (choice));
816: #endif /* has getwd */
1.40 frystyk 817: /* End AS Sep 93 */
818: }
819: }
820: #endif
1.48 frystyk 821: else
822: found = NO;
1.40 frystyk 823: break;
824:
825: case 'M':
1.68 frystyk 826: if (CHECK_INPUT("MANUAL", token)) { /* Read User manual */
1.96 frystyk 827: req = Thread_new(lm, YES);
1.81 frystyk 828: HTRequest_setPreemtive(req, YES);
1.76 frystyk 829: status = HTLoadRelative(MANUAL, HTMainAnchor,req);
1.48 frystyk 830: } else
831: found = NO;
1.40 frystyk 832: break;
833:
834: case 'P':
1.68 frystyk 835: if (CHECK_INPUT("POST", token)) {
1.96 frystyk 836: status = Upload(lm, req, METHOD_POST);
1.40 frystyk 837: }
1.70 frystyk 838:
1.50 frystyk 839: #ifdef GOT_SYSTEM
1.96 frystyk 840: else if (!lm->host && CHECK_INPUT("PRINT", token)) {
1.40 frystyk 841: char * address = HTAnchor_address((HTAnchor *) HTMainAnchor);
842: char * command;
1.62 frystyk 843: char * tmplate = (char *) getenv("WWW_PRINT_COMMAND");
1.40 frystyk 844: int result;
845:
1.46 frystyk 846: if (!tmplate) tmplate = "www -n -na -p66 '%s' | lpr";
847: command = (char *) malloc(strlen(address)+strlen(tmplate)+20);
848: sprintf(command, tmplate, address);
1.40 frystyk 849: result = system(command);
850: free(address);
851: free(command);
1.89 frystyk 852: if (result) TTYPrint(OUTPUT, " %s\n returns %d\n", command, result);
1.40 frystyk 853: }
854: #endif
855: /* this command prints the entire current text to the
856: terminal's printer; at the end it displays the top of the text */
857: #ifdef SLAVE_PRINTER
858: #define SLAVE_PRINTER_ON "\033\133\065\151"
859: #define SLAVE_PRINTER_OFF "\033\133\064\151"
860:
1.68 frystyk 861: else if (CHECK_INPUT("PS", token)) {
1.89 frystyk 862: TTYPrint(OUTPUT, "%s",SLAVE_PRINTER_ON);
863: TTYPrint(OUTPUT, "\f"); /* Form feed for new page */
1.40 frystyk 864: HText_scrollTop(HTMainText);
865: while(HText_canScrollDown(HTMainText)) {
866: HText_scrollDown(HTMainText);
867: }
1.89 frystyk 868: TTYPrint(OUTPUT, "\f"); /* Form feed for new page */
869: TTYPrint(OUTPUT, "%s",SLAVE_PRINTER_OFF);
1.40 frystyk 870: HText_scrollTop(HTMainText);
871: }
872: #endif
1.68 frystyk 873: else if (CHECK_INPUT("PUT", token)) {
1.96 frystyk 874: status = Upload(lm, req, METHOD_PUT);
1.62 frystyk 875: } else
1.48 frystyk 876: found = NO;
1.40 frystyk 877: break;
878:
879: case 'Q': /* Quit program ? */
1.68 frystyk 880: if (CHECK_INPUT("QUIT", token)) {
1.47 frystyk 881:
1.40 frystyk 882: /* JFG 9/7/92, following a complaint of 'q' mis-typed for '1'.
883: JFG Then made optional because I hate it !!!
884: TBL made it only affect remote logged on users. 921122 */
885:
1.96 frystyk 886: if (lm->host && (strcasecomp(token, "quit") != 0) ) {
1.89 frystyk 887: TTYPrint(OUTPUT, "\n Please type \"quit\" in full to leave www.\n");
1.76 frystyk 888: } else {
889: HTNet_killAll(); /* Kill all requests */
890: status = NO;
891: }
1.48 frystyk 892: } else
893: found = NO;
1.40 frystyk 894: break;
895:
896: case 'R':
1.68 frystyk 897: if (CHECK_INPUT("RECALL", token)) {
1.96 frystyk 898: if (HTHistory_count(lm->history) <= 1) {
1.89 frystyk 899: TTYPrint(OUTPUT, "\n No other documents to recall.\n");
1.47 frystyk 900: } else {
901: /* Previous node number exists, or does the user just */
902: /* require a list of nodes visited? */
1.69 frystyk 903: if (next_word) {
904: int cnt;
905: if ((cnt = atoi(next_word)) > 0) {
1.96 frystyk 906: req = Thread_new(lm, YES);
907: context->state = LM_NO_UPDATE;
908: status = HTLoadAnchor(HTHistory_find(lm->history,cnt), req);
1.47 frystyk 909: } else {
1.68 frystyk 910: if (SHOW_MSG)
1.89 frystyk 911: TTYPrint(TDEST, "Bad command (%s), for list of commands type help\n", this_command);
1.47 frystyk 912: }
913: } else {
1.96 frystyk 914: History_List(lm);
1.47 frystyk 915: }
1.40 frystyk 916: }
1.68 frystyk 917: } else if (CHECK_INPUT("REFRESH", token)) {
1.50 frystyk 918: HText_setStale(HTMainText); /* Force refresh */
919: HText_refresh(HTMainText); /* Refresh screen */
1.68 frystyk 920: } else if (CHECK_INPUT("RELOAD", token)) {
1.96 frystyk 921: req = Thread_new(lm, YES);
1.90 frystyk 922: HTRequest_setReloadMode(req, HT_FORCE_RELOAD);
1.96 frystyk 923: context->state = LM_NO_UPDATE;
1.76 frystyk 924: status = HTLoadAnchor((HTAnchor*) HTMainAnchor, req);
1.48 frystyk 925: } else
926: found = NO;
1.40 frystyk 927: break;
928:
929: case 'S': /* TBL 921009 */
1.68 frystyk 930: if (CHECK_INPUT("SOURCE", token)) { /* Apply to source */
1.47 frystyk 931: if (next_word) {
932: OutSource = YES; /* Load and print as source */
1.68 frystyk 933: token = next_word; /* Move up one word */
1.47 frystyk 934: next_word = strtok (NULL, " \t\n\r");
1.68 frystyk 935: this_command = the_choice + (token - choice);
1.47 frystyk 936: other_words = the_choice + (next_word - choice);
937: goto loop; /* Go treat as before */
938: }
1.68 frystyk 939: } else if (CHECK_INPUT("SET", token)) { /* config */
1.93 frystyk 940: HTList * rules = HTRule_global();
941: HTRule_parseLine(rules, other_words);
1.48 frystyk 942: } else
943: found = NO;
1.40 frystyk 944: break;
945:
946: case 'T':
1.68 frystyk 947: if (CHECK_INPUT("TOP", token)) { /* Return to top */
1.40 frystyk 948: HText_scrollTop(HTMainText);
1.48 frystyk 949: } else
950: found = NO;
1.40 frystyk 951: break;
952:
953: case 'U':
1.68 frystyk 954: if (CHECK_INPUT("UP", token)) { /* Scroll up one page */
1.40 frystyk 955: HText_scrollUp(HTMainText);
1.48 frystyk 956: } else
957: found = NO;
1.40 frystyk 958: break;
959:
960: case 'V':
1.68 frystyk 961: if (CHECK_INPUT("VERBOSE", token)) { /* Switch verbose mode */
1.96 frystyk 962: WWWTRACE = WWWTRACE ? 0 : lm->trace;
1.93 frystyk 963: TTYPrint(OUTPUT, "\n Verbose mode %s.\n", WWWTRACE ? "ON":"OFF");
1.68 frystyk 964: } else if (CHECK_INPUT("VERSION", token)) { /* Version */
965: VersionInfo();
1.48 frystyk 966: } else
967: found = NO;
1.40 frystyk 968: break;
969:
970: case 'Z':
1.50 frystyk 971: HText_setStale(HTMainText); /* Force refresh */
972: HText_refresh(HTMainText); /* Refresh screen */
1.76 frystyk 973: HTNet_killAll(); /* Kill all requests */
1.44 frystyk 974: break;
1.40 frystyk 975:
976: case '>':
1.96 frystyk 977: if (!lm->host) {
1.58 frystyk 978: HText *curText = HTMainText; /* Remember current main vindow */
1.96 frystyk 979: req = Thread_new(lm, NO);
1.90 frystyk 980: HTRequest_setReloadMode(req, HT_MEM_REFRESH);
981: if (OutSource) HTRequest_setOutputFormat(req, WWW_SOURCE);
1.76 frystyk 982: SaveOutputStream(req, token, next_word);
1.58 frystyk 983: HText_select(curText);
1.40 frystyk 984: }
985: break;
1.1 timbl 986:
1.50 frystyk 987: #ifdef GOT_PIPE
1.40 frystyk 988: case '|':
1.96 frystyk 989: if (!lm->host) { /* Local only!!!! */
1.40 frystyk 990: char * address = HTAnchor_address((HTAnchor *) HTMainAnchor);
991: char * command;
992: int result;
993: command = (char*) malloc(strlen(address) +strlen(this_command)+30);
994: sprintf(command, "www %s \"%s\" %s",
995: OutSource ? "-source" : "-n -na -p", address,this_command);
1.89 frystyk 996: TTYPrint(OUTPUT, "Command: %s\n", command);
1.40 frystyk 997: result = system(command);
1.96 frystyk 998: if (result) TTYPrint(OUTPUT," %s returns %d\n", command, result);
1.40 frystyk 999: free(command);
1000: free(address);
1.14 frystyk 1001: }
1.47 frystyk 1002: break;
1.40 frystyk 1003: #endif
1004:
1.50 frystyk 1005: #ifdef GOT_SYSTEM
1.40 frystyk 1006: case '!':
1.96 frystyk 1007: if (!lm->host) { /* Local only! */
1.40 frystyk 1008: int result;
1.89 frystyk 1009: if (SHOW_MSG) TTYPrint(TDEST, "Executing `%s\'\n", this_command);
1.40 frystyk 1010: result = system(strchr(this_command, '!') + 1);
1.89 frystyk 1011: if (result) TTYPrint(OUTPUT, " %s returns %d\n",
1.96 frystyk 1012: strchr(this_command, '!') + 1, result);
1.1 timbl 1013: }
1.47 frystyk 1014: break;
1.1 timbl 1015: #endif
1.40 frystyk 1016: default:
1.48 frystyk 1017: found = NO;
1018: break;
1019: } /* Switch on 1st character */
1020:
1021: if (!found) {
1.68 frystyk 1022: if (is_index && *token) { /* No commands, search keywords */
1.47 frystyk 1023: next_word = other_words = this_command;
1.48 frystyk 1024: found = YES;
1.47 frystyk 1025: goto find;
1026: } else {
1.68 frystyk 1027: if (SHOW_MSG)
1.89 frystyk 1028: TTYPrint(TDEST, "Bad command (%s), for list of commands type help\n", this_command);
1.47 frystyk 1029: }
1.48 frystyk 1030: }
1.96 frystyk 1031: MakeCommandLine(lm, is_index);
1.40 frystyk 1032: free (the_choice);
1.96 frystyk 1033:
1034: /*
1035: ** If we have created a new Request and is to update the history list then
1036: ** we can set the inactive bit on this request object.
1037: */
1038: if (context->state & LM_UPDATE) context->state |= LM_INACTIVE;
1039:
1.76 frystyk 1040: return (status==YES) ? HT_OK : HT_ERROR;
1.40 frystyk 1041: }
1042:
1.96 frystyk 1043: /* readConsole
1044: ** -----------
1045: ** non-blocking read of the WIN32 console. EGP
1046: */
1.97 frystyk 1047:
1.89 frystyk 1048: #ifdef _CONSOLE
1049: PUBLIC BOOL readConsole(HANDLE conIn, char* buf, int len, int* pRed)
1050: {
1051: DWORD recordIndex, bufferIndex, toRead, red;
1052: PINPUT_RECORD pInput;
1053:
1054: /* grab the pending input records (keystrokes plus other garbage). */
1055: GetNumberOfConsoleInputEvents(conIn, &toRead);
1056: if (len < (int)toRead) /* we'll get the rest on the next pass(es). */
1057: toRead = len;
1.97 frystyk 1058: if (!(pInput = (PINPUT_RECORD)malloc(toRead * sizeof(INPUT_RECORD)))) /* room for n input records */
1.89 frystyk 1059: return (FALSE);
1060: ReadConsoleInput(conIn, pInput, toRead, &red);
1061:
1062: for (recordIndex = bufferIndex = 0; recordIndex < red; recordIndex++) {
1063: /* grab all keydown events */
1.97 frystyk 1064: #if 1
1065: KEY_EVENT_RECORD keyEvent = pInput[recordIndex].Event.KeyEvent; /* only used if EventType == KEY_EVENT */
1066: if (pInput[recordIndex].EventType == KEY_EVENT && keyEvent.bKeyDown) {
1067: while (keyEvent.wRepeatCount && keyEvent.uChar.AsciiChar) {
1068: /* stuff the buffer with the keys */
1069: buf[bufferIndex] = keyEvent.uChar.AsciiChar;
1070: if (buf[bufferIndex] == '\r')
1071: buf[bufferIndex] = '\n';
1072: if (buf[bufferIndex] == '\b')
1073: TTYPrint(STDOUT, "\b ");
1074: TTYPrint(STDOUT, "%c", buf[bufferIndex]);
1075: bufferIndex++;
1076: keyEvent.wRepeatCount--;
1077: }
1078: }
1079: #else
1080: if (pInput[recordIndex].EventType == KEY_EVENT && pInput[recordIndex].Event.KeyEvent.bKeyDown) {
1081: while (pInput[recordIndex].Event.KeyEvent.wRepeatCount && pInput[recordIndex].Event.KeyEvent.uChar.AsciiChar) {
1082: /* stuff the buffer with the keys */
1083: buf[bufferIndex] = pInput[recordIndex].Event.KeyEvent.uChar.AsciiChar;
1084: if (buf[bufferIndex] == '\r')
1085: buf[bufferIndex] = '\n';
1086: if (buf[bufferIndex] == '\b')
1087: TTYPrint(STDOUT, "\b ");
1088: TTYPrint(STDOUT, "%c", buf[bufferIndex]);
1089: bufferIndex++;
1090: pInput[recordIndex].Event.KeyEvent.wRepeatCount--;
1091: }
1092: }
1093: #endif
1094:
1.89 frystyk 1095: }
1096:
1097: free(pInput);
1.97 frystyk 1098: *pRed = bufferIndex; /* actual characters stuck into buffer */
1.89 frystyk 1099: return (TRUE);
1100: }
1101: #endif /* _CONSOLE */
1102:
1.96 frystyk 1103: /* bufferInput
1104: ** -----------
1105: ** Read available characters from buf into stat. buf maybe bigger or
1106: ** smaller than stat.
1107: */
1108: PUBLIC int bufferInput (char* buf, int len, SOCKET s, HTRequest * req,
1109: SockOps ops)
1.89 frystyk 1110: {
1111: static char stat[RESPONSE_LENGTH];
1112: static int iStat = 0;
1113: static int ignoreNext = 0;
1114: int iBuf;
1115: for (iBuf = 0; iBuf < len; iBuf++) {
1116: switch (buf[iBuf]) {
1117: case '\r':
1118: case '\n':
1119: if (ignoreNext)
1120: ignoreNext = 0;
1121: else {
1122: int ret;
1123: stat[iStat] = 0;
1124: iStat = 0;
1125: if ((ret = parse_command(stat, 0, 0, 0)) != HT_OK)
1126: return (ret);
1127: }
1128: break;
1129: case '\b':
1.96 frystyk 1130: if (iStat) /* don't worry about ignoreNext as iStat will be 0*/
1.89 frystyk 1131: iStat--;
1132: break;
1133: default:
1134: if (!ignoreNext)
1135: stat[iStat++] = buf[iBuf];
1136: }
1137: if (iStat == sizeof(stat)) {
1138: TTYPrint(OUTPUT, "Read Console... BUFFER OVERRUN\n");
1139: iStat = 0;
1140: ignoreNext = 1;
1141: }
1142: }
1143: return (HT_OK);
1144: }
1145:
1146: PRIVATE int scan_command (SOCKET s, HTRequest * req, SockOps ops)
1147: {
1.91 frystyk 1148: /* buf happens to == eatText's buffer but not neccesary */
1149: static char buf[RESPONSE_LENGTH];
1.89 frystyk 1150: int red;
1151: int ret;
1.91 frystyk 1152:
1153: #ifndef _CONSOLE
1.89 frystyk 1154: if (!fgets(buf, sizeof(buf), stdin)) /* Read User Input */
1155: return HT_ERROR; /* Exit if EOF */
1156: return (parse_command(buf, s, req, ops));
1.91 frystyk 1157: #else
1158:
1.89 frystyk 1159: while(1) {
1160: #ifdef _CONSOLE
1161: if (!readConsole((HANDLE)s, buf, sizeof(buf), &red)) {
1.96 frystyk 1162: if (PROT_TRACE) TTYPrint(TDEST, "Read Console... READ ERROR\n");
1.89 frystyk 1163: return HT_ERROR;
1164: }
1165: #else /* _CONSOLE */
1166: if ((red = read(s, buf, sizeof(buf))) < 0) {
1167: #ifdef EAGAIN
1168: if (socerrno==EINPROGRESS || socerrno==EAGAIN)
1169: #else
1170: if (socerrno==EINPROGRESS)
1171: #endif
1172: return (HT_OK);
1.96 frystyk 1173: if (PROT_TRACE) TTYPrint(TDEST, "Read Console... READ ERROR\n");
1.89 frystyk 1174: return HT_ERROR;
1175: }
1176: #endif /* _CONSOLE */
1.96 frystyk 1177: if (!red) return (HT_OK);
1.89 frystyk 1178: ret = bufferInput(buf, red, s, req, ops);
1.96 frystyk 1179: if (ret != HT_OK) return (ret);
1.89 frystyk 1180: }
1.91 frystyk 1181: #endif
1.89 frystyk 1182: }
1.40 frystyk 1183:
1.76 frystyk 1184: /* terminate_handler
1185: ** -----------------
1.96 frystyk 1186: ** This function is registered to handle the result of the request
1.1 timbl 1187: */
1.76 frystyk 1188: PRIVATE int terminate_handler (HTRequest * request, int status)
1.40 frystyk 1189: {
1.96 frystyk 1190: Context * context = (Context *) HTRequest_context(request);
1191: LineMode * lm = context->lm;
1.40 frystyk 1192: BOOL is_index = HTAnchor_isIndex(HTMainAnchor);
1193: if (status == HT_LOADED) {
1.96 frystyk 1194:
1195: if (HTAlert_interactive()) {
1196: HText_setStale(HTMainText);
1197: MakeCommandLine(lm, is_index);
1198: } else {
1199: if (lm->flags & LM_REFS) Reference_List(lm, NO);
1200: Cleanup(lm, 0);
1201: }
1.69 frystyk 1202:
1203: /* Record new history if we have not moved around in the old one */
1.96 frystyk 1204: if (context->state & LM_UPDATE)
1205: HTHistory_replace(lm->history, (HTAnchor *) HTMainAnchor);
1.69 frystyk 1206:
1.40 frystyk 1207: /* Now generate the new prompt line as a function of the result */
1208: if (!HText_canScrollDown(HTMainText) &&
1209: !HTAnchor_hasChildren(HTMainAnchor) && !is_index &&
1.96 frystyk 1210: (!HTHistory_canBacktrack(lm->history))) {
1.91 frystyk 1211: return HT_OK;
1.40 frystyk 1212: }
1.96 frystyk 1213:
1.76 frystyk 1214: }
1.96 frystyk 1215: context->state |= LM_DONE;
1216: Thread_cleanup(lm);
1217: if (!HTAlert_interactive()) Cleanup(lm, -1);
1.76 frystyk 1218: return HT_OK;
1.40 frystyk 1219: }
1.1 timbl 1220:
1.81 frystyk 1221: /* timeout_handler
1222: ** ---------------
1.96 frystyk 1223: ** This function is registered to handle timeout in select eventloop
1.81 frystyk 1224: */
1225: PRIVATE int timeout_handler (HTRequest * request)
1226: {
1.96 frystyk 1227: if (!HTAlert_interactive()) {
1228: Context * context = (Context *) HTRequest_context(request);
1229: LineMode * lm = context->lm;
1230: HTNet_killAll();
1231: Cleanup(lm, -1);
1232: }
1.89 frystyk 1233: if (SHOW_MSG) TTYPrint(TDEST, ".");
1.81 frystyk 1234: return 0;
1235: }
1236:
1.96 frystyk 1237: /* header_handler
1238: ** ---------------
1239: ** This function is registered to handle unknown MIME headers
1240: */
1241: PRIVATE int header_handler (HTRequest * request, CONST char * token)
1242: {
1243: if (SHOW_MSG) TTYPrint(TDEST, "Parsing unknown header `%s\'\n", token);
1244: return HT_OK;
1245: }
1246:
1.40 frystyk 1247: /* ------------------------------------------------------------------------- */
1248: /* MAIN PROGRAM */
1249: /* ------------------------------------------------------------------------- */
1.1 timbl 1250:
1.90 frystyk 1251: int main (int argc, char ** argv)
1.40 frystyk 1252: {
1.68 frystyk 1253: int status = 0;
1254: int arg; /* Index into argv */
1255: HTChunk * keywords = NULL; /* From command line */
1256: int keycnt = 0;
1.101 frystyk 1257: LineMode * lm;
1.85 frystyk 1258:
1.96 frystyk 1259: /* Starts Mac GUSI socket library */
1260: #ifdef GUSI
1.75 frystyk 1261: GUSISetup(GUSIwithSIOUXSockets);
1262: GUSISetup(GUSIwithInternetSockets);
1263: #endif
1264:
1265: #ifdef __MWERKS__ /* STR */
1266: InitGraf((Ptr) &qd.thePort);
1267: InitFonts();
1268: InitWindows();
1269: InitMenus(); TEInit();
1270: InitDialogs(nil);
1271: InitCursor();
1272: SIOUXSettings.asktosaveonclose = false;
1273: argc=ccommand(&argv);
1274: #endif
1275:
1.68 frystyk 1276: /* HWL 18/7/94: patch from agl@glas2.glas.apc.org (Anton Tropashko) */
1.40 frystyk 1277: #ifdef CYRILLIC
1278: arc.locale=0; arc.encoding=0; arc.i_encoding=0; doinull();
1.1 timbl 1279: #endif
1280:
1.96 frystyk 1281: /* Initiate W3C Reference Library */
1282: HTLibInit(APP_NAME, APP_VERSION);
1.101 frystyk 1283: lm = LineMode_new();
1.96 frystyk 1284:
1285: /* Initialize the protocol modules */
1286: HTAccessInit();
1287:
1288: /* Initialize set of converters */
1289: lm->converters = HTList_new();
1290: HTConverterInit(lm->converters);
1291: HTFormat_setConversion(lm->converters);
1292:
1293: /* Initialize bindings between file suffixes and media types */
1294: HTFileInit();
1295:
1296: /* Set up default set of icons */
1297: HTStdIconInit(NULL);
1298:
1299: /* Get any proxy or gateway environment variables */
1300: HTProxy_getEnvVar();
1301:
1302: /* Scan command Line for parameters */
1303: for (arg=1; arg<argc ; arg++) {
1.40 frystyk 1304: if (*argv[arg] == '-') {
1305:
1306: /* - alone => filter */
1.96 frystyk 1307: if (argv[arg][1] == '\0') {
1308: lm->flags |= LM_FILTER;
1.94 frystyk 1309: HTAlert_setInteractive(NO);
1.40 frystyk 1310:
1.96 frystyk 1311: /* non-interactive */
1312: } else if (!strcmp(argv[arg], "-n")) {
1313: HTAlert_setInteractive(NO);
1.40 frystyk 1314:
1315: /* from -- Initial represntation (only with filter) */
1.96 frystyk 1316: } else if (!strcmp(argv[arg], "-from")) {
1317: lm->format = (arg+1 < argc && *argv[arg+1] != '-') ?
1318: HTAtom_for(argv[++arg]) : WWW_HTML;
1319: HTAlert_setInteractive(NO);
1.40 frystyk 1320:
1.96 frystyk 1321: /* to -- Final representation */
1322: } else if (!strcmp(argv[arg], "-to")) {
1323: HTFormat format = (arg+1 < argc && *argv[arg+1] != '-') ?
1324: HTAtom_for(argv[++arg]) : DEFAULT_FORMAT;
1325: HTRequest_setOutputFormat(lm->request, format);
1326: HTAlert_setInteractive(NO);
1327:
1328: /* reformat html */
1329: } else if (!strcmp(argv[arg], "-reformat")) {
1330: HTRequest_setOutputFormat(lm->request, WWW_HTML);
1331: lm->flags |= LM_REFORMAT;
1332: HTAlert_setInteractive(NO);
1333:
1334: /* List References */
1335: } else if (!strncmp(argv[arg], "-list", 5)) {
1336: lm->flags |= LM_REFS;
1337: HTAlert_setInteractive(NO);
1338:
1.100 frystyk 1339: /* original output */
1.96 frystyk 1340: } else if (!strcmp(argv[arg], "-raw")) {
1341: HTRequest_setOutputFormat(lm->request, WWW_RAW);
1342: HTAlert_setInteractive(NO);
1343:
1344: /* source please */
1345: } else if (!strcmp(argv[arg], "-source")) {
1346: HTRequest_setOutputFormat(lm->request, WWW_SOURCE);
1347: HTAlert_setInteractive(NO);
1348:
1349: /* HEAD method */
1350: } else if (!strcasecomp(argv[arg], "-head")) {
1351: HTRequest_setMethod(lm->request, METHOD_HEAD);
1352: HTRequest_setOutputFormat(lm->request, WWW_MIME);
1353: HTAlert_setInteractive(NO);
1354:
1.100 frystyk 1355: /* output filename */
1.96 frystyk 1356: } else if (!strcmp(argv[arg], "-o")) {
1357: lm->outputfile = (arg+1 < argc && *argv[arg+1] != '-') ?
1358: argv[++arg] : DEFAULT_OUTPUT_FILE;
1359: HTAlert_setInteractive(NO);
1360:
1361: /* print version and exit */
1362: } else if (!strcmp(argv[arg], "-version")) {
1363: VersionInfo();
1364: Cleanup(lm, 0);
1365:
1366: /* -? or -help: show the command line help page */
1367: } else if (!strcmp(argv[arg],"-?") || !strcmp(argv[arg],"-help")) {
1368: lm->anchor = (HTParentAnchor *) HTAnchor_findAddress(L_HELP);
1369: keycnt = 1;
1.40 frystyk 1370:
1371: #ifdef CYRILLIC
1372: /* HWL 18/7/94: applied patch from agl@glas2.glas.apc.org
1373: (Anton Tropashko) */
1374: } else if (!strcmp(argv[arg], "-koi2alt")) {
1.89 frystyk 1375: doia2k(); TTYPrint(OUTPUT, "Ahak2a!");
1.40 frystyk 1376: #endif
1377:
1378: /* Page size */
1379: } else if (!strncmp(argv[arg], "-p", 2)) {
1380: if (*(argv[arg]+2)) {
1381: if (sscanf(argv[arg]+2, "%d", &HTScreenHeight) < 1)
1382: HTScreenHeight = -1;
1383: else {
1384: if(HTScreenHeight < MIN_SCREEN_HEIGHT)
1385: HTScreenHeight = MIN_SCREEN_HEIGHT;
1386: if(HTScreenHeight > MAX_SCREEN_HEIGHT)
1387: HTScreenHeight = MAX_SCREEN_HEIGHT;
1388: }
1389: } else if (arg+1 < argc && *argv[arg+1] != '-') {
1390: if (sscanf(argv[++arg], "%d", &HTScreenHeight) < 1)
1391: HTScreenHeight = -1;
1392: else {
1393: if(HTScreenHeight < MIN_SCREEN_HEIGHT)
1394: HTScreenHeight = MIN_SCREEN_HEIGHT;
1395: if(HTScreenHeight > MAX_SCREEN_HEIGHT)
1396: HTScreenHeight = MAX_SCREEN_HEIGHT;
1397: }
1398: }
1.1 timbl 1399:
1.40 frystyk 1400: /* Page width */
1401: } else if (!strncmp(argv[arg], "-w", 2)) {
1402: if (*(argv[arg]+2)) {
1403: if (sscanf(argv[arg]+2, "%d", &HTScreenWidth) < 1)
1404: HTScreenWidth = SCREEN_WIDTH;
1405: } else if (arg+1 < argc && *argv[arg+1] != '-') {
1406: if (sscanf(argv[++arg], "%d", &HTScreenWidth) < 1)
1407: HTScreenWidth = SCREEN_WIDTH;
1.14 frystyk 1408: }
1.40 frystyk 1409: if(HTScreenWidth < MIN_SCREEN_WIDTH)
1410: HTScreenWidth = MIN_SCREEN_WIDTH;
1411: if(HTScreenWidth > MAX_SCREEN_WIDTH)
1412: HTScreenWidth = MAX_SCREEN_WIDTH;
1413:
1414: /* Telnet from */
1415: } else if (!strcmp(argv[arg], "-h")) {
1416: if (arg+1 < argc && *argv[arg+1] != '-') {
1.96 frystyk 1417: lm->host = argv[++arg]; /* Use host name */
1.92 frystyk 1418: HTLib_setSecure(YES); /* No easy access */
1.14 frystyk 1419: }
1.40 frystyk 1420:
1.96 frystyk 1421: /* log file */
1.40 frystyk 1422: } else if (!strcmp(argv[arg], "-l")) {
1.96 frystyk 1423: lm->logfile = (arg+1 < argc && *argv[arg+1] != '-') ?
1.68 frystyk 1424: argv[++arg] : DEFAULT_LOG_FILE;
1.51 frystyk 1425:
1.96 frystyk 1426: /* rule file */
1427: } else if (!strcmp(argv[arg], "-r")) {
1428: lm->rules = (arg+1 < argc && *argv[arg+1] != '-') ?
1429: argv[++arg] : DEFAULT_RULE_FILE;
1.68 frystyk 1430:
1.96 frystyk 1431: /* timeout -- Change the default request timeout */
1432: } else if (!strcmp(argv[arg], "-timeout")) {
1433: int timeout = (arg+1 < argc && *argv[arg+1] != '-') ?
1434: atoi(argv[++arg]) : -1;
1435: if (timeout > 0) lm->tv->tv_sec = timeout;
1.40 frystyk 1436:
1.96 frystyk 1437: /* preemtive or non-preemtive access */
1.50 frystyk 1438: } else if (!strcmp(argv[arg], "-single")) {
1.96 frystyk 1439: HTRequest_setPreemtive(lm->request, YES);
1440: lm->flags |= LM_PREEMTIVE;
1.50 frystyk 1441:
1.96 frystyk 1442: /* Specify a cache root (caching is otherwise disabled) */
1443: } else if (!strcmp(argv[arg], "-cacheroot")) {
1444: HTCache_enable((arg+1>=argc || *argv[arg+1]=='-') ?
1445: NULL : argv[++arg]);
1.68 frystyk 1446:
1.96 frystyk 1447: /* Handling of Expire (cache) */
1.68 frystyk 1448: } else if (!strncmp(argv[arg], "-x", 2)) {
1449: char *p = argv[arg]+2;
1450: for(;*p;p++) {
1451: switch (argv[arg][2]) {
1452: case 'i':
1.76 frystyk 1453: HTCache_setExpiresMode(HT_EXPIRES_IGNORE, NULL);
1.68 frystyk 1454: break;
1455: case 'n':
1.76 frystyk 1456: HTCache_setExpiresMode(HT_EXPIRES_NOTIFY, "Document has expired, but I show it anyway");
1.68 frystyk 1457: break;
1458: case 'a':
1.76 frystyk 1459: HTCache_setExpiresMode(HT_EXPIRES_AUTO, NULL);
1.68 frystyk 1460: break;
1461: default:
1462: if (SHOW_MSG)
1.89 frystyk 1463: TTYPrint(TDEST, "Bad parameter (%s) for option -x\n", argv[arg]);
1.68 frystyk 1464: break;
1465: }
1466: }
1467:
1.40 frystyk 1468: /* Anchor format */
1469: } else if (!strcmp(argv[arg], "-a")) {
1470: if (arg+1 < argc && *argv[arg+1] != '-')
1471: end_reference = argv[++arg]; /* New representation */
1472:
1473: /* Anchor format */
1474: } else if (!strcmp(argv[arg], "-ar")) {
1475: if (arg+1 < argc && *argv[arg+1] != '-')
1476: reference_mark = argv[++arg]; /* Change representation */
1477:
1478: /* Anchor format */
1479: } else if (!strcmp(argv[arg], "-as")) {
1480: if (arg+1 < argc && *argv[arg+1] != '-')
1481: start_reference = argv[++arg]; /* Change representation */
1482:
1483: /* No anchors */
1484: } else if (!strcmp(argv[arg], "-na")) {
1485: display_anchors = NO;
1486:
1487: #ifndef NO_DIR_OPTIONS
1488: } else if (!strncmp(argv[arg], "-d", 2)) {
1489: char *p = argv[arg]+2;
1490: for(;*p;p++) {
1491: switch (argv[arg][2]) {
1.82 frystyk 1492: case 'r':HTFile_setDirReadme(HT_DIR_README_NONE); break;
1493: case 't':HTFile_setDirReadme(HT_DIR_README_TOP); break;
1494: case 'b':HTFile_setDirReadme(HT_DIR_README_BOTTOM);break;
1495: case 'n':HTFile_setDirAccess(HT_DIR_FORBID); break;
1496: case 's':HTFile_setDirAccess(HT_DIR_SELECTIVE); break;
1497: case 'y':HTFile_setDirAccess(HT_DIR_OK); break;
1.76 frystyk 1498: default:
1.68 frystyk 1499: if (SHOW_MSG)
1.96 frystyk 1500: TTYPrint(TDEST,"Bad parameter (%s) in -d option\n",
1.68 frystyk 1501: argv[arg]);
1.40 frystyk 1502: }
1.96 frystyk 1503: }
1.40 frystyk 1504: #endif
1.1 timbl 1505:
1.85 frystyk 1506: #ifdef WWWTRACE
1.96 frystyk 1507: /* trace flags */
1.40 frystyk 1508: } else if (!strncmp(argv[arg], "-v", 2)) {
1509: char *p = argv[arg]+2;
1.93 frystyk 1510: WWWTRACE = 0;
1.40 frystyk 1511: for(; *p; p++) {
1512: switch (*p) {
1.93 frystyk 1513: case 'a': WWWTRACE |= SHOW_ANCHOR_TRACE; break;
1514: case 'b': WWWTRACE |= SHOW_BIND_TRACE; break;
1515: case 'c': WWWTRACE |= SHOW_CACHE_TRACE; break;
1516: case 'g': WWWTRACE |= SHOW_SGML_TRACE; break;
1517: case 'p': WWWTRACE |= SHOW_PROTOCOL_TRACE; break;
1518: case 's': WWWTRACE |= SHOW_STREAM_TRACE; break;
1519: case 't': WWWTRACE |= SHOW_THREAD_TRACE; break;
1520: case 'u': WWWTRACE |= SHOW_URI_TRACE; break;
1.40 frystyk 1521: default:
1.68 frystyk 1522: if (SHOW_MSG)
1.96 frystyk 1523: TTYPrint(TDEST,"Bad parameter (%s) in -v option\n",
1.76 frystyk 1524: argv[arg]);
1.40 frystyk 1525: }
1.96 frystyk 1526: }
1527: if (!WWWTRACE) WWWTRACE = SHOW_ALL_TRACE;
1528: lm->trace = WWWTRACE; /* Remember setting */
1.1 timbl 1529: #endif
1.14 frystyk 1530:
1.40 frystyk 1531: } else {
1.96 frystyk 1532: if (SHOW_MSG) TTYPrint(TDEST,"Bad Argument (%s)\n", argv[arg]);
1.40 frystyk 1533: }
1534: } else { /* If no leading `-' then check for main argument */
1.68 frystyk 1535: if (!keycnt) {
1.96 frystyk 1536: char * ref = HTParse(argv[arg], lm->cwd, PARSE_ALL);
1537: lm->anchor = (HTParentAnchor *) HTAnchor_findAddress(ref);
1.79 frystyk 1538: keycnt = 1;
1.96 frystyk 1539: FREE(ref);
1.40 frystyk 1540: } else { /* Check for successive keyword arguments */
1.79 frystyk 1541: char *escaped = HTEscape(argv[arg], URL_XALPHAS);
1.68 frystyk 1542: if (keycnt++ <= 1)
1543: keywords = HTChunkCreate(128);
1544: else
1545: HTChunkPutc(keywords, ' ');
1.79 frystyk 1546: HTChunkPuts(keywords, HTStrip(escaped));
1547: free(escaped);
1.68 frystyk 1548: }
1.79 frystyk 1549: }
1550: }
1.40 frystyk 1551:
1.96 frystyk 1552: #ifdef CATCH_SIG
1553: SetSignal();
1554: #endif
1555:
1556: /* Make home page address */
1557: if (!lm->anchor) lm->anchor = HTHomeAnchor();
1558:
1559: /* Do we need list of presenters? */
1.94 frystyk 1560: if (HTAlert_interactive()) {
1.96 frystyk 1561: lm->presenters = HTList_new();
1562: HTPresenterInit(lm->presenters);
1563: HTRequest_setConversion(lm->request, lm->presenters, NO);
1.86 frystyk 1564: }
1565:
1.40 frystyk 1566: if (HTScreenHeight == -1) { /* Default page size */
1.94 frystyk 1567: if (HTAlert_interactive()) {
1.40 frystyk 1568: #ifdef GET_SCREEN_SIZE
1569: int scr_height, scr_width;
1570: scrsize(&scr_height, &scr_width);
1571: HTScreenHeight = scr_height;
1572: #else
1.42 frystyk 1573: HTScreenHeight = SCREEN_HEIGHT;
1.1 timbl 1574: #endif
1.40 frystyk 1575: } else
1.42 frystyk 1576: HTScreenHeight = 999999;
1.40 frystyk 1577: }
1.23 frystyk 1578:
1.68 frystyk 1579: /* Disable free directory browsing when using telnet host */
1.96 frystyk 1580: if (lm->host && HTFile_dirAccess() == HT_DIR_OK)
1.82 frystyk 1581: HTFile_setDirAccess(HT_DIR_SELECTIVE);
1.1 timbl 1582:
1.96 frystyk 1583: /* Rule file specified? */
1584: if (lm->rules) {
1585: HTList * list = HTList_new();
1586: HTRequest * rr = Thread_new(lm, NO);
1587: char * rules = HTParse(lm->rules, lm->cwd, PARSE_ALL);
1588: HTParentAnchor * ra = (HTParentAnchor *) HTAnchor_findAddress(rules);
1589: HTRequest_setPreemtive(rr, YES);
1590: HTConversion_add(list, "application/x-www-rules", "*/*", HTRules,
1591: 1.0, 0.0, 0.0);
1592: HTRequest_setConversion(rr, list, YES);
1593: if (HTLoadAnchor((HTAnchor *) ra, rr) != YES)
1594: if (SHOW_MSG) TTYPrint(TDEST, "Can't access rules\n");
1595: HTConversion_deleteAll(list);
1596: HTRequest_delete(rr);
1597: FREE(rules);
1.40 frystyk 1598: }
1.1 timbl 1599:
1.40 frystyk 1600: /* Open output file */
1.94 frystyk 1601: if (!HTAlert_interactive()) {
1.99 frystyk 1602: #ifndef _WINDOWS
1.96 frystyk 1603: if (lm->outputfile) {
1.99 frystyk 1604: if ((OUTPUT = fopen(lm->outputfile, "wb")) == NULL) {
1.96 frystyk 1605: if (SHOW_MSG) TTYPrint(TDEST, "Can't open `%s'\\n",
1606: lm->outputfile);
1.100 frystyk 1607: OUTPUT = STDOUT;
1.96 frystyk 1608: }
1609: }
1.99 frystyk 1610: HTRequest_setOutputStream(lm->request, HTFWriter_new(OUTPUT, YES));
1611: #endif
1.58 frystyk 1612:
1.96 frystyk 1613: /*
1614: ** To reformat HTML, just put it through a parser running
1.68 frystyk 1615: ** into a regenerator tbl 940613
1616: */
1.96 frystyk 1617: if (lm->flags & LM_REFORMAT) {
1618: HTStructured * html =
1619: HTMLGenerator(lm->request, NULL, WWW_HTML,
1620: HTRequest_outputFormat(lm->request),
1621: HTRequest_outputStream(lm->request));
1622: HTRequest_setOutputStream(lm->request, SGML_new(&HTMLP_dtd, html));
1.40 frystyk 1623: }
1624: }
1625:
1.96 frystyk 1626: /* Log file specifed? */
1627: if (lm->logfile) HTLog_open(lm->logfile, YES, YES);
1.1 timbl 1628:
1.68 frystyk 1629: /* Just convert formats */
1.96 frystyk 1630: if (lm->flags & LM_FILTER) {
1631: #ifdef STDIN_FILENO
1632: HTRequest_setAnchor(lm->request, (HTAnchor *) lm->anchor);
1633: HTRequest_setPreemtive(lm->request, YES);
1634: HTLoadSocket(STDIN_FILENO, lm->request, FD_NONE);
1.95 frystyk 1635: #endif
1.96 frystyk 1636: Cleanup(lm, 0);
1.40 frystyk 1637: }
1.96 frystyk 1638:
1.94 frystyk 1639: /* Register our User Prompts etc in the Alert Manager */
1.102 frystyk 1640: if (HTAlert_interactive()) {
1641: HTAlert_add(HTError_print, HT_A_MESSAGE);
1642: HTAlert_add(HTConfirm, HT_A_CONFIRM);
1643: HTAlert_add(HTPrompt, HT_A_PROMPT);
1644: HTAlert_add(HTPromptPassword, HT_A_SECRET);
1645: HTAlert_add(HTPromptUsernameAndPassword, HT_A_USER_PW);
1646: }
1.94 frystyk 1647:
1.76 frystyk 1648: /* Register a call back function for the Net Manager */
1.96 frystyk 1649: HTNetInit();
1650: HTNetCall_addAfter(terminate_handler, HT_ALL);
1651:
1652: /* Register our own MIME header handler for extra headers */
1653: HTHeader_addParser("*", NO, header_handler);
1654:
1655: /* Set timeout on sockets */
1656: if (lm->tv->tv_sec < 0) {
1657: lm->tv->tv_sec = HTAlert_interactive() ?
1658: DEFAULT_I_TIMEOUT : DEFAULT_NI_TIMEOUT;
1.93 frystyk 1659: }
1.96 frystyk 1660: HTEvent_registerTimeout(lm->tv, lm->request, timeout_handler, NO);
1661:
1662: /* Set max number of sockets we want open simultanously */
1663: HTNet_setMaxSocket(6);
1664:
1665: /* Set the DNS cache timeout */
1666: HTDNS_setTimeout(3600);
1667:
1668: /* Start the request */
1669: if (keywords)
1670: status = HTSearch(HTChunkData(keywords), lm->anchor, lm->request);
1671: else
1672: status = HTLoadAnchor((HTAnchor *) lm->anchor, lm->request);
1673:
1674: if (keywords) HTChunkFree(keywords);
1675: if (status != YES) {
1676: if (SHOW_MSG) TTYPrint(TDEST, "Couldn't load home page\n");
1677: Cleanup(lm, -1);
1.76 frystyk 1678: }
1.68 frystyk 1679:
1.96 frystyk 1680: /* Set up the rest if we are in interactive mode */
1.94 frystyk 1681: if (HTAlert_interactive()) {
1.73 frystyk 1682:
1.96 frystyk 1683: /* Start History manager */
1684: lm->history = HTHistory_new();
1.73 frystyk 1685:
1686: /* Register our own memory cache handler (implemented in GridText.c) */
1687: HTMemoryCache_register(HTMemoryCache);
1688:
1.83 frystyk 1689: /*
1690: ** Register STDIN as the user socket IF not STDIN is connected to
1691: ** /dev/null or other non-terminal devices
1692: */
1.82 frystyk 1693: #ifdef STDIN_FILENO
1.83 frystyk 1694: if (isatty(STDIN_FILENO)) {
1.98 frystyk 1695: HTEvent_RegisterTTY(STDIN_FILENO, lm->tty, (SockOps)FD_READ,
1.97 frystyk 1696: scan_command, HT_PRIORITY_MAX);
1.83 frystyk 1697: }
1.82 frystyk 1698: #else
1.101 frystyk 1699: HTEvent_RegisterTTY(0, lm->tty, (SockOps)FD_READ, scan_command, 1);
1.82 frystyk 1700: #endif
1.96 frystyk 1701: }
1.77 frystyk 1702:
1.96 frystyk 1703: /* Go into the event loop... */
1704: HTEvent_Loop(lm->request);
1.73 frystyk 1705:
1.96 frystyk 1706: /* Only gets here if event loop fails */
1707: Cleanup(lm, 0);
1708: return 0;
1.14 frystyk 1709: }
Webmaster