Skip to content

Commit 31ae2aa

Browse files
committed
psql: set SHELL_ERROR and SHELL_EXIT_CODE in more places.
Make the \g, \o, \w, and \copy commands set these variables when closing a pipe. We missed doing this in commit b0d8f2d, but it seems like a good idea. There are some remaining places in psql that intentionally don't update these variables after running a child program: * pager invocations * backtick evaluation within a prompt * \e (edit query buffer) Corey Huinker and Tom Lane Discussion: https://postgr.es/m/CADkLM=eSKwRGF-rnRqhtBORRtL49QsjcVUCa-kLxKTqxypsakw@mail.gmail.com
1 parent 029dea8 commit 31ae2aa

File tree

6 files changed

+44
-27
lines changed

6 files changed

+44
-27
lines changed

doc/src/sgml/ref/psql-ref.sgml

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4277,8 +4277,12 @@ bar
42774277
<para>
42784278
<literal>true</literal> if the last shell command
42794279
failed, <literal>false</literal> if it succeeded.
4280-
This applies to shell commands invoked via the <literal>\!</literal>
4281-
meta-command or backquote (<literal>`</literal>) expansion.
4280+
This applies to shell commands invoked via the <literal>\!</literal>,
4281+
<literal>\g</literal>, <literal>\o</literal>, <literal>\w</literal>,
4282+
and <literal>\copy</literal> meta-commands, as well as backquote
4283+
(<literal>`</literal>) expansion. Note that
4284+
for <literal>\o</literal>, this variable is updated when the output
4285+
pipe is closed by the next <literal>\o</literal> command.
42824286
See also <varname>SHELL_EXIT_CODE</varname>.
42834287
</para>
42844288
</listitem>
@@ -4292,8 +4296,12 @@ bar
42924296
0&ndash;127 represent program exit codes, 128&ndash;255
42934297
indicate termination by a signal, and -1 indicates failure
42944298
to launch a program or to collect its exit status.
4295-
This applies to shell commands invoked via the <literal>\!</literal>
4296-
meta-command or backquote (<literal>`</literal>) expansion.
4299+
This applies to shell commands invoked via the <literal>\!</literal>,
4300+
<literal>\g</literal>, <literal>\o</literal>, <literal>\w</literal>,
4301+
and <literal>\copy</literal> meta-commands, as well as backquote
4302+
(<literal>`</literal>) expansion. Note that
4303+
for <literal>\o</literal>, this variable is updated when the output
4304+
pipe is closed by the next <literal>\o</literal> command.
42974305
See also <varname>SHELL_ERROR</varname>.
42984306
</para>
42994307
</listitem>

src/bin/psql/command.c

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2734,6 +2734,7 @@ exec_command_write(PsqlScanState scan_state, bool active_branch,
27342734
pg_log_error("%s: %s", fname, wait_result_to_str(result));
27352735
status = PSQL_CMD_ERROR;
27362736
}
2737+
SetShellResultVariables(result);
27372738
}
27382739
else
27392740
{
@@ -5119,20 +5120,7 @@ do_shell(const char *command)
51195120
else
51205121
result = system(command);
51215122

5122-
if (result == 0)
5123-
{
5124-
SetVariable(pset.vars, "SHELL_EXIT_CODE", "0");
5125-
SetVariable(pset.vars, "SHELL_ERROR", "false");
5126-
}
5127-
else
5128-
{
5129-
int exit_code = wait_result_to_exit_code(result);
5130-
char buf[32];
5131-
5132-
snprintf(buf, sizeof(buf), "%d", exit_code);
5133-
SetVariable(pset.vars, "SHELL_EXIT_CODE", buf);
5134-
SetVariable(pset.vars, "SHELL_ERROR", "true");
5135-
}
5123+
SetShellResultVariables(result);
51365124

51375125
if (result == 127 || result == -1)
51385126
{

src/bin/psql/common.c

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ setQFout(const char *fname)
103103
if (pset.queryFout && pset.queryFout != stdout && pset.queryFout != stderr)
104104
{
105105
if (pset.queryFoutPipe)
106-
pclose(pset.queryFout);
106+
SetShellResultVariables(pclose(pset.queryFout));
107107
else
108108
fclose(pset.queryFout);
109109
}
@@ -449,6 +449,26 @@ SetResultVariables(PGresult *result, bool success)
449449
}
450450

451451

452+
/*
453+
* Set special variables from a shell command result
454+
* - SHELL_ERROR: true/false, whether command returned exit code 0
455+
* - SHELL_EXIT_CODE: exit code according to shell conventions
456+
*
457+
* The argument is a wait status as returned by wait(2) or waitpid(2),
458+
* which also applies to pclose(3) and system(3).
459+
*/
460+
void
461+
SetShellResultVariables(int wait_result)
462+
{
463+
char buf[32];
464+
465+
SetVariable(pset.vars, "SHELL_ERROR",
466+
(wait_result == 0) ? "false" : "true");
467+
snprintf(buf, sizeof(buf), "%d", wait_result_to_exit_code(wait_result));
468+
SetVariable(pset.vars, "SHELL_EXIT_CODE", buf);
469+
}
470+
471+
452472
/*
453473
* ClearOrSaveResult
454474
*
@@ -1652,7 +1672,7 @@ ExecQueryAndProcessResults(const char *query,
16521672
{
16531673
if (gfile_is_pipe)
16541674
{
1655-
pclose(gfile_fout);
1675+
SetShellResultVariables(pclose(gfile_fout));
16561676
restore_sigpipe_trap();
16571677
}
16581678
else
@@ -1870,7 +1890,7 @@ ExecQueryUsingCursor(const char *query, double *elapsed_msec)
18701890
/* close \g argument file/pipe */
18711891
if (is_pipe)
18721892
{
1873-
pclose(fout);
1893+
SetShellResultVariables(pclose(fout));
18741894
restore_sigpipe_trap();
18751895
}
18761896
else

src/bin/psql/common.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ extern sigjmp_buf sigint_interrupt_jmp;
2929

3030
extern void psql_setup_cancel_handler(void);
3131

32+
extern void SetShellResultVariables(int wait_result);
33+
3234
extern PGresult *PSQLexec(const char *query);
3335
extern int PSQLexecWatch(const char *query, const printQueryOpt *opt, FILE *printQueryFout);
3436

src/bin/psql/copy.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -391,6 +391,7 @@ do_copy(const char *args)
391391
}
392392
success = false;
393393
}
394+
SetShellResultVariables(pclose_rc);
394395
restore_sigpipe_trap();
395396
}
396397
else

src/bin/psql/psqlscanslash.l

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@
1818
*/
1919
#include "postgres_fe.h"
2020

21+
#include "common.h"
2122
#include "psqlscanslash.h"
22-
#include "settings.h"
2323

2424
#include "common/logging.h"
2525
#include "fe_utils/conditional.h"
@@ -807,7 +807,7 @@ evaluate_backtick(PsqlScanState state)
807807
if (fd)
808808
{
809809
/*
810-
* Although pclose's result always sets SHELL_EXIT_CODE, we
810+
* Although pclose's result always sets the shell result variables, we
811811
* historically have abandoned the backtick substitution only if it
812812
* returns -1.
813813
*/
@@ -839,10 +839,8 @@ evaluate_backtick(PsqlScanState state)
839839
appendBinaryPQExpBuffer(output_buf, cmd_output.data, cmd_output.len);
840840
}
841841

842-
/* And finally, set the shell error variables */
843-
snprintf(buf, sizeof(buf), "%d", wait_result_to_exit_code(exit_code));
844-
SetVariable(pset.vars, "SHELL_EXIT_CODE", buf);
845-
SetVariable(pset.vars, "SHELL_ERROR", (exit_code == 0) ? "false" : "true");
842+
/* And finally, set the shell result variables */
843+
SetShellResultVariables(exit_code);
846844

847845
termPQExpBuffer(&cmd_output);
848846
}

0 commit comments

Comments
 (0)