aboutsummaryrefslogtreecommitdiff
path: root/src/port/exec.c
diff options
context:
space:
mode:
authorHeikki Linnakangas <heikki.linnakangas@iki.fi>2013-02-27 18:17:21 +0200
committerHeikki Linnakangas <heikki.linnakangas@iki.fi>2013-02-27 18:22:31 +0200
commit3d009e45bde2a2681826ef549637ada76508b597 (patch)
tree6f429ba5f7bbfee65dfd14fcfacd19a2e0ddd053 /src/port/exec.c
parent73dc003beef859e0b67da463c5e28f5468d3f17f (diff)
downloadpostgresql-3d009e45bde2a2681826ef549637ada76508b597.tar.gz
postgresql-3d009e45bde2a2681826ef549637ada76508b597.zip
Add support for piping COPY to/from an external program.
This includes backend "COPY TO/FROM PROGRAM '...'" syntax, and corresponding psql \copy syntax. Like with reading/writing files, the backend version is superuser-only, and in the psql version, the program is run in the client. In the passing, the psql \copy STDIN/STDOUT syntax is subtly changed: if you the stdin/stdout is quoted, it's now interpreted as a filename. For example, "\copy foo from 'stdin'" now reads from a file called 'stdin', not from standard input. Before this, there was no way to specify a filename called stdin, stdout, pstdin or pstdout. This creates a new function in pgport, wait_result_to_str(), which can be used to convert the exit status of a process, as returned by wait(3), to a human-readable string. Etsuro Fujita, reviewed by Amit Kapila.
Diffstat (limited to 'src/port/exec.c')
-rw-r--r--src/port/exec.c37
1 files changed, 10 insertions, 27 deletions
diff --git a/src/port/exec.c b/src/port/exec.c
index 18be1408f7a..01203c056cc 100644
--- a/src/port/exec.c
+++ b/src/port/exec.c
@@ -505,14 +505,12 @@ pipe_read_line(char *cmd, char *line, int maxsize)
/*
* pclose() plus useful error reporting
- * Is this necessary? bjm 2004-05-11
- * Originally this was stated to be here because pipe.c had backend linkage.
- * Perhaps that's no longer so now we have got rid of pipe.c amd 2012-03-28
*/
int
pclose_check(FILE *stream)
{
int exitstatus;
+ char *reason;
exitstatus = pclose(stream);
@@ -522,36 +520,21 @@ pclose_check(FILE *stream)
if (exitstatus == -1)
{
/* pclose() itself failed, and hopefully set errno */
- perror("pclose failed");
+ log_error(_("pclose failed: %s"), strerror(errno));
}
- else if (WIFEXITED(exitstatus))
- log_error(_("child process exited with exit code %d"),
- WEXITSTATUS(exitstatus));
- else if (WIFSIGNALED(exitstatus))
-#if defined(WIN32)
- log_error(_("child process was terminated by exception 0x%X"),
- WTERMSIG(exitstatus));
-#elif defined(HAVE_DECL_SYS_SIGLIST) && HAVE_DECL_SYS_SIGLIST
+ else
{
- char str[256];
-
- snprintf(str, sizeof(str), "%d: %s", WTERMSIG(exitstatus),
- WTERMSIG(exitstatus) < NSIG ?
- sys_siglist[WTERMSIG(exitstatus)] : "(unknown)");
- log_error(_("child process was terminated by signal %s"), str);
- }
+ reason = wait_result_to_str(exitstatus);
+ log_error("%s", reason);
+#ifdef FRONTEND
+ free(reason);
#else
- log_error(_("child process was terminated by signal %d"),
- WTERMSIG(exitstatus));
+ pfree(reason);
#endif
- else
- log_error(_("child process exited with unrecognized status %d"),
- exitstatus);
-
- return -1;
+ }
+ return exitstatus;
}
-
/*
* set_pglocale_pgservice
*