[svn-inject] Installing original source of libnss-mysql-bg
[manu/libnss-mysql-bg.git] / src / nss_config.c
1 /* Copyright (C) 2002 Ben Goodwin
2    This file is part of the nss-mysql library.
3
4    The nss-mysql library is free software; you can redistribute it and/or
5    modify it under the terms of the GNU General Public License as published
6    by the Free Software Foundation; either version 2 of the License, or
7    (at your option) any later version.
8
9    The nss-mysql library is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12    GNU General Public License for more details.
13
14    You should have received a copy of the GNU General Public License
15    along with the nss-mysql library; if not, write to the Free Software
16    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17  */
18
19 static const char rcsid[] =
20     "$Id: nss_config.c,v 1.40 2004/11/13 16:25:26 cinergi Exp $";
21
22 #include "nss_mysql.h"
23 #include <stdio.h>      /* fopen() */
24 #include <string.h>     /* strlen() */
25
26 /* global var 'conf' contains data loaded from config files */
27 conf_t  conf = CONF_INITIALIZER;
28
29 /* maps config key to spot in 'conf' */
30 typedef struct {
31     char    *name;  /* key string */
32     char    *ptr;  /* where in 'conf' to load this string */
33 } config_info_t;
34
35 /*
36  * Get the next key/value pair from an open file
37  * return NTRUE if a key/val pair is found
38  * return NFALSE if EOF or error
39  * Lines can begin (column 0) with a '#' for comments
40  * key/val pairs must be in the following format
41  *      key = val
42  * Whitespace can be spaces or tabs
43  * Keys must be one word (no whitespace)
44  * Values can be anything except CR/LF
45  * Line continuation is supported if EOL is strictly a '\'
46  *      (no trailing whitespace)
47  *
48  * The in-memory copy of LINE is modified by this routine
49  *
50  * fh = open file handle
51  * key = config key loaded here
52  * key_size = storage size of key
53  * val = config value loaded here
54  * val_size = storage size of val
55  */
56 static nboolean
57 _nss_mysql_next_key (FILE *fh, char *key, int key_size, char *val,
58                      int val_size)
59 {
60   DN ("_nss_mysql_next_key")
61   char line[MAX_LINE_SIZE];
62   char *ccil;                     /* Current Character In Line */
63   char *cur;
64   size_t size;
65   nboolean fetch_key = ntrue;
66
67   DENTER
68
69   *val = *key = '\0';
70   /* Loop through file until a key/val pair is found or EOF */
71   while (fgets (line, MAX_LINE_SIZE, fh) != NULL)
72     {
73       if (*line == '#')
74         continue;
75
76       ccil = line;
77       if (fetch_key)
78         {
79           cur = ccil;
80           /* Get key - anything but CR/LF or whitespace */
81           ccil += strcspn (ccil, "\n\r \t");
82           if (ccil == cur)
83             continue;             /* No key */
84           *ccil = '\0';           /* Null-terminate the key */
85           /* Key found, move on */
86           ++ccil;
87           /* Save the key */
88           strncpy (key, cur, key_size);
89           key[key_size - 1] = '\0'; /* strncpy doesn't guarantee null-term */
90         }
91
92       /* Skip leading whitespace */
93       ccil += strspn (ccil, " \t");
94       cur = ccil;
95       /* Get value - anything but CR/LF */
96       size = strcspn (ccil, "\n\r");
97       if (!size && fetch_key)
98         continue;                 /* No value */
99       ccil += size;
100       if (*(ccil - 1) == '\\')
101         {
102           fetch_key = nfalse;     /* Next line continues a value */
103           *(ccil - 1) = '\0';     /* Remove the '\' */
104           size--;
105         }
106       else
107         {
108           fetch_key = ntrue;      /* Next line starts with a key */
109           *ccil = '\0';           /* Null-terminate the value */
110         }
111       /* Append what we just snarfed to VAL */
112       strncat (val, cur, val_size - 1);
113       val_size -= size;
114       if (val_size <= 0)
115         {
116           _nss_mysql_log (LOG_ERR, "%s: Config value too long", FUNCNAME);
117           DBRETURN (nfalse)
118         }
119
120       if (!fetch_key)             /* Next line continues a value */
121         continue;
122
123       D ("%s: Found: %s -> %s", FUNCNAME, key, val);
124       DBRETURN (ntrue)
125     }
126   DBRETURN (nfalse)
127 }
128
129 /*
130  * Load configuration data from file
131  *
132  * file = full path of file to load
133  */
134 static void
135 _nss_mysql_load_config_file (char *file)
136 {
137   DN ("_nss_mysql_load_config_file")
138   FILE *fh;
139   char key[MAX_KEY_SIZE];
140   char val[MAX_VAL_SIZE];
141   size_t size;
142   config_info_t *c;
143
144   /* map config key to 'conf' location; must be NULL-terminated */
145   config_info_t config_fields[] =
146   {
147       {"getpwnam",  conf.sql.query.getpwnam},
148       {"getpwuid",  conf.sql.query.getpwuid},
149       {"getspnam",  conf.sql.query.getspnam},
150       {"getpwent",  conf.sql.query.getpwent},
151       {"getspent",  conf.sql.query.getspent},
152       {"getgrnam",  conf.sql.query.getgrnam},
153       {"getgrgid",  conf.sql.query.getgrgid},
154       {"getgrent",  conf.sql.query.getgrent},
155       {"memsbygid", conf.sql.query.memsbygid},
156       {"gidsbymem", conf.sql.query.gidsbymem},
157       {"host",      conf.sql.server.host},
158       {"port",      conf.sql.server.port},
159       {"socket",    conf.sql.server.socket},
160       {"username",  conf.sql.server.username},
161       {"password",  conf.sql.server.password},
162       {"database",  conf.sql.server.database},
163       {"timeout",   conf.sql.server.options.timeout},
164       {"compress",  conf.sql.server.options.compress},
165       {"initcmd",   conf.sql.server.options.initcmd},
166
167       {NULL}
168   };
169
170   DENTER
171   D ("%s: Attempting to load: %s", FUNCNAME, file);
172   /* No error-handling here; validate_config will catch missing data */
173   if ((fh = fopen (file, "r")) == NULL)
174     DRETURN;
175
176   D ("%s: fopen() successful", FUNCNAME);
177
178   /* Step through all key/val pairs available */
179   while (_nss_mysql_next_key (fh, key, MAX_KEY_SIZE, val, MAX_VAL_SIZE))
180     for (c = config_fields; c->name; c++)
181       if (!strcmp (key, c->name))
182         strncpy (c->ptr, val, MAX_VAL_SIZE);
183
184   fclose (fh);
185   DRETURN
186 }
187
188 /*
189  * Sanity-check the loaded configuration data
190  * Make sure we have at least a host and database defined
191  */
192 static nboolean
193 _nss_mysql_validate_config (void)
194 {
195   DN ("_nss_mysql_validate_config")
196
197   DENTER
198   if (!conf.sql.server.host[0] || !conf.sql.server.database[0])
199     DBRETURN (nfalse);
200
201   DBRETURN (ntrue)
202 }
203
204 /*
205  * Load our config files
206  * Upon success, set conf.valid = ntrue
207  */
208 NSS_STATUS
209 _nss_mysql_load_config (void)
210 {
211   DN ("_nss_mysql_load_config")
212
213   DENTER
214   /* Config is already loaded, don't do it again */
215   if (conf.valid == ntrue)
216     DSRETURN (NSS_SUCCESS)
217
218   memset (&conf, 0, sizeof (conf));
219
220   /* Load main (world-readable) config */
221   _nss_mysql_load_config_file (MAINCFG);
222
223   /* Load root (root-readable) config */
224   _nss_mysql_load_config_file (ROOTCFG);
225
226   /* double-check our config */
227   if (_nss_mysql_validate_config () == nfalse)
228     DSRETURN (NSS_UNAVAIL)
229
230   /* Let the rest of the module know we've got a good config */
231   conf.valid = ntrue;
232
233   DSRETURN (NSS_SUCCESS)
234 }
235