⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pg_ctl.c

📁 PostgreSQL 8.1.4的源码 适用于Linux下的开源数据库系统
💻 C
📖 第 1 页 / 共 3 页
字号:
/*------------------------------------------------------------------------- * * pg_ctl --- start/stops/restarts the PostgreSQL server * * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group * * $PostgreSQL: pgsql/src/bin/pg_ctl/pg_ctl.c,v 1.61.2.2 2006/01/14 16:16:08 petere Exp $ * *------------------------------------------------------------------------- */#include "postgres_fe.h"#include "libpq-fe.h"#include <locale.h>#include <signal.h>#include <sys/types.h>#include <sys/stat.h>#include <unistd.h>#include "libpq/pqsignal.h"#include "getopt_long.h"#if defined(__CYGWIN__)#include <sys/cygwin.h>#include <windows.h>/* Cygwin defines WIN32 in windows.h, but we don't want it. */#undef WIN32#endif#ifndef HAVE_INT_OPTRESETint			optreset;#endif/* PID can be negative for standalone backend */typedef long pgpid_t;#define WHITESPACE "\f\n\r\t\v" /* as defined by isspace() *//* postmaster version ident string */#define PM_VERSIONSTR "postmaster (PostgreSQL) " PG_VERSION "\n"typedef enum{	SMART_MODE,	FAST_MODE,	IMMEDIATE_MODE} ShutdownMode;typedef enum{	NO_COMMAND = 0,	START_COMMAND,	STOP_COMMAND,	RESTART_COMMAND,	RELOAD_COMMAND,	STATUS_COMMAND,	KILL_COMMAND,	REGISTER_COMMAND,	UNREGISTER_COMMAND,	RUN_AS_SERVICE_COMMAND} CtlCommand;static bool do_wait = false;static bool wait_set = false;static int	wait_seconds = 60;static bool silent_mode = false;static ShutdownMode shutdown_mode = SMART_MODE;static int	sig = SIGTERM;		/* default */static CtlCommand ctl_command = NO_COMMAND;static char *pg_data = NULL;static char *pgdata_opt = NULL;static char *post_opts = NULL;static const char *progname;static char *log_file = NULL;static char *postgres_path = NULL;static char *register_servicename = "PostgreSQL";		/* FIXME: + version ID? */static char *register_username = NULL;static char *register_password = NULL;static char *argv0 = NULL;static voidwrite_stderr(const char *fmt,...)/* This extension allows gcc to check the format string for consistency with   the supplied arguments. */__attribute__((format(printf, 1, 2)));static void *pg_malloc(size_t size);static char *xstrdup(const char *s);static void do_advice(void);static void do_help(void);static void set_mode(char *modeopt);static void set_sig(char *signame);static void do_start(void);static void do_stop(void);static void do_restart(void);static void do_reload(void);static void do_status(void);static void do_kill(pgpid_t pid);static void print_msg(const char *msg);#if defined(WIN32) || defined(__CYGWIN__)static bool pgwin32_IsInstalled(SC_HANDLE);static char *pgwin32_CommandLine(bool);static void pgwin32_doRegister(void);static void pgwin32_doUnregister(void);static void pgwin32_SetServiceStatus(DWORD);static void WINAPI pgwin32_ServiceHandler(DWORD);static void WINAPI pgwin32_ServiceMain(DWORD, LPTSTR *);static void pgwin32_doRunAsService(void);#endifstatic pgpid_t get_pgpid(void);static char **readfile(const char *path);static int	start_postmaster(void);static bool test_postmaster_connection(void);static bool postmaster_is_alive(pid_t pid);static char def_postopts_file[MAXPGPATH];static char postopts_file[MAXPGPATH];static char pid_file[MAXPGPATH];static char conf_file[MAXPGPATH];#if defined(WIN32) || defined(__CYGWIN__)static voidwrite_eventlog(int level, const char *line){	static HANDLE evtHandle = INVALID_HANDLE_VALUE;	if (evtHandle == INVALID_HANDLE_VALUE)	{		evtHandle = RegisterEventSource(NULL, "PostgreSQL");		if (evtHandle == NULL)		{			evtHandle = INVALID_HANDLE_VALUE;			return;		}	}	ReportEvent(evtHandle,				level,				0,				0,				/* All events are Id 0 */				NULL,				1,				0,				&line,				NULL);}#endif/* * Write errors to stderr (or by equal means when stderr is * not available). */static voidwrite_stderr(const char *fmt,...){	va_list		ap;	va_start(ap, fmt);#if !defined(WIN32) && !defined(__CYGWIN__)	/* On Unix, we just fprintf to stderr */	vfprintf(stderr, fmt, ap);#else	/*	 * On Win32, we print to stderr if running on a console, or write to	 * eventlog if running as a service	 */	if (!isatty(fileno(stderr)))	/* Running as a service */	{		char		errbuf[2048];		/* Arbitrary size? */		vsnprintf(errbuf, sizeof(errbuf), fmt, ap);		write_eventlog(EVENTLOG_ERROR_TYPE, errbuf);	}	else		/* Not running as service, write to stderr */		vfprintf(stderr, fmt, ap);#endif	va_end(ap);}/* * routines to check memory allocations and fail noisily. */static void *pg_malloc(size_t size){	void	   *result;	result = malloc(size);	if (!result)	{		write_stderr(_("%s: out of memory\n"), progname);		exit(1);	}	return result;}static char *xstrdup(const char *s){	char	   *result;	result = strdup(s);	if (!result)	{		write_stderr(_("%s: out of memory\n"), progname);		exit(1);	}	return result;}/* * Given an already-localized string, print it to stdout unless the * user has specified that no messages should be printed. */static voidprint_msg(const char *msg){	if (!silent_mode)	{		fputs(msg, stdout);		fflush(stdout);	}}static pgpid_tget_pgpid(void){	FILE	   *pidf;	long		pid;	pidf = fopen(pid_file, "r");	if (pidf == NULL)	{		/* No pid file, not an error on startup */		if (errno == ENOENT)			return 0;		else		{			write_stderr(_("%s: could not open PID file \"%s\": %s\n"),						 progname, pid_file, strerror(errno));			exit(1);		}	}	if (fscanf(pidf, "%ld", &pid) != 1)	{		write_stderr(_("%s: invalid data in PID file \"%s\"\n"),					 progname, pid_file);		exit(1);	}	fclose(pidf);	return (pgpid_t) pid;}/* * get the lines from a text file - return NULL if file can't be opened */static char **readfile(const char *path){	FILE	   *infile;	int			maxlength = 0,				linelen = 0;	int			nlines = 0;	char	  **result;	char	   *buffer;	int			c;	if ((infile = fopen(path, "r")) == NULL)		return NULL;	/* pass over the file twice - the first time to size the result */	while ((c = fgetc(infile)) != EOF)	{		linelen++;		if (c == '\n')		{			nlines++;			if (linelen > maxlength)				maxlength = linelen;			linelen = 0;		}	}	/* handle last line without a terminating newline (yuck) */	if (linelen)		nlines++;	if (linelen > maxlength)		maxlength = linelen;	/* set up the result and the line buffer */	result = (char **) pg_malloc((nlines + 1) * sizeof(char *));	buffer = (char *) pg_malloc(maxlength + 1);	/* now reprocess the file and store the lines */	rewind(infile);	nlines = 0;	while (fgets(buffer, maxlength + 1, infile) != NULL)		result[nlines++] = xstrdup(buffer);	fclose(infile);	result[nlines] = NULL;	return result;}/* * start/test/stop routines */static intstart_postmaster(void){	/*	 * Since there might be quotes to handle here, it is easier simply to pass	 * everything to a shell to process them.	 */	char		cmd[MAXPGPATH];	/*	 * Win32 needs START /B rather than "&".	 *	 * Win32 has a problem with START and quoted executable names. You must	 * add a "" as the title at the beginning so you can quote the executable	 * name: http://www.winnetmag.com/Article/ArticleID/14589/14589.html	 * http://dev.remotenetworktechnology.com/cmd/cmdfaq.htm	 */	if (log_file != NULL)#ifndef WIN32					/* Cygwin doesn't have START */		snprintf(cmd, MAXPGPATH, "%s\"%s\" %s%s < \"%s\" >> \"%s\" 2>&1 &%s",				 SYSTEMQUOTE, postgres_path, pgdata_opt, post_opts,				 DEVNULL, log_file, SYSTEMQUOTE);#else		snprintf(cmd, MAXPGPATH, "%sSTART /B \"\" \"%s\" %s%s < \"%s\" >> \"%s\" 2>&1%s",				 SYSTEMQUOTE, postgres_path, pgdata_opt, post_opts,				 DEVNULL, log_file, SYSTEMQUOTE);#endif	else#ifndef WIN32					/* Cygwin doesn't have START */		snprintf(cmd, MAXPGPATH, "%s\"%s\" %s%s < \"%s\" 2>&1 &%s",				 SYSTEMQUOTE, postgres_path, pgdata_opt, post_opts,				 DEVNULL, SYSTEMQUOTE);#else		snprintf(cmd, MAXPGPATH, "%sSTART /B \"\" \"%s\" %s%s < \"%s\" 2>&1%s",				 SYSTEMQUOTE, postgres_path, pgdata_opt, post_opts,				 DEVNULL, SYSTEMQUOTE);#endif	return system(cmd);}/* Find the pgport and try a connection */static booltest_postmaster_connection(void){	PGconn	   *conn;	bool		success = false;	int			i;	char		portstr[32];	char	   *p;	*portstr = '\0';	/* post_opts */	for (p = post_opts; *p;)	{		/* advance past whitespace/quoting */		while (isspace((unsigned char) *p) || *p == '\'' || *p == '"')			p++;		if (strncmp(p, "-p", strlen("-p")) == 0)		{			p += strlen("-p");			/* advance past whitespace/quoting */			while (isspace((unsigned char) *p) || *p == '\'' || *p == '"')				p++;			StrNCpy(portstr, p, Min(strcspn(p, "\"'" WHITESPACE) + 1,									sizeof(portstr)));			/* keep looking, maybe there is another -p */		}		/* Advance to next whitespace */		while (*p && !isspace((unsigned char) *p))			p++;	}	/* config file */	if (!*portstr)	{		char	  **optlines;		optlines = readfile(conf_file);		if (optlines != NULL)		{			for (; *optlines != NULL; optlines++)			{				p = *optlines;				while (isspace((unsigned char) *p))					p++;				if (strncmp(p, "port", strlen("port")) != 0)					continue;				p += strlen("port");				while (isspace((unsigned char) *p))					p++;				if (*p != '=')					continue;				p++;				while (isspace((unsigned char) *p))					p++;				StrNCpy(portstr, p, Min(strcspn(p, "#" WHITESPACE) + 1,										sizeof(portstr)));				/* keep looking, maybe there is another */			}		}	}	/* environment */	if (!*portstr && getenv("PGPORT") != NULL)		StrNCpy(portstr, getenv("PGPORT"), sizeof(portstr));	/* default */	if (!*portstr)		snprintf(portstr, sizeof(portstr), "%d", DEF_PGPORT);	for (i = 0; i < wait_seconds; i++)	{		if ((conn = PQsetdbLogin(NULL, portstr, NULL, NULL,								 "postgres", NULL, NULL)) != NULL &&			(PQstatus(conn) == CONNECTION_OK ||			 (strcmp(PQerrorMessage(conn),					 PQnoPasswordSupplied) == 0)))		{			PQfinish(conn);			success = true;			break;		}		else		{			print_msg(".");			pg_usleep(1000000); /* 1 sec */		}	}	return success;}static voiddo_start(void){	pgpid_t		pid;	pgpid_t		old_pid = 0;	char	   *optline = NULL;	int			exitcode;	if (ctl_command != RESTART_COMMAND)	{		old_pid = get_pgpid();		if (old_pid != 0)			write_stderr(_("%s: another postmaster may be running; "						   "trying to start postmaster anyway\n"),						 progname);	}	if (post_opts == NULL)	{		char	  **optlines;		int			len;		optlines = readfile(ctl_command == RESTART_COMMAND ?							postopts_file : def_postopts_file);		if (optlines == NULL)		{			if (ctl_command == START_COMMAND)				post_opts = "";			else			{				write_stderr(_("%s: could not read file \"%s\"\n"), progname, postopts_file);				exit(1);			}		}		else if (optlines[0] == NULL || optlines[1] != NULL)		{			write_stderr(_("%s: option file \"%s\" must have exactly one line\n"),						 progname, ctl_command == RESTART_COMMAND ?						 postopts_file : def_postopts_file);			exit(1);		}		else		{			optline = optlines[0];			len = strcspn(optline, "\r\n");			optline[len] = '\0';			if (ctl_command == RESTART_COMMAND)			{				char	   *arg1;				arg1 = strchr(optline, *SYSTEMQUOTE);				if (arg1 == NULL || arg1 == optline)					post_opts = "";				else				{					*(arg1 - 1) = '\0'; /* this should be a space */					post_opts = arg1;				}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -