summaryrefslogtreecommitdiffstats
path: root/source/param/params.c
blob: 8030e4ab58345abf5d040f501de73901c4e4a23b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
/* 
   Unix SMB/Netbios implementation.
   Version 1.9.
   Parameter loading utlities
   Copyright (C) Karl Auer 1993,1994
   
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 of the License, or
   (at your option) any later version.
   
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.
   
   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

/**************************************************************************
PARAMS.C

Copyright (C) 1990, 1991, 1992, 1993, 1994 Karl Auer

This module provides for streamlines retrieval of information from a
Windows-like parameter files. There is a function which will search for
all sections in the file and call a specified function with each. There is
a similar function which will call a specified function for all parameters 
in a section. The idea is that you pass the addresses of suitable functions
to a single function in this module which will then enumerate all sections, 
and within each section all parameters, to your program. 

Parameter files contain text lines (newline delimited) which consist of
either a section name in square brackets or a parameter name, delimited
from the parameter value by an equals sign. Blank lines or lines where the
first non-whitespace character is a colon are ignored. All whitespace in
section names and parameter names is compressed to single spaces. Leading 
and trailing whitespace on parameter names and parameter values is stripped.

Only the first equals sign in a parameter line is significant - parameter
values may contain equals signs, square brackets and semicolons. Internal
whitespace is retained in parameter values. Parameter names may not start 
with a square bracket, an equals sign or a semicolon, for obvious reasons. 

A sample parameter file might look like this:

[things]
this=1
that=2
[other things]
the other = 3

**************************************************************************/

#include "includes.h"

#include "smb.h"

/* local variable pointing to passed filename */
static char *pszParmFile = NULL;
extern int DEBUGLEVEL;


/**************************************************************************
Strip all leading whitespace from a string.
**************************************************************************/
static void trimleft(char *psz)
{
   char *pszDest;

   pszDest = psz;
   if (psz != NULL)
   {
      while (*psz != '\0' && isspace(*psz))
	 psz++;
      while (*psz != '\0')
	 *pszDest++ = *psz++;
      *pszDest = '\0';
   }
}

/**************************************************************************
Strip all trailing whitespace from a string.
**************************************************************************/
static void trimright(char *psz)
{
   char *pszTemp;

   if (psz != NULL && psz[0] != '\0')
   {
      pszTemp = psz + strlen(psz) - 1;
      while (isspace(*pszTemp))
	 *pszTemp-- = '\0';
   }
}

/***********************************************************************
Collapse each whitespace area in a string to a single space.
***********************************************************************/
static void collapse_spaces(char *psz)
{
   while (*psz)
      if (isspace(*psz))
      {
	 *psz++ = ' ';
	 trimleft(psz);
      }
      else
	 psz++;
}

/**************************************************************************
Return the value of the first non-white character in the specified string.
The terminating NUL counts as non-white for the purposes of this function.
Note - no check for a NULL string! What would we return?
**************************************************************************/
static int firstnonwhite(char *psz)
{
   while (isspace(*psz) && (*psz != '\0'))
      psz++;
   return (*psz);
}


/**************************************************************************
Identifies all parameters in the current section, calls the parameter
function for each. Ignores comment lines, stops and backs up in file when
a section is encountered. Returns True on success, False on error.
**************************************************************************/
static BOOL enumerate_parameters(FILE *fileIn, BOOL (*pfunc)(char *,char *))
{
   pstring szBuf;
   char *pszTemp;
   BOOL bRetval;
   long lFileOffset;
   int  cTemp;
   BOOL bParmFound;

   bRetval = False;
   bParmFound = False;
   while (True)
   {
      /* first remember where we are */
      if ((lFileOffset = ftell(fileIn)) >= 0L)
      {
	 /* then get and check a line */
	 if (fgets_slash(szBuf, sizeof(szBuf)-1, fileIn) == NULL)
	 {
	    /* stop - return OK unless file error */
	    bRetval = !ferror(fileIn);
            if (!bRetval)
	      DEBUG(0,( "Read error on configuration file (enumerating parameters)!\n"));
	    break;   
	 }
	 else
	    /* if first non-white is a '[', stop (new section) */
	    if ((cTemp = firstnonwhite(szBuf)) == '[')
	    {
	       /* restore position to start of new section */
	       if (fseek(fileIn, lFileOffset, SEEK_SET) < 0L)
	       {
                  DEBUG(0,( "Seek error on configuration file!\n"));
                  break;
	       }

	       /* return success */
	       bRetval = True;
	       break;
	    }
	    else
	       /* if it's a semicolon or line is blank, ignore the line */
	       if (!cTemp || strchr(";#",cTemp))
	       {
		  continue;
	       }
	       else
		  /* if no equals sign and line contains non-whitespace */
		  /* then line is badly formed */
		  if ((pszTemp = strchr(szBuf, '=')) == NULL)
		  {
		     DEBUG(0,( "Ignoring badly formed line: %s", szBuf));
		  }
		  else
		  {
                     /* Note that we have found a parameter */
                     bParmFound = True;
		     /* cut line at the equals sign */
		     *pszTemp++ = '\0';
		     /* trim leading and trailing space from both halves */
		     trimright(szBuf);
		     trimleft(szBuf);
		     trimright(pszTemp);
		     trimleft(pszTemp);
		     /* process the parameter iff passed pointer not NULL */
		     if (pfunc != NULL)
                        if (!pfunc(szBuf, pszTemp))
			   break;
		  }
      }
   }
   return (bRetval);
}


/***********************************************************************
Close up s by n chars, at offset start.
***********************************************************************/
static void closestr(char *s, int start, int n)
{
   char *src;
   char *dest;
   int  len;

   if (n > 0)
      if ((src = dest = s) != NULL)
      {
         len = strlen(s);
         if (start >= 0 && start < len - n)
         {
            src += start + n;
            dest += start;
  
            while (*src)
               *dest++ = *src++;
            *dest = '\0';
         }
      }
}

/**************************************************************************
Identifies all sections in the parameter file, calls passed section_func()
for each, passing the section name, then calls enumerate_parameters(). 
Returns True on success, False on failure. Note that the section and 
parameter names will have all internal whitespace areas collapsed to a 
single space for processing.
**************************************************************************/
static BOOL enumerate_sections(FILE *fileIn,
			       BOOL (*sfunc)(char *),BOOL (*pfunc)(char *,char *))
{
   pstring szBuf;
   BOOL bRetval;
   BOOL bSectionFound;

   /* this makes sure we get include lines right */
   enumerate_parameters(fileIn, pfunc);

   bRetval = False;
   bSectionFound = False;
   while (True)
   {
      if (fgets_slash(szBuf, sizeof(szBuf)-1, fileIn) == NULL)
      {
	 /* stop - return OK unless file error */
	 bRetval = !ferror(fileIn);
         if (!bRetval)
	   DEBUG(0,( "Read error on configuration file (enumerating sections)!\n"));
	 break;   
      }
      else
      {
	 trimleft(szBuf);
	 trimright(szBuf);
	 if (szBuf[0] == '[')
	 {
	    closestr(szBuf, 0, 1);
	    if (strlen(szBuf) > 1)
	       if (szBuf[strlen(szBuf) - 1] == ']')
	       {  
		  /* found a section - note the fact */
                  bSectionFound = True;
		  /* remove trailing metabracket */
		  szBuf[strlen(szBuf) - 1] = '\0';
		  /* remove leading and trailing whitespace from name */
		  trimleft(szBuf);
		  trimright(szBuf);
		  /* reduce all internal whitespace to one space */
		  collapse_spaces(szBuf);
		  /* process it - stop if the processing fails */
		  if (sfunc != NULL)
                     if (!sfunc(szBuf))
		        break;
		  if (!enumerate_parameters(fileIn, pfunc))
                     break;
	       }
	 }
      }
   }

   return (bRetval);
}

/**************************************************************************
Process the passed parameter file.

Returns True if successful, else False.
**************************************************************************/
BOOL pm_process(char *pszFileName,BOOL (*sfunc)(char *),BOOL (*pfunc)(char *,char *))
{
   FILE *fileIn;
   BOOL bRetval;

   bRetval = False;

   /* record the filename for use in error messages one day... */
   pszParmFile = pszFileName;

   if (pszParmFile == NULL || strlen(pszParmFile) < 1)
      DEBUG(0,( "No configuration filename specified!\n"));
   else
      if ((fileIn = fopen(pszParmFile, "r")) == NULL)
         DEBUG(0,( "Unable to open configuration file \"%s\"!\n", pszParmFile));
      else
      {
         DEBUG(3,("Processing configuration file \"%s\"\n", pszParmFile));
	 bRetval = enumerate_sections(fileIn, sfunc, pfunc);
	 fclose(fileIn);
      }

   if (!bRetval)
     DEBUG(0,("pm_process retuned false\n"));
   return (bRetval);
}