Added gitignore entries needed to ignore derived objects generated from full build...
[bash.git] / builtins / cd.def
blobb1aae26d01ebd0995d7d362af6c7f7a374da7dc9
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/>.
21 $PRODUCES cd.c
22 #include <config.h>
24 #if defined (HAVE_UNISTD_H)
25 # ifdef _MINIX
26 # include <sys/types.h>
27 # endif
28 # include <unistd.h>
29 #endif
31 #include "../bashtypes.h"
32 #include "posixdir.h"
33 #include "posixstat.h"
34 #ifndef _MINIX
35 #include <sys/param.h>
36 #endif
38 #include <stdio.h>
40 #include "../bashansi.h"
41 #include "../bashintl.h"
43 #include <errno.h>
44 #include <tilde/tilde.h>
46 #include "../shell.h"
47 #include "../flags.h"
48 #include "maxpath.h"
49 #include "common.h"
50 #include "bashgetopt.h"
52 #if !defined (errno)
53 extern int errno;
54 #endif /* !errno */
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. */
66 int cdspelling = 0;
68 int cdable_vars;
70 static int eflag; /* file scope so bindpwd() can see it */
72 $BUILTIN cd
73 $FUNCTION cd_builtin
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
78 HOME shell variable.
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.
89 Options:
90 -L force symbolic links to be followed
91 -P use the physical directory structure without following symbolic
92 links
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.
98 Exit Status:
99 Returns 0 if the directory is changed, and if $PWD is set successfully when
100 -P is used; non-zero otherwise.
101 $END
103 /* Just set $PWD, don't change OLDPWD. Used by `pwd -P' in posix mode. */
104 static int
105 setpwd (dirname)
106 char *dirname;
108 int old_anm;
109 SHELL_VAR *tvar;
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;
123 static int
124 bindpwd (no_symlinks)
125 int no_symlinks;
127 char *dirname, *pwdvar;
128 int old_anm, r;
129 SHELL_VAR *tvar;
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");
136 #undef tcwd
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)
157 free (dirname);
159 return (r);
162 /* Call get_working_directory to reset the value of
163 the_current_working_directory () */
164 static char *
165 resetpwd (caller)
166 char *caller;
168 char *tdir;
170 FREE (the_current_working_directory);
171 the_current_working_directory = (char *)NULL;
172 tdir = get_working_directory (caller);
173 return (tdir);
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. */
186 cd_builtin (list)
187 WORD_LIST *list;
189 char *dirname, *cdpath, *path, *temp;
190 int path_index, no_symlinks, opt, lflag;
192 #if defined (RESTRICTED_SHELL)
193 if (restricted)
195 sh_restricted ((char *)NULL);
196 return (EXECUTION_FAILURE);
198 #endif /* RESTRICTED_SHELL */
200 eflag = 0;
201 no_symlinks = no_symbolic_links;
202 reset_internal_getopt ();
203 while ((opt = internal_getopt (list, "LP")) != -1)
205 switch (opt)
207 case 'P':
208 no_symlinks = 1;
209 break;
210 case 'L':
211 no_symlinks = 0;
212 break;
213 case 'e':
214 eflag = 1;
215 break;
216 default:
217 builtin_usage ();
218 return (EXECUTION_FAILURE);
221 list = loptend;
223 lflag = (cdable_vars ? LCD_DOVARS : 0) |
224 ((interactive && cdspelling) ? LCD_DOSPELL : 0);
225 if (eflag && no_symlinks == 0)
226 eflag = 0;
228 if (list == 0)
230 /* `cd' without arguments is equivalent to `cd $HOME' */
231 dirname = get_string_value ("HOME");
233 if (dirname == 0)
235 builtin_error (_("HOME not set"));
236 return (EXECUTION_FAILURE);
238 lflag = 0;
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");
245 if (dirname == 0)
247 builtin_error (_("OLDPWD not set"));
248 return (EXECUTION_FAILURE);
250 #if 0
251 lflag = interactive ? LCD_PRINTPATH : 0;
252 #else
253 lflag = LCD_PRINTPATH; /* According to SUSv3 */
254 #endif
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. */
263 path_index = 0;
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);
269 free (path);
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);
280 free (temp);
281 #if 0
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));
285 #else
286 return (bindpwd (no_symlinks));
287 #endif
289 else
290 free (temp);
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);
304 #endif
306 else
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
320 change 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));
342 else
343 FREE (temp);
346 builtin_error ("%s: %s", dirname, strerror (errno));
347 return (EXECUTION_FAILURE);
350 $BUILTIN pwd
351 $FUNCTION pwd_builtin
352 $SHORT_DOC pwd [-LP]
353 Print the name of the current working directory.
355 Options:
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
360 By default, `pwd' behaves as if `-L' were specified.
362 Exit Status:
363 Returns 0 unless an invalid option is given or the current directory
364 cannot be read.
365 $END
367 /* Non-zero means that pwd always prints the physical directory, without
368 symbolic links. */
369 static int verbatim_pwd;
371 /* Print the name of the current working directory. */
373 pwd_builtin (list)
374 WORD_LIST *list;
376 char *directory;
377 int opt, pflag;
379 verbatim_pwd = no_symbolic_links;
380 pflag = 0;
381 reset_internal_getopt ();
382 while ((opt = internal_getopt (list, "LP")) != -1)
384 switch (opt)
386 case 'P':
387 verbatim_pwd = pflag = 1;
388 break;
389 case 'L':
390 verbatim_pwd = 0;
391 break;
392 default:
393 builtin_usage ();
394 return (EXECUTION_FAILURE);
397 list = loptend;
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");
410 #undef tcwd
412 if (directory)
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)
420 free (directory);
421 return (sh_chkwrite (opt));
423 else
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. */
433 static int
434 change_to_directory (newdir, nolinks)
435 char *newdir;
436 int nolinks;
438 char *t, *tdir;
439 int err, canon_failed, r, ndlen, dlen;
441 tdir = (char *)NULL;
443 if (the_current_working_directory == 0)
445 t = get_working_directory ("chdir");
446 FREE (t);
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
453 (nolinks != 0). */
454 tdir = nolinks ? sh_physpath (t, 0)
455 : sh_canonpath (t, PATH_CHECKDOTDOT|PATH_CHECKEXISTS);
457 ndlen = strlen (newdir);
458 dlen = strlen (t);
460 /* Use the canonicalized version of NEWDIR, or, if canonicalization
461 failed, use the non-canonical form. */
462 canon_failed = 0;
463 if (tdir && *tdir)
464 free (t);
465 else
467 FREE (tdir);
468 tdir = t;
469 canon_failed = 1;
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)
479 #else
480 if (errno != ENOENT)
481 #endif
482 errno = ENOTDIR;
483 free (tdir);
484 return (0);
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. */
492 if (canon_failed)
494 t = resetpwd ("cd");
495 if (t == 0)
496 set_working_directory (tdir);
498 else
499 set_working_directory (tdir);
501 free (tdir);
502 return (1);
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)
509 free (tdir);
510 return (0);
513 err = errno;
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)
520 t = resetpwd ("cd");
521 if (t == 0)
522 set_working_directory (tdir);
523 else
524 free (t);
526 r = 1;
528 else
530 errno = err;
531 r = 0;
534 free (tdir);
535 return r;