Annotation of libwww/LineMode/src/HTBrowse.c, revision 1.170
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.170 ! frystyk 6: ** @(#) $Id: HTBrowse.c,v 1.169 1996/12/05 23:20:23 eric Exp $
1.1 timbl 7: **
8: ** Authors:
9: ** NP: Nicola Pellow Tech.Student CERN 1990-91
1.61 frystyk 10: ** TBL: Tim Berners-Lee CERN (timbl@w3.org)
11: ** JFG: Jean-Francois Groff, Cooperant CERN 1991-92 (jfg@dxcern.cern.ch)
1.1 timbl 12: ** DR: Dudu Rashty +972-2-584848 <RASHTY@hujivms.bitnet>
1.8 duns 13: ** MD: Mark Donszelmann, DELPHI CERN, (duns@vxdeop.cern.ch)
1.96 frystyk 14: ** HFN: Henrik Frystyk Nielsen, MIT, (frystyk@w3.org)
1.1 timbl 15: **
16: ** History:
17: **
18: ** 4 Dec 90: Written from scratch (NP)
19: ** 11 Feb 91: Code written by TBL so that the browser could be linked with
20: ** code produced by Bernd Pollermann, enabling access to the
21: ** data on CERNVM. This involved changing the code to handle file
22: ** numbers rather than file pointers.
23: ** 18 Mar 91: The feature of history mechanism was included, enabling a
24: ** record of previous nodes visited to be kept.
25: ** 6 Apr 91: When a node is accessed, it is immediately read into a
1.40 frystyk 26: ** buffer, in an unformatted state, as soon as the connection is
1.160 frystyk 27: ** made, so that the server is freed as quickly as possible.
1.1 timbl 28: ** The program now also uses the additional modules HTBufferFile.c
29: ** and HTBufferFile.h.
30: ** 17 Apr 91: Can be used on machines running ANSI C and ordinary C.
31: ** 10 May 91: Formatted text is stored in a linked list buffer which allows
32: ** scrolling and better page breaks in the middle of text.
33: ** Code incorporated by Tim BL, to enable anonymous FTP.
34: ** 21 May 91: Accepts various parameters on the command line.
35: ** 19 Aug 91: Currently available in Unix, VAX/VMS and MVS environments.
36: ** 21 Nov 91: Character grid uses new architecture. (TBL)
37: ** added -w option, new commands, print,
38: ** ... See Features.html for further details
39: ** 16 Jan 92: Put in VIOLA-compatible options - see \017 characters.
40: ** \017 and \016 bracket user-selectable input.
41: ** 27 Feb 92: New handling of user input, enhanced command syntax. (JFG)
42: ** 18 May 92: PS command see ifdef SLAVE_PRINTER (DR/TBL)
43: ** 6 Oct 92: Painful recovery from someone(?)'s attept to pretty print.(TBL)
44: ** Please see coding style guide before changing indentation etc!
45: ** Mar 93: Force on HTFile's HTDirAccess and HTDirReadme flags.
1.8 duns 46: ** 3 Nov 93: (MD) Changed vms into VMS
1.99 frystyk 47: ** (MD) Assigne OUTPUT in main, not at initialize (VMS only)
1.1 timbl 48: **
49: ** Compilation-time macro options
50: **
51: ** REF_MARK Printf string to be used for printing anchor numbers
52: ** END_MARK String to be used to denote the end of a document
53: */
54:
1.96 frystyk 55: #include "WWWLib.h"
56: #include "WWWMIME.h"
1.110 frystyk 57: #include "WWWCache.h"
1.96 frystyk 58: #include "WWWApp.h"
1.138 frystyk 59: #include "WWWTrans.h"
1.111 frystyk 60: #include "WWWInit.h"
1.92 frystyk 61:
1.96 frystyk 62: #include "GridText.h" /* Hypertext definition */
1.68 frystyk 63: #include "HTBrowse.h" /* Things exported, short names */
1.138 frystyk 64:
1.121 eric 65: #include "CSLApp.h" /* the PICApp library should provide everything the app needs */
1.126 hallam 66: #include "CSLL.h"
1.121 eric 67: #include "CSUser.h"
1.124 eric 68: #include "CSUsrLst.h"
1.40 frystyk 69:
1.120 frystyk 70: #ifndef W3C_VERSION
71: #define W3C_VERSION "Unspecified"
1.40 frystyk 72: #endif
73:
1.96 frystyk 74: #define APP_NAME "W3CLineMode"
1.120 frystyk 75: #define APP_VERSION W3C_VERSION
1.86 frystyk 76:
1.68 frystyk 77: /* Default page for "Manual" command */
1.140 frystyk 78: #define MANUAL "http://www.w3.org/pub/WWW/LineMode/User/QuickGuide.html"
1.40 frystyk 79:
1.68 frystyk 80: /* Default page for "help" command */
1.140 frystyk 81: #define C_HELP "http://www.w3.org/pub/WWW/LineMode/User/Commands.html"
1.1 timbl 82:
1.68 frystyk 83: /* Default page for "-help" command line option */
1.140 frystyk 84: #define L_HELP "http://www.w3.org/pub/WWW/LineMode/User/CommandLine.html"
1.37 howcome 85:
1.68 frystyk 86: #define DEFAULT_OUTPUT_FILE "www.out"
87: #define DEFAULT_RULE_FILE "www.conf"
88: #define DEFAULT_LOG_FILE "www.log"
1.170 ! frystyk 89: #define DEFAULT_MEMLOG "www.mem"
1.126 hallam 90: #define DEFAULT_USERLIST_FILE "PICSusrs.html"
1.68 frystyk 91:
1.170 ! frystyk 92: #if 0
! 93: #define HT_MEMLOG
! 94: #endif
! 95:
1.68 frystyk 96: #define PROMPT "%s"
97: #define REF_MARK "[%d]"
98: #define END_MARK "[END]"
1.1 timbl 99:
1.72 frystyk 100: #define SCREEN_WIDTH 79 /* Default width of the screen */
1.13 frystyk 101: #define MIN_SCREEN_WIDTH 10
102: #define MAX_SCREEN_WIDTH 150
1.72 frystyk 103: #define SCREEN_HEIGHT 24 /* Default number of lines */
1.13 frystyk 104: #define MIN_SCREEN_HEIGHT 5
1.14 frystyk 105: #define MAX_SCREEN_HEIGHT 200
1.72 frystyk 106:
107: #define MAX_HISTORY 20 /* Don't list more than this in list */
1.1 timbl 108:
1.68 frystyk 109: #define RESPONSE_LENGTH 1024 /* Maximum length of users response */
1.16 frystyk 110:
1.94 frystyk 111: #define SHOW_MSG (WWWTRACE || HTAlert_interactive())
1.68 frystyk 112: #define CHECK_INPUT(a, b) (!strncasecomp ((a), (b), strlen((b))))
1.50 frystyk 113:
1.167 frystyk 114: #define DEFAULT_I_TIMEOUT 1000 /* Interactive timeout in millies */
115: #define DEFAULT_NI_TIMEOUT 10000 /* Non-interactive timeout in millies */
1.96 frystyk 116:
117: #define DEFAULT_FORMAT WWW_PRESENT
1.81 frystyk 118:
1.50 frystyk 119: #if defined(__svr4__)
120: #define CATCH_SIG
121: #endif
1.40 frystyk 122:
123: /* HWL 18/7/94: applied patch from agl@glas2.glas.apc.org (Anton Tropashko) */
124: #ifdef CYRILLIC
1.68 frystyk 125: #include "a_stdio.h"
1.40 frystyk 126: struct ARc arc;
127: #endif
1.2 timbl 128:
1.68 frystyk 129: /* Screen size parameters */
1.40 frystyk 130: PUBLIC int HTScreenWidth = SCREEN_WIDTH; /* By default */
131: PUBLIC int HTScreenHeight = -1; /* -1 = Undefined */
1.68 frystyk 132:
133: /* Anchor specific information */
1.40 frystyk 134: PUBLIC BOOL display_anchors = YES; /* Show anchors in text? */
135: PUBLIC char * start_reference = NULL; /* Format for start anchor */
136: PUBLIC char * end_reference = REF_MARK; /* for end anchor */
137: PUBLIC char * reference_mark = "[%d] "; /* for reference lists */
138: PUBLIC char * end_mark = END_MARK; /* Format string for [End] */
1.8 duns 139:
1.96 frystyk 140: typedef enum _LMFlags {
141: LM_FILTER = 0x1,
142: LM_REFS = 0x2,
143: LM_REFORMAT = 0x4,
144: LM_PREEMTIVE= 0x8
145: } LMFlags;
146:
1.118 eric 147: struct _LineMode {
1.115 frystyk 148: HTRequest * console; /* For user input */
1.96 frystyk 149: HTParentAnchor * anchor;
150: HTList * active; /* List of acitve contexts */
151: HTList * presenters;
152: HTHistory * history; /* History list */
153: char * cwd; /* Current dir URL */
154: char * rules;
155: char * logfile;
156: char * outputfile;
157: char * host;
158: int trace;
1.167 frystyk 159: int timer;
1.96 frystyk 160: HTFormat format; /* Input format from console */
161: LMFlags flags;
1.118 eric 162: HTView * pView;
1.126 hallam 163: char * userList;
1.124 eric 164: CSUser_t * pCSUser;
1.132 eric 165: BOOL noPICSPasswords;
1.118 eric 166: };
1.96 frystyk 167:
168: typedef enum _LMState {
169: LM_UPDATE = 0x1,
170: LM_NO_UPDATE= 0x2,
171: LM_DONE = 0x4,
1.146 frystyk 172: LM_INACTIVE = 0x8,
173: LM_IGNORE = 0x10
1.96 frystyk 174: } LMState;
175:
176: typedef struct _Context {
177: LMState state;
178: HTRequest * request;
179: LineMode * lm;
1.108 frystyk 180: HTParentAnchor * source; /* The source if we are using PUT or POST */
1.96 frystyk 181: } Context;
1.4 timbl 182:
1.162 eric 183: PRIVATE int scan_command (SOCKET s, void * param, HTEventType type);
1.164 frystyk 184:
185: PRIVATE HTEvent * ConsoleEvent = NULL;
1.162 eric 186:
1.106 frystyk 187: #ifndef WWW_WIN_WINDOW
1.118 eric 188: PRIVATE FILE * OUTPUT = stdout;
1.99 frystyk 189: #endif
1.96 frystyk 190:
1.106 frystyk 191: PRIVATE InputParser_t parse_command;
192: InputParser_t * PInputParser = &parse_command;
1.127 frystyk 193:
1.128 frystyk 194: /* Net callback handlers */
1.160 frystyk 195: PRIVATE HTNetAfter terminate_handler;
1.127 frystyk 196:
1.62 frystyk 197: /* ------------------------------------------------------------------------- */
198:
1.162 eric 199: PUBLIC int HTWatch(int id, void * obj, const char * fmt, ...)
200: {
201: va_list pArgs;
202: va_start(pArgs, fmt);
203: fprintf(stderr, "id: %x obj: %p: ", id, obj);
204: return vfprintf(stderr, fmt, pArgs);
205: }
206:
1.96 frystyk 207: /* Create a Context Object
208: ** -----------------------
209: */
1.104 frystyk 210: PRIVATE Context * Context_new (LineMode *lm, HTRequest *request, LMState state)
1.96 frystyk 211: {
1.112 frystyk 212: Context * me;
213: if ((me = (Context *) HT_CALLOC(1, sizeof (Context))) == NULL)
214: HT_OUTOFMEM("Context_new");
1.104 frystyk 215: me->state = state;
1.96 frystyk 216: me->request = request;
217: me->lm = lm;
1.116 frystyk 218: HTRequest_setContext(request, (void *) me);
219: HTList_addObject(lm->active, (void *) me);
1.72 frystyk 220: return me;
221: }
222:
1.96 frystyk 223: /* Delete a Context Object
224: ** -----------------------
1.72 frystyk 225: */
1.96 frystyk 226: PRIVATE BOOL Context_delete (Context * old)
1.72 frystyk 227: {
1.112 frystyk 228: HT_FREE(old);
1.72 frystyk 229: return YES;
230: }
231:
1.118 eric 232: PUBLIC LineMode * Context_getLineMode(HTRequest * request)
233: {
234: return ((Context *) HTRequest_context(request))->lm;
235: }
236:
1.62 frystyk 237: /*
1.96 frystyk 238: ** This function creates a new request object and adds it to the global
1.62 frystyk 239: ** list of active threads
240: */
1.130 eric 241: CSDisposition_callback PICSCallback;
1.104 frystyk 242: PRIVATE HTRequest * Thread_new (LineMode * lm, BOOL Interactive, LMState state)
1.62 frystyk 243: {
1.96 frystyk 244: HTRequest * newreq = HTRequest_new();
245: if (!lm) return NULL;
1.104 frystyk 246: Context_new(lm, newreq, state);
1.96 frystyk 247: if (Interactive) HTRequest_setConversion(newreq, lm->presenters, NO);
1.108 frystyk 248: if (lm->flags & LM_PREEMTIVE) HTRequest_setPreemptive(newreq, YES);
1.104 frystyk 249: HTRequest_addRqHd(newreq, HT_C_HOST);
1.126 hallam 250: CSApp_registerReq(newreq, lm->pCSUser, PICSCallback,
251: CSApp_callOnBad, (void *)lm);
1.62 frystyk 252: return newreq;
253: }
254:
255: /*
1.96 frystyk 256: ** This function deletes all unused request objects
1.62 frystyk 257: */
1.96 frystyk 258: PRIVATE void Thread_cleanup (LineMode * lm)
1.62 frystyk 259: {
1.96 frystyk 260: if (lm && lm->active) {
261: HTList * cur = lm->active;
262: Context * pres;
263: while ((pres = (Context *) HTList_nextObject(cur))) {
1.104 frystyk 264: if (pres->state&LM_DONE && pres->state&LM_INACTIVE) {
265: if ((HTList_removeObject(lm->active, pres)) == NO)
1.118 eric 266: HTTrace("NOT FOUND\n");
1.96 frystyk 267: HTRequest_delete(pres->request);
268: Context_delete(pres);
269: cur = lm->active;
270: }
271: }
1.62 frystyk 272: }
273: }
274:
275: /*
276: ** This function deletes the whole list of active threads.
277: */
1.96 frystyk 278: PRIVATE void Thread_deleteAll (LineMode * lm)
1.62 frystyk 279: {
1.96 frystyk 280: if (lm && lm->active) {
281: HTList * cur = lm->active;
282: Context * pres;
283: while ((pres = (Context *) HTList_nextObject(cur))) {
1.104 frystyk 284: if (pres->request) {
285: HTRequest_delete(pres->request);
286: Context_delete(pres);
287: }
1.62 frystyk 288: }
1.96 frystyk 289: HTList_delete(lm->active);
290: lm->active = NULL;
1.62 frystyk 291: }
292: }
293:
1.96 frystyk 294: /* Create a Line Mode Object
295: ** -------------------------
296: */
297: PRIVATE LineMode * LineMode_new (void)
298: {
299: LineMode * me;
1.167 frystyk 300: if ((me = (LineMode *) HT_CALLOC(1, sizeof(LineMode))) == NULL)
1.112 frystyk 301: HT_OUTOFMEM("LineMode_new");
1.147 frystyk 302: me->cwd = HTGetCurrentDirectoryURL();
1.96 frystyk 303: me->active = HTList_new();
1.115 frystyk 304: me->console = HTRequest_new();
305: Context_new(me, me->console, LM_UPDATE);
1.104 frystyk 306: me->trace = SHOW_ALL_TRACE;
1.167 frystyk 307: me->timer = -1;
1.124 eric 308: me->pCSUser = 0;
1.134 eric 309: if (!(me->pView = HTView_create("'nother Window", 25, 80, me)))
1.130 eric 310: return 0;
1.96 frystyk 311: return me;
312: }
313:
314: /* Delete a Line Mode Object
315: ** -------------------------
316: */
317: PRIVATE BOOL LineMode_delete (LineMode * lm)
318: {
319: if (lm) {
320: Thread_deleteAll(lm);
321: HTPresentation_deleteAll(lm->presenters);
322: HTHistory_delete(lm->history);
1.112 frystyk 323: HT_FREE(lm->cwd);
1.96 frystyk 324: if (lm->logfile) HTLog_close();
1.124 eric 325: if (lm->pCSUser)
326: CSLoadedUser_remove(lm->pCSUser);
1.118 eric 327: HTView_destroy(lm->pView);
1.106 frystyk 328: #ifndef WWW_WIN_WINDOW
1.118 eric 329: if (OUTPUT && OUTPUT != stdout) fclose(OUTPUT);
1.99 frystyk 330: #endif
1.147 frystyk 331: HText_freeAll(); /* Free all loaded documents */
1.112 frystyk 332: HT_FREE(lm);
1.96 frystyk 333: return YES;
334: }
335: return NO;
336: }
337:
1.118 eric 338: PUBLIC HTRequest * LineMode_getConsole(LineMode * pLm)
339: {
340: return pLm->console;
341: }
342:
343: PUBLIC HTView * LineMode_getView(LineMode * pLm)
344: {
345: return pLm ? pLm->pView : 0;
346: }
347:
1.124 eric 348: PRIVATE BOOL LineMode_load(LineMode * lm, HTParentAnchor * anchor,
349: char * url, BOOL preemptive, HTRequest ** pPReq)
350: {
351: char * fullURL;
352: HTParentAnchor * pAnchor;
353:
1.139 frystyk 354: *pPReq = Thread_new(lm, YES, LM_UPDATE);
1.124 eric 355: if (preemptive)
356: HTRequest_setPreemptive(*pPReq, YES);
357: if (anchor)
358: return HTLoadRelative(url, anchor, *pPReq);
359: fullURL = HTParse(url, lm->cwd, PARSE_ALL);
360: pAnchor = (HTParentAnchor *) HTAnchor_findAddress(fullURL);
361: HT_FREE(fullURL);
362: return HTLoadAnchor((HTAnchor *) pAnchor, *pPReq);
363: }
364:
1.96 frystyk 365: PRIVATE void Cleanup (LineMode * me, int status)
366: {
367: if (HTAlert_interactive()) /* Terminate with a LF if not interactive */
1.118 eric 368: OutputData(me->pView, "\n");
1.126 hallam 369: CSLoadedUser_deleteAll();
1.133 eric 370: CSApp_unregisterApp();
1.152 eric 371:
1.96 frystyk 372: LineMode_delete(me);
1.149 frystyk 373: HTProfile_delete();
1.170 ! frystyk 374: #ifdef HT_MEMLOG
1.168 eric 375: HTMemLog_close();
1.170 ! frystyk 376: #endif
! 377:
1.96 frystyk 378: #ifdef VMS
379: exit(status ? status : 1);
380: #else
381: exit(status ? status : 0);
382: #endif
383: }
1.7 secret 384:
385: /*
1.100 frystyk 386: ** Get size of the output screen. Stolen from less.
1.40 frystyk 387: */
1.90 frystyk 388: PRIVATE void scrsize (int * p_height, int * p_width)
1.7 secret 389: {
1.120 frystyk 390: #if defined(HAVE_IOCTL) && defined(HAVE_WINSIZE)
1.96 frystyk 391: register char *s;
1.153 frystyk 392: /* int ioctl(); - henrik */
1.96 frystyk 393: struct winsize w;
394: if (ioctl(2, TIOCGWINSZ, &w) == 0 && w.ws_row > 0)
395: *p_height = w.ws_row;
396: else if ((s = getenv("LINES")) != NULL)
397: *p_height = atoi(s);
398: else
399: *p_height = SCREEN_HEIGHT;
400:
401: if (ioctl(2, TIOCGWINSZ, &w) == 0 && w.ws_col > 0)
402: *p_width = w.ws_col;
403: else if ((s = getenv("COLUMNS")) != NULL)
404: *p_width = atoi(s);
405: else
406: *p_width = 80;
1.120 frystyk 407: #else
408: *p_height = SCREEN_HEIGHT;
409: *p_width = SCREEN_WIDTH;
410: #endif /* HAVE_IOCTL && HAVE_WINSIZE */
1.7 secret 411: }
412:
1.50 frystyk 413: #ifdef CATCH_SIG
414: #include <signal.h>
415: /* SetSignal
416: ** This function sets up signal handlers. This might not be necessary to
417: ** call if the application has its own handlers.
418: */
1.90 frystyk 419: PRIVATE void SetSignal (void)
1.50 frystyk 420: {
421: /* On some systems (SYSV) it is necessary to catch the SIGPIPE signal
422: ** when attemting to connect to a remote host where you normally should
423: ** get `connection refused' back
424: */
425: if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) {
1.118 eric 426: if (PROT_TRACE) HTTrace("HTSignal.... Can't catch SIGPIPE\n");
1.50 frystyk 427: } else {
1.118 eric 428: if (PROT_TRACE) HTTrace("HTSignal.... Ignoring SIGPIPE\n");
1.50 frystyk 429: }
1.170 ! frystyk 430:
! 431: #ifdef HT_MEMLOG
! 432: HTMemLog_flush();
! 433: #endif
! 434:
1.50 frystyk 435: }
436: #endif /* CATCH_SIG */
437:
1.96 frystyk 438: /* Print version information
439: ** -------------------------
440: */
1.118 eric 441: PRIVATE void VersionInfo (LineMode * lm)
1.96 frystyk 442: {
1.160 frystyk 443: HTView * pView = lm ? lm->pView : NULL;
1.118 eric 444: OutputData(pView, "\n\nW3C Reference Software\n\n");
445: OutputData(pView, "\tW3C Line Mode Browser version %s.\n", APP_VERSION);
446: OutputData(pView, "\tW3C Reference Library version %s.\n\n",HTLib_version());
1.160 frystyk 447: OutputData(pView, "Please send feedback to <libwww@w3.org>\n");
1.96 frystyk 448: }
1.7 secret 449:
1.40 frystyk 450: /* Reference_List
451: ** --------------
1.96 frystyk 452: ** Print out a list of HyperText References from current document
1.40 frystyk 453: */
1.96 frystyk 454: PRIVATE void Reference_List (LineMode * lm, BOOL titles)
1.40 frystyk 455: {
1.50 frystyk 456: int refs = HText_sourceAnchors(HTMainText);
457: if (refs <= 0) {
1.118 eric 458: OutputData(lm->pView, "\n\nThere are no references from this document.\n\n");
1.40 frystyk 459: } else {
1.68 frystyk 460: int cnt;
1.118 eric 461: OutputData(lm->pView, "\n*** References from this document ***\n");
1.50 frystyk 462: for (cnt=1; cnt<=refs; cnt++) {
1.146 frystyk 463: HTLink * link =
464: HTAnchor_mainLink((HTAnchor*)HText_childNumber(HTMainText,cnt));
465: HTAnchor * dest = HTLink_destination(link);
1.50 frystyk 466: HTParentAnchor * parent = HTAnchor_parent(dest);
467: char * address = HTAnchor_address(dest);
1.120 frystyk 468: const char * title = titles ? HTAnchor_title(parent) : NULL;
1.118 eric 469: OutputData(lm->pView, reference_mark, cnt);
470: OutputData(lm->pView, "%s%s\n",
1.50 frystyk 471: ((HTAnchor*)parent!=dest) && title ? "in " : "",
1.40 frystyk 472: (char *)(title ? title : address));
1.112 frystyk 473: HT_FREE(address);
1.40 frystyk 474: }
1.106 frystyk 475: #ifndef WWW_WIN_WINDOW
1.99 frystyk 476: fflush(OUTPUT);
477: #endif
1.40 frystyk 478: }
479: }
1.1 timbl 480:
1.96 frystyk 481: /* History_List
482: ** ------------
1.68 frystyk 483: ** Display a history list of nodes visited during the session.
1.1 timbl 484: */
1.96 frystyk 485: PRIVATE void History_List (LineMode * lm)
486: {
487: int current = HTHistory_position(lm->history);
488: int max = HTHistory_count(lm->history);
1.70 frystyk 489: int cnt;
1.118 eric 490: OutputData(lm->pView, "\n Documents you have visited: ");
1.70 frystyk 491: if (max > MAX_HISTORY) {
492: max = MAX_HISTORY;
1.118 eric 493: OutputData(lm->pView, "(truncated)\n");
1.70 frystyk 494: } else
1.118 eric 495: OutputData(lm->pView, "\n");
1.70 frystyk 496: for (cnt=1; cnt<=max; cnt++) {
1.96 frystyk 497: HTAnchor *anchor = HTHistory_list(lm->history, cnt);
1.70 frystyk 498: char *address = HTAnchor_address(anchor);
499: HTParentAnchor *parent = HTAnchor_parent(anchor);
1.120 frystyk 500: const char *title = HTAnchor_title(parent);
1.118 eric 501: OutputData(lm->pView, "%s R %d\t%s%s\n",
1.70 frystyk 502: (cnt==current) ? "*" : " ",
503: cnt,
1.68 frystyk 504: ((HTAnchor*)parent!=anchor) && title ? "in " : "",
505: title ? title : address);
1.112 frystyk 506: HT_FREE(address);
1.70 frystyk 507: }
1.118 eric 508: OutputData(lm->pView, "\n");
1.1 timbl 509: }
510:
1.94 frystyk 511: /* Prompt for answer and get text back. Reply text is either NULL on
1.120 frystyk 512: ** error or a dynamic string which the caller must HT_FREE.
1.94 frystyk 513: */
1.120 frystyk 514: PRIVATE char * AskUser (HTRequest * request, const char * Msg,
515: const char * deflt)
1.94 frystyk 516: {
517: char buffer[200];
518: char *reply = NULL;
1.118 eric 519: HTTrace("%s ", Msg ? Msg : "UNKNOWN");
1.94 frystyk 520: if (deflt)
1.118 eric 521: HTTrace("(RETURN for [%s]) ", deflt);
1.94 frystyk 522:
523: #ifndef NO_STDIO
524: if (!fgets(buffer, 200, stdin))
525: return NULL; /* NULL string on error, Henrik */
526: buffer[strlen(buffer)-1] = '\0'; /* Overwrite newline */
527: if (*buffer)
528: StrAllocCopy(reply, buffer);
529: else if (deflt)
530: StrAllocCopy(reply, deflt);
531: #endif
532: return reply;
533: }
534:
1.120 frystyk 535: PRIVATE BOOL confirm (HTRequest * request, const char * Msg)
1.94 frystyk 536: {
1.96 frystyk 537: char response[4];
1.118 eric 538: HTTrace("%s (y/n) ", Msg ? Msg : "UNKNOWN");
1.94 frystyk 539: #ifndef NO_STDIO
1.96 frystyk 540: if (fgets(response, 4, stdin)) /* get reply, max 3 chars */
1.94 frystyk 541: #endif
1.96 frystyk 542: {
543: char *ptr = response;
544: while (*ptr) {
545: if (*ptr == '\n') {
546: *ptr = '\0';
547: break;
548: }
549: *ptr = TOUPPER(*ptr);
550: ptr++;
551: }
552: return (!strcmp(response, "YES") || !strcmp(response, "Y")) ? YES : NO;
1.94 frystyk 553: }
1.96 frystyk 554: return NO;
1.94 frystyk 555: }
1.1 timbl 556:
1.96 frystyk 557: /* MakeCommandLine
558: ** ---------------
1.40 frystyk 559: ** Generate the Prompt line and flush it to the user
1.1 timbl 560: */
1.96 frystyk 561: PRIVATE void MakeCommandLine (LineMode * lm, BOOL is_index)
1.40 frystyk 562: {
1.70 frystyk 563: /* First Line */
1.69 frystyk 564: if (HTAnchor_hasChildren(HTMainAnchor)) {
1.40 frystyk 565: int refs = HText_sourceAnchors(HTMainText);
1.69 frystyk 566: if (refs>1)
1.118 eric 567: OutputData(lm->pView, "1-%d, ", refs);
1.69 frystyk 568: else
1.118 eric 569: OutputData(lm->pView, "1, ");
1.40 frystyk 570: }
1.70 frystyk 571: if (HText_canScrollUp(HTMainText)) {
1.118 eric 572: OutputData(lm->pView, "Top, ");
573: OutputData(lm->pView, "Up, ");
1.70 frystyk 574: }
575: if (HText_canScrollDown(HTMainText)) {
1.118 eric 576: OutputData(lm->pView, "BOttom, ");
577: OutputData(lm->pView, "Down or <RETURN> for more,");
1.70 frystyk 578: }
1.69 frystyk 579:
1.70 frystyk 580: /* Second Line */
1.118 eric 581: OutputData(lm->pView, "\n");
1.96 frystyk 582: if (HTHistory_canBacktrack(lm->history))
1.118 eric 583: OutputData(lm->pView, "Back, ");
1.96 frystyk 584: if (HTHistory_canForward(lm->history))
1.118 eric 585: OutputData(lm->pView, "Forward, ");
1.70 frystyk 586: if (is_index)
1.118 eric 587: OutputData(lm->pView, "FIND <keywords>, ");
588: OutputData(lm->pView, "Quit, or Help: ");
1.44 frystyk 589: fflush(stdout); /* For use to flush out the prompt */
1.40 frystyk 590: return;
591: }
1.1 timbl 592:
1.40 frystyk 593: /*
1.150 frystyk 594: ** PUT the current document to the destination specified by the user
1.110 frystyk 595: ** Returns the result of the load function.
596: */
1.150 frystyk 597: PRIVATE int PutAnchor (LineMode * lm, HTRequest * request)
1.110 frystyk 598: {
1.150 frystyk 599: char * dest = AskUser(request, "Destination: ", NULL);
1.110 frystyk 600:
1.150 frystyk 601: /*
602: ** If user has typed a destination then create a new request object and
603: ** start the PUT operation. The destination is taken relative to the
604: ** current location.
605: */
606: if (dest) {
607: HTRequest * new_request = Thread_new(lm, YES, LM_UPDATE);
1.158 frystyk 608: HTPutDocumentRelative(HTMainAnchor, dest, HTMainAnchor, new_request);
1.150 frystyk 609: HT_FREE(dest);
610: }
1.158 frystyk 611: return YES;
1.150 frystyk 612: }
1.110 frystyk 613:
1.150 frystyk 614: /*
615: ** Delete the current document.
616: */
617: PRIVATE int DeleteAnchor (LineMode * lm, HTRequest * request)
618: {
619: int status = HT_INTERNAL;
620: BOOL doit = confirm(request, "Delete the current document?");
621: if (doit) {
622: HTRequest * new_request = Thread_new(lm, YES, LM_UPDATE);
623: status = HTDeleteAnchor((HTAnchor *) HTMainAnchor, new_request);
1.110 frystyk 624: }
625: return status;
626: }
627:
628: /*
1.40 frystyk 629: ** This function puts up a stream to a file in order to save a document. This
630: ** is activated by '>', '>>' or '>!' from the prompt line.
1.1 timbl 631: */
1.90 frystyk 632: PRIVATE BOOL SaveOutputStream (HTRequest * req, char * This, char * Next)
1.40 frystyk 633: {
634: FILE *fp;
635: char *fname;
636: char *fmode;
637:
638: /* Checks if file exists. Can be overruled by using '>!' */
639: if (*(This+1) == '>') { /* Append to file */
1.74 frystyk 640: fmode = "ab";
1.40 frystyk 641: fname = *(This+2) ? (This+2) : Next;
642: } else if (*(This+1) == '!') {
1.74 frystyk 643: fmode = "wb"; /* Overwrite file */
1.40 frystyk 644: fname = *(This+2) ? (This+2) : Next;
645: } else { /* File name follows */
1.74 frystyk 646: fmode = "wb";
1.40 frystyk 647: fname = *(This+1) ? (This+1) : Next;
648: if (fname) { /* See if file exists */
649: if ((fp = fopen(fname, "r")) != NULL) {
650: fclose(fp);
1.94 frystyk 651: if (!confirm(req, "File exists - overwrite?"))
1.92 frystyk 652: return NO;
1.40 frystyk 653: }
654: }
655: }
656: if (!fname) /* No file name given */
657: return NO;
658: if ((fp = fopen(fname, fmode)) == NULL) {
1.118 eric 659: if (SHOW_MSG) HTTrace("Can't access file (%s)\n", fname);
1.40 frystyk 660: return NO;
661: }
1.109 frystyk 662: HTRequest_setOutputStream(req, HTFWriter_new(req, fp, NO));
1.118 eric 663: if (SHOW_MSG) HTTrace("Saving to file `%s\'\n", fname);
1.58 frystyk 664: return (HTLoadAnchor((HTAnchor*) HTMainAnchor, req) != HT_WOULD_BLOCK);
1.40 frystyk 665: }
1.1 timbl 666:
1.124 eric 667: CSError_t LoadedUsersCallback(CSUser_t * pCSUser, int index, void * pVoid)
1.121 eric 668: {
669: LineMode * lm = (LineMode *)pVoid;
1.124 eric 670: OutputData(lm->pView, "%d: %s\n", index, CSUser_name(pCSUser));
671: return CSError_OK;
1.121 eric 672: }
673:
1.124 eric 674: CSError_t UserListCallback(char * username, char * url, int index, void * pVoid)
1.121 eric 675: {
676: LineMode * lm = (LineMode *)pVoid;
677: OutputData(lm->pView, "%d: %s %s\n", index, username, url);
1.124 eric 678: return CSError_OK;
1.121 eric 679: }
680:
681: PRIVATE BOOL ShowPICSUsers(LineMode * lm)
682: {
683: OutputData(lm->pView, "Loaded users:\n");
1.124 eric 684: CSLoadedUser_enum(&LoadedUsersCallback, (void *)lm);
1.121 eric 685: OutputData(lm->pView, "Listed users:\n");
686: CSUserList_enum(&UserListCallback, (void *)lm);
687: return YES;
688: }
689:
1.126 hallam 690: PRIVATE int PICS_userCallback(CSUser_t * pCSUser, void * pVoid)
691: {
692: LineMode * lm = (LineMode *)pVoid;
693: char * userName;
694: char * password = NULL;
1.132 eric 695: HTAlertCallback *cbf;
1.126 hallam 696: int ret;
697: HTAlertPar * reply;
698:
1.132 eric 699: if (lm->noPICSPasswords) {
700: lm->pCSUser = pCSUser;
701: return 0;
702: }
703: if (!(cbf = HTAlert_find(HT_A_USER_PW)))
1.126 hallam 704: return -1;
705: reply = HTAlert_newReply();
706: userName = CSUser_name(pCSUser);
707: if ((ret = (*cbf)(lm->console, HT_A_USER_PW,
708: HT_MSG_NULL, userName, NULL, reply))) {
709: userName = HTAlert_replyMessage(reply);
710: password = HTAlert_replySecret(reply);
711: }
712: HTAlert_deleteReply(reply);
713: if (!ret) {
714: HTTrace("PICS set user *canceled*.\n");
715: return -1;
716: }
717: ret = -1;
718: if (!userName)
719: HTTrace("PICS cannot set to no name.\n");
720: else if (CSUser_checkPassword(pCSUser, password) == NO)
721: HTTrace("PICS password was not valid.\n");
722: else {
723: ret = 0;
724: lm->pCSUser = pCSUser;
725: }
726: HT_FREE(userName);
727: HT_FREE(password);
728: return ret;
729: }
730:
1.124 eric 731: PRIVATE BOOL SetPICSUser(LineMode * lm, char * userName)
1.121 eric 732: {
733: char * password = NULL;
1.132 eric 734: HTAlertCallback *cbf;
1.121 eric 735: BOOL ret;
1.124 eric 736: HTAlertPar * reply;
1.121 eric 737:
1.132 eric 738: if (!(cbf = HTAlert_find(HT_A_USER_PW)))
1.124 eric 739: return NO;
740: reply = HTAlert_newReply();
1.125 eric 741: if ((ret = (*cbf)(lm->console, HT_A_USER_PW,
742: HT_MSG_NULL, userName, NULL, reply))) {
1.124 eric 743: userName = HTAlert_replyMessage(reply);
744: password = HTAlert_replySecret(reply);
745: }
746: HTAlert_deleteReply(reply);
1.125 eric 747: if (!ret) {
748: HTTrace("PICS set user *canceled*.\n");
749: return NO;
750: }
1.126 hallam 751: ret = NO;
1.124 eric 752: if (!userName)
753: HTTrace("Canceled.\n");
1.126 hallam 754: else if (!(lm->pCSUser = CSApp_registerUserByName(userName, password))) {
1.124 eric 755: char * url;
756: if ((url = CSUserList_findURL(userName)) == NULL)
757: HTTrace("PICS user \"%s\" is unknown.\n", userName);
1.130 eric 758: else if (!CSLoadedUser_load(url, lm->cwd))
1.124 eric 759: HTTrace("Can't load PICS user \"%s\".\n", userName);
760: else if ((CSLoadedUser_find(userName)) == NO)
761: HTTrace("PICS user \"%s\" not found in \"%s\".\n", userName, url);
1.126 hallam 762: else if (!(lm->pCSUser = CSApp_registerUserByName(userName, password)))
1.124 eric 763: HTTrace("Failed to set PICS user to \"%s\".\n", userName);
1.126 hallam 764: ret = YES;
1.124 eric 765: HT_FREE(url);
766: }
767: HT_FREE(userName);
768: HT_FREE(password);
769: return ret;
770: }
771:
772: PRIVATE BOOL LoadPICSUser(LineMode * lm, char * url)
773: {
774: CSUser_t * pCSUser;
775: if (!(pCSUser = CSLoadedUser_load(url, lm->cwd)))
776: return NO;
1.126 hallam 777: lm->pCSUser = pCSUser;
778: return YES;
1.124 eric 779: }
780:
1.126 hallam 781: CSError_t PICSCallback(HTRequest* pReq, CSLabel_t * pCSLabel,
782: CSUser_t * pCSUser, CSError_t disposition, void * pVoid)
1.124 eric 783: {
784: LineMode * lm = (LineMode *)pVoid;
1.126 hallam 785: char * mesg;
1.124 eric 786: switch (disposition) {
1.126 hallam 787: case CSError_RATING_RANGE:
788: {
789: char * labelStr = CSLabel_getRatingStr(pCSLabel);
790: char * userStr = CSUser_getRatingStr(pCSUser);
1.135 eric 791: char * anchorStr = HTAnchor_address((HTAnchor*)HTRequest_anchor(pReq));
1.126 hallam 792: OutputData(lm->pView, "PICS user %s is not allowed to see document: %s\n",
1.135 eric 793: CSUser_name(pCSUser), anchorStr);
1.126 hallam 794: OutputData(lm->pView, " %s's \"%s\" rating for service %s (%s) did not include %s\n",
795: CSUser_name(pCSUser),
796: CSLabel_getRatingName(pCSLabel),
797: CSLabel_getServiceName(pCSLabel),
798: userStr, labelStr);
799: HT_FREE(userStr);
800: HT_FREE(labelStr);
1.135 eric 801: HT_FREE(anchorStr);
1.126 hallam 802: }
803: return disposition;
804: case CSError_BUREAU_NONE: mesg="label bureau was not contacted"; break;
1.134 eric 805: case CSError_RATING_VALUE: mesg="value"; break;
1.126 hallam 806: case CSError_RATING_MISSING: mesg="rating not found"; break;
1.134 eric 807: case CSError_SINGLELABEL_MISSING: mesg="no single-labels found"; break;
1.126 hallam 808: case CSError_SERVICE_MISSING: mesg="service not available";break;
809: case CSError_SERVICE_NONE: mesg="no services available for document"; break;
810: case CSError_RATING_NONE: mesg="no ratings in a service"; break;
811: case CSError_BAD_DATE: mesg="labels were out of date"; break;
812: default:HTTrace("PICSCallback: odd error code: %d\n", disposition); return disposition;
1.124 eric 813: }
1.126 hallam 814: OutputData(lm->pView, "PICS disallowed document: %s\n", mesg);
1.124 eric 815: return disposition;
1.121 eric 816: }
817:
1.62 frystyk 818: /* ------------------------------------------------------------------------- */
819: /* EVENT FUNCTIONS */
820: /* ------------------------------------------------------------------------- */
1.1 timbl 821:
1.89 frystyk 822: /* parse_command
1.76 frystyk 823: ** ------------
1.89 frystyk 824: ** Given the user's input, deal with it as necessary.
1.40 frystyk 825: ** Any Command which works returns from the routine. If nothing
826: ** works then a search or error message down at the bottom.
1.76 frystyk 827: **
828: ** Returns HT_ERROR Error has occured or we quit
829: ** HT_OK Call back was OK
1.1 timbl 830: */
1.162 eric 831: PRIVATE int parse_command (char* choice, SOCKET s, HTRequest *req, HTEventType type)
1.101 frystyk 832: {
1.68 frystyk 833: char * the_choice=NULL; /* preserved user command */
834: char * token=NULL; /* First word of command */
835: char * this_command; /* token and following */
1.40 frystyk 836: char * next_word; /* Second word */
837: char * other_words; /* Second word and following */
1.14 frystyk 838: BOOL is_index = HTAnchor_isIndex(HTMainAnchor);
1.48 frystyk 839: BOOL found = YES;
1.68 frystyk 840: BOOL OutSource = NO; /* Output source, YES/NO */
1.76 frystyk 841: int status = YES;
1.114 frystyk 842: HTRequest * cur_req = NULL;
843: Context * cur_context = NULL;
844: LineMode * lm = NULL;
1.101 frystyk 845:
1.114 frystyk 846: cur_req = req;
1.106 frystyk 847: cur_context = (Context *) HTRequest_context(req);
848: lm = cur_context->lm;
1.40 frystyk 849:
850: StrAllocCopy (the_choice, choice); /* Remember it as is, */
1.91 frystyk 851: if (*the_choice && the_choice[strlen(the_choice)-1] == '\n') /* final \n */
1.40 frystyk 852: the_choice[strlen(the_choice)-1] = '\0';
1.14 frystyk 853:
1.68 frystyk 854: token = strtok (choice, " \t\n\r"); /* Tokenize user input */
1.40 frystyk 855: this_command = the_choice;
1.68 frystyk 856: if (token) {
1.40 frystyk 857: next_word = strtok (NULL, " \t\n\r");
858: other_words = the_choice + (next_word - choice);
1.14 frystyk 859: }
1.40 frystyk 860: else
861: goto down; /* Empty input : scroll down */
862:
863: /* Process Command */
864: loop:
1.68 frystyk 865: switch (TOUPPER(*token)) {
1.40 frystyk 866: case '0':
867: case '1':
868: case '2':
869: case '3':
870: case '4':
871: case '5':
872: case '6':
873: case '7':
874: case '8':
875: case '9':
1.68 frystyk 876: {
877: int ref_num;
878: sscanf(token,"%d",&ref_num);
879: if (ref_num>0 && ref_num<=HText_sourceAnchors(HTMainText)) {
880: HTChildAnchor *source = HText_childNumber(HTMainText, ref_num);
881: if (source) {
1.146 frystyk 882: HTLink * link = HTAnchor_mainLink((HTAnchor *) source);
883: HTAnchor * destination = HTLink_destination(link);
884: req = Thread_new(lm, YES, LM_UPDATE);
1.69 frystyk 885:
886: /* Continous browsing, so we want Referer field */
1.90 frystyk 887: HTRequest_setParent(req,
888: HTAnchor_parent((HTAnchor*)source));
1.123 frystyk 889: HTLoadAnchor(destination, req);
1.68 frystyk 890: } else {
1.76 frystyk 891: status = NO; /* No anchor */
1.68 frystyk 892: }
1.45 frystyk 893: } else {
1.68 frystyk 894: if (SHOW_MSG)
1.118 eric 895: HTTrace("Warning: Invalid Reference Number: (%d)\n",
1.68 frystyk 896: ref_num);
1.44 frystyk 897: }
1.40 frystyk 898: }
899: break;
900:
901: case 'B':
1.68 frystyk 902: if (CHECK_INPUT("BACK", token)) { /* Return to previous node */
1.96 frystyk 903: if (HTHistory_canBacktrack(lm->history)) {
1.104 frystyk 904: req = Thread_new(lm, YES, LM_NO_UPDATE);
1.96 frystyk 905: status = HTLoadAnchor(HTHistory_back(lm->history), req);
1.40 frystyk 906: } else {
1.118 eric 907: OutputData(lm->pView, "\nThis is the first document in history list\n");
1.40 frystyk 908: }
1.68 frystyk 909: } else if (CHECK_INPUT("BOTTOM", token)) { /* Scroll to bottom */
1.40 frystyk 910: HText_scrollBottom(HTMainText);
1.48 frystyk 911: } else
912: found = NO;
1.40 frystyk 913: break;
914:
1.51 frystyk 915: case 'C':
1.120 frystyk 916: #ifdef HAVE_CHDIR
1.68 frystyk 917: if (CHECK_INPUT("CD", token)) { /* Change working directory ? */
1.40 frystyk 918: goto lcd;
1.64 frystyk 919: } else
1.120 frystyk 920: #endif /* HAVE_CHDIR */
1.69 frystyk 921: if (CHECK_INPUT("CLEAR", token)) { /* Clear History list */
1.96 frystyk 922: HTHistory_removeFrom(lm->history, 1);
1.69 frystyk 923: } else
1.48 frystyk 924: found = NO;
1.40 frystyk 925: break;
926:
927: case 'D':
1.108 frystyk 928: if (CHECK_INPUT("DELETE", token)) { /* DELETE */
1.150 frystyk 929: status = DeleteAnchor(lm, req);
1.108 frystyk 930: } else if (CHECK_INPUT("DOWN", token)) { /* Scroll down one page */
1.40 frystyk 931: down:
932: if (HText_canScrollDown(HTMainText))
933: HText_scrollDown(HTMainText);
1.48 frystyk 934: } else
935: found = NO;
1.40 frystyk 936: break;
937:
1.51 frystyk 938: case 'E':
1.68 frystyk 939: if (CHECK_INPUT("EDIT", token)) {
1.150 frystyk 940: status = PutAnchor(lm, req);
1.68 frystyk 941: } else if (CHECK_INPUT("EXIT", token)) { /* Quit program? */
1.76 frystyk 942: status = NO;
1.48 frystyk 943: } else
944: found = NO;
1.40 frystyk 945: break;
946:
947: case 'F': /* Keyword search ? */
1.68 frystyk 948: if (is_index && CHECK_INPUT("FIND", token)) {
1.40 frystyk 949: find:
1.47 frystyk 950: {
951: if (next_word) {
1.104 frystyk 952: req = Thread_new(lm, YES, LM_UPDATE);
1.150 frystyk 953: status = HTSearchString(other_words,
954: (HTAnchor *) HTMainAnchor, req);
1.47 frystyk 955: }
956: }
1.158 frystyk 957: } else if (CHECK_INPUT("FLUSH", token)) { /* Flush file cache */
958: if (confirm(req, "Flush Persistent Cache?") == YES)
959: HTCache_flushAll();
960:
1.69 frystyk 961: } else if (CHECK_INPUT("FORWARD", token)) {
1.96 frystyk 962: if (HTHistory_canForward(lm->history)) {
1.104 frystyk 963: req = Thread_new(lm, YES, LM_NO_UPDATE);
1.96 frystyk 964: status = HTLoadAnchor(HTHistory_forward(lm->history), req);
1.69 frystyk 965: } else {
1.118 eric 966: OutputData(lm->pView, "\nThis is the last document in history list.\n");
1.69 frystyk 967: }
1.48 frystyk 968: } else
969: found = NO;
1.40 frystyk 970: break;
971:
972: case 'G':
1.68 frystyk 973: if (CHECK_INPUT("GOTO", token)) { /* GOTO */
1.124 eric 974: if (next_word)
975: status = LineMode_load(lm, HTMainAnchor, next_word, NO, &req);
1.48 frystyk 976: } else
977: found = NO;
1.40 frystyk 978: break;
979:
980: case '?':
1.124 eric 981: status = LineMode_load(lm, HTMainAnchor, C_HELP, YES, &req);
1.47 frystyk 982: break;
1.40 frystyk 983:
984: case 'H':
1.68 frystyk 985: if (CHECK_INPUT("HELP", token)) { /* help menu, ..*/
1.124 eric 986: status = LineMode_load(lm, HTMainAnchor, C_HELP, YES, &req);
1.68 frystyk 987: } else if (CHECK_INPUT("HOME", token)) { /* back HOME */
1.96 frystyk 988: if (!HTHistory_canBacktrack(lm->history)) {
1.40 frystyk 989: HText_scrollTop(HTMainText);
990: } else {
1.104 frystyk 991: req = Thread_new(lm, YES, LM_NO_UPDATE);
1.96 frystyk 992: status = HTLoadAnchor(HTHistory_find(lm->history, 1), req);
1.40 frystyk 993: }
1.48 frystyk 994: } else
995: found = NO;
1.40 frystyk 996: break;
997:
998: case 'K': /* Keyword search ? */
1.68 frystyk 999: if (is_index && CHECK_INPUT("KEYWORDS", token)) {
1.40 frystyk 1000: goto find;
1.48 frystyk 1001: } else
1002: found = NO;
1.40 frystyk 1003: break;
1004:
1005: case 'L':
1.68 frystyk 1006: if (CHECK_INPUT("LIST", token)) { /* List of references ? */
1.96 frystyk 1007: Reference_List(lm, !OutSource);
1.40 frystyk 1008: }
1.120 frystyk 1009: #ifdef HAVE_CHDIR
1.68 frystyk 1010: else if (CHECK_INPUT ("LCD", token)) { /* Local change dir ? */
1.40 frystyk 1011: lcd:
1012: if (!next_word) { /* Missing argument */
1.118 eric 1013: OutputData(lm->pView, "\nName of the new local directory missing.\n");
1.47 frystyk 1014: } else if (chdir (next_word)) { /* failed : say why */
1.118 eric 1015: OutputData(lm->pView, "\n ");
1.40 frystyk 1016: perror (next_word);
1.47 frystyk 1017: } else { /* Success : display new local directory */
1.127 frystyk 1018: #ifdef HAVE_GETCWD
1019: OutputData(lm->pView, "\nLocal directory is now:\n %s\n",
1020: getcwd (choice, sizeof(choice)));
1021: #else
1.120 frystyk 1022: #ifdef HAVE_GETWD
1.118 eric 1023: OutputData(lm->pView, "\nLocal directory is now:\n %s\n",
1.120 frystyk 1024: (char *) getwd (choice));
1025: #else
1026: #error "This platform doesn't support getwd or getcwd"
1.68 frystyk 1027: if (SHOW_MSG)
1.120 frystyk 1028: HTTrace("This platform doesn't support getwd or getcwd\n");
1.127 frystyk 1029: #endif /* HAVE_GETWD */
1.120 frystyk 1030: #endif /* HAVE_GETCWD */
1.40 frystyk 1031: }
1032: }
1.120 frystyk 1033: #endif /* HAVE_CHDIR */
1.124 eric 1034: else if (CHECK_INPUT("LUSER", token)) { /* List of references ? */
1035: if (next_word) {
1036: LoadPICSUser(lm, next_word);
1037: } else {
1038: HTTrace("URL needed\n");
1039: }
1040: } else
1.48 frystyk 1041: found = NO;
1.40 frystyk 1042: break;
1043:
1044: case 'M':
1.68 frystyk 1045: if (CHECK_INPUT("MANUAL", token)) { /* Read User manual */
1.124 eric 1046: status = LineMode_load(lm, HTMainAnchor, MANUAL, YES, &req);
1.158 frystyk 1047: } else
1048: found = NO;
1049: break;
1050:
1051: case 'O':
1052: if (CHECK_INPUT("OPTIONS", token)) { /* OPTIONS method */
1053: req = Thread_new(lm, YES, LM_NO_UPDATE);
1054: status = HTOptionsAnchor((HTAnchor*)
1055: (HTMainAnchor ? HTMainAnchor:lm->anchor),
1056: req);
1.48 frystyk 1057: } else
1058: found = NO;
1.40 frystyk 1059: break;
1060:
1061: case 'P':
1.68 frystyk 1062: if (CHECK_INPUT("POST", token)) {
1.151 frystyk 1063: status = PutAnchor(lm, req);
1.40 frystyk 1064: }
1.70 frystyk 1065:
1.120 frystyk 1066: #ifdef HAVE_SYSTEM
1.96 frystyk 1067: else if (!lm->host && CHECK_INPUT("PRINT", token)) {
1.40 frystyk 1068: char * address = HTAnchor_address((HTAnchor *) HTMainAnchor);
1069: char * command;
1.62 frystyk 1070: char * tmplate = (char *) getenv("WWW_PRINT_COMMAND");
1.40 frystyk 1071: int result;
1072:
1.46 frystyk 1073: if (!tmplate) tmplate = "www -n -na -p66 '%s' | lpr";
1.126 hallam 1074: if ((command = (char *) HT_MALLOC(strlen(address)+strlen(tmplate)+20)) == NULL)
1.112 frystyk 1075: HT_OUTOFMEM("command");
1.46 frystyk 1076: sprintf(command, tmplate, address);
1.40 frystyk 1077: result = system(command);
1.112 frystyk 1078: HT_FREE(address);
1079: HT_FREE(command);
1.118 eric 1080: if (result) OutputData(lm->pView, " %s\n returns %d\n", command, result);
1.40 frystyk 1081: }
1082: #endif
1083: /* this command prints the entire current text to the
1084: terminal's printer; at the end it displays the top of the text */
1085: #ifdef SLAVE_PRINTER
1086: #define SLAVE_PRINTER_ON "\033\133\065\151"
1087: #define SLAVE_PRINTER_OFF "\033\133\064\151"
1088:
1.68 frystyk 1089: else if (CHECK_INPUT("PS", token)) {
1.118 eric 1090: OutputData(lm->pView, "%s",SLAVE_PRINTER_ON);
1091: OutputData(lm->pView, "\f"); /* Form feed for new page */
1.40 frystyk 1092: HText_scrollTop(HTMainText);
1093: while(HText_canScrollDown(HTMainText)) {
1094: HText_scrollDown(HTMainText);
1095: }
1.118 eric 1096: OutputData(lm->pView, "\f"); /* Form feed for new page */
1097: OutputData(lm->pView, "%s",SLAVE_PRINTER_OFF);
1.40 frystyk 1098: HText_scrollTop(HTMainText);
1099: }
1100: #endif
1.68 frystyk 1101: else if (CHECK_INPUT("PUT", token)) {
1.151 frystyk 1102: status = PutAnchor(lm, req);
1.62 frystyk 1103: } else
1.48 frystyk 1104: found = NO;
1.40 frystyk 1105: break;
1106:
1107: case 'Q': /* Quit program ? */
1.68 frystyk 1108: if (CHECK_INPUT("QUIT", token)) {
1.47 frystyk 1109:
1.40 frystyk 1110: /* JFG 9/7/92, following a complaint of 'q' mis-typed for '1'.
1111: JFG Then made optional because I hate it !!!
1112: TBL made it only affect remote logged on users. 921122 */
1113:
1.96 frystyk 1114: if (lm->host && (strcasecomp(token, "quit") != 0) ) {
1.118 eric 1115: OutputData(lm->pView, "\n Please type \"quit\" in full to leave www.\n");
1.76 frystyk 1116: } else {
1117: HTNet_killAll(); /* Kill all requests */
1118: status = NO;
1119: }
1.48 frystyk 1120: } else
1121: found = NO;
1.40 frystyk 1122: break;
1123:
1124: case 'R':
1.68 frystyk 1125: if (CHECK_INPUT("RECALL", token)) {
1.96 frystyk 1126: if (HTHistory_count(lm->history) <= 1) {
1.118 eric 1127: OutputData(lm->pView, "\n No other documents to recall.\n");
1.47 frystyk 1128: } else {
1129: /* Previous node number exists, or does the user just */
1130: /* require a list of nodes visited? */
1.69 frystyk 1131: if (next_word) {
1132: int cnt;
1133: if ((cnt = atoi(next_word)) > 0) {
1.104 frystyk 1134: req = Thread_new(lm, YES, LM_NO_UPDATE);
1.96 frystyk 1135: status = HTLoadAnchor(HTHistory_find(lm->history,cnt), req);
1.47 frystyk 1136: } else {
1.68 frystyk 1137: if (SHOW_MSG)
1.118 eric 1138: HTTrace("Bad command (%s), for list of commands type help\n", this_command);
1.47 frystyk 1139: }
1140: } else {
1.96 frystyk 1141: History_List(lm);
1.47 frystyk 1142: }
1.40 frystyk 1143: }
1.68 frystyk 1144: } else if (CHECK_INPUT("REFRESH", token)) {
1.50 frystyk 1145: HText_setStale(HTMainText); /* Force refresh */
1146: HText_refresh(HTMainText); /* Refresh screen */
1.156 frystyk 1147:
1148: } else if (CHECK_INPUT("REVALIDATE", token)) {
1149: req = Thread_new(lm, YES, LM_NO_UPDATE);
1150:
1151: /*
1152: ** Add a end-to-end validator to the request
1153: */
1154: HTRequest_setReloadMode(req, HT_CACHE_END_VALIDATE);
1155: status = HTLoadAnchor((HTAnchor*) (HTMainAnchor ? HTMainAnchor :
1156: lm->anchor), req);
1.68 frystyk 1157: } else if (CHECK_INPUT("RELOAD", token)) {
1.104 frystyk 1158: req = Thread_new(lm, YES, LM_NO_UPDATE);
1.155 frystyk 1159:
1160: /*
1161: ** Make sure that we do a complete flush of the cache
1162: */
1163: HTRequest_setReloadMode(req, HT_CACHE_FLUSH);
1.124 eric 1164: status = HTLoadAnchor((HTAnchor*) (HTMainAnchor ? HTMainAnchor :
1165: lm->anchor), req);
1.48 frystyk 1166: } else
1167: found = NO;
1.40 frystyk 1168: break;
1169:
1170: case 'S': /* TBL 921009 */
1.68 frystyk 1171: if (CHECK_INPUT("SOURCE", token)) { /* Apply to source */
1.47 frystyk 1172: if (next_word) {
1173: OutSource = YES; /* Load and print as source */
1.68 frystyk 1174: token = next_word; /* Move up one word */
1.47 frystyk 1175: next_word = strtok (NULL, " \t\n\r");
1.68 frystyk 1176: this_command = the_choice + (token - choice);
1.47 frystyk 1177: other_words = the_choice + (next_word - choice);
1178: goto loop; /* Go treat as before */
1179: }
1.68 frystyk 1180: } else if (CHECK_INPUT("SET", token)) { /* config */
1.93 frystyk 1181: HTList * rules = HTRule_global();
1182: HTRule_parseLine(rules, other_words);
1.48 frystyk 1183: } else
1184: found = NO;
1.40 frystyk 1185: break;
1186:
1187: case 'T':
1.68 frystyk 1188: if (CHECK_INPUT("TOP", token)) { /* Return to top */
1.40 frystyk 1189: HText_scrollTop(HTMainText);
1.48 frystyk 1190: } else
1191: found = NO;
1.40 frystyk 1192: break;
1193:
1194: case 'U':
1.68 frystyk 1195: if (CHECK_INPUT("UP", token)) { /* Scroll up one page */
1.40 frystyk 1196: HText_scrollUp(HTMainText);
1.121 eric 1197: } else if (CHECK_INPUT("USER", token)) {
1198: if (next_word) {
1199: if (!strcasecomp(next_word, "?")) {
1200: ShowPICSUsers(lm);
1.124 eric 1201: SetPICSUser(lm, 0);
1.121 eric 1202: } else {
1.124 eric 1203: SetPICSUser(lm, next_word);
1.121 eric 1204: }
1205: } else {
1.124 eric 1206: SetPICSUser(lm, 0);
1.121 eric 1207: }
1208: } else
1.48 frystyk 1209: found = NO;
1.40 frystyk 1210: break;
1211:
1212: case 'V':
1.155 frystyk 1213: if (CHECK_INPUT("VALIDATE", token)) { /* Cache validate */
1214: req = Thread_new(lm, YES, LM_NO_UPDATE);
1215:
1216: /*
1217: ** Add a validator to the request
1218: */
1219: HTRequest_setReloadMode(req, HT_CACHE_VALIDATE);
1220: status = HTLoadAnchor((HTAnchor*) (HTMainAnchor ? HTMainAnchor :
1221: lm->anchor), req);
1222: } else if (CHECK_INPUT("VERBOSE", token)) { /* Switch verbose mode */
1.96 frystyk 1223: WWWTRACE = WWWTRACE ? 0 : lm->trace;
1.118 eric 1224: OutputData(lm->pView, "\n Verbose mode %s.\n", WWWTRACE ? "ON":"OFF");
1.68 frystyk 1225: } else if (CHECK_INPUT("VERSION", token)) { /* Version */
1.118 eric 1226: VersionInfo(lm);
1.48 frystyk 1227: } else
1228: found = NO;
1.40 frystyk 1229: break;
1.160 frystyk 1230:
1231: case 'W':
1232: if (CHECK_INPUT("WHICH", token)) { /* Show title/URL of current page */
1233: HTView * pView = lm ? lm->pView : NULL;
1234: char * current_address = HTAnchor_address((HTAnchor *) HTMainAnchor);
1235: const char * title = HTAnchor_title(HTMainAnchor);
1236: if (title)
1237: OutputData(pView, "\n\nYou are reading\n\t`%s\'\nwith address\n\t%s\n\n",
1238: title, current_address);
1239: } else
1240: found = NO;
1241: break;
1.40 frystyk 1242:
1243: case 'Z':
1.50 frystyk 1244: HText_setStale(HTMainText); /* Force refresh */
1245: HText_refresh(HTMainText); /* Refresh screen */
1.76 frystyk 1246: HTNet_killAll(); /* Kill all requests */
1.44 frystyk 1247: break;
1.40 frystyk 1248:
1249: case '>':
1.96 frystyk 1250: if (!lm->host) {
1.58 frystyk 1251: HText *curText = HTMainText; /* Remember current main vindow */
1.104 frystyk 1252: req = Thread_new(lm, NO, LM_NO_UPDATE);
1.155 frystyk 1253: HTRequest_setReloadMode(req, HT_CACHE_FLUSH_MEM);
1.90 frystyk 1254: if (OutSource) HTRequest_setOutputFormat(req, WWW_SOURCE);
1.76 frystyk 1255: SaveOutputStream(req, token, next_word);
1.58 frystyk 1256: HText_select(curText);
1.40 frystyk 1257: }
1258: break;
1.1 timbl 1259:
1.50 frystyk 1260: #ifdef GOT_PIPE
1.40 frystyk 1261: case '|':
1.96 frystyk 1262: if (!lm->host) { /* Local only!!!! */
1.40 frystyk 1263: char * address = HTAnchor_address((HTAnchor *) HTMainAnchor);
1264: char * command;
1265: int result;
1.112 frystyk 1266: if ((command = (char *) HT_MALLOC(strlen(address) +strlen(this_command)+30)) == NULL)
1267: HT_OUTOFMEM("command");
1.40 frystyk 1268: sprintf(command, "www %s \"%s\" %s",
1269: OutSource ? "-source" : "-n -na -p", address,this_command);
1.118 eric 1270: OutputData(lm->pView, "Command: %s\n", command);
1.40 frystyk 1271: result = system(command);
1.118 eric 1272: if (result) OutputData(lm->pView, " %s returns %d\n", command, result);
1.112 frystyk 1273: HT_FREE(command);
1274: HT_FREE(address);
1.14 frystyk 1275: }
1.47 frystyk 1276: break;
1.40 frystyk 1277: #endif
1278:
1.120 frystyk 1279: #ifdef HAVE_SYSTEM
1.40 frystyk 1280: case '!':
1.96 frystyk 1281: if (!lm->host) { /* Local only! */
1.40 frystyk 1282: int result;
1.118 eric 1283: if (SHOW_MSG) HTTrace("Executing `%s\'\n", this_command);
1.40 frystyk 1284: result = system(strchr(this_command, '!') + 1);
1.118 eric 1285: if (result) OutputData(lm->pView, " %s returns %d\n",
1.96 frystyk 1286: strchr(this_command, '!') + 1, result);
1.1 timbl 1287: }
1.47 frystyk 1288: break;
1.120 frystyk 1289: #endif /* HAVE_SYSTEM */
1.40 frystyk 1290: default:
1.48 frystyk 1291: found = NO;
1292: break;
1293: } /* Switch on 1st character */
1294:
1295: if (!found) {
1.68 frystyk 1296: if (is_index && *token) { /* No commands, search keywords */
1.47 frystyk 1297: next_word = other_words = this_command;
1.48 frystyk 1298: found = YES;
1.47 frystyk 1299: goto find;
1300: } else {
1.68 frystyk 1301: if (SHOW_MSG)
1.118 eric 1302: HTTrace("Bad command (%s), for list of commands type help\n", this_command);
1.47 frystyk 1303: }
1.48 frystyk 1304: }
1.96 frystyk 1305: MakeCommandLine(lm, is_index);
1.112 frystyk 1306: HT_FREE(the_choice);
1.96 frystyk 1307:
1308: /*
1309: ** If we have created a new Request and is to update the history list then
1310: ** we can set the inactive bit on this request object.
1311: */
1.104 frystyk 1312: if (cur_req == req)
1313: cur_context->state |= LM_NO_UPDATE;
1.115 frystyk 1314: else
1.104 frystyk 1315: cur_context->state |= LM_INACTIVE;
1.76 frystyk 1316: return (status==YES) ? HT_OK : HT_ERROR;
1.40 frystyk 1317: }
1318:
1.96 frystyk 1319: /* readConsole
1320: ** -----------
1321: ** non-blocking read of the WIN32 console. EGP
1322: */
1.97 frystyk 1323:
1.106 frystyk 1324: #ifdef WWW_WIN_CONSOLE
1.89 frystyk 1325: PUBLIC BOOL readConsole(HANDLE conIn, char* buf, int len, int* pRed)
1326: {
1327: DWORD recordIndex, bufferIndex, toRead, red;
1328: PINPUT_RECORD pInput;
1329:
1330: /* grab the pending input records (keystrokes plus other garbage). */
1331: GetNumberOfConsoleInputEvents(conIn, &toRead);
1332: if (len < (int)toRead) /* we'll get the rest on the next pass(es). */
1333: toRead = len;
1.112 frystyk 1334: if ((pInput = (PINPUT_RECORD) HT_MALLOC(toRead * sizeof(INPUT_RECORD))) == NULL) /* room for n input records */
1.89 frystyk 1335: return (FALSE);
1336: ReadConsoleInput(conIn, pInput, toRead, &red);
1337:
1338: for (recordIndex = bufferIndex = 0; recordIndex < red; recordIndex++) {
1339: /* grab all keydown events */
1.97 frystyk 1340: #if 1
1341: KEY_EVENT_RECORD keyEvent = pInput[recordIndex].Event.KeyEvent; /* only used if EventType == KEY_EVENT */
1342: if (pInput[recordIndex].EventType == KEY_EVENT && keyEvent.bKeyDown) {
1343: while (keyEvent.wRepeatCount && keyEvent.uChar.AsciiChar) {
1344: /* stuff the buffer with the keys */
1345: buf[bufferIndex] = keyEvent.uChar.AsciiChar;
1346: if (buf[bufferIndex] == '\r')
1347: buf[bufferIndex] = '\n';
1348: if (buf[bufferIndex] == '\b')
1.118 eric 1349: OutputData(lm->pView, "\b ");
1350: OutputData(lm->pView, "%c", buf[bufferIndex]);
1.97 frystyk 1351: bufferIndex++;
1352: keyEvent.wRepeatCount--;
1353: }
1354: }
1355: #else
1356: if (pInput[recordIndex].EventType == KEY_EVENT && pInput[recordIndex].Event.KeyEvent.bKeyDown) {
1357: while (pInput[recordIndex].Event.KeyEvent.wRepeatCount && pInput[recordIndex].Event.KeyEvent.uChar.AsciiChar) {
1358: /* stuff the buffer with the keys */
1359: buf[bufferIndex] = pInput[recordIndex].Event.KeyEvent.uChar.AsciiChar;
1360: if (buf[bufferIndex] == '\r')
1361: buf[bufferIndex] = '\n';
1362: if (buf[bufferIndex] == '\b')
1.118 eric 1363: OutputData(lm->pView, "\b ");
1364: OutputData(lm->pView, "%c", buf[bufferIndex]);
1.97 frystyk 1365: bufferIndex++;
1366: pInput[recordIndex].Event.KeyEvent.wRepeatCount--;
1367: }
1368: }
1369: #endif
1370:
1.89 frystyk 1371: }
1372:
1.112 frystyk 1373: HT_FREE(pInput);
1.97 frystyk 1374: *pRed = bufferIndex; /* actual characters stuck into buffer */
1.89 frystyk 1375: return (TRUE);
1376: }
1.106 frystyk 1377: #endif /* WWW_WIN_CONSOLE */
1.89 frystyk 1378:
1.96 frystyk 1379: /* bufferInput
1380: ** -----------
1381: ** Read available characters from buf into stat. buf maybe bigger or
1382: ** smaller than stat.
1383: */
1.162 eric 1384: PUBLIC int bufferInput (char* buf, int len, SOCKET s, HTRequest * req, HTEventType type)
1.89 frystyk 1385: {
1386: static char stat[RESPONSE_LENGTH];
1387: static int iStat = 0;
1388: static int ignoreNext = 0;
1389: int iBuf;
1390: for (iBuf = 0; iBuf < len; iBuf++) {
1391: switch (buf[iBuf]) {
1392: case '\r':
1393: case '\n':
1394: if (ignoreNext)
1395: ignoreNext = 0;
1396: else {
1397: int ret;
1398: stat[iStat] = 0;
1399: iStat = 0;
1.162 eric 1400: if ((ret = (*PInputParser)(stat, s, req, type)) != HT_OK)
1.89 frystyk 1401: return (ret);
1402: }
1403: break;
1404: case '\b':
1.96 frystyk 1405: if (iStat) /* don't worry about ignoreNext as iStat will be 0*/
1.89 frystyk 1406: iStat--;
1407: break;
1408: default:
1409: if (!ignoreNext)
1410: stat[iStat++] = buf[iBuf];
1411: }
1412: if (iStat == sizeof(stat)) {
1.118 eric 1413: HTTrace("Read Console... BUFFER OVERRUN\n");
1.89 frystyk 1414: iStat = 0;
1415: ignoreNext = 1;
1416: }
1417: }
1418: return (HT_OK);
1419: }
1420:
1.164 frystyk 1421: /* timeout_handler
1422: ** ---------------
1423: ** This function is registered to handle timeout in select eventloop
1424: */
1425: PRIVATE int timeout_handler (SOCKET s, void * param, HTEventType type)
1426: {
1427: if (!HTAlert_interactive()) {
1428: HTRequest * req = (HTRequest *) param;
1429: Context * context = (Context *) HTRequest_context(req);
1430: LineMode * lm = context->lm;
1431: if (SHOW_MSG) HTTrace("Request timed out");
1432: HTNet_killAll();
1433: Cleanup(lm, -1);
1434: }
1.165 eric 1435: if (HTNet_count() > 0)
1436: if (SHOW_MSG) HTTrace(".");
1.164 frystyk 1437: return 0;
1438: }
1439:
1.162 eric 1440: PRIVATE int scan_command (SOCKET s, void * param, HTEventType type)
1.89 frystyk 1441: {
1.162 eric 1442: HTRequest * req = (HTRequest *)param;
1.91 frystyk 1443: /* buf happens to == eatText's buffer but not neccesary */
1444: static char buf[RESPONSE_LENGTH];
1.162 eric 1445: #ifdef WWW_MSWINDOWS
1.89 frystyk 1446: int red;
1447: int ret;
1.164 frystyk 1448: #endif
1449:
1450: /* Handle any timeout here */
1451: if (type == HTEvent_TIMEOUT) return timeout_handler (s, param, type);
1.91 frystyk 1452:
1.164 frystyk 1453: #ifdef WWW_MSWINDOWS
1.162 eric 1454: while(1) {
1455: #ifdef WWW_WIN_CONSOLE
1456: if (!readConsole((HANDLE)s, buf, sizeof(buf), &red)) {
1457: if (PROT_TRACE) HTTrace("Read Console... READ ERROR\n");
1458: return HT_ERROR;
1459: }
1460: #endif /* WWW_WIN_CONSOLE */
1461: if (!red) return (HT_OK);
1462: ret = bufferInput(buf, red, s, req, type);
1463: if (ret != HT_OK) return (ret);
1464: }
1465: #else /* WWW_MSWINDOWS */
1.89 frystyk 1466: if (!fgets(buf, sizeof(buf), stdin)) /* Read User Input */
1.106 frystyk 1467: return HT_ERROR; /* Exit if EOF */
1.162 eric 1468: return ((*PInputParser)(buf, s, req, type));
1469: #endif /* !WWW_MSWINOWS */
1.89 frystyk 1470: }
1.40 frystyk 1471:
1.76 frystyk 1472: /* terminate_handler
1473: ** -----------------
1.96 frystyk 1474: ** This function is registered to handle the result of the request
1.1 timbl 1475: */
1.160 frystyk 1476: PRIVATE int terminate_handler (HTRequest * request, HTResponse * response,
1477: void * param, int status)
1.40 frystyk 1478: {
1.96 frystyk 1479: Context * context = (Context *) HTRequest_context(request);
1.121 eric 1480: LineMode * lm;
1481: BOOL is_index;
1482:
1.151 frystyk 1483: if (!context)
1484: return HT_OK;
1.121 eric 1485: lm = context->lm;
1.146 frystyk 1486: if (context->state == LM_IGNORE) return HT_OK;
1.157 eric 1487: if (CSApp_unregisterReq(request) == NO && lm->pCSUser)
1.126 hallam 1488: HTTrace("PICS request not found\n");
1.121 eric 1489: is_index = HTAnchor_isIndex(HTMainAnchor);
1.40 frystyk 1490: if (status == HT_LOADED) {
1.96 frystyk 1491:
1.155 frystyk 1492: /*
1493: ** Make sure that we have selected the HText object. This is normally
1494: ** done by the HText interface but may have been avoided by the mem
1495: ** cache filter
1496: */
1497: {
1498: HTParentAnchor * parent = HTRequest_anchor(request);
1499: HTChildAnchor * child = HTRequest_childAnchor(request);
1500: HText * document = HTAnchor_document(parent);
1501: if (child && (HTAnchor *) child != (HTAnchor *) parent)
1502: HText_selectAnchor(document, child);
1503: else
1504: HText_select(document);
1.165 eric 1505: HTRequest_forceFlush(request);
1.155 frystyk 1506: }
1507:
1508: /* Should we output a command line? */
1.96 frystyk 1509: if (HTAlert_interactive()) {
1510: HText_setStale(HTMainText);
1511: MakeCommandLine(lm, is_index);
1512: } else {
1513: if (lm->flags & LM_REFS) Reference_List(lm, NO);
1514: Cleanup(lm, 0);
1515: }
1.69 frystyk 1516:
1517: /* Record new history if we have not moved around in the old one */
1.96 frystyk 1518: if (context->state & LM_UPDATE)
1519: HTHistory_replace(lm->history, (HTAnchor *) HTMainAnchor);
1.69 frystyk 1520:
1.40 frystyk 1521: /* Now generate the new prompt line as a function of the result */
1522: if (!HText_canScrollDown(HTMainText) &&
1523: !HTAnchor_hasChildren(HTMainAnchor) && !is_index &&
1.96 frystyk 1524: (!HTHistory_canBacktrack(lm->history))) {
1.91 frystyk 1525: return HT_OK;
1.40 frystyk 1526: }
1.96 frystyk 1527:
1.134 eric 1528: } else { /* No page loaded so sit around and wait for a go command */
1.166 eric 1529: /* was MakeCommandLine(lm, is_index); */
1530: /*
1531: ** stolen from above
1532: */
1533: if (HTAlert_interactive()) {
1534: /* HText_setStale(HTMainText); */
1535: MakeCommandLine(lm, is_index);
1536: } else {
1537: if (lm->flags & LM_REFS) Reference_List(lm, NO);
1538: Cleanup(lm, 0);
1539: }
1540:
1.76 frystyk 1541: }
1.96 frystyk 1542: context->state |= LM_DONE;
1543: Thread_cleanup(lm);
1544: if (!HTAlert_interactive()) Cleanup(lm, -1);
1.76 frystyk 1545: return HT_OK;
1.40 frystyk 1546: }
1.1 timbl 1547:
1.40 frystyk 1548: /* ------------------------------------------------------------------------- */
1549: /* MAIN PROGRAM */
1550: /* ------------------------------------------------------------------------- */
1.1 timbl 1551:
1.90 frystyk 1552: int main (int argc, char ** argv)
1.40 frystyk 1553: {
1.68 frystyk 1554: int status = 0;
1555: int arg; /* Index into argv */
1556: HTChunk * keywords = NULL; /* From command line */
1557: int keycnt = 0;
1.116 frystyk 1558: HTRequest * request = NULL;
1.101 frystyk 1559: LineMode * lm;
1.121 eric 1560: char * picsUser = NULL;
1.141 eric 1561:
1.96 frystyk 1562: /* Starts Mac GUSI socket library */
1563: #ifdef GUSI
1.75 frystyk 1564: GUSISetup(GUSIwithSIOUXSockets);
1565: GUSISetup(GUSIwithInternetSockets);
1566: #endif
1567:
1568: #ifdef __MWERKS__ /* STR */
1569: InitGraf((Ptr) &qd.thePort);
1570: InitFonts();
1571: InitWindows();
1572: InitMenus(); TEInit();
1573: InitDialogs(nil);
1574: InitCursor();
1575: SIOUXSettings.asktosaveonclose = false;
1576: argc=ccommand(&argv);
1577: #endif
1578:
1.68 frystyk 1579: /* HWL 18/7/94: patch from agl@glas2.glas.apc.org (Anton Tropashko) */
1.40 frystyk 1580: #ifdef CYRILLIC
1581: arc.locale=0; arc.encoding=0; arc.i_encoding=0; doinull();
1.1 timbl 1582: #endif
1583:
1.170 ! frystyk 1584: #ifdef HT_MEMLOG
! 1585: HTMemLog_open(DEFAULT_MEMLOG, 8192, YES);
1.168 eric 1586: HTTraceData_setCallback(HTMemLog_callback);
1.170 ! frystyk 1587: #endif
! 1588:
1.149 frystyk 1589: /* Initiate W3C Reference Library with a client profile */
1590: HTProfile_newClient(APP_NAME, APP_VERSION);
1.150 frystyk 1591:
1.163 frystyk 1592: /* FOR THE MOMENT */
1593: HTCacheMode_setEnabled(NO);
1594:
1.150 frystyk 1595: /* It's confusing to have progress notofications in linemode browser */
1596: HTAlert_delete(HTProgress);
1.117 frystyk 1597:
1.149 frystyk 1598: /* Add the default HTML parser to the set of converters */
1599: {
1600: HTList * converters = HTFormat_conversion();
1601: HTMLInit(converters);
1602: }
1.142 eric 1603:
1.108 frystyk 1604: /* Create a new Line Mode object */
1.153 frystyk 1605: lm = LineMode_new();
1.115 frystyk 1606: request = Thread_new(lm, NO, LM_UPDATE);
1.96 frystyk 1607:
1608: /* Scan command Line for parameters */
1609: for (arg=1; arg<argc ; arg++) {
1.40 frystyk 1610: if (*argv[arg] == '-') {
1611:
1612: /* - alone => filter */
1.96 frystyk 1613: if (argv[arg][1] == '\0') {
1614: lm->flags |= LM_FILTER;
1.94 frystyk 1615: HTAlert_setInteractive(NO);
1.40 frystyk 1616:
1.96 frystyk 1617: /* non-interactive */
1618: } else if (!strcmp(argv[arg], "-n")) {
1619: HTAlert_setInteractive(NO);
1.40 frystyk 1620:
1621: /* from -- Initial represntation (only with filter) */
1.96 frystyk 1622: } else if (!strcmp(argv[arg], "-from")) {
1623: lm->format = (arg+1 < argc && *argv[arg+1] != '-') ?
1624: HTAtom_for(argv[++arg]) : WWW_HTML;
1625: HTAlert_setInteractive(NO);
1.40 frystyk 1626:
1.96 frystyk 1627: /* to -- Final representation */
1628: } else if (!strcmp(argv[arg], "-to")) {
1629: HTFormat format = (arg+1 < argc && *argv[arg+1] != '-') ?
1630: HTAtom_for(argv[++arg]) : DEFAULT_FORMAT;
1.115 frystyk 1631: HTRequest_setOutputFormat(request, format);
1.96 frystyk 1632: HTAlert_setInteractive(NO);
1633:
1634: /* reformat html */
1635: } else if (!strcmp(argv[arg], "-reformat")) {
1.115 frystyk 1636: HTRequest_setOutputFormat(request, WWW_HTML);
1.96 frystyk 1637: lm->flags |= LM_REFORMAT;
1638: HTAlert_setInteractive(NO);
1639:
1640: /* List References */
1641: } else if (!strncmp(argv[arg], "-list", 5)) {
1642: lm->flags |= LM_REFS;
1643: HTAlert_setInteractive(NO);
1644:
1.100 frystyk 1645: /* original output */
1.96 frystyk 1646: } else if (!strcmp(argv[arg], "-raw")) {
1.115 frystyk 1647: HTRequest_setOutputFormat(request, WWW_RAW);
1.96 frystyk 1648: HTAlert_setInteractive(NO);
1649:
1650: /* source please */
1651: } else if (!strcmp(argv[arg], "-source")) {
1.115 frystyk 1652: HTRequest_setOutputFormat(request, WWW_SOURCE);
1.96 frystyk 1653: HTAlert_setInteractive(NO);
1654:
1655: /* HEAD method */
1656: } else if (!strcasecomp(argv[arg], "-head")) {
1.115 frystyk 1657: HTRequest_setMethod(request, METHOD_HEAD);
1658: HTRequest_setOutputFormat(request, WWW_MIME);
1.96 frystyk 1659: HTAlert_setInteractive(NO);
1660:
1.100 frystyk 1661: /* output filename */
1.96 frystyk 1662: } else if (!strcmp(argv[arg], "-o")) {
1663: lm->outputfile = (arg+1 < argc && *argv[arg+1] != '-') ?
1664: argv[++arg] : DEFAULT_OUTPUT_FILE;
1665: HTAlert_setInteractive(NO);
1666:
1667: /* print version and exit */
1668: } else if (!strcmp(argv[arg], "-version")) {
1.119 frystyk 1669: VersionInfo(lm);
1.96 frystyk 1670: Cleanup(lm, 0);
1671:
1672: /* -? or -help: show the command line help page */
1673: } else if (!strcmp(argv[arg],"-?") || !strcmp(argv[arg],"-help")) {
1674: lm->anchor = (HTParentAnchor *) HTAnchor_findAddress(L_HELP);
1675: keycnt = 1;
1.40 frystyk 1676:
1677: #ifdef CYRILLIC
1678: /* HWL 18/7/94: applied patch from agl@glas2.glas.apc.org
1679: (Anton Tropashko) */
1680: } else if (!strcmp(argv[arg], "-koi2alt")) {
1.118 eric 1681: doia2k(); OutputData(lm->pView, "Ahak2a!");
1.40 frystyk 1682: #endif
1683:
1684: /* Page size */
1685: } else if (!strncmp(argv[arg], "-p", 2)) {
1686: if (*(argv[arg]+2)) {
1687: if (sscanf(argv[arg]+2, "%d", &HTScreenHeight) < 1)
1688: HTScreenHeight = -1;
1689: else {
1690: if(HTScreenHeight < MIN_SCREEN_HEIGHT)
1691: HTScreenHeight = MIN_SCREEN_HEIGHT;
1692: if(HTScreenHeight > MAX_SCREEN_HEIGHT)
1693: HTScreenHeight = MAX_SCREEN_HEIGHT;
1694: }
1.163 frystyk 1695: } else if (arg+1 < argc && *argv[arg+1] != '-') {
1.40 frystyk 1696: if (sscanf(argv[++arg], "%d", &HTScreenHeight) < 1)
1697: HTScreenHeight = -1;
1698: else {
1699: if(HTScreenHeight < MIN_SCREEN_HEIGHT)
1700: HTScreenHeight = MIN_SCREEN_HEIGHT;
1701: if(HTScreenHeight > MAX_SCREEN_HEIGHT)
1702: HTScreenHeight = MAX_SCREEN_HEIGHT;
1703: }
1704: }
1.1 timbl 1705:
1.40 frystyk 1706: /* Page width */
1707: } else if (!strncmp(argv[arg], "-w", 2)) {
1708: if (*(argv[arg]+2)) {
1709: if (sscanf(argv[arg]+2, "%d", &HTScreenWidth) < 1)
1710: HTScreenWidth = SCREEN_WIDTH;
1.163 frystyk 1711: } else if (arg+1 < argc && *argv[arg+1] != '-') {
1.40 frystyk 1712: if (sscanf(argv[++arg], "%d", &HTScreenWidth) < 1)
1713: HTScreenWidth = SCREEN_WIDTH;
1.14 frystyk 1714: }
1.40 frystyk 1715: if(HTScreenWidth < MIN_SCREEN_WIDTH)
1716: HTScreenWidth = MIN_SCREEN_WIDTH;
1717: if(HTScreenWidth > MAX_SCREEN_WIDTH)
1718: HTScreenWidth = MAX_SCREEN_WIDTH;
1719:
1720: /* Telnet from */
1721: } else if (!strcmp(argv[arg], "-h")) {
1722: if (arg+1 < argc && *argv[arg+1] != '-') {
1.96 frystyk 1723: lm->host = argv[++arg]; /* Use host name */
1.92 frystyk 1724: HTLib_setSecure(YES); /* No easy access */
1.14 frystyk 1725: }
1.40 frystyk 1726:
1.96 frystyk 1727: /* log file */
1.40 frystyk 1728: } else if (!strcmp(argv[arg], "-l")) {
1.96 frystyk 1729: lm->logfile = (arg+1 < argc && *argv[arg+1] != '-') ?
1.68 frystyk 1730: argv[++arg] : DEFAULT_LOG_FILE;
1.51 frystyk 1731:
1.96 frystyk 1732: /* rule file */
1733: } else if (!strcmp(argv[arg], "-r")) {
1734: lm->rules = (arg+1 < argc && *argv[arg+1] != '-') ?
1735: argv[++arg] : DEFAULT_RULE_FILE;
1.68 frystyk 1736:
1.96 frystyk 1737: /* timeout -- Change the default request timeout */
1738: } else if (!strcmp(argv[arg], "-timeout")) {
1739: int timeout = (arg+1 < argc && *argv[arg+1] != '-') ?
1740: atoi(argv[++arg]) : -1;
1.167 frystyk 1741: if (timeout > 0) lm->timer = timeout;
1.40 frystyk 1742:
1.121 eric 1743: /* PICS user */
1744: } else if (!strcmp(argv[arg], "-u")) {
1745: picsUser = (arg+1 < argc && *argv[arg+1] != '-') ?
1.124 eric 1746: argv[++arg] : "user";
1.132 eric 1747: } else if (!strcmp(argv[arg], "-unp")) {
1748: lm->noPICSPasswords = 1;
1.126 hallam 1749: #if 0 /* old version of user list file, still works when enabeled here */
1.124 eric 1750: /* PICS user list */
1751: } else if (!strcmp(argv[arg], "-ul")) {
1752: picsUserList = (arg+1 < argc && *argv[arg+1] != '-') ?
1753: argv[++arg] : "users.url";
1.126 hallam 1754: #endif
1755: /* PICS user list */
1756: } else if (!strcmp(argv[arg], "-ul")) {
1757: lm->userList = (arg+1 < argc && *argv[arg+1] != '-') ?
1758: argv[++arg] : DEFAULT_USERLIST_FILE;
1.121 eric 1759:
1.126 hallam 1760: /* PICS mode */
1761: } else if (!strcmp(argv[arg], "-pics")) {
1762: lm->userList = DEFAULT_USERLIST_FILE;
1763:
1.108 frystyk 1764: /* preemptive or non-preemptive access */
1.50 frystyk 1765: } else if (!strcmp(argv[arg], "-single")) {
1.115 frystyk 1766: HTRequest_setPreemptive(request, YES);
1.96 frystyk 1767: lm->flags |= LM_PREEMTIVE;
1.50 frystyk 1768:
1.156 frystyk 1769: /* Disconnected operation */
1770: } else if (!strncmp(argv[arg], "-discon", 7)) {
1771: HTCacheMode_setDisconnected(HT_DISCONNECT_NORMAL);
1.68 frystyk 1772:
1.96 frystyk 1773: /* Handling of Expire (cache) */
1.68 frystyk 1774: } else if (!strncmp(argv[arg], "-x", 2)) {
1.155 frystyk 1775: char *p = argv[arg]+2;
1776: for(;*p;p++) {
1777: switch (argv[arg][2]) {
1.68 frystyk 1778: case 'i':
1.156 frystyk 1779: HTCacheMode_setExpires(HT_EXPIRES_IGNORE);
1.155 frystyk 1780: break;
1.68 frystyk 1781: case 'n':
1.156 frystyk 1782: HTCacheMode_setExpires(HT_EXPIRES_NOTIFY);
1.155 frystyk 1783: break;
1.68 frystyk 1784: case 'a':
1.156 frystyk 1785: HTCacheMode_setExpires(HT_EXPIRES_AUTO);
1.155 frystyk 1786: break;
1.68 frystyk 1787: default:
1.155 frystyk 1788: if (SHOW_MSG)
1789: HTTrace("Bad parameter (%s) for option -x\n", argv[arg]);
1790: break;
1791: }
1792: }
1.68 frystyk 1793:
1.40 frystyk 1794: /* Anchor format */
1795: } else if (!strcmp(argv[arg], "-a")) {
1796: if (arg+1 < argc && *argv[arg+1] != '-')
1797: end_reference = argv[++arg]; /* New representation */
1798:
1799: /* Anchor format */
1800: } else if (!strcmp(argv[arg], "-ar")) {
1801: if (arg+1 < argc && *argv[arg+1] != '-')
1802: reference_mark = argv[++arg]; /* Change representation */
1803:
1804: /* Anchor format */
1805: } else if (!strcmp(argv[arg], "-as")) {
1806: if (arg+1 < argc && *argv[arg+1] != '-')
1807: start_reference = argv[++arg]; /* Change representation */
1808:
1809: /* No anchors */
1810: } else if (!strcmp(argv[arg], "-na")) {
1811: display_anchors = NO;
1812:
1813: #ifndef NO_DIR_OPTIONS
1814: } else if (!strncmp(argv[arg], "-d", 2)) {
1815: char *p = argv[arg]+2;
1816: for(;*p;p++) {
1817: switch (argv[arg][2]) {
1.82 frystyk 1818: case 'r':HTFile_setDirReadme(HT_DIR_README_NONE); break;
1819: case 't':HTFile_setDirReadme(HT_DIR_README_TOP); break;
1820: case 'b':HTFile_setDirReadme(HT_DIR_README_BOTTOM);break;
1821: case 'n':HTFile_setDirAccess(HT_DIR_FORBID); break;
1822: case 's':HTFile_setDirAccess(HT_DIR_SELECTIVE); break;
1823: case 'y':HTFile_setDirAccess(HT_DIR_OK); break;
1.76 frystyk 1824: default:
1.68 frystyk 1825: if (SHOW_MSG)
1.118 eric 1826: HTTrace("Bad parameter (%s) in -d option\n",
1.68 frystyk 1827: argv[arg]);
1.40 frystyk 1828: }
1.96 frystyk 1829: }
1.40 frystyk 1830: #endif
1.1 timbl 1831:
1.85 frystyk 1832: #ifdef WWWTRACE
1.96 frystyk 1833: /* trace flags */
1.40 frystyk 1834: } else if (!strncmp(argv[arg], "-v", 2)) {
1.146 frystyk 1835: lm->trace = HTSetTraceMessageMask(argv[arg]+2);
1.1 timbl 1836: #endif
1.40 frystyk 1837: } else {
1.118 eric 1838: if (SHOW_MSG) HTTrace("Bad Argument (%s)\n", argv[arg]);
1.40 frystyk 1839: }
1840: } else { /* If no leading `-' then check for main argument */
1.68 frystyk 1841: if (!keycnt) {
1.96 frystyk 1842: char * ref = HTParse(argv[arg], lm->cwd, PARSE_ALL);
1843: lm->anchor = (HTParentAnchor *) HTAnchor_findAddress(ref);
1.79 frystyk 1844: keycnt = 1;
1.112 frystyk 1845: HT_FREE(ref);
1.40 frystyk 1846: } else { /* Check for successive keyword arguments */
1.79 frystyk 1847: char *escaped = HTEscape(argv[arg], URL_XALPHAS);
1.68 frystyk 1848: if (keycnt++ <= 1)
1.104 frystyk 1849: keywords = HTChunk_new(128);
1.68 frystyk 1850: else
1.104 frystyk 1851: HTChunk_putc(keywords, ' ');
1852: HTChunk_puts(keywords, HTStrip(escaped));
1.112 frystyk 1853: HT_FREE(escaped);
1.68 frystyk 1854: }
1.79 frystyk 1855: }
1856: }
1.40 frystyk 1857:
1.96 frystyk 1858: #ifdef CATCH_SIG
1859: SetSignal();
1860: #endif
1861:
1862: /* Make home page address */
1863: if (!lm->anchor) lm->anchor = HTHomeAnchor();
1864:
1.149 frystyk 1865: /* Do we need list of presenters? (external viewers) */
1.94 frystyk 1866: if (HTAlert_interactive()) {
1.96 frystyk 1867: lm->presenters = HTList_new();
1868: HTPresenterInit(lm->presenters);
1.115 frystyk 1869: HTRequest_setConversion(request, lm->presenters, NO);
1.86 frystyk 1870: }
1871:
1.40 frystyk 1872: if (HTScreenHeight == -1) { /* Default page size */
1.120 frystyk 1873: if (HTAlert_interactive())
1874: scrsize(&HTScreenHeight, &HTScreenWidth);
1875: else
1.42 frystyk 1876: HTScreenHeight = 999999;
1.40 frystyk 1877: }
1.23 frystyk 1878:
1.149 frystyk 1879: /* Disable free directory browsing when using telnet host */
1.96 frystyk 1880: if (lm->host && HTFile_dirAccess() == HT_DIR_OK)
1.82 frystyk 1881: HTFile_setDirAccess(HT_DIR_SELECTIVE);
1.1 timbl 1882:
1.40 frystyk 1883: /* Open output file */
1.94 frystyk 1884: if (!HTAlert_interactive()) {
1.106 frystyk 1885: #ifndef WWW_WIN_WINDOW
1.96 frystyk 1886: if (lm->outputfile) {
1.99 frystyk 1887: if ((OUTPUT = fopen(lm->outputfile, "wb")) == NULL) {
1.118 eric 1888: if (SHOW_MSG) HTTrace("Can't open `%s'\\n",
1.96 frystyk 1889: lm->outputfile);
1.118 eric 1890: OUTPUT = stdout;
1.96 frystyk 1891: }
1892: }
1.115 frystyk 1893: HTRequest_setOutputStream(request,
1894: HTFWriter_new(request, OUTPUT, YES));
1.99 frystyk 1895: #endif
1.58 frystyk 1896:
1.96 frystyk 1897: /*
1898: ** To reformat HTML, just put it through a parser running
1.68 frystyk 1899: ** into a regenerator tbl 940613
1900: */
1.96 frystyk 1901: if (lm->flags & LM_REFORMAT) {
1902: HTStructured * html =
1.115 frystyk 1903: HTMLGenerator(request, NULL, WWW_HTML,
1904: HTRequest_outputFormat(request),
1905: HTRequest_outputStream(request));
1906: HTRequest_setOutputStream(request, SGML_new(&HTMLP_dtd, html));
1.40 frystyk 1907: }
1908: }
1909:
1.96 frystyk 1910: /* Log file specifed? */
1911: if (lm->logfile) HTLog_open(lm->logfile, YES, YES);
1.1 timbl 1912:
1.68 frystyk 1913: /* Just convert formats */
1.96 frystyk 1914: if (lm->flags & LM_FILTER) {
1915: #ifdef STDIN_FILENO
1.115 frystyk 1916: HTRequest_setAnchor(request, (HTAnchor *) lm->anchor);
1917: HTRequest_setPreemptive(request, YES);
1.162 eric 1918: HTLoadSocket(STDIN_FILENO, request);
1.95 frystyk 1919: #endif
1.96 frystyk 1920: Cleanup(lm, 0);
1.40 frystyk 1921: }
1.96 frystyk 1922:
1923: /* Set timeout on sockets */
1.167 frystyk 1924: if (lm->timer < 0) {
1925: lm->timer = HTAlert_interactive() ?
1.96 frystyk 1926: DEFAULT_I_TIMEOUT : DEFAULT_NI_TIMEOUT;
1.93 frystyk 1927: }
1.96 frystyk 1928: /* Set the DNS cache timeout */
1929: HTDNS_setTimeout(3600);
1.121 eric 1930:
1.146 frystyk 1931: /* Rule file specified? */
1932: if (lm->rules) {
1933: char * rules = HTParse(lm->rules, lm->cwd, PARSE_ALL);
1.149 frystyk 1934: if (!HTLoadRules(rules))
1.146 frystyk 1935: if (SHOW_MSG) HTTrace("Can't access rules\n");
1936: HT_FREE(rules);
1937: }
1938:
1939: /* Set up PICS machinary */
1.126 hallam 1940: CSApp_registerApp(PICSCallback, CSApp_callOnBad, PICS_userCallback,
1941: (void *)lm);
1.151 frystyk 1942: /* Add our own filter to update the history list */
1.160 frystyk 1943: HTNet_addAfter(terminate_handler, NULL, NULL, HT_ALL, HT_FILTER_LAST);
1.164 frystyk 1944:
1.167 frystyk 1945: /* Should we load a PICS user profile? */
1.124 eric 1946: if (picsUser && !LoadPICSUser(lm, picsUser))
1947: HTTrace("Unable to load PICS user \"%s\".\n", picsUser);
1.96 frystyk 1948:
1.126 hallam 1949: /* PICS user list specified? */
1950: if (lm->userList)
1951: LoadPICSUser(lm, lm->userList);
1952:
1953: /* request was registered in Thread_new before command line parsing
1954: loaded the PICS user, so re-register to give it the correct user */
1955: CSApp_unregisterReq(request);
1956: CSApp_registerReq(request, lm->pCSUser, PICSCallback,
1957: CSApp_callOnBad, (void *)lm);
1958:
1.96 frystyk 1959: /* Start the request */
1960: if (keywords)
1.150 frystyk 1961: status = HTSearchAnchor(keywords, (HTAnchor *) lm->anchor, request);
1.96 frystyk 1962: else
1.115 frystyk 1963: status = HTLoadAnchor((HTAnchor *) lm->anchor, request);
1.96 frystyk 1964:
1.104 frystyk 1965: if (keywords) HTChunk_delete(keywords);
1.96 frystyk 1966: if (status != YES) {
1.118 eric 1967: if (SHOW_MSG) HTTrace("Couldn't load home page\n");
1.124 eric 1968: CSApp_unregisterDefaultUser();
1969: CSApp_unregisterApp();
1.96 frystyk 1970: Cleanup(lm, -1);
1.76 frystyk 1971: }
1.68 frystyk 1972:
1.96 frystyk 1973: /* Set up the rest if we are in interactive mode */
1.94 frystyk 1974: if (HTAlert_interactive()) {
1.73 frystyk 1975:
1.96 frystyk 1976: /* Start History manager */
1977: lm->history = HTHistory_new();
1.73 frystyk 1978:
1.83 frystyk 1979: /*
1980: ** Register STDIN as the user socket IF not STDIN is connected to
1981: ** /dev/null or other non-terminal devices
1982: */
1.167 frystyk 1983: ConsoleEvent = HTEvent_new(scan_command, lm->console, HT_PRIORITY_MAX, lm->timer);
1.82 frystyk 1984: #ifdef STDIN_FILENO
1.83 frystyk 1985: if (isatty(STDIN_FILENO)) {
1.164 frystyk 1986: HTEventList_register(STDIN_FILENO, HTEvent_READ, ConsoleEvent);
1.83 frystyk 1987: }
1.82 frystyk 1988: #else
1.164 frystyk 1989: HTEventList_register(GetStdHandle(STD_INPUT_HANDLE), HTEvent_READ, ConsoleEvent);
1.82 frystyk 1990: #endif
1.96 frystyk 1991: }
1.77 frystyk 1992:
1.96 frystyk 1993: /* Go into the event loop... */
1.162 eric 1994: HTEventList_loop(request);
1.73 frystyk 1995:
1.96 frystyk 1996: /* Only gets here if event loop fails */
1997: Cleanup(lm, 0);
1998: return 0;
1.14 frystyk 1999: }
1.112 frystyk 2000:
Webmaster