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))