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 int 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 (tvar
&& readonly_p (tvar
))
114 return EXECUTION_FAILURE
;
115 if (tvar
&& old_anm
== 0 && array_needs_making
&& exported_p (tvar
))
117 update_export_env_inplace ("PWD=", 4, dirname ? dirname
: "");
118 array_needs_making
= 0;
120 return EXECUTION_SUCCESS
;
124 bindpwd (no_symlinks
)
127 char
*dirname
, *pwdvar
;
131 r
= sh_chkwrite (EXECUTION_SUCCESS
);
133 #define tcwd the_current_working_directory
134 dirname
= tcwd ?
(no_symlinks ?
sh_physpath (tcwd
, 0) : tcwd
)
135 : get_working_directory ("cd");
138 old_anm
= array_needs_making
;
139 pwdvar
= get_string_value ("PWD");
141 tvar
= bind_variable ("OLDPWD", pwdvar
, 0);
142 if (tvar
&& readonly_p (tvar
))
143 r
= EXECUTION_FAILURE
;
145 if (old_anm
== 0 && array_needs_making
&& exported_p (tvar
))
147 update_export_env_inplace ("OLDPWD=", 7, pwdvar
);
148 array_needs_making
= 0;
151 if (setpwd (dirname
) == EXECUTION_FAILURE
)
152 r
= EXECUTION_FAILURE
;
153 if (dirname
== 0 && eflag
)
154 r
= EXECUTION_FAILURE
;
156 if (dirname
&& dirname
!= the_current_working_directory
)
162 /* Call get_working_directory to reset the value of
163 the_current_working_directory () */
170 FREE (the_current_working_directory
);
171 the_current_working_directory
= (char *)NULL
;
172 tdir
= get_working_directory (caller
);
176 #define LCD_DOVARS
0x001
177 #define LCD_DOSPELL
0x002
178 #define LCD_PRINTPATH
0x004
179 #define LCD_FREEDIRNAME
0x008
181 /* This builtin is ultimately the way that all user
-visible commands should
182 change the current working directory. It is called by
cd_to_string (),
183 so the programming interface is simple
, and it handles errors and
184 restrictions properly.
*/
189 char
*dirname
, *cdpath
, *path
, *temp
;
190 int path_index
, no_symlinks
, opt
, lflag
;
192 #if
defined (RESTRICTED_SHELL
)
195 sh_restricted ((char *)NULL
);
196 return (EXECUTION_FAILURE
);
198 #endif
/* RESTRICTED_SHELL
*/
201 no_symlinks
= no_symbolic_links
;
202 reset_internal_getopt ();
203 while ((opt
= internal_getopt (list
, "LP")) != -1)
218 return (EXECUTION_FAILURE
);
223 lflag
= (cdable_vars ? LCD_DOVARS
: 0) |
224 ((interactive
&& cdspelling
) ? LCD_DOSPELL
: 0);
225 if (eflag
&& no_symlinks
== 0)
230 /* `cd
' without arguments is equivalent to `cd $HOME' */
231 dirname
= get_string_value ("HOME");
235 builtin_error (_("HOME not set"));
236 return (EXECUTION_FAILURE
);
240 else
if (list
->word
->word
[0] == '-' && list
->word
->word
[1] == '\0')
242 /* This is `cd
-', equivalent to `cd $OLDPWD' */
243 dirname
= get_string_value ("OLDPWD");
247 builtin_error (_("OLDPWD not set"));
248 return (EXECUTION_FAILURE
);
251 lflag
= interactive ? LCD_PRINTPATH
: 0;
253 lflag
= LCD_PRINTPATH
; /* According to SUSv3
*/
256 else
if (absolute_pathname (list
->word
->word
))
257 dirname
= list
->word
->word
;
258 else
if (privileged_mode
== 0 && (cdpath
= get_string_value ("CDPATH")))
260 dirname
= list
->word
->word
;
262 /* Find directory in $CDPATH.
*/
264 while (path
= extract_colon_unit (cdpath
, &path_index
))
266 /* OPT is
1 if the path element is non
-empty
*/
267 opt
= path
[0] != '\0';
268 temp
= sh_makepath (path
, dirname
, MP_DOTILDE
);
271 if (change_to_directory (temp
, no_symlinks
))
273 /* POSIX
.2 says that if a nonempty directory from CDPATH
274 is used to find the directory to change to
, the new
275 directory name is echoed to stdout
, whether or not
276 the shell is interactive.
*/
277 if (opt
&& (path
= no_symlinks ? temp
: the_current_working_directory
))
278 printf ("%s\n", path
);
282 /* Posix
.2 says that after using CDPATH
, the resultant
283 value of $PWD will not contain `.
' or `..'.
*/
284 return (bindpwd (posixly_correct || no_symlinks
));
286 return (bindpwd (no_symlinks
));
293 #if
0 /* changed for bash
-4.2 Posix cd description steps
5-6 */
294 /* POSIX
.2 says that if `.
' does not appear in $CDPATH, we don't
295 try the current directory
, so we just punt now with an error
296 message if POSIXLY_CORRECT is non
-zero. The check for cdpath
[0]
297 is so we don
't mistakenly treat a CDPATH value of "" as not
298 specifying the current directory. */
299 if (posixly_correct && cdpath[0])
301 builtin_error ("%s: %s", dirname, strerror (ENOENT));
302 return (EXECUTION_FAILURE);
307 dirname = list->word->word;
309 /* When we get here, DIRNAME is the directory to change to. If we
310 chdir successfully, just return. */
311 if (change_to_directory (dirname, no_symlinks))
313 if (lflag & LCD_PRINTPATH)
314 printf ("%s\n", dirname);
315 return (bindpwd (no_symlinks));
318 /* If the user requests it, then perhaps this is the name of
319 a shell variable, whose value contains the directory to
321 if (lflag & LCD_DOVARS)
323 temp = get_string_value (dirname);
324 if (temp && change_to_directory (temp, no_symlinks))
326 printf ("%s\n", temp);
327 return (bindpwd (no_symlinks));
331 /* If the user requests it, try to find a directory name similar in
332 spelling to the one requested, in case the user made a simple
333 typo. This is similar to the UNIX 8th and 9th Edition shells. */
334 if (lflag & LCD_DOSPELL)
336 temp = dirspell (dirname);
337 if (temp && change_to_directory (temp, no_symlinks))
339 printf ("%s\n", temp);
340 return (bindpwd (no_symlinks));
346 builtin_error ("%s: %s", dirname, strerror (errno));
347 return (EXECUTION_FAILURE);
351 $FUNCTION pwd_builtin
353 Print the name of the current working directory.
356 -L print the value of $PWD if it names the current working
358 -P print the physical directory, without any symbolic links
360 By default, `pwd' behaves as if `
-L
' were specified.
363 Returns 0 unless an invalid option is given or the current directory
367 /* Non-zero means that pwd always prints the physical directory, without
369 static int verbatim_pwd;
371 /* Print the name of the current working directory. */
379 verbatim_pwd = no_symbolic_links;
381 reset_internal_getopt ();
382 while ((opt = internal_getopt (list, "LP")) != -1)
387 verbatim_pwd = pflag = 1;
394 return (EXECUTION_FAILURE);
399 #define tcwd the_current_working_directory
401 directory = tcwd ? (verbatim_pwd ? sh_physpath (tcwd, 0) : tcwd)
402 : get_working_directory ("pwd");
404 /* Try again using getcwd() if canonicalization fails (for instance, if
405 the file system has changed state underneath bash). */
406 if ((tcwd && directory == 0) ||
407 (posixly_correct && same_file (".", tcwd, (struct stat *)0, (struct stat *)0) == 0))
408 directory = resetpwd ("pwd");
414 opt = EXECUTION_SUCCESS;
415 printf ("%s\n", directory);
416 /* This is dumb but posix-mandated. */
417 if (posixly_correct && pflag)
418 opt = setpwd (directory);
419 if (directory != the_current_working_directory)
421 return (sh_chkwrite (opt));
424 return (EXECUTION_FAILURE);
427 /* Do the work of changing to the directory NEWDIR. Handle symbolic
428 link following, etc. This function *must* return with
429 the_current_working_directory either set to NULL (in which case
430 getcwd() will eventually be called), or set to a string corresponding
431 to the working directory. Return 1 on success, 0 on failure. */
434 change_to_directory (newdir, nolinks)
439 int err, canon_failed, r, ndlen, dlen;
443 if (the_current_working_directory == 0)
445 t = get_working_directory ("chdir");
449 t = make_absolute (newdir, the_current_working_directory);
451 /* TDIR is either the canonicalized absolute pathname of NEWDIR
452 (nolinks == 0) or the absolute physical pathname of NEWDIR
454 tdir = nolinks ? sh_physpath (t, 0)
455 : sh_canonpath (t, PATH_CHECKDOTDOT|PATH_CHECKEXISTS);
457 ndlen = strlen (newdir);
460 /* Use the canonicalized version of NEWDIR, or, if canonicalization
461 failed, use the non-canonical form. */
472 /* In POSIX mode, if we're resolving symlinks logically and sh_canonpath
473 returns
NULL (because it checks the path
, it will return NULL if the
474 resolved path doesn
't exist), fail immediately. */
475 if (posixly_correct && nolinks == 0 && canon_failed && (errno != ENAMETOOLONG || ndlen > PATH_MAX))
477 #if defined ENAMETOOLONG
478 if (errno != ENOENT && errno != ENAMETOOLONG)
487 /* If the chdir succeeds, update the_current_working_directory. */
488 if (chdir (nolinks ? newdir : tdir) == 0)
490 /* If canonicalization failed, but the chdir succeeded, reset the
491 shell's idea of the_current_working_directory.
*/
496 set_working_directory (tdir
);
499 set_working_directory (tdir
);
505 /* We failed to change to the appropriate directory name. If we tried
506 what the user
passed (nolinks
!= 0), punt now.
*/
515 /* We
're not in physical mode (nolinks == 0), but we failed to change to
516 the canonicalized directory name (TDIR). Try what the user passed
517 verbatim. If we succeed, reinitialize the_current_working_directory. */
518 if (chdir (newdir) == 0)
522 set_working_directory (tdir);