summaryrefslogtreecommitdiff
path: root/src/bin/psql/print.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/bin/psql/print.c')
-rw-r--r--src/bin/psql/print.c78
1 files changed, 65 insertions, 13 deletions
diff --git a/src/bin/psql/print.c b/src/bin/psql/print.c
index 190f2bc5d8..05d4b3162c 100644
--- a/src/bin/psql/print.c
+++ b/src/bin/psql/print.c
@@ -39,6 +39,13 @@
*/
volatile bool cancel_pressed = false;
+/*
+ * Likewise, the sigpipe_trap and pager open/close functions are here rather
+ * than in common.c so that this file can be used by non-psql programs.
+ */
+static bool always_ignore_sigpipe = false;
+
+
/* info for locale-aware numeric formatting; set up by setDecimalLocale() */
static char *decimal_point;
static int groupdigits;
@@ -2775,11 +2782,62 @@ print_troff_ms_vertical(const printTableContent *cont, FILE *fout)
/********************************/
-/* Public functions */
+/* Public functions */
/********************************/
/*
+ * disable_sigpipe_trap
+ *
+ * Turn off SIGPIPE interrupt --- call this before writing to a temporary
+ * query output file that is a pipe.
+ *
+ * No-op on Windows, where there's no SIGPIPE interrupts.
+ */
+void
+disable_sigpipe_trap(void)
+{
+#ifndef WIN32
+ pqsignal(SIGPIPE, SIG_IGN);
+#endif
+}
+
+/*
+ * restore_sigpipe_trap
+ *
+ * Restore normal SIGPIPE interrupt --- call this when done writing to a
+ * temporary query output file that was (or might have been) a pipe.
+ *
+ * Note: within psql, we enable SIGPIPE interrupts unless the permanent query
+ * output file is a pipe, in which case they should be kept off. This
+ * approach works only because psql is not currently complicated enough to
+ * have nested usages of short-lived output files. Otherwise we'd probably
+ * need a genuine save-and-restore-state approach; but for now, that would be
+ * useless complication. In non-psql programs, this always enables SIGPIPE.
+ *
+ * No-op on Windows, where there's no SIGPIPE interrupts.
+ */
+void
+restore_sigpipe_trap(void)
+{
+#ifndef WIN32
+ pqsignal(SIGPIPE, always_ignore_sigpipe ? SIG_IGN : SIG_DFL);
+#endif
+}
+
+/*
+ * set_sigpipe_trap_state
+ *
+ * Set the trap state that restore_sigpipe_trap should restore to.
+ */
+void
+set_sigpipe_trap_state(bool ignore)
+{
+ always_ignore_sigpipe = ignore;
+}
+
+
+/*
* PageOutput
*
* Tests if pager is needed and returns appropriate FILE pointer.
@@ -2792,9 +2850,6 @@ PageOutput(int lines, const printTableOpt *topt)
/* check whether we need / can / are supposed to use pager */
if (topt && topt->pager && isatty(fileno(stdin)) && isatty(fileno(stdout)))
{
- const char *pagerprog;
- FILE *pagerpipe;
-
#ifdef TIOCGWINSZ
unsigned short int pager = topt->pager;
int min_lines = topt->pager_min_lines;
@@ -2807,20 +2862,19 @@ PageOutput(int lines, const printTableOpt *topt)
if (result == -1
|| (lines >= screen_size.ws_row && lines >= min_lines)
|| pager > 1)
- {
#endif
+ {
+ const char *pagerprog;
+ FILE *pagerpipe;
+
pagerprog = getenv("PAGER");
if (!pagerprog)
pagerprog = DEFAULT_PAGER;
-#ifndef WIN32
- pqsignal(SIGPIPE, SIG_IGN);
-#endif
+ disable_sigpipe_trap();
pagerpipe = popen(pagerprog, "w");
if (pagerpipe)
return pagerpipe;
-#ifdef TIOCGWINSZ
}
-#endif
}
return stdout;
@@ -2848,9 +2902,7 @@ ClosePager(FILE *pagerpipe)
fprintf(pagerpipe, _("Interrupted\n"));
pclose(pagerpipe);
-#ifndef WIN32
- pqsignal(SIGPIPE, SIG_DFL);
-#endif
+ restore_sigpipe_trap();
}
}