1 /*
2 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
3 * Use is subject to license terms.
4 */
5
6 /* dlopen.c--Unix dlopen() dynamic loader interface
7 * Rob Siemborski
8 * Rob Earhart
9 * $Id: dlopen.c,v 1.45 2003/07/14 20:08:50 rbraun Exp $
10 */
11 /*
12 * Copyright (c) 1998-2003 Carnegie Mellon University. All rights reserved.
13 *
14 * Redistribution and use in source and binary forms, with or without
15 * modification, are permitted provided that the following conditions
16 * are met:
17 *
18 * 1. Redistributions of source code must retain the above copyright
19 * notice, this list of conditions and the following disclaimer.
20 *
21 * 2. Redistributions in binary form must reproduce the above copyright
22 * notice, this list of conditions and the following disclaimer in
23 * the documentation and/or other materials provided with the
24 * distribution.
25 *
26 * 3. The name "Carnegie Mellon University" must not be used to
27 * endorse or promote products derived from this software without
28 * prior written permission. For permission or any other legal
29 * details, please contact
30 * Office of Technology Transfer
31 * Carnegie Mellon University
32 * 5000 Forbes Avenue
33 * Pittsburgh, PA 15213-3890
34 * (412) 268-4387, fax: (412) 268-7395
35 * tech-transfer@andrew.cmu.edu
36 *
37 * 4. Redistributions of any form whatsoever must retain the following
38 * acknowledgment:
39 * "This product includes software developed by Computing Services
40 * at Carnegie Mellon University (http://www.cmu.edu/computing/)."
41 *
42 * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO
43 * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
44 * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE
45 * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
46 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
47 * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
48 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
49 */
50
51 #include <config.h>
52 #ifdef HAVE_DLFCN_H
53 #include <dlfcn.h>
54 #endif
55
56 #include <stdlib.h>
57 #include <errno.h>
58 #include <stdio.h>
59 #include <limits.h>
60
61 #include <sasl.h>
62 #include "saslint.h"
63
64 #ifndef PIC
65 #include <saslplug.h>
66 #include "staticopen.h"
67 #endif
68
69 #ifdef _SUN_SDK_
70 #include <sys/stat.h>
71 #endif /* _SUN_SDK_ */
72
73 #ifdef DO_DLOPEN
74 #if HAVE_DIRENT_H
75 # include <dirent.h>
76 # define NAMLEN(dirent) strlen((dirent)->d_name)
77 #else /* HAVE_DIRENT_H */
78 # define dirent direct
79 # define NAMLEN(dirent) (dirent)->d_namlen
80 # if HAVE_SYS_NDIR_H
81 # include <sys/ndir.h>
82 # endif
83 # if HAVE_SYS_DIR_H
84 # include <sys/dir.h>
85 # endif
86 # if HAVE_NDIR_H
87 # include <ndir.h>
88 # endif
89 #endif /* ! HAVE_DIRENT_H */
90
91 #ifndef NAME_MAX
92 # ifdef _POSIX_NAME_MAX
93 # define NAME_MAX _POSIX_NAME_MAX
94 # else
95 # define NAME_MAX 16
96 # endif
97 #endif
98
99 #if NAME_MAX < 8
100 # define NAME_MAX 8
101 #endif
102
103 #ifdef __hpux
104 #include <dl.h>
105
106 typedef shl_t dll_handle;
107 typedef void * dll_func;
108
109 dll_handle
dlopen(char * fname,int mode)110 dlopen(char *fname, int mode)
111 {
112 shl_t h = shl_load(fname, BIND_DEFERRED, 0L);
113 shl_t *hp = NULL;
114
115 if (h) {
116 hp = (shl_t *)malloc(sizeof (shl_t));
117 if (!hp) {
118 shl_unload(h);
119 } else {
120 *hp = h;
121 }
122 }
123
124 return (dll_handle)hp;
125 }
126
127 int
dlclose(dll_handle h)128 dlclose(dll_handle h)
129 {
130 shl_t hp = *((shl_t *)h);
131 if (hp != NULL) free(hp);
132 return shl_unload(h);
133 }
134
135 dll_func
dlsym(dll_handle h,char * n)136 dlsym(dll_handle h, char *n)
137 {
138 dll_func handle;
139
140 if (shl_findsym ((shl_t *)h, n, TYPE_PROCEDURE, &handle))
141 return NULL;
142
143 return (dll_func)handle;
144 }
145
dlerror()146 char *dlerror()
147 {
148 if (errno != 0) {
149 return strerror(errno);
150 }
151 return "Generic shared library error";
152 }
153
154 #define SO_SUFFIX ".sl"
155 #else /* __hpux */
156 #define SO_SUFFIX ".so"
157 #endif /* __hpux */
158
159 #define LA_SUFFIX ".la"
160 #endif /* DO_DLOPEN */
161
162 #if defined DO_DLOPEN || defined WIN_PLUG /* _SUN_SDK_ */
163 typedef struct lib_list
164 {
165 struct lib_list *next;
166 void *library;
167 } lib_list_t;
168
169 #ifndef _SUN_SDK_
170 static lib_list_t *lib_list_head = NULL;
171 #endif /* !_SUN_SDK_ */
172
173 DEFINE_STATIC_MUTEX(global_mutex);
174
175 #endif /* DO_DLOPEN || WIN_PLUG */ /* _SUN_SDK_ */
176
_sasl_locate_entry(void * library,const char * entryname,void ** entry_point)177 int _sasl_locate_entry(void *library, const char *entryname,
178 void **entry_point)
179 {
180 #ifdef DO_DLOPEN
181 /* note that we still check for known problem systems in
182 * case we are cross-compiling */
183 #if defined(DLSYM_NEEDS_UNDERSCORE) || defined(__OpenBSD__)
184 char adj_entryname[1024];
185 #else
186 #define adj_entryname entryname
187 #endif
188
189 if(!entryname) {
190 #ifndef _SUN_SDK_
191 _sasl_log(NULL, SASL_LOG_ERR,
192 "no entryname in _sasl_locate_entry");
193 #endif /* _SUN_SDK_ */
194 return SASL_BADPARAM;
195 }
196
197 if(!library) {
198 #ifndef _SUN_SDK_
199 _sasl_log(NULL, SASL_LOG_ERR,
200 "no library in _sasl_locate_entry");
201 #endif /* _SUN_SDK_ */
202 return SASL_BADPARAM;
203 }
204
205 if(!entry_point) {
206 #ifndef _SUN_SDK_
207 _sasl_log(NULL, SASL_LOG_ERR,
208 "no entrypoint output pointer in _sasl_locate_entry");
209 #endif /* _SUN_SDK_ */
210 return SASL_BADPARAM;
211 }
212
213 #if defined(DLSYM_NEEDS_UNDERSCORE) || defined(__OpenBSD__)
214 snprintf(adj_entryname, sizeof adj_entryname, "_%s", entryname);
215 #endif
216
217 *entry_point = NULL;
218 *entry_point = dlsym(library, adj_entryname);
219 if (*entry_point == NULL) {
220 #if 0 /* This message appears to confuse people */
221 _sasl_log(NULL, SASL_LOG_DEBUG,
222 "unable to get entry point %s: %s", adj_entryname,
223 dlerror());
224 #endif
225 return SASL_FAIL;
226 }
227
228 return SASL_OK;
229 #else
230 return SASL_FAIL;
231 #endif /* DO_DLOPEN */
232 }
233
234 #ifdef DO_DLOPEN
235
236 #ifdef _SUN_SDK_
_sasl_plugin_load(_sasl_global_context_t * gctx,char * plugin,void * library,const char * entryname,int (* add_plugin)(_sasl_global_context_t * gctx,const char *,void *))237 static int _sasl_plugin_load(_sasl_global_context_t *gctx,
238 char *plugin, void *library,
239 const char *entryname,
240 int (*add_plugin)(_sasl_global_context_t *gctx,
241 const char *, void *))
242 #else
243 static int _sasl_plugin_load(char *plugin, void *library,
244 const char *entryname,
245 int (*add_plugin)(const char *, void *))
246 #endif /* _SUN_SDK_ */
247 {
248 void *entry_point;
249 int result;
250
251 result = _sasl_locate_entry(library, entryname, &entry_point);
252 if(result == SASL_OK) {
253 #ifdef _SUN_SDK_
254 result = add_plugin(gctx, plugin, entry_point);
255 #else
256 result = add_plugin(plugin, entry_point);
257 #endif /* _SUN_SDK_ */
258 if(result != SASL_OK)
259 #ifdef _SUN_SDK_
260 __sasl_log(gctx, gctx->server_global_callbacks.callbacks == NULL ?
261 gctx->client_global_callbacks.callbacks :
262 gctx->server_global_callbacks.callbacks,
263 SASL_LOG_DEBUG,
264 "_sasl_plugin_load failed on %s for plugin: %s\n",
265 entryname, plugin);
266 #else
267 _sasl_log(NULL, SASL_LOG_DEBUG,
268 "_sasl_plugin_load failed on %s for plugin: %s\n",
269 entryname, plugin);
270 #endif /* _SUN_SDK_ */
271 }
272
273 return result;
274 }
275
276 #ifndef _SUN_SDK_
277 /* this returns the file to actually open.
278 * out should be a buffer of size PATH_MAX
279 * and may be the same as in. */
280
281 /* We'll use a static buffer for speed unless someone complains */
282 #define MAX_LINE 2048
283
_parse_la(const char * prefix,const char * in,char * out)284 static int _parse_la(const char *prefix, const char *in, char *out)
285 {
286 FILE *file;
287 size_t length;
288 char line[MAX_LINE];
289 char *ntmp = NULL;
290
291 if(!in || !out || !prefix || out == in) return SASL_BADPARAM;
292
293 /* Set this so we can detect failure */
294 *out = '\0';
295
296 length = strlen(in);
297
298 if (strcmp(in + (length - strlen(LA_SUFFIX)), LA_SUFFIX)) {
299 if(!strcmp(in + (length - strlen(SO_SUFFIX)),SO_SUFFIX)) {
300 /* check for a .la file */
301 strcpy(line, prefix);
302 strcat(line, in);
303 length = strlen(line);
304 *(line + (length - strlen(SO_SUFFIX))) = '\0';
305 strcat(line, LA_SUFFIX);
306 file = fopen(line, "rF");
307 if(file) {
308 /* We'll get it on the .la open */
309 fclose(file);
310 return SASL_FAIL;
311 }
312 }
313 strcpy(out, prefix);
314 strcat(out, in);
315 return SASL_OK;
316 }
317
318 strcpy(line, prefix);
319 strcat(line, in);
320
321 file = fopen(line, "rF");
322 if(!file) {
323 _sasl_log(NULL, SASL_LOG_WARN,
324 "unable to open LA file: %s", line);
325 return SASL_FAIL;
326 }
327
328 while(!feof(file)) {
329 if(!fgets(line, MAX_LINE, file)) break;
330 if(line[strlen(line) - 1] != '\n') {
331 _sasl_log(NULL, SASL_LOG_WARN,
332 "LA file has too long of a line: %s", in);
333 return SASL_BUFOVER;
334 }
335 if(line[0] == '\n' || line[0] == '#') continue;
336 if(!strncmp(line, "dlname=", sizeof("dlname=") - 1)) {
337 /* We found the line with the name in it */
338 char *end;
339 char *start;
340 size_t len;
341 end = strrchr(line, '\'');
342 if(!end) continue;
343 start = &line[sizeof("dlname=")-1];
344 len = strlen(start);
345 if(len > 3 && start[0] == '\'') {
346 ntmp=&start[1];
347 *end='\0';
348 /* Do we have dlname="" ? */
349 if(ntmp == end) {
350 _sasl_log(NULL, SASL_LOG_DEBUG,
351 "dlname is empty in .la file: %s", in);
352 return SASL_FAIL;
353 }
354 strcpy(out, prefix);
355 strcat(out, ntmp);
356 }
357 break;
358 }
359 }
360 if(ferror(file) || feof(file)) {
361 _sasl_log(NULL, SASL_LOG_WARN,
362 "Error reading .la: %s\n", in);
363 fclose(file);
364 return SASL_FAIL;
365 }
366 fclose(file);
367
368 if(!(*out)) {
369 _sasl_log(NULL, SASL_LOG_WARN,
370 "Could not find a dlname line in .la file: %s", in);
371 return SASL_FAIL;
372 }
373
374 return SASL_OK;
375 }
376 #endif /* !_SUN_SDK_ */
377 #endif /* DO_DLOPEN */
378
379 /* loads a plugin library */
380 #ifdef _SUN_SDK_
_sasl_get_plugin(_sasl_global_context_t * gctx,const char * file,const sasl_callback_t * verifyfile_cb,void ** libraryptr)381 int _sasl_get_plugin(_sasl_global_context_t *gctx,
382 const char *file,
383 const sasl_callback_t *verifyfile_cb,
384 void **libraryptr)
385 #else
386 int _sasl_get_plugin(const char *file,
387 const sasl_callback_t *verifyfile_cb,
388 void **libraryptr)
389 #endif /* _SUN_SDK_ */
390 {
391 #ifdef DO_DLOPEN
392 int r = 0;
393 int flag;
394 void *library;
395 lib_list_t *newhead;
396
397 r = ((sasl_verifyfile_t *)(verifyfile_cb->proc))
398 (verifyfile_cb->context, file, SASL_VRFY_PLUGIN);
399 if (r != SASL_OK) return r;
400
401 #ifdef RTLD_NOW
402 flag = RTLD_NOW;
403 #else
404 flag = 0;
405 #endif
406
407 newhead = sasl_ALLOC(sizeof(lib_list_t));
408 if(!newhead) return SASL_NOMEM;
409
410 if (!(library = dlopen(file, flag))) {
411 #ifdef _SUN_SDK_
412 __sasl_log(gctx, gctx->server_global_callbacks.callbacks == NULL ?
413 gctx->client_global_callbacks.callbacks :
414 gctx->server_global_callbacks.callbacks,
415 SASL_LOG_ERR,
416 "unable to dlopen %s: %s", file, dlerror());
417 #else
418 _sasl_log(NULL, SASL_LOG_ERR,
419 "unable to dlopen %s: %s", file, dlerror());
420 #endif /* _SUN_SDK_ */
421 sasl_FREE(newhead);
422 return SASL_FAIL;
423 }
424
425 #ifdef _SUN_SDK_
426 if (LOCK_MUTEX(&global_mutex) < 0) {
427 sasl_FREE(newhead);
428 dlclose(library);
429 return (SASL_FAIL);
430 }
431 #endif /* _SUN_SDK_ */
432
433 newhead->library = library;
434 #ifdef _SUN_SDK_
435 newhead->next = gctx->lib_list_head;
436 gctx->lib_list_head = newhead;
437 UNLOCK_MUTEX(&global_mutex);
438 #else
439 newhead->next = lib_list_head;
440 lib_list_head = newhead;
441 #endif /* _SUN_SDK_ */
442
443 *libraryptr = library;
444 return SASL_OK;
445 #else
446 return SASL_FAIL;
447 #endif /* DO_DLOPEN */
448 }
449
450 #ifdef _SUN_SDK_
451 #if defined DO_DLOPEN || defined WIN_PLUG /* _SUN_SDK_ */
452
release_plugin(_sasl_global_context_t * gctx,void * library)453 static void release_plugin(_sasl_global_context_t *gctx, void *library)
454 {
455 lib_list_t *libptr, *libptr_next = NULL, *libptr_prev = NULL;
456 int r;
457
458 r = LOCK_MUTEX(&global_mutex);
459 if (r < 0)
460 return;
461
462 for(libptr = gctx->lib_list_head; libptr; libptr = libptr_next) {
463 libptr_next = libptr->next;
464 if (library == libptr->library) {
465 if(libptr->library)
466 #if defined DO_DLOPEN /* _SUN_SDK_ */
467 dlclose(libptr->library);
468 #else
469 FreeLibrary(libptr->library);
470 #endif /* DO_DLOPEN */ /* _SUN_SDK_ */
471 sasl_FREE(libptr);
472 break;
473 }
474 libptr_prev = libptr;
475 }
476 if (libptr_prev == NULL)
477 gctx->lib_list_head = libptr_next;
478 else
479 libptr_prev->next = libptr_next;
480
481 UNLOCK_MUTEX(&global_mutex);
482 }
483 #endif /* DO_DLOPEN || WIN_PLUG */ /* _SUN_SDK_ */
484 #endif /* _SUN_SDK_ */
485
486 /* gets the list of mechanisms */
487 #ifdef _SUN_SDK_
_sasl_load_plugins(_sasl_global_context_t * gctx,int server,const add_plugin_list_t * entrypoints,const sasl_callback_t * getpath_cb,const sasl_callback_t * verifyfile_cb)488 int _sasl_load_plugins(_sasl_global_context_t *gctx,
489 int server,
490 const add_plugin_list_t *entrypoints,
491 const sasl_callback_t *getpath_cb,
492 const sasl_callback_t *verifyfile_cb)
493 #else
494 int _sasl_load_plugins(const add_plugin_list_t *entrypoints,
495 const sasl_callback_t *getpath_cb,
496 const sasl_callback_t *verifyfile_cb)
497 #endif /* _SUN_SDK_ */
498 {
499 int result;
500 const add_plugin_list_t *cur_ep;
501 #ifdef _SUN_SDK_
502 _sasl_path_info_t *path_info, *p_info;
503 #endif /* _SUN_SDK_ */
504 #ifdef DO_DLOPEN
505 char str[PATH_MAX], tmp[PATH_MAX+2], prefix[PATH_MAX+2];
506 /* 1 for '/' 1 for trailing '\0' */
507 char c;
508 int pos;
509 const char *path=NULL;
510 int position;
511 DIR *dp;
512 struct dirent *dir;
513 #ifdef _SUN_SDK_
514 int plugin_loaded;
515 struct stat b;
516 #endif /* _SUN_SDK_ */
517 #endif
518 #ifndef PIC
519 add_plugin_t *add_plugin;
520 _sasl_plug_type type;
521 _sasl_plug_rec *p;
522 #endif
523
524 if (! entrypoints
525 || ! getpath_cb
526 || getpath_cb->id != SASL_CB_GETPATH
527 || ! getpath_cb->proc
528 || ! verifyfile_cb
529 || verifyfile_cb->id != SASL_CB_VERIFYFILE
530 || ! verifyfile_cb->proc)
531 return SASL_BADPARAM;
532
533 #ifndef PIC
534 /* do all the static plugins first */
535
536 for(cur_ep = entrypoints; cur_ep->entryname; cur_ep++) {
537
538 /* What type of plugin are we looking for? */
539 if(!strcmp(cur_ep->entryname, "sasl_server_plug_init")) {
540 type = SERVER;
541 #ifdef _SUN_SDK_
542 add_plugin = (add_plugin_t *)_sasl_server_add_plugin;
543 #else
544 add_plugin = (add_plugin_t *)sasl_server_add_plugin;
545 #endif /* _SUN_SDK_ */
546 } else if (!strcmp(cur_ep->entryname, "sasl_client_plug_init")) {
547 type = CLIENT;
548 #ifdef _SUN_SDK_
549 add_plugin = (add_plugin_t *)_sasl_client_add_plugin;
550 #else
551 add_plugin = (add_plugin_t *)sasl_client_add_plugin;
552 #endif /* _SUN_SDK_ */
553 } else if (!strcmp(cur_ep->entryname, "sasl_auxprop_plug_init")) {
554 type = AUXPROP;
555 #ifdef _SUN_SDK_
556 add_plugin = (add_plugin_t *)_sasl_auxprop_add_plugin;
557 #else
558 add_plugin = (add_plugin_t *)sasl_auxprop_add_plugin;
559 #endif /* _SUN_SDK_ */
560 } else if (!strcmp(cur_ep->entryname, "sasl_canonuser_init")) {
561 type = CANONUSER;
562 #ifdef _SUN_SDK_
563 add_plugin = (add_plugin_t *)_sasl_canonuser_add_plugin;
564 #else
565 add_plugin = (add_plugin_t *)sasl_canonuser_add_plugin;
566 #endif /* _SUN_SDK_ */
567 } else {
568 /* What are we looking for then? */
569 return SASL_FAIL;
570 }
571 for (p=_sasl_static_plugins; p->type; p++) {
572 if(type == p->type)
573 #ifdef _SUN_SDK_
574 result = add_plugin(gctx, p->name, (void *)p->plug);
575 #else
576 result = add_plugin(p->name, p->plug);
577 #endif /* _SUN_SDK_ */
578 }
579 }
580 #endif /* !PIC */
581
582 /* only do the following if:
583 *
584 * we support dlopen()
585 * AND we are not staticly compiled
586 * OR we are staticly compiled and TRY_DLOPEN_WHEN_STATIC is defined
587 */
588 #if defined(DO_DLOPEN) && (defined(PIC) || (!defined(PIC) && defined(TRY_DLOPEN_WHEN_STATIC)))
589 /* get the path to the plugins */
590 result = ((sasl_getpath_t *)(getpath_cb->proc))(getpath_cb->context,
591 &path);
592 if (result != SASL_OK) return result;
593 if (! path) return SASL_FAIL;
594
595 if (strlen(path) >= PATH_MAX) { /* no you can't buffer overrun */
596 return SASL_FAIL;
597 }
598
599 position=0;
600 do {
601 pos=0;
602 do {
603 c=path[position];
604 position++;
605 str[pos]=c;
606 pos++;
607 } while ((c!=':') && (c!='=') && (c!=0));
608 str[pos-1]='\0';
609
610 strcpy(prefix,str);
611 strcat(prefix,"/");
612 #ifdef _SUN_SDK_
613 path_info = server ? gctx->splug_path_info : gctx->cplug_path_info;
614 while (path_info != NULL) {
615 if (strcmp(path_info->path, prefix) == 0)
616 break;
617 path_info = path_info->next;
618 }
619 if (stat(prefix, &b) != 0) {
620 continue;
621 }
622 if ( path_info == NULL) {
623 p_info = (_sasl_path_info_t *)
624 sasl_ALLOC(sizeof (_sasl_path_info_t));
625 if (p_info == NULL) {
626 return SASL_NOMEM;
627 }
628 if(_sasl_strdup(prefix, &p_info->path, NULL) != SASL_OK) {
629 sasl_FREE(p_info);
630 return SASL_NOMEM;
631 }
632 p_info->last_changed = b.st_mtime;
633 if (server) {
634 p_info->next = gctx->splug_path_info;
635 gctx->splug_path_info = p_info;
636 } else {
637 p_info->next = gctx->cplug_path_info;
638 gctx->cplug_path_info = p_info;
639 }
640 } else {
641 if (b.st_mtime <= path_info->last_changed) {
642 continue;
643 }
644 }
645 #endif /* _SUN_SDK_ */
646
647 if ((dp=opendir(str)) !=NULL) /* ignore errors */
648 {
649 while ((dir=readdir(dp)) != NULL)
650 {
651 size_t length;
652 void *library;
653 #ifndef _SUN_SDK_
654 char *c;
655 #endif /* !_SUN_SDK_ */
656 char plugname[PATH_MAX];
657 char name[PATH_MAX];
658
659 length = NAMLEN(dir);
660 #ifndef _SUN_SDK_
661 if (length < 4)
662 continue; /* can not possibly be what we're looking for */
663 #endif /* !_SUN_SDK_ */
664
665 if (length + pos>=PATH_MAX) continue; /* too big */
666
667 #ifdef _SUN_SDK_
668 if (dir->d_name[0] == '.')
669 continue;
670 #else
671 if (strcmp(dir->d_name + (length - strlen(SO_SUFFIX)),
672 SO_SUFFIX)
673 && strcmp(dir->d_name + (length - strlen(LA_SUFFIX)),
674 LA_SUFFIX))
675 continue;
676 #endif /* _SUN_SDK_ */
677
678 memcpy(name,dir->d_name,length);
679 name[length]='\0';
680
681 #ifdef _SUN_SDK_
682 snprintf(tmp, sizeof (tmp), "%s%s", prefix, name);
683 #else
684 result = _parse_la(prefix, name, tmp);
685 if(result != SASL_OK)
686 continue;
687 #endif /* _SUN_SDK_ */
688
689 #ifdef _SUN_SDK_
690 if (stat(tmp, &b))
691 continue; /* Can't stat it */
692 if (!S_ISREG(b.st_mode))
693 continue;
694 /* Sun plugins don't have lib prefix */
695 strcpy(plugname, name);
696 #else
697 /* skip "lib" and cut off suffix --
698 this only need be approximate */
699 strcpy(plugname, name + 3);
700 c = strchr(plugname, (int)'.');
701 if(c) *c = '\0';
702 #endif /* _SUN_SDK_ */
703
704 #ifdef _SUN_SDK_
705 result = _sasl_get_plugin(gctx, tmp, verifyfile_cb,
706 &library);
707 #else
708 result = _sasl_get_plugin(tmp, verifyfile_cb, &library);
709 #endif /* _SUN_SDK_ */
710
711 if(result != SASL_OK)
712 continue;
713
714 #ifdef _SUN_SDK_
715 plugin_loaded = 0;
716 for(cur_ep = entrypoints; cur_ep->entryname; cur_ep++) {
717 /* If this fails, it's not the end of the world */
718 if (_sasl_plugin_load(gctx, plugname, library,
719 cur_ep->entryname,
720 cur_ep->add_plugin) == SASL_OK) {
721 plugin_loaded = 1;
722 }
723 }
724 if (!plugin_loaded)
725 release_plugin(gctx, library);
726 #else
727 for(cur_ep = entrypoints; cur_ep->entryname; cur_ep++) {
728 _sasl_plugin_load(plugname, library, cur_ep->entryname,
729 cur_ep->add_plugin);
730 /* If this fails, it's not the end of the world */
731 }
732 #endif /* _SUN_SDK_ */
733 }
734
735 closedir(dp);
736 }
737
738 } while ((c!='=') && (c!=0));
739 #elif defined _SUN_SDK_ && defined WIN_PLUG
740 result =
741 _sasl_load_win_plugins(gctx, entrypoints, getpath_cb, verifyfile_cb);
742 if (result != SASL_OK)
743 return (result);
744 #endif /* defined(DO_DLOPEN) && (!defined(PIC) || (defined(PIC) && defined(TRY_DLOPEN_WHEN_STATIC))) */
745
746 return SASL_OK;
747 }
748
749 #ifdef _SUN_SDK_
750 int
_sasl_done_with_plugins(_sasl_global_context_t * gctx)751 _sasl_done_with_plugins(_sasl_global_context_t *gctx)
752 #else
753 int
754 _sasl_done_with_plugins(void)
755 #endif /* _SUN_SDK_ */
756 {
757 #if defined DO_DLOPEN || defined WIN_PLUG /* _SUN_SDK_ */
758 lib_list_t *libptr, *libptr_next;
759
760 #ifdef _SUN_SDK_
761 if (LOCK_MUTEX(&global_mutex) < 0)
762 return (SASL_FAIL);
763 #endif /* _SUN_SDK_ */
764
765 #ifdef _SUN_SDK_
766 for(libptr = gctx->lib_list_head; libptr; libptr = libptr_next) {
767 #else
768 for(libptr = lib_list_head; libptr; libptr = libptr_next) {
769 #endif /* _SUN_SDK_ */
770 libptr_next = libptr->next;
771 if(libptr->library)
772 #ifdef DO_DLOPEN /* _SUN_SDK_ */
773 dlclose(libptr->library);
774 #else
775 FreeLibrary(libptr->library);
776 #endif /* DO_DLOPEN */ /* _SUN_SDK_ */
777 sasl_FREE(libptr);
778 }
779
780 #ifdef _SUN_SDK_
781 gctx->lib_list_head = NULL;
782 #else
783 lib_list_head = NULL;
784 #endif /* _SUN_SDK_ */
785
786 #ifdef _SUN_SDK_
787 UNLOCK_MUTEX(&global_mutex);
788 #endif /* _SUN_SDK_ */
789 #endif /* DO_DLOPEN || WIN_PLUG */ /* _SUN_SDK_ */
790 return SASL_OK;
791 }
792
793 #ifdef WIN_MUTEX
794
795 static HANDLE global_mutex = NULL;
796
797 int win_global_mutex_lock()
798 {
799 DWORD dwWaitResult;
800
801 if (global_mutex == NULL) {
802 global_mutex = CreateMutex(NULL, FALSE, NULL);
803 if (global_mutex == NULL)
804 return (-1);
805 }
806
807 dwWaitResult = WaitForSingleObject(global_mutex, INFINITE);
808
809 switch (dwWaitResult) {
810 case WAIT_OBJECT_0:
811 return (0);
812
813 case WAIT_TIMEOUT:
814 return (-1); /* Shouldn't happen */
815
816 case WAIT_ABANDONED:
817 return (-1); /* Shouldn't happen */
818 }
819 return (-1); /* Unexpected result */
820 }
821
822 int win_global_mutex_unlock()
823 {
824 if (global_mutex == NULL)
825 return (-1);
826
827 return (ReleaseMutex(global_mutex) ? 0 : -1);
828 }
829
830 BOOL APIENTRY DllMain(HANDLE hModule,
831 DWORD ul_reason_for_call,
832 LPVOID lpReserved)
833 {
834 switch( ul_reason_for_call ) {
835 case DLL_PROCESS_ATTACH:
836 global_mutex = CreateMutex(NULL, FALSE, NULL);
837 if (global_mutex == NULL)
838 return (FALSE);
839 break;
840 case DLL_THREAD_ATTACH:
841 case DLL_THREAD_DETACH:
842 case DLL_PROCESS_DETACH:
843 break;
844 }
845 return TRUE;
846 }
847 #endif
848