mirror of
git://git.code.sf.net/p/cdesktopenv/code
synced 2025-03-09 15:50:02 +00:00
Add the '-e' flag to the 'cd' builtin (#358)
This change adds the -e flag to the cd builtin, as specified in <https://www.austingroupbugs.net/view.php?id=253>. The -e flag is used to verify if the the current working directory after 'cd -P' successfully changes the directory, and returns with exit status 1 if the cwd couldn't be determined. Additionally, it causes all other errors to return with exit status >1 (i.e., status 2 unless ENOMEM occurs) if -e and -P are both active. src/cmd/ksh93/bltins/cd_pwd.c: - Add -e option to the cd builtin command. It verifies $PWD by using test_inode() to execute the equivalent of [[ . -ef $PWD ]]. - The check for restricted mode has been moved after optget to allow 'cd -eP' to return with exit status 2 when in restricted mode. To avoid changing the previous behavior of cd when -e isn't passed, extra checks have been added to prevent cd from printing usage information in restricted mode. src/cmd/ksh93/tests/builtins.sh: - Add regression tests for the exit status when using the cd -P flag with and without -e. src/cmd/ksh93/data/builtins.c, src/cmd/ksh93/sh.1: - Document the addition of -e to the cd builtin.
This commit is contained in:
parent
a3f4b5efd1
commit
cd8c48cc5a
5 changed files with 111 additions and 25 deletions
|
|
@ -20,8 +20,8 @@
|
|||
***********************************************************************/
|
||||
#pragma prototyped
|
||||
/*
|
||||
* cd [-LP] [dirname]
|
||||
* cd [-LP] [old] [new]
|
||||
* cd [-L] [-Pe] [dirname]
|
||||
* cd [-L] [-Pe] [old] [new]
|
||||
* pwd [-LP]
|
||||
*
|
||||
* David Korn
|
||||
|
|
@ -57,33 +57,43 @@ int b_cd(int argc, char *argv[],Shbltin_t *context)
|
|||
register const char *dp;
|
||||
register Shell_t *shp = context->shp;
|
||||
int saverrno=0;
|
||||
int rval,flag=0;
|
||||
int rval,pflag=0,eflag=0,ret=1;
|
||||
char *oldpwd;
|
||||
Namval_t *opwdnod, *pwdnod;
|
||||
if(sh_isoption(SH_RESTRICTED))
|
||||
{
|
||||
errormsg(SH_DICT,ERROR_exit(1),e_restricted+4);
|
||||
UNREACHABLE();
|
||||
}
|
||||
while((rval = optget(argv,sh_optcd))) switch(rval)
|
||||
{
|
||||
case 'e':
|
||||
eflag = 1;
|
||||
break;
|
||||
case 'L':
|
||||
flag = 0;
|
||||
pflag = 0;
|
||||
break;
|
||||
case 'P':
|
||||
flag = 1;
|
||||
pflag = 1;
|
||||
break;
|
||||
case ':':
|
||||
if(sh_isoption(SH_RESTRICTED))
|
||||
break;
|
||||
errormsg(SH_DICT,2, "%s", opt_info.arg);
|
||||
break;
|
||||
case '?':
|
||||
if(sh_isoption(SH_RESTRICTED))
|
||||
break;
|
||||
errormsg(SH_DICT,ERROR_usage(2), "%s", opt_info.arg);
|
||||
UNREACHABLE();
|
||||
}
|
||||
if(pflag && eflag)
|
||||
ret = 2; /* exit status is 2 if -eP are both on and chdir failed */
|
||||
if(sh_isoption(SH_RESTRICTED))
|
||||
{
|
||||
/* restricted shells cannot change the directory */
|
||||
errormsg(SH_DICT,ERROR_exit(ret),e_restricted+4);
|
||||
UNREACHABLE();
|
||||
}
|
||||
argv += opt_info.index;
|
||||
argc -= opt_info.index;
|
||||
dir = argv[0];
|
||||
if(error_info.errors>0 || argc >2)
|
||||
if(error_info.errors>0 || argc>2)
|
||||
{
|
||||
errormsg(SH_DICT,ERROR_usage(2),"%s",optusage((char*)0));
|
||||
UNREACHABLE();
|
||||
|
|
@ -106,7 +116,7 @@ int b_cd(int argc, char *argv[],Shbltin_t *context)
|
|||
dir = nv_getval(opwdnod);
|
||||
if(!dir || *dir==0)
|
||||
{
|
||||
errormsg(SH_DICT,ERROR_exit(1),argc==2?e_subst+4:e_direct);
|
||||
errormsg(SH_DICT,ERROR_exit(ret),argc==2?e_subst+4:e_direct);
|
||||
UNREACHABLE();
|
||||
}
|
||||
/*
|
||||
|
|
@ -179,7 +189,7 @@ int b_cd(int argc, char *argv[],Shbltin_t *context)
|
|||
stakputs(last+PATH_OFFSET);
|
||||
stakputc(0);
|
||||
}
|
||||
if(!flag)
|
||||
if(!pflag)
|
||||
{
|
||||
register char *cp;
|
||||
stakseek(PATH_MAX+PATH_OFFSET);
|
||||
|
|
@ -200,19 +210,19 @@ int b_cd(int argc, char *argv[],Shbltin_t *context)
|
|||
{
|
||||
if(saverrno)
|
||||
errno = saverrno;
|
||||
errormsg(SH_DICT,ERROR_system(1),"%s:",dir);
|
||||
errormsg(SH_DICT,ERROR_system(ret),"%s:",dir);
|
||||
UNREACHABLE();
|
||||
}
|
||||
success:
|
||||
if(dir == nv_getval(opwdnod) || argc==2)
|
||||
dp = dir; /* print out directory for cd - */
|
||||
if(flag)
|
||||
if(pflag)
|
||||
{
|
||||
dir = stakptr(PATH_OFFSET);
|
||||
if (!(dir=pathcanon(dir,PATH_PHYSICAL)))
|
||||
{
|
||||
dir = stakptr(PATH_OFFSET);
|
||||
errormsg(SH_DICT,ERROR_system(1),"%s:",dir);
|
||||
errormsg(SH_DICT,ERROR_system(ret),"%s:",dir);
|
||||
UNREACHABLE();
|
||||
}
|
||||
stakseek(dir-stakptr(0));
|
||||
|
|
@ -223,10 +233,10 @@ success:
|
|||
nv_putval(opwdnod,oldpwd,NV_RDONLY);
|
||||
if(*dir == '/')
|
||||
{
|
||||
flag = strlen(dir);
|
||||
size_t len = strlen(dir);
|
||||
/* delete trailing '/' */
|
||||
while(--flag>0 && dir[flag]=='/')
|
||||
dir[flag] = 0;
|
||||
while(--len>0 && dir[len]=='/')
|
||||
dir[len] = 0;
|
||||
nv_putval(pwdnod,dir,NV_RDONLY);
|
||||
nv_onattr(pwdnod,NV_EXPORT);
|
||||
if(shp->pwd)
|
||||
|
|
@ -243,13 +253,18 @@ success:
|
|||
path_pwd(shp,0);
|
||||
if(*shp->pwd != '/')
|
||||
{
|
||||
errormsg(SH_DICT,ERROR_system(1),e_direct);
|
||||
errormsg(SH_DICT,ERROR_system(ret),e_direct);
|
||||
UNREACHABLE();
|
||||
}
|
||||
}
|
||||
nv_scan(sh_subtracktree(1),rehash,(void*)0,NV_TAGGED,NV_TAGGED);
|
||||
path_newdir(shp,shp->pathlist);
|
||||
path_newdir(shp,shp->cdpathlist);
|
||||
if(pflag && eflag)
|
||||
{
|
||||
/* Verify the current working directory matches $PWD */
|
||||
return(!test_inode(e_dot,nv_getval(pwdnod)));
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue