14887Schin /*********************************************************************** 24887Schin * * 34887Schin * This software is part of the ast package * 4*8462SApril.Chin@Sun.COM * Copyright (c) 1982-2008 AT&T Intellectual Property * 54887Schin * and is licensed under the * 64887Schin * Common Public License, Version 1.0 * 7*8462SApril.Chin@Sun.COM * by AT&T Intellectual Property * 84887Schin * * 94887Schin * A copy of the License is available at * 104887Schin * http://www.opensource.org/licenses/cpl1.0.txt * 114887Schin * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) * 124887Schin * * 134887Schin * Information and Software Systems Research * 144887Schin * AT&T Research * 154887Schin * Florham Park NJ * 164887Schin * * 174887Schin * David Korn <dgk@research.att.com> * 184887Schin * * 194887Schin ***********************************************************************/ 204887Schin #pragma prototyped 214887Schin /* 224887Schin * cd [-LP] [dirname] 234887Schin * cd [-LP] [old] [new] 244887Schin * pwd [-LP] 254887Schin * 264887Schin * David Korn 274887Schin * AT&T Labs 284887Schin * research!dgk 294887Schin * 304887Schin */ 314887Schin 324887Schin #include "defs.h" 334887Schin #include <stak.h> 344887Schin #include <error.h> 354887Schin #include "variables.h" 364887Schin #include "path.h" 374887Schin #include "name.h" 384887Schin #include "builtins.h" 394887Schin #include <ls.h> 404887Schin #include <ctype.h> 414887Schin 424887Schin /* 434887Schin * Invalidate path name bindings to relative paths 444887Schin */ 454887Schin static void rehash(register Namval_t *np,void *data) 464887Schin { 474887Schin Pathcomp_t *pp = (Pathcomp_t*)np->nvalue.cp; 484887Schin NOT_USED(data); 494887Schin if(pp && *pp->name!='/') 504887Schin nv_unset(np); 514887Schin } 524887Schin 534887Schin int b_cd(int argc, char *argv[],void *extra) 544887Schin { 554887Schin register char *dir; 564887Schin Pathcomp_t *cdpath = 0; 574887Schin register const char *dp; 58*8462SApril.Chin@Sun.COM register Shell_t *shp = ((Shbltin_t*)extra)->shp; 594887Schin int saverrno=0; 604887Schin int rval,flag=0; 614887Schin char *oldpwd; 624887Schin Namval_t *opwdnod, *pwdnod; 634887Schin if(sh_isoption(SH_RESTRICTED)) 644887Schin errormsg(SH_DICT,ERROR_exit(1),e_restricted+4); 654887Schin while((rval = optget(argv,sh_optcd))) switch(rval) 664887Schin { 674887Schin case 'L': 684887Schin flag = 0; 694887Schin break; 704887Schin case 'P': 714887Schin flag = 1; 724887Schin break; 734887Schin case ':': 744887Schin errormsg(SH_DICT,2, "%s", opt_info.arg); 754887Schin break; 764887Schin case '?': 774887Schin errormsg(SH_DICT,ERROR_usage(2), "%s", opt_info.arg); 784887Schin break; 794887Schin } 804887Schin argv += opt_info.index; 814887Schin argc -= opt_info.index; 824887Schin dir = argv[0]; 834887Schin if(error_info.errors>0 || argc >2) 844887Schin errormsg(SH_DICT,ERROR_usage(2),"%s",optusage((char*)0)); 854887Schin oldpwd = (char*)shp->pwd; 864887Schin opwdnod = (shp->subshell?sh_assignok(OLDPWDNOD,1):OLDPWDNOD); 874887Schin pwdnod = (shp->subshell?sh_assignok(PWDNOD,1):PWDNOD); 884887Schin if(argc==2) 894887Schin dir = sh_substitute(oldpwd,dir,argv[1]); 904887Schin else if(!dir || *dir==0) 914887Schin dir = nv_getval(HOME); 924887Schin else if(*dir == '-' && dir[1]==0) 934887Schin dir = nv_getval(opwdnod); 944887Schin if(!dir || *dir==0) 954887Schin errormsg(SH_DICT,ERROR_exit(1),argc==2?e_subst+4:e_direct); 964887Schin #if _WINIX 974887Schin if(*dir != '/' && (dir[1]!=':')) 984887Schin #else 994887Schin if(*dir != '/') 1004887Schin #endif /* _WINIX */ 1014887Schin { 1024887Schin if(!(cdpath = (Pathcomp_t*)shp->cdpathlist) && (dp=(CDPNOD)->nvalue.cp)) 1034887Schin { 1044887Schin if(cdpath=path_addpath((Pathcomp_t*)0,dp,PATH_CDPATH)) 1054887Schin { 1064887Schin shp->cdpathlist = (void*)cdpath; 1074887Schin cdpath->shp = shp; 1084887Schin } 1094887Schin } 1104887Schin if(!oldpwd) 1114887Schin oldpwd = path_pwd(1); 1124887Schin } 1134887Schin if(*dir=='.') 1144887Schin { 1154887Schin /* test for pathname . ./ .. or ../ */ 1164887Schin if(*(dp=dir+1) == '.') 1174887Schin dp++; 1184887Schin if(*dp==0 || *dp=='/') 1194887Schin cdpath = 0; 1204887Schin } 1214887Schin rval = -1; 1224887Schin do 1234887Schin { 1244887Schin dp = cdpath?cdpath->name:""; 1254887Schin cdpath = path_nextcomp(cdpath,dir,0); 1264887Schin #if _WINIX 1274887Schin if(*stakptr(PATH_OFFSET+1)==':' && isalpha(*stakptr(PATH_OFFSET))) 1284887Schin { 1294887Schin *stakptr(PATH_OFFSET+1) = *stakptr(PATH_OFFSET); 1304887Schin *stakptr(PATH_OFFSET)='/'; 1314887Schin } 1324887Schin #endif /* _WINIX */ 1334887Schin if(*stakptr(PATH_OFFSET)!='/') 1344887Schin 1354887Schin { 1364887Schin char *last=(char*)stakfreeze(1); 1374887Schin stakseek(PATH_OFFSET); 1384887Schin stakputs(oldpwd); 1394887Schin /* don't add '/' of oldpwd is / itself */ 1404887Schin if(*oldpwd!='/' || oldpwd[1]) 1414887Schin stakputc('/'); 1424887Schin stakputs(last+PATH_OFFSET); 1434887Schin stakputc(0); 1444887Schin } 1454887Schin if(!flag) 1464887Schin { 1474887Schin register char *cp; 1484887Schin stakseek(PATH_MAX+PATH_OFFSET); 1494887Schin #if SHOPT_FS_3D 1504887Schin if(!(cp = pathcanon(stakptr(PATH_OFFSET),PATH_DOTDOT))) 1514887Schin continue; 1524887Schin /* eliminate trailing '/' */ 1534887Schin while(*--cp == '/' && cp>stakptr(PATH_OFFSET)) 1544887Schin *cp = 0; 1554887Schin #else 1564887Schin if(*(cp=stakptr(PATH_OFFSET))=='/') 1574887Schin if(!pathcanon(cp,PATH_DOTDOT)) 1584887Schin continue; 1594887Schin #endif /* SHOPT_FS_3D */ 1604887Schin } 1614887Schin if((rval=chdir(path_relative(stakptr(PATH_OFFSET)))) >= 0) 1624887Schin goto success; 1634887Schin if(errno!=ENOENT && saverrno==0) 1644887Schin saverrno=errno; 1654887Schin } 1664887Schin while(cdpath); 1674887Schin if(rval<0 && *dir=='/' && *(path_relative(stakptr(PATH_OFFSET)))!='/') 1684887Schin rval = chdir(dir); 1694887Schin /* use absolute chdir() if relative chdir() fails */ 1704887Schin if(rval<0) 1714887Schin { 1724887Schin if(saverrno) 1734887Schin errno = saverrno; 1744887Schin errormsg(SH_DICT,ERROR_system(1),"%s:",dir); 1754887Schin } 1764887Schin success: 1774887Schin if(dir == nv_getval(opwdnod) || argc==2) 1784887Schin dp = dir; /* print out directory for cd - */ 1794887Schin if(flag) 1804887Schin { 1814887Schin dir = stakptr(PATH_OFFSET); 1824887Schin if (!(dir=pathcanon(dir,PATH_PHYSICAL))) 1834887Schin { 1844887Schin dir = stakptr(PATH_OFFSET); 1854887Schin errormsg(SH_DICT,ERROR_system(1),"%s:",dir); 1864887Schin } 1874887Schin stakseek(dir-stakptr(0)); 1884887Schin } 1894887Schin dir = (char*)stakfreeze(1)+PATH_OFFSET; 1904887Schin if(*dp && (*dp!='.'||dp[1]) && strchr(dir,'/')) 1914887Schin sfputr(sfstdout,dir,'\n'); 1924887Schin if(*dir != '/') 1934887Schin return(0); 1944887Schin nv_putval(opwdnod,oldpwd,NV_RDONLY); 1954887Schin if(oldpwd) 1964887Schin free(oldpwd); 1974887Schin flag = strlen(dir); 1984887Schin /* delete trailing '/' */ 1994887Schin while(--flag>0 && dir[flag]=='/') 2004887Schin dir[flag] = 0; 2014887Schin nv_putval(pwdnod,dir,NV_RDONLY); 2024887Schin nv_onattr(pwdnod,NV_NOFREE|NV_EXPORT); 2034887Schin shp->pwd = pwdnod->nvalue.cp; 2044887Schin nv_scan(shp->track_tree,rehash,(void*)0,NV_TAGGED,NV_TAGGED); 2054887Schin path_newdir(shp->pathlist); 2064887Schin path_newdir(shp->cdpathlist); 2074887Schin return(0); 2084887Schin } 2094887Schin 2104887Schin int b_pwd(int argc, char *argv[],void *extra) 2114887Schin { 2124887Schin register int n, flag = 0; 2134887Schin register char *cp; 214*8462SApril.Chin@Sun.COM register Shell_t *shp = ((Shbltin_t*)extra)->shp; 2154887Schin NOT_USED(argc); 2164887Schin while((n = optget(argv,sh_optpwd))) switch(n) 2174887Schin { 2184887Schin case 'L': 2194887Schin flag = 0; 2204887Schin break; 2214887Schin case 'P': 2224887Schin flag = 1; 2234887Schin break; 2244887Schin case ':': 2254887Schin errormsg(SH_DICT,2, "%s", opt_info.arg); 2264887Schin break; 2274887Schin case '?': 2284887Schin errormsg(SH_DICT,ERROR_usage(2), "%s", opt_info.arg); 2294887Schin break; 2304887Schin } 2314887Schin if(error_info.errors) 2324887Schin errormsg(SH_DICT,ERROR_usage(2),"%s",optusage((char*)0)); 2334887Schin if(*(cp = path_pwd(0)) != '/') 2344887Schin errormsg(SH_DICT,ERROR_system(1), e_pwd); 2354887Schin if(flag) 2364887Schin { 2374887Schin #if SHOPT_FS_3D 2384887Schin if(shp->lim.fs3d && (flag = mount(e_dot,NIL(char*),FS3D_GET|FS3D_VIEW,0))>=0) 2394887Schin { 2404887Schin cp = (char*)stakseek(++flag+PATH_MAX); 2414887Schin mount(e_dot,cp,FS3D_GET|FS3D_VIEW|FS3D_SIZE(flag),0); 2424887Schin } 2434887Schin else 2444887Schin #endif /* SHOPT_FS_3D */ 2454887Schin cp = strcpy(stakseek(strlen(cp)+PATH_MAX),cp); 2464887Schin pathcanon(cp,PATH_PHYSICAL); 2474887Schin } 2484887Schin sfputr(sfstdout,cp,'\n'); 2494887Schin return(0); 2504887Schin } 2514887Schin 252