xref: /titanic_52/usr/src/contrib/ast/src/lib/libdll/dllscan.c (revision 906afcb89d0412cc073b95c2d701a804a8cdb62c)
1*906afcb8SAndy Fiddaman /***********************************************************************
2*906afcb8SAndy Fiddaman *                                                                      *
3*906afcb8SAndy Fiddaman *               This software is part of the ast package               *
4*906afcb8SAndy Fiddaman *          Copyright (c) 1997-2012 AT&T Intellectual Property          *
5*906afcb8SAndy Fiddaman *                      and is licensed under the                       *
6*906afcb8SAndy Fiddaman *                 Eclipse Public License, Version 1.0                  *
7*906afcb8SAndy Fiddaman *                    by AT&T Intellectual Property                     *
8*906afcb8SAndy Fiddaman *                                                                      *
9*906afcb8SAndy Fiddaman *                A copy of the License is available at                 *
10*906afcb8SAndy Fiddaman *          http://www.eclipse.org/org/documents/epl-v10.html           *
11*906afcb8SAndy Fiddaman *         (with md5 checksum b35adb5213ca9657e911e9befb180842)         *
12*906afcb8SAndy Fiddaman *                                                                      *
13*906afcb8SAndy Fiddaman *              Information and Software Systems Research               *
14*906afcb8SAndy Fiddaman *                            AT&T Research                             *
15*906afcb8SAndy Fiddaman *                           Florham Park NJ                            *
16*906afcb8SAndy Fiddaman *                                                                      *
17*906afcb8SAndy Fiddaman *                 Glenn Fowler <gsf@research.att.com>                  *
18*906afcb8SAndy Fiddaman *                                                                      *
19*906afcb8SAndy Fiddaman ***********************************************************************/
20*906afcb8SAndy Fiddaman #pragma prototyped
21*906afcb8SAndy Fiddaman /*
22*906afcb8SAndy Fiddaman  * Glenn Fowler
23*906afcb8SAndy Fiddaman  * AT&T Research
24*906afcb8SAndy Fiddaman  */
25*906afcb8SAndy Fiddaman 
26*906afcb8SAndy Fiddaman #define _DLLINFO_PRIVATE_ \
27*906afcb8SAndy Fiddaman 	char*	sib[3]; \
28*906afcb8SAndy Fiddaman 	char	sibbuf[64]; \
29*906afcb8SAndy Fiddaman 	char	envbuf[64];
30*906afcb8SAndy Fiddaman 
31*906afcb8SAndy Fiddaman #define _DLLSCAN_PRIVATE_ \
32*906afcb8SAndy Fiddaman 	Dllent_t	entry; \
33*906afcb8SAndy Fiddaman 	Uniq_t*		uniq; \
34*906afcb8SAndy Fiddaman 	int		flags; \
35*906afcb8SAndy Fiddaman 	Vmalloc_t*	vm; \
36*906afcb8SAndy Fiddaman 	Dt_t*		dict; \
37*906afcb8SAndy Fiddaman 	Dtdisc_t	disc; \
38*906afcb8SAndy Fiddaman 	FTS*		fts; \
39*906afcb8SAndy Fiddaman 	FTSENT*		ent; \
40*906afcb8SAndy Fiddaman 	Sfio_t*		tmp; \
41*906afcb8SAndy Fiddaman 	char**		sb; \
42*906afcb8SAndy Fiddaman 	char**		sp; \
43*906afcb8SAndy Fiddaman 	char*		pb; \
44*906afcb8SAndy Fiddaman 	char*		pp; \
45*906afcb8SAndy Fiddaman 	char*		pe; \
46*906afcb8SAndy Fiddaman 	int		off; \
47*906afcb8SAndy Fiddaman 	int		prelen; \
48*906afcb8SAndy Fiddaman 	int		suflen; \
49*906afcb8SAndy Fiddaman 	char**		lib; \
50*906afcb8SAndy Fiddaman 	char		nam[64]; \
51*906afcb8SAndy Fiddaman 	char		pat[64]; \
52*906afcb8SAndy Fiddaman 	char		buf[64];
53*906afcb8SAndy Fiddaman 
54*906afcb8SAndy Fiddaman #define DLL_MATCH_DONE		0x8000
55*906afcb8SAndy Fiddaman #define DLL_MATCH_NAME		0x4000
56*906afcb8SAndy Fiddaman #define DLL_MATCH_VERSION	0x2000
57*906afcb8SAndy Fiddaman 
58*906afcb8SAndy Fiddaman #include <ast.h>
59*906afcb8SAndy Fiddaman #include <cdt.h>
60*906afcb8SAndy Fiddaman #include <ctype.h>
61*906afcb8SAndy Fiddaman #include <error.h>
62*906afcb8SAndy Fiddaman #include <fts.h>
63*906afcb8SAndy Fiddaman #include <vmalloc.h>
64*906afcb8SAndy Fiddaman 
65*906afcb8SAndy Fiddaman typedef struct Uniq_s
66*906afcb8SAndy Fiddaman {
67*906afcb8SAndy Fiddaman 	Dtlink_t	link;
68*906afcb8SAndy Fiddaman 	char		name[1];
69*906afcb8SAndy Fiddaman } Uniq_t;
70*906afcb8SAndy Fiddaman 
71*906afcb8SAndy Fiddaman #include <dlldefs.h>
72*906afcb8SAndy Fiddaman 
73*906afcb8SAndy Fiddaman static char		bin[] = "bin";
74*906afcb8SAndy Fiddaman static char		lib[] = "lib";
75*906afcb8SAndy Fiddaman 
76*906afcb8SAndy Fiddaman /*
77*906afcb8SAndy Fiddaman  * we need a sibling dir in PATH to search for dlls
78*906afcb8SAndy Fiddaman  * the confstr LIBPATH provides the local info
79*906afcb8SAndy Fiddaman  *
80*906afcb8SAndy Fiddaman  *	<sibling-dir>[:<env-var>[:<host-pattern>]][,...]
81*906afcb8SAndy Fiddaman  *
82*906afcb8SAndy Fiddaman  * if <host-pattern> is present then it must match confstr HOSTTYPE
83*906afcb8SAndy Fiddaman  */
84*906afcb8SAndy Fiddaman 
85*906afcb8SAndy Fiddaman Dllinfo_t*
86*906afcb8SAndy Fiddaman dllinfo(void)
87*906afcb8SAndy Fiddaman {
88*906afcb8SAndy Fiddaman 	register char*		s;
89*906afcb8SAndy Fiddaman 	register char*		h;
90*906afcb8SAndy Fiddaman 	char*			d;
91*906afcb8SAndy Fiddaman 	char*			v;
92*906afcb8SAndy Fiddaman 	char*			p;
93*906afcb8SAndy Fiddaman 	int			dn;
94*906afcb8SAndy Fiddaman 	int			vn;
95*906afcb8SAndy Fiddaman 	int			pn;
96*906afcb8SAndy Fiddaman 	char			pat[256];
97*906afcb8SAndy Fiddaman 
98*906afcb8SAndy Fiddaman 	static Dllinfo_t	info;
99*906afcb8SAndy Fiddaman 
100*906afcb8SAndy Fiddaman 	if (!info.sibling)
101*906afcb8SAndy Fiddaman 	{
102*906afcb8SAndy Fiddaman 		info.sibling = info.sib;
103*906afcb8SAndy Fiddaman 		if (*(s = astconf("LIBPATH", NiL, NiL)))
104*906afcb8SAndy Fiddaman 		{
105*906afcb8SAndy Fiddaman 			while (*s == ':' || *s == ',')
106*906afcb8SAndy Fiddaman 				s++;
107*906afcb8SAndy Fiddaman 			if (*s)
108*906afcb8SAndy Fiddaman 			{
109*906afcb8SAndy Fiddaman 				h = 0;
110*906afcb8SAndy Fiddaman 				for (;;)
111*906afcb8SAndy Fiddaman 				{
112*906afcb8SAndy Fiddaman 					for (d = s; *s && *s != ':' && *s != ','; s++);
113*906afcb8SAndy Fiddaman 					if (!(dn = s - d))
114*906afcb8SAndy Fiddaman 						d = 0;
115*906afcb8SAndy Fiddaman 					if (*s == ':')
116*906afcb8SAndy Fiddaman 					{
117*906afcb8SAndy Fiddaman 						for (v = ++s; *s && *s != ':' && *s != ','; s++);
118*906afcb8SAndy Fiddaman 						if (!(vn = s - v))
119*906afcb8SAndy Fiddaman 							v = 0;
120*906afcb8SAndy Fiddaman 						if (*s == ':')
121*906afcb8SAndy Fiddaman 						{
122*906afcb8SAndy Fiddaman 							for (p = ++s; *s && *s != ':' && *s != ','; s++);
123*906afcb8SAndy Fiddaman 							if (!(pn = s - p))
124*906afcb8SAndy Fiddaman 								p = 0;
125*906afcb8SAndy Fiddaman 						}
126*906afcb8SAndy Fiddaman 						else
127*906afcb8SAndy Fiddaman 							p = 0;
128*906afcb8SAndy Fiddaman 					}
129*906afcb8SAndy Fiddaman 					else
130*906afcb8SAndy Fiddaman 					{
131*906afcb8SAndy Fiddaman 						v = 0;
132*906afcb8SAndy Fiddaman 						p = 0;
133*906afcb8SAndy Fiddaman 					}
134*906afcb8SAndy Fiddaman 					while (*s && *s++ != ',');
135*906afcb8SAndy Fiddaman 					if (!*s || !p || !h && !*(h = astconf("HOSTTYPE", NiL, NiL)))
136*906afcb8SAndy Fiddaman 						break;
137*906afcb8SAndy Fiddaman 					if (pn >= sizeof(pat))
138*906afcb8SAndy Fiddaman 						pn = sizeof(pat) - 1;
139*906afcb8SAndy Fiddaman 					memcpy(pat, p, pn);
140*906afcb8SAndy Fiddaman 					pat[pn] = 0;
141*906afcb8SAndy Fiddaman 					if (strmatch(h, pat))
142*906afcb8SAndy Fiddaman 						break;
143*906afcb8SAndy Fiddaman 				}
144*906afcb8SAndy Fiddaman 				if (d && dn < sizeof(info.sibbuf))
145*906afcb8SAndy Fiddaman 				{
146*906afcb8SAndy Fiddaman 					memcpy(info.sibbuf, d, dn);
147*906afcb8SAndy Fiddaman 					info.sibling[0] = info.sibbuf;
148*906afcb8SAndy Fiddaman 				}
149*906afcb8SAndy Fiddaman 				if (v && vn < sizeof(info.envbuf))
150*906afcb8SAndy Fiddaman 				{
151*906afcb8SAndy Fiddaman 					memcpy(info.envbuf, v, vn);
152*906afcb8SAndy Fiddaman 					info.env = info.envbuf;
153*906afcb8SAndy Fiddaman 				}
154*906afcb8SAndy Fiddaman 			}
155*906afcb8SAndy Fiddaman 		}
156*906afcb8SAndy Fiddaman 		if (!info.sibling[0] || streq(info.sibling[0], bin))
157*906afcb8SAndy Fiddaman 			info.sibling[0] = bin;
158*906afcb8SAndy Fiddaman 		if (!streq(info.sibling[0], lib))
159*906afcb8SAndy Fiddaman 			info.sibling[1] = lib;
160*906afcb8SAndy Fiddaman 		if (!info.env)
161*906afcb8SAndy Fiddaman 			info.env = "LD_LIBRARY_PATH";
162*906afcb8SAndy Fiddaman 		info.prefix = astconf("LIBPREFIX", NiL, NiL);
163*906afcb8SAndy Fiddaman 		info.suffix = astconf("LIBSUFFIX", NiL, NiL);
164*906afcb8SAndy Fiddaman 		if (streq(info.suffix, ".dll"))
165*906afcb8SAndy Fiddaman 			info.flags |= DLL_INFO_PREVER;
166*906afcb8SAndy Fiddaman 		else
167*906afcb8SAndy Fiddaman 			info.flags |= DLL_INFO_DOTVER;
168*906afcb8SAndy Fiddaman 	}
169*906afcb8SAndy Fiddaman 	return &info;
170*906afcb8SAndy Fiddaman }
171*906afcb8SAndy Fiddaman 
172*906afcb8SAndy Fiddaman /*
173*906afcb8SAndy Fiddaman  * fts version sort order
174*906afcb8SAndy Fiddaman  * higher versions appear first
175*906afcb8SAndy Fiddaman  */
176*906afcb8SAndy Fiddaman 
177*906afcb8SAndy Fiddaman static int
178*906afcb8SAndy Fiddaman vercmp(FTSENT* const* ap, FTSENT* const* bp)
179*906afcb8SAndy Fiddaman {
180*906afcb8SAndy Fiddaman 	register unsigned char*	a = (unsigned char*)(*ap)->fts_name;
181*906afcb8SAndy Fiddaman 	register unsigned char*	b = (unsigned char*)(*bp)->fts_name;
182*906afcb8SAndy Fiddaman 	register int		n;
183*906afcb8SAndy Fiddaman 	register int		m;
184*906afcb8SAndy Fiddaman 	char*			e;
185*906afcb8SAndy Fiddaman 
186*906afcb8SAndy Fiddaman 	for (;;)
187*906afcb8SAndy Fiddaman 	{
188*906afcb8SAndy Fiddaman 		if (isdigit(*a) && isdigit(*b))
189*906afcb8SAndy Fiddaman 		{
190*906afcb8SAndy Fiddaman 			m = strtol((char*)a, &e, 10);
191*906afcb8SAndy Fiddaman 			a = (unsigned char*)e;
192*906afcb8SAndy Fiddaman 			n = strtol((char*)b, &e, 10);
193*906afcb8SAndy Fiddaman 			b = (unsigned char*)e;
194*906afcb8SAndy Fiddaman 			if (n -= m)
195*906afcb8SAndy Fiddaman 				return n;
196*906afcb8SAndy Fiddaman 		}
197*906afcb8SAndy Fiddaman 		if (n = *a - *b)
198*906afcb8SAndy Fiddaman 			return n;
199*906afcb8SAndy Fiddaman 		if (!*a++)
200*906afcb8SAndy Fiddaman 			return *b ? 0 : -1;
201*906afcb8SAndy Fiddaman 		if (!*b++)
202*906afcb8SAndy Fiddaman 			return 1;
203*906afcb8SAndy Fiddaman 	}
204*906afcb8SAndy Fiddaman 	/*NOTREACHED*/
205*906afcb8SAndy Fiddaman }
206*906afcb8SAndy Fiddaman 
207*906afcb8SAndy Fiddaman /*
208*906afcb8SAndy Fiddaman  * open a scan stream
209*906afcb8SAndy Fiddaman  */
210*906afcb8SAndy Fiddaman 
211*906afcb8SAndy Fiddaman Dllscan_t*
212*906afcb8SAndy Fiddaman dllsopen(const char* lib, const char* name, const char* version)
213*906afcb8SAndy Fiddaman {
214*906afcb8SAndy Fiddaman 	register char*	s;
215*906afcb8SAndy Fiddaman 	register char*	t;
216*906afcb8SAndy Fiddaman 	Dllscan_t*	scan;
217*906afcb8SAndy Fiddaman 	Dllinfo_t*	info;
218*906afcb8SAndy Fiddaman 	Vmalloc_t*	vm;
219*906afcb8SAndy Fiddaman 	int		i;
220*906afcb8SAndy Fiddaman 	int		j;
221*906afcb8SAndy Fiddaman 	int		k;
222*906afcb8SAndy Fiddaman 	char		buf[32];
223*906afcb8SAndy Fiddaman 
224*906afcb8SAndy Fiddaman 	if (!(vm = vmopen(Vmdcheap, Vmlast, 0)))
225*906afcb8SAndy Fiddaman 		return 0;
226*906afcb8SAndy Fiddaman 	if (lib && *lib && (*lib != '-' || *(lib + 1)))
227*906afcb8SAndy Fiddaman 	{
228*906afcb8SAndy Fiddaman 		/*
229*906afcb8SAndy Fiddaman 		 * grab the local part of the library id
230*906afcb8SAndy Fiddaman 		 */
231*906afcb8SAndy Fiddaman 
232*906afcb8SAndy Fiddaman 		if (s = strrchr(lib, ':'))
233*906afcb8SAndy Fiddaman 			lib = (const char*)(s + 1);
234*906afcb8SAndy Fiddaman 		i = 2 * sizeof(char**) + strlen(lib) + 5;
235*906afcb8SAndy Fiddaman 	}
236*906afcb8SAndy Fiddaman 	else
237*906afcb8SAndy Fiddaman 	{
238*906afcb8SAndy Fiddaman 		lib = 0;
239*906afcb8SAndy Fiddaman 		i = 0;
240*906afcb8SAndy Fiddaman 	}
241*906afcb8SAndy Fiddaman 	if (version && (!*version || *version == '-' && !*(version + 1)))
242*906afcb8SAndy Fiddaman 		version = 0;
243*906afcb8SAndy Fiddaman 	if (!(scan = vmnewof(vm, 0, Dllscan_t, 1, i)) || !(scan->tmp = sfstropen()))
244*906afcb8SAndy Fiddaman 	{
245*906afcb8SAndy Fiddaman 		vmclose(vm);
246*906afcb8SAndy Fiddaman 		return 0;
247*906afcb8SAndy Fiddaman 	}
248*906afcb8SAndy Fiddaman 	scan->vm = vm;
249*906afcb8SAndy Fiddaman 	info = dllinfo();
250*906afcb8SAndy Fiddaman 	scan->flags = info->flags;
251*906afcb8SAndy Fiddaman 	if (lib)
252*906afcb8SAndy Fiddaman 	{
253*906afcb8SAndy Fiddaman 		scan->lib = (char**)(scan + 1);
254*906afcb8SAndy Fiddaman 		s = *scan->lib = (char*)(scan->lib + 2);
255*906afcb8SAndy Fiddaman 		sfsprintf(s, i, "lib/%s", lib);
256*906afcb8SAndy Fiddaman 		if (!version && streq(info->suffix, ".dylib"))
257*906afcb8SAndy Fiddaman 			version = "0.0";
258*906afcb8SAndy Fiddaman 	}
259*906afcb8SAndy Fiddaman 	if (!name || !*name || *name == '-' && !*(name + 1))
260*906afcb8SAndy Fiddaman 	{
261*906afcb8SAndy Fiddaman 		name = (const char*)"?*";
262*906afcb8SAndy Fiddaman 		scan->flags |= DLL_MATCH_NAME;
263*906afcb8SAndy Fiddaman 	}
264*906afcb8SAndy Fiddaman 	else if (t = strrchr(name, '/'))
265*906afcb8SAndy Fiddaman 	{
266*906afcb8SAndy Fiddaman 		if (!(scan->pb = vmnewof(vm, 0, char, t - (char*)name, 2)))
267*906afcb8SAndy Fiddaman 			goto bad;
268*906afcb8SAndy Fiddaman 		memcpy(scan->pb, name, t - (char*)name);
269*906afcb8SAndy Fiddaman 		name = (const char*)(t + 1);
270*906afcb8SAndy Fiddaman 	}
271*906afcb8SAndy Fiddaman 	if (name)
272*906afcb8SAndy Fiddaman 	{
273*906afcb8SAndy Fiddaman 		i = strlen(name);
274*906afcb8SAndy Fiddaman 		j = strlen(info->prefix);
275*906afcb8SAndy Fiddaman 		if (!j || i > j && strneq(name, info->prefix, j))
276*906afcb8SAndy Fiddaman 		{
277*906afcb8SAndy Fiddaman 			k = strlen(info->suffix);
278*906afcb8SAndy Fiddaman 			if (i > k && streq(name + i - k, info->suffix))
279*906afcb8SAndy Fiddaman 			{
280*906afcb8SAndy Fiddaman 				i -= j + k;
281*906afcb8SAndy Fiddaman 				if (!(t = vmnewof(vm, 0, char, i, 1)))
282*906afcb8SAndy Fiddaman 					goto bad;
283*906afcb8SAndy Fiddaman 				memcpy(t, name + j, i);
284*906afcb8SAndy Fiddaman 				t[i] = 0;
285*906afcb8SAndy Fiddaman 				name = (const char*)t;
286*906afcb8SAndy Fiddaman 			}
287*906afcb8SAndy Fiddaman 		}
288*906afcb8SAndy Fiddaman 		if (!version)
289*906afcb8SAndy Fiddaman 			for (t = (char*)name; *t; t++)
290*906afcb8SAndy Fiddaman 				if ((*t == '-' || *t == '.' || *t == '?') && isdigit(*(t + 1)))
291*906afcb8SAndy Fiddaman 				{
292*906afcb8SAndy Fiddaman 					if (*t != '-')
293*906afcb8SAndy Fiddaman 						scan->flags |= DLL_MATCH_VERSION;
294*906afcb8SAndy Fiddaman 					version = t + 1;
295*906afcb8SAndy Fiddaman 					if (!(s = vmnewof(vm, 0, char, t - (char*)name, 1)))
296*906afcb8SAndy Fiddaman 						goto bad;
297*906afcb8SAndy Fiddaman 					memcpy(s, name, t - (char*)name);
298*906afcb8SAndy Fiddaman 					name = (const char*)s;
299*906afcb8SAndy Fiddaman 					break;
300*906afcb8SAndy Fiddaman 				}
301*906afcb8SAndy Fiddaman 	}
302*906afcb8SAndy Fiddaman 	if (!version)
303*906afcb8SAndy Fiddaman 	{
304*906afcb8SAndy Fiddaman 		scan->flags |= DLL_MATCH_VERSION;
305*906afcb8SAndy Fiddaman 		sfsprintf(scan->nam, sizeof(scan->nam), "%s%s%s", info->prefix, name, info->suffix);
306*906afcb8SAndy Fiddaman 	}
307*906afcb8SAndy Fiddaman 	else if (scan->flags & DLL_INFO_PREVER)
308*906afcb8SAndy Fiddaman 	{
309*906afcb8SAndy Fiddaman 		sfprintf(scan->tmp, "%s%s", info->prefix, name);
310*906afcb8SAndy Fiddaman 		for (s = (char*)version; *s; s++)
311*906afcb8SAndy Fiddaman 			if (isdigit(*s))
312*906afcb8SAndy Fiddaman 				sfputc(scan->tmp, *s);
313*906afcb8SAndy Fiddaman 		sfprintf(scan->tmp, "%s", info->suffix);
314*906afcb8SAndy Fiddaman 		if (!(s = sfstruse(scan->tmp)))
315*906afcb8SAndy Fiddaman 			goto bad;
316*906afcb8SAndy Fiddaman 		sfsprintf(scan->nam, sizeof(scan->nam), "%s", s);
317*906afcb8SAndy Fiddaman 	}
318*906afcb8SAndy Fiddaman 	else
319*906afcb8SAndy Fiddaman 		sfsprintf(scan->nam, sizeof(scan->nam), "%s%s%s.%s", info->prefix, name, info->suffix, version);
320*906afcb8SAndy Fiddaman 	if (scan->flags & (DLL_MATCH_NAME|DLL_MATCH_VERSION))
321*906afcb8SAndy Fiddaman 	{
322*906afcb8SAndy Fiddaman 		if (scan->flags & DLL_INFO_PREVER)
323*906afcb8SAndy Fiddaman 		{
324*906afcb8SAndy Fiddaman 			if (!version)
325*906afcb8SAndy Fiddaman 				version = "*([0-9_])";
326*906afcb8SAndy Fiddaman 			else
327*906afcb8SAndy Fiddaman 			{
328*906afcb8SAndy Fiddaman 				t = buf;
329*906afcb8SAndy Fiddaman 				for (s = (char*)version; *s; s++)
330*906afcb8SAndy Fiddaman 					if (isdigit(*s) && t < &buf[sizeof(buf)-1])
331*906afcb8SAndy Fiddaman 						*t++ = *s;
332*906afcb8SAndy Fiddaman 				*t = 0;
333*906afcb8SAndy Fiddaman 				version = (const char*)buf;
334*906afcb8SAndy Fiddaman 			}
335*906afcb8SAndy Fiddaman 			sfsprintf(scan->pat, sizeof(scan->pat), "%s%s%s%s", info->prefix, name, version, info->suffix);
336*906afcb8SAndy Fiddaman 		}
337*906afcb8SAndy Fiddaman 		else if (version)
338*906afcb8SAndy Fiddaman 			sfsprintf(scan->pat, sizeof(scan->pat), "%s%s@(%s([-.])%s%s|%s.%s)", info->prefix, name, strchr(version, '.') ? "@" : "?", version, info->suffix, info->suffix, version);
339*906afcb8SAndy Fiddaman 		else
340*906afcb8SAndy Fiddaman 		{
341*906afcb8SAndy Fiddaman 			version = "*([0-9.])";
342*906afcb8SAndy Fiddaman 			sfsprintf(scan->pat, sizeof(scan->pat), "%s%s@(?([-.])%s%s|%s%s)", info->prefix, name, version, info->suffix, info->suffix, version);
343*906afcb8SAndy Fiddaman 		}
344*906afcb8SAndy Fiddaman 	}
345*906afcb8SAndy Fiddaman 	scan->sp = scan->sb = (scan->lib ? scan->lib : info->sibling);
346*906afcb8SAndy Fiddaman 	scan->prelen = strlen(info->prefix);
347*906afcb8SAndy Fiddaman 	scan->suflen = strlen(info->suffix);
348*906afcb8SAndy Fiddaman 	return scan;
349*906afcb8SAndy Fiddaman  bad:
350*906afcb8SAndy Fiddaman 	dllsclose(scan);
351*906afcb8SAndy Fiddaman 	return 0;
352*906afcb8SAndy Fiddaman }
353*906afcb8SAndy Fiddaman 
354*906afcb8SAndy Fiddaman /*
355*906afcb8SAndy Fiddaman  * close a scan stream
356*906afcb8SAndy Fiddaman  */
357*906afcb8SAndy Fiddaman 
358*906afcb8SAndy Fiddaman int
359*906afcb8SAndy Fiddaman dllsclose(Dllscan_t* scan)
360*906afcb8SAndy Fiddaman {
361*906afcb8SAndy Fiddaman 	if (!scan)
362*906afcb8SAndy Fiddaman 		return -1;
363*906afcb8SAndy Fiddaman 	if (scan->fts)
364*906afcb8SAndy Fiddaman 		fts_close(scan->fts);
365*906afcb8SAndy Fiddaman 	if (scan->dict)
366*906afcb8SAndy Fiddaman 		dtclose(scan->dict);
367*906afcb8SAndy Fiddaman 	if (scan->tmp)
368*906afcb8SAndy Fiddaman 		sfclose(scan->tmp);
369*906afcb8SAndy Fiddaman 	if (scan->vm)
370*906afcb8SAndy Fiddaman 		vmclose(scan->vm);
371*906afcb8SAndy Fiddaman 	return 0;
372*906afcb8SAndy Fiddaman }
373*906afcb8SAndy Fiddaman 
374*906afcb8SAndy Fiddaman /*
375*906afcb8SAndy Fiddaman  * return the next scan stream entry
376*906afcb8SAndy Fiddaman  */
377*906afcb8SAndy Fiddaman 
378*906afcb8SAndy Fiddaman Dllent_t*
379*906afcb8SAndy Fiddaman dllsread(register Dllscan_t* scan)
380*906afcb8SAndy Fiddaman {
381*906afcb8SAndy Fiddaman 	register char*		p;
382*906afcb8SAndy Fiddaman 	register char*		b;
383*906afcb8SAndy Fiddaman 	register char*		t;
384*906afcb8SAndy Fiddaman 	register Uniq_t*	u;
385*906afcb8SAndy Fiddaman 	register int		n;
386*906afcb8SAndy Fiddaman 	register int		m;
387*906afcb8SAndy Fiddaman 
388*906afcb8SAndy Fiddaman 	if (scan->flags & DLL_MATCH_DONE)
389*906afcb8SAndy Fiddaman 		return 0;
390*906afcb8SAndy Fiddaman  again:
391*906afcb8SAndy Fiddaman 	do
392*906afcb8SAndy Fiddaman 	{
393*906afcb8SAndy Fiddaman 		while (!scan->ent || !(scan->ent = scan->ent->fts_link))
394*906afcb8SAndy Fiddaman 		{
395*906afcb8SAndy Fiddaman 			if (scan->fts)
396*906afcb8SAndy Fiddaman 			{
397*906afcb8SAndy Fiddaman 				fts_close(scan->fts);
398*906afcb8SAndy Fiddaman 				scan->fts = 0;
399*906afcb8SAndy Fiddaman 			}
400*906afcb8SAndy Fiddaman 			if (!scan->pb)
401*906afcb8SAndy Fiddaman 				scan->pb = pathbin();
402*906afcb8SAndy Fiddaman 			else if (!*scan->sp)
403*906afcb8SAndy Fiddaman 			{
404*906afcb8SAndy Fiddaman 				scan->sp = scan->sb;
405*906afcb8SAndy Fiddaman 				if (!*scan->pe++)
406*906afcb8SAndy Fiddaman 					return 0;
407*906afcb8SAndy Fiddaman 				scan->pb = scan->pe;
408*906afcb8SAndy Fiddaman 			}
409*906afcb8SAndy Fiddaman 			for (p = scan->pp = scan->pb; *p && *p != ':'; p++)
410*906afcb8SAndy Fiddaman 				if (*p == '/')
411*906afcb8SAndy Fiddaman 					scan->pp = p;
412*906afcb8SAndy Fiddaman 			scan->pe = p;
413*906afcb8SAndy Fiddaman 			if (*scan->sp == bin)
414*906afcb8SAndy Fiddaman 				scan->off = sfprintf(scan->tmp, "%-.*s", scan->pe - scan->pb, scan->pb);
415*906afcb8SAndy Fiddaman 			else
416*906afcb8SAndy Fiddaman 				scan->off = sfprintf(scan->tmp, "%-.*s/%s", scan->pp - scan->pb, scan->pb, *scan->sp);
417*906afcb8SAndy Fiddaman 			scan->sp++;
418*906afcb8SAndy Fiddaman 			if (!(scan->flags & DLL_MATCH_NAME))
419*906afcb8SAndy Fiddaman 			{
420*906afcb8SAndy Fiddaman 				sfprintf(scan->tmp, "/%s", scan->nam);
421*906afcb8SAndy Fiddaman 				if (!(p = sfstruse(scan->tmp)))
422*906afcb8SAndy Fiddaman 					return 0;
423*906afcb8SAndy Fiddaman 				if (!eaccess(p, R_OK))
424*906afcb8SAndy Fiddaman 				{
425*906afcb8SAndy Fiddaman 					b = scan->nam;
426*906afcb8SAndy Fiddaman 					goto found;
427*906afcb8SAndy Fiddaman 				}
428*906afcb8SAndy Fiddaman 				if (errno != ENOENT)
429*906afcb8SAndy Fiddaman 					continue;
430*906afcb8SAndy Fiddaman 			}
431*906afcb8SAndy Fiddaman 			if (scan->flags & (DLL_MATCH_NAME|DLL_MATCH_VERSION))
432*906afcb8SAndy Fiddaman 			{
433*906afcb8SAndy Fiddaman 				sfstrseek(scan->tmp, scan->off, SEEK_SET);
434*906afcb8SAndy Fiddaman 				if (!(t = sfstruse(scan->tmp)))
435*906afcb8SAndy Fiddaman 					return 0;
436*906afcb8SAndy Fiddaman 				if ((scan->fts = fts_open((char**)t, FTS_LOGICAL|FTS_NOPOSTORDER|FTS_ONEPATH, vercmp)) && (scan->ent = fts_read(scan->fts)) && (scan->ent = fts_children(scan->fts, FTS_NOSTAT)))
437*906afcb8SAndy Fiddaman 					break;
438*906afcb8SAndy Fiddaman 			}
439*906afcb8SAndy Fiddaman 		}
440*906afcb8SAndy Fiddaman 	} while (!strmatch(scan->ent->fts_name, scan->pat));
441*906afcb8SAndy Fiddaman 	b = scan->ent->fts_name;
442*906afcb8SAndy Fiddaman 	sfstrseek(scan->tmp, scan->off, SEEK_SET);
443*906afcb8SAndy Fiddaman 	sfprintf(scan->tmp, "/%s", b);
444*906afcb8SAndy Fiddaman 	if (!(p = sfstruse(scan->tmp)))
445*906afcb8SAndy Fiddaman 		return 0;
446*906afcb8SAndy Fiddaman  found:
447*906afcb8SAndy Fiddaman 	b = scan->buf + sfsprintf(scan->buf, sizeof(scan->buf), "%s", b + scan->prelen);
448*906afcb8SAndy Fiddaman 	if (!(scan->flags & DLL_INFO_PREVER))
449*906afcb8SAndy Fiddaman 		while (b > scan->buf)
450*906afcb8SAndy Fiddaman 		{
451*906afcb8SAndy Fiddaman 			if (!isdigit(*(b - 1)) && *(b - 1) != '.')
452*906afcb8SAndy Fiddaman 				break;
453*906afcb8SAndy Fiddaman 			b--;
454*906afcb8SAndy Fiddaman 		}
455*906afcb8SAndy Fiddaman 	b -= scan->suflen;
456*906afcb8SAndy Fiddaman 	if (b > (scan->buf + 2) && (*(b - 1) == 'g' || *(b - 1) == 'O') && *(b - 2) == '-')
457*906afcb8SAndy Fiddaman 		b -= 2;
458*906afcb8SAndy Fiddaman 	n = m = 0;
459*906afcb8SAndy Fiddaman 	for (t = b; t > scan->buf; t--)
460*906afcb8SAndy Fiddaman 		if (isdigit(*(t - 1)))
461*906afcb8SAndy Fiddaman 			n = 1;
462*906afcb8SAndy Fiddaman 		else if (*(t - 1) != m)
463*906afcb8SAndy Fiddaman 		{
464*906afcb8SAndy Fiddaman 			if (*(t - 1) == '.' || *(t - 1) == '-' || *(t - 1) == '_')
465*906afcb8SAndy Fiddaman 			{
466*906afcb8SAndy Fiddaman 				n = 1;
467*906afcb8SAndy Fiddaman 				if (m)
468*906afcb8SAndy Fiddaman 				{
469*906afcb8SAndy Fiddaman 					m = -1;
470*906afcb8SAndy Fiddaman 					t--;
471*906afcb8SAndy Fiddaman 					break;
472*906afcb8SAndy Fiddaman 				}
473*906afcb8SAndy Fiddaman 				m = *(t - 1);
474*906afcb8SAndy Fiddaman 			}
475*906afcb8SAndy Fiddaman 			else
476*906afcb8SAndy Fiddaman 				break;
477*906afcb8SAndy Fiddaman 		}
478*906afcb8SAndy Fiddaman 	if (n)
479*906afcb8SAndy Fiddaman 	{
480*906afcb8SAndy Fiddaman 		if (isdigit(t[0]) && isdigit(t[1]) && !isdigit(t[2]))
481*906afcb8SAndy Fiddaman 			n = (t[0] - '0') * 10 + (t[1] - '0');
482*906afcb8SAndy Fiddaman 		else if (isdigit(t[1]) && isdigit(t[2]) && !isdigit(t[3]))
483*906afcb8SAndy Fiddaman 			n = (t[1] - '0') * 10 + (t[2] - '0');
484*906afcb8SAndy Fiddaman 		else
485*906afcb8SAndy Fiddaman 			n = 0;
486*906afcb8SAndy Fiddaman 		if (n && !(n & (n - 1)))
487*906afcb8SAndy Fiddaman 		{
488*906afcb8SAndy Fiddaman 			if (!isdigit(t[0]))
489*906afcb8SAndy Fiddaman 				t++;
490*906afcb8SAndy Fiddaman 			m = *(t += 2);
491*906afcb8SAndy Fiddaman 		}
492*906afcb8SAndy Fiddaman 		if (m || (scan->flags & DLL_INFO_PREVER))
493*906afcb8SAndy Fiddaman 			b = t;
494*906afcb8SAndy Fiddaman 	}
495*906afcb8SAndy Fiddaman 	*b = 0;
496*906afcb8SAndy Fiddaman 	if (!*(b = scan->buf))
497*906afcb8SAndy Fiddaman 		goto again;
498*906afcb8SAndy Fiddaman 	if (scan->uniq)
499*906afcb8SAndy Fiddaman 	{
500*906afcb8SAndy Fiddaman 		if (!scan->dict)
501*906afcb8SAndy Fiddaman 		{
502*906afcb8SAndy Fiddaman 			scan->disc.key = offsetof(Uniq_t, name);
503*906afcb8SAndy Fiddaman 			scan->disc.size = 0;
504*906afcb8SAndy Fiddaman 			scan->disc.link = offsetof(Uniq_t, link);
505*906afcb8SAndy Fiddaman 			if (!(scan->dict = dtopen(&scan->disc, Dtset)))
506*906afcb8SAndy Fiddaman 				return 0;
507*906afcb8SAndy Fiddaman 			dtinsert(scan->dict, scan->uniq);
508*906afcb8SAndy Fiddaman 		}
509*906afcb8SAndy Fiddaman 		if (dtmatch(scan->dict, b))
510*906afcb8SAndy Fiddaman 			goto again;
511*906afcb8SAndy Fiddaman 		if (!(u = vmnewof(scan->vm, 0, Uniq_t, 1, strlen(b))))
512*906afcb8SAndy Fiddaman 			return 0;
513*906afcb8SAndy Fiddaman 		strcpy(u->name, b);
514*906afcb8SAndy Fiddaman 		dtinsert(scan->dict, u);
515*906afcb8SAndy Fiddaman 	}
516*906afcb8SAndy Fiddaman 	else if (!(scan->flags & DLL_MATCH_NAME))
517*906afcb8SAndy Fiddaman 		scan->flags |= DLL_MATCH_DONE;
518*906afcb8SAndy Fiddaman 	else if (!(scan->uniq = vmnewof(scan->vm, 0, Uniq_t, 1, strlen(b))))
519*906afcb8SAndy Fiddaman 		return 0;
520*906afcb8SAndy Fiddaman 	else
521*906afcb8SAndy Fiddaman 		strcpy(scan->uniq->name, b);
522*906afcb8SAndy Fiddaman 	scan->entry.name = b;
523*906afcb8SAndy Fiddaman 	scan->entry.path = p;
524*906afcb8SAndy Fiddaman 	errorf("dll", NiL, -1, "dllsread: %s bound to %s", b, p);
525*906afcb8SAndy Fiddaman 	return &scan->entry;
526*906afcb8SAndy Fiddaman }
527