From afca77f0c62b04630fde858c923134e8c680ffa9 Mon Sep 17 00:00:00 2001 From: Ben Pfaff Date: Sun, 3 Oct 2010 20:36:33 -0700 Subject: [PATCH] pspp: Fix crash passing the name of a nonexistent file on the command line. Also adds a test. --- src/ui/terminal/main.c | 42 ++++++++++++++++++++++-- src/ui/terminal/terminal-opts.c | 57 +++++++-------------------------- src/ui/terminal/terminal-opts.h | 7 ++-- tests/automake.mk | 1 + tests/ui/terminal/main.at | 7 ++++ 5 files changed, 65 insertions(+), 49 deletions(-) create mode 100644 tests/ui/terminal/main.at diff --git a/src/ui/terminal/main.c b/src/ui/terminal/main.c index 860d04f9..1be99732 100644 --- a/src/ui/terminal/main.c +++ b/src/ui/terminal/main.c @@ -28,6 +28,7 @@ #if HAVE_IEEEFP_H #include #endif +#include #include "data/dictionary.h" #include "data/file-handle-def.h" @@ -39,6 +40,7 @@ #include "language/command.h" #include "language/lexer/lexer.h" #include "language/prompt.h" +#include "language/syntax-file.h" #include "libpspp/argv-parser.h" #include "libpspp/compiler.h" #include "libpspp/getl.h" @@ -66,6 +68,8 @@ static struct dataset * the_dataset = NULL; static struct lexer *the_lexer; static struct source_stream *the_source_stream ; +static void add_syntax_file (struct source_stream *, enum syntax_mode, + const char *file_name); static void bug_handler(int sig); static void fpu_init (void); static void clean_up (void); @@ -76,6 +80,8 @@ main (int argc, char **argv) { struct terminal_opts *terminal_opts; struct argv_parser *parser; + enum syntax_mode syntax_mode; + bool process_statrc; set_program_name (argv[0]); @@ -99,7 +105,7 @@ main (int argc, char **argv) the_dataset = create_dataset (); parser = argv_parser_create (); - terminal_opts = terminal_opts_init (parser, the_source_stream); + terminal_opts = terminal_opts_init (parser, &syntax_mode, &process_statrc); source_init_register_argv_parser (parser, the_source_stream); if (!argv_parser_run (parser, argc, argv)) exit (EXIT_FAILURE); @@ -108,8 +114,28 @@ main (int argc, char **argv) msg_ui_init (the_source_stream); - the_lexer = lex_create (the_source_stream); + /* Add syntax files to source stream. */ + if (process_statrc) + { + char *rc = fn_search_path ("rc", getl_include_path (the_source_stream)); + if (rc != NULL) + { + add_syntax_file (the_source_stream, GETL_BATCH, rc); + free (rc); + } + } + if (optind < argc) + { + int i; + + for (i = optind; i < argc; i++) + add_syntax_file (the_source_stream, syntax_mode, argv[i]); + } + else + add_syntax_file (the_source_stream, syntax_mode, "-"); + /* Parse and execute syntax. */ + the_lexer = lex_create (the_source_stream); for (;;) { int result = cmd_parse (the_lexer, the_dataset); @@ -199,3 +225,15 @@ clean_up (void) i18n_done (); } } + +static void +add_syntax_file (struct source_stream *ss, enum syntax_mode syntax_mode, + const char *file_name) +{ + struct getl_interface *source; + + source = (!strcmp (file_name, "-") && isatty (STDIN_FILENO) + ? create_readln_source () + : create_syntax_file_source (file_name)); + getl_append_source (ss, source, syntax_mode, ERRMODE_CONTINUE); +} diff --git a/src/ui/terminal/terminal-opts.c b/src/ui/terminal/terminal-opts.c index d885cd0e..d55a8a2e 100644 --- a/src/ui/terminal/terminal-opts.c +++ b/src/ui/terminal/terminal-opts.c @@ -19,9 +19,7 @@ #include "terminal-opts.h" #include -#include #include -#include #include "data/settings.h" #include "data/file-name.h" @@ -47,6 +45,7 @@ #include "gl/progname.h" #include "gl/version-etc.h" #include "gl/xmemdup0.h" +#include "gl/xalloc.h" #include "gettext.h" #define _(msgid) gettext (msgid) @@ -54,13 +53,12 @@ struct terminal_opts { - struct source_stream *source_stream; - enum syntax_mode syntax_mode; + enum syntax_mode *syntax_mode; struct string_map options; /* Output driver options. */ bool has_output_driver; bool has_terminal_driver; bool has_error_file; - bool process_statrc; + bool *process_statrc; }; enum @@ -260,11 +258,11 @@ terminal_option_callback (int id, void *to_) break; case OPT_INTERACTIVE: - to->syntax_mode = GETL_INTERACTIVE; + *to->syntax_mode = GETL_INTERACTIVE; break; case OPT_NO_STATRC: - to->process_statrc = false; + *to->process_statrc = false; break; case OPT_HELP: @@ -283,60 +281,29 @@ terminal_option_callback (int id, void *to_) } struct terminal_opts * -terminal_opts_init (struct argv_parser *ap, struct source_stream *ss) +terminal_opts_init (struct argv_parser *ap, + enum syntax_mode *syntax_mode, bool *process_statrc) { struct terminal_opts *to; + *syntax_mode = GETL_BATCH; + *process_statrc = true; + to = xzalloc (sizeof *to); - to->source_stream = ss; - to->syntax_mode = GETL_BATCH; + to->syntax_mode = syntax_mode; string_map_init (&to->options); to->has_output_driver = false; to->has_error_file = false; - to->process_statrc = true; + to->process_statrc = process_statrc; argv_parser_add_options (ap, terminal_argv_options, N_TERMINAL_OPTIONS, terminal_option_callback, to); return to; } -static void -add_syntax_file (struct terminal_opts *to, const char *file_name) -{ - if (!strcmp (file_name, "-") && isatty (STDIN_FILENO)) - getl_append_source (to->source_stream, create_readln_source (), - GETL_INTERACTIVE, ERRMODE_CONTINUE); - else - getl_append_source (to->source_stream, - create_syntax_file_source (file_name), - to->syntax_mode, ERRMODE_CONTINUE); -} - void terminal_opts_done (struct terminal_opts *to, int argc, char *argv[]) { - if (to->process_statrc) - { - char *rc = fn_search_path ("rc", getl_include_path (to->source_stream)); - if (rc != NULL) - { - getl_append_source (to->source_stream, - create_syntax_file_source (rc), GETL_BATCH, - ERRMODE_CONTINUE); - free (rc); - } - } - - if (optind < argc) - { - int i; - - for (i = optind; i < argc; i++) - add_syntax_file (to, argv[i]); - } - else - add_syntax_file (to, "-"); - register_output_driver (to); if (!to->has_output_driver) { diff --git a/src/ui/terminal/terminal-opts.h b/src/ui/terminal/terminal-opts.h index 12251123..50f23196 100644 --- a/src/ui/terminal/terminal-opts.h +++ b/src/ui/terminal/terminal-opts.h @@ -18,12 +18,15 @@ #ifndef UI_TERMINAL_TERMINAL_OPTS_H #define UI_TERMINAL_TERMINAL_OPTS_H 1 +#include +#include "libpspp/getl.h" + struct argv_parser; -struct source_stream; struct terminal_opts; struct terminal_opts *terminal_opts_init (struct argv_parser *, - struct source_stream *); + enum syntax_mode *, + bool *process_statrc); void terminal_opts_done (struct terminal_opts *, int argc, char *argv[]); #endif /* ui/terminal/terminal-opts.h */ diff --git a/tests/automake.mk b/tests/automake.mk index 28776cf1..ad83e1c8 100644 --- a/tests/automake.mk +++ b/tests/automake.mk @@ -407,6 +407,7 @@ TESTSUITE_AT = \ tests/math/moments.at \ tests/output/render.at \ tests/output/charts.at \ + tests/ui/terminal/main.at \ tests/perl-module.at TESTSUITE = $(srcdir)/tests/testsuite diff --git a/tests/ui/terminal/main.at b/tests/ui/terminal/main.at new file mode 100644 index 00000000..1ee82268 --- /dev/null +++ b/tests/ui/terminal/main.at @@ -0,0 +1,7 @@ +AT_BANNER([PSPP terminal UI]) + +AT_SETUP([nonexistent syntax file crash]) +AT_CHECK([pspp nonexistent], [1], + [error: Opening `nonexistent': No such file or directory. +]) +AT_CLEANUP -- 2.30.2