Fix a few errors in comments. Patch by Fujii Masao, plus the one in
[PostgreSQL.git] / src / bin / scripts / common.c
blobbe17ab8c93f691c41abc905ed6155c0059459d72
1 /*-------------------------------------------------------------------------
3 * common.c
4 * Common support routines for bin/scripts/
7 * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
8 * Portions Copyright (c) 1994, Regents of the University of California
10 * $PostgreSQL$
12 *-------------------------------------------------------------------------
15 #include "postgres_fe.h"
17 #include <pwd.h>
18 #include <signal.h>
19 #include <unistd.h>
21 #include "common.h"
22 #include "libpq/pqsignal.h"
24 static void SetCancelConn(PGconn *conn);
25 static void ResetCancelConn(void);
27 static PGcancel *volatile cancelConn = NULL;
29 #ifdef WIN32
30 static CRITICAL_SECTION cancelConnLock;
31 #endif
34 * Returns the current user name.
36 const char *
37 get_user_name(const char *progname)
39 #ifndef WIN32
40 struct passwd *pw;
42 pw = getpwuid(geteuid());
43 if (!pw)
45 fprintf(stderr, _("%s: could not obtain information about current user: %s\n"),
46 progname, strerror(errno));
47 exit(1);
49 return pw->pw_name;
50 #else
51 static char username[128]; /* remains after function exit */
52 DWORD len = sizeof(username) - 1;
54 if (!GetUserName(username, &len))
56 fprintf(stderr, _("%s: could not get current user name: %s\n"),
57 progname, strerror(errno));
58 exit(1);
60 return username;
61 #endif
66 * Provide strictly harmonized handling of --help and --version
67 * options.
69 void
70 handle_help_version_opts(int argc, char *argv[],
71 const char *fixed_progname, help_handler hlp)
73 if (argc > 1)
75 if (strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-?") == 0)
77 hlp(get_progname(argv[0]));
78 exit(0);
80 if (strcmp(argv[1], "--version") == 0 || strcmp(argv[1], "-V") == 0)
82 printf("%s (PostgreSQL) " PG_VERSION "\n", fixed_progname);
83 exit(0);
90 * Make a database connection with the given parameters. An
91 * interactive password prompt is automatically issued if required.
93 PGconn *
94 connectDatabase(const char *dbname, const char *pghost, const char *pgport,
95 const char *pguser, enum trivalue prompt_password,
96 const char *progname)
98 PGconn *conn;
99 char *password = NULL;
100 bool new_pass;
102 if (prompt_password == TRI_YES)
103 password = simple_prompt("Password: ", 100, false);
106 * Start the connection. Loop until we have a password if requested by
107 * backend.
111 new_pass = false;
112 conn = PQsetdbLogin(pghost, pgport, NULL, NULL, dbname, pguser, password);
114 if (!conn)
116 fprintf(stderr, _("%s: could not connect to database %s\n"),
117 progname, dbname);
118 exit(1);
121 if (PQstatus(conn) == CONNECTION_BAD &&
122 PQconnectionNeedsPassword(conn) &&
123 password == NULL &&
124 prompt_password != TRI_NO)
126 PQfinish(conn);
127 password = simple_prompt("Password: ", 100, false);
128 new_pass = true;
130 } while (new_pass);
132 if (password)
133 free(password);
135 /* check to see that the backend connection was successfully made */
136 if (PQstatus(conn) == CONNECTION_BAD)
138 fprintf(stderr, _("%s: could not connect to database %s: %s"),
139 progname, dbname, PQerrorMessage(conn));
140 exit(1);
143 return conn;
148 * Run a query, return the results, exit program on failure.
150 PGresult *
151 executeQuery(PGconn *conn, const char *query, const char *progname, bool echo)
153 PGresult *res;
155 if (echo)
156 printf("%s\n", query);
158 res = PQexec(conn, query);
159 if (!res ||
160 PQresultStatus(res) != PGRES_TUPLES_OK)
162 fprintf(stderr, _("%s: query failed: %s"),
163 progname, PQerrorMessage(conn));
164 fprintf(stderr, _("%s: query was: %s\n"),
165 progname, query);
166 PQfinish(conn);
167 exit(1);
170 return res;
175 * As above for a SQL command (which returns nothing).
177 void
178 executeCommand(PGconn *conn, const char *query,
179 const char *progname, bool echo)
181 PGresult *res;
183 if (echo)
184 printf("%s\n", query);
186 res = PQexec(conn, query);
187 if (!res ||
188 PQresultStatus(res) != PGRES_COMMAND_OK)
190 fprintf(stderr, _("%s: query failed: %s"),
191 progname, PQerrorMessage(conn));
192 fprintf(stderr, _("%s: query was: %s\n"),
193 progname, query);
194 PQfinish(conn);
195 exit(1);
198 PQclear(res);
203 * As above for a SQL maintenance command (returns command success).
204 * Command is executed with a cancel handler set, so Ctrl-C can
205 * interrupt it.
207 bool
208 executeMaintenanceCommand(PGconn *conn, const char *query, bool echo)
210 PGresult *res;
211 bool r;
213 if (echo)
214 printf("%s\n", query);
216 SetCancelConn(conn);
217 res = PQexec(conn, query);
218 ResetCancelConn();
220 r = (res && PQresultStatus(res) == PGRES_COMMAND_OK);
222 if (res)
223 PQclear(res);
225 return r;
229 * "Safe" wrapper around strdup(). Pulled from psql/common.c
231 char *
232 pg_strdup(const char *string)
234 char *tmp;
236 if (!string)
238 fprintf(stderr, _("pg_strdup: cannot duplicate null pointer (internal error)\n"));
239 exit(EXIT_FAILURE);
241 tmp = strdup(string);
242 if (!tmp)
244 fprintf(stderr, _("out of memory\n"));
245 exit(EXIT_FAILURE);
247 return tmp;
251 * Check yes/no answer in a localized way. 1=yes, 0=no, -1=neither.
254 /* translator: abbreviation for "yes" */
255 #define PG_YESLETTER gettext_noop("y")
256 /* translator: abbreviation for "no" */
257 #define PG_NOLETTER gettext_noop("n")
259 bool
260 yesno_prompt(const char *question)
262 char prompt[256];
265 * translator: This is a question followed by the translated options for
266 * "yes" and "no".
268 snprintf(prompt, sizeof(prompt), _("%s (%s/%s) "),
269 _(question), _(PG_YESLETTER), _(PG_NOLETTER));
271 for (;;)
273 char *resp;
275 resp = simple_prompt(prompt, 1, true);
277 if (strcmp(resp, _(PG_YESLETTER)) == 0)
279 free(resp);
280 return true;
282 else if (strcmp(resp, _(PG_NOLETTER)) == 0)
284 free(resp);
285 return false;
288 free(resp);
289 printf(_("Please answer \"%s\" or \"%s\".\n"),
290 _(PG_YESLETTER), _(PG_NOLETTER));
295 * SetCancelConn
297 * Set cancelConn to point to the current database connection.
299 static void
300 SetCancelConn(PGconn *conn)
302 PGcancel *oldCancelConn;
304 #ifdef WIN32
305 EnterCriticalSection(&cancelConnLock);
306 #endif
308 /* Free the old one if we have one */
309 oldCancelConn = cancelConn;
311 /* be sure handle_sigint doesn't use pointer while freeing */
312 cancelConn = NULL;
314 if (oldCancelConn != NULL)
315 PQfreeCancel(oldCancelConn);
317 cancelConn = PQgetCancel(conn);
319 #ifdef WIN32
320 LeaveCriticalSection(&cancelConnLock);
321 #endif
325 * ResetCancelConn
327 * Free the current cancel connection, if any, and set to NULL.
329 static void
330 ResetCancelConn(void)
332 PGcancel *oldCancelConn;
334 #ifdef WIN32
335 EnterCriticalSection(&cancelConnLock);
336 #endif
338 oldCancelConn = cancelConn;
340 /* be sure handle_sigint doesn't use pointer while freeing */
341 cancelConn = NULL;
343 if (oldCancelConn != NULL)
344 PQfreeCancel(oldCancelConn);
346 #ifdef WIN32
347 LeaveCriticalSection(&cancelConnLock);
348 #endif
351 #ifndef WIN32
353 * Handle interrupt signals by cancelling the current command,
354 * if it's being executed through executeMaintenanceCommand(),
355 * and thus has a cancelConn set.
357 static void
358 handle_sigint(SIGNAL_ARGS)
360 int save_errno = errno;
361 char errbuf[256];
363 /* Send QueryCancel if we are processing a database query */
364 if (cancelConn != NULL)
366 if (PQcancel(cancelConn, errbuf, sizeof(errbuf)))
367 fprintf(stderr, _("Cancel request sent\n"));
368 else
369 fprintf(stderr, _("Could not send cancel request: %s"), errbuf);
372 errno = save_errno; /* just in case the write changed it */
375 void
376 setup_cancel_handler(void)
378 pqsignal(SIGINT, handle_sigint);
380 #else /* WIN32 */
383 * Console control handler for Win32. Note that the control handler will
384 * execute on a *different thread* than the main one, so we need to do
385 * proper locking around those structures.
387 static BOOL WINAPI
388 consoleHandler(DWORD dwCtrlType)
390 char errbuf[256];
392 if (dwCtrlType == CTRL_C_EVENT ||
393 dwCtrlType == CTRL_BREAK_EVENT)
395 /* Send QueryCancel if we are processing a database query */
396 EnterCriticalSection(&cancelConnLock);
397 if (cancelConn != NULL)
399 if (PQcancel(cancelConn, errbuf, sizeof(errbuf)))
400 fprintf(stderr, _("Cancel request sent\n"));
401 else
402 fprintf(stderr, _("Could not send cancel request: %s"), errbuf);
404 LeaveCriticalSection(&cancelConnLock);
406 return TRUE;
408 else
409 /* Return FALSE for any signals not being handled */
410 return FALSE;
413 void
414 setup_cancel_handler(void)
416 InitializeCriticalSection(&cancelConnLock);
418 SetConsoleCtrlHandler(consoleHandler, TRUE);
421 #endif /* WIN32 */