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 
35 static int
upper_strneq(char * s1,char * s2,int n)36 upper_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 
76 static char *			/* return new position in input str */
readtoken(char * istr,char * obuf)77 readtoken (
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 
122 char *
_iodbcdm_getinifile(char * buf,int size)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  */
194 char *
_iodbcdm_getkeyvalbydsn(char * dsn,int dsnlen,char * keywd,char * value,int size)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 
339 char *
_iodbcdm_getkeyvalinstr(char * cnstr,int cnlen,char * keywd,char * value,int size)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