From c75adac757b302962a8f68eaec0121c59805fd1e Mon Sep 17 00:00:00 2001 From: Peter Eisentraut <peter_e@gmx.net> Date: Wed, 1 Mar 2000 21:10:05 +0000 Subject: [PATCH] More fixes for psql ^C handling, especially during copy. Still doesn't cope so well with copy to but that will have to wait for the next release. Also added -X option to prevent reading .psqlrc startup file. --- doc/src/sgml/ref/psql-ref.sgml | 25 ++++++++++++++++--- src/bin/psql/command.c | 6 ++--- src/bin/psql/common.c | 44 ++++++++++++++++++---------------- src/bin/psql/common.h | 3 ++- src/bin/psql/copy.c | 17 +++++++++---- src/bin/psql/copy.h | 4 ++-- src/bin/psql/create_help.pl | 14 +++++------ src/bin/psql/help.c | 5 ++-- src/bin/psql/mainloop.c | 36 +++++++++++++++++----------- src/bin/psql/startup.c | 29 +++++++++++++++------- src/test/regress/regress.sh | 4 ++-- src/test/regress/run_check.sh | 4 ++-- 12 files changed, 121 insertions(+), 70 deletions(-) diff --git a/doc/src/sgml/ref/psql-ref.sgml b/doc/src/sgml/ref/psql-ref.sgml index f76d212c1e0..a265bff87b3 100644 --- a/doc/src/sgml/ref/psql-ref.sgml +++ b/doc/src/sgml/ref/psql-ref.sgml @@ -1,5 +1,5 @@ <!-- -$Header: /cvsroot/pgsql/doc/src/sgml/ref/psql-ref.sgml,v 1.26 2000/02/20 14:29:21 petere Exp $ +$Header: /cvsroot/pgsql/doc/src/sgml/ref/psql-ref.sgml,v 1.27 2000/03/01 21:09:56 petere Exp $ Postgres documentation --> @@ -1554,6 +1554,16 @@ Access permissions for database "test" </varlistentry> + <varlistentry> + <term>-X, --no-psqlrc</term> + <listitem> + <para> + Do not read the startup file <filename>~/.psqlrc</filename>. + </para> + </listitem> + </varlistentry> + + <varlistentry> <term>-?, --help</term> <listitem> @@ -2065,7 +2075,7 @@ testdb=> <userinput>\set content `sed -e "s/'/\\\\\\'/g" < my_file.txt`</userinp </para> <para> - Before starting up in interactive mode, <application>psql</application> attempts + Before starting up, <application>psql</application> attempts to read and execute commands from the file <filename>$HOME/.psqlrc</filename>. It could be used to set up the client or the server to taste (using the <command>\set </command> and <command>SET</command> commands). @@ -2101,7 +2111,7 @@ $endif does not seem to use it, you must make sure that <productname>PostgreSQL</productname>'s top-level <filename>configure</filename> script finds it. <filename>configure</filename> needs to find both the library <filename>libreadline.a</filename> - (or <filename>libreadline.so</filename> on systems with shared libraries) + (or a shared library equivalent) <emphasis>and</emphasis> the header files <filename>readline.h</filename> and <filename>history.h</filename> (or <filename>readline/readline.h</filename> and <filename>readline/history.h</filename>) in appropriate directories. If @@ -2276,6 +2286,15 @@ Field separator is "oo". </para> </listitem> + <listitem> + <para> + Pressing Control-C during a <quote>copy in</quote> (data sent to the + server) doesn't show the most ideal of behaviours. If you get a message + such as <quote>PQexec: you gotta get out of a COPY state yourself</quote>, + simply reset the connection by entering <literal>\c - -</literal>. + </para> + </listitem> + </itemizedlist> </refsect2> diff --git a/src/bin/psql/command.c b/src/bin/psql/command.c index 07581fd82c6..e515f1e151b 100644 --- a/src/bin/psql/command.c +++ b/src/bin/psql/command.c @@ -3,7 +3,7 @@ * * Copyright 2000 by PostgreSQL Global Development Group * - * $Header: /cvsroot/pgsql/src/bin/psql/command.c,v 1.23 2000/02/21 02:05:12 ishii Exp $ + * $Header: /cvsroot/pgsql/src/bin/psql/command.c,v 1.24 2000/03/01 21:09:58 petere Exp $ */ #include "postgres.h" #include "command.h" @@ -432,7 +432,7 @@ exec_command(const char *cmd, } else { - success = process_file(fname) == EXIT_SUCCESS; + success = (process_file(fname) == EXIT_SUCCESS); free (fname); } } @@ -727,7 +727,7 @@ exec_command(const char *cmd, else if (strcmp(cmd, "?") == 0) slashUsage(); -#if 1 +#if 0 /* * These commands don't do anything. I just use them to test the * parser. diff --git a/src/bin/psql/common.c b/src/bin/psql/common.c index e149d7ec539..30e0cb5473e 100644 --- a/src/bin/psql/common.c +++ b/src/bin/psql/common.c @@ -3,7 +3,7 @@ * * Copyright 2000 by PostgreSQL Global Development Group * - * $Header: /cvsroot/pgsql/src/bin/psql/common.c,v 1.17 2000/02/21 19:40:41 petere Exp $ + * $Header: /cvsroot/pgsql/src/bin/psql/common.c,v 1.18 2000/03/01 21:09:58 petere Exp $ */ #include "postgres.h" #include "common.h" @@ -170,6 +170,8 @@ NoticeProcessor(void * arg, const char * message) * * Returns a malloc()'ed string with the input (w/o trailing newline). */ +static bool prompt_state; + char * simple_prompt(const char *prompt, int maxlen, bool echo) { @@ -187,6 +189,8 @@ simple_prompt(const char *prompt, int maxlen, bool echo) if (prompt) fputs(prompt, stderr); + prompt_state = true; + #ifdef HAVE_TERMIOS_H if (!echo) { @@ -207,6 +211,8 @@ simple_prompt(const char *prompt, int maxlen, bool echo) } #endif + prompt_state = false; + length = strlen(destination); if (length > 0 && destination[length - 1] != '\n') { @@ -238,7 +244,7 @@ simple_prompt(const char *prompt, int maxlen, bool echo) * facilities in a signal handler. */ -static PGconn *cancelConn; +PGconn *cancelConn; volatile bool cancel_pressed; #define write_stderr(String) write(fileno(stderr), String, strlen(String)) @@ -246,24 +252,20 @@ volatile bool cancel_pressed; void handle_sigint(SIGNAL_ARGS) { - cancel_pressed = true; - - if (copy_state) + /* Don't muck around if copying in or prompting for a password. */ + if ((copy_in_state && pset.cur_cmd_interactive) || prompt_state) return; if (cancelConn == NULL) -#ifndef WIN32 siglongjmp(main_loop_jmp, 1); -#else - return; -#endif - /* Try to send cancel request */ + cancel_pressed = true; + if (PQrequestCancel(cancelConn)) - write_stderr("\nCancel request sent\n"); + write_stderr("Cancel request sent\n"); else { - write_stderr("\nCould not send cancel request: "); + write_stderr("Could not send cancel request: "); write_stderr(PQerrorMessage(cancelConn)); } } @@ -300,10 +302,11 @@ PSQLexec(const char *query) cancelConn = pset.db; res = PQexec(pset.db, query); - if (PQresultStatus(res) == PGRES_COPY_IN || - PQresultStatus(res) == PGRES_COPY_OUT) - copy_state = true; - cancelConn = NULL; + if (PQresultStatus(res) == PGRES_COPY_IN) + copy_in_state = true; + /* keep cancel connection for copy out state */ + if (PQresultStatus(res) != PGRES_COPY_OUT) + cancelConn = NULL; if (PQstatus(pset.db) == CONNECTION_BAD) { @@ -394,10 +397,11 @@ SendQuery(const char *query) cancelConn = pset.db; results = PQexec(pset.db, query); - if (PQresultStatus(results) == PGRES_COPY_IN || - PQresultStatus(results) == PGRES_COPY_OUT) - copy_state = true; - cancelConn = NULL; + if (PQresultStatus(results) == PGRES_COPY_IN) + copy_in_state = true; + /* keep cancel connection for copy out state */ + if (PQresultStatus(results) != PGRES_COPY_OUT) + cancelConn = NULL; if (results == NULL) { diff --git a/src/bin/psql/common.h b/src/bin/psql/common.h index 6a7be3ec202..96c8a799489 100644 --- a/src/bin/psql/common.h +++ b/src/bin/psql/common.h @@ -3,7 +3,7 @@ * * Copyright 2000 by PostgreSQL Global Development Group * - * $Header: /cvsroot/pgsql/src/bin/psql/common.h,v 1.7 2000/02/20 14:28:20 petere Exp $ + * $Header: /cvsroot/pgsql/src/bin/psql/common.h,v 1.8 2000/03/01 21:09:58 petere Exp $ */ #ifndef COMMON_H #define COMMON_H @@ -29,6 +29,7 @@ void NoticeProcessor(void * arg, const char * message); char * simple_prompt(const char *prompt, int maxlen, bool echo); extern volatile bool cancel_pressed; +extern PGconn *cancelConn; void handle_sigint(SIGNAL_ARGS); PGresult * PSQLexec(const char *query); diff --git a/src/bin/psql/copy.c b/src/bin/psql/copy.c index 7caf82edfdd..9f338979f18 100644 --- a/src/bin/psql/copy.c +++ b/src/bin/psql/copy.c @@ -3,7 +3,7 @@ * * Copyright 2000 by PostgreSQL Global Development Group * - * $Header: /cvsroot/pgsql/src/bin/psql/copy.c,v 1.11 2000/02/21 19:40:41 petere Exp $ + * $Header: /cvsroot/pgsql/src/bin/psql/copy.c,v 1.12 2000/03/01 21:09:58 petere Exp $ */ #include "postgres.h" #include "copy.h" @@ -28,7 +28,7 @@ #define strcasecmp(x,y) stricmp(x,y) #endif -bool copy_state; +bool copy_in_state; /* * parse_slash_copy @@ -335,6 +335,8 @@ handleCopyOut(PGconn *conn, FILE *copystream) char copybuf[COPYBUFSIZ]; int ret; + assert(cancelConn); + while (!copydone) { ret = PQgetline(conn, copybuf, COPYBUFSIZ); @@ -363,7 +365,7 @@ handleCopyOut(PGconn *conn, FILE *copystream) } fflush(copystream); ret = !PQendcopy(conn); - copy_state = false; + cancelConn = NULL; return ret; } @@ -394,6 +396,10 @@ handleCopyIn(PGconn *conn, FILE *copystream, const char *prompt) int c = 0; int ret; +#ifdef USE_ASSERT_CHECKING + assert(copy_in_state); +#endif + if (prompt) /* disable prompt if not interactive */ { if (! isatty(fileno(copystream))) @@ -409,6 +415,7 @@ handleCopyIn(PGconn *conn, FILE *copystream, const char *prompt) } firstload = true; linedone = false; + while (!linedone) { /* for each bufferload in line ... */ s = copybuf; @@ -427,6 +434,8 @@ handleCopyIn(PGconn *conn, FILE *copystream, const char *prompt) { PQputline(conn, "\\."); copydone = true; + if (pset.cur_cmd_interactive) + puts("\\."); break; } PQputline(conn, copybuf); @@ -443,6 +452,6 @@ handleCopyIn(PGconn *conn, FILE *copystream, const char *prompt) PQputline(conn, "\n"); } ret = !PQendcopy(conn); - copy_state = false; + copy_in_state = false; return ret; } diff --git a/src/bin/psql/copy.h b/src/bin/psql/copy.h index e25dfa9b6b7..66114fdbf42 100644 --- a/src/bin/psql/copy.h +++ b/src/bin/psql/copy.h @@ -3,14 +3,14 @@ * * Copyright 2000 by PostgreSQL Global Development Group * - * $Header: /cvsroot/pgsql/src/bin/psql/copy.h,v 1.8 2000/02/21 19:40:42 petere Exp $ + * $Header: /cvsroot/pgsql/src/bin/psql/copy.h,v 1.9 2000/03/01 21:09:58 petere Exp $ */ #ifndef COPY_H #define COPY_H #include "libpq-fe.h" -extern bool copy_state; +extern bool copy_in_state; /* handler for \copy */ bool do_copy(const char *args); diff --git a/src/bin/psql/create_help.pl b/src/bin/psql/create_help.pl index 638b96600f8..f8e5379c893 100644 --- a/src/bin/psql/create_help.pl +++ b/src/bin/psql/create_help.pl @@ -5,35 +5,33 @@ # # Copyright 2000 by PostgreSQL Global Development Group # -# $Header: /cvsroot/pgsql/src/bin/psql/create_help.pl,v 1.4 2000/02/07 23:10:06 petere Exp $ +# $Header: /cvsroot/pgsql/src/bin/psql/create_help.pl,v 1.5 2000/03/01 21:09:58 petere Exp $ ################################################################# # # This script automatically generates the help on SQL in psql from # the SGML docs. So far the format of the docs was consistent -# enough that this worked, but this here is my no means an SGML +# enough that this worked, but this here is by no means an SGML # parser. # # Call: perl create_help.pl sql_help.h # The name of the header file doesn't matter to this script, but it # sure does matter to the rest of the source. # -# A rule for this is also in the psql makefile. -# $docdir = "./../../../doc/src/sgml/ref"; -$outputfile = $ARGV[0] or die "Missing required argument.\n"; +$outputfile = $ARGV[0] or die "$0: missing required argument\n"; $define = $outputfile; $define =~ tr/a-z/A-Z/; $define =~ s/\W/_/g; -opendir DIR, $docdir or die "Couldn't open documentation sources: $!\n"; -open OUT, ">$outputfile" or die "Couldn't open output file '$outputfile': $!\n"; +opendir DIR, $docdir or die "$0: could not open documentation sources: $!\n"; +open OUT, ">$outputfile" or die "$0: could not open output file '$outputfile': $!\n"; print OUT "/* - * *** Do not change this file directly. Changes will be overwritten. *** + * *** Do not change this file. It is machine-generated. *** * * This file was generated by * $^X $0 $outputfile diff --git a/src/bin/psql/help.c b/src/bin/psql/help.c index 8fa9187d2da..33c187bdb2a 100644 --- a/src/bin/psql/help.c +++ b/src/bin/psql/help.c @@ -3,7 +3,7 @@ * * Copyright 2000 by PostgreSQL Global Development Group * - * $Header: /cvsroot/pgsql/src/bin/psql/help.c,v 1.22 2000/02/20 14:28:20 petere Exp $ + * $Header: /cvsroot/pgsql/src/bin/psql/help.c,v 1.23 2000/03/01 21:09:58 petere Exp $ */ #include "postgres.h" #include "help.h" @@ -124,10 +124,11 @@ usage(void) env = user; printf(" -U <username> Specify database username (default: %s)\n", env); - puts( " -x Turn on expanded table output (-P expanded)"); puts( " -v name=val Set psql variable 'name' to 'value'"); puts( " -V Show version information and exit"); puts( " -W Prompt for password (should happen automatically)"); + puts( " -x Turn on expanded table output (-P expanded)"); + puts( " -X Do not read startup file (~/.psqlrc)"); puts( "\nFor more information, type \"\\?\" (for internal commands) or \"\\help\""); puts( "(for SQL commands) from within psql, or consult the psql section in"); diff --git a/src/bin/psql/mainloop.c b/src/bin/psql/mainloop.c index 9b3834cca7d..4c5c7c55858 100644 --- a/src/bin/psql/mainloop.c +++ b/src/bin/psql/mainloop.c @@ -3,7 +3,7 @@ * * Copyright 2000 by PostgreSQL Global Development Group * - * $Header: /cvsroot/pgsql/src/bin/psql/mainloop.c,v 1.22 2000/02/20 14:28:20 petere Exp $ + * $Header: /cvsroot/pgsql/src/bin/psql/mainloop.c,v 1.23 2000/03/01 21:09:58 petere Exp $ */ #include "postgres.h" #include "mainloop.h" @@ -40,18 +40,17 @@ MainLoop(FILE *source) yet, use this one for \e, etc. */ char *line; /* current line of input */ int len; /* length of the line */ - int successResult = EXIT_SUCCESS; - backslashResult slashCmdStatus; + volatile int successResult = EXIT_SUCCESS; + volatile backslashResult slashCmdStatus; bool success; - char in_quote; /* == 0 for no in_quote */ - bool xcomment; /* in extended comment */ - int paren_level; + volatile char in_quote; /* == 0 for no in_quote */ + volatile bool xcomment; /* in extended comment */ + volatile int paren_level; unsigned int query_start; - int count_eof = 0; + volatile int count_eof = 0; const char *var; - bool was_bslash; - unsigned int bslash_count = 0; + volatile unsigned int bslash_count = 0; int i, prevlen, @@ -98,7 +97,6 @@ MainLoop(FILE *source) */ if (cancel_pressed) { - cancel_pressed = false; if (!pset.cur_cmd_interactive) { /* @@ -109,23 +107,33 @@ MainLoop(FILE *source) successResult = EXIT_USER; break; } + + cancel_pressed = false; } -#ifndef WIN32 + if (sigsetjmp(main_loop_jmp, 1) != 0) { /* got here with longjmp */ + if (pset.cur_cmd_interactive) { fputc('\n', stdout); resetPQExpBuffer(query_buf); + + /* reset parsing state */ + xcomment = false; + in_quote = 0; + paren_level = 0; + count_eof = 0; + slashCmdStatus = CMD_UNKNOWN; } else { successResult = EXIT_USER; break; - } + } } -#endif + if (slashCmdStatus == CMD_NEWEDIT) { @@ -273,7 +281,7 @@ MainLoop(FILE *source) ADVANCE_1) { /* was the previous character a backslash? */ - was_bslash = (i > 0 && line[i - prevlen] == '\\'); + bool was_bslash = (i > 0 && line[i - prevlen] == '\\'); if (was_bslash) bslash_count++; else diff --git a/src/bin/psql/startup.c b/src/bin/psql/startup.c index 82a7bcd4d13..81c21a225b0 100644 --- a/src/bin/psql/startup.c +++ b/src/bin/psql/startup.c @@ -3,7 +3,7 @@ * * Copyright 2000 by PostgreSQL Global Development Group * - * $Header: /cvsroot/pgsql/src/bin/psql/startup.c,v 1.26 2000/02/27 01:10:31 tgl Exp $ + * $Header: /cvsroot/pgsql/src/bin/psql/startup.c,v 1.27 2000/03/01 21:09:58 petere Exp $ */ #include "postgres.h" @@ -70,6 +70,7 @@ struct adhoc_opts enum _actions action; char *action_string; bool no_readline; + bool no_psqlrc; }; static void @@ -192,7 +193,7 @@ main(int argc, char *argv[]) int success = listAllDbs(false); PQfinish(pset.db); - exit(!success); + exit(success ? EXIT_SUCCESS : EXIT_FAILURE); } SetVariable(pset.vars, "DBNAME", PQdb(pset.db)); @@ -213,7 +214,12 @@ main(int argc, char *argv[]) * process file given by -f */ if (options.action == ACT_FILE) + { + if (!options.no_psqlrc) + process_psqlrc(); + successResult = process_file(options.action_string); + } /* * process slash command if one was given to -c */ @@ -257,7 +263,8 @@ main(int argc, char *argv[]) SetVariable(pset.vars, "PROMPT1", DEFAULT_PROMPT1); SetVariable(pset.vars, "PROMPT2", DEFAULT_PROMPT2); SetVariable(pset.vars, "PROMPT3", DEFAULT_PROMPT3); - process_psqlrc(); + if (!options.no_psqlrc) + process_psqlrc(); if (!pset.notty) initializeInput(options.no_readline ? 0 : 1); successResult = MainLoop(stdin); @@ -310,11 +317,12 @@ parse_psql_options(int argc, char *argv[], struct adhoc_opts * options) {"tuples-only", no_argument, NULL, 't'}, {"table-attr", required_argument, NULL, 'T'}, {"username", required_argument, NULL, 'U'}, - {"expanded", no_argument, NULL, 'x'}, {"set", required_argument, NULL, 'v'}, {"variable", required_argument, NULL, 'v'}, {"version", no_argument, NULL, 'V'}, {"password", no_argument, NULL, 'W'}, + {"expanded", no_argument, NULL, 'x'}, + {"no-psqlrc", no_argument, NULL, 'X'}, {"help", no_argument, NULL, '?'}, }; @@ -329,13 +337,13 @@ parse_psql_options(int argc, char *argv[], struct adhoc_opts * options) memset(options, 0, sizeof *options); #ifdef HAVE_GETOPT_LONG - while ((c = getopt_long(argc, argv, "aAc:d:eEf:F:lh:Hno:p:P:qRsStT:uU:v:VWx?", long_options, &optindex)) != -1) + while ((c = getopt_long(argc, argv, "aAc:d:eEf:F:lh:Hno:p:P:qRsStT:uU:v:VWxX?", long_options, &optindex)) != -1) #else /* not HAVE_GETOPT_LONG */ /* * Be sure to leave the '-' in here, so we can catch accidental long * options. */ - while ((c = getopt(argc, argv, "aAc:d:eEf:F:lh:Hno:p:P:qRsStT:uU:v:VWx?-")) != -1) + while ((c = getopt(argc, argv, "aAc:d:eEf:F:lh:Hno:p:P:qRsStT:uU:v:VWxX?-")) != -1) #endif /* not HAVE_GETOPT_LONG */ { switch (c) @@ -439,9 +447,6 @@ parse_psql_options(int argc, char *argv[], struct adhoc_opts * options) case 'U': options->username = optarg; break; - case 'x': - pset.popt.topt.expanded = true; - break; case 'v': { char *value; @@ -478,6 +483,12 @@ parse_psql_options(int argc, char *argv[], struct adhoc_opts * options) case 'W': pset.getPassword = true; break; + case 'x': + pset.popt.topt.expanded = true; + break; + case 'X': + options->no_psqlrc = true; + break; case '?': /* Actual help option given */ if (strcmp(argv[optind-1], "-?")==0 || strcmp(argv[optind-1], "--help")==0) diff --git a/src/test/regress/regress.sh b/src/test/regress/regress.sh index b717f34dfb9..3e422be9c5f 100755 --- a/src/test/regress/regress.sh +++ b/src/test/regress/regress.sh @@ -1,5 +1,5 @@ #!/bin/sh -# $Header: /cvsroot/pgsql/src/test/regress/Attic/regress.sh,v 1.42 2000/03/01 19:11:06 momjian Exp $ +# $Header: /cvsroot/pgsql/src/test/regress/Attic/regress.sh,v 1.43 2000/03/01 21:10:04 petere Exp $ # if [ $# -eq 0 ] then @@ -30,7 +30,7 @@ fi PGTZ="PST8PDT"; export PGTZ PGDATESTYLE="Postgres,US"; export PGDATESTYLE -FRONTEND="psql $HOSTLOC -a -q" +FRONTEND="psql $HOSTLOC -a -q -X" # ---------- # Scan resultmap file to find which platform-specific expected files to use. diff --git a/src/test/regress/run_check.sh b/src/test/regress/run_check.sh index 3e4e1baae1c..68c524bb9ab 100755 --- a/src/test/regress/run_check.sh +++ b/src/test/regress/run_check.sh @@ -1,6 +1,6 @@ #!/bin/sh # -# $Header: /cvsroot/pgsql/src/test/regress/Attic/run_check.sh,v 1.10 2000/02/24 23:37:30 petere Exp $ +# $Header: /cvsroot/pgsql/src/test/regress/Attic/run_check.sh,v 1.11 2000/03/01 21:10:05 petere Exp $ # ---------- # Check call syntax @@ -91,7 +91,7 @@ PGDATESTYLE="ISO,US"; export PGDATESTYLE # ---------- # The SQL shell to use during this test # ---------- -FRONTEND="$BINDIR/psql $HOSTLOC -a -q" +FRONTEND="$BINDIR/psql $HOSTLOC -a -q -X" # ---------- # Scan resultmap file to find which platform-specific expected files to use. -- GitLab