1*b30d1939SAndy Fiddaman /***********************************************************************
2*b30d1939SAndy Fiddaman *                                                                      *
3*b30d1939SAndy Fiddaman *               This software is part of the ast package               *
4*b30d1939SAndy Fiddaman *          Copyright (c) 1985-2011 AT&T Intellectual Property          *
5*b30d1939SAndy Fiddaman *                      and is licensed under the                       *
6*b30d1939SAndy Fiddaman *                 Eclipse Public License, Version 1.0                  *
7*b30d1939SAndy Fiddaman *                    by AT&T Intellectual Property                     *
8*b30d1939SAndy Fiddaman *                                                                      *
9*b30d1939SAndy Fiddaman *                A copy of the License is available at                 *
10*b30d1939SAndy Fiddaman *          http://www.eclipse.org/org/documents/epl-v10.html           *
11*b30d1939SAndy Fiddaman *         (with md5 checksum b35adb5213ca9657e911e9befb180842)         *
12*b30d1939SAndy Fiddaman *                                                                      *
13*b30d1939SAndy Fiddaman *              Information and Software Systems Research               *
14*b30d1939SAndy Fiddaman *                            AT&T Research                             *
15*b30d1939SAndy Fiddaman *                           Florham Park NJ                            *
16*b30d1939SAndy Fiddaman *                                                                      *
17*b30d1939SAndy Fiddaman *                 Glenn Fowler <gsf@research.att.com>                  *
18*b30d1939SAndy Fiddaman *                  David Korn <dgk@research.att.com>                   *
19*b30d1939SAndy Fiddaman *                   Phong Vo <kpv@research.att.com>                    *
20*b30d1939SAndy Fiddaman *                                                                      *
21*b30d1939SAndy Fiddaman ***********************************************************************/
22*b30d1939SAndy Fiddaman #pragma prototyped
23*b30d1939SAndy Fiddaman /*
24*b30d1939SAndy Fiddaman  * Glenn Fowler
25*b30d1939SAndy Fiddaman  * AT&T Research
26*b30d1939SAndy Fiddaman  *
27*b30d1939SAndy Fiddaman  * include style search support
28*b30d1939SAndy Fiddaman  */
29*b30d1939SAndy Fiddaman 
30*b30d1939SAndy Fiddaman #include <ast.h>
31*b30d1939SAndy Fiddaman #include <error.h>
32*b30d1939SAndy Fiddaman #include <ls.h>
33*b30d1939SAndy Fiddaman 
34*b30d1939SAndy Fiddaman #define directory(p,s)	(stat((p),(s))>=0&&S_ISDIR((s)->st_mode))
35*b30d1939SAndy Fiddaman #define regular(p,s)	(stat((p),(s))>=0&&(S_ISREG((s)->st_mode)||streq(p,"/dev/null")))
36*b30d1939SAndy Fiddaman 
37*b30d1939SAndy Fiddaman typedef struct Dir_s			/* directory list element	*/
38*b30d1939SAndy Fiddaman {
39*b30d1939SAndy Fiddaman 	struct Dir_s*	next;		/* next in list			*/
40*b30d1939SAndy Fiddaman 	char		dir[1];		/* directory path		*/
41*b30d1939SAndy Fiddaman } Dir_t;
42*b30d1939SAndy Fiddaman 
43*b30d1939SAndy Fiddaman static struct				/* directory list state		*/
44*b30d1939SAndy Fiddaman {
45*b30d1939SAndy Fiddaman 	Dir_t*		head;		/* directory list head		*/
46*b30d1939SAndy Fiddaman 	Dir_t*		tail;		/* directory list tail		*/
47*b30d1939SAndy Fiddaman } state;
48*b30d1939SAndy Fiddaman 
49*b30d1939SAndy Fiddaman /*
50*b30d1939SAndy Fiddaman  * append dir to pathfind() include list
51*b30d1939SAndy Fiddaman  */
52*b30d1939SAndy Fiddaman 
53*b30d1939SAndy Fiddaman int
pathinclude(const char * dir)54*b30d1939SAndy Fiddaman pathinclude(const char* dir)
55*b30d1939SAndy Fiddaman {
56*b30d1939SAndy Fiddaman 	register Dir_t*	dp;
57*b30d1939SAndy Fiddaman 	struct stat	st;
58*b30d1939SAndy Fiddaman 
59*b30d1939SAndy Fiddaman 	if (dir && *dir && !streq(dir, ".") && directory(dir, &st))
60*b30d1939SAndy Fiddaman 	{
61*b30d1939SAndy Fiddaman 		for (dp = state.head; dp; dp = dp->next)
62*b30d1939SAndy Fiddaman 			if (streq(dir, dp->dir))
63*b30d1939SAndy Fiddaman 				return 0;
64*b30d1939SAndy Fiddaman 		if (!(dp = oldof(0, Dir_t, 1, strlen(dir))))
65*b30d1939SAndy Fiddaman 			return -1;
66*b30d1939SAndy Fiddaman 		strcpy(dp->dir, dir);
67*b30d1939SAndy Fiddaman 		dp->next = 0;
68*b30d1939SAndy Fiddaman 		if (state.tail)
69*b30d1939SAndy Fiddaman 			state.tail = state.tail->next = dp;
70*b30d1939SAndy Fiddaman 		else
71*b30d1939SAndy Fiddaman 			state.head = state.tail = dp;
72*b30d1939SAndy Fiddaman 	}
73*b30d1939SAndy Fiddaman 	return 0;
74*b30d1939SAndy Fiddaman }
75*b30d1939SAndy Fiddaman 
76*b30d1939SAndy Fiddaman /*
77*b30d1939SAndy Fiddaman  * return path to name using pathinclude() list
78*b30d1939SAndy Fiddaman  * path placed in <buf,size>
79*b30d1939SAndy Fiddaman  * if lib!=0 then pathpath() attempted after include search
80*b30d1939SAndy Fiddaman  * if type!=0 and name has no '.' then file.type also attempted
81*b30d1939SAndy Fiddaman  * any *: prefix in lib is ignored (discipline library dictionary support)
82*b30d1939SAndy Fiddaman  */
83*b30d1939SAndy Fiddaman 
84*b30d1939SAndy Fiddaman char*
pathfind(const char * name,const char * lib,const char * type,char * buf,size_t size)85*b30d1939SAndy Fiddaman pathfind(const char* name, const char* lib, const char* type, char* buf, size_t size)
86*b30d1939SAndy Fiddaman {
87*b30d1939SAndy Fiddaman 	register Dir_t*		dp;
88*b30d1939SAndy Fiddaman 	register char*		s;
89*b30d1939SAndy Fiddaman 	char			tmp[PATH_MAX];
90*b30d1939SAndy Fiddaman 	struct stat		st;
91*b30d1939SAndy Fiddaman 
92*b30d1939SAndy Fiddaman 	if (((s = strrchr(name, '/')) || (s = (char*)name)) && strchr(s, '.'))
93*b30d1939SAndy Fiddaman 		type = 0;
94*b30d1939SAndy Fiddaman 
95*b30d1939SAndy Fiddaman 	/*
96*b30d1939SAndy Fiddaman 	 * always check the unadorned path first
97*b30d1939SAndy Fiddaman 	 * this handles . and absolute paths
98*b30d1939SAndy Fiddaman 	 */
99*b30d1939SAndy Fiddaman 
100*b30d1939SAndy Fiddaman 	if (regular(name, &st))
101*b30d1939SAndy Fiddaman 	{
102*b30d1939SAndy Fiddaman 		strncopy(buf, name, size);
103*b30d1939SAndy Fiddaman 		return buf;
104*b30d1939SAndy Fiddaman 	}
105*b30d1939SAndy Fiddaman 	if (type)
106*b30d1939SAndy Fiddaman 	{
107*b30d1939SAndy Fiddaman 		sfsprintf(buf, size, "%s.%s", name, type);
108*b30d1939SAndy Fiddaman 		if (regular(buf, &st))
109*b30d1939SAndy Fiddaman 			return buf;
110*b30d1939SAndy Fiddaman 	}
111*b30d1939SAndy Fiddaman 	if (*name == '/')
112*b30d1939SAndy Fiddaman 		return 0;
113*b30d1939SAndy Fiddaman 
114*b30d1939SAndy Fiddaman 	/*
115*b30d1939SAndy Fiddaman 	 * check the directory of the including file
116*b30d1939SAndy Fiddaman 	 * on the assumption that error_info.file is properly stacked
117*b30d1939SAndy Fiddaman 	 */
118*b30d1939SAndy Fiddaman 
119*b30d1939SAndy Fiddaman 	if (error_info.file && (s = strrchr(error_info.file, '/')))
120*b30d1939SAndy Fiddaman 	{
121*b30d1939SAndy Fiddaman 		sfsprintf(buf, size, "%-.*s%s", s - error_info.file + 1, error_info.file, name);
122*b30d1939SAndy Fiddaman 		if (regular(buf, &st))
123*b30d1939SAndy Fiddaman 			return buf;
124*b30d1939SAndy Fiddaman 		if (type)
125*b30d1939SAndy Fiddaman 		{
126*b30d1939SAndy Fiddaman 			sfsprintf(buf, size, "%-.*s%s%.s", s - error_info.file + 1, error_info.file, name, type);
127*b30d1939SAndy Fiddaman 			if (regular(buf, &st))
128*b30d1939SAndy Fiddaman 				return buf;
129*b30d1939SAndy Fiddaman 		}
130*b30d1939SAndy Fiddaman 	}
131*b30d1939SAndy Fiddaman 
132*b30d1939SAndy Fiddaman 	/*
133*b30d1939SAndy Fiddaman 	 * check the include dir list
134*b30d1939SAndy Fiddaman 	 */
135*b30d1939SAndy Fiddaman 
136*b30d1939SAndy Fiddaman 	for (dp = state.head; dp; dp = dp->next)
137*b30d1939SAndy Fiddaman 	{
138*b30d1939SAndy Fiddaman 		sfsprintf(tmp, sizeof(tmp), "%s/%s", dp->dir, name);
139*b30d1939SAndy Fiddaman 		if (pathpath(tmp, "", PATH_REGULAR, buf, size))
140*b30d1939SAndy Fiddaman 			return buf;
141*b30d1939SAndy Fiddaman 		if (type)
142*b30d1939SAndy Fiddaman 		{
143*b30d1939SAndy Fiddaman 			sfsprintf(tmp, sizeof(tmp), "%s/%s.%s", dp->dir, name, type);
144*b30d1939SAndy Fiddaman 			if (pathpath(tmp, "", PATH_REGULAR, buf, size))
145*b30d1939SAndy Fiddaman 				return buf;
146*b30d1939SAndy Fiddaman 		}
147*b30d1939SAndy Fiddaman 	}
148*b30d1939SAndy Fiddaman 
149*b30d1939SAndy Fiddaman 	/*
150*b30d1939SAndy Fiddaman 	 * finally a lib related search on PATH
151*b30d1939SAndy Fiddaman 	 */
152*b30d1939SAndy Fiddaman 
153*b30d1939SAndy Fiddaman 	if (lib)
154*b30d1939SAndy Fiddaman 	{
155*b30d1939SAndy Fiddaman 		if (s = strrchr((char*)lib, ':'))
156*b30d1939SAndy Fiddaman 			lib = (const char*)s + 1;
157*b30d1939SAndy Fiddaman 		sfsprintf(tmp, sizeof(tmp), "lib/%s/%s", lib, name);
158*b30d1939SAndy Fiddaman 		if (pathpath(tmp, "", PATH_REGULAR, buf, size))
159*b30d1939SAndy Fiddaman 			return buf;
160*b30d1939SAndy Fiddaman 		if (type)
161*b30d1939SAndy Fiddaman 		{
162*b30d1939SAndy Fiddaman 			sfsprintf(tmp, sizeof(tmp), "lib/%s/%s.%s", lib, name, type);
163*b30d1939SAndy Fiddaman 			if (pathpath(tmp, "", PATH_REGULAR, buf, size))
164*b30d1939SAndy Fiddaman 				return buf;
165*b30d1939SAndy Fiddaman 		}
166*b30d1939SAndy Fiddaman 	}
167*b30d1939SAndy Fiddaman 	return 0;
168*b30d1939SAndy Fiddaman }
169