1 This file is cd.def, from which is created cd.c. It implements the
2 builtins "cd" and "pwd" in Bash.
4 Copyright (C) 1987-2009 Free Software Foundation, Inc.
6 This file is part of GNU Bash, the Bourne Again SHell.
8 Bash is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 3 of the License, or
11 (at your option) any later version.
13 Bash is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with Bash. If not, see <http://www.gnu.org/licenses/>.
24 #if defined (HAVE_UNISTD_H)
26 # include <sys/types.h>
31 #include "../bashtypes.h"
33 #include "posixstat.h"
35 #include <sys/param.h>
40 #include "../bashansi.h"
41 #include "../bashintl.h"
44 #include <tilde/tilde.h>
50 #include "bashgetopt.h"
56 extern int posixly_correct;
57 extern int array_needs_making;
58 extern const char * const bash_getcwd_errstr;
60 static int bindpwd __P((int));
61 static void setpwd __P((char *));
62 static char *resetpwd __P((char *));
63 static int change_to_directory __P((char *, int));
65 /* Change this to 1 to get cd spelling correction by default. */
72 $SHORT_DOC cd [-L|-P] [dir]
73 Change the shell working directory.
75 Change the current directory to DIR. The default DIR is the value of the
78 The variable CDPATH defines the search path for the directory containing
79 DIR. Alternative directory names in CDPATH are separated by a colon (:).
80 A null directory name is the same as the current directory. If DIR begins
81 with a slash (/), then CDPATH is not used.
83 If the directory is not found, and the shell option `cdable_vars' is set,
84 the word is assumed to be a variable name. If that variable has a value,
85 its value is used for DIR.
88 -L force symbolic links to be followed
89 -P use the physical directory structure without following symbolic
92 The default is to follow symbolic links, as if `-L' were specified.
95 Returns 0 if the directory is changed; non-zero otherwise.
98 /* Just set $PWD, don't change OLDPWD. Used by `pwd -P' in posix mode. */
106 old_anm = array_needs_making;
107 tvar = bind_variable ("PWD", dirname ? dirname : "", 0);
108 if (old_anm == 0 && array_needs_making && exported_p (tvar))
110 update_export_env_inplace ("PWD=", 4, dirname ? dirname : "");
111 array_needs_making = 0;
116 bindpwd (no_symlinks)
119 char *dirname, *pwdvar;
123 r = sh_chkwrite (EXECUTION_SUCCESS);
125 #define tcwd the_current_working_directory
126 dirname = tcwd ? (no_symlinks ? sh_physpath (tcwd, 0) : tcwd)
127 : get_working_directory ("cd");
130 old_anm = array_needs_making;
131 pwdvar = get_string_value ("PWD");
133 tvar = bind_variable ("OLDPWD", pwdvar, 0);
134 if (old_anm == 0 && array_needs_making && exported_p (tvar))
136 update_export_env_inplace ("OLDPWD=", 7, pwdvar);
137 array_needs_making = 0;
142 if (dirname && dirname != the_current_working_directory)
148 /* Call get_working_directory to reset the value of
149 the_current_working_directory () */
156 FREE (the_current_working_directory);
157 the_current_working_directory = (char *)NULL;
158 tdir = get_working_directory (caller);
162 #define LCD_DOVARS 0x001
163 #define LCD_DOSPELL 0x002
164 #define LCD_PRINTPATH 0x004
165 #define LCD_FREEDIRNAME 0x010
167 /* This builtin is ultimately the way that all user-visible commands should
168 change the current working directory. It is called by cd_to_string (),
169 so the programming interface is simple, and it handles errors and
170 restrictions properly. */
175 char *dirname, *cdpath, *path, *temp;
176 int path_index, no_symlinks, opt, lflag;
178 #if defined (RESTRICTED_SHELL)
181 sh_restricted ((char *)NULL);
182 return (EXECUTION_FAILURE);
184 #endif /* RESTRICTED_SHELL */
186 no_symlinks = no_symbolic_links;
187 reset_internal_getopt ();
188 while ((opt = internal_getopt (list, "LP")) != -1)
200 return (EXECUTION_FAILURE);
205 lflag = (cdable_vars ? LCD_DOVARS : 0) |
206 ((interactive && cdspelling) ? LCD_DOSPELL : 0);
210 /* `cd' without arguments is equivalent to `cd $HOME' */
211 dirname = get_string_value ("HOME");
215 builtin_error (_("HOME not set"));
216 return (EXECUTION_FAILURE);
220 else if (list->word->word[0] == '-' && list->word->word[1] == '\0')
222 /* This is `cd -', equivalent to `cd $OLDPWD' */
223 dirname = get_string_value ("OLDPWD");
227 builtin_error (_("OLDPWD not set"));
228 return (EXECUTION_FAILURE);
231 lflag = interactive ? LCD_PRINTPATH : 0;
233 lflag = LCD_PRINTPATH; /* According to SUSv3 */
236 else if (absolute_pathname (list->word->word))
237 dirname = list->word->word;
238 else if (privileged_mode == 0 && (cdpath = get_string_value ("CDPATH")))
240 dirname = list->word->word;
242 /* Find directory in $CDPATH. */
244 while (path = extract_colon_unit (cdpath, &path_index))
246 /* OPT is 1 if the path element is non-empty */
247 opt = path[0] != '\0';
248 temp = sh_makepath (path, dirname, MP_DOTILDE);
251 if (change_to_directory (temp, no_symlinks))
253 /* POSIX.2 says that if a nonempty directory from CDPATH
254 is used to find the directory to change to, the new
255 directory name is echoed to stdout, whether or not
256 the shell is interactive. */
257 if (opt && (path = no_symlinks ? temp : the_current_working_directory))
258 printf ("%s\n", path);
262 /* Posix.2 says that after using CDPATH, the resultant
263 value of $PWD will not contain `.' or `..'. */
264 return (bindpwd (posixly_correct || no_symlinks));
266 return (bindpwd (no_symlinks));
273 /* POSIX.2 says that if `.' does not appear in $CDPATH, we don't
274 try the current directory, so we just punt now with an error
275 message if POSIXLY_CORRECT is non-zero. The check for cdpath[0]
276 is so we don't mistakenly treat a CDPATH value of "" as not
277 specifying the current directory. */
278 if (posixly_correct && cdpath[0])
280 builtin_error ("%s: %s", dirname, strerror (ENOENT));
281 return (EXECUTION_FAILURE);
285 dirname = list->word->word;
287 /* When we get here, DIRNAME is the directory to change to. If we
288 chdir successfully, just return. */
289 if (change_to_directory (dirname, no_symlinks))
291 if (lflag & LCD_PRINTPATH)
292 printf ("%s\n", dirname);
293 return (bindpwd (no_symlinks));
296 /* If the user requests it, then perhaps this is the name of
297 a shell variable, whose value contains the directory to
299 if (lflag & LCD_DOVARS)
301 temp = get_string_value (dirname);
302 if (temp && change_to_directory (temp, no_symlinks))
304 printf ("%s\n", temp);
305 return (bindpwd (no_symlinks));
309 /* If the user requests it, try to find a directory name similar in
310 spelling to the one requested, in case the user made a simple
311 typo. This is similar to the UNIX 8th and 9th Edition shells. */
312 if (lflag & LCD_DOSPELL)
314 temp = dirspell (dirname);
315 if (temp && change_to_directory (temp, no_symlinks))
317 printf ("%s\n", temp);
318 return (bindpwd (no_symlinks));
324 builtin_error ("%s: %s", dirname, strerror (errno));
325 return (EXECUTION_FAILURE);
329 $FUNCTION pwd_builtin
331 Print the name of the current working directory.
334 -L print the value of $PWD if it names the current working
336 -P print the physical directory, without any symbolic links
338 By default, `pwd' behaves as if `-L' were specified.
341 Returns 0 unless an invalid option is given or the current directory
345 /* Non-zero means that pwd always prints the physical directory, without
347 static int verbatim_pwd;
349 /* Print the name of the current working directory. */
357 verbatim_pwd = no_symbolic_links;
359 reset_internal_getopt ();
360 while ((opt = internal_getopt (list, "LP")) != -1)
365 verbatim_pwd = pflag = 1;
372 return (EXECUTION_FAILURE);
377 #define tcwd the_current_working_directory
379 directory = tcwd ? (verbatim_pwd ? sh_physpath (tcwd, 0) : tcwd)
380 : get_working_directory ("pwd");
382 /* Try again using getcwd() if canonicalization fails (for instance, if
383 the file system has changed state underneath bash). */
384 if ((tcwd && directory == 0) ||
385 (posixly_correct && same_file (".", tcwd, (struct stat *)0, (struct stat *)0) == 0))
386 directory = resetpwd ("pwd");
392 printf ("%s\n", directory);
393 /* This is dumb but posix-mandated. */
394 if (posixly_correct && pflag)
396 if (directory != the_current_working_directory)
398 return (sh_chkwrite (EXECUTION_SUCCESS));
401 return (EXECUTION_FAILURE);
404 /* Do the work of changing to the directory NEWDIR. Handle symbolic
405 link following, etc. This function *must* return with
406 the_current_working_directory either set to NULL (in which case
407 getcwd() will eventually be called), or set to a string corresponding
408 to the working directory. Return 1 on success, 0 on failure. */
411 change_to_directory (newdir, nolinks)
416 int err, canon_failed, r, ndlen, dlen;
420 if (the_current_working_directory == 0)
422 t = get_working_directory ("chdir");
426 t = make_absolute (newdir, the_current_working_directory);
428 /* TDIR is either the canonicalized absolute pathname of NEWDIR
429 (nolinks == 0) or the absolute physical pathname of NEWDIR
431 tdir = nolinks ? sh_physpath (t, 0)
432 : sh_canonpath (t, PATH_CHECKDOTDOT|PATH_CHECKEXISTS);
434 ndlen = strlen (newdir);
437 /* Use the canonicalized version of NEWDIR, or, if canonicalization
438 failed, use the non-canonical form. */
449 /* In POSIX mode, if we're resolving symlinks logically and sh_canonpath
450 returns NULL (because it checks the path, it will return NULL if the
451 resolved path doesn't exist), fail immediately. */
452 if (posixly_correct && nolinks == 0 && canon_failed && (errno != ENAMETOOLONG || ndlen > PATH_MAX))
454 #if defined ENAMETOOLONG
455 if (errno != ENOENT && errno != ENAMETOOLONG)
464 /* If the chdir succeeds, update the_current_working_directory. */
465 if (chdir (nolinks ? newdir : tdir) == 0)
467 /* If canonicalization failed, but the chdir succeeded, reset the
468 shell's idea of the_current_working_directory. */
473 set_working_directory (tdir);
476 set_working_directory (tdir);
482 /* We failed to change to the appropriate directory name. If we tried
483 what the user passed (nolinks != 0), punt now. */
492 /* We're not in physical mode (nolinks == 0), but we failed to change to
493 the canonicalized directory name (TDIR). Try what the user passed
494 verbatim. If we succeed, reinitialize the_current_working_directory. */
495 if (chdir (newdir) == 0)
499 set_working_directory (tdir);