summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/settings.c65
1 files changed, 59 insertions, 6 deletions
diff --git a/src/settings.c b/src/settings.c
index 36245de..b15053d 100644
--- a/src/settings.c
+++ b/src/settings.c
@@ -27,11 +27,13 @@ THE SOFTWARE.
#include "settings.h"
#include "config.h"
+#include "ui.h"
#include "ui_dispatch.h"
#include <stdlib.h>
#include <assert.h>
#include <memory.h>
#include <string.h>
+#include <ctype.h>
#define PACKAGE_CONFIG PACKAGE ".cfg"
#define PACKAGE_STATE PACKAGE ".state"
@@ -214,8 +216,9 @@ 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;
+ char line[512];
+ size_t lineNum = 0;
char * const path = BarGetXdgConfigDir (configfiles[j]);
assert (path != NULL);
@@ -225,14 +228,64 @@ 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;
+ char * const ret = fgets (line, sizeof (line), configfd);
+ if (ret == NULL) {
+ /* EOF or error */
break;
- } else if (scanRet != 4 || lwhite != ' ' || rwhite != ' ') {
- /* invalid config line */
+ }
+ if (strchr (line, '\n') == NULL && !feof (configfd)) {
+ BarUiMsg (settings, MSG_INFO, "Line %s:%zu too long, "
+ "ignoring\n", path, lineNum);
+ continue;
+ }
+ /* 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)) {