00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "postgres_fe.h"
00016
00017 #include <pwd.h>
00018 #include <signal.h>
00019 #include <unistd.h>
00020
00021 #include "common.h"
00022
00023 static void SetCancelConn(PGconn *conn);
00024 static void ResetCancelConn(void);
00025
00026 static PGcancel *volatile cancelConn = NULL;
00027
00028 #ifdef WIN32
00029 static CRITICAL_SECTION cancelConnLock;
00030 #endif
00031
00032
00033
00034
00035 const char *
00036 get_user_name(const char *progname)
00037 {
00038 #ifndef WIN32
00039 struct passwd *pw;
00040
00041 pw = getpwuid(geteuid());
00042 if (!pw)
00043 {
00044 fprintf(stderr, _("%s: could not obtain information about current user: %s\n"),
00045 progname, strerror(errno));
00046 exit(1);
00047 }
00048 return pw->pw_name;
00049 #else
00050 static char username[128];
00051 DWORD len = sizeof(username) - 1;
00052
00053 if (!GetUserName(username, &len))
00054 {
00055 fprintf(stderr, _("%s: could not get current user name: %s\n"),
00056 progname, strerror(errno));
00057 exit(1);
00058 }
00059 return username;
00060 #endif
00061 }
00062
00063
00064
00065
00066
00067
00068 void
00069 handle_help_version_opts(int argc, char *argv[],
00070 const char *fixed_progname, help_handler hlp)
00071 {
00072 if (argc > 1)
00073 {
00074 if (strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-?") == 0)
00075 {
00076 hlp(get_progname(argv[0]));
00077 exit(0);
00078 }
00079 if (strcmp(argv[1], "--version") == 0 || strcmp(argv[1], "-V") == 0)
00080 {
00081 printf("%s (PostgreSQL) " PG_VERSION "\n", fixed_progname);
00082 exit(0);
00083 }
00084 }
00085 }
00086
00087
00088
00089
00090
00091
00092 PGconn *
00093 connectDatabase(const char *dbname, const char *pghost, const char *pgport,
00094 const char *pguser, enum trivalue prompt_password,
00095 const char *progname, bool fail_ok)
00096 {
00097 PGconn *conn;
00098 char *password = NULL;
00099 bool new_pass;
00100
00101 if (prompt_password == TRI_YES)
00102 password = simple_prompt("Password: ", 100, false);
00103
00104
00105
00106
00107
00108 do
00109 {
00110 #define PARAMS_ARRAY_SIZE 7
00111 const char **keywords = pg_malloc(PARAMS_ARRAY_SIZE * sizeof(*keywords));
00112 const char **values = pg_malloc(PARAMS_ARRAY_SIZE * sizeof(*values));
00113
00114 keywords[0] = "host";
00115 values[0] = pghost;
00116 keywords[1] = "port";
00117 values[1] = pgport;
00118 keywords[2] = "user";
00119 values[2] = pguser;
00120 keywords[3] = "password";
00121 values[3] = password;
00122 keywords[4] = "dbname";
00123 values[4] = dbname;
00124 keywords[5] = "fallback_application_name";
00125 values[5] = progname;
00126 keywords[6] = NULL;
00127 values[6] = NULL;
00128
00129 new_pass = false;
00130 conn = PQconnectdbParams(keywords, values, true);
00131
00132 free(keywords);
00133 free(values);
00134
00135 if (!conn)
00136 {
00137 fprintf(stderr, _("%s: could not connect to database %s\n"),
00138 progname, dbname);
00139 exit(1);
00140 }
00141
00142 if (PQstatus(conn) == CONNECTION_BAD &&
00143 PQconnectionNeedsPassword(conn) &&
00144 password == NULL &&
00145 prompt_password != TRI_NO)
00146 {
00147 PQfinish(conn);
00148 password = simple_prompt("Password: ", 100, false);
00149 new_pass = true;
00150 }
00151 } while (new_pass);
00152
00153 if (password)
00154 free(password);
00155
00156
00157 if (PQstatus(conn) == CONNECTION_BAD)
00158 {
00159 if (fail_ok)
00160 {
00161 PQfinish(conn);
00162 return NULL;
00163 }
00164 fprintf(stderr, _("%s: could not connect to database %s: %s"),
00165 progname, dbname, PQerrorMessage(conn));
00166 exit(1);
00167 }
00168
00169 return conn;
00170 }
00171
00172
00173
00174
00175 PGconn *
00176 connectMaintenanceDatabase(const char *maintenance_db, const char *pghost,
00177 const char *pgport, const char *pguser,
00178 enum trivalue prompt_password,
00179 const char *progname)
00180 {
00181 PGconn *conn;
00182
00183
00184 if (maintenance_db)
00185 return connectDatabase(maintenance_db, pghost, pgport, pguser,
00186 prompt_password, progname, false);
00187
00188
00189 conn = connectDatabase("postgres", pghost, pgport, pguser, prompt_password,
00190 progname, true);
00191 if (!conn)
00192 conn = connectDatabase("template1", pghost, pgport, pguser,
00193 prompt_password, progname, false);
00194
00195 return conn;
00196 }
00197
00198
00199
00200
00201 PGresult *
00202 executeQuery(PGconn *conn, const char *query, const char *progname, bool echo)
00203 {
00204 PGresult *res;
00205
00206 if (echo)
00207 printf("%s\n", query);
00208
00209 res = PQexec(conn, query);
00210 if (!res ||
00211 PQresultStatus(res) != PGRES_TUPLES_OK)
00212 {
00213 fprintf(stderr, _("%s: query failed: %s"),
00214 progname, PQerrorMessage(conn));
00215 fprintf(stderr, _("%s: query was: %s\n"),
00216 progname, query);
00217 PQfinish(conn);
00218 exit(1);
00219 }
00220
00221 return res;
00222 }
00223
00224
00225
00226
00227
00228 void
00229 executeCommand(PGconn *conn, const char *query,
00230 const char *progname, bool echo)
00231 {
00232 PGresult *res;
00233
00234 if (echo)
00235 printf("%s\n", query);
00236
00237 res = PQexec(conn, query);
00238 if (!res ||
00239 PQresultStatus(res) != PGRES_COMMAND_OK)
00240 {
00241 fprintf(stderr, _("%s: query failed: %s"),
00242 progname, PQerrorMessage(conn));
00243 fprintf(stderr, _("%s: query was: %s\n"),
00244 progname, query);
00245 PQfinish(conn);
00246 exit(1);
00247 }
00248
00249 PQclear(res);
00250 }
00251
00252
00253
00254
00255
00256
00257
00258 bool
00259 executeMaintenanceCommand(PGconn *conn, const char *query, bool echo)
00260 {
00261 PGresult *res;
00262 bool r;
00263
00264 if (echo)
00265 printf("%s\n", query);
00266
00267 SetCancelConn(conn);
00268 res = PQexec(conn, query);
00269 ResetCancelConn();
00270
00271 r = (res && PQresultStatus(res) == PGRES_COMMAND_OK);
00272
00273 if (res)
00274 PQclear(res);
00275
00276 return r;
00277 }
00278
00279
00280
00281
00282
00283
00284 #define PG_YESLETTER gettext_noop("y")
00285
00286 #define PG_NOLETTER gettext_noop("n")
00287
00288 bool
00289 yesno_prompt(const char *question)
00290 {
00291 char prompt[256];
00292
00293
00294
00295
00296 snprintf(prompt, sizeof(prompt), _("%s (%s/%s) "),
00297 _(question), _(PG_YESLETTER), _(PG_NOLETTER));
00298
00299 for (;;)
00300 {
00301 char *resp;
00302
00303 resp = simple_prompt(prompt, 1, true);
00304
00305 if (strcmp(resp, _(PG_YESLETTER)) == 0)
00306 {
00307 free(resp);
00308 return true;
00309 }
00310 else if (strcmp(resp, _(PG_NOLETTER)) == 0)
00311 {
00312 free(resp);
00313 return false;
00314 }
00315
00316 free(resp);
00317 printf(_("Please answer \"%s\" or \"%s\".\n"),
00318 _(PG_YESLETTER), _(PG_NOLETTER));
00319 }
00320 }
00321
00322
00323
00324
00325
00326
00327 static void
00328 SetCancelConn(PGconn *conn)
00329 {
00330 PGcancel *oldCancelConn;
00331
00332 #ifdef WIN32
00333 EnterCriticalSection(&cancelConnLock);
00334 #endif
00335
00336
00337 oldCancelConn = cancelConn;
00338
00339
00340 cancelConn = NULL;
00341
00342 if (oldCancelConn != NULL)
00343 PQfreeCancel(oldCancelConn);
00344
00345 cancelConn = PQgetCancel(conn);
00346
00347 #ifdef WIN32
00348 LeaveCriticalSection(&cancelConnLock);
00349 #endif
00350 }
00351
00352
00353
00354
00355
00356
00357 static void
00358 ResetCancelConn(void)
00359 {
00360 PGcancel *oldCancelConn;
00361
00362 #ifdef WIN32
00363 EnterCriticalSection(&cancelConnLock);
00364 #endif
00365
00366 oldCancelConn = cancelConn;
00367
00368
00369 cancelConn = NULL;
00370
00371 if (oldCancelConn != NULL)
00372 PQfreeCancel(oldCancelConn);
00373
00374 #ifdef WIN32
00375 LeaveCriticalSection(&cancelConnLock);
00376 #endif
00377 }
00378
00379 #ifndef WIN32
00380
00381
00382
00383
00384
00385 static void
00386 handle_sigint(SIGNAL_ARGS)
00387 {
00388 int save_errno = errno;
00389 char errbuf[256];
00390
00391
00392 if (cancelConn != NULL)
00393 {
00394 if (PQcancel(cancelConn, errbuf, sizeof(errbuf)))
00395 fprintf(stderr, _("Cancel request sent\n"));
00396 else
00397 fprintf(stderr, _("Could not send cancel request: %s"), errbuf);
00398 }
00399
00400 errno = save_errno;
00401 }
00402
00403 void
00404 setup_cancel_handler(void)
00405 {
00406 pqsignal(SIGINT, handle_sigint);
00407 }
00408 #else
00409
00410
00411
00412
00413
00414
00415 static BOOL WINAPI
00416 consoleHandler(DWORD dwCtrlType)
00417 {
00418 char errbuf[256];
00419
00420 if (dwCtrlType == CTRL_C_EVENT ||
00421 dwCtrlType == CTRL_BREAK_EVENT)
00422 {
00423
00424 EnterCriticalSection(&cancelConnLock);
00425 if (cancelConn != NULL)
00426 {
00427 if (PQcancel(cancelConn, errbuf, sizeof(errbuf)))
00428 fprintf(stderr, _("Cancel request sent\n"));
00429 else
00430 fprintf(stderr, _("Could not send cancel request: %s"), errbuf);
00431 }
00432 LeaveCriticalSection(&cancelConnLock);
00433
00434 return TRUE;
00435 }
00436 else
00437
00438 return FALSE;
00439 }
00440
00441 void
00442 setup_cancel_handler(void)
00443 {
00444 InitializeCriticalSection(&cancelConnLock);
00445
00446 SetConsoleCtrlHandler(consoleHandler, TRUE);
00447 }
00448
00449 #endif