1/*
2 *  misc.c
3 *
4 *  $Id: misc.c 2613 1999-06-01 15:32:12Z VZ $
5 *
6 *  Miscellaneous functions
7 *
8 *  The iODBC driver manager.
9 *
10 *  Copyright (C) 1995 by Ke Jin <kejin@empress.com>
11 *
12 *  This library is free software; you can redistribute it and/or
13 *  modify it under the terms of the GNU Library General Public
14 *  License as published by the Free Software Foundation; either
15 *  version 2 of the License, or (at your option) any later version.
16 *
17 *  This library is distributed in the hope that it will be useful,
18 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
19 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
20 *  Library General Public License for more details.
21 *
22 *  You should have received a copy of the GNU Library General Public
23 *  License along with this library; if not, write to the Free
24 *  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 */
26
27#include	"config.h"
28
29#include	"isql.h"
30#include	"isqlext.h"
31
32#include	<stdio.h>
33#include        <unistd.h>
34
35static int
36upper_strneq (
37    char *s1,
38    char *s2,
39    int n)
40{
41  int i;
42  char c1, c2;
43
44  for (i = 1; i < n; i++)
45    {
46      c1 = s1[i];
47      c2 = s2[i];
48
49      if (c1 >= 'a' && c1 <= 'z')
50	{
51	  c1 += ('A' - 'a');
52	}
53      else if (c1 == '\n')
54	{
55	  c1 = '\0';
56	}
57
58      if (c2 >= 'a' && c2 <= 'z')
59	{
60	  c2 += ('A' - 'a');
61	}
62      else if (c2 == '\n')
63	{
64	  c2 = '\0';
65	}
66
67      if ((c1 - c2) || !c1 || !c2)
68	{
69	  break;
70	}
71    }
72
73  return (int) !(c1 - c2);
74}
75
76static char *			/* return new position in input str */
77readtoken (
78    char *istr,			/* old position in input buf */
79    char *obuf)			/* token string ( if "\0", then finished ) */
80{
81  char *start = obuf;
82
83  /* Skip leading white space */
84  while (*istr == ' ' || *istr == '\t')
85    istr++;
86
87  for (; *istr && *istr != '\n'; istr++)
88    {
89      char c, nx;
90
91      c = *(istr);
92      nx = *(istr + 1);
93
94      if (c == ';')
95	{
96	  for (; *istr && *istr != '\n'; istr++);
97	  break;
98	}
99      *obuf = c;
100      obuf++;
101
102      if (nx == ';' || nx == '=' || c == '=')
103	{
104	  istr++;
105	  break;
106	}
107    }
108  *obuf = '\0';
109
110  /* Trim end of token */
111  for (; obuf > start && (*(obuf - 1) == ' ' || *(obuf - 1) == '\t');)
112    *--obuf = '\0';
113
114  return istr;
115}
116
117#if	!defined(WINDOWS) && !defined(WIN32) && !defined(OS2)
118# include	<pwd.h>
119# define	UNIX_PWD
120#endif
121
122char *
123_iodbcdm_getinifile (char *buf, int size)
124{
125  int i, j;
126  char *ptr;
127
128  j = STRLEN ("/odbc.ini") + 1;
129
130  if (size < j)
131    {
132      return NULL;
133    }
134
135#if	!defined(UNIX_PWD)
136
137  i = GetWindowsDirectory ((LPSTR) buf, size);
138
139  if (i == 0 || i > size - j)
140    {
141      return NULL;
142    }
143
144  sprintf (buf + i, "/odbc.ini");
145
146  return buf;
147#else
148  if ((ptr = getenv ("ODBCINI")) != NULL)
149    {
150      strcpy (buf, ptr);
151      return buf;
152    }
153
154  if ((ptr = getenv ("IODBCINI")) != NULL)
155    {
156      strcpy (buf, ptr);
157      return buf;
158    }
159
160  if ((ptr = getenv ("HOME")) == NULL)
161    {
162      ptr = (char *) getpwuid (getuid ());
163
164      if (ptr == NULL)
165	{
166	  return NULL;
167	}
168
169      ptr = ((struct passwd *) ptr)->pw_dir;
170    }
171
172  if (ptr == NULL || *ptr == '\0')
173    {
174      ptr = "/home";
175    }
176
177  if (size < STRLEN (ptr) + j)
178    {
179      return NULL;
180    }
181
182  sprintf (buf, "%s%s", ptr, "/.odbc.ini");
183  /* i.e. searching ~/.odbc.ini */
184#endif
185
186  return buf;
187}
188
189
190/*
191 *  read odbc init file to resolve the value of specified
192 *  key from named or defaulted dsn section
193 */
194char *
195_iodbcdm_getkeyvalbydsn (
196    char *dsn,
197    int dsnlen,
198    char *keywd,
199    char *value,
200    int size)
201{
202  char buf[1024];
203  char dsntk[SQL_MAX_DSN_LENGTH + 3] = {'[', '\0'};
204  char token[1024];		/* large enough */
205  FILE *file;
206  char pathbuf[1024];
207  char *path;
208
209#define DSN_NOMATCH	0
210#define DSN_NAMED	1
211#define DSN_DEFAULT	2
212
213  int dsnid = DSN_NOMATCH;
214  int defaultdsn = DSN_NOMATCH;
215
216  if (dsn == NULL || *dsn == 0)
217    {
218      dsn = "default";
219      dsnlen = STRLEN (dsn);
220    }
221
222  if (dsnlen == SQL_NTS)
223    {
224      dsnlen = STRLEN (dsn);
225    }
226
227  if (dsnlen <= 0 || keywd == NULL || buf == 0 || size <= 0)
228    {
229      return NULL;
230    }
231
232  if (dsnlen > sizeof (dsntk) - 2)
233    {
234      return NULL;
235    }
236
237  value[0] = '\0';
238
239  STRNCAT (dsntk, dsn, dsnlen);
240  STRCAT (dsntk, "]");
241
242  dsnlen = dsnlen + 2;
243
244  path = _iodbcdm_getinifile (pathbuf, sizeof (pathbuf));
245
246  if (path == NULL)
247    {
248      return NULL;
249    }
250
251  file = (FILE *) fopen (path, "r");
252
253  if (file == NULL)
254    {
255      return NULL;
256    }
257
258  for (;;)
259    {
260      char *str;
261
262      str = fgets (buf, sizeof (buf), file);
263
264      if (str == NULL)
265	{
266	  break;
267	}
268
269      if (*str == '[')
270	{
271	  if (upper_strneq (str, "[default]", STRLEN ("[default]")))
272	    {
273	      /* we only read first dsn default dsn
274	       * section (as well as named dsn).
275	       */
276	      if (defaultdsn == DSN_NOMATCH)
277		{
278		  dsnid = DSN_DEFAULT;
279		  defaultdsn = DSN_DEFAULT;
280		}
281	      else
282		{
283		  dsnid = DSN_NOMATCH;
284		}
285
286	      continue;
287	    }
288	  else if (upper_strneq (str, dsntk, dsnlen))
289	    {
290	      dsnid = DSN_NAMED;
291	    }
292	  else
293	    {
294	      dsnid = DSN_NOMATCH;
295	    }
296
297	  continue;
298	}
299      else if (dsnid == DSN_NOMATCH)
300	{
301	  continue;
302	}
303
304      str = readtoken (str, token);
305
306      if (upper_strneq (keywd, token, STRLEN (keywd)))
307	{
308	  str = readtoken (str, token);
309
310	  if (!STREQ (token, "="))
311	    /* something other than = */
312	    {
313	      continue;
314	    }
315
316	  str = readtoken (str, token);
317
318	  if (STRLEN (token) > size - 1)
319	    {
320	      break;
321	    }
322
323	  STRNCPY (value, token, size);
324	  /* copy the value(i.e. next token) to buf */
325
326	  if (dsnid != DSN_DEFAULT)
327	    {
328	      break;
329	    }
330	}
331    }
332
333  fclose (file);
334
335  return (*value) ? value : NULL;
336}
337
338
339char *
340_iodbcdm_getkeyvalinstr (
341    char *cnstr,
342    int cnlen,
343    char *keywd,
344    char *value,
345    int size)
346{
347  char token[1024] = {'\0'};
348  int flag = 0;
349
350  if (cnstr == NULL || value == NULL
351      || keywd == NULL || size < 1)
352    {
353      return NULL;
354    }
355
356  if (cnlen == SQL_NTS)
357    {
358      cnlen = STRLEN (cnstr);
359    }
360
361  if (cnlen <= 0)
362    {
363      return NULL;
364    }
365
366  for (;;)
367    {
368      cnstr = readtoken (cnstr, token);
369
370      if (*token == '\0')
371	{
372	  break;
373	}
374
375      if (STREQ (token, ";"))
376	{
377	  flag = 0;
378	  continue;
379	}
380
381      switch (flag)
382	{
383	case 0:
384	  if (upper_strneq (token, keywd, strlen (keywd)))
385	    {
386	      flag = 1;
387	    }
388	  break;
389
390	case 1:
391	  if (STREQ (token, "="))
392	    {
393	      flag = 2;
394	    }
395	  break;
396
397	case 2:
398	  if (size < strlen (token) + 1)
399	    {
400	      return NULL;
401	    }
402
403	  STRNCPY (value, token, size);
404
405	  return value;
406
407	default:
408	  break;
409	}
410    }
411
412  return NULL;
413}
414