1 /***********************************************************************
2 * *
3 * This software is part of the ast package *
4 * Copyright (c) 1985-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 * 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
23 /*
24 * Glenn Fowler
25 * AT&T Research
26 *
27 * return full path to p with mode access using $PATH
28 * a!=0 enables related root search
29 * a!=0 && a!="" searches a dir first
30 * the related root must have a bin subdir
31 * p==0 sets the cached relative dir to a
32 * full path returned in path buffer
33 * if path==0 then the space is malloc'd
34 */
35
36 #define _AST_API_H 1
37
38 #include <ast.h>
39
40 char*
pathpath(char * path,const char * p,const char * a,int mode)41 pathpath(char* path, const char* p, const char* a, int mode)
42 {
43 return pathpath_20100601(p, a, mode, path, PATH_MAX);
44 }
45
46 #undef _AST_API_H
47
48 #include <ast_api.h>
49
50 char*
pathpath_20100601(const char * p,const char * a,int mode,register char * path,size_t size)51 pathpath_20100601(const char* p, const char* a, int mode, register char* path, size_t size)
52 {
53 register char* s;
54 char* x;
55 char buf[PATH_MAX];
56
57 static char* cmd;
58
59 if (!path)
60 {
61 path = buf;
62 if (!size || size > sizeof(buf))
63 size = sizeof(buf);
64 }
65 if (!p)
66 {
67 if (cmd)
68 free(cmd);
69 cmd = a ? strdup(a) : (char*)0;
70 return 0;
71 }
72 if (strlen(p) < size)
73 {
74 strcpy(path, p);
75 if (pathexists(path, mode))
76 {
77 if (*p != '/' && (mode & PATH_ABSOLUTE))
78 {
79 getcwd(buf, sizeof(buf));
80 s = buf + strlen(buf);
81 sfsprintf(s, sizeof(buf) - (s - buf), "/%s", p);
82 if (path != buf)
83 strcpy(path, buf);
84 }
85 return (path == buf) ? strdup(path) : path;
86 }
87 }
88 if (*p == '/')
89 a = 0;
90 else if (s = (char*)a)
91 {
92 x = s;
93 if (strchr(p, '/'))
94 {
95 a = p;
96 p = "..";
97 }
98 else
99 a = 0;
100 if ((!cmd || *cmd) && (strchr(s, '/') || (s = cmd)))
101 {
102 if (!cmd && *s == '/')
103 cmd = strdup(s);
104 if (strlen(s) < (sizeof(buf) - 6))
105 {
106 s = strcopy(path, s);
107 for (;;)
108 {
109 do if (s <= path) goto normal; while (*--s == '/');
110 do if (s <= path) goto normal; while (*--s != '/');
111 strcpy(s + 1, "bin");
112 if (pathexists(path, PATH_EXECUTE))
113 {
114 if (s = pathaccess(path, p, a, mode, path, size))
115 return path == buf ? strdup(s) : s;
116 goto normal;
117 }
118 }
119 normal: ;
120 }
121 }
122 }
123 x = !a && strchr(p, '/') ? "" : pathbin();
124 if (!(s = pathaccess(x, p, a, mode, path, size)) && !*x && (x = getenv("FPATH")))
125 s = pathaccess(x, p, a, mode, path, size);
126 return (s && path == buf) ? strdup(s) : s;
127 }
128