1/*
2 *  misc.c
3 *
4 *  $Id: misc.c,v 1.23 2006/07/10 13:49:29 source Exp $
5 *
6 *  Miscellaneous functions
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#include <iodbc.h>
79
80#include <sql.h>
81#include <sqlext.h>
82#include <odbcinst.h>
83
84#include <stdio.h>
85#include <stdlib.h>
86#include <unistd.h>
87
88#include <unicode.h>
89
90#include <fcntl.h>
91#include <sys/stat.h>
92
93#include "herr.h"
94#include "misc.h"
95#include "iodbc_misc.h"
96
97#ifdef _MAC
98#include <getfpn.h>
99#endif /* _MAC */
100
101
102/*
103 *  Parse a configuration from string (internal)
104 */
105int
106_iodbcdm_cfg_parse_str_Internal (PCONFIG pconfig, char *str)
107{
108  char *s;
109  int count;
110
111  /* init image */
112  _iodbcdm_cfg_freeimage (pconfig);
113  if (str == NULL)
114    {
115      /* NULL string is ok */
116      return 0;
117    }
118  s = pconfig->image = strdup (str);
119
120  /* Add [ODBC] section */
121  if (_iodbcdm_cfg_storeentry (pconfig, "ODBC", NULL, NULL, NULL, 0) == -1)
122    return -1;
123
124  for (count = 0; *s; count++)
125    {
126      char *keywd = NULL, *value;
127      char *cp, *n;
128
129      /*
130       *  Extract KEY=VALUE upto first ';'
131       */
132      for (cp = s; *cp && *cp != ';'; cp++)
133	{
134	  if (*cp == '{')
135	    {
136	      for (cp++; *cp && *cp != '}'; cp++)
137		;
138	    }
139	}
140
141      /*
142       *  Store start of next token if available in n and terminate string
143       */
144      if (*cp)
145	{
146	  *cp = 0;
147	  n = cp + 1;
148	}
149      else
150	n = cp;
151
152      /*
153       *  Find '=' in string
154       */
155      for (cp = s; *cp && *cp != '='; cp++)
156	;
157
158      if (*cp)
159	{
160	  *cp++ = 0;
161          keywd = s;
162          value = cp;
163	}
164      else if (count == 0)
165	{
166	  /*
167	   *  Handle missing DSN=... from the beginning of the string, e.g.:
168	   *  'dsn_ora7;UID=scott;PWD=tiger'
169	   */
170          keywd = "DSN";
171	  value = s;
172	}
173
174      if (keywd != NULL)
175        {
176          /* store entry */
177          if (_iodbcdm_cfg_storeentry (pconfig, NULL,
178		  keywd, value, NULL, 0) == -1)
179            return -1;
180	}
181
182      /*
183       *  Continue with next token
184       */
185      s = n;
186    }
187
188  /* we're done */
189  pconfig->flags |= CFG_VALID;
190  pconfig->dirty = 1;
191  return 0;
192}
193
194
195/*
196 *  Initialize a configuration from string
197 */
198int
199_iodbcdm_cfg_init_str (PCONFIG *ppconf, void *str, int size, int wide)
200{
201  PCONFIG pconfig;
202
203  *ppconf = NULL;
204
205  /* init config */
206  if ((pconfig = (PCONFIG) calloc (1, sizeof (TCONFIG))) == NULL)
207    return -1;
208
209  /* parse */
210  if (_iodbcdm_cfg_parse_str (pconfig, str, size, wide) == -1)
211    {
212      _iodbcdm_cfg_done (pconfig);
213      return -1;
214    }
215
216  /* we're done */
217  *ppconf = pconfig;
218  return 0;
219}
220
221
222/*
223 *  Parse a configuration from string
224 */
225int
226_iodbcdm_cfg_parse_str (PCONFIG pconfig, void *str, int size, int wide)
227{
228  int ret;
229  char *_str;
230
231  _str = wide ? (char *) dm_SQL_WtoU8 (str, size) : str;
232
233  ret = _iodbcdm_cfg_parse_str_Internal (pconfig, _str);
234
235  if (wide)
236    MEM_FREE (_str);
237
238  return ret;
239}
240
241
242#define CATBUF(buf, str, buf_sz)					\
243  do {									\
244    if (_iodbcdm_strlcat (buf, str, buf_sz) >= buf_sz)			\
245      return -1;							\
246  } while (0)
247
248int
249_iodbcdm_cfg_to_string (PCONFIG pconfig, char *section,
250			char *buf, size_t buf_sz)
251{
252  BOOL atsection;
253
254  if (_iodbcdm_cfg_rewind (pconfig) == -1)
255    return -1;
256
257  atsection = FALSE;
258  buf[0] = '\0';
259  while (_iodbcdm_cfg_nextentry (pconfig) == 0)
260    {
261      if (atsection)
262        {
263          if (_iodbcdm_cfg_section (pconfig))
264            break;
265          else if (_iodbcdm_cfg_define (pconfig))
266            {
267              if (buf[0] != '\0')
268                CATBUF (buf, ";", buf_sz);
269              CATBUF (buf, pconfig->id, buf_sz);
270              CATBUF (buf, "=", buf_sz);
271              CATBUF (buf, pconfig->value, buf_sz);
272            }
273        }
274      else if (_iodbcdm_cfg_section (pconfig) &&
275	       !strcasecmp (pconfig->section, section))
276        atsection = TRUE;
277    }
278  return 0;
279}
280