Skip to content

Commit

Permalink
Fixing up compiler warnings. Fixed the API for parsing a single line …
Browse files Browse the repository at this point in the history
…of text

so that it is actually _useful_ for callers outside of pr_parser_parse_file().
Added more unit tests for parsing.
  • Loading branch information
Castaglian committed Sep 24, 2015
1 parent 6c196c3 commit f2f36f1
Show file tree
Hide file tree
Showing 6 changed files with 210 additions and 103 deletions.
18 changes: 7 additions & 11 deletions include/parser.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
* ProFTPD - FTP server daemon
* Copyright (c) 2004-2011 The ProFTPD Project team
* Copyright (c) 2004-2015 The ProFTPD Project team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
Expand All @@ -22,9 +22,7 @@
* OpenSSL in the source distribution.
*/

/* Configuration parser
* $Id: parser.h,v 1.4 2011-05-23 20:35:35 castaglia Exp $
*/
/* Configuration parser */

#ifndef PR_PARSER_H
#define PR_PARSER_H
Expand Down Expand Up @@ -60,8 +58,7 @@ config_rec *pr_parser_config_ctxt_get(void);
*/
config_rec *pr_parser_config_ctxt_open(const char *name);

/* Returns the line number of the configuration stream being parsed.
*/
/* Returns the line number of the configuration stream being parsed. */
unsigned int pr_parser_get_lineno(void);

/* This is the main function to be used by consumers of the Parser
Expand All @@ -85,12 +82,11 @@ int pr_parser_parse_file(pool *p, const char *path, config_rec *start,
#define PR_PARSER_FL_DYNAMIC_CONFIG 0x0001

/* The dispatching of configuration data to the registered configuration
* handlers is done using a cmd_rec. This function calls pr_parse_read_line()
* to obtain the next line of configuration text, then allocates a cmd_rec
* from the given pool p and populates the struct with data from the
* line of text.
* handlers is done using a cmd_rec. This function parses the given line of
* text, then allocates a cmd_rec from the given pool p and populates the
* struct with data from the line of text.
*/
cmd_rec *pr_parser_parse_line(pool *p);
cmd_rec *pr_parser_parse_line(pool *p, const char *text, size_t text_len);

/* This convenience function reads the next line from the configuration
* stream, performing any necessary transformations on the text (e.g.
Expand Down
8 changes: 4 additions & 4 deletions modules/mod_auth_unix.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
* ProFTPD - FTP server daemon
* Copyright (c) 1997, 1998 Public Flood Software
* Copyright (c) 1999, 2000 MacGyver aka Habeeb J. Dihu <macgyver@tos.net>
* Copyright (c) 2001-2014 The ProFTPD Project team
* Copyright (c) 2001-2015 The ProFTPD Project team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
Expand All @@ -24,8 +24,7 @@
* the source code for OpenSSL in the source distribution.
*/

/* Unix authentication module for ProFTPD
*/
/* Unix authentication module for ProFTPD */

#include "conf.h"

Expand Down Expand Up @@ -1120,7 +1119,8 @@ MODRET pw_getgroups(cmd_rec *cmd) {
"using getgrouplist(3) to look up group membership");

memset(group_ids, 0, sizeof(group_ids));
if (getgrouplist(pw->pw_name, pw->pw_gid, group_ids, &ngroups) < 0) {
if (getgrouplist(pw->pw_name, pw->pw_gid, (int *) group_ids,
&ngroups) < 0) {
int xerrno = errno;

pr_log_pri(PR_LOG_WARNING, "getgrouplist error: %s", strerror(xerrno));
Expand Down
2 changes: 1 addition & 1 deletion modules/mod_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -363,7 +363,7 @@ MODRET add_include(cmd_rec *cmd) {
"unable to use path for configuration file '", cmd->argv[1], "'", NULL));
}

if (parse_config_path(cmd->tmp_pool, cmd->argv[1]) == -1) {
if (parse_config_path(cmd->tmp_pool, cmd->argv[1]) < 0) {
int xerrno = errno;

if (xerrno != EINVAL) {
Expand Down
29 changes: 21 additions & 8 deletions src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -949,13 +949,20 @@ void restart_daemon(void *d1, void *d2, void *d3, void *d4) {
pr_event_generate("core.preparse", NULL);

PRIVS_ROOT
if (pr_parser_parse_file(NULL, config_filename, NULL, 0) == -1) {
if (pr_parser_parse_file(NULL, config_filename, NULL, 0) < 0) {
int xerrno = errno;

PRIVS_RELINQUISH
pr_log_pri(PR_LOG_WARNING,
"fatal: unable to read configuration file '%s': %s", config_filename,
strerror(xerrno));

/* Note: EPERM is used to indicate the presence of unrecognized
* configuration directives in the parsed file(s).
*/
if (xerrno != EPERM) {
pr_log_pri(PR_LOG_WARNING,
"fatal: unable to read configuration file '%s': %s", config_filename,
strerror(xerrno));
}

pr_session_end(0);
}
PRIVS_RELINQUISH
Expand Down Expand Up @@ -2406,10 +2413,16 @@ int main(int argc, char *argv[], char **envp) {

pr_event_generate("core.preparse", NULL);

if (pr_parser_parse_file(NULL, config_filename, NULL, 0) == -1) {
pr_log_pri(PR_LOG_WARNING,
"fatal: unable to read configuration file '%s': %s", config_filename,
strerror(errno));
if (pr_parser_parse_file(NULL, config_filename, NULL, 0) < 0) {
/* Note: EPERM is used to indicate the presence of unrecognized
* configuration directives in the parsed file(s).
*/
if (errno != EPERM) {
pr_log_pri(PR_LOG_WARNING,
"fatal: unable to read configuration file '%s': %s", config_filename,
strerror(errno));
}

exit(1);
}

Expand Down
156 changes: 86 additions & 70 deletions src/parser.c
Original file line number Diff line number Diff line change
Expand Up @@ -331,6 +331,7 @@ int pr_parser_parse_file(pool *p, const char *path, config_rec *start,
cmd_rec *cmd;
pool *tmp_pool;
char *report_path;
char buf[PR_TUNABLE_BUFFER_SIZE+1];

if (path == NULL) {
errno = EINVAL;
Expand All @@ -341,11 +342,13 @@ int pr_parser_parse_file(pool *p, const char *path, config_rec *start,
pr_pool_tag(tmp_pool, "parser file pool");

report_path = (char *) path;
if (session.chroot_path)
if (session.chroot_path) {
report_path = pdircat(tmp_pool, session.chroot_path, path, NULL);
}

if (!(flags & PR_PARSER_FL_DYNAMIC_CONFIG))
if (!(flags & PR_PARSER_FL_DYNAMIC_CONFIG)) {
pr_trace_msg(trace_channel, 3, "parsing '%s' configuration", report_path);
}

fh = pr_fsio_open(path, O_RDONLY);
if (fh == NULL) {
Expand Down Expand Up @@ -398,9 +401,15 @@ int pr_parser_parse_file(pool *p, const char *path, config_rec *start,
add_config_ctxt(start);
}

while ((cmd = pr_parser_parse_line(tmp_pool)) != NULL) {
memset(buf, '\0', sizeof(buf));
while (pr_parser_read_line(buf, sizeof(buf)-1) != NULL) {
pr_signals_handle();

cmd = pr_parser_parse_line(tmp_pool, buf, 0);
if (cmd == NULL) {
continue;
}

if (cmd->argc) {
conftable *conftab;
char found = FALSE;
Expand All @@ -425,11 +434,11 @@ int pr_parser_parse_file(pool *p, const char *path, config_rec *start,
mr = pr_module_call(conftab->m, conftab->handler, cmd);
if (mr != NULL) {
if (MODRET_ISERROR(mr)) {

if (!(flags & PR_PARSER_FL_DYNAMIC_CONFIG)) {
pr_log_pri(PR_LOG_WARNING, "fatal: %s on line %u of '%s'",
MODRET_ERRMSG(mr), cs->cs_lineno, report_path);
exit(1);
errno = EPERM;
return -1;

} else {
pr_log_pri(PR_LOG_WARNING, "warning: %s on line %u of '%s'",
Expand Down Expand Up @@ -486,7 +495,8 @@ int pr_parser_parse_file(pool *p, const char *path, config_rec *start,
"'%s' (contains non-ASCII characters)", name);
}

exit(1);
errno = EPERM;
return -1;
}

pr_log_pri(PR_LOG_WARNING, "warning: unknown configuration directive "
Expand All @@ -499,6 +509,7 @@ int pr_parser_parse_file(pool *p, const char *path, config_rec *start,
}

destroy_pool(cmd->pool);
memset(buf, '\0', sizeof(buf));
}

/* Pop this configuration stream from the stack. */
Expand All @@ -510,101 +521,106 @@ int pr_parser_parse_file(pool *p, const char *path, config_rec *start,
return 0;
}

cmd_rec *pr_parser_parse_line(pool *p) {
cmd_rec *pr_parser_parse_line(pool *p, const char *text, size_t text_len) {
register unsigned int i;
char buf[PR_TUNABLE_BUFFER_SIZE+1], *arg = "", *word = NULL;
char *arg = "", *ptr, *word = NULL;
cmd_rec *cmd = NULL;
pool *sub_pool = NULL;
array_header *arr = NULL;

if (p == NULL) {
if (p == NULL ||
text == NULL) {
errno = EINVAL;
return NULL;
}

memset(buf, '\0', sizeof(buf));

while (pr_parser_read_line(buf, sizeof(buf)-1) != NULL) {
char *bufp = buf;
if (text_len == 0) {
text_len = strlen(text);
}

pr_signals_handle();
if (text_len == 0) {
errno = ENOENT;
return NULL;
}

/* Build a new pool for the command structure and array */
sub_pool = make_sub_pool(p);
pr_pool_tag(sub_pool, "parser cmd subpool");
ptr = (char *) text;

cmd = pcalloc(sub_pool, sizeof(cmd_rec));
cmd->pool = sub_pool;
cmd->stash_index = -1;
cmd->stash_hash = 0;
/* Build a new pool for the command structure and array */
sub_pool = make_sub_pool(p);
pr_pool_tag(sub_pool, "parser cmd subpool");

/* Add each word to the array */
arr = make_array(cmd->pool, 4, sizeof(char **));
while ((word = pr_str_get_word(&bufp, 0)) != NULL) {
char *tmp;
cmd = pcalloc(sub_pool, sizeof(cmd_rec));
cmd->pool = sub_pool;
cmd->stash_index = -1;
cmd->stash_hash = 0;

tmp = get_config_word(cmd->pool, word);
/* Add each word to the array */
arr = make_array(cmd->pool, 4, sizeof(char **));
while ((word = pr_str_get_word(&ptr, 0)) != NULL) {
char *ptr2;

*((char **) push_array(arr)) = tmp;
cmd->argc++;
}
pr_signals_handle();
ptr2 = get_config_word(cmd->pool, word);
*((char **) push_array(arr)) = ptr2;
cmd->argc++;
}

/* Terminate the array with a NULL. */
*((char **) push_array(arr)) = NULL;
/* Terminate the array with a NULL. */
*((char **) push_array(arr)) = NULL;

/* The array header's job is done, we can forget about it and
* it will get purged when the command's pool is destroyed.
*/
/* The array header's job is done, we can forget about it and
* it will get purged when the command's pool is destroyed.
*/

cmd->argv = (void **) arr->elts;
cmd->argv = (void **) arr->elts;

/* Perform a fixup on configuration directives so that:
*
* -argv[0]-- -argv[1]-- ----argv[2]-----
* <Option /etc/adir /etc/anotherdir>
*
* becomes:
*
* -argv[0]-- -argv[1]- ----argv[2]----
* <Option> /etc/adir /etc/anotherdir
*/
/* Perform a fixup on configuration directives so that:
*
* -argv[0]-- -argv[1]-- ----argv[2]-----
* <Option /etc/adir /etc/anotherdir>
*
* becomes:
*
* -argv[0]-- -argv[1]- ----argv[2]----
* <Option> /etc/adir /etc/anotherdir
*/

if (cmd->argc &&
*((char *) cmd->argv[0]) == '<') {
char *cp;
if (cmd->argc &&
*((char *) cmd->argv[0]) == '<') {
char *cp;
size_t cp_len;

cp = cmd->argv[cmd->argc-1];
if (*(cp + strlen(cp)-1) == '>' &&
cmd->argc > 1) {
cp = cmd->argv[cmd->argc-1];
cp_len = strlen(cp);

if (strncmp(cp, ">", 2) == 0) {
cmd->argv[cmd->argc-1] = NULL;
cmd->argc--;
if (*(cp + cp_len-1) == '>' &&
cmd->argc > 1) {

} else {
*(cp + strlen(cp)-1) = '\0';
}
if (strncmp(cp, ">", 2) == 0) {
cmd->argv[cmd->argc-1] = NULL;
cmd->argc--;

cp = cmd->argv[0];
if (*(cp + strlen(cp)-1) != '>') {
cmd->argv[0] = pstrcat(cmd->pool, cp, ">", NULL);
}
} else {
*(cp + cp_len-1) = '\0';
}
}

if (cmd->argc < 2) {
arg = pstrdup(cmd->pool, arg);
cp = cmd->argv[0];
if (*(cp + cp_len-1) != '>') {
cmd->argv[0] = pstrcat(cmd->pool, cp, ">", NULL);
}
}
}

for (i = 1; i < cmd->argc; i++) {
arg = pstrcat(cmd->pool, arg, *arg ? " " : "", cmd->argv[i], NULL);
}
if (cmd->argc < 2) {
arg = pstrdup(cmd->pool, arg);
}

cmd->arg = arg;
return cmd;
for (i = 1; i < cmd->argc; i++) {
arg = pstrcat(cmd->pool, arg, *arg ? " " : "", cmd->argv[i], NULL);
}

return NULL;
cmd->arg = arg;
return cmd;
}

int pr_parser_prepare(pool *p, xaset_t **parsed_servers) {
Expand Down

0 comments on commit f2f36f1

Please sign in to comment.