1da2e3ebdSchin /***********************************************************************
2da2e3ebdSchin *                                                                      *
3da2e3ebdSchin *               This software is part of the ast package               *
4*b30d1939SAndy Fiddaman *          Copyright (c) 1982-2012 AT&T Intellectual Property          *
5da2e3ebdSchin *                      and is licensed under the                       *
6*b30d1939SAndy Fiddaman *                 Eclipse Public License, Version 1.0                  *
77c2fbfb3SApril Chin *                    by AT&T Intellectual Property                     *
8da2e3ebdSchin *                                                                      *
9da2e3ebdSchin *                A copy of the License is available at                 *
10*b30d1939SAndy Fiddaman *          http://www.eclipse.org/org/documents/epl-v10.html           *
11*b30d1939SAndy Fiddaman *         (with md5 checksum b35adb5213ca9657e911e9befb180842)         *
12da2e3ebdSchin *                                                                      *
13da2e3ebdSchin *              Information and Software Systems Research               *
14da2e3ebdSchin *                            AT&T Research                             *
15da2e3ebdSchin *                           Florham Park NJ                            *
16da2e3ebdSchin *                                                                      *
17da2e3ebdSchin *                  David Korn <dgk@research.att.com>                   *
18da2e3ebdSchin *                                                                      *
19da2e3ebdSchin ***********************************************************************/
20da2e3ebdSchin #pragma prototyped
21da2e3ebdSchin /*
22da2e3ebdSchin  * cd [-LP]  [dirname]
23da2e3ebdSchin  * cd [-LP]  [old] [new]
24da2e3ebdSchin  * pwd [-LP]
25da2e3ebdSchin  *
26da2e3ebdSchin  *   David Korn
27da2e3ebdSchin  *   AT&T Labs
28da2e3ebdSchin  *   research!dgk
29da2e3ebdSchin  *
30da2e3ebdSchin  */
31da2e3ebdSchin 
32da2e3ebdSchin #include	"defs.h"
33da2e3ebdSchin #include	<stak.h>
34da2e3ebdSchin #include	<error.h>
35da2e3ebdSchin #include	"variables.h"
36da2e3ebdSchin #include	"path.h"
37da2e3ebdSchin #include	"name.h"
38da2e3ebdSchin #include	"builtins.h"
39da2e3ebdSchin #include	<ls.h>
40da2e3ebdSchin 
41da2e3ebdSchin /*
42da2e3ebdSchin  * Invalidate path name bindings to relative paths
43da2e3ebdSchin  */
rehash(register Namval_t * np,void * data)44da2e3ebdSchin static void rehash(register Namval_t *np,void *data)
45da2e3ebdSchin {
46da2e3ebdSchin 	Pathcomp_t *pp = (Pathcomp_t*)np->nvalue.cp;
47da2e3ebdSchin 	NOT_USED(data);
48da2e3ebdSchin 	if(pp && *pp->name!='/')
49*b30d1939SAndy Fiddaman 		_nv_unset(np,0);
50da2e3ebdSchin }
51da2e3ebdSchin 
b_cd(int argc,char * argv[],Shbltin_t * context)52*b30d1939SAndy Fiddaman int	b_cd(int argc, char *argv[],Shbltin_t *context)
53da2e3ebdSchin {
54da2e3ebdSchin 	register char *dir;
55da2e3ebdSchin 	Pathcomp_t *cdpath = 0;
56da2e3ebdSchin 	register const char *dp;
57*b30d1939SAndy Fiddaman 	register Shell_t *shp = context->shp;
58da2e3ebdSchin 	int saverrno=0;
59da2e3ebdSchin 	int rval,flag=0;
60da2e3ebdSchin 	char *oldpwd;
61da2e3ebdSchin 	Namval_t *opwdnod, *pwdnod;
62da2e3ebdSchin 	if(sh_isoption(SH_RESTRICTED))
63da2e3ebdSchin 		errormsg(SH_DICT,ERROR_exit(1),e_restricted+4);
64da2e3ebdSchin 	while((rval = optget(argv,sh_optcd))) switch(rval)
65da2e3ebdSchin 	{
66da2e3ebdSchin 		case 'L':
67da2e3ebdSchin 			flag = 0;
68da2e3ebdSchin 			break;
69da2e3ebdSchin 		case 'P':
70da2e3ebdSchin 			flag = 1;
71da2e3ebdSchin 			break;
72da2e3ebdSchin 		case ':':
73da2e3ebdSchin 			errormsg(SH_DICT,2, "%s", opt_info.arg);
74da2e3ebdSchin 			break;
75da2e3ebdSchin 		case '?':
76da2e3ebdSchin 			errormsg(SH_DICT,ERROR_usage(2), "%s", opt_info.arg);
77da2e3ebdSchin 			break;
78da2e3ebdSchin 	}
79da2e3ebdSchin 	argv += opt_info.index;
80da2e3ebdSchin 	argc -= opt_info.index;
81da2e3ebdSchin 	dir =  argv[0];
82da2e3ebdSchin 	if(error_info.errors>0 || argc >2)
83da2e3ebdSchin 		errormsg(SH_DICT,ERROR_usage(2),"%s",optusage((char*)0));
84*b30d1939SAndy Fiddaman 	oldpwd = path_pwd(shp,0);
85da2e3ebdSchin 	opwdnod = (shp->subshell?sh_assignok(OLDPWDNOD,1):OLDPWDNOD);
86da2e3ebdSchin 	pwdnod = (shp->subshell?sh_assignok(PWDNOD,1):PWDNOD);
87da2e3ebdSchin 	if(argc==2)
88da2e3ebdSchin 		dir = sh_substitute(oldpwd,dir,argv[1]);
89*b30d1939SAndy Fiddaman 	else if(!dir)
90da2e3ebdSchin 		dir = nv_getval(HOME);
91da2e3ebdSchin 	else if(*dir == '-' && dir[1]==0)
92da2e3ebdSchin 		dir = nv_getval(opwdnod);
93da2e3ebdSchin 	if(!dir || *dir==0)
94da2e3ebdSchin 		errormsg(SH_DICT,ERROR_exit(1),argc==2?e_subst+4:e_direct);
95da2e3ebdSchin #if _WINIX
96da2e3ebdSchin 	if(*dir != '/' && (dir[1]!=':'))
97da2e3ebdSchin #else
98da2e3ebdSchin 	if(*dir != '/')
99da2e3ebdSchin #endif /* _WINIX */
100da2e3ebdSchin 	{
101*b30d1939SAndy Fiddaman 		if(!(cdpath = (Pathcomp_t*)shp->cdpathlist) && (dp=sh_scoped(shp,CDPNOD)->nvalue.cp))
102da2e3ebdSchin 		{
103*b30d1939SAndy Fiddaman 			if(cdpath=path_addpath(shp,(Pathcomp_t*)0,dp,PATH_CDPATH))
104da2e3ebdSchin 			{
105da2e3ebdSchin 				shp->cdpathlist = (void*)cdpath;
106da2e3ebdSchin 				cdpath->shp = shp;
107da2e3ebdSchin 			}
108da2e3ebdSchin 		}
109da2e3ebdSchin 		if(!oldpwd)
110*b30d1939SAndy Fiddaman 			oldpwd = path_pwd(shp,1);
111da2e3ebdSchin 	}
112*b30d1939SAndy Fiddaman 	if(*dir!='/')
113da2e3ebdSchin 	{
114*b30d1939SAndy Fiddaman 		/* check for leading .. */
115*b30d1939SAndy Fiddaman 		char *cp;
116*b30d1939SAndy Fiddaman 		sfprintf(shp->strbuf,"%s",dir);
117*b30d1939SAndy Fiddaman 		cp = sfstruse(shp->strbuf);
118*b30d1939SAndy Fiddaman 		pathcanon(cp, 0);
119*b30d1939SAndy Fiddaman 		if(cp[0]=='.' && cp[1]=='.' && (cp[2]=='/' || cp[2]==0))
120*b30d1939SAndy Fiddaman 		{
121*b30d1939SAndy Fiddaman 			if(!shp->strbuf2)
122*b30d1939SAndy Fiddaman 				shp->strbuf2 = sfstropen();
123*b30d1939SAndy Fiddaman 			sfprintf(shp->strbuf2,"%s/%s",oldpwd,cp);
124*b30d1939SAndy Fiddaman 			dir = sfstruse(shp->strbuf2);
125*b30d1939SAndy Fiddaman 			pathcanon(dir, 0);
126*b30d1939SAndy Fiddaman 		}
127da2e3ebdSchin 	}
128da2e3ebdSchin 	rval = -1;
129da2e3ebdSchin 	do
130da2e3ebdSchin 	{
131da2e3ebdSchin 		dp = cdpath?cdpath->name:"";
132*b30d1939SAndy Fiddaman 		cdpath = path_nextcomp(shp,cdpath,dir,0);
133da2e3ebdSchin #if _WINIX
134da2e3ebdSchin                 if(*stakptr(PATH_OFFSET+1)==':' && isalpha(*stakptr(PATH_OFFSET)))
135da2e3ebdSchin 		{
136da2e3ebdSchin 			*stakptr(PATH_OFFSET+1) = *stakptr(PATH_OFFSET);
137da2e3ebdSchin 			*stakptr(PATH_OFFSET)='/';
138da2e3ebdSchin 		}
139da2e3ebdSchin #endif /* _WINIX */
140da2e3ebdSchin                 if(*stakptr(PATH_OFFSET)!='/')
141da2e3ebdSchin 
142da2e3ebdSchin 		{
143da2e3ebdSchin 			char *last=(char*)stakfreeze(1);
144da2e3ebdSchin 			stakseek(PATH_OFFSET);
145da2e3ebdSchin 			stakputs(oldpwd);
146da2e3ebdSchin 			/* don't add '/' of oldpwd is / itself */
147da2e3ebdSchin 			if(*oldpwd!='/' || oldpwd[1])
148da2e3ebdSchin 				stakputc('/');
149da2e3ebdSchin 			stakputs(last+PATH_OFFSET);
150da2e3ebdSchin 			stakputc(0);
151da2e3ebdSchin 		}
152da2e3ebdSchin 		if(!flag)
153da2e3ebdSchin 		{
154da2e3ebdSchin 			register char *cp;
155da2e3ebdSchin 			stakseek(PATH_MAX+PATH_OFFSET);
156da2e3ebdSchin #if SHOPT_FS_3D
157da2e3ebdSchin 			if(!(cp = pathcanon(stakptr(PATH_OFFSET),PATH_DOTDOT)))
158da2e3ebdSchin 				continue;
159da2e3ebdSchin 			/* eliminate trailing '/' */
160da2e3ebdSchin 			while(*--cp == '/' && cp>stakptr(PATH_OFFSET))
161da2e3ebdSchin 				*cp = 0;
162da2e3ebdSchin #else
163da2e3ebdSchin 			if(*(cp=stakptr(PATH_OFFSET))=='/')
164da2e3ebdSchin 				if(!pathcanon(cp,PATH_DOTDOT))
165da2e3ebdSchin 					continue;
166da2e3ebdSchin #endif /* SHOPT_FS_3D */
167da2e3ebdSchin 		}
168*b30d1939SAndy Fiddaman 		if((rval=chdir(path_relative(shp,stakptr(PATH_OFFSET)))) >= 0)
169da2e3ebdSchin 			goto success;
170da2e3ebdSchin 		if(errno!=ENOENT && saverrno==0)
171da2e3ebdSchin 			saverrno=errno;
172da2e3ebdSchin 	}
173da2e3ebdSchin 	while(cdpath);
174*b30d1939SAndy Fiddaman 	if(rval<0 && *dir=='/' && *(path_relative(shp,stakptr(PATH_OFFSET)))!='/')
175da2e3ebdSchin 		rval = chdir(dir);
176da2e3ebdSchin 	/* use absolute chdir() if relative chdir() fails */
177da2e3ebdSchin 	if(rval<0)
178da2e3ebdSchin 	{
179da2e3ebdSchin 		if(saverrno)
180da2e3ebdSchin 			errno = saverrno;
181da2e3ebdSchin 		errormsg(SH_DICT,ERROR_system(1),"%s:",dir);
182da2e3ebdSchin 	}
183da2e3ebdSchin success:
184da2e3ebdSchin 	if(dir == nv_getval(opwdnod) || argc==2)
185da2e3ebdSchin 		dp = dir;	/* print out directory for cd - */
186da2e3ebdSchin 	if(flag)
187da2e3ebdSchin 	{
188da2e3ebdSchin 		dir = stakptr(PATH_OFFSET);
189da2e3ebdSchin 		if (!(dir=pathcanon(dir,PATH_PHYSICAL)))
190da2e3ebdSchin 		{
191da2e3ebdSchin 			dir = stakptr(PATH_OFFSET);
192da2e3ebdSchin 			errormsg(SH_DICT,ERROR_system(1),"%s:",dir);
193da2e3ebdSchin 		}
194da2e3ebdSchin 		stakseek(dir-stakptr(0));
195da2e3ebdSchin 	}
196da2e3ebdSchin 	dir = (char*)stakfreeze(1)+PATH_OFFSET;
197da2e3ebdSchin 	if(*dp && (*dp!='.'||dp[1]) && strchr(dir,'/'))
198da2e3ebdSchin 		sfputr(sfstdout,dir,'\n');
199da2e3ebdSchin 	if(*dir != '/')
200da2e3ebdSchin 		return(0);
201da2e3ebdSchin 	nv_putval(opwdnod,oldpwd,NV_RDONLY);
202da2e3ebdSchin 	flag = strlen(dir);
203da2e3ebdSchin 	/* delete trailing '/' */
204da2e3ebdSchin 	while(--flag>0 && dir[flag]=='/')
205da2e3ebdSchin 		dir[flag] = 0;
206da2e3ebdSchin 	nv_putval(pwdnod,dir,NV_RDONLY);
207da2e3ebdSchin 	nv_onattr(pwdnod,NV_NOFREE|NV_EXPORT);
208da2e3ebdSchin 	shp->pwd = pwdnod->nvalue.cp;
209da2e3ebdSchin 	nv_scan(shp->track_tree,rehash,(void*)0,NV_TAGGED,NV_TAGGED);
210*b30d1939SAndy Fiddaman 	path_newdir(shp,shp->pathlist);
211*b30d1939SAndy Fiddaman 	path_newdir(shp,shp->cdpathlist);
212*b30d1939SAndy Fiddaman 	if(oldpwd && (oldpwd!=e_dot))
213*b30d1939SAndy Fiddaman 		free(oldpwd);
214da2e3ebdSchin 	return(0);
215da2e3ebdSchin }
216da2e3ebdSchin 
b_pwd(int argc,char * argv[],Shbltin_t * context)217*b30d1939SAndy Fiddaman int	b_pwd(int argc, char *argv[],Shbltin_t *context)
218da2e3ebdSchin {
219da2e3ebdSchin 	register int n, flag = 0;
220da2e3ebdSchin 	register char *cp;
221*b30d1939SAndy Fiddaman 	register Shell_t *shp = context->shp;
222da2e3ebdSchin 	NOT_USED(argc);
223da2e3ebdSchin 	while((n = optget(argv,sh_optpwd))) switch(n)
224da2e3ebdSchin 	{
225da2e3ebdSchin 		case 'L':
226da2e3ebdSchin 			flag = 0;
227da2e3ebdSchin 			break;
228da2e3ebdSchin 		case 'P':
229da2e3ebdSchin 			flag = 1;
230da2e3ebdSchin 			break;
231da2e3ebdSchin 		case ':':
232da2e3ebdSchin 			errormsg(SH_DICT,2, "%s", opt_info.arg);
233da2e3ebdSchin 			break;
234da2e3ebdSchin 		case '?':
235da2e3ebdSchin 			errormsg(SH_DICT,ERROR_usage(2), "%s", opt_info.arg);
236da2e3ebdSchin 			break;
237da2e3ebdSchin 	}
238da2e3ebdSchin 	if(error_info.errors)
239da2e3ebdSchin 		errormsg(SH_DICT,ERROR_usage(2),"%s",optusage((char*)0));
240*b30d1939SAndy Fiddaman 	if(*(cp = path_pwd(shp,0)) != '/')
241da2e3ebdSchin 		errormsg(SH_DICT,ERROR_system(1), e_pwd);
242da2e3ebdSchin 	if(flag)
243da2e3ebdSchin 	{
244da2e3ebdSchin #if SHOPT_FS_3D
245*b30d1939SAndy Fiddaman 		if(shp->gd->lim.fs3d && (flag = mount(e_dot,NIL(char*),FS3D_GET|FS3D_VIEW,0))>=0)
246da2e3ebdSchin 		{
247da2e3ebdSchin 			cp = (char*)stakseek(++flag+PATH_MAX);
248da2e3ebdSchin 			mount(e_dot,cp,FS3D_GET|FS3D_VIEW|FS3D_SIZE(flag),0);
249da2e3ebdSchin 		}
250da2e3ebdSchin 		else
251da2e3ebdSchin #endif /* SHOPT_FS_3D */
252da2e3ebdSchin 			cp = strcpy(stakseek(strlen(cp)+PATH_MAX),cp);
253da2e3ebdSchin 		pathcanon(cp,PATH_PHYSICAL);
254da2e3ebdSchin 	}
255da2e3ebdSchin 	sfputr(sfstdout,cp,'\n');
256da2e3ebdSchin 	return(0);
257da2e3ebdSchin }
258da2e3ebdSchin 
259