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
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#include <ast.h>
37
38char*
39pathpath(register char* path, const char* p, const char* a, int mode)
40{
41	register char*	s;
42	char*		x;
43	char		buf[PATH_MAX];
44
45	static char*	cmd;
46
47	if (!path)
48		path = buf;
49	if (!p)
50	{
51		if (cmd)
52			free(cmd);
53		cmd = a ? strdup(a) : (char*)0;
54		return 0;
55	}
56	if (strlen(p) < PATH_MAX)
57	{
58		strcpy(path, p);
59		if (pathexists(path, mode))
60		{
61			if (*p != '/' && (mode & PATH_ABSOLUTE))
62			{
63				getcwd(buf, sizeof(buf));
64				s = buf + strlen(buf);
65				sfsprintf(s, sizeof(buf) - (s - buf), "/%s", p);
66				if (path != buf)
67					strcpy(path, buf);
68			}
69			return (path == buf) ? strdup(path) : path;
70		}
71	}
72	if (*p == '/')
73		a = 0;
74	else if (s = (char*)a)
75	{
76		x = s;
77		if (strchr(p, '/'))
78		{
79			a = p;
80			p = "..";
81		}
82		else
83			a = 0;
84		if ((!cmd || *cmd) && (strchr(s, '/') || (s = cmd)))
85		{
86			if (!cmd && *s == '/')
87				cmd = strdup(s);
88			if (strlen(s) < (sizeof(buf) - 6))
89			{
90				s = strcopy(path, s);
91				for (;;)
92				{
93					do if (s <= path) goto normal; while (*--s == '/');
94					do if (s <= path) goto normal; while (*--s != '/');
95					strcpy(s + 1, "bin");
96					if (pathexists(path, PATH_EXECUTE))
97					{
98						if (s = pathaccess(path, path, p, a, mode))
99							return path == buf ? strdup(s) : s;
100						goto normal;
101					}
102				}
103			normal: ;
104			}
105		}
106	}
107	x = !a && strchr(p, '/') ? "" : pathbin();
108	if (!(s = pathaccess(path, x, p, a, mode)) && !*x && (x = getenv("FPATH")))
109		s = pathaccess(path, x, p, a, mode);
110	return (s && path == buf) ? strdup(s) : s;
111}
112