1 /*
2  * $LynxId: LYMain.c,v 1.295 2021/07/05 20:26:11 tom Exp $
3  */
4 #include <HTUtils.h>
5 #include <HTTP.h>
6 #include <HTParse.h>
7 #include <HTAccess.h>
8 #include <HTList.h>
9 #include <HTFile.h>
10 #include <UCMap.h>
11 #include <UCDefs.h>
12 #include <HTInit.h>
13 #include <HTAlert.h>
14 #include <LYCurses.h>
15 #include <LYStyle.h>
16 #include <HTML.h>
17 #include <LYUtils.h>
18 #include <LYGlobalDefs.h>
19 #include <LYMail.h>
20 #include <LYOptions.h>
21 #include <LYSignal.h>
22 #include <LYGetFile.h>
23 #include <LYStrings.h>
24 #include <LYClean.h>
25 #include <LYCharSets.h>
26 #include <LYCharUtils.h>
27 #include <LYReadCFG.h>
28 #include <LYrcFile.h>
29 #include <LYKeymap.h>
30 #include <HTForms.h>
31 #include <LYList.h>
32 #include <LYJump.h>
33 
34 #ifdef USE_SESSIONS
35 #include <LYSession.h>
36 #endif
37 
38 #include <LYMainLoop.h>
39 #include <LYBookmark.h>
40 #include <LYCookie.h>
41 #include <LYPrettySrc.h>
42 #include <LYShowInfo.h>
43 #include <LYHistory.h>
44 
45 #ifdef VMS
46 #include <HTFTP.h>
47 #endif /* !DECNET */
48 
49 #ifdef __DJGPP__
50 #include <dos.h>
51 #include <dpmi.h>
52 #include <io.h>
53 #include <sys/stat.h>
54 #include <sys/exceptn.h>
55 #endif /* __DJGPP__ */
56 
57 #ifdef __EMX__
58 #include <io.h>
59 #endif
60 
61 #if defined(LOCALE) && (!defined(HAVE_LIBINTL_H) || !defined(LC_ALL))
62 #undef gettext			/* Solaris locale.h prototypes gettext() */
63 #include <locale.h>
64 #ifndef HAVE_GETTEXT
65 #define gettext(s) s
66 #endif
67 #endif /* LOCALE */
68 
69 #include <LYexit.h>
70 #include <LYLeaks.h>
71 
72 /* ahhhhhhhhhh!! Global variables :-< */
73 #ifdef SOCKS
74 BOOLEAN socks_flag = TRUE;
75 #endif /* SOCKS */
76 
77 #ifdef IGNORE_CTRL_C
78 BOOLEAN sigint = FALSE;
79 #endif /* IGNORE_CTRL_C */
80 
81 #ifdef __DJGPP__
82 static char init_ctrl_break[1];
83 #endif /* __DJGPP__ */
84 
85 #if USE_VMS_MAILER
86 char *mail_adrs = NULL;		/* the mask for a VMS mail transport */
87 #endif
88 
89 #ifdef VMS
90 	       /* create FIXED 512 binaries */
91 BOOLEAN UseFixedRecords = USE_FIXED_RECORDS;
92 #endif /* VMS */
93 
94 #ifndef VMS
95 static char *lynx_version_putenv_command = NULL;
96 char *list_format = NULL;	/* LONG_LIST formatting mask */
97 #endif /* !VMS */
98 
99 char *ftp_format = NULL;	/* LONG_LIST formatting mask */
100 
101 #ifdef SYSLOG_REQUESTED_URLS
102 char *syslog_txt = NULL;	/* syslog arb text for session */
103 BOOLEAN syslog_requested_urls = FALSE;
104 #endif
105 
106 int cfg_bad_html = BAD_HTML_WARN;
107 
108 #ifdef DIRED_SUPPORT
109 BOOLEAN lynx_edit_mode = FALSE;
110 BOOLEAN no_dired_support = FALSE;
111 HTList *tagged = NULL;
112 int LYAutoUncacheDirLists = 2;	/* default dired uncaching behavior */
113 int dir_list_order = ORDER_BY_NAME;
114 int dir_list_style = MIXED_STYLE;
115 
116 #ifdef OK_OVERRIDE
117 BOOLEAN prev_lynx_edit_mode = FALSE;
118 #endif /* OK_OVERRIDE */
119 
120 #ifdef OK_PERMIT
121 #ifdef NO_CHANGE_EXECUTE_PERMS
122 BOOLEAN no_change_exec_perms = TRUE;
123 
124 #else
125 BOOLEAN no_change_exec_perms = FALSE;
126 #endif /* NO_CHANGE_EXECUTE_PERMS */
127 #endif /* OK_PERMIT */
128 
129 #endif /* DIRED_SUPPORT */
130 
131 	   /* Number of docs cached in memory */
132 int HTCacheSize = DEFAULT_CACHE_SIZE;
133 
134 #if defined(VMS) && defined(VAXC) && !defined(__DECC)
135 	   /* Don't dump doc cache unless this size is exceeded */
136 int HTVirtualMemorySize = DEFAULT_VIRTUAL_MEMORY_SIZE;
137 #endif /* VMS && VAXC && !_DECC */
138 
139 #if defined(EXEC_LINKS) || defined(EXEC_SCRIPTS)
140 #ifndef NEVER_ALLOW_REMOTE_EXEC
141 BOOLEAN local_exec = LOCAL_EXECUTION_LINKS_ALWAYS_ON;
142 
143 #else
144 BOOLEAN local_exec = FALSE;
145 #endif /* NEVER_ALLOW_REMOTE_EXEC */
146 BOOLEAN local_exec_on_local_files =
147 LOCAL_EXECUTION_LINKS_ON_BUT_NOT_REMOTE;
148 #endif /* EXEC_LINKS || EXEC_SCRIPTS */
149 
150 #if defined(LYNXCGI_LINKS) && !defined(VMS)	/* WebSter Mods -jkt */
151 char *LYCgiDocumentRoot = NULL;	/* DOCUMENT_ROOT in the lynxcgi env */
152 #endif /* LYNXCGI_LINKS */
153 
154 #ifdef TRACK_INTERNAL_LINKS
155 BOOLEAN track_internal_links = TRUE;
156 
157 #else
158 BOOLEAN track_internal_links = FALSE;
159 #endif
160 
161 BOOLEAN enable_scrollback = FALSE;
162 
163 char empty_string[] =
164 {'\0'};
165 
166 int display_lines;		/* number of lines in display */
167 int www_search_result = -1;
168 
169 			       /* linked list of printers */
170 lynx_list_item_type *printers = NULL;
171 
172 			    /* linked list of download options */
173 lynx_list_item_type *downloaders = NULL;
174 
175 			    /* linked list of upload options */
176 #ifdef USE_EXTERNALS
177 lynx_list_item_type *externals = NULL;
178 
179 			    /* linked list of external options */
180 #endif
181 #ifdef USE_IDN2
182 int LYidnaMode = LYidnaTR46;
183 #endif
184 
185 lynx_list_item_type *uploaders = NULL;
186 int LYShowColor = SHOW_COLOR_UNKNOWN;	/* to show or not */
187 int LYrcShowColor = SHOW_COLOR_UNKNOWN;		/* ... last used */
188 
189 #if !defined(NO_OPTION_FORMS) && !defined(NO_OPTION_MENU)
190 BOOLEAN LYUseFormsOptions = TRUE;	/* use forms-based options menu */
191 #endif
192 
193 BOOLEAN LYGuessScheme = FALSE;
194 BOOLEAN LYJumpFileURL = FALSE;	/* always FALSE the first time */
195 BOOLEAN LYPermitURL = FALSE;
196 BOOLEAN LYRestricted = FALSE;	/* whether we have -anonymous option */
197 BOOLEAN LYShowCursor = SHOW_CURSOR;	/* to show or not to show */
198 BOOLEAN LYUnderlineLinks = UNDERLINE_LINKS;	/* Show the links underlined vs bold */
199 BOOLEAN LYUseDefShoCur = TRUE;	/* Command line -show_cursor toggle */
200 BOOLEAN LYUserSpecifiedURL = TRUE;	/* always TRUE  the first time */
201 BOOLEAN LYValidate = FALSE;
202 BOOLEAN LYforce_no_cache = FALSE;
203 BOOLEAN LYinternal_flag = FALSE;	/* override no-cache b/c internal link */
204 BOOLEAN LYoverride_no_cache = FALSE;	/*override no-cache b/c history etc */
205 BOOLEAN LYresubmit_posts = ALWAYS_RESUBMIT_POSTS;
206 BOOLEAN LYtrimBlankLines = TRUE;
207 BOOLEAN LYtrimInputFields = FALSE;
208 BOOLEAN LYxhtml_parsing = FALSE;
209 BOOLEAN bold_H1 = FALSE;
210 BOOLEAN bold_headers = FALSE;
211 BOOLEAN bold_name_anchors = FALSE;
212 BOOLEAN LYcase_sensitive = CASE_SENSITIVE_ALWAYS_ON;
213 BOOLEAN check_mail = CHECKMAIL;
214 BOOLEAN child_lynx = FALSE;
215 BOOLEAN dump_links_decoded = TRUE;
216 BOOLEAN dump_links_inline = FALSE;
217 BOOLEAN dump_links_only = FALSE;
218 BOOLEAN dump_output_immediately = FALSE;
219 BOOLEAN dump_to_stderr = FALSE;
220 BOOLEAN emacs_keys = EMACS_KEYS_ALWAYS_ON;
221 BOOLEAN error_logging = MAIL_SYSTEM_ERROR_LOGGING;
222 BOOLEAN goto_buffer = GOTOBUFFER;	/* TRUE if offering default goto URL */
223 BOOLEAN historical_comments = FALSE;
224 BOOLEAN html5_charsets = FALSE;
225 BOOLEAN is_www_index = FALSE;
226 BOOLEAN jump_buffer = JUMPBUFFER;	/* TRUE if offering default shortcut */
227 BOOLEAN lynx_mode = NORMAL_LYNX_MODE;
228 BOOLEAN minimal_comments = FALSE;
229 BOOLEAN number_fields_on_left = TRUE;
230 BOOLEAN number_links_on_left = TRUE;
231 BOOLEAN recent_sizechange = FALSE;	/* the window size changed recently? */
232 BOOLEAN soft_dquotes = FALSE;
233 BOOLEAN unique_urls = FALSE;
234 BOOLEAN use_underscore = SUBSTITUTE_UNDERSCORES;
235 BOOLEAN verbose_img = VERBOSE_IMAGES;	/* show filenames or not */
236 BOOLEAN vi_keys = VI_KEYS_ALWAYS_ON;
237 int keypad_mode = DEFAULT_KEYPAD_MODE;
238 int user_mode = NOVICE_MODE;
239 
240 BOOLEAN telnet_ok = TRUE;
241 
242 #ifndef DISABLE_NEWS
243 BOOLEAN news_ok = TRUE;
244 #endif
245 BOOLEAN rlogin_ok = TRUE;
246 BOOLEAN long_url_ok = FALSE;
247 BOOLEAN ftp_ok = TRUE;
248 BOOLEAN system_editor = FALSE;
249 
250 BOOLEAN had_restrictions_default = FALSE;
251 BOOLEAN had_restrictions_all = FALSE;
252 
253 BOOLEAN exec_frozen = FALSE;
254 BOOLEAN no_bookmark = FALSE;
255 BOOLEAN no_bookmark_exec = FALSE;
256 BOOLEAN no_chdir = FALSE;
257 BOOLEAN no_disk_save = FALSE;
258 BOOLEAN no_dotfiles = NO_DOT_FILES;
259 BOOLEAN no_download = FALSE;
260 BOOLEAN no_editor = FALSE;
261 BOOLEAN no_exec = FALSE;
262 BOOLEAN no_file_url = FALSE;
263 BOOLEAN no_goto = FALSE;
264 BOOLEAN no_goto_configinfo = FALSE;
265 BOOLEAN no_goto_cso = FALSE;
266 BOOLEAN no_goto_file = FALSE;
267 BOOLEAN no_goto_finger = FALSE;
268 BOOLEAN no_goto_ftp = FALSE;
269 BOOLEAN no_goto_gopher = FALSE;
270 BOOLEAN no_goto_http = FALSE;
271 BOOLEAN no_goto_https = FALSE;
272 BOOLEAN no_goto_lynxcgi = FALSE;
273 BOOLEAN no_goto_lynxexec = FALSE;
274 BOOLEAN no_goto_lynxprog = FALSE;
275 BOOLEAN no_goto_mailto = FALSE;
276 BOOLEAN no_goto_rlogin = FALSE;
277 BOOLEAN no_goto_telnet = FALSE;
278 BOOLEAN no_goto_tn3270 = FALSE;
279 BOOLEAN no_goto_wais = FALSE;
280 BOOLEAN no_inside_ftp = FALSE;
281 BOOLEAN no_inside_rlogin = FALSE;
282 BOOLEAN no_inside_telnet = FALSE;
283 BOOLEAN no_jump = FALSE;
284 BOOLEAN no_lynxcfg_info = FALSE;
285 BOOLEAN no_lynxcgi = FALSE;
286 BOOLEAN no_mail = FALSE;
287 BOOLEAN no_multibook = FALSE;
288 BOOLEAN no_option_save = FALSE;
289 BOOLEAN no_outside_ftp = FALSE;
290 BOOLEAN no_outside_rlogin = FALSE;
291 BOOLEAN no_outside_telnet = FALSE;
292 BOOLEAN no_print = FALSE;
293 BOOLEAN no_shell = FALSE;
294 BOOLEAN no_suspend = FALSE;
295 BOOLEAN no_telnet_port = FALSE;
296 BOOLEAN no_useragent = FALSE;
297 
298 #ifndef DISABLE_FTP
299 BOOLEAN ftp_passive = FTP_PASSIVE;	/* TRUE if doing ftp in passive mode */
300 BOOLEAN ftp_local_passive;
301 HTList *broken_ftp_epsv = NULL;
302 HTList *broken_ftp_retr = NULL;
303 char *ftp_lasthost = NULL;
304 #endif
305 
306 #ifndef DISABLE_NEWS
307 BOOLEAN no_goto_news = FALSE;
308 BOOLEAN no_goto_nntp = FALSE;
309 BOOLEAN no_goto_snews = FALSE;
310 BOOLEAN no_inside_news = FALSE;
311 BOOLEAN no_newspost = FALSE;
312 BOOLEAN no_outside_news = FALSE;
313 #endif
314 
315 #ifdef USE_EXTERNALS
316 BOOLEAN no_externals = FALSE;
317 #endif
318 
319 #ifndef NO_CONFIG_INFO
320 BOOLEAN no_lynxcfg_xinfo = FALSE;
321 
322 #ifdef HAVE_CONFIG_H
323 BOOLEAN no_compileopts_info = FALSE;
324 #endif
325 #endif
326 
327 BOOLEAN no_statusline = FALSE;
328 BOOLEAN no_filereferer = TRUE;
329 char LYRefererWithQuery = 'D';	/* 'D' for drop */
330 BOOLEAN local_host_only = FALSE;
331 BOOLEAN override_no_download = FALSE;
332 BOOLEAN show_dotfiles = FALSE;	/* From rcfile if no_dotfiles is false */
333 BOOLEAN LYforce_HTML_mode = FALSE;
334 BOOLEAN LYfind_leaks = TRUE;
335 
336 #ifdef __DJGPP__
337 BOOLEAN watt_debug = FALSE;	/* WATT-32 debugging */
338 BOOLEAN dj_is_bash = FALSE;	/* Check for bash shell under DJGPP */
339 #endif /* __DJGPP__ */
340 
341 #ifdef WIN_EX
342 BOOLEAN focus_window = FALSE;	/* 1998/10/05 (Mon) 17:18:42 */
343 char windows_drive[4];		/* 1998/01/13 (Tue) 21:13:24 */
344 #endif
345 
346 #ifdef _WINDOWS
347 #define	TIMEOUT	180		/* 1998/03/30 (Mon) 14:50:44 */
348 int lynx_timeout = TIMEOUT;
349 CRITICAL_SECTION critSec_READ;	/* 1998/09/03 (Thu) 22:01:56 */
350 #endif /* _WINDOWS */
351 
352 #if defined(WIN_EX)
353 BOOLEAN system_is_NT = FALSE;
354 #endif
355 
356 BOOLEAN show_cfg = FALSE;
357 
358 BOOLEAN no_table_center = FALSE;	/* 1998/10/09 (Fri) 15:12:49 */
359 
360 #if USE_BLAT_MAILER
361 BOOLEAN mail_is_blat = TRUE;
362 BOOLEAN mail_is_altblat = USE_ALT_BLAT_MAILER;
363 
364 #if USE_ALT_BLAT_MAILER
365 #define THIS_BLAT_MAIL ALTBLAT_MAIL
366 #define THAT_BLAT_MAIL BLAT_MAIL
367 #else
368 #define THIS_BLAT_MAIL BLAT_MAIL
369 #define THAT_BLAT_MAIL ALTBLAT_MAIL
370 #endif
371 #endif
372 
373 #ifdef USE_BLINK
374 #  ifdef __EMX__
375 BOOLEAN term_blink_is_boldbg = TRUE;
376 
377 #  else
378 BOOLEAN term_blink_is_boldbg = FALSE;
379 
380 #  endif
381 #endif
382 
383 BOOLEAN HEAD_request = FALSE;
384 BOOLEAN LYAcceptAllCookies = ACCEPT_ALL_COOKIES;	/* take all cookies? */
385 BOOLEAN LYCancelledFetch = FALSE;	/* TRUE if cancelled binary fetch */
386 BOOLEAN LYCollapseBRs = COLLAPSE_BR_TAGS;	/* Collapse serial BRs? */
387 BOOLEAN LYDefaultRawMode;
388 BOOLEAN LYListNewsDates = LIST_NEWS_DATES;
389 BOOLEAN LYListNewsNumbers = LIST_NEWS_NUMBERS;
390 BOOLEAN LYMBMBlocked = BLOCK_MULTI_BOOKMARKS;
391 BOOLEAN LYNewsPosting = NEWS_POSTING;	/* News posting supported? */
392 BOOLEAN LYNoFromHeader = TRUE;	/* Never send From header?         */
393 BOOLEAN LYNoRefererForThis = FALSE;	/* No Referer header for this URL? */
394 BOOLEAN LYNoRefererHeader = FALSE;	/* Never send Referer header?     */
395 BOOLEAN LYRawMode;
396 BOOLEAN LYSelectPopups = USE_SELECT_POPUPS;
397 BOOLEAN LYSendUserAgent = SEND_USERAGENT;	/* send Lynx User-Agent header? */
398 BOOLEAN LYSetCookies = SET_COOKIES;	/* Process Set-Cookie headers? */
399 BOOLEAN LYUseDefSelPop = TRUE;	/* Command line -popup toggle */
400 BOOLEAN LYUseDefaultRawMode = TRUE;
401 BOOLEAN LYUseMouse = FALSE;
402 BOOLEAN LYisConfiguredForX = FALSE;
403 BOOLEAN UCForce8bitTOUPPER = FALSE;	/* override locale for case-conversion? */
404 BOOLEAN UCSaveBookmarksInUnicode = FALSE;
405 BOOLEAN bookmark_start = FALSE;
406 BOOLEAN check_realm = FALSE;	/* Restrict to the starting realm? */
407 BOOLEAN clickable_images = MAKE_LINKS_FOR_ALL_IMAGES;
408 BOOLEAN crawl = FALSE;		/* Do crawl? */
409 BOOLEAN keep_mime_headers = FALSE;	/* Include mime headers with source dump */
410 BOOLEAN more_text = FALSE;	/* is there more text to display? */
411 BOOLEAN more_links = FALSE;	/* Links beyond a displayed page with no links? */
412 BOOLEAN no_list = FALSE;
413 BOOLEAN no_margins = FALSE;
414 BOOLEAN no_pause = FALSE;
415 BOOLEAN no_title = FALSE;
416 BOOLEAN update_term_title = FALSE;
417 BOOLEAN no_url_redirection = FALSE;	/* Don't follow URL redirections */
418 BOOLEAN pseudo_inline_alts = MAKE_PSEUDO_ALTS_FOR_INLINES;
419 BOOLEAN scan_for_buried_news_references = TRUE;
420 BOOLEAN startfile_ok = FALSE;
421 static BOOLEAN startfile_stdin = FALSE;
422 BOOLEAN traversal = FALSE;	/* Do traversals? */
423 
424 char *BookmarkPage = NULL;	/* the name of the current bookmark page */
425 char *LYCookieAcceptDomains = NULL;	/* domains to accept all cookies */
426 char *LYCookieLooseCheckDomains = NULL;		/* check loosely   */
427 char *LYCookieQueryCheckDomains = NULL;		/* check w/a query */
428 char *LYCookieRejectDomains = NULL;	/* domains to reject all cookies */
429 char *LYCookieSAcceptDomains = NULL;	/* domains to accept all cookies */
430 char *LYCookieSLooseCheckDomains = NULL;	/* check loosely   */
431 char *LYCookieSQueryCheckDomains = NULL;	/* check w/a query */
432 char *LYCookieSRejectDomains = NULL;	/* domains to reject all cookies */
433 char *LYCookieSStrictCheckDomains = NULL;	/* check strictly  */
434 char *LYCookieStrictCheckDomains = NULL;	/* check strictly  */
435 char *LYHostName = NULL;	/* treat as a local host name */
436 char *LYLocalDomain = NULL;	/* treat as a local domain tail */
437 char *LYUserAgent = NULL;	/* Lynx User-Agent header          */
438 char *LYUserAgentDefault = NULL;	/* Lynx default User-Agent header  */
439 char *LynxHome = NULL;		/* the default Home HREF. */
440 char *LynxSigFile = NULL;	/* Signature file, in or off home */
441 char *UCAssume_MIMEcharset = NULL;
442 char *URLDomainPrefixes = NULL;
443 char *URLDomainSuffixes = NULL;
444 char *anonftp_password = NULL;	/* anonymous ftp password (default: email) */
445 char *authentication_info[2] =
446 {NULL, NULL};			/* Id:Password for protected documents */
447 char *bookmark_page = NULL;	/* the name of the default bookmark page */
448 char *editor = NULL;		/* the name of the current editor */
449 char *form_get_data = NULL;	/* User data for get form */
450 char *form_post_data = NULL;	/* User data for post form */
451 char *global_extension_map = NULL;	/* global mime.types */
452 char *global_type_map = NULL;	/* global mailcap */
453 char *helpfile = NULL;		/* the main help file */
454 char *helpfilepath = NULL;	/* the path to the help file set */
455 char *homepage = NULL;		/* home page or main screen */
456 char *http_error_file = NULL;	/* Place HTTP status code in this file */
457 char *indexfile = NULL;		/* an index file if there is one */
458 char *jumpfile = NULL;		/* the name of the default jumps file */
459 char *jumpprompt = NULL;	/* the default jumps prompt */
460 char *language = NULL;		/* preferred language */
461 char *lynx_cfg_file = NULL;	/* location of active lynx.cfg */
462 char *lynx_cmd_logfile;		/* file to write keystroke commands, if any */
463 char *lynx_cmd_script;		/* file to read keystroke commands, if any */
464 char *lynx_save_space = NULL;	/* The prefix for save to disk paths */
465 char *lynx_temp_space = NULL;	/* The prefix for temporary file paths */
466 char *lynxjumpfile = NULL;	/* the current jump file URL */
467 char *lynxlinksfile = NULL;	/* the current visited links file URL */
468 char *lynxlistfile = NULL;	/* the current list file URL */
469 char *original_dir = NULL;	/* the original directory */
470 char *personal_extension_map = NULL;	/* .mime.types */
471 char *personal_mail_address = NULL;	/* the user's mail address */
472 char *personal_mail_name = NULL;	/* the user's personal name mail */
473 char *personal_type_map = NULL;	/* .mailcap */
474 char *pref_charset = NULL;	/* preferred character set */
475 char *proxyauth_info[2] =
476 {NULL, NULL};			/* Id:Password for protected proxy servers */
477 
478 #ifdef USE_SESSIONS
479 BOOLEAN LYAutoSession = FALSE;	/* enable/disable auto saving/restoring of */
480 
481 				/* session */
482 char *LYSessionFile = NULL;	/* the session file from lynx.cfg */
483 char *session_file = NULL;	/* the current session file */
484 char *sessionin_file = NULL;	/* only resume session from this file */
485 char *sessionout_file = NULL;	/* only save session to this file */
486 short session_limit = 250;	/* maximal number of entries saved per */
487 
488 				/* session file, rest will be ignored */
489 #endif /* USE_SESSIONS */
490 char *startfile = NULL;		/* the first file */
491 char *startrealm = NULL;	/* the startfile realm */
492 char *system_mail = NULL;	/* The path for sending mail */
493 char *system_mail_flags = NULL;	/* Flags for sending mail */
494 char *x_display = NULL;		/* display environment variable */
495 
496 HistInfo *history;
497 int nhist = 0;			/* number of used history entries */
498 unsigned size_history;		/* number of allocated history entries */
499 
500 LinkInfo links[MAXLINKS];
501 
502 BOOLEAN nomore = FALSE;		/* display -more- string in statusline messages */
503 int AlertSecs;			/* time-delay for HTAlert() messages   */
504 int DelaySecs;			/* time-delay for HTProgress messages */
505 int InfoSecs;			/* time-delay for Information messages */
506 int LYMultiBookmarks = MULTI_BOOKMARK_SUPPORT;
507 int LYStatusLine = -1;		/* Line for statusline() if > -1 */
508 int LYcols = DFT_COLS;
509 int LYlines = DFT_ROWS;
510 int MessageSecs;		/* time-delay for important Messages   */
511 int ReplaySecs;			/* time-delay for command-scripts */
512 int crawl_count = 0;		/* Starting number for lnk#.dat files in crawls */
513 int dump_output_width = 0;
514 int dump_server_status = 0;
515 int lynx_temp_subspace = 0;	/* > 0 if we made temp-directory */
516 int max_cookies_domain = 50;
517 int max_cookies_global = 500;
518 int max_cookies_buffer = 4096;
519 int max_uri_size = 8192;
520 int nlinks = 0;			/* number of links in memory */
521 int outgoing_mail_charset = -1;	/* translate mail to this charset */
522 
523 #ifndef DISABLE_BIBP
524 BOOLEAN BibP_bibhost_available = FALSE;		/* until check succeeds  */
525 BOOLEAN BibP_bibhost_checked = FALSE;	/*  until LYCheckBibHost   */
526 BOOLEAN no_goto_bibp = FALSE;
527 char *BibP_bibhost = NULL;	/* local server for bibp: links  */
528 char *BibP_globalserver = NULL;	/* global server for bibp: links */
529 #endif
530 
531 #ifdef USE_PERSISTENT_COOKIES
532 BOOLEAN persistent_cookies = FALSE;	/* disabled by default! */
533 char *LYCookieFile = NULL;	/* cookie read file */
534 char *LYCookieSaveFile = NULL;	/* cookie save file */
535 #endif /* USE_PERSISTENT_COOKIES */
536 
537 #ifdef EXP_NESTED_TABLES
538 BOOLEAN nested_tables =
539 #if defined(USE_COLOR_STYLE)
540 TRUE
541 #else
542 FALSE				/* see 2001-08-15  */
543 #endif
544  ;
545 #endif
546 
547 BOOLEAN LYShowTransferRate = TRUE;
548 int LYTransferRate = rateKB;
549 int LYAcceptEncoding = encodingALL;
550 int LYAcceptMedia = mediaOpt1;
551 int LYContentType = contentTEXT;
552 const char *ContentTypes[] =
553 {
554     STR_BINARY,
555     STR_PLAINTEXT,
556     STR_HTML
557 };
558 char *LYTransferName = NULL;
559 
560 char *XLoadImageCommand = NULL;	/* Default image viewer for X */
561 BOOLEAN LYNoISMAPifUSEMAP = FALSE;	/* Omit ISMAP link if MAP present? */
562 int LYHiddenLinks = HIDDENLINKS_SEPARATE;	/* Show hidden links? */
563 
564 char *SSL_cert_file = NULL;	/* Default CA CERT file */
565 char *SSL_client_cert_file = NULL;
566 char *SSL_client_key_file = NULL;
567 
568 int HTprotocolLevel = HTTP_1_0;
569 
570 int Old_DTD = NO;
571 static BOOLEAN DTD_recovery = NO;
572 
573 #ifndef NO_LYNX_TRACE
574 FILE *LYTraceLogFP = NULL;	/* Pointer for TRACE log  */
575 #endif
576 char *LYTraceLogPath = NULL;	/* Path for TRACE log      */
577 BOOLEAN LYUseTraceLog = USE_TRACE_LOG;	/* Use a TRACE log?        */
578 
579 #ifdef LY_FIND_LEAKS
580 char LYLeaksPath[LY_MAXPATH];
581 #endif
582 
583 BOOLEAN LYSeekFragMAPinCur = TRUE;
584 BOOLEAN LYSeekFragAREAinCur = TRUE;
585 BOOLEAN LYStripDotDotURLs = TRUE;	/* Try to fix ../ in some URLs? */
586 BOOLEAN LYForceSSLCookiesSecure = FALSE;
587 BOOLEAN LYNoCc = FALSE;
588 BOOLEAN LYPreparsedSource = FALSE;	/* Show source as preparsed? */
589 BOOLEAN LYPrependBaseToSource = TRUE;
590 BOOLEAN LYPrependCharsetToSource = TRUE;
591 BOOLEAN LYQuitDefaultYes = QUIT_DEFAULT_YES;
592 BOOLEAN dont_wrap_pre = FALSE;
593 
594 int cookie_noprompt;
595 int cookie_version = COOKIES_RFC_6265;
596 
597 #ifdef USE_SSL
598 int ssl_noprompt = FORCE_PROMPT_DFT;
599 #endif
600 BOOLEAN conv_jisx0201kana = TRUE;
601 BOOLEAN wait_viewer_termination = FALSE;
602 
603 int connect_timeout = 18000; /*=180000*0.1 - used in HTDoConnect.*/
604 int reading_timeout = 18000; /*=180000*0.1 - used in HTDoConnect.*/
605 
606 #ifdef USE_JUSTIFY_ELTS
607 BOOLEAN ok_justify = FALSE;
608 int justify_max_void_percent = 35;
609 #endif
610 
611 #ifdef USE_LOCALE_CHARSET
612 BOOLEAN LYLocaleCharset = FALSE;
613 #endif
614 BOOLEAN assumed_charset = FALSE;
615 
616 #ifndef NO_DUMP_WITH_BACKSPACES
617 BOOLEAN with_backspaces = FALSE;
618 #endif
619 
620 #if defined(PDCURSES) && defined(PDC_BUILD) && PDC_BUILD >= 2401
621 int scrsize_x = 0;
622 int scrsize_y = 0;
623 #endif
624 
625 BOOLEAN force_empty_hrefless_a = FALSE;
626 
627 #ifdef TEXTFIELDS_MAY_NEED_ACTIVATION
628 BOOL textfields_need_activation = FALSE;
629 BOOLEAN textfields_activation_option = FALSE;
630 #endif
631 
632 BOOLEAN textfield_prompt_at_left_edge = FALSE;
633 
634 #ifdef MARK_HIDDEN_LINKS
635 char *hidden_link_marker = NULL;
636 #endif
637 
638 #ifdef DISP_PARTIAL
639 BOOLEAN display_partial_flag = TRUE;	/* Display document during download */
640 BOOLEAN debug_display_partial = FALSE;	/* Show with MessageSecs delay */
641 int partial_threshold = -1;	/* # of lines to be d/l'ed until we repaint */
642 #endif
643 
644 char *socks5_proxy = NULL;
645 
646 BOOLEAN LYNonRestartingSIGWINCH = FALSE;
647 BOOLEAN LYReuseTempfiles = FALSE;
648 BOOLEAN LYUseBuiltinSuffixes = TRUE;
649 
650 int LYNoZapKey = 0;		/* 0: off (do z checking), 1: full, 2: initially */
651 
652 #ifndef DISABLE_NEWS
653 #include <HTNews.h>
654 #endif
655 
656 BOOLEAN FileInitAlreadyDone = FALSE;
657 
658 #ifdef USE_PROGRAM_DIR
659 char *program_dir = NULL;
660 #endif
661 
662 static BOOLEAN stack_dump = FALSE;
663 static char *terminal = NULL;
664 static const char *pgm;
665 static BOOLEAN no_numbers = FALSE;
666 static BOOLEAN number_links = FALSE;
667 static BOOLEAN number_fields = FALSE;
668 static BOOLEAN LYPrependBase = FALSE;
669 static HTList *LYStdinArgs = NULL;
670 HTList *positionable_editor = NULL;
671 
672 #ifndef EXTENDED_OPTION_LOGIC
673 /* if set then '--' will be recognized as the end of options */
674 #define EXTENDED_OPTION_LOGIC 1
675 #endif
676 
677 #ifndef EXTENDED_STARTFILE_RECALL
678 /* if set then additional non-option args (before the last one) will be
679    made available for 'g'oto recall - kw */
680 #define EXTENDED_STARTFILE_RECALL 1
681 #endif
682 
683 #if EXTENDED_STARTFILE_RECALL
684 static char *nonoption = 0;
685 #endif
686 
687 #ifndef OPTNAME_ALLOW_DASHES
688 /* if set, then will allow dashes and underscores to be used interchangeable
689    in commandline option's names - VH */
690 #define OPTNAME_ALLOW_DASHES 1
691 #endif
692 
693 static BOOL parse_arg(char **arg, unsigned mask, int *countp);
694 static GCC_NORETURN void print_help_and_exit(int exit_status);
695 static void print_help_strings(const char *name,
696 			       const char *help,
697 			       const char *value,
698 			       int option);
699 
700 #ifndef VMS
701 BOOLEAN LYNoCore = NO_FORCED_CORE_DUMP;
702 BOOLEAN restore_sigpipe_for_children = FALSE;
703 static void FatalProblem(int sig);
704 #endif /* !VMS */
705 
706 #if defined(USE_COLOR_STYLE)
707 int LYuse_color_style = TRUE;
708 char *lynx_lss_file = NULL;	/* from config-file, etc. */
709 static char *lynx_lss_file2 = NULL;	/* from command-line options */
710 const char *default_color_styles = "\
711 lynx.lss;\
712 blue-background.lss;\
713 bright-blue.lss;\
714 midnight.lss;\
715 mild-colors.lss;\
716 opaque.lss\
717 ";
718 #endif
719 
720 #ifdef USE_DEFAULT_COLORS
721 BOOLEAN LYuse_default_colors = TRUE;
722 #endif
723 
724 #ifdef __DJGPP__
LY_set_ctrl_break(int setting)725 static void LY_set_ctrl_break(int setting)
726 {
727     (void) signal(SIGINT, (setting ? SIG_DFL : SIG_IGN));
728     setcbrk(setting);
729 }
730 
LY_get_ctrl_break(void)731 static int LY_get_ctrl_break(void)
732 {
733     __dpmi_regs regs;
734 
735     regs.h.ah = 0x33;
736     regs.h.al = 0x00;
737     __dpmi_int(0x21, &regs);
738     return ((int) regs.h.dl);
739 }
740 
reset_break(void)741 static void reset_break(void)
742 {
743     LY_set_ctrl_break(init_ctrl_break[0]);
744 }
745 #endif /* __DJGPP__ */
746 
747 #if defined(WIN_EX)
is_windows_nt(void)748 static int is_windows_nt(void)
749 {
750     DWORD version;
751 
752     version = GetVersion();
753     if ((version & 0x80000000) == 0)
754 	return 1;
755     else
756 	return 0;
757 }
758 #endif
759 
760 #ifdef LY_FIND_LEAKS
free_lynx_globals(void)761 static void free_lynx_globals(void)
762 {
763     int i;
764 
765 #if defined(USE_COLOR_STYLE)
766     clear_lss_list();
767 #endif
768     FREE(ftp_format);
769 #ifndef VMS
770     FREE(list_format);
771 #ifdef LYNXCGI_LINKS		/* WebSter Mods -jkt */
772     FREE(LYCgiDocumentRoot);
773 #endif /* LYNXCGI_LINKS */
774     free_lynx_cfg();
775 #endif /* !VMS */
776 
777 #ifdef SYSLOG_REQUESTED_URLS
778     FREE(syslog_txt);
779 #endif
780 
781 #ifdef VMS
782     Define_VMSLogical("LYNX_VERSION", "");
783 #else
784     (void) putenv("LYNX_VERSION=" LYNX_VERSION);
785 #endif /* VMS */
786 #ifndef VMS
787     FREE(lynx_version_putenv_command);
788 #endif
789 
790 #if USE_VMS_MAILER
791     FREE(mail_adrs);
792 #endif
793 
794     FREE(LynxHome);
795     FREE(history);
796     FREE(homepage);
797     FREE(original_dir);
798     FREE(startfile);
799     FREE(helpfile);
800     FREE(helpfilepath);
801     FREE(jumpprompt);
802 #ifdef JUMPFILE
803     FREE(jumpfile);
804 #endif /* JUMPFILE */
805     FREE(indexfile);
806     FREE(x_display);
807     FREE(global_type_map);
808     FREE(personal_type_map);
809     FREE(global_extension_map);
810     FREE(personal_extension_map);
811     FREE(language);
812     FREE(pref_charset);
813     FREE(LynxSigFile);
814     FREE(system_mail);
815     FREE(system_mail_flags);
816 #ifndef DISABLE_BIBP
817     FREE(BibP_bibhost);
818     FREE(BibP_globalserver);
819 #endif
820 #ifdef USE_PERSISTENT_COOKIES
821     FREE(LYCookieFile);
822     FREE(LYCookieSaveFile);
823 #endif
824     FREE(LYCookieAcceptDomains);
825     FREE(LYCookieRejectDomains);
826     FREE(LYCookieLooseCheckDomains);
827     FREE(LYCookieStrictCheckDomains);
828     FREE(LYCookieQueryCheckDomains);
829     FREE(LYUserAgent);
830     FREE(LYUserAgentDefault);
831     FREE(LYHostName);
832     FREE(LYLocalDomain);
833     FREE(lynx_save_space);
834     FREE(bookmark_page);
835     FREE(BookmarkPage);
836     for (i = 0; i <= MBM_V_MAXFILES; i++) {
837 	FREE(MBM_A_subbookmark[i]);
838 	FREE(MBM_A_subdescript[i]);
839     }
840     FREE(editor);
841     FREE(authentication_info[0]);
842     FREE(authentication_info[1]);
843     FREE(proxyauth_info[0]);
844     FREE(proxyauth_info[1]);
845     FREE(lynxjumpfile);
846 #ifndef DISABLE_FTP
847     FREE(ftp_lasthost);
848     LYFreeStringList(broken_ftp_epsv);
849     LYFreeStringList(broken_ftp_retr);
850 #endif
851     FREE(startrealm);
852     FREE(personal_mail_address);
853     FREE(personal_mail_name);
854     FREE(anonftp_password);
855     FREE(URLDomainPrefixes);
856     FREE(URLDomainSuffixes);
857     FREE(XLoadImageCommand);
858     FREE(lynx_temp_space);
859     FREE(LYTransferName);
860     FREE(LYTraceLogPath);
861     FREE(lynx_cfg_file);
862     FREE(SSL_cert_file);
863     FREE(SSL_client_cert_file);
864     FREE(SSL_client_key_file);
865 #if defined(USE_COLOR_STYLE)
866     FREE(lynx_lss_file2);
867     FREE(lynx_lss_file);
868 #endif
869     FREE(UCAssume_MIMEcharset);
870     LYUIPages_free();
871     LYFreeHilites(0, nlinks);
872     nlinks = 0;
873     LYFreeStringList(LYcommandList());
874     HTInitProgramPaths(FALSE);
875 #if EXTENDED_STARTFILE_RECALL
876     FREE(nonoption);
877 #endif
878     LYFreeStringList(positionable_editor);
879 
880     return;
881 }
882 #endif /* LY_FIND_LEAKS */
883 
884 /*
885  * This function frees the LYStdinArgs list.  - FM
886  */
LYStdinArgs_free(void)887 static void LYStdinArgs_free(void)
888 {
889     LYFreeStringList(LYStdinArgs);
890     LYStdinArgs = NULL;
891 }
892 
reset_signals(void)893 void reset_signals(void)
894 {
895 #ifndef NOSIGHUP
896     (void) signal(SIGHUP, SIG_DFL);
897 #endif /* NOSIGHUP */
898     (void) signal(SIGTERM, SIG_DFL);
899 #ifndef VMS
900     (void) signal(SIGINT, SIG_DFL);
901 #endif /* !VMS */
902 #ifdef SIGTSTP
903     if (no_suspend)
904 	(void) signal(SIGTSTP, SIG_DFL);
905 #endif /* SIGTSTP */
906 }
907 
exit_immediately(int code)908 void exit_immediately(int code)
909 {
910     reset_signals();
911     exit(code);
912 }
913 
914 #ifdef  EBCDIC
FixCharacters(void)915 static void FixCharacters(void)
916 {
917     int c;
918     int work1[256], work2[256];
919 
920     for (c = 0; c < 256; c++) {
921 	work1[c] = keymap[c + 1];
922 	work2[c] = key_override[c + 1];
923     }
924     for (c = 0; c < 256; c++) {
925 	keymap[IBM1047[c] + 1] = work1[c];
926 	key_override[IBM1047[c] + 1] = work2[c];
927     }
928 }
929 #endif /* EBCDIC */
930 
GetStdin(char ** buf,int marker)931 static BOOL GetStdin(char **buf,
932 		     int marker)
933 {
934     if (LYSafeGets(buf, stdin) != 0
935 	&& (!marker || StrNCmp(*buf, "---", 3) != 0)) {
936 	LYTrimTrailing(*buf);
937 	CTRACE((tfp, "...data: %s\n", *buf));
938 	return TRUE;
939     }
940     CTRACE((tfp, "...mark: %s\n", *buf ? *buf : ""));
941     return FALSE;
942 }
943 
944 #ifdef WIN32
cleanup_win32(DWORD fdwCtrlType)945 static BOOL cleanup_win32(DWORD fdwCtrlType)
946 {
947     switch (fdwCtrlType) {
948     case CTRL_CLOSE_EVENT:
949 	cleanup_sig(-1);
950 	return TRUE;
951     default:
952 	return FALSE;
953     }
954 }
955 #endif
956 
957 /*
958  * Append the SSL version to lynx version or user-agent string.
959  */
960 #ifdef USE_SSL
append_ssl_version(char ** target,const char * separator)961 static void append_ssl_version(char **target,
962 			       const char *separator)
963 {
964     char SSLLibraryVersion[256];
965     char *SSLcp;
966 
967     HTSprintf(target, " SSL-MM%s1.4.1", separator);
968 
969 #undef LYNX_SSL_VERSION
970 
971 #if defined(SSLEAY_VERSION)
972 #define LYNX_SSL_VERSION SSLeay_version(SSLEAY_VERSION)
973 #elif defined(OPENSSL_VERSION_TEXT)
974 #define LYNX_SSL_VERSION OPENSSL_VERSION_TEXT
975 #elif defined(GNUTLS_VERSION)
976 #define LYNX_SSL_VERSION "GNUTLS " GNUTLS_VERSION " "
977 #endif
978 
979 #ifdef LYNX_SSL_VERSION
980     if (*separator == ' ')
981 	StrAllocCat(*target, ",");
982     LYStrNCpy(SSLLibraryVersion, LYNX_SSL_VERSION, sizeof(SSLLibraryVersion) - 1);
983     if ((SSLcp = StrChr(SSLLibraryVersion, ' ')) != NULL) {
984 	*SSLcp++ = *separator;
985 	if ((SSLcp = StrChr(SSLcp, ' ')) != NULL) {
986 	    *SSLcp = '\0';
987 	    StrAllocCat(*target, " ");
988 	    StrAllocCat(*target, SSLLibraryVersion);
989 	}
990     }
991 #endif /* LYNX_SSL_VERSION */
992 }
993 #endif /* USE_SSL */
994 
995 /* Set the text message domain.  */
LYSetTextDomain(void)996 void LYSetTextDomain(void)
997 {
998 #if defined(HAVE_LIBINTL_H) || defined(HAVE_LIBGETTEXT_H)
999     const char *cp;
1000 
1001     if ((cp = LYGetEnv("LYNX_LOCALEDIR")) == 0) {
1002 #ifdef USE_PROGRAM_DIR
1003 	char *localedir = NULL;
1004 
1005 	HTSprintf0(&localedir, "%s\\locale", program_dir);
1006 	cp = localedir;
1007 #else
1008 	cp = LOCALEDIR;
1009 #endif
1010     }
1011     bindtextdomain(NLS_TEXTDOMAIN, cp);
1012     textdomain(NLS_TEXTDOMAIN);
1013 #endif
1014 }
1015 
SetLocale(void)1016 static void SetLocale(void)
1017 {
1018 #ifdef LOCALE
1019     /*
1020      * LOCALE support for international characters.
1021      */
1022     setlocale(LC_ALL, "");
1023 #endif /* LOCALE */
1024     LYSetTextDomain();
1025 }
1026 
1027 /*
1028  * Wow!  Someone wants to start up Lynx.
1029  */
main(int argc,char ** argv)1030 int main(int argc,
1031 	 char **argv)
1032 {
1033     int i;			/* indexing variable */
1034     int status = 0;		/* exit status */
1035     char *temp = NULL;
1036     const char *ccp;
1037     char *cp;
1038     FILE *fp;
1039     struct stat dir_info;
1040     char filename[LY_MAXPATH];
1041     BOOL LYGetStdinArgs = FALSE;
1042 
1043 #ifdef _WINDOWS
1044     WSADATA WSAData;
1045 #endif /* _WINDOWS */
1046 
1047     /*
1048      * Just in case someone has the idea to install lynx set-uid, let's try
1049      * to discourage it.
1050      */
1051 #if defined(GETUID) && defined(SETUID)
1052     setuid(getuid());
1053 #endif
1054 
1055 #ifdef LY_FIND_LEAKS
1056     /*
1057      * Register the final function to be executed when being exited.  Will
1058      * display memory leaks if the -find-leaks option is used.  This should
1059      * be the first call to atexit() for leak-checking, which ensures that
1060      * all of the other functions will be invoked before LYLeaks().
1061      */
1062     atexit(LYLeaks);
1063     /*
1064      * Register the function which will free our allocated globals.
1065      */
1066     atexit(free_lynx_globals);
1067 
1068     LYAddPathToHome(LYLeaksPath, (size_t) LY_MAXPATH, LEAKAGE_SINK);
1069 #endif /* LY_FIND_LEAKS */
1070 
1071 #ifdef    NOT_ASCII
1072     FixCharacters();
1073 #endif /* NOT_ASCII */
1074 
1075 #ifndef DISABLE_FTP
1076     /* malloc a sizeof(char) so 1st strcmp() won't dump in HTLoadFile() */
1077     ftp_lasthost = typecalloc(char);
1078 #endif
1079 
1080     LYinitEditmap();
1081     LYinitKeymap();
1082 #ifdef USE_CHARSET_CHOICE
1083     memset((char *) charset_subsets, 0, sizeof(charset_subset_t) * MAXCHARSETS);
1084 #endif
1085 
1086 #ifdef _WINDOWS
1087     {
1088 	int err;
1089 	WORD wVerReq;
1090 
1091 	wVerReq = MAKEWORD(1, 1);
1092 
1093 	err = WSAStartup(wVerReq, &WSAData);
1094 	if (err != 0) {
1095 	    puts(gettext("No Winsock found, sorry."));
1096 	    sleep(5);
1097 	    return 1;
1098 	}
1099     }
1100 
1101     /* 1998/09/03 (Thu) 22:02:32 */
1102     InitializeCriticalSection(&critSec_READ);
1103 
1104 #endif /* _WINDOWS */
1105 
1106 #if defined(WIN_EX)
1107     /* 1997/10/19 (Sun) 21:40:54 */
1108     system_is_NT = (BOOL) is_windows_nt();
1109 
1110     /* 1998/01/13 (Tue) 21:13:47 */
1111     GetWindowsDirectory(filename, sizeof filename);
1112     windows_drive[0] = filename[0];
1113     windows_drive[1] = filename[1];
1114     windows_drive[2] = '\0';
1115 #endif
1116 
1117 #ifdef __DJGPP__
1118     if (LY_get_ctrl_break() == 0) {
1119 	LY_set_ctrl_break(TRUE);
1120 	init_ctrl_break[0] = 0;
1121     } else {
1122 	init_ctrl_break[0] = 1;
1123     }
1124     __djgpp_set_sigquit_key(0x082D);	/* Bind ALT-X to SIGQUIT */
1125     signal(SIGQUIT, cleanup_sig);
1126     atexit(reset_break);
1127 
1128     if (((ccp = LYGetEnv("SHELL")) != NULL)
1129 	&& (strstr(LYPathLeaf(ccp), "sh") != NULL))
1130 	dj_is_bash = TRUE;
1131 #endif /* __DJGPP__ */
1132 
1133     /*
1134      * To prevent corrupting binary data on DOS, MS-WINDOWS or OS/2
1135      * we open files and stdout in BINARY mode by default.
1136      * Where necessary we should open and (close!) TEXT mode.
1137      * (use LYNewTxtFile/LYAppendToTxtFile to open text files for writing)
1138      */
1139     SetDefaultMode(O_BINARY);
1140     SetOutputMode(O_BINARY);
1141 
1142 #ifdef DOSPATH
1143     if (LYGetEnv("TERM") == NULL)
1144 	putenv("TERM=vt100");
1145 #endif
1146 
1147     LYShowColor = (SHOW_COLOR ? SHOW_COLOR_ON : SHOW_COLOR_OFF);
1148     /*
1149      * Set up the argument list.
1150      */
1151     pgm = argv[0];
1152     cp = NULL;
1153 #ifdef USE_PROGRAM_DIR
1154     StrAllocCopy(program_dir, pgm);
1155     if ((cp = strrchr(program_dir, '\\')) != NULL) {
1156 	*cp = '\0';
1157     } else {
1158 	FREE(program_dir);
1159 	StrAllocCopy(program_dir, ".");
1160     }
1161 #endif
1162     if ((cp = LYLastPathSep(pgm)) != NULL) {
1163 	pgm = cp + 1;
1164     }
1165 
1166     /*
1167      * Set up trace, the anonymous account defaults, validate restrictions,
1168      * and/or the nosocks flag, if requested, and an alternate configuration
1169      * file, if specified, NOW.  Also, if we only want the help menu, output
1170      * that and exit.  - FM
1171      */
1172 #ifndef NO_LYNX_TRACE
1173     if (LYGetEnv("LYNX_TRACE") != 0) {
1174 	WWW_TraceFlag = TRUE;
1175     }
1176 #endif
1177 
1178     /*
1179      * Set up the TRACE log path, and logging if appropriate.  - FM
1180      */
1181     if ((ccp = LYGetEnv("LYNX_TRACE_FILE")) == 0)
1182 	ccp = FNAME_LYNX_TRACE;
1183     LYTraceLogPath = typeMallocn(char, LY_MAXPATH);
1184 
1185     LYAddPathToHome(LYTraceLogPath, (size_t) LY_MAXPATH, ccp);
1186 
1187     /*
1188      * Act on -version, -trace and -trace-mask NOW.
1189      */
1190     for (i = 1; i < argc; i++) {
1191 	parse_arg(&argv[i], 1, &i);
1192     }
1193     LYOpenTraceLog();
1194 
1195     SetLocale();
1196 
1197     /*
1198      * Initialize our startup and global variables.
1199      */
1200 #ifdef ULTRIX
1201     /*
1202      * Need this for Ultrix.
1203      */
1204     terminal = LYGetEnv("TERM");
1205     if ((terminal == NULL) || !strncasecomp(terminal, "xterm", 5))
1206 	terminal = "vt100";
1207 #endif /* ULTRIX */
1208     /*
1209      * Zero the links and history struct arrays.
1210      */
1211     memset((void *) links, 0, sizeof(LinkInfo) * MAXLINKS);
1212     LYAllocHistory(8);
1213     /*
1214      * Zero the MultiBookmark arrays.
1215      */
1216     memset((void *) MBM_A_subbookmark, 0, sizeof(char *) * (MBM_V_MAXFILES + 1));
1217     memset((void *) MBM_A_subdescript, 0, sizeof(char *) * (MBM_V_MAXFILES + 1));
1218 
1219 #ifndef VMS
1220     StrAllocCopy(list_format, LIST_FORMAT);
1221     StrAllocCopy(ftp_format, FTP_FORMAT);
1222 #endif /* !VMS */
1223 
1224     AlertSecs = SECS2Secs(ALERTSECS);
1225     DelaySecs = SECS2Secs(DEBUGSECS);
1226     InfoSecs = SECS2Secs(INFOSECS);
1227     MessageSecs = SECS2Secs(MESSAGESECS);
1228     ReplaySecs = SECS2Secs(REPLAYSECS);
1229 
1230     StrAllocCopy(LYTransferName, "KiB");
1231     StrAllocCopy(helpfile, HELPFILE);
1232     StrAllocCopy(startfile, STARTFILE);
1233     LYEscapeStartfile(&startfile);
1234     StrAllocCopy(indexfile, DEFAULT_INDEX_FILE);
1235     StrAllocCopy(global_type_map, GLOBAL_MAILCAP);
1236     StrAllocCopy(personal_type_map, PERSONAL_MAILCAP);
1237     StrAllocCopy(global_extension_map, GLOBAL_EXTENSION_MAP);
1238     StrAllocCopy(personal_extension_map, PERSONAL_EXTENSION_MAP);
1239     StrAllocCopy(language, PREFERRED_LANGUAGE);
1240     StrAllocCopy(pref_charset, PREFERRED_CHARSET);
1241     StrAllocCopy(system_mail, SYSTEM_MAIL);
1242     StrAllocCopy(system_mail_flags, SYSTEM_MAIL_FLAGS);
1243 
1244     StrAllocCopy(LYUserAgent, LYNX_NAME);
1245     StrAllocCat(LYUserAgent, "/");
1246     StrAllocCat(LYUserAgent, LYNX_VERSION);
1247     if (HTLibraryVersion) {
1248 	StrAllocCat(LYUserAgent, " libwww-FM/");
1249 	StrAllocCat(LYUserAgent, HTLibraryVersion);
1250     }
1251 #ifdef USE_SSL
1252     append_ssl_version(&LYUserAgent, "/");
1253 #endif /* USE_SSL */
1254     StrAllocCopy(LYUserAgentDefault, LYUserAgent);
1255 
1256 #ifdef VMS
1257     Define_VMSLogical("LYNX_VERSION", LYNX_VERSION);
1258 #else
1259     StrAllocCopy(lynx_version_putenv_command, "LYNX_VERSION=");
1260     StrAllocCat(lynx_version_putenv_command, LYNX_VERSION);
1261     (void) putenv(lynx_version_putenv_command);
1262     /* Note: you must not free the data passed to 'putenv()' until you give it
1263      * a new value for that variable.
1264      */
1265 #endif /* VMS */
1266 
1267     if ((ccp = LYGetEnv("LYNX_TEMP_SPACE")) != NULL)
1268 	StrAllocCopy(lynx_temp_space, ccp);
1269 #if defined (UNIX) || defined (__DJGPP__)
1270     else if ((ccp = LYGetEnv("TMPDIR")) != NULL)
1271 	StrAllocCopy(lynx_temp_space, ccp);
1272 #endif
1273 #if defined (DOSPATH) || defined (__EMX__)
1274     else if ((ccp = LYGetEnv("TEMP")) != NULL)
1275 	StrAllocCopy(lynx_temp_space, ccp);
1276     else if ((ccp = LYGetEnv("TMP")) != NULL)
1277 	StrAllocCopy(lynx_temp_space, ccp);
1278 #endif
1279     else {
1280 #if defined(USE_PROGRAM_DIR)
1281 	StrAllocCopy(lynx_temp_space, program_dir);
1282 #elif defined(TEMP_SPACE)
1283 	StrAllocCopy(lynx_temp_space, TEMP_SPACE);
1284 #else
1285 	puts(gettext("You MUST define a valid TMP or TEMP area!"));
1286 	exit_immediately(EXIT_FAILURE);
1287 #endif
1288     }
1289 
1290 #ifdef WIN_EX			/* for Windows 2000 ... 1999/08/23 (Mon) 08:24:35 */
1291     if (access(lynx_temp_space, 0) != 0)
1292 #endif
1293 	LYTildeExpand(&lynx_temp_space, TRUE);
1294 
1295     if ((cp = strstr(lynx_temp_space, "$USER")) != NULL) {
1296 	char *cp1;
1297 
1298 	if ((cp1 = LYGetEnv("USER")) != NULL) {
1299 	    *cp = '\0';
1300 	    StrAllocCopy(temp, lynx_temp_space);
1301 	    *cp = '$';
1302 	    StrAllocCat(temp, cp1);
1303 	    cp += 5;
1304 	    StrAllocCat(temp, cp);
1305 	    StrAllocCopy(lynx_temp_space, temp);
1306 	    FREE(temp);
1307 	}
1308     }
1309 #ifdef VMS
1310     LYLowerCase(lynx_temp_space);
1311     if (StrChr(lynx_temp_space, '/') != NULL) {
1312 	if (strlen(lynx_temp_space) == 1) {
1313 	    StrAllocCopy(lynx_temp_space, "sys$scratch:");
1314 	} else {
1315 	    LYAddPathSep(&lynx_temp_space);
1316 	    StrAllocCopy(temp, HTVMS_name("", lynx_temp_space));
1317 	    StrAllocCopy(lynx_temp_space, temp);
1318 	    FREE(temp);
1319 	}
1320     }
1321     if (StrChr(lynx_temp_space, ':') == NULL &&
1322 	StrChr(lynx_temp_space, ']') == NULL) {
1323 	StrAllocCat(lynx_temp_space, ":");
1324     }
1325 #else
1326     LYAddPathSep(&lynx_temp_space);
1327     StrAllocCopy(lynx_temp_space, HTSYS_name(lynx_temp_space));
1328 #endif /* VMS */
1329 
1330     if ((HTStat(lynx_temp_space, &dir_info) < 0
1331 #if defined(MULTI_USER_UNIX)
1332 	 && mkdir(lynx_temp_space, 0700) < 0
1333 #endif
1334 	)
1335 	|| !S_ISDIR(dir_info.st_mode)) {
1336 	fprintf(stderr, "%s: %s\n",
1337 		lynx_temp_space,
1338 		gettext("No such directory"));
1339 	exit_immediately(EXIT_FAILURE);
1340     }
1341 #if USE_VMS_MAILER
1342 #ifndef MAIL_ADRS
1343 #define MAIL_ADRS "\"IN%%\"\"%s\"\"\""
1344 #endif
1345     StrAllocCopy(mail_adrs, MAIL_ADRS);
1346 #endif
1347 
1348 #ifdef LYNX_HOST_NAME
1349     StrAllocCopy(LYHostName, LYNX_HOST_NAME);
1350 #else
1351     StrAllocCopy(LYHostName, HTHostName());
1352 #endif /* LYNX_HOST_NAME */
1353 
1354     StrAllocCopy(LYLocalDomain, LOCAL_DOMAIN);
1355     StrAllocCopy(URLDomainPrefixes, URL_DOMAIN_PREFIXES);
1356     StrAllocCopy(URLDomainSuffixes, URL_DOMAIN_SUFFIXES);
1357     StrAllocCopy(XLoadImageCommand, XLOADIMAGE_COMMAND);
1358     StrAllocCopy(SSL_cert_file, SSL_CERT_FILE);
1359 
1360 #ifndef DISABLE_BIBP
1361     StrAllocCopy(BibP_globalserver, BIBP_GLOBAL_SERVER);
1362     StrAllocCopy(BibP_bibhost, "http://bibhost/");	/* protocol specified. */
1363 #endif
1364 
1365     /*
1366      * Disable news posting if the compilation-based LYNewsPosting value is
1367      * FALSE.  This may be changed further down via lynx.cfg or the
1368      * -restriction command line switch.  - FM
1369      */
1370 #ifndef DISABLE_NEWS
1371     no_newspost = (BOOL) (LYNewsPosting == FALSE);
1372 #endif
1373 
1374     for (i = 1; i < argc; i++) {
1375 	parse_arg(&argv[i], 2, &i);
1376     }
1377 
1378     /*
1379      * If we have a lone "-" switch for getting arguments from stdin, get them
1380      * NOW, and act on the relevant ones, saving the others into an HTList for
1381      * handling after the other initializations.  The primary purpose of this
1382      * feature is to allow for the potentially very long command line that can
1383      * be associated with post or get data.  The original implementation
1384      * required that the lone "-" be the only command line argument, but that
1385      * precluded its use when the lynx command is aliased with other arguments.
1386      * When interactive, the stdin input is terminated by by Control-D on Unix
1387      * or Control-Z on VMS, and each argument is terminated by a RETURN.  When
1388      * the argument is -get_data or -post_data, the data are terminated by a
1389      * "---" string, alone on the line (also terminated by RETURN).  - FM
1390      */
1391     for (i = 1; i < argc; i++) {
1392 	if (strcmp(argv[i], "-") == 0) {
1393 	    LYGetStdinArgs = TRUE;
1394 	    break;
1395 	}
1396     }
1397     if (LYGetStdinArgs == TRUE) {
1398 	char *buf = NULL;
1399 
1400 	CTRACE((tfp, "processing stdin arguments\n"));
1401 	while (GetStdin(&buf, TRUE)) {
1402 	    char *noargv[2];
1403 
1404 	    noargv[0] = buf;
1405 	    noargv[1] = NULL;
1406 	    LYTrimTrailing(buf);
1407 
1408 	    if (parse_arg(&noargv[0], 2, (int *) 0) == FALSE
1409 		&& buf[0] != '\0') {
1410 		char *argument = NULL;
1411 
1412 		if (LYStdinArgs == NULL) {
1413 		    LYStdinArgs = HTList_new();
1414 #ifdef LY_FIND_LEAKS
1415 		    atexit(LYStdinArgs_free);
1416 #endif
1417 		}
1418 		StrAllocCopy(argument, buf);
1419 		HTList_appendObject(LYStdinArgs, argument);
1420 		CTRACE((tfp, "...StdinArg:%s\n", argument));
1421 	    } else {
1422 		CTRACE((tfp, "...complete:%s\n", buf));
1423 	    }
1424 	}
1425 	CTRACE((tfp, "...done with stdin arguments\n"));
1426 	FREE(buf);
1427     }
1428 #ifdef SOCKS
1429     if (socks_flag)
1430 	SOCKSinit(argv[0]);
1431 #endif /* SOCKS */
1432 
1433     /*
1434      * If we had -validate set all of the restrictions and disallow a TRACE log
1435      * NOW.  - FM
1436      */
1437     if (LYValidate == TRUE) {
1438 	parse_restrictions("all");
1439 	LYUseTraceLog = FALSE;
1440     }
1441 
1442     /*
1443      * If we didn't get and act on a -validate or -anonymous switch, but can
1444      * verify that this is the anonymous account, set the default restrictions
1445      * for that account and disallow a TRACE log NOW.  - FM
1446      */
1447     if (!LYValidate && !LYRestricted &&
1448 	strlen(ANONYMOUS_USER) > 0 &&
1449 #if defined (VMS) || defined (NOUSERS)
1450 	!strcasecomp((LYGetEnv("USER") == NULL ? " " : LYGetEnv("USER")),
1451 		     ANONYMOUS_USER)
1452 #else
1453 #ifdef HAVE_CUSERID
1454 	STREQ((char *) cuserid((char *) NULL), ANONYMOUS_USER)
1455 #else
1456 	STREQ(((char *) getlogin() == NULL ? " " : getlogin()), ANONYMOUS_USER)
1457 #endif /* HAVE_CUSERID */
1458 #endif /* VMS */
1459 	) {
1460 	parse_restrictions("default");
1461 	LYRestricted = TRUE;
1462 	LYUseTraceLog = FALSE;
1463     }
1464 #ifdef USE_CMD_LOGGING
1465     /*
1466      * Open command-script, if specified
1467      */
1468     if (non_empty(lynx_cmd_script)) {
1469 	LYTildeExpand(&lynx_cmd_script, TRUE);
1470 	LYOpenCmdScript();
1471     }
1472     /*
1473      * Open command-logging, if specified
1474      */
1475     if (non_empty(lynx_cmd_logfile)) {
1476 	LYTildeExpand(&lynx_cmd_logfile, TRUE);
1477 	LYOpenCmdLogfile(argc, argv);
1478     }
1479 #endif
1480 
1481     /*
1482      * Set up the default jump file stuff.  - FM
1483      */
1484     StrAllocCopy(jumpprompt, JUMP_PROMPT);
1485 #ifdef JUMPFILE
1486     StrAllocCopy(jumpfile, JUMPFILE);
1487     {
1488 	temp = NULL;
1489 	HTSprintf0(&temp, "JUMPFILE:%s", jumpfile);
1490 	if (!LYJumpInit(temp)) {
1491 	    CTRACE((tfp, "Failed to register %s\n", temp));
1492 	}
1493 	FREE(temp);
1494     }
1495 #endif /* JUMPFILE */
1496 
1497     /*
1498      * If no alternate configuration file was specified on the command line,
1499      * see if it's in the environment.
1500      */
1501     if (isEmpty(lynx_cfg_file)) {
1502 	if (((cp = LYGetEnv("LYNX_CFG")) != NULL) ||
1503 	    (cp = LYGetEnv("lynx_cfg")) != NULL)
1504 	    StrAllocCopy(lynx_cfg_file, cp);
1505     }
1506 #ifdef USE_PROGRAM_DIR
1507     if (isEmpty(lynx_cfg_file)) {
1508 	HTSprintf0(&lynx_cfg_file, "%s\\lynx.cfg", program_dir);
1509 	if (!LYCanReadFile(lynx_cfg_file)) {
1510 	    FREE(lynx_cfg_file);
1511 	    lynx_cfg_file = NULL;
1512 	}
1513     }
1514 #endif
1515 
1516     /*
1517      * If we still don't have a configuration file, use the userdefs.h
1518      * definition.
1519      */
1520     if (isEmpty(lynx_cfg_file))
1521 	StrAllocCopy(lynx_cfg_file, LYNX_CFG_FILE);
1522 
1523 #ifndef _WINDOWS		/* avoid the whole ~ thing for now */
1524     LYTildeExpand(&lynx_cfg_file, FALSE);
1525 #endif
1526 
1527     /*
1528      * If the configuration file is not available, inform the user and exit.
1529      */
1530     if (!LYCanReadFile(lynx_cfg_file)) {
1531 	fprintf(stderr,
1532 		gettext("\nConfiguration file \"%s\" is not available.\n\n"),
1533 		lynx_cfg_file);
1534 	exit_immediately(EXIT_FAILURE);
1535     }
1536 
1537     /*
1538      * Make sure we have the character sets declared.  This will initialize the
1539      * CHARTRANS handling.  - KW
1540      */
1541     if (!LYCharSetsDeclared()) {
1542 	fprintf(stderr, gettext("\nLynx character sets not declared.\n\n"));
1543 	exit_immediately(EXIT_FAILURE);
1544     }
1545     /*
1546      * (**) in Lynx, UCLYhndl_HTFile_for_unspec and UCLYhndl_for_unrec may be
1547      * valid or not, but current_char_set and UCLYhndl_for_unspec SHOULD ALWAYS
1548      * be a valid charset.  Initialized here and may be changed later from
1549      * lynx.cfg/command_line/options_menu.  - LP (**)
1550      */
1551     /*
1552      * Set up the compilation default character set.  - FM
1553      */
1554 #ifdef CAN_AUTODETECT_DISPLAY_CHARSET
1555     if (auto_display_charset >= 0)
1556 	current_char_set = auto_display_charset;
1557     else
1558 #endif
1559 	current_char_set = safeUCGetLYhndl_byMIME(CHARACTER_SET);
1560     /*
1561      * Set up HTTP default for unlabeled charset (iso-8859-1).
1562      */
1563     UCLYhndl_for_unspec = LATIN1;
1564     StrAllocCopy(UCAssume_MIMEcharset,
1565 		 LYCharSet_UC[UCLYhndl_for_unspec].MIMEname);
1566 
1567 #ifdef USE_COLOR_TABLE
1568     /*
1569      * Set up default foreground and background colors.
1570      */
1571     lynx_setup_colors();
1572 #endif /* USE_COLOR_TABLE */
1573 
1574     /*
1575      * Set the original directory, used for default download
1576      */
1577     if (!strcmp(Current_Dir(filename), ".")) {
1578 	if ((cp = LYGetEnv("PWD")) != 0)
1579 	    StrAllocCopy(original_dir, cp);
1580     } else {
1581 	StrAllocCopy(original_dir, filename);
1582     }
1583 
1584     /*
1585      * Set the compilation default signature file.  - FM
1586      */
1587     LYStrNCpy(filename, LYNX_SIG_FILE, sizeof(filename) - 1);
1588     if (LYPathOffHomeOK(filename, sizeof(filename))) {
1589 	StrAllocCopy(LynxSigFile, filename);
1590 	LYAddPathToHome(filename, sizeof(filename), LynxSigFile);
1591 	StrAllocCopy(LynxSigFile, filename);
1592 	CTRACE((tfp, "LYNX_SIG_FILE set to '%s'\n", LynxSigFile));
1593     } else {
1594 	CTRACE((tfp, "LYNX_SIG_FILE '%s' is bad. Ignoring.\n", LYNX_SIG_FILE));
1595     }
1596 
1597 #ifdef USE_PRETTYSRC
1598     /*this is required for checking the tagspecs when parsing cfg file by
1599        LYReadCFG.c:parse_html_src_spec -HV */
1600     HTSwitchDTD(TRUE);
1601 #endif
1602     /*
1603      * Process the configuration file.
1604      */
1605     read_cfg(lynx_cfg_file, "main program", 1, (FILE *) 0);
1606 
1607     {
1608 	static char *client_keyfile = NULL;
1609 	static char *client_certfile = NULL;
1610 
1611 	if ((client_keyfile = LYGetEnv("SSL_CLIENT_KEY_FILE")) != NULL) {
1612 	    CTRACE((tfp,
1613 		    "HTGetSSLHandle: client keyfile is set to %s by SSL_CLIENT_KEY_FILE\n",
1614 		    client_keyfile));
1615 	    StrAllocCopy(SSL_client_key_file, client_keyfile);
1616 	}
1617 
1618 	if ((client_certfile = LYGetEnv("SSL_CLIENT_CERT_FILE")) != NULL) {
1619 	    CTRACE((tfp,
1620 		    "HTGetSSLHandle: client certfile is set to %s by SSL_CLIENT_CERT_FILE\n",
1621 		    client_certfile));
1622 	    StrAllocCopy(SSL_client_cert_file, client_certfile);
1623 	}
1624     }
1625 
1626 #if defined(USE_COLOR_STYLE)
1627     if (!dump_output_immediately) {
1628 	init_color_styles(&lynx_lss_file2, default_color_styles);
1629     }
1630 #endif /* USE_COLOR_STYLE */
1631 
1632     /*
1633      * Process the RC file.
1634      */
1635     read_rc(NULL);
1636 
1637 #ifdef USE_LOCALE_CHARSET
1638     LYFindLocaleCharset();
1639 #endif
1640 
1641     /*
1642      * Get WWW_HOME environment variable if it exists.
1643      */
1644     if ((cp = LYGetEnv("WWW_HOME")) != NULL) {
1645 	StrAllocCopy(startfile, cp);
1646 	LYEscapeStartfile(&startfile);
1647     }
1648 
1649     /*
1650      * Set the LynxHome URL.  If it's a file URL and the
1651      * host is defaulted, force in "//localhost", and if
1652      * it's not an absolute URL, make it one. - FM
1653      */
1654     StrAllocCopy(LynxHome, startfile);
1655     LYEnsureAbsoluteURL(&LynxHome, "LynxHome", FALSE);
1656 
1657     /*
1658      * Process any command line arguments not already handled.  - FM
1659      * May set startfile as a side-effect.
1660      */
1661     for (i = 1; i < argc; i++) {
1662 	parse_arg(&argv[i], 4, &i);
1663     }
1664 
1665     /*
1666      * Process any stdin-derived arguments for a lone "-" which we've loaded
1667      * into LYStdinArgs.  - FM
1668      */
1669     if (LYStdinArgs != NULL) {
1670 	char *my_args[2];
1671 	HTList *cur = LYStdinArgs;
1672 
1673 	my_args[1] = NULL;
1674 	while (NULL != (my_args[0] = (char *) HTList_nextObject(cur))) {
1675 	    parse_arg(my_args, 4, (int *) 0);
1676 	}
1677 	LYStdinArgs_free();
1678     }
1679 #ifdef HAVE_TTYNAME
1680     /*
1681      * If the input is not a tty, we are either running in cron, or are
1682      * getting input via a pipe:
1683      *
1684      * a) in cron, none of stdin/stdout/stderr are tty's.
1685      * b) from a pipe, we should have either "-" or "-stdin" options.
1686      */
1687     if (!LYGetStdinArgs
1688 	&& !startfile_stdin
1689 	&& !isatty(fileno(stdin))
1690 	&& (isatty(fileno(stdout) || isatty(fileno(stderr))))) {
1691 	int ignored = 0;
1692 
1693 	while (fgetc(stdin) != EOF) {
1694 	    ++ignored;
1695 	}
1696 	if (ignored) {
1697 	    fprintf(stderr,
1698 		    gettext("Ignored %d characters from standard input.\n"), ignored);
1699 	    fprintf(stderr,
1700 		    gettext("Use \"-stdin\" or \"-\" to tell how to handle piped input.\n"));
1701 	}
1702     }
1703 #endif /* HAVE_TTYNAME */
1704 
1705 #ifdef CAN_SWITCH_DISPLAY_CHARSET
1706     if (current_char_set == auto_display_charset)	/* Better: explicit option */
1707 	switch_display_charsets = 1;
1708 #endif
1709 
1710 #if defined (TTY_DEVICE) || defined(HAVE_TTYNAME)
1711     /*
1712      * If we are told to read the startfile from standard input, do it now,
1713      * after we have read all of the option data from standard input.
1714      * Later we'll use LYReopenInput().
1715      */
1716     if (startfile_stdin) {
1717 	char result[LY_MAXPATH];
1718 	char *buf = NULL;
1719 
1720 	CTRACE((tfp, "processing stdin startfile\n"));
1721 	if ((fp = LYOpenTemp(result, HTML_SUFFIX, "w")) != 0) {
1722 	    StrAllocCopy(startfile, result);
1723 	    while (GetStdin(&buf, FALSE)) {
1724 		fputs(buf, fp);
1725 		fputc('\n', fp);
1726 	    }
1727 	    FREE(buf);
1728 	    LYCloseTempFP(fp);
1729 	}
1730 	CTRACE((tfp, "...done stdin startfile\n"));
1731     }
1732 #endif
1733 
1734     /*
1735      * Initialize other things based on the configuration read.
1736      */
1737 
1738 #ifdef USE_PRETTYSRC
1739     if ((!Old_DTD) != TRUE)	/* skip if they are already initialized -HV */
1740 #endif
1741 	HTSwitchDTD(!Old_DTD);
1742 
1743     /*
1744      * Set up the proper character set with the desired
1745      * startup raw 8-bit or CJK mode handling.  - FM
1746      */
1747     HTMLUseCharacterSet(current_char_set);
1748 
1749 #ifdef USE_PERSISTENT_COOKIES
1750     /*
1751      * Sod it, this looks like a reasonable place to load the
1752      * cookies file, probably.  - RP
1753      *
1754      * And to set LYCookieSaveFile. - BJP
1755      */
1756     if (persistent_cookies) {
1757 	if (LYCookieFile == NULL) {
1758 	    LYCookieFile = typeMallocn(char, LY_MAXPATH);
1759 
1760 	    LYAddPathToHome(LYCookieFile, (size_t) LY_MAXPATH, FNAME_LYNX_COOKIES);
1761 	} else {
1762 	    LYTildeExpand(&LYCookieFile, FALSE);
1763 	}
1764 	LYLoadCookies(LYCookieFile);
1765     }
1766 
1767     /* tilde-expand LYCookieSaveFile */
1768     if (non_empty(LYCookieSaveFile)) {
1769 	LYTildeExpand(&LYCookieSaveFile, FALSE);
1770     }
1771 #ifdef USE_PROGRAM_DIR
1772     if (is_url(helpfile) == 0) {
1773 	char *tmp = NULL;
1774 
1775 	HTSprintf0(&tmp, "%s\\%s", program_dir, helpfile);
1776 	FREE(helpfile);
1777 	LYLocalFileToURL(&helpfile, tmp);
1778 	FREE(tmp);
1779     }
1780 #endif
1781 
1782     /*
1783      * In dump_output_immediately mode, LYCookieSaveFile defaults to
1784      * /dev/null, otherwise it defaults to LYCookieFile.
1785      */
1786 
1787     if (LYCookieSaveFile == NULL) {
1788 	if (dump_output_immediately) {
1789 	    StrAllocCopy(LYCookieSaveFile, "/dev/null");
1790 	} else {
1791 	    StrAllocCopy(LYCookieSaveFile, LYCookieFile);
1792 	}
1793     }
1794 #endif
1795 
1796     /*
1797      * Check for a help file URL in the environment. Overriding
1798      * compiled-in default and configuration file setting, if found.
1799      */
1800     if ((cp = LYGetEnv("LYNX_HELPFILE")) != NULL)
1801 	StrAllocCopy(helpfile, cp);
1802 
1803     /*
1804      * Set up our help and about file base paths. - FM
1805      */
1806     StrAllocCopy(helpfilepath, helpfile);
1807     if ((cp = LYPathLeaf(helpfilepath)) != helpfilepath)
1808 	*cp = '\0';
1809     LYAddHtmlSep(&helpfilepath);
1810 
1811     /*
1812      * Check for a save space path in the environment.  If one was set in the
1813      * configuration file, that one will be overridden.  - FM
1814      */
1815     if ((cp = LYGetEnv("LYNX_SAVE_SPACE")) != NULL)
1816 	StrAllocCopy(lynx_save_space, cp);
1817 
1818     /*
1819      * We have a save space path, make sure it's valid.  - FM
1820      */
1821     if (isEmpty(lynx_save_space)) {
1822 	FREE(lynx_save_space);
1823     }
1824     if (non_empty(lynx_save_space)) {
1825 	LYTildeExpand(&lynx_save_space, TRUE);
1826 #ifdef VMS
1827 	LYLowerCase(lynx_save_space);
1828 	if (StrChr(lynx_save_space, '/') != NULL) {
1829 	    if (strlen(lynx_save_space) == 1) {
1830 		StrAllocCopy(lynx_save_space, "sys$login:");
1831 	    } else {
1832 		LYAddPathSep(&lynx_save_space);
1833 		StrAllocCopy(temp, HTVMS_name("", lynx_save_space));
1834 		StrAllocCopy(lynx_save_space, temp);
1835 		FREE(temp);
1836 	    }
1837 	}
1838 	if (StrChr(lynx_save_space, ':') == NULL &&
1839 	    StrChr(lynx_save_space, ']') == NULL) {
1840 	    StrAllocCat(lynx_save_space, ":");
1841 	}
1842 #else
1843 	LYAddPathSep(&lynx_save_space);
1844 #endif /* VMS */
1845     }
1846 
1847     /*
1848      * Set up the file extension and mime type maps from src/HTInit.c and the
1849      * global and personal mime.types and mailcap files.  These will override
1850      * any SUFFIX or VIEWER maps in userdefs.h or the configuration file, if
1851      * they overlap.
1852      */
1853     HTFormatInit();
1854     if (!FileInitAlreadyDone)
1855 	HTFileInit();
1856 
1857     if (!LYCheckUserAgent()) {
1858 	HTAlwaysAlert(gettext("Warning:"), UA_NO_LYNX_WARNING);
1859     }
1860     if (show_cfg) {
1861 	cleanup();
1862 	exit_immediately(EXIT_SUCCESS);
1863     }
1864 #ifdef USE_SLANG
1865     if (LYShowColor >= SHOW_COLOR_ON &&
1866 	!(Lynx_Color_Flags & SL_LYNX_USE_COLOR)) {
1867 	Lynx_Color_Flags |= SL_LYNX_USE_COLOR;
1868     } else if ((Lynx_Color_Flags & SL_LYNX_USE_COLOR) ||
1869 	       LYGetEnv("COLORTERM") != NULL) {
1870 	if (LYShowColor != SHOW_COLOR_NEVER &&
1871 	    LYShowColor != SHOW_COLOR_ALWAYS) {
1872 	    LYShowColor = SHOW_COLOR_ON;
1873 	}
1874     }
1875 #endif /* USE_SLANG */
1876 
1877     if (LYPreparsedSource) {
1878 	HTPreparsedFormatInit();
1879     }
1880 #if defined(EXEC_LINKS) || defined(EXEC_SCRIPTS)
1881 #ifdef NEVER_ALLOW_REMOTE_EXEC
1882     if (local_exec) {
1883 	local_exec = FALSE;
1884 	local_exec_on_local_files = TRUE;
1885     }
1886 #endif /* NEVER_ALLOW_REMOTE_EXEC */
1887 #endif /* EXEC_LINKS || EXEC_SCRIPTS */
1888 
1889     if (emacs_keys)
1890 	set_emacs_keys();
1891 
1892     if (vi_keys)
1893 	set_vi_keys();
1894 
1895     if (no_numbers) {
1896 	number_links = FALSE;
1897 	number_fields = FALSE;
1898 	keypad_mode = NUMBERS_AS_ARROWS;
1899 	set_numbers_as_arrows();
1900     }
1901 
1902     if (crawl) {
1903 	/* No numbered links by default, as documented
1904 	   in CRAWL.announce. - kw */
1905 	if (!number_links) {
1906 	    keypad_mode = NUMBERS_AS_ARROWS;
1907 	}
1908     }
1909 
1910     if (!links_are_numbered()) {
1911 	if (number_fields)
1912 	    keypad_mode = LINKS_AND_FIELDS_ARE_NUMBERED;
1913 	if (number_links)
1914 	    keypad_mode = LINKS_ARE_NUMBERED;
1915 	set_numbers_as_arrows();
1916     }
1917 
1918     /*
1919      * Check the -popup command line toggle.  - FM
1920      */
1921     if (LYUseDefSelPop == FALSE) {
1922 	LYSelectPopups = (BOOLEAN) !LYSelectPopups;
1923     }
1924 
1925     /*
1926      * Check the -show_cursor command line toggle.  - FM
1927      */
1928     if (LYUseDefShoCur == FALSE) {
1929 	LYShowCursor = (BOOLEAN) !LYShowCursor;
1930     }
1931 
1932     /*
1933      * Check the -base command line switch with -source.  - FM
1934      */
1935     if (LYPrependBase && HTOutputFormat == HTAtom_for("www/download")) {
1936 	LYPrependBaseToSource = TRUE;
1937     }
1938 
1939     /*
1940      * Disable multiple bookmark support if not interactive, so it doesn't
1941      * crash on curses functions, or if the support was blocked via userdefs.h
1942      * and/or lynx.cfg, or via command line restrictions.  - FM
1943      */
1944     if (no_multibook)
1945 	LYMBMBlocked = TRUE;
1946     if (dump_output_immediately || LYMBMBlocked || no_multibook) {
1947 	LYMultiBookmarks = MBM_OFF;
1948 	LYMBMBlocked = TRUE;
1949 	no_multibook = TRUE;
1950     }
1951 #ifdef USE_SOURCE_CACHE
1952     /*
1953      * Disable source caching if not interactive.
1954      */
1955     if (dump_output_immediately)
1956 	LYCacheSource = SOURCE_CACHE_NONE;
1957 #endif
1958 #ifdef DISP_PARTIAL
1959     /*
1960      * Disable partial mode if not interactive.
1961      */
1962     if (dump_output_immediately)
1963 	display_partial_flag = FALSE;
1964 #endif
1965 
1966 #ifdef VMS
1967     set_vms_keys();
1968 #endif /* VMS */
1969 
1970 #if defined (__DJGPP__)
1971     if (watt_debug)
1972 	dbug_init();
1973     sock_init();
1974 
1975     __system_flags =
1976 	__system_emulate_chdir |	/* handle `cd' internally */
1977 	__system_handle_null_commands |		/* ignore cmds with no effect */
1978 	__system_allow_long_cmds |	/* handle commands > 126 chars   */
1979 	__system_use_shell |	/* use $SHELL if set */
1980 	__system_allow_multiple_cmds |	/* allow `cmd1; cmd2; ...' */
1981 	__system_redirect;	/* redirect internally */
1982 
1983     /* This speeds up stat() tremendously */
1984     _djstat_flags |= _STAT_INODE | _STAT_EXEC_MAGIC | _STAT_DIRSIZE;
1985 #endif /* __DJGPP__ */
1986 
1987     /* trap interrupts */
1988 #ifdef WIN32
1989     SetConsoleCtrlHandler((PHANDLER_ROUTINE) cleanup_win32, TRUE);
1990 #endif
1991 
1992 #ifndef NOSIGHUP
1993     if (!dump_output_immediately)
1994 	(void) signal(SIGHUP, cleanup_sig);
1995 #endif /* NOSIGHUP */
1996 
1997     (void) signal(SIGTERM, cleanup_sig);
1998 #ifdef SIGWINCH
1999     LYExtSignal(SIGWINCH, size_change);
2000 #endif /* SIGWINCH */
2001 #ifndef VMS
2002     if (!TRACE && !dump_output_immediately && !stack_dump) {
2003 	(void) signal(SIGINT, cleanup_sig);
2004 #ifndef __linux__
2005 #ifdef SIGBUS
2006 	(void) signal(SIGBUS, FatalProblem);
2007 #endif /* SIGBUS */
2008 #endif /* !__linux__ */
2009 	(void) signal(SIGSEGV, FatalProblem);
2010 	(void) signal(SIGILL, FatalProblem);
2011 	/*
2012 	 * Since we're doing lots of TCP, just ignore SIGPIPE altogether.
2013 	 *
2014 	 * HTTCP.c should deal with a broken pipe for servers.  Rick Mallet's
2015 	 * check after c = GetChar() in LYStrings.c should deal with a
2016 	 * disconnected terminal.  So the runaway CPU time problem on Unix
2017 	 * should not occur any more.
2018 	 */
2019 #ifdef SIGPIPE
2020 	if (signal(SIGPIPE, SIG_IGN) != SIG_IGN)
2021 	    restore_sigpipe_for_children = TRUE;
2022 #endif /* SIGPIPE */
2023     }
2024 #endif /* !VMS */
2025 
2026 #ifdef SIGTSTP
2027     /*
2028      * Block Control-Z suspending if requested.  - FM
2029      */
2030     if (no_suspend)
2031 	(void) signal(SIGTSTP, SIG_IGN);
2032 #endif /* SIGTSTP */
2033 
2034     /*
2035      * Check for a valid HEAD request.  - FM
2036      */
2037     if (HEAD_request && LYCanDoHEAD(startfile) != TRUE) {
2038 	fprintf(stderr,
2039 		"The '-head' switch is for http HEAD requests and cannot be used for\n'%s'.\n",
2040 		startfile);
2041 	exit_immediately(EXIT_FAILURE);
2042     }
2043 
2044     /*
2045      * Check for a valid MIME headers request.  - FM
2046      */
2047     if (keep_mime_headers && LYCanDoHEAD(startfile) != TRUE) {
2048 	fprintf(stderr,
2049 		"The '-mime_header' switch is for http URLs and cannot be used for\n'%s'.\n",
2050 		startfile);
2051 	exit_immediately(EXIT_FAILURE);
2052     }
2053 
2054     /*
2055      * Check for a valid traversal request.  - FM
2056      */
2057     if (traversal && StrNCmp(startfile, "http", 4)) {
2058 	fprintf(stderr,
2059 		"The '-traversal' switch is for http URLs and cannot be used for\n'%s'.\n",
2060 		startfile);
2061 	exit_immediately(EXIT_FAILURE);
2062     }
2063 
2064     /*
2065      * Finish setting up for an INTERACTIVE session.  Done here so that URL
2066      * guessing in LYEnsureAbsoluteURL() can be interruptible (terminal is in
2067      * raw mode, select() works).  -BL
2068      */
2069 #ifdef USE_PRETTYSRC
2070     if (!dump_output_immediately) {
2071 	HTMLSRC_init_caches(FALSE);	/* do it before terminal is initialized */
2072     }
2073 #ifdef LY_FIND_LEAKS
2074     atexit(html_src_clean_data);
2075 #endif
2076 #endif
2077 
2078     if (!dump_output_immediately) {
2079 	setup(terminal);
2080     }
2081     /*
2082      * If startfile is a file URL and the host is defaulted, force in
2083      * "//localhost", and if it's not an absolute URL, make it one.  - FM
2084      */
2085     LYEnsureAbsoluteURL(&startfile, "STARTFILE", FALSE);
2086 
2087     /*
2088      * If homepage was specified and is a file URL with the host defaulted,
2089      * force in "//localhost", and if it's not an absolute URL, make it one.  -
2090      * FM
2091      */
2092     if (non_empty(homepage)) {
2093 	LYEnsureAbsoluteURL(&homepage, "HOMEPAGE", FALSE);
2094     }
2095 
2096     /*
2097      * If we don't have a homepage specified, set it to startfile.  Otherwise,
2098      * reset LynxHome.  - FM
2099      */
2100     if (isEmpty(homepage)) {
2101 	StrAllocCopy(homepage, startfile);
2102     } else {
2103 	StrAllocCopy(LynxHome, homepage);
2104     }
2105 
2106     /*
2107      * Set up the inside/outside domain restriction flags.  - FM
2108      */
2109     if (inlocaldomain()) {
2110 #if !defined(HAVE_UTMP) || defined(VMS)		/* not selective */
2111 	telnet_ok = (BOOL) (!no_inside_telnet && !no_outside_telnet && telnet_ok);
2112 #ifndef DISABLE_NEWS
2113 	news_ok = (BOOL) (!no_inside_news && !no_outside_news && news_ok);
2114 #endif
2115 	ftp_ok = (BOOL) (!no_inside_ftp && !no_outside_ftp && ftp_ok);
2116 	rlogin_ok = (BOOL) (!no_inside_rlogin && !no_outside_rlogin && rlogin_ok);
2117 #else
2118 	CTRACE((tfp, "LYMain: User in Local domain\n"));
2119 	telnet_ok = (BOOL) (!no_inside_telnet && telnet_ok);
2120 #ifndef DISABLE_NEWS
2121 	news_ok = (BOOL) (!no_inside_news && news_ok);
2122 #endif
2123 	ftp_ok = (BOOL) (!no_inside_ftp && ftp_ok);
2124 	rlogin_ok = (BOOL) (!no_inside_rlogin && rlogin_ok);
2125 #endif /* !HAVE_UTMP || VMS */
2126     } else {
2127 	CTRACE((tfp, "LYMain: User in REMOTE domain\n"));
2128 	telnet_ok = (BOOL) (!no_outside_telnet && telnet_ok);
2129 #ifndef DISABLE_NEWS
2130 	news_ok = (BOOL) (!no_outside_news && news_ok);
2131 #endif
2132 	ftp_ok = (BOOL) (!no_outside_ftp && ftp_ok);
2133 	rlogin_ok = (BOOL) (!no_outside_rlogin && rlogin_ok);
2134     }
2135 #ifdef DISABLE_FTP
2136     ftp_ok = FALSE;
2137 #else
2138     /* predefine some known broken ftp servers */
2139     LYSetConfigValue(RC_BROKEN_FTP_RETR, "ProFTPD 1.2.5");
2140     LYSetConfigValue(RC_BROKEN_FTP_RETR, "spftp/");
2141     LYSetConfigValue(RC_BROKEN_FTP_EPSV, "(Version wu-2.6.2-12)");
2142 #endif
2143 
2144     /*
2145      * Make sure our bookmark default strings are all allocated and
2146      * synchronized.  - FM
2147      */
2148     if (isEmpty(bookmark_page)) {
2149 	temp = NULL;
2150 	HTSprintf0(&temp, "lynx_bookmarks%s", HTML_SUFFIX);
2151 	set_default_bookmark_page(temp);
2152 	FREE(temp);
2153     }
2154     if (isEmpty(BookmarkPage)) {
2155 	set_default_bookmark_page(bookmark_page);
2156     }
2157 #if defined(SYSLOG_REQUESTED_URLS)
2158     LYOpenlog(syslog_txt);
2159 #endif
2160 
2161     if (non_empty(x_display)) {
2162 	LYisConfiguredForX = TRUE;
2163     }
2164 
2165     /*
2166      * Here's where we do all the work.
2167      */
2168     if (dump_output_immediately) {
2169 	/*
2170 	 * Finish setting up and start a NON-INTERACTIVE session.  - FM
2171 	 */
2172 	if (crawl && !number_links && !number_fields) {
2173 	    keypad_mode = NUMBERS_AS_ARROWS;
2174 	} else if (no_numbers) {
2175 	    keypad_mode = NUMBERS_AS_ARROWS;
2176 	} else if (!no_list) {
2177 	    if (!links_are_numbered()) {
2178 		if (number_fields)
2179 		    keypad_mode = LINKS_AND_FIELDS_ARE_NUMBERED;
2180 		else
2181 		    keypad_mode = LINKS_ARE_NUMBERED;
2182 	    }
2183 	}
2184 	if (dump_output_width > 0) {
2185 	    LYcols = dump_output_width;
2186 	}
2187 	/*
2188 	 * Normal argument processing puts non-options (URLs) into the Goto
2189 	 * history.  Use this to dump all of the pages listed on the command
2190 	 * line, or (if none are listed) via the startfile mechanism.
2191 	 * history.
2192 	 */
2193 #ifdef EXTENDED_STARTFILE_RECALL
2194 	HTAddGotoURL(startfile);
2195 	for (i = HTList_count(Goto_URLs) - 1; i >= 0; --i) {
2196 	    StrAllocCopy(startfile, (char *) HTList_objectAt(Goto_URLs, i));
2197 	    CTRACE((tfp, "dumping %d:%d %s\n",
2198 		    i + 1, HTList_count(Goto_URLs), startfile));
2199 	    status = mainloop();
2200 	    if (!no_list &&
2201 		!dump_links_inline &&
2202 		!crawl)		/* For -crawl it has already been done! */
2203 		printlist(stdout, FALSE);
2204 	    if (i != 0)
2205 		printf("\n");
2206 	}
2207 #else
2208 	status = mainloop();
2209 	if (!no_list &&
2210 	    !dump_links_inline &&
2211 	    !crawl &&		/* For -crawl it has already been done! */
2212 	    links_are_numbered())
2213 	    printlist(stdout, FALSE);
2214 #endif
2215 #ifdef USE_PERSISTENT_COOKIES
2216 	/*
2217 	 * We want to save cookies picked up when in immediate dump mode.
2218 	 * Instead of calling cleanup() here, let's only call this one.  - BJP
2219 	 */
2220 	if (persistent_cookies)
2221 	    LYStoreCookies(LYCookieSaveFile);
2222 #endif /* USE_PERSISTENT_COOKIES */
2223 	exit_immediately(status);
2224     } else {
2225 	/*
2226 	 * Start an INTERACTIVE session.  - FM
2227 	 */
2228 #ifdef USE_COLOR_STYLE
2229 	cache_tag_styles();
2230 #endif
2231 
2232 #ifndef NO_DUMP_WITH_BACKSPACES
2233 	if (with_backspaces) {
2234 	    /* we should warn about this somehow (nop for now) -VH */
2235 	    with_backspaces = FALSE;
2236 	}
2237 #endif
2238 
2239 #ifndef ALL_CHARSETS_IN_O_MENU_SCREEN
2240 	init_charset_subsets();
2241 #endif
2242 
2243 	ena_csi((BOOLEAN) (LYlowest_eightbit[current_char_set] > 155));
2244 #ifdef USE_SESSIONS
2245 	RestoreSession();
2246 #endif /* USE_SESSIONS */
2247 	status = mainloop();
2248 	LYCloseCloset(RECALL_URL);
2249 	LYCloseCloset(RECALL_MAIL);
2250 #if defined(PDCURSES) && defined(PDC_BUILD) && PDC_BUILD >= 2401
2251 	if (!isendwin()) {
2252 	    if ((saved_scrsize_x != 0) && (saved_scrsize_y != 0)) {
2253 		resize_term(saved_scrsize_y, saved_scrsize_x);
2254 	    }
2255 	}
2256 #endif
2257 	cleanup();
2258 	exit_immediately(status);
2259     }
2260 
2261     return (status);		/* though redundant, for compiler-warnings */
2262 }
2263 
2264 /*
2265  * Called by HTAccessInit to register any protocols supported by lynx.
2266  * Protocols added by lynx:
2267  *    LYNXKEYMAP, lynxcgi, LYNXIMGMAP, LYNXCOOKIE, LYNXCACHE, LYNXMESSAGES
2268  */
2269 #ifdef GLOBALREF_IS_MACRO
2270 extern GLOBALREF (HTProtocol, LYLynxEditmap);
2271 extern GLOBALREF (HTProtocol, LYLynxKeymap);
2272 extern GLOBALREF (HTProtocol, LYLynxCGI);
2273 extern GLOBALREF (HTProtocol, LYLynxIMGmap);
2274 extern GLOBALREF (HTProtocol, LYLynxCookies);
2275 
2276 #ifdef USE_CACHEJAR
2277 extern GLOBALREF (HTProtocol, LYLynxCache);
2278 #endif
2279 extern GLOBALREF (HTProtocol, LYLynxStatusMessages);
2280 
2281 #else
2282 GLOBALREF HTProtocol LYLynxEditmap;
2283 GLOBALREF HTProtocol LYLynxKeymap;
2284 GLOBALREF HTProtocol LYLynxCGI;
2285 GLOBALREF HTProtocol LYLynxIMGmap;
2286 GLOBALREF HTProtocol LYLynxCookies;
2287 
2288 #ifdef USE_CACHEJAR
2289 GLOBALREF HTProtocol LYLynxCache;
2290 #endif
2291 GLOBALREF HTProtocol LYLynxStatusMessages;
2292 #endif /* GLOBALREF_IS_MACRO */
2293 
LYRegisterLynxProtocols(void)2294 void LYRegisterLynxProtocols(void)
2295 {
2296     HTRegisterProtocol(&LYLynxEditmap);
2297     HTRegisterProtocol(&LYLynxKeymap);
2298     HTRegisterProtocol(&LYLynxCGI);
2299     HTRegisterProtocol(&LYLynxIMGmap);
2300     HTRegisterProtocol(&LYLynxCookies);
2301 #ifdef USE_CACHEJAR
2302     HTRegisterProtocol(&LYLynxCache);
2303 #endif
2304     HTRegisterProtocol(&LYLynxStatusMessages);
2305 }
2306 
2307 #ifndef NO_CONFIG_INFO
2308 /*
2309  * Some stuff to reload lynx.cfg without restarting new lynx session, also load
2310  * options menu items and command-line options to make things consistent.
2311  *
2312  * Called by user of interactive session by LYNXCFG://reload/ link.
2313  *
2314  * Warning:  experimental, more main() reorganization required.
2315  *	*Known* exceptions: persistent cookies, cookie files.
2316  *
2317  *	Some aspects of COLOR (with slang?).
2318  *	Viewer stuff, mailcap files
2319  *	SUFFIX, mime.types files
2320  *	RULESFILE/RULE
2321  *
2322  *	All work "somewhat", but not exactly as the first time.
2323  */
reload_read_cfg(void)2324 void reload_read_cfg(void)
2325 {
2326     char *tempfile;
2327     FILE *rcfp;
2328 
2329     /*
2330      * no_option_save is always set for -anonymous and -validate.  It is better
2331      * to check for one or several specific restriction flags than for
2332      * 'LYRestricted', which doesn't get set for individual restrictions or for
2333      * -validate!  However, no_option_save may not be the appropriate one to
2334      * check - in that case, a new no_something should be added that gets
2335      * automatically set for -anonymous and -validate (and whether it applies
2336      * for -anonymous can be made installer- configurable in the usual way at
2337      * the bottom of userdefs.h).  - kw
2338      *
2339      */
2340     if (no_option_save) {
2341 	/* current logic requires(?) that saving user preferences is
2342 	   possible.  Additional applicable restrictions are already
2343 	   checked by caller. - kw */
2344 	return;
2345     }
2346 
2347     /*
2348      * Current user preferences are saved in a temporary file, to be read in
2349      * again after lynx.cfg has been read.  This avoids accidental changing of
2350      * the preferences file.  The regular preferences file doesn't even need to
2351      * exist, and won't be created as a side effect of this function.  Honoring
2352      * the no_option_save restriction may thus be unnecessarily restrictive,
2353      * but the check is currently still left in place.  - kw
2354      */
2355     tempfile = typecallocn(char, LY_MAXPATH);
2356     if (!tempfile) {
2357 	HTAlwaysAlert(NULL, NOT_ENOUGH_MEMORY);
2358 	return;
2359     }
2360     rcfp = LYOpenTemp(tempfile, ".rc", "w");
2361     if (rcfp == NULL) {
2362 	FREE(tempfile);
2363 	HTAlwaysAlert(NULL, CANNOT_OPEN_TEMP);
2364 	return;
2365     }
2366     if (!save_rc(rcfp)) {
2367 	HTAlwaysAlert(NULL, OPTIONS_NOT_SAVED);
2368 	(void) LYRemoveTemp(tempfile);
2369 	FREE(tempfile);
2370 	return;			/* can not write the very own file :( */
2371     }
2372 #ifdef USE_PERSISTENT_COOKIES
2373     if (LYCookieFile != NULL && LYCookieSaveFile != NULL) {
2374 	/* set few safe flags: */
2375 	BOOLEAN persistent_cookies_flag = persistent_cookies;
2376 	char *LYCookieFile_flag = NULL;
2377 	char *LYCookieSaveFile_flag = NULL;
2378 
2379 	if (persistent_cookies) {
2380 	    StrAllocCopy(LYCookieFile_flag, LYCookieFile);
2381 	    StrAllocCopy(LYCookieSaveFile_flag, LYCookieSaveFile);
2382 	}
2383 #ifdef USE_CHARSET_CHOICE
2384 	custom_assumed_doc_charset = FALSE;
2385 	custom_display_charset = FALSE;
2386 	memset((char *) charset_subsets, 0, sizeof(charset_subset_t) * MAXCHARSETS);
2387 #endif
2388 
2389 #ifdef USE_PRETTYSRC
2390 	html_src_on_lynxcfg_reload();
2391 #endif
2392 	/* free downloaders, printers, environments, dired menu */
2393 	free_lynx_cfg();
2394 #ifdef USE_SOURCE_CACHE
2395 	source_cache_file_error = FALSE;	/* reset flag */
2396 #endif
2397 
2398 	/*
2399 	 * Process the configuration file.
2400 	 */
2401 	read_cfg(lynx_cfg_file, "main program", 1, (FILE *) 0);
2402 
2403 	/*
2404 	 * Process the temporary RC file.
2405 	 */
2406 	rcfp = fopen(tempfile, "r");
2407 	read_rc(rcfp);
2408 	(void) LYRemoveTemp(tempfile);
2409 	FREE(tempfile);		/* done with it - kw */
2410 
2411 #ifdef USE_CHARSET_CHOICE
2412 	init_charset_subsets();
2413 #endif
2414 
2415 	/*
2416 	 * Initialize other things based on the configuration read.
2417 	 */
2418 	LYSetDisplayLines();
2419 	/* Not implemented yet here,
2420 	 * a major problem: file paths
2421 	 * like lynx_save_space, LYCookieFile etc.
2422 	 */
2423 	/* restore old settings */
2424 	if (persistent_cookies != persistent_cookies_flag) {
2425 	    persistent_cookies = persistent_cookies_flag;
2426 	    HTAlert(gettext("persistent cookies state will be changed in next session only."));
2427 	}
2428 	if (persistent_cookies && LYCookieFile_flag != NULL) {
2429 	    if (strcmp(LYCookieFile, LYCookieFile_flag)) {
2430 		StrAllocCopy(LYCookieFile, LYCookieFile_flag);
2431 		CTRACE((tfp,
2432 			"cookie file can be changed in next session only, restored.\n"));
2433 	    }
2434 	    if (strcmp(LYCookieSaveFile, LYCookieSaveFile_flag)) {
2435 		StrAllocCopy(LYCookieSaveFile, LYCookieSaveFile_flag);
2436 		CTRACE((tfp,
2437 			"cookie save file can be changed in next session only, restored.\n"));
2438 	    }
2439 	    FREE(LYCookieFile_flag);
2440 	    FREE(LYCookieSaveFile_flag);
2441 	}
2442     }
2443 #endif /* USE_PERSISTENT_COOKIES */
2444 }
2445 #endif /* !NO_CONFIG_INFO */
2446 
force_dump_mode(void)2447 static void force_dump_mode(void)
2448 {
2449     dump_output_immediately = TRUE;
2450     no_pause = TRUE;
2451     LYcols = DFT_COLS;
2452 }
2453 
2454 /* There are different ways of setting arguments on the command line, and
2455  * there are different types of arguments.  These include:
2456  *
2457  *   -set_some_variable		 ==> some_variable  = TRUE
2458  *   -toggle_some_variable	 ==> some_variable = !some_variable
2459  *   -some_variable=value	 ==> some_variable = value
2460  *
2461  * Others are complicated and require a function call.
2462  */
2463 
2464 #define PARSE_SET(n,t,v,h) {n,    t, UNION_SET(v), h}
2465 #define PARSE_INT(n,t,v,h) {n,    t, UNION_INT(v), h}
2466 #define PARSE_STR(n,t,v,h) {n,    t, UNION_STR(v), h}
2467 #define PARSE_FUN(n,t,v,h) {n,    t, UNION_FUN(v), h}
2468 #define PARSE_NIL          {NULL, 0, UNION_DEF(0), NULL}
2469 
2470 typedef struct parse_args_type {
2471     const char *name;
2472     int type;
2473 
2474 #define TOGGLE_ARG		0x0010
2475 #define SET_ARG			0x0020
2476 #define UNSET_ARG		0x0030
2477 #define FUNCTION_ARG		0x0040
2478 #define LYSTRING_ARG		0x0050
2479 #define INT_ARG			0x0060
2480 #define STRING_ARG		0x0070
2481 #define TIME_ARG		0x0080
2482 #define ARG_TYPE_MASK		0x0FF0
2483 #define NEED_NEXT_ARG		0x1000
2484 
2485 #define NEED_INT_ARG		(NEED_NEXT_ARG | INT_ARG)
2486 #define NEED_TIME_ARG		(NEED_NEXT_ARG | TIME_ARG)
2487 #define NEED_LYSTRING_ARG	(NEED_NEXT_ARG | LYSTRING_ARG)
2488 #define NEED_STRING_ARG		(NEED_NEXT_ARG | STRING_ARG)
2489 #define NEED_FUNCTION_ARG	(NEED_NEXT_ARG | FUNCTION_ARG)
2490 
2491     /* If the NEED_NEXT_ARG flags is set, and the option was not specified
2492      * with an '=' character, then use the next argument in the argv list.
2493      */
2494 
2495       ParseData;
2496     const char *help_string;
2497 } Config_Type;
2498 
2499 /* -auth, -pauth */
parse_authentication(char * next_arg,char ** result)2500 static int parse_authentication(char *next_arg,
2501 				char **result)
2502 {
2503     /*
2504      * Authentication information for protected documents.
2505      */
2506     char *auth_info = NULL;
2507 
2508     if (next_arg != NULL) {
2509 	StrAllocCopy(auth_info, next_arg);
2510 	memset(next_arg, ' ', strlen(next_arg));	/* Let's not show too much */
2511     }
2512 
2513     if (auth_info != NULL) {
2514 	char *cp;
2515 
2516 	if ((cp = StrChr(auth_info, ':')) != NULL) {	/* Pw */
2517 	    *cp++ = '\0';	/* Terminate ID */
2518 	    HTUnEscape(cp);
2519 	    StrAllocCopy(result[1], cp);
2520 	}
2521 	if (*auth_info) {	/* Id */
2522 	    HTUnEscape(auth_info);
2523 	    StrAllocCopy(result[0], auth_info);
2524 	}
2525 	FREE(auth_info);
2526     }
2527     return 0;
2528 }
2529 
2530 /* -anonymous */
anonymous_fun(char * next_arg GCC_UNUSED)2531 static int anonymous_fun(char *next_arg GCC_UNUSED)
2532 {
2533     if (!LYValidate && !LYRestricted)
2534 	parse_restrictions("default");
2535     LYRestricted = TRUE;
2536     return 0;
2537 }
2538 
2539 /* -assume_charset */
assume_charset_fun(char * next_arg)2540 static int assume_charset_fun(char *next_arg)
2541 {
2542     assumed_charset = TRUE;
2543     UCLYhndl_for_unspec = safeUCGetLYhndl_byMIME(next_arg);
2544     StrAllocCopy(UCAssume_MIMEcharset,
2545 		 LYCharSet_UC[UCLYhndl_for_unspec].MIMEname);
2546     CTRACE((tfp, "assume_charset_fun %s ->%d ->%s\n",
2547 	    NonNull(next_arg),
2548 	    UCLYhndl_for_unspec,
2549 	    UCAssume_MIMEcharset));
2550     return 0;
2551 }
2552 
2553 /* -assume_local_charset */
assume_local_charset_fun(char * next_arg)2554 static int assume_local_charset_fun(char *next_arg)
2555 {
2556     UCLYhndl_HTFile_for_unspec = safeUCGetLYhndl_byMIME(next_arg);
2557     return 0;
2558 }
2559 
2560 /* -assume_unrec_charset */
assume_unrec_charset_fun(char * next_arg)2561 static int assume_unrec_charset_fun(char *next_arg)
2562 {
2563     UCLYhndl_for_unrec = safeUCGetLYhndl_byMIME(next_arg);
2564     return 0;
2565 }
2566 
2567 /* -auth */
auth_fun(char * next_arg)2568 static int auth_fun(char *next_arg)
2569 {
2570     parse_authentication(next_arg, authentication_info);
2571     return 0;
2572 }
2573 
2574 /* -base */
base_fun(char * next_arg GCC_UNUSED)2575 static int base_fun(char *next_arg GCC_UNUSED)
2576 {
2577     /*
2578      * Treat -source equivalently to an interactive download with
2579      * LYPrefixBaseToSource configured to TRUE, so that a BASE tag is prepended
2580      * for text/html content types.  We normally treat the module-wide global
2581      * LYPrefixBaseToSource flag as FALSE with -source, but force it TRUE,
2582      * later, if LYPrependBase is set TRUE here.  - FM
2583      */
2584     LYPrependBase = TRUE;
2585     if (HTOutputFormat == HTAtom_for("www/dump"))
2586 	HTOutputFormat = HTAtom_for("www/download");
2587 
2588     return 0;
2589 }
2590 
2591 /* -cache */
cache_fun(char * next_arg)2592 static int cache_fun(char *next_arg)
2593 {
2594     if (next_arg != 0)
2595 	HTCacheSize = atoi(next_arg);
2596     /*
2597      * Limit size.
2598      */
2599     if (HTCacheSize < 2)
2600 	HTCacheSize = 2;
2601 
2602     return 0;
2603 }
2604 
2605 /* -child */
child_fun(char * next_arg GCC_UNUSED)2606 static int child_fun(char *next_arg GCC_UNUSED)
2607 {
2608     child_lynx = TRUE;
2609     no_disk_save = TRUE;
2610     no_mail = TRUE;
2611     return 0;
2612 }
2613 
2614 /* -child_relaxed */
child_relaxed_fun(char * next_arg GCC_UNUSED)2615 static int child_relaxed_fun(char *next_arg GCC_UNUSED)
2616 {
2617     child_lynx = TRUE;
2618     return 0;
2619 }
2620 
2621 #ifdef USE_SLANG
2622 /* -color */
color_fun(char * next_arg GCC_UNUSED)2623 static int color_fun(char *next_arg GCC_UNUSED)
2624 {
2625     Lynx_Color_Flags |= SL_LYNX_USE_COLOR;
2626 
2627     if (LYShowColor != SHOW_COLOR_ALWAYS)
2628 	LYShowColor = SHOW_COLOR_ON;
2629 
2630     return 0;
2631 }
2632 #endif
2633 
2634 /* -convert_to */
convert_to_fun(char * next_arg)2635 static int convert_to_fun(char *next_arg)
2636 {
2637     if (next_arg != 0) {
2638 	char *outformat = NULL;
2639 	char *cp1, *cp2, *cp4;
2640 	int chndl;
2641 
2642 	StrAllocCopy(outformat, next_arg);
2643 	/* not lowercased, to allow for experimentation - kw */
2644 	/*LYLowerCase(outformat); */
2645 	if ((cp1 = StrChr(outformat, ';')) != NULL) {
2646 	    if ((cp2 = LYstrstr(cp1, "charset")) != NULL) {
2647 		cp2 += 7;
2648 		while (*cp2 == ' ' || *cp2 == '=' || *cp2 == '"')
2649 		    cp2++;
2650 		for (cp4 = cp2; (*cp4 != '\0' && *cp4 != '"' &&
2651 				 *cp4 != ';' &&
2652 				 !WHITE(*cp4)); cp4++) ;	/* do nothing */
2653 		*cp4 = '\0';
2654 		/* This is intentionally not the "safe" version,
2655 		   to allow for experimentation. */
2656 		chndl = UCGetLYhndl_byMIME(cp2);
2657 		if (chndl < 0)
2658 		    chndl = UCLYhndl_for_unrec;
2659 		if (chndl < 0) {
2660 		    fprintf(stderr,
2661 			    gettext("Lynx: ignoring unrecognized charset=%s\n"), cp2);
2662 		} else {
2663 		    current_char_set = chndl;
2664 		}
2665 		*cp1 = '\0';	/* truncate outformat */
2666 	    }
2667 	}
2668 	HTOutputFormat = HTAtom_for(outformat);
2669 	FREE(outformat);
2670     } else {
2671 	HTOutputFormat = NULL;
2672     }
2673     return 0;
2674 }
2675 
2676 /* -crawl */
crawl_fun(char * next_arg GCC_UNUSED)2677 static int crawl_fun(char *next_arg GCC_UNUSED)
2678 {
2679     crawl = TRUE;
2680     LYcols = DFT_COLS;
2681     return 0;
2682 }
2683 
2684 /* -display */
display_fun(char * next_arg)2685 static int display_fun(char *next_arg)
2686 {
2687     if (next_arg != 0) {
2688 	LYsetXDisplay(next_arg);
2689     }
2690 
2691     return 0;
2692 }
2693 
2694 /* -display_charset */
display_charset_fun(char * next_arg)2695 static int display_charset_fun(char *next_arg)
2696 {
2697     int i = UCGetLYhndl_byMIME(next_arg);
2698 
2699 #ifdef CAN_AUTODETECT_DISPLAY_CHARSET
2700     if (i < 0 && !strcasecomp(next_arg, "auto"))
2701 	i = auto_display_charset;
2702 #endif
2703     if (i < 0) {		/* do nothing here: so fallback to lynx.cfg */
2704 	fprintf(stderr,
2705 		gettext("Lynx: ignoring unrecognized charset=%s\n"), next_arg);
2706     } else
2707 	current_char_set = i;
2708     return 0;
2709 }
2710 
2711 /* -dump */
dump_output_fun(char * next_arg GCC_UNUSED)2712 static int dump_output_fun(char *next_arg GCC_UNUSED)
2713 {
2714     force_dump_mode();
2715     return 0;
2716 }
2717 
2718 /* -editor */
editor_fun(char * next_arg)2719 static int editor_fun(char *next_arg)
2720 {
2721     if (next_arg != 0)
2722 	StrAllocCopy(editor, next_arg);
2723     system_editor = TRUE;
2724     return 0;
2725 }
2726 
2727 /* -error_file */
error_file_fun(char * next_arg)2728 static int error_file_fun(char *next_arg)
2729 {
2730     /*
2731      * Output return (success/failure) code of an HTTP transaction.
2732      */
2733     if (next_arg != 0)
2734 	http_error_file = next_arg;
2735     return 0;
2736 }
2737 
2738 #if defined(EXEC_LINKS) || defined(EXEC_SCRIPTS)
2739 /* -exec */
exec_fun(char * next_arg GCC_UNUSED)2740 static int exec_fun(char *next_arg GCC_UNUSED)
2741 {
2742 #ifndef NEVER_ALLOW_REMOTE_EXEC
2743     local_exec = TRUE;
2744 #else
2745     local_exec_on_local_files = TRUE;
2746 #endif /* NEVER_ALLOW_REMOTE_EXEC */
2747     return 0;
2748 }
2749 #endif
2750 
2751 /* -get_data */
get_data_fun(char * next_arg GCC_UNUSED)2752 static int get_data_fun(char *next_arg GCC_UNUSED)
2753 {
2754     /*
2755      * User data for GET form.
2756      */
2757     char **get_data;
2758     char *buf = NULL;
2759 
2760     /*
2761      * On Unix, conflicts with curses when interactive so let's force a dump.
2762      * -CL
2763      *
2764      * On VMS, mods have been made in LYCurses.c to deal with potential
2765      * conflicts, so don't force the dump here.  - FM
2766      */
2767 #ifndef VMS
2768     force_dump_mode();
2769 #endif /* VMS */
2770 
2771     StrAllocCopy(form_get_data, "?");	/* Prime the pump */
2772     get_data = &form_get_data;
2773 
2774     /*
2775      * Build GET data for later.  Stop reading when we see a line with "---" as
2776      * its first three characters.
2777      */
2778     while (GetStdin(&buf, TRUE)) {
2779 	StrAllocCat(*get_data, buf);
2780     }
2781 
2782     CTRACE((tfp, "get_data:%s\n", *get_data));
2783     CTRACE((tfp, "get_data:%s\n", form_get_data));
2784     return 0;
2785 }
2786 
2787 /* -help */
help_fun(char * next_arg GCC_UNUSED)2788 static int help_fun(char *next_arg GCC_UNUSED)
2789 {
2790     print_help_and_exit(0);
2791     return 0;
2792 }
2793 
2794 /* -hiddenlinks */
hiddenlinks_fun(char * next_arg)2795 int hiddenlinks_fun(char *next_arg)
2796 {
2797     /* *INDENT-OFF* */
2798     static Config_Enum table[] = {
2799 	{ "merge",	HIDDENLINKS_MERGE },
2800 	{ "listonly",	HIDDENLINKS_SEPARATE },
2801 	{ "ignore",	HIDDENLINKS_IGNORE },
2802 	{ NULL,		-1 },
2803     };
2804     /* *INDENT-ON* */
2805 
2806     if (next_arg != 0) {
2807 	if (!LYgetEnum(table, next_arg, &LYHiddenLinks))
2808 	    print_help_and_exit(-1);
2809     } else {
2810 	LYHiddenLinks = HIDDENLINKS_MERGE;
2811     }
2812 
2813     return 0;
2814 }
2815 
2816 /* -homepage */
homepage_fun(char * next_arg)2817 static int homepage_fun(char *next_arg)
2818 {
2819     if (next_arg != 0) {
2820 	StrAllocCopy(homepage, next_arg);
2821 	LYEscapeStartfile(&homepage);
2822     }
2823     return 0;
2824 }
2825 
2826 /* -mime_header */
mime_header_fun(char * next_arg GCC_UNUSED)2827 static int mime_header_fun(char *next_arg GCC_UNUSED)
2828 {
2829     /*
2830      * Include mime headers and force source dump.
2831      */
2832     keep_mime_headers = TRUE;
2833     force_dump_mode();
2834     HTOutputFormat = (LYPrependBase ?
2835 		      HTAtom_for("www/download") : HTAtom_for("www/dump"));
2836     LYcols = MAX_COLS;
2837     return 0;
2838 }
2839 
2840 #ifndef DISABLE_NEWS
2841 /* -newschunksize */
newschunksize_fun(char * next_arg)2842 static int newschunksize_fun(char *next_arg)
2843 {
2844     if (next_arg != 0) {
2845 	HTNewsChunkSize = atoi(next_arg);
2846 	/*
2847 	 * If the new HTNewsChunkSize exceeds the maximum,
2848 	 * increase HTNewsMaxChunk to this size. - FM
2849 	 */
2850 	if (HTNewsChunkSize > HTNewsMaxChunk)
2851 	    HTNewsMaxChunk = HTNewsChunkSize;
2852     }
2853     return 0;
2854 }
2855 
2856 /* -newsmaxchunk */
newsmaxchunk_fun(char * next_arg)2857 static int newsmaxchunk_fun(char *next_arg)
2858 {
2859     if (next_arg) {
2860 	HTNewsMaxChunk = atoi(next_arg);
2861 	/*
2862 	 * If HTNewsChunkSize exceeds the new maximum,
2863 	 * reduce HTNewsChunkSize to this maximum. - FM
2864 	 */
2865 	if (HTNewsChunkSize > HTNewsMaxChunk)
2866 	    HTNewsChunkSize = HTNewsMaxChunk;
2867     }
2868     return 0;
2869 }
2870 #endif /* not DISABLE_NEWS */
2871 
2872 /* -nobold */
nobold_fun(char * next_arg GCC_UNUSED)2873 static int nobold_fun(char *next_arg GCC_UNUSED)
2874 {
2875     LYnoVideo(1);
2876     return 0;
2877 }
2878 
2879 /* -nobrowse */
nobrowse_fun(char * next_arg GCC_UNUSED)2880 static int nobrowse_fun(char *next_arg GCC_UNUSED)
2881 {
2882     HTDirAccess = HT_DIR_FORBID;
2883     return 0;
2884 }
2885 
2886 /* -nocolor */
nocolor_fun(char * next_arg GCC_UNUSED)2887 static int nocolor_fun(char *next_arg GCC_UNUSED)
2888 {
2889     LYShowColor = SHOW_COLOR_NEVER;
2890 #ifdef USE_SLANG
2891     Lynx_Color_Flags &= ~(unsigned) SL_LYNX_USE_COLOR;
2892     Lynx_Color_Flags |= SL_LYNX_OVERRIDE_COLOR;
2893 #endif
2894     return 0;
2895 }
2896 
2897 /* -nopause */
nopause_fun(char * next_arg GCC_UNUSED)2898 static int nopause_fun(char *next_arg GCC_UNUSED)
2899 {
2900     no_pause = TRUE;
2901     return 0;
2902 }
2903 
2904 /* -nomore */
nomore_fun(char * next_arg GCC_UNUSED)2905 static int nomore_fun(char *next_arg GCC_UNUSED)
2906 {
2907     nomore = TRUE;
2908     return 0;
2909 }
2910 
2911 /* -noreverse */
noreverse_fun(char * next_arg GCC_UNUSED)2912 static int noreverse_fun(char *next_arg GCC_UNUSED)
2913 {
2914     LYnoVideo(2);
2915     return 0;
2916 }
2917 
2918 /* -nounderline */
nounderline_fun(char * next_arg GCC_UNUSED)2919 static int nounderline_fun(char *next_arg GCC_UNUSED)
2920 {
2921     LYnoVideo(4);
2922     return 0;
2923 }
2924 
2925 /* -nozap */
nozap_fun(char * next_arg)2926 static int nozap_fun(char *next_arg)
2927 {
2928     LYNoZapKey = 1;		/* everything but "initially" treated as "full" - kw */
2929     if (next_arg != 0) {
2930 	if (strcasecomp(next_arg, "initially") == 0)
2931 	    LYNoZapKey = 2;
2932 
2933     }
2934     return 0;
2935 }
2936 
2937 /* -pauth */
pauth_fun(char * next_arg)2938 static int pauth_fun(char *next_arg)
2939 {
2940     parse_authentication(next_arg, proxyauth_info);
2941     return 0;
2942 }
2943 
2944 /* -post_data */
post_data_fun(char * next_arg GCC_UNUSED)2945 static int post_data_fun(char *next_arg GCC_UNUSED)
2946 {
2947     /*
2948      * User data for POST form.
2949      */
2950     char **post_data;
2951     char *buf = NULL;
2952 
2953     /*
2954      * On Unix, conflicts with curses when interactive so let's force a dump.
2955      * - CL
2956      *
2957      * On VMS, mods have been made in LYCurses.c to deal with potential
2958      * conflicts, so don't force a dump here.  - FM
2959      */
2960 #ifndef VMS
2961     force_dump_mode();
2962 #endif /* VMS */
2963 
2964     post_data = &form_post_data;
2965 
2966     /*
2967      * Build post data for later.  Stop reading when we see a line with "---"
2968      * as its first three characters.
2969      */
2970     while (GetStdin(&buf, TRUE)) {
2971 	StrAllocCat(*post_data, buf);
2972     }
2973     return 0;
2974 }
2975 
show_restriction(const char * name)2976 static const char *show_restriction(const char *name)
2977 {
2978     const char *value = 0;
2979 
2980     switch (find_restriction(name, -1)) {
2981     case TRUE:
2982 	value = "on";
2983 	break;
2984     case FALSE:
2985 	value = "off";
2986 	break;
2987     default:
2988 	value = "?";
2989 	break;
2990     }
2991     return value;
2992 }
2993 
2994 /* -restrictions */
restrictions_fun(char * next_arg)2995 static int restrictions_fun(char *next_arg)
2996 {
2997     /* *INDENT-OFF* */
2998     static const struct {
2999 	const char *name;
3000 	const char *help;
3001     } table[] = {
3002 	{ "all", "restricts all options." },
3003 	{ "bookmark", "disallow changing the location of the bookmark file" },
3004 	{ "bookmark_exec", "disallow execution links via the bookmark file" },
3005 #if defined(DIRED_SUPPORT) && defined(OK_PERMIT)
3006 	{ "change_exec_perms", "\
3007 disallow changing the eXecute permission on files\n\
3008 (but still allow it for directories) when local file\n\
3009 management is enabled." },
3010 #endif /* DIRED_SUPPORT && OK_PERMIT */
3011 #ifdef SUPPORT_CHDIR
3012 	{ "chdir", "\
3013 disallow changing the working directory of lynx, e.g.,\n\
3014 to affect the behavior of download command" },
3015 #endif
3016 #if defined(HAVE_CONFIG_H) && !defined(NO_CONFIG_INFO)
3017 	{ "compileopts_info", "\
3018 disable info on options used to compile the binary" },
3019 #endif
3020 	{ "default", "\
3021 same as commandline option -anonymous.  Sets the\n\
3022 default service restrictions for anonymous users.  Set to\n\
3023 all restricted, except for: inside_telnet, outside_telnet,\n\
3024 inside_ftp, outside_ftp, inside_rlogin, outside_rlogin,\n\
3025 inside_news, outside_news, telnet_port, jump, mail, print,\n\
3026 exec, and goto.  The settings for these, as well as\n\
3027 additional goto restrictions for specific URL schemes\n\
3028 that are also applied, are derived from definitions\n\
3029 within userdefs.h." },
3030 #ifdef DIRED_SUPPORT
3031 	{ "dired_support", "disallow local file management" },
3032 #endif /* DIRED_SUPPORT */
3033 	{ "disk_save", "disallow saving to disk in the download and print menus" },
3034 	{ "dotfiles", "disallow access to, or creation of, hidden (dot) files" },
3035 	{ "download", "disallow some downloaders in the download menu" },
3036 	{ "editor", "disallow editing" },
3037 	{ "exec", "disable execution scripts" },
3038 	{ "exec_frozen", "disallow the user from changing the execution link option" },
3039 #ifdef USE_EXTERNALS
3040 	{ "externals", "disable passing URLs to some external programs" },
3041 #endif
3042 	{ "file_url", "\
3043 disallow using G)oto, served links or bookmarks for\n\
3044 file: URL's" },
3045 	{ "goto", "disable the 'g' (goto) command" },
3046 #if !defined(HAVE_UTMP) || defined(VMS) /* not selective */
3047 	{ "inside_ftp", "\
3048 disallow ftps coming from inside your\n\
3049 domain (utmp required for selectivity)" },
3050 	{ "inside_news", "\
3051 disallow USENET news reading and posting coming\n\
3052 from inside your domain (utmp required for selectivity)" },
3053 	{ "inside_rlogin", "\
3054 disallow rlogins coming from inside your\n\
3055 domain (utmp required for selectivity)" },
3056 	{ "inside_telnet", "\
3057 disallow telnets coming from inside your\n\
3058 domain (utmp required for selectivity)" },
3059 #else
3060 	{ "inside_ftp", "\
3061 disallow ftps coming from inside your domain" },
3062 	{ "inside_news", "\
3063 disallow USENET news reading and posting coming\n\
3064 from inside your domain" },
3065 	{ "inside_rlogin", "\
3066 disallow rlogins coming from inside your domain" },
3067 	{ "inside_telnet", "\
3068 disallow telnets coming from inside your domain" },
3069 #endif /* HAVE_UTMP || VMS */
3070 	{ "jump", "disable the 'j' (jump) command" },
3071 	{ "lynxcfg_info", "\
3072 disable viewing of lynx.cfg configuration file info" },
3073 #ifndef NO_CONFIG_INFO
3074 	{ "lynxcfg_xinfo", "\
3075 disable extended lynx.cfg viewing and reloading" },
3076 #endif
3077 	{ "lynxcgi", "\
3078 disallow execution of Lynx CGI URLs" },
3079 	{ "mail", "disallow mail" },
3080 	{ "multibook", "disallow multiple bookmark files" },
3081 	{ "news_post", "disallow USENET News posting." },
3082 	{ "option_save", "disallow saving options in .lynxrc" },
3083 #if !defined(HAVE_UTMP) || defined(VMS) /* not selective */
3084 	{ "outside_ftp", "\
3085 disallow ftps coming from outside your\n\
3086 domain (utmp required for selectivity)" },
3087 	{ "outside_news", "\
3088 disallow USENET news reading and posting coming\n\
3089 from outside your domain (utmp required for selectivity)" },
3090 	{ "outside_rlogin", "\
3091 disallow rlogins coming from outside your\n\
3092 domain (utmp required for selectivity)" },
3093 	{ "outside_telnet", "\
3094 disallow telnets coming from outside your\n\
3095 domain (utmp required for selectivity)" },
3096 #else
3097 	{ "outside_ftp", "\
3098 disallow ftp coming from outside your domain" },
3099 	{ "outside_news", "\
3100 disallow USENET news reading and posting coming\n\
3101 from outside your domain" },
3102 	{ "outside_rlogin", "\
3103 disallow rlogins coming from outside your domain" },
3104 	{ "outside_telnet", "\
3105 disallow telnets coming from outside your domain" },
3106 #endif /* !HAVE_UTMP || VMS */
3107 	{ "print", "disallow most print options" },
3108 	{ "shell", "\
3109 disallow shell escapes, and lynxexec, lynxprog or lynxcgi\n\
3110 G)oto's" },
3111 	{ "suspend", "disallow Control-Z suspends with escape to shell" },
3112 	{ "telnet_port", "disallow specifying a port in telnet G)oto's" },
3113 	{ "useragent", "disallow modifications of the User-Agent header" },
3114     };
3115     /* *INDENT-ON* */
3116 
3117     static const char *Usage[] =
3118     {
3119 	""
3120 	,"USAGE: lynx -restrictions=[option][,option][,option]"
3121 	,"List of Options:"
3122 	,"  ?                 when used alone, list restrictions in effect."
3123 
3124     };
3125     unsigned j, k, column = 0;
3126     const char *name;
3127     const char *value;
3128     BOOLEAN found, first;
3129 
3130     if (isEmpty(next_arg)) {
3131 	SetOutputMode(O_TEXT);
3132 	for (j = 0; j < TABLESIZE(Usage); j++) {
3133 	    printf("%s\n", Usage[j]);
3134 	}
3135 	for (j = 0; j < TABLESIZE(table); j++) {
3136 	    if (!strcmp(table[j].name, "all")
3137 		|| !strcmp(table[j].name, "default")) {
3138 		value = NULL;
3139 	    } else {
3140 		value = show_restriction(table[j].name);
3141 	    }
3142 	    print_help_strings(table[j].name, table[j].help, value, FALSE);
3143 	}
3144 	first = TRUE;
3145 	for (j = 0; j < TABLESIZE(table); j++) {
3146 	    found = FALSE;
3147 	    if ((name = index_to_restriction(j)) == 0) {
3148 		break;
3149 	    }
3150 	    for (k = 0; k < TABLESIZE(table); k++) {
3151 		if (!strcmp(name, table[k].name)) {
3152 		    found = TRUE;
3153 		}
3154 	    }
3155 	    if (!found) {
3156 		if (first) {
3157 		    printf("Other restrictions (see the user's guide):\n");
3158 		}
3159 		value = show_restriction(table[j].name);
3160 		printf("%s%s (%s)", column ? ", " : "  ", name, value);
3161 		column += (unsigned) (5 + strlen(name) + strlen(value));
3162 		if (column > 50) {
3163 		    column = 0;
3164 		    printf("\n");
3165 		}
3166 		first = FALSE;
3167 	    }
3168 	}
3169 	if (column)
3170 	    printf("\n");
3171 	SetOutputMode(O_BINARY);
3172 	exit_immediately(EXIT_SUCCESS);
3173     } else if (*next_arg == '?') {
3174 	SetOutputMode(O_TEXT);
3175 	print_restrictions_to_fd(stdout);
3176 	SetOutputMode(O_BINARY);
3177 	exit_immediately(EXIT_SUCCESS);
3178     } else {
3179 	parse_restrictions(next_arg);
3180     }
3181     return 0;
3182 }
3183 
3184 /* -selective */
selective_fun(char * next_arg GCC_UNUSED)3185 static int selective_fun(char *next_arg GCC_UNUSED)
3186 {
3187     HTDirAccess = HT_DIR_SELECTIVE;
3188     return 0;
3189 }
3190 
3191 /* -source */
source_fun(char * next_arg GCC_UNUSED)3192 static int source_fun(char *next_arg GCC_UNUSED)
3193 {
3194     force_dump_mode();
3195     HTOutputFormat = (LYPrependBase ?
3196 		      HTAtom_for("www/download") : HTAtom_for("www/dump"));
3197     LYcols = MAX_COLS;
3198     return 0;
3199 }
3200 
3201 /* -traversal */
traversal_fun(char * next_arg GCC_UNUSED)3202 static int traversal_fun(char *next_arg GCC_UNUSED)
3203 {
3204     traversal = TRUE;
3205 #ifdef USE_SLANG
3206     LYcols = DFT_COLS;
3207 #else
3208     LYcols = MAX_COLS;
3209 #endif /* USE_SLANG */
3210 
3211     return 0;
3212 }
3213 
3214 /* -version */
version_fun(char * next_arg GCC_UNUSED)3215 static int version_fun(char *next_arg GCC_UNUSED)
3216 {
3217     char *result = NULL;
3218 
3219     SetLocale();
3220     SetOutputMode(O_TEXT);
3221 
3222     HTSprintf0(&result, gettext("%s Version %s (%s)"),
3223 	       LYNX_NAME, LYNX_VERSION,
3224 	       LYVersionDate());
3225 
3226     StrAllocCat(result, "\n");
3227 #ifdef USE_SSL
3228     HTSprintf(&result, "libwww-FM %s,", HTLibraryVersion);
3229     append_ssl_version(&result, " ");
3230 #else
3231     HTSprintf(&result, "libwww-FM %s", HTLibraryVersion);
3232 #endif /* USE_SSL */
3233 
3234 #if defined(NCURSES) && defined(HAVE_CURSES_VERSION)
3235     HTSprintf(&result, ", %s", curses_version());
3236 #if defined(WIDEC_CURSES)
3237     HTSprintf(&result, "(wide)");
3238 #endif
3239 #elif defined(PDCURSES) && defined(PDC_BUILD)
3240     HTSprintf(&result, ", pdcurses %.3f", PDC_BUILD * 0.001);
3241 #elif defined(USE_SLANG) && defined(SLANG_VERSION_STRING)
3242     HTSprintf(&result, ", s-lang %s", SLANG_VERSION_STRING);
3243 #endif
3244 
3245     printf("%s\n", result);
3246     free(result);
3247 
3248 /*
3249  * Define NO_BUILDSTAMP if you really want an executable with no timestamp in
3250  * the -version message.
3251  */
3252 #ifdef NO_BUILDSTAMP
3253 #define BUILDSTAMP ""
3254 #else
3255 #define BUILDSTAMP " (" __DATE__ " " __TIME__ ")"
3256 #endif
3257 
3258 /*
3259  * SYSTEM_NAME is set by the configure script.  Show build date/time for other
3260  * systems, according to predefined compiler symbols.
3261  */
3262 #ifdef SYSTEM_NAME
3263     printf(gettext("Built on %s%s.\n"), SYSTEM_NAME, BUILDSTAMP);
3264 #elif defined(__CYGWIN__)
3265     printf("Compiled by CYGWIN%s.\n", BUILDSTAMP);
3266 #elif defined(__BORLANDC__)
3267     printf("Compiled by Borland C++%s.\n", BUILDSTAMP);
3268 #elif defined(_MSC_VER)
3269     printf("Compiled by Microsoft Visual C++%s.\n", BUILDSTAMP);
3270 #elif defined(__DJGPP__)
3271     printf("Compiled by DJGPP%s.\n", BUILDSTAMP);
3272 #elif !defined(NO_BUILDSTAMP)
3273     printf("Compiled at %s %s.\n", __DATE__, __TIME__);
3274 #endif
3275 
3276     puts("");
3277     puts(gettext("Copyrights held by the Lynx Developers Group,"));
3278     puts(gettext("the University of Kansas, CERN, and other contributors."));
3279     puts(gettext("Distributed under the GNU General Public License (Version 2)."));
3280     puts(gettext("See https://lynx.invisible-island.net/ and the online help for more information."));
3281     puts("");
3282 #ifdef USE_SSL
3283 #if defined(OPENSSL_VERSION_TEXT) && !defined(LIBGNUTLS_VERSION)
3284     puts("See http://www.openssl.org/ for information about OpenSSL.");
3285 #endif /* OPENSSL_VERSION_TEXT */
3286     puts("");
3287 #endif /* USE_SSL */
3288 
3289     SetOutputMode(O_BINARY);
3290 
3291     exit_immediately(EXIT_SUCCESS);
3292     /* NOT REACHED */
3293     return 0;
3294 }
3295 
3296 /* -width */
width_fun(char * next_arg)3297 static int width_fun(char *next_arg)
3298 {
3299     if (next_arg != 0) {
3300 	int w = atoi(next_arg);
3301 
3302 	if (w > 0)
3303 	    dump_output_width = ((w < MAX_COLS) ? w : MAX_COLS);
3304     }
3305 
3306     return 0;
3307 }
3308 
3309 #if defined(PDCURSES) && defined(PDC_BUILD) && PDC_BUILD >= 2401
3310 /* -scrsize */
scrsize_fun(char * next_arg)3311 static int scrsize_fun(char *next_arg)
3312 {
3313     if (next_arg != 0) {
3314 	char *cp;
3315 
3316 	if ((cp = StrChr(next_arg, ',')) != 0) {
3317 	    *cp++ = '\0';	/* Terminate ID */
3318 	    scrsize_x = atoi(next_arg);
3319 	    scrsize_y = atoi(cp);
3320 	    if ((scrsize_x <= 1) || (scrsize_y <= 1)) {
3321 		scrsize_x = scrsize_y = 0;
3322 	    }
3323 	    if ((scrsize_x > 0) && (scrsize_x < 40)) {
3324 		scrsize_x = 40;
3325 	    }
3326 	    if ((scrsize_y > 0) && (scrsize_y < 6)) {
3327 		scrsize_y = 6;
3328 	    }
3329 	    CTRACE((tfp, "scrsize: x=%d, y=%d\n", scrsize_x, scrsize_y));
3330 	}
3331     }
3332     return 0;
3333 }
3334 #endif
3335 
3336 /* NOTE: This table is sorted by name to make the help message useful */
3337 /* *INDENT-OFF* */
3338 static Config_Type Arg_Table [] =
3339 {
3340    PARSE_SET(
3341       "accept_all_cookies", 4|SET_ARG,		LYAcceptAllCookies,
3342       "\naccept cookies without prompting if Set-Cookie handling\nis on"
3343    ),
3344 #if USE_BLAT_MAILER
3345    PARSE_SET(
3346       "altblat",	4|TOGGLE_ARG,		mail_is_altblat,
3347       "select mail tool (`"THIS_BLAT_MAIL"' ==> `"THAT_BLAT_MAIL"')"
3348    ),
3349 #endif
3350    PARSE_FUN(
3351       "anonymous",	2|FUNCTION_ARG,		anonymous_fun,
3352       "apply restrictions for anonymous account,\nsee also -restrictions"
3353    ),
3354    PARSE_FUN(
3355       "assume_charset", 4|NEED_FUNCTION_ARG,	assume_charset_fun,
3356       "=MIMEname\ncharset for documents that don't specify it"
3357    ),
3358    PARSE_FUN(
3359       "assume_local_charset", 4|NEED_FUNCTION_ARG, assume_local_charset_fun,
3360       "=MIMEname\ncharset assumed for local files"
3361    ),
3362    PARSE_FUN(
3363       "assume_unrec_charset", 4|NEED_FUNCTION_ARG, assume_unrec_charset_fun,
3364       "=MIMEname\nuse this instead of unrecognized charsets"
3365    ),
3366    PARSE_FUN(
3367       "auth",		4|NEED_FUNCTION_ARG,	auth_fun,
3368       "=id:pw\nauthentication information for protected documents"
3369    ),
3370    PARSE_FUN(
3371       "base",		4|FUNCTION_ARG,		base_fun,
3372       "prepend a request URL comment and BASE tag to " STR_HTML "\n\
3373 outputs for -source dumps"
3374    ),
3375 #ifndef DISABLE_BIBP
3376    PARSE_STR(
3377       "bibhost",	4|NEED_LYSTRING_ARG,	BibP_bibhost,
3378       "=URL\nlocal bibp server (default http://bibhost/)"
3379    ),
3380 #endif
3381 #ifdef USE_BLINK
3382    PARSE_SET(
3383       "blink",		4|SET_ARG,		term_blink_is_boldbg,
3384       "enable bright background via the BLINK terminal attribute"
3385    ),
3386 #endif
3387    PARSE_SET(
3388       "book",		4|SET_ARG,		bookmark_start,
3389       "use the bookmark page as the startfile"
3390    ),
3391    PARSE_SET(
3392       "buried_news",	4|TOGGLE_ARG,		scan_for_buried_news_references,
3393       "toggles scanning of news articles for buried references"
3394    ),
3395    PARSE_FUN(
3396       "cache",		4|NEED_FUNCTION_ARG,	cache_fun,
3397       "=NUMBER\nNUMBER of documents cached in memory"
3398    ),
3399    PARSE_SET(
3400       "case",		4|SET_ARG,		LYcase_sensitive,
3401       "enable case sensitive user searching"
3402    ),
3403    PARSE_SET(
3404       "center",		4|TOGGLE_ARG,		no_table_center,
3405       "toggle center alignment in HTML TABLE"
3406    ),
3407    PARSE_STR(
3408       "cfg",		2|NEED_LYSTRING_ARG,	lynx_cfg_file,
3409       "=FILENAME\nspecifies a lynx.cfg file other than the default"
3410    ),
3411    PARSE_FUN(
3412       "child",		4|FUNCTION_ARG,		child_fun,
3413       "exit on left-arrow in startfile, and disable save to disk"
3414    ),
3415    PARSE_FUN(
3416       "child_relaxed",	4|FUNCTION_ARG,		child_relaxed_fun,
3417       "exit on left-arrow in startfile (allows save to disk)"
3418    ),
3419 #ifdef USE_CMD_LOGGING
3420    PARSE_STR(
3421       "cmd_log",	2|NEED_LYSTRING_ARG,	lynx_cmd_logfile,
3422       "=FILENAME\nlog keystroke commands to the given file"
3423    ),
3424    PARSE_STR(
3425       "cmd_script",	2|NEED_LYSTRING_ARG,	lynx_cmd_script,
3426       "=FILENAME\nread keystroke commands from the given file\n(see -cmd_log)"
3427    ),
3428 #endif
3429    PARSE_SET(
3430       "collapse_br_tags", 4|TOGGLE_ARG,		LYCollapseBRs,
3431       "toggles collapsing of BR tags"
3432    ),
3433 #ifdef USE_SLANG
3434    PARSE_FUN(
3435       "color",		4|FUNCTION_ARG,		color_fun,
3436       "force color mode on with standard bg colors"
3437    ),
3438 #endif
3439    PARSE_INT(
3440       "connect_timeout", 4|NEED_INT_ARG,	connect_timeout,
3441       "=N\nset the N-second connection timeout"
3442    ),
3443    PARSE_FUN(
3444       "convert_to",	4|FUNCTION_ARG,		convert_to_fun,
3445       "=FORMAT\nconvert input, FORMAT is in MIME type notation\n(experimental)"
3446    ),
3447 #ifdef USE_PERSISTENT_COOKIES
3448    PARSE_STR(
3449       "cookie_file",	4|LYSTRING_ARG,		LYCookieFile,
3450       "=FILENAME\nspecifies a file to use to read cookies"
3451    ),
3452    PARSE_STR(
3453       "cookie_save_file", 4|LYSTRING_ARG,	LYCookieSaveFile,
3454       "=FILENAME\nspecifies a file to use to store cookies"
3455    ),
3456 #endif /* USE_PERSISTENT_COOKIES */
3457    PARSE_SET(
3458       "cookies",	4|TOGGLE_ARG,		LYSetCookies,
3459       "toggles handling of Set-Cookie headers"
3460    ),
3461 #ifndef VMS
3462    PARSE_SET(
3463       "core",		4|TOGGLE_ARG,		LYNoCore,
3464       "toggles forced core dumps on fatal errors"
3465    ),
3466 #endif
3467    PARSE_FUN(
3468       "crawl",		4|FUNCTION_ARG,		crawl_fun,
3469       "with -traversal, output each page to a file\n\
3470 with -dump, format output as with -traversal, but to stdout"
3471    ),
3472 #ifdef USE_CURSES_PADS
3473    PARSE_SET(
3474       "curses_pads",	4|TOGGLE_ARG,		LYuseCursesPads,
3475       "uses curses pad feature to support left/right shifting"
3476    ),
3477 #endif
3478 #ifdef DISP_PARTIAL
3479    PARSE_SET(
3480       "debug_partial",	4|TOGGLE_ARG,		debug_display_partial,
3481       "incremental display stages with MessageSecs delay"
3482    ),
3483 #endif
3484 #ifdef USE_DEFAULT_COLORS
3485    PARSE_SET(
3486       "default_colors",	4|TOGGLE_ARG,		LYuse_default_colors,
3487       "use terminal default foreground/background colors"
3488    ),
3489 #endif
3490    PARSE_INT(
3491       "delay",		4|NEED_TIME_ARG,	DelaySecs,
3492       "=NNN\nset NNN-second delay at statusline message"
3493    ),
3494    PARSE_FUN(
3495       "display",	4|NEED_FUNCTION_ARG,	display_fun,
3496       "=DISPLAY\nset the display variable for X exec'ed programs"
3497    ),
3498    PARSE_FUN(
3499       "display_charset", 4|NEED_FUNCTION_ARG,	display_charset_fun,
3500       "=MIMEname\ncharset for the terminal output"
3501    ),
3502    PARSE_SET(
3503       "dont_wrap_pre",	4|SET_ARG,		dont_wrap_pre,
3504       "inhibit wrapping of text in <pre> when -dump'ing and\n\
3505 -crawl'ing, mark wrapped lines in interactive session"
3506    ),
3507    PARSE_FUN(
3508       "dump",		1|FUNCTION_ARG,		dump_output_fun,
3509       "dump the first file to stdout and exit"
3510    ),
3511    PARSE_FUN(
3512       "editor",		4|NEED_FUNCTION_ARG,	editor_fun,
3513       "=EDITOR\nenable edit mode with specified editor"
3514    ),
3515    PARSE_SET(
3516       "emacskeys",	4|SET_ARG,		emacs_keys,
3517       "enable emacs-like key movement"
3518    ),
3519    PARSE_SET(
3520       "enable_scrollback", 4|TOGGLE_ARG,	enable_scrollback,
3521       "\ntoggles compatibility with comm programs' scrollback\n\
3522 keys (may be incompatible with some curses packages)"
3523    ),
3524    PARSE_FUN(
3525       "error_file",	4|NEED_FUNCTION_ARG,	error_file_fun,
3526       "=FILE\nwrite the HTTP status code here"
3527    ),
3528 #if defined(EXEC_LINKS) || defined(EXEC_SCRIPTS)
3529 #ifndef NEVER_ALLOW_REMOTE_EXEC
3530    PARSE_FUN(
3531       "exec",		4|FUNCTION_ARG,		exec_fun,
3532       "enable local program execution"
3533    ),
3534 #endif
3535 #endif /* EXEC_LINKS || EXEC_SCRIPTS */
3536 #ifdef VMS
3537    PARSE_SET(
3538       "fileversions",	4|SET_ARG,		HTVMSFileVersions,
3539       "include all versions of files in local VMS directory\nlistings"
3540    ),
3541 #endif
3542 #ifdef LY_FIND_LEAKS
3543    PARSE_SET(
3544       "find_leaks",	4|TOGGLE_ARG,		LYfind_leaks,
3545       "toggles memory-leak checking"
3546    ),
3547 #endif
3548    PARSE_SET(
3549       "force_empty_hrefless_a",	4|SET_ARG,	force_empty_hrefless_a,
3550       "\nforce HREF-less 'A' elements to be empty (close them as\n\
3551 soon as they are seen)"
3552    ),
3553    PARSE_SET(
3554       "force_html",	4|SET_ARG,		LYforce_HTML_mode,
3555       "forces the first document to be interpreted as HTML"
3556    ),
3557    PARSE_SET(
3558       "force_secure",	4|TOGGLE_ARG,		LYForceSSLCookiesSecure,
3559       "toggles forcing of the secure flag for SSL cookies"
3560    ),
3561 #if !defined(NO_OPTION_FORMS) && !defined(NO_OPTION_MENU)
3562    PARSE_SET(
3563       "forms_options",	4|TOGGLE_ARG,		LYUseFormsOptions,
3564       "toggles forms-based vs old-style options menu"
3565    ),
3566 #endif
3567    PARSE_SET(
3568       "from",		4|TOGGLE_ARG,		LYNoFromHeader,
3569       "toggle transmission of From headers"
3570    ),
3571 #ifndef DISABLE_FTP
3572    PARSE_SET(
3573       "ftp",		4|UNSET_ARG,		ftp_ok,
3574       "disable ftp access"
3575    ),
3576 #endif
3577    PARSE_FUN(
3578       "get_data",	2|FUNCTION_ARG,		get_data_fun,
3579       "user data for get forms, read from stdin,\nterminated by '---' on a line"
3580    ),
3581    PARSE_SET(
3582       "head",		4|SET_ARG,		HEAD_request,
3583       "send a HEAD request"
3584    ),
3585    PARSE_FUN(
3586       "help",		4|FUNCTION_ARG,		help_fun,
3587       "print this usage message"
3588    ),
3589    PARSE_FUN(
3590       "hiddenlinks",	4|NEED_FUNCTION_ARG,	hiddenlinks_fun,
3591       "=[option]\nhidden links: options are merge, listonly, or ignore"
3592    ),
3593    PARSE_SET(
3594       "historical",	4|TOGGLE_ARG,		historical_comments,
3595       "toggles use of '>' or '-->' as terminator for comments"
3596    ),
3597    PARSE_FUN(
3598       "homepage",	4|NEED_FUNCTION_ARG,	homepage_fun,
3599       "=URL\nset homepage separate from start page"
3600    ),
3601    PARSE_SET(
3602       "html5_charsets",	4|TOGGLE_ARG,		html5_charsets,
3603       "toggles use of HTML5 charset replacements"
3604    ),
3605    PARSE_SET(
3606       "image_links",	4|TOGGLE_ARG,		clickable_images,
3607       "toggles inclusion of links for all images"
3608    ),
3609    PARSE_STR(
3610       "index",		4|NEED_LYSTRING_ARG,	indexfile,
3611       "=URL\nset the default index file to URL"
3612    ),
3613    PARSE_SET(
3614       "ismap",		4|TOGGLE_ARG,		LYNoISMAPifUSEMAP,
3615       "toggles inclusion of ISMAP links when client-side\nMAPs are present"
3616    ),
3617 #ifdef USE_JUSTIFY_ELTS
3618    PARSE_SET(
3619       "justify",	4|SET_ARG,		ok_justify,
3620       "do justification of text"
3621    ),
3622 #endif
3623    PARSE_INT(
3624       "link",		4|NEED_INT_ARG,		crawl_count,
3625       "=NUMBER\nstarting count for lnk#.dat files produced by -crawl"
3626    ),
3627    PARSE_SET(
3628       "list_decoded",	4|TOGGLE_ARG,		dump_links_decoded,
3629       "with -dump, forces it to decode URL-encoded links"
3630    ),
3631    PARSE_SET(
3632       "list_inline",	4|TOGGLE_ARG,		dump_links_inline,
3633       "with -dump, forces it to show links inline with text"
3634    ),
3635    PARSE_SET(
3636       "listonly",	4|TOGGLE_ARG,		dump_links_only,
3637       "with -dump, forces it to show only the list of links"
3638    ),
3639    PARSE_SET(
3640       "localhost",	4|SET_ARG,		local_host_only,
3641       "disable URLs that point to remote hosts"
3642    ),
3643 #if defined(EXEC_LINKS) || defined(EXEC_SCRIPTS)
3644    PARSE_SET(
3645       "locexec",	4|SET_ARG,		local_exec_on_local_files,
3646       "enable local program execution from local files only"
3647    ),
3648 #endif /* EXEC_LINKS || EXEC_SCRIPTS */
3649 #if defined(USE_COLOR_STYLE)
3650    PARSE_STR(
3651       "lss",		2|NEED_LYSTRING_ARG,	lynx_lss_file2,
3652       "=FILENAME\nspecifies a lynx.lss file other than the default"
3653    ),
3654 #endif
3655    PARSE_FUN(
3656       "mime_header",	4|FUNCTION_ARG,		mime_header_fun,
3657       "include mime headers and force source dump"
3658    ),
3659    PARSE_SET(
3660       "minimal",	4|TOGGLE_ARG,		minimal_comments,
3661       "toggles minimal versus valid comment parsing"
3662    ),
3663 #ifdef EXP_NESTED_TABLES
3664    PARSE_SET(
3665       "nested_tables",	4|TOGGLE_ARG,		nested_tables,
3666       "toggles nested-tables logic"
3667    ),
3668 #endif
3669 #ifndef DISABLE_NEWS
3670    PARSE_FUN(
3671       "newschunksize",	4|NEED_FUNCTION_ARG,	newschunksize_fun,
3672       "=NUMBER\nnumber of articles in chunked news listings"
3673    ),
3674    PARSE_FUN(
3675       "newsmaxchunk",	4|NEED_FUNCTION_ARG,	newsmaxchunk_fun,
3676       "=NUMBER\nmaximum news articles in listings before chunking"
3677    ),
3678 #endif
3679 #if USE_BLAT_MAILER
3680    PARSE_SET(
3681       "noblat",		4|TOGGLE_ARG,		mail_is_blat,
3682       "select mail tool (`"THIS_BLAT_MAIL"' ==> `"SYSTEM_MAIL"')"
3683    ),
3684 #endif
3685    PARSE_FUN(
3686       "nobold",		4|FUNCTION_ARG,		nobold_fun,
3687       "disable bold video-attribute"
3688    ),
3689    PARSE_FUN(
3690       "nobrowse",	4|FUNCTION_ARG,		nobrowse_fun,
3691       "disable directory browsing"
3692    ),
3693    PARSE_SET(
3694       "nocc",		4|SET_ARG,		LYNoCc,
3695       "disable Cc: prompts for self copies of mailings"
3696    ),
3697    PARSE_FUN(
3698       "nocolor",	4|FUNCTION_ARG,		nocolor_fun,
3699       "turn off color support"
3700    ),
3701 #if defined(EXEC_LINKS) || defined(EXEC_SCRIPTS)
3702    PARSE_SET(
3703       "noexec",		4|UNSET_ARG,		local_exec,
3704       "disable local program execution (DEFAULT)"
3705    ),
3706 #endif /* EXEC_LINKS || EXEC_SCRIPTS */
3707    PARSE_SET(
3708       "nofilereferer",	4|SET_ARG,		no_filereferer,
3709       "disable transmission of Referer headers for file URLs"
3710    ),
3711    PARSE_SET(
3712       "nolist",		4|SET_ARG,		no_list,
3713       "disable the link list feature in dumps"
3714    ),
3715    PARSE_SET(
3716       "nolog",		4|UNSET_ARG,		error_logging,
3717       "disable mailing of error messages to document owners"
3718    ),
3719    PARSE_SET(
3720       "nomargins",	4|SET_ARG,		no_margins,
3721       "disable the right/left margins in the default\nstyle-sheet"
3722    ),
3723    PARSE_FUN(
3724       "nomore",		4|FUNCTION_ARG,		nomore_fun,
3725       "disable -more- string in statusline messages"
3726    ),
3727 #if defined(HAVE_SIGACTION) && defined(SIGWINCH)
3728    PARSE_SET(
3729       "nonrestarting_sigwinch", 4|SET_ARG,	LYNonRestartingSIGWINCH,
3730       "\nmake window size change handler non-restarting"
3731    ),
3732 #endif /* HAVE_SIGACTION */
3733    PARSE_SET(
3734       "nonumbers",	4|SET_ARG,		no_numbers,
3735       "disable the link/form numbering feature in dumps"
3736    ),
3737    PARSE_FUN(
3738       "nopause",	4|FUNCTION_ARG,		nopause_fun,
3739       "disable forced pauses for statusline messages"
3740    ),
3741    PARSE_SET(
3742       "noprint",	4|SET_ARG,		no_print,
3743       "disable some print functions, like -restrictions=print"
3744    ),
3745    PARSE_SET(
3746       "noredir",	4|SET_ARG,		no_url_redirection,
3747       "don't follow Location: redirection"
3748    ),
3749    PARSE_SET(
3750       "noreferer",	4|SET_ARG,		LYNoRefererHeader,
3751       "disable transmission of Referer headers"
3752    ),
3753    PARSE_FUN(
3754       "noreverse",	4|FUNCTION_ARG,		noreverse_fun,
3755       "disable reverse video-attribute"
3756    ),
3757 #ifdef SOCKS
3758    PARSE_SET(
3759       "nosocks",	2|UNSET_ARG,		socks_flag,
3760       "don't use SOCKS proxy for this session"
3761    ),
3762 #endif
3763    PARSE_SET(
3764       "nostatus",	4|SET_ARG,		no_statusline,
3765       "disable the miscellaneous information messages"
3766    ),
3767    PARSE_SET(
3768       "notitle",	4|SET_ARG,		no_title,
3769       "disable the title at the top of each page"
3770    ),
3771    PARSE_FUN(
3772       "nounderline",	4|FUNCTION_ARG,		nounderline_fun,
3773       "disable underline video-attribute"
3774    ),
3775    PARSE_FUN(
3776       "nozap",		4|FUNCTION_ARG,		nozap_fun,
3777       "=DURATION (\"initially\" or \"full\") disable checks for 'z' key"
3778    ),
3779    PARSE_SET(
3780       "number_fields",	4|SET_ARG,		number_fields,
3781       "force numbering of links as well as form input fields"
3782    ),
3783    PARSE_SET(
3784       "number_links",	4|SET_ARG,		number_links,
3785       "force numbering of links"
3786    ),
3787 #ifdef DISP_PARTIAL
3788    PARSE_SET(
3789       "partial",	4|TOGGLE_ARG,		display_partial_flag,
3790       "toggles display partial pages while downloading"
3791    ),
3792    PARSE_INT(
3793       "partial_thres",	4|NEED_INT_ARG,		partial_threshold,
3794       "[=NUMBER]\nnumber of lines to render before repainting display\n\
3795 with partial-display logic"
3796    ),
3797 #endif
3798 #ifndef DISABLE_FTP
3799    PARSE_SET(
3800       "passive_ftp",	4|TOGGLE_ARG,		ftp_passive,
3801       "toggles passive ftp connection"
3802    ),
3803 #endif
3804    PARSE_FUN(
3805       "pauth",		4|NEED_FUNCTION_ARG,	pauth_fun,
3806       "=id:pw\nauthentication information for protected proxy server"
3807    ),
3808    PARSE_SET(
3809       "popup",		4|UNSET_ARG,		LYUseDefSelPop,
3810       "toggles handling of single-choice SELECT options via\n\
3811 popup windows or as lists of radio buttons"
3812    ),
3813    PARSE_FUN(
3814       "post_data",	2|FUNCTION_ARG,		post_data_fun,
3815       "user data for post forms, read from stdin,\n\
3816 terminated by '---' on a line"
3817    ),
3818    PARSE_SET(
3819       "preparsed",	4|SET_ARG,		LYPreparsedSource,
3820       "show parsed " STR_HTML " with -source and in source view\n\
3821 to visualize how lynx behaves with invalid HTML"
3822    ),
3823 #ifdef USE_PRETTYSRC
3824    PARSE_SET(
3825       "prettysrc",	4|SET_ARG,		LYpsrc,
3826       "do syntax highlighting and hyperlink handling in source\nview"
3827    ),
3828 #endif
3829    PARSE_SET(
3830       "print",		4|UNSET_ARG,		no_print,
3831       "enable print functions (DEFAULT), opposite of -noprint"
3832    ),
3833    PARSE_SET(
3834       "pseudo_inlines", 4|TOGGLE_ARG,		pseudo_inline_alts,
3835       "toggles pseudo-ALTs for inlines with no ALT string"
3836    ),
3837    PARSE_SET(
3838       "raw",		4|UNSET_ARG,		LYUseDefaultRawMode,
3839       "toggles default setting of 8-bit character translations\n\
3840 or CJK mode for the startup character set"
3841    ),
3842    PARSE_SET(
3843       "realm",		4|SET_ARG,		check_realm,
3844       "restricts access to URLs in the starting realm"
3845    ),
3846    PARSE_INT(
3847       "read_timeout",	4|NEED_INT_ARG,		reading_timeout,
3848       "=N\nset the N-second read-timeout"
3849    ),
3850    PARSE_SET(
3851       "reload",		4|SET_ARG,		reloading,
3852       "flushes the cache on a proxy server\n(only the first document affected)"
3853    ),
3854    PARSE_FUN(
3855       "restrictions",	4|FUNCTION_ARG,		restrictions_fun,
3856       "=[options]\nuse -restrictions to see list"
3857    ),
3858    PARSE_SET(
3859       "resubmit_posts", 4|TOGGLE_ARG,		LYresubmit_posts,
3860       "toggles forced resubmissions (no-cache) of forms with\n\
3861 method POST when the documents they returned are sought\n\
3862 with the PREV_DOC command or from the History List"
3863    ),
3864    PARSE_SET(
3865       "rlogin",		4|UNSET_ARG,		rlogin_ok,
3866       "disable rlogins"
3867    ),
3868 #if defined(PDCURSES) && defined(PDC_BUILD) && PDC_BUILD >= 2401
3869    PARSE_FUN(
3870       "scrsize",	4|NEED_FUNCTION_ARG,	scrsize_fun,
3871       "=width,height\nsize of window"
3872    ),
3873 #endif
3874 #ifdef USE_SCROLLBAR
3875    PARSE_SET(
3876       "scrollbar",	4|TOGGLE_ARG,		LYShowScrollbar,
3877       "toggles showing scrollbar"
3878    ),
3879    PARSE_SET(
3880       "scrollbar_arrow", 4|TOGGLE_ARG,		LYsb_arrow,
3881       "toggles showing arrows at ends of the scrollbar"
3882    ),
3883 #endif
3884    PARSE_FUN(
3885       "selective",	4|FUNCTION_ARG,		selective_fun,
3886       "require .www_browsable files to browse directories"
3887    ),
3888 #ifdef USE_SESSIONS
3889    PARSE_STR(
3890       "session",	2|NEED_LYSTRING_ARG,	session_file,
3891       "=FILENAME\nresumes from specified file on startup and\n\
3892 saves session to that file on exit"
3893    ),
3894    PARSE_STR(
3895       "sessionin",	2|NEED_LYSTRING_ARG,	sessionin_file,
3896       "=FILENAME\nresumes session from specified file"
3897    ),
3898    PARSE_STR(
3899       "sessionout",	2|NEED_LYSTRING_ARG,	sessionout_file,
3900       "=FILENAME\nsaves session to specified file"
3901    ),
3902 #endif /* USE_SESSIONS */
3903    PARSE_SET(
3904       "short_url",	4|SET_ARG,		long_url_ok,
3905       "enables examination of beginning and end of long URL in\nstatus line"
3906    ),
3907    PARSE_SET(
3908       "show_cfg",	1|SET_ARG,		show_cfg,
3909       "Show `LYNX.CFG' setting"
3910    ),
3911    PARSE_SET(
3912       "show_cursor",	4|TOGGLE_ARG,		LYUseDefShoCur,
3913       "toggles hiding of the cursor in the lower right corner"
3914    ),
3915 #ifdef USE_READPROGRESS
3916    PARSE_SET(
3917       "show_rate",	4|TOGGLE_ARG,		LYShowTransferRate,
3918       "toggles display of transfer rate"
3919    ),
3920 #endif
3921    PARSE_STR(
3922       "socks5_proxy",	2|NEED_LYSTRING_ARG,	socks5_proxy,
3923       "=URL\n(via which) SOCKS5 proxy to connect (unrelated to -nosocks!)"
3924    ),
3925    PARSE_SET(
3926       "soft_dquotes",	4|TOGGLE_ARG,		soft_dquotes,
3927       "toggles emulation of the old Netscape and Mosaic\n\
3928 bug which treated '>' as a co-terminator for\ndouble-quotes and tags"
3929    ),
3930    PARSE_FUN(
3931       "source",		4|FUNCTION_ARG,		source_fun,
3932       "dump the source of the first file to stdout and exit"
3933    ),
3934    PARSE_SET(
3935       "stack_dump",	4|SET_ARG,		stack_dump,
3936       "disable SIGINT cleanup handler"
3937    ),
3938    PARSE_SET(
3939       "startfile_ok",	4|SET_ARG,		startfile_ok,
3940       "allow non-http startfile and homepage with -validate"
3941    ),
3942    PARSE_SET(
3943       "stderr",		4|SET_ARG,		dump_to_stderr,
3944       "write warning messages to standard error when -dump\nor -source is used"
3945    ),
3946    PARSE_SET(
3947       "stdin",		4|SET_ARG,		startfile_stdin,
3948       "read startfile from standard input"
3949    ),
3950 #ifdef SYSLOG_REQUESTED_URLS
3951    PARSE_STR(
3952       "syslog",		4|NEED_LYSTRING_ARG,	syslog_txt,
3953       "=text\ninformation for syslog call"
3954    ),
3955    PARSE_SET(
3956       "syslog_urls",	4|SET_ARG,		syslog_requested_urls,
3957       "log requested URLs with syslog"
3958    ),
3959 #endif
3960    PARSE_SET(
3961       "tagsoup",	4|SET_ARG,		DTD_recovery,
3962       "use TagSoup rather than SortaSGML parser"
3963    ),
3964    PARSE_SET(
3965       "telnet",		4|UNSET_ARG,		telnet_ok,
3966       "disable telnets"
3967    ),
3968    PARSE_STR(
3969       "term",		4|NEED_STRING_ARG,	terminal,
3970       "=TERM\nset terminal type to TERM"
3971    ),
3972 #ifdef _WINDOWS
3973    PARSE_INT(
3974       "timeout",	4|INT_ARG,		lynx_timeout,
3975       "=NUMBER\nset TCP/IP timeout"
3976    ),
3977 #endif
3978    PARSE_SET(
3979       "tlog",		2|TOGGLE_ARG,		LYUseTraceLog,
3980       "toggles use of a Lynx Trace Log for the current\nsession"
3981    ),
3982 #ifdef TEXTFIELDS_MAY_NEED_ACTIVATION
3983    PARSE_SET(
3984       "tna",		4|SET_ARG,		textfields_activation_option,
3985       "turn on \"Textfields Need Activation\" mode"
3986    ),
3987 #endif
3988 #ifndef NO_LYNX_TRACE
3989    PARSE_SET(
3990       "trace",		1|SET_ARG,		WWW_TraceFlag,
3991       "turns on Lynx trace mode"
3992    ),
3993    PARSE_INT(
3994       "trace_mask",	1|INT_ARG,		WWW_TraceMask,
3995       "customize Lynx trace mode"
3996    ),
3997 #endif
3998    PARSE_FUN(
3999       "traversal",	4|FUNCTION_ARG,		traversal_fun,
4000       "traverse all http links derived from startfile"
4001    ),
4002    PARSE_SET(
4003       "trim_blank_lines", 2|TOGGLE_ARG,		LYtrimBlankLines,
4004       "\ntoggle trimming of leading/trailing/collapsed-br blank lines"
4005    ),
4006    PARSE_SET(
4007       "trim_input_fields", 2|SET_ARG,		LYtrimInputFields,
4008       "\ntrim input text/textarea fields in forms"
4009    ),
4010    PARSE_SET(
4011       "underline_links",4|TOGGLE_ARG,		LYUnderlineLinks,
4012       "toggles use of underline/bold attribute for links"
4013    ),
4014    PARSE_SET(
4015       "underscore",	4|TOGGLE_ARG,		use_underscore,
4016       "toggles use of _underline_ format in dumps"
4017    ),
4018    PARSE_SET(
4019       "unique_urls",	4|TOGGLE_ARG,		unique_urls,
4020       "toggles use of unique-urls setting for -dump and -listonly options"
4021    ),
4022    PARSE_SET(
4023        "update_term_title", 4|SET_ARG, update_term_title,
4024        "enables updating the title of terminal emulators"
4025    ),
4026 #if defined(USE_MOUSE)
4027    PARSE_SET(
4028       "use_mouse",	4|SET_ARG,		LYUseMouse,
4029       "turn on mouse support"
4030    ),
4031 #endif
4032    PARSE_STR(
4033       "useragent",	4|NEED_LYSTRING_ARG,	LYUserAgent,
4034       "=Name\nset alternate Lynx User-Agent header"
4035    ),
4036    PARSE_SET(
4037       "validate",	2|SET_ARG,		LYValidate,
4038       "accept only http URLs (meant for validation)\n\
4039 implies more restrictions than -anonymous, but\n\
4040 goto is allowed for http and https"
4041    ),
4042    PARSE_SET(
4043       "verbose",	4|TOGGLE_ARG,		verbose_img,
4044       "toggles [LINK], [IMAGE] and [INLINE] comments\n\
4045 with filenames of these images"
4046    ),
4047    PARSE_FUN(
4048       "version",	1|FUNCTION_ARG,		version_fun,
4049       "print Lynx version information"
4050    ),
4051    PARSE_SET(
4052       "vikeys",		4|SET_ARG,		vi_keys,
4053       "enable vi-like key movement"
4054    ),
4055 #ifdef __DJGPP__
4056    PARSE_SET(
4057       "wdebug",		4|TOGGLE_ARG,		watt_debug,
4058       "enables Waterloo tcp/ip packet debug. Prints to watt\ndebugfile"
4059   ),
4060 #endif /* __DJGPP__ */
4061    PARSE_FUN(
4062       "width",		4|NEED_FUNCTION_ARG,	width_fun,
4063       "=NUMBER\nscreen width for formatting of dumps (default is 80)"
4064    ),
4065 #ifndef NO_DUMP_WITH_BACKSPACES
4066    PARSE_SET(
4067       "with_backspaces", 4|SET_ARG,		with_backspaces,
4068       "emit backspaces in output if -dumping or -crawling\n(like 'man' does)"
4069    ),
4070 #endif
4071    PARSE_SET(
4072       "xhtml_parsing",	4|SET_ARG,		LYxhtml_parsing,
4073       "enable XHTML 1.0 parsing"
4074    ),
4075    PARSE_NIL
4076 };
4077 /* *INDENT-ON* */
4078 
print_help_strings(const char * name,const char * help,const char * value,int option)4079 static void print_help_strings(const char *name,
4080 			       const char *help,
4081 			       const char *value,
4082 			       int option)
4083 {
4084     int pad;
4085     int c;
4086     int first;
4087     int field_width = 20;
4088 
4089     pad = field_width - (2 + option + (int) strlen(name));
4090 
4091     fprintf(stdout, "  %s%s", option ? "-" : "", name);
4092 
4093     if (*help != '=') {
4094 	pad--;
4095 	while (pad > 0) {
4096 	    fputc(' ', stdout);
4097 	    pad--;
4098 	}
4099 	fputc(' ', stdout);	/* at least one space */
4100 	first = 0;
4101     } else {
4102 	first = pad;
4103     }
4104 
4105     if (StrChr(help, '\n') == 0) {
4106 	fprintf(stdout, "%s", help);
4107     } else {
4108 	while ((c = *help) != 0) {
4109 	    if (c == '\n') {
4110 		if ((pad = --first) < 0) {
4111 		    pad = field_width;
4112 		} else {
4113 		    c = ' ';
4114 		}
4115 		fputc(c, stdout);
4116 		while (pad--)
4117 		    fputc(' ', stdout);
4118 	    } else {
4119 		fputc(c, stdout);
4120 	    }
4121 	    help++;
4122 	    first--;
4123 	}
4124     }
4125     if (value)
4126 	printf(" (%s)", value);
4127     fputc('\n', stdout);
4128 }
4129 
print_help_and_exit(int exit_status)4130 static void print_help_and_exit(int exit_status)
4131 {
4132     Config_Type *p;
4133 
4134     if (pgm == NULL)
4135 	pgm = "lynx";
4136 
4137     SetOutputMode(O_TEXT);
4138 
4139     fprintf(stdout, gettext("USAGE: %s [options] [file]\n"), pgm);
4140     fprintf(stdout, gettext("Options are:\n"));
4141 #ifdef VMS
4142     print_help_strings("",
4143 		       "receive the arguments from stdin (enclose\n\
4144 in double-quotes (\"-\") on VMS)", NULL, TRUE);
4145 #else
4146     print_help_strings("", "receive options and arguments from stdin", NULL, TRUE);
4147 #endif /* VMS */
4148 
4149     for (p = Arg_Table; p->name != 0; p++) {
4150 	char temp[LINESIZE], *value = temp;
4151 	ParseUnionPtr q = ParseUnionOf(p);
4152 
4153 	switch (p->type & ARG_TYPE_MASK) {
4154 	case TOGGLE_ARG:
4155 	case SET_ARG:
4156 	    strcpy(temp, *(q->set_value) ? "on" : "off");
4157 	    break;
4158 	case UNSET_ARG:
4159 	    strcpy(temp, *(q->set_value) ? "off" : "on");
4160 	    break;
4161 	case INT_ARG:
4162 	    sprintf(temp, "%d", *(q->int_value));
4163 	    break;
4164 	case TIME_ARG:
4165 	    sprintf(temp, SECS_FMT, (double) Secs2SECS(*(q->int_value)));
4166 	    break;
4167 	case STRING_ARG:
4168 	    if ((value = *(q->str_value)) != 0
4169 		&& !*value)
4170 		value = 0;
4171 	    break;
4172 	default:
4173 	    value = 0;
4174 	    break;
4175 	}
4176 	print_help_strings(p->name, p->help_string, value, TRUE);
4177     }
4178 
4179     SetOutputMode(O_BINARY);
4180 
4181     exit_immediately(exit_status);
4182 }
4183 
4184 /*
4185  * This function performs a string comparison on two strings a and b.  a is
4186  * assumed to be an ordinary null terminated string, but b may be terminated
4187  * by an '=', '+' or '-' character.  If terminated by '=', *c will be pointed
4188  * to the character following the '='.  If terminated by '+' or '-', *c will
4189  * be pointed to that character.  (+/- added for toggle processing - BL.)
4190  * If a and b match, it returns 1.  Otherwise 0 is returned.
4191  */
arg_eqs_parse(const char * a,char * b,char ** c)4192 static int arg_eqs_parse(const char *a,
4193 			 char *b,
4194 			 char **c)
4195 {
4196     int result = -1;
4197 
4198     *c = NULL;
4199     while (result < 0) {
4200 	if ((*a != *b)
4201 	    || (*a == 0)
4202 	    || (*b == 0)) {
4203 	    if (*a == 0) {
4204 		switch (*b) {
4205 		case '\t':	/* embedded blank when reading stdin */
4206 		case ' ':
4207 		    *c = LYSkipBlanks(b);
4208 		    result = 1;
4209 		    break;
4210 		case '=':
4211 		case ':':
4212 		    *c = b + 1;
4213 		    result = 1;
4214 		    break;
4215 		case '-':
4216 #if OPTNAME_ALLOW_DASHES
4217 		    if (isalpha(UCH(b[1]))) {
4218 			result = 0;
4219 			break;
4220 		    }
4221 #endif
4222 		    /* FALLTHRU */
4223 		case '+':
4224 		    *c = b;
4225 		    result = 1;
4226 		    break;
4227 		case 0:
4228 		    result = 1;
4229 		    break;
4230 		default:
4231 		    result = 0;
4232 		    break;
4233 		}
4234 	    } else {
4235 #if OPTNAME_ALLOW_DASHES
4236 		if (!(*a == '_' && *b == '-'))
4237 #endif
4238 		    result = 0;
4239 	    }
4240 	}
4241 	a++;
4242 	b++;
4243     }
4244     return result;
4245 }
4246 
4247 #define is_true(s)  (*s == '1' || *s == '+' || !strcasecomp(s, "on")  || !strcasecomp(s, "true"))
4248 #define is_false(s) (*s == '0' || *s == '-' || !strcasecomp(s, "off") || !strcasecomp(s, "false"))
4249 
4250 /*
4251  * Parse an option.
4252  *	argv[] points to the beginning of the unprocessed options.
4253  *	mask is used to select certain options which must be processed
4254  *		before others.
4255  *	countp (if nonnull) points to an index into argv[], which is updated
4256  *		to reflect option values which are also parsed.
4257  */
parse_arg(char ** argv,unsigned mask,int * countp)4258 static BOOL parse_arg(char **argv,
4259 		      unsigned mask,
4260 		      int *countp)
4261 {
4262     Config_Type *p;
4263     char *arg_name;
4264 
4265 #if EXTENDED_STARTFILE_RECALL
4266     static BOOLEAN no_options_further = FALSE;	/* set to TRUE after '--' argument */
4267     static int nof_index = 0;	/* set the index of -- argument */
4268 #endif
4269 
4270     arg_name = argv[0];
4271     CTRACE((tfp, "parse_arg(arg_name=%s, mask=%u, count=%d)\n",
4272 	    arg_name, mask, countp ? *countp : -1));
4273 
4274 #if EXTENDED_STARTFILE_RECALL
4275     if (mask == (unsigned) ((countp != 0) ? 0 : 1)) {
4276 	no_options_further = FALSE;
4277 	/* want to reset nonoption when beginning scan for --stdin */
4278 	if (nonoption != 0) {
4279 	    FREE(nonoption);
4280 	}
4281     }
4282 #endif
4283 
4284     /*
4285      * Check for a command line startfile.  - FM
4286      */
4287     if (*arg_name != '-'
4288 #if EXTENDED_OPTION_LOGIC
4289 	|| ((no_options_further == TRUE)
4290 	    && (countp != 0)
4291 	    && (nof_index < (*countp)))
4292 #endif
4293 	) {
4294 #if EXTENDED_STARTFILE_RECALL
4295 	/*
4296 	 * On the last pass (mask==4), check for cases where we may want to
4297 	 * provide G)oto history for multiple startfiles.
4298 	 */
4299 	if (mask == 4) {
4300 	    if (nonoption != 0) {
4301 		LYEnsureAbsoluteURL(&nonoption, "NONOPTION", FALSE);
4302 		HTAddGotoURL(nonoption);
4303 		FREE(nonoption);
4304 	    }
4305 	    StrAllocCopy(nonoption, arg_name);
4306 	}
4307 #endif
4308 	StrAllocCopy(startfile, arg_name);
4309 	LYEscapeStartfile(&startfile);
4310 #ifdef _WINDOWS			/* 1998/01/14 (Wed) 20:11:17 */
4311 	HTUnEscape(startfile);
4312 	{
4313 	    char *q = startfile;
4314 
4315 	    while (*q++) {
4316 		if (*q == '|')
4317 		    *q = ':';
4318 	    }
4319 	}
4320 #endif
4321 	CTRACE((tfp, "parse_arg startfile:%s\n", startfile));
4322 	return (BOOL) (countp != 0);
4323     }
4324 #if EXTENDED_OPTION_LOGIC
4325     if (strcmp(arg_name, "--") == 0) {
4326 	no_options_further = TRUE;
4327 	nof_index = countp ? *countp : -1;
4328 	return TRUE;
4329     }
4330 #endif
4331 
4332     /* lose the first '-' character */
4333     arg_name++;
4334 
4335     /*
4336      * Skip any lone "-" arguments, because we've loaded the stdin input into
4337      * an HTList structure for special handling.  - FM
4338      */
4339     if (*arg_name == 0)
4340 	return TRUE;
4341 
4342     /* allow GNU-style options with -- prefix */
4343     if (*arg_name == '-')
4344 	++arg_name;
4345 
4346     CTRACE((tfp, "parse_arg lookup(%s)\n", arg_name));
4347 
4348     p = Arg_Table;
4349     while (p->name != 0) {
4350 	ParseUnionPtr q = ParseUnionOf(p);
4351 	ParseFunc fun;
4352 	char *next_arg = NULL;
4353 	char *temp_ptr = NULL;
4354 
4355 	if ((p->name[0] != *arg_name)
4356 	    || (0 == arg_eqs_parse(p->name, arg_name, &next_arg))) {
4357 	    p++;
4358 	    continue;
4359 	}
4360 
4361 	if (p->type & NEED_NEXT_ARG) {
4362 	    if (next_arg == 0) {
4363 		next_arg = argv[1];
4364 		if ((countp != 0) && (next_arg != 0))
4365 		    (*countp)++;
4366 	    }
4367 	    CTRACE((tfp, "...arg:%s\n", NONNULL(next_arg)));
4368 	}
4369 
4370 	/* ignore option if it's not our turn */
4371 	if (((unsigned) (p->type) & mask) == 0) {
4372 	    CTRACE((tfp, "...skip (mask %u/%d)\n", mask, p->type & 7));
4373 	    return FALSE;
4374 	}
4375 
4376 	switch (p->type & ARG_TYPE_MASK) {
4377 	case TOGGLE_ARG:	/* FALLTHRU */
4378 	case SET_ARG:		/* FALLTHRU */
4379 	case UNSET_ARG:
4380 	    if (q->set_value != 0) {
4381 		if (next_arg == 0) {
4382 		    switch (p->type & ARG_TYPE_MASK) {
4383 		    case TOGGLE_ARG:
4384 			*(q->set_value) = (BOOL) !(*(q->set_value));
4385 			break;
4386 		    case SET_ARG:
4387 			*(q->set_value) = TRUE;
4388 			break;
4389 		    case UNSET_ARG:
4390 			*(q->set_value) = FALSE;
4391 			break;
4392 		    }
4393 		} else if (is_true(next_arg)) {
4394 		    *(q->set_value) = TRUE;
4395 		} else if (is_false(next_arg)) {
4396 		    *(q->set_value) = FALSE;
4397 		}
4398 		/* deliberately ignore anything else - BL */
4399 	    }
4400 	    break;
4401 
4402 	case FUNCTION_ARG:
4403 	    fun = q->fun_value;
4404 	    if (0 != fun) {
4405 		if (-1 == (*fun) (next_arg)) {
4406 		}
4407 	    }
4408 	    break;
4409 
4410 	case LYSTRING_ARG:
4411 	    if ((q->str_value != 0) && (next_arg != 0))
4412 		StrAllocCopy(*(q->str_value), next_arg);
4413 	    break;
4414 
4415 	case INT_ARG:
4416 	    if ((q->int_value != 0) && (next_arg != 0))
4417 		*(q->int_value) = (int) strtol(next_arg, &temp_ptr, 0);
4418 	    break;
4419 
4420 	case TIME_ARG:
4421 	    if ((q->int_value != 0) && (next_arg != 0)) {
4422 		float ival;
4423 
4424 		if (1 == LYscanFloat(next_arg, &ival)) {
4425 		    *(q->int_value) = (int) SECS2Secs(ival);
4426 		}
4427 	    }
4428 	    break;
4429 
4430 	case STRING_ARG:
4431 	    if ((q->str_value != 0) && (next_arg != 0))
4432 		*(q->str_value) = next_arg;
4433 	    break;
4434 	}
4435 
4436 	Old_DTD = DTD_recovery;	/* BOOL != int */
4437 	return TRUE;
4438     }
4439 
4440     if (pgm == 0)
4441 	pgm = "LYNX";
4442 
4443     fprintf(stderr, gettext("%s: Invalid Option: %s\n"), pgm, argv[0]);
4444     print_help_and_exit(-1);
4445     return FALSE;
4446 }
4447 
4448 #ifndef VMS
FatalProblem(int sig)4449 static void FatalProblem(int sig)
4450 {
4451     /*
4452      * Ignore further interrupts.  - mhc:  11/2/91
4453      */
4454 #ifndef NOSIGHUP
4455     (void) signal(SIGHUP, SIG_IGN);
4456 #endif /* NOSIGHUP */
4457     (void) signal(SIGTERM, SIG_IGN);
4458     (void) signal(SIGINT, SIG_IGN);
4459 #ifndef __linux__
4460 #ifdef SIGBUS
4461     (void) signal(SIGBUS, SIG_IGN);
4462 #endif /* ! SIGBUS */
4463 #endif /* !__linux__ */
4464     (void) signal(SIGSEGV, SIG_IGN);
4465     (void) signal(SIGILL, SIG_IGN);
4466 
4467     /*
4468      * Flush all messages.  - FM
4469      */
4470     fflush(stderr);
4471     fflush(stdout);
4472 
4473     /*
4474      * Deal with curses, if on, and clean up.  - FM
4475      */
4476     if (LYOutOfMemory && LYCursesON) {
4477 	LYSleepAlert();
4478     }
4479     cleanup_sig(0);
4480 #ifndef __linux__
4481 #ifdef SIGBUS
4482     signal(SIGBUS, SIG_DFL);
4483 #endif /* SIGBUS */
4484 #endif /* !__linux__ */
4485     signal(SIGSEGV, SIG_DFL);
4486     signal(SIGILL, SIG_DFL);
4487 
4488     /*
4489      * Issue appropriate messages and abort or exit.  - FM
4490      */
4491     if (LYOutOfMemory == FALSE) {
4492 	fprintf(stderr, "\r\n\
4493 A Fatal error has occurred in %s Ver. %s\r\n", LYNX_NAME, LYNX_VERSION);
4494 
4495 	fprintf(stderr, "\r\n\
4496 Please notify your system administrator to confirm a bug, and\r\n\
4497 if confirmed, to notify the lynx-dev list.  Bug reports should\r\n\
4498 have concise descriptions of the command and/or URL which causes\r\n\
4499 the problem, the operating system name with version number, the\r\n\
4500 TCPIP implementation, and any other relevant information.\r\n");
4501 
4502 	if (!(sig == 0 && LYNoCore)) {
4503 	    fprintf(stderr, "\r\n\
4504 Do NOT mail the core file if one was generated.\r\n");
4505 	}
4506 	if (sig != 0) {
4507 	    fprintf(stderr, "\r\n\
4508 Lynx now exiting with signal:  %d\r\n\r\n", sig);
4509 #ifdef WIN_EX			/* 1998/08/09 (Sun) 09:58:25 */
4510 	    {
4511 		char *msg;
4512 
4513 		switch (sig) {
4514 		case SIGABRT:
4515 		    msg = "SIGABRT";
4516 		    break;
4517 		case SIGFPE:
4518 		    msg = "SIGFPE";
4519 		    break;
4520 		case SIGILL:
4521 		    msg = "SIGILL";
4522 		    break;
4523 		case SIGSEGV:
4524 		    msg = "SIGSEGV";
4525 		    break;
4526 		default:
4527 		    msg = "Not-def";
4528 		    break;
4529 		}
4530 		fprintf(stderr, "signal code = %s\n", msg);
4531 	    }
4532 #endif
4533 	}
4534 
4535 	/*
4536 	 * Exit and possibly dump core.
4537 	 */
4538 	if (LYNoCore) {
4539 	    exit_immediately(EXIT_FAILURE);
4540 	}
4541 	abort();
4542 
4543     } else {
4544 	LYOutOfMemory = FALSE;
4545 	printf("\r\n%s\r\n\r\n", MEMORY_EXHAUSTED_ABORT);
4546 	fflush(stdout);
4547 
4548 	/*
4549 	 * Exit without dumping core.
4550 	 */
4551 	exit_immediately(EXIT_FAILURE);
4552     }
4553 }
4554 #endif /* !VMS */
4555