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-2010 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. */
70 static int eflag; /* file scope so bindpwd() can see it */
74 $SHORT_DOC cd [-L|[-P [-e]]] [dir]
75 Change the shell working directory.
77 Change the current directory to DIR. The default DIR is the value of the
80 The variable CDPATH defines the search path for the directory containing
81 DIR. Alternative directory names in CDPATH are separated by a colon (:).
82 A null directory name is the same as the current directory. If DIR begins
83 with a slash (/), then CDPATH is not used.
85 If the directory is not found, and the shell option `cdable_vars' is set,
86 the word is assumed to be a variable name. If that variable has a value,
87 its value is used for DIR.
90 -L force symbolic links to be followed
91 -P use the physical directory structure without following symbolic
93 -e if the -P option is supplied, and the current working directory
94 cannot be determined successfully, exit with a non-zero status
96 The default is to follow symbolic links, as if `-L' were specified.
99 Returns 0 if the directory is changed, and if $PWD is set successfully when
100 -P is used; non-zero otherwise.
103 /* Just set $PWD, don't change OLDPWD. Used by `pwd -P' in posix mode. */
111 old_anm = array_needs_making;
112 tvar = bind_variable ("PWD", dirname ? dirname : "", 0);
113 if (old_anm == 0 && array_needs_making && exported_p (tvar))
115 update_export_env_inplace ("PWD=", 4, dirname ? dirname : "");
116 array_needs_making = 0;
121 bindpwd (no_symlinks)
124 char *dirname, *pwdvar;
128 r = sh_chkwrite (EXECUTION_SUCCESS);
130 #define tcwd the_current_working_directory
131 dirname = tcwd ? (no_symlinks ? sh_physpath (tcwd, 0) : tcwd)
132 : get_working_directory ("cd");
135 old_anm = array_needs_making;
136 pwdvar = get_string_value ("PWD");
138 tvar = bind_variable ("OLDPWD", pwdvar, 0);
139 if (old_anm == 0 && array_needs_making && exported_p (tvar))
141 update_export_env_inplace ("OLDPWD=", 7, pwdvar);
142 array_needs_making = 0;
146 if (dirname == 0 && eflag)
147 r = EXECUTION_FAILURE;
149 if (dirname && dirname != the_current_working_directory)
155 /* Call get_working_directory to reset the value of
156 the_current_working_directory () */
163 FREE (the_current_working_directory);
164 the_current_working_directory = (char *)NULL;
165 tdir = get_working_directory (caller);
169 #define LCD_DOVARS 0x001
170 #define LCD_DOSPELL 0x002
171 #define LCD_PRINTPATH 0x004
172 #define LCD_FREEDIRNAME 0x008
174 /* This builtin is ultimately the way that all user-visible commands should
175 change the current working directory. It is called by cd_to_string (),
176 so the programming interface is simple, and it handles errors and
177 restrictions properly. */
182 char *dirname, *cdpath, *path, *temp;
183 int path_index, no_symlinks, opt, lflag;
185 #if defined (RESTRICTED_SHELL)
188 sh_restricted ((char *)NULL);
189 return (EXECUTION_FAILURE);
191 #endif /* RESTRICTED_SHELL */
194 no_symlinks = no_symbolic_links;
195 reset_internal_getopt ();
196 while ((opt = internal_getopt (list, "LP")) != -1)
211 return (EXECUTION_FAILURE);
216 lflag = (cdable_vars ? LCD_DOVARS : 0) |
217 ((interactive && cdspelling) ? LCD_DOSPELL : 0);
218 if (eflag && no_symlinks == 0)
223 /* `cd' without arguments is equivalent to `cd $HOME' */
224 dirname = get_string_value ("HOME");
228 builtin_error (_("HOME not set"));
229 return (EXECUTION_FAILURE);
233 else if (list->word->word[0] == '-' && list->word->word[1] == '\0')
235 /* This is `cd -', equivalent to `cd $OLDPWD' */
236 dirname = get_string_value ("OLDPWD");
240 builtin_error (_("OLDPWD not set"));
241 return (EXECUTION_FAILURE);
244 lflag = interactive ? LCD_PRINTPATH : 0;
246 lflag = LCD_PRINTPATH; /* According to SUSv3 */
249 else if (absolute_pathname (list->word->word))
250 dirname = list->word->word;
251 else if (privileged_mode == 0 && (cdpath = get_string_value ("CDPATH")))
253 dirname = list->word->word;
255 /* Find directory in $CDPATH. */
257 while (path = extract_colon_unit (cdpath, &path_index))
259 /* OPT is 1 if the path element is non-empty */
260 opt = path[0] != '\0';
261 temp = sh_makepath (path, dirname, MP_DOTILDE);
264 if (change_to_directory (temp, no_symlinks))
266 /* POSIX.2 says that if a nonempty directory from CDPATH
267 is used to find the directory to change to, the new
268 directory name is echoed to stdout, whether or not
269 the shell is interactive. */
270 if (opt && (path = no_symlinks ? temp : the_current_working_directory))
271 printf ("%s\n", path);
275 /* Posix.2 says that after using CDPATH, the resultant
276 value of $PWD will not contain `.' or `..'. */
277 return (bindpwd (posixly_correct || no_symlinks));
279 return (bindpwd (no_symlinks));
286 #if 0 /* changed for bash-4.2 Posix cd description steps 5-6 */
287 /* POSIX.2 says that if `.' does not appear in $CDPATH, we don't
288 try the current directory, so we just punt now with an error
289 message if POSIXLY_CORRECT is non-zero. The check for cdpath[0]
290 is so we don't mistakenly treat a CDPATH value of "" as not
291 specifying the current directory. */
292 if (posixly_correct && cdpath[0])
294 builtin_error ("%s: %s", dirname, strerror (ENOENT));
295 return (EXECUTION_FAILURE);
300 dirname = list->word->word;
302 /* When we get here, DIRNAME is the directory to change to. If we
303 chdir successfully, just return. */
304 if (change_to_directory (dirname, no_symlinks))
306 if (lflag & LCD_PRINTPATH)
307 printf ("%s\n", dirname);
308 return (bindpwd (no_symlinks));
311 /* If the user requests it, then perhaps this is the name of
312 a shell variable, whose value contains the directory to
314 if (lflag & LCD_DOVARS)
316 temp = get_string_value (dirname);
317 if (temp && change_to_directory (temp, no_symlinks))
319 printf ("%s\n", temp);
320 return (bindpwd (no_symlinks));
324 /* If the user requests it, try to find a directory name similar in
325 spelling to the one requested, in case the user made a simple
326 typo. This is similar to the UNIX 8th and 9th Edition shells. */
327 if (lflag & LCD_DOSPELL)
329 temp = dirspell (dirname);
330 if (temp && change_to_directory (temp, no_symlinks))
332 printf ("%s\n", temp);
333 return (bindpwd (no_symlinks));
339 builtin_error ("%s: %s", dirname, strerror (errno));
340 return (EXECUTION_FAILURE);
344 $FUNCTION pwd_builtin
346 Print the name of the current working directory.
349 -L print the value of $PWD if it names the current working
351 -P print the physical directory, without any symbolic links
353 By default, `pwd' behaves as if `-L' were specified.
356 Returns 0 unless an invalid option is given or the current directory
360 /* Non-zero means that pwd always prints the physical directory, without
362 static int verbatim_pwd;
364 /* Print the name of the current working directory. */
372 verbatim_pwd = no_symbolic_links;
374 reset_internal_getopt ();
375 while ((opt = internal_getopt (list, "LP")) != -1)
380 verbatim_pwd = pflag = 1;
387 return (EXECUTION_FAILURE);
392 #define tcwd the_current_working_directory
394 directory = tcwd ? (verbatim_pwd ? sh_physpath (tcwd, 0) : tcwd)
395 : get_working_directory ("pwd");
397 /* Try again using getcwd() if canonicalization fails (for instance, if
398 the file system has changed state underneath bash). */
399 if ((tcwd && directory == 0) ||
400 (posixly_correct && same_file (".", tcwd, (struct stat *)0, (struct stat *)0) == 0))
401 directory = resetpwd ("pwd");
407 printf ("%s\n", directory);
408 /* This is dumb but posix-mandated. */
409 if (posixly_correct && pflag)
411 if (directory != the_current_working_directory)
413 return (sh_chkwrite (EXECUTION_SUCCESS));
416 return (EXECUTION_FAILURE);
419 /* Do the work of changing to the directory NEWDIR. Handle symbolic
420 link following, etc. This function *must* return with
421 the_current_working_directory either set to NULL (in which case
422 getcwd() will eventually be called), or set to a string corresponding
423 to the working directory. Return 1 on success, 0 on failure. */
426 change_to_directory (newdir, nolinks)
431 int err, canon_failed, r, ndlen, dlen;
435 if (the_current_working_directory == 0)
437 t = get_working_directory ("chdir");
441 t = make_absolute (newdir, the_current_working_directory);
443 /* TDIR is either the canonicalized absolute pathname of NEWDIR
444 (nolinks == 0) or the absolute physical pathname of NEWDIR
446 tdir = nolinks ? sh_physpath (t, 0)
447 : sh_canonpath (t, PATH_CHECKDOTDOT|PATH_CHECKEXISTS);
449 ndlen = strlen (newdir);
452 /* Use the canonicalized version of NEWDIR, or, if canonicalization
453 failed, use the non-canonical form. */
464 /* In POSIX mode, if we're resolving symlinks logically and sh_canonpath
465 returns NULL (because it checks the path, it will return NULL if the
466 resolved path doesn't exist), fail immediately. */
467 if (posixly_correct && nolinks == 0 && canon_failed && (errno != ENAMETOOLONG || ndlen > PATH_MAX))
469 #if defined ENAMETOOLONG
470 if (errno != ENOENT && errno != ENAMETOOLONG)
479 /* If the chdir succeeds, update the_current_working_directory. */
480 if (chdir (nolinks ? newdir : tdir) == 0)
482 /* If canonicalization failed, but the chdir succeeded, reset the
483 shell's idea of the_current_working_directory. */
488 set_working_directory (tdir);
491 set_working_directory (tdir);
497 /* We failed to change to the appropriate directory name. If we tried
498 what the user passed (nolinks != 0), punt now. */
507 /* We're not in physical mode (nolinks == 0), but we failed to change to
508 the canonicalized directory name (TDIR). Try what the user passed
509 verbatim. If we succeed, reinitialize the_current_working_directory. */
510 if (chdir (newdir) == 0)
514 set_working_directory (tdir);