summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog6
-rw-r--r--Src/compat.c19
-rw-r--r--configure.ac30
3 files changed, 52 insertions, 3 deletions
diff --git a/ChangeLog b/ChangeLog
index 123f9926d..83ebe3ee7 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,7 @@
+2010-06-14  Peter Stephenson  <pws@csr.com>
+
+	* 28010
+
 2010-06-13  Peter Stephenson  <p.w.stephenson@ntlworld.com>
 
 	* Mikael: 28027: Doc/Zsh/expn.yo: typo.
@@ -13280,5 +13284,5 @@
 
 *****************************************************
 * This is used by the shell to define $ZSH_PATCHLEVEL
-* $Revision: 1.5000 $
+* $Revision: 1.5001 $
 *****************************************************
diff --git a/Src/compat.c b/Src/compat.c
index e72bf6268..e36de3219 100644
--- a/Src/compat.c
+++ b/Src/compat.c
@@ -420,9 +420,9 @@ zgetdir(struct dirsav *d)
 
 /*
  * Try to find the current directory.
+ * If we couldn't work it out internally, fall back to getcwd().
  * If it fails, fall back to pwd; if zgetcwd() is being used
  * to set pwd, pwd should be NULL and we just return ".".
- * We could fall back to getcwd() instead.
  */
 
 /**/
@@ -430,6 +430,23 @@ char *
 zgetcwd(void)
 {
     char *ret = zgetdir(NULL);
+#ifdef HAVE_GETCWD
+    if (!ret) {
+#ifdef GETCWD_CALLS_MALLOC
+	char *cwd = getcwd(NULL, 0);
+	if (cwd) {
+	    ret = dupstring(cwd);
+	    free(cwd);
+	}
+#else
+	char *cwdbuf = zalloc(PATH_MAX);
+	ret = getcwd(cwdbuf, PATH_MAX);
+	if (ret)
+	    ret = dupstring(ret);
+	free(cwdbuf);
+#endif /* GETCWD_CALLS_MALLOC */
+    }
+#endif /* HAVE_GETCWD */
     if (!ret)
 	ret = pwd;
     if (!ret)
diff --git a/configure.ac b/configure.ac
index 262fe5d14..a93eb5115 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1170,7 +1170,7 @@ AC_CHECK_FUNCS(strftime strptime mktime timelocal \
 	       regcomp regexec regerror regfree \
 	       gdbm_open getxattr \
 	       realpath canonicalize_file_name \
-	       symlink)
+	       symlink getcwd)
 AC_FUNC_STRCOLL
 
 if test x$enable_cap = xyes; then
@@ -1898,6 +1898,34 @@ if test x$zsh_cv_use_getcwd = xyes; then
   AC_DEFINE(USE_GETCWD)
 fi
 
+dnl GNU getcwd() can allocate as much space as necessary for a
+dnl directory name, preventing guessing games.
+AH_TEMPLATE([GETCWD_CALLS_MALLOC],
+[Define to 1 if getcwd() calls malloc to allocate memory.])
+if test x$ac_cv_func_getcwd = xyes; then
+  AC_CACHE_CHECK(whether getcwd calls malloc to allocate memory,
+  zsh_cv_getcwd_malloc,
+  [AC_TRY_RUN([
+#include <unistd.h>
+#include <string.h>
+int main() {
+    char buf[1024], *ptr1, *ptr2;
+    ptr1 = getcwd(buf, 1024);
+    ptr2 = getcwd(NULL, 0);
+    if (ptr1 && ptr2 && !strcmp(ptr1, ptr2)) {
+      return 0;
+    }
+    return 1;
+}
+],
+  zsh_cv_getcwd_malloc=yes,
+  zsh_cv_getcwd_malloc=no,
+  zsh_cv_getcwd_malloc=no)])
+  if test x$zsh_cv_getcwd_malloc = xyes; then
+    AC_DEFINE(GETCWD_CALLS_MALLOC)
+  fi
+fi
+
 dnl CHECK FOR setproctitle() FOR jobs -Z / ARGV0
 AH_TEMPLATE([HAVE_SETPROCTITLE],
 [Define to 1 if the system supports `setproctitle' to change process name])