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-2005 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 it under
9 the terms of the GNU General Public License as published by the Free
10 Software Foundation; either version 2, or (at your option) any later
13 Bash is distributed in the hope that it will be useful, but WITHOUT ANY
14 WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
18 You should have received a copy of the GNU General Public License along
19 with Bash; see the file COPYING. If not, write to the Free Software
20 Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA.
25 #if defined (HAVE_UNISTD_H)
27 # include <sys/types.h>
32 #include "../bashtypes.h"
34 #include "posixstat.h"
36 #include <sys/param.h>
41 #include "../bashansi.h"
42 #include "../bashintl.h"
45 #include <tilde/tilde.h>
51 #include "bashgetopt.h"
57 extern int posixly_correct;
58 extern int array_needs_making;
59 extern char *bash_getcwd_errstr;
61 static int bindpwd __P((int));
62 static void setpwd __P((char *));
63 static char *resetpwd __P((char *));
64 static int change_to_directory __P((char *, int));
66 static char *cdspell __P((char *));
68 /* Change this to 1 to get cd spelling correction by default. */
75 $SHORT_DOC cd [-L|-P] [dir]
76 Change the current directory to DIR. The variable $HOME is the
77 default DIR. The variable CDPATH defines the search path for
78 the directory containing DIR. Alternative directory names in CDPATH
79 are separated by a colon (:). A null directory name is the same as
80 the current directory, i.e. `.'. If DIR begins with a slash (/),
81 then CDPATH is not used. If the directory is not found, and the
82 shell option `cdable_vars' is set, then try the word as a variable
83 name. If that variable has a value, then cd to the value of that
84 variable. The -P option says to use the physical directory structure
85 instead of following symbolic links; the -L option forces symbolic links
89 /* Just set $PWD, don't change OLDPWD. Used by `pwd -P' in posix mode. */
97 old_anm = array_needs_making;
98 tvar = bind_variable ("PWD", dirname ? dirname : "", 0);
99 if (old_anm == 0 && array_needs_making && exported_p (tvar))
101 update_export_env_inplace ("PWD=", 4, dirname ? dirname : "");
102 array_needs_making = 0;
107 bindpwd (no_symlinks)
110 char *dirname, *pwdvar;
114 #define tcwd the_current_working_directory
115 dirname = tcwd ? (no_symlinks ? sh_physpath (tcwd, 0) : tcwd)
116 : get_working_directory ("cd");
119 old_anm = array_needs_making;
120 pwdvar = get_string_value ("PWD");
122 tvar = bind_variable ("OLDPWD", pwdvar, 0);
123 if (old_anm == 0 && array_needs_making && exported_p (tvar))
125 update_export_env_inplace ("OLDPWD=", 7, pwdvar);
126 array_needs_making = 0;
131 if (dirname && dirname != the_current_working_directory)
134 return (EXECUTION_SUCCESS);
137 /* Call get_working_directory to reset the value of
138 the_current_working_directory () */
145 FREE (the_current_working_directory);
146 the_current_working_directory = (char *)NULL;
147 tdir = get_working_directory (caller);
151 #define LCD_DOVARS 0x001
152 #define LCD_DOSPELL 0x002
153 #define LCD_PRINTPATH 0x004
154 #define LCD_FREEDIRNAME 0x010
156 /* This builtin is ultimately the way that all user-visible commands should
157 change the current working directory. It is called by cd_to_string (),
158 so the programming interface is simple, and it handles errors and
159 restrictions properly. */
164 char *dirname, *cdpath, *path, *temp;
165 int path_index, no_symlinks, opt, lflag;
167 #if defined (RESTRICTED_SHELL)
170 sh_restricted ((char *)NULL);
171 return (EXECUTION_FAILURE);
173 #endif /* RESTRICTED_SHELL */
175 no_symlinks = no_symbolic_links;
176 reset_internal_getopt ();
177 while ((opt = internal_getopt (list, "LP")) != -1)
189 return (EXECUTION_FAILURE);
194 lflag = (cdable_vars ? LCD_DOVARS : 0) |
195 ((interactive && cdspelling) ? LCD_DOSPELL : 0);
199 /* `cd' without arguments is equivalent to `cd $HOME' */
200 dirname = get_string_value ("HOME");
204 builtin_error (_("HOME not set"));
205 return (EXECUTION_FAILURE);
209 else if (list->word->word[0] == '-' && list->word->word[1] == '\0')
211 /* This is `cd -', equivalent to `cd $OLDPWD' */
212 dirname = get_string_value ("OLDPWD");
216 builtin_error (_("OLDPWD not set"));
217 return (EXECUTION_FAILURE);
220 lflag = interactive ? LCD_PRINTPATH : 0;
222 lflag = LCD_PRINTPATH; /* According to SUSv3 */
225 else if (absolute_pathname (list->word->word))
226 dirname = list->word->word;
227 else if (cdpath = get_string_value ("CDPATH"))
229 dirname = list->word->word;
231 /* Find directory in $CDPATH. */
233 while (path = extract_colon_unit (cdpath, &path_index))
235 /* OPT is 1 if the path element is non-empty */
236 opt = path[0] != '\0';
237 temp = sh_makepath (path, dirname, MP_DOTILDE);
240 if (change_to_directory (temp, no_symlinks))
242 /* POSIX.2 says that if a nonempty directory from CDPATH
243 is used to find the directory to change to, the new
244 directory name is echoed to stdout, whether or not
245 the shell is interactive. */
246 if (opt && (path = no_symlinks ? temp : the_current_working_directory))
247 printf ("%s\n", path);
251 /* Posix.2 says that after using CDPATH, the resultant
252 value of $PWD will not contain `.' or `..'. */
253 return (bindpwd (posixly_correct || no_symlinks));
255 return (bindpwd (no_symlinks));
262 /* POSIX.2 says that if `.' does not appear in $CDPATH, we don't
263 try the current directory, so we just punt now with an error
264 message if POSIXLY_CORRECT is non-zero. The check for cdpath[0]
265 is so we don't mistakenly treat a CDPATH value of "" as not
266 specifying the current directory. */
267 if (posixly_correct && cdpath[0])
269 builtin_error ("%s: %s", dirname, strerror (ENOENT));
270 return (EXECUTION_FAILURE);
274 dirname = list->word->word;
276 /* When we get here, DIRNAME is the directory to change to. If we
277 chdir successfully, just return. */
278 if (change_to_directory (dirname, no_symlinks))
280 if (lflag & LCD_PRINTPATH)
281 printf ("%s\n", dirname);
282 return (bindpwd (no_symlinks));
285 /* If the user requests it, then perhaps this is the name of
286 a shell variable, whose value contains the directory to
288 if (lflag & LCD_DOVARS)
290 temp = get_string_value (dirname);
291 if (temp && change_to_directory (temp, no_symlinks))
293 printf ("%s\n", temp);
294 return (bindpwd (no_symlinks));
298 /* If the user requests it, try to find a directory name similar in
299 spelling to the one requested, in case the user made a simple
300 typo. This is similar to the UNIX 8th and 9th Edition shells. */
301 if (lflag & LCD_DOSPELL)
303 temp = cdspell (dirname);
304 if (temp && change_to_directory (temp, no_symlinks))
306 printf ("%s\n", temp);
307 return (bindpwd (no_symlinks));
313 builtin_error ("%s: %s", dirname, strerror (errno));
314 return (EXECUTION_FAILURE);
318 $FUNCTION pwd_builtin
320 Print the current working directory. With the -P option, pwd prints
321 the physical directory, without any symbolic links; the -L option
322 makes pwd follow symbolic links.
325 /* Non-zero means that pwd always prints the physical directory, without
327 static int verbatim_pwd;
329 /* Print the name of the current working directory. */
337 verbatim_pwd = no_symbolic_links;
339 reset_internal_getopt ();
340 while ((opt = internal_getopt (list, "LP")) != -1)
345 verbatim_pwd = pflag = 1;
352 return (EXECUTION_FAILURE);
357 #define tcwd the_current_working_directory
359 directory = tcwd ? (verbatim_pwd ? sh_physpath (tcwd, 0) : tcwd)
360 : get_working_directory ("pwd");
362 /* Try again using getcwd() if canonicalization fails (for instance, if
363 the file system has changed state underneath bash). */
364 if ((tcwd && directory == 0) ||
365 (posixly_correct && same_file (".", tcwd, (struct stat *)0, (struct stat *)0) == 0))
366 directory = resetpwd ("pwd");
372 printf ("%s\n", directory);
373 /* This is dumb but posix-mandated. */
374 if (posixly_correct && pflag)
376 if (directory != the_current_working_directory)
383 return (EXECUTION_FAILURE);
386 return (EXECUTION_SUCCESS);
389 return (EXECUTION_FAILURE);
392 /* Do the work of changing to the directory NEWDIR. Handle symbolic
393 link following, etc. This function *must* return with
394 the_current_working_directory either set to NULL (in which case
395 getcwd() will eventually be called), or set to a string corresponding
396 to the working directory. Return 1 on success, 0 on failure. */
399 change_to_directory (newdir, nolinks)
404 int err, canon_failed, r, ndlen, dlen;
408 if (the_current_working_directory == 0)
410 t = get_working_directory ("chdir");
414 t = make_absolute (newdir, the_current_working_directory);
416 /* TDIR is either the canonicalized absolute pathname of NEWDIR
417 (nolinks == 0) or the absolute physical pathname of NEWDIR
419 tdir = nolinks ? sh_physpath (t, 0)
420 : sh_canonpath (t, PATH_CHECKDOTDOT|PATH_CHECKEXISTS);
422 ndlen = strlen (newdir);
425 /* Use the canonicalized version of NEWDIR, or, if canonicalization
426 failed, use the non-canonical form. */
437 /* In POSIX mode, if we're resolving symlinks logically and sh_canonpath
438 returns NULL (because it checks the path, it will return NULL if the
439 resolved path doesn't exist), fail immediately. */
440 if (posixly_correct && nolinks == 0 && canon_failed && (errno != ENAMETOOLONG || ndlen > PATH_MAX))
442 #if defined ENAMETOOLONG
443 if (errno != ENOENT && errno != ENAMETOOLONG)
452 /* If the chdir succeeds, update the_current_working_directory. */
453 if (chdir (nolinks ? newdir : tdir) == 0)
455 /* If canonicalization failed, but the chdir succeeded, reset the
456 shell's idea of the_current_working_directory. */
461 set_working_directory (tdir);
464 set_working_directory (tdir);
470 /* We failed to change to the appropriate directory name. If we tried
471 what the user passed (nolinks != 0), punt now. */
480 /* We're not in physical mode (nolinks == 0), but we failed to change to
481 the canonicalized directory name (TDIR). Try what the user passed
482 verbatim. If we succeed, reinitialize the_current_working_directory. */
483 if (chdir (newdir) == 0)
487 set_working_directory (tdir);
503 /* Code for cd spelling correction. Original patch submitted by
504 Neil Russel (caret@c-side.com). */
513 n = (strlen (dirname) * 3 + 1) / 2 + 1;
514 guess = (char *)xmalloc (n);
516 switch (spname (dirname, guess))