| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | This file is cd.def, from which is created cd.c.  It implements the | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | builtins "cd" and "pwd" in Bash. | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-15 16:59:08 -04:00
										 |  |  | Copyright (C) 1987-2016 Free Software Foundation, Inc. | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | This file is part of GNU Bash, the Bourne Again SHell. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  | Bash is free software: you can redistribute it and/or modify | 
					
						
							|  |  |  | it under the terms of the GNU General Public License as published by | 
					
						
							|  |  |  | the Free Software Foundation, either version 3 of the License, or | 
					
						
							|  |  |  | (at your option) any later version. | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  | Bash is distributed in the hope that it will be useful, | 
					
						
							|  |  |  | but WITHOUT ANY WARRANTY; without even the implied warranty of | 
					
						
							|  |  |  | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
					
						
							|  |  |  | GNU General Public License for more details. | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  | You should have received a copy of the GNU General Public License | 
					
						
							|  |  |  | along with Bash.  If not, see <http://www.gnu.org/licenses/>. | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | $PRODUCES cd.c | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | #include <config.h> | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | #if defined (HAVE_UNISTD_H) | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  | #  ifdef _MINIX | 
					
						
							|  |  |  | #    include <sys/types.h> | 
					
						
							|  |  |  | #  endif | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | #  include <unistd.h> | 
					
						
							|  |  |  | #endif | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "../bashtypes.h" | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  | #include "posixdir.h" | 
					
						
							|  |  |  | #include "posixstat.h" | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  | #if defined (HAVE_SYS_PARAM_H) | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | #include <sys/param.h> | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  | #endif | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  | #include <fcntl.h> | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | #include <stdio.h> | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "../bashansi.h" | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  | #include "../bashintl.h" | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | #include <errno.h> | 
					
						
							|  |  |  | #include <tilde/tilde.h> | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "../shell.h" | 
					
						
							|  |  |  | #include "../flags.h" | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  | #include "maxpath.h" | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | #include "common.h" | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | #include "bashgetopt.h" | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | #if !defined (errno) | 
					
						
							|  |  |  | extern int errno; | 
					
						
							|  |  |  | #endif /* !errno */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  | extern int posixly_correct; | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  | extern int array_needs_making; | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  | extern const char * const bash_getcwd_errstr; | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  | static int bindpwd __P((int)); | 
					
						
							| 
									
										
										
										
											2011-11-22 19:11:26 -05:00
										 |  |  | static int setpwd __P((char *)); | 
					
						
							| 
									
										
										
										
											2006-10-10 14:15:34 +00:00
										 |  |  | static char *resetpwd __P((char *)); | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  | static int change_to_directory __P((char *, int, int)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int cdxattr __P((char *, char **)); | 
					
						
							|  |  |  | static void resetxattr __P((void)); | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  | /* Change this to 1 to get cd spelling correction by default. */ | 
					
						
							|  |  |  | int cdspelling = 0; | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | int cdable_vars; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-11-22 19:11:26 -05:00
										 |  |  | static int eflag;	/* file scope so bindpwd() can see it */ | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  | static int xattrflag;	/* O_XATTR support for openat */ | 
					
						
							|  |  |  | static int xattrfd = -1; | 
					
						
							| 
									
										
										
										
											2011-11-22 19:11:26 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | $BUILTIN cd | 
					
						
							|  |  |  | $FUNCTION cd_builtin | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  | $SHORT_DOC cd [-L|[-P [-e]] [-@]] [dir] | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  | Change the shell working directory. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Change the current directory to DIR.  The default DIR is the value of the | 
					
						
							|  |  |  | HOME shell variable. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The variable CDPATH defines the search path for the directory containing | 
					
						
							|  |  |  | DIR.  Alternative directory names in CDPATH are separated by a colon (:). | 
					
						
							|  |  |  | A null directory name is the same as the current directory.  If DIR begins | 
					
						
							|  |  |  | with a slash (/), then CDPATH is not used. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | If the directory is not found, and the shell option `cdable_vars' is set, | 
					
						
							|  |  |  | the word is assumed to be  a variable name.  If that variable has a value, | 
					
						
							|  |  |  | its value is used for DIR. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Options: | 
					
						
							| 
									
										
										
										
											2016-09-15 16:59:08 -04:00
										 |  |  |   -L	force symbolic links to be followed: resolve symbolic | 
					
						
							|  |  |  | 		links in DIR after processing instances of `..' | 
					
						
							|  |  |  |   -P	use the physical directory structure without following | 
					
						
							|  |  |  | 		symbolic links: resolve symbolic links in DIR before | 
					
						
							|  |  |  | 		processing instances of `..' | 
					
						
							|  |  |  |   -e	if the -P option is supplied, and the current working | 
					
						
							|  |  |  | 		directory cannot be determined successfully, exit with | 
					
						
							|  |  |  | 		a non-zero status | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  | #if defined (O_XATTR) | 
					
						
							| 
									
										
										
										
											2016-09-15 16:59:08 -04:00
										 |  |  |   -@	on systems that support it, present a file with extended | 
					
						
							|  |  |  | 		attributes as a directory containing the file attributes | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  | #endif | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | The default is to follow symbolic links, as if `-L' were specified. | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  | `..' is processed by removing the immediately previous pathname component | 
					
						
							|  |  |  | back to a slash or the beginning of DIR. | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | Exit Status: | 
					
						
							| 
									
										
										
										
											2011-11-22 19:11:26 -05:00
										 |  |  | Returns 0 if the directory is changed, and if $PWD is set successfully when | 
					
						
							|  |  |  | -P is used; non-zero otherwise. | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | $END | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  | /* Just set $PWD, don't change OLDPWD.  Used by `pwd -P' in posix mode. */ | 
					
						
							| 
									
										
										
										
											2011-11-22 19:11:26 -05:00
										 |  |  | static int | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  | setpwd (dirname) | 
					
						
							|  |  |  |      char *dirname; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   int old_anm; | 
					
						
							|  |  |  |   SHELL_VAR *tvar; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   old_anm = array_needs_making; | 
					
						
							|  |  |  |   tvar = bind_variable ("PWD", dirname ? dirname : "", 0); | 
					
						
							| 
									
										
										
										
											2011-11-22 19:11:26 -05:00
										 |  |  |   if (tvar && readonly_p (tvar)) | 
					
						
							|  |  |  |     return EXECUTION_FAILURE; | 
					
						
							|  |  |  |   if (tvar && old_anm == 0 && array_needs_making && exported_p (tvar)) | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  |     { | 
					
						
							|  |  |  |       update_export_env_inplace ("PWD=", 4, dirname ? dirname : ""); | 
					
						
							|  |  |  |       array_needs_making = 0; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2011-11-22 19:11:26 -05:00
										 |  |  |   return EXECUTION_SUCCESS; | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | static int | 
					
						
							|  |  |  | bindpwd (no_symlinks) | 
					
						
							|  |  |  |      int no_symlinks; | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  |   char *dirname, *pwdvar; | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  |   int old_anm, r; | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  |   SHELL_VAR *tvar; | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  |   r = sh_chkwrite (EXECUTION_SUCCESS); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  | #define tcwd the_current_working_directory | 
					
						
							|  |  |  |   dirname = tcwd ? (no_symlinks ? sh_physpath (tcwd, 0) : tcwd) | 
					
						
							|  |  |  |   		 : get_working_directory ("cd"); | 
					
						
							|  |  |  | #undef tcwd | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  |   old_anm = array_needs_making; | 
					
						
							| 
									
										
										
										
											1999-02-19 17:11:39 +00:00
										 |  |  |   pwdvar = get_string_value ("PWD"); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  |   tvar = bind_variable ("OLDPWD", pwdvar, 0); | 
					
						
							| 
									
										
										
										
											2011-11-22 19:11:26 -05:00
										 |  |  |   if (tvar && readonly_p (tvar)) | 
					
						
							|  |  |  |     r = EXECUTION_FAILURE; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1999-02-19 17:11:39 +00:00
										 |  |  |   if (old_anm == 0 && array_needs_making && exported_p (tvar)) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       update_export_env_inplace ("OLDPWD=", 7, pwdvar); | 
					
						
							|  |  |  |       array_needs_making = 0; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-11-22 19:11:26 -05:00
										 |  |  |   if (setpwd (dirname) == EXECUTION_FAILURE) | 
					
						
							|  |  |  |     r = EXECUTION_FAILURE; | 
					
						
							|  |  |  |   if (dirname == 0 && eflag) | 
					
						
							|  |  |  |     r = EXECUTION_FAILURE; | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  |   if (dirname && dirname != the_current_working_directory) | 
					
						
							|  |  |  |     free (dirname); | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  |   return (r); | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | /* Call get_working_directory to reset the value of | 
					
						
							|  |  |  |    the_current_working_directory () */ | 
					
						
							|  |  |  | static char * | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  | resetpwd (caller) | 
					
						
							|  |  |  |      char *caller; | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | { | 
					
						
							|  |  |  |   char *tdir; | 
					
						
							|  |  |  |        | 
					
						
							|  |  |  |   FREE (the_current_working_directory); | 
					
						
							|  |  |  |   the_current_working_directory = (char *)NULL; | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  |   tdir = get_working_directory (caller); | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   return (tdir); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  | static int | 
					
						
							|  |  |  | cdxattr (dir, ndirp) | 
					
						
							|  |  |  |      char *dir;		/* don't assume we can always free DIR */ | 
					
						
							|  |  |  |      char **ndirp;	/* return new constructed directory name */ | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | #if defined (O_XATTR) | 
					
						
							|  |  |  |   int apfd, fd, r, e; | 
					
						
							|  |  |  |   char buf[11+40+40];	/* construct new `fake' path for pwd */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   apfd = openat (AT_FDCWD, dir, O_RDONLY|O_NONBLOCK); | 
					
						
							|  |  |  |   if (apfd < 0) | 
					
						
							|  |  |  |     return -1; | 
					
						
							|  |  |  |   fd = openat (apfd, ".", O_XATTR); | 
					
						
							|  |  |  |   e = errno; | 
					
						
							|  |  |  |   close (apfd);		/* ignore close error for now */ | 
					
						
							|  |  |  |   errno = e; | 
					
						
							|  |  |  |   if (fd < 0) | 
					
						
							|  |  |  |     return -1; | 
					
						
							|  |  |  |   r = fchdir (fd);	/* assume fchdir exists everywhere with O_XATTR */ | 
					
						
							|  |  |  |   if (r < 0) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       close (fd); | 
					
						
							|  |  |  |       return -1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   /* NFSv4 and ZFS extended attribute directories do not have names which are | 
					
						
							|  |  |  |      visible in the standard Unix directory tree structure.  To ensure we have | 
					
						
							|  |  |  |      a valid name for $PWD, we synthesize one under /proc, but to keep that | 
					
						
							|  |  |  |      path valid, we need to keep the file descriptor open as long as we are in | 
					
						
							|  |  |  |      this directory.  This imposes a certain structure on /proc. */ | 
					
						
							|  |  |  |   if (ndirp) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       sprintf (buf, "/proc/%d/fd/%d", getpid(), fd); | 
					
						
							|  |  |  |       *ndirp = savestring (buf); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (xattrfd >= 0) | 
					
						
							|  |  |  |     close (xattrfd); | 
					
						
							|  |  |  |   xattrfd = fd;   | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return r; | 
					
						
							|  |  |  | #else | 
					
						
							|  |  |  |   return -1; | 
					
						
							|  |  |  | #endif | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Clean up the O_XATTR baggage.  Currently only closes xattrfd */ | 
					
						
							|  |  |  | static void | 
					
						
							|  |  |  | resetxattr () | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | #if defined (O_XATTR) | 
					
						
							|  |  |  |   if (xattrfd >= 0) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       close (xattrfd); | 
					
						
							|  |  |  |       xattrfd = -1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | #else | 
					
						
							|  |  |  |   xattrfd = -1;		/* not strictly necessary */ | 
					
						
							|  |  |  | #endif | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  | #define LCD_DOVARS	0x001 | 
					
						
							|  |  |  | #define LCD_DOSPELL	0x002 | 
					
						
							|  |  |  | #define LCD_PRINTPATH	0x004 | 
					
						
							| 
									
										
										
										
											2011-11-22 19:11:26 -05:00
										 |  |  | #define LCD_FREEDIRNAME	0x008 | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | /* This builtin is ultimately the way that all user-visible commands should | 
					
						
							|  |  |  |    change the current working directory.  It is called by cd_to_string (), | 
					
						
							|  |  |  |    so the programming interface is simple, and it handles errors and | 
					
						
							|  |  |  |    restrictions properly. */ | 
					
						
							|  |  |  | int | 
					
						
							|  |  |  | cd_builtin (list) | 
					
						
							|  |  |  |      WORD_LIST *list; | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |   char *dirname, *cdpath, *path, *temp; | 
					
						
							| 
									
										
										
										
											2016-09-15 16:59:08 -04:00
										 |  |  |   int path_index, no_symlinks, opt, lflag, e; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | #if defined (RESTRICTED_SHELL) | 
					
						
							|  |  |  |   if (restricted) | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |       sh_restricted ((char *)NULL); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |       return (EXECUTION_FAILURE); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | #endif /* RESTRICTED_SHELL */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-11-22 19:11:26 -05:00
										 |  |  |   eflag = 0; | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |   no_symlinks = no_symbolic_links; | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  |   xattrflag = 0; | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |   reset_internal_getopt (); | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  | #if defined (O_XATTR) | 
					
						
							|  |  |  |   while ((opt = internal_getopt (list, "eLP@")) != -1) | 
					
						
							|  |  |  | #else | 
					
						
							|  |  |  |   while ((opt = internal_getopt (list, "eLP")) != -1) | 
					
						
							|  |  |  | #endif | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |       switch (opt) | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 	case 'P': | 
					
						
							|  |  |  | 	  no_symlinks = 1; | 
					
						
							|  |  |  | 	  break; | 
					
						
							|  |  |  | 	case 'L': | 
					
						
							|  |  |  | 	  no_symlinks = 0; | 
					
						
							|  |  |  | 	  break; | 
					
						
							| 
									
										
										
										
											2011-11-22 19:11:26 -05:00
										 |  |  | 	case 'e': | 
					
						
							|  |  |  | 	  eflag = 1; | 
					
						
							|  |  |  | 	  break; | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  | #if defined (O_XATTR) | 
					
						
							|  |  |  | 	case '@': | 
					
						
							|  |  |  | 	  xattrflag = 1; | 
					
						
							|  |  |  | 	  break; | 
					
						
							|  |  |  | #endif | 
					
						
							| 
									
										
										
										
											2016-09-15 16:59:08 -04:00
										 |  |  | 	CASE_HELPOPT; | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 	default: | 
					
						
							|  |  |  | 	  builtin_usage (); | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  | 	  return (EX_USAGE); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |   list = loptend; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  |   lflag = (cdable_vars ? LCD_DOVARS : 0) | | 
					
						
							|  |  |  | 	  ((interactive && cdspelling) ? LCD_DOSPELL : 0); | 
					
						
							| 
									
										
										
										
											2011-11-22 19:11:26 -05:00
										 |  |  |   if (eflag && no_symlinks == 0) | 
					
						
							|  |  |  |     eflag = 0; | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |   if (list == 0) | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |       /* `cd' without arguments is equivalent to `cd $HOME' */ | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |       dirname = get_string_value ("HOME"); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |       if (dirname == 0) | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  | 	  builtin_error (_("HOME not set")); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 	  return (EXECUTION_FAILURE); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  |       lflag = 0; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  | #if defined (CD_COMPLAINS) | 
					
						
							|  |  |  |   else if (list->next) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       builtin_error (_("too many arguments")); | 
					
						
							|  |  |  |       return (EXECUTION_FAILURE); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2016-09-15 16:59:08 -04:00
										 |  |  | #endif | 
					
						
							|  |  |  | #if 0 | 
					
						
							|  |  |  |   else if (list->word->word[0] == '\0') | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       builtin_error (_("null directory")); | 
					
						
							|  |  |  |       return (EXECUTION_FAILURE); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  | #endif | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |   else if (list->word->word[0] == '-' && list->word->word[1] == '\0') | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |       /* This is `cd -', equivalent to `cd $OLDPWD' */ | 
					
						
							|  |  |  |       dirname = get_string_value ("OLDPWD"); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  |       if (dirname == 0) | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  | 	  builtin_error (_("OLDPWD not set")); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 	  return (EXECUTION_FAILURE); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  | #if 0 | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  |       lflag = interactive ? LCD_PRINTPATH : 0; | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  | #else | 
					
						
							|  |  |  |       lflag = LCD_PRINTPATH;		/* According to SUSv3 */ | 
					
						
							|  |  |  | #endif | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  |   else if (absolute_pathname (list->word->word)) | 
					
						
							|  |  |  |     dirname = list->word->word; | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  |   else if (privileged_mode == 0 && (cdpath = get_string_value ("CDPATH"))) | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |       dirname = list->word->word; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  |       /* Find directory in $CDPATH. */ | 
					
						
							|  |  |  |       path_index = 0; | 
					
						
							|  |  |  |       while (path = extract_colon_unit (cdpath, &path_index)) | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  | 	  /* OPT is 1 if the path element is non-empty */ | 
					
						
							|  |  |  | 	  opt = path[0] != '\0'; | 
					
						
							|  |  |  | 	  temp = sh_makepath (path, dirname, MP_DOTILDE); | 
					
						
							|  |  |  | 	  free (path); | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  | 	  if (change_to_directory (temp, no_symlinks, xattrflag)) | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  | 	    { | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  | 	      /* POSIX.2 says that if a nonempty directory from CDPATH | 
					
						
							|  |  |  | 		 is used to find the directory to change to, the new | 
					
						
							|  |  |  | 		 directory name is echoed to stdout, whether or not | 
					
						
							|  |  |  | 		 the shell is interactive. */ | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  | 	      if (opt && (path = no_symlinks ? temp : the_current_working_directory)) | 
					
						
							|  |  |  | 		printf ("%s\n", path); | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	      free (temp); | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  | #if 0 | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  | 	      /* Posix.2 says that after using CDPATH, the resultant | 
					
						
							|  |  |  | 		 value of $PWD will not contain `.' or `..'. */ | 
					
						
							|  |  |  | 	      return (bindpwd (posixly_correct || no_symlinks)); | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  | #else | 
					
						
							|  |  |  | 	      return (bindpwd (no_symlinks)); | 
					
						
							|  |  |  | #endif | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  | 	    } | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  | 	  else | 
					
						
							|  |  |  | 	    free (temp); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  | #if 0 | 
					
						
							|  |  |  |       /* changed for bash-4.2 Posix cd description steps 5-6 */ | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  |       /* POSIX.2 says that if `.' does not appear in $CDPATH, we don't | 
					
						
							|  |  |  | 	 try the current directory, so we just punt now with an error | 
					
						
							|  |  |  | 	 message if POSIXLY_CORRECT is non-zero.  The check for cdpath[0] | 
					
						
							|  |  |  | 	 is so we don't mistakenly treat a CDPATH value of "" as not | 
					
						
							|  |  |  | 	 specifying the current directory. */ | 
					
						
							|  |  |  |       if (posixly_correct && cdpath[0]) | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  | 	  builtin_error ("%s: %s", dirname, strerror (ENOENT)); | 
					
						
							|  |  |  | 	  return (EXECUTION_FAILURE); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2011-11-22 19:11:26 -05:00
										 |  |  | #endif | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  |     } | 
					
						
							|  |  |  |   else | 
					
						
							|  |  |  |     dirname = list->word->word; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* When we get here, DIRNAME is the directory to change to.  If we | 
					
						
							|  |  |  |      chdir successfully, just return. */ | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  |   if (change_to_directory (dirname, no_symlinks, xattrflag)) | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  |     { | 
					
						
							|  |  |  |       if (lflag & LCD_PRINTPATH) | 
					
						
							|  |  |  | 	printf ("%s\n", dirname); | 
					
						
							|  |  |  |       return (bindpwd (no_symlinks)); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  |   /* If the user requests it, then perhaps this is the name of | 
					
						
							|  |  |  |      a shell variable, whose value contains the directory to | 
					
						
							|  |  |  |      change to. */ | 
					
						
							|  |  |  |   if (lflag & LCD_DOVARS) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       temp = get_string_value (dirname); | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  |       if (temp && change_to_directory (temp, no_symlinks, xattrflag)) | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  | 	  printf ("%s\n", temp); | 
					
						
							|  |  |  | 	  return (bindpwd (no_symlinks)); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  |   /* If the user requests it, try to find a directory name similar in | 
					
						
							|  |  |  |      spelling to the one requested, in case the user made a simple | 
					
						
							|  |  |  |      typo.  This is similar to the UNIX 8th and 9th Edition shells. */ | 
					
						
							|  |  |  |   if (lflag & LCD_DOSPELL) | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  |       temp = dirspell (dirname); | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  |       if (temp && change_to_directory (temp, no_symlinks, xattrflag)) | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  | 	{ | 
					
						
							|  |  |  | 	  printf ("%s\n", temp); | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  | 	  free (temp); | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  | 	  return (bindpwd (no_symlinks)); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  |       else | 
					
						
							|  |  |  | 	FREE (temp); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-15 16:59:08 -04:00
										 |  |  |   e = errno; | 
					
						
							|  |  |  |   temp = printable_filename (dirname, 0); | 
					
						
							|  |  |  |   builtin_error ("%s: %s", temp, strerror (e)); | 
					
						
							|  |  |  |   if (temp != dirname) | 
					
						
							|  |  |  |     free (temp); | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  |   return (EXECUTION_FAILURE); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | $BUILTIN pwd | 
					
						
							|  |  |  | $FUNCTION pwd_builtin | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  | $SHORT_DOC pwd [-LP] | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  | Print the name of the current working directory. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Options: | 
					
						
							|  |  |  |   -L	print the value of $PWD if it names the current working | 
					
						
							| 
									
										
										
										
											2016-09-15 16:59:08 -04:00
										 |  |  | 		directory | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  |   -P	print the physical directory, without any symbolic links | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | By default, `pwd' behaves as if `-L' were specified. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Exit Status: | 
					
						
							|  |  |  | Returns 0 unless an invalid option is given or the current directory | 
					
						
							|  |  |  | cannot be read. | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | $END | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | /* Non-zero means that pwd always prints the physical directory, without | 
					
						
							|  |  |  |    symbolic links. */ | 
					
						
							|  |  |  | static int verbatim_pwd; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Print the name of the current working directory. */ | 
					
						
							|  |  |  | int | 
					
						
							|  |  |  | pwd_builtin (list) | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |      WORD_LIST *list; | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  |   char *directory; | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  |   int opt, pflag; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |   verbatim_pwd = no_symbolic_links; | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  |   pflag = 0; | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |   reset_internal_getopt (); | 
					
						
							|  |  |  |   while ((opt = internal_getopt (list, "LP")) != -1) | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |       switch (opt) | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 	case 'P': | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  | 	  verbatim_pwd = pflag = 1; | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 	  break; | 
					
						
							|  |  |  | 	case 'L': | 
					
						
							|  |  |  | 	  verbatim_pwd = 0; | 
					
						
							|  |  |  | 	  break; | 
					
						
							| 
									
										
										
										
											2016-09-15 16:59:08 -04:00
										 |  |  | 	CASE_HELPOPT; | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 	default: | 
					
						
							|  |  |  | 	  builtin_usage (); | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  | 	  return (EX_USAGE); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |   list = loptend; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  | #define tcwd the_current_working_directory | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  |   directory = tcwd ? (verbatim_pwd ? sh_physpath (tcwd, 0) : tcwd) | 
					
						
							|  |  |  | 		   : get_working_directory ("pwd"); | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   /* Try again using getcwd() if canonicalization fails (for instance, if | 
					
						
							|  |  |  |      the file system has changed state underneath bash). */ | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  |   if ((tcwd && directory == 0) || | 
					
						
							|  |  |  |       (posixly_correct && same_file (".", tcwd, (struct stat *)0, (struct stat *)0) == 0)) | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  |     { | 
					
						
							|  |  |  |       if (directory && directory != tcwd) | 
					
						
							|  |  |  |         free (directory); | 
					
						
							|  |  |  |       directory = resetpwd ("pwd"); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  | #undef tcwd | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |   if (directory) | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2011-11-22 19:11:26 -05:00
										 |  |  |       opt = EXECUTION_SUCCESS; | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |       printf ("%s\n", directory); | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  |       /* This is dumb but posix-mandated. */ | 
					
						
							|  |  |  |       if (posixly_correct && pflag) | 
					
						
							| 
									
										
										
										
											2011-11-22 19:11:26 -05:00
										 |  |  | 	opt = setpwd (directory); | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  |       if (directory != the_current_working_directory) | 
					
						
							|  |  |  | 	free (directory); | 
					
						
							| 
									
										
										
										
											2011-11-22 19:11:26 -05:00
										 |  |  |       return (sh_chkwrite (opt)); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |   else | 
					
						
							|  |  |  |     return (EXECUTION_FAILURE); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Do the work of changing to the directory NEWDIR.  Handle symbolic | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  |    link following, etc.  This function *must* return with | 
					
						
							|  |  |  |    the_current_working_directory either set to NULL (in which case | 
					
						
							|  |  |  |    getcwd() will eventually be called), or set to a string corresponding | 
					
						
							|  |  |  |    to the working directory.  Return 1 on success, 0 on failure. */ | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  | change_to_directory (newdir, nolinks, xattr) | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |      char *newdir; | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  |      int nolinks, xattr; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  |   char *t, *tdir, *ndir; | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  |   int err, canon_failed, r, ndlen, dlen; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  |   tdir = (char *)NULL; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  |   if (the_current_working_directory == 0) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       t = get_working_directory ("chdir"); | 
					
						
							|  |  |  |       FREE (t); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  |   t = make_absolute (newdir, the_current_working_directory); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  |   /* TDIR is either the canonicalized absolute pathname of NEWDIR | 
					
						
							|  |  |  |      (nolinks == 0) or the absolute physical pathname of NEWDIR | 
					
						
							|  |  |  |      (nolinks != 0). */ | 
					
						
							|  |  |  |   tdir = nolinks ? sh_physpath (t, 0) | 
					
						
							|  |  |  | 		 : sh_canonpath (t, PATH_CHECKDOTDOT|PATH_CHECKEXISTS); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  |   ndlen = strlen (newdir); | 
					
						
							|  |  |  |   dlen = strlen (t); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  |   /* Use the canonicalized version of NEWDIR, or, if canonicalization | 
					
						
							|  |  |  |      failed, use the non-canonical form. */ | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   canon_failed = 0; | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  |   if (tdir && *tdir) | 
					
						
							|  |  |  |     free (t); | 
					
						
							|  |  |  |   else | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       FREE (tdir); | 
					
						
							|  |  |  |       tdir = t; | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |       canon_failed = 1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* In POSIX mode, if we're resolving symlinks logically and sh_canonpath | 
					
						
							|  |  |  |      returns NULL (because it checks the path, it will return NULL if the | 
					
						
							|  |  |  |      resolved path doesn't exist), fail immediately. */ | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  |   if (posixly_correct && nolinks == 0 && canon_failed && (errno != ENAMETOOLONG || ndlen > PATH_MAX)) | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  | #if defined ENAMETOOLONG | 
					
						
							|  |  |  |       if (errno != ENOENT && errno != ENAMETOOLONG) | 
					
						
							|  |  |  | #else | 
					
						
							|  |  |  |       if (errno != ENOENT) | 
					
						
							|  |  |  | #endif | 
					
						
							|  |  |  | 	errno = ENOTDIR; | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  |       free (tdir); | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |       return (0); | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  | #if defined (O_XATTR) | 
					
						
							|  |  |  |   if (xattrflag) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       r = cdxattr (nolinks ? newdir : tdir, &ndir); | 
					
						
							|  |  |  |       if (r >= 0) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	  canon_failed = 0; | 
					
						
							|  |  |  | 	  free (tdir); | 
					
						
							|  |  |  | 	  tdir = ndir; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  |       else | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	  err = errno; | 
					
						
							|  |  |  | 	  free (tdir); | 
					
						
							|  |  |  | 	  errno = err; | 
					
						
							|  |  |  | 	  return (0);		/* no xattr */ | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   else | 
					
						
							|  |  |  | #endif | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       r = chdir (nolinks ? newdir : tdir); | 
					
						
							|  |  |  |       if (r >= 0) | 
					
						
							|  |  |  | 	resetxattr (); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  |   /* If the chdir succeeds, update the_current_working_directory. */ | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  |   if (r == 0) | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |       /* If canonicalization failed, but the chdir succeeded, reset the | 
					
						
							|  |  |  | 	 shell's idea of the_current_working_directory. */ | 
					
						
							|  |  |  |       if (canon_failed) | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  | 	  t = resetpwd ("cd"); | 
					
						
							|  |  |  | 	  if (t == 0) | 
					
						
							|  |  |  | 	    set_working_directory (tdir); | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  | 	  else | 
					
						
							|  |  |  | 	    free (t); | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  |       else | 
					
						
							|  |  |  | 	set_working_directory (tdir); | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  |       free (tdir); | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  |       return (1); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  |   /* We failed to change to the appropriate directory name.  If we tried | 
					
						
							|  |  |  |      what the user passed (nolinks != 0), punt now. */ | 
					
						
							|  |  |  |   if (nolinks) | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  |     { | 
					
						
							|  |  |  |       free (tdir); | 
					
						
							|  |  |  |       return (0); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  |   err = errno; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  |   /* We're not in physical mode (nolinks == 0), but we failed to change to | 
					
						
							|  |  |  |      the canonicalized directory name (TDIR).  Try what the user passed | 
					
						
							|  |  |  |      verbatim. If we succeed, reinitialize the_current_working_directory. */ | 
					
						
							|  |  |  |   if (chdir (newdir) == 0) | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  |       t = resetpwd ("cd"); | 
					
						
							|  |  |  |       if (t == 0) | 
					
						
							|  |  |  | 	set_working_directory (tdir); | 
					
						
							|  |  |  |       else | 
					
						
							|  |  |  | 	free (t); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  |       r = 1; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |     } | 
					
						
							|  |  |  |   else | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  |     { | 
					
						
							|  |  |  |       errno = err; | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  |       r = 0; | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   free (tdir); | 
					
						
							|  |  |  |   return r; | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | } |