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