/* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Library General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "config_option.h" unsigned int parse_config_file(const char *filename) { /* ----------------------------------------------------------------------------- * Parse a config file and create all option * * @param const char *, the filename * @param int * -------------------------------------------------------------------------- */ FILE * stream; char *buffer = NULL; struct chain_string *strings = NULL, *strings_value = NULL, *strings_tmp = NULL; char *parameter_name = NULL, *parameter_value = NULL, *one_value = NULL; char *old_parameter_name = NULL; int nb_chain_string = 0, int_val = 0; stream = fopen(filename, "r"); if (stream == NULL) { return 0; } safefgets(&buffer, FGETS_BUF_SIZE, stream); while(!feof(stream)) { /* On a lu une ligne dans le fichier */ if ((*buffer != '#') && (*buffer != '\r') && (*buffer != '\n')) { /* On skippe les lignes vides et les lignes commentées */ stripcrlf(buffer); strings = explode_to_chain_string(buffer, "="); nb_chain_string = get_nb_chain_string(strings); /* Format type : name = string value name = int value name = string value1, string value2, string value3 name = string value1 string value2 string value3 */ if (nb_chain_string >= 2) { /* On est sur un paramètre */ parameter_name = trim(get_chain_string(strings, 0)->value); parameter_value = trim(get_chain_string(strings, 1)->value); strings_value = explode_to_chain_string(parameter_value, ","); nb_chain_string = get_nb_chain_string(strings_value); if (nb_chain_string >= 2) { /* On est sur un paramètre multi valeurs */ for (strings_tmp = strings_value; strings_tmp != NULL; strings_tmp = strings_tmp->next) { one_value = trim(strings_tmp->value); if ((int_val = str2int(one_value)) == -1) add_option(parameter_name, OPTION_STRING, one_value); else add_option(parameter_name, OPTION_INT, &int_val); free(one_value); } } else { /* On est sur un paramètre à une seule valeur */ if (*parameter_value) { if ((int_val = str2int(parameter_value)) == -1) set_option(parameter_name, OPTION_STRING, parameter_value); else set_option(parameter_name, OPTION_INT, &int_val); } } free(old_parameter_name); old_parameter_name = strdup(parameter_name); if (old_parameter_name == NULL) return 0; free(parameter_name); free(parameter_value); drop_all_chain_string(strings_value); strings_value = NULL; } else if (((*buffer == ' ') || (*buffer == '\t')) && (old_parameter_name != NULL)) { /* On est sur un paramètre multi valeurs, sur plusieurs lignes */ parameter_value = trim(get_chain_string(strings, 0)->value); if (*parameter_value) { if ((int_val = str2int(parameter_value)) == -1) add_option(old_parameter_name, OPTION_STRING, parameter_value); else add_option(old_parameter_name, OPTION_INT, &int_val); } free(parameter_value); } drop_all_chain_string(strings); strings = NULL; } free(buffer); buffer = NULL; safefgets(&buffer, FGETS_BUF_SIZE, stream); } free(old_parameter_name); free(buffer); fclose(stream); return 1; } size_t safefgets(char **buffer, int size, FILE * stream) { /* ----------------------------------------------------------------------------- * Safe implementation of fgets() * * @param char **, address to the buffer to fill and dynamically allocated * @param int, block size for fread() * @param FILE *, the file stream * @param size_t, number of character read * -------------------------------------------------------------------------- */ char *tmp_buffer = NULL; char *buffer2 = NULL; int i = 0; size_t size_read = 0; size_t total_size_read = 0; tmp_buffer = (char *)malloc((size + 1) * sizeof(char)); if (tmp_buffer == NULL) return -1; for (;;) { size_read = fread(tmp_buffer, sizeof(char), size, stream); if ((size_read <= 0) || (ferror(stream))) return -1; total_size_read += size_read; buffer2 = (char *)realloc(*buffer, (total_size_read + 1) * sizeof(char)); if (buffer2 == NULL) return -1; *buffer = buffer2; memcpy(*buffer + total_size_read - size_read, tmp_buffer, size_read * sizeof(char)); for(i = 0; i < size_read; i++) { if (tmp_buffer[i] == '\n') { break; } } if (i < size_read) { /* On a récupéré une ligne */ *(*buffer + total_size_read - size_read + i + 1) = '\0'; fseek(stream, i - size_read + 1, SEEK_CUR); free(tmp_buffer); return total_size_read - size_read + i + 1; } if (feof(stream)) { free(tmp_buffer); return total_size_read; } } }