/* * newsl_config.c * * Configuration load/save for newslettersan * * Author: Dario Rodriguez dario@softhome.net * This program is licensed under the terms of the Affero GPL v1+ */ #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #include <sys/types.h> #include <sys/stat.h> #include "loglib.h" #include "newsl_config.h" #define MAXLINESIZE 2048 #define LINESBLOCK 32 typedef enum esection { section_none=0, section_general } esection; newslconfig * newslconfig_init(char *configfile, char *deflogfile, char *defrootdir) { newslconfig *config; FILE *f; char line[MAXLINESIZE]; int len; char *ptr,*sep,*value; esection section; int lineno; char **configvalue; if((f=fopen(configfile,"r"))==NULL) return(NULL); if((config=malloc(sizeof(newslconfig)))==NULL) { fclose(f),f=NULL; return(NULL); } memset(config,0,sizeof(newslconfig)); section=section_none; lineno=0; while(fgets(line,sizeof(line),f)!=NULL) { lineno++; line[sizeof(line)-1]='\0'; /* trim line */ for(ptr=line;*ptr!='\0' && strchr("\t ",*ptr)!=NULL;ptr++) ; len=strlen(line); while(len>0 && strchr("\n\t ",line[len-1])!=NULL) line[len-1]='\0',len--; for(ptr=line;*ptr!='\0' && strchr("\t ",*ptr)!=NULL;ptr++) ; len=strlen(ptr); /* ignore empty lines and comments */ if(*ptr=='\0' || strchr("#;",*ptr)!=NULL) continue; /* parse line */ if(*ptr=='[' && ptr[len-1]==']') { /* section */ if(strcmp(ptr,"[general]")==0) { section=section_general; } else { log_write("CONF","%s:%i: unknown section name \"%s\"\n",configfile,lineno,ptr); section=section_none; } continue; } else if((sep=strchr(ptr,'='))!=NULL) { *sep='\0'; value=sep+1; /* trim key */ while(sep>ptr && strchr(" \t",sep[-1])!=NULL) { sep--; *sep='\0'; } /* trim value */ while(*value!='\0' && strchr(" \t",*value)!=NULL) value++; /* sanity check */ if(*value=='\0') { log_write("CONF","%s:%i: ignoring key without value; key:\"%s\"\n",configfile,lineno,ptr); continue; } /* assign value */ if(section==section_none) { log_write("CONF","%s:%i: ignoring key-value pair in unknown section; key:\"%s\"\n",configfile,lineno,ptr); continue; } /* identify key-value pair */ if(section==section_general) { if(strcmp(ptr,"logfile")==0) { configvalue=&(config->logfile); } else if(strcmp(ptr,"rootdir")==0) { configvalue=&(config->rootdir); } else { log_write("CONF","%s:%i: unknown key, ignoring key-value pair; key:\"%s\"\n",configfile,lineno,ptr); continue; } } else continue; /* store value */ if(*configvalue!=NULL) { log_write("CONF","%s:%i: duplicate key, ignoring key-value pair; key:\"%s\"\n",configfile,lineno,ptr); continue; } if((*configvalue=strdup(value))==NULL) { fclose(f),f=NULL; newslconfig_free(config),config=NULL; return(NULL); /* insufficient memory */ } continue; } else { log_write("CONF","%s:%i: malformed line, ignoring; contents:\"%s\"\n",configfile,lineno,ptr); continue; } } fclose(f),f=NULL; if((config->logfile==NULL && (config->logfile=strdup(deflogfile))==NULL) || (config->rootdir==NULL && (config->rootdir=strdup(defrootdir))==NULL)) { newslconfig_free(config),config=NULL; return(NULL); } return(config); } void newslconfig_free(newslconfig *config) { if(config==NULL) return; if(config->logfile!=NULL) free(config->logfile),config->logfile=NULL; if(config->rootdir!=NULL) free(config->rootdir),config->rootdir=NULL; free(config),config=NULL; return; } int newslconfig_exists(char *configfile) { struct stat st; if(stat(configfile,&st)!=0) return(-1); return(0); } int newslconfig_write(char *configfile,char *logfile,char *rootdir) { FILE *f; if((f=fopen(configfile,"w"))==NULL) return(-1); fprintf(f,"; newslettersan config file\n"); fprintf(f,"[general]\n"); fprintf(f,"logfile=%s\n",(logfile!=NULL)?logfile:"newslettersan.log"); fprintf(f,"rootdir=%s\n",(rootdir!=NULL)?rootdir:"subscribe"); return(0); }