head     1.23;
branch   ;
access   ;
symbols  Version_2:1.21 C_Demo_1:1.9;
locks    ; strict;
comment  @ * @;


1.23
date     90.08.23.16.30.15;  author kemnitz;  state Exp;
branches ;
next     1.22;

1.22
date     90.08.17.15.28.38;  author kemnitz;  state Exp;
branches ;
next     1.21;

1.21
date     90.07.12.01.39.45;  author kemnitz;  state Version_2;
branches ;
next     1.20;

1.20
date     90.07.11.21.22.13;  author kemnitz;  state Exp;
branches ;
next     1.19;

1.19
date     90.02.13.00.44.59;  author kemnitz;  state Exp;
branches ;
next     1.18;

1.18
date     90.02.12.19.51.06;  author cimarron;  state Exp;
branches ;
next     1.17;

1.17
date     90.02.08.00.29.04;  author kemnitz;  state Exp;
branches ;
next     1.16;

1.16
date     90.01.30.23.06.08;  author sp;  state Exp;
branches ;
next     1.15;

1.15
date     90.01.26.23.16.25;  author kemnitz;  state Exp;
branches ;
next     1.14;

1.14
date     89.10.11.01.08.21;  author hirohama;  state Exp;
branches ;
next     1.13;

1.13
date     89.10.09.22.35.04;  author mao;  state Exp;
branches ;
next     1.12;

1.12
date     89.10.09.22.29.03;  author mao;  state Exp;
branches ;
next     1.11;

1.11
date     89.09.20.17.31.47;  author mao;  state Exp;
branches ;
next     1.10;

1.10
date     89.09.11.16.42.54;  author hirohama;  state Exp;
branches ;
next     1.9;

1.9
date     89.09.05.16.52.21;  author mao;  state C_Demo_1;
branches ;
next     1.8;

1.8
date     89.08.03.04.41.16;  author dillon;  state Exp;
branches ;
next     1.7;

1.7
date     89.08.03.00.18.35;  author dillon;  state Exp;
branches ;
next     1.6;

1.6
date     89.08.02.23.56.29;  author dillon;  state Exp;
branches ;
next     1.5;

1.5
date     89.07.17.14.41.50;  author dillon;  state Exp;
branches ;
next     1.4;

1.4
date     89.07.17.14.39.38;  author dillon;  state Exp;
branches ;
next     1.3;

1.3
date     89.03.06.18.11.26;  author hirohama;  state Stab;
branches ;
next     1.2;

1.2
date     89.02.02.15.57.31;  author dillon;  state Exp;
branches ;
next     1.1;

1.1
date     89.01.17.05.57.50;  author cimarron;  state Exp;
branches ;
next     ;


desc
@@


1.23
log
@A last bug fix before this puppy bites it.
@
text
@/*
 * createdb.c --
 *	POSTGRES database creation utility program
 *
 * Flags:
 *	-e	database already exists
 *	-t db	use "db" as a template for a new database
 *	-v on	create a database without a vacuum
 *	-v off	create a database with a vacuum (default)
 *
 * Files:
 *	/tmp/psort.XXXXXX	psort tape files
 *	$(GLOBALDIR)/		root of the global (shared) relations
 *	.../PG_VERSION		access method version numbers
 *	.../../files/global.bki	global database creation script
 *	.../../files/local1_template1.bki
 *				local template database creation script
 *	support/dbdb.bki	global database default script
 *	support/local.bki	local database default script
 *
 * NOTES:
 *	This should be discarded and merged into POSTGRES after version 1.
 */

#include "tmp/c.h"

RcsId("$Header: RCS/createdb.c,v 1.22 90/08/17 15:28:38 kemnitz Exp Locker: kemnitz $");

#include "installinfo.h"	/* in obj*/installinfo.h -I path set */

#include <errno.h>
#include <signal.h>
#include <stdio.h>
#include <strings.h>
#include <sys/file.h>
#include <sys/param.h>
#include <sys/stat.h>
#include <sys/types.h>
/* #include <sys/wait.h> */

#include "utils/log.h"

#include "daemon.h"
#include "support/master.h"	/* for DefaultVacuumDemonPath */
#include "suputils.h"

#define TemplateMode	0x1
#define VacuumOnMode	0x2
#define VacuumOffMode	0x4
#define DBExistsMode	0x8

#define OptionString	"p:h:v:t:ed"

#define SharedTemplateSource		"dbdb.bki"
#define LocalTemplateSource		"local.bki"
#define SharedTemplateDestination	"global1.bki"
#define LocalTemplateDestination	"local1_template1.bki"

/*
 * FindPath --
 *	Returns the absolute path to the given filename.
 */
extern
String
FindPath ARGS((
	String	tail
));

static int	Useid;
static int	DebugMode;
static char	*TemplateName = NULL;
static int	TemplateNameLength = 0;
static char	DefaultTemplateName[] = "template1";
static char	*cmdname = (char *) NULL;
int Noversion = 0;
char  *postgres_home = NULL;

/* XXX hacks below added to make this compile in the obj.dec tree */
#ifndef AMIINT
CompilerError();
#endif
#ifndef SCRDIR
CompilerError();
#endif

main(argc, argv)
     int	argc;
     char	*argv[];
{
     int		uid;				/* uid_t */
     int		euid;				/* uid_t */
     struct stat	buf;
     int		madedir;
     char		*append;
     char		*path;
     char		pathBuffer[128];		/* XXX */
     char		*portString = NULL;
     char		*hostString = NULL;
     char		hostStringData[32];
     int		c;
     int		errors = 0;
     int		mode = 0;
     extern		errno;
     extern char	*getenv();
     extern char	*optarg;
     extern int		optind, opterr, getopt();

     cmdname = PathGetRoot(argv[0]);
     while ((c = getopt(argc, argv, OptionString)) != EOF && !errors) {
	     switch (c) {
	     case 'd':  /* debug mode 	   */
		     DebugMode = 1;
		     break;
	     case 'p':	/* postmaster port */
		     portString = optarg;
		     break;
	     case 'h':	/* postmaster host */
		     hostString = optarg;
		     break;
	     case 't': /* Templates */
		     mode |= TemplateMode;
		     TemplateName = optarg;
		     if (!TemplateName)
			     ++errors;
		     break;
	     case 'v': /* vacuum on or off */
		     if (!strcmp(optarg, "on"))
			     mode |= VacuumOnMode;
		     else if (!strcmp(optarg, "off"))
			     mode |= VacuumOffMode;
		     else
			     ++errors;
		     break;
	     case 'e':
		     mode |= DBExistsMode;
		     break;
	     default:
		     ++errors;
		     break;
	     }
     } 
     if (optind + 1 != argc || errors != 0) {
	     printf("Usage: %s [-p port] [-h host] [-e] [-v on|off] [-t template] dbname\n",
		    cmdname);
	     exit(1);
     }

	 postgres_home = getenv("POSTGRESHOME");
	 if (postgres_home == NULL)
	 {
		fprintf(stderr, "%s: POSTGRESHOME not set.\n", cmdname);
		exit(1);
	 }
		
     if(!(mode & DBExistsMode)) {
	  if (TemplateName == NULL) {
	       TemplateName = getenv("CREATDBTEM");
	       if (TemplateName == NULL) {
		    TemplateName = DefaultTemplateName;
	       }
	  }
	  TemplateNameLength = strlen(TemplateName);
	  
	  uid = getuid();
	  euid = geteuid();
	  /* check if valid user */
	  Useid = uid;
	  
	  bcopy("files", pathBuffer, sizeof "files");
	  path = FindPath(pathBuffer);
	  
	  if (stat(path, &buf) < 0) {
	       if (errno != ENOENT) {
		    perror(path);
		    exit(1);
	       }
	       mknwdirs(path, uid);			/* XXX euid better? */
	       
	       if (chdir(path) < 0) {
		    perror("chdir");
		    exit(1);
	       }
	       
	       printf("%s: creating system files in %s\n", cmdname, path);
	       if (installfiles(path) == -1) {
		       fprintf(stderr, "%s: could not install system files\n",
			      cmdname);
		       PathRemoveRecursively(path);
		       exit(1);
	       }
	  } else {
	       errno = 0;
	       if (!(buf.st_mode & S_IFDIR)) {
		       fprintf(stderr, "%s: FILESDIR %s is not a directory\n",
			       cmdname, path);
		       exit(1);
	       }
	  }
	  
	  bcopy("data/base/", pathBuffer, sizeof "data/base/");
	  append = &pathBuffer[sizeof "data/base/" - 1];
	  
	  strcpy(append, argv[optind]);
	  append -= sizeof "/base/" - 1;
	  *append = '\0';
	  madedir = 0;
	  
	  path = FindPath(pathBuffer);
	  
	  if (stat(path, &buf) < 0) {
	       if (errno != ENOENT) {
		    perror(path);
		    exit(1);
	       }
	       *append = '/';
	       path = FindPath(pathBuffer);
	       madedir += mknwdirs(path, uid);		/* XXX euid better? */
	       if (chdir(path) < 0) {
		    perror("chdir");
		    exit(1);
	       }
	       *append = '\0';
	       path = FindPath(pathBuffer);
	       printf("%s: creating SHARED relations in %s\n", cmdname, path);
	       if (runami(argv[optind], (char *)NULL, euid) < 0) {
		       fprintf(stderr,
			       "%s: Could not create shared relations\n",
			       cmdname);
		       PathRemoveRecursively(path);
		       exit(1);
	       }
	       SetPgVersion(path);
	  } else {
	       errno = 0;
	       if (!(buf.st_mode & S_IFDIR)) {
		       fprintf(stderr, "%s: GLOBALDIR %s is not a directory\n",
			       cmdname, path);
		       exit(1);
	       }
	       *append = '/';
	       path = FindPath(pathBuffer);
	       madedir += mknwdirs(path, uid);
	       *append = '\0';
	       path = FindPath(pathBuffer);
	  }
	  if (!ValidPgVersion(path)) {
		  fprintf(stderr, "%s: GLOBALDIR %s is in an invalid format\n",
			  cmdname, path);
		  exit(1);
	  }
	  *append = '/';
	  path = FindPath(pathBuffer);
	  if (stat(path, &buf) == 0 && !madedir)
		  if (ValidPgVersion(path)) {
			  fprintf(stderr, "%s: database %s already exists!\n",
				  cmdname, argv[optind]);
			  exit(1);
		  } else if (errno != ENOENT) {
			  perror(argv[optind]);
			  exit(1);
		  } else {
			  mknwdirs(path, euid);
		  }
	  
	  sprintf(pathBuffer,"data/base/%s\0",TemplateName);
	  append = &pathBuffer[sizeof "data/base/" - 1];
	  path = FindPath(pathBuffer);
	  
	  if (stat(path, &buf) == 0) {
	       if (!ValidPgVersion(path)) {
		       fprintf(stderr, "%s: invalid template database %s\n",
			       cmdname, TemplateName);
		       exit(1);
	       }
	  } else if (errno != ENOENT) {
	       perror(TemplateName);
	       exit(1);
	  } else {
	       mknwdirs(path, euid);
	       strncpy(append, TemplateName, TemplateNameLength);
	       path = FindPath(pathBuffer);
	       
	       if (stat(path, &buf) == 0) {
		    if (ValidPgVersion(path)) {
			    fprintf(stderr, "%s: database %s already exists\n",
				    cmdname, TemplateName);
			    exit(1);
		    }
	       } else if (errno != ENOENT) {
		    perror(TemplateName);
		    exit(1);
	       } else {
	            mknwdirs(path, euid);
	       }
	       printf("%s: creating template database in %s\n",
		      cmdname, path);
	       if (runami(TemplateName, TemplateName, uid) < 0) {
		       fprintf(stderr, "%s: could not create %s\n",
			       cmdname, TemplateName);
		       PathRemoveRecursively(path);
		       exit(1);
	       }
	       SetPgVersion(path);
	  }
	  
	  printf("%s: now creating database %s\n", cmdname, argv[optind]);
	  if (copydb(TemplateName, argv[optind]) < 0) {
		  fprintf(stderr, "%s: could not create %s\n",
			  cmdname, argv[optind]);
		  bcopy("data/base/", pathBuffer, sizeof "data/base/" - 1);
		  append = &pathBuffer[sizeof "data/base/" - 1];
		  bcopy(argv[optind], append, strlen(argv[optind]));

/* 
 * Hack by GJK to make it delete the right file - should be using strcpy
 * instead of bcopy all over this code.  This pointer string crap sucks
 * and should probably be rewritten.
 */

		  append[strlen(argv[optind])] = '\0'; 
		  path = FindPath(pathBuffer);
		  PathRemoveRecursively(path);
		  exit(1);
	  }
     } /* if(!DBExists) then create */

     /*
      * turn vacuum on or off
      */

     if((mode & VacuumOnMode) && (mode & VacuumOffMode)) {
	     fprintf(stderr, "%s: cannot have vacuum daemon both on and off\n",
		     cmdname);
	     exit(1);
     }
     if (mode & VacuumOnMode) {
	     IFDEBUG(printf("%s: turning vacuum daemon on...\n", cmdname));
	     if (DBNameGetVacuumDaemonProcessId(argv[optind])) {
		     fprintf(stderr, "%s: vacuumd already running on %s\n",
			     cmdname, argv[optind]);
	     } else {
			/*
			 * Note:
			 *	NULL hostString means use libpq default.
			 */
		     InitVacuumDemon(hostString, argv[optind],
			     NULL, NULL, portString, DefaultVacuumDemonPath);
	     }
     }
     if (mode & VacuumOffMode) {
	     IFDEBUG(printf("%s: turning vacuum daemon off...\n", cmdname));
	     if (DBNameGetVacuumDaemonProcessId(argv[optind]) == 0) {
		     fprintf(stderr, "%s: no vacuumd running on %s\n",
			     cmdname, argv[optind]);
	     } else {
		     DBNameStopVacuumDaemon(argv[optind]);
	     }
     }
} /*main()*/

int
mknwdirs(path, uid)
	char	path[];
	int	uid;
{
	char		*cp;
	struct stat	buf;
	int		made;

	made = 0;
	cp = path;
	while ((cp = index(cp + 1, '/')) != (char *)NULL) {
		*cp = '\0';
		if (stat(path, &buf) < 0) {
			if (errno != ENOENT) {
				perror(path);
				exit(1);
			}
			if (mknwdir(path, uid) < 0) {
				*cp = '/';
				fprintf(stderr, "%s: please mkdir %s\n",
					cmdname, path);
				exit(1);
			} else {
				made += 1;
				printf("%s: created directory %s\n",
				       cmdname, path);
			}
			if (chdir(path) < 0) {
				perror("chdir");
				exit(1);
			}
		}
		*cp = '/';
	}
	if (stat(path, &buf) < 0) {
		if (errno != ENOENT) {
			perror(path);
			exit(1);
		}
		if (mknwdir(path, uid) < 0) {
			*cp = '/';
			fprintf(stderr, "%s: please mkdir %s\n",
				cmdname, path);
			exit(1);
		} else {
			printf("%s: created directory %s\n", cmdname, path);
		}
		if (chdir(path) < 0) {
			perror("chdir");
			exit(1);
		}
	}
	return made;
}

int
mknwdir(path, uid)
	char	path[];
	int	uid;
{
	char		*cp;
	union	wait	status;
	int		pid;
	extern	int	errno;
	int		fork();
	int		chdir();
	int		chmod();
	int		umask();
	int		execl();
	int		seteuid();	/* uid_t */
	int		wait();
	extern		perror();

	FlushOutput();
	pid = fork();
	if (pid < 0) {
		perror("fork");
		exit(1);
	}
	if (pid == 0) {
		/* split off directory */
		*(cp = rindex(path, '/')) = '\0';
		if (chdir(path) < 0) {
			perror("chdir");
			exit(1);
		}
		if (seteuid(uid) < 0) {
			perror("seteuid");
			exit(1);
		}
		*cp++ = '/';
		umask(00);
		FlushOutput();
		FlushErrors();
		execl("/bin/mkdir", "/bin/mkdir", cp, 0);
		execl("/usr/bin/mkdir", "/usr/bin/mkdir", cp, 0);
		perror("exec mkdir");
		exit(1);
	}
	while (wait(&status) != -1)
		continue;
	if (status.w_retcode != 0)
		return(-1);
	/* move into data/base directory */
	if (chdir(path) < 0) {
		perror(path);
		exit(1);
	}
	/* change the mode of the database -- not needed ??		XXX */
	FlushOutput();
	pid = fork();
	if (pid < 0) {
		perror("fork");
		exit(1);
	}
	if (pid == 0) {
		if (seteuid(uid) < 0) {
			perror("seteuid");
			exit(1);
		}
		if (chmod(".", 0777)) {
			perror("chmod");
			exit(1);
		}
		exit(0);
	}
	while (wait(&status) != -1)
		;
	if (status.w_retcode != 0)		/* (status & 0377) */
		return(-1);
	/* reset 'errno', set from possibly bad chdir */
	errno = 0;
	return(0);
}

int
runami(database, template, uid)
	char	database[];
	char	*template;
	int	uid;			/* uid_t */
{
	int		fd;
	int		nchars;
	union wait	status;
	int		pid;
	int		amifds[2];
	int		catfds[2];
	long		tval;
	Size		length;
	char		templatePath[64];
	char		buf[512];
	char		*append;
	char		str[8];
	static char	amiint[] = AMIINT;
	static char	*AMIInt = NULL;
	int		open();
	int		read();
	int		write();
	int		close();
	int		dup2();
	int		fork();
	int		pipe();
	int		execl();
	int		seteuid();	/* uid_t */
	int		wait();
	long		time();
	extern		bcopy();
	extern		perror();
	char *GetBackendName();

	if (AMIInt == NULL) {
		AMIInt = getenv("AMIINT");
		if (AMIInt == NULL) {
			AMIInt = GetBackendName();
			if (AMIInt == NULL) {
				AMIInt = amiint;
			}
		}
	}

	if (template == NULL) {
		bcopy("files/global1.bki", templatePath,
			sizeof ("files/global1.bki"));
	} else {
		bcopy("files/local1_", templatePath,
			sizeof ("files/local1_") - 1);
		append = &templatePath[sizeof ("files/local1_") - 1];
		length = strlen(template);
		bcopy(template, append, length);
		append += length;
		bcopy(".bki", append, sizeof (".bki"));
	}

	if (pipe(amifds) < 0) {
		perror("pipe");
		exit(1);
	}
	FlushOutput();
	pid = fork();
	if (pid < 0) {
		perror("fork");
		exit(1);
	}
	if (pid == 0) {
		seteuid(uid);
		if ((fd = open("/dev/null", O_WRONLY, 0)) < 0) {
			perror("open");
			exit(1);
		}
		if (DebugMode == 0) {
		    close(1);
		    dup2(fd, 1);
		}
		close(fd);
		close(amifds[0]);
		if ((fd = open(FindPath(templatePath), O_RDONLY, 0)) < 0) {
			perror(FindPath(templatePath));
			exit(1);
		}
		if (template != NULL) {
			tval = time(0);
			if (pipe(catfds) < 0) {
				perror("pipe");
				exit(1);
			}
			FlushOutput();
			pid = fork();
			if (pid < 0) {
				perror("fork");
				exit(1);
			}
			if (pid == 0) {
				/* note: limited error checking below */
				close(amifds[1]);
				close(catfds[0]);
				close(0);
				if (DebugMode == 0)
				    close(1);
				while ((nchars=read(fd, buf, sizeof (buf))) >0)
				    if (write(catfds[1], buf, nchars)!=nchars){
					perror("write");
					exit(1);
				    }
				if (nchars < 0) {
				    perror("read");
				    exit(1);
				}
				writestr(catfds[1], "open pg_database\n");
				writestr(catfds[1], "insert ( ");
				writestr(catfds[1], database);
				buf[0] = ' ';
				ltoa(Useid, buf + 1);
				nchars = strlen(buf);
				buf[nchars] = ' ';
				write(catfds[1], buf, 1 + nchars);
				writestr(catfds[1], database);
				writestr(catfds[1], " )\n");
				writestr(
				    catfds[1], 
				    "show\nclose pg_database\n"
				);
				close(catfds[1]);
				close(2);
				exit(0);
			}
			close(fd);
			close(catfds[1]);
			dup2(catfds[0], fd);
			close(catfds[0]);
		}
		close(0);
		dup2(fd, 0);
		close(fd);
		close(2);
		dup2(amifds[1], 2);
		close(amifds[1]);
		/* if (islocal) child not waited for */

		strcpy(str, "-CO");
		if (DebugMode)
		    strcat(str, "d");
		else
		    strcat(str, "Q");
		if (DebugMode) {
		    printf("Exec: %s %s %s\n", AMIInt, str, database);
		    sleep (2);
		}
		execl(AMIInt, AMIInt, str, "-ami", database, 0);
		perror(AMIInt);
		exit(1);
	}
	close(amifds[1]);
	while ((nchars = read(amifds[0], buf, sizeof (buf))) > 0)
		if (write(1, buf, nchars) != nchars) {
			perror("write");
			exit(1);
		}
	if (nchars < 0) {
		perror("read");
		exit(1);
	}
	close(amifds[0]);
	while (wait(&status) != -1)
		continue;
	if (status.w_retcode != 0)
		return(-1);
	return(0);
}

int
copydb(from, to)
	String	from;
	String	to;
{
	String	path;
	char	my_data[1024];

	bcopy("data/base/", my_data, sizeof("data/base/"));
	path = FindPath(my_data);
	if (chdir(path) < 0) {
		perror(path);
		exit(1);
	}
	sprintf(my_data, "/bin/cp %s/* %s\0", from, to);
	FlushOutput();
	if (system(my_data) != 0) {
		fprintf(stderr, "%s: system cp error\n", cmdname);
		return(-1);
	}
	if (lognewdb(to) < 0) {
		fprintf(stderr, "%s: failed to log new database\n", cmdname);
		return(-1);
	}
	return(0);
}

int
lognewdb(database)
	char	database[];
{
	int		fd;
	int		nchars;
	union wait	status;
	int		pid;
	int		amifds[2];
	int		catfds[2];
	char		buf[512];
	char		str[8];
	static char	amiint[] = AMIINT;
	static char	*AMIInt = NULL;
	extern long	time();
	char *GetBackendName();

	if (AMIInt == NULL) {
		AMIInt = getenv("AMIINT");
		if (AMIInt == NULL) {
			AMIInt = GetBackendName();
			if (AMIInt == NULL) {
				AMIInt = amiint;
			}
		}
	}

	if (pipe(amifds) < 0) {
		perror("pipe");
		exit(1);
	}
	FlushOutput();
	pid = fork();
	if (pid < 0) {
		perror("fork");
		exit(1);
	}
	if (pid == 0) {
		if ((fd = open("/dev/null", O_WRONLY, 0)) < 0) {
			perror("open");
			exit(1);
		}
		if (DebugMode == 0) {
		    close(1);
		    dup2(fd, 1);
		}
		close(fd);
		close(amifds[0]);

		if (pipe(catfds) < 0) {
			perror("pipe");
			exit(1);
		}
		FlushOutput();
		pid = fork();
		if (pid < 0) {
			perror("fork");
			exit(1);
		}
		if (pid == 0) {
			/* note: limited error checking below */
			close(amifds[1]);
			close(catfds[0]);
			close(0);
			if (DebugMode == 0)
			    close(1);
			writestr(catfds[1], "open pg_database\n");
			writestr(catfds[1], "insert ( ");
			writestr(catfds[1], database);
			buf[0] = ' ';
			ltoa(Useid, buf + 1);
			nchars = strlen(buf);
			buf[nchars] = ' ';
			write(catfds[1], buf, 1 + nchars);
			writestr(catfds[1], database);
			writestr(catfds[1], " )\n");
			writestr(catfds[1], "show\nclose pg_database\n");
			close(catfds[1]);
			if (DebugMode == 0)
			    close(2);
			exit(0);
		}
		close(fd);
		close(catfds[1]);
		dup2(catfds[0], fd);
		close(catfds[0]);

		close(0);
		dup2(fd, 0);
		close(fd);
		close(2);
		dup2(amifds[1], 2);
		close(amifds[1]);
		/* if (islocal) child not waited for */

		strcpy(str, "-CO");
		if (DebugMode)
		    strcat(str, "d");
		else
		    strcat(str, "Q");
		if (DebugMode) {
		    printf("Exec: %s %s %s\n", AMIInt, str, database);
		    sleep (2);
		}
		execl(AMIInt, AMIInt, str, "-ami", database, 0);
		perror(AMIInt);
		exit(1);
	}
	close(amifds[1]);
	while ((nchars = read(amifds[0], buf, sizeof (buf))) > 0)
		if (write(1, buf, nchars) != nchars) {
			perror("write");
			exit(1);
		}
	if (nchars < 0) {
		perror("read");
		exit(1);
	}
	close(amifds[0]);
	while (wait(&status) != -1)
		continue;
	if (status.w_retcode != 0)
		return(-1);
	return(0);
}

/**********************************************************************
  installfiles
  installs the files necessary for operation of createdb in the
  directory specified by the parameter 'path'

 **********************************************************************/

int
installfiles(path)
	char	*path;
{
     static char	srcpath[256],destpath[256];
     
     sprintf(srcpath, "%s/%s\0", SCRDIR, SharedTemplateSource);
     sprintf(destpath,"%s/%s\0",path,SharedTemplateDestination);
     printf("%s: now copying %s %s\n", cmdname, srcpath, destpath);
     if (copyfile(srcpath, destpath) == -1) {
	     fprintf(stderr, "%s: could not install shared system file %s\n",
		    SharedTemplateDestination);
	     return(-1);
     }

     sprintf(srcpath, "%s/%s\0", SCRDIR, LocalTemplateSource);
     sprintf(destpath,"%s/%s\0",path,LocalTemplateDestination);
     printf("%s: now copying %s %s\n", cmdname, srcpath, destpath);
     if (copyfile(srcpath, destpath) == -1) {
	     fprintf(stderr, "%s: could not install local system file %s\n",
		    cmdname, LocalTemplateDestination);
	     return(-1);
     }
     return(0);
}

int
copyfile(sourceName, destinationName)
	char	*sourceName;
	char	*destinationName;
{
	int	sourceDescriptor;
	int	destinationDescriptor;
	int	nchars;
	char	buf[8192];

	sourceDescriptor = open(sourceName, O_RDONLY, 00);
	if (sourceDescriptor == -1) {
		perror(sourceName);
		return -1;
	}

	destinationDescriptor = open(destinationName, O_WRONLY|O_CREAT|O_EXCL,
		0644);
	if (destinationDescriptor == -1) {
		perror(destinationName);
		close(destinationDescriptor);
		return -1;
	}

	while ((nchars = read(sourceDescriptor, buf, sizeof buf)) > 0) {
		if (write(destinationDescriptor, buf, nchars) < nchars) {
			perror("write");
			exit(1);
		}
	}
	if (nchars == -1) {
		perror("read");
		exit(1);
	}
	close(destinationDescriptor);
	close(sourceDescriptor);
	return(0);
}

String
FindPath(tail)
	String	tail;
{
	Size		length;
	String		string;
	static char	*append = NULL;
	static char	path[1024];
	extern char	*GetDataHome();

	if (append == NULL) {
		string = GetDataHome();
		length = strlen(string);
		bcopy(string, path, length);
		append = &path[length];
		*append = '/';
		append += 1;
	}
	length = strlen(tail);
	bcopy(tail, append, 1 + length);
	append[length] = '\0';
	return (path);
}

/*
 *	ltoa		- converts a long int to its string represention
 *
 *	Identical to version in ~postgres/src/fmgr/numutils.c.
 */
ltoa(l, a)
	register long	l;
	register char	*a;
{
	register char	*t;
	char		temp[11];

	if (l < 0) {
		l = -l;
		*a++ = '-';
	}
	t = temp + 10;
	*t-- = '\0';
	do {
		*t-- = l % 10 + '0';
		l /= 10;
	} while (l != 0);
	do {
		*a++ = *++t;
	} while (*t != '\0');
}

writestr(fd, str)
char *str;
{
    return(write(fd, str, strlen(str)));
}

/*
 * GetBackendName returns $POSTGRESHOME/bin/backend or NUL if it doesn't
 * exist.
 */

char *GetBackendName()

#define BACKEND "/bin/backend"

{
	FILE *fp;
	char *postgres_home, *return_value, *getenv(), *malloc();

	postgres_home = getenv("POSTGRESHOME");
	return_value = malloc(strlen(postgres_home) + strlen(BACKEND) + 1);
	strcpy(return_value, postgres_home);
	strcat(return_value, BACKEND);

	/*
	 * does this file exist ??
	 */
	fp = fopen(return_value, "r");
	if (fp==NULL) {
	    return(NULL);
	} else {
	    fclose(fp);
	    return(return_value);
	}
}

/*
 *	GetDataHome
 *
 *	Extract the installation home directory from the environment.
 */
char *
GetDataHome()
{
	char		*home;
	extern char	*getenv();

	home = getenv("POSTGRESHOME");
	if (!StringIsValid(home)) {
		home = getenv("POSTHOME");
	}
	if (!StringIsValid(home)) {
		home = DATAHOME;
	}
	return(home);
}

/* XXX Hack so linking to postgres stuff doesn't fail */

exitpg(num)

int num;

{
	exit(num);
}
@


1.22
log
@*** empty log message ***
@
text
@d25 1
a25 1
#include "c.h"
d27 1
a27 1
RcsId("$Header: RCS/createdb.c,v 1.21 90/07/12 01:39:45 kemnitz Version_2 Locker: kemnitz $");
d41 1
a41 2
#include "c.h"
#include "log.h"
d44 1
a44 1
#include "master.h"	/* for DefaultVacuumDemonPath */
@


1.21
log
@Now it complains if POSTGRESHOME isn't set.
@
text
@d27 1
a27 1
RcsId("$Header: RCS/createdb.c,v 1.20 90/07/11 21:22:13 kemnitz Exp Locker: kemnitz $");
@


1.20
log
@Added a few things so that it can be linked without cinterface.a
@
text
@d27 1
a27 1
RcsId("$Header: RCS/createdb.c,v 1.19 90/02/13 00:44:59 kemnitz Exp Locker: kemnitz $");
d77 1
d149 7
@


1.19
log
@Merged changes in 1.17 (fixes to strings) with changes in 1.18
(exitpg added).
@
text
@d27 1
a27 1
RcsId("$Header: RCS/createdb.c,v 1.17 90/02/08 00:29:04 kemnitz Exp $");
d76 1
d145 1
a145 1
	     exitpg(1);
d168 1
a168 1
		    exitpg(1);
d174 1
a174 1
		    exitpg(1);
d182 1
a182 1
		       exitpg(1);
d189 1
a189 1
		       exitpg(1);
d206 1
a206 1
		    exitpg(1);
d213 1
a213 1
		    exitpg(1);
d223 1
a223 1
		       exitpg(1);
d231 1
a231 1
		       exitpg(1);
d242 1
a242 1
		  exitpg(1);
d250 1
a250 1
			  exitpg(1);
d253 1
a253 1
			  exitpg(1);
d266 1
a266 1
		       exitpg(1);
d270 1
a270 1
	       exitpg(1);
d280 1
a280 1
			    exitpg(1);
d284 1
a284 1
		    exitpg(1);
d294 1
a294 1
		       exitpg(1);
d316 1
a316 1
		  exitpg(1);
d327 1
a327 1
	     exitpg(1);
d370 1
a370 1
				exitpg(1);
d376 1
a376 1
				exitpg(1);
d384 1
a384 1
				exitpg(1);
d392 1
a392 1
			exitpg(1);
d398 1
a398 1
			exitpg(1);
d404 1
a404 1
			exitpg(1);
d432 1
a432 1
		exitpg(1);
d439 1
a439 1
			exitpg(1);
d443 1
a443 1
			exitpg(1);
d452 1
a452 1
		exitpg(1);
d461 1
a461 1
		exitpg(1);
d468 1
a468 1
		exitpg(1);
d473 1
a473 1
			exitpg(1);
d477 1
a477 1
			exitpg(1);
d479 1
a479 1
		exitpg(0);
d550 1
a550 1
		exitpg(1);
d556 1
a556 1
		exitpg(1);
d562 1
a562 1
			exitpg(1);
d572 1
a572 1
			exitpg(1);
d578 1
a578 1
				exitpg(1);
d584 1
a584 1
				exitpg(1);
d596 1
a596 1
					exitpg(1);
d600 1
a600 1
				    exitpg(1);
d618 1
a618 1
				exitpg(0);
d644 1
a644 1
		exitpg(1);
d650 1
a650 1
			exitpg(1);
d654 1
a654 1
		exitpg(1);
d676 1
a676 1
		exitpg(1);
d720 1
a720 1
		exitpg(1);
d726 1
a726 1
		exitpg(1);
d731 1
a731 1
			exitpg(1);
d742 1
a742 1
			exitpg(1);
d748 1
a748 1
			exitpg(1);
d771 1
a771 1
			exitpg(0);
d797 1
a797 1
		exitpg(1);
d803 1
a803 1
			exitpg(1);
d807 1
a807 1
		exitpg(1);
d877 1
a877 1
			exitpg(1);
d882 1
a882 1
		exitpg(1);
d974 31
@


1.18
log
@added buffer manager statistics and exitpg() stuff -cim
@
text
@d27 1
a27 1
RcsId("$Header: RCS/createdb.c,v 1.16 90/01/30 23:06:08 sp Exp $");
d305 8
d669 1
a669 1
	char	tail[80];
d671 2
a672 2
	bcopy("data/base/", tail, sizeof("data/base/"));
	path = FindPath(tail);
d677 1
a677 1
	sprintf(path, "/bin/cp %s/* %s\0", from, to);
d679 1
a679 1
	if (system(path) != 0) {
d908 1
@


1.17
log
@Fixed various string problems - including "rm /bin/cp" problem.
@
text
@d27 1
a27 1
RcsId("$Header: RCS/createdb.c,v 1.16 90/01/30 23:06:08 sp Exp Locker: kemnitz $");
d144 1
a144 1
	     exit(1);
d167 1
a167 1
		    exit(1);
d173 1
a173 1
		    exit(1);
d181 1
a181 1
		       exit(1);
d188 1
a188 1
		       exit(1);
d205 1
a205 1
		    exit(1);
d212 1
a212 1
		    exit(1);
d222 1
a222 1
		       exit(1);
d230 1
a230 1
		       exit(1);
d241 1
a241 1
		  exit(1);
d249 1
a249 1
			  exit(1);
d252 1
a252 1
			  exit(1);
d265 1
a265 1
		       exit(1);
d269 1
a269 1
	       exit(1);
d279 1
a279 1
			    exit(1);
d283 1
a283 1
		    exit(1);
d293 1
a293 1
		       exit(1);
a304 8

/* 
 * Hack by GJK to make it delete the right file - should be using strcpy
 * instead of bcopy all over this code.  This pointer string crap sucks
 * and should probably be rewritten.
 */

		  append[strlen(argv[optind])] = '\0'; 
d307 1
a307 1
		  exit(1);
d318 1
a318 1
	     exit(1);
d361 1
a361 1
				exit(1);
d367 1
a367 1
				exit(1);
d375 1
a375 1
				exit(1);
d383 1
a383 1
			exit(1);
d389 1
a389 1
			exit(1);
d395 1
a395 1
			exit(1);
d423 1
a423 1
		exit(1);
d430 1
a430 1
			exit(1);
d434 1
a434 1
			exit(1);
d443 1
a443 1
		exit(1);
d452 1
a452 1
		exit(1);
d459 1
a459 1
		exit(1);
d464 1
a464 1
			exit(1);
d468 1
a468 1
			exit(1);
d470 1
a470 1
		exit(0);
d541 1
a541 1
		exit(1);
d547 1
a547 1
		exit(1);
d553 1
a553 1
			exit(1);
d563 1
a563 1
			exit(1);
d569 1
a569 1
				exit(1);
d575 1
a575 1
				exit(1);
d587 1
a587 1
					exit(1);
d591 1
a591 1
				    exit(1);
d609 1
a609 1
				exit(0);
d635 1
a635 1
		exit(1);
d641 1
a641 1
			exit(1);
d645 1
a645 1
		exit(1);
d661 1
a661 1
	char	my_data[1024];
d663 2
a664 2
	bcopy("data/base/", my_data, sizeof("data/base/"));
	path = FindPath(my_data);
d667 1
a667 1
		exit(1);
d669 1
a669 1
	sprintf(my_data, "/bin/cp %s/* %s\0", from, to);
d671 1
a671 1
	if (system(my_data) != 0) {
d711 1
a711 1
		exit(1);
d717 1
a717 1
		exit(1);
d722 1
a722 1
			exit(1);
d733 1
a733 1
			exit(1);
d739 1
a739 1
			exit(1);
d762 1
a762 1
			exit(0);
d788 1
a788 1
		exit(1);
d794 1
a794 1
			exit(1);
d798 1
a798 1
		exit(1);
d868 1
a868 1
			exit(1);
d873 1
a873 1
		exit(1);
a899 1
	append[length] = '\0';
@


1.16
log
@oops! now GetBackendname() checks for file existence!
@
text
@d27 1
a27 1
RcsId("$Header: RCS/createdb.c,v 1.15 90/01/26 23:16:25 kemnitz Exp $");
d305 8
d669 1
a669 1
	char	tail[80];
d671 2
a672 2
	bcopy("data/base/", tail, sizeof("data/base/"));
	path = FindPath(tail);
d677 1
a677 1
	sprintf(path, "/bin/cp %s/* %s\0", from, to);
d679 1
a679 1
	if (system(path) != 0) {
d908 1
@


1.15
log
@Changed the fork stuff which runs the backend so it uses
$POSTGRESHOME/bin/backend before trying to use (obj.dir)/support/backend.

,
@
text
@d27 1
a27 1
RcsId("$Header: RCS/createdb.c,v 1.14 89/10/11 01:08:21 hirohama Exp Locker: kemnitz $");
d946 1
d953 11
a963 1
	return(return_value);
@


1.14
log
@SRCDIR -> SCRDIR at least until dmake is not supported
@
text
@d27 1
a27 1
RcsId("$Header: RCS/createdb.c,v 1.13 89/10/09 22:35:04 mao Exp Locker: hirohama $");
d514 1
d519 4
a522 1
			AMIInt = amiint;
d697 1
d702 4
a705 1
			AMIInt = amiint;
d936 18
@


1.13
log
@don't use mao's private vacuumd anymore.  this is real life.
@
text
@d27 1
a27 1
RcsId("$Header: RCS/createdb.c,v 1.12 89/10/09 22:29:03 mao Exp Locker: mao $");
d81 1
a81 1
#ifndef SRCDIR
d813 1
a813 1
     sprintf(srcpath,"%s/%s\0",SRCDIR,SharedTemplateSource);
d822 1
a822 1
     sprintf(srcpath,"%s/%s\0",SRCDIR,LocalTemplateSource);
@


1.12
log
@use SRCDIR -- typo made this SCRDIR
@
text
@d27 1
a27 1
RcsId("$Header: RCS/createdb.c,v 1.11 89/09/20 17:31:47 mao Exp Locker: mao $");
a47 2
#undef DefaultVacuumDemonPath
#define DefaultVacuumDemonPath	"/a/postgres/mao/postgres/obj.sun/support/vacuumd"
@


1.11
log
@works with new version of vacuumd
@
text
@d27 1
a27 1
RcsId("$Header: RCS/createdb.c,v 1.10 89/09/11 16:42:54 hirohama Exp $");
d83 1
a83 1
#ifndef SCRDIR
d815 1
a815 1
     sprintf(srcpath,"%s/%s\0",SCRDIR,SharedTemplateSource);
d824 1
a824 1
     sprintf(srcpath,"%s/%s\0",SCRDIR,LocalTemplateSource);
@


1.10
log
@check in of *non-stable* version
don't check this out without later fixes
@
text
@d27 1
a27 1
RcsId("$Header: RCS/createdb.c,v 1.9 89/09/05 16:52:21 mao C_Demo_1 Locker: hirohama $");
d48 2
@


1.9
log
@Working version of C-only demo
@
text
@d25 4
a47 2
RcsId("$Header: RCS/createdb.c,v 1.8 89/08/03 04:41:16 dillon Exp Locker: mao $");

d53 1
a53 1
#define OptionString	"p:h:v:t:e:d"
a314 4
     puts("WARNING: Vacuum Daemon code temporarily removed!");
    
#ifdef NOTDEF

d326 4
a329 7
/*
		     if (gethostname(&hostStringData, 32) == -1) {
			     perror("gethostname");
			     exit(1);
		     }
		     hostString = &hostStringData;
*/
a342 2
#endif

@


1.8
log
@now #include's installinfo.h (from obj*/installinfo.h)
@
text
@d44 1
a44 1
RcsId("$Header: /usr6/postgres/dillon/tree/src/support/RCS/createdb.c,v 1.7 89/08/03 00:18:35 dillon Exp $");
d282 3
a284 3
	  } else {
	       mknwdirs(path, euid);
	  }
d293 1
a293 1
	  SetPgVersion(path);
@


1.7
log
@*** empty log message ***
@
text
@d25 2
d44 1
a44 1
RcsId("$Header: /usr6/postgres/dillon/tree/src/support/RCS/createdb.c,v 1.6 89/08/02 23:56:29 dillon Exp $");
@


1.6
log
@major changes, works with new backend now
@
text
@d42 1
a42 1
RcsId("$Header: createdb.c,v 1.5 89/07/17 14:41:50 dillon Locked $");
d595 1
a595 1
				writestr(catfds[1], "insert ( 0 ");
d746 1
a746 1
			writestr(catfds[1], "insert ( 0 ");
@


1.5
log
@sends the -ami flag to the backend so the backendparse.y parser is used.
@
text
@d42 1
a42 1
RcsId("$Header: createdb.c,v 1.4 89/07/17 14:39:38 dillon Locked $");
a66 1
static int	SlowCreation;
d75 1
a75 1
#define AMIINT	"/tmp/bin/backend"
d78 1
a78 1
#define SCRDIR	"/a/postgres/dillon/postgres/src/support"
a625 2
		if (SlowCreation == 0)
		    strcat(str, "Q");
d628 2
d773 1
a774 2
		if (SlowCreation == 0)
		    strcat(str, "Q");
d777 2
@


1.4
log
@createdb now uses *.bki scripts for the Mike H parser (backendparse.y)

@
text
@d42 1
a42 1
RcsId("$Header: createdb.c,v 1.3 89/03/06 18:11:26 dillon Locked $");
d635 1
a635 1
		execl(AMIInt, AMIInt, str, database, 0);
d783 1
a783 1
		execl(AMIInt, AMIInt, str, database, 0);
@


1.3
log
@removed AMIINT and SCRDIR hacks
@
text
@d15 2
a16 2
 *	.../../files/global.ami	global database creation script
 *	.../../files/local1_template1.ami
d18 2
a19 2
 *	support/dbdb.ami	global database default script
 *	support/local.ami	local database default script
d24 1
d42 1
a42 1
RcsId("$Header: createdb.c,v 1.2 89/02/02 15:57:31 hirohama Locked $");
d49 1
a49 1
#define OptionString	"p:h:v:t:e"
d51 4
a54 4
#define SharedTemplateSource		"dbdb.ami"
#define LocalTemplateSource		"local.ami"
#define SharedTemplateDestination	"global1.ami"
#define LocalTemplateDestination	"local1_template1.ami"
d68 1
d74 8
d107 3
d312 4
d347 2
d504 1
d529 2
a530 2
		bcopy("files/global1.ami", templatePath,
			sizeof ("files/global1.ami"));
d538 1
a538 1
		bcopy(".ami", append, sizeof (".ami"));
d557 4
a560 2
		close(1);
		dup2(fd, 1);
d584 7
a590 6
				close(1);
				while ((nchars = read(fd, buf, sizeof (buf))) > 0)
					if (write(catfds[1], buf, nchars) != nchars) {
						perror("write");
						exit(1);
					}
d592 2
a593 2
					perror("read");
					exit(1);
d595 3
a597 3
				write(catfds[1], "o pg_database\n", 14);
				write(catfds[1], "i 0 ", 4);
				write(catfds[1], database, strlen(database));
d603 6
a608 2
				write(catfds[1], database, strlen(database));
				write(catfds[1], "\np\nc\n", 5);
d625 11
a635 2
		execl(AMIInt, AMIInt, (SlowCreation) ? "-CO" : "-CQO", database,
			0);
d695 1
d722 4
a725 2
		close(1);
		dup2(fd, 1);
d744 5
a748 4
			close(1);
			write(catfds[1], "o pg_database\n", 14);
			write(catfds[1], "i 0 ", 4);
			write(catfds[1], database, strlen(database));
d754 3
a756 2
			write(catfds[1], database, strlen(database));
			write(catfds[1], "\np\nc\n", 5);
d758 2
a759 1
			close(2);
d774 10
a783 2
		execl(AMIInt, AMIInt, (SlowCreation) ? "-CO" : "-CQO", database,
			0);
d926 7
@


1.2
log
@txfer from old tree
@
text
@d41 1
a41 1
RcsId("$Header: createdb.c,v 1.13 88/09/13 01:29:13 dillon Locked $");
a53 7

#ifndef AMIINT
#define	AMIINT		"/usr/postgres/bin/amiint"
#endif
#ifndef SCRDIR
#define	SCRDIR		"/usr/postgres/src/support"
#endif
@


1.1
log
@Initial revision
@
text
@a0 1

a1 26
 * 
 * POSTGRES Data Base Management System
 * 
 * Copyright (c) 1988 Regents of the University of California
 * 
 * Permission to use, copy, modify, and distribute this software and its
 * documentation for educational, research, and non-profit purposes and
 * without fee is hereby granted, provided that the above copyright
 * notice appear in all copies and that both that copyright notice and
 * this permission notice appear in supporting documentation, and that
 * the name of the University of California not be used in advertising
 * or publicity pertaining to distribution of the software without
 * specific, written prior permission.  Permission to incorporate this
 * software into commercial products can be obtained from the Campus
 * Software Office, 295 Evans Hall, University of California, Berkeley,
 * Ca., 94720 provided only that the the requestor give the University
 * of California a free licence to any derived software for educational
 * and research purposes.  The University of California makes no
 * representations about the suitability of this software for any
 * purpose.  It is provided "as is" without express or implied warranty.
 * 
 */



/*
d41 1
a41 1
RcsId("$Header: createdb.c,v 1.1 88/11/11 16:39:54 postgres Exp $");
@
