aboutsummaryrefslogtreecommitdiff
path: root/contrib/pg_upgrade/exec.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/pg_upgrade/exec.c')
-rw-r--r--contrib/pg_upgrade/exec.c80
1 files changed, 42 insertions, 38 deletions
diff --git a/contrib/pg_upgrade/exec.c b/contrib/pg_upgrade/exec.c
index 6f993df53a3..c75d9dbcc97 100644
--- a/contrib/pg_upgrade/exec.c
+++ b/contrib/pg_upgrade/exec.c
@@ -26,77 +26,81 @@ static int win32_check_directory_write_permissions(void);
/*
* exec_prog()
+ * Execute an external program with stdout/stderr redirected, and report
+ * errors
*
- * Formats a command from the given argument list and executes that
- * command. If the command executes, exec_prog() returns 1 otherwise
- * exec_prog() logs an error message and returns 0. Either way, the command
- * line to be executed is saved to the specified log file.
+ * Formats a command from the given argument list, logs it to the log file,
+ * and attempts to execute that command. If the command executes
+ * successfully, exec_prog() returns true.
*
- * If throw_error is TRUE, this function will throw a PG_FATAL error
- * instead of returning should an error occur. The command it appended
- * to log_file; opt_log_file is used in error messages.
+ * If the command fails, an error message is saved to the specified log_file.
+ * If throw_error is true, this raises a PG_FATAL error and pg_upgrade
+ * terminates; otherwise it is just reported as PG_REPORT and exec_prog()
+ * returns false.
*/
-int
-exec_prog(bool throw_error, bool is_priv, const char *log_file,
- const char *opt_log_file, const char *fmt,...)
+bool
+exec_prog(const char *log_file, const char *opt_log_file,
+ bool throw_error, const char *fmt,...)
{
- va_list args;
int result;
- int retval;
- char cmd[MAXPGPATH];
+ int written;
+#define MAXCMDLEN (2 * MAXPGPATH)
+ char cmd[MAXCMDLEN];
mode_t old_umask = 0;
FILE *log;
+ va_list ap;
- if (is_priv)
- old_umask = umask(S_IRWXG | S_IRWXO);
+ old_umask = umask(S_IRWXG | S_IRWXO);
- va_start(args, fmt);
- vsnprintf(cmd, MAXPGPATH, fmt, args);
- va_end(args);
+ written = strlcpy(cmd, SYSTEMQUOTE, strlen(SYSTEMQUOTE));
+ va_start(ap, fmt);
+ written += vsnprintf(cmd + written, MAXCMDLEN - written, fmt, ap);
+ va_end(ap);
+ if (written >= MAXCMDLEN)
+ pg_log(PG_FATAL, "command too long\n");
+ written += snprintf(cmd + written, MAXCMDLEN - written,
+ " >> \"%s\" 2>&1" SYSTEMQUOTE, log_file);
+ if (written >= MAXCMDLEN)
+ pg_log(PG_FATAL, "command too long\n");
if ((log = fopen_priv(log_file, "a+")) == NULL)
pg_log(PG_FATAL, "cannot write to log file %s\n", log_file);
pg_log(PG_VERBOSE, "%s\n", cmd);
fprintf(log, "command: %s\n", cmd);
+
/*
- * In Windows, we must close then reopen the log file so the file is
- * not open while the command is running, or we get a share violation.
+ * In Windows, we must close the log file at this point so the file is not
+ * open while the command is running, or we get a share violation.
*/
fclose(log);
result = system(cmd);
- if (is_priv)
- umask(old_umask);
+ umask(old_umask);
if (result != 0)
{
- char opt_string[MAXPGPATH];
-
- /* Create string for optional second log file */
- if (opt_log_file)
- snprintf(opt_string, sizeof(opt_string), " or \"%s\"", opt_log_file);
- else
- opt_string[0] = '\0';
-
report_status(PG_REPORT, "*failure*");
fflush(stdout);
pg_log(PG_VERBOSE, "There were problems executing \"%s\"\n", cmd);
- pg_log(throw_error ? PG_FATAL : PG_REPORT,
- "Consult the last few lines of \"%s\"%s for\n"
- "the probable cause of the failure.\n",
- log_file, opt_string);
- retval = 1;
+ if (opt_log_file)
+ pg_log(throw_error ? PG_FATAL : PG_REPORT,
+ "Consult the last few lines of \"%s\" or \"%s\" for\n"
+ "the probable cause of the failure.\n",
+ log_file, opt_log_file);
+ else
+ pg_log(throw_error ? PG_FATAL : PG_REPORT,
+ "Consult the last few lines of \"%s\" for\n"
+ "the probable cause of the failure.\n",
+ log_file);
}
- else
- retval = 0;
if ((log = fopen_priv(log_file, "a+")) == NULL)
pg_log(PG_FATAL, "cannot write to log file %s\n", log_file);
fprintf(log, "\n\n");
fclose(log);
- return retval;
+ return result == 0;
}