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#if HAVE_ERRNO_H
38#  include <errno.h>
39#endif
40
41#include <conf_file.h>
42#include <dprintf.h>
43
44#if HAVE_STRERROR
45//extern int errno;
46#  define error_string strerror(errno)
47#elif HAVE_SYS_ERRLIST
48extern const char *const sys_errlist[];
49extern int errno;
50#  define error_string (sys_errlist[errno])
51#else
52#  define error_string "error message not found"
53#endif
54
55int parse_conf_file(char *fname, struct conf_cmd *commands)
56{
57  char buf[BUFSIZ+1];
58  FILE *in;
59  int using_a_file = 1;
60  char *p;
61  char *cmd_start;
62  char *arg;
63  struct conf_cmd *cmd;
64  int lnum = 0;
65
66  // safety first
67  buf[BUFSIZ] = '\0';
68
69  if(strcmp("-", fname) == 0)
70  {
71    in = stdin;
72    using_a_file = 0;
73  }
74  else
75  {
76    if((in=fopen(fname, "r")) == NULL)
77    {
78      show_message("could not open config file \"%s\": %s\n", fname, error_string);
79      return(-1);
80    }
81  }
82
83  while(lnum++, fgets(buf, BUFSIZ, in) != NULL)
84  {
85    p = buf;
86
87    /* eat space */
88    while(*p == ' ' || *p == '\t') { p++; }
89
90    /* ignore comments and blanks */
91    if(*p == '#' || *p == '\r' || *p == '\n' || *p == '\0')
92    {
93      continue;
94    }
95
96    cmd_start = p;
97
98    /* chomp new line */
99    while(*p != '\0' && *p != '\r' && *p != '\n') { p++; }
100    *p = '\0';
101    p = cmd_start;
102
103    /* find the end of the command */
104    while(*p != '\0' && *p != '=') { p++; }
105
106    /* insure that it is terminated and find arg */
107    if(*p == '\0')
108    {
109      arg = NULL;
110    }
111    else
112    {
113      *p = '\0';
114      p++;
115      arg = p;
116    }
117
118    /* look up the command */
119    cmd = commands;
120    while(cmd->name != NULL)
121    {
122      if(strcmp(cmd->name, cmd_start) == 0)
123      {
124        dprintf((stderr, "using cmd %s\n", cmd->name));
125        break;
126      }
127      cmd++;
128    }
129    if(cmd->name == NULL)
130    {
131      show_message("%s,%d: unknown command: %s\n", fname, lnum, cmd_start);
132
133      fprintf(stderr, "commands are:\n");
134      cmd = commands;
135      while(cmd->name != NULL)
136      {
137        fprintf(stderr, "  %-14s usage: ", cmd->name);
138        fprintf(stderr, cmd->help, cmd->name);
139        fprintf(stderr, "\n");
140        cmd++;
141      }
142      goto ERR;
143    }
144
145    /* check the arg */
146    switch(cmd->arg_type)
147    {
148      case CONF_NEED_ARG:
149        if(arg == NULL)
150        {
151          show_message("option \"%s\" requires an argument\n", cmd->name);
152          goto ERR;
153        }
154        break;
155      case CONF_OPT_ARG:
156        if(arg == NULL)
157        {
158          arg = "";
159        }
160        break;
161      case CONF_NO_ARG:
162        arg = "";
163        break;
164      default:
165        dprintf((stderr, "case not handled: %d\n", cmd->arg_type));
166        break;
167    }
168
169    /* is the command implemented? */
170    if(!cmd->available)
171    {
172      show_message("the command \"%s\" is not available\n", cmd->name);
173      continue;
174    }
175
176    /* handle the command */
177    cmd->proc(cmd, arg);
178  }
179
180  if(using_a_file)
181  {
182    if(in)
183    {
184      fclose(in);
185    }
186  }
187  return 0;
188
189ERR:
190  if(using_a_file)
191  {
192    if(in)
193    {
194      fclose(in);
195    }
196  }
197  return(-1);
198}
199