1 /*-------------------------------------------------------------------------
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
12 *-------------------------------------------------------------------------
15 #include "postgres_fe.h"
22 #include "libpq/pqsignal.h"
24 static void SetCancelConn(PGconn
*conn
);
25 static void ResetCancelConn(void);
27 static PGcancel
*volatile cancelConn
= NULL
;
30 static CRITICAL_SECTION cancelConnLock
;
34 * Returns the current user name.
37 get_user_name(const char *progname
)
42 pw
= getpwuid(geteuid());
45 fprintf(stderr
, _("%s: could not obtain information about current user: %s\n"),
46 progname
, strerror(errno
));
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
));
66 * Provide strictly harmonized handling of --help and --version
70 handle_help_version_opts(int argc
, char *argv
[],
71 const char *fixed_progname
, help_handler hlp
)
75 if (strcmp(argv
[1], "--help") == 0 || strcmp(argv
[1], "-?") == 0)
77 hlp(get_progname(argv
[0]));
80 if (strcmp(argv
[1], "--version") == 0 || strcmp(argv
[1], "-V") == 0)
82 printf("%s (PostgreSQL) " PG_VERSION
"\n", fixed_progname
);
90 * Make a database connection with the given parameters. An
91 * interactive password prompt is automatically issued if required.
94 connectDatabase(const char *dbname
, const char *pghost
, const char *pgport
,
95 const char *pguser
, enum trivalue prompt_password
,
99 char *password
= NULL
;
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
112 conn
= PQsetdbLogin(pghost
, pgport
, NULL
, NULL
, dbname
, pguser
, password
);
116 fprintf(stderr
, _("%s: could not connect to database %s\n"),
121 if (PQstatus(conn
) == CONNECTION_BAD
&&
122 PQconnectionNeedsPassword(conn
) &&
124 prompt_password
!= TRI_NO
)
127 password
= simple_prompt("Password: ", 100, false);
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
));
148 * Run a query, return the results, exit program on failure.
151 executeQuery(PGconn
*conn
, const char *query
, const char *progname
, bool echo
)
156 printf("%s\n", query
);
158 res
= PQexec(conn
, query
);
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"),
175 * As above for a SQL command (which returns nothing).
178 executeCommand(PGconn
*conn
, const char *query
,
179 const char *progname
, bool echo
)
184 printf("%s\n", query
);
186 res
= PQexec(conn
, query
);
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"),
203 * As above for a SQL maintenance command (returns command success).
204 * Command is executed with a cancel handler set, so Ctrl-C can
208 executeMaintenanceCommand(PGconn
*conn
, const char *query
, bool echo
)
214 printf("%s\n", query
);
217 res
= PQexec(conn
, query
);
220 r
= (res
&& PQresultStatus(res
) == PGRES_COMMAND_OK
);
229 * "Safe" wrapper around strdup(). Pulled from psql/common.c
232 pg_strdup(const char *string
)
238 fprintf(stderr
, _("pg_strdup: cannot duplicate null pointer (internal error)\n"));
241 tmp
= strdup(string
);
244 fprintf(stderr
, _("out of memory\n"));
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")
260 yesno_prompt(const char *question
)
265 * translator: This is a question followed by the translated options for
268 snprintf(prompt
, sizeof(prompt
), _("%s (%s/%s) "),
269 _(question
), _(PG_YESLETTER
), _(PG_NOLETTER
));
275 resp
= simple_prompt(prompt
, 1, true);
277 if (strcmp(resp
, _(PG_YESLETTER
)) == 0)
282 else if (strcmp(resp
, _(PG_NOLETTER
)) == 0)
289 printf(_("Please answer \"%s\" or \"%s\".\n"),
290 _(PG_YESLETTER
), _(PG_NOLETTER
));
297 * Set cancelConn to point to the current database connection.
300 SetCancelConn(PGconn
*conn
)
302 PGcancel
*oldCancelConn
;
305 EnterCriticalSection(&cancelConnLock
);
308 /* Free the old one if we have one */
309 oldCancelConn
= cancelConn
;
311 /* be sure handle_sigint doesn't use pointer while freeing */
314 if (oldCancelConn
!= NULL
)
315 PQfreeCancel(oldCancelConn
);
317 cancelConn
= PQgetCancel(conn
);
320 LeaveCriticalSection(&cancelConnLock
);
327 * Free the current cancel connection, if any, and set to NULL.
330 ResetCancelConn(void)
332 PGcancel
*oldCancelConn
;
335 EnterCriticalSection(&cancelConnLock
);
338 oldCancelConn
= cancelConn
;
340 /* be sure handle_sigint doesn't use pointer while freeing */
343 if (oldCancelConn
!= NULL
)
344 PQfreeCancel(oldCancelConn
);
347 LeaveCriticalSection(&cancelConnLock
);
353 * Handle interrupt signals by cancelling the current command,
354 * if it's being executed through executeMaintenanceCommand(),
355 * and thus has a cancelConn set.
358 handle_sigint(SIGNAL_ARGS
)
360 int save_errno
= errno
;
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"));
369 fprintf(stderr
, _("Could not send cancel request: %s"), errbuf
);
372 errno
= save_errno
; /* just in case the write changed it */
376 setup_cancel_handler(void)
378 pqsignal(SIGINT
, handle_sigint
);
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.
388 consoleHandler(DWORD dwCtrlType
)
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"));
402 fprintf(stderr
, _("Could not send cancel request: %s"), errbuf
);
404 LeaveCriticalSection(&cancelConnLock
);
409 /* Return FALSE for any signals not being handled */
414 setup_cancel_handler(void)
416 InitializeCriticalSection(&cancelConnLock
);
418 SetConsoleCtrlHandler(consoleHandler
, TRUE
);