static void
set_mode(char *modeopt)
{
	if (strcmp(modeopt, "s") == 0 || strcmp(modeopt, "smart") == 0)
	{
		shutdown_mode = SMART_MODE;
		sig = SIGTERM;
	}
	else if (strcmp(modeopt, "f") == 0 || strcmp(modeopt, "fast") == 0)
	{
		shutdown_mode = FAST_MODE;
		sig = SIGINT;
	}
	else if (strcmp(modeopt, "i") == 0 || strcmp(modeopt, "immediate") == 0)
	{
		shutdown_mode = IMMEDIATE_MODE;
		sig = SIGQUIT;
	}
	else
	{
		write_stderr(_("%s: unrecognized shutdown mode \"%s\"\n"), progname, modeopt);
		do_advice();
		exit(1);
	}
}
static void
set_sig(char *signame)
{
	if (!strcmp(signame, "HUP"))
		sig = SIGHUP;
	else if (!strcmp(signame, "INT"))
		sig = SIGINT;
	else if (!strcmp(signame, "QUIT"))
		sig = SIGQUIT;
	else if (!strcmp(signame, "ABRT"))
		sig = SIGABRT;

	/*
	 * probably should NOT provide SIGKILL
	 *
	 * else if (!strcmp(signame,"KILL")) sig = SIGKILL;
	 */
	else if (!strcmp(signame, "TERM"))
		sig = SIGTERM;
	else if (!strcmp(signame, "USR1"))
		sig = SIGUSR1;
	else if (!strcmp(signame, "USR2"))
		sig = SIGUSR2;
	else
	{
		write_stderr(_("%s: unrecognized signal name \"%s\"\n"), progname, signame);
		do_advice();
		exit(1);
	}

}
int
main(int argc, char **argv)
{
	static struct option long_options[] = {
		{"help", no_argument, NULL, '?'},
		{"version", no_argument, NULL, 'V'},
		{"log", required_argument, NULL, 'l'},
		{"mode", required_argument, NULL, 'm'},
		{"pgdata", required_argument, NULL, 'D'},
		{"silent", no_argument, NULL, 's'},
		{"timeout", required_argument, NULL, 't'},
		{"core-files", no_argument, NULL, 'c'},
		{NULL, 0, NULL, 0}
	};

	int			option_index;
	int			c;
	pgpid_t		killproc = 0;

#if defined(WIN32) || defined(__CYGWIN__)
	setvbuf(stderr, NULL, _IONBF, 0);
#endif

	progname = get_progname(argv[0]);
	set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("pg_ctl"));

	/*
	 * save argv[0] so do_start() can look for the postmaster if necessary. we
	 * don't look for postmaster here because in many cases we won't need it.
	 */
	argv0 = argv[0];

	umask(077);

	/* support --help and --version even if invoked as root */
	if (argc > 1)
	{
		if (strcmp(argv[1], "-h") == 0 || strcmp(argv[1], "--help") == 0 ||
			strcmp(argv[1], "-?") == 0)
		{
			do_help();
			exit(0);
		}
		else if (strcmp(argv[1], "-V") == 0 || strcmp(argv[1], "--version") == 0)
		{
			puts("pg_ctl (PostgreSQL) " PG_VERSION);
			exit(0);
		}
	}

	/*
	 * Disallow running as root, to forestall any possible security holes.
	 */
#ifndef WIN32
	if (geteuid() == 0)
	{
		write_stderr(_("%s: cannot be run as root\n"
					   "Please log in (using, e.g., \"su\") as the "
					   "(unprivileged) user that will\n"
					   "own the server process.\n"),
					 progname);
		exit(1);
	}
#endif

	/*
	 * 'Action' can be before or after args so loop over both. Some
	 * getopt_long() implementations will reorder argv[] to place all flags
	 * first (GNU?), but we don't rely on it. Our /port version doesn't do
	 * that.
	 */
	optind = 1;

	/* process command-line options */
	while (optind < argc)
	{
		while ((c = getopt_long(argc, argv, "cD:l:m:N:o:p:P:st:U:wW", long_options, &option_index)) != -1)
		{
			switch (c)
			{
				case 'D':
					{
						char	   *pgdata_D;
						char	   *env_var = pg_malloc(strlen(optarg) + 8);

						pgdata_D = xstrdup(optarg);
						canonicalize_path(pgdata_D);
						snprintf(env_var, strlen(optarg) + 8, "PGDATA=%s",
								 pgdata_D);
						putenv(env_var);

						/*
						 * We could pass PGDATA just in an environment
						 * variable but we do -D too for clearer postmaster
						 * 'ps' display
						 */
						pgdata_opt = pg_malloc(strlen(pgdata_D) + 7);
						snprintf(pgdata_opt, strlen(pgdata_D) + 7,
								 "-D \"%s\" ",
								 pgdata_D);
						break;
					}
				case 'l':
					log_file = xstrdup(optarg);
					break;
				case 'm':
					set_mode(optarg);
					break;
				case 'N':
					register_servicename = xstrdup(optarg);
					break;
				case 'o':
					post_opts = xstrdup(optarg);
					break;
				case 'p':
					exec_path = xstrdup(optarg);
					break;
				case 'P':
					register_password = xstrdup(optarg);
					break;
				case 's':
					silent_mode = true;
					break;
				case 't':
					wait_seconds = atoi(optarg);
					break;
				case 'U':
					if (strchr(optarg, '\\'))
						register_username = xstrdup(optarg);
					else
						/* Prepend .\ for local accounts */
					{
						register_username = malloc(strlen(optarg) + 3);
						if (!register_username)
						{
							write_stderr(_("%s: out of memory\n"), progname);
							exit(1);
						}
						strcpy(register_username, ".\\");
						strcat(register_username, optarg);
					}
					break;
				case 'w':
					do_wait = true;
					wait_set = true;
					break;
				case 'W':
					do_wait = false;
					wait_set = true;
					break;
				case 'c':
					allow_core_files = true;
					break;
				default:
					/* getopt_long already issued a suitable error message */
					do_advice();
					exit(1);
			}
		}

		/* Process an action */
		if (optind < argc)
		{
			if (ctl_command != NO_COMMAND)
			{
				write_stderr(_("%s: too many command-line arguments (first is \"%s\")\n"), progname, argv[optind]);
				do_advice();
				exit(1);
			}

			if (strcmp(argv[optind], "init") == 0
				|| strcmp(argv[optind], "initdb") == 0)
				ctl_command = INIT_COMMAND;
			else if (strcmp(argv[optind], "start") == 0)
				ctl_command = START_COMMAND;
			else if (strcmp(argv[optind], "stop") == 0)
				ctl_command = STOP_COMMAND;
			else if (strcmp(argv[optind], "restart") == 0)
				ctl_command = RESTART_COMMAND;
			else if (strcmp(argv[optind], "reload") == 0)
				ctl_command = RELOAD_COMMAND;
			else if (strcmp(argv[optind], "status") == 0)
				ctl_command = STATUS_COMMAND;
			else if (strcmp(argv[optind], "kill") == 0)
			{
				if (argc - optind < 3)
				{
					write_stderr(_("%s: missing arguments for kill mode\n"), progname);
					do_advice();
					exit(1);
				}
				ctl_command = KILL_COMMAND;
				set_sig(argv[++optind]);
				killproc = atol(argv[++optind]);
			}
#if defined(WIN32) || defined(__CYGWIN__)
			else if (strcmp(argv[optind], "register") == 0)
				ctl_command = REGISTER_COMMAND;
			else if (strcmp(argv[optind], "unregister") == 0)
				ctl_command = UNREGISTER_COMMAND;
			else if (strcmp(argv[optind], "runservice") == 0)
				ctl_command = RUN_AS_SERVICE_COMMAND;
#endif
			else
			{
				write_stderr(_("%s: unrecognized operation mode \"%s\"\n"), progname, argv[optind]);
				do_advice();
				exit(1);
			}
			optind++;
		}
	}

	if (ctl_command == NO_COMMAND)
	{
		write_stderr(_("%s: no operation specified\n"), progname);
		do_advice();
		exit(1);
	}

	/* Note we put any -D switch into the env var above */
	pg_data = getenv("PGDATA");
	if (pg_data)
	{
		pg_data = xstrdup(pg_data);
		canonicalize_path(pg_data);
	}

	if (pg_data == NULL &&
		ctl_command != KILL_COMMAND && ctl_command != UNREGISTER_COMMAND)
	{
		write_stderr(_("%s: no database directory specified "
					   "and environment variable PGDATA unset\n"),
					 progname);
		do_advice();
		exit(1);
	}

	if (!wait_set)
	{
		switch (ctl_command)
		{
			case RESTART_COMMAND:
			case START_COMMAND:
				do_wait = false;
				break;
			case STOP_COMMAND:
				do_wait = true;
				break;
			default:
				break;
		}
	}

	if (ctl_command == RELOAD_COMMAND)
	{
		sig = SIGHUP;
		do_wait = false;
	}

	if (pg_data)
	{
		snprintf(postopts_file, MAXPGPATH, "%s/postmaster.opts", pg_data);
		snprintf(pid_file, MAXPGPATH, "%s/postmaster.pid", pg_data);
		snprintf(conf_file, MAXPGPATH, "%s/postgresql.conf", pg_data);
		snprintf(backup_file, MAXPGPATH, "%s/backup_label", pg_data);
		snprintf(recovery_file, MAXPGPATH, "%s/recovery.conf", pg_data);
	}

	switch (ctl_command)
	{
		case INIT_COMMAND:
			do_init();
			break;
		case STATUS_COMMAND:
			do_status();
			break;
		case START_COMMAND:
			do_start();
			break;
		case STOP_COMMAND:
			do_stop();
			break;
		case RESTART_COMMAND:
			do_restart();
			break;
		case RELOAD_COMMAND:
			do_reload();
			break;
		case KILL_COMMAND:
			do_kill(killproc);
			break;
#if defined(WIN32) || defined(__CYGWIN__)
		case REGISTER_COMMAND:
			pgwin32_doRegister();
			break;
		case UNREGISTER_COMMAND:
			pgwin32_doUnregister();
			break;
		case RUN_AS_SERVICE_COMMAND:
			pgwin32_doRunAsService();
			break;
#endif
		default:
			break;
	}

	exit(0);
}
Exemple #4
0
int
main(int argc, char **argv)
{
	int			c;
	char		*nodename = NULL; /* GTM Proxy nodename */

	progname = "gtm_ctl";

	/*
	 * save argv[0] so do_start() can look for the gtm if necessary. we
	 * don't look for gtm here because in many cases we won't need it.
	 */
	argv0 = argv[0];

	umask(077);

	/* support --help and --version even if invoked as root */
	if (argc > 1)
	{
		if (strcmp(argv[1], "-h") == 0 || strcmp(argv[1], "--help") == 0 ||
			strcmp(argv[1], "-?") == 0)
		{
			do_help();
			exit(0);
		}
		if (strcmp(argv[1], "--version") == 0 || strcmp(argv[1], "-V") == 0)
		{
			puts("gtm_ctl (Postgres-XC) " PGXC_VERSION);
			exit(0);
		}
	}

	/*
	 * Disallow running as root, to forestall any possible security holes.
	 */
	if (geteuid() == 0)
	{
		write_stderr(_("%s: cannot be run as root\n"
					   "Please log in (using, e.g., \"su\") as the "
					   "(unprivileged) user that will\n"
					   "own the server process.\n"),
					 progname);
		exit(1);
	}

	/*
	 * 'Action' can be before or after args so loop over both. Some
	 * getopt_long() implementations will reorder argv[] to place all flags
	 * first (GNU?), but we don't rely on it. Our /port version doesn't do
	 * that.
	 */
	optind = 1;

	/* process command-line options */
	while (optind < argc)
	{
		while ((c = getopt(argc, argv, "D:i:l:m:o:p:t:wWZ:C:")) != -1)
		{
			switch (c)
			{
				case 'D':
					{
						char	   *env_var = pg_malloc(strlen(optarg) + 9);

						gtmdata_D = xstrdup(optarg);
						canonicalize_path(gtmdata_D);
						snprintf(env_var, strlen(optarg) + 9, "GTMDATA=%s",
								 gtmdata_D);
						putenv(env_var);

						/*
						 * We could pass GTMDATA just in an environment
						 * variable but we do -D too for clearer gtm
						 * 'ps' display
						 */
						gtmdata_opt = (char *) pg_malloc(strlen(gtmdata_D) + 8);
						snprintf(gtmdata_opt, strlen(gtmdata_D) + 8,
								 "-D \"%s\" ",
								 gtmdata_D);
						break;
					}
				case 'i':
					nodename = strdup(optarg);
					break;
				case 'l':
					log_file = xstrdup(optarg);
					break;
				case 'm':
					set_mode(optarg);
					break;
				case 'o':
					gtm_opts = xstrdup(optarg);
					break;
				case 'p':
					gtm_path = xstrdup(optarg);
					canonicalize_path(gtm_path);
					break;
				case 't':
					wait_seconds = atoi(optarg);
					break;
				case 'C':
					control_file = xstrdup(optarg);
					break;
				case 'w':
					do_wait = true;
					wait_set = true;
					break;
				case 'W':
					do_wait = false;
					wait_set = true;
					break;
				case 'Z':
					gtm_app = xstrdup(optarg);
					if (strcmp(gtm_app,"gtm_proxy") != 0
						&& strcmp(gtm_app,"gtm_standby") != 0
						&& strcmp(gtm_app,"gtm") != 0)
					{
						write_stderr(_("%s: %s launch name set not correct\n"), progname, gtm_app);
						do_advice();
						exit(1);
					}
					break;
				default:
					/* getopt_long already issued a suitable error message */
					do_advice();
					exit(1);
			}
		}

		/* Process an action */
		if (optind < argc)
		{
			if (ctl_command != NO_COMMAND)
			{
				write_stderr(_("%s: too many command-line arguments (first is \"%s\")\n"), progname, argv[optind]);
				do_advice();
				exit(1);
			}

			if (strcmp(argv[optind], "start") == 0)
				ctl_command = START_COMMAND;
			else if (strcmp(argv[optind], "stop") == 0)
				ctl_command = STOP_COMMAND;
			else if (strcmp(argv[optind], "promote") == 0)
				ctl_command = PROMOTE_COMMAND;
			else if (strcmp(argv[optind], "restart") == 0)
				ctl_command = RESTART_COMMAND;
			else if (strcmp(argv[optind], "status") == 0)
				ctl_command = STATUS_COMMAND;
			else if (strcmp(argv[optind], "reconnect") == 0)
				ctl_command = RECONNECT_COMMAND;
			else
			{
				write_stderr(_("%s: unrecognized operation mode \"%s\"\n"),
							 progname, argv[optind]);
				do_advice();
				exit(1);
			}
			optind++;
		}
	}

	/*
	 * Take care of the control file (-C Option)
	 */
	if (control_file)
	{
		char ctrl_path[MAXPGPATH+1];
		char C_opt_path[MAXPGPATH+1];
		char bkup_path[MAXPGPATH+1];
		FILE *f1, *f2;
		int c;

		if (!gtmdata_D)
		{
			write_stderr(_("No -D option specified.\n"));
			exit(1);
		}
		if ((strcmp(gtm_app, "gtm") != 0) && (strcmp(gtm_app, "gtm_master") != 0))
		{
			write_stderr(_("-C option is valid only for gtm.\n"));
			exit(1);
		}
		/* If there's already a control file, backup it to *.bak */
		trim_last_slash(gtmdata_D);
		snprintf(ctrl_path, MAXPGPATH, "%s/%s", gtmdata_D, GTM_CONTROL_FILE);
		if ((f1 = fopen(ctrl_path, "r")))
		{

			snprintf(bkup_path, MAXPGPATH, "%s/%s.bak", gtmdata_D, GTM_CONTROL_FILE);
			if (!(f2 = fopen(bkup_path, "w")))
			{
				fclose(f1);
				write_stderr(_("Cannot open backup file, %s/%s.bak, %s\n"),
							 gtmdata_D, GTM_CONTROL_FILE, strerror(errno));
				exit(1);
			}
			while ((c = getc(f1)) != EOF)
				putc(c, f2);
			fclose(f1);
			fclose(f2);
		}
		/* Copy specified control file. */
		snprintf(C_opt_path, MAXPGPATH, "%s/%s", gtmdata_D, control_file);
		if (!(f1 = fopen(ctrl_path, "w")))
		{
			write_stderr(_("Cannot oopen control file, %s, %s\n"), ctrl_path, strerror(errno));
			exit(1);
		}
		if (!(f2 = fopen(C_opt_path, "r")))
		{
			fclose(f1);
			write_stderr(_("Cannot open -C option file, %s, %s\n"), C_opt_path, strerror(errno));
			exit(1);
		}
		while ((c = getc(f2)) != EOF)
			putc(c, f1);
		fclose(f1);
		fclose(f2);
	}

	if (ctl_command == NO_COMMAND)
	{
		write_stderr(_("%s: no operation specified\n"), progname);
		do_advice();
		exit(1);
	}

	gtm_data = getenv("GTMDATA");

	if (gtm_data)
	{
		gtm_data = xstrdup(gtm_data);
		canonicalize_path(gtm_data);
	}

	if (!gtm_data)
	{
		write_stderr("%s: no GTM/GTM Proxy directory specified \n",
					 progname);
		do_advice();
		exit(1);
	}

	/*
	 * pid files of gtm and gtm proxy are named differently
	 * -Z option has also to be set for STOP_COMMAND
	 * or gtm_ctl will not be able to find the correct pid_file
	 */
	if (!gtm_app)
	{
		write_stderr("%s: no launch option not specified\n",
					 progname);
		do_advice();
		exit(1);
	}

	if (strcmp(gtm_app,"gtm_proxy") != 0 &&
		strcmp(gtm_app, "gtm_standby") != 0 &&
		strcmp(gtm_app,"gtm") != 0)
	{
		write_stderr(_("%s: launch option incorrect\n"),
						progname);
		do_advice();
		exit(1);
	}

	/* Check if GTM Proxy ID is set, this is not necessary when stopping */
	if (ctl_command == START_COMMAND ||
		ctl_command == RESTART_COMMAND)
	{
		/* Rebuild option string to include Proxy ID */
		if (strcmp(gtm_app, "gtm_proxy") == 0)
		{
			gtmdata_opt = (char *) pg_realloc(gtmdata_opt, strlen(gtmdata_opt) + 9);
			if (nodename)
				sprintf(gtmdata_opt, "%s -i %s ", gtmdata_opt, nodename);
			else
				sprintf(gtmdata_opt, "%s ", gtmdata_opt);
		}
	}

	if (!wait_set)
	{
		switch (ctl_command)
		{
			case RESTART_COMMAND:
			case START_COMMAND:
			case PROMOTE_COMMAND:
			case STATUS_COMMAND:
				do_wait = false;
				break;
			case STOP_COMMAND:
				do_wait = true;
				break;
			default:
				break;
		}
	}

	/* Build strings for pid file and option file */
	if (strcmp(gtm_app,"gtm_proxy") == 0)
	{
		snprintf(pid_file, MAXPGPATH, "%s/gtm_proxy.pid", gtm_data);
		snprintf(gtmopts_file, MAXPGPATH, "%s/gtm_proxy.opts", gtm_data);
		snprintf(conf_file, MAXPGPATH, "%s/gtm_proxy.conf", gtm_data);
	}
	else if (strcmp(gtm_app,"gtm") == 0)
	{
		snprintf(pid_file, MAXPGPATH, "%s/gtm.pid", gtm_data);
		snprintf(gtmopts_file, MAXPGPATH, "%s/gtm.opts", gtm_data);
		snprintf(conf_file, MAXPGPATH, "%s/gtm.conf", gtm_data);
	}
	else if (strcmp(gtm_app,"gtm_standby") == 0)
	{
		snprintf(pid_file, MAXPGPATH, "%s/gtm.pid", gtm_data);
		snprintf(gtmopts_file, MAXPGPATH, "%s/gtm.opts", gtm_data);
		snprintf(conf_file, MAXPGPATH, "%s/gtm.conf", gtm_data);
	}

	if (ctl_command==STATUS_COMMAND)
		gtm_opts = xstrdup("-c");

	switch (ctl_command)
	{
		case START_COMMAND:
			do_start();
			break;
		case STOP_COMMAND:
			do_stop();
			break;
		case PROMOTE_COMMAND:
			do_promote();
			break;
		case RESTART_COMMAND:
			do_restart();
			break;
		case STATUS_COMMAND:
			do_status();
			break;
		case RECONNECT_COMMAND:
			do_reconnect();
			break;
		default:
			break;
	}

	exit(0);
}