1/* ============================================================================
2 * Copyright (C) 1999 Angus Mackay. All rights reserved;
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2, or (at your option)
7 * any later version.
8 *
9 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
10 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
11 * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
12 * AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
13 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
14 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
15 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
16 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
17 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
18 * POSSIBILITY OF SUCH DAMAGE.
19 * ============================================================================
20 */
21
22/*
23 * conf_file.c
24 *
25 * simple config file code
26 *
27 */
28
29
30#ifdef HAVE_CONFIG_H
31#  include <config.h>
32#endif
33
34#include <stdio.h>
35#include <stdlib.h>
36#include <string.h>
37
38#include <conf_file.h>
39#include <dprintf.h>
40
41#if HAVE_STRERROR
42extern int errno;
43#  define error_string strerror(errno)
44#elif HAVE_SYS_ERRLIST
45extern const char *const sys_errlist[];
46extern int errno;
47#  define error_string (sys_errlist[errno])
48#else
49#  define error_string "error message not found"
50#endif
51
52int parse_conf_file(char *fname, struct conf_cmd *commands)
53{
54  char buf[BUFSIZ+1];
55  FILE *in;
56  int using_a_file = 1;
57  char *p;
58  char *cmd_start;
59  char *arg;
60  struct conf_cmd *cmd;
61  int lnum = 0;
62
63  // safety first
64  buf[BUFSIZ] = '\0';
65
66  if(strcmp("-", fname) == 0)
67  {
68    in = stdin;
69    using_a_file = 0;
70  }
71  else
72  {
73    if((in=fopen(fname, "r")) == NULL)
74    {
75      show_message("could not open config file \"%s\": %s\n", fname, error_string);
76      return(-1);
77    }
78  }
79
80  while(lnum++, fgets(buf, BUFSIZ, in) != NULL)
81  {
82    p = buf;
83
84    /* eat space */
85    while(*p == ' ' || *p == '\t') { p++; }
86
87    /* ignore comments and blanks */
88    if(*p == '#' || *p == '\r' || *p == '\n' || *p == '\0')
89    {
90      continue;
91    }
92
93    cmd_start = p;
94
95    /* chomp new line */
96    while(*p != '\0' && *p != '\r' && *p != '\n') { p++; }
97    *p = '\0';
98    p = cmd_start;
99
100    /* find the end of the command */
101    while(*p != '\0' && *p != '=') { p++; }
102
103    /* insure that it is terminated and find arg */
104    if(*p == '\0')
105    {
106      arg = NULL;
107    }
108    else
109    {
110      *p = '\0';
111      p++;
112      arg = p;
113    }
114
115    /* look up the command */
116    cmd = commands;
117    while(cmd->name != NULL)
118    {
119      if(strcmp(cmd->name, cmd_start) == 0)
120      {
121        dprintf((stderr, "using cmd %s\n", cmd->name));
122        break;
123      }
124      cmd++;
125    }
126    if(cmd->name == NULL)
127    {
128      show_message("%s,%d: unknown command: %s\n", fname, lnum, cmd_start);
129
130      fprintf(stderr, "commands are:\n");
131      cmd = commands;
132      while(cmd->name != NULL)
133      {
134        fprintf(stderr, "  %-14s usage: ", cmd->name);
135        fprintf(stderr, cmd->help, cmd->name);
136        fprintf(stderr, "\n");
137        cmd++;
138      }
139      goto ERR;
140    }
141
142    /* check the arg */
143    switch(cmd->arg_type)
144    {
145      case CONF_NEED_ARG:
146        if(arg == NULL)
147        {
148          show_message("option \"%s\" requires an argument\n", cmd->name);
149          goto ERR;
150        }
151        break;
152      case CONF_OPT_ARG:
153        if(arg == NULL)
154        {
155          arg = "";
156        }
157        break;
158      case CONF_NO_ARG:
159        arg = "";
160        break;
161      default:
162        dprintf((stderr, "case not handled: %d\n", cmd->arg_type));
163        break;
164    }
165
166    /* is the command implemented? */
167    if(!cmd->available)
168    {
169      show_message("the command \"%s\" is not available\n", cmd->name);
170      continue;
171    }
172
173    /* handle the command */
174    cmd->proc(cmd, arg);
175  }
176
177  if(using_a_file)
178  {
179    if(in)
180    {
181      fclose(in);
182    }
183  }
184  return 0;
185
186ERR:
187  if(using_a_file)
188  {
189    if(in)
190    {
191      fclose(in);
192    }
193  }
194  return(-1);
195}
196