:pserver:cvs@pserver.samba.org:/cvsroot - gnokii - Tue Dec 4 22:45 CET 2001
[gnokii.git] / common / cfgreader.c
1 /*
2
3   $Id$
4
5   G N O K I I
6
7   A Linux/Unix toolset and driver for Nokia mobile phones.
8
9   Copyright (C) 1999, 2000 Hugh Blemings & Pavel Janík ml.
10
11   Released under the terms of the GNU GPL, see file COPYING for more details.
12
13   Config file (/etc/gnokiirc and ~/.gnokiirc) reader.
14
15   Modified from code by Tim Potter.
16
17   $Log$
18   Revision 1.1.1.1  2001/11/25 21:58:58  short
19   :pserver:cvs@pserver.samba.org:/cvsroot - gnokii - Sun Nov 25 22:56 CET 2001
20
21   Revision 1.16  2001/11/14 10:46:12  pkot
22   Small cleanup with __unices__
23
24   Revision 1.15  2001/06/10 11:24:57  machek
25   Kill "slash star" inside comment.
26
27   Revision 1.14  2001/03/19 23:43:45  pkot
28   Solaris/ *BSD '#if defined' cleanup
29
30   Revision 1.13  2001/03/13 01:21:38  pkot
31   *BSD updates (Bert Driehuis)
32
33   Revision 1.12  2001/01/08 15:11:36  pkot
34   Documentation updates.
35   Fixed some bugs and removed FIXMEs.
36   We need to move some stuff from configure.in to aclocal.m4
37
38   Revision 1.11  2001/01/02 09:09:07  pkot
39   Misc fixes and updates.
40
41   Revision 1.10  2000/12/19 16:18:15  pkot
42   configure script updates and added shared function for configfile reading
43
44
45 */
46
47 #include "misc.h"
48
49 #include <stdio.h>
50 #include <stdlib.h>
51 #include <string.h>
52 #include <ctype.h>
53 #include <errno.h>
54
55 #include "cfgreader.h"
56
57 /* Read configuration information from a ".INI" style file */
58 struct CFG_Header *CFG_ReadFile(char *filename)
59 {
60         FILE *handle;
61         char *line;
62         char *buf;
63         struct CFG_Header *cfg_info = NULL, *cfg_head = NULL;
64
65         /* Error check */
66         if (filename == NULL) {
67                 return NULL;
68         }
69
70         /* Initialisation */
71         if ((buf = (char *)malloc(255)) == NULL) {
72                 return NULL;
73         }
74     
75         /* Open file */
76         if ((handle = fopen(filename, "r")) == NULL) {
77 #ifdef DEBUG
78                 fprintf( stderr, "CFG_ReadFile - open %s: %s\n", filename, strerror(errno));
79 #endif /* DEBUG */
80                 return NULL;
81         }
82 #ifdef DEBUG
83         else
84                 fprintf( stderr, "Opened configuration file %s\n", filename );
85 #endif /* DEBUG */
86
87         /* Iterate over lines in the file */
88         while (fgets(buf, 255, handle) != NULL) {
89
90                 line = buf;
91
92                 /* Strip leading, trailing whitespace */
93                 while(isspace((int) *line))
94                         line++;
95
96                 while((strlen(line) > 0) && isspace((int) line[strlen(line) - 1]))
97                         line[strlen(line) - 1] = '\0';
98         
99                 /* Ignore blank lines and comments */
100                 if ((*line == '\n') || (*line == '\0') || (*line == '#'))
101                         continue;
102
103                 /* Look for "headings" enclosed in square brackets */
104                 if ((line[0] == '[') && (line[strlen(line) - 1] == ']')) {
105                         struct CFG_Header *heading;
106
107                         /* Allocate new heading entry */
108                         if ((heading = (struct CFG_Header *)malloc(sizeof(*heading))) == NULL) {
109                                 return NULL;
110                         }
111
112                         /* Fill in fields */
113                         memset(heading, '\0', sizeof(*heading));
114             
115                         line++;
116                         line[strlen(line) - 1] = '\0';
117
118                         /* FIXME: strdup is not ANSI C compliant. */
119                         heading->section = strdup(line);
120
121                         /* Add to tail of list  */
122                         heading->prev = cfg_info;
123
124                         if (cfg_info != NULL) {
125                                 cfg_info->next = heading;
126                         } else {
127                                 /* Store copy of head of list for return value */
128                                 cfg_head = heading;
129                         }
130
131                         cfg_info = heading;
132
133 #ifdef DEBUG
134                         fprintf(stderr, "Added new section %s\n", heading->section);
135 #endif
136                         /* Go on to next line */
137
138                         continue;
139                 }
140
141                 /* Process key/value line */
142
143                 if ((strchr(line, '=') != NULL) && cfg_info != NULL) {
144                         struct CFG_Entry *entry;
145                         char *value;
146
147                         /* Allocate new entry */
148                         if ((entry = (struct CFG_Entry *)malloc(sizeof(*entry))) == NULL) {
149                                 return NULL;
150                         }
151
152                         /* Fill in fields */
153                         memset(entry, '\0', sizeof(*entry));
154
155                         value = strchr(line, '=');
156                         *value = '\0';                /* Split string */
157                         value++;
158             
159                         while(isspace((int) *value)) {      /* Remove leading white */
160                                 value++;
161                         }
162
163                         entry->value = strdup(value);
164
165                         while((strlen(line) > 0) && isspace((int) line[strlen(line) - 1])) {
166                                 line[strlen(line) - 1] = '\0';  /* Remove trailing white */
167                         }
168
169                         /* FIXME: strdup is not ANSI C compliant. */
170                         entry->key = strdup(line);
171
172                         /* Add to head of list */
173
174                         entry->next = cfg_info->entries;
175
176                         if (cfg_info->entries != NULL) {
177                                 cfg_info->entries->prev = entry;
178                         }
179
180                         cfg_info->entries = entry;
181
182 #ifdef DEBUG
183                         fprintf(stderr, "Adding key/value %s/%s\n", entry->key, entry->value);
184 #endif
185                         /* Go on to next line */
186                         continue;
187                 }
188
189                         /* Line not part of any heading */
190                 fprintf(stderr, "Orphaned line: %s\n", line);
191         }
192
193         /* Return pointer to configuration information */
194         return cfg_head;
195 }
196
197 /*  Write configuration information to a config file */
198
199 int CFG_WriteFile(struct CFG_Header *cfg, char *filename)
200 {
201   /* Not implemented - tricky to do and preserve comments */
202
203   return 0;
204 }
205
206 /* 
207  * Find the value of a key in a config file.  Return value associated
208  * with key or NULL if no such key exists. 
209  */
210
211 char *CFG_Get(struct CFG_Header *cfg, char *section, char *key)
212 {
213         struct CFG_Header *h;
214         struct CFG_Entry *e;
215
216         if ((cfg == NULL) || (section == NULL) || (key == NULL)) {
217                 return NULL;
218         }
219
220         /* Search for section name */
221         for (h = cfg; h != NULL; h = h->next) {
222                 if (strcmp(section, h->section) == 0) {
223                         /* Search for key within section */
224                         for (e = h->entries; e != NULL; e = e->next) {
225                                 if (strcmp(key, e->key) == 0) {
226                                         /* Found! */
227                                         return e->value;
228                                 }
229                         }
230                 }
231         }
232         /* Key not found in section */
233         return NULL;
234 }
235
236 /*  Set the value of a key in a config file.  Return the new value if
237     the section/key can be found, else return NULL.  */
238
239 char *CFG_Set(struct CFG_Header *cfg, char *section, char *key, 
240                     char *value)
241 {
242         struct CFG_Header *h;
243         struct CFG_Entry *e;
244
245         if ((cfg == NULL) || (section == NULL) || (key == NULL) || 
246             (value == NULL)) {
247                 return NULL;
248         }
249
250         /* Search for section name */
251         for (h = cfg; h != NULL; h = h->next) {
252                 if (strcmp(section, h->section) == 0) {
253                         /* Search for key within section */
254                         for (e = h->entries; e != NULL; e = e->next) {
255                                 if ((e->key != NULL) && strcmp(key, e->key) == 0) {
256                                         /* Found - set value */
257                                         free(e->key);
258                                         /* FIXME: strdup is not ANSI C compliant. */
259                                         e->key = strdup(value);
260                                         return e->value;
261                                 }
262                         }
263                 }
264         }
265         /* Key not found in section */
266         return NULL;    
267 }
268
269 int readconfig(char **model, char **port, char **initlength,
270                char **connection, char **bindir)
271 {
272         struct CFG_Header *cfg_info;
273         char *homedir;
274         char rcfile[200];
275         char *DefaultConnection = "serial";
276         char *DefaultBindir     = "/usr/local/sbin/";
277
278 #ifdef WIN32
279         homedir = getenv("HOMEDRIVE");
280         strncpy(rcfile, homedir ? homedir : "", 200);
281         homedir = getenv("HOMEPATH");
282         strncat(rcfile, homedir ? homedir : "", 200);
283         strncat(rcfile, "\\_gnokiirc", 200);
284 #else
285         homedir = getenv("HOME");
286         if (homedir) strncpy(rcfile, homedir, 200);
287         strncat(rcfile, "/.gnokiirc", 200);
288 #endif
289
290         /* Try opening .gnokirc from users home directory first */
291         if ((cfg_info = CFG_ReadFile(rcfile)) == NULL) {
292                 /* It failed so try for /etc/gnokiirc */
293                 if ((cfg_info = CFG_ReadFile("/etc/gnokiirc")) == NULL) {
294                         /* That failed too so exit */
295                         fprintf(stderr, _("Couldn't open %s or /etc/gnokiirc. Exiting now...\n"), rcfile);
296                         return -1;
297                 }
298         }
299
300         (char *)*model = CFG_Get(cfg_info, "global", "model");
301         if (!*model) {
302                 fprintf(stderr, _("Config error - no model specified. Exiting now...\n"));
303                 return -2;
304         }
305
306         (char *)*port = CFG_Get(cfg_info, "global", "port");
307         if (!*port) {
308                 fprintf(stderr, _("Config error - no port specified. Exiting now...\n"));
309                 return -3;
310         }
311
312         (char *)*initlength = CFG_Get(cfg_info, "global", "initlength");
313         if (!*initlength) (char *)*initlength = "default";
314
315         (char *)*connection = CFG_Get(cfg_info, "global", "connection");
316         if (!*connection) (char *)*connection = DefaultConnection;
317
318         (char *)*bindir = CFG_Get(cfg_info, "global", "bindir");
319         if (!*bindir) (char *)*bindir = DefaultBindir;
320
321         return 0;
322 }