xref: /onnv-gate/usr/src/lib/libdll/common/dllnext.c (revision 12068:08a39a083754)
14887Schin /***********************************************************************
24887Schin *                                                                      *
34887Schin *               This software is part of the ast package               *
4*12068SRoger.Faulkner@Oracle.COM *          Copyright (c) 1997-2010 AT&T Intellectual Property          *
54887Schin *                      and is licensed under the                       *
64887Schin *                  Common Public License, Version 1.0                  *
78462SApril.Chin@Sun.COM *                    by AT&T Intellectual Property                     *
84887Schin *                                                                      *
94887Schin *                A copy of the License is available at                 *
104887Schin *            http://www.opensource.org/licenses/cpl1.0.txt             *
114887Schin *         (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9)         *
124887Schin *                                                                      *
134887Schin *              Information and Software Systems Research               *
144887Schin *                            AT&T Research                             *
154887Schin *                           Florham Park NJ                            *
164887Schin *                                                                      *
174887Schin *                 Glenn Fowler <gsf@research.att.com>                  *
184887Schin *                                                                      *
194887Schin ***********************************************************************/
204887Schin #pragma prototyped
214887Schin /*
224887Schin  * Glenn Fowler
234887Schin  * AT&T Research
244887Schin  */
254887Schin 
264887Schin #ifndef _GNU_SOURCE
274887Schin #define _GNU_SOURCE	1
284887Schin #endif
294887Schin #ifndef __EXTENSIONS__
304887Schin #define __EXTENSIONS__	1
314887Schin #endif
324887Schin 
334887Schin #include <ast.h>
344887Schin #include <dlldefs.h>
354887Schin 
364887Schin #if _hdr_rld_interface
374887Schin #include <rld_interface.h>
384887Schin #endif
394887Schin 
404887Schin /*
414887Schin  * return a handle for the next layer down,
424887Schin  * i.e., the next layer that has symbols covered
434887Schin  * by the main prog and dll's loaded so far
444887Schin  *
454887Schin  * intentionally light on external lib calls
464887Schin  * so this routine can be used early in process
474887Schin  * startup
484887Schin  */
494887Schin 
504887Schin #ifdef	_DLL_RLD_SYM
514887Schin 
524887Schin #define DEBUG		1
534887Schin 
544887Schin #if DEBUG
554887Schin 
564887Schin typedef ssize_t (*Write_f)(int, const void*, size_t);
574887Schin 
584887Schin #endif
594887Schin 
604887Schin #undef	dllnext
614887Schin 
624887Schin void*
_dll_next(int flags,_DLL_RLD_SYM_TYPE * here)634887Schin _dll_next(int flags, _DLL_RLD_SYM_TYPE* here)
644887Schin {
654887Schin 	register char*	vp;
664887Schin 	register void*	lp;
674887Schin 	register int	found = 0;
684887Schin 	char*		s;
694887Schin 	char*		b;
704887Schin 	char*		e;
714887Schin 	char		dummy[256];
724887Schin #if DEBUG
734887Schin 	Write_f		wr = 0;
744887Schin 	Write_f		xr;
754887Schin 	char		buf[1024];
764887Schin #endif
774887Schin 
784887Schin #if DEBUG
794887Schin 	if (getenv("DLL_DEBUG") && (vp = (char*)_rld_new_interface(_RLD_FIRST_PATHNAME)))
804887Schin 	{
814887Schin 		do
824887Schin 		{
8310898Sroland.mainz@nrubsig.org 			if (strcmp(vp, "MAIN") && (lp = dllopen(vp, flags)))
844887Schin 			{
854887Schin 				if (xr = (Write_f)dlsym(lp, "write"))
864887Schin 					wr = xr;
874887Schin 			}
884887Schin 		} while (vp = (char*)_rld_new_interface(_RLD_NEXT_PATHNAME));
894887Schin 	}
904887Schin #endif
914887Schin 	if (vp = (char*)_rld_new_interface(_RLD_FIRST_PATHNAME))
924887Schin 	{
934887Schin 		do
944887Schin 		{
9510898Sroland.mainz@nrubsig.org 			if (lp = dllopen(strcmp(vp, "MAIN") ? vp : (char*)0, flags))
964887Schin 			{
974887Schin 				if (found)
984887Schin 				{
994887Schin 					b = e = 0;
1004887Schin 					s = vp;
1014887Schin 					for (;;)
1024887Schin 					{
1034887Schin 						switch (*s++)
1044887Schin 						{
1054887Schin 						case 0:
1064887Schin 							break;
1074887Schin 						case '/':
1084887Schin 							b = s;
1094887Schin 							e = 0;
1104887Schin 							continue;
1114887Schin 						case '.':
1124887Schin 							if (!e)
1134887Schin 								e = s - 1;
1144887Schin 							continue;
1154887Schin 						default:
1164887Schin 							continue;
1174887Schin 						}
1184887Schin 						break;
1194887Schin 					}
1204887Schin 					if (b && e)
1214887Schin 					{
1224887Schin 						s = dummy;
1234887Schin 						*s++ = '_';
1244887Schin 						*s++ = '_';
1254887Schin 						while (b < e)
1264887Schin 							*s++ = *b++;
1274887Schin 						b = "_dummy";
1284887Schin 						while (*s++ = *b++);
1294887Schin 						if (dlsym(lp, dummy))
1304887Schin 						{
1314887Schin 							dlclose(lp);
1324887Schin 							lp = 0;
1334887Schin 						}
1344887Schin 					}
1354887Schin 					if (lp)
1364887Schin 					{
1374887Schin #if DEBUG
1384887Schin 						if (wr)
1394887Schin 							(*wr)(2, buf, sfsprintf(buf, sizeof(buf), "dll: next %s\n", vp));
1404887Schin #endif
1414887Schin 						return lp;
1424887Schin 					}
1434887Schin #if DEBUG
1444887Schin 					else if (wr)
1454887Schin 						(*wr)(2, buf, sfsprintf(buf, sizeof(buf), "dll: skip %s\n", vp));
1464887Schin #endif
1474887Schin 				}
1484887Schin 				else if ((_DLL_RLD_SYM_TYPE*)dlsym(lp, _DLL_RLD_SYM_STR) == here)
1494887Schin 				{
1504887Schin #if DEBUG
1514887Schin 					if (wr)
1524887Schin 						(*wr)(2, buf, sfsprintf(buf, sizeof(buf), "dll: this %s\n", vp));
1534887Schin #endif
1544887Schin 					found = 1;
1554887Schin 				}
1564887Schin 			}
1574887Schin 		} while (vp = (char*)_rld_new_interface(_RLD_NEXT_PATHNAME));
1584887Schin 	}
1594887Schin 	return dllnext(flags);
1604887Schin }
1614887Schin 
1624887Schin #endif
1634887Schin 
1644887Schin #ifndef RTLD_NEXT
1654887Schin #if _dll_DYNAMIC
1664887Schin 
1674887Schin #include <link.h>
1684887Schin 
1694887Schin extern struct link_dynamic	_DYNAMIC;
1704887Schin 
1714887Schin #endif
1724887Schin #endif
1734887Schin 
1744887Schin void*
dllnext(int flags)1754887Schin dllnext(int flags)
1764887Schin {
1774887Schin 	register void*			dll;
1784887Schin #ifndef RTLD_NEXT
1794887Schin #if _dll_DYNAMIC
1804887Schin 	register struct link_map*	map;
1814887Schin 	register char*			s;
1824887Schin 	register char*			b;
1834887Schin #endif
1844887Schin 	register char*			ver;
1854887Schin 	char*				path;
1864887Schin 
1874887Schin 	static char			next[] = { _DLL_NEXT_PATH };
1884887Schin #endif
1894887Schin 
1904887Schin #ifdef RTLD_NEXT
1914887Schin 	dll = RTLD_NEXT;
1924887Schin #else
1934887Schin 	path = next;
1944887Schin #if _dll_DYNAMIC
1954887Schin 	for (map = _DYNAMIC.ld_un.ld_1->ld_loaded; map; map = map->lm_next)
1964887Schin 	{
1974887Schin 		b = 0;
1984887Schin 		s = map->lm_name;
1994887Schin 		while (*s)
2004887Schin 			if (*s++ == '/')
2014887Schin 				b = s;
2024887Schin 		if (b && b[0] == 'l' && b[1] == 'i' && b[2] == 'b' && b[3] == 'c' && b[4] == '.')
2034887Schin 		{
2044887Schin 			path = map->lm_name;
2054887Schin 			break;
2064887Schin 		}
2074887Schin 	}
2084887Schin #endif
2094887Schin 	ver = path + strlen(path);
21010898Sroland.mainz@nrubsig.org 	while (!(dll = dllopen(path, flags)))
2114887Schin 	{
2124887Schin 		do
2134887Schin 		{
2144887Schin 			if (ver <= path)
2154887Schin 				return 0;
2164887Schin 		} while (*--ver != '.');
2174887Schin 		if (*(ver + 1) <= '0' || *(ver + 1) >= '9')
2184887Schin 			return 0;
2194887Schin 		*ver = 0;
2204887Schin 	}
2214887Schin #endif
2224887Schin 	return dll;
2234887Schin }
224