1/*---------------------------------------------------------------------------* 2 | PDFlib - A library for generating PDF on the fly | 3 +---------------------------------------------------------------------------+ 4 | Copyright (c) 1997-2004 Thomas Merz and PDFlib GmbH. All rights reserved. | 5 +---------------------------------------------------------------------------+ 6 | | 7 | This software is subject to the PDFlib license. It is NOT in the | 8 | public domain. Extended versions and commercial licenses are | 9 | available, please check http://www.pdflib.com. | 10 | | 11 *---------------------------------------------------------------------------*/ 12 13/* $Id: pdflibdl.c 14574 2005-10-29 16:27:43Z bonefish $ 14 * 15 * C wrapper code for dynamically loading the PDFlib DLL at runtime. 16 * 17 * This module is not supported on all platforms. 18 * 19 */ 20 21#include <stdlib.h> 22 23#include "pdflibdl.h" 24 25/* enable this to avoid error messages */ 26//#define PDF_SILENT 27 28/* ---------------------------------- WIN32 ----------------------------- */ 29 30#ifdef WIN32 31 32#define WIN32_LEAN_AND_MEAN 33#include <windows.h> 34#include <winbase.h> 35#undef WIN32_LEAN_AND_MEAN 36 37#define PDF_DLLNAME "pdflib.dll" 38 39static void * 40pdf_dlopen(const char *filename) 41{ 42 return (void *) LoadLibrary(filename); 43} 44 45static void * 46pdf_dlsym(void *handle, const char *funcname) 47{ 48 return (void *) GetProcAddress((HINSTANCE) handle, funcname); 49} 50 51static void 52pdf_dlclose(void *handle) 53{ 54 (void) FreeLibrary((HINSTANCE) handle); 55} 56 57/* ---------------------------------- MVS ----------------------------- */ 58 59#elif defined(__MVS__) 60 61#include <dynit.h> 62#include <dll.h> 63 64#define PDF_DLLNAME "PDFLIB" 65 66static void * 67pdf_dlopen(const char *filename) 68{ 69 return dllload(filename); 70} 71 72static void * 73pdf_dlsym(void *handle, const char *funcname) 74{ 75 return dllqueryfn((dllhandle *) handle, funcname); 76} 77 78static void pdf_dlclose(void *handle) 79{ 80 (void) dllfree((dllhandle *) handle); 81} 82 83/* ---------------------------------- Linux ----------------------------- */ 84 85#elif defined(linux) 86 87#include <dlfcn.h> 88 89#define PDF_DLLNAME "libpdf.so" 90 91static void * 92pdf_dlopen(const char *filename) 93{ 94 return dlopen(filename, RTLD_LAZY); 95} 96 97static void * 98pdf_dlsym(void *handle, const char *funcname) 99{ 100 return dlsym(handle, funcname); 101} 102 103static void pdf_dlclose(void *handle) 104{ 105 (void) dlclose(handle); 106} 107 108/* ---------------------------------- Mac OS X ----------------------------- */ 109 110#elif defined(__ppc__) && defined(__APPLE__) 111 112#define PDF_DLLNAME "libpdf.dylib" 113 114/* 115 * The dl code for Mac OS X has been butchered from dlcompat, 116 * see http://www.opendarwin.org/projects/dlcompat 117 * It contained the copyright notice below. 118 */ 119 120/* 121Copyright (c) 2002 Peter O'Gorman <ogorman@users.sourceforge.net> 122 123Permission is hereby granted, free of charge, to any person obtaining 124a copy of this software and associated documentation files (the 125"Software"), to deal in the Software without restriction, including 126without limitation the rights to use, copy, modify, merge, publish, 127distribute, sublicense, and/or sell copies of the Software, and to 128permit persons to whom the Software is furnished to do so, subject to 129the following conditions: 130 131The above copyright notice and this permission notice shall be 132included in all copies or substantial portions of the Software. 133 134THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 135EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 136MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 137NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 138LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 139OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 140WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 141*/ 142 143#include <string.h> 144#include <mach-o/dyld.h> 145 146#if defined (__GNUC__) && __GNUC__ > 3 147#define dl_restrict __restrict 148#else 149#define dl_restrict 150#endif 151/* 152 * Structure filled in by dladdr(). 153 */ 154 155typedef struct dl_info { 156 const char *dli_fname; /* Pathname of shared object */ 157 void *dli_fbase; /* Base address of shared object */ 158 const char *dli_sname; /* Name of nearest symbol */ 159 void *dli_saddr; /* Address of nearest symbol */ 160} Dl_info; 161 162#define RTLD_LAZY 0x1 163#define RTLD_NOW 0x2 164#define RTLD_LOCAL 0x4 165#define RTLD_GLOBAL 0x8 166#define RTLD_NOLOAD 0x10 167#define RTLD_NODELETE 0x80 168 169/* 170 * Special handle arguments for dlsym(). 171 */ 172#define RTLD_NEXT ((void *) -1) /* Search subsequent objects. */ 173#define RTLD_DEFAULT ((void *) -2) /* Use default search algorithm. */ 174 175static void *dlsymIntern(void *handle, const char *symbol); 176 177void *pdf_dlopen(const char *path) 178{ 179 int mode = RTLD_LAZY; 180 void *module = 0; 181 NSObjectFileImage ofi = 0; 182 NSObjectFileImageReturnCode ofirc; 183 static int (*make_private_module_public) (NSModule module) = 0; 184 unsigned int flags = 185 NSLINKMODULE_OPTION_RETURN_ON_ERROR | NSLINKMODULE_OPTION_PRIVATE; 186 187/* If we got no path, the app wants the global namespace, use -1 as the marker 188 in this case */ 189 if (!path) 190 return (void *)-1; 191 192 /* Create the object file image, works for things linked with the 193 -bundle arg to ld */ 194 ofirc = NSCreateObjectFileImageFromFile(path, &ofi); 195 switch (ofirc) 196 { 197 case NSObjectFileImageSuccess: 198 /* It was okay, so use NSLinkModule to link in the image */ 199 if (!(mode & RTLD_LAZY)) flags += NSLINKMODULE_OPTION_BINDNOW; 200 module = NSLinkModule(ofi, path,flags); 201 /* Don't forget to destroy the object file image, unless you like leaks */ 202 NSDestroyObjectFileImage(ofi); 203 /* If the mode was global, then change the module, this avoids 204 multiply defined symbol errors to first load private then make 205 global. Silly, isn't it. */ 206 if ((mode & RTLD_GLOBAL)) 207 { 208 if (!make_private_module_public) 209 { 210 _dyld_func_lookup("__dyld_NSMakePrivateModulePublic", 211 (unsigned long *)&make_private_module_public); 212 } 213 make_private_module_public(module); 214 } 215 break; 216 case NSObjectFileImageInappropriateFile: 217/* It may have been a dynamic library rather than a bundle, try to load it */ 218 module = 219 (void *)NSAddImage(path, NSADDIMAGE_OPTION_RETURN_ON_ERROR); 220 break; 221 case NSObjectFileImageFailure: 222 /* 223 error(0,"Object file setup failure : \"%s\"", path); 224 */ 225 return 0; 226 case NSObjectFileImageArch: 227 /* 228 error(0,"No object for this architecture : \"%s\"", path); 229 */ 230 return 0; 231 case NSObjectFileImageFormat: 232 /* 233 error(0,"Bad object file format : \"%s\"", path); 234 */ 235 return 0; 236 case NSObjectFileImageAccess: 237 /* 238 error(0,"Can't read object file : \"%s\"", path); 239 */ 240 return 0; 241 } 242 if (!module) 243 /* 244 error(0, "Can not open \"%s\"", path); 245 */ 246 ; 247 248 return module; 249} 250 251/* dlsymIntern is used by dlsym to find the symbol */ 252void *dlsymIntern(void *handle, const char *symbol) 253{ 254 NSSymbol *nssym = 0; 255 /* If the handle is -1, if is the app global context */ 256 if (handle == (void *)-1) 257 { 258 /* Global context, use NSLookupAndBindSymbol */ 259 if (NSIsSymbolNameDefined(symbol)) 260 { 261 nssym = NSLookupAndBindSymbol(symbol); 262 } 263 264 } 265 /* Now see if the handle is a struch mach_header* or not, use 266 NSLookupSymbol in image for libraries, and NSLookupSymbolInModule 267 for bundles */ 268 else 269 { 270 /* Check for both possible magic numbers depending on x86/ppc byte order */ 271 if ((((struct mach_header *)handle)->magic == MH_MAGIC) || 272 (((struct mach_header *)handle)->magic == MH_CIGAM)) 273 { 274 if (NSIsSymbolNameDefinedInImage((struct mach_header *)handle, symbol)) 275 { 276 nssym = NSLookupSymbolInImage((struct mach_header *)handle, 277 symbol, NSLOOKUPSYMBOLINIMAGE_OPTION_BIND 278 | NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR); 279 } 280 281 } 282 else 283 { 284 nssym = NSLookupSymbolInModule(handle, symbol); 285 } 286 } 287 if (!nssym) 288 { 289 /* 290 error(0, "Symbol \"%s\" Not found", symbol); 291 */ 292 return NULL; 293 } 294 return NSAddressOfSymbol(nssym); 295} 296 297int pdf_dlclose(void *handle) 298{ 299 if ((((struct mach_header *)handle)->magic == MH_MAGIC) || 300 (((struct mach_header *)handle)->magic == MH_CIGAM)) 301 { 302 /* 303 error(-1, "Can't remove dynamic libraries on darwin"); 304 */ 305 return 0; 306 } 307 if (!NSUnLinkModule(handle, 0)) 308 { 309 /* 310 error(0, "unable to unlink module %s", NSNameOfModule(handle)); 311 */ 312 return 1; 313 } 314 return 0; 315} 316 317/* dlsym, prepend the underscore and call dlsymIntern */ 318void *pdf_dlsym(void *handle, const char *symbol) 319{ 320 static char undersym[257]; /* Saves calls to malloc(3) */ 321 int sym_len = strlen(symbol); 322 void *value = NULL; 323 char *malloc_sym = NULL; 324 325 if (sym_len < 256) 326 { 327 snprintf(undersym, 256, "_%s", symbol); 328 value = dlsymIntern(handle, undersym); 329 } 330 else 331 { 332 malloc_sym = malloc(sym_len + 2); 333 if (malloc_sym) 334 { 335 sprintf(malloc_sym, "_%s", symbol); 336 value = dlsymIntern(handle, malloc_sym); 337 free(malloc_sym); 338 } 339 else 340 { 341 /* 342 error(-1, "Unable to allocate memory"); 343 */ 344 } 345 } 346 return value; 347} 348 349/* ---------------------------------- AS/400 ----------------------------- */ 350 351#elif defined __ILEC400__ 352 353#include <string.h> 354 355#include <miptrnam.h> 356#include <qleawi.h> 357#include <qusec.h> 358#include "mgosifc.h" 359 360#define PDF_DLLNAME "PDFLIB" 361 362static void * 363pdf_dlopen(const char *filename) 364{ 365 char libName[11], objName[11], *s; 366 HMODULE handle; 367 _SYSPTR pSrvPgm; 368 Qle_ABP_Info_t actInfo; 369 int actInfoLen; 370 Qus_EC_t errCode; 371 372 memset(libName, '\0', sizeof(libName)); 373 if ((s = strchr(filename, '/')) == NULL) { 374 s = filename; 375 } else { 376 memcpy(libName, filename, s - filename); 377 if (!strcmp(libName, "*LIBL")) 378 libName[0] = '\0'; 379 s += 1; 380 } 381 strcpy(objName, s); 382 383 /* Get system pointer to service program */ 384 pSrvPgm = rslvsp(WLI_SRVPGM, objName, libName, _AUTH_NONE); 385 386 /* Activate Bound Program */ 387 handle = malloc(sizeof(int)); 388 actInfoLen = sizeof(actInfo); 389 errCode.Bytes_Provided = sizeof(errCode); 390 QleActBndPgm(&pSrvPgm, handle, &actInfo, &actInfoLen, &errCode); 391 392 if (errCode.Bytes_Available > 0) 393 return NULL; 394 395 return (void *) handle; 396} 397 398static void * 399pdf_dlsym(void *handle, const char *funcname) 400{ 401 int expID; 402 int expNameLen; 403 void *ret; 404 int expType; 405 Qus_EC_t errCode; 406 407 expID = 0; 408 expNameLen = strlen(funcname); 409 errCode.Bytes_Provided = sizeof(errCode); 410 QleGetExp((HMODULE) handle, 411 &expID, &expNameLen, funcname, &ret, &expType, &errCode); 412 413 if (errCode.Bytes_Available > 0) 414 return NULL; 415 416 return ret; 417} 418 419static void pdf_dlclose(void *handle) 420{ 421 free((HMODULE) handle); 422} 423 424/* ---------------------------------- unknown ----------------------------- */ 425 426#else 427 428#error No DLL loading code for this platform available! 429 430#endif 431 432/* ---------------------------------- generic ----------------------------- */ 433 434static void 435pdf_dlerror(const char *msg) 436{ 437#ifndef PDF_SILENT 438 fprintf(stderr, msg); 439#endif 440} 441 442/* Load the PDFlib DLL and fetch the API structure */ 443 444PDFLIB_API PDFlib_api * PDFLIB_CALL 445PDF_new_dl(PDF **pp) 446{ 447 PDFlib_api *PDFlib, *(PDFLIB_CALL *get_api)(void); 448 char buf[256]; 449 void *handle; 450 PDF *p; 451 452 /* load the PDFLIB DLL... */ 453 handle = pdf_dlopen(PDF_DLLNAME); 454 455 if (!handle) 456 { 457 pdf_dlerror("Error: couldn't load PDFlib DLL\n"); 458 return NULL; 459 } 460 461 /* ...and fetch function pointers */ 462 get_api = (PDFlib_api *(PDFLIB_CALL *)(void)) 463 pdf_dlsym(handle, "PDF_get_api"); 464 465 if (get_api == NULL) 466 { 467 pdf_dlerror( 468 "Error: couldn't find function PDF_get_api in PDFlib DLL\n"); 469 pdf_dlclose(handle); 470 return NULL; 471 } 472 473 /* Fetch the API structure and boot the library. */ 474 PDFlib = (*get_api)(); 475 476 /* 477 * Check the version number of the loaded DLL against that of 478 * the included header file to avoid version mismatch. 479 */ 480 481 if (PDFlib->sizeof_PDFlib_api != sizeof(PDFlib_api) || 482 PDFlib->major != PDFLIB_MAJORVERSION || 483 PDFlib->minor != PDFLIB_MINORVERSION) { 484 sprintf(buf, 485 "Error: loaded wrong version of PDFlib DLL\n" 486 "Expected version %d.%d (API size %d), loaded %d.%d (API size %d)\n", 487 PDFLIB_MAJORVERSION, PDFLIB_MINORVERSION, sizeof(PDFlib_api), 488 PDFlib->major, PDFlib->minor, PDFlib->sizeof_PDFlib_api); 489 pdf_dlerror(buf); 490 pdf_dlclose(handle); 491 return NULL; 492 } 493 494 /* Boot the library. */ 495 PDFlib->PDF_boot(); 496 497 /* 498 * Create a new PDFlib object; use PDF_new2() so that we can store 499 * the DLL handle within PDFlib and later retrieve it. 500 */ 501 if ((p = PDFlib->PDF_new2(NULL, NULL, NULL, NULL, handle)) == (PDF *) NULL) 502 { 503 pdf_dlerror("Couldn't create PDFlib object (out of memory)!\n"); 504 return NULL; 505 } 506 507 /* Make the PDF * available to the client and return */ 508 *pp = p; 509 return PDFlib; 510} 511 512/* delete the PDFlib object and unload the previously loaded PDFlib DLL */ 513 514PDFLIB_API void PDFLIB_CALL 515PDF_delete_dl(PDFlib_api *PDFlib, PDF *p) 516{ 517 void *handle; 518 519 if (!PDFlib || !p) 520 return; 521 522 /* fetch the DLL handle (previously stored in PDFlib) */ 523 handle = PDFlib->PDF_get_opaque(p); 524 525 if (!handle) 526 return; 527 528 PDFlib->PDF_delete(p); 529 PDFlib->PDF_shutdown(); 530 531 pdf_dlclose(handle); 532} 533