4 #include "src/compat.h"
7 * Contains a routine to search a : separated list of
8 * paths (a la CDPATH) and make appropiate file names.
9 * Also contains a routine to simplify .'s and ..'s out of
12 * Larry Bouzane (larry@cs.mun.ca)
17 * Revision 1.2 1994/05/19 18:32:40 michael
18 * Merge complete, stdio replaced, various fixes. (pre autoconf)
20 * Revision 1.1 1994/04/06 13:14:03 michael
23 * Revision 4.2 1990/12/06 18:05:24 larry
24 * Updated test code to reflect parameter change.
25 * Fixed problem with /a/./.dir being simplified to /a and not /a/.dir due
26 * to *(cur+2) == *f test instead of the correct cur+2 == f
28 * Revision 4.1 90/10/29 14:42:19 larry
31 * Revision 3.1.0.4 89/02/16 20:28:36 larry
32 * Forgot to set *pathlist to NULL when last changed make_path().
34 * Revision 3.1.0.3 89/02/13 20:29:55 larry
35 * Fixed up cd so that it knew when a node from CDPATH was used and would
36 * print a message only when really necessary.
38 * Revision 3.1.0.2 89/02/13 17:51:22 larry
39 * Merged with Eric Gisin's version.
41 * Revision 3.1.0.1 89/02/13 17:50:58 larry
42 * *** empty log message ***
44 * Revision 3.1 89/02/13 17:49:28 larry
45 * *** empty log message ***
50 * Makes a filename into result using the following algorithm.
52 * - if file starts with '/', append file to result & set cdpathp to NULL
53 * - if file starts with ./ or ../ append cwd and file to result
54 * and set cdpathp to NULL
55 * - if the first element of cdpathp doesnt start with a '/' xx or '.' xx
56 * then cwd is appended to result.
57 * - the first element of cdpathp is appended to result
58 * - file is appended to result
59 * - cdpathp is set to the start of the next element in cdpathp (or NULL
60 * if there are no more elements.
61 * The return value indicates whether a non-null element from cdpathp
62 * was appened to result.
66 make_path(cwd
, file
, cdpathp
, xsp
, phys_pathp
)
69 char **cdpathp
; /* & of : separated list */
78 char *xp
= Xstring(*xsp
, xp
);
83 if (!ISRELPATH(file
)) {
92 if (ISDIRSEP(c
) || c
== '\0')
99 else if (use_cdpath
) {
102 for (pend
= plist
; *pend
&& *pend
!= PATHSEP
; pend
++)
105 *cdpathp
= *pend
? ++pend
: (char *) 0;
108 if ((use_cdpath
== 0 || !plen
|| ISRELPATH(plist
))
112 XcheckN(*xsp
, xp
, len
);
113 memcpy(xp
, cwd
, len
);
115 if (!ISDIRSEP(cwd
[len
- 1]))
116 Xput(*xsp
, xp
, DIRSEP
);
118 *phys_pathp
= Xlength(*xsp
, xp
);
119 if (use_cdpath
&& plen
) {
120 XcheckN(*xsp
, xp
, plen
);
121 memcpy(xp
, plist
, plen
);
123 if (!ISDIRSEP(plist
[plen
- 1]))
124 Xput(*xsp
, xp
, DIRSEP
);
129 len
= strlen(file
) + 1;
130 XcheckN(*xsp
, xp
, len
);
131 memcpy(xp
, file
, len
);
134 *cdpathp
= (char *) 0;
140 * Simplify pathnames containing "." and ".." entries.
141 * ie, simplify_path("/a/b/c/./../d/..") returns "/a/b"
150 char *very_start
= path
;
156 if ((isrooted
= ISROOTEDPATH(path
)))
158 #if defined (OS2) || defined (__CYGWIN__)
159 if (path
[0] && path
[1] == ':') /* skip a: */
161 #endif /* OS2 || __CYGWIN__ */
165 * /foo/../../bar /bar
166 * /foo/./blah/.. /foo
170 * foo/../../../bar ../../bar
175 * a:foo/../../blah a:../blah
179 /* preserve leading double-slash on pathnames (for UNC paths) */
180 if (path
[0] && ISDIRSEP(path
[0]) && path
[1] && ISDIRSEP(path
[1]))
182 #endif /* __CYGWIN__ */
184 for (cur
= t
= start
= very_start
; ; ) {
185 /* treat multiple '/'s as one '/' */
191 /* convert empty path to dot */
198 if (!t
[1] || ISDIRSEP(t
[1])) {
201 } else if (t
[1] == '.' && (!t
[2] || ISDIRSEP(t
[2]))) {
202 if (!isrooted
&& cur
== start
) {
203 if (cur
!= very_start
)
208 } else if (cur
!= start
)
209 while (--cur
> start
&& !ISDIRSEP(*cur
))
216 if (cur
!= very_start
)
219 /* find/copy next component of pathname */
220 while (*t
&& !ISDIRSEP(*t
))
227 set_current_wd(char *path
)
232 if (!p
&& !(p
= get_current_dir_name()))
237 if (len
> current_wd_size
)
238 current_wd
= aresize(current_wd
, current_wd_size
= len
, APERM
);
239 memcpy(current_wd
, p
, len
);
240 if (p
!= path
&& p
!= NULL
)
249 char *cp
, cdpath
[256], pwd
[256], file
[256], result
[256];
251 printf("enter CDPATH: "); gets(cdpath
);
252 printf("enter PWD: "); gets(pwd
);
254 if (printf("Enter file: "), gets(file
) == 0)
258 rv
= make_path(pwd
, file
, &cp
, result
, sizeof(result
));
259 printf("make_path returns (%d), \"%s\" ", rv
, result
);
260 simplify_path(result
);
261 printf("(simpifies to \"%s\")\n", result
);