Some other platforms doesn't support fmemopen(3) (not unexpectedly), so

don't use it - since we only use getc/ungetc on the file anyway it is
easy not to.
pull/1758/head
nicm 2019-05-26 10:08:50 +00:00
parent a65a6d62d1
commit 6dee409981
1 changed files with 76 additions and 51 deletions

View File

@ -53,6 +53,11 @@ TAILQ_HEAD(cmd_parse_commands, cmd_parse_command);
struct cmd_parse_state { struct cmd_parse_state {
FILE *f; FILE *f;
const char *buf;
size_t len;
size_t off;
int eof; int eof;
struct cmd_parse_input *input; struct cmd_parse_input *input;
u_int escapes; u_int escapes;
@ -66,7 +71,6 @@ struct cmd_parse_state {
static struct cmd_parse_state parse_state; static struct cmd_parse_state parse_state;
static char *cmd_parse_get_error(const char *, u_int, const char *); static char *cmd_parse_get_error(const char *, u_int, const char *);
static char *cmd_parse_get_strerror(const char *, u_int);
static void cmd_parse_free_command(struct cmd_parse_command *); static void cmd_parse_free_command(struct cmd_parse_command *);
static void cmd_parse_free_commands(struct cmd_parse_commands *); static void cmd_parse_free_commands(struct cmd_parse_commands *);
@ -483,12 +487,6 @@ cmd_parse_get_error(const char *file, u_int line, const char *error)
return (s); return (s);
} }
static char *
cmd_parse_get_strerror(const char *file, u_int line)
{
return (cmd_parse_get_error(file, line, strerror(errno)));
}
static void static void
cmd_parse_free_command(struct cmd_parse_command *cmd) cmd_parse_free_command(struct cmd_parse_command *cmd)
{ {
@ -509,19 +507,13 @@ cmd_parse_free_commands(struct cmd_parse_commands *cmds)
} }
static struct cmd_parse_commands * static struct cmd_parse_commands *
cmd_parse_run_parser(FILE *f, struct cmd_parse_input *pi, char **cause) cmd_parse_run_parser(char **cause)
{ {
struct cmd_parse_state *ps = &parse_state; struct cmd_parse_state *ps = &parse_state;
struct cmd_parse_commands *cmds; struct cmd_parse_commands *cmds;
struct cmd_parse_scope *scope, *scope1; struct cmd_parse_scope *scope, *scope1;
int retval; int retval;
memset(ps, 0, sizeof *ps);
ps->f = f;
ps->eof = 0;
ps->input = pi;
TAILQ_INIT(&ps->commands); TAILQ_INIT(&ps->commands);
TAILQ_INIT(&ps->stack); TAILQ_INIT(&ps->stack);
@ -541,6 +533,30 @@ cmd_parse_run_parser(FILE *f, struct cmd_parse_input *pi, char **cause)
return (cmds); return (cmds);
} }
static struct cmd_parse_commands *
cmd_parse_do_file(FILE *f, struct cmd_parse_input *pi, char **cause)
{
struct cmd_parse_state *ps = &parse_state;
memset(ps, 0, sizeof *ps);
ps->input = pi;
ps->f = f;
return (cmd_parse_run_parser(cause));
}
static struct cmd_parse_commands *
cmd_parse_do_buffer(const char *buf, size_t len, struct cmd_parse_input *pi,
char **cause)
{
struct cmd_parse_state *ps = &parse_state;
memset(ps, 0, sizeof *ps);
ps->input = pi;
ps->buf = buf;
ps->len = len;
return (cmd_parse_run_parser(cause));
}
static struct cmd_parse_result * static struct cmd_parse_result *
cmd_parse_build_commands(struct cmd_parse_commands *cmds, cmd_parse_build_commands(struct cmd_parse_commands *cmds,
struct cmd_parse_input *pi) struct cmd_parse_input *pi)
@ -548,7 +564,6 @@ cmd_parse_build_commands(struct cmd_parse_commands *cmds,
static struct cmd_parse_result pr; static struct cmd_parse_result pr;
struct cmd_parse_commands *cmds2; struct cmd_parse_commands *cmds2;
struct cmd_parse_command *cmd, *cmd2, *next, *next2, *after; struct cmd_parse_command *cmd, *cmd2, *next, *next2, *after;
FILE *f;
u_int line = UINT_MAX; u_int line = UINT_MAX;
int i; int i;
struct cmd_list *cmdlist = NULL, *result; struct cmd_list *cmdlist = NULL, *result;
@ -576,16 +591,8 @@ cmd_parse_build_commands(struct cmd_parse_commands *cmds,
line = cmd->line; line = cmd->line;
log_debug("%s: %u %s = %s", __func__, line, cmd->name, alias); log_debug("%s: %u %s = %s", __func__, line, cmd->name, alias);
f = fmemopen(alias, strlen(alias), "r");
if (f == NULL) {
free(alias);
pr.status = CMD_PARSE_ERROR;
pr.error = cmd_parse_get_strerror(pi->file, line);
goto out;
}
pi->line = line; pi->line = line;
cmds2 = cmd_parse_run_parser(f, pi, &cause); cmds2 = cmd_parse_do_buffer(alias, strlen(alias), pi, &cause);
fclose(f);
free(alias); free(alias);
if (cmds2 == NULL) { if (cmds2 == NULL) {
pr.status = CMD_PARSE_ERROR; pr.status = CMD_PARSE_ERROR;
@ -678,10 +685,7 @@ cmd_parse_from_file(FILE *f, struct cmd_parse_input *pi)
} }
memset(&pr, 0, sizeof pr); memset(&pr, 0, sizeof pr);
/* cmds = cmd_parse_do_file(f, pi, &cause);
* Parse the file into a list of commands.
*/
cmds = cmd_parse_run_parser(f, pi, &cause);
if (cmds == NULL) { if (cmds == NULL) {
pr.status = CMD_PARSE_ERROR; pr.status = CMD_PARSE_ERROR;
pr.error = cause; pr.error = cause;
@ -694,9 +698,9 @@ struct cmd_parse_result *
cmd_parse_from_string(const char *s, struct cmd_parse_input *pi) cmd_parse_from_string(const char *s, struct cmd_parse_input *pi)
{ {
static struct cmd_parse_result pr; static struct cmd_parse_result pr;
struct cmd_parse_result *prp;
struct cmd_parse_input input; struct cmd_parse_input input;
FILE *f; struct cmd_parse_commands *cmds;
char *cause;
if (pi == NULL) { if (pi == NULL) {
memset(&input, 0, sizeof input); memset(&input, 0, sizeof input);
@ -711,16 +715,13 @@ cmd_parse_from_string(const char *s, struct cmd_parse_input *pi)
return (&pr); return (&pr);
} }
f = fmemopen((void *)s, strlen(s), "r"); cmds = cmd_parse_do_buffer(s, strlen(s), pi, &cause);
if (f == NULL) { if (cmds == NULL) {
pr.status = CMD_PARSE_ERROR; pr.status = CMD_PARSE_ERROR;
pr.cmdlist = NULL; pr.error = cause;
pr.error = cmd_parse_get_strerror(pi->file, pi->line); return (&pr);
return (NULL);
} }
prp = cmd_parse_from_file(f, pi); return (cmd_parse_build_commands(cmds, pi));
fclose(f);
return (prp);
} }
struct cmd_parse_result * struct cmd_parse_result *
@ -847,6 +848,34 @@ yylex_append1(char **buf, size_t *len, char add)
yylex_append(buf, len, &add, 1); yylex_append(buf, len, &add, 1);
} }
static int
yylex_getc1(void)
{
struct cmd_parse_state *ps = &parse_state;
int ch;
if (ps->f != NULL)
ch = getc(ps->f);
else {
if (ps->off == ps->len)
ch = EOF;
else
ch = ps->buf[ps->off++];
}
return (ch);
}
static void
yylex_ungetc(int ch)
{
struct cmd_parse_state *ps = &parse_state;
if (ps->f != NULL)
ungetc(ch, ps->f);
else if (ps->off > 0 && ch != EOF)
ps->off--;
}
static int static int
yylex_getc(void) yylex_getc(void)
{ {
@ -858,7 +887,7 @@ yylex_getc(void)
return ('\\'); return ('\\');
} }
for (;;) { for (;;) {
ch = getc(ps->f); ch = yylex_getc1();
if (ch == '\\') { if (ch == '\\') {
ps->escapes++; ps->escapes++;
continue; continue;
@ -870,7 +899,7 @@ yylex_getc(void)
} }
if (ps->escapes != 0) { if (ps->escapes != 0) {
ungetc(ch, ps->f); yylex_ungetc(ch);
ps->escapes--; ps->escapes--;
return ('\\'); return ('\\');
} }
@ -881,9 +910,8 @@ yylex_getc(void)
static char * static char *
yylex_get_word(int ch) yylex_get_word(int ch)
{ {
struct cmd_parse_state *ps = &parse_state; char *buf;
char *buf; size_t len;
size_t len;
len = 0; len = 0;
buf = xmalloc(1); buf = xmalloc(1);
@ -891,7 +919,7 @@ yylex_get_word(int ch)
do do
yylex_append1(&buf, &len, ch); yylex_append1(&buf, &len, ch);
while ((ch = yylex_getc()) != EOF && strchr(" \t\n", ch) == NULL); while ((ch = yylex_getc()) != EOF && strchr(" \t\n", ch) == NULL);
ungetc(ch, ps->f); yylex_ungetc(ch);
buf[len] = '\0'; buf[len] = '\0';
log_debug("%s: %s", __func__, buf); log_debug("%s: %s", __func__, buf);
@ -1117,7 +1145,6 @@ unicode:
static int static int
yylex_token_variable(char **buf, size_t *len) yylex_token_variable(char **buf, size_t *len)
{ {
struct cmd_parse_state *ps = &parse_state;
struct environ_entry *envent; struct environ_entry *envent;
int ch, brackets = 0; int ch, brackets = 0;
char name[BUFSIZ]; char name[BUFSIZ];
@ -1132,7 +1159,7 @@ yylex_token_variable(char **buf, size_t *len)
else { else {
if (!yylex_is_var(ch, 1)) { if (!yylex_is_var(ch, 1)) {
yylex_append1(buf, len, '$'); yylex_append1(buf, len, '$');
ungetc(ch, ps->f); yylex_ungetc(ch);
return (1); return (1);
} }
name[namelen++] = ch; name[namelen++] = ch;
@ -1144,7 +1171,7 @@ yylex_token_variable(char **buf, size_t *len)
break; break;
if (ch == EOF || !yylex_is_var(ch, 0)) { if (ch == EOF || !yylex_is_var(ch, 0)) {
if (!brackets) { if (!brackets) {
ungetc(ch, ps->f); yylex_ungetc(ch);
break; break;
} }
yyerror("invalid environment variable"); yyerror("invalid environment variable");
@ -1170,7 +1197,6 @@ yylex_token_variable(char **buf, size_t *len)
static int static int
yylex_token_tilde(char **buf, size_t *len) yylex_token_tilde(char **buf, size_t *len)
{ {
struct cmd_parse_state *ps = &parse_state;
struct environ_entry *envent; struct environ_entry *envent;
int ch; int ch;
char name[BUFSIZ]; char name[BUFSIZ];
@ -1181,7 +1207,7 @@ yylex_token_tilde(char **buf, size_t *len)
for (;;) { for (;;) {
ch = yylex_getc(); ch = yylex_getc();
if (ch == EOF || strchr("/ \t\n\"'", ch) != NULL) { if (ch == EOF || strchr("/ \t\n\"'", ch) != NULL) {
ungetc(ch, ps->f); yylex_ungetc(ch);
break; break;
} }
if (namelen == (sizeof name) - 2) { if (namelen == (sizeof name) - 2) {
@ -1213,7 +1239,6 @@ yylex_token_tilde(char **buf, size_t *len)
static char * static char *
yylex_token(int ch) yylex_token(int ch)
{ {
struct cmd_parse_state *ps = &parse_state;
char *buf; char *buf;
size_t len; size_t len;
enum { START, enum { START,
@ -1293,7 +1318,7 @@ yylex_token(int ch)
next: next:
ch = yylex_getc(); ch = yylex_getc();
} }
ungetc(ch, ps->f); yylex_ungetc(ch);
buf[len] = '\0'; buf[len] = '\0';
log_debug("%s: %s", __func__, buf); log_debug("%s: %s", __func__, buf);