about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/GridText.c25
-rw-r--r--src/HTAlert.c8
-rw-r--r--src/HTFWriter.c104
-rw-r--r--src/HTML.c24
-rw-r--r--src/LYBookmark.c4
-rw-r--r--src/LYCgi.c8
-rw-r--r--src/LYCharUtils.c12
-rw-r--r--src/LYClean.c4
-rw-r--r--src/LYCookie.c132
-rw-r--r--src/LYCurses.c4
-rw-r--r--src/LYDownload.c184
-rw-r--r--src/LYExtern.c61
-rw-r--r--src/LYForms.c14
-rw-r--r--src/LYGetFile.c7
-rw-r--r--src/LYGlobalDefs.h1
-rw-r--r--src/LYHash.c4
-rw-r--r--src/LYHistory.c2
-rw-r--r--src/LYList.c6
-rw-r--r--src/LYLocal.c215
-rw-r--r--src/LYMail.c10
-rw-r--r--src/LYMain.c14
-rw-r--r--src/LYMainLoop.c7
-rw-r--r--src/LYMap.c6
-rw-r--r--src/LYOptions.c15
-rw-r--r--src/LYPrint.c256
-rw-r--r--src/LYStrings.c4
-rw-r--r--src/LYUpload.c91
-rw-r--r--src/LYUtils.c208
-rw-r--r--src/LYUtils.h5
-rw-r--r--src/LYrcFile.c4
-rw-r--r--src/UCAux.c4
-rw-r--r--src/UCdomap.c208
-rw-r--r--src/chrtrans/README.format4
-rw-r--r--src/chrtrans/makefile.in3
-rw-r--r--src/makefile.in4
35 files changed, 783 insertions, 879 deletions
diff --git a/src/GridText.c b/src/GridText.c
index dea8155f..f31d8d1f 100644
--- a/src/GridText.c
+++ b/src/GridText.c
@@ -28,6 +28,7 @@
 #include <LYStructs.h>
 #include <LYGlobalDefs.h>
 #include <LYGetFile.h>
+#include <LYClean.h>
 #include <LYSignal.h>
 #include <LYMail.h>
 #include <LYList.h>
@@ -429,7 +430,7 @@ PUBLIC HText *	HText_new ARGS1(
     }
 
     /*
-     *  Links between anchors & documents are a 1-1 relationship. If
+     *  Links between anchors & documents are a 1-1 relationship.  If
      *  an anchor is already linked to a document we didn't call
      *  HTuncache_current_document(), e.g., for the showinfo, options,
      *  download, print, etc., temporary file URLs, so we'll check now
@@ -1654,7 +1655,7 @@ PUBLIC void HText_beginAppend ARGS1(
 **		may be set to indicate direct output of the finished line.
 ** On exit,
 **		A new line has been made, justified according to the
-**		current style. Text after the split (if split nonzero)
+**		current style.  Text after the split (if split nonzero)
 **		is taken over onto the next line.
 **
 **		If display_on_the_fly is set, then it is decremented and
@@ -2469,7 +2470,7 @@ PUBLIC void HText_appendCharacter ARGS2(
      *  I'm going to cheat here in a BIG way.  Since I know that all
      *  \r's will be trapped by HTML_put_character I'm going to use
      *  \r to mean go down a line but don't start a new paragraph.
-     *  i.e. use the second line indenting.
+     *  i.e., use the second line indenting.
      */
     if (ch == '\r') {
 	new_line(text);
@@ -3026,7 +3027,7 @@ PUBLIC void HText_endAnchor ARGS2(
 	     * Well, let's do this only if -hiddenlinks=merged is not in
 	     * effect, or if we can be reasonably sure that
 	     * this is the result of an intentional non-generation of
-	     * anchor text via NO_ISMAP_IF_USEMAP. In other cases it can
+	     * anchor text via NO_ISMAP_IF_USEMAP.  In other cases it can
 	     * actually be a feature that numbered links alert the viewer
 	     * to the presence of a link which is otherwise not selectable -
 	     * possibly caused by HTML errors. - kw
@@ -4271,7 +4272,7 @@ PUBLIC void HText_pageDisplay ARGS2(
 	CTRACE(tfp, "GridText: HText_pageDisplay at line %d started\n", line_num);
     }
 
-    if (display_partial && detected_forms_input_partial) {
+    if (display_partial) {
 	/*
 	**  Garbage is reported from forms input fields in incremental mode.
 	**  So we start HText_trimHightext() to forget this side effect.
@@ -4283,7 +4284,6 @@ PUBLIC void HText_pageDisplay ARGS2(
 	*/
 	HText_trimHightext(HTMainText, FALSE);
     }
-    detected_forms_input_partial = FALSE;
 #endif
 
     display_page(HTMainText, line_num-1, target);
@@ -4571,7 +4571,7 @@ PUBLIC BOOL HText_selectAnchor ARGS2(
 /*		Editing functions		- NOT IMPLEMENTED
 **		=================
 **
-**	These are called from the application. There are many more functions
+**	These are called from the application.  There are many more functions
 **	not included here from the original text object.
 */
 
@@ -4944,9 +4944,6 @@ PUBLIC void print_wwwfile_to_fd ARGS2(
     register int i;
     int first = TRUE;
     HTLine * line;
-#ifdef VMS
-    extern BOOLEAN HadVMSInterrupt;
-#endif /* VMS */
 
     if (!HTMainText)
 	return;
@@ -5028,9 +5025,6 @@ PUBLIC void print_crawl_to_fd ARGS3(
     register int i;
     int first = TRUE;
     HTLine * line;
-#ifdef VMS
-    extern BOOLEAN HadVMSInterrupt;
-#endif /* VMS */
 
     if (!HTMainText)
 	return;
@@ -6549,11 +6543,6 @@ PUBLIC int HText_beginInput ARGS3(
 
     CTRACE(tfp,"Entering HText_beginInput\n");
 
-#ifdef DISP_PARTIAL
-    if (display_partial)
-	detected_forms_input_partial = TRUE; /* trimHightext temp fix */
-#endif
-
     if (a == NULL || f == NULL)
 	outofmem(__FILE__, "HText_beginInput");
 
diff --git a/src/HTAlert.c b/src/HTAlert.c
index 98f53c86..86b24721 100644
--- a/src/HTAlert.c
+++ b/src/HTAlert.c
@@ -15,6 +15,7 @@
 #include <LYCurses.h>
 #include <LYStrings.h>
 #include <LYUtils.h>
+#include <LYClean.h>
 #include <LYSignal.h>
 #include <GridText.h>
 #include <LYCookie.h>
@@ -167,9 +168,6 @@ PUBLIC BOOL HTConfirm ARGS1(CONST char *, Msg)
 	return(NO);
     } else {
 	int c;
-#ifdef VMS
-	extern BOOLEAN HadVMSInterrupt;
-#endif /* VMS */
 
 	_user_message(gettext("%s (y/n) "), Msg);
 
@@ -414,10 +412,6 @@ PUBLIC BOOL HTConfirmCookie ARGS4(
     domain_entry *de;
     int ch, namelen, valuelen, space_free;
 
-#ifdef VMS
-    extern BOOLEAN HadVMSInterrupt;
-#endif /* VMS */
-
     if ((de = (domain_entry *)dp) == NULL)
 	return FALSE;
 
diff --git a/src/HTFWriter.c b/src/HTFWriter.c
index 9e0b03b6..73980117 100644
--- a/src/HTFWriter.c
+++ b/src/HTFWriter.c
@@ -23,6 +23,7 @@
 #include <LYStrings.h>
 #include <LYUtils.h>
 #include <LYGlobalDefs.h>
+#include <LYClean.h>
 #include <LYSignal.h>
 #include <GridText.h>
 #include <LYexit.h>
@@ -35,7 +36,6 @@ PUBLIC char * WWW_Download_File=NULL; /* contains the name of the temp file
 PUBLIC char LYCancelDownload=FALSE;   /* exported to HTFormat.c in libWWW */
 
 #ifdef VMS
-extern BOOLEAN HadVMSInterrupt;      /* flag from cleanup_sig() 	*/
 PRIVATE char * FIXED_RECORD_COMMAND = NULL;
 #ifdef USE_COMMAND_FILE 	     /* Keep this as an option. - FM	*/
 #define FIXED_RECORD_COMMAND_MASK "@Lynx_Dir:FIXED512 %s"
@@ -156,8 +156,11 @@ PRIVATE void HTFWriter_free ARGS1(HTStream *, me)
 		 *  and remove any previous uncompressed copy. - FM
 		 */
 		StrAllocCopy(path, me->anchor->FileCache);
-		if ((len = strlen(path)) > 2) {
-		    if (!strcasecomp(&path[len-2], "gz")) {
+		if ((len = strlen(path)) > 3) {
+		    if (!strcasecomp(&path[len-3], "bz2")) {
+			    path[len-4] = '\0';
+			    remove(path);
+		    } else if (!strcasecomp(&path[len-2], "gz")) {
 #ifdef USE_ZLIB
 			if (!skip_loadfile) {
 			    use_gzread = YES;
@@ -283,16 +286,10 @@ PRIVATE void HTFWriter_free ARGS1(HTStream *, me)
 			 *  created. - kw
 			 */
 			FREE(me->end_command);
-			me->end_command = (char *)calloc (
-			    (strlen (me->viewer_command) + 10 +
-			     strlen(me->anchor->FileCache))
-			    * sizeof (char),1);
-			if (me->end_command == NULL)
-			    outofmem(__FILE__, "HTFWriter_free (HTCompressed)");
-
-			sprintf(me->end_command,
-				me->viewer_command, me->anchor->FileCache,
-				"", "", "", "", "", "");
+
+			HTAddParam(&(me->end_command), me->viewer_command, 1, me->anchor->FileCache);
+			HTEndParam(&(me->end_command), me->viewer_command, 1);
+
 			if (!dump_output_immediately) {
 			    /*
 			     *	Tell user what's happening. - FM
@@ -441,7 +438,6 @@ PUBLIC HTStream* HTFWriter_new ARGS1(FILE *, fp)
 **
 **	See mailcap spec for description of template.
 */
-/* @@ to be written.  sprintfs will do for now.  */
 
 #ifndef VMS
 #define REMOVE_COMMAND "/bin/rm -f %s"
@@ -488,11 +484,12 @@ PUBLIC HTStream* HTSaveAndExecute ARGS3(
 		 !strncmp(anchor->address,"file://localhost",16))) {
 		/* allow it to continue */
 	    } else {
-		char buf[512];
+		char *buf = 0;
 
-		sprintf(buf, EXECUTION_DISABLED_FOR_FILE,
-			     key_for_func(LYK_OPTIONS));
+		HTSprintf0(&buf, EXECUTION_DISABLED_FOR_FILE,
+			   key_for_func(LYK_OPTIONS));
 		HTAlert(buf);
+		FREE(buf);
 		return HTPlainPresent(pres, anchor, sink);
 	    }
     }
@@ -542,24 +539,16 @@ PUBLIC HTStream* HTSaveAndExecute ARGS3(
     /*
      *	Make command to process file.
      */
-    me->end_command = (char *)calloc (
-			(strlen (pres->command) + 10 + strlen(fnam))
-			 * sizeof (char),1);
-    if (me->end_command == NULL)
-	outofmem(__FILE__, "HTSaveAndExecute");
-
-    sprintf(me->end_command, pres->command, fnam, "", "", "", "", "", "");
+    me->end_command = 0;
+    HTAddParam(&(me->end_command), pres->command, 1, fnam);
+    HTEndParam(&(me->end_command), pres->command, 1);
 
     /*
      *	Make command to delete file.
      */
-    me->remove_command = (char *)calloc (
-			(strlen (REMOVE_COMMAND) + 10 + strlen(fnam))
-			 * sizeof (char),1);
-    if (me->remove_command == NULL)
-	outofmem(__FILE__, "HTSaveAndExecute");
-
-    sprintf(me->remove_command, REMOVE_COMMAND, fnam);
+    me->remove_command = 0;
+    HTAddParam(&(me->remove_command), REMOVE_COMMAND, 1, fnam);
+    HTEndParam(&(me->remove_command), REMOVE_COMMAND, 1);
 
     StrAllocCopy(anchor->FileCache, fnam);
     return me;
@@ -715,32 +704,20 @@ PUBLIC HTStream* HTSaveToFile ARGS3(
     /*
      *	Make command to delete file.
      */
-    ret_obj->remove_command = (char *)calloc (
-			(strlen (REMOVE_COMMAND) + 10+ strlen(fnam))
-			 * sizeof (char),1);
-    if (ret_obj->remove_command == NULL)
-	outofmem(__FILE__, "HTSaveToFile");
-
-    sprintf(ret_obj->remove_command, REMOVE_COMMAND, fnam);
+    ret_obj->remove_command = 0;
+    HTAddParam(&(ret_obj->remove_command), REMOVE_COMMAND, 1, fnam);
+    HTEndParam(&(ret_obj->remove_command), REMOVE_COMMAND, 1);
 
 #ifdef VMS
     if (IsBinary && UseFixedRecords) {
-	ret_obj->end_command = (char *)calloc (sizeof(char)*20,1);
-	if (ret_obj->end_command == NULL)
-	    outofmem(__FILE__, "HTSaveToFile");
-	sprintf(ret_obj->end_command, "SaveVMSBinaryFile");
-	FIXED_RECORD_COMMAND = (char *)calloc (
-		(strlen (FIXED_RECORD_COMMAND_MASK) + 10 + strlen(fnam))
-		* sizeof (char),1);
-	if (FIXED_RECORD_COMMAND == NULL)
-	    outofmem(__FILE__, "HTSaveToFile");
-	sprintf(FIXED_RECORD_COMMAND, FIXED_RECORD_COMMAND_MASK, fnam);
+	StrAllocCopy(ret_obj->end_command, "SaveVMSBinaryFile");
+	FIXED_RECORD_COMMAND = 0;
+	HTAddParam(&FIXED_RECORD_COMMAND, FIXED_RECORD_COMMAND_MASK, 1, fnam);
+	HTEndParam(&FIXED_RECORD_COMMAND, FIXED_RECORD_COMMAND_MASK, 1);
+
     } else {
 #endif /* VMS */
-    ret_obj->end_command = (char *)calloc (sizeof(char)*12,1);
-    if (ret_obj->end_command == NULL)
-	outofmem(__FILE__, "HTSaveToFile");
-    sprintf(ret_obj->end_command, "SaveToFile");
+    StrAllocCopy(ret_obj->end_command, "SaveToFile");
 #ifdef VMS
     }
 #endif /* VMS */
@@ -856,7 +833,12 @@ PUBLIC HTStream* HTCompressed ARGS3(
 	     *	We have a presentation mapping for it. - FM
 	     */
 	    can_present = TRUE;
-	    if (!strcasecomp(anchor->content_encoding, "x-gzip") ||
+	    if (!strcasecomp(anchor->content_encoding, "x-bzip2") ||
+		!strcasecomp(anchor->content_encoding, "bzip")) {
+		StrAllocCopy(uncompress_mask, BZIP2_PATH);
+		StrAllocCat(uncompress_mask, " -d %s");
+		compress_suffix = "bz2";
+	    } else if (!strcasecomp(anchor->content_encoding, "x-gzip") ||
 		!strcasecomp(anchor->content_encoding, "gzip")) {
 		/*
 		 *  It's compressed with the modern gzip. - FM
@@ -1010,22 +992,18 @@ PUBLIC HTStream* HTCompressed ARGS3(
     } else
 #endif /* USE_ZLIB */
     {
-	me->end_command = (char *)calloc(1, (strlen(uncompress_mask) + 10 +
-					     strlen(fnam)) * sizeof(char));
-	if (me->end_command == NULL)
-	    outofmem(__FILE__, "HTCompressed");
-	sprintf(me->end_command, uncompress_mask, fnam, "", "", "", "", "", "");
+	me->end_command = 0;
+	HTAddParam(&(me->end_command), uncompress_mask, 1, fnam);
+	HTEndParam(&(me->end_command), uncompress_mask, 1);
     }
     FREE(uncompress_mask);
 
     /*
      *	Make command to delete file. - FM
      */
-    me->remove_command = (char *)calloc(1, (strlen(REMOVE_COMMAND) + 10 +
-					    strlen(fnam)) * sizeof(char));
-    if (me->remove_command == NULL)
-	outofmem(__FILE__, "HTCompressed");
-    sprintf(me->remove_command, REMOVE_COMMAND, fnam);
+    me->remove_command = 0;
+    HTAddParam(&(me->remove_command), REMOVE_COMMAND, 1, fnam);
+    HTEndParam(&(me->remove_command), REMOVE_COMMAND, 1);
 
     /*
      *	Save the filename and return the structure. - FM
diff --git a/src/HTML.c b/src/HTML.c
index 24e5acf2..6c3ff556 100644
--- a/src/HTML.c
+++ b/src/HTML.c
@@ -128,7 +128,7 @@ PUBLIC void strtolower ARGS1(char*, i)
 **		------------------------------
 **
 On the NeXT, and on any read-only browser, it is simpler for the text to have
-a sequence of styles, rather than a nested tree of styles. In this
+a sequence of styles, rather than a nested tree of styles.  In this
 case we have to flatten the structure as it arrives from SGML tags into
 a sequence of styles.
 */
@@ -583,14 +583,14 @@ PUBLIC void HTML_write ARGS3(HTStructured *, me, CONST char*, s, int, l)
  * *Note that this doesn't apply to form ACTIONs (always resolved using base,
  *  never marked internal).  Also other references encountered or generated
  *  are not marked internal, whether they have a URL or not, if in a given
- *  context an internal link makes no sense (e.g. IMG SRC=).
+ *  context an internal link makes no sense (e.g., IMG SRC=).
  */
 
 #ifndef DONT_TRACK_INTERNAL_LINKS
 /* A flag is used to keep track of whether an "URL reference" encountered
-   had a real "URL" or not. In the latter case, it will be marked as
+   had a real "URL" or not.  In the latter case, it will be marked as
    "internal".	The flag is set before we start messing around with the
-   string (resolution of relative URLs etc.). This variable only used
+   string (resolution of relative URLs etc.).  This variable only used
    locally here, don't confuse with LYinternal_flag which is for
    for overriding non-caching similar to LYoverride_no_cache. - kw */
 #define CHECK_FOR_INTERN(s) intern_flag = (s && (*s=='#' || *s=='\0')) ? TRUE : FALSE;
@@ -1686,7 +1686,7 @@ PRIVATE void HTML_start_element ARGS6(
 
     case HTML_TAB:
 	if (!present) { /* Bad tag.  Must have at least one attribute. - FM */
-	    CTRACE(tfp, "HTML: TAB tag has no attributes. Ignored.\n");
+	    CTRACE(tfp, "HTML: TAB tag has no attributes.  Ignored.\n");
 	    break;
 	}
 	UPDATE_STYLE;
@@ -1699,7 +1699,7 @@ PRIVATE void HTML_start_element ARGS6(
 	     *	the ALIGN and DP attributes implemented. - FM
 	     */
 	    HTML_put_character(me, ' ');
-	    CTRACE(tfp, "HTML: ALIGN not 'left'. Using space instead of TAB.\n");
+	    CTRACE(tfp, "HTML: ALIGN not 'left'.  Using space instead of TAB.\n");
 
 	} else if (!LYoverride_default_alignment(me) &&
 		   me->current_default_alignment != HT_LEFT) {
@@ -1710,7 +1710,7 @@ PRIVATE void HTML_start_element ARGS6(
 	     *	that the alignment be HT_LEFT. - FM
 	     */
 	    HTML_put_character(me, ' ');
-	    CTRACE(tfp, "HTML: Not HT_LEFT. Using space instead of TAB.\n");
+	    CTRACE(tfp, "HTML: Not HT_LEFT.  Using space instead of TAB.\n");
 
 	} else if ((present[HTML_TAB_TO] &&
 		    value[HTML_TAB_TO] && *value[HTML_TAB_TO]) ||
@@ -1749,7 +1749,7 @@ PRIVATE void HTML_start_element ARGS6(
 	    if (target < column ||
 		target > HText_getMaximumColumn(me->text)) {
 		HTML_put_character(me, ' ');
-		CTRACE(tfp, "HTML: Column out of bounds. Using space instead of TAB.\n");
+		CTRACE(tfp, "HTML: Column out of bounds.  Using space instead of TAB.\n");
 	    } else {
 		for (i = column; i < target; i++)
 		    HText_appendCharacter(me->text, ' ');
@@ -3909,7 +3909,7 @@ PRIVATE void HTML_start_element ARGS6(
 	     *	that one now. - FM
 	     */
 	    if (me->inFORM) {
-		CTRACE(tfp, "HTML: Missing FORM end tag. Faking it!\n");
+		CTRACE(tfp, "HTML: Missing FORM end tag.  Faking it!\n");
 		SET_SKIP_STACK(HTML_FORM);
 		HTML_end_element(me, HTML_FORM, include);
 	    }
@@ -4802,7 +4802,7 @@ PRIVATE void HTML_start_element ARGS6(
 	if (me->inSELECT) {
 	    if (TRACE) {
 		fprintf(tfp,
-		   "Bad HTML: SELECT start tag in SELECT element. Faking SELECT end tag. *****\n");
+		   "Bad HTML: SELECT start tag in SELECT element.  Faking SELECT end tag. *****\n");
 	    } else if (!me->inBadHTML) {
 		HTUserMsg(BAD_HTML_USE_TRACE);
 		me->inBadHTML = TRUE;
@@ -5303,7 +5303,7 @@ PRIVATE void HTML_start_element ARGS6(
 **	TBL 921119
 **
 **	We don't turn on "CAREFUL" check because the parser produces
-**	(internal code errors apart) good nesting. The parser checks
+**	(internal code errors apart) good nesting.  The parser checks
 **	incoming code errors, not this module.
 */
 PRIVATE void HTML_end_element ARGS3(
@@ -6814,7 +6814,7 @@ PRIVATE void HTML_free ARGS1(HTStructured *, me)
 	    HTML_put_character(me, '[');
 	    HTML_start_element(me, HTML_EM, 0, 0, -1, &include);
 	    HTML_put_string(me,
-		gettext("Document has only hidden links. Use the 'l'ist command."));
+		gettext("Document has only hidden links.  Use the 'l'ist command."));
 	    HTML_end_element(me, HTML_EM, &include);
 	    HTML_put_character(me, ']');
 	    HTML_end_element(me, HTML_P, &include);
diff --git a/src/LYBookmark.c b/src/LYBookmark.c
index a05fb6aa..1a400ed3 100644
--- a/src/LYBookmark.c
+++ b/src/LYBookmark.c
@@ -4,6 +4,7 @@
 #include <LYStrings.h>
 #include <LYBookmark.h>
 #include <LYGlobalDefs.h>
+#include <LYClean.h>
 #include <LYSignal.h>
 #include <LYKeymap.h>
 #include <LYCharUtils.h> /* need for META charset */
@@ -14,7 +15,6 @@
 
 #ifdef VMS
 #include <nam.h>
-extern BOOLEAN HadVMSInterrupt; /* Flag from cleanup_sig() AST */
 #endif /* VMS */
 
 #include <LYLeaks.h>
@@ -928,7 +928,7 @@ PRIVATE  BOOLEAN have8bit ARGS1(CONST char *, Title)
 
 /*
  *  Ok, title have 8-bit characters and they are in display charset.
- *  Bookmarks is a permanent file. To avoid dependencies from display
+ *  Bookmarks is a permanent file.  To avoid dependencies from display
  *  character set which may be changed with time
  *  we store 8-bit characters as numeric character reference (NCR),
  *  so where the character encoded as unicode number in form of &#xUUUU;
diff --git a/src/LYCgi.c b/src/LYCgi.c
index 7843ad58..4ad5f376 100644
--- a/src/LYCgi.c
+++ b/src/LYCgi.c
@@ -6,8 +6,8 @@
 **
 ** History
 **      15 Jun 95   Created as way to provide a lynx based service with
-**                  dynamic pages without the need for a http daemon. GL
-**      27 Jun 95   Added <index> (command line) support. Various cleanup
+**                  dynamic pages without the need for a http daemon.  GL
+**      27 Jun 95   Added <index> (command line) support.  Various cleanup
 **                  and bug fixes. GL
 **	04 Sep 97   Added support for PATH_INFO scripts.  JKT
 **
@@ -17,7 +17,7 @@
 **
 **      Should do something about SIGPIPE, (but then it should never happen)
 **
-**      No support for redirection. Or mime-types.
+**      No support for redirection.  Or mime-types.
 **
 **      Should try and parse for a HTTP 1.1 header in case we are "calling" a
 **      nph- script.
@@ -187,7 +187,7 @@ PRIVATE int LYLoadCGI ARGS4(
 	    if (TRACE)
 		perror("LYNXCGI: stat() of pgm_buff failed");
 	} else {
-	    /* Found PATH_INFO data. Strip it off of pgm and into path_info. */
+	    /* Found PATH_INFO data.  Strip it off of pgm and into path_info. */
 	    StrAllocCopy(path_info, pgm+strlen(pgm_buff));
 	    strcpy(pgm, pgm_buff);
 	    CTRACE(tfp, "LYNXCGI: stat() of %s succeeded, path_info=\"%s\".\n",
diff --git a/src/LYCharUtils.c b/src/LYCharUtils.c
index 6c872341..d29fde06 100644
--- a/src/LYCharUtils.c
+++ b/src/LYCharUtils.c
@@ -839,7 +839,7 @@ PUBLIC void LYGetChartransInfo ARGS1(
 **  characters for the current display character set.  It assumes
 **  that invalid control characters have been dealt with by the
 **  SGML (or other initial) parser of the document input stream
-**  (i.e. are present only if elements or global flags have been
+**  (i.e., are present only if elements or global flags have been
 **  set to allow them), and that otherwise this is a copy of the
 **  string with the charset of the input stream.  It handles Lynx
 **  special characters based on the 'me' structure's element values
@@ -1527,7 +1527,7 @@ PRIVATE CONST char *hex = "0123456789ABCDEF";
 **
 **  Some characters (see descriptions in `put_special_unicodes' from SGML.c)
 **  translated in relation with the state of boolean variables
-**  `use_lynx_specials', `plain_space' and `hidden'. It is not clear yet:
+**  `use_lynx_specials', `plain_space' and `hidden'.  It is not clear yet:
 **
 **  If plain_space is TRUE, nbsp (160) will be treated as an ASCII
 **  space (32).  If hidden is TRUE, entities will be translated
@@ -1541,7 +1541,7 @@ PRIVATE CONST char *hex = "0123456789ABCDEF";
 **  (unless input and output charset are both iso-8859-1, for compatibility
 **  with previous usage in HTML.c) even if `hidden' or `plain_space' is set.
 **
-**  If `Back' is YES, the reverse is done instead i.e. Lynx special codes
+**  If `Back' is YES, the reverse is done instead i.e., Lynx special codes
 **  in the input are translated back to character values.
 **
 **  If `Back' is YES, an attempt is made to use UCReverseTransChar() for
@@ -1559,7 +1559,7 @@ PRIVATE CONST char *hex = "0123456789ABCDEF";
 **
 **  Escape characters (0x1B, '\033') are
 **  - URL-encoded	if `stype'  is st_URL,	 otherwise
-**  - dropped		if `stype'  is st_other, otherwise (i.e. st_HTML)
+**  - dropped		if `stype'  is st_other, otherwise (i.e., st_HTML)
 **  - passed		if `hidden' is TRUE or HTCJK is set, otherwise
 **  - dropped.
 **
@@ -3098,7 +3098,7 @@ PUBLIC void LYHandleP ARGS5(
 	    }
 	} else if (me->sp[0].tag_number == HTML_ADDRESS) {
 	    /*
-	     *	We're in an ADDRESS. Treat P as an instruction
+	     *	We're in an ADDRESS.  Treat P as an instruction
 	     *	to start a newline, if needed, then fall through
 	     *	to handle attributes. - FM
 	     */
@@ -3771,7 +3771,7 @@ PUBLIC void LYResetParagraphAlignment ARGS1(
 **  For functions similar to this but which depend on details of
 **  the HTML handler's internal data, the calling interface should
 **  be changed, and functions in SGML.c would have to make sure not
-**  to call such functions inappropriately (e.g. calling a function
+**  to call such functions inappropriately (e.g., calling a function
 **  specific to the Lynx_HTML_Handler when SGML.c output goes to
 **  some other HTStructured object like in HTMLGen.c), or the new
 **  functions could be added to the SGML.h interface.
diff --git a/src/LYClean.c b/src/LYClean.c
index 78e5a67e..af30f09a 100644
--- a/src/LYClean.c
+++ b/src/LYClean.c
@@ -183,9 +183,9 @@ PUBLIC void cleanup NOARGS
 
 #ifdef EXP_PERSISTENT_COOKIES
     /*
-     * This can go right here for now. We need to work up a better place
+     * This can go right here for now.  We need to work up a better place
      * to save cookies for the next release, preferably whenever a new
-     * persistent cookie is received or used. Some sort of protocol to
+     * persistent cookie is received or used.  Some sort of protocol to
      * handle two processes writing to the cookie file needs to be worked
      * out as well.
      */
diff --git a/src/LYCookie.c b/src/LYCookie.c
index 73d9049e..4c0053cc 100644
--- a/src/LYCookie.c
+++ b/src/LYCookie.c
@@ -37,7 +37,7 @@
 	actively removing cookies and/or domains based on age or frequency
 	of use.
       * If a cookie has the secure flag set, we presently treat only SSL
-	connections as secure.	This may need to be expanded for other
+	connections as secure.  This may need to be expanded for other
 	secure communication protocols that become standardized.
 */
 
@@ -180,19 +180,6 @@ PRIVATE void LYCookieJar_free NOARGS
 	}
 	dl = dl->next;
     }
-    if (dump_output_immediately) {
-	cl = cookie_list;
-	while (cl) {
-	    next = cl->next;
-	    co = cl->object;
-	    if (co) {
-		HTList_removeObject(cookie_list, co);
-		freeCookie(co);
-	    }
-	    cl = next;
-	}
-	HTList_delete(cookie_list);
-    }
     cookie_list = NULL;
     HTList_delete(domain_list);
     domain_list = NULL;
@@ -209,7 +196,7 @@ PRIVATE BOOLEAN host_matches ARGS2(
 {
     /*
      *	The following line will handle both numeric IP addresses and
-     *	FQDNs.	Do numeric addresses require special handling?
+     *	FQDNs.  Do numeric addresses require special handling?
      */
     if (*B != '.' && !strcmp(A, B))
 	return YES;
@@ -382,46 +369,41 @@ PRIVATE void store_cookie ARGS3(
      *	Look through domain_list to see if the cookie's domain
      *	is already listed.
      */
-    if (dump_output_immediately) { /* Non-interactive, can't respond */
-	if (cookie_list == NULL)
-	    cookie_list = HTList_new();
-    } else {
-	cookie_list = NULL;
-	for (hl = domain_list; hl != NULL; hl = hl->next) {
-	    de = (domain_entry *)hl->object;
-	    if ((de != NULL && de->domain != NULL) &&
-		!strcmp(co->domain, de->domain)) {
-		cookie_list = de->cookie_list;
-		break;
-	    }
+    cookie_list = NULL;
+    for (hl = domain_list; hl != NULL; hl = hl->next) {
+	de = (domain_entry *)hl->object;
+	if ((de != NULL && de->domain != NULL) &&
+	    !strcmp(co->domain, de->domain)) {
+	    cookie_list = de->cookie_list;
+	    break;
 	}
-	if (hl == NULL) {
-	    /*
-	     *	Domain not found; add a new entry for this domain.
-	     */
-	    de = (domain_entry *)calloc(1, sizeof(domain_entry));
-	    if (de == NULL)
-		outofmem(__FILE__, "store_cookie");
+    }
+    if (hl == NULL) {
+	/*
+	 *	Domain not found; add a new entry for this domain.
+	 */
+	de = (domain_entry *)calloc(1, sizeof(domain_entry));
+	if (de == NULL)
+	    outofmem(__FILE__, "store_cookie");
 #ifdef EXP_PERSISTENT_COOKIES
-	    /*
-	     * Ok, this is a problem.  The first cookie for a domain
-	     * effectively sets the policy for that whole domain - for
-	     * something like Netlink, where there are lots of websites
-	     * under www.netlink.co.uk, this isn't sensible.  However,
-	     * taking this sort of decision down to cookie level also
-	     * isn't sensible.	Perhaps something based on the domain
-	     * and the path in conjunction makes more sense?  - RP
-	     */
-	    if (persistent_cookies
-	     && (co->flags & COOKIE_FLAG_PERSISTENT))
-		de->bv = FROM_FILE;
-	    else
+	/*
+	 * Ok, this is a problem.  The first cookie for a domain
+	 * effectively sets the policy for that whole domain - for
+	 * something like Netlink, where there are lots of websites
+	 * under www.netlink.co.uk, this isn't sensible.  However,
+	 * taking this sort of decision down to cookie level also
+	 * isn't sensible.  Perhaps something based on the domain
+	 * and the path in conjunction makes more sense?  - RP
+	 */
+	if (persistent_cookies
+	 && (co->flags & COOKIE_FLAG_PERSISTENT))
+	    de->bv = FROM_FILE;
+	else
 #endif
-		de->bv = QUERY_USER;
-	    cookie_list = de->cookie_list = HTList_new();
-	    StrAllocCopy(de->domain, co->domain);
-	    HTList_addObject(domain_list, de);
-	}
+	    de->bv = QUERY_USER;
+	cookie_list = de->cookie_list = HTList_new();
+	StrAllocCopy(de->domain, co->domain);
+	HTList_addObject(domain_list, de);
     }
 
     /*
@@ -513,7 +495,7 @@ PRIVATE void store_cookie ARGS3(
 	 * If the cookie domain came from persistent cookie file,
 	 * we want to add new cookies to the end of the cookie list
 	 * to maintain their order for servers that need cookies in
-	 * a particular order. This is a hack.
+	 * a particular order.  This is a hack.
 	 */
 	if (persistent_cookies) {
 	    if ((de->bv = FROM_FILE) != 0) {
@@ -634,7 +616,7 @@ PRIVATE char * scan_cookie_sublist ARGS6(
 		 *
 		 *  HTTP/1.0 headers may be folded onto multiple lines
 		 *  if each continuation line begins with a space or
-		 *  horizontal tab. All linear whitespace, including
+		 *  horizontal tab.  All linear whitespace, including
 		 *  folding, has the same semantics as SP.
 		 *  [...]
 		 *  However, folding of header lines is not expected by
@@ -1154,8 +1136,8 @@ PRIVATE void LYProcessSetCookies ARGS6(
 	    /* if (!known_attr && value_end > value_start) */
 
 	    /* Is there any reason we don't want to accept cookies with
-	     * no value? This seems to be needed for sites that reset a
-	     * cookie by nulling out the value. If this causes problems,
+	     * no value?  This seems to be needed for sites that reset a
+	     * cookie by nulling out the value.  If this causes problems,
 	     * we can go back to the original behavior above.  - BJP
 	     */
 	    if (!known_attr) {
@@ -1625,8 +1607,8 @@ PRIVATE void LYProcessSetCookies ARGS6(
 	    /* if (!known_attr && value_end > value_start) */
 
 	    /* Is there any reason we don't want to accept cookies with
-	     * no value? This seems to be needed for sites that reset a
-	     * cookie by nulling out the value. If this causes problems,
+	     * no value?  This seems to be needed for sites that reset a
+	     * cookie by nulling out the value.  If this causes problems,
 	     * we can go back to the original behavior above.  - BJP
 	     */
 	    if (!known_attr) {
@@ -1907,6 +1889,8 @@ PUBLIC void LYLoadCookies ARGS1 (
     if (!cookie_handle)
 	return;
 
+    CTRACE(tfp, "LYLoadCookies: reading cookies from %s\n", cookie_file);
+
     while (!feof(cookie_handle)) {
 	cookie *moo;
 	unsigned i = 0;
@@ -1920,7 +1904,6 @@ PUBLIC void LYLoadCookies ARGS1 (
 	    continue;
 	}
 
-
 	/*
 	 * Strip out the newline that fgets() puts at the end of a
 	 * cookie.
@@ -1941,11 +1924,12 @@ PUBLIC void LYLoadCookies ARGS1 (
 	 * 'fixed' by using strsep instead of strtok.  No idea
 	 * what kind of platform problems this might introduce. - RP
 	 */
+	CTRACE(tfp, "LYLoadCookies: tokenising %s\n", buf);
 	tok_ptr = buf;
 	tok_out = LYstrsep(&tok_ptr, "\t");
 	for (tok_loop = 0; tok_out && tok_values[tok_loop].s; tok_loop++) {
-	CTRACE(tfp, ">%d:%p:%p:[%s]:%s\n",
-	    tok_loop, tok_values[tok_loop].s, tok_out, tok_out, buf);
+	    CTRACE(tfp, "\t%d:%p:%p:[%s]\n",
+	        tok_loop, tok_values[tok_loop].s, tok_out, tok_out);
 	    LYstrncpy(tok_values[tok_loop].s, tok_out, tok_values[tok_loop].n);
 	    /*
 	     * It looks like strtok ignores a leading delimiter,
@@ -1956,7 +1940,6 @@ PUBLIC void LYLoadCookies ARGS1 (
 	    tok_out = LYstrsep(&tok_ptr, "\t");
 	}
 	expires = atol(expires_a);
-	CTRACE(tfp, "COOKIE: expires %s\n", ctime(&expires));
 
 	/*
 	 * This fails when the path is blank
@@ -1965,8 +1948,9 @@ PUBLIC void LYLoadCookies ARGS1 (
 	 *  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);
+	CTRACE(tfp, "expires:\t%s\n", ctime(&expires));
+/* 	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);
@@ -1997,9 +1981,6 @@ PUBLIC void LYStoreCookies ARGS1 (
     domain_entry *de;
     cookie *co;
     FILE *cookie_handle;
-#ifdef VMS
-    extern BOOLEAN HadVMSInterrupt;
-#endif /* VMS */
     time_t now = time(NULL); /* system specific? - RP */
 
     /*
@@ -2047,7 +2028,7 @@ PUBLIC void LYStoreCookies ARGS1 (
 	    if ((co = (cookie *)cl->object) == NULL)
 		continue;
 
-	    CTRACE(tfp, "COOKIE: %ld cf %ld\n", (long) now, (long) co->expires);
+	    CTRACE(tfp, "LYStoreCookies: %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,
@@ -2096,9 +2077,6 @@ PRIVATE int LYHandleCookies ARGS4 (
     char *name = NULL, *value = NULL, *path = NULL;
     char *comment = NULL, *Address = NULL, *Title = NULL;
     int ch;
-#ifdef VMS
-    extern BOOLEAN HadVMSInterrupt;
-#endif /* VMS */
 
     /*
      *	Check whether we have something to do. - FM
@@ -2529,7 +2507,7 @@ PUBLIC void cookie_add_acceptlist ARGS1(
 {
     domain_entry *de = NULL;
     domain_entry *de2 = NULL;
-    HTList *hl;
+    HTList *hl = NULL;
     char **str = (char **)calloc(1, sizeof(acceptstr));
     char *astr = NULL;
     char *strsmall = NULL;
@@ -2550,9 +2528,7 @@ PUBLIC void cookie_add_acceptlist ARGS1(
 
     *str = astr;
 
-    for(; (strsmall = LYstrsep(str, ","));) {
-	if(strsmall == NULL)
-	    break;
+    while ((strsmall = LYstrsep(str, ",")) != 0) {
 
 	/*
 	 * Check the list of existing cookies to see if this is a
@@ -2607,7 +2583,7 @@ PUBLIC void cookie_add_rejectlist ARGS1(
 {
     domain_entry *de = NULL;
     domain_entry *de2 = NULL;
-    HTList *hl;
+    HTList *hl = NULL;
     char **str = (char **)calloc(1, sizeof(rejectstr));
     char *rstr = NULL;
     char *strsmall = NULL;
@@ -2628,9 +2604,7 @@ PUBLIC void cookie_add_rejectlist ARGS1(
 
     *str = rstr;
 
-    for(; (strsmall = LYstrsep(str, ","));) {
-	if(strsmall == NULL)
-	    break;
+    while ((strsmall = LYstrsep(str, ",")) != 0) {
 
 	/*
 	 * Check the list of existing cookies to see if this is a
diff --git a/src/LYCurses.c b/src/LYCurses.c
index b103d4de..ac20eca1 100644
--- a/src/LYCurses.c
+++ b/src/LYCurses.c
@@ -879,7 +879,7 @@ PUBLIC void lynx_enable_mouse ARGS1(int,state)
      * to translate other events to single-clicks.
      * Compensate for small value of maxclick in ncurses.  */
     if (state) {
-	static was = 0;
+	static int was = 0;
 
 	if (!was) {
 	    int old = mouseinterval(-1);
@@ -1081,7 +1081,7 @@ PUBLIC BOOLEAN setup ARGS1(
 	    strcpy(buffer,"vt100");
 
 	sprintf(term_putenv,"TERM=%s", buffer);
-	putenv(term_putenv);
+	(void) putenv(term_putenv);
 	printf("\n%s%s\n", gettext("TERMINAL TYPE IS SET TO"), getenv("TERM"));
 	sleep(MESSAGESECS);
     }
diff --git a/src/LYDownload.c b/src/LYDownload.c
index e0215020..d15dc1d3 100644
--- a/src/LYDownload.c
+++ b/src/LYDownload.c
@@ -7,7 +7,6 @@
 #include <LYGlobalDefs.h>
 #include <LYSignal.h>
 #include <LYStrings.h>
-#include <LYClean.h>
 #include <LYGetFile.h>
 #include <LYDownload.h>
 
@@ -25,6 +24,8 @@
 #ifdef VMS
 #define COPY_COMMAND "copy/nolog/noconf %s %s"
 PUBLIC BOOLEAN LYDidRename = FALSE;
+#else
+#define COPY_COMMAND "%s %s %s"
 #endif /* VMS */
 
 PRIVATE char LYValidDownloadFile[LY_MAXPATH] = "\0";
@@ -35,11 +36,11 @@ PUBLIC void LYDownload ARGS1(
     char *Line = NULL, *method, *file, *sug_file = NULL;
     int method_number;
     int count;
-    char buffer[512];
-    char command[512];
-    char *cp, *cp1;
+    char *the_command = 0;
+    char buffer[LY_MAXPATH];
+    char command[LY_MAXPATH];
+    char *cp;
     lynx_html_item_type *download_command = 0;
-    int c;
     FILE *fp;
     int ch, recall;
     int FnameTotal;
@@ -47,7 +48,6 @@ PUBLIC void LYDownload ARGS1(
     BOOLEAN FirstRecall = TRUE;
     BOOLEAN SecondS = FALSE;
 #ifdef VMS
-    extern BOOLEAN HadVMSInterrupt;
     LYDidRename = FALSE;
 #endif /* VMS */
 
@@ -206,103 +206,34 @@ check_recall:
 	    goto cancelled;
 	}
 
-	if (no_dotfiles || !show_dotfiles) {
-	  if (*LYPathLeaf(buffer) == '.') {
-		HTAlert(FILENAME_CANNOT_BE_DOT);
-		_statusline(NEW_FILENAME_PROMPT);
-		FirstRecall = TRUE;
-		FnameNum = FnameTotal;
-		goto retry;
-	  }
-	}
-	/*
-	 *  Cancel if the user entered "/dev/null" on Unix,
-	 *  or an "nl:" path (case-insensitive) on VMS. - FM
-	 */
-#ifdef VMS
-	if (!strncasecomp(buffer, "nl:", 3) ||
-	    !strncasecomp(buffer, "/nl/", 4))
-#else
-	if (!strcmp(buffer, "/dev/null"))
-#endif /* VMS */
-	{
+	strcpy(command, buffer);
+	if (!LYValidateFilename(buffer, command))
 	    goto cancelled;
+#if HAVE_POPEN
+	else if (LYIsPipeCommand(buffer)) {
+	    /* I don't know how to download to a pipe */
+	    HTAlert(CANNOT_WRITE_TO_FILE);
+	    _statusline(NEW_FILENAME_PROMPT);
+	    FirstRecall = TRUE;
+	    FnameNum = FnameTotal;
+	    goto retry;
 	}
-	if ((cp = strchr(buffer, '~'))) {
-	    *(cp++) = '\0';
-	    strcpy(command, buffer);
-	    LYTrimPathSep(command);
-	    strcat(command, wwwName(Home_Dir()));
-	    strcat(command, cp);
-	    strcpy(buffer, command);
-	}
-#ifdef VMS
-	if (strchr(buffer, '/') != NULL) {
-	    strcpy(command, HTVMS_name("", buffer));
-	    strcpy(buffer, command);
-	}
-	if (buffer[0] != '/' && strchr(buffer, ':') == NULL) {
-	    strcpy(command, "sys$disk:");
-	    if (strchr(buffer, ']') == NULL)
-		strcat(command, "[]");
-	    strcat(command, buffer);
-	    strcpy(buffer, command);
-	}
-#else
-
-#ifndef __EMX__
-	if (!LYIsPathSep(*buffer)) {
-#if defined(__DJGPP__) || defined(_WINDOWS)
-	    if (strchr(buffer, ':') != NULL)
-		cp = NULL;
-	    else
-#endif /*  __DJGPP__ || _WINDOWS */
-	    cp = getenv("PWD");
-	}
-	else
-#endif /* __EMX__*/
-	    cp = NULL;
-
-	LYTrimPathSep(cp);
-
-	if (cp) {
-	    sprintf(command, "%s/%s", cp, buffer);
-	    strcpy(buffer, HTSYS_name(command));
-	}
-#endif /* VMS */
+#endif
 
 	/*
 	 *  See if it already exists.
 	 */
-	if ((fp = fopen(buffer, "r")) != NULL) {
-	    fclose(fp);
-
-#ifdef VMS
-	    _statusline(FILE_EXISTS_HPROMPT);
-#else
-	    _statusline(FILE_EXISTS_OPROMPT);
-#endif /* VMS */
-	    c = 0;
-	    while(TOUPPER(c)!='Y' && TOUPPER(c)!='N' && c != 7 && c != 3)
-		c = LYgetch();
-#ifdef VMS
-	    if (HadVMSInterrupt) {
-		HadVMSInterrupt = FALSE;
-		FREE(Line);
-		return;
-	    }
-#endif /* VMS */
-
-	    if (c == 7 || c == 3) { /* Control-G or Control-C */
-		goto cancelled;
-	    }
-
-	    if (TOUPPER(c) == 'N') {
-		_statusline(NEW_FILENAME_PROMPT);
-		FirstRecall = TRUE;
-		FnameNum = FnameTotal;
-		goto retry;
-	    }
+	switch (LYValidateOutput(buffer)) {
+	case 'Y':
+	    break;
+	case 'N':
+	    _statusline(NEW_FILENAME_PROMPT);
+	    FirstRecall = TRUE;
+	    FnameNum = FnameTotal;
+	    goto retry;
+	default:
+	    FREE(Line);
+	    return;
 	}
 
 	/*
@@ -333,10 +264,13 @@ check_recall:
 	     *	Failed.  Use spawned COPY_COMMAND. - FM
 	     */
 	    CTRACE(tfp, "         FAILED!\n");
-	    sprintf(command, COPY_COMMAND, file, buffer);
-	    CTRACE(tfp, "command: %s\n", command);
+	    HTAddParam(&the_command, COPY_COMMAND, 1, file);
+	    HTAddParam(&the_command, COPY_COMMAND, 2, buffer);
+	    HTEndParam(&the_command, COPY_COMMAND, 2);
+	    CTRACE(tfp, "command: %s\n", the_command);
 	    stop_curses();
-	    LYSystem(command);
+	    LYSystem(the_command);
+	    FREE(the_command);
 	    start_curses();
 	} else {
 	    /*
@@ -349,24 +283,15 @@ check_recall:
 	chmod(buffer, HIDE_CHMOD);
 #else /* Unix: */
 
-#if !( defined(__EMX__) || defined(__DJGPP__) )
-	/*
-	 *  Prevent spoofing of the shell.
-	 */
-	cp = quote_pathname(file);
-	cp1 = quote_pathname(buffer);
-	sprintf(command, "%s %s %s", COPY_PATH, cp, cp1);
-	FREE(cp);
-	FREE(cp1);
-#else
-	/* DJGPP: no " or space possible in 8+3 dos filenames.     */
-	/* (but EMX probably allows spaces which should be quoted, */
-	/* like Win32 LFN does...)                                 */
-	sprintf(command, "%s %s %s", COPY_PATH, file, buffer);
-#endif /* __EMX__ */
-	CTRACE(tfp, "command: %s\n", command);
+	HTAddParam(&the_command, COPY_COMMAND, 1, COPY_PATH);
+	HTAddParam(&the_command, COPY_COMMAND, 2, file);
+	HTAddParam(&the_command, COPY_COMMAND, 3, buffer);
+	HTEndParam(&the_command, COPY_COMMAND, 3);
+
+	CTRACE(tfp, "command: %s\n", the_command);
 	stop_curses();
-	LYSystem(command);
+	LYSystem(the_command);
+	FREE(the_command);
 	start_curses();
 #if defined(UNIX)
 	LYRelaxFilePermissions(buffer);
@@ -392,8 +317,7 @@ check_recall:
 	     *	Check for two '%s' and ask for the local filename if
 	     *	there is.
 	     */
-	    char *first_s = strstr(download_command->command, "%s");
-	    if (first_s && strstr(first_s+1, "%s")) {
+	    if (HTCountCommandArgs(download_command->command) >= 2) {
 		_statusline(FILENAME_PROMPT);
 	again:	if (sug_file)
 		    strcpy(buffer, sug_file);
@@ -508,29 +432,19 @@ check_recall:
 	     *	It actually is not a bug at all and does as it should,
 	     *	putting both names on the command line.
 	     */
-#ifdef VMS
-	    sprintf(command, download_command->command, file, buffer,
-			     "", "", "", "", "", "", "", "", "", "");
-#else /* Unix: */
-	    /*
-	     *	Prevent spoofing of the shell.
-	     */
-	    cp = quote_pathname(file);
-	    cp1 = quote_pathname(buffer);
-	    sprintf(command, download_command->command, cp, cp1,
-			     "", "", "", "", "", "", "", "", "", "");
-	    FREE(cp);
-	    FREE(cp1);
-#endif /* VMS */
+	    HTAddParam(&the_command, download_command->command, 1, file);
+	    HTAddParam(&the_command, download_command->command, 2, buffer);
+	    HTEndParam(&the_command, download_command->command, 2);
 
 	} else {
 	    HTAlert(MISCONF_DOWNLOAD_COMMAND);
 	    goto failed;
 	}
 
-	CTRACE(tfp, "command: %s\n", command);
+	CTRACE(tfp, "command: %s\n", the_command);
 	stop_curses();
-	LYSystem(command);
+	LYSystem(the_command);
+	FREE(the_command);
 	start_curses();
 	/* don't remove(file); */
     }
diff --git a/src/LYExtern.c b/src/LYExtern.c
index 652fb3e2..8d22d54b 100644
--- a/src/LYExtern.c
+++ b/src/LYExtern.c
@@ -24,56 +24,35 @@
 #include <LYLeaks.h>
 
 #ifdef USE_EXTERNALS
-void run_external ARGS1(char *, c)
+void run_external ARGS1(char *, cmd)
 {
-	char command[1024];
-	lynx_html_item_type *externals2=0;
+    char *the_command = 0;
+    lynx_html_item_type *ext = 0;
 
-	if (externals == NULL) return;
+    for (ext = externals; ext != NULL; ext = ext->next) {
 
-	for(externals2=externals; externals2 != NULL;
-		 externals2=externals2->next)
-	{
+	if (ext->command != 0
+	&& !strncasecomp(ext->name, cmd, strlen(ext->name))) {
 
-	 if (externals2->command != 0
-	  && !strncasecomp(externals2->name,c,strlen(externals2->name)))
-	 {
-	     char *cp;
+	    if (no_externals && !ext->always_enabled) {
+		HTUserMsg(EXTERNALS_DISABLED);
+	    } else {
 
-		if(no_externals && !externals2->always_enabled)
-		{
-		  HTUserMsg(EXTERNALS_DISABLED);
-		  return;
-		}
+		HTAddParam(&the_command, ext->command, 1, cmd);
+		HTEndParam(&the_command, ext->command, 1);
 
-		/*  Too dangerous to leave any URL that may come along unquoted.
-		 *  They often contain '&', ';', and '?' chars, and who knows
-		 *  what else may occur.
-		 *  Prevent spoofing of the shell.
-		 *  Dunno how this needs to be modified for VMS or DOS. - kw
-		 */
-#if defined(VMS) || defined(DOSPATH) || defined(__EMX__)
-		sprintf(command, externals2->command, c);
-#else /* Unix: */
-		cp = quote_pathname(c);
-		sprintf(command, externals2->command, cp);
-		FREE(cp);
-#endif /* VMS */
+		HTUserMsg(the_command);
 
-		if (*command != '\0')
-		{
+		stop_curses();
+		LYSystem(the_command);
+		FREE(the_command);
+		start_curses();
+	    }
 
-		 HTUserMsg(command);
-
-		 stop_curses();
-		 LYSystem(command);
-		 start_curses();
-		}
-
-		return;
-	 }
+	    break;
 	}
+    }
 
-	return;
+    return;
 }
 #endif /* USE_EXTERNALS */
diff --git a/src/LYForms.c b/src/LYForms.c
index 2de3e9e3..e91f9982 100644
--- a/src/LYForms.c
+++ b/src/LYForms.c
@@ -11,6 +11,7 @@
 #include <LYStrings.h>
 #include <LYGlobalDefs.h>
 #include <LYKeymap.h>
+#include <LYClean.h>
 #include <LYSignal.h>
 
 #include <LYLeaks.h>
@@ -265,10 +266,6 @@ PRIVATE int form_getstr ARGS1(
     BOOL HaveMaxlength = FALSE;
     int action, repeat, non_first = 0;
 
-#ifdef VMS
-    extern BOOLEAN HadVMSInterrupt;	/* Flag from cleanup_sig() AST */
-#endif
-
     EditFieldData MyEdit;
     BOOLEAN Edited = FALSE;		/* Value might be updated? */
 
@@ -482,9 +479,9 @@ breakfor:
 	/*
 	 *  Remove trailing spaces
 	 *
-	 *  Do we really need to do that here? Trailing spaces will only
-	 *  be there if user keyed them in. Rather rude to throw away
-	 *  their hard earned spaces. Better deal with trailing spaces
+	 *  Do we really need to do that here?  Trailing spaces will only
+	 *  be there if user keyed them in.  Rather rude to throw away
+	 *  their hard earned spaces.  Better deal with trailing spaces
 	 *  when submitting the form????
 	 */
 	p = &(form->value[strlen(form->value)]);
@@ -592,9 +589,6 @@ PRIVATE int popup_options ARGS7(
     int window_offset = 0;
     int lines_to_show;
     int npages;
-#ifdef VMS
-    extern BOOLEAN HadVMSInterrupt; /* Flag from cleanup_sig() AST */
-#endif /* VMS */
     static char prev_target[512];		/* Search string buffer */
     static char prev_target_buffer[512];	/* Next search buffer */
     static BOOL first = TRUE;
diff --git a/src/LYGetFile.c b/src/LYGetFile.c
index 6c0b883f..5ea77c2e 100644
--- a/src/LYGetFile.c
+++ b/src/LYGetFile.c
@@ -392,10 +392,7 @@ Try_Redirected_URL:
 			    fflush(stdout);
 			    LYgetch();
 #ifdef VMS
-			    {
-			      extern BOOLEAN HadVMSInterrupt;
-			      HadVMSInterrupt = FALSE;
-			    }
+			    HadVMSInterrupt = FALSE;
 #endif /* VMS */
 			}
 			start_curses();
@@ -672,7 +669,7 @@ Try_Redirected_URL:
 				 *  the RIGHT thing and returning an invalid
 				 *  address message. - FM
 				 */
-				HTAlert(LOCATION_NOT_ABSOLUTE);
+				HTUserMsg(LOCATION_NOT_ABSOLUTE);
 				temp = HTParse(use_this_url_instead,
 					       WWWDoc.address,
 					       PARSE_ALL);
diff --git a/src/LYGlobalDefs.h b/src/LYGlobalDefs.h
index 3028e143..40752064 100644
--- a/src/LYGlobalDefs.h
+++ b/src/LYGlobalDefs.h
@@ -260,7 +260,6 @@ extern int Newline_partial;          /* -//- "current" newline position */
 extern int NumOfLines_partial;       /* -//- "current" number of lines */
 extern int partial_threshold;
 extern BOOLEAN debug_display_partial;  /* show with MessageSecs delay */
-extern BOOLEAN detected_forms_input_partial; /* trimHightext temp fix */
 #endif
 extern char *form_post_data;         /* User data for post form */
 extern char *form_get_data;          /* User data for get form */
diff --git a/src/LYHash.c b/src/LYHash.c
index e6439a3d..265814cd 100644
--- a/src/LYHash.c
+++ b/src/LYHash.c
@@ -31,10 +31,10 @@ PUBLIC int hash_code_rp ARGS1(char*,string)
 /*
  *	This is the same function as the private HASH_FUNCTION() in HTAnchor.c,
  *      but with a different value for HASH_SIZE.
- */ 
+ */
 
 #ifdef NOT_USED
-#define HASH_SIZE 8193		/* Arbitrary prime. Memory/speed tradeoff */
+#define HASH_SIZE 8193		/* Arbitrary prime.  Memory/speed tradeoff */
 #else
 #define HASH_SIZE CSHASHSIZE
 #endif
diff --git a/src/LYHistory.c b/src/LYHistory.c
index 9c94786f..874099e2 100644
--- a/src/LYHistory.c
+++ b/src/LYHistory.c
@@ -266,7 +266,7 @@ PUBLIC void LYpush ARGS2(
 			    HTAnchor_parent(HTAnchor_findAddress(&WWWDoc));
 		    }
 		/* In addition to equality of the ParentAnchors, require
-		** that IF we have a HTMainText (i.e. it wasn't just
+		** that IF we have a HTMainText (i.e., it wasn't just
 		** HTuncache'd by mainloop), THEN it has to be consistent
 		** with what we are trying to push.
 		**   This may be overkill... - kw
diff --git a/src/LYList.c b/src/LYList.c
index c147294a..140d7894 100644
--- a/src/LYList.c
+++ b/src/LYList.c
@@ -10,6 +10,7 @@
 #include <LYUtils.h>
 #include <GridText.h>
 #include <LYList.h>
+#include <LYClean.h>
 #include <LYSignal.h>
 #include <LYGlobalDefs.h>
 #include <LYCharUtils.h>
@@ -237,9 +238,6 @@ PUBLIC void printlist ARGS2(
 	FILE *, 	fp,
 	BOOLEAN,	titles)
 {
-#ifdef VMS
-    extern BOOLEAN HadVMSInterrupt;
-#endif /* VMS */
     int cnt;
     int refs, hidden_links;
     char *address = NULL;
@@ -282,7 +280,7 @@ PUBLIC void printlist ARGS2(
 	    }
 	    dest = HTAnchor_followMainLink((HTAnchor *)child);
 	    /*
-	     *	Ignore if child anchor points to itself, i.e. we had
+	     *	Ignore if child anchor points to itself, i.e., we had
 	     *	something like <A NAME=xyz HREF="#xyz"> and it is not
 	     *	treated as a hidden link.  Useful if someone 'P'rints
 	     *	the List Page (which isn't a very useful action to do,
diff --git a/src/LYLocal.c b/src/LYLocal.c
index 37c63cb3..21bb24a7 100644
--- a/src/LYLocal.c
+++ b/src/LYLocal.c
@@ -43,6 +43,7 @@
 #include <LYHistory.h>
 #include <LYUpload.h>
 #include <LYLocal.h>
+#include <LYClean.h>
 
 #ifndef VMS
 #ifndef _WINDOWS
@@ -134,7 +135,7 @@ struct dired_menu {
 { DE_DIR,	      "", "Modify Directory Name",
 "(of current selection)", "LYNXDIRED://MODIFY_NAME%p",		NULL },
 { DE_SYMLINK,	      "", "Modify Name",
-"(of selected symbolic link)", "LYNXDIRED://MODIFY_NAME%p",		NULL },
+"(of selected symbolic link)", "LYNXDIRED://MODIFY_NAME%p",	NULL },
 
 #ifdef OK_PERMIT
 { DE_FILE,	      "", "Modify File Permissions",
@@ -270,7 +271,7 @@ PRIVATE BOOLEAN ok_file_or_dir ARGS1(struct stat*, sb)
 {
     if (!S_ISDIR(sb->st_mode)
      && !S_ISREG(sb->st_mode)) {
-	HTAlert(gettext("The selected item is not a file or a directory! Request ignored."));
+	HTAlert(gettext("The selected item is not a file or a directory!  Request ignored."));
 	return FALSE;
     }
     return TRUE;
@@ -508,13 +509,13 @@ PRIVATE BOOLEAN modify_tagged ARGS1(
 		clear_tags();
 		return count;
 	    } else {
-		HTAlert(gettext("Destination has different owner! Request denied."));
+		HTAlert(gettext("Destination has different owner!  Request denied."));
 		FREE(srcpath);
 		FREE(savepath);
 		return 0;
 	    }
 	} else {
-	    HTAlert(gettext("Destination is not a valid directory! Request denied."));
+	    HTAlert(gettext("Destination is not a valid directory!  Request denied."));
 	    FREE(savepath);
 	    return 0;
 	}
@@ -549,7 +550,7 @@ PRIVATE BOOLEAN modify_name ARGS1(
 	} else if (S_ISREG(dir_info.st_mode)) {
 	     cp = gettext("Enter new name for file: ");
 	} else {
-	     HTAlert(gettext("The selected item is not a file or a directory! Request ignored."));
+	     HTAlert(gettext("The selected item is not a file or a directory!  Request ignored."));
 	     return 0;
 	}
 	if (filename(cp, tmpbuf, sizeof(tmpbuf)) == NULL)
@@ -589,11 +590,11 @@ PRIVATE BOOLEAN modify_name ARGS1(
 		    return code;
 		}
 	    } else if (S_ISDIR(dir_info.st_mode)) {
-		HTAlert(gettext("There is already a directory with that name! Request ignored."));
+		HTAlert(gettext("There is already a directory with that name!  Request ignored."));
 	    } else if (S_ISREG(dir_info.st_mode)) {
-		HTAlert(gettext("There is already a file with that name! Request ignored."));
+		HTAlert(gettext("There is already a file with that name!  Request ignored."));
 	    } else {
-		HTAlert(gettext("The specified name is already in use! Request ignored."));
+		HTAlert(gettext("The specified name is already in use!  Request ignored."));
 	    }
 	}
     }
@@ -675,7 +676,7 @@ PRIVATE BOOLEAN modify_location ARGS1(
 	    return 0;
 	}
 	if (!S_ISDIR(dir_info.st_mode)) {
-	    HTAlert(gettext("Destination is not a valid directory! Request denied."));
+	    HTAlert(gettext("Destination is not a valid directory!  Request denied."));
 	    return 0;
 	}
 
@@ -683,7 +684,7 @@ PRIVATE BOOLEAN modify_location ARGS1(
 	 *  Make sure the source and target are not the same location.
 	 */
 	if (dev == dir_info.st_dev && inode == dir_info.st_ino) {
-	    HTAlert(gettext("Source and destination are the same location! Request ignored!"));
+	    HTAlert(gettext("Source and destination are the same location!  Request ignored!"));
 	    return 0;
 	}
 	if (dir_info.st_uid == owner) {
@@ -698,7 +699,7 @@ PRIVATE BOOLEAN modify_location ARGS1(
 	    FREE(msg);
 	    return code;
 	} else {
-	    HTAlert(gettext("Destination has different owner! Request denied."));
+	    HTAlert(gettext("Destination has different owner!  Request denied."));
 	    return 0;
 	}
     }
@@ -829,11 +830,11 @@ PRIVATE BOOLEAN create_file ARGS1(
 	    FREE(msg);
 	    return code;
 	} else if (S_ISDIR(dir_info.st_mode)) {
-	    HTAlert(gettext("There is already a directory with that name! Request ignored."));
+	    HTAlert(gettext("There is already a directory with that name!  Request ignored."));
 	} else if (S_ISREG(dir_info.st_mode)) {
-	    HTAlert(gettext("There is already a file with that name! Request ignored."));
+	    HTAlert(gettext("There is already a file with that name!  Request ignored."));
 	} else {
-	    HTAlert(gettext("The specified name is already in use! Request ignored."));
+	    HTAlert(gettext("The specified name is already in use!  Request ignored."));
 	}
     }
     return 0;
@@ -889,11 +890,11 @@ PRIVATE BOOLEAN create_directory ARGS1(
 	    FREE(msg);
 	    return code;
 	} else if (S_ISDIR(dir_info.st_mode)) {
-	    HTAlert(gettext("There is already a directory with that name! Request ignored."));
+	    HTAlert(gettext("There is already a directory with that name!  Request ignored."));
 	} else if (S_ISREG(dir_info.st_mode)) {
-	    HTAlert(gettext("There is already a file with that name! Request ignored."));
+	    HTAlert(gettext("There is already a file with that name!  Request ignored."));
 	} else {
-	    HTAlert(gettext("The specified name is already in use! Request ignored."));
+	    HTAlert(gettext("The specified name is already in use!  Request ignored."));
 	}
     }
     return 0;
@@ -1361,9 +1362,24 @@ PUBLIC void showtags ARGS1(
     }
 }
 
+PRIVATE char * DirectoryOf ARGS1(
+	char *,		pathname)
+{
+    char *result = 0;
+    char *leaf;
+
+    StrAllocCopy(result, pathname);
+    leaf = LYPathLeaf(result);
+    if (leaf != result) {
+	*leaf = '\0';
+	LYTrimPathSep(result);
+    }
+    return result;
+}
+
 /*
  *  Perform file management operations for LYNXDIRED URL's.
- *  Attempt to be consistent.  These are (pseudo) URLs - i.e. they should
+ *  Attempt to be consistent.  These are (pseudo) URLs - i.e., they should
  *  be in URL syntax: some bytes will be URL-escaped with '%'.	This is
  *  necessary because these (pseudo) URLs will go through some of the same
  *  kinds of interpretations and mutilations as real ones: HTParse, stripping
@@ -1371,17 +1387,15 @@ PUBLIC void showtags ARGS1(
  *  about not escaping parsing '#' "the URL way" built into HTParse, but that
  *  doesn't look like a clean way.)
  */
-#ifdef VMS
-    extern BOOLEAN HadVMSInterrupt;
-#endif /* VMS */
 PUBLIC int local_dired ARGS1(
 	document *,	doc)
 {
     char *line_url;    /* will point to doc's address, which is a URL */
     char *line = NULL; /* same as line_url, but HTUnEscaped, will be alloced */
-    char *cp, *tp, *bp;
+    char *tp;
     char *tmpbuf = NULL;
     char *buffer = NULL;
+    char *dirname = NULL;
 
     line_url = doc->address;
     CTRACE(tfp, "local_dired: called for <%s>.\n",
@@ -1449,7 +1463,7 @@ PUBLIC int local_dired ARGS1(
 	    LYforce_no_cache = TRUE;
     } else {
 	LYTrimPathSep(line);
-	if ((cp = strrchr(line, '/')) == NULL) {
+	if (strrchr(line, '/') == NULL) {
 	    FREE(line);
 	    return 0;
 	}
@@ -1459,117 +1473,125 @@ PUBLIC int local_dired ARGS1(
 	 *  escape all path references to avoid spoofing the shell.
 	 */
 	if (!strncmp(line, "LYNXDIRED://DECOMPRESS", 22)) {
-	    tp = quote_pathname(line + 22);
-	    HTSprintf0(&buffer,"%s %s", UNCOMPRESS_PATH, tp);
-	    FREE(tp);
+#define FMT_UNCOMPRESS "%s %s"
+	    HTAddParam(&buffer, FMT_UNCOMPRESS, 1, UNCOMPRESS_PATH);
+	    HTAddParam(&buffer, FMT_UNCOMPRESS, 2, line+22);
+	    HTEndParam(&buffer, FMT_UNCOMPRESS, 2);
 
 #if defined(OK_UUDECODE) && !defined(ARCHIVE_ONLY)
 	} else if (!strncmp(line, "LYNXDIRED://UUDECODE", 20)) {
-	    tp = quote_pathname(line + 20);
-	    HTSprintf0(&buffer,"%s %s", UUDECODE_PATH, tp);
-	    HTAlert(gettext("Warning! UUDecoded file will exist in the directory you started Lynx."));
-	    FREE(tp);
+#define FMT_UUDECODE "%s %s"
+	    HTAddParam(&buffer, FMT_UUDECODE, 1, UUDECODE_PATH);
+	    HTAddParam(&buffer, FMT_UUDECODE, 2, line+20);
+	    HTEndParam(&buffer, FMT_UUDECODE, 2);
+	    HTAlert(gettext("Warning!  UUDecoded file will exist in the directory you started Lynx."));
 #endif /* OK_UUDECODE && !ARCHIVE_ONLY */
 
 #ifdef OK_TAR
 # ifndef ARCHIVE_ONLY
 #  ifdef OK_GZIP
 	} else if (!strncmp(line, "LYNXDIRED://UNTAR_GZ", 20)) {
-	    tp = quote_pathname(line+20);
-	    *cp++ = '\0';
-	    cp = quote_pathname(line + 20);
-	    HTSprintf0(&buffer, "%s -qdc %s | (cd %s; %s -xf -)",
-				GZIP_PATH, tp, cp, TAR_PATH);
-	    FREE(cp);
-	    FREE(tp);
+#define FMT_UNTAR_GZ "%s -qdc %s | (cd %s; %s -xf -)"
+	    dirname = DirectoryOf(line+20);
+	    HTAddParam(&buffer, FMT_UNTAR_GZ, 1, GZIP_PATH);
+	    HTAddParam(&buffer, FMT_UNTAR_GZ, 2, line+20);
+	    HTAddParam(&buffer, FMT_UNTAR_GZ, 3, dirname);
+	    HTAddParam(&buffer, FMT_UNTAR_GZ, 4, TAR_PATH);
+	    HTEndParam(&buffer, FMT_UNTAR_GZ, 4);
 #  endif /* OK_GZIP */
 
 	} else if (!strncmp(line, "LYNXDIRED://UNTAR_Z", 19)) {
-	    tp = quote_pathname(line + 19);
-	    *cp++ = '\0';
-	    cp = quote_pathname(line + 19);
-	    HTSprintf0(&buffer, "%s %s | (cd %s; %s -xf -)",
-				ZCAT_PATH, tp, cp, TAR_PATH);
-	    FREE(cp);
-	    FREE(tp);
+#define FMT_UNTAR_Z "%s %s | (cd %s; %s -xf -)"
+	    dirname = DirectoryOf(line+19);
+	    HTAddParam(&buffer, FMT_UNTAR_Z, 1, ZCAT_PATH);
+	    HTAddParam(&buffer, FMT_UNTAR_Z, 2, line+19);
+	    HTAddParam(&buffer, FMT_UNTAR_Z, 3, dirname);
+	    HTAddParam(&buffer, FMT_UNTAR_Z, 4, TAR_PATH);
+	    HTEndParam(&buffer, FMT_UNTAR_Z, 4);
 
 	} else if (!strncmp(line, "LYNXDIRED://UNTAR", 17)) {
-	    tp = quote_pathname(line + 17);
-	    *cp++ = '\0';
-	    cp = quote_pathname(line + 17);
-	    HTSprintf0(&buffer, "cd %s; %s -xf %s", cp, TAR_PATH, tp);
-	    FREE(cp);
-	    FREE(tp);
+#define FMT_UNTAR "cd %s; %s -xf %s"
+	    dirname = DirectoryOf(line+17);
+	    HTAddParam(&buffer, FMT_UNTAR, 1, dirname);
+	    HTAddParam(&buffer, FMT_UNTAR, 2, TAR_PATH);
+	    HTAddParam(&buffer, FMT_UNTAR, 3, line+17);
+	    HTEndParam(&buffer, FMT_UNTAR, 3);
 # endif /* !ARCHIVE_ONLY */
 
 # ifdef OK_GZIP
 	} else if (!strncmp(line, "LYNXDIRED://TAR_GZ", 18)) {
-	    *cp++ = '\0';
-	    cp = quote_pathname(cp);
-	    tp = quote_pathname(line + 18);
-	    HTSprintf0(&buffer, "(cd %s; %s -cf - %s) | %s -qc >%s/%s.tar.gz",
-				tp, TAR_PATH, cp, GZIP_PATH, tp, cp);
-	    FREE(cp);
-	    FREE(tp);
+#define FMT_TAR_GZ "(cd %s; %s -cf - %s) | %s -qc >%s/%s.tar.gz"
+	    dirname = DirectoryOf(line+18);
+	    HTAddParam(&buffer, FMT_TAR_GZ, 1, dirname);
+	    HTAddParam(&buffer, FMT_TAR_GZ, 2, TAR_PATH);
+	    HTAddParam(&buffer, FMT_TAR_GZ, 3, LYPathLeaf(line+18));
+	    HTAddParam(&buffer, FMT_TAR_GZ, 4, GZIP_PATH);
+	    HTAddParam(&buffer, FMT_TAR_GZ, 5, dirname);
+	    HTAddParam(&buffer, FMT_TAR_GZ, 6, LYPathLeaf(line+18));
+	    HTEndParam(&buffer, FMT_TAR_GZ, 6);
 # endif /* OK_GZIP */
 
 	} else if (!strncmp(line, "LYNXDIRED://TAR_Z", 17)) {
-	    *cp++ = '\0';
-	    cp = quote_pathname(cp);
-	    tp = quote_pathname(line + 17);
-	    HTSprintf0(&buffer, "(cd %s; %s -cf - %s) | %s >%s/%s.tar.Z",
-				tp, TAR_PATH, cp, COMPRESS_PATH, tp, cp);
-	    FREE(cp);
-	    FREE(tp);
+#define FMT_TAR_Z "(cd %s; %s -cf - %s) | %s >%s/%s.tar.Z"
+	    dirname = DirectoryOf(line+17);
+	    HTAddParam(&buffer, FMT_TAR_Z, 1, dirname);
+	    HTAddParam(&buffer, FMT_TAR_Z, 2, TAR_PATH);
+	    HTAddParam(&buffer, FMT_TAR_Z, 3, LYPathLeaf(line+17));
+	    HTAddParam(&buffer, FMT_TAR_Z, 4, COMPRESS_PATH);
+	    HTAddParam(&buffer, FMT_TAR_Z, 5, dirname);
+	    HTAddParam(&buffer, FMT_TAR_Z, 6, LYPathLeaf(line+17));
+	    HTEndParam(&buffer, FMT_TAR_Z, 6);
 
 	} else if (!strncmp(line, "LYNXDIRED://TAR", 15)) {
-	    *cp++ = '\0';
-	    cp = quote_pathname(cp);
-	    tp = quote_pathname(line + 15);
-	    HTSprintf0(&buffer, "(cd %s; %s -cf %s.tar %s)",
-			    tp, TAR_PATH, cp, cp);
-	    FREE(cp);
-	    FREE(tp);
+#define FMT_TAR "(cd %s; %s -cf %s.tar %s)"
+	    dirname = DirectoryOf(line+15);
+	    HTAddParam(&buffer, FMT_TAR, 1, dirname);
+	    HTAddParam(&buffer, FMT_TAR, 2, TAR_PATH);
+	    HTAddParam(&buffer, FMT_TAR, 3, LYPathLeaf(line+15));
+	    HTAddParam(&buffer, FMT_TAR, 4, LYPathLeaf(line+15));
+	    HTEndParam(&buffer, FMT_TAR, 4);
 #endif /* OK_TAR */
 
 #ifdef OK_GZIP
 	} else if (!strncmp(line, "LYNXDIRED://GZIP", 16)) {
-	    tp = quote_pathname(line + 16);
-	    HTSprintf0(&buffer, "%s -q %s", GZIP_PATH, tp);
-	    FREE(tp);
+#define FMT_GZIP "%s -q %s"
+	    HTAddParam(&buffer, FMT_GZIP, 1, GZIP_PATH);
+	    HTAddParam(&buffer, FMT_GZIP, 2, line+16);
+	    HTEndParam(&buffer, FMT_GZIP, 2);
 #ifndef ARCHIVE_ONLY
 	} else if (!strncmp(line, "LYNXDIRED://UNGZIP", 18)) {
-	    tp = quote_pathname(line + 18);
-	    HTSprintf0(&buffer, "%s -d %s", GZIP_PATH, tp);
-	    FREE(tp);
+#define FMT_UNGZIP "%s -d %s"
+	    HTAddParam(&buffer, FMT_UNGZIP, 1, GZIP_PATH);
+	    HTAddParam(&buffer, FMT_UNGZIP, 2, line+18);
+	    HTEndParam(&buffer, FMT_UNGZIP, 2);
 #endif /* !ARCHIVE_ONLY */
 #endif /* OK_GZIP */
 
 #ifdef OK_ZIP
 	} else if (!strncmp(line, "LYNXDIRED://ZIP", 15)) {
-	    tp = quote_pathname(line + 15);
-	    *cp++ = '\0';
-	    bp = quote_pathname(cp);
-	    cp = quote_pathname(line + 15);
-	    HTSprintf0(&buffer, "cd %s; %s -rq %s.zip %s", cp, ZIP_PATH, tp, bp);
-	    FREE(cp);
-	    FREE(bp);
-	    FREE(tp);
+#define FMT_ZIP "cd %s; %s -rq %s.zip %s"
+	    dirname = DirectoryOf(line+15);
+	    HTAddParam(&buffer, FMT_ZIP, 1, dirname);
+	    HTAddParam(&buffer, FMT_ZIP, 2, ZIP_PATH);
+	    HTAddParam(&buffer, FMT_ZIP, 3, line+15);
+	    HTAddParam(&buffer, FMT_ZIP, 4, LYPathLeaf(line+15));
+	    HTEndParam(&buffer, FMT_ZIP, 4);
 #ifndef ARCHIVE_ONLY
 	} else if (!strncmp(line, "LYNXDIRED://UNZIP", 17)) {
-	    tp = quote_pathname(line + 17);
-	    *cp = '\0';
-	    cp = quote_pathname(line + 17);
-	    HTSprintf0(&buffer, "cd %s; %s -q %s", cp, UNZIP_PATH, tp);
-	    FREE(cp);
-	    FREE(tp);
+#define FMT_UNZIP "cd %s; %s -q %s"
+	    dirname = DirectoryOf(line+17);
+	    HTAddParam(&buffer, FMT_UNZIP, 1, dirname);
+	    HTAddParam(&buffer, FMT_UNZIP, 2, UNZIP_PATH);
+	    HTAddParam(&buffer, FMT_UNZIP, 3, line+17);
+	    HTEndParam(&buffer, FMT_UNZIP, 3);
 # endif /* !ARCHIVE_ONLY */
 #endif /* OK_ZIP */
 
 	} else if (!strncmp(line, "LYNXDIRED://COMPRESS", 20)) {
-	    tp = quote_pathname(line + 20);
-	    HTSprintf0(&buffer, "%s %s", COMPRESS_PATH, tp);
-	    FREE(tp);
+#define FMT_COMPRESS "%s %s"
+	    HTAddParam(&buffer, FMT_COMPRESS, 1, COMPRESS_PATH);
+	    HTAddParam(&buffer, FMT_COMPRESS, 2, line+20);
+	    HTEndParam(&buffer, FMT_COMPRESS, 2);
 	}
 
 	if (buffer != 0) {
@@ -1591,6 +1613,7 @@ PUBLIC int local_dired ARGS1(
 	}
     }
 
+    FREE(dirname);
     FREE(tmpbuf);
     FREE(buffer);
     FREE(line);
@@ -1825,7 +1848,7 @@ PUBLIC BOOLEAN local_install ARGS3(
     if (!ok_stat(destpath, &dir_info)) {
 	return 0;
     } else if (!S_ISDIR(dir_info.st_mode)) {
-	HTAlert(gettext("The selected item is not a directory! Request ignored."));
+	HTAlert(gettext("The selected item is not a directory!  Request ignored."));
 	return 0;
     } else if (0 /*directory not writable*/) {
 	HTAlert(gettext("Install in the selected directory not permitted."));
@@ -2022,7 +2045,7 @@ PRIVATE char * render_item ARGS6(
 	} else {
 	    /*
 	     *	Other chars come from the lynx.cfg or
-	     *	the default. Let's assume there isn't
+	     *	the default.  Let's assume there isn't
 	     *	anything weird there that needs escaping.
 	     */
 	    *BP_INC =*s;
diff --git a/src/LYMail.c b/src/LYMail.c
index 73bf04bd..3f483194 100644
--- a/src/LYMail.c
+++ b/src/LYMail.c
@@ -503,7 +503,7 @@ PUBLIC void mailform ARGS4(
 	 *  won't confuse the mailer and give a blank address.
 	 *
 	 *  ignore addresses so long that they would overflow the
-	 *  temporary buffer (i.e. about 500 chars). - BL
+	 *  temporary buffer (i.e., about 500 chars). - BL
 	 */
 	if (strlen(address_ptr1) > 3 &&
             strlen(address_ptr1) + strlen(mail_adrs) < sizeof(cmd)) {
@@ -536,7 +536,7 @@ PUBLIC void mailform ARGS4(
 	     *	won't confuse the mailer and give a blank address.
 	     *
 	     *  ignore addresses so long that they would overflow the
-	     *  temporary buffer (i.e. about 500 chars). - BL
+	     *  temporary buffer (i.e., about 500 chars). - BL
 	     */
 	    if (strlen(address_ptr1) > 3 &&
                 strlen(address_ptr1) + strlen(mail_adrs) < sizeof(cmd)) {
@@ -797,7 +797,7 @@ PUBLIC void mailmsg ARGS4(
 	 *  won't confuse the mailer and give a blank address.
 	 *
 	 *  ignore addresses so long that they would overflow the
-	 *  temporary buffer (i.e. about 500 chars). - BL
+	 *  temporary buffer (i.e., about 500 chars). - BL
 	 */
 	if (strlen(address) > 3 &&
             strlen(address) + strlen(mail_adrs) < sizeof(cmd)) {
@@ -1766,7 +1766,7 @@ PUBLIC void reply_by_mail ARGS3(
 	 *  won't confuse the mailer and give a blank address.
 	 *
 	 *  ignore addresses so long that they would overflow the
-	 *  temporary buffer (i.e. about 500 chars). - BL
+	 *  temporary buffer (i.e., about 500 chars). - BL
 	 */
 	if (strlen(address_ptr1) > 3 &&
             strlen(address_ptr1) + strlen(mail_adrs) < sizeof(cmd)) {
@@ -1799,7 +1799,7 @@ PUBLIC void reply_by_mail ARGS3(
 	     *	won't confuse the mailer and give a blank address.
 	     *
 	     *  ignore addresses so long that they would overflow the
-	     *  temporary buffer (i.e. about 500 chars). - BL
+	     *  temporary buffer (i.e., about 500 chars). - BL
 	     */
 	    if (strlen(address_ptr1) > 3 &&
                 strlen(address_ptr1) + strlen(mail_adrs) < sizeof(cmd)) {
diff --git a/src/LYMain.c b/src/LYMain.c
index 12edc851..852a9c59 100644
--- a/src/LYMain.c
+++ b/src/LYMain.c
@@ -367,7 +367,6 @@ PUBLIC BOOLEAN LYQuitDefaultYes = QUIT_DEFAULT_YES;
 #ifdef DISP_PARTIAL
 PUBLIC BOOLEAN display_partial = TRUE; /* Display document during download */
 PUBLIC BOOLEAN debug_display_partial = FALSE; /* Show with MessageSecs delay */
-PUBLIC BOOLEAN detected_forms_input_partial = FALSE; /* trimHightext temp fix */
 PUBLIC int partial_threshold = -1;  /* # of lines to be d/l'ed until we repaint */
 #endif
 
@@ -485,7 +484,6 @@ PRIVATE void free_lynx_globals NOARGS
     FREE(lynxjumpfile);
     FREE(startrealm);
     FREE(personal_mail_address);
-    FREE(UC_TEMPcharset);
     FREE(URLDomainPrefixes);
     FREE(URLDomainSuffixes);
     FREE(XLoadImageCommand);
@@ -753,7 +751,7 @@ PUBLIC int main ARGS2(
 #else
     StrAllocCopy(lynx_version_putenv_command, "LYNX_VERSION=");
     StrAllocCat(lynx_version_putenv_command, LYNX_VERSION);
-    putenv(lynx_version_putenv_command);
+    (void) putenv(lynx_version_putenv_command);
 #endif /* VMS */
 
     if ((cp = getenv("LYNX_TEMP_SPACE")) != NULL)
@@ -1218,7 +1216,7 @@ PUBLIC int main ARGS2(
     /*
      *  (**) in Lynx, UCLYhndl_HTFile_for_unspec and UCLYhndl_for_unrec may be
      *  valid or not, but current_char_set and UCLYhndl_for_unspec SHOULD
-     *  ALWAYS be a valid charset. Initialized here and may be changed later
+     *  ALWAYS be a valid charset.  Initialized here and may be changed later
      *  from lynx.cfg/command_line/options_menu. - LP  (**)
      */
     /*
@@ -1732,6 +1730,14 @@ PUBLIC int main ARGS2(
 	    (keypad_mode == LINKS_ARE_NUMBERED ||
 	     keypad_mode == LINKS_AND_FORM_FIELDS_ARE_NUMBERED))
 	    printlist(stdout,FALSE);
+#ifdef EXP_PERSISTENT_COOKIES
+	/*
+	 *  We want to save cookies picked up when in immediate dump
+	 *  mode.  Instead of calling cleanup() here, let's only call
+	 *  this one. - BJP
+	 */
+	LYStoreCookies(LYCookieFile);
+#endif /* EXP_PERSISTENT_COOKIES */
 	exit_immediately(status);
     } else {
 	/*
diff --git a/src/LYMainLoop.c b/src/LYMainLoop.c
index 9b601f3c..c38a5d4b 100644
--- a/src/LYMainLoop.c
+++ b/src/LYMainLoop.c
@@ -216,9 +216,6 @@ int mainloop NOARGS
     char cfile[128];
     FILE *cfp;
     char *cp, *toolbar;
-#ifdef VMS
-    extern BOOLEAN HadVMSInterrupt;   /* Flag from cleanup_sig */
-#endif /* VMS */
     int ch, recall;
     int URLTotal;
     int URLNum;
@@ -1238,7 +1235,7 @@ try_again:
 		    /*
 		     *	We may have popped a doc (possibly in local_dired)
 		     *	which didn't have any links when it was pushed, but
-		     *	does have links now (e.g. a file was created) - KW
+		     *	does have links now (e.g., a file was created) - KW
 		     */
 		    curdoc.link = 0;
 		}
@@ -2558,7 +2555,7 @@ new_cmd:  /*
 		 *  Check if the previous document is a reply from a POST,
 		 *  and if so, seek confirmation of resubmission if the safe
 		 *  element is not set and the document is not still in the
-		 *  cache or LYresubmit_posts is set. If not confirmed and
+		 *  cache or LYresubmit_posts is set.  If not confirmed and
 		 *  it is not the startfile, pop it so we go to the yet
 		 *  previous document, until we're OK or reach the startfile.
 		 *  If we reach the startfile and its not OK or we don't get
diff --git a/src/LYMap.c b/src/LYMap.c
index 55b44121..d28cff2f 100644
--- a/src/LYMap.c
+++ b/src/LYMap.c
@@ -105,7 +105,7 @@ PRIVATE void LYLynxMaps_free NOARGS
  *    HTParentAnchor structure and is freed when the document is removed
  *    from memory, in the course of normal removal of anchors.
  *    MAPs from POST responses can only be accessed via internal links,
- *    i.e. from within the same document (with the same post_data).
+ *    i.e., from within the same document (with the same post_data).
  *    The notion of "same document" is extended, so that LYNXIMGMAP:
  *    and List Page screens are logically part of the document on which
  *    they are based. - kw
@@ -318,7 +318,7 @@ PUBLIC BOOL LYHaveImageMap ARGS1(
  *  the underlying resource.  ALso returns a pointer to that anchor in
  *  *punderlying if we are dealing with POST data. - kw
  *
- *  address  is the address of the underlying resource, i.e. the one
+ *  address  is the address of the underlying resource, i.e., the one
  *	     containing the MAP element, the MAP's name appended as
  *	     fragment is ignored.
  *  anAnchor is the LYNXIMGMAP: anchor; if it is associated with POST
@@ -361,7 +361,7 @@ PRIVATE void fill_DocAddress ARGS4(
  *  list if a List Page for a POST response is requested.  Also
  *  fill in the DocAddress structure etc. by calling fill_DocAddress().
  *
- *  address is the address of the underlying resource, i.e. the one
+ *  address is the address of the underlying resource, i.e., the one
  *	    containing the MAP element, the MAP's name appended as
  *	    fragment is ignored.
  *  anchor  is the LYNXIMGMAP: anchor for which LYLoadIMGmap() is
diff --git a/src/LYOptions.c b/src/LYOptions.c
index 848e4a25..6ac5fa41 100644
--- a/src/LYOptions.c
+++ b/src/LYOptions.c
@@ -1733,9 +1733,6 @@ PRIVATE int boolean_choice ARGS4(
     int number = 0;
     int col = (column >= 0 ? column : COL_OPTION_VALUES);
     int orig_choice = cur_choice;
-#ifdef VMS
-    extern BOOLEAN HadVMSInterrupt; /* Flag from cleanup_sig() AST */
-#endif /* VMS */
 
     /*
      *	Get the number of choices and then make
@@ -2243,9 +2240,6 @@ PRIVATE int popup_choice ARGS6(
     char Cnum[64];
     int Lnum;
     int npages;
-#ifdef VMS
-    extern BOOLEAN HadVMSInterrupt; /* Flag from cleanup_sig() AST */
-#endif /* VMS */
     static char prev_target[512];		/* Search string buffer */
     static char prev_target_buffer[512];	/* Next search buffer */
     static BOOL first = TRUE;
@@ -3526,7 +3520,10 @@ PUBLIC int postoptions ARGS1(
     if (strstr(newdoc->address, "LYNXOPTIONS://MBM_MENU")) {
 	FREE(newdoc->post_data);
 	FREE(data);
-	edit_bookmarks();
+	if (!no_bookmark)
+	   edit_bookmarks();
+	else /* anonymous */
+	   HTAlert(BOOKMARK_CHANGE_DISALLOWED);
 	return(NULLFILE);
     }
 
@@ -3686,8 +3683,8 @@ PUBLIC int postoptions ARGS1(
 	    }
 	}
 
-	/* Single Bookmarks filename: INPUT */
-	if (!strcmp(data[i].tag, single_bookmark_string)) {
+	/* Default Bookmarks filename: INPUT */
+	if (!strcmp(data[i].tag, single_bookmark_string) && (!no_bookmark)) {
 	    if (strcmp(data[i].value, "")) {
 		FREE(bookmark_page);
 		StrAllocCopy(bookmark_page, data[i].value);
diff --git a/src/LYPrint.c b/src/LYPrint.c
index e7b3e27f..dbdd7f5a 100644
--- a/src/LYPrint.c
+++ b/src/LYPrint.c
@@ -59,10 +59,53 @@ PRIVATE int remove_quotes PARAMS((char *string));
 
 PRIVATE  char* subject_translate8bit PARAMS((char *source));
 
+#define LYNX_PRINT_TITLE   0
+#define LYNX_PRINT_URL     1
+#define LYNX_PRINT_DATE    2
+#define LYNX_PRINT_LASTMOD 3
+
+#define MAX_PUTENV 4
+
+PRIVATE void set_environ ARGS3(
+	int,		name,
+	CONST char *,	value,
+	CONST char *,	no_value)
+{
+    static CONST char *names[MAX_PUTENV] = {
+	"LYNX_PRINT_TITLE",
+	"LYNX_PRINT_URL",
+	"LYNX_PRINT_DATE",
+	"LYNX_PRINT_LASTMOD",
+    };
+    static char *pointers[MAX_PUTENV];
+    char *envbuffer = 0;
+#ifdef VMS
+#define SET_ENVIRON(name, value, no_value) set_environ(name, value, no_value)
+    StrAllocCopy(envbuffer, value);
+    if (!(envbuffer && *envbuffer))
+	StrAllocCopy(envbuffer, no_value);
+    Define_VMSLogical(names[name], envbuffer);
+    FREE(envbuffer);
+#else
+#define SET_ENVIRON(name, value, no_value) set_environ(name, value, "")
+    /*
+     * Once we've given a string to 'putenv()', we must not free it until we
+     * give it a string to replace it.
+     */
+    StrAllocCopy(envbuffer, names[name]);
+    StrAllocCat(envbuffer, "=");
+    StrAllocCat(envbuffer, value ? value : no_value);
+    putenv(envbuffer);
+    FREE(pointers[name]);
+    pointers[name] = envbuffer;
+#endif
+}
+
 PUBLIC int printfile ARGS1(
 	document *,	newdoc)
 {
     static char tempfile[LY_MAXPATH];
+    char *the_command = 0;
     char buffer[LINESIZE];
     char filename[LINESIZE];
     char user_response[256];
@@ -89,7 +132,6 @@ PUBLIC int printfile ARGS1(
     CONST char *disp_charset;
     char *subject = NULL;   /* print-to-email */
     static BOOLEAN first_mail_preparsed = TRUE;
-    char *envbuffer = NULL;
 #ifdef VMS
     BOOLEAN isPMDF = FALSE;
     char hdrfile[LY_MAXPATH];
@@ -340,103 +382,24 @@ PUBLIC int printfile ARGS1(
 		    break;
 		}
 
-		if (no_dotfiles || !show_dotfiles) {
-		    if (*LYPathLeaf(filename) == '.') {
-			HTAlert(FILENAME_CANNOT_BE_DOT);
-			_statusline(NEW_FILENAME_PROMPT);
-			FirstRecall = TRUE;
-			FnameNum = FnameTotal;
-			goto retry;
-		    }
-		}
-		/*
-		 *  Cancel if the user entered "/dev/null" on Unix,
-		 *  or an "nl:" path (case-insensitive) on VMS. - FM
-		 */
-#ifdef VMS
-		if (!strncasecomp(filename, "nl:", 3) ||
-		    !strncasecomp(filename, "/nl/", 4))
-#else
-		if (!strcmp(filename, "/dev/null"))
-#endif /* VMS */
-		{
+		if (!LYValidateFilename(buffer, filename)) {
 		    HTInfoMsg(SAVE_REQUEST_CANCELLED);
 		    break;
 		}
-		if ((cp = strchr(filename, '~'))) {
-		    *(cp++) = '\0';
-		    strcpy(buffer, filename);
-		    LYTrimPathSep(buffer);
-		    strcat(buffer, wwwName(Home_Dir()));
-		    strcat(buffer, cp);
-		    strcpy(filename, buffer);
-		}
-#ifdef VMS
-		if (strchr(filename, '/') != NULL) {
-		    strcpy(buffer, HTVMS_name("", filename));
-		    strcpy(filename, buffer);
-		}
-		if (filename[0] != '/' && strchr(filename, ':') == NULL) {
-		    strcpy(buffer, "sys$disk:");
-		    if (strchr(filename, ']') == NULL)
-		    strcat(buffer, "[]");
-		    strcat(buffer, filename);
-		} else {
-		    strcpy(buffer, filename);
-		}
-#else
-
-#ifndef __EMX__
-		if (!LYIsPathSep(*filename)) {
-#if defined(__DJGPP__) || defined(_WINDOWS)
-		if (strchr(buffer, ':') != NULL)
-			cp = NULL;
-		else
-#endif /*  __DJGPP__ || _WINDOWS */
-		    cp = getenv("PWD");
-		}
-		else
-#endif
-		    cp = NULL;
-
-		LYTrimPathSep(cp);
-		if (cp)
-		    sprintf(buffer, "%s/%s", cp, HTSYS_name(filename));
-		else
-		    strcpy(buffer, HTSYS_name(filename));
-#endif /* VMS */
 
 		/*
 		 *  See if it already exists.
 		 */
-		if ((outfile_fp = fopen(buffer, "r")) != NULL) {
-		    fclose(outfile_fp);
-#ifdef VMS
-		    _statusline(FILE_EXISTS_HPROMPT);
-#else
-		    _statusline(FILE_EXISTS_OPROMPT);
-#endif /* VMS */
-		    c = 0;
-		    while (TOUPPER(c)!='Y' && TOUPPER(c)!='N' &&
-			   TOUPPER(c)!='A' && c != 7 && c != 3)
-			c = LYgetch();
-#ifdef VMS
-		    if (HadVMSInterrupt) {
-			HadVMSInterrupt = FALSE;
-			HTInfoMsg(SAVE_REQUEST_CANCELLED);
-			break;
-		    }
-#endif /* VMS */
-		    if (c == 7 || c == 3) { /* Control-G or Control-C */
-			HTInfoMsg(SAVE_REQUEST_CANCELLED);
-			break;
-		    }
-		    if (TOUPPER(c) == 'N') {
-			_statusline(NEW_FILENAME_PROMPT);
-			FirstRecall = TRUE;
-			FnameNum = FnameTotal;
-			goto retry;
-		    }
+		switch (LYValidateOutput(buffer)) {
+		case 'Y':
+		    break;
+		case 'N':
+		    _statusline(NEW_FILENAME_PROMPT);
+		    FirstRecall = TRUE;
+		    FnameNum = FnameTotal;
+		    goto retry;
+		default:
+		    goto done;
 		}
 
 		/*
@@ -444,6 +407,23 @@ PUBLIC int printfile ARGS1(
 		 */
 		CTRACE(tfp, "LYPrint: filename is %s, action is `%c'\n", buffer, c);
 
+#if HAVE_POPEN
+		if (*buffer == '|') {
+		    if (no_shell) {
+			HTUserMsg(SPAWNING_DISABLED);
+			FirstRecall = TRUE;
+			FnameNum = FnameTotal;
+			goto retry;
+		    } else if ((outfile_fp = popen(buffer+1, "w")) == NULL) {
+			CTRACE(tfp, "LYPrint: errno is %d\n", errno);
+			HTAlert(CANNOT_WRITE_TO_FILE);
+			_statusline(NEW_FILENAME_PROMPT);
+			FirstRecall = TRUE;
+			FnameNum = FnameTotal;
+			goto retry;
+		    }
+		} else
+#endif
 		if ((outfile_fp = (TOUPPER(c) == 'A'
 			? LYAppendToTxtFile(buffer)
 			: LYNewTxtFile(buffer))) == NULL) {
@@ -510,6 +490,11 @@ PUBLIC int printfile ARGS1(
 		if (keypad_mode)
 		    printlist(outfile_fp,FALSE);
 
+#if HAVE_POPEN
+		if (LYIsPipeCommand(buffer))
+		    pclose(outfile_fp);
+		else
+#endif
 		fclose(outfile_fp);
 #ifdef VMS
 		if (0 == strncasecomp(buffer, "sys$disk:", 9)) {
@@ -588,7 +573,17 @@ PUBLIC int printfile ARGS1(
 		 *  MORE readable and 8-bit letters shouldn't be a problem - LP
 		 */
 		/* change_sug_filename(sug_filename); */
-		StrAllocCopy(subject, subject_translate8bit(newdoc->title));
+	       subject = subject_translate8bit(newdoc->title);
+
+	       if (newdoc->isHEAD) {
+		       /*
+			* Special case for mailing HEAD responce:
+			* this is rather technical information, show URL.
+			*/
+		       FREE(subject);
+		       StrAllocCopy(subject, "HEAD  ");
+		       StrAllocCat(subject, newdoc->address);
+		}
 
 #ifdef VMS
 		if (strchr(user_response,'@') && !strchr(user_response,':') &&
@@ -1008,8 +1003,7 @@ PUBLIC int printfile ARGS1(
 		     *	Check for two '%s' and ask for the second filename
 		     *	argument if there is.
 		     */
-		    char *first_s = strstr(cur_printer->command, "%s");
-		    if (first_s && strstr(first_s+1, "%s")) {
+		    if (HTCountCommandArgs (cur_printer->command) >= 2) {
 			_statusline(FILENAME_PROMPT);
 		again:	strcpy(filename, sug_filename);
 			change_sug_filename(filename);
@@ -1130,18 +1124,9 @@ PUBLIC int printfile ARGS1(
 			HTAddSugFilename(filename);
 		    }
 
-#if defined (VMS) || defined (__EMX__) || defined(__DJGPP__)
-		    sprintf(buffer, cur_printer->command, tempfile, filename,
-				    "", "", "", "", "", "", "", "", "", "");
-#else /* Unix: */
-		    /*
-		     *	Prevent spoofing of the shell.
-		     */
-		    cp = quote_pathname(filename);
-		    sprintf(buffer, cur_printer->command, tempfile, cp,
-				    "", "", "", "", "", "", "", "", "", "");
-		    FREE(cp);
-#endif /* !VMS */
+		    HTAddParam (&the_command, cur_printer->command, 1, tempfile);
+		    HTAddParam (&the_command, cur_printer->command, 2, filename);
+		    HTEndParam (&the_command, cur_printer->command, 2);
 
 		} else {
 		    HTAlert(PRINTER_MISCONF_ERROR);
@@ -1156,38 +1141,38 @@ PUBLIC int printfile ARGS1(
 		move(1,1);
 
 		stop_curses();
-		CTRACE(tfp, "command: %s\n", buffer);
+		CTRACE(tfp, "command: %s\n", the_command);
 		printf(PRINTING_FILE);
-#ifdef VMS
 		/*
-		 *  Set document's title as a VMS logical. -  FM
+		 * Set various bits of document information as environment
+		 * variables, for use by external print scripts/etc.  On UNIX,
+		 * We assume there are values, and leave NULL value checking
+		 * up to the external PRINTER:  cmd/script - KED
 		 */
-		StrAllocCopy(envbuffer, HText_getTitle());
-		if (!(envbuffer && *envbuffer))
-		    StrAllocCopy(envbuffer, "No Title");
-		Define_VMSLogical("LYNX_PRINT_TITLE", envbuffer);
-#else
+		SET_ENVIRON(LYNX_PRINT_TITLE,
+			    HText_getTitle(),
+			    "No Title");
+		SET_ENVIRON(LYNX_PRINT_URL,
+			    newdoc->address,
+			    "No URL");
+		SET_ENVIRON(LYNX_PRINT_DATE,
+			    HText_getDate(),
+			    "No Date");
+		SET_ENVIRON(LYNX_PRINT_LASTMOD,
+			    HText_getLastModified(),
+			    "No LastMod");
+
+		LYSystem(the_command);
+		FREE(the_command);
 		/*
-		 *  Set document's title as an environment variable. - JKT
+		 * Remove the various LYNX_PRINT_xxxx logicals.  - KED
+		 * [could use unsetenv(), but it's not portable]
 		 */
-		StrAllocCopy(envbuffer, "LYNX_PRINT_TITLE=");
-		StrAllocCat(envbuffer, HText_getTitle());
-		putenv(envbuffer);
-#endif /* VMS */
-		LYSystem(buffer);
-#ifdef VMS
-		/*
-		 *  Remove LYNX_PRINT_TITLE logical. - FM
-		 */
-		Define_VMSLogical("LYNX_PRINT_TITLE", "");
-#else
-		/*
-		 *  Remove LYNX_PRINT_TITLE value from environment. - KW
-		 */
-		envbuffer[17] = '\0'; /* truncate after '=' */
-		putenv(envbuffer);
-#endif /* VMS */
-		FREE(envbuffer);
+		SET_ENVIRON(LYNX_PRINT_TITLE,   "", "");
+		SET_ENVIRON(LYNX_PRINT_URL,     "","");
+		SET_ENVIRON(LYNX_PRINT_DATE,    "", "");
+		SET_ENVIRON(LYNX_PRINT_LASTMOD, "", "");
+
 		fflush(stdout);
 #ifndef VMS
 		signal(SIGINT, cleanup_sig);
@@ -1196,6 +1181,7 @@ PUBLIC int printfile ARGS1(
 		start_curses();
     } /* end switch */
 
+done:
     FREE(link_info);
     FREE(sug_filename);
     FREE(subject);
@@ -1234,6 +1220,7 @@ PRIVATE int remove_quotes ARGS1(
  *  it may correspond to US-ASCII as the safest value or any other
  *  lynx character handler, -1 for no translation (so display charset).
  *
+ *  Always returns a new allocated string which has to be freed.
  */
 PRIVATE char* subject_translate8bit ARGS1(char *, source)
 {
@@ -1250,7 +1237,8 @@ PRIVATE char* subject_translate8bit ARGS1(char *, source)
     if (i < 0
      || LYHaveCJKCharacterSet
      || LYCharSet_UC[i].enc == UCT_ENC_CJK) {
-	return(source); /* OK */
+	StrAllocCopy(target, source);
+	return(target); /* OK */
     } else {
 	charset_out = i;
 	charset_in  = current_char_set;
diff --git a/src/LYStrings.c b/src/LYStrings.c
index 6f4ac249..ac24013a 100644
--- a/src/LYStrings.c
+++ b/src/LYStrings.c
@@ -131,7 +131,7 @@ PUBLIC int fancy_mouse ARGS3(
 	    cmd = LYX_TOGGLE;
 #endif
 	} else if (event.bstate & (BUTTON_ALT | BUTTON_SHIFT | BUTTON_CTRL)) {
-	    /* Probably some unrelated activity, such as selecting some text. 
+	    /* Probably some unrelated activity, such as selecting some text.
 	     * Select, but do nothing else.
 	     */
 	    *position += delta;
@@ -1785,7 +1785,7 @@ PUBLIC void LYRefreshEdit ARGS1(
  *  Figure out new display starting point.
  *
  *   The first "if" below makes Lynx scroll several columns at a time when
- *   extending the string. Looks awful, but that way we can keep up with
+ *   extending the string.  Looks awful, but that way we can keep up with
  *   data entry at low baudrates.
  */
     if ((DspStart + DspWdth) <= length)
diff --git a/src/LYUpload.c b/src/LYUpload.c
index 422c4fda..0dd98b14 100644
--- a/src/LYUpload.c
+++ b/src/LYUpload.c
@@ -6,7 +6,7 @@
 **	Reread the upload menu page every time, in case the "upload" directory
 **	  has changed (make the current directory that for the upload process).
 **	Prompt for the upload file name if there is no "%s" in the command
-**	  string. Most protocols allow the user to specify the file name
+**	  string.  Most protocols allow the user to specify the file name
 **	  from the client side.  Xmodem appears to be the only that can't
 **	  figure out the filename from the transfer data so it needs the
 **	  information from lynx (or an upload script which prompts for it).
@@ -33,6 +33,8 @@
 
 PUBLIC char LYUploadFileURL[LY_MAXPATH] = "\0";
 
+#define SUBDIR_COMMAND "cd %s ; "
+
 /*
  *  LYUpload uploads a file to a given location using a
  *  specified upload method.  It parses an incoming link
@@ -42,19 +44,15 @@ PUBLIC char LYUploadFileURL[LY_MAXPATH] = "\0";
 PUBLIC int LYUpload ARGS1(
 	char *, 	line)
 {
-    char *method, *directory, *dir;
+    char *method, *directory;
     int method_number;
     int count;
+    char *the_upload = 0;
     char tmpbuf[LY_MAXPATH];
     char buffer[LY_MAXPATH];
     lynx_html_item_type *upload_command = 0;
-    int c;
-    char *cp;
     FILE *fp;
-    char cmd[20 + (LY_MAXPATH*2)];
-#ifdef VMS
-    extern BOOLEAN HadVMSInterrupt;
-#endif /* VMS */
+    char *the_command = 0;
 
     /*
      *	Use configured upload commands.
@@ -88,7 +86,7 @@ PUBLIC int LYUpload ARGS1(
     /*
      *	Care about the local name?
      */
-    if (strstr(upload_command->command, "%s")) {
+    if (HTCountCommandArgs (upload_command->command)) {
 	/*
 	 *  Commands have the form "command %s [etc]"
 	 *  where %s is the filename.
@@ -114,43 +112,20 @@ retry:
 	}
 	sprintf(buffer, "%s/%s", directory, tmpbuf);
 
-	if (no_dotfiles || !show_dotfiles) {
-	    if (*LYPathLeaf(buffer) == '.') {
-		HTAlert(FILENAME_CANNOT_BE_DOT);
-		_statusline(NEW_FILENAME_PROMPT);
-		goto retry;
-	    }
+#if HAVE_POPEN
+	if (LYIsPipeCommand(buffer)) {
+	    HTAlert(CANNOT_WRITE_TO_FILE);
+	    _statusline(NEW_FILENAME_PROMPT);
+	    goto retry;
 	}
-
-	/*
-	 *  See if it already exists.
-	 */
-	if ((fp = fopen(buffer, "r")) != NULL) {
-	    fclose(fp);
-
-#ifdef VMS
-	    _statusline(FILE_EXISTS_HPROMPT);
-#else
-	    _statusline(FILE_EXISTS_OPROMPT);
-#endif /* VMS */
-	    c = 0;
-	    while (TOUPPER(c) != 'Y' && TOUPPER(c) != 'N' && c != 7 && c != 3)
-		c = LYgetch();
-#ifdef VMS
-	    if (HadVMSInterrupt) {
-		HadVMSInterrupt = FALSE;
-		goto cancelled;
-	    }
-#endif /* VMS */
-
-	    if (c == 7 || c == 3) { /* Control-G or Control-C */
-		goto cancelled;
-	    }
-
-	    if (TOUPPER(c) == 'N') {
-		_statusline(NEW_FILENAME_PROMPT);
-		goto retry;
-	    }
+#endif
+	switch (LYValidateOutput(buffer)) {
+	case 'Y':
+	    break;
+	case 'N':
+	    goto retry;
+	default:
+	    goto cancelled;
 	}
 
 	/*
@@ -167,24 +142,24 @@ retry:
 	    goto retry;
 	}
 
-#if defined (VMS) || defined (__EMX__) || defined(__DJGPP__)
-	sprintf(tmpbuf, upload_command->command, buffer, "", "", "", "", "");
-#else
-	cp = quote_pathname(buffer); /* to prevent spoofing of the shell */
-	sprintf(tmpbuf, upload_command->command, cp, "", "", "", "", "");
-	FREE(cp);
-#endif /* VMS */
+	HTAddParam(&the_upload, upload_command->command, 1, buffer);
+	HTEndParam(&the_upload, upload_command->command, 1);
     } else {			/* No substitution, no changes */
-	strcpy(tmpbuf, upload_command->command);
+	StrAllocCopy(the_upload, upload_command->command);
     }
 
-    dir = quote_pathname(directory);
-    sprintf(cmd, "cd %s ; %s", dir, tmpbuf);
-    FREE(dir);
+    HTAddParam(&the_command, SUBDIR_COMMAND, 1, directory);
+    HTEndParam(&the_command, SUBDIR_COMMAND, 1);
+    StrAllocCat(the_command, the_upload);
+
+    CTRACE(tfp, "command: %s\n", the_command);
+
     stop_curses();
-    CTRACE(tfp, "command: %s\n", cmd);
-    LYSystem(cmd);
+    LYSystem(the_command);
     start_curses();
+
+    FREE(the_command);
+    FREE(the_upload);
 #ifdef UNIX
     chmod(buffer, HIDE_CHMOD);
 #endif /* UNIX */
diff --git a/src/LYUtils.c b/src/LYUtils.c
index 554914b4..d836ea14 100644
--- a/src/LYUtils.c
+++ b/src/LYUtils.c
@@ -11,6 +11,7 @@
 #include <LYGlobalDefs.h>
 #include <LYSignal.h>
 #include <GridText.h>
+#include <LYClean.h>
 #include <LYCharSets.h>
 #include <LYCharUtils.h>
 
@@ -2040,8 +2041,8 @@ PUBLIC void LYFakeZap ARGS1(
 
 PRIVATE int DontCheck NOARGS
 {
-    static time_t last;
-    time_t next;
+    static long last;
+    long next;
 
     /** Curses or slang setup was not invoked **/
     if (dump_output_immediately)
@@ -2051,7 +2052,15 @@ PRIVATE int DontCheck NOARGS
      * Avoid checking interrupts more than one per second, since it is a slow
      * and expensive operation - TD
      */
+#if HAVE_GETTIMEOFDAY
+    {
+	struct timeval tv;
+	gettimeofday(&tv, (struct timezone *)0);
+	next = tv.tv_usec / 100000L;	/* 0.1 seconds is a compromise */
+    }
+#else
     next = time((time_t*)0);
+#endif
     if (next == last)
 	return (TRUE);
 
@@ -2127,7 +2136,6 @@ PUBLIC int HTCheckForInterrupt NOARGS
 #endif /* DOSPATH */
 
 #else /* VMS: */
-    extern BOOLEAN HadVMSInterrupt;
     extern int typeahead();
 
     if (fake_zap > 0) {
@@ -2752,50 +2760,6 @@ PUBLIC void remove_backslashes ARGS1(
     return;
 }
 
-/*
- *  Quote the path to make it safe for shell command processing.
- *
- *  We use a simple technique which involves quoting the entire
- *  string using single quotes, escaping the real single quotes
- *  with double quotes. This may be gross but it seems to work.
- */
-PUBLIC char * quote_pathname ARGS1(
-	char *, 	pathname)
-#ifndef __DJGPP__
-{
-    size_t i, n = 0;
-    char * result;
-
-    for (i=0; i < strlen(pathname); ++i)
-	if (pathname[i] == '\'') ++n;
-
-    result = (char *)malloc(strlen(pathname) + 5*n + 3);
-    if (result == NULL)
-	outofmem(__FILE__, "quote_pathname");
-
-    n = 0;
-    result[n++] = '\'';
-    for (i = 0; i < strlen(pathname); i++) {
-	if (pathname[i] == '\'') {
-	    result[n++] = '\'';
-	    result[n++] = '"';
-	    result[n++] = '\'';
-	    result[n++] = '"';
-	    result[n++] = '\'';
-	} else {
-	    result[n++] = pathname[i];
-	}
-    }
-    result[n++] = '\'';
-    result[n] = '\0';
-    return result;
-}
-#else
-{
-	return pathname;
-}
-#endif /* !__DJGPP__ */
-
 #if HAVE_UTMP
 extern char *ttyname PARAMS((int fd));
 #endif
@@ -3960,10 +3924,10 @@ have_VMS_URL:
 		 *  It is a subdirectory or file on the local system.
 		 */
 #if defined (DOSPATH) || defined (__EMX__)
-		/* Don't want to see DOS local paths like c: escaped */
-		/* especially when we really have file://localhost/  */
-		/* at the beginning. To avoid any confusion we allow */
-		/* escaping the path if URL specials % or # present. */
+		/* Don't want to see DOS local paths like c: escaped  */
+		/* especially when we really have file://localhost/   */
+		/* at the beginning.  To avoid any confusion we allow */
+		/* escaping the path if URL specials % or # present.  */
 		if (strchr(temp, '#') == NULL &&
 			   strchr(temp, '%') == NULL)
 		StrAllocCopy(cp, temp);
@@ -5871,6 +5835,148 @@ PUBLIC  char * wwwName ARGS1(
 }
 
 /*
+ * Given a user-specified filename, e.g., for download or print, validate and
+ * expand it.  Expand home-directory expressions in the given string.  Only
+ * allow pipes if the user can spawn shell commands.
+ */
+PUBLIC BOOLEAN LYValidateFilename ARGS2(
+    	char *,		result,
+	char *,		given)
+{
+    char *cp;
+
+    /*
+     *  Cancel if the user entered "/dev/null" on Unix,
+     *  or an "nl:" path (case-insensitive) on VMS. - FM
+     */
+#ifdef VMS
+    if (!strncasecomp(given, "nl:", 3) ||
+	!strncasecomp(given, "/nl/", 4))
+#else
+    if (!strcmp(given, "/dev/null"))
+#endif /* VMS */
+    {
+	/* just ignore it */
+	return FALSE;
+    }
+#if HAVE_POPEN
+    if (LYIsPipeCommand(given)) {
+	if (no_shell) {
+	    HTUserMsg(SPAWNING_DISABLED);
+	    return FALSE;
+	}
+	strcpy(result, given);
+	return TRUE;
+    }
+#endif
+    if ((cp = strchr(given, '~'))) {
+	*(cp++) = '\0';
+	strcpy(result, given);
+	LYTrimPathSep(result);
+	strcat(result, wwwName(Home_Dir()));
+	strcat(result, cp);
+	strcpy(given, result);
+    }
+#ifdef VMS
+    if (strchr(given, '/') != NULL) {
+	strcpy(result, HTVMS_name("", given));
+	strcpy(given, result);
+    }
+    if (given[0] != '/' && strchr(given, ':') == NULL) {
+	strcpy(result, "sys$disk:");
+	if (strchr(given, ']') == NULL)
+	    strcat(result, "[]");
+	strcat(result, given);
+    } else {
+	strcpy(result, given);
+    }
+#else
+
+#ifndef __EMX__
+    if (!LYIsPathSep(*given)) {
+#if defined(__DJGPP__) || defined(_WINDOWS)
+    if (strchr(result, ':') != NULL)
+	cp = NULL;
+    else
+#endif /*  __DJGPP__ || _WINDOWS */
+	cp = getenv("PWD");
+    }
+    else
+#endif /* __EMX__*/
+	cp = NULL;
+
+    if (cp) {
+	LYTrimPathSep(cp);
+	sprintf(result, "%s/%s", cp, HTSYS_name(given));
+    } else {
+	strcpy(result, HTSYS_name(given));
+    }
+#endif /* VMS */
+    return TRUE;
+}
+
+/*
+ * Given a valid filename, check if it exists.  If so, we'll have to worry
+ * about overwriting it.
+ *
+ * Returns:
+ *	'Y' (yes/success)
+ *	'N' (no/retry)
+ *	3   (cancel)
+ */
+PUBLIC int LYValidateOutput ARGS1(
+    	char *,		filename)
+{
+    FILE *fp;
+    int c;
+
+    /*
+     * Assume we can write to a pipe
+     */
+#if HAVE_POPEN
+    if (LYIsPipeCommand(filename))
+	return 'Y';
+#endif
+
+    if (no_dotfiles || !show_dotfiles) {
+	if (*LYPathLeaf(filename) == '.') {
+	    HTAlert(FILENAME_CANNOT_BE_DOT);
+	    return 'N';
+	}
+    }
+
+    /*
+     *  See if it already exists.
+     */
+    if ((fp = fopen(filename, "r")) != NULL) {
+	fclose(fp);
+#ifdef VMS
+	_statusline(FILE_EXISTS_HPROMPT);
+#else
+	_statusline(FILE_EXISTS_OPROMPT);
+#endif /* VMS */
+	c = 0;
+	while (TOUPPER(c)!='Y' && TOUPPER(c)!='N' &&
+	       TOUPPER(c)!='A' && c != 7 && c != 3)
+	    c = LYgetch();
+#ifdef VMS
+	if (HadVMSInterrupt) {
+	    HadVMSInterrupt = FALSE;
+	    c = 3;
+	}
+#endif /* VMS */
+	if (c == 7 || c == 3) { /* Control-G or Control-C */
+	    HTInfoMsg(SAVE_REQUEST_CANCELLED);
+	    return 3;
+	}
+	if (TOUPPER(c) == 'N') {
+	    return 'N';
+	}
+    }
+    return 'Y';
+}
+
+/*
  * Convert a local filename to a URL
  */
 PUBLIC void LYLocalFileToURL ARGS2(
diff --git a/src/LYUtils.h b/src/LYUtils.h
index 9f4be263..4264fe91 100644
--- a/src/LYUtils.h
+++ b/src/LYUtils.h
@@ -31,6 +31,8 @@
 #define HTSYS_remove(path) remove(path)
 #endif
 
+#define LYIsPipeCommand(s) ((s)[0] == '|')
+
 #ifdef DOSPATH
 #define LYIsPathSep(ch) ((ch) == '/' || (ch) == '\\')
 #else
@@ -46,6 +48,7 @@ extern BOOLEAN LYCachedTemp PARAMS((char *result, char **cached));
 extern BOOLEAN LYCanDoHEAD PARAMS((CONST char *address));
 extern BOOLEAN LYExpandHostForURL PARAMS((char **AllocatedString, char *prefix_list, char *suffix_list));
 extern BOOLEAN LYPathOffHomeOK PARAMS((char *fbuffer, size_t fbuffer_size));
+extern BOOLEAN LYValidateFilename PARAMS((char * result, char * given));
 extern BOOLEAN LYisLocalAlias PARAMS((char *filename));
 extern BOOLEAN LYisLocalFile PARAMS((char *filename));
 extern BOOLEAN LYisLocalHost PARAMS((char *filename));
@@ -60,13 +63,13 @@ extern FILE *LYReopenTemp PARAMS((char *name));
 extern char *LYPathLeaf PARAMS((char * pathname));
 extern char *LYSysShell NOPARAMS;
 extern char *LYgetXDisplay NOPARAMS;
-extern char *quote_pathname PARAMS((char *pathname));
 extern char *strip_trailing_slash PARAMS((char * my_dirname));
 extern char *wwwName PARAMS((CONST char *pathname));
 extern int HTCheckForInterrupt NOPARAMS;
 extern int LYCheckForProxyURL PARAMS((char *filename));
 extern int LYOpenInternalPage PARAMS((FILE **fp0, char **newfile));
 extern int LYSystem PARAMS((char *command));
+extern int LYValidateOutput PARAMS((char * filename));
 extern int is_url PARAMS((char *filename));
 extern int number2arrows PARAMS((int number));
 extern time_t LYmktime PARAMS((char *string, BOOL absolute));
diff --git a/src/LYrcFile.c b/src/LYrcFile.c
index d2613946..c79b4727 100644
--- a/src/LYrcFile.c
+++ b/src/LYrcFile.c
@@ -766,7 +766,7 @@ PUBLIC int save_rc NOPARAMS
 # A value of \"default\" will yield the behavior of assuming\n\
 # a monochrome terminal unless color capability is inferred at startup\n\
 # based on the terminal type, or the -color command line switch is used, or\n\
-# the COLORTERM environment variable is set. The default behavior always is\n\
+# the COLORTERM environment variable is set.  The default behavior always is\n\
 # used in anonymous accounts or if the \"option_save\" restriction is set.\n\
 # The effect of the saved value can be overridden via\n\
 # the -color and -nocolor command line switches.\n\
@@ -878,7 +878,7 @@ PUBLIC int save_rc NOPARAMS
     fprintf(fp, gettext("\
 # partial_thres specifies the number of lines Lynx should download and render\n\
 # before we redraw the screen in Partial Display logic\n\
-# e.g. partial_thres=2\n\
+# e.g., partial_thres=2\n\
 # would have Lynx redraw every 2 lines that it renders\n\
 # partial_thres=-1 would use the entire screensize\n"));
     fprintf(fp, "partial_thres=%d\n\n", partial_threshold);
diff --git a/src/UCAux.c b/src/UCAux.c
index d10df1e8..bbe5321c 100644
--- a/src/UCAux.c
+++ b/src/UCAux.c
@@ -137,7 +137,7 @@ PUBLIC BOOL UCNeedNotTranslate ARGS2(
 **
 **  Should be called once when a stage starts processing text (and the
 **  input and output charsets are known), or whenever one of input or
-**  output charsets has changed (e.g. by SGML.c stage after HTML.c stage
+**  output charsets has changed (e.g., by SGML.c stage after HTML.c stage
 **  has processed a META tag).
 **  The global flags (LYRawMode, HTPassEightBitRaw etc.) are currently
 **  not taken into account here (except for HTCJK, somewhat), it's still
@@ -215,7 +215,7 @@ PUBLIC void UCSetTransParams ARGS5(
 	    **  Set up for all other charset combinations.
 	    **  The intm_ucs flag is set TRUE if the input
 	    **  charset is iso-8859-1 or UTF-8, or largely
-	    **  equivalent to them, i.e. if we have UCS without
+	    **  equivalent to them, i.e., if we have UCS without
 	    **  having to do a table translation.
 	    */
 	    intm_ucs = (cs_in == LATIN1 || pT->decode_utf8 ||
diff --git a/src/UCdomap.c b/src/UCdomap.c
index 2d49dc26..711b60a9 100644
--- a/src/UCdomap.c
+++ b/src/UCdomap.c
@@ -69,8 +69,6 @@
 #include <mnem_suni.h>
 #endif /* NOTDEFINED */
 
-PUBLIC  char *UC_TEMPcharset = 0;	/* temporary in UCGetLYhndl_byMIME */
-
 /*
  *  Some of the code below, and some of the comments, are left in for
  *  historical reasons.  Not all those tables below are currently
@@ -1509,7 +1507,6 @@ PUBLIC int UCGetRawUniMode_byLYhndl ARGS1(
 PUBLIC int UCGetLYhndl_byMIME ARGS1(
 	CONST char *,	value)
 {
-#define UC_MIMEcharset UC_TEMPcharset
     int i;
     int LYhndl = -1;
 
@@ -1518,127 +1515,122 @@ PUBLIC int UCGetLYhndl_byMIME ARGS1(
 	return -1;
     }
 
-    StrAllocCopy(UC_MIMEcharset, value);
-    LYLowerCase(UC_MIMEcharset);
-
     for (i = 0;
 	 (i < MAXCHARSETS && i < LYNumCharsets &&
 	  LYchar_set_names[i]); i++) {
 	if (LYCharSet_UC[i].MIMEname &&
-	    !strcmp(UC_MIMEcharset, LYCharSet_UC[i].MIMEname)) {
+	   !strcasecomp(value, LYCharSet_UC[i].MIMEname)) {
 	    return i;
 	}
     }
-    {
+
+    /*
+     * Not yet found, try synonyms.  - FM
+     */
+    if (!strcasecomp(value, "unicode-1-1-utf-8") ||
+	!strcasecomp(value, "utf8")) {
 	/*
-	 *  Not yet found, try synonyms. - FM
+	 * Treat these as synonyms for the IANA registered name.  - FM
 	 */
-	if (!strcmp(UC_MIMEcharset, "unicode-1-1-utf-8") ||
-	    !strcmp(UC_MIMEcharset, "utf8")) {
-	    /*
-	     *	Treat these as synonyms for the IANA registered name. - FM
-	     */
-	    return UCGetLYhndl_byMIME("utf-8");
-	}
-	if (!strncmp(UC_MIMEcharset, "iso-2022-jp", 11) ||
-	    !strcmp(UC_MIMEcharset, "x-euc-jp")) {
-	    return UCGetLYhndl_byMIME("euc-jp");
-	}
-	if (!strcmp(UC_MIMEcharset, "x-shift-jis")) {
-	    return UCGetLYhndl_byMIME("shift_jis");
-	}
-	if (!strcmp(UC_MIMEcharset, "iso-2022-kr")) {
-	    return UCGetLYhndl_byMIME("euc-kr");
-	}
-	if (!strcmp(UC_MIMEcharset, "gb2312") ||
-	    !strncmp(UC_MIMEcharset, "cn-gb", 5) ||
-	    !strcmp(UC_MIMEcharset, "iso-2022-cn")) {
-	    return UCGetLYhndl_byMIME("euc-cn");
-	}
-	if (!strcmp(UC_MIMEcharset, "cn-big5")) {
-	    return UCGetLYhndl_byMIME("big5");
-	}
-	if (!strcmp(UC_MIMEcharset, "x-mac-roman") ||
-	    !strcmp(UC_MIMEcharset, "mac-roman")) {
-	    return UCGetLYhndl_byMIME("macintosh");
-	}
-	if (!strcmp(UC_MIMEcharset, "x-next") ||
-	    !strcmp(UC_MIMEcharset, "nextstep") ||
-	    !strcmp(UC_MIMEcharset, "x-nextstep")) {
-	    return UCGetLYhndl_byMIME("next");
-	}
-	if (!strcmp(UC_MIMEcharset, "iso-8859-1-windows-3.1-latin-1") ||
-	    !strcmp(UC_MIMEcharset, "cp1252") ||
-	    !strcmp(UC_MIMEcharset, "cp-1252") ||
-	    !strcmp(UC_MIMEcharset, "ibm1252") ||
-	    !strcmp(UC_MIMEcharset, "iso-8859-1-windows-3.0-latin-1")) {
-	    /*
-	     *	Treat these as synonyms for windows-1252, which is more
-	     *	commonly used than the IANA registered name. - FM
-	     */
-	    return UCGetLYhndl_byMIME("windows-1252");
-	}
-	if (!strcmp(UC_MIMEcharset, "iso-8859-2-windows-latin-2") ||
-	    !strcmp(UC_MIMEcharset, "cp1250") ||
-	    !strcmp(UC_MIMEcharset, "cp-1250") ||
-	    !strcmp(UC_MIMEcharset, "ibm1250")) {
-	    /*
-	     *	Treat these as synonyms for windows-1250. - FM
-	     */
-	    return UCGetLYhndl_byMIME("windows-1250");
-	}
-	if ((!strncmp(UC_MIMEcharset, "ibm", 3) ||
-	     !strncmp(UC_MIMEcharset, "cp-", 3)) &&
-	    isdigit((unsigned char)UC_MIMEcharset[3]) &&
-	    isdigit((unsigned char)UC_MIMEcharset[4]) &&
-	    isdigit((unsigned char)UC_MIMEcharset[5])) {
-	    /*
-	     *	For "ibmNNN<...>" or "cp-NNN", try "cpNNN<...>"
-	     *	if not yet found. - KW & FM
-	     */
-	    char * cptmp = NULL;
-
-	    StrAllocCopy(cptmp, (UC_MIMEcharset + 1));
-	    cptmp[0] = 'c';
-	    cptmp[1] = 'p';
-	    if ((LYhndl = UCGetLYhndl_byMIME(cptmp)) >= 0) {
-		FREE(cptmp);
-		return LYhndl;
-	    }
-	    /*
-	     *	Try windows-NNN<...> if not yet found. - FM
-	     */
-	    StrAllocCopy(cptmp, "windows-");
-	    StrAllocCat(cptmp, (UC_MIMEcharset + 3));
-	    LYhndl = UCGetLYhndl_byMIME(cptmp);
-	    FREE(cptmp);
-	    return LYhndl;
-	}
-	if (!strncmp(UC_MIMEcharset, "windows-", 8) &&
-	    isdigit((unsigned char)UC_MIMEcharset[8]) &&
-	    isdigit((unsigned char)UC_MIMEcharset[9]) &&
-	    isdigit((unsigned char)UC_MIMEcharset[10])) {
-	    /*
-	     *	For "windows-NNN<...>", try "cpNNN<...>" - FM
-	     */
-	    char * cptmp = NULL;
+	return UCGetLYhndl_byMIME("utf-8");
+    }
+    if (!strncasecomp(value, "iso-2022-jp", 11) ||
+	!strcasecomp(value, "x-euc-jp")) {
+	return UCGetLYhndl_byMIME("euc-jp");
+    }
+    if (!strcasecomp(value, "x-shift-jis")) {
+	return UCGetLYhndl_byMIME("shift_jis");
+    }
+    if (!strcasecomp(value, "iso-2022-kr")) {
+	return UCGetLYhndl_byMIME("euc-kr");
+    }
+    if (!strcasecomp(value, "gb2312") ||
+	!strncasecomp(value, "cn-gb", 5) ||
+	!strcasecomp(value, "iso-2022-cn")) {
+	return UCGetLYhndl_byMIME("euc-cn");
+    }
+    if (!strcasecomp(value, "cn-big5")) {
+	return UCGetLYhndl_byMIME("big5");
+    }
+    if (!strcasecomp(value, "x-mac-roman") ||
+	!strcasecomp(value, "mac-roman")) {
+	return UCGetLYhndl_byMIME("macintosh");
+    }
+    if (!strcasecomp(value, "x-next") ||
+	!strcasecomp(value, "nextstep") ||
+	!strcasecomp(value, "x-nextstep")) {
+	return UCGetLYhndl_byMIME("next");
+    }
+    if (!strcasecomp(value, "iso-8859-1-windows-3.1-latin-1") ||
+	!strcasecomp(value, "cp1252") ||
+	!strcasecomp(value, "cp-1252") ||
+	!strcasecomp(value, "ibm1252") ||
+	!strcasecomp(value, "iso-8859-1-windows-3.0-latin-1")) {
+	/*
+	 * Treat these as synonyms for windows-1252, which is more
+	 * commonly used than the IANA registered name.  - FM
+	 */
+	return UCGetLYhndl_byMIME("windows-1252");
+    }
+    if (!strcasecomp(value, "iso-8859-2-windows-latin-2") ||
+	!strcasecomp(value, "cp1250") ||
+	!strcasecomp(value, "cp-1250") ||
+	!strcasecomp(value, "ibm1250")) {
+	/*
+	 * Treat these as synonyms for windows-1250.  - FM
+	 */
+	return UCGetLYhndl_byMIME("windows-1250");
+    }
+    if ((!strncasecomp(value, "ibm", 3) ||
+	 !strncasecomp(value, "cp-", 3)) &&
+	isdigit((unsigned char)value[3]) &&
+	isdigit((unsigned char)value[4]) &&
+	isdigit((unsigned char)value[5])) {
+	/*
+	 * For "ibmNNN<...>" or "cp-NNN", try "cpNNN<...>"
+	 * if not yet found.  - KW & FM
+	 */
+	char * cptmp = NULL;
 
-	    StrAllocCopy(cptmp, (UC_MIMEcharset + 6));
-	    cptmp[0] = 'c';
-	    cptmp[1] = 'p';
-	    LYhndl = UCGetLYhndl_byMIME(cptmp);
+	StrAllocCopy(cptmp, (value + 1));
+	cptmp[0] = 'c';
+	cptmp[1] = 'p';
+	if ((LYhndl = UCGetLYhndl_byMIME(cptmp)) >= 0) {
 	    FREE(cptmp);
 	    return LYhndl;
 	}
-	if (!strcmp(UC_MIMEcharset, "koi-8")) { /* accentsoft bugosity */
-	  return UCGetLYhndl_byMIME("koi8-r");
-	}
+	/*
+	 * Try windows-NNN<...> if not yet found.  - FM
+	 */
+	StrAllocCopy(cptmp, "windows-");
+	StrAllocCat(cptmp, (value + 3));
+	LYhndl = UCGetLYhndl_byMIME(cptmp);
+	FREE(cptmp);
+	return LYhndl;
+    }
+    if (!strncasecomp(value, "windows-", 8) &&
+	isdigit((unsigned char)value[8]) &&
+	isdigit((unsigned char)value[9]) &&
+	isdigit((unsigned char)value[10])) {
+	/*
+	 * For "windows-NNN<...>", try "cpNNN<...>" - FM
+	 */
+	char * cptmp = NULL;
+
+	StrAllocCopy(cptmp, (value + 6));
+	cptmp[0] = 'c';
+	cptmp[1] = 'p';
+	LYhndl = UCGetLYhndl_byMIME(cptmp);
+	FREE(cptmp);
+	return LYhndl;
+    }
+    if (!strcasecomp(value, "koi-8")) { /* accentsoft bugosity */
+      return UCGetLYhndl_byMIME("koi8-r");
     }
     /* no more synonyms if come here... */
 
     CTRACE(tfp, "UCGetLYhndl_byMIME: unrecognized MIME name \"%s\"\n", value);
     return -1;	/* returns -1 if no charset found by that MIME name */
-#undef UC_MIMEcharset
 }
 
 /*
@@ -1873,7 +1865,7 @@ PRIVATE int UC_Register_with_LYCharSets ARGS4(
     if (LYhndl < 0) {		/* not found */
 	found = 0;
 	if (LYNumCharsets >= MAXCHARSETS) {
-	    CTRACE(tfp, "UC_Register_with_LYCharSets: Too many. Ignoring %s/%s.",
+	    CTRACE(tfp, "UC_Register_with_LYCharSets: Too many.  Ignoring %s/%s.",
 			UC_MIMEcharset, UC_LYNXcharset);
 	    return -1;
 	}
@@ -1958,7 +1950,7 @@ PUBLIC void UC_Charset_Setup ARGS9(
 	s = found;
     } else {
 	if (UCNumCharsets >= MAXCHARSETS) {
-	    CTRACE(tfp, "UC_Charset_Setup: Too many. Ignoring %s/%s.",
+	    CTRACE(tfp, "UC_Charset_Setup: Too many.  Ignoring %s/%s.",
 			UC_MIMEcharset, UC_LYNXcharset);
 	    return;
 	}
diff --git a/src/chrtrans/README.format b/src/chrtrans/README.format
index 4b425a00..3d269c57 100644
--- a/src/chrtrans/README.format
+++ b/src/chrtrans/README.format
@@ -127,11 +127,11 @@ Motivation:
 
 - The format is independent of details of other parts of the Lynx code,
   unlike the "old" LYCharsets.c mechanism.  The tables don't have to
-  be changed in synch when e.g. new entities are added to the entities.h.
+  be changed in synch when e.g., new entities are added to the entities.h.
 
 
 Note: the Default "7bit approximation" table can be used for
 case-insensitive search for non-ascii letters if no upper/lower case
-information provided by other means, e.g. locale.  It is assumed that
+information provided by other means, e.g., locale.  It is assumed that
 upper/lower case letters have their "7bit approximation" images
 in def7_uni.tbl matched case-insensitively.
diff --git a/src/chrtrans/makefile.in b/src/chrtrans/makefile.in
index 8173b31e..285e0566 100644
--- a/src/chrtrans/makefile.in
+++ b/src/chrtrans/makefile.in
@@ -4,7 +4,7 @@
 # This may not yet work for the general case.
 # Only some dependencies included.
 #
-SHELL		= /bin/sh
+SHELL		= @CONFIG_SHELL@
 
 x		= @PROG_EXT@
 
@@ -33,6 +33,7 @@ CPP_OPTS	= @DEFS@ @CPPFLAGS@ \
 		-I$(top_srcdir)/src \
 		-I$(top_srcdir)/src/chrtrans \
 		-I$(top_srcdir)/$(WWWINC) \
+		-I$(top_srcdir)/ \
 		$(SITE_DEFS)
 CC_OPTS		= $(CPP_OPTS) $(CFLAGS)
 
diff --git a/src/makefile.in b/src/makefile.in
index 87ef8437..2b7c5d46 100644
--- a/src/makefile.in
+++ b/src/makefile.in
@@ -1,6 +1,6 @@
 # template-makefile for Lynx src directory
 
-SHELL = /bin/sh
+SHELL		= @CONFIG_SHELL@
 
 x		= @PROG_EXT@
 
@@ -14,7 +14,7 @@ VPATH		= $(srcdir)
 top_builddir	= ..
 
 # see po/makefile
-localedir	= $(prefix)/@DATADIRNAME@/locale
+localedir	= @NLS_DATADIR@/locale
 
 # Symbols which the configure script can set in each makefile:
 CC		= @CC@