import less(1)
[unleashed/tickless.git] / usr / src / lib / libdll / common / dllnext.c
blob178a053d5228bcb147328c4cacef03cc1fadc84e
1 /***********************************************************************
2 * *
3 * This software is part of the ast package *
4 * Copyright (c) 1997-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 * *
19 ***********************************************************************/
20 #pragma prototyped
22 * Glenn Fowler
23 * AT&T Research
26 #ifndef _GNU_SOURCE
27 #define _GNU_SOURCE 1
28 #endif
29 #ifndef __EXTENSIONS__
30 #define __EXTENSIONS__ 1
31 #endif
33 #include <ast.h>
34 #include <dlldefs.h>
36 #if _hdr_rld_interface
37 #include <rld_interface.h>
38 #endif
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
45 * intentionally light on external lib calls
46 * so this routine can be used early in process
47 * startup
50 #ifdef _DLL_RLD_SYM
52 #define DEBUG 1
54 #if DEBUG
56 typedef ssize_t (*Write_f)(int, const void*, size_t);
58 #endif
60 #undef dllnext
62 void*
63 _dll_next(int flags, _DLL_RLD_SYM_TYPE* here)
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
78 #if DEBUG
79 if (getenv("DLL_DEBUG") && (vp = (char*)_rld_new_interface(_RLD_FIRST_PATHNAME)))
83 if (strcmp(vp, "MAIN") && (lp = dllopen(vp, flags)))
85 if (xr = (Write_f)dlsym(lp, "write"))
86 wr = xr;
88 } while (vp = (char*)_rld_new_interface(_RLD_NEXT_PATHNAME));
90 #endif
91 if (vp = (char*)_rld_new_interface(_RLD_FIRST_PATHNAME))
95 if (lp = dllopen(strcmp(vp, "MAIN") ? vp : (char*)0, flags))
97 if (found)
99 b = e = 0;
100 s = vp;
101 for (;;)
103 switch (*s++)
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;
118 break;
120 if (b && e)
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))
131 dlclose(lp);
132 lp = 0;
135 if (lp)
137 #if DEBUG
138 if (wr)
139 (*wr)(2, buf, sfsprintf(buf, sizeof(buf), "dll: next %s\n", vp));
140 #endif
141 return lp;
143 #if DEBUG
144 else if (wr)
145 (*wr)(2, buf, sfsprintf(buf, sizeof(buf), "dll: skip %s\n", vp));
146 #endif
148 else if ((_DLL_RLD_SYM_TYPE*)dlsym(lp, _DLL_RLD_SYM_STR) == here)
150 #if DEBUG
151 if (wr)
152 (*wr)(2, buf, sfsprintf(buf, sizeof(buf), "dll: this %s\n", vp));
153 #endif
154 found = 1;
157 } while (vp = (char*)_rld_new_interface(_RLD_NEXT_PATHNAME));
159 return dllnext(flags);
162 #endif
164 #ifndef RTLD_NEXT
165 #if _dll_DYNAMIC
167 #include <link.h>
169 extern struct link_dynamic _DYNAMIC;
171 #endif
172 #endif
174 void*
175 dllnext(int flags)
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;
187 static char next[] = { _DLL_NEXT_PATH };
188 #endif
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)
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] == '.')
204 path = map->lm_name;
205 break;
208 #endif
209 ver = path + strlen(path);
210 while (!(dll = dllopen(path, flags)))
214 if (ver <= path)
215 return 0;
216 } while (*--ver != '.');
217 if (*(ver + 1) <= '0' || *(ver + 1) >= '9')
218 return 0;
219 *ver = 0;
221 #endif
222 return dll;