4242 * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
4343 * Portions Copyright (c) 1994, Regents of the University of California
4444 *
45- * $Header: /cvsroot/pgsql/src/bin/initdb/initdb.c,v 1.9 2003/11/1417:30:41 tgl Exp $
45+ * $Header: /cvsroot/pgsql/src/bin/initdb/initdb.c,v 1.10 2003/11/1418:32:34 tgl Exp $
4646 *
4747 *-------------------------------------------------------------------------
4848 */
5151
5252#include <dirent.h>
5353#include <sys/stat.h>
54+ #include <sys/wait.h>
5455#include <unistd.h>
5556#include <locale.h>
5657#include <signal.h>
@@ -112,8 +113,10 @@ char *system_views_file;
112113char * effective_user ;
113114bool testpath = true;
114115bool made_new_pgdata = false;
116+ bool found_existing_pgdata = false;
115117char infoversion [100 ];
116- bool not_ok = false;
118+ bool caught_signal = false;
119+ bool output_failed = false;
117120
118121/* defaults */
119122int n_connections = 10 ;
@@ -159,6 +162,7 @@ static char *expanded_path(char *);
159162#endif
160163static char * * readfile (char * );
161164static void writefile (char * ,char * * );
165+ static void pclose_check (FILE * stream );
162166static char * get_id (void );
163167static char * get_encoding_id (char * );
164168static char * get_short_version (void );
@@ -206,22 +210,20 @@ static void *xmalloc(size_t);
206210do { \
207211fflush(stdout); \
208212fflush(stderr); \
209- pg = popen(cmd,PG_BINARY_W ); \
213+ pg = popen(cmd,"w" ); \
210214if (pg == NULL) \
211215exit_nicely(); \
212216} while (0)
213217
214218#define PG_CMD_CLOSE \
215219do { \
216- if ((pclose(pg) >> 8) & 0xff) \
217- exit_nicely(); \
220+ pclose_check(pg); \
218221} while (0)
219222
220223#define PG_CMD_PUTLINE \
221224do { \
222- if (fputs(*line, pg) < 0) \
223- exit_nicely(); \
224- fflush(pg); \
225+ if (fputs(*line, pg) < 0 || fflush(pg) < 0) \
226+ output_failed = true; \
225227} while (0)
226228
227229#ifndef WIN32
@@ -460,6 +462,41 @@ writefile(char *path, char **lines)
460462exit_nicely ();
461463}
462464
465+ /* pclose() plus useful error reporting */
466+ static void
467+ pclose_check (FILE * stream )
468+ {
469+ int exitstatus ;
470+
471+ exitstatus = pclose (stream );
472+
473+ if (exitstatus == 0 )
474+ return ;/* all is well */
475+
476+ if (exitstatus == -1 )
477+ {
478+ /* pclose() itself failed, and hopefully set errno */
479+ perror ("pclose failed" );
480+ }
481+ else if (WIFEXITED (exitstatus ))
482+ {
483+ fprintf (stderr ,"child process exited with exit code %d\n" ,
484+ WEXITSTATUS (exitstatus ));
485+ }
486+ else if (WIFSIGNALED (exitstatus ))
487+ {
488+ fprintf (stderr ,"child process was terminated by signal %d\n" ,
489+ WTERMSIG (exitstatus ));
490+ }
491+ else
492+ {
493+ fprintf (stderr ,"child process exited with unexpected status %d\n" ,
494+ exitstatus );
495+ }
496+
497+ exit_nicely ();
498+ }
499+
463500/* source stolen from FreeBSD /src/bin/mkdir/mkdir.c and adapted */
464501
465502/*
@@ -585,21 +622,24 @@ exit_nicely(void)
585622if (!rmtree (pg_data , true))
586623fprintf (stderr ,"%s: failed\n" ,progname );
587624}
588- else
625+ else if ( found_existing_pgdata )
589626{
590627fprintf (stderr ,
591628"%s: removing contents of data directory \"%s\"\n" ,
592629progname ,pg_data );
593630if (!rmtree (pg_data , false))
594631fprintf (stderr ,"%s: failed\n" ,progname );
595632}
633+ /* otherwise died during startup, do nothing! */
596634}
597635else
598636{
599- fprintf (stderr ,
600- "%s: data directory \"%s\" not removed at user's request\n" ,
601- progname ,pg_data );
637+ if (made_new_pgdata || found_existing_pgdata )
638+ fprintf (stderr ,
639+ "%s: data directory \"%s\" not removed at user's request\n" ,
640+ progname ,pg_data );
602641}
642+
603643exit (1 );
604644}
605645
@@ -874,7 +914,7 @@ find_postgres(char *path)
874914if (fgets (line ,sizeof (line ),pgver )== NULL )
875915perror ("fgets failure" );
876916
877- pclose (pgver );
917+ pclose_check (pgver );
878918
879919if (strcmp (line ,PG_VERSIONSTR )!= 0 )
880920return FIND_WRONG_VERSION ;
@@ -1839,7 +1879,7 @@ trapsig(int signum)
18391879{
18401880/* handle systems that reset the handler, like Windows (grr) */
18411881pqsignal (signum ,trapsig );
1842- not_ok = true;
1882+ caught_signal = true;
18431883}
18441884
18451885/*
@@ -1848,14 +1888,19 @@ trapsig(int signum)
18481888static void
18491889check_ok ()
18501890{
1851- if (not_ok )
1891+ if (caught_signal )
1892+ {
1893+ printf ("caught signal\n" );
1894+ exit_nicely ();
1895+ }
1896+ else if (output_failed )
18521897{
1853- printf ("Caught Signal. \n" );
1898+ printf ("failed to write to child process \n" );
18541899exit_nicely ();
18551900}
18561901else
18571902{
1858- /*no signal caught */
1903+ /*all seems well */
18591904printf ("ok\n" );
18601905}
18611906}
@@ -2329,6 +2374,11 @@ main(int argc, char *argv[])
23292374pqsignal (SIGTERM ,trapsig );
23302375#endif
23312376
2377+ /* Ignore SIGPIPE when writing to backend, so we can clean up */
2378+ #ifdef SIGPIPE
2379+ pqsignal (SIGPIPE ,SIG_IGN );
2380+ #endif
2381+
23322382switch (check_data_dir ())
23332383{
23342384case 0 :
@@ -2354,11 +2404,12 @@ main(int argc, char *argv[])
23542404if (chmod (pg_data ,0700 )!= 0 )
23552405{
23562406perror (pg_data );
2357- /* don't exit_nicely(), it'll try to remove pg_data contents */
2358- exit (1 );
2407+ exit_nicely ();
23592408}
23602409else
23612410check_ok ();
2411+
2412+ found_existing_pgdata = true;
23622413break ;
23632414
23642415case 2 :
@@ -2369,14 +2420,12 @@ main(int argc, char *argv[])
23692420"the directory \"%s\" or run %s\n"
23702421"with an argument other than \"%s\".\n" ,
23712422progname ,pg_data ,pg_data ,progname ,pg_data );
2372- /* don't exit_nicely(), it'll try to remove pg_data contents */
2373- exit (1 );
2423+ exit (1 );/* no further message needed */
23742424
23752425default :
23762426/* Trouble accessing directory */
23772427perror (pg_data );
2378- /* don't exit_nicely(), it'll try to remove pg_data contents */
2379- exit (1 );
2428+ exit_nicely ();
23802429}
23812430
23822431/* Create required subdirectories */