1/*
2 *  dlproc.c
3 *
4 *  $Id: dlproc.c,v 1.14 2006/01/20 15:58:34 source Exp $
5 *
6 *  Load driver and resolve driver's function entry point
7 *
8 *  The iODBC driver manager.
9 *
10 *  Copyright (C) 1995 by Ke Jin <kejin@empress.com>
11 *  Copyright (C) 1996-2006 by OpenLink Software <iodbc@openlinksw.com>
12 *  All Rights Reserved.
13 *
14 *  This software is released under the terms of either of the following
15 *  licenses:
16 *
17 *      - GNU Library General Public License (see LICENSE.LGPL)
18 *      - The BSD License (see LICENSE.BSD).
19 *
20 *  Note that the only valid version of the LGPL license as far as this
21 *  project is concerned is the original GNU Library General Public License
22 *  Version 2, dated June 1991.
23 *
24 *  While not mandated by the BSD license, any patches you make to the
25 *  iODBC source code may be contributed back into the iODBC project
26 *  at your discretion. Contributions will benefit the Open Source and
27 *  Data Access community as a whole. Submissions may be made at:
28 *
29 *      http://www.iodbc.org
30 *
31 *
32 *  GNU Library Generic Public License Version 2
33 *  ============================================
34 *  This library is free software; you can redistribute it and/or
35 *  modify it under the terms of the GNU Library General Public
36 *  License as published by the Free Software Foundation; only
37 *  Version 2 of the License dated June 1991.
38 *
39 *  This library is distributed in the hope that it will be useful,
40 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
41 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
42 *  Library General Public License for more details.
43 *
44 *  You should have received a copy of the GNU Library General Public
45 *  License along with this library; if not, write to the Free
46 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
47 *
48 *
49 *  The BSD License
50 *  ===============
51 *  Redistribution and use in source and binary forms, with or without
52 *  modification, are permitted provided that the following conditions
53 *  are met:
54 *
55 *  1. Redistributions of source code must retain the above copyright
56 *     notice, this list of conditions and the following disclaimer.
57 *  2. Redistributions in binary form must reproduce the above copyright
58 *     notice, this list of conditions and the following disclaimer in
59 *     the documentation and/or other materials provided with the
60 *     distribution.
61 *  3. Neither the name of OpenLink Software Inc. nor the names of its
62 *     contributors may be used to endorse or promote products derived
63 *     from this software without specific prior written permission.
64 *
65 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
66 *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
67 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
68 *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL OPENLINK OR
69 *  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
70 *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
71 *  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
72 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
73 *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
74 *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
75 *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
76 */
77
78
79#include <iodbc.h>
80
81#include <sql.h>
82#include <sqlext.h>
83
84#include <dlproc.h>
85
86#include <herr.h>
87#include <henv.h>
88#include <hdbc.h>
89
90#include <itrace.h>
91
92char *odbcapi_symtab[] =
93{
94    "UNKNOWN FUNCTION"
95#define FUNCDEF(A, B, C)	,C
96#include "henv.ci"
97#undef FUNCDEF
98};
99
100
101HPROC
102_iodbcdm_getproc (HDBC hdbc, int idx)
103{
104  CONN (pdbc, hdbc);
105  ENV_t *penv;
106  HPROC *phproc;
107
108  if (idx <= 0 || idx >= __LAST_API_FUNCTION__)
109    return SQL_NULL_HPROC;
110
111  penv = (ENV_t *) (pdbc->henv);
112
113  if (penv == NULL)
114    return SQL_NULL_HPROC;
115
116  phproc = penv->dllproc_tab + idx;
117
118  if (*phproc == SQL_NULL_HPROC)
119    *phproc = _iodbcdm_dllproc (penv->hdll, odbcapi_symtab[idx]);
120
121  return *phproc;
122}
123
124
125static dlproc_t *pRoot = NULL;
126
127
128HDLL
129_iodbcdm_dllopen (char *path)
130{
131  dlproc_t *pDrv = NULL, *p;
132
133  /*
134   *  Check if we have already loaded the driver
135   */
136  for (p = pRoot; p; p = p->next)
137    {
138      if (STREQ (p->path, path))
139	{
140	  pDrv = p;
141	  break;
142	}
143    }
144
145  /*
146   *  If already loaded, increase ref counter
147   */
148  if (pDrv)
149    {
150      pDrv->refcount++;
151
152      /*
153       *  If the driver was unloaded, load it again
154       */
155      if (pDrv->dll == NULL)
156	pDrv->dll = (HDLL) DLL_OPEN (path);
157
158      return pDrv->dll;
159    }
160
161  /*
162   *  Initialize new structure
163   */
164  if ((pDrv = calloc (1, sizeof (dlproc_t))) == NULL)
165    return NULL;
166
167  pDrv->refcount = 1;
168  pDrv->path = STRDUP (path);
169  pDrv->dll = (HDLL) DLL_OPEN (path);
170
171  /*
172   *  Add to linked list
173   */
174  pDrv->next = pRoot;
175  pRoot = pDrv;
176
177  return pDrv->dll;
178}
179
180
181HPROC
182_iodbcdm_dllproc (HDLL hdll, char *sym)
183{
184  return (HPROC) DLL_PROC (hdll, sym);
185}
186
187
188int
189_iodbcdm_dllclose (HDLL hdll)
190{
191  dlproc_t *pDrv = NULL, *p;
192
193  /*
194   *  Find loaded driver
195   */
196  for (p = pRoot; p; p = p->next)
197    {
198      if (p->dll == hdll)
199	{
200	  pDrv = p;
201	  break;
202	}
203    }
204
205  /*
206   *  Not found
207   */
208  if (!pDrv)
209    return -1;
210
211  /*
212   *  Decrease reference counter
213   */
214  pDrv->refcount--;
215
216  /*
217   *  Check if it is possible to unload the driver safely
218   *
219   *  NOTE: Some drivers set explicit on_exit hooks, which makes it
220   *        impossible for the driver manager to unload the driver
221   *        as this would crash the executable at exit.
222   */
223  if (pDrv->refcount == 0 && pDrv->safe_unload)
224    {
225      DLL_CLOSE (pDrv->dll);
226      pDrv->dll = NULL;
227    }
228
229  return 0;
230}
231
232
233char *
234_iodbcdm_dllerror ()
235{
236  return DLL_ERROR ();
237}
238
239
240/*
241 *  If driver manager determines this driver is safe, flag the driver can
242 *  be unloaded if not used.
243 */
244void
245_iodbcdm_safe_unload (HDLL hdll)
246{
247  dlproc_t *pDrv = NULL, *p;
248
249  /*
250   *  Find loaded driver
251   */
252  for (p = pRoot; p; p = p->next)
253    {
254      if (p->dll == hdll)
255	{
256	  pDrv = p;
257	  break;
258	}
259    }
260
261  /*
262   *  Driver not found
263   */
264  if (!pDrv)
265    return;
266
267  pDrv->safe_unload = 1;
268}
269