This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
POSIX: Check fds against negatives.
[perl5.git] / ext / DynaLoader / dlutils.c
CommitLineData
a0d0e21e
LW
1/* dlutils.c - handy functions and definitions for dl_*.xs files
2 *
3 * Currently this file is simply #included into dl_*.xs/.c files.
4 * It should really be split into a dlutils.h and dlutils.c
5 *
abb9e9dc
GS
6 * Modified:
7 * 29th Feburary 2000 - Alan Burlison: Added functionality to close dlopen'd
8 * files when the interpreter exits
a0d0e21e
LW
9 */
10
2e346879 11#define PERL_EUPXS_ALWAYS_EXPORT
27da23d5 12#ifndef START_MY_CXT /* Some IDEs try compiling this standalone. */
73e43954 13# define PERL_EXT
27da23d5
JH
14# include "EXTERN.h"
15# include "perl.h"
16# include "XSUB.h"
17#endif
18
89ca4ac7
JH
19#ifndef XS_VERSION
20# define XS_VERSION "0"
21#endif
39c19e8a 22#define MY_CXT_KEY "DynaLoader::_guts" XS_VERSION
a0d0e21e 23
db6e00bd
DD
24/* disable version checking since DynaLoader can't be DynaLoaded */
25#undef dXSBOOTARGSXSAPIVERCHK
9a189793 26#define dXSBOOTARGSXSAPIVERCHK dXSBOOTARGSNOVERCHK
db6e00bd 27
cdc73a10 28typedef struct {
591022fb 29 SV* x_dl_last_error; /* pointer to allocated memory for
cdc73a10 30 last error message */
11f610b5 31#if defined(PERL_IN_DL_HPUX_XS) || defined(PERL_IN_DL_DLOPEN_XS)
cdc73a10
JH
32 int x_dl_nonlazy; /* flag for immediate rather than lazy
33 linking (spots unresolved symbol) */
11f610b5 34#endif
cdc73a10
JH
35#ifdef DL_LOADONCEONLY
36 HV * x_dl_loaded_files; /* only needed on a few systems */
37#endif
38#ifdef DL_CXT_EXTRA
39 my_cxtx_t x_dl_cxtx; /* extra platform-specific data */
40#endif
41#ifdef DEBUGGING
42 int x_dl_debug; /* value copied from $DynaLoader::dl_debug */
43#endif
44} my_cxt_t;
45
89ca4ac7 46START_MY_CXT
cdc73a10 47
591022fb 48#define dl_last_error (SvPVX(MY_CXT.x_dl_last_error))
11f610b5 49#if defined(PERL_IN_DL_HPUX_XS) || defined(PERL_IN_DL_DLOPEN_XS)
89ca4ac7 50#define dl_nonlazy (MY_CXT.x_dl_nonlazy)
11f610b5 51#endif
cdc73a10 52#ifdef DL_LOADONCEONLY
89ca4ac7 53#define dl_loaded_files (MY_CXT.x_dl_loaded_files)
cdc73a10
JH
54#endif
55#ifdef DL_CXT_EXTRA
89ca4ac7 56#define dl_cxtx (MY_CXT.x_dl_cxtx)
cdc73a10
JH
57#endif
58#ifdef DEBUGGING
89ca4ac7 59#define dl_debug (MY_CXT.x_dl_debug)
cdc73a10
JH
60#endif
61
a0d0e21e 62#ifdef DEBUGGING
cdc73a10
JH
63#define DLDEBUG(level,code) \
64 STMT_START { \
65 dMY_CXT; \
66 if (dl_debug>=level) { code; } \
67 } STMT_END
a0d0e21e 68#else
cdc73a10 69#define DLDEBUG(level,code) NOOP
a0d0e21e
LW
70#endif
71
c6c619a9 72#ifdef DL_UNLOAD_ALL_AT_EXIT
abb9e9dc
GS
73/* Close all dlopen'd files */
74static void
acfe0abc 75dl_unload_all_files(pTHX_ void *unused)
abb9e9dc
GS
76{
77 CV *sub;
78 AV *dl_librefs;
79 SV *dl_libref;
80
b96d8cd9 81 if ((sub = get_cvs("DynaLoader::dl_unload_file", 0)) != NULL) {
cbfd0a87 82 dl_librefs = get_av("DynaLoader::dl_librefs", 0);
bb6a367a 83 EXTEND(SP,1);
abb9e9dc
GS
84 while ((dl_libref = av_pop(dl_librefs)) != &PL_sv_undef) {
85 dSP;
86 ENTER;
87 SAVETMPS;
88 PUSHMARK(SP);
bb6a367a 89 PUSHs(sv_2mortal(dl_libref));
abb9e9dc 90 PUTBACK;
22851543 91 call_sv((SV*)sub, G_DISCARD | G_NODEBUG);
abb9e9dc
GS
92 FREETMPS;
93 LEAVE;
94 }
95 }
96}
c6c619a9 97#endif
abb9e9dc 98
a0d0e21e 99static void
acfe0abc 100dl_generic_private_init(pTHX) /* called by dl_*.xs dl_private_init() */
a0d0e21e 101{
11f610b5 102#if defined(PERL_IN_DL_HPUX_XS) || defined(PERL_IN_DL_DLOPEN_XS)
8e07c86e 103 char *perl_dl_nonlazy;
22ff3130 104 UV uv;
11f610b5 105#endif
89ca4ac7 106 MY_CXT_INIT;
cdc73a10 107
c2b90b61 108 MY_CXT.x_dl_last_error = newSVpvs("");
cdc73a10 109#ifdef DL_LOADONCEONLY
5c284bb0 110 dl_loaded_files = NULL;
cdc73a10 111#endif
a0d0e21e 112#ifdef DEBUGGING
cdc73a10
JH
113 {
114 SV *sv = get_sv("DynaLoader::dl_debug", 0);
115 dl_debug = sv ? SvIV(sv) : 0;
116 }
8e07c86e 117#endif
11f610b5
DD
118
119#if defined(PERL_IN_DL_HPUX_XS) || defined(PERL_IN_DL_DLOPEN_XS)
22ff3130
HS
120 if ( (perl_dl_nonlazy = getenv("PERL_DL_NONLAZY")) != NULL
121 && grok_atoUV(perl_dl_nonlazy, &uv, NULL)
122 && uv <= INT_MAX
123 ) {
124 dl_nonlazy = (int)uv;
125 } else
11f610b5 126 dl_nonlazy = 0;
8e07c86e 127 if (dl_nonlazy)
bf49b057 128 DLDEBUG(1,PerlIO_printf(Perl_debug_log, "DynaLoader bind mode is 'non-lazy'\n"));
11f610b5 129#endif
8e07c86e
AD
130#ifdef DL_LOADONCEONLY
131 if (!dl_loaded_files)
132 dl_loaded_files = newHV(); /* provide cache for dl_*.xs if needed */
a0d0e21e 133#endif
23d2500b 134#ifdef DL_UNLOAD_ALL_AT_EXIT
abb9e9dc 135 call_atexit(&dl_unload_all_files, (void*)0);
23d2500b 136#endif
a0d0e21e
LW
137}
138
139
27da23d5 140#ifndef SYMBIAN
cdc73a10 141/* SaveError() takes printf style args and saves the result in dl_last_error */
a0d0e21e 142static void
dd374669 143SaveError(pTHX_ const char* pat, ...)
a0d0e21e
LW
144{
145 va_list args;
a6c40364 146 SV *msv;
dd374669 147 const char *message;
a6c40364 148 STRLEN len;
a0d0e21e 149
8e07c86e 150 /* This code is based on croak/warn, see mess() in util.c */
a0d0e21e 151
a0d0e21e 152 va_start(args, pat);
5a844595 153 msv = vmess(pat, &args);
a0d0e21e
LW
154 va_end(args);
155
a6c40364
GS
156 message = SvPV(msv,len);
157 len++; /* include terminating null char */
a0d0e21e 158
09b319af
DD
159 {
160 dMY_CXT;
cdc73a10 161 /* Copy message into dl_last_error (including terminating null char) */
09b319af
DD
162 sv_setpvn(MY_CXT.x_dl_last_error, message, len) ;
163 DLDEBUG(2,PerlIO_printf(Perl_debug_log, "DynaLoader: stored error msg '%s'\n",dl_last_error));
164 }
a0d0e21e 165}
27da23d5 166#endif
a0d0e21e 167