1da2e3ebdSchin /***********************************************************************
2da2e3ebdSchin * *
3da2e3ebdSchin * This software is part of the ast package *
4*3e14f97fSRoger A. Faulkner * Copyright (c) 1982-2010 AT&T Intellectual Property *
5da2e3ebdSchin * and is licensed under the *
6da2e3ebdSchin * Common Public License, Version 1.0 *
77c2fbfb3SApril Chin * by AT&T Intellectual Property *
8da2e3ebdSchin * *
9da2e3ebdSchin * A copy of the License is available at *
10da2e3ebdSchin * http://www.opensource.org/licenses/cpl1.0.txt *
11da2e3ebdSchin * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
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!='/')
49da2e3ebdSchin nv_unset(np);
50da2e3ebdSchin }
51da2e3ebdSchin
b_cd(int argc,char * argv[],void * extra)52da2e3ebdSchin int b_cd(int argc, char *argv[],void *extra)
53da2e3ebdSchin {
54da2e3ebdSchin register char *dir;
55da2e3ebdSchin Pathcomp_t *cdpath = 0;
56da2e3ebdSchin register const char *dp;
577c2fbfb3SApril Chin register Shell_t *shp = ((Shbltin_t*)extra)->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));
84da2e3ebdSchin oldpwd = (char*)shp->pwd;
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]);
89da2e3ebdSchin else if(!dir || *dir==0)
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 {
101da2e3ebdSchin if(!(cdpath = (Pathcomp_t*)shp->cdpathlist) && (dp=(CDPNOD)->nvalue.cp))
102da2e3ebdSchin {
103da2e3ebdSchin if(cdpath=path_addpath((Pathcomp_t*)0,dp,PATH_CDPATH))
104da2e3ebdSchin {
105da2e3ebdSchin shp->cdpathlist = (void*)cdpath;
106da2e3ebdSchin cdpath->shp = shp;
107da2e3ebdSchin }
108da2e3ebdSchin }
109da2e3ebdSchin if(!oldpwd)
110da2e3ebdSchin oldpwd = path_pwd(1);
111da2e3ebdSchin }
112da2e3ebdSchin if(*dir=='.')
113da2e3ebdSchin {
114da2e3ebdSchin /* test for pathname . ./ .. or ../ */
115da2e3ebdSchin if(*(dp=dir+1) == '.')
116da2e3ebdSchin dp++;
117da2e3ebdSchin if(*dp==0 || *dp=='/')
118da2e3ebdSchin cdpath = 0;
119da2e3ebdSchin }
120da2e3ebdSchin rval = -1;
121da2e3ebdSchin do
122da2e3ebdSchin {
123da2e3ebdSchin dp = cdpath?cdpath->name:"";
124da2e3ebdSchin cdpath = path_nextcomp(cdpath,dir,0);
125da2e3ebdSchin #if _WINIX
126da2e3ebdSchin if(*stakptr(PATH_OFFSET+1)==':' && isalpha(*stakptr(PATH_OFFSET)))
127da2e3ebdSchin {
128da2e3ebdSchin *stakptr(PATH_OFFSET+1) = *stakptr(PATH_OFFSET);
129da2e3ebdSchin *stakptr(PATH_OFFSET)='/';
130da2e3ebdSchin }
131da2e3ebdSchin #endif /* _WINIX */
132da2e3ebdSchin if(*stakptr(PATH_OFFSET)!='/')
133da2e3ebdSchin
134da2e3ebdSchin {
135da2e3ebdSchin char *last=(char*)stakfreeze(1);
136da2e3ebdSchin stakseek(PATH_OFFSET);
137da2e3ebdSchin stakputs(oldpwd);
138da2e3ebdSchin /* don't add '/' of oldpwd is / itself */
139da2e3ebdSchin if(*oldpwd!='/' || oldpwd[1])
140da2e3ebdSchin stakputc('/');
141da2e3ebdSchin stakputs(last+PATH_OFFSET);
142da2e3ebdSchin stakputc(0);
143da2e3ebdSchin }
144da2e3ebdSchin if(!flag)
145da2e3ebdSchin {
146da2e3ebdSchin register char *cp;
147da2e3ebdSchin stakseek(PATH_MAX+PATH_OFFSET);
148da2e3ebdSchin #if SHOPT_FS_3D
149da2e3ebdSchin if(!(cp = pathcanon(stakptr(PATH_OFFSET),PATH_DOTDOT)))
150da2e3ebdSchin continue;
151da2e3ebdSchin /* eliminate trailing '/' */
152da2e3ebdSchin while(*--cp == '/' && cp>stakptr(PATH_OFFSET))
153da2e3ebdSchin *cp = 0;
154da2e3ebdSchin #else
155da2e3ebdSchin if(*(cp=stakptr(PATH_OFFSET))=='/')
156da2e3ebdSchin if(!pathcanon(cp,PATH_DOTDOT))
157da2e3ebdSchin continue;
158da2e3ebdSchin #endif /* SHOPT_FS_3D */
159da2e3ebdSchin }
160da2e3ebdSchin if((rval=chdir(path_relative(stakptr(PATH_OFFSET)))) >= 0)
161da2e3ebdSchin goto success;
162da2e3ebdSchin if(errno!=ENOENT && saverrno==0)
163da2e3ebdSchin saverrno=errno;
164da2e3ebdSchin }
165da2e3ebdSchin while(cdpath);
166da2e3ebdSchin if(rval<0 && *dir=='/' && *(path_relative(stakptr(PATH_OFFSET)))!='/')
167da2e3ebdSchin rval = chdir(dir);
168da2e3ebdSchin /* use absolute chdir() if relative chdir() fails */
169da2e3ebdSchin if(rval<0)
170da2e3ebdSchin {
171da2e3ebdSchin if(saverrno)
172da2e3ebdSchin errno = saverrno;
173da2e3ebdSchin errormsg(SH_DICT,ERROR_system(1),"%s:",dir);
174da2e3ebdSchin }
175da2e3ebdSchin success:
176da2e3ebdSchin if(dir == nv_getval(opwdnod) || argc==2)
177da2e3ebdSchin dp = dir; /* print out directory for cd - */
178da2e3ebdSchin if(flag)
179da2e3ebdSchin {
180da2e3ebdSchin dir = stakptr(PATH_OFFSET);
181da2e3ebdSchin if (!(dir=pathcanon(dir,PATH_PHYSICAL)))
182da2e3ebdSchin {
183da2e3ebdSchin dir = stakptr(PATH_OFFSET);
184da2e3ebdSchin errormsg(SH_DICT,ERROR_system(1),"%s:",dir);
185da2e3ebdSchin }
186da2e3ebdSchin stakseek(dir-stakptr(0));
187da2e3ebdSchin }
188da2e3ebdSchin dir = (char*)stakfreeze(1)+PATH_OFFSET;
189da2e3ebdSchin if(*dp && (*dp!='.'||dp[1]) && strchr(dir,'/'))
190da2e3ebdSchin sfputr(sfstdout,dir,'\n');
191da2e3ebdSchin if(*dir != '/')
192da2e3ebdSchin return(0);
193da2e3ebdSchin nv_putval(opwdnod,oldpwd,NV_RDONLY);
194da2e3ebdSchin if(oldpwd)
195da2e3ebdSchin free(oldpwd);
196da2e3ebdSchin flag = strlen(dir);
197da2e3ebdSchin /* delete trailing '/' */
198da2e3ebdSchin while(--flag>0 && dir[flag]=='/')
199da2e3ebdSchin dir[flag] = 0;
200da2e3ebdSchin nv_putval(pwdnod,dir,NV_RDONLY);
201da2e3ebdSchin nv_onattr(pwdnod,NV_NOFREE|NV_EXPORT);
202da2e3ebdSchin shp->pwd = pwdnod->nvalue.cp;
203da2e3ebdSchin nv_scan(shp->track_tree,rehash,(void*)0,NV_TAGGED,NV_TAGGED);
204da2e3ebdSchin path_newdir(shp->pathlist);
205da2e3ebdSchin path_newdir(shp->cdpathlist);
206da2e3ebdSchin return(0);
207da2e3ebdSchin }
208da2e3ebdSchin
b_pwd(int argc,char * argv[],void * extra)209da2e3ebdSchin int b_pwd(int argc, char *argv[],void *extra)
210da2e3ebdSchin {
211da2e3ebdSchin register int n, flag = 0;
212da2e3ebdSchin register char *cp;
213*3e14f97fSRoger A. Faulkner #if SHOPT_FS_3D
2147c2fbfb3SApril Chin register Shell_t *shp = ((Shbltin_t*)extra)->shp;
215*3e14f97fSRoger A. Faulkner #else
216*3e14f97fSRoger A. Faulkner NOT_USED(extra);
217*3e14f97fSRoger A. Faulkner #endif
218da2e3ebdSchin NOT_USED(argc);
219da2e3ebdSchin while((n = optget(argv,sh_optpwd))) switch(n)
220da2e3ebdSchin {
221da2e3ebdSchin case 'L':
222da2e3ebdSchin flag = 0;
223da2e3ebdSchin break;
224da2e3ebdSchin case 'P':
225da2e3ebdSchin flag = 1;
226da2e3ebdSchin break;
227da2e3ebdSchin case ':':
228da2e3ebdSchin errormsg(SH_DICT,2, "%s", opt_info.arg);
229da2e3ebdSchin break;
230da2e3ebdSchin case '?':
231da2e3ebdSchin errormsg(SH_DICT,ERROR_usage(2), "%s", opt_info.arg);
232da2e3ebdSchin break;
233da2e3ebdSchin }
234da2e3ebdSchin if(error_info.errors)
235da2e3ebdSchin errormsg(SH_DICT,ERROR_usage(2),"%s",optusage((char*)0));
236da2e3ebdSchin if(*(cp = path_pwd(0)) != '/')
237da2e3ebdSchin errormsg(SH_DICT,ERROR_system(1), e_pwd);
238da2e3ebdSchin if(flag)
239da2e3ebdSchin {
240da2e3ebdSchin #if SHOPT_FS_3D
241da2e3ebdSchin if(shp->lim.fs3d && (flag = mount(e_dot,NIL(char*),FS3D_GET|FS3D_VIEW,0))>=0)
242da2e3ebdSchin {
243da2e3ebdSchin cp = (char*)stakseek(++flag+PATH_MAX);
244da2e3ebdSchin mount(e_dot,cp,FS3D_GET|FS3D_VIEW|FS3D_SIZE(flag),0);
245da2e3ebdSchin }
246da2e3ebdSchin else
247da2e3ebdSchin #endif /* SHOPT_FS_3D */
248da2e3ebdSchin cp = strcpy(stakseek(strlen(cp)+PATH_MAX),cp);
249da2e3ebdSchin pathcanon(cp,PATH_PHYSICAL);
250da2e3ebdSchin }
251da2e3ebdSchin sfputr(sfstdout,cp,'\n');
252da2e3ebdSchin return(0);
253da2e3ebdSchin }
254da2e3ebdSchin
255