*
* utility functions
*
- * Copyright (c) 2010, PostgreSQL Global Development Group
+ * Copyright (c) 2010-2014, PostgreSQL Global Development Group
* contrib/pg_upgrade/util.c
*/
+#include "postgres_fe.h"
+
+#include "common/username.h"
#include "pg_upgrade.h"
#include <signal.h>
-LogOpts log_opts;
+LogOpts log_opts;
/*
* report_status()
}
+/* force blank output for progress display */
+void
+end_progress_output(void)
+{
+ /*
+ * In case nothing printed; pass a space so gcc doesn't complain about
+ * empty format string.
+ */
+ prep_status(" ");
+}
+
+
/*
* prep_status
*
* if(( message = flarbFiles(fileCount)) == NULL)
* report_status(PG_REPORT, "ok" );
* else
- * pg_log(PG_FATAL, "failed - %s", message );
+ * pg_log(PG_FATAL, "failed - %s\n", message );
*/
void
prep_status(const char *fmt,...)
if (strlen(message) > 0 && message[strlen(message) - 1] == '\n')
pg_log(PG_REPORT, "%s", message);
else
- pg_log(PG_REPORT, "%-" MESSAGE_WIDTH "s", message);
+ /* trim strings that don't end in a newline */
+ pg_log(PG_REPORT, "%-*s", MESSAGE_WIDTH, message);
}
+static
+__attribute__((format(PG_PRINTF_ATTRIBUTE, 2, 0)))
void
-pg_log(eLogType type, char *fmt,...)
+pg_log_v(eLogType type, const char *fmt, va_list ap)
{
- va_list args;
char message[MAX_STRING];
- va_start(args, fmt);
- vsnprintf(message, sizeof(message), fmt, args);
- va_end(args);
+ vsnprintf(message, sizeof(message), fmt, ap);
- if (log_opts.fd != NULL)
+ /* PG_VERBOSE and PG_STATUS are only output in verbose mode */
+ /* fopen() on log_opts.internal might have failed, so check it */
+ if (((type != PG_VERBOSE && type != PG_STATUS) || log_opts.verbose) &&
+ log_opts.internal != NULL)
{
- fwrite(message, strlen(message), 1, log_opts.fd);
- /* if we are using OVERWRITE_MESSAGE, add newline */
- if (strchr(message, '\r') != NULL)
- fwrite("\n", 1, 1, log_opts.fd);
- fflush(log_opts.fd);
+ if (type == PG_STATUS)
+ /* status messages need two leading spaces and a newline */
+ fprintf(log_opts.internal, " %s\n", message);
+ else
+ fprintf(log_opts.internal, "%s", message);
+ fflush(log_opts.internal);
}
switch (type)
{
- case PG_INFO:
+ case PG_VERBOSE:
if (log_opts.verbose)
printf("%s", _(message));
break;
+ case PG_STATUS:
+ /* for output to a display, do leading truncation and append \r */
+ if (isatty(fileno(stdout)))
+ /* -2 because we use a 2-space indent */
+ printf(" %s%-*.*s\r",
+ /* prefix with "..." if we do leading truncation */
+ strlen(message) <= MESSAGE_WIDTH - 2 ? "" : "...",
+ MESSAGE_WIDTH - 2, MESSAGE_WIDTH - 2,
+ /* optional leading truncation */
+ strlen(message) <= MESSAGE_WIDTH - 2 ? message :
+ message + strlen(message) - MESSAGE_WIDTH + 3 + 2);
+ else
+ printf(" %s\n", _(message));
+ break;
+
case PG_REPORT:
case PG_WARNING:
printf("%s", _(message));
break;
case PG_FATAL:
- printf("%s", "\n");
- printf("%s", _(message));
- exit_nicely(true);
- break;
-
- case PG_DEBUG:
- if (log_opts.debug)
- fprintf(log_opts.debug_fd, "%s\n", _(message));
+ printf("\n%s", _(message));
+ printf("Failure, exiting\n");
+ exit(1);
break;
default:
}
+void
+pg_log(eLogType type, const char *fmt,...)
+{
+ va_list args;
+
+ va_start(args, fmt);
+ pg_log_v(type, fmt, args);
+ va_end(args);
+}
+
+
+void
+pg_fatal(const char *fmt,...)
+{
+ va_list args;
+
+ va_start(args, fmt);
+ pg_log_v(PG_FATAL, fmt, args);
+ va_end(args);
+ printf("Failure, exiting\n");
+ exit(1);
+}
+
+
void
check_ok(void)
{
/*
* get_user_info()
- * (copied from initdb.c) find the current user
*/
int
-get_user_info(char **user_name)
+get_user_info(char **user_name_p)
{
int user_id;
+ const char *user_name;
+ char *errstr;
#ifndef WIN32
- struct passwd *pw = getpwuid(geteuid());
-
user_id = geteuid();
-#else /* the windows code */
- struct passwd_win32
- {
- int pw_uid;
- char pw_name[128];
- } pass_win32;
- struct passwd_win32 *pw = &pass_win32;
- DWORD pwname_size = sizeof(pass_win32.pw_name) - 1;
-
- GetUserName(pw->pw_name, &pwname_size);
-
+#else
user_id = 1;
#endif
- *user_name = pg_strdup(pw->pw_name);
-
- return user_id;
-}
-
-
-void
-exit_nicely(bool need_cleanup)
-{
- stop_postmaster(true, true);
-
- pg_free(log_opts.filename);
-
- if (log_opts.fd)
- fclose(log_opts.fd);
-
- if (log_opts.debug_fd)
- fclose(log_opts.debug_fd);
+ user_name = get_user_name(&errstr);
+ if (!user_name)
+ pg_fatal("%s\n", errstr);
- /* terminate any running instance of postmaster */
- if (os_info.postmasterPID != 0)
- kill(os_info.postmasterPID, SIGTERM);
+ /* make a copy */
+ *user_name_p = pg_strdup(user_name);
- if (need_cleanup)
- {
- /*
- * FIXME must delete intermediate files
- */
- exit(1);
- }
- else
- exit(0);
-}
-
-
-void *
-pg_malloc(int n)
-{
- void *p = malloc(n);
-
- if (p == NULL)
- pg_log(PG_FATAL, "%s: out of memory\n", os_info.progname);
-
- return p;
-}
-
-
-void
-pg_free(void *p)
-{
- if (p != NULL)
- free(p);
-}
-
-
-char *
-pg_strdup(const char *s)
-{
- char *result = strdup(s);
-
- if (result == NULL)
- pg_log(PG_FATAL, "%s: out of memory\n", os_info.progname);
-
- return result;
+ return user_id;
}
#ifdef WIN32
_dosmaperr(GetLastError());
#endif
- return strdup(strerror(errNum));
+ return pg_strdup(strerror(errNum));
}
{
return strtoul(str, NULL, 10);
}
+
+
+/*
+ * pg_putenv()
+ *
+ * This is like putenv(), but takes two arguments.
+ * It also does unsetenv() if val is NULL.
+ */
+void
+pg_putenv(const char *var, const char *val)
+{
+ if (val)
+ {
+#ifndef WIN32
+ char *envstr;
+
+ envstr = psprintf("%s=%s", var, val);
+ putenv(envstr);
+
+ /*
+ * Do not free envstr because it becomes part of the environment on
+ * some operating systems. See port/unsetenv.c::unsetenv.
+ */
+#else
+ SetEnvironmentVariableA(var, val);
+#endif
+ }
+ else
+ {
+#ifndef WIN32
+ unsetenv(var);
+#else
+ SetEnvironmentVariableA(var, "");
+#endif
+ }
+}