1 /* -*-pgsql-c-*- */
2 /*
3  * $Header$
4  *
5  * pgpool: a language independent connection pool server for PostgreSQL
6  * written by Tatsuo Ishii
7  *
8  * Copyright (c) 2003-2018	PgPool Global Development Group
9  *
10  * Permission to use, copy, modify, and distribute this software and
11  * its documentation for any purpose and without fee is hereby
12  * granted, provided that the above copyright notice appear in all
13  * copies and that both that copyright notice and this permission
14  * notice appear in supporting documentation, and that the name of the
15  * author not be used in advertising or publicity pertaining to
16  * distribution of the software without specific, written prior
17  * permission. The author makes no representations about the
18  * suitability of this software for any purpose.  It is provided "as
19  * is" without express or implied warranty.
20  */
21 #include "pool.h"
22 #include "pool_config.h"
23 #include <fcntl.h>
24 #include <sys/types.h>
25 #include <sys/stat.h>
26 #include <unistd.h>
27 
28 
29 #ifdef HAVE_GETOPT_H
30 #include <getopt.h>
31 #else
32 #include "utils/getopt_long.h"
33 #endif
34 
35 #include <errno.h>
36 #include <string.h>
37 #include <libgen.h>
38 #include "utils/elog.h"
39 #include "utils/palloc.h"
40 #include "utils/memutils.h"
41 #include "utils/pool_path.h"
42 
43 #include "version.h"
44 #include "auth/pool_passwd.h"
45 #include "auth/pool_hba.h"
46 #include "query_cache/pool_memqcache.h"
47 #include "watchdog/wd_utils.h"
48 #include "pool_config_variables.h"
49 
50 
51 static bool get_pool_key_filename(char *poolKeyFile);
52 
53 static void daemonize(void);
54 static char *get_pid_file_path(void);
55 static int	read_pid_file(void);
56 static void write_pid_file(void);
57 static void usage(void);
58 static void show_version(void);
59 static void stop_me(void);
60 static void FileUnlink(int code, Datum path);
61 
62 char	   *pcp_conf_file = NULL;	/* absolute path of the pcp.conf */
63 char	   *conf_file = NULL;	/* absolute path of the pgpool.conf */
64 char	   *hba_file = NULL;	/* absolute path of the hba.conf */
65 char	   *base_dir = NULL;	/* The working dir from where pgpool was
66 								 * invoked from */
67 
68 static int	not_detach = 0;		/* non 0 if non detach option (-n) is given */
69 int			stop_sig = SIGTERM; /* stopping signal default value */
70 int			myargc;
71 char	  **myargv;
72 int			assert_enabled = 0;
73 char	   *pool_key = NULL;
74 int
main(int argc,char ** argv)75 main(int argc, char **argv)
76 {
77 	int			opt;
78 	int			debug_level = 0;
79 	int			optindex;
80 	bool		discard_status = false;
81 	bool		clear_memcache_oidmaps = false;
82 
83 	char		pcp_conf_file_path[POOLMAXPATHLEN + 1];
84 	char		conf_file_path[POOLMAXPATHLEN + 1];
85 	char		hba_file_path[POOLMAXPATHLEN + 1];
86 	char		pool_passwd_key_file_path[POOLMAXPATHLEN + 1 + sizeof(POOLKEYFILE) + 1];
87 
88 	static struct option long_options[] = {
89 		{"hba-file", required_argument, NULL, 'a'},
90 		{"debug", no_argument, NULL, 'd'},
91 		{"config-file", required_argument, NULL, 'f'},
92 		{"key-file", required_argument, NULL, 'k'},
93 		{"pcp-file", required_argument, NULL, 'F'},
94 		{"help", no_argument, NULL, 'h'},
95 		{"mode", required_argument, NULL, 'm'},
96 		{"dont-detach", no_argument, NULL, 'n'},
97 		{"discard-status", no_argument, NULL, 'D'},
98 		{"clear-oidmaps", no_argument, NULL, 'C'},
99 		{"debug-assertions", no_argument, NULL, 'x'},
100 		{"version", no_argument, NULL, 'v'},
101 		{NULL, 0, NULL, 0}
102 	};
103 
104 	myargc = argc;
105 	myargv = argv;
106 
107 	snprintf(conf_file_path, sizeof(conf_file_path), "%s/%s", DEFAULT_CONFIGDIR, POOL_CONF_FILE_NAME);
108 	snprintf(pcp_conf_file_path, sizeof(pcp_conf_file_path), "%s/%s", DEFAULT_CONFIGDIR, PCP_PASSWD_FILE_NAME);
109 	snprintf(hba_file_path, sizeof(hba_file_path), "%s/%s", DEFAULT_CONFIGDIR, HBA_CONF_FILE_NAME);
110 	pool_passwd_key_file_path[0] = 0;
111 
112 	while ((opt = getopt_long(argc, argv, "a:df:k:F:hm:nDCxv", long_options, &optindex)) != -1)
113 	{
114 		switch (opt)
115 		{
116 			case 'a':			/* specify hba configuration file */
117 				if (!optarg)
118 				{
119 					usage();
120 					exit(1);
121 				}
122 				strlcpy(hba_file_path, optarg, sizeof(hba_file_path));
123 				break;
124 
125 			case 'x':			/* enable cassert */
126 				assert_enabled = 1;
127 				break;
128 
129 			case 'd':			/* debug option */
130 				debug_level = 1;
131 				break;
132 
133 			case 'f':			/* specify configuration file */
134 				if (!optarg)
135 				{
136 					usage();
137 					exit(1);
138 				}
139 				strlcpy(conf_file_path, optarg, sizeof(conf_file_path));
140 				break;
141 
142 			case 'F':			/* specify PCP password file */
143 				if (!optarg)
144 				{
145 					usage();
146 					exit(1);
147 				}
148 				strlcpy(pcp_conf_file_path, optarg, sizeof(pcp_conf_file_path));
149 				break;
150 
151 			case 'k':			/* specify key file for decrypt pool_password
152 								 * entries */
153 				if (!optarg)
154 				{
155 					usage();
156 					exit(1);
157 				}
158 				strlcpy(pool_passwd_key_file_path, optarg, sizeof(pool_passwd_key_file_path));
159 				break;
160 
161 			case 'h':
162 				usage();
163 				exit(0);
164 				break;
165 
166 			case 'm':			/* stop mode */
167 				if (!optarg)
168 				{
169 					usage();
170 					exit(1);
171 				}
172 				if (*optarg == 's' || !strcmp("smart", optarg))
173 					stop_sig = SIGTERM; /* smart shutdown */
174 				else if (*optarg == 'f' || !strcmp("fast", optarg))
175 					stop_sig = SIGINT;	/* fast shutdown */
176 				else if (*optarg == 'i' || !strcmp("immediate", optarg))
177 					stop_sig = SIGQUIT; /* immediate shutdown */
178 				else
179 				{
180 					usage();
181 					exit(1);
182 				}
183 				break;
184 
185 			case 'n':			/* no detaching control ttys */
186 				not_detach = 1;
187 				break;
188 
189 			case 'D':			/* discard pgpool_status */
190 				discard_status = true;
191 				break;
192 
193 			case 'C':			/* discard caches in memcached */
194 				clear_memcache_oidmaps = true;
195 				break;
196 
197 			case 'v':
198 				show_version();
199 				exit(0);
200 
201 			default:
202 				usage();
203 				exit(1);
204 		}
205 	}
206 
207 	myargv = save_ps_display_args(myargc, myargv);
208 	/* create MemoryContexts */
209 	MemoryContextInit();
210 
211 	/* load the CWD before it is changed */
212 	base_dir = get_current_working_dir();
213 	/* convert all the paths to absolute paths */
214 	conf_file = make_absolute_path(conf_file_path, base_dir);
215 	pcp_conf_file = make_absolute_path(pcp_conf_file_path, base_dir);
216 	hba_file = make_absolute_path(hba_file_path, base_dir);
217 
218 	mypid = getpid();
219 
220 	pool_init_config();
221 
222 	pool_get_config(conf_file, CFGCXT_INIT);
223 
224 	/*
225 	 * Override debug level if command line -d arg is given adjust the
226 	 * log_min_message config variable
227 	 */
228 	if (debug_level > 0 && pool_config->log_min_messages > DEBUG1)
229 		set_one_config_option("log_min_messages", "DEBUG1", CFGCXT_INIT, PGC_S_ARGV, INFO);
230 
231 	/*
232 	 * If a non-switch argument remains, then it should be either "reload" or
233 	 * "stop".
234 	 */
235 	if (optind == (argc - 1))
236 	{
237 		if (!strcmp(argv[optind], "reload"))
238 		{
239 			pid_t		pid;
240 
241 			pid = read_pid_file();
242 			if (pid < 0)
243 			{
244 				ereport(FATAL,
245 						(return_code(1),
246 						 errmsg("could not read pid file")));
247 			}
248 
249 			if (kill(pid, SIGHUP) == -1)
250 			{
251 				ereport(FATAL,
252 						(return_code(1),
253 						 errmsg("could not reload configuration file pid: %d", pid),
254 						 errdetail("%m")));
255 			}
256 			exit(0);
257 		}
258 		if (!strcmp(argv[optind], "stop"))
259 		{
260 			stop_me();
261 			exit(0);
262 		}
263 		else
264 		{
265 			usage();
266 			exit(1);
267 		}
268 	}
269 
270 	/*
271 	 * else if no non-switch argument remains, then it should be a start
272 	 * request
273 	 */
274 	else if (optind == argc)
275 	{
276 		int			pid = read_pid_file();
277 
278 		if (pid > 0)
279 		{
280 			if (kill(pid, 0) == 0)
281 			{
282 				fprintf(stderr, "ERROR: pid file found. is another pgpool(%d) is running?\n", pid);
283 				exit(EXIT_FAILURE);
284 			}
285 			else
286 				fprintf(stderr, "NOTICE: pid file found but it seems bogus. Trying to start pgpool anyway...\n");
287 		}
288 	}
289 
290 	/*
291 	 * otherwise an error...
292 	 */
293 	else
294 	{
295 		usage();
296 		exit(1);
297 	}
298 
299 	if (pool_config->enable_pool_hba)
300 		load_hba(hba_file);
301 
302 #ifdef USE_SSL
303 
304 	/*
305 	 * If ssl is enabled, initialize the SSL context
306 	 */
307 	if (pool_config->ssl)
308 		SSL_ServerSide_init();
309 #endif							/* USE_SSL */
310 
311 	/* check effective user id for watchdog */
312 	/* watchdog must be started under the privileged user */
313 	wd_check_network_command_configurations();
314 
315 	/* set signal masks */
316 	poolinitmask();
317 
318 	/* read the pool password key */
319 	if (strlen(pool_passwd_key_file_path) == 0)
320 	{
321 		get_pool_key_filename(pool_passwd_key_file_path);
322 	}
323 	pool_key = read_pool_key(pool_passwd_key_file_path);
324 
325 	if (not_detach)
326 		write_pid_file();
327 	else
328 		daemonize();
329 
330 	/*
331 	 * Locate pool_passwd The default file name "pool_passwd" can be changed
332 	 * by setting pgpool.conf's "pool_passwd" directive.
333 	 */
334 	if (strcmp("", pool_config->pool_passwd))
335 	{
336 		char		pool_passwd[POOLMAXPATHLEN + 1];
337 		char		dirnamebuf[POOLMAXPATHLEN + 1];
338 		char	   *dirp;
339 
340 		if (pool_config->pool_passwd[0] != '/')
341 		{
342 			strlcpy(dirnamebuf, conf_file, sizeof(dirnamebuf));
343 			dirp = dirname(dirnamebuf);
344 			snprintf(pool_passwd, sizeof(pool_passwd), "%s/%s",
345 					 dirp, pool_config->pool_passwd);
346 		}
347 		else
348 			strlcpy(pool_passwd, pool_config->pool_passwd,
349 				 sizeof(pool_passwd));
350 
351 		pool_init_pool_passwd(pool_passwd, POOL_PASSWD_R);
352 	}
353 
354 	pool_semaphore_create(MAX_NUM_SEMAPHORES);
355 
356 	PgpoolMain(discard_status, clear_memcache_oidmaps); /* this is an infinate
357 														 * loop */
358 
359 	exit(0);
360 
361 }
362 
363 static void
show_version(void)364 show_version(void)
365 {
366 	fprintf(stderr, "%s version %s (%s)\n", PACKAGE, VERSION, PGPOOLVERSION);
367 }
368 
369 static void
usage(void)370 usage(void)
371 {
372 	char		homedir[POOLMAXPATHLEN];
373 
374 	if (!get_home_directory(homedir, sizeof(homedir)))
375 		strncpy(homedir, "USER-HOME-DIR", POOLMAXPATHLEN);
376 
377 	fprintf(stderr, "%s version %s (%s),\n", PACKAGE, VERSION, PGPOOLVERSION);
378 	fprintf(stderr, "  A generic connection pool/replication/load balance server for PostgreSQL\n\n");
379 	fprintf(stderr, "Usage:\n");
380 	fprintf(stderr, "  pgpool [ -c] [ -f CONFIG_FILE ] [ -F PCP_CONFIG_FILE ] [ -a HBA_CONFIG_FILE ]\n");
381 	fprintf(stderr, "         [ -n ] [ -D ] [ -d ]\n");
382 	fprintf(stderr, "  pgpool [ -f CONFIG_FILE ] [ -F PCP_CONFIG_FILE ] [ -a HBA_CONFIG_FILE ]\n");
383 	fprintf(stderr, "         [ -m SHUTDOWN-MODE ] stop\n");
384 	fprintf(stderr, "  pgpool [ -f CONFIG_FILE ] [ -F PCP_CONFIG_FILE ] [ -a HBA_CONFIG_FILE ] reload\n\n");
385 	fprintf(stderr, "Common options:\n");
386 	fprintf(stderr, "  -a, --hba-file=HBA_CONFIG_FILE\n");
387 	fprintf(stderr, "                      Set the path to the pool_hba.conf configuration file\n");
388 	fprintf(stderr, "                      (default: %s/%s)\n", DEFAULT_CONFIGDIR, HBA_CONF_FILE_NAME);
389 	fprintf(stderr, "  -f, --config-file=CONFIG_FILE\n");
390 	fprintf(stderr, "                      Set the path to the pgpool.conf configuration file\n");
391 	fprintf(stderr, "                      (default: %s/%s)\n", DEFAULT_CONFIGDIR, POOL_CONF_FILE_NAME);
392 	fprintf(stderr, "  -k, --key-file=KEY_FILE\n");
393 	fprintf(stderr, "                      Set the path to the pgpool key file\n");
394 	fprintf(stderr, "                      (default: %s/%s)\n", homedir, POOLKEYFILE);
395 	fprintf(stderr, "                      can be over ridden by %s environment variable\n", POOLKEYFILEENV);
396 	fprintf(stderr, "  -F, --pcp-file=PCP_CONFIG_FILE\n");
397 	fprintf(stderr, "                      Set the path to the pcp.conf configuration file\n");
398 	fprintf(stderr, "                      (default: %s/%s)\n", DEFAULT_CONFIGDIR, PCP_PASSWD_FILE_NAME);
399 	fprintf(stderr, "  -h, --help          Print this help\n\n");
400 	fprintf(stderr, "Start options:\n");
401 	fprintf(stderr, "  -C, --clear-oidmaps Clear query cache oidmaps when memqcache_method is memcached\n");
402 	fprintf(stderr, "                      (If shmem, discards whenever pgpool starts.)\n");
403 	fprintf(stderr, "  -n, --dont-detach   Don't run in daemon mode, does not detach control tty\n");
404 	fprintf(stderr, "  -x, --debug-assertions   Turns on various assertion checks, This is a debugging aid\n");
405 	fprintf(stderr, "  -D, --discard-status Discard pgpool_status file and do not restore previous status\n");
406 	fprintf(stderr, "  -d, --debug         Debug mode\n\n");
407 	fprintf(stderr, "Stop options:\n");
408 	fprintf(stderr, "  -m, --mode=SHUTDOWN-MODE\n");
409 	fprintf(stderr, "                      Can be \"smart\", \"fast\", or \"immediate\"\n\n");
410 	fprintf(stderr, "Shutdown modes are:\n");
411 	fprintf(stderr, "  smart       quit after all clients have disconnected\n");
412 	fprintf(stderr, "  fast        quit directly, with proper shutdown\n");
413 	fprintf(stderr, "  immediate   the same mode as fast\n");
414 }
415 
416 static bool
get_pool_key_filename(char * poolKeyFile)417 get_pool_key_filename(char *poolKeyFile)
418 {
419 	char	   *passfile_env;
420 
421 	if ((passfile_env = getenv(POOLKEYFILEENV)) != NULL)
422 	{
423 		/* use the literal path from the environment, if set */
424 		strlcpy(poolKeyFile, passfile_env, POOLMAXPATHLEN);
425 	}
426 	else
427 	{
428 		char		homedir[POOLMAXPATHLEN];
429 
430 		if (!get_home_directory(homedir, sizeof(homedir)))
431 			return false;
432 		snprintf(poolKeyFile, POOLMAXPATHLEN + sizeof(POOLKEYFILE) + 1, "%s/%s", homedir, POOLKEYFILE);
433 	}
434 	return true;
435 }
436 
437 
438 char *
get_pool_key(void)439 get_pool_key(void)
440 {
441 	return pool_key;
442 }
443 
444 /*
445 * detach control ttys
446 */
447 static void
daemonize(void)448 daemonize(void)
449 {
450 	int			i;
451 	pid_t		pid;
452 	int			fdlimit;
453 
454 	pid = fork();
455 	if (pid == (pid_t) -1)
456 	{
457 		ereport(FATAL,
458 				(errmsg("could not daemonize the pgpool-II"),
459 				 errdetail("fork() system call failed with reason: \"%m\"")));
460 	}
461 	else if (pid > 0)
462 	{							/* parent */
463 		exit(0);
464 	}
465 
466 #ifdef HAVE_SETSID
467 	if (setsid() < 0)
468 	{
469 		ereport(FATAL,
470 				(errmsg("could not daemonize the pgpool-II"),
471 				 errdetail("setsid() system call failed with reason: \"%m\"")));
472 	}
473 #endif
474 
475 	mypid = getpid();
476 	write_pid_file();
477 	if (chdir("/"))
478 		ereport(WARNING,
479 				(errmsg("change directory failed"),
480 				 errdetail("chdir() system call failed with reason: \"%m\"")));
481 
482 	/* redirect stdin, stdout and stderr to /dev/null */
483 	i = open("/dev/null", O_RDWR);
484 	if (i < 0)
485 	{
486 		ereport(WARNING,
487 				(errmsg("failed to open \"/dev/null\""),
488 				 errdetail("%m")));
489 	}
490 	else
491 	{
492 		dup2(i, 0);
493 		dup2(i, 1);
494 		dup2(i, 2);
495 		close(i);
496 	}
497 	/* close syslog connection for daemonizing */
498 	if (pool_config->log_destination & LOG_DESTINATION_SYSLOG)
499 	{
500 		closelog();
501 	}
502 
503 	/* close other file descriptors */
504 	fdlimit = sysconf(_SC_OPEN_MAX);
505 	for (i = 3; i < fdlimit; i++)
506 		close(i);
507 }
508 
509 /*
510 * stop myself
511 */
512 static void
stop_me(void)513 stop_me(void)
514 {
515 	pid_t		pid;
516 	char	   *pid_file;
517 
518 	pid = read_pid_file();
519 	if (pid < 0)
520 	{
521 		ereport(FATAL,
522 				(errmsg("could not read pid file")));
523 	}
524 
525 	if (kill(pid, stop_sig) == -1)
526 	{
527 		ereport(FATAL,
528 				(errmsg("could not stop process with pid: %d", pid),
529 				 errdetail("%m")));
530 	}
531 	ereport(LOG,
532 			(errmsg("stop request sent to pgpool. waiting for termination...")));
533 
534 	while (kill(pid, 0) == 0)
535 	{
536 		fprintf(stderr, ".");
537 		sleep(1);
538 	}
539 	fprintf(stderr, "done.\n");
540 	pid_file = get_pid_file_path();
541 	unlink(pid_file);
542 	pfree(pid_file);
543 }
544 
545 /*
546  * The function returns the palloc'd copy of pid_file_path,
547  * caller must free it after use
548  */
549 static char *
get_pid_file_path(void)550 get_pid_file_path(void)
551 {
552 	char	   *new = NULL;
553 
554 	if (!is_absolute_path(pool_config->pid_file_name))
555 	{
556 		/*
557 		 * some implementations of dirname() may modify the string argument
558 		 * passed to it, so do not use the original conf_file as an argument
559 		 */
560 		char	   *conf_file_copy = pstrdup(conf_file);
561 		char	   *conf_dir = dirname(conf_file_copy);
562 		size_t		path_size;
563 
564 		if (conf_dir == NULL)
565 		{
566 			ereport(LOG,
567 					(errmsg("failed to get the dirname of pid file:\"%s\"",
568 							pool_config->pid_file_name),
569 					 errdetail("%m")));
570 			return NULL;
571 		}
572 		path_size = strlen(conf_dir) + strlen(pool_config->pid_file_name) + 1 + 1;
573 		new = palloc(path_size);
574 		snprintf(new, path_size, "%s/%s", conf_dir, pool_config->pid_file_name);
575 
576 		ereport(DEBUG1,
577 				(errmsg("pid file location is \"%s\"",
578 						new)));
579 
580 		pfree(conf_file_copy);
581 	}
582 	else
583 	{
584 		new = pstrdup(pool_config->pid_file_name);
585 	}
586 
587 	return new;
588 }
589 
590 /*
591 * read the pid file
592 */
593 static int
read_pid_file(void)594 read_pid_file(void)
595 {
596 	int			fd;
597 	int			readlen;
598 	char		pidbuf[128];
599 	char	   *pid_file = get_pid_file_path();
600 
601 	if (pid_file == NULL)
602 	{
603 		ereport(FATAL,
604 				(errmsg("failed to read pid file"),
605 				 errdetail("failed to get pid file path from \"%s\"",
606 						   pool_config->pid_file_name)));
607 	}
608 	fd = open(pid_file, O_RDONLY);
609 	if (fd == -1)
610 	{
611 		pfree(pid_file);
612 		return -1;
613 	}
614 	if ((readlen = read(fd, pidbuf, sizeof(pidbuf))) == -1)
615 	{
616 		close(fd);
617 		pfree(pid_file);
618 		ereport(FATAL,
619 				(errmsg("could not read pid file \"%s\"",
620 						pool_config->pid_file_name),
621 				 errdetail("%m")));
622 	}
623 	else if (readlen == 0)
624 	{
625 		close(fd);
626 		pfree(pid_file);
627 		ereport(FATAL,
628 				(errmsg("EOF detected while reading pid file \"%s\"",
629 						pool_config->pid_file_name),
630 				 errdetail("%m")));
631 	}
632 	pfree(pid_file);
633 	close(fd);
634 	return (atoi(pidbuf));
635 }
636 
637 /*
638 * write the pid file
639 */
640 static void
write_pid_file(void)641 write_pid_file(void)
642 {
643 	int			fd;
644 	char		pidbuf[128];
645 	char	   *pid_file = get_pid_file_path();
646 
647 	if (pid_file == NULL)
648 	{
649 		ereport(FATAL,
650 				(errmsg("failed to write pid file"),
651 				 errdetail("failed to get pid file path from \"%s\"",
652 						   pool_config->pid_file_name)));
653 	}
654 
655 	fd = open(pid_file, O_CREAT | O_TRUNC | O_WRONLY, S_IRUSR | S_IWUSR);
656 	if (fd == -1)
657 	{
658 		ereport(FATAL,
659 				(errmsg("could not open pid file \"%s\"",
660 						pool_config->pid_file_name),
661 				 errdetail("%m")));
662 	}
663 	snprintf(pidbuf, sizeof(pidbuf), "%d", (int) getpid());
664 	if (write(fd, pidbuf, strlen(pidbuf) + 1) == -1)
665 	{
666 		close(fd);
667 		pfree(pid_file);
668 		ereport(FATAL,
669 				(errmsg("could not write pid file \"%s\"",
670 						pool_config->pid_file_name),
671 				 errdetail("%m")));
672 	}
673 	if (fsync(fd) == -1)
674 	{
675 		close(fd);
676 		pfree(pid_file);
677 		ereport(FATAL,
678 				(errmsg("could not fsync pid file \"%s\"",
679 						pool_config->pid_file_name),
680 				 errdetail("%m")));
681 	}
682 	if (close(fd) == -1)
683 	{
684 		pfree(pid_file);
685 		ereport(FATAL,
686 				(errmsg("could not close pid file \"%s\"",
687 						pool_config->pid_file_name),
688 				 errdetail("%m")));
689 	}
690 	/* register the call back to delete the pid file at system exit */
691 	on_proc_exit(FileUnlink, (Datum) pid_file);
692 }
693 
694 /*
695  * get_config_file_name: return full path of pgpool.conf.
696  */
697 char *
get_config_file_name(void)698 get_config_file_name(void)
699 {
700 	return conf_file;
701 }
702 
703 /*
704  * get_hba_file_name: return full path of pool_hba.conf.
705  */
706 char *
get_hba_file_name(void)707 get_hba_file_name(void)
708 {
709 	return hba_file;
710 }
711 
712 /*
713  * Call back function to unlink the file
714  */
715 static void
FileUnlink(int code,Datum path)716 FileUnlink(int code, Datum path)
717 {
718 	char	   *filePath = (char *) path;
719 
720 	if (unlink(filePath) == 0)
721 		return;
722 
723 	/*
724 	 * We are already exiting the system just produce a log entry to report an
725 	 * error
726 	 */
727 	ereport(LOG,
728 			(errmsg("unlink failed for file at path \"%s\"", filePath),
729 			 errdetail("%m")));
730 }
731