PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
util.c
Go to the documentation of this file.
1 /*
2  * util.c
3  *
4  * utility functions
5  *
6  * Copyright (c) 2010-2017, PostgreSQL Global Development Group
7  * src/bin/pg_upgrade/util.c
8  */
9 
10 #include "postgres_fe.h"
11 
12 #include "common/username.h"
13 #include "pg_upgrade.h"
14 
15 #include <signal.h>
16 
17 
19 
20 static void pg_log_v(eLogType type, const char *fmt, va_list ap) pg_attribute_printf(2, 0);
21 
22 
23 /*
24  * report_status()
25  *
26  * Displays the result of an operation (ok, failed, error message,...)
27  */
28 void
29 report_status(eLogType type, const char *fmt,...)
30 {
31  va_list args;
32  char message[MAX_STRING];
33 
34  va_start(args, fmt);
35  vsnprintf(message, sizeof(message), fmt, args);
36  va_end(args);
37 
38  pg_log(type, "%s\n", message);
39 }
40 
41 
42 /* force blank output for progress display */
43 void
45 {
46  /*
47  * In case nothing printed; pass a space so gcc doesn't complain about
48  * empty format string.
49  */
50  prep_status(" ");
51 }
52 
53 
54 /*
55  * prep_status
56  *
57  * Displays a message that describes an operation we are about to begin.
58  * We pad the message out to MESSAGE_WIDTH characters so that all of the "ok" and
59  * "failed" indicators line up nicely.
60  *
61  * A typical sequence would look like this:
62  * prep_status("about to flarb the next %d files", fileCount );
63  *
64  * if(( message = flarbFiles(fileCount)) == NULL)
65  * report_status(PG_REPORT, "ok" );
66  * else
67  * pg_log(PG_FATAL, "failed - %s\n", message );
68  */
69 void
70 prep_status(const char *fmt,...)
71 {
72  va_list args;
73  char message[MAX_STRING];
74 
75  va_start(args, fmt);
76  vsnprintf(message, sizeof(message), fmt, args);
77  va_end(args);
78 
79  if (strlen(message) > 0 && message[strlen(message) - 1] == '\n')
80  pg_log(PG_REPORT, "%s", message);
81  else
82  /* trim strings that don't end in a newline */
83  pg_log(PG_REPORT, "%-*s", MESSAGE_WIDTH, message);
84 }
85 
86 
87 static void
88 pg_log_v(eLogType type, const char *fmt, va_list ap)
89 {
90  char message[QUERY_ALLOC];
91 
92  vsnprintf(message, sizeof(message), _(fmt), ap);
93 
94  /* PG_VERBOSE and PG_STATUS are only output in verbose mode */
95  /* fopen() on log_opts.internal might have failed, so check it */
96  if (((type != PG_VERBOSE && type != PG_STATUS) || log_opts.verbose) &&
97  log_opts.internal != NULL)
98  {
99  if (type == PG_STATUS)
100  /* status messages need two leading spaces and a newline */
101  fprintf(log_opts.internal, " %s\n", message);
102  else
103  fprintf(log_opts.internal, "%s", message);
104  fflush(log_opts.internal);
105  }
106 
107  switch (type)
108  {
109  case PG_VERBOSE:
110  if (log_opts.verbose)
111  printf("%s", message);
112  break;
113 
114  case PG_STATUS:
115  /* for output to a display, do leading truncation and append \r */
116  if (isatty(fileno(stdout)))
117  /* -2 because we use a 2-space indent */
118  printf(" %s%-*.*s\r",
119  /* prefix with "..." if we do leading truncation */
120  strlen(message) <= MESSAGE_WIDTH - 2 ? "" : "...",
121  MESSAGE_WIDTH - 2, MESSAGE_WIDTH - 2,
122  /* optional leading truncation */
123  strlen(message) <= MESSAGE_WIDTH - 2 ? message :
124  message + strlen(message) - MESSAGE_WIDTH + 3 + 2);
125  else
126  printf(" %s\n", message);
127  break;
128 
129  case PG_REPORT:
130  case PG_WARNING:
131  printf("%s", message);
132  break;
133 
134  case PG_FATAL:
135  printf("\n%s", message);
136  printf(_("Failure, exiting\n"));
137  exit(1);
138  break;
139 
140  default:
141  break;
142  }
143  fflush(stdout);
144 }
145 
146 
147 void
148 pg_log(eLogType type, const char *fmt,...)
149 {
150  va_list args;
151 
152  va_start(args, fmt);
153  pg_log_v(type, fmt, args);
154  va_end(args);
155 }
156 
157 
158 void
159 pg_fatal(const char *fmt,...)
160 {
161  va_list args;
162 
163  va_start(args, fmt);
164  pg_log_v(PG_FATAL, fmt, args);
165  va_end(args);
166  printf(_("Failure, exiting\n"));
167  exit(1);
168 }
169 
170 
171 void
172 check_ok(void)
173 {
174  /* all seems well */
175  report_status(PG_REPORT, "ok");
176  fflush(stdout);
177 }
178 
179 
180 /*
181  * quote_identifier()
182  * Properly double-quote a SQL identifier.
183  *
184  * The result should be pg_free'd, but most callers don't bother because
185  * memory leakage is not a big deal in this program.
186  */
187 char *
188 quote_identifier(const char *s)
189 {
190  char *result = pg_malloc(strlen(s) * 2 + 3);
191  char *r = result;
192 
193  *r++ = '"';
194  while (*s)
195  {
196  if (*s == '"')
197  *r++ = *s;
198  *r++ = *s;
199  s++;
200  }
201  *r++ = '"';
202  *r++ = '\0';
203 
204  return result;
205 }
206 
207 
208 /*
209  * get_user_info()
210  */
211 int
212 get_user_info(char **user_name_p)
213 {
214  int user_id;
215  const char *user_name;
216  char *errstr;
217 
218 #ifndef WIN32
219  user_id = geteuid();
220 #else
221  user_id = 1;
222 #endif
223 
224  user_name = get_user_name(&errstr);
225  if (!user_name)
226  pg_fatal("%s\n", errstr);
227 
228  /* make a copy */
229  *user_name_p = pg_strdup(user_name);
230 
231  return user_id;
232 }
233 
234 
235 /*
236  * str2uint()
237  *
238  * convert string to oid
239  */
240 unsigned int
241 str2uint(const char *str)
242 {
243  return strtoul(str, NULL, 10);
244 }
245 
246 
247 /*
248  * pg_putenv()
249  *
250  * This is like putenv(), but takes two arguments.
251  * It also does unsetenv() if val is NULL.
252  */
253 void
254 pg_putenv(const char *var, const char *val)
255 {
256  if (val)
257  {
258 #ifndef WIN32
259  char *envstr;
260 
261  envstr = psprintf("%s=%s", var, val);
262  putenv(envstr);
263 
264  /*
265  * Do not free envstr because it becomes part of the environment on
266  * some operating systems. See port/unsetenv.c::unsetenv.
267  */
268 #else
269  SetEnvironmentVariableA(var, val);
270 #endif
271  }
272  else
273  {
274 #ifndef WIN32
275  unsetenv(var);
276 #else
277  SetEnvironmentVariableA(var, "");
278 #endif
279  }
280 }
static void void report_status(eLogType type, const char *fmt,...)
Definition: util.c:29
#define MESSAGE_WIDTH
Definition: logging.c:28
void * pg_malloc(size_t size)
Definition: fe_memutils.c:47
char * quote_identifier(const char *s)
Definition: util.c:188
char * psprintf(const char *fmt,...)
Definition: psprintf.c:46
static void pg_log_v(eLogType type, const char *fmt, va_list ap) pg_attribute_printf(2
Definition: util.c:88
LogOpts log_opts
Definition: util.c:18
int get_user_info(char **user_name_p)
Definition: util.c:212
#define putenv(x)
Definition: win32.h:411
#define QUERY_ALLOC
Definition: logging.c:26
void end_progress_output(void)
Definition: util.c:44
#define pg_attribute_printf(f, a)
Definition: c.h:627
const char * get_user_name(char **errstr)
Definition: username.c:31
int int vsnprintf(char *str, size_t count, const char *fmt, va_list args)
void pg_fatal(const char *fmt,...)
Definition: util.c:159
eLogType
Definition: logging.h:22
void pg_putenv(const char *var, const char *val)
Definition: util.c:254
void check_ok(void)
Definition: util.c:172
char * pg_strdup(const char *in)
Definition: fe_memutils.c:85
unsigned int str2uint(const char *str)
Definition: util.c:241
bool verbose
Definition: pg_upgrade.h:287
#define MAX_STRING
Definition: pg_upgrade.h:21
FILE * internal
Definition: pg_upgrade.h:286
#define unsetenv(x)
Definition: win32.h:412
void pg_log(eLogType type, const char *fmt,...)
Definition: util.c:148
void prep_status(const char *fmt,...)
Definition: util.c:70
#define _(x)
Definition: elog.c:84
long val
Definition: informix.c:689