/* Attempt to read and parse a config file. Return a handle to the config file * structure, or NULL if errors were encountered. */ struct configFile *readConfigFile (char *filename) { /* TODO: Attempt to read from homedir, /etc, etc if file not found in cwd. */ struct stat filestats; struct configFile *cfg; int fileHandle, bytesRead; if (stat (filename, &filestats) != 0) { perror ("ReadConfigFile: stat"); return NULL; } if (filestats.st_size > MAXIMUM_SANE_FILESIZE) return NULL; cfg = malloc (sizeof (struct configFile)); cfg->bbdg = malloc (filestats.st_size); cfg->sections = hashConstructTable (31); /* Some prime, just for laughs */ if ( (fileHandle=open (filename, O_RDONLY)) == -1) { perror ("ReadConfigFile: open"); return NULL; } if ( (bytesRead=read (fileHandle, cfg->bbdg, filestats.st_size)) != filestats.st_size) { perror ("ReadConfigFile: read"); return NULL; } close (fileHandle); cfg->bbdgSize=filestats.st_size; return _cfgParseConfigFile (cfg); }
struct configFile *readPlayList(char *filename) { /* TODO: Attempt to read from homedir, /etc, etc if file not found in cwd. */ struct stat filestats; struct configFile *cfg; int /* fileHandle ,*/ bytesRead; FILE *fin; if (stat(filename, &filestats) != 0) { /*perror ("ReadConfigFile: stat"); */ return NULL; } if (filestats.st_size > MAXIMUM_SANE_FILESIZE) return NULL; #ifdef _GLOBAL_CFG if(gplist == NULL) gplist = malloc(sizeof(struct configFile)); else return gplist; cfg = gplist; #else cfg = (struct configFile *)malloc(sizeof(struct configFile)); #endif cfg->bbdg = (unsigned char*)malloc(filestats.st_size); cfg->sections = hashConstructTable(31); if ((fin = fopen(filename, "r")) == NULL) { printf("can not open %s\n", filename); return NULL; } if ((bytesRead = fread(cfg->bbdg, 1, filestats.st_size, fin)) != filestats.st_size) { printf("read %s error\n", filename); return NULL; } fclose(fin); cfg->bbdgSize = filestats.st_size; return _cfgParseConfigFile(cfg); }
/* Small FSM. States indicate what the machine is looking for *next*, * so eg _cfgKEYSTART means "looking for the token that indicates the start * of a key" */ struct configFile *_cfgParseConfigFile (struct configFile *cfg) { char *currentSectionString="DEFAULT"; char *currentStringStart=NULL; char *currentKey=NULL; unsigned int filePos=0, state=_cfgKEYSTART; hash_table *tempHash; /* Create the default section. */ tempHash=hashConstructTable (31); hashInsert (currentSectionString, tempHash, cfg->sections); while (filePos < cfg->bbdgSize) { switch (state) { case _cfgKEYSTART: if (cfg->bbdg[filePos]=='[') { filePos++; currentStringStart=(char *) &(cfg->bbdg[filePos]); state=_cfgSECTIONEND; break; } if (isCommentStart(cfg->bbdg[filePos])) { filePos++; state=_cfgCOMMENTEND; break; } if ( !isspace (cfg->bbdg[filePos]) ) { currentStringStart=(char *) &(cfg->bbdg[filePos]); state=_cfgKEYEND; } else { filePos ++; } break; case _cfgCOMMENTEND: if (cfg->bbdg[filePos]=='\n') { state=_cfgKEYSTART; } filePos++; break; case _cfgSECTIONEND: if (cfg->bbdg[filePos]==']') { cfg->bbdg[filePos]='\0'; currentSectionString=currentStringStart; state=_cfgKEYSTART; } filePos++; break; case _cfgKEYEND: if (isspace (cfg->bbdg[filePos]) || isKeyValSep(cfg->bbdg[filePos])) { if (isKeyValSep(cfg->bbdg[filePos])) { cfg->bbdg[filePos]='\0'; } else { cfg->bbdg[filePos]='\0'; filePos++; } currentKey=currentStringStart; state=_cfgCOLON; } else { //Do this in search routine instead (with strcasecmp) //cfg->bbdg[filePos] = tolower(cfg->bbdg[filePos]); filePos++; } break; case _cfgCOLON: if (isKeyValSep(cfg->bbdg[filePos]) || cfg->bbdg[filePos]=='\0') { state=_cfgVALSTART; } filePos++; break; case _cfgVALSTART: if (!myisblank(cfg->bbdg[filePos])) { currentStringStart=(char *) &(cfg->bbdg[filePos]); state=_cfgVALEND; } else { filePos ++; } break; case _cfgVALEND: if (cfg->bbdg[filePos]=='\n' || isCommentStart(cfg->bbdg[filePos])) { /* First see if the current section exists. */ tempHash=hashLookup (currentSectionString, cfg->sections); if (tempHash==NULL) { tempHash=hashConstructTable (31); hashInsert (currentSectionString, tempHash, cfg->sections); } /* Now stick it in the table. */ if (isCommentStart(cfg->bbdg[filePos])) { cfg->bbdg[filePos]='\0'; hashInsert (currentKey, currentStringStart, tempHash); state=_cfgCOMMENTEND; } else { cfg->bbdg[filePos]='\0'; hashInsert (currentKey, currentStringStart, tempHash); state=_cfgKEYSTART; } } filePos++; break; } } return cfg; }