conf-file.c 7.4 KB
Newer Older
Per Cederqvist's avatar
Per Cederqvist committed
1
/*
2
3
 * $Id: conf-file.c,v 1.16 1999/05/24 09:34:20 ceder Exp $
 * Copyright (C) 1994-1995, 1998-1999  Lysator Academic Computer Association.
Per Cederqvist's avatar
Per Cederqvist committed
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
 *
 * This file is part of the LysKOM server.
 * 
 * LysKOM 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 1, or (at your option) 
 * any later version.
 * 
 * LysKOM 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 LysKOM; see the file COPYING.  If not, write to
 * Lysator, c/o ISY, Linkoping University, S-581 83 Linkoping, SWEDEN,
 * or the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, 
 * MA 02139, USA.
 *
 * Please mail bug reports to bug-lyskom@lysator.liu.se. 
 */
/* 
 * Read configuration files.
 */

David Byers's avatar
David Byers committed
29
30
31
32
33
34

#ifdef HAVE_CONFIG_H
#  include <config.h>
#endif


35
static const char *
36
rcsid = "$Id: conf-file.c,v 1.16 1999/05/24 09:34:20 ceder Exp $";
Per Cederqvist's avatar
Per Cederqvist committed
37
38
39
40
41
42
43
#include "rcs.h"
USE(rcsid);

#include <stdio.h>
#include <sys/types.h>
#include <time.h>
#include <assert.h>
44
#include <ctype.h>
45
46
47
48
49
50
51
52
53
54
55
56
57
#ifdef HAVE_STRING_H
#  include <string.h>
#else
#  ifdef HAVE_STRINGS_H
#    include <strings.h>
#  endif
#endif
#ifndef HAVE_STRCHR
#  define strchr index
#endif
#ifdef HAVE_STDLIB_H
#  include <stdlib.h>
#endif
Per Cederqvist's avatar
Per Cederqvist committed
58
59
60
#include <stdarg.h>

#include "s-string.h"
61
#include "server/smalloc.h"
Per Cederqvist's avatar
Per Cederqvist committed
62
63
64
65
66
67
#include "log.h"
#include "misc-types.h"
#include "kom-types.h"
#include "conf-file.h"
#include "lyskomd.h"

David Byers's avatar
David Byers committed
68
#define MAXLINE 1001
Per Cederqvist's avatar
Per Cederqvist committed
69
70
71
72
73
74
75
76
77

static int *assignment_count = NULL;
static int  npar = 0;

static void
init_init(const struct parameter *par)
{
    int ix;

Per Cederqvist's avatar
Per Cederqvist committed
78
79
80
    for (npar = 0; par[npar].name != NULL; npar++)
      ;

Per Cederqvist's avatar
Per Cederqvist committed
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
    assert (assignment_count == NULL);
    assignment_count = smalloc(npar * sizeof (*assignment_count));
    
    for (ix = 0; ix < npar; ix++)
	assignment_count[ix] = 0;
}

/* Check that each parameter is assigned at least as many times
   as the struct parameter says.  Assign the default value if it
   is not assigned at all. */
static void
assign_defaults(const struct parameter *par,
		int *err)
{
    int ix;

    for (ix = 0; ix < npar; ix++)
    {
	if (assignment_count[ix] < par[ix].min_assignments)
	{
David Byers's avatar
David Byers committed
101
102
	    kom_log ("Parameter %s only assigned %d times (%d times needed)\n",
                     par[ix].name, assignment_count[ix], par[ix].min_assignments);
Per Cederqvist's avatar
Per Cederqvist committed
103
104
105
106
107
	    (*err)++;
	}
	else if (assignment_count[ix] == 0)
	{
	    if ((*par[ix].assigner)(par[ix].default_val, &par[ix]) != OK)
Per Cederqvist's avatar
Per Cederqvist committed
108
	    {
David Byers's avatar
David Byers committed
109
		kom_log ("default assigner failed for %s\n", par[ix].name);
Per Cederqvist's avatar
Per Cederqvist committed
110
		(*err)++;
Per Cederqvist's avatar
Per Cederqvist committed
111
	    }
Per Cederqvist's avatar
Per Cederqvist committed
112
113
114
115
	}
    }
}

Per Cederqvist's avatar
Per Cederqvist committed
116
117
118
119
/* Perform the assignments on one line. 
   Returns EOF on end-of-file, 0 otherwise. 
   A log message is printed, and (*err) is incremented,
   if errors are detected. */
Per Cederqvist's avatar
Per Cederqvist committed
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
static int
configure_line(FILE *fp,
	       const struct parameter *par,
	       int *err)
{
    char line[MAXLINE];
    char *start;
    char *val;
    char *end;
    int   found;
    int   ix;

    if (fgets(line, MAXLINE, fp) == NULL)
	return EOF;

135
136
137
138
    /* Separate the line into its two parts.  Set up ``start'' to point 
       to the beginning of the variable name, ``val'' to point to the
       beginning of the value, and remove the trailing newline (using
       ``end''). */
Per Cederqvist's avatar
Per Cederqvist committed
139
140
141
142
143
144
145
    for (start = line; *start == ' ' || *start == '\t'; start++)
	;
    switch (*start)
    {
    case '#':			/* Comment line */
	return 0;
    case '\0':			/* Too long */
David Byers's avatar
David Byers committed
146
	kom_log ("line too long (max %d chars allowed): %s\n", MAXLINE-1, line);
Per Cederqvist's avatar
Per Cederqvist committed
147
148
149
150
151
152
153
154
155
	(*err)++;
	return 0;
    case '\n':			/* Empty line */
	return 0;
    }
    
    val = strchr(line, ':');
    if (val == NULL)
    {
David Byers's avatar
David Byers committed
156
	kom_log("missing colon: %s\n", line);
Per Cederqvist's avatar
Per Cederqvist committed
157
158
159
160
161
162
163
164
165
	(*err)++;
	return 0;
    }
    *val = '\0';		/* NUL-terminate key */
    for (val++; *val == ' ' || *val == '\t'; val++)
	;
    switch (*val)
    {
    case '\0':
David Byers's avatar
David Byers committed
166
	kom_log ("line too long (max %d chars allowed): %s\n", MAXLINE-1, line);
Per Cederqvist's avatar
Per Cederqvist committed
167
168
169
170
171
172
173
	(*err)++;
	return 0;
    }

    end = strchr(val, '\n');
    if (end == NULL)
    {
David Byers's avatar
David Byers committed
174
	kom_log ("line too long (max %d chars allowed): %s\n", MAXLINE-1, line);
Per Cederqvist's avatar
Per Cederqvist committed
175
176
177
178
179
180
181
182
183
	(*err)++;
	return 0;
    }	
    *end = '\0';

    /* Set the variable which match this line. */
    found = 0;
    for (ix = 0; ix < npar; ix++)
    {
184
	if (!strcmp(start, par[ix].name))
Per Cederqvist's avatar
Per Cederqvist committed
185
186
	{
	    found++;
David Byers's avatar
David Byers committed
187
	    if (assignment_count[ix] >= par[ix].max_assignments
Per Cederqvist's avatar
Per Cederqvist committed
188
		&& par[ix].max_assignments != -1)
Per Cederqvist's avatar
Per Cederqvist committed
189
190
	    {
		(*err)++;
David Byers's avatar
David Byers committed
191
		kom_log ("variable already assigned %d times: %s\n", 
Per Cederqvist's avatar
Per Cederqvist committed
192
193
194
195
196
197
		     assignment_count[ix], line);
	    }
	    else
	    {
		assignment_count[ix]++;
		if ((*par[ix].assigner)(val, &par[ix]) != OK)
Per Cederqvist's avatar
Per Cederqvist committed
198
		{
David Byers's avatar
David Byers committed
199
		    kom_log ("assigner for %s failed\n", par[ix].name);
Per Cederqvist's avatar
Per Cederqvist committed
200
		    (*err)++;
Per Cederqvist's avatar
Per Cederqvist committed
201
		}
Per Cederqvist's avatar
Per Cederqvist committed
202
203
204
205
	    }
	}
    }

Per Cederqvist's avatar
Per Cederqvist committed
206
    if (found != 1)
Per Cederqvist's avatar
Per Cederqvist committed
207
    {
David Byers's avatar
David Byers committed
208
	kom_log ("line matches %d times: %s\n", found, line);
Per Cederqvist's avatar
Per Cederqvist committed
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
	(*err)++;
	return 0;
    }
    return 0;
}

void
read_config(const char *config_file, 
	    const struct parameter *par)
{
    FILE *fp;
    int errs = 0;

    init_init(par);

    fp = fopen(config_file, "r");
    if (fp == NULL)
226
	restart_kom("cannot open config file %s\n", config_file);
Per Cederqvist's avatar
Per Cederqvist committed
227
228
229

    while (configure_line(fp, par, &errs) != EOF)
	;
230
    fclose(fp);
Per Cederqvist's avatar
Per Cederqvist committed
231
232
233
    assign_defaults(par, &errs);

    if (errs)
234
	restart_kom("Please fix the above errors in %s and restart lyskomd\n",
Per Cederqvist's avatar
Per Cederqvist committed
235
236
237
238
239
240
241
242
243
244
		    config_file);

    sfree(assignment_count);
    assignment_count = 0;
}

Success
assign_text_no(const char *val, 
	       const struct parameter *par)
{
245
246
247
    int c;

    /* FIXME: use strtol */
Per Cederqvist's avatar
Per Cederqvist committed
248
    if (val != NULL)
249
    {
250
251
	c = (unsigned char)*val;
	if (!isascii(c) || !isdigit(c))
252
	    return FAILURE;
Per Cederqvist's avatar
Per Cederqvist committed
253
	*(Text_no*)par->value = atol(val);
254
    }
Per Cederqvist's avatar
Per Cederqvist committed
255
256
257
258
259
260
261
    return OK;
}

Success
assign_conf_no(const char *val, 
	       const struct parameter *par)
{
262
263
264
    int c;

    /* FIXME: use strtol */
Per Cederqvist's avatar
Per Cederqvist committed
265
    if (val != NULL)
266
    {
267
268
	c = (unsigned char)*val;
	if (!isascii(c) || !isdigit(c))
269
	    return FAILURE;
Per Cederqvist's avatar
Per Cederqvist committed
270
	*(Conf_no*)par->value = atol(val);
271
    }
Per Cederqvist's avatar
Per Cederqvist committed
272
273
274
275
276
277
278
    return OK;
}

Success
assign_int(const char *val, 
	   const struct parameter *par)
{
279
280
281
    int c;

    /* FIXME: use strtol */
Per Cederqvist's avatar
Per Cederqvist committed
282
    if (val != NULL)
283
    {
284
285
	c = (unsigned char)*val;
	if ((!isascii(c) || !isdigit(c)) && c != '-')
286
	    return FAILURE;
Per Cederqvist's avatar
Per Cederqvist committed
287
	*(int*)par->value = atol(val);
288
    }
Per Cederqvist's avatar
Per Cederqvist committed
289
290
291
    return OK;
}

David Byers's avatar
David Byers committed
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
Success
assign_ulong(const char *val,
             const struct parameter *par)
{
    int c;

    if (val != NULL)
    {
        c = (unsigned char)*val;
	if ((!isascii(c) || !isdigit(c)) && c != '-')
	    return FAILURE;
	*(unsigned long*)par->value = (unsigned long)atol(val);
    }
    return OK;
}

Per Cederqvist's avatar
Per Cederqvist committed
308
309
310
311
Success
assign_string(const char *val, 
	      const struct parameter *par)
{
Per Cederqvist's avatar
Per Cederqvist committed
312
313
314
315
316
317
318
    if (val == NULL)
	*(char**)par->value = NULL;
    else
    {
	*(char**)par->value = smalloc(strlen(val) + 1);
	strcpy(*(char**)par->value, val);
    }
Per Cederqvist's avatar
Per Cederqvist committed
319
320
321
322
323
324
325
    return OK;
}

Success
assign_bool(const char *val, 
	    const struct parameter *par)
{
Per Cederqvist's avatar
Per Cederqvist committed
326
    if (val == NULL 
327
328
329
330
	||!strcmp(val, "false") 
	|| !strcmp(val, "off")
	|| !strcmp(val, "no")
	|| !strcmp(val, "0"))
Per Cederqvist's avatar
Per Cederqvist committed
331
332
333
    {
	*(Bool*)par->value = FALSE;
    }
334
335
336
337
    else if (!strcmp(val, "true") 
	|| !strcmp(val, "on")
	|| !strcmp(val, "yes")
	|| !strcmp(val, "1"))
Per Cederqvist's avatar
Per Cederqvist committed
338
    {
Per Cederqvist's avatar
Per Cederqvist committed
339
	*(Bool*)par->value = TRUE;
Per Cederqvist's avatar
Per Cederqvist committed
340
    }
Per Cederqvist's avatar
Per Cederqvist committed
341
    else
Per Cederqvist's avatar
Per Cederqvist committed
342
    {
Per Cederqvist's avatar
Per Cederqvist committed
343
	return FAILURE;
Per Cederqvist's avatar
Per Cederqvist committed
344
    }
Per Cederqvist's avatar
Per Cederqvist committed
345
346
347

    return OK;
}
David Byers's avatar
David Byers committed
348
349
350
351
352
353
354
355
356
357
358


void
unassign_string(const struct parameter *par)
{
    if (*(char**)par->value != NULL)
    {
        sfree(*(char**)par->value);
        *(char**)par->value = NULL;
    }
}