Index: common/cfgreader.c =================================================================== RCS file: /cvsroot/gnokii/gnokii/common/cfgreader.c,v retrieving revision 1.53 diff -u -r1.53 cfgreader.c --- common/cfgreader.c 2 Jan 2005 14:21:45 -0000 1.53 +++ common/cfgreader.c 5 Feb 2005 20:15:22 -0000 @@ -46,36 +46,25 @@ API struct gn_cfg_header *gn_cfg_info; static gn_config gn_config_default, gn_config_global; -/* Read configuration information from a ".INI" style file */ -struct gn_cfg_header *cfg_file_read(const char *filename) +struct gn_cfg_header *cfg_memory_read(const char **lines) { - FILE *handle; - char *line; - char *buf; + char *line, *buf; struct gn_cfg_header *cfg_info = NULL, *cfg_head = NULL; - - /* Error check */ - if (filename == NULL) { - return NULL; - } - - /* Initialisation */ - if ((buf = (char *)malloc(255)) == NULL) { - return NULL; - } + int i; /* Open file */ - if ((handle = fopen(filename, "r")) == NULL) { - dprintf("cfg_file_read - open %s: %s\n", filename, strerror(errno)); + if (lines == NULL) { + dprintf("cfg_memory_read - passed nil data\n"); return NULL; } else { - dprintf("Opened configuration file %s\n", filename); + dprintf("Opened configuration file from memory\n"); } /* Iterate over lines in the file */ - while (fgets(buf, 255, handle) != NULL) { + for (i = 0; lines[i] != NULL; i++) { - line = buf; + line = strdup (lines[i]); + buf = line; /* Strip leading, trailing whitespace */ while(isspace((int) *line)) @@ -94,7 +83,6 @@ /* Allocate new heading entry */ if ((heading = (struct gn_cfg_header *)malloc(sizeof(*heading))) == NULL) { - free(buf); return NULL; } @@ -121,6 +109,8 @@ dprintf("Added new section %s\n", heading->section); + free(buf); + /* Go on to next line */ continue; } @@ -133,7 +123,6 @@ /* Allocate new entry */ if ((entry = (struct gn_cfg_entry *)malloc(sizeof(*entry))) == NULL) { - free(buf); return NULL; } @@ -169,19 +158,110 @@ dprintf("Adding key/value %s/%s\n", entry->key, entry->value); + free(buf); + /* Go on to next line */ continue; } /* Line not part of any heading */ fprintf(stderr, "Orphaned line: %s\n", line); + + free(buf); } - free(buf); /* Return pointer to configuration information */ return cfg_head; } +#define READ_CHUNK_SIZE 64 + +/* Read configuration information from a ".INI" style file */ +struct gn_cfg_header *cfg_file_read(const char *filename) +{ + FILE *handle; + char *lines, *line_begin, *line_end; + char **split_lines; + int read, ret, num_lines, i; + struct gn_cfg_header *header; + + /* Open file */ + if ((handle = fopen(filename, "r")) == NULL) { + dprintf("cfg_file_read - open %s: %s\n", filename, strerror(errno)); + return NULL; + } else { + dprintf("Opened configuration file %s\n", filename); + } + + /* Read the lines */ + lines = NULL; + read = 0; + do { + lines = realloc (lines, read + READ_CHUNK_SIZE); + ret = fread (lines + read, 1, READ_CHUNK_SIZE, handle); + /* Read error */ + if (ret < 0 && feof (handle) == 0) { + fclose (handle); + free (lines); + return NULL; + } + /* Overflow */ + if (read + ret < read) { + fclose (handle); + free (lines); + return NULL; + } + + read += ret; + } while (ret > 0); + + fclose (handle); + lines = realloc (lines, read + 1); + lines[read] = '\0'; + + /* Now split the lines */ + split_lines = NULL; + line_begin = NULL; + num_lines = 0; + for (i = 0; lines[i] != '\0'; i++) { + char *buf; + + if (lines[i] != '\n') { + if (line_begin == NULL) { + line_begin = lines + i; + num_lines++; + } + continue; + } + if (line_begin == NULL) + break; + + line_end = lines + i; + buf = (char *)strndup (line_begin, line_end - line_begin); + split_lines = realloc (split_lines, + (num_lines + 1) * sizeof (char*)); + split_lines[num_lines - 1] = buf; + line_begin = NULL; + } + + free (lines); + if (split_lines == NULL) + return NULL; + + split_lines[num_lines] = NULL; + + /* Finally, load the configuration from the split lines */ + header = cfg_memory_read ((const char **)split_lines); + + /* Free the split_lines */ + for (i = 0; split_lines[i] != NULL; i++) { + free (split_lines[i]); + } + free (split_lines); + + return header; +} + /* Write configuration information to a config file */ int cfg_file_write(struct gn_cfg_header *cfg, const char *filename) { @@ -466,10 +546,16 @@ return retval; } -API int gn_cfg_file_read(const char *file) +static +int gn_cfg_file_or_memory_read(const char *file, const char **lines) { char *val; + if (file == NULL && lines == NULL) { + dprintf(_("Couldn't open a config file or memory,\n")); + return -1; + } + /* I know that it doesn't belong here but currently there is now generic * application init function anywhere. */ @@ -479,7 +565,12 @@ /* * Try opening a given config file */ - if ((gn_cfg_info = cfg_file_read(file)) == NULL) { + if (file != NULL) + gn_cfg_info = cfg_file_read(file); + else + gn_cfg_info = cfg_memory_read(lines); + + if (gn_cfg_info == NULL) { /* this is bad, but the previous was much worse - bozo */ dprintf(_("Couldn't open %s config file,\n"), file); return -1; @@ -521,6 +612,16 @@ return 0; } +API int gn_cfg_file_read(const char *file) +{ + return gn_cfg_file_or_memory_read (file, NULL); +} + +API int gn_cfg_memory_read(const char **lines) +{ + return gn_cfg_file_or_memory_read (NULL, lines); +} + API bool gn_cfg_phone_load(const char *iname, struct gn_statemachine *state) { char section[256]; Index: include/gnokii.h =================================================================== RCS file: /cvsroot/gnokii/gnokii/include/gnokii.h,v retrieving revision 1.75 diff -u -r1.75 gnokii.h --- include/gnokii.h 1 Jan 2005 18:33:53 -0000 1.75 +++ include/gnokii.h 5 Feb 2005 20:15:25 -0000 @@ -103,6 +103,7 @@ API char *gn_cfg_get(struct gn_cfg_header *cfg, const char *section, const char *key); API int gn_cfg_read(char **bindir); /* DEPRECATED */ API int gn_cfg_file_read(const char *filename); +API int gn_cfg_memory_read(const char **lines); API int gn_cfg_read_default(); API int gn_cfg_phone_load(const char *iname, struct gn_statemachine *state);