--- mc-4.6.0/slang/sltermin.c.jj	2002-10-07 13:08:16.000000000 +0200
+++ mc-4.6.0/slang/sltermin.c	2004-04-05 13:06:14.000000000 +0200
@@ -267,9 +267,12 @@ SLterminfo_Type *_SLtt_tigetent (char *t
 
    if (NULL != (home = getenv ("HOME")))
      {
-	strncpy (home_ti, home, sizeof (home_ti) - 11);
-	home_ti [sizeof(home_ti) - 11] = 0;
-	strcat (home_ti, "/.terminfo");
+	size_t len = strlen (home);
+
+	if (len > sizeof (home_ti) - sizeof ("/.terminfo"))
+	  len = sizeof (home_ti) - sizeof ("/.terminfo");
+	memcpy (home_ti, home, len);
+	memcpy (home_ti + len, "/.terminfo", sizeof ("/.terminfo"));
 	Terminfo_Dirs [0] = home_ti;
      }
 
--- mc-4.6.0/src/cmd.c.jj	2003-02-05 16:54:33.000000000 +0100
+++ mc-4.6.0/src/cmd.c	2004-03-16 10:49:41.000000000 +0100
@@ -1132,7 +1132,7 @@ void edit_symlink_cmd (void)
 
 	q = g_strdup_printf (_(" Symlink `%s\' points to: "), name_trunc (p, 32));
 
-	i = readlink (p, buffer, MC_MAXPATHLEN);
+	i = readlink (p, buffer, MC_MAXPATHLEN - 1);
 	if (i > 0) {
 	    buffer [i] = 0;
 	    dest = input_expand_dialog (_(" Edit symlink "), q, buffer);
--- mc-4.6.0/src/command.c.jj	2002-11-14 08:25:19.000000000 +0100
+++ mc-4.6.0/src/command.c	2004-03-30 18:17:47.000000000 +0200
@@ -258,7 +258,7 @@ command_callback (WInput *cmd, int msg, 
 WInput *
 command_new (int y, int x, int cols)
 {
-    WInput *cmd = g_new (WInput, 1);
+    WInput *cmd;
 
     cmd = input_new (y, x, DEFAULT_COLOR, cols, "", "cmdline");
 
--- mc-4.6.0/src/complete.c.jj	2002-11-13 03:56:41.000000000 +0100
+++ mc-4.6.0/src/complete.c	2004-04-07 17:36:34.000000000 +0200
@@ -270,7 +270,7 @@ variable_completion_function (char *text
 	*temp = '$';
 	if (isbrace)
 	    temp [1] = '{';
-        strncpy (temp + 1 + isbrace, *env_p, p - *env_p);
+        memcpy (temp + 1 + isbrace, *env_p, p - *env_p);
         if (isbrace)
             strcpy (temp + 2 + (p - *env_p), "}");
         else
@@ -605,8 +605,7 @@ completion_matches (char *text, Completi
 	    matches = i;
             match_list [matches + 1] = NULL;
 	    match_list[0] = g_malloc (low + 1);
-	    strncpy (match_list[0], match_list[1], low);
-	    match_list[0][low] = 0;
+	    g_strlcpy (match_list[0], match_list[1], low + 1);
 	}
     } else {				/* There were no matches. */
         g_free (match_list);
@@ -806,7 +805,7 @@ static int insert_text (WInput *in, char
 	    	*(p++) = *(q++);
 	    *p = 0;
 	}
-	strncpy (in->buffer + start, text, len - start + end);
+	memcpy (in->buffer + start, text, len - start + end);
 	in->point += len;
 	update_input (in, 1);
 	end += len;
--- mc-4.6.0/src/dir.c.jj	2003-01-21 01:41:45.000000000 +0100
+++ mc-4.6.0/src/dir.c	2004-04-05 15:50:19.000000000 +0200
@@ -503,9 +503,11 @@ do_load_dir (dir_list *list, sortfn *sor
     }
 
     if (next_free) {
+	char *path = vfs_canon (".");
 	/* Add ".." except the root directory */
-	if (strcmp (vfs_canon ("."), "/") != 0)
+	if (strcmp (path, "/") != 0)
 	    add_dotdot_to_list (list, next_free++);
+	g_free (path);
 	do_sort (list, sort, next_free - 1, reverse, case_sensitive);
     } else {
 	tree_store_end_check ();
@@ -576,7 +578,7 @@ do_reload_dir (dir_list * list, sortfn *
     int i, status, link_to_dir, stale_link;
     struct stat buf;
     int marked_cnt;
-    GHashTable *marked_files = g_hash_table_new (g_str_hash, g_str_equal);
+    GHashTable *marked_files;
 
     tree_store_start_check_cwd ();
     dirp = mc_opendir (".");
@@ -587,6 +589,7 @@ do_reload_dir (dir_list * list, sortfn *
 	return set_zero_dir (list);
     }
 
+    marked_files = g_hash_table_new (g_str_hash, g_str_equal);
     alloc_dir_copy (list->size);
     for (marked_cnt = i = 0; i < count; i++) {
 	dir_copy.list[i].fnamelen = list->list[i].fnamelen;
@@ -622,6 +625,7 @@ do_reload_dir (dir_list * list, sortfn *
 	       clean_dir (&dir_copy, count);
 	     */
 	    tree_store_end_check ();
+	    g_hash_table_destroy (marked_files);
 	    return next_free;
 	}
 
@@ -655,9 +659,11 @@ do_reload_dir (dir_list * list, sortfn *
     tree_store_end_check ();
     g_hash_table_destroy (marked_files);
     if (next_free) {
+	char *path = vfs_canon (".");
 	/* Add ".." except the root directory */
-	if (strcmp (vfs_canon ("."), "/") != 0)
+	if (strcmp (path, "/") != 0)
 	    add_dotdot_to_list (list, next_free++);
+	g_free (path);
 	do_sort (list, sort, next_free - 1, rev, case_sensitive);
     } else
 	next_free = set_zero_dir (list);
--- mc-4.6.0/src/file.c.jj	2002-12-26 20:04:10.000000000 +0100
+++ mc-4.6.0/src/file.c	2004-03-16 11:13:46.000000000 +0100
@@ -366,7 +366,7 @@ make_symlink (FileOpContext *ctx, char *
 	dst_is_symlink = 0;
 
   retry_src_readlink:
-    len = mc_readlink (src_path, link_target, MC_MAXPATHLEN);
+    len = mc_readlink (src_path, link_target, MC_MAXPATHLEN - 1);
     if (len < 0) {
 	return_status =
 	    file_error (_(" Cannot read source link \"%s\" \n %s "),
@@ -715,6 +715,7 @@ copy_file_file (FileOpContext *ctx, char
 	    gettimeofday (&tv_current, NULL);
 
 	    if (n_read > 0) {
+		char *t = buf;
 		n_read_total += n_read;
 
 		/* Windows NT ftp servers report that files have no
@@ -729,9 +730,10 @@ copy_file_file (FileOpContext *ctx, char
 
 		/* dst_write */
 		while ((n_written =
-			mc_write (dest_desc, buf, n_read)) < n_read) {
+			mc_write (dest_desc, t, n_read)) < n_read) {
 		    if (n_written > 0) {
 			n_read -= n_written;
+			t += n_written;
 			continue;
 		    }
 		    return_status =
--- mc-4.6.0/src/find.c.jj	2004-01-30 19:02:39.000000000 +0100
+++ mc-4.6.0/src/find.c	2004-03-16 11:54:29.000000000 +0100
@@ -312,7 +312,7 @@ push_directory (char *dir)
     dir_stack *new;
 
     new = g_new (dir_stack, 1);
-    new->name = g_strdup (dir);
+    new->name = concat_dir_and_file (dir, "");
     new->prev = dir_stack_base;
     dir_stack_base = new;
 }
@@ -338,17 +338,9 @@ insert_file (char *dir, char *file)
 {
     char *tmp_name;
     static char *dirname;
-    int i;
 
-    if (dir [0] == PATH_SEP && dir [1] == PATH_SEP)
+    while (dir [0] == PATH_SEP && dir [1] == PATH_SEP)
 	dir++;
-    i = strlen (dir);
-    if (i){
-	if (dir [i - 1] != PATH_SEP){
-	    dir [i] = PATH_SEP;
-	    dir [i + 1] = 0;
-	}
-    }
 
     if (old_dir){
 	if (strcmp (old_dir, dir)){
@@ -401,7 +393,7 @@ get_line_at (int file_fd, char *buf, int
     char ch = 0;
     int  i = 0;
 
-    do {
+    for (;;) {
 	if (*pos >= *n_read){
 	    *pos = 0;
 	    if ((*n_read = mc_read (file_fd, buf, buf_size)) <= 0)
@@ -420,10 +412,12 @@ get_line_at (int file_fd, char *buf, int
 	if (i >= buffer_size - 1){
 	    buffer = g_realloc (buffer, buffer_size += 80);
 	}
+	/* Strip newline to fix $ matching */
+	if (ch == '\n')
+	    break;
 
 	buffer [i++] = ch;
-
-    } while (ch != '\n');
+    }
 
     *has_newline = ch ? 1 : 0;
 
@@ -502,7 +496,7 @@ do_search (struct Dlg_head *h)
 {
     static struct dirent *dp   = 0;
     static DIR  *dirp = 0;
-    static char directory [MC_MAXPATHLEN+2];
+    static char *directory;
     struct stat tmp_stat;
     static int pos;
     static int subdirs_left = 0;
@@ -513,6 +507,10 @@ do_search (struct Dlg_head *h)
 	    mc_closedir (dirp);
 	    dirp = 0;
 	}
+	if (directory) {
+	    g_free (directory);
+	    directory = NULL;
+	}
         dp = 0;
 	return 1;
     }
@@ -550,8 +548,9 @@ do_search (struct Dlg_head *h)
 		    break;
 	    } 
 	    
-	    strcpy (directory, tmp);
-	    g_free (tmp);
+	    if (directory)
+		g_free (directory);
+	    directory = tmp;
 
 	    if (verbose){
 		    char buffer [BUF_SMALL];
@@ -582,8 +581,8 @@ do_search (struct Dlg_head *h)
     tmp_name = concat_dir_and_file (directory, dp->d_name);
 
     if (subdirs_left){
-	mc_lstat (tmp_name, &tmp_stat);
-	if (S_ISDIR (tmp_stat.st_mode)){
+	if (!mc_lstat (tmp_name, &tmp_stat)
+	    && S_ISDIR (tmp_stat.st_mode)){
 	    push_directory (tmp_name);
 	    subdirs_left--;
 	}
--- mc-4.6.0/src/info.c.jj	2004-04-05 15:52:18.000000000 +0200
+++ mc-4.6.0/src/info.c	2004-04-08 16:54:35.000000000 +0200
@@ -123,7 +123,7 @@ info_show_info (WInfo *info)
 	    size_trunc_len (buffer1, 5, myfs_stats.avail, 1);
 	    size_trunc_len (buffer2, 5, myfs_stats.total, 1);
 	    printw (_("Free space: %s (%d%%) of %s"), buffer1, myfs_stats.total ?
-		    100 * myfs_stats.avail / myfs_stats.total : 0, buffer2);
+		    (int) (100.0 * myfs_stats.avail / myfs_stats.total) : 0, buffer2);
 	} else
 	    addstr (_("No space information"));
 
@@ -170,7 +170,7 @@ info_show_info (WInfo *info)
 	    printw (_("Size:      %s"), buffer);
 #ifdef HAVE_ST_BLOCKS
 	    printw ((buf.st_blocks==1) ?
-		_(" (%d block)") : _(" (%d blocks)"), buf.st_blocks);
+		_(" (%ld block)") : _(" (%ld blocks)"), (long) buf.st_blocks);
 #endif
 	}
 	
--- mc-4.6.0/src/main.c.jj	2003-02-05 16:54:34.000000000 +0100
+++ mc-4.6.0/src/main.c	2004-03-16 10:50:28.000000000 +0100
@@ -1300,7 +1300,7 @@ copy_readlink (WPanel *panel)
 	    concat_dir_and_file (panel->cwd, selection (panel)->fname);
 	int i;
 
-	i = mc_readlink (p, buffer, MC_MAXPATHLEN);
+	i = mc_readlink (p, buffer, MC_MAXPATHLEN - 1);
 	g_free (p);
 	if (i > 0) {
 	    buffer[i] = 0;
--- mc-4.6.0/src/man2hlp.c.jj	2003-01-21 00:23:42.000000000 +0100
+++ mc-4.6.0/src/man2hlp.c	2004-04-05 12:44:35.000000000 +0200
@@ -611,8 +611,7 @@ handle_link (char *buffer)
 	/* Bold text or italics text */
 	if (buffer[0] == '.' && (buffer[1] == 'I' || buffer[1] == 'B'))
 	    for (buffer += 2; *buffer == ' ' || *buffer == '\t'; buffer++);
-	strncpy (old, buffer, sizeof (old) - 1);
-	old[sizeof (old) - 1] = 0;
+	g_strlcpy (old, buffer, sizeof (old));
 	link_flag = 3;
 	break;
     case 3:
--- mc-4.6.0/src/profile.c.jj	2003-01-20 15:33:02.000000000 +0100
+++ mc-4.6.0/src/profile.c	2004-04-05 12:45:03.000000000 +0200
@@ -325,8 +325,7 @@ static short GetSetProfile (int set, con
     
     s = GetSetProfileChar (set, AppName, KeyName, Default, FileName);
     if (!set){
-	ReturnedString [Size-1] = 0;
-	strncpy (ReturnedString, s, Size-1);
+	g_strlcpy (ReturnedString, s, Size);
    }
     return 1;
 }
--- mc-4.6.0/src/subshell.c.jj	2003-01-24 22:37:28.000000000 +0100
+++ mc-4.6.0/src/subshell.c	2004-03-30 18:24:08.000000000 +0200
@@ -710,7 +710,9 @@ int exit_subshell (void)
     }
 
     g_free (subshell_prompt);
+    g_free (pty_buffer);
     subshell_prompt = NULL;
+    pty_buffer = NULL;
 
     return quit;
 }
--- mc-4.6.0/src/user.c.jj	2002-11-29 04:03:53.000000000 +0100
+++ mc-4.6.0/src/user.c	2004-04-06 15:11:56.000000000 +0200
@@ -138,19 +138,14 @@ int check_format_var (const char *p, cha
 	}
 	
 	/* Copy the variable name */
-	var_name = g_malloc (dots - p);
-	strncpy (var_name, p+4, dots-2 - (p+3));
-	var_name [dots-2 - (p+3)] = 0;
-
+	var_name = g_strndup (p + 4, dots - p - 5);
 	value = getenv (var_name);
 	g_free (var_name);
 	if (value){
 	    *v = g_strdup (value);
 	    return q-p;
 	}
-	var_name = g_malloc (q - dots + 1);
-	strncpy (var_name, dots, q - dots + 1);
-	var_name [q-dots] = 0;
+	var_name = g_strndup (dots, q - dots);
 	*v = var_name;
 	return q-p;
     }
@@ -300,13 +295,15 @@ check_patterns (char *p)
 
 /* Copies a whitespace separated argument from p to arg. Returns the
    point after argument. */
-static char *extract_arg (char *p, char *arg)
+static char *extract_arg (char *p, char *arg, size_t size)
 {
     while (*p && (*p == ' ' || *p == '\t' || *p == '\n'))
 	p++;
                 /* support quote space .mnu */
-    while (*p && (*p != ' ' || *(p-1) == '\\') && *p != '\t' && *p != '\n')
+    while (size > 1 && *p && (*p != ' ' || *(p-1) == '\\') && *p != '\t' && *p != '\n') {
 	*arg++ = *p++;
+	size--;
+    }
     *arg = 0;
     if (!*p || *p == '\n')
 	p --;
@@ -389,29 +386,29 @@ static char *test_condition (WEdit *edit
 	    p--;
 	    break;
 	case 'f': /* file name pattern */
-	    p = extract_arg (p, arg);
+	    p = extract_arg (p, arg, sizeof (arg));
 	    *condition = panel && regexp_match (arg, panel->dir.list [panel->selected].fname, match_file);
 	    break;
 	case 'y': /* syntax pattern */
             if (edit_widget && edit_widget->syntax_type) {
-	        p = extract_arg (p, arg);
+	        p = extract_arg (p, arg, sizeof (arg));
 	        *condition = panel &&
                     regexp_match (arg, edit_widget->syntax_type, match_normal);
 	    }
                 break;
 	case 'd':
-	    p = extract_arg (p, arg);
+	    p = extract_arg (p, arg, sizeof (arg));
 	    *condition = panel && regexp_match (arg, panel->cwd, match_file);
 	    break;
 	case 't':
-	    p = extract_arg (p, arg);
+	    p = extract_arg (p, arg, sizeof (arg));
 	    *condition = panel && test_type (panel, arg);
 	    break;
 	case 'x': /* executable */
 	{
 	    struct stat status;
 	    
-	    p = extract_arg (p, arg);
+	    p = extract_arg (p, arg, sizeof (arg));
 	    if (stat (arg, &status) == 0)
 		*condition = is_exe (status.st_mode);
 	    else
@@ -431,50 +428,43 @@ static char *test_condition (WEdit *edit
 static void
 debug_out (char *start, char *end, int cond)
 {
-    static char msg [256];
+    static char *msg;
     int len;
 
     if (start == NULL && end == NULL){
-	if (cond == 0){
-	    /* Init */
-	    msg [0] = 0;
-	} else {
-	    /* Show output */
-	    if (!debug_flag)
-		return;
+	/* Show output */
+	if (debug_flag && msg) {
 	    len = strlen (msg);
 	    if (len)
 		msg [len - 1] = 0;
 	    message (0, _(" Debug "), "%s", msg);
-	    debug_flag = 0;
 	}
+	debug_flag = 0;
+	g_free (msg);
+	msg = NULL;
     } else {
+	char *type, *p;
+
 	/* Save debug info for later output */
 	if (!debug_flag)
 	    return;
 	/* Save the result of the condition */
 	if (debug_error){
-	    strcat (msg, _(" ERROR: "));
+	    type = _(" ERROR: ");
 	    debug_error = 0;
 	}
 	else if (cond)
-	    strcat (msg, _(" True:  "));
+	    type = _(" True:  ");
 	else
-	    strcat (msg, _(" False: "));
-	/* Copy condition statement */
-	len = strlen (msg);
-	if (end == NULL){
-	    /* Copy one character */
-	    msg [len] = *start;
-	    msg [len + 1] = 0;
-	} else {
-	    /* Copy many characters */
-	    while (start < end){
-		msg [len++] = *start++;
-	    }
-	    msg [len] = 0;
-	}
-	strcat (msg, " \n");
+	    type = _(" False: ");
+	/* This is for debugging, don't need to be super efficient.  */
+	if (end == NULL)
+	    p = g_strdup_printf ("%s%s%c \n", msg ? msg : "", type, *start);
+	else
+	    p = g_strdup_printf ("%s%s%.*s \n", msg ? msg : "", type,
+				 (int) (end - start), start);
+        g_free (msg);
+        msg = p;
     }
 }
 
@@ -486,8 +476,6 @@ static char *test_line (WEdit *edit_widg
     char operator;
     char *debug_start, *debug_end;
 
-    /* Init debugger */
-    debug_out (NULL, NULL, 0);
     /* Repeat till end of line */
     while (*p && *p != '\n') {
         /* support quote space .mnu */
@@ -578,6 +566,8 @@ execute_menu_command (WEdit *edit_widget
 		break;
 	    while (*commands == ' ' || *commands == '\t')
 	        commands++;
+	  if (*commands == '0')
+		break;
 	}
 	col++;
 	if (*commands == '\n')
@@ -734,7 +724,7 @@ user_menu_cmd (struct WEdit *edit_widget
 	    } else if (*p == '+'){
 		if (*(p+1) == '='){
 		    /* Combined adding and default */
-		    p = test_line (edit_widget, p, &accept_entry);
+		    p = test_line (edit_widget, p + 1, &accept_entry);
 		    if (selected == 0 && accept_entry)
 			selected = menu_lines;
 		} else {
@@ -744,7 +734,7 @@ user_menu_cmd (struct WEdit *edit_widget
 	    } else if (*p == '='){
 		if (*(p+1) == '+'){
 		    /* Combined adding and default */
-		    p = test_line (edit_widget, p, &accept_entry);
+		    p = test_line (edit_widget, p + 1, &accept_entry);
 		    if (selected == 0 && accept_entry)
 			selected = menu_lines;
 		} else {
--- mc-4.6.0/src/util.c.jj	2004-01-30 19:02:39.000000000 +0100
+++ mc-4.6.0/src/util.c	2004-04-05 12:55:40.000000000 +0200
@@ -591,7 +591,7 @@ char *convert_pattern (char *pattern, in
     char *new_pattern;
     int was_wildcard = 0;
 
-    if (easy_patterns){
+    if ((match_type != match_regex) && easy_patterns){
 	new_pattern = g_malloc (MC_MAXPATHLEN);
 	d = new_pattern;
 	if (match_type == match_file)
@@ -940,7 +940,7 @@ char *get_current_wd (char *buffer, int 
 	return NULL;
     }
 
-    strncpy (buffer, p, len);
+    memcpy (buffer, p, len);
     g_free (p);
 
     return buffer;
@@ -1155,7 +1155,7 @@ static char *resolve_symlinks (char *pat
 	if (!S_ISLNK (mybuf.st_mode))
 	    strcpy (r, p + 1);
 	else {
-	    len = mc_readlink (path, buf2, MC_MAXPATHLEN);
+	    len = mc_readlink (path, buf2, MC_MAXPATHLEN - 1);
 	    if (len < 0) {
 		 g_free (buf);
 		 g_free (buf2);
--- mc-4.6.0/src/util.h.jj	2004-01-30 19:02:39.000000000 +0100
+++ mc-4.6.0/src/util.h	2004-03-16 11:58:18.000000000 +0100
@@ -64,7 +64,7 @@ char *_icase_search (char *text, char *d
 #define icase_search(T,D) _icase_search((T), (D), NULL)
 
 /* Matching */
-enum { match_file, match_normal };
+enum { match_file, match_normal, match_regex };
 extern int easy_patterns;
 char *convert_pattern (char *pattern, int match_type, int do_group);
 int regexp_match (char *pattern, char *string, int match_type);
--- mc-4.6.0/src/utilunix.c.jj	2002-12-26 15:47:46.000000000 +0100
+++ mc-4.6.0/src/utilunix.c	2004-04-07 18:09:29.000000000 +0200
@@ -280,9 +280,7 @@ char *tilde_expand (const char *director
 	if (!p){
 	    passwd = getpwnam (directory);
 	} else {
-	    name = g_malloc (p - directory + 1);
-	    strncpy (name, directory, p - directory);
-	    name [p - directory] = 0;
+	    name = g_strndup (directory, p - directory);
 	    passwd = getpwnam (name);
 	    g_free (name);
 	}
@@ -298,7 +296,7 @@ char *tilde_expand (const char *director
 
 /*
  * Return the directory where mc should keep its temporary files.
- * This directory is (in Bourne shell terms) "${TMPDIR=/tmp}-$USER"
+ * This directory is (in Bourne shell terms) "${TMPDIR=/tmp}/mc-$USER"
  * When called the first time, the directory is created if needed.
  * The first call should be done early, since we are using fprintf()
  * and not message() to report possible problems.
@@ -372,6 +370,7 @@ mc_tmpdir (void)
 	if (fallback_ok) {
 	    fprintf (stderr, _("Temporary files will be created in %s\n"),
 		     sys_tmp);
+	    error = NULL;
 	} else {
 	    fprintf (stderr, _("Temporary files will not be created\n"));
 	    tmpdir = "/dev/null/";
@@ -381,6 +380,9 @@ mc_tmpdir (void)
 	getc (stdin);
     }
 
+    if (!error)
+	setenv ("MC_TMPDIR", tmpdir, 1);
+
     return tmpdir;
 }
 
--- mc-4.6.0/src/wtools.c.jj	2004-01-30 19:02:39.000000000 +0100
+++ mc-4.6.0/src/wtools.c	2004-04-05 12:59:56.000000000 +0200
@@ -412,8 +412,7 @@ real_input_dialog_help (char *header, ch
 /* we need a unique name for tkname because widget.c:history_tool()
    needs a unique name for each dialog - using the header is ideal */
 
-    strncpy (tk_name + 3, header, 60);
-    tk_name[63] = '\0';
+    g_strlcpy (tk_name + 3, header, 61);
     quick_widgets[2].tkname = tk_name;
 
     len = max (mbstrlen (header), msglen (text, &lines)) + 4;
--- mc-4.6.0/vfs/cpio.c.jj	2002-12-08 02:12:28.000000000 +0100
+++ mc-4.6.0/vfs/cpio.c	2004-04-05 15:49:04.000000000 +0200
@@ -103,9 +103,9 @@ static int cpio_read(void *fh, char *buf
 
 static struct defer_inode * defer_find(struct defer_inode *l, struct defer_inode *i)
 {
-    if(!l) return NULL;
-    return l->inumber == i->inumber && l->device == i->device ? l : 
-	   defer_find(l->next, i);
+    while (l && (l->inumber != i->inumber || l->device != i->device))
+	l = l->next;
+    return l;
 }
 
 static int cpio_skip_padding(vfs_s_super *super)
@@ -127,8 +127,14 @@ static int cpio_skip_padding(vfs_s_super
 
 static void cpio_free_archive(vfs *me, vfs_s_super *super)
 {
+    struct defer_inode *l, *lnext;
     if(super->u.cpio.fd != -1)
-	mc_close(super->u.cpio.fd);
+	mc_close(super->u.cpio.fd), super->u.cpio.fd = -1;
+    for (l = super->u.cpio.defered; l; l = lnext) {
+	lnext = l->next;
+	g_free (l);
+    }
+    super->u.cpio.defered = NULL;
 }
 
 static int cpio_open_cpio_file(vfs *me, vfs_s_super *super, char *name)
@@ -246,26 +252,34 @@ static int cpio_find_head(vfs *me, vfs_s
 #define HEAD_LENGTH (26)
 static int cpio_read_bin_head(vfs *me, vfs_s_super *super)
 {
-    struct old_cpio_header buf;
+    union {
+	struct old_cpio_header buf;
+	short shorts[HEAD_LENGTH >> 1];
+    } u;
     int len;
     char *name;
     struct stat stat;
 
-    if((len = mc_read(super->u.cpio.fd, (char *)&buf, HEAD_LENGTH)) < HEAD_LENGTH)
+    if((len = mc_read(super->u.cpio.fd, (char *)&u.buf, HEAD_LENGTH)) < HEAD_LENGTH)
 	return STATUS_EOF;
     CPIO_POS(super) += len;
     if(super->u.cpio.type == CPIO_BINRE) {
 	int i;
 	for(i = 0; i < (HEAD_LENGTH >> 1); i++)
-	    ((short *)&buf)[i] = GUINT16_SWAP_LE_BE(((short *)&buf)[i]);
+	    u.shorts[i] = GUINT16_SWAP_LE_BE(u.shorts[i]);
     }
-    g_assert(buf.c_magic == 070707);
+    g_assert(u.buf.c_magic == 070707);
 
-    name = g_malloc(buf.c_namesize);
-    if((len = mc_read(super->u.cpio.fd, name, buf.c_namesize)) < buf.c_namesize){
+    if (u.buf.c_namesize == 0 || u.buf.c_namesize > MC_MAXPATHLEN) {
+	message (1, MSG_ERROR, _("Corrupted cpio header encountered in\n%s"), super->name);
+	return STATUS_FAIL;
+    }
+    name = g_malloc(u.buf.c_namesize);
+    if((len = mc_read(super->u.cpio.fd, name, u.buf.c_namesize)) < u.buf.c_namesize){
 	g_free(name);
 	return STATUS_EOF;
     }
+    name[u.buf.c_namesize - 1] = '\0';
     CPIO_POS(super) += len;
     cpio_skip_padding(super);
 
@@ -274,15 +288,15 @@ static int cpio_read_bin_head(vfs *me, v
 	return STATUS_TRAIL;
     }
 
-    stat.st_dev = buf.c_dev;
-    stat.st_ino = buf.c_ino;
-    stat.st_mode = buf.c_mode;
-    stat.st_nlink = buf.c_nlink;
-    stat.st_uid = buf.c_uid;
-    stat.st_gid = buf.c_gid;
-    stat.st_rdev = buf.c_rdev;
-    stat.st_size = (buf.c_filesizes[0] << 16) | buf.c_filesizes[1];
-    stat.st_atime = stat.st_mtime = stat.st_ctime = (buf.c_mtimes[0] << 16) | buf.c_mtimes[1];
+    stat.st_dev = u.buf.c_dev;
+    stat.st_ino = u.buf.c_ino;
+    stat.st_mode = u.buf.c_mode;
+    stat.st_nlink = u.buf.c_nlink;
+    stat.st_uid = u.buf.c_uid;
+    stat.st_gid = u.buf.c_gid;
+    stat.st_rdev = u.buf.c_rdev;
+    stat.st_size = (u.buf.c_filesizes[0] << 16) | u.buf.c_filesizes[1];
+    stat.st_atime = stat.st_mtime = stat.st_ctime = (u.buf.c_mtimes[0] << 16) | u.buf.c_mtimes[1];
 
     return cpio_create_entry(me, super, &stat, name);
 }
@@ -310,11 +324,16 @@ static int cpio_read_oldc_head(vfs *me, 
 	return STATUS_FAIL;
     }
 
+    if (hd.c_namesize == 0 || hd.c_namesize > MC_MAXPATHLEN) {
+	message (1, MSG_ERROR, _("Corrupted cpio header encountered in\n%s"), super->name);
+	return STATUS_FAIL;
+    }
     name = g_malloc(hd.c_namesize);
     if((len = mc_read(super->u.cpio.fd, name, hd.c_namesize)) < hd.c_namesize) {
 	g_free (name);
 	return STATUS_EOF;
     }
+    name[hd.c_namesize - 1] = '\0';
     CPIO_POS(super) +=  len;
     cpio_skip_padding(super);
 
@@ -365,11 +384,16 @@ static int cpio_read_crc_head(vfs *me, v
        (super->u.cpio.type == CPIO_CRC && hd.c_magic != 070702))
 	return STATUS_FAIL;
 
+    if (hd.c_namesize == 0 || hd.c_namesize > MC_MAXPATHLEN) {
+	message (1, MSG_ERROR, _("Corrupted cpio header encountered in\n%s"), super->name);
+	return STATUS_FAIL;
+    }
     name = g_malloc(hd.c_namesize);
     if((len = mc_read(super->u.cpio.fd, name, hd.c_namesize)) < hd.c_namesize){
 	g_free (name);
 	return STATUS_EOF;
     }
+    name[hd.c_namesize - 1] = '\0';
     CPIO_POS(super) += len;
     cpio_skip_padding(super);
 
@@ -430,7 +454,8 @@ static int cpio_create_entry(vfs *me, vf
 		message_3s(1, MSG_ERROR, _("Inconsistent hardlinks of\n%s\nin cpio archive\n%s"),
 			   name, super->name);
 		inode = NULL;
-	    }
+	    } else if (!inode->st.st_size)
+		inode->st.st_size = stat->st_size;
 	}
     }
 
--- mc-4.6.0/vfs/direntry.c.jj	2004-01-30 19:02:39.000000000 +0100
+++ mc-4.6.0/vfs/direntry.c	2004-04-05 12:20:09.000000000 +0200
@@ -217,13 +217,11 @@ vfs_s_automake (vfs *me, vfs_s_inode *di
 vfs_s_entry *
 vfs_s_find_entry_tree (vfs *me, vfs_s_inode *root, char *path, int follow, int flags)
 {
-    unsigned int pseg;
+    size_t pseg;
     vfs_s_entry *ent = NULL;
-    char p[MC_MAXPATHLEN] = "";
+    char p[MC_MAXPATHLEN] = "", *t = p;
 
     while (root){
-	int t;
-
 	while (*path == PATH_SEP)	/* Strip leading '/' */
 	    path++;
 
@@ -233,9 +231,14 @@ vfs_s_find_entry_tree (vfs *me, vfs_s_in
 	for (pseg = 0; path[pseg] && path[pseg] != PATH_SEP; pseg++)
 		;
 
-	strcat (p, PATH_SEP_STR);
-	strncpy (p + (t = strlen (p)), path, pseg);
-	p[t + pseg] = '\0';
+	if (t + pseg + sizeof (PATH_SEP_STR) > p + sizeof (p))
+	    ERRNOR (ENOMEM, NULL);
+
+	memcpy (t, PATH_SEP_STR, sizeof (PATH_SEP_STR) - 1);
+	t += sizeof (PATH_SEP_STR) - 1;
+	memcpy (t, path, pseg);
+	t += pseg;
+	*t = '\0';
 
 	for (ent = root->subdir; ent != NULL; ent = ent->next)
 	    if (strlen (ent->name) == pseg && (!strncmp (ent->name, path, pseg)))
@@ -632,8 +635,7 @@ vfs_s_readdir(void *data)
 	return NULL;
 
     if (info->cur->name) {
-	strncpy(dir.dent.d_name, info->cur->name, MC_MAXPATHLEN);
-	dir.dent.d_name[MC_MAXPATHLEN] = 0;
+	g_strlcpy(dir.dent.d_name, info->cur->name, MC_MAXPATHLEN);
     } else {
 	vfs_die("Null in structure-cannot happen");
     }
@@ -739,8 +741,7 @@ vfs_s_readlink (vfs *me, char *path, cha
     if (ino->linkname == NULL)
 	ERRNOR (EFAULT, -1);
 
-    strncpy (buf, ino->linkname, size);
-    *(buf+size-1) = 0;
+    g_strlcpy (buf, ino->linkname, size);
     return strlen (buf);
 }
 
@@ -1047,7 +1048,7 @@ vfs_s_getlocalcopy (vfs *me, char *path)
     struct vfs_s_inode *ino;
     char buf[MC_MAXPATHLEN];
 
-    strncpy (buf, path, MC_MAXPATHLEN);
+    g_strlcpy (buf, path, MC_MAXPATHLEN);
     ino = vfs_s_inode_from_path (me, path, FL_FOLLOW | FL_NONE);
 
     if (!ino->localname)
--- mc-4.6.0/vfs/extfs.c.jj	2002-12-25 22:42:59.000000000 +0100
+++ mc-4.6.0/vfs/extfs.c	2004-04-05 12:20:38.000000000 +0200
@@ -888,8 +888,7 @@ static void * s_readdir(void *data)
     if (!*info)
 	return NULL;
 
-    strncpy(dir.dent.d_name, (*info)->name, MC_MAXPATHLEN);
-    dir.dent.d_name[MC_MAXPATHLEN] = 0;
+    g_strlcpy(dir.dent.d_name, (*info)->name, MC_MAXPATHLEN);
 
     compute_namelen(&dir.dent);
     *info = (*info)->next_in_dir;
@@ -1002,10 +1001,10 @@ static int s_readlink (vfs *me, char *pa
     if (entry == NULL)
     	return -1;
     if (!S_ISLNK (entry->inode->mode)) ERRNOR (EINVAL, -1);
-    if (size > (i = strlen (entry->inode->linkname))) {
-    	size = i;
+    if (size < (i = strlen (entry->inode->linkname))) {
+    	i = size;
     }
-    strncpy (buf, entry->inode->linkname, i);
+    memcpy (buf, entry->inode->linkname, i);
     return i;
 }
 
--- mc-4.6.0/vfs/fish.c.jj	2002-12-26 03:21:43.000000000 +0100
+++ mc-4.6.0/vfs/fish.c	2004-04-05 12:27:23.000000000 +0200
@@ -96,8 +96,7 @@ static int get_reply (vfs *me, int sock,
 	if (strncmp(answer, "### ", 4)) {
 	    was_garbage = 1;
 	    if (string_buf) {
-	        strncpy(string_buf, answer, string_len - 1);
-		*(string_buf + string_len - 1) = 0;
+	        g_strlcpy(string_buf, answer, string_len);
 	    }
 	} else return decode_reply(answer+4, was_garbage);
     }
@@ -668,7 +667,7 @@ send_fish_command(vfs *me, vfs_s_super *
 {
     int r;
 
-    r = command (me, super, WAIT_REPLY, cmd);
+    r = command (me, super, WAIT_REPLY, "%s", cmd);
     vfs_add_noncurrent_stamps (&vfs_fish_ops, (vfsid) super, NULL);
     if (r != COMPLETE) ERRNOR (E_REMOTE, -1);
     if (flags & OPT_FLUSH)
--- mc-4.6.0/vfs/ftpfs.c.jj	2002-12-26 03:21:43.000000000 +0100
+++ mc-4.6.0/vfs/ftpfs.c	2004-04-05 12:27:51.000000000 +0200
@@ -266,8 +266,7 @@ get_reply (vfs *me, int sock, char *stri
 	switch (sscanf(answer, "%d", &code)){
 	    case 0:
 	        if (string_buf) {
-		    strncpy (string_buf, answer, string_len - 1);
-		    *(string_buf + string_len - 1) = 0;
+		    g_strlcpy (string_buf, answer, string_len);
 		}
 	        code = 500;
 	        return 5;
@@ -286,8 +285,7 @@ get_reply (vfs *me, int sock, char *stri
 		    }
 		}
 	        if (string_buf){
-		    strncpy (string_buf, answer, string_len - 1);
-		    *(string_buf + string_len - 1) = 0;
+		    g_strlcpy (string_buf, answer, string_len);
 		}
 		return code / 100;
 	}
@@ -321,28 +319,28 @@ command (vfs *me, vfs_s_super *super, in
     va_list ap;
     char *str, *fmt_str;
     int status;
-    int sock = SUP.sock;
+    int cmdlen;
     
     va_start (ap, fmt);
     fmt_str = g_strdup_vprintf (fmt, ap);
     va_end (ap);
 
-    status = strlen (fmt_str);
-    str = g_realloc (fmt_str, status + 3);
-    strcpy (str + status, "\r\n");
+    cmdlen = strlen (fmt_str);
+    str = g_realloc (fmt_str, cmdlen + 3);
+    strcpy (str + cmdlen, "\r\n");
 
     if (logfile){
         if (strncmp (str, "PASS ", 5) == 0){
             fputs ("PASS <Password not logged>\r\n", logfile);
         } else
-	    fwrite (str, status + 2, 1, logfile);
+	    fwrite (str, cmdlen + 2, 1, logfile);
 
 	fflush (logfile);
     }
 
     got_sigpipe = 0;
     enable_interrupt_key ();
-    status = write (SUP.sock, str, status + 2);
+    status = write (SUP.sock, str, cmdlen + 2);
     
     if (status < 0){
 	code = 421;
@@ -353,7 +351,7 @@ command (vfs *me, vfs_s_super *super, in
 		level = 1;
 		status = reconnect (me, super);
 		level = 0;
-		if (status && write (SUP.sock, str, status + 2) > 0)
+		if (status && write (SUP.sock, str, cmdlen + 2) > 0)
 		    goto ok;
 	    }
 	    got_sigpipe = 1;
@@ -367,7 +365,7 @@ command (vfs *me, vfs_s_super *super, in
     disable_interrupt_key ();
     
     if (wait_reply)
-	return get_reply (me, sock, (wait_reply & WANT_STRING) ? reply_str : NULL, sizeof (reply_str)-1);
+	return get_reply (me, SUP.sock, (wait_reply & WANT_STRING) ? reply_str : NULL, sizeof (reply_str)-1);
     return COMPLETE;
 }
 
@@ -903,23 +901,29 @@ initconn (vfs *me, vfs_s_super *super)
     int data, len = sizeof(data_addr);
     struct protoent *pe;
 
-    getsockname(SUP.sock, (struct sockaddr *) &data_addr, &len);
-    data_addr.sin_port = 0;
-    
     pe = getprotobyname("tcp");
     if (pe == NULL)
 	    ERRNOR (EIO, -1);
+again:
+    if (getsockname(SUP.sock, (struct sockaddr *) &data_addr, &len) == -1)
+	ERRNOR (EIO, -1);
+    data_addr.sin_port = 0;
+    
     data = socket (AF_INET, SOCK_STREAM, pe->p_proto);
     if (data < 0)
 	    ERRNOR (EIO, -1);
 
     if (SUP.use_passive_connection){
-	if ((SUP.use_passive_connection = setup_passive (me, super, data, &data_addr)))
+	if (setup_passive (me, super, data, &data_addr))
 	    return data;
 
 	SUP.use_source_route = 0;
 	SUP.use_passive_connection = 0;
 	print_vfs_message (_("ftpfs: could not setup passive mode"));
+
+	/* data or data_addr may be damaged by setup_passive */
+	close (data);
+	goto again;
     }
 
     /* If passive setup fails, fallback to active connections */
@@ -971,11 +975,12 @@ open_data_connection (vfs *me, vfs_s_sup
 	data = s;
     else {
 	data = accept (s, (struct sockaddr *)&from, &fromlen);
-	close(s);
 	if (data < 0) {
 	    my_errno = errno;
+	    close(s);
 	    return -1;
 	}
+	close(s);
     } 
     disable_interrupt_key();
     return data;
@@ -1019,6 +1024,7 @@ linear_abort (vfs *me, vfs_s_fh *fh)
 		gettimeofday (&tim, NULL);
 		if (tim.tv_sec > start_tim.tv_sec + ABORT_TIMEOUT) {
 		    /* server keeps sending, drop the connection and reconnect */
+		    close (dsock);
 		    reconnect (me, super);
 		    return;
 		}
--- mc-4.6.0/vfs/mcfs.c.jj	2002-11-15 08:49:39.000000000 +0100
+++ mc-4.6.0/vfs/mcfs.c	2004-04-05 12:28:08.000000000 +0200
@@ -756,8 +756,7 @@ mcfs_readdir (void *info)
 	return NULL;
     }
     dirent_dest = mcfs_readdir_data.dent.d_name;
-    strncpy (dirent_dest, mcfs_info->current->text, MC_MAXPATHLEN);
-    dirent_dest[MC_MAXPATHLEN] = 0;
+    g_strlcpy (dirent_dest, mcfs_info->current->text, MC_MAXPATHLEN);
     cached_lstat_info = &mcfs_info->current->my_stat;
     mcfs_info->current = mcfs_info->current->next;
 
@@ -985,9 +984,12 @@ mcfs_readlink (vfs *me, char *path, char
     if (!rpc_get (mc->sock, RPC_STRING, &stat_str, RPC_END))
 	return the_error (-1, EIO);
 
-    strncpy (buf, stat_str, size);
+    status = strlen (stat_str);
+    if (status < size)
+	size = status;
+    memcpy (buf, stat_str, size);
     g_free (stat_str);
-    return strlen (buf);
+    return size;
 }
 
 static int
--- mc-4.6.0/vfs/mcserv.c.jj	2002-12-08 02:12:30.000000000 +0100
+++ mc-4.6.0/vfs/mcserv.c	2004-03-16 11:03:23.000000000 +0100
@@ -582,7 +582,7 @@ do_readlink (void)
     int n;
 
     rpc_get (msock, RPC_STRING, &file, RPC_END);
-    n = readlink (file, buffer, 2048);
+    n = readlink (file, buffer, 2048 - 1);
     send_status (n, errno);
     if (n >= 0) {
 	buffer[n] = 0;
--- mc-4.6.0/vfs/names.c.jj	2002-11-15 07:19:34.000000000 +0100
+++ mc-4.6.0/vfs/names.c	2004-04-05 15:51:09.000000000 +0200
@@ -31,6 +31,7 @@ GNU Library General Public License for m
 #include <stdio.h>
 #include <pwd.h>
 #include <grp.h>
+#include <glib.h>
 
 #include "names.h"
 
@@ -59,7 +60,7 @@ finduid (char *uname)
 
     if (uname[0] != saveuname[0]	/* Quick test w/o proc call */
 	||0 != strncmp (uname, saveuname, TUNMLEN)) {
-	strncpy (saveuname, uname, TUNMLEN);
+	g_strlcpy (saveuname, uname, TUNMLEN);
 	pw = getpwnam (uname);
 	if (pw) {
 	    saveuid = pw->pw_uid;
@@ -77,7 +78,7 @@ findgid (char *gname)
 
     if (gname[0] != savegname[0]	/* Quick test w/o proc call */
 	||0 != strncmp (gname, savegname, TUNMLEN)) {
-	strncpy (savegname, gname, TUNMLEN);
+	g_strlcpy (savegname, gname, TUNMLEN);
 	gr = getgrnam (gname);
 	if (gr) {
 	    savegid = gr->gr_gid;
--- mc-4.6.0/vfs/samba/lib/util.c.jj	2002-11-15 18:02:44.000000000 +0100
+++ mc-4.6.0/vfs/samba/lib/util.c	2004-04-13 18:30:23.929359353 +0200
@@ -114,7 +114,7 @@ static char *filename_dos(char *path,cha
 char *tmpdir(void)
 {
   char *p;
-  if ((p = getenv("TMPDIR"))) {
+  if ((p = getenv("MC_TMPDIR")) || (p = getenv("TMPDIR"))) {
     return p;
   }
   return "/tmp";
@@ -1885,20 +1885,17 @@ static char *automount_lookup(char *user
  
   char *nis_map = (char *)lp_nis_home_map_name();
  
-  char nis_domain[NIS_MAXNAMELEN + 1];
   char buffer[NIS_MAXATTRVAL + 1];
   nis_result *result;
   nis_object *object;
   entry_obj  *entry;
  
-  strncpy(nis_domain, (char *)nis_local_directory(), NIS_MAXNAMELEN);
-  nis_domain[NIS_MAXNAMELEN] = '\0';
- 
-  DEBUG(5, ("NIS+ Domain: %s\n", nis_domain));
+  DEBUG(5, ("NIS+ Domain: %s\n", (char *)nis_local_directory()));
  
   if (strcmp(user_name, last_key))
   {
-    slprintf(buffer, sizeof(buffer)-1, "[%s=%s]%s.%s", "key", user_name, nis_map, nis_domain);
+    slprintf(buffer, sizeof(buffer)-1, "[%s=%s]%s.%s", "key", user_name, nis_map,
+	     (char *)nis_local_directory());
     DEBUG(5, ("NIS+ querystring: %s\n", buffer));
  
     if (result = nis_list(buffer, RETURN_RESULT, NULL, NULL))
--- mc-4.6.0/vfs/smbfs.c.jj	2003-01-24 22:37:29.000000000 +0100
+++ mc-4.6.0/vfs/smbfs.c	2004-04-05 12:30:15.000000000 +0200
@@ -785,8 +785,7 @@ smbfs_readdir(void *info)
 #endif
 	return NULL;
     }
-    strncpy(dirent_dest, smbfs_info->current->text, MC_MAXPATHLEN);
-    dirent_dest[MC_MAXPATHLEN] = 0;
+    g_strlcpy(dirent_dest, smbfs_info->current->text, MC_MAXPATHLEN);
     smbfs_info->current = smbfs_info->current->next;
 
     compute_namelen(&smbfs_readdir_data.dent);
--- mc-4.6.0/vfs/tar.c.jj	2002-12-08 02:12:30.000000000 +0100
+++ mc-4.6.0/vfs/tar.c	2004-03-16 13:24:47.000000000 +0100
@@ -264,19 +264,26 @@ read_header (vfs *me, vfs_s_super *archi
 	char *bp, *data;
 	int size, written;
 
+	if (hstat.st_size > MC_MAXPATHLEN) {
+	    message_1s (1, MSG_ERROR, _("Inconsistent tar archive"));
+	    return STATUS_BADCHECKSUM;
+	}
+
 	longp = ((header->header.linkflag == LF_LONGNAME)
 		 ? &next_long_name
 		 : &next_long_link);
 
 	if (*longp)
 	    g_free (*longp);
-	bp = *longp = g_malloc (hstat.st_size);
+	bp = *longp = g_malloc (hstat.st_size + 1);
 
 	for (size = hstat.st_size;
 	     size > 0;
 	     size -= written) {
 	    data = get_next_record (archive, tard)->charptr;
 	    if (data == NULL) {
+		g_free (*longp);
+		*longp = NULL;
 		message_1s (1, MSG_ERROR, _("Unexpected EOF on archive file"));
 		return STATUS_BADCHECKSUM;
 	    }
@@ -287,10 +294,14 @@ read_header (vfs *me, vfs_s_super *archi
 	    memcpy (bp, data, written);
 	    bp += written;
 	}
-#if 0
-	if (hstat.st_size > 1)
-	    bp [hstat.st_size - 1] = 0;	/* just to make sure */
-#endif
+
+	if (bp - *longp == MC_MAXPATHLEN && bp[-1] != '\0') {
+	    g_free (*longp);
+	    *longp = NULL;
+	    message_1s (1, MSG_ERROR, _("Inconsistent tar archive"));
+	    return STATUS_BADCHECKSUM;
+	}	 
+	*bp = 0;
 	goto recurse;
     } else {
 	struct stat st;
--- mc-4.6.0/vfs/vfs.c.jj	2002-12-26 03:21:43.000000000 +0100
+++ mc-4.6.0/vfs/vfs.c	2004-04-05 12:30:31.000000000 +0200
@@ -637,8 +637,7 @@ mc_get_current_wd (char *buffer, int siz
 {
     const char *cwd = mc_return_cwd();
 
-    strncpy (buffer, cwd, size - 1);
-    buffer [size - 1] = 0;
+    g_strlcpy (buffer, cwd, size);
     return buffer;
 }
 
