aboutsummaryrefslogblamecommitdiffstats
path: root/configfile.c
blob: d98989c4312aed59e9a6a45aee3b603c8ac1c48f (plain) (tree)
1
2
3
4
5
6
7
8
9
10
11
12











                                               
                             

                         
                        
                             
                                






                                     
                              


              
                                                           


                 
                                                                                 



                              
                                 
                                     
                                                        





                                          
                                          
                                    

                                                  

                                 
                                                   


                                    
                                    



                           
                        
















                                                                  
                                                                           





                                
/* configfile.c: parsing of config files
 *
 * Copyright (C) 2008 Lars Hjemli
 *
 * Licensed under GNU General Public License v2
 *   (see COPYING for full license text)
 */

#include <ctype.h>
#include <stdio.h>
#include "configfile.h"

static int next_char(FILE *f)
{
	int c = fgetc(f);
	if (c == '\r') {
		c = fgetc(f);
		if (c != '\n') {
			ungetc(c, f);
			c = '\r';
		}
	}
	return c;
}

static void skip_line(FILE *f)
{
	int c;

	while ((c = next_char(f)) && c != '\n' && c != EOF)
		;
}

static int read_config_line(FILE *f, char *line, const char **value, int bufsize)
{
	int i = 0, isname = 0;

	*value = NULL;
	while (i < bufsize - 1) {
		int c = next_char(f);
		if (!isname && (c == '#' || c == ';')) {
			skip_line(f);
			continue;
		}
		if (!isname && isspace(c))
			continue;

		if (c == '=' && !*value) {
			line[i] = 0;
			*value = &line[i + 1];
		} else if (c == '\n' && !isname) {
			i = 0;
			continue;
		} else if (c == '\n' || c == EOF) {
			line[i] = 0;
			break;
		} else {
			line[i] = c;
		}
		isname = 1;
		i++;
	}
	line[i + 1] = 0;
	return i;
}

int parse_configfile(const char *filename, configfile_value_fn fn)
{
	static int nesting;
	int len;
	char line[256];
	const char *value;
	FILE *f;

	/* cancel deeply nested include-commands */
	if (nesting > 8)
		return -1;
	if (!(f = fopen(filename, "r")))
		return -1;
	nesting++;
	while ((len = read_config_line(f, line, &value, sizeof(line))) > 0)
		fn(line, value);
	nesting--;
	fclose(f);
	return 0;
}