blob: e49b3bd1cc289c718970354e5e36595529d0649b [file] [log] [blame]
Jari Aalto726f6381996-08-26 18:22:31 +00001This file is cd.def, from which is created cd.c. It implements the
Jari Aaltoccc6cda1996-12-23 17:02:34 +00002builtins "cd" and "pwd" in Bash.
Jari Aalto726f6381996-08-26 18:22:31 +00003
Chet Rameyac50fba2014-02-26 09:36:43 -05004Copyright (C) 1987-2013 Free Software Foundation, Inc.
Jari Aalto726f6381996-08-26 18:22:31 +00005
6This file is part of GNU Bash, the Bourne Again SHell.
7
Jari Aalto31859422009-01-12 13:36:28 +00008Bash 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.
Jari Aalto726f6381996-08-26 18:22:31 +000012
Jari Aalto31859422009-01-12 13:36:28 +000013Bash 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.
Jari Aalto726f6381996-08-26 18:22:31 +000017
Jari Aalto31859422009-01-12 13:36:28 +000018You should have received a copy of the GNU General Public License
19along with Bash. If not, see <http://www.gnu.org/licenses/>.
Jari Aalto726f6381996-08-26 18:22:31 +000020
21$PRODUCES cd.c
Jari Aaltoccc6cda1996-12-23 17:02:34 +000022#include <config.h>
Jari Aalto726f6381996-08-26 18:22:31 +000023
Jari Aaltoccc6cda1996-12-23 17:02:34 +000024#if defined (HAVE_UNISTD_H)
Jari Aaltocce855b1998-04-17 19:52:44 +000025# ifdef _MINIX
26# include <sys/types.h>
27# endif
Jari Aaltoccc6cda1996-12-23 17:02:34 +000028# include <unistd.h>
29#endif
30
31#include "../bashtypes.h"
Jari Aaltobb706242000-03-17 21:46:59 +000032#include "posixdir.h"
33#include "posixstat.h"
Chet Rameyac50fba2014-02-26 09:36:43 -050034#if defined (HAVE_SYS_PARAM_H)
Jari Aalto726f6381996-08-26 18:22:31 +000035#include <sys/param.h>
Jari Aaltocce855b1998-04-17 19:52:44 +000036#endif
Chet Rameyac50fba2014-02-26 09:36:43 -050037#include <fcntl.h>
Jari Aalto726f6381996-08-26 18:22:31 +000038
Jari Aaltoccc6cda1996-12-23 17:02:34 +000039#include <stdio.h>
40
41#include "../bashansi.h"
Jari Aaltob80f6442004-07-27 13:29:18 +000042#include "../bashintl.h"
Jari Aalto726f6381996-08-26 18:22:31 +000043
44#include <errno.h>
45#include <tilde/tilde.h>
46
47#include "../shell.h"
48#include "../flags.h"
Jari Aaltobb706242000-03-17 21:46:59 +000049#include "maxpath.h"
Jari Aalto726f6381996-08-26 18:22:31 +000050#include "common.h"
Jari Aaltoccc6cda1996-12-23 17:02:34 +000051#include "bashgetopt.h"
Jari Aalto726f6381996-08-26 18:22:31 +000052
53#if !defined (errno)
Ricardo Cerqueiraa02fbff2013-07-25 22:35:34 +010054#include <errno.h>
Jari Aalto726f6381996-08-26 18:22:31 +000055#endif /* !errno */
56
Jari Aaltof73dda02001-11-13 17:56:06 +000057extern int posixly_correct;
Jari Aaltod166f041997-06-05 14:59:13 +000058extern int array_needs_making;
Jari Aalto31859422009-01-12 13:36:28 +000059extern const char * const bash_getcwd_errstr;
Jari Aaltoccc6cda1996-12-23 17:02:34 +000060
Jari Aaltof73dda02001-11-13 17:56:06 +000061static int bindpwd __P((int));
Chet Ramey495aee42011-11-22 19:11:26 -050062static int setpwd __P((char *));
Jari Aalto06285672006-10-10 14:15:34 +000063static char *resetpwd __P((char *));
Chet Rameyac50fba2014-02-26 09:36:43 -050064static int change_to_directory __P((char *, int, int));
65
66static int cdxattr __P((char *, char **));
67static void resetxattr __P((void));
Jari Aaltoccc6cda1996-12-23 17:02:34 +000068
Jari Aaltod166f041997-06-05 14:59:13 +000069/* Change this to 1 to get cd spelling correction by default. */
70int cdspelling = 0;
Jari Aaltoccc6cda1996-12-23 17:02:34 +000071
72int cdable_vars;
Jari Aalto726f6381996-08-26 18:22:31 +000073
Chet Ramey495aee42011-11-22 19:11:26 -050074static int eflag; /* file scope so bindpwd() can see it */
Chet Rameyac50fba2014-02-26 09:36:43 -050075static int xattrflag; /* O_XATTR support for openat */
76static int xattrfd = -1;
Chet Ramey495aee42011-11-22 19:11:26 -050077
Jari Aalto726f6381996-08-26 18:22:31 +000078$BUILTIN cd
79$FUNCTION cd_builtin
Chet Rameyac50fba2014-02-26 09:36:43 -050080$SHORT_DOC cd [-L|[-P [-e]] [-@]] [dir]
Jari Aalto31859422009-01-12 13:36:28 +000081Change the shell working directory.
82
83Change the current directory to DIR. The default DIR is the value of the
84HOME shell variable.
85
86The variable CDPATH defines the search path for the directory containing
87DIR. Alternative directory names in CDPATH are separated by a colon (:).
88A null directory name is the same as the current directory. If DIR begins
89with a slash (/), then CDPATH is not used.
90
91If the directory is not found, and the shell option `cdable_vars' is set,
92the word is assumed to be a variable name. If that variable has a value,
93its value is used for DIR.
94
95Options:
Chet Rameyac50fba2014-02-26 09:36:43 -050096 -L force symbolic links to be followed: resolve symbolic links in
97 DIR after processing instances of `..'
Jari Aalto31859422009-01-12 13:36:28 +000098 -P use the physical directory structure without following symbolic
Chet Rameyac50fba2014-02-26 09:36:43 -050099 links: resolve symbolic links in DIR before processing instances
100 of `..'
Chet Ramey495aee42011-11-22 19:11:26 -0500101 -e if the -P option is supplied, and the current working directory
102 cannot be determined successfully, exit with a non-zero status
Chet Rameyac50fba2014-02-26 09:36:43 -0500103#if defined (O_XATTR)
104 -@ on systems that support it, present a file with extended attributes
105 as a directory containing the file attributes
106#endif
Jari Aalto31859422009-01-12 13:36:28 +0000107
108The default is to follow symbolic links, as if `-L' were specified.
Chet Rameyac50fba2014-02-26 09:36:43 -0500109`..' is processed by removing the immediately previous pathname component
110back to a slash or the beginning of DIR.
Jari Aalto31859422009-01-12 13:36:28 +0000111
112Exit Status:
Chet Ramey495aee42011-11-22 19:11:26 -0500113Returns 0 if the directory is changed, and if $PWD is set successfully when
114-P is used; non-zero otherwise.
Jari Aalto726f6381996-08-26 18:22:31 +0000115$END
116
Jari Aalto95732b42005-12-07 14:08:12 +0000117/* Just set $PWD, don't change OLDPWD. Used by `pwd -P' in posix mode. */
Chet Ramey495aee42011-11-22 19:11:26 -0500118static int
Jari Aalto95732b42005-12-07 14:08:12 +0000119setpwd (dirname)
120 char *dirname;
121{
122 int old_anm;
123 SHELL_VAR *tvar;
124
125 old_anm = array_needs_making;
126 tvar = bind_variable ("PWD", dirname ? dirname : "", 0);
Chet Ramey495aee42011-11-22 19:11:26 -0500127 if (tvar && readonly_p (tvar))
128 return EXECUTION_FAILURE;
129 if (tvar && old_anm == 0 && array_needs_making && exported_p (tvar))
Jari Aalto95732b42005-12-07 14:08:12 +0000130 {
131 update_export_env_inplace ("PWD=", 4, dirname ? dirname : "");
132 array_needs_making = 0;
133 }
Chet Ramey495aee42011-11-22 19:11:26 -0500134 return EXECUTION_SUCCESS;
Jari Aalto95732b42005-12-07 14:08:12 +0000135}
136
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000137static int
138bindpwd (no_symlinks)
139 int no_symlinks;
140{
Jari Aaltod166f041997-06-05 14:59:13 +0000141 char *dirname, *pwdvar;
Jari Aalto31859422009-01-12 13:36:28 +0000142 int old_anm, r;
Jari Aaltod166f041997-06-05 14:59:13 +0000143 SHELL_VAR *tvar;
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000144
Jari Aalto31859422009-01-12 13:36:28 +0000145 r = sh_chkwrite (EXECUTION_SUCCESS);
146
Jari Aalto28ef6c32001-04-06 19:14:31 +0000147#define tcwd the_current_working_directory
148 dirname = tcwd ? (no_symlinks ? sh_physpath (tcwd, 0) : tcwd)
149 : get_working_directory ("cd");
150#undef tcwd
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000151
Jari Aaltod166f041997-06-05 14:59:13 +0000152 old_anm = array_needs_making;
Jari Aaltob72432f1999-02-19 17:11:39 +0000153 pwdvar = get_string_value ("PWD");
154
Jari Aalto95732b42005-12-07 14:08:12 +0000155 tvar = bind_variable ("OLDPWD", pwdvar, 0);
Chet Ramey495aee42011-11-22 19:11:26 -0500156 if (tvar && readonly_p (tvar))
157 r = EXECUTION_FAILURE;
158
Jari Aaltod166f041997-06-05 14:59:13 +0000159 if (old_anm == 0 && array_needs_making && exported_p (tvar))
160 {
Jari Aaltob72432f1999-02-19 17:11:39 +0000161 update_export_env_inplace ("OLDPWD=", 7, pwdvar);
162 array_needs_making = 0;
163 }
164
Chet Ramey495aee42011-11-22 19:11:26 -0500165 if (setpwd (dirname) == EXECUTION_FAILURE)
166 r = EXECUTION_FAILURE;
167 if (dirname == 0 && eflag)
168 r = EXECUTION_FAILURE;
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000169
Jari Aalto28ef6c32001-04-06 19:14:31 +0000170 if (dirname && dirname != the_current_working_directory)
171 free (dirname);
Jari Aaltob80f6442004-07-27 13:29:18 +0000172
Jari Aalto31859422009-01-12 13:36:28 +0000173 return (r);
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000174}
175
Jari Aalto7117c2d2002-07-17 14:10:11 +0000176/* Call get_working_directory to reset the value of
177 the_current_working_directory () */
178static char *
Jari Aaltob80f6442004-07-27 13:29:18 +0000179resetpwd (caller)
180 char *caller;
Jari Aalto7117c2d2002-07-17 14:10:11 +0000181{
182 char *tdir;
183
184 FREE (the_current_working_directory);
185 the_current_working_directory = (char *)NULL;
Jari Aaltob80f6442004-07-27 13:29:18 +0000186 tdir = get_working_directory (caller);
Jari Aalto7117c2d2002-07-17 14:10:11 +0000187 return (tdir);
188}
189
Chet Rameyac50fba2014-02-26 09:36:43 -0500190static int
191cdxattr (dir, ndirp)
192 char *dir; /* don't assume we can always free DIR */
193 char **ndirp; /* return new constructed directory name */
194{
195#if defined (O_XATTR)
196 int apfd, fd, r, e;
197 char buf[11+40+40]; /* construct new `fake' path for pwd */
198
199 apfd = openat (AT_FDCWD, dir, O_RDONLY|O_NONBLOCK);
200 if (apfd < 0)
201 return -1;
202 fd = openat (apfd, ".", O_XATTR);
203 e = errno;
204 close (apfd); /* ignore close error for now */
205 errno = e;
206 if (fd < 0)
207 return -1;
208 r = fchdir (fd); /* assume fchdir exists everywhere with O_XATTR */
209 if (r < 0)
210 {
211 close (fd);
212 return -1;
213 }
214 /* NFSv4 and ZFS extended attribute directories do not have names which are
215 visible in the standard Unix directory tree structure. To ensure we have
216 a valid name for $PWD, we synthesize one under /proc, but to keep that
217 path valid, we need to keep the file descriptor open as long as we are in
218 this directory. This imposes a certain structure on /proc. */
219 if (ndirp)
220 {
221 sprintf (buf, "/proc/%d/fd/%d", getpid(), fd);
222 *ndirp = savestring (buf);
223 }
224
225 if (xattrfd >= 0)
226 close (xattrfd);
227 xattrfd = fd;
228
229 return r;
230#else
231 return -1;
232#endif
233}
234
235/* Clean up the O_XATTR baggage. Currently only closes xattrfd */
236static void
237resetxattr ()
238{
239#if defined (O_XATTR)
240 if (xattrfd >= 0)
241 {
242 close (xattrfd);
243 xattrfd = -1;
244 }
245#else
246 xattrfd = -1; /* not strictly necessary */
247#endif
248}
249
Jari Aalto28ef6c32001-04-06 19:14:31 +0000250#define LCD_DOVARS 0x001
251#define LCD_DOSPELL 0x002
252#define LCD_PRINTPATH 0x004
Chet Ramey495aee42011-11-22 19:11:26 -0500253#define LCD_FREEDIRNAME 0x008
Jari Aalto28ef6c32001-04-06 19:14:31 +0000254
Jari Aalto726f6381996-08-26 18:22:31 +0000255/* This builtin is ultimately the way that all user-visible commands should
256 change the current working directory. It is called by cd_to_string (),
257 so the programming interface is simple, and it handles errors and
258 restrictions properly. */
259int
260cd_builtin (list)
261 WORD_LIST *list;
262{
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000263 char *dirname, *cdpath, *path, *temp;
Jari Aalto28ef6c32001-04-06 19:14:31 +0000264 int path_index, no_symlinks, opt, lflag;
Jari Aalto726f6381996-08-26 18:22:31 +0000265
266#if defined (RESTRICTED_SHELL)
267 if (restricted)
268 {
Jari Aalto7117c2d2002-07-17 14:10:11 +0000269 sh_restricted ((char *)NULL);
Jari Aalto726f6381996-08-26 18:22:31 +0000270 return (EXECUTION_FAILURE);
271 }
272#endif /* RESTRICTED_SHELL */
273
Chet Ramey495aee42011-11-22 19:11:26 -0500274 eflag = 0;
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000275 no_symlinks = no_symbolic_links;
Chet Rameyac50fba2014-02-26 09:36:43 -0500276 xattrflag = 0;
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000277 reset_internal_getopt ();
Chet Rameyac50fba2014-02-26 09:36:43 -0500278#if defined (O_XATTR)
279 while ((opt = internal_getopt (list, "eLP@")) != -1)
280#else
281 while ((opt = internal_getopt (list, "eLP")) != -1)
282#endif
Jari Aalto726f6381996-08-26 18:22:31 +0000283 {
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000284 switch (opt)
Jari Aalto726f6381996-08-26 18:22:31 +0000285 {
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000286 case 'P':
287 no_symlinks = 1;
288 break;
289 case 'L':
290 no_symlinks = 0;
291 break;
Chet Ramey495aee42011-11-22 19:11:26 -0500292 case 'e':
293 eflag = 1;
294 break;
Chet Rameyac50fba2014-02-26 09:36:43 -0500295#if defined (O_XATTR)
296 case '@':
297 xattrflag = 1;
298 break;
299#endif
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000300 default:
301 builtin_usage ();
Chet Rameyac50fba2014-02-26 09:36:43 -0500302 return (EX_USAGE);
Jari Aalto726f6381996-08-26 18:22:31 +0000303 }
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000304 }
305 list = loptend;
306
Jari Aalto28ef6c32001-04-06 19:14:31 +0000307 lflag = (cdable_vars ? LCD_DOVARS : 0) |
308 ((interactive && cdspelling) ? LCD_DOSPELL : 0);
Chet Ramey495aee42011-11-22 19:11:26 -0500309 if (eflag && no_symlinks == 0)
310 eflag = 0;
Jari Aalto28ef6c32001-04-06 19:14:31 +0000311
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000312 if (list == 0)
313 {
314 /* `cd' without arguments is equivalent to `cd $HOME' */
315 dirname = get_string_value ("HOME");
316
317 if (dirname == 0)
318 {
Jari Aaltob80f6442004-07-27 13:29:18 +0000319 builtin_error (_("HOME not set"));
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000320 return (EXECUTION_FAILURE);
321 }
Jari Aalto28ef6c32001-04-06 19:14:31 +0000322 lflag = 0;
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000323 }
Chet Rameyac50fba2014-02-26 09:36:43 -0500324#if defined (CD_COMPLAINS)
325 else if (list->next)
326 {
327 builtin_error (_("too many arguments"));
328 return (EXECUTION_FAILURE);
329 }
330#endif
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000331 else if (list->word->word[0] == '-' && list->word->word[1] == '\0')
332 {
333 /* This is `cd -', equivalent to `cd $OLDPWD' */
334 dirname = get_string_value ("OLDPWD");
335
Jari Aalto28ef6c32001-04-06 19:14:31 +0000336 if (dirname == 0)
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000337 {
Jari Aaltob80f6442004-07-27 13:29:18 +0000338 builtin_error (_("OLDPWD not set"));
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000339 return (EXECUTION_FAILURE);
340 }
Jari Aaltob80f6442004-07-27 13:29:18 +0000341#if 0
Jari Aalto28ef6c32001-04-06 19:14:31 +0000342 lflag = interactive ? LCD_PRINTPATH : 0;
Jari Aaltob80f6442004-07-27 13:29:18 +0000343#else
344 lflag = LCD_PRINTPATH; /* According to SUSv3 */
345#endif
Jari Aalto726f6381996-08-26 18:22:31 +0000346 }
Jari Aalto28ef6c32001-04-06 19:14:31 +0000347 else if (absolute_pathname (list->word->word))
348 dirname = list->word->word;
Jari Aalto31859422009-01-12 13:36:28 +0000349 else if (privileged_mode == 0 && (cdpath = get_string_value ("CDPATH")))
Jari Aalto726f6381996-08-26 18:22:31 +0000350 {
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000351 dirname = list->word->word;
Jari Aalto726f6381996-08-26 18:22:31 +0000352
Jari Aalto28ef6c32001-04-06 19:14:31 +0000353 /* Find directory in $CDPATH. */
354 path_index = 0;
355 while (path = extract_colon_unit (cdpath, &path_index))
Jari Aalto726f6381996-08-26 18:22:31 +0000356 {
Jari Aalto28ef6c32001-04-06 19:14:31 +0000357 /* OPT is 1 if the path element is non-empty */
358 opt = path[0] != '\0';
359 temp = sh_makepath (path, dirname, MP_DOTILDE);
360 free (path);
361
Chet Rameyac50fba2014-02-26 09:36:43 -0500362 if (change_to_directory (temp, no_symlinks, xattrflag))
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000363 {
Jari Aalto28ef6c32001-04-06 19:14:31 +0000364 /* POSIX.2 says that if a nonempty directory from CDPATH
365 is used to find the directory to change to, the new
366 directory name is echoed to stdout, whether or not
367 the shell is interactive. */
Jari Aaltob80f6442004-07-27 13:29:18 +0000368 if (opt && (path = no_symlinks ? temp : the_current_working_directory))
369 printf ("%s\n", path);
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000370
Jari Aalto28ef6c32001-04-06 19:14:31 +0000371 free (temp);
Jari Aalto95732b42005-12-07 14:08:12 +0000372#if 0
Jari Aalto28ef6c32001-04-06 19:14:31 +0000373 /* Posix.2 says that after using CDPATH, the resultant
374 value of $PWD will not contain `.' or `..'. */
375 return (bindpwd (posixly_correct || no_symlinks));
Jari Aalto95732b42005-12-07 14:08:12 +0000376#else
377 return (bindpwd (no_symlinks));
378#endif
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000379 }
Jari Aalto28ef6c32001-04-06 19:14:31 +0000380 else
381 free (temp);
Jari Aalto726f6381996-08-26 18:22:31 +0000382 }
383
Chet Rameyac50fba2014-02-26 09:36:43 -0500384#if 0
385 /* changed for bash-4.2 Posix cd description steps 5-6 */
Jari Aalto28ef6c32001-04-06 19:14:31 +0000386 /* POSIX.2 says that if `.' does not appear in $CDPATH, we don't
387 try the current directory, so we just punt now with an error
388 message if POSIXLY_CORRECT is non-zero. The check for cdpath[0]
389 is so we don't mistakenly treat a CDPATH value of "" as not
390 specifying the current directory. */
391 if (posixly_correct && cdpath[0])
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000392 {
Jari Aalto28ef6c32001-04-06 19:14:31 +0000393 builtin_error ("%s: %s", dirname, strerror (ENOENT));
394 return (EXECUTION_FAILURE);
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000395 }
Chet Ramey495aee42011-11-22 19:11:26 -0500396#endif
Jari Aalto28ef6c32001-04-06 19:14:31 +0000397 }
398 else
399 dirname = list->word->word;
Jari Aalto726f6381996-08-26 18:22:31 +0000400
Jari Aalto28ef6c32001-04-06 19:14:31 +0000401 /* When we get here, DIRNAME is the directory to change to. If we
402 chdir successfully, just return. */
Chet Rameyac50fba2014-02-26 09:36:43 -0500403 if (change_to_directory (dirname, no_symlinks, xattrflag))
Jari Aalto28ef6c32001-04-06 19:14:31 +0000404 {
405 if (lflag & LCD_PRINTPATH)
406 printf ("%s\n", dirname);
407 return (bindpwd (no_symlinks));
Jari Aalto726f6381996-08-26 18:22:31 +0000408 }
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000409
Jari Aalto28ef6c32001-04-06 19:14:31 +0000410 /* If the user requests it, then perhaps this is the name of
411 a shell variable, whose value contains the directory to
412 change to. */
413 if (lflag & LCD_DOVARS)
414 {
415 temp = get_string_value (dirname);
Chet Rameyac50fba2014-02-26 09:36:43 -0500416 if (temp && change_to_directory (temp, no_symlinks, xattrflag))
Jari Aalto28ef6c32001-04-06 19:14:31 +0000417 {
418 printf ("%s\n", temp);
419 return (bindpwd (no_symlinks));
420 }
421 }
422
423 /* If the user requests it, try to find a directory name similar in
424 spelling to the one requested, in case the user made a simple
425 typo. This is similar to the UNIX 8th and 9th Edition shells. */
426 if (lflag & LCD_DOSPELL)
427 {
Jari Aalto31859422009-01-12 13:36:28 +0000428 temp = dirspell (dirname);
Chet Rameyac50fba2014-02-26 09:36:43 -0500429 if (temp && change_to_directory (temp, no_symlinks, xattrflag))
Jari Aalto28ef6c32001-04-06 19:14:31 +0000430 {
431 printf ("%s\n", temp);
Chet Rameyac50fba2014-02-26 09:36:43 -0500432 free (temp);
Jari Aalto28ef6c32001-04-06 19:14:31 +0000433 return (bindpwd (no_symlinks));
434 }
435 else
436 FREE (temp);
437 }
438
439 builtin_error ("%s: %s", dirname, strerror (errno));
440 return (EXECUTION_FAILURE);
Jari Aalto726f6381996-08-26 18:22:31 +0000441}
442
443$BUILTIN pwd
444$FUNCTION pwd_builtin
Jari Aalto95732b42005-12-07 14:08:12 +0000445$SHORT_DOC pwd [-LP]
Jari Aalto31859422009-01-12 13:36:28 +0000446Print the name of the current working directory.
447
448Options:
449 -L print the value of $PWD if it names the current working
450 directory
451 -P print the physical directory, without any symbolic links
452
453By default, `pwd' behaves as if `-L' were specified.
454
455Exit Status:
456Returns 0 unless an invalid option is given or the current directory
457cannot be read.
Jari Aalto726f6381996-08-26 18:22:31 +0000458$END
459
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000460/* Non-zero means that pwd always prints the physical directory, without
461 symbolic links. */
Jari Aalto726f6381996-08-26 18:22:31 +0000462static int verbatim_pwd;
463
464/* Print the name of the current working directory. */
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000465int
Jari Aalto726f6381996-08-26 18:22:31 +0000466pwd_builtin (list)
467 WORD_LIST *list;
468{
Jari Aalto28ef6c32001-04-06 19:14:31 +0000469 char *directory;
Jari Aalto95732b42005-12-07 14:08:12 +0000470 int opt, pflag;
Jari Aalto726f6381996-08-26 18:22:31 +0000471
Jari Aalto726f6381996-08-26 18:22:31 +0000472 verbatim_pwd = no_symbolic_links;
Jari Aalto95732b42005-12-07 14:08:12 +0000473 pflag = 0;
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000474 reset_internal_getopt ();
475 while ((opt = internal_getopt (list, "LP")) != -1)
476 {
477 switch (opt)
478 {
479 case 'P':
Jari Aalto95732b42005-12-07 14:08:12 +0000480 verbatim_pwd = pflag = 1;
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000481 break;
482 case 'L':
483 verbatim_pwd = 0;
484 break;
485 default:
486 builtin_usage ();
Chet Rameyac50fba2014-02-26 09:36:43 -0500487 return (EX_USAGE);
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000488 }
489 }
490 list = loptend;
Jari Aalto726f6381996-08-26 18:22:31 +0000491
Jari Aalto28ef6c32001-04-06 19:14:31 +0000492#define tcwd the_current_working_directory
Jari Aalto726f6381996-08-26 18:22:31 +0000493
Jari Aalto28ef6c32001-04-06 19:14:31 +0000494 directory = tcwd ? (verbatim_pwd ? sh_physpath (tcwd, 0) : tcwd)
495 : get_working_directory ("pwd");
Jari Aaltob80f6442004-07-27 13:29:18 +0000496
497 /* Try again using getcwd() if canonicalization fails (for instance, if
498 the file system has changed state underneath bash). */
Jari Aalto95732b42005-12-07 14:08:12 +0000499 if ((tcwd && directory == 0) ||
500 (posixly_correct && same_file (".", tcwd, (struct stat *)0, (struct stat *)0) == 0))
Chet Rameyac50fba2014-02-26 09:36:43 -0500501 {
502 if (directory && directory != tcwd)
503 free (directory);
504 directory = resetpwd ("pwd");
505 }
Jari Aaltob80f6442004-07-27 13:29:18 +0000506
Jari Aalto28ef6c32001-04-06 19:14:31 +0000507#undef tcwd
Jari Aalto726f6381996-08-26 18:22:31 +0000508
509 if (directory)
510 {
Chet Ramey495aee42011-11-22 19:11:26 -0500511 opt = EXECUTION_SUCCESS;
Jari Aalto726f6381996-08-26 18:22:31 +0000512 printf ("%s\n", directory);
Jari Aalto95732b42005-12-07 14:08:12 +0000513 /* This is dumb but posix-mandated. */
514 if (posixly_correct && pflag)
Chet Ramey495aee42011-11-22 19:11:26 -0500515 opt = setpwd (directory);
Jari Aalto28ef6c32001-04-06 19:14:31 +0000516 if (directory != the_current_working_directory)
517 free (directory);
Chet Ramey495aee42011-11-22 19:11:26 -0500518 return (sh_chkwrite (opt));
Jari Aalto726f6381996-08-26 18:22:31 +0000519 }
520 else
521 return (EXECUTION_FAILURE);
522}
523
Jari Aalto726f6381996-08-26 18:22:31 +0000524/* Do the work of changing to the directory NEWDIR. Handle symbolic
Jari Aalto28ef6c32001-04-06 19:14:31 +0000525 link following, etc. This function *must* return with
526 the_current_working_directory either set to NULL (in which case
527 getcwd() will eventually be called), or set to a string corresponding
528 to the working directory. Return 1 on success, 0 on failure. */
Jari Aalto726f6381996-08-26 18:22:31 +0000529
530static int
Chet Rameyac50fba2014-02-26 09:36:43 -0500531change_to_directory (newdir, nolinks, xattr)
Jari Aalto726f6381996-08-26 18:22:31 +0000532 char *newdir;
Chet Rameyac50fba2014-02-26 09:36:43 -0500533 int nolinks, xattr;
Jari Aalto726f6381996-08-26 18:22:31 +0000534{
Chet Rameyac50fba2014-02-26 09:36:43 -0500535 char *t, *tdir, *ndir;
Jari Aalto95732b42005-12-07 14:08:12 +0000536 int err, canon_failed, r, ndlen, dlen;
Jari Aalto726f6381996-08-26 18:22:31 +0000537
Jari Aalto28ef6c32001-04-06 19:14:31 +0000538 tdir = (char *)NULL;
539
540 if (the_current_working_directory == 0)
Jari Aalto726f6381996-08-26 18:22:31 +0000541 {
Jari Aalto28ef6c32001-04-06 19:14:31 +0000542 t = get_working_directory ("chdir");
543 FREE (t);
544 }
Jari Aalto726f6381996-08-26 18:22:31 +0000545
Jari Aalto28ef6c32001-04-06 19:14:31 +0000546 t = make_absolute (newdir, the_current_working_directory);
Jari Aalto726f6381996-08-26 18:22:31 +0000547
Jari Aalto28ef6c32001-04-06 19:14:31 +0000548 /* TDIR is either the canonicalized absolute pathname of NEWDIR
549 (nolinks == 0) or the absolute physical pathname of NEWDIR
550 (nolinks != 0). */
551 tdir = nolinks ? sh_physpath (t, 0)
552 : sh_canonpath (t, PATH_CHECKDOTDOT|PATH_CHECKEXISTS);
Jari Aalto726f6381996-08-26 18:22:31 +0000553
Jari Aalto95732b42005-12-07 14:08:12 +0000554 ndlen = strlen (newdir);
555 dlen = strlen (t);
556
Jari Aalto28ef6c32001-04-06 19:14:31 +0000557 /* Use the canonicalized version of NEWDIR, or, if canonicalization
558 failed, use the non-canonical form. */
Jari Aalto7117c2d2002-07-17 14:10:11 +0000559 canon_failed = 0;
Jari Aalto28ef6c32001-04-06 19:14:31 +0000560 if (tdir && *tdir)
561 free (t);
562 else
563 {
564 FREE (tdir);
565 tdir = t;
Jari Aalto7117c2d2002-07-17 14:10:11 +0000566 canon_failed = 1;
567 }
568
569 /* In POSIX mode, if we're resolving symlinks logically and sh_canonpath
570 returns NULL (because it checks the path, it will return NULL if the
571 resolved path doesn't exist), fail immediately. */
Jari Aalto95732b42005-12-07 14:08:12 +0000572 if (posixly_correct && nolinks == 0 && canon_failed && (errno != ENAMETOOLONG || ndlen > PATH_MAX))
Jari Aalto7117c2d2002-07-17 14:10:11 +0000573 {
Jari Aaltob80f6442004-07-27 13:29:18 +0000574#if defined ENAMETOOLONG
575 if (errno != ENOENT && errno != ENAMETOOLONG)
576#else
577 if (errno != ENOENT)
578#endif
579 errno = ENOTDIR;
Jari Aalto95732b42005-12-07 14:08:12 +0000580 free (tdir);
Jari Aalto7117c2d2002-07-17 14:10:11 +0000581 return (0);
Jari Aalto28ef6c32001-04-06 19:14:31 +0000582 }
Jari Aalto726f6381996-08-26 18:22:31 +0000583
Chet Rameyac50fba2014-02-26 09:36:43 -0500584#if defined (O_XATTR)
585 if (xattrflag)
586 {
587 r = cdxattr (nolinks ? newdir : tdir, &ndir);
588 if (r >= 0)
589 {
590 canon_failed = 0;
591 free (tdir);
592 tdir = ndir;
593 }
594 else
595 {
596 err = errno;
597 free (tdir);
598 errno = err;
599 return (0); /* no xattr */
600 }
601 }
602 else
603#endif
604 {
605 r = chdir (nolinks ? newdir : tdir);
606 if (r >= 0)
607 resetxattr ();
608 }
609
Jari Aalto28ef6c32001-04-06 19:14:31 +0000610 /* If the chdir succeeds, update the_current_working_directory. */
Chet Rameyac50fba2014-02-26 09:36:43 -0500611 if (r == 0)
Jari Aalto28ef6c32001-04-06 19:14:31 +0000612 {
Jari Aalto7117c2d2002-07-17 14:10:11 +0000613 /* If canonicalization failed, but the chdir succeeded, reset the
614 shell's idea of the_current_working_directory. */
615 if (canon_failed)
Jari Aalto7117c2d2002-07-17 14:10:11 +0000616 {
Jari Aaltob80f6442004-07-27 13:29:18 +0000617 t = resetpwd ("cd");
618 if (t == 0)
619 set_working_directory (tdir);
Chet Rameyac50fba2014-02-26 09:36:43 -0500620 else
621 free (t);
Jari Aalto7117c2d2002-07-17 14:10:11 +0000622 }
Jari Aaltob80f6442004-07-27 13:29:18 +0000623 else
624 set_working_directory (tdir);
Jari Aalto7117c2d2002-07-17 14:10:11 +0000625
Jari Aalto95732b42005-12-07 14:08:12 +0000626 free (tdir);
Jari Aalto28ef6c32001-04-06 19:14:31 +0000627 return (1);
628 }
Jari Aalto726f6381996-08-26 18:22:31 +0000629
Jari Aalto28ef6c32001-04-06 19:14:31 +0000630 /* We failed to change to the appropriate directory name. If we tried
631 what the user passed (nolinks != 0), punt now. */
632 if (nolinks)
Jari Aalto95732b42005-12-07 14:08:12 +0000633 {
634 free (tdir);
635 return (0);
636 }
Jari Aalto726f6381996-08-26 18:22:31 +0000637
Jari Aalto28ef6c32001-04-06 19:14:31 +0000638 err = errno;
Jari Aalto726f6381996-08-26 18:22:31 +0000639
Jari Aalto28ef6c32001-04-06 19:14:31 +0000640 /* We're not in physical mode (nolinks == 0), but we failed to change to
641 the canonicalized directory name (TDIR). Try what the user passed
642 verbatim. If we succeed, reinitialize the_current_working_directory. */
643 if (chdir (newdir) == 0)
644 {
Jari Aaltob80f6442004-07-27 13:29:18 +0000645 t = resetpwd ("cd");
646 if (t == 0)
647 set_working_directory (tdir);
648 else
649 free (t);
Jari Aalto726f6381996-08-26 18:22:31 +0000650
Jari Aaltob80f6442004-07-27 13:29:18 +0000651 r = 1;
Jari Aalto726f6381996-08-26 18:22:31 +0000652 }
653 else
Jari Aalto28ef6c32001-04-06 19:14:31 +0000654 {
655 errno = err;
Jari Aaltob80f6442004-07-27 13:29:18 +0000656 r = 0;
Jari Aalto28ef6c32001-04-06 19:14:31 +0000657 }
Jari Aaltob80f6442004-07-27 13:29:18 +0000658
659 free (tdir);
660 return r;
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000661}