Magellan Linux

Annotation of /trunk/mkinitrd-magellan/klibc/usr/dash/cd.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1122 - (hide annotations) (download)
Wed Aug 18 21:11:40 2010 UTC (13 years, 9 months ago) by niro
File MIME type: text/plain
File size: 6287 byte(s)
-updated to klibc-1.5.19
1 niro 532 /*-
2     * Copyright (c) 1991, 1993
3     * The Regents of the University of California. All rights reserved.
4     * Copyright (c) 1997-2005
5     * Herbert Xu <herbert@gondor.apana.org.au>. All rights reserved.
6     *
7     * This code is derived from software contributed to Berkeley by
8     * Kenneth Almquist.
9     *
10     * Redistribution and use in source and binary forms, with or without
11     * modification, are permitted provided that the following conditions
12     * are met:
13     * 1. Redistributions of source code must retain the above copyright
14     * notice, this list of conditions and the following disclaimer.
15     * 2. Redistributions in binary form must reproduce the above copyright
16     * notice, this list of conditions and the following disclaimer in the
17     * documentation and/or other materials provided with the distribution.
18     * 3. Neither the name of the University nor the names of its contributors
19     * may be used to endorse or promote products derived from this software
20     * without specific prior written permission.
21     *
22     * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23     * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24     * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25     * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26     * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27     * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28     * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29     * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30     * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31     * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32     * SUCH DAMAGE.
33     */
34    
35     #include <sys/types.h>
36     #include <sys/stat.h>
37     #include <stdlib.h>
38     #include <string.h>
39     #include <unistd.h>
40    
41     /*
42     * The cd and pwd commands.
43     */
44    
45     #include "shell.h"
46     #include "var.h"
47     #include "nodes.h" /* for jobs.h */
48     #include "jobs.h"
49     #include "options.h"
50     #include "output.h"
51     #include "memalloc.h"
52     #include "error.h"
53     #include "exec.h"
54     #include "redir.h"
55 niro 1122 #include "main.h"
56 niro 532 #include "mystring.h"
57     #include "show.h"
58     #include "cd.h"
59    
60     #define CD_PHYSICAL 1
61     #define CD_PRINT 2
62    
63     STATIC int docd(const char *, int);
64     STATIC const char *updatepwd(const char *);
65     STATIC char *getpwd(void);
66     STATIC int cdopt(void);
67    
68     STATIC char *curdir = nullstr; /* current working directory */
69     STATIC char *physdir = nullstr; /* physical working directory */
70    
71     STATIC int
72     cdopt()
73     {
74     int flags = 0;
75     int i, j;
76    
77     j = 'L';
78     while ((i = nextopt("LP"))) {
79     if (i != j) {
80     flags ^= CD_PHYSICAL;
81     j = i;
82     }
83     }
84    
85     return flags;
86     }
87    
88     int
89     cdcmd(int argc, char **argv)
90     {
91     const char *dest;
92     const char *path;
93     const char *p;
94     char c;
95     struct stat statb;
96     int flags;
97    
98     flags = cdopt();
99     dest = *argptr;
100     if (!dest)
101     dest = bltinlookup(homestr);
102     else if (dest[0] == '-' && dest[1] == '\0') {
103     dest = bltinlookup("OLDPWD");
104     flags |= CD_PRINT;
105     }
106     if (!dest)
107     dest = nullstr;
108     if (*dest == '/')
109 niro 1122 goto step6;
110 niro 532 if (*dest == '.') {
111     c = dest[1];
112     dotdot:
113     switch (c) {
114     case '\0':
115     case '/':
116     goto step6;
117     case '.':
118     c = dest[2];
119     if (c != '.')
120     goto dotdot;
121     }
122     }
123     if (!*dest)
124     dest = ".";
125 niro 1122 path = bltinlookup("CDPATH");
126     while (path) {
127 niro 532 c = *path;
128     p = padvance(&path, dest);
129     if (stat(p, &statb) >= 0 && S_ISDIR(statb.st_mode)) {
130     if (c && c != ':')
131     flags |= CD_PRINT;
132     docd:
133     if (!docd(p, flags))
134     goto out;
135 niro 1122 goto err;
136 niro 532 }
137 niro 1122 }
138    
139     step6:
140     p = dest;
141     goto docd;
142    
143     err:
144 niro 532 sh_error("can't cd to %s", dest);
145     /* NOTREACHED */
146     out:
147     if (flags & CD_PRINT)
148     out1fmt(snlfmt, curdir);
149     return 0;
150     }
151    
152    
153     /*
154     * Actually do the chdir. We also call hashcd to let the routines in exec.c
155     * know that the current directory has changed.
156     */
157    
158     STATIC int
159     docd(const char *dest, int flags)
160     {
161     const char *dir = 0;
162     int err;
163    
164     TRACE(("docd(\"%s\", %d) called\n", dest, flags));
165    
166     INTOFF;
167     if (!(flags & CD_PHYSICAL)) {
168     dir = updatepwd(dest);
169     if (dir)
170     dest = dir;
171     }
172     err = chdir(dest);
173     if (err)
174     goto out;
175     setpwd(dir, 1);
176     hashcd();
177     out:
178     INTON;
179     return err;
180     }
181    
182    
183     /*
184     * Update curdir (the name of the current directory) in response to a
185     * cd command.
186     */
187    
188     STATIC const char *
189     updatepwd(const char *dir)
190     {
191     char *new;
192     char *p;
193     char *cdcomppath;
194     const char *lim;
195    
196     cdcomppath = sstrdup(dir);
197     STARTSTACKSTR(new);
198     if (*dir != '/') {
199     if (curdir == nullstr)
200     return 0;
201     new = stputs(curdir, new);
202     }
203     new = makestrspace(strlen(dir) + 2, new);
204     lim = stackblock() + 1;
205     if (*dir != '/') {
206     if (new[-1] != '/')
207     USTPUTC('/', new);
208     if (new > lim && *lim == '/')
209     lim++;
210     } else {
211     USTPUTC('/', new);
212     cdcomppath++;
213     if (dir[1] == '/' && dir[2] != '/') {
214     USTPUTC('/', new);
215     cdcomppath++;
216     lim++;
217     }
218     }
219     p = strtok(cdcomppath, "/");
220     while (p) {
221     switch(*p) {
222     case '.':
223     if (p[1] == '.' && p[2] == '\0') {
224     while (new > lim) {
225     STUNPUTC(new);
226     if (new[-1] == '/')
227     break;
228     }
229     break;
230     } else if (p[1] == '\0')
231     break;
232     /* fall through */
233     default:
234     new = stputs(p, new);
235     USTPUTC('/', new);
236     }
237     p = strtok(0, "/");
238     }
239     if (new > lim)
240     STUNPUTC(new);
241     *new = 0;
242     return stackblock();
243     }
244    
245    
246     /*
247     * Find out what the current directory is. If we already know the current
248     * directory, this routine returns immediately.
249     */
250     inline
251     STATIC char *
252     getpwd()
253     {
254 niro 1122 #ifdef __GLIBC__
255     char *dir = getcwd(0, 0);
256     if (dir)
257     return dir;
258     #else
259 niro 532 char buf[PATH_MAX];
260 niro 1122 if(getcwd(buf, sizeof(buf)))
261     return savestr(buf);
262     #endif
263     sh_warnx("getcwd() failed: %s", strerror(errno));
264     return nullstr;
265 niro 532 }
266    
267     int
268     pwdcmd(int argc, char **argv)
269     {
270     int flags;
271     const char *dir = curdir;
272    
273     flags = cdopt();
274     if (flags) {
275     if (physdir == nullstr)
276     setpwd(dir, 0);
277     dir = physdir;
278     }
279     out1fmt(snlfmt, dir);
280     return 0;
281     }
282    
283     void
284     setpwd(const char *val, int setold)
285     {
286     char *oldcur, *dir;
287    
288     oldcur = dir = curdir;
289    
290     if (setold) {
291     setvar("OLDPWD", oldcur, VEXPORT);
292     }
293     INTOFF;
294     if (physdir != nullstr) {
295     if (physdir != oldcur)
296     free(physdir);
297     physdir = nullstr;
298     }
299     if (oldcur == val || !val) {
300     char *s = getpwd();
301     physdir = s;
302     if (!val)
303     dir = s;
304     } else
305     dir = savestr(val);
306     if (oldcur != dir && oldcur != nullstr) {
307     free(oldcur);
308     }
309     curdir = dir;
310     INTON;
311     setvar("PWD", dir, VEXPORT);
312     }