--- psiconv/trunk/lib/psiconv/configuration.c 2003/12/02 19:47:47 176 +++ psiconv/trunk/lib/psiconv/configuration.c 2003/12/13 23:26:37 180 @@ -20,9 +20,14 @@ #include "config.h" #include "error.h" #include "compat.h" + #include #include #include +#include +#include +#include +#include #include "configuration.h" @@ -33,29 +38,217 @@ #ifndef CONFIGURATION_SEARCH_PATH #define CONFIGURATION_SEARCH_PATH "/etc/psiconv.conf:~/.psiconv.conf" #endif -struct psiconv_config_s default_config = +static struct psiconv_config_s default_config = { PSICONV_VERB_WARN, 2, 0,0,0,psiconv_bool_false,NULL }; -psiconv_config psiconv_config_read(const char *extra_config_file) +static void psiconv_config_parse_statement(const char *filename, + int linenr, + const char *var, int value, + psiconv_config *config); + +static void psiconv_config_parse_line(const char *filename, int linenr, + const char *line, psiconv_config *config); + +static void psiconv_config_parse_file(const char *filename, + psiconv_config *config); + +psiconv_config psiconv_config_default(void) { - psiconv_config config; - if (!(config = malloc(sizeof(*config)))) - return NULL; - memcpy(config,&default_config,sizeof(*config)); - return config; + psiconv_config result; + result = malloc(sizeof(*result)); + *result = default_config; + return result; +} + +void psiconv_config_parse_statement(const char *filename, + int linenr, + const char *var, int value, + psiconv_config *config) +{ + if (!(strcasecmp(var,"verbosity"))) { + if ((value >= 1) && (value <= 4)) + (*config)->verbosity = value; + else + psiconv_fatal(*config,0,0,"Configuration file %s, line %d: " + "Verbosity should be between 1 and 4",filename,linenr); + } else if (!(strcasecmp(var,"color"))) { + if ((value == 0) || (value == 1)) + (*config)->color = value; + else + psiconv_fatal(*config,0,0,"Configuration file %s, line %d: " + "Color should be 0 or 1",filename,linenr); + } else if (!(strcasecmp(var,"colordepth"))) { + if ((value > 0) && (value <= 32)) + (*config)->colordepth = value; + else + psiconv_fatal(*config,0,0,"Configuration file %s, line %d: " + "ColorDepth should be between 1 and 32",filename,linenr); + } else if (!(strcasecmp(var,"redbits"))) { + if ((value >= 0) && (value <= 32)) + (*config)->redbits = value; + else + psiconv_fatal(*config,0,0,"Configuration file %s, line %d: " + "RedBits should be between 1 and 32 or 0",filename,linenr); + } else if (!(strcasecmp(var,"greenbits"))) { + if ((value >= 0) && (value <= 32)) + (*config)->greenbits = value; + else + psiconv_fatal(*config,0,0,"Configuration file %s, line %d: " + "GreenBits should be between 1 and 32 or 0",filename,linenr); + } else if (!(strcasecmp(var,"bluebits"))) { + if ((value >= 0) && (value <= 32)) + (*config)->bluebits = value; + else + psiconv_fatal(*config,0,0,"Configuration file %s, line %d: " + "BlueBits should be between 1 and 32 or 0",filename,linenr); + } else { + psiconv_fatal(*config,0,0,"Configuration file %s, line %d: " + "Unknown variable %s",filename,linenr,var); + } + psiconv_debug(*config,0,0,"Configuration file %s, line %d: " + "Set variable %s to %d",filename,linenr,var,value); } -/*TO DO */ -#if 0 +void psiconv_config_parse_line(const char *filename, int linenr, + const char *line, psiconv_config *config) +{ + + int sovar,eovar,soval,eoval,eol; + char *var; + long val; + + psiconv_debug(*config,0,0,"Going to parse line %d: %s",linenr,line); + sovar = 0; + while (line[sovar] && (line[sovar] < 32)) + sovar ++; + if (!line[sovar] || line[sovar] == '#') + return; + eovar = sovar; + while (line[eovar] && (((line[eovar] >= 'A') && (line[eovar] <= 'Z')) || + ((line[eovar] >= 'a') && (line[eovar] <= 'z')))) + eovar ++; + if (sovar == eovar) + psiconv_fatal(*config,0,0,"Configuration file %s, line %d: " + "Syntax error (no variable found)",filename,linenr); + soval = eovar; + while (line[soval] && (line[soval] <= 32)) + soval ++; + if (line[soval] != '=') + psiconv_fatal(*config,0,0,"Configuration file %s, line %d: " + "Syntax error (no = token found)",filename,linenr); + soval ++; + while (line[soval] && (line[soval] <= 32)) + soval ++; + eoval = soval; + while (line[eoval] && ((line[eoval] >= '0') && (line[eovar] <= '9'))) + eoval ++; + if (eoval == soval) + psiconv_fatal(*config,0,0,"Configuration file %s, line %d: " + "Syntax error (no value found)",filename,linenr); + if (soval - eoval > 7) + psiconv_fatal(*config,0,0,"Configuration file %s, line %d: " + "Syntax error (value too large)",filename,linenr); + eol = eoval; + while (line[eol] && (line[eol] < 32)) + eol ++; + if (line[eol]) + psiconv_fatal(*config,0,0,"Configuration file %s, line %d: " + "Syntax error (trailing garbage)",filename,linenr); + + var = malloc(eovar - sovar + 1); + memcpy(var,line + sovar, eovar - sovar); + var[eovar-sovar] = 0; + + val = atol(line + soval); + + psiconv_config_parse_statement(filename,linenr,var,val,config); + free(var); +} -/* I hate string manipulation in C */ -psiconv_config_t psiconv_config_read(const char *extra_config_files) + +void psiconv_config_parse_file(const char *filename, psiconv_config *config) { - psiconv_config_t result = default_config; - char *path,pathptr; - int file; + int file,linenr; struct stat stat_buf; + off_t filesize,bytes_left,bytes_read,sol,eol; + char *filebuffer,*filebuffer_ptr; + + psiconv_progress(*config,0,0, + "Going to access configuration file %s",filename); + + /* Try to open the file; it may fail, if it does not exist for example */ + if ((file = open(filename,O_RDONLY)) == -1) + return; + + /* Read the contents of the file into filebuffer. This may fail */ + if (fstat(file,&stat_buf)) { + if (close(file)) + psiconv_fatal(*config,0,0,"Configuration file %s: " + "Couldn't close file",filename); + return; + } + + filesize = stat_buf.st_size; + if (!(filebuffer = malloc(filesize + 1))) + psiconv_fatal(*config,0,0,"Configuration file %s: " + "Out of memory error",filename); + filebuffer_ptr = filebuffer; + bytes_left = filesize; + bytes_read = 1; /* Dummy for the first time through the loop */ + while ((bytes_read > 0) && bytes_left) { + bytes_read = read(file,filebuffer_ptr,bytes_left); + if (bytes_read > 0) { + filebuffer_ptr += bytes_read; + bytes_left -= bytes_read; + } + } + + /* On NFS, the first read may fail and this is not fatal */ + if (bytes_left && (bytes_left != filesize)) { + psiconv_fatal(*config,0,0,"Configuration file %s: " + "Couldn't read file into memory",filename); + } + + if (close(file)) + psiconv_fatal(*config,0,0,"Configuration file %s: " + "Couldn't close file",filename); + + psiconv_progress(*config,0,0, + "Going to parse configuration file %s: ",filename); + /* Now we walk through the file to isolate lines */ + linenr = 0; + sol = 0; + + while (sol < filesize) { + linenr ++; + eol = sol; + while ((eol < filesize) && (filebuffer[eol] != 13) && + (filebuffer[eol] != 10) && (filebuffer[eol] != 0)) + eol ++; + + if ((eol < filesize) && (filebuffer[eol] == 0)) + psiconv_fatal(*config,0,0,"Configuration file %s, line %d: " + "Unexpected character \000 found",filename,linenr); + if ((eol < filesize + 1) && + (((filebuffer[eol] == 13) && (filebuffer[eol+1] == 10)) || + ((filebuffer[eol] == 10) && (filebuffer[eol+1] == 13)))) { + filebuffer[eol] = 0; + eol ++; + } + filebuffer[eol] = 0; + psiconv_config_parse_line(filename,linenr,filebuffer + sol,config); + sol = eol+1; + } + free(filebuffer); +} + +void psiconv_config_read(const char *extra_config_files, + psiconv_config *config) +{ + char *path,*pathptr,*filename,*filename_old; + const char *home; + int filename_len; /* Make path be the complete search path, colon separated */ if (extra_config_files && strlen(extra_config_files)) { @@ -63,53 +256,36 @@ strlen(extra_config_files) + 2); strcpy(path,CONFIGURATION_SEARCH_PATH); strcat(path,":"); - strcat(path,extra_config_files) + strcat(path,extra_config_files); } else { - path = strdup(CONFIGURATION_SEARCH_PATH) + path = strdup(CONFIGURATION_SEARCH_PATH); } pathptr = path; while (strlen(pathptr)) { /* Isolate the next filename */ - filename_len = (path - index(':',path)) || strlen(path); + filename_len = (index(pathptr,':')?(index(pathptr,':') - pathptr): + strlen(pathptr)); filename = malloc(filename_len + 1); - filename = strncpy(filename,path,filename_len); - filename[filename_len + 1] = 0; + filename = strncpy(filename,pathptr,filename_len); + filename[filename_len] = 0; pathptr += filename_len; if (strlen(pathptr)) pathptr ++; - - /* Try to open the file; it may fail, if it does not exist for example */ - if ((file = open(filename,O_RDONLY)) == -1) - continue; - - /* Read the contents of the file into filebuffer */ - if (!fstat(file,&stat_buf)) - continue; - filesize = stat_buf.off_t; - filebuffer = malloc(filesize + 1); - filebuffer_ptr = filebuffer; - bytes_left = filesize; - bytes_read = 1 /* Dummy for the first time through the loop */ - while ((bytes_read > 0) && bytes_left) { - bytes_read = read(file,filebuffer_ptr,bytes_left); - if (bytes_read == -1) { - filebuffer_ptr += bytes_read; - bytes_left -= bytes_read; + + /* Do ~ substitution */ + if ((filename[0] == '~') && ((filename[1] == '/') || filename[1] == 0)) { + home = getenv("HOME"); + if (home) { + filename_old = filename; + filename = malloc(strlen(filename_old) + strlen(home)); + strcpy(filename,home); + strcpy(filename + strlen(filename),filename_old+1); + free(filename_old); } } - if (bytes_left) - continue; - - /* Try to parse the filebuffer */ - filebuffer_ptr = file_buffer; - bytes_left = filesize; - while (bytes_left) { - /* Parse a line */ - line_length = index('' - + + psiconv_config_parse_file(filename,config); + free(filename); } } - -#endif -