about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorThomas E. Dickey <dickey@invisible-island.net>1998-07-31 09:38:29 -0400
committerThomas E. Dickey <dickey@invisible-island.net>1998-07-31 09:38:29 -0400
commite6ba2a01f70f84d9133cf305e4b493c9d656cb21 (patch)
tree264c4d01cf7791c9f77d583f05456a6108df3cdc /src
parentaa3258c631eaca9dc2e7e2590b8778b827006144 (diff)
downloadlynx-snapshots-e6ba2a01f70f84d9133cf305e4b493c9d656cb21.tar.gz
snapshot of project "lynx", label v2-8-1dev_19
Diffstat (limited to 'src')
-rw-r--r--src/HTAlert.c215
-rw-r--r--src/LYCookie.c28
-rw-r--r--src/LYGetFile.c18
-rw-r--r--src/LYGlobalDefs.h1
-rw-r--r--src/LYMail.c2
-rw-r--r--src/LYMain.c41
-rw-r--r--src/LYMainLoop.c56
-rw-r--r--src/LYOptions.c816
-rw-r--r--src/LYOptions.h6
-rw-r--r--src/LYPrint.c5
-rw-r--r--src/LYReadCFG.c24
-rw-r--r--src/LYStrings.c17
-rw-r--r--src/LYStrings.h3
-rw-r--r--src/LYUtils.c31
-rw-r--r--src/LYUtils.h6
-rw-r--r--src/LYexit.c10
-rw-r--r--src/LYrcFile.c18
17 files changed, 1127 insertions, 170 deletions
diff --git a/src/HTAlert.c b/src/HTAlert.c
index c2dba887..3a160ca5 100644
--- a/src/HTAlert.c
+++ b/src/HTAlert.c
@@ -32,13 +32,13 @@ PUBLIC void HTAlert ARGS1(
 	CONST char *,	Msg)
 {
     if (TRACE) {
-        fprintf(tfp, "\nAlert!: %s", Msg);
+	fprintf(tfp, "\nAlert!: %s", Msg);
 	fflush(tfp);
-        _user_message("Alert!: %s", Msg);
-        fprintf(tfp, "\n\n");
+	_user_message("Alert!: %s", Msg);
+	fprintf(tfp, "\n\n");
 	fflush(tfp);
     } else
-        _user_message("Alert!: %s", Msg);
+	_user_message("Alert!: %s", Msg);
 
     sleep(AlertSecs);
 }
@@ -50,9 +50,9 @@ PUBLIC void HTProgress ARGS1(
 	CONST char *,	Msg)
 {
     if (TRACE)
-        fprintf(tfp, "%s\n", Msg);
+	fprintf(tfp, "%s\n", Msg);
     else
-        statusline(Msg);
+	statusline(Msg);
 }
 
 /*	Issue a read-progress message.			HTReadProgress()
@@ -81,7 +81,7 @@ PUBLIC void HTReadProgress ARGS2(
 	/* optimal refresh time: every 0.2 sec */
 	if ((bytes - bytes_last) > (transfer_rate / 5)) {
 
-	    bytes_last += (transfer_rate / 5);  /* until we got next second */
+	    bytes_last += (transfer_rate / 5);	/* until we got next second */
 
 	    if (now != last) {
 		last = now;
@@ -98,7 +98,7 @@ PUBLIC void HTReadProgress ARGS2(
 	    if (total <= 0)
 		sprintf (line, "Read %ld %s of data.", bytes, units);
 	     if (transfer_rate > 0)
-	        sprintf (line + strlen(line), " %ld kb/sec.", transfer_rate / 1024);
+		sprintf (line + strlen(line), " %ld kb/sec.", transfer_rate / 1024);
 	    if (total <  0) {
 		if (total < -1)
 		    strcat(line, " (Press 'z' to abort)");
@@ -169,10 +169,10 @@ PUBLIC char * HTPrompt ARGS2(
 
     _statusline(Msg);
     if (deflt)
-        strncpy(Tmp, deflt, 199);
+	strncpy(Tmp, deflt, 199);
 
     if (!dump_output_immediately)
-        LYgetstr(Tmp, VISIBLE, sizeof(Tmp), NORECALL);
+	LYgetstr(Tmp, VISIBLE, sizeof(Tmp), NORECALL);
 
     StrAllocCopy(rep, Tmp);
 
@@ -192,37 +192,37 @@ PUBLIC char * HTPromptPassword ARGS1(
     pw[0] = '\0';
 
     if (!dump_output_immediately) {
-        _statusline(Msg ? Msg : PASSWORD_PROMPT);
-        LYgetstr(pw, HIDDEN, sizeof(pw), NORECALL); /* hidden */
-        StrAllocCopy(result, pw);
+	_statusline(Msg ? Msg : PASSWORD_PROMPT);
+	LYgetstr(pw, HIDDEN, sizeof(pw), NORECALL); /* hidden */
+	StrAllocCopy(result, pw);
     } else {
-        printf("\n%s\n", PASSWORD_REQUIRED);
+	printf("\n%s\n", PASSWORD_REQUIRED);
 	StrAllocCopy(result, "");
     }
     return result;
 }
 
-/*     	Prompt both username and password.       HTPromptUsernameAndPassword()
-**      ----------------------------------
+/*	Prompt both username and password.	 HTPromptUsernameAndPassword()
+**	----------------------------------
 **
 **  On entry,
-**      Msg             is the prompting message.
-**      *username and
-**      *password       are char pointers which contain default
+**	Msg		is the prompting message.
+**	*username and
+**	*password	are char pointers which contain default
 **			or zero-length strings; they are changed
-**                      to point to result strings.
-**	IsProxy		should be TRUE if this is for
+**			to point to result strings.
+**	IsProxy 	should be TRUE if this is for
 **			proxy authentication.
 **
-**                      If *username is not NULL, it is taken
-**                      to point to a default value.
-**                      Initial value of *password is
-**                      completely discarded.
+**			If *username is not NULL, it is taken
+**			to point to a default value.
+**			Initial value of *password is
+**			completely discarded.
 **
 **  On exit,
-**      *username and *password point to newly allocated
-**      strings -- original strings pointed to by them
-**      are NOT freed.
+**	*username and *password point to newly allocated
+**	strings -- original strings pointed to by them
+**	are NOT freed.
 **
 */
 PUBLIC void HTPromptUsernameAndPassword ARGS4(
@@ -240,7 +240,7 @@ PUBLIC void HTPromptUsernameAndPassword ARGS4(
 	**  and password to use for the first realm or proxy server,
 	**  respectively, so just use them without any prompting. - FM
 	*/
- 	StrAllocCopy(*username, (IsProxy ?
+	StrAllocCopy(*username, (IsProxy ?
 		       proxyauth_info[0] : authentication_info[0]));
 	if (IsProxy) {
 	    FREE(proxyauth_info[0]);
@@ -255,15 +255,15 @@ PUBLIC void HTPromptUsernameAndPassword ARGS4(
 	    FREE(authentication_info[1]);
 	}
     } else if (dump_output_immediately) {
-        /*
+	/*
 	 *  We are not interactive and don't have both the
 	 *  username and password from the command line,
 	 *  but might have one or the other. - FM
 	 */
-        if ((IsProxy == FALSE && authentication_info[0]) ||
+	if ((IsProxy == FALSE && authentication_info[0]) ||
 	    (IsProxy == TRUE && proxyauth_info[0])) {
 	    /*
-	    **  Use the command line username. - FM
+	    **	Use the command line username. - FM
 	    */
 	    StrAllocCopy(*username, (IsProxy ?
 			   proxyauth_info[0] : authentication_info[0]));
@@ -274,14 +274,14 @@ PUBLIC void HTPromptUsernameAndPassword ARGS4(
 	    }
 	} else {
 	    /*
-	    **  Default to "WWWuser". - FM
+	    **	Default to "WWWuser". - FM
 	    */
-            StrAllocCopy(*username, "WWWuser");
+	    StrAllocCopy(*username, "WWWuser");
 	}
-        if ((IsProxy == FALSE && authentication_info[1]) ||
+	if ((IsProxy == FALSE && authentication_info[1]) ||
 	    (IsProxy == TRUE && proxyauth_info[1])) {
 	    /*
-	    **  Use the command line password. - FM
+	    **	Use the command line password. - FM
 	    */
 	    StrAllocCopy(*password, (IsProxy ?
 			   proxyauth_info[1] : authentication_info[1]));
@@ -292,23 +292,23 @@ PUBLIC void HTPromptUsernameAndPassword ARGS4(
 	    }
 	} else {
 	    /*
-	    **  Default to a zero-length string. - FM
+	    **	Default to a zero-length string. - FM
 	    */
 	    StrAllocCopy(*password, "");
 	}
 	printf("\n%s\n", USERNAME_PASSWORD_REQUIRED);
 
     } else {
-        /*
+	/*
 	 *  We are interactive and don't have both the
 	 *  username and password from the command line,
 	 *  but might have one or the other. - FM
 	 */
-        if ((IsProxy == FALSE && authentication_info[0]) ||
+	if ((IsProxy == FALSE && authentication_info[0]) ||
 	    (IsProxy == TRUE && proxyauth_info[0])) {
 	    /*
-	    **  Offer the command line username in the
-	    **  prompt for the first realm. - FM
+	    **	Offer the command line username in the
+	    **	prompt for the first realm. - FM
 	    */
 	    StrAllocCopy(*username, (IsProxy ?
 			   proxyauth_info[0] : authentication_info[0]));
@@ -326,10 +326,10 @@ PUBLIC void HTPromptUsernameAndPassword ARGS4(
 	} else {
 	    *username = HTPrompt(USERNAME_PROMPT, *username);
 	}
-        if ((IsProxy == FALSE && authentication_info[1]) ||
+	if ((IsProxy == FALSE && authentication_info[1]) ||
 	    (IsProxy == TRUE && proxyauth_info[1])) {
 	    /*
-	    **  Use the command line password for the first realm. - FM
+	    **	Use the command line password for the first realm. - FM
 	    */
 	    StrAllocCopy(*password, (IsProxy ?
 			   proxyauth_info[1] : authentication_info[1]));
@@ -340,13 +340,13 @@ PUBLIC void HTPromptUsernameAndPassword ARGS4(
 	    }
 	} else if (*username != NULL && *username[0] != '\0') {
 	    /*
-	    **  We have a non-zero length username,
-	    **  so prompt for the password. - FM
+	    **	We have a non-zero length username,
+	    **	so prompt for the password. - FM
 	    */
 	    *password = HTPromptPassword(PASSWORD_PROMPT);
 	} else {
 	    /*
-	    **  Return a zero-length password. - FM
+	    **	Return a zero-length password. - FM
 	    */
 	    StrAllocCopy(*password, "");
 	}
@@ -368,7 +368,7 @@ PUBLIC void HTPromptUsernameAndPassword ARGS4(
 **		TRUE if the cookie should be set.
 */
 PUBLIC BOOL HTConfirmCookie ARGS4(
-	void *,		dp,
+	void *, 	dp,
 	CONST char *,	server,
 	CONST char *,	name,
 	CONST char *,	value)
@@ -382,57 +382,70 @@ PUBLIC BOOL HTConfirmCookie ARGS4(
 #endif /* VMS */
 
     if ((de = (domain_entry *)dp) == NULL)
-        return FALSE;
+	return FALSE;
 
+#ifdef ENHANCED_COOKIES
+    /*	If the user has specified a list of domains to allow or deny
+    **	from the config file, then they'll already have de->bv set to
+    **	ACCEPT_ALWAYS or REJECT_ALWAYS so we can relax and let the
+    **	default cookie handling code cope with this fine.  I hope.
+    */
+#endif
     /*
-    **  If the user has specified a constant action, don't prompt at all.
+    **	If the user has specified a constant action, don't prompt at all.
     */
     if (de->bv == ACCEPT_ALWAYS || de->bv == FROM_FILE)
-        return TRUE;
+	return TRUE;
     if (de->bv == REJECT_ALWAYS)
-        return FALSE;
+	return FALSE;
 
     if (dump_output_immediately) {
-        /*
+	/*
 	**  Non-interactive, can't respond.  Use the LYSetCookies value
 	*   based on its compilation or configuration setting, or on the
 	**  command line toggle. - FM
 	*/
-        return LYSetCookies;
+	return LYSetCookies;
     }
 
     /*
-    **  Figure out how much of the cookie we can show.
-    **  The '37' is the length of ADVANCED_COOKIE_CONFIRMATION,
-    **  minus the length of the %s directives (10 chars)
+    **	Figure out how much of the cookie we can show.
+    **	The '37' is the length of ADVANCED_COOKIE_CONFIRMATION,
+    **	minus the length of the %s directives (10 chars)
     */
     if (de != NULL) {
-        if (de->bv == ACCEPT_ALWAYS)
+	if (de->bv == ACCEPT_ALWAYS)
 	    return TRUE;
 	if (de->bv == REJECT_ALWAYS)
 	    return FALSE;
     }
     space_free = (((LYcols - 1) - 37) - strlen(server));
     if (space_free < 0)
-        space_free = 0;
+	space_free = 0;
     namelen = strlen(name);
     valuelen = strlen(value);
     if ((namelen + valuelen) > space_free) {
-        /*
+	/*
 	**  Argh... there isn't enough space on our single line for
 	**  the whole cookie.  Reduce them both by a percentage.
 	**  This should be smarter.
 	*/
-        float percentage;
-        percentage = (float)space_free/(float)(namelen + valuelen);
-        namelen = (int)(percentage*(float)namelen);
-        valuelen = (int)(percentage*(float)valuelen);
+	float percentage;
+	percentage = (float)space_free/(float)(namelen + valuelen);
+	namelen = (int)(percentage*(float)namelen);
+	valuelen = (int)(percentage*(float)valuelen);
+    }
+    if(!LYEatAllCookies) {
+	sprintf(message, ADVANCED_COOKIE_CONFIRMATION,
+		server, namelen, name, valuelen, value);
+	_statusline(message);
     }
-    sprintf(message, ADVANCED_COOKIE_CONFIRMATION,
-    	    server, namelen, name, valuelen, value);
-    _statusline(message);
     while (1) {
-	ch = LYgetch();
+	if(!LYEatAllCookies) {
+	    ch = LYgetch();
+	} else {
+	    ch = 'A';
+	}
 #ifdef VMS
 	if (HadVMSInterrupt) {
 	    HadVMSInterrupt = FALSE;
@@ -441,7 +454,7 @@ PUBLIC BOOL HTConfirmCookie ARGS4(
 #endif /* VMS */
 	switch(TOUPPER(ch)) {
 	    case 'A':
-	        /*
+		/*
 		**  Set to accept all cookies for this domain.
 		*/
 		de->bv = ACCEPT_ALWAYS;
@@ -452,15 +465,15 @@ PUBLIC BOOL HTConfirmCookie ARGS4(
 	    case 'N':
 	    case 7:	/* Ctrl-G */
 	    case 3:	/* Ctrl-C */
-	        /*
+		/*
 		**  Reject the cookie.
 		*/
 		_statusline(REJECTING_COOKIE);
 		sleep(MessageSecs);
 		return FALSE;
 
-    	    case 'V':
-	        /*
+	    case 'V':
+		/*
 		**  Set to reject all cookies from this domain.
 		*/
 		de->bv = REJECT_ALWAYS;
@@ -469,7 +482,7 @@ PUBLIC BOOL HTConfirmCookie ARGS4(
 		return FALSE;
 
 	    case 'Y':
-	        /*
+		/*
 		**  Accept the cookie.
 		*/
 		_statusline(ALLOWING_COOKIE);
@@ -477,20 +490,20 @@ PUBLIC BOOL HTConfirmCookie ARGS4(
 		return TRUE;
 
 	    default:
-	        continue;
+		continue;
 	}
     }
 }
 
-/*      Confirm redirection of POST.		HTConfirmPostRedirect()
+/*	Confirm redirection of POST.		HTConfirmPostRedirect()
 **	----------------------------
 **
 **  On entry,
-**      Redirecting_url             is the Location.
+**	Redirecting_url 	    is the Location.
 **	server_status		    is the server status code.
 **
 **  On exit,
-**      Returns 0 on cancel,
+**	Returns 0 on cancel,
 **	  1 for redirect of POST with content,
 **	303 for redirect as GET without content
 */
@@ -502,11 +515,11 @@ PUBLIC int HTConfirmPostRedirect ARGS2(
     char StatusInfo[256];
     char url[256];
     int on_screen = 0;	/* 0 - show menu
-   			 * 1 - show url
+			 * 1 - show url
 			 * 2 - menu is already on screen */
 
     if (server_status == 303 ||
-        server_status == 302) {
+	server_status == 302) {
 	/*
 	 *  HTTP.c should not have called us for either of
 	 *  these because we're treating 302 as historical,
@@ -516,17 +529,17 @@ PUBLIC int HTConfirmPostRedirect ARGS2(
     }
 
     if (dump_output_immediately) {
-        if (server_status == 301) {
+	if (server_status == 301) {
 	    /*
-	    **  Treat 301 as historical, i.e., like 303 (GET
-	    **  without content), when not interactive. - FM
+	    **	Treat 301 as historical, i.e., like 303 (GET
+	    **	without content), when not interactive. - FM
 	    */
-            return 303;
-        } else {
+	    return 303;
+	} else {
 	    /*
-	    **  Treat anything else (e.g., 305, 306 or 307) as too
-	    **  dangerous to redirect without confirmation, and thus
-	    **  cancel when not interactive. - FM
+	    **	Treat anything else (e.g., 305, 306 or 307) as too
+	    **	dangerous to redirect without confirmation, and thus
+	    **	cancel when not interactive. - FM
 	    */
 	    return 0;
 	}
@@ -535,15 +548,15 @@ PUBLIC int HTConfirmPostRedirect ARGS2(
     StatusInfo[254] = StatusInfo[255] = '\0';
     url[254] = url[(LYcols < 250 ? LYcols-1 : 255)] = '\0';
     if (user_mode == NOVICE_MODE) {
-        on_screen = 2;
-        move(LYlines-2, 0);
-        sprintf(StatusInfo, SERVER_ASKED_FOR_REDIRECTION, server_status);
+	on_screen = 2;
+	move(LYlines-2, 0);
+	sprintf(StatusInfo, SERVER_ASKED_FOR_REDIRECTION, server_status);
 	addstr(StatusInfo);
 	clrtoeol();
-        move(LYlines-1, 0);
+	move(LYlines-1, 0);
 	sprintf(url, "URL: %.*s",
 		    (LYcols < 250 ? LYcols-6 : 250), Redirecting_url);
-        addstr(url);
+	addstr(url);
 	clrtoeol();
 	if (server_status == 301) {
 	    _statusline(PROCEED_GET_CANCEL);
@@ -568,7 +581,7 @@ PUBLIC int HTConfirmPostRedirect ARGS2(
 		_statusline(StatusInfo);
 		break;
 	    case 1:
-	        _statusline(show_POST_url);
+		_statusline(show_POST_url);
 	}
 	c = LYgetch();
 	switch (TOUPPER(c)) {
@@ -577,22 +590,22 @@ PUBLIC int HTConfirmPostRedirect ARGS2(
 		**  Proceed with 301 or 307 redirect of POST
 		**  with same method and POST content. - FM
 		*/
-	        FREE(show_POST_url);
+		FREE(show_POST_url);
 		return 1;
 
- 	    case 7:
- 	    case 'C':
-	        /*
+	    case 7:
+	    case 'C':
+		/*
 		**  Cancel request.
 		*/
-	        FREE(show_POST_url);
+		FREE(show_POST_url);
 		return 0;
 
 	    case 'U':
-	        /*
+		/*
 		**  Show URL for intermediate or advanced mode.
 		*/
-	        if (user_mode != NOVICE_MODE) {
+		if (user_mode != NOVICE_MODE) {
 		    if (on_screen == 1) {
 			on_screen = 0;
 		    } else {
@@ -604,7 +617,7 @@ PUBLIC int HTConfirmPostRedirect ARGS2(
 	    case 'G':
 		if (server_status == 301) {
 		    /*
-		    **  Treat as 303 (GET without content).
+		    **	Treat as 303 (GET without content).
 		    */
 		    FREE(show_POST_url);
 		    return 303;
@@ -612,7 +625,7 @@ PUBLIC int HTConfirmPostRedirect ARGS2(
 		/* fall through to default */
 
 	    default:
-	        /*
+		/*
 		**  Get another character.
 		*/
 		if (on_screen == 1) {
diff --git a/src/LYCookie.c b/src/LYCookie.c
index e4937e33..c1979941 100644
--- a/src/LYCookie.c
+++ b/src/LYCookie.c
@@ -358,6 +358,8 @@ PRIVATE void store_cookie ARGS3(
 				strlen(INVALID_COOKIE_DOMAIN_CONFIRMATION) +
 				1));
 
+	    if (msg == 0)
+	    	outofmem(__FILE__, "store_cookie");
 	    sprintf(msg,
 		    INVALID_COOKIE_DOMAIN_CONFIRMATION,
 		    co->domain,
@@ -1829,16 +1831,16 @@ PUBLIC char * LYCookie ARGS4(
     return(NULL);
 }
 
-/* rjp - experiment cookie loading */
 #ifdef EXP_PERSISTENT_COOKIES
+/* rjp - experiment cookie loading */
 PUBLIC void LYLoadCookies ARGS1 (
 	CONST char *,	cookie_file)
 {
     FILE *cookie_handle;
     char buf[5000]; /* should be long enough for a cookie line */
-    char domain[256], path[256], name[256], value[4100];
-    char what[8], secure[8], expires_a[16];
-    int expires;
+    static char domain[256], path[256], name[256], value[4100];
+    static char what[8], secure[8], expires_a[16];
+    time_t expires;
 
     cookie_handle = fopen(cookie_file, "r+");
     if (!cookie_handle)
@@ -1863,10 +1865,9 @@ PUBLIC void LYLoadCookies ARGS1 (
 	 * what kind of platform problems this might introduce. - RP
 	 */
 	tok_ptr = buf;
-	tok_out = strsep(&tok_ptr, "\t");
+	tok_out = LYstrsep(&tok_ptr, "\t");
 	for (tok_loop = 0; tok_out && tok_values[tok_loop]; tok_loop++) {
-	if (TRACE)
-	fprintf(stderr, ">%d:%p:%p:[%s]:%s\n",
+	CTRACE(tfp, ">%d:%p:%p:[%s]:%s\n",
 	    tok_loop, tok_values[tok_loop], tok_out, tok_out, buf);
 	    strcpy(tok_values[tok_loop], tok_out);
 	    /*
@@ -1875,9 +1876,10 @@ PUBLIC void LYLoadCookies ARGS1 (
 	     * like "FALSE\t\tFALSE\t" translates to FALSE,FALSE
 	     * instead of FALSE,,FALSE. - RP
 	     */
-	    tok_out = strsep(&tok_ptr, "\t");
+	    tok_out = LYstrsep(&tok_ptr, "\t");
 	}
-	expires = atoi(expires_a);
+	expires = atol(expires_a);
+	fprintf(stderr, "COOKIE: expires %s\n", ctime(&expires));
 
 	/*
 	 * This fails when the path is blank
@@ -1886,9 +1888,8 @@ PUBLIC void LYLoadCookies ARGS1 (
 	 *  domain, what, path, secure, &expires, name, value);
 	 */
 
-	if (TRACE)
-	fprintf(stderr, "%s\t%s\t%s\t%s\t%d\t%s\t%s\tREADCOOKIE\n",
-	    domain, what, path, secure, expires, name, value);
+	CTRACE(tfp, "%s\t%s\t%s\t%s\t%ld\t%s\t%s\tREADCOOKIE\n",
+	    domain, what, path, secure, (long) expires, name, value);
 	moo = newCookie();
 	StrAllocCopy(moo->domain, domain);
 	StrAllocCopy(moo->path, path);
@@ -1896,6 +1897,7 @@ PUBLIC void LYLoadCookies ARGS1 (
 	StrAllocCopy(moo->value, value);
 	moo->pathlen = strlen(moo->path);
 	moo->flags |= COOKIE_FLAG_PERSISTENT;
+	moo->expires = expires;
 	/*
 	 * I don't like using this to store the cookies because it's
 	 * designed to store cookies that have been received from an
@@ -1920,6 +1922,7 @@ PRIVATE void LYStoreCookies ARGS1 (
 #ifdef VMS
     extern BOOLEAN HadVMSInterrupt;
 #endif /* VMS */
+    time_t now = time(NULL); /* system specific? - RP */
 
     /*
      *	Check whether we have something to do. - FM
@@ -1963,6 +1966,7 @@ PRIVATE void LYStoreCookies ARGS1 (
 	    if ((co = (cookie *)cl->object) == NULL)
 		continue;
 
+	    CTRACE(tfp, "COOKIE: %ld cf %ld\n", (long) now, (long) co->expires);
 	    fprintf(cookie_handle, "%s\t%s\t%s\t%s\t%ld\t%s\t%s\n",
 		de->domain,
 		"FALSE", co->path,
diff --git a/src/LYGetFile.c b/src/LYGetFile.c
index 96063576..28bac09e 100644
--- a/src/LYGetFile.c
+++ b/src/LYGetFile.c
@@ -14,6 +14,7 @@
 #include <LYSignal.h>
 #include <LYGetFile.h>
 #include <LYPrint.h>
+#include <LYOptions.h>
 #include <LYHistory.h>
 #include <LYStrings.h>
 #include <LYClean.h>
@@ -221,6 +222,7 @@ Try_Redirected_URL:
 			  url_type == LYNXIMGMAP_URL_TYPE ||
 			  url_type == LYNXCOOKIE_URL_TYPE ||
 			  url_type == LYNXPRINT_URL_TYPE ||
+			  url_type == LYNXOPTIONS_URL_TYPE ||
 			  url_type == LYNXDOWNLOAD_URL_TYPE ||
 			  url_type == MAILTO_URL_TYPE ||
 			  url_type == NEWSPOST_URL_TYPE ||
@@ -254,6 +256,7 @@ Try_Redirected_URL:
 		    url_type != GOPHER_URL_TYPE &&
 		    url_type != CSO_URL_TYPE &&
 		    url_type != PROXY_URL_TYPE &&
+		    url_type != LYNXOPTIONS_URL_TYPE &&
 		    !(url_type == FILE_URL_TYPE &&
 		      *(LYlist_temp_url()) &&
 		      !strncmp(WWWDoc.address, LYlist_temp_url(),
@@ -283,6 +286,9 @@ Try_Redirected_URL:
 		} else if (url_type == LYNXPRINT_URL_TYPE) {
 		    return(printfile(doc));
 
+		} else if (url_type == LYNXOPTIONS_URL_TYPE) {
+		    return(postoptions(doc));
+
 		} else if (url_type == NEWSPOST_URL_TYPE ||
 			   url_type == NEWSREPLY_URL_TYPE ||
 			   url_type == SNEWSPOST_URL_TYPE ||
@@ -429,6 +435,10 @@ Try_Redirected_URL:
 			/*
 			 *  Run the command.
 			 */
+#ifdef __DJGPP__
+			__djgpp_set_ctrl_c(0);
+			_go32_want_ctrl_break(1);
+#endif /* __DJGPP__ */
 			if (strstr(p,"//") == p+9)
 			    system(p+11);
 			else
@@ -442,13 +452,21 @@ Try_Redirected_URL:
 #endif /* !VMS */
 			    printf("\n%s", RETURN_TO_LYNX);
 			    fflush(stdout);
+#ifdef DJGPP_KEYHANDLER
+			    getxkey();
+#else
 			    LYgetch();
+#endif /* DJGPP_KEYHANDLER */
 #ifdef VMS
 			    {
 			      extern BOOLEAN HadVMSInterrupt;
 			      HadVMSInterrupt = FALSE;
 			    }
 #endif /* VMS */
+#ifdef __DJGPP__
+			    __djgpp_set_ctrl_c(1);
+			    _go32_want_ctrl_break(0);
+#endif /* __DJGPP__ */
 			}
 			start_curses();
 			LYAddVisitedLink(doc);
diff --git a/src/LYGlobalDefs.h b/src/LYGlobalDefs.h
index 85ebc101..a66dc1af 100644
--- a/src/LYGlobalDefs.h
+++ b/src/LYGlobalDefs.h
@@ -285,6 +285,7 @@ extern BOOLEAN LYMBMAdvanced;		/* MBM statusline for ADVANCED?	 */
 extern int LYStatusLine;		/* Line for statusline() or -1   */
 extern BOOLEAN LYCollapseBRs;		/* Collapse serial BRs?		 */
 extern BOOLEAN LYSetCookies;		/* Process Set-Cookie headers?	 */
+extern BOOLEAN LYEatAllCookies;         /* accept ALL cookies?          */
 extern char *XLoadImageCommand;		/* Default image viewer for X	 */
 #ifdef USE_EXTERNALS
 extern BOOLEAN no_externals; /* don't allow the use of externals */
diff --git a/src/LYMail.c b/src/LYMail.c
index 94b38c74..50c78f19 100644
--- a/src/LYMail.c
+++ b/src/LYMail.c
@@ -1252,7 +1252,7 @@ PUBLIC void reply_by_mail ARGS3(
         StrAllocCat(header, "mailto:");
         StrAllocCat(header, address);
     }
-    StrAllocCat(header, buf);
+    StrAllocCat(header, "\n");
     sprintf(buf, "X-Mailer: Lynx, Version %s\n", LYNX_VERSION);
     StrAllocCat(header, buf);
 #endif /* VMS */
diff --git a/src/LYMain.c b/src/LYMain.c
index 65687a51..3651f0cc 100644
--- a/src/LYMain.c
+++ b/src/LYMain.c
@@ -81,23 +81,7 @@ PUBLIC BOOLEAN UseFixedRecords = USE_FIXED_RECORDS;
 
 #ifndef VMS
 PUBLIC char *lynx_version_putenv_command = NULL;
-PUBLIC char *NNTPSERVER_putenv_cmd = NULL;   /* lynx.cfg defined NNTPSERVER */
-PUBLIC char *http_proxy_putenv_cmd = NULL;   /* lynx.cfg defined http_proxy */
-PUBLIC char *https_proxy_putenv_cmd = NULL;  /* lynx.cfg defined https_proxy */
-PUBLIC char *ftp_proxy_putenv_cmd = NULL;    /* lynx.cfg defined ftp_proxy */
-PUBLIC char *gopher_proxy_putenv_cmd = NULL; /* lynx.cfg defined gopher_proxy */
-PUBLIC char *cso_proxy_putenv_cmd = NULL;    /* lynx.cfg defined cso_proxy */
-PUBLIC char *news_proxy_putenv_cmd = NULL;   /* lynx.cfg defined news_proxy */
-PUBLIC char *newspost_proxy_putenv_cmd = NULL;
-PUBLIC char *newsreply_proxy_putenv_cmd = NULL;
-PUBLIC char *snews_proxy_putenv_cmd = NULL;  /* lynx.cfg defined snews_proxy */
-PUBLIC char *snewspost_proxy_putenv_cmd = NULL;
-PUBLIC char *snewsreply_proxy_putenv_cmd = NULL;
-PUBLIC char *nntp_proxy_putenv_cmd = NULL;   /* lynx.cfg defined nntp_proxy */
-PUBLIC char *wais_proxy_putenv_cmd = NULL;   /* lynx.cfg defined wais_proxy */
-PUBLIC char *finger_proxy_putenv_cmd = NULL; /* lynx.cfg defined finger_proxy */
-PUBLIC char *no_proxy_putenv_cmd = NULL;     /* lynx.cfg defined no_proxy */
-PUBLIC char *list_format=NULL;		/* LONG_LIST formatting mask */
+PUBLIC char *list_format = NULL;	/* LONG_LIST formatting mask */
 #ifdef SYSLOG_REQUESTED_URLS
 PUBLIC char *syslog_txt = NULL; 	/* syslog arb text for session */
 #endif /* SYSLOG_REQUESTED_URLS */
@@ -352,6 +336,7 @@ PUBLIC BOOLEAN LYMBMAdvanced = TRUE;
 PUBLIC int LYStatusLine = -1;		 /* Line for statusline() if > -1 */
 PUBLIC BOOLEAN LYCollapseBRs = COLLAPSE_BR_TAGS;  /* Collapse serial BRs? */
 PUBLIC BOOLEAN LYSetCookies = SET_COOKIES; /* Process Set-Cookie headers? */
+PUBLIC BOOLEAN LYEatAllCookies = EAT_ALL_COOKIES; /* take all cookies?    */
 PUBLIC char *XLoadImageCommand = NULL;	/* Default image viewer for X */
 PUBLIC BOOLEAN LYNoISMAPifUSEMAP = FALSE; /* Omit ISMAP link if MAP present? */
 PUBLIC int LYHiddenLinks = HIDDENLINKS_SEPARATE; /* Show hidden links? */
@@ -925,7 +910,7 @@ PUBLIC int main ARGS2(
 		    cp = LYSkipNonBlanks(buf);
 		    cp = LYSkipBlanks(cp);
 		    if (*cp)
-			StrAllocCopy(lynx_cfg_file, cp);
+			StrAllocCopy(lynx_lss_file, cp);
 		}
 		CTRACE(tfp, "LYMain found -lss flag, lss file is %s\n",
 			lynx_lss_file ? lynx_lss_file : "<NONE>");
@@ -1525,14 +1510,14 @@ PUBLIC int main ARGS2(
      */
     HTMLUseCharacterSet(current_char_set);
 
-#ifdef EXP_PERSISTENT_COOKIES 
-    /* 
-     *	Sod it, this looks like a reasonable place to load the 
-     *	cookies file, probably.  - RP 
-     */ 
-    LYLoadCookies("cookies"); /* add command line options! */ 
+#ifdef EXP_PERSISTENT_COOKIES
+    /*
+     *	Sod it, this looks like a reasonable place to load the
+     *	cookies file, probably.  - RP
+     */
+    LYLoadCookies("cookies"); /* add command line options! */
 #endif
-	 
+
     /*
      *	If startfile is a file URL and the host is defaulted,
      *	force in "//localhost", and if it's not an absolute URL,
@@ -2623,6 +2608,10 @@ with -dump, format output as with -traversal, but to stdout"
       "dump",		FUNCTION_ARG,		dump_output_fun,
       "dump the first file to stdout and exit"
    ),
+   PARSE_SET(
+      "eat_all_cookies", SET_ARG,		&LYEatAllCookies,
+      "accepts all cookies"
+   ),
    PARSE_FUN(
       "editor", 	NEED_FUNCTION_ARG,	editor_fun,
       "=EDITOR\nenable edit mode with specified editor"
@@ -2725,7 +2714,7 @@ keys (may be incompatible with some curses packages)"
 #if defined(USE_HASH)
    PARSE_STR(
       "lss",		IGNORE_ARG|NEED_NEXT_ARG,	0,
-      "=FILENAME\nspecifies a lynx.css file other than the default"
+      "=FILENAME\nspecifies a lynx.lss file other than the default"
    ),
 #endif
    PARSE_FUN(
diff --git a/src/LYMainLoop.c b/src/LYMainLoop.c
index fa01fdbe..a232be02 100644
--- a/src/LYMainLoop.c
+++ b/src/LYMainLoop.c
@@ -205,15 +205,17 @@ int mainloop NOARGS
     BOOLEAN rlink_allowed;
     BOOLEAN vi_keys_flag = vi_keys;
     BOOLEAN emacs_keys_flag = emacs_keys;
+    BOOLEAN LYRawMode_flag = LYRawMode;
+#ifndef EXP_FORMS_OPTIONS
+    BOOLEAN LYSelectPopups_flag = LYSelectPopups;
     BOOLEAN keypad_mode_flag = keypad_mode;
+    BOOLEAN show_dotfiles_flag = show_dotfiles;
     BOOLEAN user_mode_flag = user_mode;
-    int HTfileSortMethod_flag = HTfileSortMethod;
-    int CurrentCharSet_flag = current_char_set;
     int CurrentAssumeCharSet_flag = UCLYhndl_for_unspec;
     int CurrentAssumeLocalCharSet_flag = UCLYhndl_HTFile_for_unspec;
-    BOOLEAN show_dotfiles_flag = show_dotfiles;
-    BOOLEAN LYRawMode_flag = LYRawMode;
-    BOOLEAN LYSelectPopups_flag = LYSelectPopups;
+    int CurrentCharSet_flag = current_char_set;
+    int HTfileSortMethod_flag = HTfileSortMethod;
+#endif
     BOOLEAN trace_mode_flag = FALSE;
     BOOLEAN forced_HTML_mode = LYforce_HTML_mode;
 #ifdef DISP_PARTIAL
@@ -232,6 +234,7 @@ int mainloop NOARGS
     char *temp = NULL;
     BOOLEAN ForcePush = FALSE;
     BOOLEAN override_LYresubmit_posts = FALSE;
+    BOOLEAN was_in_options = FALSE;
     unsigned int len;
     int i;
 
@@ -378,7 +381,12 @@ try_again:
 		     *	elements to the curdoc structure elements
 		     *	under case NORMAL.  - FM
 		     */
+#ifndef EXP_FORMS_OPTIONS
 		    if (strncmp(newdoc.address, "LYNXDOWNLOAD:", 13)) {
+#else /* EXP_FORMS_OPTIONS */
+		    if (strncmp(newdoc.address, "LYNXDOWNLOAD:", 13) &&
+			strncmp(newdoc.address, "LYNXOPTIONS:", 12)) {
+#endif /* EXP_FORMS_OPTIONS */
 			LYpush(&curdoc, ForcePush);
 		    }
 		} else if (!newdoc.address) {
@@ -679,6 +687,12 @@ try_again:
 			trace_mode_flag = FALSE;
 			fprintf(tfp, "Turning TRACE back on.\n\n");
 		    }
+#ifdef EXP_FORMS_OPTIONS
+		    if (newdoc.address) {
+			was_in_options =
+			    (!strncmp(newdoc.address, "LYNXOPTIONS:", 12));
+		    }
+#endif /* LD_OPTIONS */
 		    FREE(newdoc.address); /* to pop last doc */
 		    FREE(newdoc.bookmark);
 		    LYJumpFileURL = FALSE;
@@ -3641,6 +3655,7 @@ check_goto_URL:
 	    } else if (!strncmp(user_input_buffer, "LYNXCOOKIE:", 11) ||
 		       !strncmp(user_input_buffer, "LYNXDIRED:", 10) ||
 		       !strncmp(user_input_buffer, "LYNXDOWNLOAD:", 13) ||
+		       !strncmp(user_input_buffer, "LYNXOPTIONS:", 12) ||
 		       !strncmp(user_input_buffer, "LYNXPRINT:", 10)) {
 		_statusline(GOTO_SPECIAL_DISALLOWED);
 		sleep(MessageSecs);
@@ -3802,6 +3817,7 @@ check_goto_URL:
 #ifdef DIRED_SUPPORT
 	    c = dir_list_style;
 #endif /* DIRED_SUPPORT */
+#ifndef EXP_FORMS_OPTIONS
 	    options(); /* do the options stuff */
 
 	    if (keypad_mode_flag != keypad_mode ||
@@ -3901,6 +3917,32 @@ check_goto_URL:
 	    StrAllocCopy(CurrentNegoCharset, (pref_charset ?
 					      pref_charset : ""));
 	    refresh_screen = TRUE; /* to repaint screen */
+#else /* EXP_FORMS_OPTIONS */
+	    /*
+	     * FIXME: Blatantly stolen from LYK_PRINT below.
+	     * how much is really valid here?  I don't know the
+	     * innards well enough. MRC
+	     */
+	    /*
+	     *	Don't do if already viewing options page.
+	     */
+	    if (strcmp((curdoc.title ? curdoc.title : ""),
+		       OPTIONS_TITLE)) {
+
+		if (gen_options(&newdoc.address) < 0)
+		    break;
+		StrAllocCopy(newdoc.title, OPTIONS_TITLE);
+		FREE(newdoc.post_data);
+		FREE(newdoc.post_content_type);
+		FREE(newdoc.bookmark);
+		newdoc.isHEAD = FALSE;
+		newdoc.safe = FALSE;
+		ForcePush = TRUE;
+		if (check_realm)
+		    LYPermitURL = TRUE;
+		refresh_screen = TRUE;	/* redisplay */
+	    }
+#endif /* EXP_FORMS_OPTIONS */
 	    break;
 
 	case LYK_INDEX_SEARCH: /* search for a user string */
@@ -4707,6 +4749,8 @@ check_goto_URL:
 		  strncmp(links[curdoc.link].lname,
 			 "LYNXCOOKIE:", 11) &&
 		  strncmp(links[curdoc.link].lname,
+			 "LYNXOPTIONS:", 12) &&
+		  strncmp(links[curdoc.link].lname,
 			 "LYNXLIST:", 9)))) {
 		if (nlinks > 0) {
 		    if (curdoc.post_data == NULL &&
@@ -5061,6 +5105,8 @@ check_add_bookmark_to_self:
 			   !strncmp(links[curdoc.link].lname,
 				    "LYNXPRINT:", 10) ||
 			   !strncmp(links[curdoc.link].lname,
+				    "LYNXOPTIONS:", 12) ||
+			   !strncmp(links[curdoc.link].lname,
 				    "lynxexec:", 9) ||
 			   !strncmp(links[curdoc.link].lname,
 				    "lynxprog:", 9)) {
diff --git a/src/LYOptions.c b/src/LYOptions.c
index d4a20f8d..62f1c367 100644
--- a/src/LYOptions.c
+++ b/src/LYOptions.c
@@ -18,6 +18,7 @@
 #include <HTAlert.h>
 #include <LYBookmark.h>
 #include <GridText.h>
+#include <LYGetFile.h>
 
 #include <LYLeaks.h>
 
@@ -3104,3 +3105,818 @@ restore_popup_statusline:
 	return(cur_choice);
     }
 }
+
+/*
+ * I'm paranoid about mistyping strings.  Also, this way they get combined
+ * so we don't have to worry about the intelligence of the compiler.
+ * We don't need to burn memory like it's cheap.  We're better than that.
+ */
+static char * selected_string = "selected";
+static char * disabled_string = "disabled";
+static char * label_string = "label";
+static char * on_string = "ON";
+static char * off_string = "OFF";
+static char * never_string = "NEVER";
+static char * always_string = "ALWAYS";
+static char * empty_string = "";
+
+static char * secure_string = "secure";
+static char * secure_value = NULL;
+
+static char * editor_string = "editor";
+
+static char * display_string = "display";
+
+static char * ftp_sort_string = "ftp_sort";
+static char * ftp_by_name_string = "ftp_by_name";
+static char * ftp_by_type_string = "ftp_by_type";
+static char * ftp_by_size_string = "ftp_by_size";
+static char * ftp_by_date_string = "ftp_by_date";
+
+static char * mail_address_string = "mail_address";
+
+static char * save_options_string = "save_options";
+
+static char * search_type_string = "search_type";
+static char * search_case_insensitive_string = "case_insensitive";
+static char * search_case_sensitive_string = "case_sensitive";
+
+static char * prefered_doc_lang_string = "prefered_doc_lang";
+
+static char * prefered_doc_char_string = "prefered_doc_char";
+
+static char * assume_char_set_string = "assume_char_set";
+
+static char * display_char_set_string = "display_char_set";
+
+static char * raw_mode_string = "raw_mode";
+
+static char * show_color_string = "show_color";
+
+static char * vi_keys_string = "vi_keys";
+
+static char * emacs_keys_string = "emacs_keys";
+
+static char * show_dotfiles_string = "show_dotfiles";
+
+static char * select_popups_string = "select_popups";
+
+static char * show_cursor_string = "show_cursor";
+
+static char * keypad_mode_string = "keypad_mode";
+static char * number_arrows_string = "number_arrows";
+static char * links_numbered_string = "links_numbered";
+static char * links_and_forms_string = "links_and_forms";
+
+static char * dired_sort_string = "dired_sort";
+static char * dired_dir_string = "dired_dir";
+static char * dired_files_string = "dired_files";
+static char * dired_mixed_string = "dired_mixed";
+
+static char * user_mode_string = "user_mode";
+static char * user_novice = "Novice";
+static char * user_intermediate = "Intermediate";
+static char * user_advanced = "Advanced";
+
+struct post_pair {
+    char * tag;
+    char * value;
+};
+
+/*
+ * Break cgi line into array of pairs of pointers.  Don't bother trying to
+ * be efficient.  We're not called all that often.
+ * We come in with a string looking like:
+ * tag1=value1&tag2=value2&...&tagN=valueN
+ * We leave with an array of post_pairs.  The last element in the array
+ * will have a tag pointing to NULL.
+ * Not pretty, but works.  Hey, if strings can be null terminate arrays...
+ */
+
+PRIVATE struct post_pair * break_data ARGS1(
+    char *,	data)
+{
+    char * p = data;
+    struct post_pair * q = NULL;
+    int count = 0;
+
+    if (p==NULL || p[0]=='\0')
+	return NULL;
+
+    q = calloc(sizeof(struct post_pair), 1);
+    if (q==NULL)
+	outofmem(__FILE__, "break_data(calloc)");
+
+    do {
+	/*
+	 * First, break up on '&', sliding 'p' on down the line.
+	 */
+	q[count].value = LYstrsep(&p, "&");
+	/*
+	 * Then break up on '=', sliding value down, and setting tag.
+	 */
+	q[count].tag = LYstrsep(&(q[count].value), "=");
+
+	/*
+	 * Clean them up a bit, in case user entered a funky string.
+	 */
+	HTUnEscape(q[count].tag);
+	HTUnEscape(q[count].value);
+
+	count++;
+	/*
+	 * Like I said, screw effeciency.  Sides, realloc is fast on
+	 * Linux ;->
+	 */
+	q = realloc(q, sizeof(struct post_pair)*(count+1));
+	if (q==NULL)
+	    outofmem(__FILE__, "break_data(realloc)");
+	q[count].tag=NULL;
+    } while (p!=NULL && p[0]!='\0');
+    return q;
+}
+
+/*
+ * Handle options from the pseudo-post.  I think we really only need
+ * post_data here, but bring along everything just in case.  It's only a
+ * pointer.  MRC
+ */
+
+PUBLIC int postoptions ARGS1(
+    document *,		newdoc)
+{
+    struct post_pair *data;
+    int i;
+    BOOLEAN save_all = FALSE;
+
+    data = break_data(newdoc->post_data);
+
+    /*
+     * This is just plain ugly.  Perhaps someone will have the will power
+     * to do this programmatically?  MRC
+     */
+    for (i = 0; data[i].tag != NULL; i++) {
+	/*
+	 * Paranoid security.
+	 */
+	if (!strcmp(data[i].tag, secure_string)) {
+	    if (!secure_value || strcmp(data[i].value, secure_value)) {
+		/*
+		 * FIXME: We've been spoofed message here.
+		 */
+		FREE(data);
+		return(NULLFILE);
+	    }
+	    FREE(secure_value);
+	}
+
+	/*
+	 * editor
+	 */
+	if (!strcmp(data[i].tag, editor_string)) {
+	    FREE(editor);
+	    StrAllocCopy(editor, data[i].value);
+	}
+
+	/*
+	 * display
+	 */
+	if (!strcmp(data[i].tag, display_string)) {
+	    FREE(display);
+	    StrAllocCopy(display, data[i].value);
+	}
+
+	/*
+	 * ftp sort
+	 */
+	if (!strcmp(data[i].tag, ftp_sort_string)) {
+	    if (!strcmp(data[i].value, ftp_by_name_string)) {
+		HTfileSortMethod = FILE_BY_NAME;
+	    } else if (!strcmp(data[i].value, ftp_by_type_string)) {
+		HTfileSortMethod = FILE_BY_TYPE;
+	    } else if (!strcmp(data[i].value, ftp_by_size_string)) {
+		HTfileSortMethod = FILE_BY_SIZE;
+	    } else if (!strcmp(data[i].value, ftp_by_date_string)) {
+		HTfileSortMethod = FILE_BY_DATE;
+	    }
+	}
+
+	/*
+	 * mail_address
+	 */
+	if (!strcmp(data[i].tag, mail_address_string)) {
+	    FREE(personal_mail_address);
+	    StrAllocCopy(personal_mail_address, data[i].value);
+	}
+
+	/*
+	 * search_type
+	 */
+	if (!strcmp(data[i].tag, search_type_string)) {
+	    if (!strcmp(data[i].value, search_case_insensitive_string)) {
+		case_sensitive = FALSE;
+	    } else if (!strcmp(data[i].value, search_case_sensitive_string)) {
+		case_sensitive = TRUE;
+	    }
+	}
+
+	/*
+	 * prefered_doc_lang
+	 */
+	if (!strcmp(data[i].tag, prefered_doc_lang_string)) {
+	    FREE(language);
+	    StrAllocCopy(language, data[i].value);
+	}
+
+	/*
+	 * prefered_doc_char
+	 */
+	if (!strcmp(data[i].tag, prefered_doc_lang_string)) {
+	    FREE(pref_charset);
+	    StrAllocCopy(pref_charset, data[i].value);
+	}
+
+	/*
+	 * assume_char_set
+	 */
+	if (!strcmp(data[i].tag, assume_char_set_string)) {
+	    int newval;
+
+	    newval = UCGetLYhndl_byMIME(data[i].value);
+	    /*
+	     *  Set the raw 8-bit or CJK mode defaults and
+	     *  character set if changed. - FM
+	     */
+	    /*
+	     * FIXME: I have no clue if I got this right.  Since this is
+	     * forms based, we should probably flag that we may have
+	     * changed something here, then when we're done, check to see
+	     * if the user also changed RAW mode.  If they did, take what
+	     * they set, even if it doesn't make sense.  Otherwise, use
+	     * what we calculate here.
+	     */
+	    if (newval != UCLYhndl_for_unspec) {
+		UCLYhndl_for_unspec = newval;
+		StrAllocCopy(UCAssume_MIMEcharset, data[i].value);
+		LYRawMode = (UCLYhndl_for_unspec == current_char_set);
+		HTMLSetUseDefaultRawMode(current_char_set, LYRawMode);
+		HTMLUseCharacterSet(current_char_set);
+	    }
+	}
+
+	/*
+	 * display_char_set
+	 */
+	/*
+	 * FIXME: This needs validation.  - MRC
+	 */
+	if (!strcmp(data[i].tag, display_char_set_string)) {
+	    int newval;
+
+	    newval = atoi(data[i].value);
+	    /*
+	     *  Set the LYUseDefaultRawMode value and character
+	     *  handling if LYRawMode was changed. - FM
+	     */
+	    if (newval != current_char_set) {
+		current_char_set = newval;
+		HTMLSetRawModeDefault(current_char_set);
+		LYUseDefaultRawMode = TRUE;
+		HTMLUseCharacterSet(current_char_set);
+	    }
+	}
+
+	/*
+	 * show_color
+	 */
+	if (!strcmp(data[i].tag, show_color_string)) {
+	    if (!strcmp(data[i].value, never_string)) {
+		LYShowColor = SHOW_COLOR_NEVER;
+	    } else if (!strcmp(data[i].value, off_string)) {
+		LYShowColor = SHOW_COLOR_OFF;
+	    } else if (!strcmp(data[i].value, on_string)) {
+		LYShowColor = SHOW_COLOR_ON;
+	    } else if (!strcmp(data[i].value, always_string)) {
+		LYShowColor = SHOW_COLOR_ALWAYS;
+	    }
+	    LYChosenShowColor = LYShowColor;
+	}
+
+	/*
+	 * raw_mode
+	 */
+	if (!strcmp(data[i].tag, raw_mode_string)) {
+	    BOOLEAN newmode;
+	    newmode = (!strcmp(data[i].value, on_string));
+	    if (newmode != LYRawMode) {
+		LYRawMode = newmode;
+		HTMLSetUseDefaultRawMode(current_char_set, LYRawMode);
+		HTMLSetCharacterHandling(current_char_set);
+	    }
+	}
+
+	/*
+	 * vi_keys
+	 */
+	if (!strcmp(data[i].tag, vi_keys_string)) {
+	    if (!strcmp(data[i].value, on_string)) {
+		vi_keys = TRUE;
+		set_vi_keys();
+	    } else if (!strcmp(data[i].value, off_string)) {
+		vi_keys = FALSE;
+		reset_vi_keys();
+	    }
+	}
+
+	/*
+	 * emacs_keys
+	 */
+	if (!strcmp(data[i].tag, emacs_keys_string)) {
+	    if (!strcmp(data[i].value, on_string)) {
+		emacs_keys = TRUE;
+		set_emacs_keys();
+	    } else if (!strcmp(data[i].value, off_string)) {
+		emacs_keys = FALSE;
+		reset_emacs_keys();
+	    }
+	}
+
+	/*
+	 * show_dotfiles
+	 */
+	if (!strcmp(data[i].tag, show_dotfiles_string)) {
+	    if (!strcmp(data[i].value, on_string)) {
+		show_dotfiles = TRUE;
+	    } else if (!strcmp(data[i].value, off_string)) {
+		show_dotfiles = FALSE;
+	    }
+	}
+
+	/*
+	 * select_popups
+	 */
+	if (!strcmp(data[i].tag, select_popups_string)) {
+	    if (!strcmp(data[i].value, on_string)) {
+		LYSelectPopups = TRUE;
+	    } else if (!strcmp(data[i].value, off_string)) {
+		LYSelectPopups = FALSE;
+	    }
+	}
+
+	/*
+	 * show_cursor
+	 */
+	if (!strcmp(data[i].tag, show_cursor_string)) {
+	    if (!strcmp(data[i].value, on_string)) {
+		LYShowCursor = TRUE;
+	    } else if (!strcmp(data[i].value, off_string)) {
+		LYShowCursor = FALSE;
+	    }
+	}
+
+	/*
+	 * keypad_mode
+	 */
+	if (!strcmp(data[i].tag, keypad_mode_string)) {
+	    if (!strcmp(data[i].value, number_arrows_string)) {
+		keypad_mode = NUMBERS_AS_ARROWS;
+	    } else if (!strcmp(data[i].value, links_numbered_string)) {
+		keypad_mode = LINKS_ARE_NUMBERED;
+	    } else if (!strcmp(data[i].value, links_and_forms_string)) {
+		keypad_mode = LINKS_AND_FORM_FIELDS_ARE_NUMBERED;
+	    }
+	}
+
+#ifdef DIRED_SUPPORT
+	/*
+	 * dired_sort
+	 */
+	if (!strcmp(data[i].tag, dired_sort_string)) {
+	    if (!strcmp(data[i].value, dired_dir_string)) {
+		dir_list_style = 0;
+	    } else if (!strcmp(data[i].value, dired_files_string)) {
+		dir_list_style = FILES_FIRST;
+	    } else if (!strcmp(data[i].value, dired_mixed_string)) {
+		dir_list_style = MIXED_STYLE;
+	    }
+	}
+#endif /* DIRED_SUPPORT */
+
+	/*
+	 * user_mode
+	 */
+	if (!strcmp(data[i].tag, user_mode_string)) {
+	    if (!strcmp(data[i].value, user_novice)) {
+		user_mode = NOVICE_MODE;
+	    } else if (!strcmp(data[i].value, user_intermediate)) {
+		user_mode = INTERMEDIATE_MODE;
+	    } else if (!strcmp(data[i].value, user_advanced)) {
+		user_mode = ADVANCED_MODE;
+	    }
+	}
+
+	/*
+	 * save_options
+	 */
+	if (!strcmp(data[i].tag, save_options_string)) {
+	    save_all = TRUE;
+	}
+    }
+    /*
+     * FIXME: Golly gee, we need to write all of this out now, don't we?
+     */
+    FREE(newdoc->post_data);
+    FREE(data);
+    if (save_all) {
+	option_statusline(SAVING_OPTIONS);
+	if (save_rc()) {
+	    option_statusline(OPTIONS_SAVED);
+	} else {
+	    HTAlert(OPTIONS_NOT_SAVED);
+	}
+    }
+    return(NULLFILE);
+}
+
+/*
+ * Okay, someone wants to change options.  So, lets gen up a form for them
+ * and pass it around.  Gor, this is ugly.  Be a lot easier in Bourne with
+ * "here" documents.  :->
+ * Basic Strategy:  For each option, throw up the appropriate type of
+ * control, giving defaults as appropriate.  If nothing else, we're
+ * probably going to test every control there is.  MRC
+ */
+PUBLIC int gen_options ARGS1(
+	char **,	newfile)
+{
+    int i;
+    BOOLEAN can_do_colors;
+    static char tempfile[256];
+    static char print_filename[256];
+    FILE *fp0;
+
+    LYRemoveTemp(tempfile);
+    fp0 = LYOpenTemp(tempfile, HTML_SUFFIX, "w");
+    if (fp0 == NULL) {
+	HTAlert(UNABLE_TO_OPEN_TEMPFILE);
+	return(-1);
+    }
+
+    LYLocalFileToURL(print_filename, tempfile);
+
+    StrAllocCopy(*newfile, print_filename);
+    LYforce_no_cache = TRUE;
+
+    fprintf(fp0, "<head>\n<title>%s</title>\n</head>\n<body>\n",
+	    OPTIONS_TITLE);
+
+    fprintf(fp0,"<h1>Options Menu (%s Version %s)</h1><pre>\n",
+	    LYNX_NAME, LYNX_VERSION);
+
+    /*
+     * I do C, not HTML.  Feel free to pretty this up.
+     */
+    fprintf(fp0,"<form action=\"LYNXOPTIONS:\" method=\"post\">\n");
+    /*
+     * use following with some sort of one shot secret key akin to NCSA
+     * (or was it CUTE?) telnet one shot password to allow ftp to self.
+     * to prevent spoofing.
+     */
+    FREE(secure_value);
+    StrAllocCopy(secure_value, "FIXMEtest=the&encoding");
+    fprintf(fp0,"<input name=\"%s\" type=\"hidden\" value=\"%s\">\n",
+	    secure_string, secure_value);
+
+    /*
+     * editor
+     */
+    fprintf(fp0,"<%s>Editor:</%s> ", label_string, label_string);
+    fprintf(fp0,"<input %s type=\"text\" name=\"%s\" value=\"%s\">\n",
+	    (no_editor || system_editor)?disabled_string:empty_string,
+	    editor_string, (editor && editor[0])?editor:empty_string);
+
+    /*
+     * display
+     */
+    fprintf(fp0,"<%s>Display:</%s> ", label_string, label_string);
+    fprintf(fp0,"<input type=\"text\" name=\"%s\" value=\"%s\">\n",
+	    display_string, (display && display[0])?display:empty_string);
+
+    /*
+     * ftp sort
+     */
+    fprintf(fp0,"<%s>Ftp sort criteria:</%s> ", label_string, label_string);
+    fprintf(fp0,"<select name=\"%s\">\n", ftp_sort_string);
+    fprintf(fp0,"<option %s value=\"%s\">By Name</option>\n",
+	    (HTfileSortMethod == FILE_BY_NAME)?selected_string:empty_string,
+	    ftp_by_name_string);
+    fprintf(fp0,"<option %s value=\"%s\">By Type</option>\n",
+	    (HTfileSortMethod == FILE_BY_TYPE)?selected_string:empty_string,
+	    ftp_by_type_string);
+    fprintf(fp0,"<option %s value=\"%s\">By Size</option>\n",
+	    (HTfileSortMethod == FILE_BY_SIZE)?selected_string:empty_string,
+	    ftp_by_size_string);
+    fprintf(fp0,"<option %s value=\"%s\">By Date</option>\n",
+	    (HTfileSortMethod == FILE_BY_DATE)?selected_string:empty_string,
+	    ftp_by_date_string);
+    fprintf(fp0,"</select>\n");
+
+    /*
+     * mail_address
+     */
+    fprintf(fp0,"<%s>Personal mail address:</%s> ", label_string,
+	    label_string);
+    fprintf(fp0,"<input type=\"text\" name=\"%s\" value=\"%s\">\n",
+	    mail_address_string,
+	    (personal_mail_address && personal_mail_address[0])?
+		personal_mail_address:empty_string);
+
+    /*
+     * search_type
+     */
+    fprintf(fp0,"<%s>Searching type:</%s> ", label_string, label_string);
+    fprintf(fp0,"<select name=\"%s\">\n", search_type_string);
+    fprintf(fp0,"<option %s value=\"%s\">Case insensitive</option>\n",
+	    case_sensitive?empty_string:selected_string,
+	    search_case_insensitive_string);
+    fprintf(fp0,"<option %s value=\"%s\">Case sensitive</option>\n",
+	    case_sensitive?selected_string:empty_string,
+	    search_case_sensitive_string);
+    fprintf(fp0,"</select>\n");
+
+    /*
+     * prefered_doc_lang
+     */
+    fprintf(fp0,"<%s>Prefered document language</%s> ", label_string,
+	    label_string);
+    fprintf(fp0,"<input type=\"text\" name=\"%s\" value=\"%s\">\n",
+	    prefered_doc_lang_string,
+	    (language && language[0])?language:empty_string);
+
+    /*
+     * prefered_doc_char
+     */
+    fprintf(fp0,"<%s>Prefered document character set</%s> ", label_string,
+	    label_string);
+    fprintf(fp0,"<input type=\"text\" name=\"%s\" value=\"%s\">\n",
+	    prefered_doc_char_string,
+	    (pref_charset && pref_charset[0])?pref_charset:empty_string);
+
+    /*
+     * assume_char_set
+     */
+    /*
+     * FIXME: If bogus value in lynx.cfg, then in old way, that is the
+     * string that was displayed.  Now, user will never see that.  Good
+     * or bad?  I don't know.  MRC
+     */
+    if (user_mode==ADVANCED_MODE) {
+	int curval;
+
+	curval = UCLYhndl_for_unspec;
+	if (curval == current_char_set && UCAssume_MIMEcharset) {
+	    curval = UCGetLYhndl_byMIME(UCAssume_MIMEcharset);
+	}
+	if (curval < 0) {
+	    curval = LYRawMode ? current_char_set : 0;
+	}
+	fprintf(fp0,"<%s>Assume Character Set:</%s> ", label_string,
+		label_string);
+	fprintf(fp0,"<select name=\"%s\">\n", assume_char_set_string);
+	for (i = 0; i < LYNumCharsets; i++) {
+	    fprintf(fp0,"<option %s value=\"%s\">%s</option>\n",
+		    (i==curval)?selected_string:empty_string,
+		    LYCharSet_UC[i].MIMEname, LYCharSet_UC[i].MIMEname);
+	}
+	fprintf(fp0,"</select>\n");
+    }
+
+    /*
+     * display_char_set
+     */
+    fprintf(fp0,"<%s>Display character set:</%s> ", label_string,
+	    label_string);
+    fprintf(fp0,"<select name=\"%s\">\n", display_char_set_string);
+    for (i = 0; LYchar_set_names[i]; i++) {
+	fprintf(fp0,"<option %s value=\"%d\">%s</options>\n",
+		(i==current_char_set)?selected_string:empty_string,
+		i, LYchar_set_names[i]);
+    }
+    fprintf(fp0,"</select>\n");
+
+    /*
+     * raw_mode
+     */
+    fprintf(fp0,"<%s>Raw 8-bit or CJK mode:</%s> ", label_string,
+	    label_string);
+    fprintf(fp0,"<select name=\"%s\">\n", raw_mode_string);
+    fprintf(fp0,"<option %s value=\"%s\">%s</option>\n",
+	    (LYRawMode)?empty_string:selected_string,
+	    off_string, off_string);
+    fprintf(fp0,"<option %s value=\"%s\">%s</option>\n",
+	    (LYRawMode)?selected_string:empty_string,
+	    on_string, on_string);
+    fprintf(fp0,"</select>\n");
+
+    /*
+     * show_color
+     */
+#if defined(USE_SLANG) || defined(COLOR_CURSES)
+    can_do_colors = 1;
+#if defined(COLOR_CURSES)
+    can_do_colors = has_colors();
+#endif
+    fprintf(fp0,"<%s>Show Color:</%s> ", label_string, label_string);
+    fprintf(fp0,"<select %s name=\"%s\">\n",
+	    can_do_colors?empty_string:disabled_string, show_color_string);
+    if (no_option_save) {
+	if (LYShowColor == SHOW_COLOR_NEVER) {
+	    LYShowColor = SHOW_COLOR_OFF;
+	} else if (LYShowColor == SHOW_COLOR_ALWAYS) {
+	    LYShowColor = SHOW_COLOR_ON;
+	}
+	fprintf(fp0,"<option %s value=\"%s\">%s</option>\n",
+		(LYShowColor==SHOW_COLOR_OFF)?empty_string:selected_string,
+		off_string, off_string);
+	fprintf(fp0,"<option %s value=\"%s\">%s</option>\n",
+		(LYShowColor==SHOW_COLOR_ON)?empty_string:selected_string,
+		on_string, on_string);
+    } else {
+	if (LYChosenShowColor == SHOW_COLOR_UNKNOWN) {
+	    switch (LYrcShowColor) {
+	    case SHOW_COLOR_NEVER:
+		LYChosenShowColor =
+		    (LYShowColor >= SHOW_COLOR_ON) ?
+			SHOW_COLOR_ON : SHOW_COLOR_NEVER;
+		break;
+	    case SHOW_COLOR_ALWAYS:
+		if (!can_do_colors)
+		    LYChosenShowColor = SHOW_COLOR_ALWAYS;
+		else
+		    LYChosenShowColor =
+			(LYShowColor >= SHOW_COLOR_ON) ?
+				SHOW_COLOR_ALWAYS : SHOW_COLOR_OFF;
+		break;
+	    default:
+		LYChosenShowColor =
+		    (LYShowColor >= SHOW_COLOR_ON) ?
+			SHOW_COLOR_ON : SHOW_COLOR_OFF;
+	    }
+	}
+	fprintf(fp0,"<option %s value=\"%s\">%s</option>\n",
+		(LYChosenShowColor==SHOW_COLOR_NEVER)?selected_string:empty_string,
+		never_string, never_string);
+	fprintf(fp0,"<option %s value=\"%s\">%s</option>\n",
+		(LYChosenShowColor==SHOW_COLOR_OFF)?selected_string:empty_string,
+		off_string, off_string);
+	fprintf(fp0,"<option %s value=\"%s\">%s</option>\n",
+		(LYChosenShowColor==SHOW_COLOR_ON)?selected_string:empty_string,
+		on_string, on_string);
+	fprintf(fp0,"<option %s value=\"%s\">%s</option>\n",
+		(LYChosenShowColor==SHOW_COLOR_ALWAYS)?selected_string:empty_string,
+		always_string, (can_do_colors)?always_string:"Always try");
+    }
+    fprintf(fp0,"</select>\n");
+#endif /* USE_SLANG || COLOR_CURSES */
+
+    /*
+     * vi_keys
+     */
+    fprintf(fp0,"<%s>VI Keys:</%s> ", label_string, label_string);
+    fprintf(fp0,"<select name=\"%s\">\n", vi_keys_string);
+    fprintf(fp0,"<option %s value=\"%s\">%s</option>\n",
+	    (vi_keys)?empty_string:selected_string,
+	    off_string, off_string);
+    fprintf(fp0,"<option %s value=\"%s\">%s</option>\n",
+	    (vi_keys)?selected_string:empty_string,
+	    on_string, on_string);
+    fprintf(fp0,"</select>\n");
+
+    /*
+     * emacs_keys
+     */
+    fprintf(fp0,"<%s>Emacs Keys:</%s> ", label_string, label_string);
+    fprintf(fp0,"<select name=\"%s\">\n", emacs_keys_string);
+    fprintf(fp0,"<option %s value=\"%s\">%s</option>\n",
+	    (emacs_keys)?empty_string:selected_string,
+	    off_string, off_string);
+    fprintf(fp0,"<option %s value=\"%s\">%s</option>\n",
+	    (emacs_keys)?selected_string:empty_string,
+	    on_string, on_string);
+    fprintf(fp0,"</select>\n");
+
+    /*
+     * show_dotfiles
+     */
+    if (!no_dotfiles) {
+	fprintf(fp0,"<%s>Show dot files:</%s> ", label_string, label_string);
+	fprintf(fp0,"<select name=\"%s\">\n", show_dotfiles_string);
+	fprintf(fp0,"<option %s value=\"%s\">%s</option>\n",
+		(show_dotfiles)?empty_string:selected_string,
+		off_string, off_string);
+	fprintf(fp0,"<option %s value=\"%s\">%s</option>\n",
+		(show_dotfiles)?selected_string:empty_string,
+		on_string, on_string);
+	fprintf(fp0,"</select>\n");
+    }
+
+    /*
+     * select_popups
+     */
+    fprintf(fp0,"<%s>Popups for select fields:</%s> ", label_string,
+	    label_string);
+    fprintf(fp0,"<select name=\"%s\">\n", select_popups_string);
+    fprintf(fp0,"<option %s value=\"%s\">%s</option>\n",
+	    (LYSelectPopups)?empty_string:selected_string,
+	    off_string, off_string);
+    fprintf(fp0,"<option %s value=\"%s\">%s</option>\n",
+	    (LYSelectPopups)?selected_string:empty_string,
+	    on_string, on_string);
+    fprintf(fp0,"</select>\n");
+
+    /*
+     * show_cursor
+     */
+    fprintf(fp0,"<%s>Show cursor:</%s> ", label_string, label_string);
+    fprintf(fp0,"<select name=\"%s\">\n", show_cursor_string);
+    fprintf(fp0,"<option %s value=\"%s\">%s</option>\n",
+	    (LYShowCursor)?empty_string:selected_string,
+	    off_string, off_string);
+    fprintf(fp0,"<option %s value=\"%s\">%s</option>\n",
+	    (LYShowCursor)?selected_string:empty_string,
+	    on_string, on_string);
+    fprintf(fp0,"</select>\n");
+
+    /*
+     * keypad_mode
+     */
+    fprintf(fp0,"<%s>Keypad Mode:</%s> ", label_string, label_string);
+    fprintf(fp0,"<select name=\"%s\">\n", keypad_mode_string);
+    fprintf(fp0,"<option %s value=\"%s\">Numbers act as arrows</option>\n",
+	    (keypad_mode==NUMBERS_AS_ARROWS)?selected_string:empty_string,
+	    number_arrows_string);
+    fprintf(fp0,"<option %s value=\"%s\">Links are numbered</option>\n",
+	    (keypad_mode==LINKS_ARE_NUMBERED)?selected_string:empty_string,
+	    links_numbered_string);
+    fprintf(fp0,"<option %s value=\"%s\">\
+	    Links and form fields are numbered</option>\n",
+	    (keypad_mode==LINKS_AND_FORM_FIELDS_ARE_NUMBERED)?
+		selected_string:empty_string, links_and_forms_string);
+    fprintf(fp0,"</select>\n");
+
+#ifdef DIRED_SUPPORT
+    /*
+     * dired_sort
+     */
+    fprintf(fp0,"<%s>User Mode:</%s> ", label_string, label_string);
+    fprintf(fp0,"<select name=\"%s\">\n", dired_sort_string);
+    fprintf(fp0,"<option %s value=\"%s\">Directories first</option>\n",
+	    (dir_list_style==0)?selected_string:empty_string,
+	    dired_dir_string);
+    fprintf(fp0,"<option %s value=\"%s\">Files first</option>\n",
+	    (dir_list_style==FILES_FIRST)?selected_string:empty_string,
+	    dired_files_string);
+    fprintf(fp0,"<option %s value=\"%s\">Mixed style</option>\n",
+	    (dir_list_style==MIXED_STYLE)?selected_string:empty_string,
+	    dired_mixed_string);
+    fprintf(fp0,"</select>\n");
+#endif /* DIRED_SUPPORT */
+
+    /*
+     * user_mode
+     */
+    fprintf(fp0,"<%s>User Mode:</%s> ", label_string, label_string);
+    fprintf(fp0,"<select name=\"%s\">\n", user_mode_string);
+    fprintf(fp0,"<option %s value=\"%s\">%s</option>\n",
+	    (user_mode==NOVICE_MODE)?selected_string:empty_string,
+	    user_novice, user_novice);
+    fprintf(fp0,"<option %s value=\"%s\">%s</option>\n",
+	    (user_mode==INTERMEDIATE_MODE)?selected_string:empty_string,
+	    user_intermediate, user_intermediate);
+    fprintf(fp0,"<option %s value=\"%s\">%s</option>\n",
+	    (user_mode==ADVANCED_MODE)?selected_string:empty_string,
+	    user_advanced, user_advanced);
+    fprintf(fp0,"</select>\n");
+
+    /*
+     * save options
+     */
+    if (!no_option_save) {
+        fprintf(fp0,"<%s>Save options to disk: </%s> ", label_string,
+		label_string);
+        fprintf(fp0,"<input type=\"checkbox\" name=\"%s\">\n",
+		save_options_string);
+    }
+
+    /*
+     * save/reset
+     */
+    fprintf(fp0,"<p>Use the back key to cancel changes.\n");
+    fprintf(fp0,"<input type=\"submit\" value=\"Accept Changes\">");
+    fprintf(fp0," <input type=\"reset\" value=\"Reset\">\n");
+    fprintf(fp0,"</p>");
+    fprintf(fp0,"</body>\n");
+
+    fclose(fp0);
+    return(0);
+}
diff --git a/src/LYOptions.h b/src/LYOptions.h
index ea9e914a..973901a3 100644
--- a/src/LYOptions.h
+++ b/src/LYOptions.h
@@ -5,6 +5,8 @@ extern BOOLEAN term_options;
 
 extern void options NOPARAMS;
 extern void edit_bookmarks NOPARAMS;
+extern int postoptions PARAMS((document *newdoc));
+extern int gen_options PARAMS((char **newfile));
 
 /*
  *  Values for the options menu. - FM
@@ -48,7 +50,7 @@ extern void edit_bookmarks NOPARAMS;
 #define B_SHOW_CURSOR	44
 #define C_SHOW_CURSOR	62
 
-#define L_KEYPAD	14 
+#define L_KEYPAD	14
 #define L_LINEED	15
 
 #ifdef DIRED_SUPPORT
@@ -62,4 +64,6 @@ extern void edit_bookmarks NOPARAMS;
 #define L_EXEC		18
 #endif /* DIRED_SUPPORT */
 
+#define OPTIONS_TITLE "Lynx Options Configuration"
+
 #endif /* LYOPTIONS_H */
diff --git a/src/LYPrint.c b/src/LYPrint.c
index 05ff5ee6..d4005267 100644
--- a/src/LYPrint.c
+++ b/src/LYPrint.c
@@ -30,7 +30,7 @@
 
 /*
  *  printfile prints out the current file minus the links and targets
- *  to a veriaty of places
+ *  to a verity of places
  */
 
 /* it parses an incoming link that looks like
@@ -764,7 +764,7 @@ PUBLIC int printfile ARGS1(
 		/*
 		 *  Don't send a charset if we have a CJK character set
 		 *  selected, since it may not be appropriate for mail...
-		 *  Also don't use an inofficial "x-" charset. - kw
+		 *  Also don't use an unofficial "x-" charset. - kw
 		 */
 		if (!use_cte || LYHaveCJKCharacterSet ||
 		    strncasecomp(disp_charset, "x-", 2) == 0) {
@@ -1285,7 +1285,6 @@ PUBLIC int print_options ARGS2(
     LYLocalFileToURL(print_filename, tempfile);
 
     StrAllocCopy(*newfile, print_filename);
-    LYforce_no_cache = TRUE;
 
     fprintf(fp0, "<head>\n<title>%s</title>\n</head>\n<body>\n",
 		 PRINT_OPTIONS_TITLE);
diff --git a/src/LYReadCFG.c b/src/LYReadCFG.c
index b5abda17..a49bf7a6 100644
--- a/src/LYReadCFG.c
+++ b/src/LYReadCFG.c
@@ -138,7 +138,7 @@ PRIVATE void add_item_to_list ARGS2(
 	 */
 	cur_item = (lynx_html_item_type *)calloc(sizeof(lynx_html_item_type),1);
 	if (cur_item == NULL)
-	    perror("Out of memory in read_cfg");
+	    outofmem(__FILE__, "read_cfg");
 	*list_ptr = cur_item;
 	atexit(free_item_list);
     } else {
@@ -151,7 +151,7 @@ PRIVATE void add_item_to_list ARGS2(
 	    ;  /* null body */
 	cur_item = (lynx_html_item_type *)calloc(sizeof(lynx_html_item_type),1);
 	if (cur_item == NULL)
-	    perror("Out of memory in read_cfg");
+	    outofmem(__FILE__, "read_cfg");
 	else
 	    prev_item->next = cur_item;
     }
@@ -169,7 +169,7 @@ PRIVATE void add_item_to_list ARGS2(
 	 */
 	cur_item->name = (char *)calloc((colon-buffer+1),sizeof(char));
 	if (cur_item->name == NULL)
-	    perror("Out of memory in read_cfg");
+	    outofmem(__FILE__, "read_cfg");
 	LYstrncpy(cur_item->name, buffer, (int)(colon-buffer));
 	remove_backslashes(cur_item->name);
 
@@ -179,7 +179,7 @@ PRIVATE void add_item_to_list ARGS2(
 	if ((next_colon = find_colon(colon+1)) != NULL) {
 	    cur_item->command = (char *)calloc(next_colon-colon, sizeof(char));
 	    if (cur_item->command == NULL)
-		perror("Out of memory in read_cfg");
+		outofmem(__FILE__, "read_cfg");
 	    LYstrncpy(cur_item->command, colon+1, (int)(next_colon-(colon+1)));
 	    remove_backslashes(cur_item->command);
 	    cur_item->always_enabled = is_true(next_colon+1);
@@ -227,7 +227,7 @@ PRIVATE void add_printer_to_list ARGS2(
 	 */
 	cur_item = (lynx_printer_item_type *)calloc(sizeof(lynx_printer_item_type),1);
 	if (cur_item == NULL)
-	    perror("Out of memory in read_cfg");
+	    outofmem(__FILE__, "read_cfg");
 	*list_ptr = cur_item;
 	atexit(free_printer_item_list);
     } else {
@@ -241,7 +241,7 @@ PRIVATE void add_printer_to_list ARGS2(
 
 	cur_item = (lynx_printer_item_type *)calloc(sizeof(lynx_printer_item_type),1);
 	if (cur_item == NULL)
-	    perror("Out of memory in read_cfg");
+	    outofmem(__FILE__, "read_cfg");
 	else
 	    prev_item->next = cur_item;
     }
@@ -259,7 +259,7 @@ PRIVATE void add_printer_to_list ARGS2(
 	 */
 	cur_item->name = (char *)calloc((colon-buffer+1), sizeof(char));
 	if (cur_item->name == NULL)
-	    perror("Out of memory in read_cfg");
+	    outofmem(__FILE__, "read_cfg");
 	LYstrncpy(cur_item->name, buffer, (int)(colon-buffer));
 	remove_backslashes(cur_item->name);
 
@@ -269,7 +269,7 @@ PRIVATE void add_printer_to_list ARGS2(
 	if ((next_colon = find_colon(colon+1)) != NULL) {
 	    cur_item->command = (char *)calloc(next_colon-colon, sizeof(char));
 	    if (cur_item->command == NULL)
-		perror("Out of memory in read_cfg");
+		outofmem(__FILE__, "read_cfg");
 	    LYstrncpy(cur_item->command, colon+1, (int)(next_colon-(colon+1)));
 	    remove_backslashes(cur_item->command);
 	    cur_item->always_enabled = is_true(next_colon+1);
@@ -823,6 +823,7 @@ static Config_Type Config_Table [] =
      PARSE_FUN("dired_menu", CONF_FUN, dired_menu_fun),
 #endif
      PARSE_ADD("downloader", CONF_ADD_ITEM, downloaders),
+     PARSE_SET("eat_all_cookies", CONF_BOOL, LYEatAllCookies),
      PARSE_SET("emacs_keys_always_on", CONF_BOOL, emacs_keys),
      PARSE_SET("enable_scrollback", CONF_BOOL, enable_scrollback),
 #ifdef USE_EXTERNALS
@@ -1117,9 +1118,10 @@ PUBLIC void read_cfg ARGS3(
 #else
 		char tmpbuf[MAX_LINE_BUFFER_LEN];
 		sprintf (tmpbuf, "%s=%s", tbl->name, value);
-		q->str_value = (char **)calloc(1, sizeof(char **));
-		StrAllocCopy(*(q->str_value), tmpbuf);
-		putenv (*(q->str_value));
+		if ((q->str_value = (char **)calloc(1, sizeof(char **))) != 0) {
+			StrAllocCopy(*(q->str_value), tmpbuf);
+			putenv (*(q->str_value));
+		}
 #endif
 	    }
 	    break;
diff --git a/src/LYStrings.c b/src/LYStrings.c
index 9f8b3f19..90cb8979 100644
--- a/src/LYStrings.c
+++ b/src/LYStrings.c
@@ -1452,6 +1452,23 @@ again:
 }
 
 /*
+ *  A replacement for 'strsep()'
+ */
+PUBLIC char *LYstrsep ARGS2(
+	char **,	stringp,
+	CONST char *,	delim)
+{
+    char *tmp, *out = 0;
+    tmp = strpbrk(*stringp, delim);
+    if (tmp) {
+	out = *stringp;		/* save the start of the string */
+	*tmp = '\0';		/* terminate the substring with \0 */
+	*stringp = ++tmp;	/* point at the terminator */
+    }
+    return out;
+}
+
+/*
  *  LYstrstr will find the first occurrence of the string
  *  pointed to by tarptr in the string pointed to by chptr.
  *  It returns NULL if string not found.
diff --git a/src/LYStrings.h b/src/LYStrings.h
index c115b7db..cfb8b5eb 100644
--- a/src/LYStrings.h
+++ b/src/LYStrings.h
@@ -21,6 +21,9 @@ extern int LYgetstr PARAMS((
 	int		hidden,
 	size_t		bufsize,
 	int		recall));
+extern char *LYstrsep PARAMS((
+	char **		stringp,
+	const char *	delim));
 extern char * LYstrstr PARAMS((
 	char *		chptr,
 	CONST char *	tarptr));
diff --git a/src/LYUtils.c b/src/LYUtils.c
index f124c664..7f926295 100644
--- a/src/LYUtils.c
+++ b/src/LYUtils.c
@@ -2433,7 +2433,7 @@ static BOOLEAN compare_type ARGS3(
 /*
 **  Must recognize a URL and return the type.
 **  If recognized, based on a case-insensitive
-**  analyis of the scheme field, ensures that
+**  analysis of the scheme field, ensures that
 **  the scheme field has the expected case.
 **
 **  Returns 0 (not a URL) for a NULL argument,
@@ -2539,7 +2539,7 @@ PUBLIC int is_url ARGS1(
     } else if (compare_type(cp, "lynxprog:", 9)) {
 	/*
 	 *  Special External Lynx type to handle execution
-	 *  of commans, sriptis or programs with do not
+	 *  of commands, scripts or programs with do not
 	 *  require a pause to read screen upon completion.
 	 */
 	return(LYNXPROG_URL_TYPE);
@@ -2556,6 +2556,12 @@ PUBLIC int is_url ARGS1(
 	 */
 	return(LYNXPRINT_URL_TYPE);
 
+    } else if (compare_type(cp, "LYNXOPTIONS:", 12)) {
+	/*
+	 *  Special Internal Lynx type.
+	 */
+	return(LYNXOPTIONS_URL_TYPE);
+
     } else if (compare_type(cp, "LYNXDOWNLOAD:", 13)) {
 	/*
 	 *  Special Internal Lynx type.
@@ -2926,7 +2932,7 @@ PUBLIC void HTSugFilenames_free NOARGS
 
 /*
  *  Utility for listing suggested filenames, making any
- *  repeated filenanmes the most current in the list. - FM
+ *  repeated filenames the most current in the list. - FM
  */
 PUBLIC void HTAddSugFilename ARGS1(
 	char *, 	fname)
@@ -3104,7 +3110,7 @@ PUBLIC void change_sug_filename ARGS1(
 
     /*
      *	Trim any trailing or leading
-     *	underscrores or dashes.
+     *	underscores or dashes.
      */
     cp = fname + (strlen(fname)) - 1;
     while (*cp == '_' || *cp == '-') {
@@ -3200,7 +3206,7 @@ PUBLIC void change_sug_filename ARGS1(
 	/*
 	 *  No period, so put one on the end, or after
 	 *  the 39th character, trimming trailing dashes
-	 *  or underscrores.
+	 *  or underscores.
 	 */
 	if (strlen(fname) > 39) {
 	    fname[39] = '\0';
@@ -4126,7 +4132,7 @@ have_VMS_URL:
  *  and returns TRUE, otherwise it does not modify the string and
  *  returns FALSE.  It first tries the element as is, then, if the
  *  element does not end with a dot, it adds prefixes from the
- *  (comma separated) prefix list arguement, and, if the element
+ *  (comma separated) prefix list argument, and, if the element
  *  does not begin with a dot, suffixes from the (comma separated)
  *  suffix list arguments (e.g., www.host.com, then www.host,edu,
  *  then www.host.net, then www.host.org).  The remaining path, if
@@ -4745,7 +4751,7 @@ PUBLIC CONST char * Home_Dir NOARGS
  *  are intended to be off the home directory.	The file path
  *  should be passed in fbuffer, together with the size of the
  *  buffer.  The function simplifies the file path, and if it
- *  is acceptible, loads it into fbuffer and returns TRUE.
+ *  is acceptable, loads it into fbuffer and returns TRUE.
  *  Otherwise, it does not modify fbuffer and returns FALSE.
  *  If a subdirectory is present and the path does not begin
  *  with "./", that is prefixed to make the situation clear. - FM
@@ -5052,7 +5058,7 @@ PUBLIC time_t LYmktime ARGS2(
 
     /*
      *	Skip any lead alphabetic "Day, " field and
-     *	seek a numberic day field. - FM
+     *	seek a numeric day field. - FM
      */
     while (*s != '\0' && !isdigit((unsigned char)*s))
 	s++;
@@ -5395,10 +5401,17 @@ PRIVATE FILE *OpenHiddenFile ARGS2(char *, name, char *, mode)
      * that no one has an existing file or link that they happen to own.
      */
     if (*mode == 'w') {
+	struct stat sb;
 	int fd = open(name, O_CREAT|O_EXCL|O_WRONLY, HIDE_CHMOD);
 	if (fd >= 0) {
 	    fp = fdopen(fd, mode);
 	}
+	else if (errno == EEXIST
+	 && stat(name, &sb) == 0
+	 && sb.st_uid == getuid()
+	 && chmod(name, HIDE_CHMOD) == 0
+	 && (fd = open(name, O_TRUNC|O_WRONLY, HIDE_CHMOD)) >= 0)
+	    fp = fdopen(fd, mode);
     }
     else
 #endif
@@ -5460,7 +5473,7 @@ PUBLIC FILE *LYAppendToTxtFile ARGS1(char *, name)
 
 #ifdef UNIX
 /*
- *  Restore normal permisions to a copy of a file that we have created
+ *  Restore normal permissions to a copy of a file that we have created
  *  with temp file restricted permissions.  The normal umask should
  *  apply for user files. - kw
  */
diff --git a/src/LYUtils.h b/src/LYUtils.h
index 7c925f4a..e7cb4cc3 100644
--- a/src/LYUtils.h
+++ b/src/LYUtils.h
@@ -123,7 +123,11 @@ extern BOOLEAN mustshow;
 
 #define PROXY_URL_TYPE		36
 
-#define UNKNOWN_URL_TYPE	37
+/*
+ * FIXME: Where should this really go?
+ */
+#define LYNXOPTIONS_URL_TYPE	37
+#define UNKNOWN_URL_TYPE	38
 
 /*
  *  For change_sug_filename().
diff --git a/src/LYexit.c b/src/LYexit.c
index d60e62f5..5c8d7d2c 100644
--- a/src/LYexit.c
+++ b/src/LYexit.c
@@ -169,3 +169,13 @@ PRIVATE void LYCompleteExit NOPARAMS
 	callstack[topOfStack]();
     }
 }
+
+PUBLIC void outofmem ARGS2(
+	CONST char *,	fname,
+	CONST char *,	func)
+{
+    fprintf(stderr,
+	"\r\n\r\n\r\n%s %s: out of memory.  Aborting...\r\n", fname, func);
+    LYOutOfMemory = TRUE;
+    LYexit(-1);
+}
diff --git a/src/LYrcFile.c b/src/LYrcFile.c
index ecb3f78b..986e3942 100644
--- a/src/LYrcFile.c
+++ b/src/LYrcFile.c
@@ -427,6 +427,24 @@ PUBLIC void read_rc NOPARAMS
 #endif /* DIRED_SUPPORT */
 
 	/*
+	 * eat all cookies? i think it should work user-by-user.
+	 *  -BJP
+	 */
+	} else if ((cp = LYstrstr(line_buffer, "eat_all_cookies")) != NULL &&
+		   cp-line_buffer < number_sign) {
+	    if((cp2 = (char *)strchr(cp,'=')) != NULL)
+		cp = cp2 + 1;
+	    while (isspace(*cp))
+		cp++; /* get rid of spaces */
+	    if (LYstrstr(cp,"TRUE") != NULL) {
+		LYEatAllCookies = TRUE;
+	    } else {
+		LYEatAllCookies = FALSE;
+	    }
+	/* BJP */
+
+
+	/*
 	 *  User mode.
 	 */
 	} else if ((cp = LYstrstr(line_buffer, "user_mode")) != NULL &&