diff options
| author | Lars-Dominik Braun <lars@6xq.net> | 2015-09-25 17:44:58 +0200 | 
|---|---|---|
| committer | Lars-Dominik Braun <lars@6xq.net> | 2015-09-25 17:52:33 +0200 | 
| commit | 9dbd0f308b10f6a2982e72f25b0d26c951f5e87f (patch) | |
| tree | 419e6f5d29449478ea869298c94fae66f6f458e1 /src | |
| parent | 77ffe368e9b5045a801360c563623d5bc1c78771 (diff) | |
| download | pianobar-9dbd0f308b10f6a2982e72f25b0d26c951f5e87f.tar.gz pianobar-9dbd0f308b10f6a2982e72f25b0d26c951f5e87f.tar.bz2 pianobar-9dbd0f308b10f6a2982e72f25b0d26c951f5e87f.zip | |
settings: Fix config file parser
scanf’s %s matches non-whitespace characters only and thus ‘# foo = bar’
is parsed as ‘foo’, ‘bar’ and not ‘# foo’, ‘bar’ (as expected). Thus
comments did not work if they a) started with a valid key and b) had a
space between hash-sign and key.
Fixes issue #526.
Diffstat (limited to 'src')
| -rw-r--r-- | src/settings.c | 67 | 
1 files changed, 60 insertions, 7 deletions
| diff --git a/src/settings.c b/src/settings.c index 11a2982..f98874c 100644 --- a/src/settings.c +++ b/src/settings.c @@ -1,5 +1,5 @@  /* -Copyright (c) 2008-2012 +Copyright (c) 2008-2015  	Lars-Dominik Braun <lars@6xq.net>  Permission is hereby granted, free of charge, to any person obtaining a copy @@ -33,11 +33,13 @@ THE SOFTWARE.  #include <sys/types.h>  #include <pwd.h>  #include <unistd.h> +#include <ctype.h>  #include <piano.h>  #include "settings.h"  #include "config.h" +#include "ui.h"  #include "ui_dispatch.h"  #define streq(a, b) (strcmp (a, b) == 0) @@ -197,8 +199,10 @@ void BarSettingsRead (BarSettings_t *settings) {  	/* read config files */  	for (size_t j = 0; j < sizeof (configfiles) / sizeof (*configfiles); j++) {  		static const char *formatMsgPrefix = "format_msg_"; -		char key[256], val[256];  		FILE *configfd; +		/* getline allocates these on the first run */ +		char *line = NULL; +		size_t lineLen = 0, lineNum = 0;  		char * const path = BarGetXdgConfigDir (configfiles[j]);  		assert (path != NULL); @@ -208,14 +212,59 @@ void BarSettingsRead (BarSettings_t *settings) {  		}  		while (1) { -			char lwhite, rwhite; -			int scanRet = fscanf (configfd, "%255s%c=%c%255[^\n]", key, &lwhite, &rwhite, val); -			if (scanRet == EOF) { +			++lineNum; +			ssize_t ret = getline (&line, &lineLen, configfd); +			if (ret == -1) { +				/* EOF or error */  				break; -			} else if (scanRet != 4 || lwhite != ' ' || rwhite != ' ') { -				/* invalid config line */ +			} +			/* parse lines that match "^\s*(.*?)\s?=\s?(.*)$". Windows and Unix +			 * line terminators are supported. */ +			char *key = line; + +			/* skip leading spaces */ +			while (isspace ((unsigned char) key[0])) { +				++key; +			} + +			/* skip comments */ +			if (key[0] == '#') {  				continue;  			} + +			/* search for delimiter and split key-value pair */ +			char *val = strchr (line, '='); +			if (val == NULL) { +				/* no warning for empty lines */ +				if (key[0] != '\0') { +					BarUiMsg (settings, MSG_INFO, +							"Invalid line at %s:%zu\n", path, lineNum); +				} +				/* invalid line */ +				continue; +			} +			*val = '\0'; +			++val; + +			/* drop spaces at the end */ +			char *keyend = &key[strlen (key)-1]; +			while (keyend >= key && isspace ((unsigned char) *keyend)) { +				*keyend = '\0'; +				--keyend; +			} + +			/* strip at most one space, legacy cruft, required for values with +			 * leading spaces like love_icon */ +			if (isspace ((unsigned char) val[0])) { +				++val; +			} +			/* drop trailing cr/lf */ +			char *valend = &val[strlen (val)-1]; +			while (valend >= val && (*valend == '\r' || *valend == '\n')) { +				*valend = '\0'; +				--valend; +			} +  			if (streq ("control_proxy", key)) {  				settings->controlProxy = strdup (val);  			} else if (streq ("proxy", key)) { @@ -350,11 +399,15 @@ void BarSettingsRead (BarSettings_t *settings) {  						break;  					}  				} +			} else { +				BarUiMsg (settings, MSG_INFO, +						"Unrecognized key %s at %s:%zu\n", key, path, lineNum);  			}  		}  		fclose (configfd);  		free (path); +		free (line);  	}  	/* check environment variable if proxy is not set explicitly */ | 
