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