/* Copyright (c) 2002-2018 Dovecot authors, see the included COPYING file */
#include "lib.h"
#include "str.h"
#include "istream.h"
#include "strescape.h"
#include "settings.h"
#include <stdio.h>
#include <fcntl.h>
#ifdef HAVE_GLOB_H
# include <glob.h>
#endif
#ifndef GLOB_BRACE
# define GLOB_BRACE 0
#endif
struct input_stack {
const char *path;
unsigned int linenum;
};
{
else
return NULL;
}
{
int num;
return NULL;
}
const char *
{
case SET_STR:
return NULL;
case SET_INT:
/* use %i so we can handle eg. 0600
as octal value with umasks */
case SET_BOOL:
}
}
}
}
static const char *
{
const char *p;
if (*path == '/')
return path;
if (p == NULL)
return path;
}
bool ignore_errors, const char **error_r)
{
int fd;
break;
}
return -1;
}
if (ignore_errors)
return 0;
path);
return -1;
}
return 0;
}
static int
bool ignore_errors, const char **error_r)
{
#ifdef HAVE_GLOB
unsigned int i;
case 0:
break;
case GLOB_NOSPACE:
*error_r = "glob() failed: Not enough memory";
return -1;
case GLOB_ABORTED:
*error_r = "glob() failed: Read error";
return -1;
case GLOB_NOMATCH:
if (ignore_errors)
return 0;
*error_r = "No matches";
return -1;
default:
*error_r = "glob() failed: Unknown error";
return -1;
}
/* iterate through the different files matching the globbing */
ignore_errors, error_r) < 0)
return -1;
}
return 0;
#else
#endif
}
const char **error_r)
{
/* pretty horrible code, but v2.0 will have this rewritten anyway.. */
if (fd < 0) {
"Can't open configuration file %s: %m", path);
return FALSE;
}
skip = 0;
next_section = NULL;
} else {
skip = 1;
}
/* @UNSAFE: line is modified */
/* skip whitespace */
line++;
/* ignore comments or empty lines */
continue;
/* strip away comments. pretty kludgy way really.. */
for (p = line; *p != '\0'; p++) {
if (*p == '\'' || *p == '"') {
quote = *p;
for (p++; *p != quote && *p != '\0'; p++) {
if (*p == '\\' && p[1] != '\0')
p++;
}
if (*p == '\0')
break;
} else if (*p == '#') {
if (!IS_WHITE(p[-1])) {
i_warning("Configuration file %s line %u: "
"Ambiguous '#' character in line, treating it as comment. "
"Add a space before it to remove this warning.",
}
*p = '\0';
break;
}
}
/* remove whitespace from end of line */
len--;
/* continues in next line */
len--;
len--;
continue;
}
}
/* a) key = value
b) section_type [section_name] {
c) } */
line++;
*line++ = '\0';
}
&input,
&errormsg) == 0)
goto prevfile;
} else if (*line == '=') {
/* a) */
*line++ = '\0';
if (len > 0 &&
}
/* b) + errors */
if (*line == '{')
name = "";
else {
line++;
if (*line != '\0') {
*line++ = '\0';
line++;
}
}
if (*line != '{')
errormsg = "Expecting '='";
else {
sections++;
if (next_section != NULL &&
if (*section == '\0') {
skip = 0;
next_section = NULL;
} else {
section++;
}
}
if (skip > 0)
skip++;
else {
&errormsg);
last_section_line != 0) {
}
}
}
} else {
/* c) */
if (sections == 0)
errormsg = "Unexpected '}'";
else {
if (skip > 0)
skip--;
else {
&errormsg);
if (root_section == sections &&
/* we found the section,
now quit */
break;
}
}
sections--;
}
}
"Error in configuration file %s line %d: %s",
break;
}
str_truncate(full_line, 0);
}
goto prevfile;
}