1/***********************************************************************
2*                                                                      *
3*               This software is part of the ast package               *
4*          Copyright (c) 1997-2011 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*                                                                      *
19***********************************************************************/
20#pragma prototyped
21/*
22 * Glenn Fowler
23 * AT&T Research
24 */
25
26#ifndef _GNU_SOURCE
27#define _GNU_SOURCE	1
28#endif
29#ifndef __EXTENSIONS__
30#define __EXTENSIONS__	1
31#endif
32
33#include <ast.h>
34#include <dlldefs.h>
35
36#if _hdr_rld_interface
37#include <rld_interface.h>
38#endif
39
40/*
41 * return a handle for the next layer down,
42 * i.e., the next layer that has symbols covered
43 * by the main prog and dll's loaded so far
44 *
45 * intentionally light on external lib calls
46 * so this routine can be used early in process
47 * startup
48 */
49
50#ifdef	_DLL_RLD_SYM
51
52#define DEBUG		1
53
54#if DEBUG
55
56typedef ssize_t (*Write_f)(int, const void*, size_t);
57
58#endif
59
60#undef	dllnext
61
62void*
63_dll_next(int flags, _DLL_RLD_SYM_TYPE* here)
64{
65	register char*	vp;
66	register void*	lp;
67	register int	found = 0;
68	char*		s;
69	char*		b;
70	char*		e;
71	char		dummy[256];
72#if DEBUG
73	Write_f		wr = 0;
74	Write_f		xr;
75	char		buf[1024];
76#endif
77
78#if DEBUG
79	if (getenv("DLL_DEBUG") && (vp = (char*)_rld_new_interface(_RLD_FIRST_PATHNAME)))
80	{
81		do
82		{
83			if (strcmp(vp, "MAIN") && (lp = dllopen(vp, flags)))
84			{
85				if (xr = (Write_f)dlsym(lp, "write"))
86					wr = xr;
87			}
88		} while (vp = (char*)_rld_new_interface(_RLD_NEXT_PATHNAME));
89	}
90#endif
91	if (vp = (char*)_rld_new_interface(_RLD_FIRST_PATHNAME))
92	{
93		do
94		{
95			if (lp = dllopen(strcmp(vp, "MAIN") ? vp : (char*)0, flags))
96			{
97				if (found)
98				{
99					b = e = 0;
100					s = vp;
101					for (;;)
102					{
103						switch (*s++)
104						{
105						case 0:
106							break;
107						case '/':
108							b = s;
109							e = 0;
110							continue;
111						case '.':
112							if (!e)
113								e = s - 1;
114							continue;
115						default:
116							continue;
117						}
118						break;
119					}
120					if (b && e)
121					{
122						s = dummy;
123						*s++ = '_';
124						*s++ = '_';
125						while (b < e)
126							*s++ = *b++;
127						b = "_dummy";
128						while (*s++ = *b++);
129						if (dlsym(lp, dummy))
130						{
131							dlclose(lp);
132							lp = 0;
133						}
134					}
135					if (lp)
136					{
137#if DEBUG
138						if (wr)
139							(*wr)(2, buf, sfsprintf(buf, sizeof(buf), "dll: next %s\n", vp));
140#endif
141						return lp;
142					}
143#if DEBUG
144					else if (wr)
145						(*wr)(2, buf, sfsprintf(buf, sizeof(buf), "dll: skip %s\n", vp));
146#endif
147				}
148				else if ((_DLL_RLD_SYM_TYPE*)dlsym(lp, _DLL_RLD_SYM_STR) == here)
149				{
150#if DEBUG
151					if (wr)
152						(*wr)(2, buf, sfsprintf(buf, sizeof(buf), "dll: this %s\n", vp));
153#endif
154					found = 1;
155				}
156			}
157		} while (vp = (char*)_rld_new_interface(_RLD_NEXT_PATHNAME));
158	}
159	return dllnext(flags);
160}
161
162#endif
163
164#ifndef RTLD_NEXT
165#if _dll_DYNAMIC
166
167#include <link.h>
168
169extern struct link_dynamic	_DYNAMIC;
170
171#endif
172#endif
173
174void*
175dllnext(int flags)
176{
177	register void*			dll;
178#ifndef RTLD_NEXT
179#if _dll_DYNAMIC
180	register struct link_map*	map;
181	register char*			s;
182	register char*			b;
183#endif
184	register char*			ver;
185	char*				path;
186
187	static char			next[] = { _DLL_NEXT_PATH };
188#endif
189
190#ifdef RTLD_NEXT
191	dll = RTLD_NEXT;
192#else
193	path = next;
194#if _dll_DYNAMIC
195	for (map = _DYNAMIC.ld_un.ld_1->ld_loaded; map; map = map->lm_next)
196	{
197		b = 0;
198		s = map->lm_name;
199		while (*s)
200			if (*s++ == '/')
201				b = s;
202		if (b && b[0] == 'l' && b[1] == 'i' && b[2] == 'b' && b[3] == 'c' && b[4] == '.')
203		{
204			path = map->lm_name;
205			break;
206		}
207	}
208#endif
209	ver = path + strlen(path);
210	while (!(dll = dllopen(path, flags)))
211	{
212		do
213		{
214			if (ver <= path)
215				return 0;
216		} while (*--ver != '.');
217		if (*(ver + 1) <= '0' || *(ver + 1) >= '9')
218			return 0;
219		*ver = 0;
220	}
221#endif
222	return dll;
223}
224