]> git.saurik.com Git - wxWidgets.git/blame - src/iodbc/dlf.c
Better disabling of toolbars and menubars
[wxWidgets.git] / src / iodbc / dlf.c
CommitLineData
1a6944fd 1/** dynamic library loader (mapping to svr4)
7e616b10
RR
2
3 Copyright (C) 1995 by Ke Jin <kejin@empress.com>
1a6944fd
RR
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14**/
15
7e616b10
RR
16#ifdef DLDAPI_OS2
17# define INCL_DOSMODULEMGR /* Module Manager values */
18# define INCL_DOSERRORS /* Error values */
19# include <os2.h>
20# include <stdio.h>
21#endif
1a6944fd 22
7e616b10 23#include "wx/setup.h"
1a6944fd
RR
24#include <../iodbc/dlf.h>
25#include <errno.h>
26
7e616b10 27#ifdef DLDAPI_DEFINED
1a6944fd
RR
28# undef DLDAPI_DEFINED
29#endif
30
7e616b10 31#ifdef DLDAPI_SVR4_DLFCN
1a6944fd 32# define DLDAPI_DEFINED
7e616b10 33static char sccsid[] = "@(#)dynamic load interface -- SVR4 dlfcn";
1a6944fd
RR
34#endif
35
7e616b10 36/*********************************
1a6944fd 37 *
7e616b10 38 * HP/UX
1a6944fd
RR
39 *
40 *********************************/
7e616b10
RR
41#ifdef DLDAPI_HP_SHL
42# define DLDAPI_DEFINED
43# include <dl.h>
1a6944fd 44
7e616b10 45static char sccsid[] = "@(#)dynamic load interface -- HP/UX dl(shl)";
1a6944fd 46
7e616b10 47void* dlopen(char* path, int mode)
1a6944fd 48{
7e616b10 49 return (void*)shl_load((char*)(path), BIND_DEFERRED, 0L);
1a6944fd
RR
50}
51
7e616b10 52void* dlsym(void* hdll, char* sym)
1a6944fd 53{
7e616b10
RR
54 void* symaddr = 0;
55 int ret;
1a6944fd 56
7e616b10
RR
57 if( ! hdll )
58 hdll = (void*)PROG_HANDLE;
1a6944fd 59
7e616b10
RR
60 /* Remember, a driver may export calls as function pointers
61 * (i.e. with type TYPE_DATA) rather than as functions
62 * (i.e. with type TYPE_PROCEDURE). Thus, to be safe, we
63 * uses TYPE_UNDEFINED to cover all of them.
64 */
65 ret = shl_findsym((shl_t*)&hdll, sym, TYPE_UNDEFINED, &symaddr);
1a6944fd 66
7e616b10
RR
67 if( ret == -1 )
68 return 0;
1a6944fd 69
7e616b10 70 return symaddr;
1a6944fd
RR
71}
72
7e616b10 73char* dlerror()
1a6944fd 74{
7e616b10 75 extern char* strerror();
1a6944fd 76
7e616b10 77 return strerror(errno);
1a6944fd
RR
78}
79
7e616b10 80int dlclose(void* hdll)
1a6944fd 81{
7e616b10 82 return shl_unload((shl_t)hdll);
1a6944fd
RR
83}
84
7e616b10 85#endif /* end of HP/UX Seection */
1a6944fd
RR
86
87/*********************************
88 *
7e616b10 89 * IBM AIX
1a6944fd
RR
90 *
91 *********************************/
7e616b10
RR
92#ifdef DLDAPI_AIX_LOAD
93# define DLDAPI_DEFINED
94# include <sys/ldr.h>
95# include <sys/stat.h>
96# include <nlist.h>
1a6944fd
RR
97
98/*
7e616b10 99 * Following id sting is a copyright mark. Removing(i.e. use the
1a6944fd 100 * source code in this .c file without include it or make it not
7e616b10
RR
101 * appear in the final object file of AIX platform) or modifing
102 * it without permission from original author(kejin@empress.com)
1a6944fd
RR
103 * are copyright violation.
104 */
105static char sccsid[]
7e616b10 106 = "@(#)dynamic load interface, Copyright(c) 1995 by Ke Jin";
1a6944fd 107
7e616b10
RR
108# ifndef HTAB_SIZE
109# define HTAB_SIZE 256
1a6944fd
RR
110# endif
111
7e616b10 112# define FACTOR 0.618039887 /* i.e. (sqrt(5) - 1)/2 */
1a6944fd 113
7e616b10
RR
114# ifndef ENTRY_SYM
115# define ENTRY_SYM ".__start" /* default entry point for aix */
1a6944fd
RR
116# endif
117
118typedef struct slot_s
119{
7e616b10
RR
120 char* sym;
121 long fdesc[3]; /* 12 bytes function descriptor */
122 struct slot_s* next;
1a6944fd
RR
123} slot_t;
124
125/* Note: on AIX, a function pointer actually points to a
126 * function descriptor, a 12 bytes data. The first 4 bytes
7e616b10 127 * is the virtual address of the function. The next 4 bytes
1a6944fd 128 * is the virtual address of TOC (Table of Contents) of the
7e616b10
RR
129 * object module the function belong to. The last 4 bytes
130 * are always 0 for C and Fortran functions. Every object
1a6944fd
RR
131 * module has an entry point (which can be specified at link
132 * time by -e ld option). iODBC driver manager requires ODBC
133 * driver shared library always use the default entry point
134 * (so you shouldn't use -e ld option when creating a driver
7e616b10 135 * share library). load() returns the function descriptor of
1a6944fd
RR
136 * a module's entry point. From which we can calculate function
137 * descriptors of other functions in the same module by using
7e616b10
RR
138 * the fact that the load() doesn't change the relative
139 * offset of functions to their module entry point(i.e the
140 * offset in memory loaded by load() will be as same as in
141 * the module library file).
1a6944fd
RR
142 */
143
7e616b10
RR
144typedef slot_t* hent_t;
145typedef struct nlist nlist_t;
146typedef struct stat stat_t;
1a6944fd 147
7e616b10 148typedef struct obj
1a6944fd 149{
7e616b10
RR
150 int dev; /* device id */
151 int ino; /* inode number */
152 char* path; /* file name */
153 int (*pentry)(); /* entry point of this share library */
154 int refn; /* number of reference */
155 hent_t htab[HTAB_SIZE];
156 struct obj*
157 next;
1a6944fd
RR
158} obj_t;
159
7e616b10 160static char* errmsg = 0;
1a6944fd
RR
161
162static void init_htab(hent_t* ht)
163/* initate a hashing table */
164{
7e616b10 165 int i;
1a6944fd 166
7e616b10
RR
167 for(i=0; i<HTAB_SIZE; i++)
168 ht[i] = (slot_t*)0;
1a6944fd 169
7e616b10 170 return;
1a6944fd
RR
171}
172
173static void clean_htab(hent_t* ht)
174/* free all slots */
175{
7e616b10
RR
176 int i;
177 slot_t* ent;
178 slot_t* tent;
179
180 for(i = 0; i< HTAB_SIZE; i++)
181 {
182 for( ent = ht[i]; ent; )
183 {
184 tent = ent->next;
185
186 free(ent->sym);
187 free(ent);
188
189 ent = tent;
190 }
191
192 ht[i] = 0;
193 }
194
195 return;
1a6944fd
RR
196}
197
7e616b10 198static int hash(char* sym )
1a6944fd 199{
7e616b10
RR
200 int a, key;
201 double f;
1a6944fd 202
7e616b10
RR
203 if( !sym || !*sym )
204 return 0;
1a6944fd 205
7e616b10 206 for(key=*sym;*sym;sym++)
1a6944fd 207 {
7e616b10 208 key += *sym;
1a6944fd
RR
209 a = key;
210
7e616b10
RR
211 key = (int)( (a<<8) + (key>>8) );
212 key = (key>0)? key:-key;
1a6944fd
RR
213 }
214
7e616b10
RR
215 f = key*FACTOR;
216 a = (int)f;
1a6944fd 217
7e616b10 218 return (int)((HTAB_SIZE - 1)*( f - a ));
1a6944fd
RR
219}
220
7e616b10 221static hent_t search(hent_t* htab, char* sym)
1a6944fd
RR
222/* search hashing table to find a matched slot */
223{
7e616b10
RR
224 int key;
225 slot_t* ent;
1a6944fd 226
7e616b10 227 key = hash(sym);
1a6944fd 228
7e616b10
RR
229 for(ent = htab[key]; ent; ent = ent->next )
230 {
231 if(!strcmp(ent->sym, sym))
232 return ent;
233 }
1a6944fd 234
7e616b10 235 return 0; /* no match */
1a6944fd
RR
236}
237
7e616b10 238static void insert(hent_t* htab, slot_t* ent)
1a6944fd
RR
239/* insert a new slot to hashing table */
240{
7e616b10 241 int key;
1a6944fd 242
7e616b10 243 key = hash(ent->sym);
1a6944fd 244
7e616b10
RR
245 ent->next = htab[key];
246 htab[key] = ent;
1a6944fd 247
7e616b10 248 return;
1a6944fd
RR
249}
250
7e616b10 251static slot_t* slot_alloc(char* sym)
1a6944fd
RR
252/* allocate a new slot with symbol */
253{
7e616b10 254 slot_t* ent;
1a6944fd 255
7e616b10 256 ent = (slot_t*)malloc(sizeof(slot_t));
1a6944fd 257
7e616b10 258 ent->sym = (char*)malloc(strlen(sym)+1);
1a6944fd 259
7e616b10
RR
260 if( ! ent->sym )
261 {
262 free(ent);
263 return 0;
264 }
1a6944fd 265
7e616b10 266 strcpy( ent->sym, sym );
1a6944fd 267
7e616b10 268 return ent;
1a6944fd
RR
269}
270
271static obj_t* obj_list = 0;
272
7e616b10 273void* dlopen(char* file, int mode )
1a6944fd 274{
7e616b10
RR
275 stat_t st;
276 obj_t* pobj;
277 char buf[1024];
278
279 if( ! file || ! *file )
280 {
281 errno = EINVAL;
282 return 0;
283 }
284
285 errno = 0;
286 errmsg = 0;
1a6944fd
RR
287
288#if 0
7e616b10
RR
289 if( file[0] != '/' && file[0] != '.' )
290 {
291 for(;;)
292 {
293 sprintf(buf, "/lib/%s", file);
294
295 if( stat( buf, &st ) )
296 {
297 file = buf;
298 break;
299 }
300
301 sprintf(buf, "/usr/lib/%s", file);
302
303 if( stat( buf, &st ) )
304 {
305 file = buf;
306 break;
307 }
308
309 if( stat( file, &st ) )
310 break;
311
312 return 0;
313 }
314 }
315 else
1a6944fd 316#endif
7e616b10
RR
317 if( stat( file, &st ) )
318 return 0;
1a6944fd 319
7e616b10
RR
320 for( pobj = obj_list; pobj; pobj = pobj->next )
321 /* find a match object */
322 {
323 if( pobj->ino == st.st_ino
324 && pobj->dev == st.st_dev )
325 {
326 /* found a match. increase its
327 * reference count and return
328 * its address */
329 pobj->refn ++;
330 return pobj;
331 }
332 }
1a6944fd 333
7e616b10 334 pobj = (obj_t*)malloc( sizeof(obj_t) );
1a6944fd 335
7e616b10
RR
336 if( ! pobj )
337 return 0;
1a6944fd 338
7e616b10 339 pobj->path = (char*)malloc( strlen(file) + 1);
1a6944fd 340
7e616b10
RR
341 if( ! pobj->path )
342 {
343 free( pobj );
344 return 0;
345 }
1a6944fd 346
7e616b10 347 strcpy( pobj->path, file );
1a6944fd 348
7e616b10
RR
349 pobj->dev = st.st_dev;
350 pobj->ino = st.st_ino;
351 pobj->refn = 1;
1a6944fd 352
7e616b10 353 pobj->pentry = (int(*)())load(file, 0, 0);
1a6944fd 354
7e616b10
RR
355 if( ! pobj->pentry )
356 {
357 free( pobj->path );
358 free( pobj );
359 return 0;
360 }
1a6944fd 361
7e616b10 362 init_htab(pobj->htab);
1a6944fd 363
7e616b10
RR
364 pobj->next = obj_list;
365 obj_list = pobj;
1a6944fd 366
7e616b10 367 return pobj;
1a6944fd
RR
368}
369
7e616b10 370int dlclose(void* hobj)
1a6944fd 371{
7e616b10
RR
372 obj_t* pobj = (obj_t*)hobj;
373 obj_t* tpobj;
374 int match = 0;
375
376 if( ! hobj )
377 {
378 errno = EINVAL;
379 return -1;
380 }
381
382 errno = 0;
383 errmsg = 0;
384
385 if( pobj == obj_list )
386 {
387 pobj->refn --;
388
389 if( pobj->refn )
390 return 0;
391
392 match = 1;
393 obj_list = pobj->next;
394 }
395
396 for( tpobj = obj_list; !match && tpobj; tpobj = tpobj->next )
397 {
398 if( tpobj->next == pobj )
399 {
400 pobj->refn --;
401
402 if( pobj->refn )
403 return 0;
404
405 match = 1;
406 tpobj->next = pobj->next;
407 }
408 }
409
410 if(match)
411 {
412 unload((void*)(pobj->pentry));
413 clean_htab(pobj->htab);
414 free(pobj->path);
415 free(pobj);
416 }
417
418 return 0;
1a6944fd
RR
419}
420
7e616b10 421char* dlerror()
1a6944fd 422{
7e616b10 423 extern char* sys_errlist[];
1a6944fd 424
7e616b10
RR
425 if( ! errmsg || ! errmsg[0] )
426 {
427 if( errno >= 0 )
428 return sys_errlist[errno];
429
430 return "";
431 }
1a6944fd 432
7e616b10 433 return errmsg;
1a6944fd
RR
434}
435
7e616b10 436void* dlsym(void* hdl, char* sym)
1a6944fd 437{
7e616b10
RR
438 nlist_t nl[3];
439 obj_t* pobj = (obj_t*)hdl;
440 slot_t* ent;
441 int (*fp)();
442 long lbuf[3];
443
444 if( !hdl || !(pobj->htab) || !sym || ! *sym )
445 {
446 errno = EINVAL;
447 return 0;
448 }
449
450 errno = 0;
451 errmsg = 0;
452
453 ent = search( pobj->htab, sym );
454
455 if( ent )
456 return ent->fdesc;
457
458#define n_name _n._n_name
459
460 nl[0].n_name = ENTRY_SYM;
461 nl[1].n_name = sym;
462 nl[2].n_name = 0;
463
464 /* There is a potential problem here. If application
465 * did not pass a full path name, and changed the
466 * working directory after the load(), then nlist()
467 * will be unable to open the original shared library
468 * file to resolve the symbols. there are 3 ways to working
469 * round this: 1. convert to full pathname in driver
470 * manager. 2. applications always pass driver's full
471 * path name. 3. if driver itself don't support
472 * SQLGetFunctions(), call it with SQL_ALL_FUNCTIONS
473 * as flag immidately after SQLConnect(), SQLDriverConnect()
474 * and SQLBrowseConnect() to force the driver manager
475 * resolving all will be used symbols.
476 */
477 if( nlist( pobj->path, nl) == -1 )
478 return 0;
479
480 if( ! nl[0].n_type && ! nl[0].n_value )
481 {
482 errmsg = "can't locate module entry symbol";
483 return 0;
484 }
485
486 /* Note: On AIX 3.x if the object library is not
487 * built with -g compiling option, .n_type field
488 * is always 0. While on 4.x it will be 32.
489 * On AIX 4.x, if the symbol is a entry point,
490 * n_value will be 0. However, one thing is for sure
491 * that if a symbol is not existance in the file,
492 * both .n_type and .n_value would be 0.
493 */
494
495 if( ! nl[1].n_type && ! nl[1].n_value )
496 {
497 errmsg = "symbol not existance in this module";
498 return 0;
499 }
500
501 ent = slot_alloc(sym);
502
503 if( ! ent )
504 return 0;
505
506 /* catch it with a slot in the hashing table */
507 insert(pobj->htab, ent);
508
509 memcpy(ent->fdesc, pobj->pentry, sizeof(ent->fdesc));
510
511 /* now ent->fdesc[0] is the virtual address of entry point
512 * and ent->fdesc[1] is the TOC of the module
513 */
514
515 /* let's calculate the virtual address of the symbol
516 * by adding a relative offset getting from the module
517 * file symbol table, i.e
518 *
519 * functin virtual address = entry point virtual address +
520 * + ( function offset in file - entry point offset in file )
521 */
522
523 (ent->fdesc)[0] = (ent->fdesc)[0] +
524 ( nl[1].n_value - nl[0].n_value );
525
526 /* return the function descriptor */
527 return ent->fdesc;
1a6944fd
RR
528}
529
7e616b10 530#endif /* end of IBM AIX Section */
1a6944fd
RR
531
532
7e616b10 533/*********************************
1a6944fd 534 *
7e616b10 535 * Windows 3.x, 95, NT
1a6944fd
RR
536 *
537 *********************************/
7e616b10
RR
538#ifdef DLDAPI_WINDOWS
539# define DLDAPI_DEFINED
540# include <windows.h>
1a6944fd 541
7e616b10 542void FAR* dlopen(char FAR* dll, int mode)
1a6944fd 543{
7e616b10 544 HINSTANCE hint;
1a6944fd 545
7e616b10
RR
546 if( dll == NULL )
547 {
548 return GetWindowWord( NULL, GWW_HINSTANCE );
549 }
1a6944fd 550
7e616b10 551 hint = LoadLibrary(dll);
1a6944fd 552
7e616b10
RR
553 if( hint < HINSTANCE_ERROR )
554 {
555 return NULL;
556 }
1a6944fd 557
7e616b10 558 return (void FAR*)hint;
1a6944fd
RR
559}
560
7e616b10 561void FAR* dlsym( void FAR* hdll, char FAR* sym )
1a6944fd 562{
7e616b10 563 return (void FAR*)GetProcAddress(hdll, sym);
1a6944fd
RR
564}
565
7e616b10 566char FAR* dlerror()
1a6944fd 567{
7e616b10 568 return 0L; /* unimplemented yet */
1a6944fd
RR
569}
570
7e616b10 571int dlclose(void FAR* hdll)
1a6944fd 572{
7e616b10 573 FreeLibrary((HINSTANCE)hdll);
1a6944fd
RR
574}
575
7e616b10 576#endif /* end of Windows family */
1a6944fd 577
7e616b10 578/*********************************
1a6944fd 579 *
7e616b10 580 * OS/2 2.x, 3.x
1a6944fd 581 *
7e616b10 582 *********************************/
1a6944fd 583#ifdef DLDAPI_OS2
7e616b10 584# define DLDAPI_DEFINED
1a6944fd 585/*
7e616b10 586 * DosLoadModule(), DosQueryProcAddress(), DosFreeModule(), ...
1a6944fd 587 */
7e616b10
RR
588
589void FAR* dlopen(char FAR* dll, int mode)
590{
591 APIRET rc = NO_ERROR; /* API return code */
592 UCHAR LoadError[256] = ""; /* Area for Load fail. info */
593 HMODULE ModuleHandle = NULLHANDLE; /* Module handle */
594
595 if( dll == NULL || '\0' == *dll )
596 {
597 return NULL;
598 }
599
600 rc = NO_ERROR;
601 rc = DosLoadModule( LoadError, /* Failure info buffer */
602 sizeof(LoadError), /* Size of buffer */
603 dll, /* Module to load */
604 &ModuleHandle ); /* Module handle returned */
605 if (rc != NO_ERROR)
606 {
607#ifdef DEBUG
608 fprintf( stderr,
609 "[dlf.c] dlopen: DosLoadModule(0x%08lX, %d, \"%s\", 0x%08lX) = %d\n",
610 &LoadError, sizeof(LoadError), dll, &ModuleHandle, rc
611 );
612 fprintf( stderr,
613 " ---> missing module '%s'\n",
614 LoadError );
1a6944fd 615#endif
7e616b10
RR
616 return NULL;
617 }
1a6944fd 618
7e616b10
RR
619 return (void FAR*) ModuleHandle;
620
621}
622
623void FAR* dlsym( void FAR* hdll, char FAR* sym )
624{
625 APIRET rc = NO_ERROR; /* API return code */
626 PFN ModuleAddress = NULL; /* Module address */
627
628 rc = DosQueryProcAddr( (HMODULE) hdll, 0, sym, &ModuleAddress );
629
630 return (void FAR*) (NO_ERROR == rc) ? ModuleAddress
631 : NULL;
632}
633
634char FAR* dlerror()
635{
636 return 0L; /* unimplemented yet */
637}
638
639int dlclose(void FAR* hdll)
640{
641 return DosFreeModule( (HMODULE) hdll );
642}
643
644#endif
645
646/***********************************
647 *
648 * other platforms
649 *
650 ***********************************/
651#ifdef DLDAPI_MAC
652# define DLDAPI_DEFINED
1a6944fd
RR
653#endif
654
655#ifdef DLDAPI_NEXT
7e616b10 656# define DLDAPI_DEFINED
1a6944fd
RR
657#endif
658
659#ifndef DLDAPI_DEFINED
7e616b10 660# error "dynamic load editor undefined"
1a6944fd 661#endif