]> git.ipfire.org Git - thirdparty/bash.git/blame - builtins/cd.def
Bash-4.2 distribution sources and documentation
[thirdparty/bash.git] / builtins / cd.def
CommitLineData
726f6388 1This file is cd.def, from which is created cd.c. It implements the
ccc6cda3 2builtins "cd" and "pwd" in Bash.
726f6388 3
495aee44 4Copyright (C) 1987-2010 Free Software Foundation, Inc.
726f6388
JA
5
6This file is part of GNU Bash, the Bourne Again SHell.
7
3185942a
JA
8Bash is free software: you can redistribute it and/or modify
9it under the terms of the GNU General Public License as published by
10the Free Software Foundation, either version 3 of the License, or
11(at your option) any later version.
726f6388 12
3185942a
JA
13Bash is distributed in the hope that it will be useful,
14but WITHOUT ANY WARRANTY; without even the implied warranty of
15MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16GNU General Public License for more details.
726f6388 17
3185942a
JA
18You should have received a copy of the GNU General Public License
19along with Bash. If not, see <http://www.gnu.org/licenses/>.
726f6388
JA
20
21$PRODUCES cd.c
ccc6cda3 22#include <config.h>
726f6388 23
ccc6cda3 24#if defined (HAVE_UNISTD_H)
cce855bc
JA
25# ifdef _MINIX
26# include <sys/types.h>
27# endif
ccc6cda3
JA
28# include <unistd.h>
29#endif
30
31#include "../bashtypes.h"
bb70624e
JA
32#include "posixdir.h"
33#include "posixstat.h"
cce855bc 34#ifndef _MINIX
726f6388 35#include <sys/param.h>
cce855bc 36#endif
726f6388 37
ccc6cda3
JA
38#include <stdio.h>
39
40#include "../bashansi.h"
b80f6443 41#include "../bashintl.h"
726f6388
JA
42
43#include <errno.h>
44#include <tilde/tilde.h>
45
46#include "../shell.h"
47#include "../flags.h"
bb70624e 48#include "maxpath.h"
726f6388 49#include "common.h"
ccc6cda3 50#include "bashgetopt.h"
726f6388
JA
51
52#if !defined (errno)
53extern int errno;
54#endif /* !errno */
55
f73dda09 56extern int posixly_correct;
d166f048 57extern int array_needs_making;
3185942a 58extern const char * const bash_getcwd_errstr;
ccc6cda3 59
f73dda09 60static int bindpwd __P((int));
495aee44 61static int setpwd __P((char *));
0628567a 62static char *resetpwd __P((char *));
f73dda09 63static int change_to_directory __P((char *, int));
ccc6cda3 64
d166f048
JA
65/* Change this to 1 to get cd spelling correction by default. */
66int cdspelling = 0;
ccc6cda3
JA
67
68int cdable_vars;
726f6388 69
495aee44
CR
70static int eflag; /* file scope so bindpwd() can see it */
71
726f6388
JA
72$BUILTIN cd
73$FUNCTION cd_builtin
495aee44 74$SHORT_DOC cd [-L|[-P [-e]]] [dir]
3185942a
JA
75Change the shell working directory.
76
77Change the current directory to DIR. The default DIR is the value of the
78HOME shell variable.
79
80The variable CDPATH defines the search path for the directory containing
81DIR. Alternative directory names in CDPATH are separated by a colon (:).
82A null directory name is the same as the current directory. If DIR begins
83with a slash (/), then CDPATH is not used.
84
85If the directory is not found, and the shell option `cdable_vars' is set,
86the word is assumed to be a variable name. If that variable has a value,
87its value is used for DIR.
88
89Options:
90 -L force symbolic links to be followed
91 -P use the physical directory structure without following symbolic
92 links
495aee44
CR
93 -e if the -P option is supplied, and the current working directory
94 cannot be determined successfully, exit with a non-zero status
3185942a
JA
95
96The default is to follow symbolic links, as if `-L' were specified.
97
98Exit Status:
495aee44
CR
99Returns 0 if the directory is changed, and if $PWD is set successfully when
100-P is used; non-zero otherwise.
726f6388
JA
101$END
102
95732b49 103/* Just set $PWD, don't change OLDPWD. Used by `pwd -P' in posix mode. */
495aee44 104static int
95732b49
JA
105setpwd (dirname)
106 char *dirname;
107{
108 int old_anm;
109 SHELL_VAR *tvar;
110
111 old_anm = array_needs_making;
112 tvar = bind_variable ("PWD", dirname ? dirname : "", 0);
495aee44
CR
113 if (tvar && readonly_p (tvar))
114 return EXECUTION_FAILURE;
115 if (tvar && old_anm == 0 && array_needs_making && exported_p (tvar))
95732b49
JA
116 {
117 update_export_env_inplace ("PWD=", 4, dirname ? dirname : "");
118 array_needs_making = 0;
119 }
495aee44 120 return EXECUTION_SUCCESS;
95732b49
JA
121}
122
ccc6cda3
JA
123static int
124bindpwd (no_symlinks)
125 int no_symlinks;
126{
d166f048 127 char *dirname, *pwdvar;
3185942a 128 int old_anm, r;
d166f048 129 SHELL_VAR *tvar;
ccc6cda3 130
3185942a
JA
131 r = sh_chkwrite (EXECUTION_SUCCESS);
132
28ef6c31
JA
133#define tcwd the_current_working_directory
134 dirname = tcwd ? (no_symlinks ? sh_physpath (tcwd, 0) : tcwd)
135 : get_working_directory ("cd");
136#undef tcwd
ccc6cda3 137
d166f048 138 old_anm = array_needs_making;
b72432fd
JA
139 pwdvar = get_string_value ("PWD");
140
95732b49 141 tvar = bind_variable ("OLDPWD", pwdvar, 0);
495aee44
CR
142 if (tvar && readonly_p (tvar))
143 r = EXECUTION_FAILURE;
144
b72432fd
JA
145 if (old_anm == 0 && array_needs_making && exported_p (tvar))
146 {
147 update_export_env_inplace ("OLDPWD=", 7, pwdvar);
148 array_needs_making = 0;
149 }
150
495aee44
CR
151 if (setpwd (dirname) == EXECUTION_FAILURE)
152 r = EXECUTION_FAILURE;
153 if (dirname == 0 && eflag)
154 r = EXECUTION_FAILURE;
ccc6cda3 155
28ef6c31
JA
156 if (dirname && dirname != the_current_working_directory)
157 free (dirname);
b80f6443 158
3185942a 159 return (r);
ccc6cda3
JA
160}
161
7117c2d2
JA
162/* Call get_working_directory to reset the value of
163 the_current_working_directory () */
164static char *
b80f6443
JA
165resetpwd (caller)
166 char *caller;
7117c2d2
JA
167{
168 char *tdir;
169
170 FREE (the_current_working_directory);
171 the_current_working_directory = (char *)NULL;
b80f6443 172 tdir = get_working_directory (caller);
7117c2d2
JA
173 return (tdir);
174}
175
28ef6c31
JA
176#define LCD_DOVARS 0x001
177#define LCD_DOSPELL 0x002
178#define LCD_PRINTPATH 0x004
495aee44 179#define LCD_FREEDIRNAME 0x008
28ef6c31 180
726f6388
JA
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. */
185int
186cd_builtin (list)
187 WORD_LIST *list;
188{
ccc6cda3 189 char *dirname, *cdpath, *path, *temp;
28ef6c31 190 int path_index, no_symlinks, opt, lflag;
726f6388
JA
191
192#if defined (RESTRICTED_SHELL)
193 if (restricted)
194 {
7117c2d2 195 sh_restricted ((char *)NULL);
726f6388
JA
196 return (EXECUTION_FAILURE);
197 }
198#endif /* RESTRICTED_SHELL */
199
495aee44 200 eflag = 0;
ccc6cda3
JA
201 no_symlinks = no_symbolic_links;
202 reset_internal_getopt ();
203 while ((opt = internal_getopt (list, "LP")) != -1)
726f6388 204 {
ccc6cda3 205 switch (opt)
726f6388 206 {
ccc6cda3
JA
207 case 'P':
208 no_symlinks = 1;
209 break;
210 case 'L':
211 no_symlinks = 0;
212 break;
495aee44
CR
213 case 'e':
214 eflag = 1;
215 break;
ccc6cda3
JA
216 default:
217 builtin_usage ();
726f6388
JA
218 return (EXECUTION_FAILURE);
219 }
726f6388 220 }
ccc6cda3
JA
221 list = loptend;
222
28ef6c31
JA
223 lflag = (cdable_vars ? LCD_DOVARS : 0) |
224 ((interactive && cdspelling) ? LCD_DOSPELL : 0);
495aee44
CR
225 if (eflag && no_symlinks == 0)
226 eflag = 0;
28ef6c31 227
ccc6cda3 228 if (list == 0)
726f6388 229 {
ccc6cda3 230 /* `cd' without arguments is equivalent to `cd $HOME' */
726f6388
JA
231 dirname = get_string_value ("HOME");
232
ccc6cda3 233 if (dirname == 0)
726f6388 234 {
b80f6443 235 builtin_error (_("HOME not set"));
726f6388
JA
236 return (EXECUTION_FAILURE);
237 }
28ef6c31 238 lflag = 0;
726f6388 239 }
ccc6cda3 240 else if (list->word->word[0] == '-' && list->word->word[1] == '\0')
726f6388 241 {
ccc6cda3
JA
242 /* This is `cd -', equivalent to `cd $OLDPWD' */
243 dirname = get_string_value ("OLDPWD");
726f6388 244
28ef6c31 245 if (dirname == 0)
726f6388 246 {
b80f6443 247 builtin_error (_("OLDPWD not set"));
726f6388
JA
248 return (EXECUTION_FAILURE);
249 }
b80f6443 250#if 0
28ef6c31 251 lflag = interactive ? LCD_PRINTPATH : 0;
b80f6443
JA
252#else
253 lflag = LCD_PRINTPATH; /* According to SUSv3 */
254#endif
726f6388 255 }
28ef6c31
JA
256 else if (absolute_pathname (list->word->word))
257 dirname = list->word->word;
3185942a 258 else if (privileged_mode == 0 && (cdpath = get_string_value ("CDPATH")))
726f6388 259 {
ccc6cda3
JA
260 dirname = list->word->word;
261
28ef6c31
JA
262 /* Find directory in $CDPATH. */
263 path_index = 0;
264 while (path = extract_colon_unit (cdpath, &path_index))
726f6388 265 {
28ef6c31
JA
266 /* OPT is 1 if the path element is non-empty */
267 opt = path[0] != '\0';
268 temp = sh_makepath (path, dirname, MP_DOTILDE);
269 free (path);
cce855bc 270
28ef6c31 271 if (change_to_directory (temp, no_symlinks))
cce855bc 272 {
28ef6c31
JA
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. */
b80f6443
JA
277 if (opt && (path = no_symlinks ? temp : the_current_working_directory))
278 printf ("%s\n", path);
28ef6c31
JA
279
280 free (temp);
95732b49 281#if 0
28ef6c31
JA
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));
95732b49
JA
285#else
286 return (bindpwd (no_symlinks));
287#endif
cce855bc 288 }
28ef6c31
JA
289 else
290 free (temp);
726f6388
JA
291 }
292
495aee44 293#if 0 /* changed for bash-4.2 Posix cd description steps 5-6 */
28ef6c31
JA
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])
726f6388 300 {
28ef6c31
JA
301 builtin_error ("%s: %s", dirname, strerror (ENOENT));
302 return (EXECUTION_FAILURE);
726f6388 303 }
495aee44 304#endif
28ef6c31
JA
305 }
306 else
307 dirname = list->word->word;
308
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))
312 {
313 if (lflag & LCD_PRINTPATH)
314 printf ("%s\n", dirname);
315 return (bindpwd (no_symlinks));
316 }
726f6388 317
28ef6c31
JA
318 /* If the user requests it, then perhaps this is the name of
319 a shell variable, whose value contains the directory to
320 change to. */
321 if (lflag & LCD_DOVARS)
322 {
323 temp = get_string_value (dirname);
324 if (temp && change_to_directory (temp, no_symlinks))
726f6388 325 {
28ef6c31
JA
326 printf ("%s\n", temp);
327 return (bindpwd (no_symlinks));
726f6388 328 }
28ef6c31 329 }
726f6388 330
28ef6c31
JA
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)
335 {
3185942a 336 temp = dirspell (dirname);
28ef6c31
JA
337 if (temp && change_to_directory (temp, no_symlinks))
338 {
339 printf ("%s\n", temp);
340 return (bindpwd (no_symlinks));
341 }
342 else
343 FREE (temp);
726f6388
JA
344 }
345
28ef6c31
JA
346 builtin_error ("%s: %s", dirname, strerror (errno));
347 return (EXECUTION_FAILURE);
726f6388 348}
726f6388 349
ccc6cda3
JA
350$BUILTIN pwd
351$FUNCTION pwd_builtin
95732b49 352$SHORT_DOC pwd [-LP]
3185942a
JA
353Print the name of the current working directory.
354
355Options:
356 -L print the value of $PWD if it names the current working
357 directory
358 -P print the physical directory, without any symbolic links
359
360By default, `pwd' behaves as if `-L' were specified.
361
362Exit Status:
363Returns 0 unless an invalid option is given or the current directory
364cannot be read.
726f6388
JA
365$END
366
ccc6cda3
JA
367/* Non-zero means that pwd always prints the physical directory, without
368 symbolic links. */
369static int verbatim_pwd;
370
371/* Print the name of the current working directory. */
372int
373pwd_builtin (list)
726f6388
JA
374 WORD_LIST *list;
375{
28ef6c31 376 char *directory;
95732b49 377 int opt, pflag;
726f6388 378
ccc6cda3 379 verbatim_pwd = no_symbolic_links;
95732b49 380 pflag = 0;
ccc6cda3
JA
381 reset_internal_getopt ();
382 while ((opt = internal_getopt (list, "LP")) != -1)
726f6388 383 {
ccc6cda3 384 switch (opt)
726f6388 385 {
ccc6cda3 386 case 'P':
95732b49 387 verbatim_pwd = pflag = 1;
ccc6cda3
JA
388 break;
389 case 'L':
390 verbatim_pwd = 0;
391 break;
392 default:
393 builtin_usage ();
726f6388
JA
394 return (EXECUTION_FAILURE);
395 }
396 }
ccc6cda3 397 list = loptend;
726f6388 398
28ef6c31 399#define tcwd the_current_working_directory
726f6388 400
28ef6c31
JA
401 directory = tcwd ? (verbatim_pwd ? sh_physpath (tcwd, 0) : tcwd)
402 : get_working_directory ("pwd");
b80f6443
JA
403
404 /* Try again using getcwd() if canonicalization fails (for instance, if
405 the file system has changed state underneath bash). */
95732b49
JA
406 if ((tcwd && directory == 0) ||
407 (posixly_correct && same_file (".", tcwd, (struct stat *)0, (struct stat *)0) == 0))
b80f6443
JA
408 directory = resetpwd ("pwd");
409
28ef6c31 410#undef tcwd
726f6388 411
ccc6cda3
JA
412 if (directory)
413 {
495aee44 414 opt = EXECUTION_SUCCESS;
ccc6cda3 415 printf ("%s\n", directory);
95732b49
JA
416 /* This is dumb but posix-mandated. */
417 if (posixly_correct && pflag)
495aee44 418 opt = setpwd (directory);
28ef6c31
JA
419 if (directory != the_current_working_directory)
420 free (directory);
495aee44 421 return (sh_chkwrite (opt));
726f6388 422 }
ccc6cda3
JA
423 else
424 return (EXECUTION_FAILURE);
726f6388 425}
726f6388
JA
426
427/* Do the work of changing to the directory NEWDIR. Handle symbolic
28ef6c31
JA
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. */
726f6388
JA
432
433static int
ccc6cda3 434change_to_directory (newdir, nolinks)
726f6388 435 char *newdir;
ccc6cda3 436 int nolinks;
726f6388 437{
28ef6c31 438 char *t, *tdir;
95732b49 439 int err, canon_failed, r, ndlen, dlen;
726f6388 440
28ef6c31 441 tdir = (char *)NULL;
726f6388 442
28ef6c31
JA
443 if (the_current_working_directory == 0)
444 {
445 t = get_working_directory ("chdir");
446 FREE (t);
447 }
726f6388 448
28ef6c31 449 t = make_absolute (newdir, the_current_working_directory);
726f6388 450
28ef6c31
JA
451 /* TDIR is either the canonicalized absolute pathname of NEWDIR
452 (nolinks == 0) or the absolute physical pathname of NEWDIR
453 (nolinks != 0). */
454 tdir = nolinks ? sh_physpath (t, 0)
455 : sh_canonpath (t, PATH_CHECKDOTDOT|PATH_CHECKEXISTS);
726f6388 456
95732b49
JA
457 ndlen = strlen (newdir);
458 dlen = strlen (t);
459
28ef6c31
JA
460 /* Use the canonicalized version of NEWDIR, or, if canonicalization
461 failed, use the non-canonical form. */
7117c2d2 462 canon_failed = 0;
28ef6c31
JA
463 if (tdir && *tdir)
464 free (t);
465 else
466 {
467 FREE (tdir);
468 tdir = t;
7117c2d2
JA
469 canon_failed = 1;
470 }
471
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. */
95732b49 475 if (posixly_correct && nolinks == 0 && canon_failed && (errno != ENAMETOOLONG || ndlen > PATH_MAX))
7117c2d2 476 {
b80f6443
JA
477#if defined ENAMETOOLONG
478 if (errno != ENOENT && errno != ENAMETOOLONG)
479#else
480 if (errno != ENOENT)
481#endif
482 errno = ENOTDIR;
95732b49 483 free (tdir);
7117c2d2 484 return (0);
28ef6c31 485 }
726f6388 486
28ef6c31
JA
487 /* If the chdir succeeds, update the_current_working_directory. */
488 if (chdir (nolinks ? newdir : tdir) == 0)
489 {
7117c2d2
JA
490 /* If canonicalization failed, but the chdir succeeded, reset the
491 shell's idea of the_current_working_directory. */
492 if (canon_failed)
7117c2d2 493 {
b80f6443
JA
494 t = resetpwd ("cd");
495 if (t == 0)
496 set_working_directory (tdir);
7117c2d2 497 }
b80f6443
JA
498 else
499 set_working_directory (tdir);
7117c2d2 500
95732b49 501 free (tdir);
28ef6c31
JA
502 return (1);
503 }
726f6388 504
28ef6c31
JA
505 /* We failed to change to the appropriate directory name. If we tried
506 what the user passed (nolinks != 0), punt now. */
507 if (nolinks)
95732b49
JA
508 {
509 free (tdir);
510 return (0);
511 }
726f6388 512
28ef6c31 513 err = errno;
726f6388 514
28ef6c31
JA
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)
519 {
b80f6443
JA
520 t = resetpwd ("cd");
521 if (t == 0)
522 set_working_directory (tdir);
523 else
524 free (t);
726f6388 525
b80f6443 526 r = 1;
726f6388
JA
527 }
528 else
28ef6c31
JA
529 {
530 errno = err;
b80f6443 531 r = 0;
28ef6c31 532 }
b80f6443
JA
533
534 free (tdir);
535 return r;
ccc6cda3 536}