$BUILTIN cd
$FUNCTION cd_builtin
-$SHORT_DOC cd [-PL] [dir]
+$SHORT_DOC cd [-L|-P] [dir]
Change the current directory to DIR. The variable $HOME is the
default DIR. The variable CDPATH defines the search path for
the directory containing DIR. Alternative directory names in CDPATH
return (EXECUTION_SUCCESS);
}
+/* Call get_working_directory to reset the value of
+ the_current_working_directory () */
+static char *
+resetpwd ()
+{
+ char *tdir;
+
+ FREE (the_current_working_directory);
+ the_current_working_directory = (char *)NULL;
+ tdir = get_working_directory ("cd");
+ return (tdir);
+}
+
#define LCD_DOVARS 0x001
#define LCD_DOSPELL 0x002
#define LCD_PRINTPATH 0x004
#if defined (RESTRICTED_SHELL)
if (restricted)
{
- builtin_error ("restricted");
+ sh_restricted ((char *)NULL);
return (EXECUTION_FAILURE);
}
#endif /* RESTRICTED_SHELL */
int nolinks;
{
char *t, *tdir;
- int err;
+ int err, canon_failed;
tdir = (char *)NULL;
/* Use the canonicalized version of NEWDIR, or, if canonicalization
failed, use the non-canonical form. */
+ canon_failed = 0;
if (tdir && *tdir)
free (t);
else
{
FREE (tdir);
tdir = t;
+ canon_failed = 1;
+ }
+
+ /* In POSIX mode, if we're resolving symlinks logically and sh_canonpath
+ returns NULL (because it checks the path, it will return NULL if the
+ resolved path doesn't exist), fail immediately. */
+ if (posixly_correct && nolinks == 0 && canon_failed)
+ {
+ errno = ENOENT;
+ return (0);
}
/* If the chdir succeeds, update the_current_working_directory. */
if (chdir (nolinks ? newdir : tdir) == 0)
{
- FREE (the_current_working_directory);
- the_current_working_directory = tdir;
-
+ /* If canonicalization failed, but the chdir succeeded, reset the
+ shell's idea of the_current_working_directory. */
+ if (canon_failed)
+ resetpwd ();
+ else
+ {
+ FREE (the_current_working_directory);
+ the_current_working_directory = tdir;
+ }
+
return (1);
}
verbatim. If we succeed, reinitialize the_current_working_directory. */
if (chdir (newdir) == 0)
{
- FREE (the_current_working_directory);
- the_current_working_directory = (char *)NULL;
- tdir = get_working_directory ("cd");
+ tdir = resetpwd ();
FREE (tdir);
return (1);