datacalls decoding patches
[gnokii.git] / common / files / 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   Released under the terms of the GNU GPL, see file COPYING for more details.
10
11   Config file (/etc/gnokiirc and ~/.gnokiirc) reader.
12
13   Modified from code by Tim Potter.
14
15 */
16
17 #include "misc.h"
18
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <string.h>
22 #if __unices__
23 #  include <strings.h>
24 #endif
25 #include <ctype.h>
26 #include <errno.h>
27
28 #include "files/cfgreader.h"
29
30 /* Read configuration information from a ".INI" style file */
31 struct CFG_Header *CFG_ReadFile(char *filename)
32 {
33         FILE *handle;
34         char *line;
35         char *buf;
36         struct CFG_Header *cfg_info = NULL, *cfg_head = NULL;
37
38         /* Error check */
39         if (filename == NULL) {
40                 return NULL;
41         }
42
43         /* Initialisation */
44         if ((buf = (char *)malloc(255)) == NULL) {
45                 return NULL;
46         }
47     
48         /* Open file */
49         if ((handle = fopen(filename, "r")) == NULL) {
50 #ifdef DEBUG
51                 fprintf( stderr, "CFG_ReadFile - open %s: %s\n", filename, strerror(errno));
52 #endif /* DEBUG */
53                 return NULL;
54         }
55 #ifdef DEBUG
56         else
57                 fprintf( stderr, "Opened configuration file %s\n", filename );
58 #endif /* DEBUG */
59
60         /* Iterate over lines in the file */
61         while (fgets(buf, 255, handle) != NULL) {
62
63                 line = buf;
64
65                 /* Strip leading, trailing whitespace */
66                 while(isspace((int) *line))
67                         line++;
68
69                 while((strlen(line) > 0) && isspace((int) line[strlen(line) - 1]))
70                         line[strlen(line) - 1] = '\0';
71         
72                 /* Ignore blank lines and comments */
73                 if ((*line == '\n') || (*line == '\0') || (*line == '#'))
74                         continue;
75
76                 /* Look for "headings" enclosed in square brackets */
77                 if ((line[0] == '[') && (line[strlen(line) - 1] == ']')) {
78                         struct CFG_Header *heading;
79
80                         /* Allocate new heading entry */
81                         if ((heading = (struct CFG_Header *)malloc(sizeof(*heading))) == NULL) {
82                                 return NULL;
83                         }
84
85                         /* Fill in fields */
86                         memset(heading, '\0', sizeof(*heading));
87             
88                         line++;
89                         line[strlen(line) - 1] = '\0';
90
91                         /* FIXME: strdup is not ANSI C compliant. */
92                         heading->section = strdup(line);
93
94                         /* Add to tail of list  */
95                         heading->prev = cfg_info;
96
97                         if (cfg_info != NULL) {
98                                 cfg_info->next = heading;
99                         } else {
100                                 /* Store copy of head of list for return value */
101                                 cfg_head = heading;
102                         }
103
104                         cfg_info = heading;
105
106 #ifdef DEBUG
107                         fprintf(stderr, "Added new section %s\n", heading->section);
108 #endif
109                         /* Go on to next line */
110
111                         continue;
112                 }
113
114                 /* Process key/value line */
115
116                 if ((strchr(line, '=') != NULL) && cfg_info != NULL) {
117                         struct CFG_Entry *entry;
118                         char *value;
119
120                         /* Allocate new entry */
121                         if ((entry = (struct CFG_Entry *)malloc(sizeof(*entry))) == NULL) {
122                                 return NULL;
123                         }
124
125                         /* Fill in fields */
126                         memset(entry, '\0', sizeof(*entry));
127
128                         value = strchr(line, '=');
129                         *value = '\0';                /* Split string */
130                         value++;
131             
132                         while(isspace((int) *value)) {      /* Remove leading white */
133                                 value++;
134                         }
135
136                         entry->value = strdup(value);
137
138                         while((strlen(line) > 0) && isspace((int) line[strlen(line) - 1])) {
139                                 line[strlen(line) - 1] = '\0';  /* Remove trailing white */
140                         }
141
142                         /* FIXME: strdup is not ANSI C compliant. */
143                         entry->key = strdup(line);
144
145                         /* Add to head of list */
146
147                         entry->next = cfg_info->entries;
148
149                         if (cfg_info->entries != NULL) {
150                                 cfg_info->entries->prev = entry;
151                         }
152
153                         cfg_info->entries = entry;
154
155 #ifdef DEBUG
156                         fprintf(stderr, "Adding key/value %s/%s\n", entry->key, entry->value);
157 #endif
158                         /* Go on to next line */
159                         continue;
160                 }
161
162                         /* Line not part of any heading */
163                 fprintf(stderr, "Orphaned line: %s\n", line);
164         }
165
166         /* Return pointer to configuration information */
167         return cfg_head;
168 }
169
170 /*  Write configuration information to a config file */
171
172 int CFG_WriteFile(struct CFG_Header *cfg, char *filename)
173 {
174   /* Not implemented - tricky to do and preserve comments */
175
176   return 0;
177 }
178
179 /* 
180  * Find the value of a key in a config file.  Return value associated
181  * with key or NULL if no such key exists. 
182  */
183
184 char *CFG_Get(struct CFG_Header *cfg, char *section, char *key)
185 {
186         struct CFG_Header *h;
187         struct CFG_Entry *e;
188
189         if ((cfg == NULL) || (section == NULL) || (key == NULL)) {
190                 return NULL;
191         }
192
193         /* Search for section name */
194         for (h = cfg; h != NULL; h = h->next) {
195                 if (strcmp(section, h->section) == 0) {
196                         /* Search for key within section */
197                         for (e = h->entries; e != NULL; e = e->next) {
198                                 if (strcmp(key, e->key) == 0) {
199                                         /* Found! */
200                                         return e->value;
201                                 }
202                         }
203                 }
204         }
205         /* Key not found in section */
206         return NULL;
207 }
208
209 /*  Set the value of a key in a config file.  Return the new value if
210     the section/key can be found, else return NULL.  */
211
212 char *CFG_Set(struct CFG_Header *cfg, char *section, char *key, 
213                     char *value)
214 {
215         struct CFG_Header *h;
216         struct CFG_Entry *e;
217
218         if ((cfg == NULL) || (section == NULL) || (key == NULL) || 
219             (value == NULL)) {
220                 return NULL;
221         }
222
223         /* Search for section name */
224         for (h = cfg; h != NULL; h = h->next) {
225                 if (strcmp(section, h->section) == 0) {
226                         /* Search for key within section */
227                         for (e = h->entries; e != NULL; e = e->next) {
228                                 if ((e->key != NULL) && strcmp(key, e->key) == 0) {
229                                         /* Found - set value */
230                                         free(e->key);
231                                         /* FIXME: strdup is not ANSI C compliant. */
232                                         e->key = strdup(value);
233                                         return e->value;
234                                 }
235                         }
236                 }
237         }
238         /* Key not found in section */
239         return NULL;    
240 }
241
242 struct CFG_Header *CFG_FindGnokiirc()
243 {
244         struct CFG_Header *cfg_info;
245         char *homedir;
246         char rcfile[200];
247
248 #ifdef WIN32
249         homedir = getenv("HOMEDRIVE");
250         strncpy(rcfile, homedir ? homedir : "", 200);
251         homedir = getenv("HOMEPATH");
252         strncat(rcfile, homedir ? homedir : "", 200);
253         strncat(rcfile, "\gnokiirc", 200);
254 #else
255         homedir = getenv("HOME");
256         if (homedir) strncpy(rcfile, homedir, 200);
257         strncat(rcfile, "/.mygnokiirc", 200);
258 #endif
259
260         /* Try opening .gnokirc from users home directory first */
261         if ((cfg_info = CFG_ReadFile(rcfile)) == NULL) {
262 #ifndef WIN32
263
264                 /* It failed so try for /etc/gnokiirc */
265                 if ((cfg_info = CFG_ReadFile("/etc/gnokiirc")) == NULL) {
266                         /* That failed too so exit */
267 #ifdef DEBUG
268                         fprintf(stderr, _("Couldn't open %s or /etc/gnokiirc. Using defaults...\n"), rcfile);
269 #endif /* DEBUG */
270                         return NULL;
271                 }
272
273 #else /* WIN32 */
274
275                 /* It failed so try for gnokiirc */
276                 if ((cfg_info = CFG_ReadFile("gnokiirc")) == NULL) {
277                         /* That failed too so exit */
278 #ifdef DEBUG
279                         fprintf(stderr, _("Couldn't open %s or gnokiirc. Using defaults...\n"), rcfile);
280 #endif /* DEBUG */
281                         return NULL;
282                 }
283
284 #endif /* WIN32 */
285         }
286
287         return cfg_info;
288 }
289
290 int CFG_ReadConfig(char **model, char **port, char **initlength,
291                char **connection, char **bindir, char **synchronizetime,
292                bool isgnokiid)
293 {
294         struct CFG_Header *cfg_info;
295 #ifdef WIN32
296         char *DefaultPort            = "com2:";
297 #else
298         char *DefaultPort            = "/dev/ttyS1";
299 #endif
300         char *DefaultModel           = "auto";
301         char *DefaultConnection      = "fbus";
302         char *DefaultBindir          = "/usr/local/sbin/";
303         char *DefaultSynchronizeTime = "yes";
304         char *DefaultInitLength      = "30";
305
306         char *section = "global";
307
308         (char *)*model = DefaultModel;
309         (char *)*port = DefaultPort;
310         (char *)*connection = DefaultConnection;
311         (char *)*bindir = DefaultBindir;
312         (char *)*synchronizetime = DefaultSynchronizeTime;
313         (char *)*initlength = DefaultInitLength;
314         
315         cfg_info=CFG_FindGnokiirc();
316         if (cfg_info==NULL) return 0;
317
318         if (isgnokiid) (char *)section = "gnokiid";
319         
320         (char *)*model = CFG_Get(cfg_info, section, "model");
321         if (!*model) (char *)*model = DefaultModel;
322
323         (char *)*port = CFG_Get(cfg_info, section, "port");
324         if (!*port) (char *)*port = DefaultPort;
325
326         (char *)*connection = CFG_Get(cfg_info, section, "connection");
327         if (!*connection) (char *)*connection = DefaultConnection;
328
329         (char *)*bindir = CFG_Get(cfg_info, section, "bindir");
330         if (!*bindir) (char *)*bindir = DefaultBindir;
331
332         (char *)*synchronizetime = CFG_Get(cfg_info, section, "synchronizetime");
333         if (!*synchronizetime) (char *)*synchronizetime = DefaultSynchronizeTime;
334
335         (char *)*initlength = CFG_Get(cfg_info, section, "initlength");
336         if (!*initlength) (char *)*initlength = "default";
337
338         return 0;
339 }