dmake: do not set MAKEFLAGS=k
[unleashed/tickless.git] / usr / src / lib / libast / common / path / pathcd.c
blobb9cd83726818465a0d529b4e6c550309251a97b7
1 /***********************************************************************
2 * *
3 * This software is part of the ast package *
4 * Copyright (c) 1985-2010 AT&T Intellectual Property *
5 * and is licensed under the *
6 * Common Public License, Version 1.0 *
7 * by AT&T Intellectual Property *
8 * *
9 * A copy of the License is available at *
10 * http://www.opensource.org/licenses/cpl1.0.txt *
11 * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
12 * *
13 * Information and Software Systems Research *
14 * AT&T Research *
15 * Florham Park NJ *
16 * *
17 * Glenn Fowler <gsf@research.att.com> *
18 * David Korn <dgk@research.att.com> *
19 * Phong Vo <kpv@research.att.com> *
20 * *
21 ***********************************************************************/
22 #pragma prototyped
24 * K. P. Vo
25 * G. S. Fowler
26 * AT&T Research
29 #include <ast.h>
30 #include <error.h>
31 #include <stk.h>
33 #if DEBUG
35 #undef PATH_MAX
37 #define PATH_MAX 16
39 static int
40 vchdir(const char* path)
42 int n;
44 if (strlen(path) >= PATH_MAX)
46 errno = ENAMETOOLONG;
47 n = -1;
49 else n = chdir(path);
50 return n;
53 #define chdir(p) vchdir(p)
55 #endif
58 * set the current directory to path
59 * if path is long and home!=0 then pathcd(home,0)
60 * is called on intermediate chdir errors
63 int
64 pathcd(const char* path, const char* home)
66 register char* p = (char*)path;
67 register char* s;
68 register int n;
69 int i;
70 int r;
72 r = 0;
73 for (;;)
76 * this should work 99% of the time
79 if (!chdir(p))
80 return r;
83 * chdir failed
86 if ((n = strlen(p)) < PATH_MAX)
87 return -1;
88 #ifdef ENAMETOOLONG
89 if (errno != ENAMETOOLONG)
90 return -1;
91 #endif
94 * path is too long -- copy so it can be modified in place
97 i = stktell(stkstd);
98 sfputr(stkstd, p, 0);
99 stkseek(stkstd, i);
100 p = stkptr(stkstd, i);
101 for (;;)
104 * get a short prefix component
107 s = p + PATH_MAX;
108 while (--s >= p && *s != '/');
109 if (s <= p)
110 break;
113 * chdir to the prefix
116 *s++ = 0;
117 if (chdir(p))
118 break;
121 * do the remainder
124 if ((n -= s - p) < PATH_MAX)
126 if (chdir(s))
127 break;
128 return r;
130 p = s;
134 * try to recover back to home
137 if (!(p = (char*)home))
138 return -1;
139 home = 0;
140 r = -1;