]> granicus.if.org Git - postgresql/blob - src/bin/pg_dump/pg_dumpall.c
Quote database name properly when invoking pg_dump. Per report from
[postgresql] / src / bin / pg_dump / pg_dumpall.c
1 /*-------------------------------------------------------------------------
2  *
3  * pg_dumpall
4  *
5  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
6  * Portions Copyright (c) 1994, Regents of the University of California
7  *
8  *
9  * $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_dumpall.c,v 1.10 2002/11/22 03:09:43 tgl Exp $
10  *
11  *-------------------------------------------------------------------------
12  */
13
14 #include "postgres_fe.h"
15
16 #include <unistd.h>
17 #ifdef ENABLE_NLS
18 #include <locale.h>
19 #endif
20 #ifdef HAVE_GETOPT_H
21 #include <getopt.h>
22 #endif
23 #ifndef HAVE_STRDUP
24 #include "strdup.h"
25 #endif
26 #include <errno.h>
27
28 #include "dumputils.h"
29 #include "libpq-fe.h"
30 #include "pg_backup.h"
31 #include "pqexpbuffer.h"
32
33 #define _(x) gettext((x))
34
35
36 static char *progname;
37
38 static void help(void);
39
40 static void dumpUsers(PGconn *conn);
41 static void dumpGroups(PGconn *conn);
42 static void dumpCreateDB(PGconn *conn);
43 static void dumpDatabaseConfig(PGconn *conn, const char *dbname);
44 static void dumpUserConfig(PGconn *conn, const char *username);
45 static void makeAlterConfigCommand(const char *arrayitem, const char *type, const char *name);
46 static void dumpDatabases(PGconn *conn);
47
48 static int      runPgDump(const char *dbname);
49 static PGconn *connectDatabase(const char *dbname, const char *pghost, const char *pgport,
50                                 const char *pguser, bool require_password);
51 static PGresult *executeQuery(PGconn *conn, const char *query);
52 static char *findPgDump(const char *argv0);
53
54
55 char       *pgdumploc;
56 PQExpBuffer pgdumpopts;
57 bool            output_clean = false;
58 bool            verbose = false;
59 int                     server_version;
60
61
62
63 int
64 main(int argc, char *argv[])
65 {
66         char       *pghost = NULL;
67         char       *pgport = NULL;
68         char       *pguser = NULL;
69         bool            force_password = false;
70         bool            globals_only = false;
71         PGconn     *conn;
72         int                     c;
73
74 #ifdef HAVE_GETOPT_LONG
75         static struct option long_options[] = {
76                 {"clean", no_argument, NULL, 'c'},
77                 {"inserts", no_argument, NULL, 'd'},
78                 {"attribute-inserts", no_argument, NULL, 'D'},
79                 {"column-inserts", no_argument, NULL, 'D'},
80                 {"host", required_argument, NULL, 'h'},
81                 {"ignore-version", no_argument, NULL, 'i'},
82                 {"oids", no_argument, NULL, 'o'},
83                 {"port", required_argument, NULL, 'p'},
84                 {"password", no_argument, NULL, 'W'},
85                 {"username", required_argument, NULL, 'U'},
86                 {"verbose", no_argument, NULL, 'v'},
87                 {NULL, 0, NULL, 0}
88         };
89
90         int                     optindex;
91 #endif
92
93 #ifdef ENABLE_NLS
94         setlocale(LC_ALL, "");
95         bindtextdomain("pg_dump", LOCALEDIR);
96         textdomain("pg_dump");
97 #endif
98
99         if (!strrchr(argv[0], '/'))
100                 progname = argv[0];
101         else
102                 progname = strrchr(argv[0], '/') + 1;
103
104         if (argc > 1)
105         {
106                 if (strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-?") == 0)
107                 {
108                         help();
109                         exit(0);
110                 }
111                 if (strcmp(argv[1], "--version") == 0 || strcmp(argv[1], "-V") == 0)
112                 {
113                         puts("pg_dumpall (PostgreSQL) " PG_VERSION);
114                         exit(0);
115                 }
116         }
117
118         pgdumploc = findPgDump(argv[0]);
119         pgdumpopts = createPQExpBuffer();
120
121 #ifdef HAVE_GETOPT_LONG
122         while ((c = getopt_long(argc, argv, "cdDgh:iop:U:vW", long_options, &optindex)) != -1)
123 #else
124         while ((c = getopt(argc, argv, "cdDgh:iop:U:vW")) != -1)
125 #endif
126         {
127                 switch (c)
128                 {
129                         case 'c':
130                                 output_clean = true;
131                                 break;
132
133                         case 'd':
134                         case 'D':
135                                 appendPQExpBuffer(pgdumpopts, " -%c", c);
136                                 break;
137
138                         case 'g':
139                                 globals_only = true;
140                                 break;
141
142                         case 'h':
143                                 pghost = optarg;
144                                 appendPQExpBuffer(pgdumpopts, " -h '%s'", pghost);
145                                 break;
146
147                         case 'i':
148                         case 'o':
149                                 appendPQExpBuffer(pgdumpopts, " -%c", c);
150                                 break;
151
152                         case 'p':
153                                 pgport = optarg;
154                                 appendPQExpBuffer(pgdumpopts, " -p '%s'", pgport);
155                                 break;
156
157                         case 'U':
158                                 pguser = optarg;
159                                 appendPQExpBuffer(pgdumpopts, " -U '%s'", pguser);
160                                 break;
161
162                         case 'v':
163                                 verbose = true;
164                                 appendPQExpBuffer(pgdumpopts, " -v");
165                                 break;
166
167                         case 'W':
168                                 force_password = true;
169                                 appendPQExpBuffer(pgdumpopts, " -W");
170                                 break;
171
172                         default:
173                                 fprintf(stderr, _("Try '%s --help' for more information.\n"), progname);
174                                 exit(1);
175                 }
176         }
177
178         if (optind < argc)
179         {
180                 fprintf(stderr,
181                                 _("%s: too many command line options (first is '%s')\n"
182                                   "Try '%s --help' for more information.\n"),
183                                 progname, argv[optind], progname);
184                 exit(1);
185         }
186
187
188         conn = connectDatabase("template1", pghost, pgport, pguser, force_password);
189
190         printf("--\n");
191         printf("-- PostgreSQL database cluster dump\n");
192         printf("--\n\n");
193         printf("\\connect \"template1\"\n\n");
194
195         dumpUsers(conn);
196         dumpGroups(conn);
197
198         if (globals_only)
199                 goto end;
200
201         dumpCreateDB(conn);
202         dumpDatabases(conn);
203
204 end:
205         PQfinish(conn);
206         exit(0);
207 }
208
209
210
211 static void
212 help(void)
213 {
214         printf(_("%s extracts a PostgreSQL database cluster into an SQL script file.\n\n"), progname);
215         printf(_("Usage:\n"));
216         printf(_("  %s [OPTION]...\n"), progname);
217
218         printf(_("\nOptions:\n"));
219 #ifdef HAVE_GETOPT_LONG
220         printf(_("  -c, --clean              clean (drop) databases prior to create\n"));
221         printf(_("  -d, --inserts            dump data as INSERT, rather than COPY, commands\n"));
222         printf(_("  -D, --column-inserts     dump data as INSERT commands with column names\n"));
223         printf(_("  -g, --globals-only       dump only global objects, no databases\n"));
224         printf(_("  -i, --ignore-version     proceed even when server version mismatches\n"
225                          "                           pg_dumpall version\n"));
226         printf(_("  -o, --oids               include OIDs in dump\n"));
227         printf(_("  -v, --verbose            verbose mode\n"));
228 #else /* not HAVE_GETOPT_LONG */
229         printf(_("  -c                       clean (drop) databases prior to create\n"));
230         printf(_("  -d                       dump data as INSERT, rather than COPY, commands\n"));
231         printf(_("  -D                       dump data as INSERT commands with column names\n"));
232         printf(_("  -g                       dump only global objects, no databases\n"));
233         printf(_("  -i                       proceed even when server version mismatches\n"
234                          "                           pg_dumpall version\n"));
235         printf(_("  -o                       include OIDs in dump\n"));
236         printf(_("  -v                       verbose mode\n"));
237 #endif /* not HAVE_GETOPT_LONG */
238         printf(_("  --help                   show this help, then exit\n"));
239         printf(_("  --version                output version information, then exit\n"));
240
241         printf(_("\nConnection options:\n"));
242 #ifdef HAVE_GETOPT_LONG
243         printf(_("  -h, --host=HOSTNAME      database server host name\n"));
244         printf(_("  -p, --port=PORT          database server port number\n"));
245         printf(_("  -U, --username=NAME      connect as specified database user\n"));
246         printf(_("  -W, --password           force password prompt (should happen automatically)\n"));
247 #else /* not HAVE_GETOPT_LONG */
248         printf(_("  -h HOSTNAME              database server host name\n"));
249         printf(_("  -p PORT                  database server port number\n"));
250         printf(_("  -U NAME                  connect as specified database user\n"));
251         printf(_("  -W                       force password prompt (should happen automatically)\n"));
252 #endif /* not HAVE_GETOPT_LONG */
253
254         printf(_("\nThe SQL script will be written to the standard output.\n\n"));
255         printf(_("Report bugs to <pgsql-bugs@postgresql.org>.\n"));
256 }
257
258
259
260 /*
261  * Dump users (but not the user created by initdb).
262  */
263 static void
264 dumpUsers(PGconn *conn)
265 {
266         PGresult   *res;
267         int                     i;
268
269         printf("--\n-- Users\n--\n\n");
270         printf("DELETE FROM pg_shadow WHERE usesysid <> (SELECT datdba FROM pg_database WHERE datname = 'template0');\n\n");
271
272         res = executeQuery(conn,
273                                            "SELECT usename, usesysid, passwd, usecreatedb, usesuper, CAST(valuntil AS timestamp) "
274                                            "FROM pg_shadow "
275                                            "WHERE usesysid <> (SELECT datdba FROM pg_database WHERE datname = 'template0');");
276
277         for (i = 0; i < PQntuples(res); i++)
278         {
279                 PQExpBuffer buf = createPQExpBuffer();
280                 const char *username;
281
282                 username = PQgetvalue(res, i, 0);
283                 appendPQExpBuffer(buf, "CREATE USER %s WITH SYSID %s",
284                                                   fmtId(username),
285                                                   PQgetvalue(res, i, 1));
286
287                 if (!PQgetisnull(res, i, 2))
288                 {
289                         appendPQExpBuffer(buf, " PASSWORD ");
290                         appendStringLiteral(buf, PQgetvalue(res, i, 2), true);
291                 }
292
293                 if (strcmp(PQgetvalue(res, i, 3), "t") == 0)
294                         appendPQExpBuffer(buf, " CREATEDB");
295                 else
296                         appendPQExpBuffer(buf, " NOCREATEDB");
297
298                 if (strcmp(PQgetvalue(res, i, 4), "t") == 0)
299                         appendPQExpBuffer(buf, " CREATEUSER");
300                 else
301                         appendPQExpBuffer(buf, " NOCREATEUSER");
302
303                 if (!PQgetisnull(res, i, 5))
304                         appendPQExpBuffer(buf, " VALID UNTIL '%s'", PQgetvalue(res, i, 5));
305
306                 appendPQExpBuffer(buf, ";\n");
307
308                 printf("%s", buf->data);
309                 destroyPQExpBuffer(buf);
310
311                 if (server_version >= 70300)
312                         dumpUserConfig(conn, username);
313         }
314
315         PQclear(res);
316         printf("\n\n");
317 }
318
319
320
321 /*
322  * Dump groups.
323  */
324 static void
325 dumpGroups(PGconn *conn)
326 {
327         PGresult   *res;
328         int                     i;
329
330         printf("--\n-- Groups\n--\n\n");
331         printf("DELETE FROM pg_group;\n\n");
332
333         res = executeQuery(conn, "SELECT groname, grosysid, grolist FROM pg_group;");
334
335         for (i = 0; i < PQntuples(res); i++)
336         {
337                 PQExpBuffer buf = createPQExpBuffer();
338                 char       *val;
339                 char       *tok;
340
341                 appendPQExpBuffer(buf, "CREATE GROUP %s WITH SYSID %s;\n",
342                                                   fmtId(PQgetvalue(res, i, 0)),
343                                                   PQgetvalue(res, i, 1));
344
345                 val = strdup(PQgetvalue(res, i, 2));
346                 tok = strtok(val, ",{}");
347                 do
348                 {
349                         PGresult   *res2;
350                         PQExpBuffer buf2 = createPQExpBuffer();
351                         int                     j;
352
353                         appendPQExpBuffer(buf2, "SELECT usename FROM pg_shadow WHERE usesysid = %s;", tok);
354                         res2 = executeQuery(conn, buf2->data);
355                         destroyPQExpBuffer(buf2);
356
357                         for (j = 0; j < PQntuples(res2); j++)
358                         {
359                                 appendPQExpBuffer(buf, "ALTER GROUP %s ", fmtId(PQgetvalue(res, i, 0)));
360                                 appendPQExpBuffer(buf, "ADD USER %s;\n", fmtId(PQgetvalue(res2, j, 0)));
361                         }
362
363                         PQclear(res2);
364
365                         tok = strtok(NULL, "{},");
366                 }
367                 while (tok);
368
369                 printf("%s", buf->data);
370                 destroyPQExpBuffer(buf);
371         }
372
373         PQclear(res);
374         printf("\n\n");
375 }
376
377
378
379 /*
380  * Dump commands to create each database.
381  *
382  * To minimize the number of reconnections (and possibly ensuing
383  * password prompts) required by the output script, we emit all CREATE
384  * DATABASE commands during the initial phase of the script, and then
385  * run pg_dump for each database to dump the contents of that
386  * database.  We skip databases marked not datallowconn, since we'd be
387  * unable to connect to them anyway (and besides, we don't want to
388  * dump template0).
389  */
390 static void
391 dumpCreateDB(PGconn *conn)
392 {
393         PGresult   *res;
394         int                     i;
395
396         printf("--\n-- Database creation\n--\n\n");
397
398         /*
399          * Basically this query returns: dbname, dbowner, encoding,
400          * istemplate, dbpath
401          */
402         res = executeQuery(conn, "SELECT datname, coalesce(usename, (select usename from pg_shadow where usesysid=(select datdba from pg_database where datname='template0'))), pg_encoding_to_char(d.encoding), datistemplate, datpath FROM pg_database d LEFT JOIN pg_shadow u ON (datdba = usesysid) WHERE datallowconn ORDER BY 1;");
403
404         for (i = 0; i < PQntuples(res); i++)
405         {
406                 PQExpBuffer buf = createPQExpBuffer();
407                 char       *dbname = PQgetvalue(res, i, 0);
408                 char       *dbowner = PQgetvalue(res, i, 1);
409                 char       *dbencoding = PQgetvalue(res, i, 2);
410                 char       *dbistemplate = PQgetvalue(res, i, 3);
411                 char       *dbpath = PQgetvalue(res, i, 4);
412
413                 if (strcmp(dbname, "template1") == 0)
414                         continue;
415
416                 if (output_clean)
417                         appendPQExpBuffer(buf, "DROP DATABASE %s\n;", fmtId(dbname));
418
419                 appendPQExpBuffer(buf, "CREATE DATABASE %s", fmtId(dbname));
420                 appendPQExpBuffer(buf, " WITH OWNER = %s TEMPLATE = template0", fmtId(dbowner));
421
422                 if (strcmp(dbpath, "") != 0)
423                 {
424                         appendPQExpBuffer(buf, " LOCATION = ");
425                         appendStringLiteral(buf, dbpath, true);
426                 }
427
428                 appendPQExpBuffer(buf, " ENCODING = ");
429                 appendStringLiteral(buf, dbencoding, true);
430
431                 appendPQExpBuffer(buf, ";\n");
432
433                 if (strcmp(dbistemplate, "t") == 0)
434                 {
435                         appendPQExpBuffer(buf, "UPDATE pg_database SET datistemplate = 't' WHERE datname = ");
436                         appendStringLiteral(buf, dbname, true);
437                         appendPQExpBuffer(buf, ";\n");
438                 }
439                 printf("%s", buf->data);
440                 destroyPQExpBuffer(buf);
441
442                 if (server_version >= 70300)
443                         dumpDatabaseConfig(conn, dbname);
444         }
445
446         PQclear(res);
447         printf("\n\n");
448 }
449
450
451
452 /*
453  * Dump database-specific configuration
454  */
455 static void
456 dumpDatabaseConfig(PGconn *conn, const char *dbname)
457 {
458         PQExpBuffer buf = createPQExpBuffer();
459         int                     count = 1;
460
461         for (;;)
462         {
463                 PGresult   *res;
464
465                 printfPQExpBuffer(buf, "SELECT datconfig[%d] FROM pg_database WHERE datname = ", count);
466                 appendStringLiteral(buf, dbname, true);
467                 appendPQExpBuffer(buf, ";");
468
469                 res = executeQuery(conn, buf->data);
470                 if (!PQgetisnull(res, 0, 0))
471                 {
472                         makeAlterConfigCommand(PQgetvalue(res, 0, 0), "DATABASE", dbname);
473                         PQclear(res);
474                         count++;
475                 }
476                 else
477                 {
478                         PQclear(res);
479                         break;
480                 }
481         }
482
483         destroyPQExpBuffer(buf);
484 }
485
486
487
488 /*
489  * Dump user-specific configuration
490  */
491 static void
492 dumpUserConfig(PGconn *conn, const char *username)
493 {
494         PQExpBuffer buf = createPQExpBuffer();
495         int                     count = 1;
496
497         for (;;)
498         {
499                 PGresult   *res;
500
501                 printfPQExpBuffer(buf, "SELECT useconfig[%d] FROM pg_shadow WHERE usename = ", count);
502                 appendStringLiteral(buf, username, true);
503                 appendPQExpBuffer(buf, ";");
504
505                 res = executeQuery(conn, buf->data);
506                 if (!PQgetisnull(res, 0, 0))
507                 {
508                         makeAlterConfigCommand(PQgetvalue(res, 0, 0), "USER", username);
509                         PQclear(res);
510                         count++;
511                 }
512                 else
513                 {
514                         PQclear(res);
515                         break;
516                 }
517         }
518
519         destroyPQExpBuffer(buf);
520 }
521
522
523
524 /*
525  * Helper function for dumpXXXConfig().
526  */
527 static void
528 makeAlterConfigCommand(const char *arrayitem, const char *type, const char *name)
529 {
530         char       *pos;
531         char       *mine;
532         PQExpBuffer buf = createPQExpBuffer();
533
534         mine = strdup(arrayitem);
535         pos = strchr(mine, '=');
536         if (pos == NULL)
537                 return;
538
539         *pos = 0;
540         appendPQExpBuffer(buf, "ALTER %s %s ", type, fmtId(name));
541         appendPQExpBuffer(buf, "SET %s TO ", fmtId(mine));
542         appendStringLiteral(buf, pos + 1, false);
543         appendPQExpBuffer(buf, ";\n");
544
545         printf("%s", buf->data);
546         destroyPQExpBuffer(buf);
547         free(mine);
548 }
549
550
551
552 /*
553  * Dump contents of databases.
554  */
555 static void
556 dumpDatabases(PGconn *conn)
557 {
558         PGresult   *res;
559         int                     i;
560
561         res = executeQuery(conn, "SELECT datname FROM pg_database WHERE datallowconn ORDER BY 1;");
562         for (i = 0; i < PQntuples(res); i++)
563         {
564                 int                     ret;
565
566                 char       *dbname = PQgetvalue(res, i, 0);
567
568                 if (verbose)
569                         fprintf(stderr, _("%s: dumping database \"%s\"...\n"), progname, dbname);
570
571                 printf("\\connect %s\n", fmtId(dbname));
572                 ret = runPgDump(dbname);
573                 if (ret != 0)
574                 {
575                         fprintf(stderr, _("%s: pg_dump failed on %s, exiting\n"), progname, dbname);
576                         exit(1);
577                 }
578         }
579
580         PQclear(res);
581 }
582
583
584
585 /*
586  * Run pg_dump on dbname.
587  */
588 static int
589 runPgDump(const char *dbname)
590 {
591         PQExpBuffer cmd = createPQExpBuffer();
592         const char *p;
593         int                     ret;
594
595         appendPQExpBuffer(cmd, "%s %s -X use-set-session-authorization -Fp '",
596                                           pgdumploc, pgdumpopts->data);
597
598         /* Shell quoting is not quite like SQL quoting, so can't use fmtId */
599         for (p = dbname; *p; p++)
600         {
601                 if (*p == '\'')
602                         appendPQExpBuffer(cmd, "'\"'\"'");
603                 else
604                         appendPQExpBufferChar(cmd, *p);
605         }
606
607         appendPQExpBufferChar(cmd, '\'');
608
609         if (verbose)
610                 fprintf(stderr, _("%s: running %s\n"), progname, cmd->data);
611
612         fflush(stdout);
613         fflush(stderr);
614
615         ret = system(cmd->data);
616
617         destroyPQExpBuffer(cmd);
618
619         return ret;
620 }
621
622
623
624 /*
625  * Make a database connection with the given parameters.  An
626  * interactive password prompt is automatically issued if required.
627  */
628 static PGconn *
629 connectDatabase(const char *dbname, const char *pghost, const char *pgport,
630                                 const char *pguser, bool require_password)
631 {
632         PGconn     *conn;
633         char       *password = NULL;
634         bool            need_pass = false;
635         PGresult   *res;
636
637         if (require_password)
638                 password = simple_prompt("Password: ", 100, false);
639
640         /*
641          * Start the connection.  Loop until we have a password if requested
642          * by backend.
643          */
644         do
645         {
646                 need_pass = false;
647                 conn = PQsetdbLogin(pghost, pgport, NULL, NULL, dbname, pguser, password);
648
649                 if (!conn)
650                 {
651                         fprintf(stderr, _("%s: could not connect to database %s\n"),
652                                         progname, dbname);
653                         exit(1);
654                 }
655
656                 if (PQstatus(conn) == CONNECTION_BAD &&
657                         strcmp(PQerrorMessage(conn), "fe_sendauth: no password supplied\n") == 0 &&
658                         !feof(stdin))
659                 {
660                         PQfinish(conn);
661                         need_pass = true;
662                         free(password);
663                         password = NULL;
664                         password = simple_prompt("Password: ", 100, false);
665                 }
666         } while (need_pass);
667
668         if (password)
669                 free(password);
670
671         /* check to see that the backend connection was successfully made */
672         if (PQstatus(conn) == CONNECTION_BAD)
673         {
674                 fprintf(stderr, _("%s: could not connect to database %s: %s\n"),
675                                 progname, dbname, PQerrorMessage(conn));
676                 exit(1);
677         }
678
679         res = executeQuery(conn, "SELECT version();");
680         if (PQntuples(res) != 1)
681         {
682                 fprintf(stderr, _("%s: could not get server version\n"), progname);
683                 exit(1);
684         }
685         else
686         {
687                 char *val = PQgetvalue(res, 0, 0);
688                 server_version = parse_version(val + strcspn(val, "0123456789"));
689                 if (server_version < 0)
690                 {
691                         fprintf(stderr, _("%s: could not parse server version \"%s\"\n"), progname, val);
692                         exit(1);
693                 }
694         }
695
696         return conn;
697 }
698
699
700
701 /*
702  * Run a query, return the results, exit program on failure.
703  */
704 static PGresult *
705 executeQuery(PGconn *conn, const char *query)
706 {
707         PGresult   *res;
708
709         res = PQexec(conn, query);
710         if (!res ||
711                 PQresultStatus(res) != PGRES_TUPLES_OK)
712         {
713                 fprintf(stderr, _("%s: query failed: %s"), progname, PQerrorMessage(conn));
714                 fprintf(stderr, _("%s: query was: %s\n"), progname, query);
715                 PQfinish(conn);
716                 exit(1);
717         }
718
719         return res;
720 }
721
722
723
724 /*
725  * Find location of pg_dump executable.
726  */
727 static char *
728 findPgDump(const char *argv0)
729 {
730         char       *last;
731         PQExpBuffer cmd;
732         static char *result = NULL;
733
734         if (result)
735                 return result;
736
737         cmd = createPQExpBuffer();
738         last = strrchr(argv0, '/');
739
740         if (!last)
741                 appendPQExpBuffer(cmd, "pg_dump");
742         else
743         {
744                 char       *dir = strdup(argv0);
745
746                 *(dir + (last - argv0)) = '\0';
747                 appendPQExpBuffer(cmd, "%s/pg_dump", dir);
748         }
749
750         result = strdup(cmd->data);
751
752         appendPQExpBuffer(cmd, " -V >/dev/null 2>&1");
753         if (system(cmd->data) == 0)
754                 goto end;
755
756         result = BINDIR "/pg_dump";
757         if (system(BINDIR "/pg_dump -V >/dev/null 2>&1") == 0)
758                 goto end;
759
760         fprintf(stderr, _("%s: could not find pg_dump\n"
761                 "Make sure it is in the path or in the same directory as %s.\n"),
762                         progname, progname);
763         exit(1);
764
765 end:
766         destroyPQExpBuffer(cmd);
767         return result;
768 }