summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org>2018-02-17 23:06:10 +0200
committerSergey Poznyakoff <gray@gnu.org>2018-02-17 23:23:52 +0200
commit1d89e35c9305cd235a0d645dae4212db14c0baf1 (patch)
treeb5f317d6cbea610762c3345df75c3af8aae63e71 /src
parentc93a6c17a2af32dd15c09adb926088d353ff800d (diff)
downloadfileserv-1d89e35c9305cd235a0d645dae4212db14c0baf1.tar.gz
fileserv-1d89e35c9305cd235a0d645dae4212db14c0baf1.tar.bz2
Don't bail out on out-of-memory errors in daemon mode.
* src/catfile.c: Use malloc instead of xmalloc. * src/config.c (dirconfig): Change signature. Return FSE_ constant. (config_init): Use calloc instead of xcalloc. (set_index_files,set_hidden_files): Use nrealloc instead of xnrealloc. (all setters): Use string_copy instead of xstrdup. (config_parse): Return meaningful FSE_ constant. * src/fileserv.c (fse_to_http_code): New function. (find_index_files,get_file_resp): Handle out-of-memory errors. * src/fileserv.h (fileserv_error): New enum. (alloc_warn,nrealloc): New protos. (dirconfig): Change prototype and return value. * src/mem.c (alloc_warn) (nrealloc): New functions.
Diffstat (limited to 'src')
-rw-r--r--src/catfile.c25
-rw-r--r--src/config.c240
-rw-r--r--src/dirls.h6
-rw-r--r--src/fileserv.c41
-rw-r--r--src/fileserv.h12
-rw-r--r--src/idx.c61
-rw-r--r--src/mem.c18
7 files changed, 269 insertions, 134 deletions
diff --git a/src/catfile.c b/src/catfile.c
index 929e15e..37aee62 100644
--- a/src/catfile.c
+++ b/src/catfile.c
@@ -6,7 +6,7 @@ char *
catfile_n(char const *dir, size_t len, char const *file)
{
size_t flen;
- char *res, *p;
+ char *res;
while (len > 0 && dir[len-1] == '/')
len--;
@@ -15,15 +15,20 @@ catfile_n(char const *dir, size_t len, char const *file)
flen = strlen(file);
while (flen && file[flen-1] == '/')
--flen;
- res = xmalloc(len + flen + 2);
- memcpy(res, dir, len);
- p = res + len;
- if (flen) {
- *p++ = '/';
- memcpy(p, file, flen);
- p += flen;
- }
- *p = 0;
+ res = malloc(len + flen + 2);
+ if (res) {
+ char *p;
+
+ memcpy(res, dir, len);
+ p = res + len;
+ if (flen) {
+ *p++ = '/';
+ memcpy(p, file, flen);
+ p += flen;
+ }
+ *p = 0;
+ } else
+ alloc_warn();
return res;
}
diff --git a/src/config.c b/src/config.c
index adcc677..7e50819 100644
--- a/src/config.c
+++ b/src/config.c
@@ -22,6 +22,8 @@ readconfig(void)
{
if (!config_file) {
config_file = catfile(SYSCONFDIR, DEFAULT_CONF_FILE);
+ if (!config_file)
+ xmalloc_fail();
if (access(config_file, F_OK)) {
if (verbose)
error("warning: no configuration file %s",
@@ -32,32 +34,55 @@ readconfig(void)
}
}
global_config = config_init();
+ if (!global_config)
+ exit(1);
if (config_parse(config_file, global_config, CTXGLOB))
exit(1);
}
-CONFIG *
-dirconfig(char const *path, size_t prefix_len)
+int
+dirconfig(char const *path, size_t prefix_len, CONFIG **ret)
{
- CONFIG *conf = config_clone(global_config);
+ CONFIG *conf;
char *tmp = NULL;
struct stat st;
-
+ int rc = FSE_SUCCESS;
+
if (stat(path, &st) == 0 && S_ISDIR(st.st_mode)) {
tmp = catfile(path, ".");
+ if (!tmp)
+ return FSE_ERROR;
path = tmp;
}
- while (path[prefix_len]) {
- char *name = catfile_n(path, prefix_len, dotfile);
- config_parse(name, conf, CTXDIR);
- free(name);
- if (path[prefix_len] == '/')
- prefix_len++;
- while (path[prefix_len] && path[prefix_len] != '/')
- prefix_len++;
- }
+
+ conf = config_clone(global_config);
+ if (conf) {
+ while (path[prefix_len]) {
+ char *name = catfile_n(path, prefix_len, dotfile);
+ if (!name) {
+ rc = FSE_ERROR;
+ break;
+ }
+ if (access(name, F_OK) == 0) {
+ rc = config_parse(name, conf, CTXDIR);
+ free(name);
+ if (rc)
+ break;
+ }
+ if (path[prefix_len] == '/')
+ prefix_len++;
+ while (path[prefix_len] && path[prefix_len] != '/')
+ prefix_len++;
+ }
+ } else
+ rc = FSE_ERROR;
+
free(tmp);
- return conf;
+ if (rc == FSE_SUCCESS)
+ *ret = conf;
+ else
+ config_free(conf);
+ return rc;
}
static void
@@ -89,8 +114,11 @@ hidden_files_free(CONFIG *conf)
CONFIG *
config_init(void)
{
- CONFIG *p = xcalloc(1, sizeof(*p));
- p->list_unreadable = 1;
+ CONFIG *p = calloc(1, sizeof(*p));
+ if (p)
+ p->list_unreadable = 1;
+ else
+ alloc_warn();
return p;
}
@@ -99,7 +127,9 @@ config_clone(CONFIG const *source)
{
size_t i;
CONFIG *p = config_init();
-
+
+ if (!p)
+ return NULL;
if (!source)
return p;
p->follow = source->follow;
@@ -163,17 +193,28 @@ static int
bad_argc(const char *file, int line, char const *id)
{
error("%s:%d: bad number of arguments to '%s'", file, line, id);
- return 1;
+ return FSE_SYNTAX;
}
static int
not_a_bool(const char *file, int line)
{
error("%s:%d: invalid boolean value", file, line);
- return 1;
+ return FSE_SYNTAX;
}
static int
+string_copy(char **dst, char const *src)
+{
+ *dst = strdup(src);
+ if (!*dst) {
+ alloc_warn();
+ return FSE_ERROR;
+ }
+ return FSE_SUCCESS;
+}
+
+static int
set_follow(size_t argc, char **argv, CONFIG *conf,
char const *file, int line)
{
@@ -184,7 +225,7 @@ set_follow(size_t argc, char **argv, CONFIG *conf,
if (n == -1)
return not_a_bool(file, line);
conf->follow = n;
- return 0;
+ return FSE_SUCCESS;
}
static int
@@ -198,7 +239,7 @@ set_listing(size_t argc, char **argv, CONFIG *conf,
if (n == -1)
return not_a_bool(file, line);
conf->listing = n;
- return 0;
+ return FSE_SUCCESS;
}
static int
@@ -212,7 +253,7 @@ set_list_unreadable(size_t argc, char **argv, CONFIG *conf,
if (n == -1)
return not_a_bool(file, line);
conf->list_unreadable = n;
- return 0;
+ return FSE_SUCCESS;
}
static int
@@ -220,6 +261,7 @@ set_index_files(size_t argc, char **argv, CONFIG *conf,
char const *file, int line)
{
size_t i;
+ void *p;
if (argc < 2)
return bad_argc(file, line, argv[0]);
@@ -230,20 +272,28 @@ set_index_files(size_t argc, char **argv, CONFIG *conf,
else
index_files_free(conf);
- conf->index_files_v = xnrealloc(conf->index_files_v,
- argc + conf->index_files_c,
- sizeof(conf->index_files_v[0]));
+ p = nrealloc(conf->index_files_v,
+ argc + conf->index_files_c,
+ sizeof(conf->index_files_v[0]));
+ if (!p) {
+ alloc_warn();
+ return FSE_ERROR;
+ }
+ conf->index_files_v = p;
+
for (; argv[i]; i++)
conf->index_files_v[conf->index_files_c++] = xstrdup(argv[i]);
conf->index_files_v[conf->index_files_c] = NULL;
- return 0;
+ return FSE_SUCCESS;
}
static int
set_hidden_files(size_t argc, char **argv, CONFIG *conf,
- char const *file, int line)
+ char const *file, int line)
{
size_t i;
+ void *p;
+ int rc;
if (argc < 2)
return bad_argc(file, line, argv[0]);
@@ -254,9 +304,16 @@ set_hidden_files(size_t argc, char **argv, CONFIG *conf,
else
hidden_files_free(conf);
- conf->hidden_files_rxv = xnrealloc(conf->hidden_files_rxv,
- argc + conf->hidden_files_rxc,
- sizeof(conf->hidden_files_rxv[0]));
+ p = nrealloc(conf->hidden_files_rxv,
+ argc + conf->hidden_files_rxc,
+ sizeof(conf->hidden_files_rxv[0]));
+ if (!p) {
+ alloc_warn();
+ return FSE_ERROR;
+ }
+ conf->hidden_files_rxv = p;
+
+ rc = FSE_SUCCESS;
for (; argv[i]; i++) {
int ec;
ec = regcomp(&conf->hidden_files_rxv[conf->hidden_files_rxc],
@@ -267,10 +324,12 @@ set_hidden_files(size_t argc, char **argv, CONFIG *conf,
&conf->hidden_files_rxv[conf->hidden_files_rxc],
buf, sizeof buf);
error("%s: %s", argv[i], buf);
+ rc = FSE_ERROR;
+ break;
} else
conf->hidden_files_rxc++;
}
- return 0;
+ return rc;
}
static int
@@ -279,10 +338,9 @@ set_user(size_t argc, char **argv, CONFIG *conf,
{
if (argc != 2) {
error("%s:%d: expected exactly one argument", file, line);
- return 1;
+ return FSE_SYNTAX;
}
- user = xstrdup(argv[1]);
- return 0;
+ return string_copy(&user, argv[1]);
}
static int
@@ -291,10 +349,9 @@ set_group(size_t argc, char **argv, CONFIG *conf,
{
if (argc != 2) {
error("%s:%d: expected exactly one argument", file, line);
- return 1;
+ return FSE_SYNTAX;
}
- group = xstrdup(argv[1]);
- return 0;
+ return string_copy(&group, argv[1]);
}
static int
@@ -303,10 +360,9 @@ set_listen(size_t argc, char **argv, CONFIG *conf,
{
if (argc != 2) {
error("%s:%d: expected exactly one argument", file, line);
- return 1;
+ return FSE_SYNTAX;
}
- address = xstrdup(argv[1]);
- return 0;
+ return string_copy(&address, argv[1]);
}
static int
@@ -315,13 +371,13 @@ set_index_template(size_t argc, char **argv, CONFIG *conf,
{
if (argc != 2) {
error("%s:%d: expected exactly one argument", file, line);
- return 1;
+ return FSE_SYNTAX;
}
if (parse_template_file(argv[1])) {
error("%s:%d: invalid template", file, line);
- return 1;
+ return FSE_SYNTAX;
}
- return 0;
+ return FSE_SUCCESS;
}
static int
@@ -330,10 +386,9 @@ set_index_css(size_t argc, char **argv, CONFIG *conf,
{
if (argc != 2) {
error("%s:%d: expected exactly one argument", file, line);
- return 1;
+ return FSE_SYNTAX;
}
- index_css = xstrdup(argv[1]);
- return 0;
+ return string_copy(&index_css, argv[1]);
}
static int
@@ -342,10 +397,9 @@ set_dotfile(size_t argc, char **argv, CONFIG *conf,
{
if (argc != 2) {
error("%s:%d: expected exactly one argument", file, line);
- return 1;
+ return FSE_SYNTAX;
}
- dotfile = xstrdup(argv[1]);
- return 0;
+ return string_copy(&dotfile, argv[1]);
}
static int
@@ -354,10 +408,9 @@ set_forwarded_header(size_t argc, char **argv, CONFIG *conf,
{
if (argc != 2) {
error("%s:%d: expected exactly one argument", file, line);
- return 1;
+ return FSE_SYNTAX;
}
- forwarded_header = xstrdup(argv[1]);
- return 0;
+ return string_copy(&forwarded_header, argv[1]);
}
static int
@@ -366,10 +419,9 @@ set_temp_dir(size_t argc, char **argv, CONFIG *conf,
{
if (argc != 2) {
error("%s:%d: expected exactly one argument", file, line);
- return 1;
+ return FSE_SYNTAX;
}
- tmpdir = xstrdup(argv[1]);
- return 0;
+ return string_copy(&tmpdir, argv[1]);
}
static int
@@ -378,10 +430,9 @@ set_mime_magic_file(size_t argc, char **argv, CONFIG *conf,
{
if (argc != 2) {
error("%s:%d: expected exactly one argument", file, line);
- return 1;
+ return FSE_SYNTAX;
}
- mime_types_file = xstrdup(argv[1]);
- return 0;
+ return string_copy(&mime_types_file, argv[1]);
}
static int
@@ -392,11 +443,11 @@ set_trusted_proxy(size_t argc, char **argv, CONFIG *conf,
if (argc == 1) {
error("%s:%d: expected one or more arguments", file, line);
- return 1;
+ return FSE_SYNTAX;
}
for (i = 1; i < argc; i++)
trusted_ip_add(argv[i]);
- return 0;
+ return FSE_SUCCESS;
}
static int
@@ -405,10 +456,9 @@ set_pidfile(size_t argc, char **argv, CONFIG *conf,
{
if (argc != 2) {
error("%s:%d: expected exactly one argument", file, line);
- return 1;
+ return FSE_SYNTAX;
}
- pidfile = xstrdup(argv[1]);
- return 0;
+ return string_copy(&pidfile, argv[1]);
}
static int
@@ -417,13 +467,13 @@ set_syslog(size_t argc, char **argv, CONFIG *conf,
{
if (argc != 2) {
error("%s:%d: expected exactly one argument", file, line);
- return 1;
+ return FSE_SYNTAX;
}
if (set_log_facility(argv[1])) {
error("%s:%d: not a valid syslog facility", file, line);
- return 1;
+ return FSE_SYNTAX;
}
- return 0;
+ return FSE_SUCCESS;
}
static int
@@ -434,11 +484,11 @@ set_mapping(size_t argc, char **argv, CONFIG *conf,
if (argc == 1) {
error("%s:%d: expected one or more arguments", file, line);
- return 1;
+ return FSE_SYNTAX;
}
for (i = 1; i < argc; i++)
urimap_add(argv[i]);
- return 0;
+ return FSE_SUCCESS;
}
/* set-mime-icon icon [ALT=X] mime-type ...
@@ -453,7 +503,7 @@ set_mime_icon(size_t argc, char **argv, CONFIG *conf,
if (argc < 3) {
error("%s:%d: expected two or more arguments", file, line);
- return 1;
+ return FSE_SYNTAX;
}
icon = argv[1];
@@ -466,14 +516,14 @@ set_mime_icon(size_t argc, char **argv, CONFIG *conf,
if (i == argc) {
error("%s:%d: expected one or more mime types", file, line);
- return 1;
+ return FSE_SYNTAX;
}
for (; i < argc; i++)
add_icon_by_mime(argv[i], icon, alt);
- return 0;
+ return FSE_SUCCESS;
}
static int
@@ -486,7 +536,7 @@ set_name_icon(size_t argc, char **argv, CONFIG *conf,
if (argc < 3) {
error("%s:%d: expected two or more arguments", file, line);
- return 1;
+ return FSE_SYNTAX;
}
icon = argv[1];
@@ -499,14 +549,14 @@ set_name_icon(size_t argc, char **argv, CONFIG *conf,
if (i == argc) {
error("%s:%d: expected one or more mime types", file, line);
- return 1;
+ return FSE_SYNTAX;
}
for (; i < argc; i++)
add_icon_by_name(argv[i], icon, alt);
- return 0;
+ return FSE_SUCCESS;
}
static int
@@ -519,7 +569,7 @@ set_type_icon(size_t argc, char **argv, CONFIG *conf,
if (argc < 3) {
error("%s:%d: expected two or three arguments", file, line);
- return 1;
+ return FSE_SYNTAX;
}
icon = argv[1];
@@ -532,11 +582,11 @@ set_type_icon(size_t argc, char **argv, CONFIG *conf,
if (i == argc) {
error("%s:%d: expected file type", file, line);
- return 1;
+ return FSE_SYNTAX;
}
add_icon_by_type(argv[i], icon, alt);
- return 0;
+ return FSE_SUCCESS;
}
@@ -584,7 +634,28 @@ line_interpret(struct wordsplit const *ws,
conf, file, line);
}
error("%s:%d: unrecognized keyword", file, line);
- return 1;
+ return FSE_SYNTAX;
+}
+
+int
+wrdse_to_fse(int wse)
+{
+ switch (wse) {
+ case WRDSE_OK:
+ return FSE_SUCCESS;
+
+ case WRDSE_NOSPACE:
+ case WRDSE_USAGE:
+ return FSE_ERROR;
+
+ case WRDSE_USERERR:
+ /* FIXME: This one can map to any FSE_ code. In the
+ lack of more specific information, it is mapped to
+ syntax error */
+
+ default:
+ return FSE_SYNTAX;
+ }
}
int
@@ -602,7 +673,7 @@ config_parse(const char *file, CONFIG *conf, int ctx)
if (ctx == CTXGLOB || errno != ENOENT)
error("can't open file %s: %s", file,
strerror(errno));
- return 1;
+ return FSE_ERROR;
}
ws.ws_comment = "#";
@@ -619,30 +690,29 @@ config_parse(const char *file, CONFIG *conf, int ctx)
buf[--len] = 0;
else if (!feof(fp)) {
error("%s:%d: line too long", file, ln);
- err = 1;
+ err = FSE_SYNTAX;
break;
}
if (wordsplit(buf, &ws, wsflags)) {
error("%s:%d: %s", file, ln, wordsplit_strerror(&ws));
- err = 1;
+ err = wrdse_to_fse(ws.ws_errno);
break;
}
wsflags |= WRDSF_REUSE;
if (ws.ws_wordc == 0)
continue;
- if (line_interpret(&ws, conf, ctx, file, ln)) {
- err = 1;
+ err = line_interpret(&ws, conf, ctx, file, ln);
+ if (err)
break;
- }
}
if (wsflags & WRDSF_REUSE)
wordsplit_free(&ws);
if (ferror(fp)) {
- err = 1;
+ err = FSE_ERROR;
error("%s: %s", file, strerror(errno));
}
fclose(fp);
diff --git a/src/dirls.h b/src/dirls.h
index 0067bff..7ec2f3e 100644
--- a/src/dirls.h
+++ b/src/dirls.h
@@ -1,7 +1,7 @@
typedef struct dirlsent {
- char *name;
- struct stat st;
- char const *type;
+ char *name; /* File name */
+ struct stat st; /* Meta-data */
+ char const *type; /* Mime type */
STAILQ_ENTRY(dirlsent) next;
} DIRLSENT;
diff --git a/src/fileserv.c b/src/fileserv.c
index ae1599d..4bf6e8e 100644
--- a/src/fileserv.c
+++ b/src/fileserv.c
@@ -65,6 +65,21 @@ fileserv_panic(void *cls, const char *file, unsigned int line,
}
static inline int
+fse_to_http_code(int ec)
+{
+ switch (ec) {
+ case FSE_SUCCESS:
+ return MHD_HTTP_OK;
+ case FSE_SYNTAX:
+ case FSE_ACCESS:
+ return MHD_HTTP_FORBIDDEN;
+ case FSE_ERROR:
+ break;
+ }
+ return MHD_HTTP_INTERNAL_SERVER_ERROR;
+}
+
+static inline int
errno_to_http_code(int ec)
{
switch (ec) {
@@ -272,6 +287,10 @@ find_index_file(char const *dir, CONFIG *conf, char **index_file,
for (i = 0; conf->index_files_v[i]; i++) {
struct stat st;
cf = catfile(dir, conf->index_files_v[i]);
+ if (!cf) {
+ lasterr = errno;
+ break;
+ }
if (access(cf, F_OK) || lstat(cf, &st)) {
free(cf);
lasterr = errno;
@@ -372,7 +391,8 @@ get_file_resp(struct MHD_Connection *conn, char const *url, FILE_RESP *resp)
char const *host = MHD_lookup_connection_value(conn,
MHD_HEADER_KIND,
MHD_HTTP_HEADER_HOST);
-
+ int rc;
+
file_resp_init(resp);
if (!filename_is_valid(url))
@@ -383,11 +403,15 @@ get_file_resp(struct MHD_Connection *conn, char const *url, FILE_RESP *resp)
return MHD_HTTP_NOT_FOUND;
resp->file_name = catfile_n(map->dir, map->dir_len,
url + map->uri_len);
+ if (!resp->file_name)
+ return MHD_HTTP_INTERNAL_SERVER_ERROR;
if (lstat(resp->file_name, &resp->st))
return errno_to_http_code(errno);
- resp->conf = dirconfig(resp->file_name, map->dir_len);
-
+ rc = dirconfig(resp->file_name, map->dir_len, &resp->conf);
+ if (rc)
+ return fse_to_http_code(rc);
+
if (filename_is_hidden(basename(resp->file_name), resp->conf))
return MHD_HTTP_NOT_FOUND;
@@ -430,6 +454,9 @@ get_file_resp(struct MHD_Connection *conn, char const *url, FILE_RESP *resp)
int fd;
template = catfile(tmpdir, "idxXXXXXX");
+ if (!template)
+ return MHD_HTTP_INTERNAL_SERVER_ERROR;
+
fd = mkstemp(template);
if (fd == -1) {
error("can't create temporary file name: %s",
@@ -528,11 +555,11 @@ http_redirect(struct MHD_Connection *connection,
{
int ret;
struct MHD_Response *response;
-
+
http_log(connection, method, url, status, NULL);
- response = MHD_create_response_from_buffer (strlen(loc),
- xstrdup(loc),
- MHD_RESPMEM_MUST_FREE);
+ response = MHD_create_response_from_buffer(0,
+ "",
+ MHD_RESPMEM_PERSISTENT);
MHD_add_response_header(response,
MHD_HTTP_HEADER_LOCATION,
loc);
diff --git a/src/fileserv.h b/src/fileserv.h
index cf72b39..a79cf28 100644
--- a/src/fileserv.h
+++ b/src/fileserv.h
@@ -37,6 +37,13 @@ extern char *address;
extern char *index_css;
extern int verbose;
+enum fileserv_error {
+ FSE_SUCCESS, /* Processing successful */
+ FSE_SYNTAX, /* Syntax error encountered */
+ FSE_ACCESS, /* Access denied */
+ FSE_ERROR /* System error encountered */
+};
+
void error(char const *fmt, ...);
void info(char const *fmt, ...);
void syslog_enable(void);
@@ -44,6 +51,9 @@ int set_log_facility(char const *arg);
void fileserv_logger(void *arg, const char *fmt, va_list ap);
+void alloc_warn(void);
+void *nrealloc(void *ptr, size_t nmemb, size_t size);
+
void xmalloc_fail(void);
void *xmalloc(size_t s);
void *xcalloc(size_t nmemb, size_t size);
@@ -88,7 +98,7 @@ enum {
void readconfig(void);
-CONFIG *dirconfig(char const *path, size_t prefix_len);
+int dirconfig(char const *path, size_t prefix_len, CONFIG **);
int config_parse(const char *file, CONFIG *conf, int ctx);
CONFIG *config_init(void);
CONFIG *config_clone(CONFIG const *source);
diff --git a/src/idx.c b/src/idx.c
index 1db1370..7ea7543 100644
--- a/src/idx.c
+++ b/src/idx.c
@@ -157,7 +157,7 @@ node_cond_free(TMPL_NODE *node)
}
/* Parser error codes */
-enum {
+enum template_error {
TMPL_NOERR,
TMPL_ERR_LOOP_NESTING,
TMPL_ERR_ENDLOOP_WITHOUT_LOOP,
@@ -185,18 +185,18 @@ static char const *tmpl_err_str[] = {
};
/* Template parser state */
-struct template_state {
- int escape:1;
- int loop:1;
- COND_LIST cond;
- char const *start;
- char const *cur;
- int error;
-};
+typedef struct template_parser_state {
+ int escape:1; /* True if in a {% %} construct */
+ int loop:1; /* True if within a loop / endloop block */
+ COND_LIST cond; /* Stack of nested conditionals */
+ char const *start; /* Start of text fragment being parsed */
+ char const *cur; /* Current position in the text */
+ int error; /* Error state */
+} TEMPLATE_PARSER_STATE;
/* Allocate and initialize single node */
static inline TMPL_NODE *
-node_alloc(struct template_state *st, int type, size_t extra)
+node_alloc(TEMPLATE_PARSER_STATE *st, int type, size_t extra)
{
TMPL_NODE *np = calloc(1, sizeof(*np) + extra);
if (np)
@@ -208,10 +208,10 @@ node_alloc(struct template_state *st, int type, size_t extra)
}
/* Template parser */
-static void parse_template(TMPL_NODE_LIST *nodes, struct template_state *st);
+static void parse_template(TMPL_NODE_LIST *nodes, TEMPLATE_PARSER_STATE *st);
static TMPL_NODE *
-new_text_node(struct template_state *st, int type, size_t len)
+new_text_node(TEMPLATE_PARSER_STATE *st, int type, size_t len)
{
TMPL_NODE *np = node_alloc(st, type, len + 1);
if (np) {
@@ -223,7 +223,7 @@ new_text_node(struct template_state *st, int type, size_t len)
}
static TMPL_NODE *
-next_text_node(struct template_state *st)
+next_text_node(TEMPLATE_PARSER_STATE *st)
{
st->start = st->cur;
while (*st->cur) {
@@ -238,7 +238,7 @@ next_text_node(struct template_state *st)
}
static TMPL_NODE *
-parse_cond(struct template_state *st, int brn, size_t off, size_t len)
+parse_cond(TEMPLATE_PARSER_STATE *st, int brn, size_t off, size_t len)
{
struct condition cond;
TMPL_NODE *np;
@@ -263,7 +263,7 @@ parse_cond(struct template_state *st, int brn, size_t off, size_t len)
}
static TMPL_NODE *
-next_escape_node(struct template_state *st)
+next_escape_node(TEMPLATE_PARSER_STATE *st)
{
size_t len;
@@ -350,7 +350,7 @@ next_escape_node(struct template_state *st)
}
static TMPL_NODE *
-next_node(struct template_state *st)
+next_node(TEMPLATE_PARSER_STATE *st)
{
if (st->error)
return NULL;
@@ -360,7 +360,7 @@ next_node(struct template_state *st)
}
static void
-parse_template(TMPL_NODE_LIST *nodes, struct template_state *st)
+parse_template(TMPL_NODE_LIST *nodes, TEMPLATE_PARSER_STATE *st)
{
TMPL_NODE *np;
@@ -371,11 +371,15 @@ parse_template(TMPL_NODE_LIST *nodes, struct template_state *st)
}
TMPL_NODE_LIST node_list = STAILQ_HEAD_INITIALIZER(node_list);
+/* index_disabled inhibits creation of directory indexes. It is set only
+ if the built-in index template cannot be compiled and the custom template
+ was not supplied or failed to compile too. */
+static int index_disabled;
int
parse_template_string(char const *str)
{
- struct template_state state;
+ TEMPLATE_PARSER_STATE state;
state.escape = 0;
state.loop = 0;
@@ -454,15 +458,15 @@ parse_template_file(char const *file_name)
/* Run-time template evaluator */
typedef struct eval_env {
- int fd;
- CONFIG const *conf;
- DIRLSENT *ent;
- int n;
- struct wordsplit ws;
- int wsflags;
- INDEX_SORT_COL col;
- INDEX_SORT_ORD ord;
- ICON const *icon;
+ int fd; /* Output file descriptor */
+ CONFIG const *conf; /* Associated configuration settings */
+ DIRLSENT *ent; /* Current listing entry */
+ int n; /* Ordinal number of the entry in the listing */
+ ICON const *icon; /* Icon associated with the entry */
+ struct wordsplit ws; /* Word-splitter tool */
+ int wsflags; /* Its flags */
+ INDEX_SORT_COL col; /* Sorting column */
+ INDEX_SORT_ORD ord; /* Sorting order */
#define expansion ws.ws_wordv[0]
} EVAL_ENV;
@@ -751,9 +755,12 @@ directory_index(int fd, CONFIG const *conf,
EVAL_ENV env;
char const *varenv[5];
+ if (index_disabled)
+ return ENOSYS;
if (STAILQ_EMPTY(&node_list)) {
if (parse_template_string(defidx) == 0) {
error("error compiling built-in template!");
+ index_disabled = 1;
return ENOSYS;
}
}
diff --git a/src/mem.c b/src/mem.c
index 93c0adf..10a36d5 100644
--- a/src/mem.c
+++ b/src/mem.c
@@ -1,8 +1,17 @@
#include <stdio.h>
#include <string.h>
+#include <errno.h>
#include "fileserv.h"
void
+alloc_warn(void)
+{
+ int ec = errno;
+ error("not enough memory");
+ errno = ec;
+}
+
+void
xmalloc_fail(void)
{
error("not enough memory");
@@ -32,12 +41,19 @@ xcalloc(size_t nmemb, size_t size)
}
void *
-xnrealloc(void *ptr, size_t nmemb, size_t size)
+nrealloc(void *ptr, size_t nmemb, size_t size)
{
if (size < SIZE_T_MAX / nmemb)
ptr = realloc(ptr, nmemb * size);
else
ptr = NULL;
+ return ptr;
+}
+
+void *
+xnrealloc(void *ptr, size_t nmemb, size_t size)
+{
+ ptr = nrealloc(ptr, nmemb, size);
if (!ptr)
xmalloc_fail();
return ptr;

Return to:

Send suggestions and report system problems to the System administrator.