14887Schin /*********************************************************************** 24887Schin * * 34887Schin * This software is part of the ast package * 4*12068SRoger.Faulkner@Oracle.COM * Copyright (c) 1982-2010 AT&T Intellectual Property * 54887Schin * and is licensed under the * 64887Schin * Common Public License, Version 1.0 * 78462SApril.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 414887Schin /* 424887Schin * Invalidate path name bindings to relative paths 434887Schin */ 444887Schin static void rehash(register Namval_t *np,void *data) 454887Schin { 464887Schin Pathcomp_t *pp = (Pathcomp_t*)np->nvalue.cp; 474887Schin NOT_USED(data); 484887Schin if(pp && *pp->name!='/') 494887Schin nv_unset(np); 504887Schin } 514887Schin 524887Schin int b_cd(int argc, char *argv[],void *extra) 534887Schin { 544887Schin register char *dir; 554887Schin Pathcomp_t *cdpath = 0; 564887Schin register const char *dp; 578462SApril.Chin@Sun.COM register Shell_t *shp = ((Shbltin_t*)extra)->shp; 584887Schin int saverrno=0; 594887Schin int rval,flag=0; 604887Schin char *oldpwd; 614887Schin Namval_t *opwdnod, *pwdnod; 624887Schin if(sh_isoption(SH_RESTRICTED)) 634887Schin errormsg(SH_DICT,ERROR_exit(1),e_restricted+4); 644887Schin while((rval = optget(argv,sh_optcd))) switch(rval) 654887Schin { 664887Schin case 'L': 674887Schin flag = 0; 684887Schin break; 694887Schin case 'P': 704887Schin flag = 1; 714887Schin break; 724887Schin case ':': 734887Schin errormsg(SH_DICT,2, "%s", opt_info.arg); 744887Schin break; 754887Schin case '?': 764887Schin errormsg(SH_DICT,ERROR_usage(2), "%s", opt_info.arg); 774887Schin break; 784887Schin } 794887Schin argv += opt_info.index; 804887Schin argc -= opt_info.index; 814887Schin dir = argv[0]; 824887Schin if(error_info.errors>0 || argc >2) 834887Schin errormsg(SH_DICT,ERROR_usage(2),"%s",optusage((char*)0)); 844887Schin oldpwd = (char*)shp->pwd; 854887Schin opwdnod = (shp->subshell?sh_assignok(OLDPWDNOD,1):OLDPWDNOD); 864887Schin pwdnod = (shp->subshell?sh_assignok(PWDNOD,1):PWDNOD); 874887Schin if(argc==2) 884887Schin dir = sh_substitute(oldpwd,dir,argv[1]); 894887Schin else if(!dir || *dir==0) 904887Schin dir = nv_getval(HOME); 914887Schin else if(*dir == '-' && dir[1]==0) 924887Schin dir = nv_getval(opwdnod); 934887Schin if(!dir || *dir==0) 944887Schin errormsg(SH_DICT,ERROR_exit(1),argc==2?e_subst+4:e_direct); 954887Schin #if _WINIX 964887Schin if(*dir != '/' && (dir[1]!=':')) 974887Schin #else 984887Schin if(*dir != '/') 994887Schin #endif /* _WINIX */ 1004887Schin { 1014887Schin if(!(cdpath = (Pathcomp_t*)shp->cdpathlist) && (dp=(CDPNOD)->nvalue.cp)) 1024887Schin { 1034887Schin if(cdpath=path_addpath((Pathcomp_t*)0,dp,PATH_CDPATH)) 1044887Schin { 1054887Schin shp->cdpathlist = (void*)cdpath; 1064887Schin cdpath->shp = shp; 1074887Schin } 1084887Schin } 1094887Schin if(!oldpwd) 1104887Schin oldpwd = path_pwd(1); 1114887Schin } 1124887Schin if(*dir=='.') 1134887Schin { 1144887Schin /* test for pathname . ./ .. or ../ */ 1154887Schin if(*(dp=dir+1) == '.') 1164887Schin dp++; 1174887Schin if(*dp==0 || *dp=='/') 1184887Schin cdpath = 0; 1194887Schin } 1204887Schin rval = -1; 1214887Schin do 1224887Schin { 1234887Schin dp = cdpath?cdpath->name:""; 1244887Schin cdpath = path_nextcomp(cdpath,dir,0); 1254887Schin #if _WINIX 1264887Schin if(*stakptr(PATH_OFFSET+1)==':' && isalpha(*stakptr(PATH_OFFSET))) 1274887Schin { 1284887Schin *stakptr(PATH_OFFSET+1) = *stakptr(PATH_OFFSET); 1294887Schin *stakptr(PATH_OFFSET)='/'; 1304887Schin } 1314887Schin #endif /* _WINIX */ 1324887Schin if(*stakptr(PATH_OFFSET)!='/') 1334887Schin 1344887Schin { 1354887Schin char *last=(char*)stakfreeze(1); 1364887Schin stakseek(PATH_OFFSET); 1374887Schin stakputs(oldpwd); 1384887Schin /* don't add '/' of oldpwd is / itself */ 1394887Schin if(*oldpwd!='/' || oldpwd[1]) 1404887Schin stakputc('/'); 1414887Schin stakputs(last+PATH_OFFSET); 1424887Schin stakputc(0); 1434887Schin } 1444887Schin if(!flag) 1454887Schin { 1464887Schin register char *cp; 1474887Schin stakseek(PATH_MAX+PATH_OFFSET); 1484887Schin #if SHOPT_FS_3D 1494887Schin if(!(cp = pathcanon(stakptr(PATH_OFFSET),PATH_DOTDOT))) 1504887Schin continue; 1514887Schin /* eliminate trailing '/' */ 1524887Schin while(*--cp == '/' && cp>stakptr(PATH_OFFSET)) 1534887Schin *cp = 0; 1544887Schin #else 1554887Schin if(*(cp=stakptr(PATH_OFFSET))=='/') 1564887Schin if(!pathcanon(cp,PATH_DOTDOT)) 1574887Schin continue; 1584887Schin #endif /* SHOPT_FS_3D */ 1594887Schin } 1604887Schin if((rval=chdir(path_relative(stakptr(PATH_OFFSET)))) >= 0) 1614887Schin goto success; 1624887Schin if(errno!=ENOENT && saverrno==0) 1634887Schin saverrno=errno; 1644887Schin } 1654887Schin while(cdpath); 1664887Schin if(rval<0 && *dir=='/' && *(path_relative(stakptr(PATH_OFFSET)))!='/') 1674887Schin rval = chdir(dir); 1684887Schin /* use absolute chdir() if relative chdir() fails */ 1694887Schin if(rval<0) 1704887Schin { 1714887Schin if(saverrno) 1724887Schin errno = saverrno; 1734887Schin errormsg(SH_DICT,ERROR_system(1),"%s:",dir); 1744887Schin } 1754887Schin success: 1764887Schin if(dir == nv_getval(opwdnod) || argc==2) 1774887Schin dp = dir; /* print out directory for cd - */ 1784887Schin if(flag) 1794887Schin { 1804887Schin dir = stakptr(PATH_OFFSET); 1814887Schin if (!(dir=pathcanon(dir,PATH_PHYSICAL))) 1824887Schin { 1834887Schin dir = stakptr(PATH_OFFSET); 1844887Schin errormsg(SH_DICT,ERROR_system(1),"%s:",dir); 1854887Schin } 1864887Schin stakseek(dir-stakptr(0)); 1874887Schin } 1884887Schin dir = (char*)stakfreeze(1)+PATH_OFFSET; 1894887Schin if(*dp && (*dp!='.'||dp[1]) && strchr(dir,'/')) 1904887Schin sfputr(sfstdout,dir,'\n'); 1914887Schin if(*dir != '/') 1924887Schin return(0); 1934887Schin nv_putval(opwdnod,oldpwd,NV_RDONLY); 1944887Schin if(oldpwd) 1954887Schin free(oldpwd); 1964887Schin flag = strlen(dir); 1974887Schin /* delete trailing '/' */ 1984887Schin while(--flag>0 && dir[flag]=='/') 1994887Schin dir[flag] = 0; 2004887Schin nv_putval(pwdnod,dir,NV_RDONLY); 2014887Schin nv_onattr(pwdnod,NV_NOFREE|NV_EXPORT); 2024887Schin shp->pwd = pwdnod->nvalue.cp; 2034887Schin nv_scan(shp->track_tree,rehash,(void*)0,NV_TAGGED,NV_TAGGED); 2044887Schin path_newdir(shp->pathlist); 2054887Schin path_newdir(shp->cdpathlist); 2064887Schin return(0); 2074887Schin } 2084887Schin 2094887Schin int b_pwd(int argc, char *argv[],void *extra) 2104887Schin { 2114887Schin register int n, flag = 0; 2124887Schin register char *cp; 213*12068SRoger.Faulkner@Oracle.COM #if SHOPT_FS_3D 2148462SApril.Chin@Sun.COM register Shell_t *shp = ((Shbltin_t*)extra)->shp; 215*12068SRoger.Faulkner@Oracle.COM #else 216*12068SRoger.Faulkner@Oracle.COM NOT_USED(extra); 217*12068SRoger.Faulkner@Oracle.COM #endif 2184887Schin NOT_USED(argc); 2194887Schin while((n = optget(argv,sh_optpwd))) switch(n) 2204887Schin { 2214887Schin case 'L': 2224887Schin flag = 0; 2234887Schin break; 2244887Schin case 'P': 2254887Schin flag = 1; 2264887Schin break; 2274887Schin case ':': 2284887Schin errormsg(SH_DICT,2, "%s", opt_info.arg); 2294887Schin break; 2304887Schin case '?': 2314887Schin errormsg(SH_DICT,ERROR_usage(2), "%s", opt_info.arg); 2324887Schin break; 2334887Schin } 2344887Schin if(error_info.errors) 2354887Schin errormsg(SH_DICT,ERROR_usage(2),"%s",optusage((char*)0)); 2364887Schin if(*(cp = path_pwd(0)) != '/') 2374887Schin errormsg(SH_DICT,ERROR_system(1), e_pwd); 2384887Schin if(flag) 2394887Schin { 2404887Schin #if SHOPT_FS_3D 2414887Schin if(shp->lim.fs3d && (flag = mount(e_dot,NIL(char*),FS3D_GET|FS3D_VIEW,0))>=0) 2424887Schin { 2434887Schin cp = (char*)stakseek(++flag+PATH_MAX); 2444887Schin mount(e_dot,cp,FS3D_GET|FS3D_VIEW|FS3D_SIZE(flag),0); 2454887Schin } 2464887Schin else 2474887Schin #endif /* SHOPT_FS_3D */ 2484887Schin cp = strcpy(stakseek(strlen(cp)+PATH_MAX),cp); 2494887Schin pathcanon(cp,PATH_PHYSICAL); 2504887Schin } 2514887Schin sfputr(sfstdout,cp,'\n'); 2524887Schin return(0); 2534887Schin } 2544887Schin 255