diff --git a/ChangeLog b/ChangeLog
index 0d5871c56c07a9e72784206ba3756350169728ed..dddd7f88f4cfa45166eadcf9e22b76d903e68c05 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -26,6 +26,12 @@ CVS Code -
 	- Fix incorrect cursor location when cutting long lines
 	  (David Benbennick).
 - files.c:
+	- Set a default PATH_MAX for getcwd() etc calls (David 
+	  Benbennick).
+  do_browse_from()
+	- Fix path checking to fix bad paths, escaping 
+	  the operating directory, new function readable_dir() (David 
+	  Benbennick).
   do_browser()
 	- Fix incorrect path check for check_operating_dir() 
 	  (David Benbennick).
diff --git a/files.c b/files.c
index 8805632090747d184101968d830b7429a98564d3..7c46929ec317ad22360b7888cd903e7100c4f396 100644
--- a/files.c
+++ b/files.c
@@ -38,6 +38,12 @@
 #include "proto.h"
 #include "nano.h"
 
+/* Set a default value for PATH_MAX, so we can use it below in lines like
+	path = getcwd(NULL, PATH_MAX + 1); */
+#ifndef PATH_MAX
+#define PATH_MAX -1
+#endif
+
 #ifndef NANO_SMALL
 static int fileformat = 0;	/* 0 = *nix, 1 = DOS, 2 = Mac */
 #endif
@@ -2408,6 +2414,16 @@ void striponedir(char *foo)
     }
 }
 
+int readable_dir(const char *path)
+{
+    DIR *dir = opendir(path);
+
+    /* If dir is NULL, don't do closedir(), since that changes errno. */
+    if (dir != NULL)
+	closedir(dir);
+    return dir != NULL;
+}
+
 /* Initialize the browser code, including the list of files in *path */
 char **browser_init(const char *path, int *longest, int *numents)
 {
@@ -2810,34 +2826,39 @@ char *do_browser(const char *inpath)
 char *do_browse_from(const char *inpath)
 {
     struct stat st;
-    char *tmp;
     char *bob;
+	/* The result of do_browser; the selected file name. */
+    char *path;
+	/* inpath, tilde expanded. */
 
-    /* If there's no / in the string, we may as well start from . */
-    if (inpath == NULL || strchr(inpath, '/') == NULL) {
-#ifdef PATH_MAX
-	char *from = getcwd(NULL, PATH_MAX + 1);
-#else
-	char *from = getcwd(NULL, 0);
-#endif
+    assert(inpath != NULL);
+
+    path = real_dir_from_tilde(inpath);
 
-	bob = do_browser(from != NULL ? from : "./");
-	free(from);
-	return bob;
+    /*
+     * Perhaps path is a directory.  If so, we will pass that to
+     * do_browser.  Otherwise, perhaps path is a directory / a file.  So
+     * we try stripping off the last path element.  If it still isn't a
+     * directory, just use the current directory. */
+
+    if (stat(path, &st) == -1 || !S_ISDIR(st.st_mode)) {
+	striponedir(path);
+	if (stat(path, &st) == -1 || !S_ISDIR(st.st_mode))
+	    path = getcwd(NULL, PATH_MAX + 1);
     }
 
-    /* If the string is a directory, pass do_browser() that */
-    st = filestat(inpath);
-    if (S_ISDIR(st.st_mode))
-	return do_browser(inpath);
-
-    tmp = mallocstrcpy(NULL, inpath);
-    /* Okay, there's a dir in there, but not at the end of the string... 
-       try stripping it off */
-    striponedir(tmp);
-    align(&tmp);
-    bob = do_browser(tmp);
-    free(tmp);
+#ifndef DISABLE_OPERATINGDIR
+    /* If the resulting path isn't in the operating directory, use that. */
+    if (check_operating_dir(path, FALSE))
+	path = mallocstrcpy(path, operating_dir);
+#endif
+
+    if (!readable_dir(path)) {
+	beep();
+	bob = NULL;
+    } else
+	bob = do_browser(path);
+    free(path);
     return bob;
 }
 #endif /* !DISABLE_BROWSER */
diff --git a/proto.h b/proto.h
index 8f202b56c2a7bf7b34dde38774012a91aca2cef0..530f552a3950eb16252a8911c489bef58ed7860c 100644
--- a/proto.h
+++ b/proto.h
@@ -182,6 +182,7 @@ int diralphasort(const void *va, const void *vb);
 void free_charptrarray(char **array, int len);
 const char *tail(const char *foo);
 void striponedir(char *foo);
+int readable_dir(const char *path);
 char **browser_init(const char *path, int *longest, int *numents);
 char *do_browser(const char *inpath);
 char *do_browse_from(const char *inpath);