From 8dea497fc398738c47cd0088adfbf628e4256159 Mon Sep 17 00:00:00 2001 From: User yamaguti Date: Thu, 1 Feb 2007 15:31:59 +0000 Subject: [PATCH] New files and modifications to support client authentication (pool_hba). --- Makefile.am | 6 +- Makefile.in | 17 +- README | 114 ++- README.euc_jp | 114 ++- ac_func_accept_argtypes.m4 | 85 ++ aclocal.m4 | 1 + child.c | 64 +- config.h.in | 51 ++ configure | 1713 ++++++++++++++++++++++++++++++------ configure.in | 31 +- main.c | 24 +- pgpool.conf.sample | 12 + pool.h | 41 +- pool_config.c | 1387 ++++++++++++++++------------- pool_config.l | 24 + pool_hba.c | 1420 ++++++++++++++++++++++++++++++ pool_hba.conf.sample | 69 ++ pool_ip.c | 498 +++++++++++ pool_ip.h | 63 ++ pool_list.c | 171 ++++ pool_list.h | 95 ++ pool_path.c | 193 ++++ pool_path.h | 81 ++ pool_process_query.c | 15 + pool_type.h | 139 +++ 25 files changed, 5493 insertions(+), 935 deletions(-) create mode 100644 ac_func_accept_argtypes.m4 create mode 100644 pool_hba.c create mode 100644 pool_hba.conf.sample create mode 100644 pool_ip.c create mode 100644 pool_ip.h create mode 100644 pool_list.c create mode 100644 pool_list.h create mode 100644 pool_path.c create mode 100644 pool_path.h create mode 100644 pool_type.h diff --git a/Makefile.am b/Makefile.am index 71eb178..2e97714 100644 --- a/Makefile.am +++ b/Makefile.am @@ -4,12 +4,14 @@ pgpool_SOURCES = pool.h version.h pgpool.conf.sample \ README.euc_jp pgpool.spec \ main.c child.c pool_auth.c pool_config.l pool_error.c \ pool_process_query.c pool_stream.c pool_connection_pool.c pool_params.c \ - pool_signal.h pool_signal.c ps_status.c strlcpy.c + pool_signal.h pool_signal.c ps_status.c strlcpy.c \ + pool_hba.c pool_list.h pool_list.c pool_path.h pool_path.c \ + pool_type.h pool_ip.h pool_ip.c pool_hba.conf.sample DEFS = @DEFS@ \ -DDEFAULT_CONFIGDIR=\"$(sysconfdir)\" -sysconf_DATA = pgpool.conf.sample +sysconf_DATA = pgpool.conf.sample pool_hba.conf.sample AM_CPPFLAGS = -Wall -Wmissing-prototypes -Wmissing-declarations -D_GNU_SOURCE diff --git a/Makefile.in b/Makefile.in index 6f77c65..1d34735 100644 --- a/Makefile.in +++ b/Makefile.in @@ -42,7 +42,8 @@ DIST_COMMON = README $(am__configure_deps) $(srcdir)/Makefile.am \ $(top_srcdir)/configure AUTHORS COPYING ChangeLog INSTALL NEWS \ TODO depcomp install-sh missing mkinstalldirs pool_config.c ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 -am__aclocal_m4_deps = $(top_srcdir)/configure.in +am__aclocal_m4_deps = $(top_srcdir)/ac_func_accept_argtypes.m4 \ + $(top_srcdir)/configure.in am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \ @@ -58,7 +59,9 @@ am_pgpool_OBJECTS = main.$(OBJEXT) child.$(OBJEXT) pool_auth.$(OBJEXT) \ pool_config.$(OBJEXT) pool_error.$(OBJEXT) \ pool_process_query.$(OBJEXT) pool_stream.$(OBJEXT) \ pool_connection_pool.$(OBJEXT) pool_params.$(OBJEXT) \ - pool_signal.$(OBJEXT) ps_status.$(OBJEXT) strlcpy.$(OBJEXT) + pool_signal.$(OBJEXT) ps_status.$(OBJEXT) strlcpy.$(OBJEXT) \ + pool_hba.$(OBJEXT) pool_list.$(OBJEXT) pool_path.$(OBJEXT) \ + pool_ip.$(OBJEXT) pgpool_OBJECTS = $(am_pgpool_OBJECTS) pgpool_LDADD = $(LDADD) DEFAULT_INCLUDES = -I. -I$(srcdir) -I. @@ -176,9 +179,11 @@ pgpool_SOURCES = pool.h version.h pgpool.conf.sample \ README.euc_jp pgpool.spec \ main.c child.c pool_auth.c pool_config.l pool_error.c \ pool_process_query.c pool_stream.c pool_connection_pool.c pool_params.c \ - pool_signal.h pool_signal.c ps_status.c strlcpy.c + pool_signal.h pool_signal.c ps_status.c strlcpy.c \ + pool_hba.c pool_list.h pool_list.c pool_path.h pool_path.c \ + pool_type.h pool_ip.h pool_ip.c pool_hba.conf.sample -sysconf_DATA = pgpool.conf.sample +sysconf_DATA = pgpool.conf.sample pool_hba.conf.sample AM_CPPFLAGS = -Wall -Wmissing-prototypes -Wmissing-declarations -D_GNU_SOURCE man_MANS = pgpool.8 CLEANFILES = pgpool.8 @@ -277,7 +282,11 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pool_config.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pool_connection_pool.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pool_error.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pool_hba.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pool_ip.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pool_list.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pool_params.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pool_path.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pool_process_query.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pool_signal.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pool_stream.Po@am__quote@ diff --git a/README b/README index f04d32f..353553d 100644 --- a/README +++ b/README @@ -17,7 +17,7 @@ pgpool version 3.1 README secondary server. Moreover, pgpool supports scheduled switch over. See - "9. Switchover" for more details. + "10. Switchover" for more details. 1.1 About replication facility of pgpool @@ -222,8 +222,9 @@ pgpool version 3.1 README Default installation directories are: - /usr/local/bin/pgpool pgpool executable - /usr/local/etc/pgpool.conf.sample example configuration file + /usr/local/bin/pgpool pgpool executable + /usr/local/etc/pgpool.conf.sample example configuration file + /usr/local/etc/pool_hba.conf.sample example HBA configuration file You could change the installation directory by giving --prefix option to configure: @@ -234,7 +235,7 @@ pgpool version 3.1 README pgpool.conf is the configuration file for pgpool. - Copy pgpool.conf.sample as pgpool.conf and change it if neccessary. + Copy pgpool.conf.sample as pgpool.conf and change it if necessary. Here is a explanation of pgpool.conf's grammar. @@ -479,7 +480,81 @@ pgpool version 3.1 README to PostgreSQL, this allows for observing queries without engaging in full debugging. -7. Starting pgpool + log_connections + + If true, all incoming connections will be printed to the log. + + enable_pool_hba + + If true, use pool_hba.conf for client authentication. In pgpool 3.2, + the default value is false. This parameter is planned to be deleted + in the next version of pgpool, and pool_hba.conf will always be used. + See "7. Setting up pool_hba.conf for client authentication". + +7. Setting up pool_hba.conf for client authentication (HBA) + + Just like pg_hba.conf with PostgreSQL, pgpool supports a similar + client authentication function using a configuration file called + "pool_hba.conf". + + When you install pgpool, pool_hba.conf.sample will be installed in + "/usr/local/etc", which is the default directory for configuration + files. + + Copy pool_hba.conf.sample as pool_hba.conf and edit it if necessary. + By default, pool_hba authentication is disabled for backward + compatibility. To enable it, set enable_pool_hba to true in + pgpool.conf. See "6. Setting up pgpool.conf" for more detail. + + The format of pool_hba.conf file follows very closely to pg_hba.conf. + + local DATABASE USER METHOD [OPTION] + host DATABASE USER CIDR-ADDRESS METHOD [OPTION] + + See "pool_hba.conf.sample" for details of each field. + + Here are the limitations of pool_hba. + + * "hostssl" connection type is not supported + + "hostssl" is invalid since pgpool currently does not support SSL + connections. + + * "samegroup" for DATABASE field is not supported + + Since pgpool does not know anything about users in the backend server, + database name is simply checked against the entries in the DATABASE + field of pool_hba.conf. + + * group names following "+" for USER field is not supported + + This is the same reason as in the "samegroup" described above. A + user name is simply checked against the entries in the USER field + of pool_hba.conf. + + * IPv6 for IP address/mask is not supported + + pgpool currently does not support IPv6. + + * Only "trust", "reject" and "pam" for METHOD field are supported + + Again, this is the same reason as in the "samegroup" described above. + pgpool does not hold user/password information. + + Note that everything described in this section is about a client authen- + tication between a client and pgpool; a client still have to go through + an authentication process with PostgreSQL. As far as pool_hba is concerned, + it does not matter if a user name and/or database name given by a client + (i.e. psql -U testuser testdb) really exist in the backend. pool_hba only + cares if a match in the pool_hba.conf is found or not. + + PAM authenticaion is supported using user information on the host where + pgpool is executed. To enable PAM support in pgpool, specify "--with-pam" + option to configure: + + configure --with-pam + +8. Starting pgpool The simplist way to start pgpool is: @@ -493,6 +568,10 @@ pgpool version 3.1 README the path to the configuration file. + -a path + + the path to the pool_hba configuration file. + -n do not start as daemon. Error messages go to stdout or stderr. Thus @@ -507,7 +586,7 @@ pgpool version 3.1 README print the help message and quit -8. Stopping pgpool +9. Stopping pgpool You can stop pgpool by using "stop" option: @@ -524,7 +603,7 @@ pgpool version 3.1 README $ pgpool -m i[mmediate] stop -9. switchover +10. switchover For maintenance purpose, scheduled switching or degeneration is supported. @@ -540,7 +619,7 @@ pgpool version 3.1 README If there's only one PostgreSQL server, pgpool switch will just restart pgpool child processes. -10. how to get logging +11. how to get logging You could save messages from pgpool to a file by starting it with -n option: @@ -551,14 +630,14 @@ pgpool version 3.1 README pgpool -n 2>&1 |logger -t pgpool -p local0.info& -11. getting internal status of pgpool +12. getting internal status of pgpool You could use psql or whatever to obtain the internal status of pgpool by issuing a special SQL command: psql -p 9999 -c 'show pool_status' template1 - item | value | description + item | value | description ------------------------------+------------------------------------------------------+------------------------------------------------------------------------ listen_addresses | * | host name(s) or IP address(es) to listen to port | 9998 | pgpool accepting port number @@ -570,6 +649,7 @@ pgpool version 3.1 README num_init_children | 32 | # of children initially pre-forked child_life_time | 0 | if idle for this seconds, child exits connection_life_time | 0 | if idle for this seconds, connection closes + child_max_connections | 0 | if max_connections received, chile exits max_pool | 2 | max # of connection pool per child logdir | /tmp | logging directory backend_socket_dir | /tmp | Unix domain socket directory for the PostgreSQL server @@ -588,13 +668,17 @@ pgpool version 3.1 README health_check_period | 0 | health check period health_check_user | t-ishii | health check user insert_lock | 1 | insert lock + ignore_leading_white_space | 0 | ignore leading white spaces current_backend_host_name | | current master host name current_backend_port | 5432 | current master port # replication_enabled | 1 | non 0 if actually operating in replication mode master_slave_enabled | 0 | non 0 if actually operating in master/slave num_reset_queries | 3 | number of queries in reset_query_list + log_statement | 0 | if true, print all statements to the log + log_connections | 1 | if true, print incoming connections to the log + enable_pool_hba | 1 | if true, use pool_hba.conf for client authentication server_status | master( on 5432) up secondary( on 5433) up | server status -(34 rows) +(39 rows) By using contrib/dblink, you can see part of the result of show_pool_status someting like: @@ -606,13 +690,13 @@ test=# SELECT * FROM dblink('port=9999 dbname=test', 'show pool_status') port | 9999 (1 row) -12. Playing with regression test +13. Playing with regression test $ cd /usr/local/src/postgresql-7.4.5/src/test/regress $ make all $ ./pg_regress --schedule=parallel_schedule --port=9999 -13. Playing with benchmarking +14. Playing with benchmarking Here is a brief explanation how to play with benchmarking using pgbench/PHP/ab. @@ -641,7 +725,7 @@ test=# SELECT * FROM dblink('port=9999 dbname=test', 'show pool_status') $ /usr/local/apache/bin/ab -c 100 -n 1000 "http://localhost/bench.php" -14. master/slave mode +15. master/slave mode master/slave mode is designed to cope with master/slave replication softwares, such as Slony-I. To enable this mode, you need to set @@ -658,7 +742,7 @@ test=# SELECT * FROM dblink('port=9999 dbname=test', 'show pool_status') 2) in all other case, quries are sent to only master -15. Multiple simultaneous instances of pgpool +16. Multiple simultaneous instances of pgpool In order to run multiple instances of pgpool on the same server simultaneously (in order to have two separate, non-conflicting diff --git a/README.euc_jp b/README.euc_jp index 516284e..b163aea 100644 --- a/README.euc_jp +++ b/README.euc_jp @@ -21,7 +21,7 @@ pgpool version 3.1(kalekale) README ¤Ê¤ª¡¤¥Õ¥§¥¤¥ë¥ª¡¼¥Ð¤ä½ÌÂ౿ž¤Ï²¿¤«¾ã³²¤¬µ¯¤­¤¿¤³¤È¤ò¥È¥ê¥¬¤Ë¤·¤Æ µ¯Æ°¤µ¤ì¤Þ¤¹¤¬¡¤¥á¥¤¥ó¥Æ¥Ê¥ó¥¹¤Ê¤É¤Î¤¿¤á¤Ë°Õ¿ÞŪ¤Ë¥Õ¥§¥¤¥ë¥ª¡¼¥Ð¤ä - ½ÌÂ౿ž¥â¡¼¥É¤Ë°Ü¹Ô¤¹¤ë¤³¤È¤â¤Ç¤­¤Þ¤¹¡¥¾ÜºÙ¤Ï¡Ö9. ¥¹¥¤¥Ã¥Á¥ª¡¼¥Ð¡× + ½ÌÂ౿ž¥â¡¼¥É¤Ë°Ü¹Ô¤¹¤ë¤³¤È¤â¤Ç¤­¤Þ¤¹¡¥¾ÜºÙ¤Ï¡Ö10. ¥¹¥¤¥Ã¥Á¥ª¡¼¥Ð¡× ¤ò¤´Í÷²¼¤µ¤¤¡¥ 1.1 ¥ì¥×¥ê¥±¡¼¥·¥ç¥ó¤Ë¤Ä¤¤¤Æ @@ -342,8 +342,9 @@ pgpool version 3.1(kalekale) README make¤ògmake¤ËÆÉ¤ßÂØ¤¨¤Æ¤¯¤À¤µ¤¤)¡¥¥Ç¥Õ¥©¥ë¥È¤Î¥¤¥ó¥¹¥È¡¼¥ëÀè¤Ï¡¤ /usr/local°Ê²¼¤Ç°Ê²¼¤Î¤è¤¦¤Ê¥Õ¥¡¥¤¥ë¤¬¥¤¥ó¥¹¥È¡¼¥ë¤µ¤ì¤Þ¤¹¡¥ - /usr/local/bin/pgpool ¥×¥í¥°¥é¥àËÜÂÎ - /usr/local/etc/pgpool.conf.sample ÀßÄê¥Õ¥¡¥¤¥ë¥µ¥ó¥×¥ë + /usr/local/bin/pgpool ¥×¥í¥°¥é¥àËÜÂÎ + /usr/local/etc/pgpool.conf.sample ÀßÄê¥Õ¥¡¥¤¥ë¥µ¥ó¥×¥ë + /usr/local/etc/pool_hba.conf.sample HBAÀßÄê¥Õ¥¡¥¤¥ë¥µ¥ó¥×¥ë ¥¤¥ó¥¹¥È¡¼¥ëÀè¤òÊѹ¹¤¹¤ë¾ì¹ç¤Ï¡¤configure --prefix=path... ¤È¤· ¤Æ¤¯¤À¤µ¤¤¡¥ @@ -665,7 +666,86 @@ pgpool version 3.1(kalekale) README log_statement¥ª¥×¥·¥ç¥ó¤È»÷¤Æ¤¤¤Æ¡¤¥Ç¥Ð¥Ã¥°¥ª¥×¥·¥ç¥ó¤¬¤Ê¤¤¤È¤­¤Ç¤â Ì䤤¹ç¤ï¤»¤ò¥í¥°½ÐÎϤ·¤ÆÄ´¤Ù¤ë¤³¤È¤¬¤Ç¤­¤ë¤Î¤ÇÊØÍø¤Ç¤¹¡¥ -7. pgpool¤Îµ¯Æ° + log_connections + + true¤Ê¤é¤Ð¡¢Á´¤Æ¤Î¥¯¥é¥¤¥¢¥ó¥ÈÀܳ¤ò¥í¥°¤Ø½ÐÎϤ·¤Þ¤¹¡£ + + enable_pool_conf + + true¤Ê¤é¤Ð¡¢pool_hba.conf¤Ë½¾¤Ã¤Æ¥¯¥é¥¤¥¢¥ó¥Èǧ¾Ú¤ò¹Ô¤¤¤Þ¤¹¡£pgpool + 3.2¤Î¥Ç¥Õ¥©¥ë¥ÈÃͤÏfalse¤È¤Ê¤Ã¤Æ¤¤¤Þ¤¹¤¬¡¢¼¡¤Î¥ê¥ê¡¼¥¹¥Ð¡¼¥¸¥ç¥ó¤Ç + ¤Ï¤³¤Î¥Ñ¥é¥á¡¼¥¿¤Ïºï½ü¤µ¤ì¡¢¾ï¤Ëpool_hba.conf¤Ë¤è¤ë¥¯¥é¥¤¥ó¥¢¥ó¥Èǧ + ¾Ú¤¬¹Ô¤ï¤ì¤ëͽÄê¤Ç¤¹¡£¾ÜºÙ¤Ï¡Ö7. ¥¯¥é¥¤¥¢¥ó¥Èǧ¾Ú(HBA)¤Î¤¿¤á¤Î + pool_hba.confÀßÄêÊýË¡¡×¤ò»²¾È¤·¤Æ¤¯¤À¤µ¤¤¡£ + +7. ¥¯¥é¥¤¥¢¥ó¥Èǧ¾Ú(HBA)¤Î¤¿¤á¤Î pool_hba.conf ÀßÄêÊýË¡ + + PostgreSQL¤Îpg_hba.conf¤ÈƱ¤¸¤è¤¦¤Ëpgpool¤Ç¤âpool_config.conf¥Õ¥¡¥¤ + ¥ë¤ò»È¤Ã¤¿¥¯¥é¥¤¥¢¥ó¥Èǧ¾Ú¤¬¥µ¥Ý¡¼¥È¤µ¤ì¤Æ¤¤¤Þ¤¹¡£ + + pgpool¤ò¥¤¥ó¥¹¥È¡¼¥ë¤¹¤ë¤È¥Ç¥Õ¥©¥ë¥È¥¤¥ó¥¹¥È¡¼¥ëÀè¤ÎÀßÄê¥Õ¥¡¥¤¥ë¥Ç¥£ + ¥ì¥¯¥È¥ê"/usr/local/etc"¤Ëpool_hba.conf.sample¤¬°ì½ï¤Ë¥¤¥ó¥¹¥È¡¼¥ë + ¤µ¤ì¤Þ¤¹¡£ + + ¤³¤Îpool_hba.conf.sample¥Õ¥¡¥¤¥ë¤òpool_hba.conf¤È¤·¤Æ¥³¥Ô¡¼¤·¡¢É¬Í× + ¤Ç¤¢¤ì¤ÐÊÔ½¸¤·¤Æ¤¯¤À¤µ¤¤¡£¥Ç¥Õ¥©¥ë¥È¤Ç¤Ïpool_hba¤Ë¤è¤ëǧ¾Ú¤Ï̵¸ú¤Ë + ¤Ê¤Ã¤Æ¤¤¤Þ¤¹¡£¤³¤ì¤Ï°ÊÁ°¤Îpgpool¤È¤Î¸ß´¹À­¤òÊݤĤ¿¤á¤Ç¤¹¡£Í­¸ú¤Ë¤¹ + ¤ë¤¿¤á¤Ë¤Ïpgpool.conf¤Îenable_pool_hba¤òtrue¤ËÀßÄꤹ¤ëɬÍפ¬¤¢¤ê¤Þ + ¤¹¡£ + + pool_hba.conf¤Î¥Õ¥©¡¼¥Þ¥Ã¥È¤Ïpg_hba.conf¤Î¤â¤Î¤È¤Û¤È¤ó¤ÉƱ¤¸¤Ç¤¹¡£ + + local DATABASE USER METHOD [OPTION] + host DATABASE USER CIDR-ADDRESS METHOD [OPTION] + + ³Æ¥Õ¥£¡¼¥ë¥É¤ÇÀßÄê¤Ç¤­¤ëÃͤξܺ٤Ï"pool_hba.conf.sample"¤ò»²¾È¤·¤Æ + ¤¯¤À¤µ¤¤¡£ + + °Ê²¼¤Ïpool_hba¤ÎÀ©¸Â»ö¹à¤Ç¤¹¡£ + + * "hostssl"Àܳ¥¿¥¤¥×¤Ï¥µ¥Ý¡¼¥È¤µ¤ì¤Þ¤»¤ó + + ¸½ºßpgpool¤ÏSSLÀܳ¤ò¥µ¥Ý¡¼¥È¤·¤Æ¤¤¤Ê¤¤¤Î¤Ç"hostssl"¤Ï»ØÄꤹ¤ë¤³ + ¤È¤¬¤Ç¤­¤Þ¤»¤ó¡£ + + * DATABASE¥Õ¥£¡¼¥ë¥ÉÃͤȤ·¤Æ"samegroup"¤Ï¥µ¥Ý¡¼¥È¤µ¤ì¤Þ¤»¤ó + + pgpool¤Ï¥Ð¥Ã¥¯¥¨¥ó¥É¥µ¡¼¥Ð¤Ë¤¢¤ë¥æ¡¼¥¶¾ðÊó¤ò»öÁ°¤ËÃΤë»ö¤¬¤Ç¤­¤Ê + ¤¤¤¿¤á¡¢¥Ç¡¼¥¿¥Ù¡¼¥¹Ì¾¤Ïpool_hba.conf¤Ë¤¢¤ëÃͤΤߤÈÈæ³Ó¤µ¤ì¤Þ¤¹¡£ + ¤Ê¤Î¤Ç¥°¥ë¡¼¥×¤Ë´Ø¤¹¤ëǧ¾Ú¤Ïpool_hba¤Ç¹Ô¤¦¤³¤È¤¬¤Ç¤­¤Þ¤»¤ó¡£ + + * USER¥Õ¥£¡¼¥ë¥ÉÃͤȤ·¤Æ"+"¤ò»È¤Ã¤¿¥°¥ë¡¼¥×»ØÄê¤Ï¥µ¥Ý¡¼¥È¤µ¤ì¤Þ¤»¤ó + + ¾åµ­¤Î"samegroup"¤ÈƱ¤¸Íýͳ¤Ç¡¢¥æ¡¼¥¶Ì¾¤Ïpool_hba.conf¤Ë¤¢¤ëÃͤΠ+ ¤ß¤ÈÈæ³Ó¤µ¤ì¤Þ¤¹¡£¥°¥ë¡¼¥×¤Ë´Ø¤¹¤ëǧ¾Ú¤Ïpool_hba¤Ç¹Ô¤¦¤³¤È¤Ï¤Ç¤­ + ¤Þ¤»¤ó¡£ + + * IPv6¥¢¥É¥ì¥¹/¥Þ¥¹¥¯É½µ­Ë¡¤Ï¥µ¥Ý¡¼¥È¤µ¤ì¤Þ¤»¤ó + + ¸½ºßpgpool¤ÏIPv6¤ò¥µ¥Ý¡¼¥È¤·¤Æ¤¤¤Þ¤»¤ó¡£ + + * "trust", "reject", "pam"°Ê³°¤Î¥á¥½¥Ã¥É¤Ï¥µ¥Ý¡¼¥È¤µ¤ì¤Þ¤»¤ó + + ¤³¤ì¤â¾åµ­¤Î"samegroup"¤ÈƱ¤¸Íýͳ¤Ë¤è¤ë¤â¤Î¤Ç¤¹¡£pgpool¤Ï¥Ð¥Ã¥¯¥¨ + ¥ó¥É¤Î¥æ¡¼¥¶/¥Ñ¥¹¥ï¡¼¥É¾ðÊó¤ò»ý¤Ã¤Æ¤¤¤Ê¤¤¤Î¤Ç¡¢¥Ð¥Ã¥¯¥¨¥ó¥É¤ËÊݸ + ¤µ¤ì¤Æ¤¤¤ë¥Ñ¥¹¥ï¡¼¥É¤ò»È¤Ã¤¿Ç§¾Ú¤ò¹Ô¤¦¤³¤È¤¬¤Ç¤­¤Þ¤»¤ó¡£ + + ¤³¤³¤ÇÀâÌÀ¤µ¤ì¤¿µ¡Ç½¡¢À©¸Â¤Ï¥¯¥é¥¤¥¢¥ó¥È¤Èpgpool´Ö¤Ç¹Ô¤ï¤ì¤ë¥¯¥é¥¤ + ¥¢¥ó¥Èǧ¾Ú¤Ë¤Ä¤¤¤Æ¤À¤È¤¤¤¦¤³¤È¤ËÃí°Õ¤·¤Æ¤¯¤À¤µ¤¤¡£¥¯¥é¥¤¥ó¥¢¥ó¥È¤Ï + pgpool¤Î¥¯¥é¥¤¥¢¥ó¥Èǧ¾Ú¤ËÀ®¸ù¤·¤¿¤È¤·¤Æ¤â¡¢PostgreSQL¤Ë¤è¤ë¥¯¥é¥¤ + ¥¢¥ó¥Èǧ¾Ú¤ËÀ®¸ù¤·¤Ê¤¤¤ÈÀܳ¾õÂ֤Ȥʤê¤Þ¤»¤ó¡£pool_hba¤Ë¤È¤Ã¤Æ¤Ï¥¯ + ¥é¥¤¥¢¥ó¥È¤Ë»ØÄꤵ¤ì¤¿¥æ¡¼¥¶Ì¾¤ä¥Ç¡¼¥¿¥Ù¡¼¥¹Ì¾ + (Îã. psql -U testuser testdb)¤¬¼ÂºÝ¤Ë¥Ð¥Ã¥¯¥¨¥ó¥É¾å¤Ë¸ºß¤¹¤ë¤«¤É¤¦ + ¤«¤ÏÌäÂê¤Ç¤Ï¤¢¤ê¤Þ¤»¤ó¡£¤½¤ì¤¬pool_hba.conf¤ÎÃͤȥޥåÁ¤¹¤ë¤«¤É¤¦¤« + ¤Ç¥Á¥§¥Ã¥¯¤¬¹Ô¤ï¤ì¤Þ¤¹¡£ + + pgpool¤¬²ÔƯ¤¹¤ë¥Û¥¹¥È¾å¤Î¥æ¡¼¥¶¾ðÊó¤ò»È¤Ã¤¿PAMǧ¾Ú¤òÍøÍѤ¹¤ë¤³¤È¤¬ + ¤Ç¤­¤Þ¤¹¡£pgpool¤òPAM¥µ¥Ý¡¼¥ÈÉÕ¤­¤Ç¥Ó¥ë¥É¤¹¤ë¤Ë¤Ïconfigure¥ª¥×¥·¥ç + ¥ó¤Ë"--with-pam"¤ò»ØÄꤷ¤Æ¤¯¤À¤µ¤¤¡£ + + configure --with-pam + +8. pgpool¤Îµ¯Æ° pgpool¤òµ¯Æ°¤¹¤ë¤â¤Ã¤È¤â´Êñ¤ÊÊýË¡¤Ï¡¤ @@ -693,7 +773,7 @@ pgpool version 3.1(kalekale) README ¥Ø¥ë¥×¥á¥Ã¥»¡¼¥¸¤ò½ÐÎϤ·¤Æ½ªÎ»¤·¤Þ¤¹¡¥ -8. pgpool¤Î½ªÎ» +9. pgpool¤Î½ªÎ» ¡Östop¡×¥ª¥×¥·¥ç¥ó¤ò»È¤¤¤Þ¤¹¡¥ @@ -725,7 +805,7 @@ pgpool version 3.1(kalekale) README ¤È¤¹¤ë¤È¡¤pgpool stop¤ÈƱ¤¸Æ°ºî¤ò¤·¤Þ¤¹¡¥ -9. ¥¹¥¤¥Ã¥Á¥ª¡¼¥Ð +10. ¥¹¥¤¥Ã¥Á¥ª¡¼¥Ð ¥á¥¤¥ó¥Æ¥Ê¥ó¥¹¤Ê¤É¤Î¤¿¤á¤Ë°Õ¿ÞŪ¤Ë¥Õ¥§¥¤¥ë¥ª¡¼¥Ð¤ä½ÌÂ౿ž¥â¡¼¥É¤Ë °Ü¹Ô¤¹¤ë¤³¤È¤¬¤Ç¤­¤Þ¤¹¡¥ @@ -744,7 +824,7 @@ pgpool version 3.1(kalekale) README ¥ó¥È¤«¤épgpool¤Ø¤Î¥³¥Í¥¯¥·¥ç¥ó¤ò¶¯À©Åª¤Ë°ìÅÙÀÚÃǤ·¡¤pgpool¤Î»Ò¥×¥í ¥»¥¹¤¬ºÆµ¯Æ°¤µ¤ì¤Þ¤¹¡¥ -10. ¥í¥°¤Î¼è¤êÊý +11. ¥í¥°¤Î¼è¤êÊý pgpool¤ò-n¥ª¥×¥·¥ç¥óÉդǵ¯Æ°¤¹¤ë¤È¡¤stderr(ɸ½à¥¨¥é¡¼½ÐÎÏ)¤Ë¥¨¥é¡¼ ¤ä½ÅÂç¤Ê¾ðÊó(¤¿¤È¤¨¤Ð¥Õ¥§¥¤¥ë¥ª¡¼¥Ð¤·¤¿¤è¤¦¤Ê¾ì¹ç)¤Ë´Ø¤¹¤ë¥á¥Ã¥»¡¼ @@ -773,7 +853,7 @@ pgpool version 3.1(kalekale) README Apr 13 15:07:11 srapc1977 4·î 13 15:07:11 pgpool: log: pid 2038: failover from (5432) to (5433) done. -11. pgpool¤ÎÆâÉô¾ðÊó¤Î¼èÆÀ +12. pgpool¤ÎÆâÉô¾ðÊó¤Î¼èÆÀ pgpool¤¬Ç§¼±¤·¤Æ¤¤¤ëÀßÄê¥Õ¥¡¥¤¥ë(pgpool.conf)¤ÎÆâÍÆ¤ä¡¤¸½ºß¤Î¥ì¥× ¥ê¥±¡¼¥·¥ç¥ó¤Î¾õÂÖ¤òSQL¤òȯ¹Ô¤¹¤ë¤³¤È¤Ë¤è¤Ã¤Æ¼èÆÀ¤¹¤ë¤³¤È¤¬¤Ç¤­¤Þ @@ -784,8 +864,7 @@ pgpool version 3.1(kalekale) README (¥Ç¡¼¥¿¥Ù¡¼¥¹Ì¾¤Ï²¿¤Ç¤â¤«¤Þ¤¤¤Þ¤»¤ó)¡¥ - item | value | description -------------------------------+------------------------------------------------------+------------------------------------------------------------------------ + item | value | description --------------------------------+------------------------------------------------------+------------------------------------------------------------------------ listen_addresses | * | host name(s) or IP address(es) to listen to port | 9998 | pgpool accepting port number socket_dir | /tmp | pgpool socket directory @@ -796,6 +875,7 @@ pgpool version 3.1(kalekale) README num_init_children | 32 | # of children initially pre-forked child_life_time | 0 | if idle for this seconds, child exits connection_life_time | 0 | if idle for this seconds, connection closes + child_max_connections | 0 | if max_connections received, chile exits max_pool | 2 | max # of connection pool per child logdir | /tmp | logging directory backend_socket_dir | /tmp | Unix domain socket directory for the PostgreSQL server @@ -814,13 +894,17 @@ pgpool version 3.1(kalekale) README health_check_period | 0 | health check period health_check_user | t-ishii | health check user insert_lock | 1 | insert lock + ignore_leading_white_space | 0 | ignore leading white spaces current_backend_host_name | | current master host name current_backend_port | 5432 | current master port # replication_enabled | 1 | non 0 if actually operating in replication mode master_slave_enabled | 0 | non 0 if actually operating in master/slave num_reset_queries | 3 | number of queries in reset_query_list + log_statement | 0 | if true, print all statements to the log + log_connections | 1 | if true, print incoming connections to the log + enable_pool_hba | 1 | if true, use pool_hba.conf for client authentication server_status | master( on 5432) up secondary( on 5433) up | server status -(34 rows) +(39 rows) contrib/dblink¤ò»È¤¨¤Ð¡¤°Ê²¼¤Î¤è¤¦¤Ë¤·¤Æ°ìÉô¤Î·ë²Ì¤À¤±¤ò¸«¤ë¤³¤È¤¬¤Ç¤­ ¤Þ¤¹¡¥ @@ -832,7 +916,7 @@ test=# SELECT * FROM dblink('port=9999 dbname=test', 'show pool_status') port | 9999 (1 row) -12. regression test¤Î¼Â»Ü +13. regression test¤Î¼Â»Ü °Ê²¼¤Î¤è¤¦¤Ë¤·¤Æpgpool¤òÊ»ÍѤ·¤Æregression test¤ò¹Ô¤¦¤³¤È¤¬¤Ç¤­¤Þ¤¹¡¥ @@ -845,7 +929,7 @@ test=# SELECT * FROM dblink('port=9999 dbname=test', 'show pool_status') ¥ì¥×¥ê¥±¡¼¥·¥ç¥ó¥â¡¼¥É¤Çregression test¤ò¤¹¤ë¤Èɬ¤ºtablespace¤Î¥Æ¥¹ ¥È¤¬fail¤·¤Þ¤¹¤¬¡¤¤³¤ì¤Ï°Û¾ï¤Ç¤Ï¤¢¤ê¤Þ¤»¤ó¡¥ -13. ¥Ù¥ó¥Á¥Þ¡¼¥¯¤Î¼Â»Ü +14. ¥Ù¥ó¥Á¥Þ¡¼¥¯¤Î¼Â»Ü ¥Ù¥ó¥Á¥Þ¡¼¥¯¤ò¼Â»Ü¤¹¤ë¤Ë¤Ï¤¤¤í¤¤¤í¤ÊÊýË¡¤¬¤¢¤ê¤Þ¤¹¤¬¡¤¤³¤³¤Ç¤Ï pgbench¤ÈPHP¤½¤ì¤Ëab¤ò»È¤Ã¤¿´Êñ¤ÊÊýË¡¤ò¤´¾Ò²ð¤·¤Þ¤¹¡¥ @@ -874,7 +958,7 @@ test=# SELECT * FROM dblink('port=9999 dbname=test', 'show pool_status') $ /usr/local/apache/bin/ab -c 100 -n 1000 "http://localhost/bench.php" -14. master/slave¥â¡¼¥É +15. master/slave¥â¡¼¥É master/slave¥â¡¼¥É¤Ï¡¤Slony-I¤Î¤è¤¦¤Ê¡¤master/slave¼°¤Î¥ì¥×¥ê¥±¡¼¥·¥ç ¥ó¥½¥Õ¥È¤Ë¥ì¥×¥ê¥±¡¼¥·¥ç¥ó¤ò¤Þ¤«¤»¤ë¥â¡¼¥É¤Ç¤¹¡¥¤³¤Î¥â¡¼¥É¤Ç»È¤¦¤¿¤á¤Ë @@ -895,7 +979,7 @@ test=# SELECT * FROM dblink('port=9999 dbname=test', 'show pool_status') 2) 1)°Ê³°¤Î¾ì¹ç¤Ï¡¤¥Þ¥¹¥¿¤À¤±¤ËÌ䤤¹ç¤ï¤»¤¬Á÷¤é¤ì¤Þ¤¹¡¥ -15. Ê£¿ô¤Îpgpool¤òƱ¤¸¥Û¥¹¥È¤ÇΩ¤Á¾å¤²¤ë¤Ë¤Ï +16. Ê£¿ô¤Îpgpool¤òƱ¤¸¥Û¥¹¥È¤ÇΩ¤Á¾å¤²¤ë¤Ë¤Ï Ê£¿ô¤Îpgpool¤òƱ¤¸¥Û¥¹¥È¤ÇΩ¤Á¾å¤²¤ë¤Ë¤Ï(¤¿¤È¤¨¤Ð2¤Ä¤ÎDB¥¯¥é¥¹¥¿¤òÊÌ¡¹ ¤Ëpgpool¤Ç°·¤¦¥±¡¼¥¹)¡¤2¤Ä¤ÎÀßÄê¥Õ¥¡¥¤¥ë¤òºî¤ê¤Þ¤¹¡¥ diff --git a/ac_func_accept_argtypes.m4 b/ac_func_accept_argtypes.m4 new file mode 100644 index 0000000..917d59a --- /dev/null +++ b/ac_func_accept_argtypes.m4 @@ -0,0 +1,85 @@ +# $PostgreSQL: pgsql/config/ac_func_accept_argtypes.m4,v 1.6 2003/11/29 19:51:17 pgsql Exp $ +# This comes from the official Autoconf macro archive at +# +# (I removed the $ before the Id CVS keyword below.) + + +dnl @synopsis AC_FUNC_ACCEPT_ARGTYPES +dnl +dnl Checks the data types of the three arguments to accept(). Results are +dnl placed into the symbols ACCEPT_TYPE_RETURN and ACCEPT_TYPE_ARG[123], +dnl consistent with the following example: +dnl +dnl #define ACCEPT_TYPE_RETURN int +dnl #define ACCEPT_TYPE_ARG1 int +dnl #define ACCEPT_TYPE_ARG2 struct sockaddr * +dnl #define ACCEPT_TYPE_ARG3 socklen_t +dnl +dnl This macro requires AC_CHECK_HEADERS to have already verified the +dnl presence or absence of sys/types.h and sys/socket.h. +dnl +dnl NOTE: This is just a modified version of the AC_FUNC_SELECT_ARGTYPES +dnl macro. Credit for that one goes to David MacKenzie et. al. +dnl +dnl @version Id: ac_func_accept_argtypes.m4,v 1.1 1999/12/03 11:29:29 simons Exp $ +dnl @author Daniel Richard G. +dnl + +# PostgreSQL local changes: In the original version ACCEPT_TYPE_ARG3 +# is a pointer type. That's kind of useless because then you can't +# use the macro to define a corresponding variable. We also make the +# reasonable(?) assumption that you can use arg3 for getsocktype etc. +# as well (i.e., anywhere POSIX.2 has socklen_t). +# +# arg2 can also be `const' (e.g., RH 4.2). Change the order of tests +# for arg3 so that `int' is first, in case there is no prototype at all. +# +# Solaris 7 and 8 have arg3 as 'void *' (disguised as 'Psocklen_t' +# which is *not* 'socklen_t *'). If we detect that, then we assume +# 'int' as the result, because that ought to work best. +# +# On Win32, accept() returns 'unsigned int PASCAL' + +AC_DEFUN([AC_FUNC_ACCEPT_ARGTYPES], +[AC_MSG_CHECKING([types of arguments for accept()]) + AC_CACHE_VAL(ac_cv_func_accept_return,dnl + [AC_CACHE_VAL(ac_cv_func_accept_arg1,dnl + [AC_CACHE_VAL(ac_cv_func_accept_arg2,dnl + [AC_CACHE_VAL(ac_cv_func_accept_arg3,dnl + [for ac_cv_func_accept_return in 'int' 'unsigned int PASCAL'; do + for ac_cv_func_accept_arg1 in 'int' 'unsigned int'; do + for ac_cv_func_accept_arg2 in 'struct sockaddr *' 'const struct sockaddr *' 'void *'; do + for ac_cv_func_accept_arg3 in 'int' 'size_t' 'socklen_t' 'unsigned int' 'void'; do + AC_TRY_COMPILE( +[#ifdef HAVE_SYS_TYPES_H +#include +#endif +#ifdef HAVE_SYS_SOCKET_H +#include +#endif +extern $ac_cv_func_accept_return accept ($ac_cv_func_accept_arg1, $ac_cv_func_accept_arg2, $ac_cv_func_accept_arg3 *);], + [], [ac_not_found=no; break 4], [ac_not_found=yes]) + done + done + done + done + if test "$ac_not_found" = yes; then + AC_MSG_ERROR([could not determine argument types]) + fi + if test "$ac_cv_func_accept_arg3" = "void"; then + ac_cv_func_accept_arg3=int + fi + ])dnl AC_CACHE_VAL + ])dnl AC_CACHE_VAL + ])dnl AC_CACHE_VAL + ])dnl AC_CACHE_VAL + AC_MSG_RESULT([$ac_cv_func_accept_return, $ac_cv_func_accept_arg1, $ac_cv_func_accept_arg2, $ac_cv_func_accept_arg3 *]) + AC_DEFINE_UNQUOTED(ACCEPT_TYPE_RETURN, $ac_cv_func_accept_return, + [Define to the return type of 'accept']) + AC_DEFINE_UNQUOTED(ACCEPT_TYPE_ARG1, $ac_cv_func_accept_arg1, + [Define to the type of arg 1 of 'accept']) + AC_DEFINE_UNQUOTED(ACCEPT_TYPE_ARG2, $ac_cv_func_accept_arg2, + [Define to the type of arg 2 of 'accept']) + AC_DEFINE_UNQUOTED(ACCEPT_TYPE_ARG3, $ac_cv_func_accept_arg3, + [Define to the type of arg 3 of 'accept']) +]) diff --git a/aclocal.m4 b/aclocal.m4 index 20ce300..7258915 100644 --- a/aclocal.m4 +++ b/aclocal.m4 @@ -881,3 +881,4 @@ AC_SUBST([am__tar]) AC_SUBST([am__untar]) ]) # _AM_PROG_TAR +m4_include([ac_func_accept_argtypes.m4]) diff --git a/child.c b/child.c index 40b466d..33684f3 100644 --- a/child.c +++ b/child.c @@ -27,6 +27,8 @@ #include #include #include +#include +#include #ifdef HAVE_NETINET_TCP_H #include #endif @@ -45,6 +47,7 @@ #endif #include "pool.h" +#include "pool_ip.h" #ifdef NONE_BLOCK static void set_nonblock(int fd); @@ -218,6 +221,29 @@ void do_child(int unix_fd, int inet_fd) goto retry_startup; } + if (pool_config.enable_pool_hba) + { + /* + * do client authentication. + * Note that ClientAuthentication does not return if frontend + * was rejected; it simply terminates this process. + */ + frontend->protoVersion = sp->major; + frontend->database = strdup(sp->database); + if (frontend->database == NULL) + { + pool_error("do_child: strdup failed: %s\n", strerror(errno)); + exit(1); + } + frontend->username = strdup(sp->user); + if (frontend->username == NULL) + { + pool_error("do_child: strdup failed: %s\n", strerror(errno)); + exit(1); + } + ClientAuthentication(frontend); + } + /* * Ok, negotiaton with frontend has been done. Let's go to the next step. */ @@ -490,8 +516,7 @@ static POOL_CONNECTION *do_accept(int unix_fd, int inet_fd, struct timeval *time fd_set readmask; int fds; - struct sockaddr addr; - socklen_t addrlen; + SockAddr saddr; int fd = 0; int afd; int inet = 0; @@ -590,12 +615,13 @@ static POOL_CONNECTION *do_accept(int unix_fd, int inet_fd, struct timeval *time * Note that some SysV systems do not work here. For those * systems, we need some locking mechanism for the fd. */ - addrlen = sizeof(addr); + memset(&saddr, 0, sizeof(saddr)); + saddr.salen = sizeof(saddr.addr); #ifdef ACCEPT_PERFORMANCE gettimeofday(&now1,0); #endif - afd = accept(fd, &addr, &addrlen); + afd = accept(fd, (struct sockaddr *)&saddr.addr, &saddr.salen); if (afd < 0) { /* @@ -618,6 +644,30 @@ static POOL_CONNECTION *do_accept(int unix_fd, int inet_fd, struct timeval *time set_ps_display("accept connection", false); pool_debug("I am %d accept fd %d", getpid(), afd); + /* log who is connecting */ + if (pool_config.log_connections) + { + char remote_host[NI_MAXHOST]; + char remote_port[NI_MAXSERV]; + + remote_host[0] = '\0'; + remote_port[0] = '\0'; + if (getnameinfo_all(&saddr.addr, saddr.salen, + remote_host, sizeof(remote_host), + remote_port, sizeof(remote_port), + NI_NUMERICHOST | NI_NUMERICSERV)) + { + int ret = getnameinfo_all(&saddr.addr, saddr.salen, + remote_host, sizeof(remote_host), + remote_port, sizeof(remote_port), + NI_NUMERICHOST | NI_NUMERICSERV); + if (ret) + pool_error("getnameinfo_all() failed: %s", gai_strerror(ret)); + } + pool_log("connection received: host=%s%s%s", + remote_host, remote_port[0] ? " port=" : "", remote_port); + } + /* set NODELAY and KEEPALIVE options if INET connection */ if (inet) { @@ -646,6 +696,12 @@ static POOL_CONNECTION *do_accept(int unix_fd, int inet_fd, struct timeval *time close(afd); return NULL; } + + /* save ip addres for hba */ + memcpy(&cp->raddr, &saddr, sizeof(SockAddr)); + if (cp->raddr.addr.ss_family == 0) + cp->raddr.addr.ss_family = AF_UNIX; + return cp; } diff --git a/config.h.in b/config.h.in index 44d2ad3..91589de 100644 --- a/config.h.in +++ b/config.h.in @@ -1,5 +1,17 @@ /* config.h.in. Generated from configure.in by autoheader. */ +/* Define to the type of arg 1 of 'accept' */ +#undef ACCEPT_TYPE_ARG1 + +/* Define to the type of arg 2 of 'accept' */ +#undef ACCEPT_TYPE_ARG2 + +/* Define to the type of arg 3 of 'accept' */ +#undef ACCEPT_TYPE_ARG3 + +/* Define to the return type of 'accept' */ +#undef ACCEPT_TYPE_RETURN + /* Define to 1 if you have the `asprintf' function. */ #undef HAVE_ASPRINTF @@ -36,6 +48,9 @@ /* Define to 1 if you have the `nsl' library (-lnsl). */ #undef HAVE_LIBNSL +/* Define to 1 if you have the `pam' library (-lpam). */ +#undef HAVE_LIBPAM + /* Define to 1 if you have the `PW' library (-lPW). */ #undef HAVE_LIBPW @@ -48,12 +63,21 @@ /* Define to 1 if you have the header file. */ #undef HAVE_MEMORY_H +/* Define to 1 if you have the header file. */ +#undef HAVE_NETDB_H + /* Define to 1 if you have the header file. */ #undef HAVE_NETINET_IN_H /* Define to 1 if you have the header file. */ #undef HAVE_NETINET_TCP_H +/* Define to 1 if you have the header file. */ +#undef HAVE_PAM_PAM_APPL_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SECURITY_PAM_APPL_H + /* Define to 1 if you have the `select' function. */ #undef HAVE_SELECT @@ -93,12 +117,33 @@ /* Define to 1 if you have the `strtok' function. */ #undef HAVE_STRTOK +/* Define to 1 if `sa_len' is member of `struct sockaddr'. */ +#undef HAVE_STRUCT_SOCKADDR_SA_LEN + +/* Define to 1 if the system has the type `struct sockaddr_storage'. */ +#undef HAVE_STRUCT_SOCKADDR_STORAGE + +/* Define to 1 if `ss_family' is member of `struct sockaddr_storage'. */ +#undef HAVE_STRUCT_SOCKADDR_STORAGE_SS_FAMILY + +/* Define to 1 if `ss_len' is member of `struct sockaddr_storage'. */ +#undef HAVE_STRUCT_SOCKADDR_STORAGE_SS_LEN + +/* Define to 1 if `__ss_family' is member of `struct sockaddr_storage'. */ +#undef HAVE_STRUCT_SOCKADDR_STORAGE___SS_FAMILY + +/* Define to 1 if `__ss_len' is member of `struct sockaddr_storage'. */ +#undef HAVE_STRUCT_SOCKADDR_STORAGE___SS_LEN + /* Define to 1 if you have the header file. */ #undef HAVE_SYS_PARAM_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_PSTAT_H +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_SOCKET_H + /* Define to 1 if you have the header file. */ #undef HAVE_SYS_STAT_H @@ -108,6 +153,9 @@ /* Define to 1 if you have the header file. */ #undef HAVE_SYS_TYPES_H +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_UN_H + /* Define to 1 if you have that is POSIX.1 compatible. */ #undef HAVE_SYS_WAIT_H @@ -148,6 +196,9 @@ /* Define to 1 if you can safely include both and . */ #undef TIME_WITH_SYS_TIME +/* Define to 1 to build with PAM support. (--with-pam) */ +#undef USE_PAM + /* Version number of package */ #undef VERSION diff --git a/configure b/configure index e4de826..6cde5b6 100755 --- a/configure +++ b/configure @@ -718,13 +718,13 @@ echo X"$0" | /^X\(\/\).*/{ s//\1/; q; } s/.*/./; q'` srcdir=$ac_confdir - if test ! -r $srcdir/$ac_unique_file; then + if test ! -r "$srcdir/$ac_unique_file"; then srcdir=.. fi else ac_srcdir_defaulted=no fi -if test ! -r $srcdir/$ac_unique_file; then +if test ! -r "$srcdir/$ac_unique_file"; then if test "$ac_srcdir_defaulted" = yes; then { echo "$as_me: error: cannot find sources ($ac_unique_file) in $ac_confdir or .." >&2 { (exit 1); exit 1; }; } @@ -733,7 +733,7 @@ if test ! -r $srcdir/$ac_unique_file; then { (exit 1); exit 1; }; } fi fi -(cd $srcdir && test -r ./$ac_unique_file) 2>/dev/null || +(cd $srcdir && test -r "./$ac_unique_file") 2>/dev/null || { echo "$as_me: error: sources are in $srcdir, but \`cd $srcdir' does not work" >&2 { (exit 1); exit 1; }; } srcdir=`echo "$srcdir" | sed 's%\([^\\/]\)[\\/]*$%\1%'` @@ -851,6 +851,7 @@ Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) --with-pgsql=DIR site header files for PostgreSQL in DIR + --with-pam build with PAM support Some influential environment variables: CC C compiler command @@ -4439,7 +4440,10 @@ done -for ac_header in fcntl.h unistd.h getopt.h netinet/tcp.h netinet/in.h sys/param.h sys/types.h sys/time.h sys/pstat.h + + + +for ac_header in fcntl.h unistd.h getopt.h netinet/tcp.h netinet/in.h netdb.h sys/param.h sys/types.h sys/socket.h sys/un.h sys/time.h sys/pstat.h do as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` if eval "test \"\${$as_ac_Header+set}\" = set"; then @@ -4828,9 +4832,9 @@ _ACEOF fi -echo "$as_me:$LINENO: checking return type of signal handlers" >&5 -echo $ECHO_N "checking return type of signal handlers... $ECHO_C" >&6 -if test "${ac_cv_type_signal+set}" = set; then +echo "$as_me:$LINENO: checking for struct sockaddr_storage" >&5 +echo $ECHO_N "checking for struct sockaddr_storage... $ECHO_C" >&6 +if test "${ac_cv_type_struct_sockaddr_storage+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF @@ -4840,20 +4844,18 @@ cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include -#include -#ifdef signal -# undef signal -#endif -#ifdef __cplusplus -extern "C" void (*signal (int, void (*)(int)))(int); -#else -void (*signal ()) (); +#ifdef HAVE_SYS_SOCKET_H +#include #endif + int main () { -int i; +if ((struct sockaddr_storage *) 0) + return 0; +if (sizeof (struct sockaddr_storage)) + return 0; ; return 0; } @@ -4880,30 +4882,29 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then - ac_cv_type_signal=void + ac_cv_type_struct_sockaddr_storage=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 -ac_cv_type_signal=int +ac_cv_type_struct_sockaddr_storage=no fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext fi -echo "$as_me:$LINENO: result: $ac_cv_type_signal" >&5 -echo "${ECHO_T}$ac_cv_type_signal" >&6 +echo "$as_me:$LINENO: result: $ac_cv_type_struct_sockaddr_storage" >&5 +echo "${ECHO_T}$ac_cv_type_struct_sockaddr_storage" >&6 +if test $ac_cv_type_struct_sockaddr_storage = yes; then cat >>confdefs.h <<_ACEOF -#define RETSIGTYPE $ac_cv_type_signal +#define HAVE_STRUCT_SOCKADDR_STORAGE 1 _ACEOF +fi -for ac_func in vprintf -do -as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` -echo "$as_me:$LINENO: checking for $ac_func" >&5 -echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6 -if eval "test \"\${$as_ac_var+set}\" = set"; then +echo "$as_me:$LINENO: checking for struct sockaddr_storage.ss_family" >&5 +echo $ECHO_N "checking for struct sockaddr_storage.ss_family... $ECHO_C" >&6 +if test "${ac_cv_member_struct_sockaddr_storage_ss_family+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF @@ -4912,54 +4913,25 @@ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ -/* Define $ac_func to an innocuous variant, in case declares $ac_func. - For example, HP-UX 11i declares gettimeofday. */ -#define $ac_func innocuous_$ac_func - -/* System header to define __stub macros and hopefully few prototypes, - which can conflict with char $ac_func (); below. - Prefer to if __STDC__ is defined, since - exists even on freestanding compilers. */ - -#ifdef __STDC__ -# include -#else -# include +#include +#ifdef HAVE_SYS_SOCKET_H +#include #endif -#undef $ac_func - -/* Override any gcc2 internal prototype to avoid an error. */ -#ifdef __cplusplus -extern "C" -{ -#endif -/* We use char because int might match the return type of a gcc2 - builtin and then its argument prototype would still apply. */ -char $ac_func (); -/* The GNU C library defines this for functions which it implements - to always fail with ENOSYS. Some functions are actually named - something starting with __ and the normal name is an alias. */ -#if defined (__stub_$ac_func) || defined (__stub___$ac_func) -choke me -#else -char (*f) () = $ac_func; -#endif -#ifdef __cplusplus -} -#endif int main () { -return f != $ac_func; +static struct sockaddr_storage ac_aggr; +if (ac_aggr.ss_family) +return 0; ; return 0; } _ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>conftest.er1 +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 @@ -4973,88 +4945,42 @@ if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' + { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then - eval "$as_ac_var=yes" + ac_cv_member_struct_sockaddr_storage_ss_family=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 -eval "$as_ac_var=no" -fi -rm -f conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -fi -echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5 -echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6 -if test `eval echo '${'$as_ac_var'}'` = yes; then - cat >>confdefs.h <<_ACEOF -#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 -_ACEOF - -echo "$as_me:$LINENO: checking for _doprnt" >&5 -echo $ECHO_N "checking for _doprnt... $ECHO_C" >&6 -if test "${ac_cv_func__doprnt+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - cat >conftest.$ac_ext <<_ACEOF +cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ -/* Define _doprnt to an innocuous variant, in case declares _doprnt. - For example, HP-UX 11i declares gettimeofday. */ -#define _doprnt innocuous__doprnt - -/* System header to define __stub macros and hopefully few prototypes, - which can conflict with char _doprnt (); below. - Prefer to if __STDC__ is defined, since - exists even on freestanding compilers. */ - -#ifdef __STDC__ -# include -#else -# include +#include +#ifdef HAVE_SYS_SOCKET_H +#include #endif -#undef _doprnt - -/* Override any gcc2 internal prototype to avoid an error. */ -#ifdef __cplusplus -extern "C" -{ -#endif -/* We use char because int might match the return type of a gcc2 - builtin and then its argument prototype would still apply. */ -char _doprnt (); -/* The GNU C library defines this for functions which it implements - to always fail with ENOSYS. Some functions are actually named - something starting with __ and the normal name is an alias. */ -#if defined (__stub__doprnt) || defined (__stub____doprnt) -choke me -#else -char (*f) () = _doprnt; -#endif -#ifdef __cplusplus -} -#endif int main () { -return f != _doprnt; +static struct sockaddr_storage ac_aggr; +if (sizeof ac_aggr.ss_family) +return 0; ; return 0; } _ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>conftest.er1 +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 @@ -5068,43 +4994,37 @@ if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' + { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then - ac_cv_func__doprnt=yes + ac_cv_member_struct_sockaddr_storage_ss_family=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 -ac_cv_func__doprnt=no +ac_cv_member_struct_sockaddr_storage_ss_family=no fi -rm -f conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext fi -echo "$as_me:$LINENO: result: $ac_cv_func__doprnt" >&5 -echo "${ECHO_T}$ac_cv_func__doprnt" >&6 -if test $ac_cv_func__doprnt = yes; then +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_member_struct_sockaddr_storage_ss_family" >&5 +echo "${ECHO_T}$ac_cv_member_struct_sockaddr_storage_ss_family" >&6 +if test $ac_cv_member_struct_sockaddr_storage_ss_family = yes; then -cat >>confdefs.h <<\_ACEOF -#define HAVE_DOPRNT 1 +cat >>confdefs.h <<_ACEOF +#define HAVE_STRUCT_SOCKADDR_STORAGE_SS_FAMILY 1 _ACEOF -fi fi -done - - -echo "$as_me:$LINENO: checking for wait3 that fills in rusage" >&5 -echo $ECHO_N "checking for wait3 that fills in rusage... $ECHO_C" >&6 -if test "${ac_cv_func_wait3_rusage+set}" = set; then +echo "$as_me:$LINENO: checking for struct sockaddr_storage.__ss_family" >&5 +echo $ECHO_N "checking for struct sockaddr_storage.__ss_family... $ECHO_C" >&6 +if test "${ac_cv_member_struct_sockaddr_storage___ss_family+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test "$cross_compiling" = yes; then - ac_cv_func_wait3_rusage=no else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ @@ -5113,90 +5033,116 @@ cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include -#include -#include -#include -/* HP-UX has wait3 but does not fill in rusage at all. */ +#ifdef HAVE_SYS_SOCKET_H +#include +#endif + + int main () { - struct rusage r; - int i; - /* Use a field that we can force nonzero -- - voluntary context switches. - For systems like NeXT and OSF/1 that don't set it, - also use the system CPU time. And page faults (I/O) for Linux. */ - r.ru_nvcsw = 0; - r.ru_stime.tv_sec = 0; - r.ru_stime.tv_usec = 0; - r.ru_majflt = r.ru_minflt = 0; - switch (fork ()) - { - case 0: /* Child. */ - sleep(1); /* Give up the CPU. */ - _exit(0); - break; - case -1: /* What can we do? */ - _exit(0); - break; - default: /* Parent. */ - wait3(&i, 0, &r); - /* Avoid "text file busy" from rm on fast HP-UX machines. */ - sleep(2); - exit (r.ru_nvcsw == 0 && r.ru_majflt == 0 && r.ru_minflt == 0 - && r.ru_stime.tv_sec == 0 && r.ru_stime.tv_usec == 0); - } +static struct sockaddr_storage ac_aggr; +if (ac_aggr.__ss_family) +return 0; + ; + return 0; } _ACEOF -rm -f conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>&5 +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then - ac_cv_func_wait3_rusage=yes + ac_cv_member_struct_sockaddr_storage___ss_family=yes else - echo "$as_me: program exited with status $ac_status" >&5 -echo "$as_me: failed program was:" >&5 + echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 -( exit $ac_status ) -ac_cv_func_wait3_rusage=no -fi -rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext -fi -fi -echo "$as_me:$LINENO: result: $ac_cv_func_wait3_rusage" >&5 -echo "${ECHO_T}$ac_cv_func_wait3_rusage" >&6 -if test $ac_cv_func_wait3_rusage = yes; then - -cat >>confdefs.h <<\_ACEOF -#define HAVE_WAIT3 1 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ _ACEOF - -fi - - - - - - - - - +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#ifdef HAVE_SYS_SOCKET_H +#include +#endif -for ac_func in setsid select socket sigprocmask strdup strerror strftime strtok asprintf setproctitle -do -as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` -echo "$as_me:$LINENO: checking for $ac_func" >&5 -echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6 -if eval "test \"\${$as_ac_var+set}\" = set"; then +int +main () +{ +static struct sockaddr_storage ac_aggr; +if (sizeof ac_aggr.__ss_family) +return 0; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_member_struct_sockaddr_storage___ss_family=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_member_struct_sockaddr_storage___ss_family=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_member_struct_sockaddr_storage___ss_family" >&5 +echo "${ECHO_T}$ac_cv_member_struct_sockaddr_storage___ss_family" >&6 +if test $ac_cv_member_struct_sockaddr_storage___ss_family = yes; then + +cat >>confdefs.h <<_ACEOF +#define HAVE_STRUCT_SOCKADDR_STORAGE___SS_FAMILY 1 +_ACEOF + + +fi +echo "$as_me:$LINENO: checking for struct sockaddr_storage.ss_len" >&5 +echo $ECHO_N "checking for struct sockaddr_storage.ss_len... $ECHO_C" >&6 +if test "${ac_cv_member_struct_sockaddr_storage_ss_len+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF @@ -5205,54 +5151,74 @@ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ -/* Define $ac_func to an innocuous variant, in case declares $ac_func. - For example, HP-UX 11i declares gettimeofday. */ -#define $ac_func innocuous_$ac_func - -/* System header to define __stub macros and hopefully few prototypes, - which can conflict with char $ac_func (); below. - Prefer to if __STDC__ is defined, since - exists even on freestanding compilers. */ - -#ifdef __STDC__ -# include -#else -# include +#include +#ifdef HAVE_SYS_SOCKET_H +#include #endif -#undef $ac_func -/* Override any gcc2 internal prototype to avoid an error. */ -#ifdef __cplusplus -extern "C" +int +main () { -#endif -/* We use char because int might match the return type of a gcc2 - builtin and then its argument prototype would still apply. */ -char $ac_func (); -/* The GNU C library defines this for functions which it implements - to always fail with ENOSYS. Some functions are actually named - something starting with __ and the normal name is an alias. */ -#if defined (__stub_$ac_func) || defined (__stub___$ac_func) -choke me -#else -char (*f) () = $ac_func; -#endif -#ifdef __cplusplus +static struct sockaddr_storage ac_aggr; +if (ac_aggr.ss_len) +return 0; + ; + return 0; } +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_member_struct_sockaddr_storage_ss_len=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#ifdef HAVE_SYS_SOCKET_H +#include #endif + int main () { -return f != $ac_func; +static struct sockaddr_storage ac_aggr; +if (sizeof ac_aggr.ss_len) +return 0; ; return 0; } _ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>conftest.er1 +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 @@ -5266,51 +5232,1264 @@ if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' + { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then - eval "$as_ac_var=yes" + ac_cv_member_struct_sockaddr_storage_ss_len=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 -eval "$as_ac_var=no" +ac_cv_member_struct_sockaddr_storage_ss_len=no fi -rm -f conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext fi -echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5 -echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6 -if test `eval echo '${'$as_ac_var'}'` = yes; then - cat >>confdefs.h <<_ACEOF -#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_member_struct_sockaddr_storage_ss_len" >&5 +echo "${ECHO_T}$ac_cv_member_struct_sockaddr_storage_ss_len" >&6 +if test $ac_cv_member_struct_sockaddr_storage_ss_len = yes; then + +cat >>confdefs.h <<_ACEOF +#define HAVE_STRUCT_SOCKADDR_STORAGE_SS_LEN 1 _ACEOF + fi -done +echo "$as_me:$LINENO: checking for struct sockaddr_storage.__ss_len" >&5 +echo $ECHO_N "checking for struct sockaddr_storage.__ss_len... $ECHO_C" >&6 +if test "${ac_cv_member_struct_sockaddr_storage___ss_len+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#ifdef HAVE_SYS_SOCKET_H +#include +#endif -PGSQL_INCLUDE_DIR=/usr/local/pgsql/include +int +main () +{ +static struct sockaddr_storage ac_aggr; +if (ac_aggr.__ss_len) +return 0; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_member_struct_sockaddr_storage___ss_len=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 -# Check whether --with-pgsql or --without-pgsql was given. -if test "${with_pgsql+set}" = set; then - withval="$with_pgsql" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#ifdef HAVE_SYS_SOCKET_H +#include +#endif - case "$withval" in - "" | y | ye | yes | n | no) - { { echo "$as_me:$LINENO: error: *** You must supply an argument to the --with-pgsql option." >&5 -echo "$as_me: error: *** You must supply an argument to the --with-pgsql option." >&2;} - { (exit 1); exit 1; }; } - ;; - esac - PGSQL_INCLUDE_DIR="$withval" -fi; +int +main () +{ +static struct sockaddr_storage ac_aggr; +if (sizeof ac_aggr.__ss_len) +return 0; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_member_struct_sockaddr_storage___ss_len=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_member_struct_sockaddr_storage___ss_len=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_member_struct_sockaddr_storage___ss_len" >&5 +echo "${ECHO_T}$ac_cv_member_struct_sockaddr_storage___ss_len" >&6 +if test $ac_cv_member_struct_sockaddr_storage___ss_len = yes; then + +cat >>confdefs.h <<_ACEOF +#define HAVE_STRUCT_SOCKADDR_STORAGE___SS_LEN 1 +_ACEOF +fi +echo "$as_me:$LINENO: checking for struct sockaddr.sa_len" >&5 +echo $ECHO_N "checking for struct sockaddr.sa_len... $ECHO_C" >&6 +if test "${ac_cv_member_struct_sockaddr_sa_len+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#ifdef HAVE_SYS_SOCKET_H +#include +#endif + + +int +main () +{ +static struct sockaddr ac_aggr; +if (ac_aggr.sa_len) +return 0; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_member_struct_sockaddr_sa_len=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#ifdef HAVE_SYS_SOCKET_H +#include +#endif + + +int +main () +{ +static struct sockaddr ac_aggr; +if (sizeof ac_aggr.sa_len) +return 0; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_member_struct_sockaddr_sa_len=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_member_struct_sockaddr_sa_len=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_member_struct_sockaddr_sa_len" >&5 +echo "${ECHO_T}$ac_cv_member_struct_sockaddr_sa_len" >&6 +if test $ac_cv_member_struct_sockaddr_sa_len = yes; then + +cat >>confdefs.h <<_ACEOF +#define HAVE_STRUCT_SOCKADDR_SA_LEN 1 +_ACEOF + + +fi + + +echo "$as_me:$LINENO: checking return type of signal handlers" >&5 +echo $ECHO_N "checking return type of signal handlers... $ECHO_C" >&6 +if test "${ac_cv_type_signal+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#include +#ifdef signal +# undef signal +#endif +#ifdef __cplusplus +extern "C" void (*signal (int, void (*)(int)))(int); +#else +void (*signal ()) (); +#endif + +int +main () +{ +int i; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_type_signal=void +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_type_signal=int +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_type_signal" >&5 +echo "${ECHO_T}$ac_cv_type_signal" >&6 + +cat >>confdefs.h <<_ACEOF +#define RETSIGTYPE $ac_cv_type_signal +_ACEOF + + + +for ac_func in vprintf +do +as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` +echo "$as_me:$LINENO: checking for $ac_func" >&5 +echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6 +if eval "test \"\${$as_ac_var+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define $ac_func to an innocuous variant, in case declares $ac_func. + For example, HP-UX 11i declares gettimeofday. */ +#define $ac_func innocuous_$ac_func + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef $ac_func + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +{ +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char $ac_func (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_$ac_func) || defined (__stub___$ac_func) +choke me +#else +char (*f) () = $ac_func; +#endif +#ifdef __cplusplus +} +#endif + +int +main () +{ +return f != $ac_func; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + eval "$as_ac_var=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +eval "$as_ac_var=no" +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6 +if test `eval echo '${'$as_ac_var'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +echo "$as_me:$LINENO: checking for _doprnt" >&5 +echo $ECHO_N "checking for _doprnt... $ECHO_C" >&6 +if test "${ac_cv_func__doprnt+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define _doprnt to an innocuous variant, in case declares _doprnt. + For example, HP-UX 11i declares gettimeofday. */ +#define _doprnt innocuous__doprnt + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char _doprnt (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef _doprnt + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +{ +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char _doprnt (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub__doprnt) || defined (__stub____doprnt) +choke me +#else +char (*f) () = _doprnt; +#endif +#ifdef __cplusplus +} +#endif + +int +main () +{ +return f != _doprnt; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_func__doprnt=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_func__doprnt=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_func__doprnt" >&5 +echo "${ECHO_T}$ac_cv_func__doprnt" >&6 +if test $ac_cv_func__doprnt = yes; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_DOPRNT 1 +_ACEOF + +fi + +fi +done + + +echo "$as_me:$LINENO: checking for wait3 that fills in rusage" >&5 +echo $ECHO_N "checking for wait3 that fills in rusage... $ECHO_C" >&6 +if test "${ac_cv_func_wait3_rusage+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test "$cross_compiling" = yes; then + ac_cv_func_wait3_rusage=no +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#include +#include +#include +/* HP-UX has wait3 but does not fill in rusage at all. */ +int +main () +{ + struct rusage r; + int i; + /* Use a field that we can force nonzero -- + voluntary context switches. + For systems like NeXT and OSF/1 that don't set it, + also use the system CPU time. And page faults (I/O) for Linux. */ + r.ru_nvcsw = 0; + r.ru_stime.tv_sec = 0; + r.ru_stime.tv_usec = 0; + r.ru_majflt = r.ru_minflt = 0; + switch (fork ()) + { + case 0: /* Child. */ + sleep(1); /* Give up the CPU. */ + _exit(0); + break; + case -1: /* What can we do? */ + _exit(0); + break; + default: /* Parent. */ + wait3(&i, 0, &r); + /* Avoid "text file busy" from rm on fast HP-UX machines. */ + sleep(2); + exit (r.ru_nvcsw == 0 && r.ru_majflt == 0 && r.ru_minflt == 0 + && r.ru_stime.tv_sec == 0 && r.ru_stime.tv_usec == 0); + } +} +_ACEOF +rm -f conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_func_wait3_rusage=yes +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +ac_cv_func_wait3_rusage=no +fi +rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi +fi +echo "$as_me:$LINENO: result: $ac_cv_func_wait3_rusage" >&5 +echo "${ECHO_T}$ac_cv_func_wait3_rusage" >&6 +if test $ac_cv_func_wait3_rusage = yes; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_WAIT3 1 +_ACEOF + +fi + +echo "$as_me:$LINENO: checking types of arguments for accept()" >&5 +echo $ECHO_N "checking types of arguments for accept()... $ECHO_C" >&6 + if test "${ac_cv_func_accept_return+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test "${ac_cv_func_accept_arg1+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test "${ac_cv_func_accept_arg2+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test "${ac_cv_func_accept_arg3+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + for ac_cv_func_accept_return in 'int' 'unsigned int PASCAL'; do + for ac_cv_func_accept_arg1 in 'int' 'unsigned int'; do + for ac_cv_func_accept_arg2 in 'struct sockaddr *' 'const struct sockaddr *' 'void *'; do + for ac_cv_func_accept_arg3 in 'int' 'size_t' 'socklen_t' 'unsigned int' 'void'; do + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#ifdef HAVE_SYS_TYPES_H +#include +#endif +#ifdef HAVE_SYS_SOCKET_H +#include +#endif +extern $ac_cv_func_accept_return accept ($ac_cv_func_accept_arg1, $ac_cv_func_accept_arg2, $ac_cv_func_accept_arg3 *); +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_not_found=no; break 4 +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_not_found=yes +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext + done + done + done + done + if test "$ac_not_found" = yes; then + { { echo "$as_me:$LINENO: error: could not determine argument types" >&5 +echo "$as_me: error: could not determine argument types" >&2;} + { (exit 1); exit 1; }; } + fi + if test "$ac_cv_func_accept_arg3" = "void"; then + ac_cv_func_accept_arg3=int + fi + +fi + +fi + +fi + +fi + echo "$as_me:$LINENO: result: $ac_cv_func_accept_return, $ac_cv_func_accept_arg1, $ac_cv_func_accept_arg2, $ac_cv_func_accept_arg3 *" >&5 +echo "${ECHO_T}$ac_cv_func_accept_return, $ac_cv_func_accept_arg1, $ac_cv_func_accept_arg2, $ac_cv_func_accept_arg3 *" >&6 + +cat >>confdefs.h <<_ACEOF +#define ACCEPT_TYPE_RETURN $ac_cv_func_accept_return +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define ACCEPT_TYPE_ARG1 $ac_cv_func_accept_arg1 +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define ACCEPT_TYPE_ARG2 $ac_cv_func_accept_arg2 +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define ACCEPT_TYPE_ARG3 $ac_cv_func_accept_arg3 +_ACEOF + + + + + + + + + + + + +for ac_func in setsid select socket sigprocmask strdup strerror strftime strtok asprintf setproctitle +do +as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` +echo "$as_me:$LINENO: checking for $ac_func" >&5 +echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6 +if eval "test \"\${$as_ac_var+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define $ac_func to an innocuous variant, in case declares $ac_func. + For example, HP-UX 11i declares gettimeofday. */ +#define $ac_func innocuous_$ac_func + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef $ac_func + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +{ +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char $ac_func (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_$ac_func) || defined (__stub___$ac_func) +choke me +#else +char (*f) () = $ac_func; +#endif +#ifdef __cplusplus +} +#endif + +int +main () +{ +return f != $ac_func; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + eval "$as_ac_var=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +eval "$as_ac_var=no" +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6 +if test `eval echo '${'$as_ac_var'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + + +PGSQL_INCLUDE_DIR=/usr/local/pgsql/include + +# Check whether --with-pgsql or --without-pgsql was given. +if test "${with_pgsql+set}" = set; then + withval="$with_pgsql" + + case "$withval" in + "" | y | ye | yes | n | no) + { { echo "$as_me:$LINENO: error: *** You must supply an argument to the --with-pgsql option." >&5 +echo "$as_me: error: *** You must supply an argument to the --with-pgsql option." >&2;} + { (exit 1); exit 1; }; } + ;; + esac + PGSQL_INCLUDE_DIR="$withval" + +fi; + + + + +# Check whether --with-pam or --without-pam was given. +if test "${with_pam+set}" = set; then + withval="$with_pam" + +cat >>confdefs.h <<\_ACEOF +#define USE_PAM 1 +_ACEOF + +fi; +if test "$with_pam" = yes ; then + +echo "$as_me:$LINENO: checking for pam_start in -lpam" >&5 +echo $ECHO_N "checking for pam_start in -lpam... $ECHO_C" >&6 +if test "${ac_cv_lib_pam_pam_start+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lpam $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char pam_start (); +int +main () +{ +pam_start (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_pam_pam_start=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_pam_pam_start=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_pam_pam_start" >&5 +echo "${ECHO_T}$ac_cv_lib_pam_pam_start" >&6 +if test $ac_cv_lib_pam_pam_start = yes; then + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBPAM 1 +_ACEOF + + LIBS="-lpam $LIBS" + +else + { { echo "$as_me:$LINENO: error: library 'pam' is required for PAM" >&5 +echo "$as_me: error: library 'pam' is required for PAM" >&2;} + { (exit 1); exit 1; }; } +fi + + +for ac_header in security/pam_appl.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 +else + # Is the header compilable? +echo "$as_me:$LINENO: checking $ac_header usability" >&5 +echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_header_compiler=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6 + +# Is the header present? +echo "$as_me:$LINENO: checking $ac_header presence" >&5 +echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <$ac_header> +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi +rm -f conftest.err conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6 + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 +echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} + ( + cat <<\_ASBOX +## ------------------------------------------ ## +## Report this to the AC_PACKAGE_NAME lists. ## +## ------------------------------------------ ## +_ASBOX + ) | + sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + eval "$as_ac_Header=\$ac_header_preproc" +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 + +fi +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +else + +for ac_header in pam/pam_appl.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 +else + # Is the header compilable? +echo "$as_me:$LINENO: checking $ac_header usability" >&5 +echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_header_compiler=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6 + +# Is the header present? +echo "$as_me:$LINENO: checking $ac_header presence" >&5 +echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <$ac_header> +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi +rm -f conftest.err conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6 + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 +echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} + ( + cat <<\_ASBOX +## ------------------------------------------ ## +## Report this to the AC_PACKAGE_NAME lists. ## +## ------------------------------------------ ## +_ASBOX + ) | + sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + eval "$as_ac_Header=\$ac_header_preproc" +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 + +fi +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +else + { { echo "$as_me:$LINENO: error: header file or is required for PAM." >&5 +echo "$as_me: error: header file or is required for PAM." >&2;} + { (exit 1); exit 1; }; } +fi + +done + +fi + +done + +fi ac_config_headers="$ac_config_headers config.h" diff --git a/configure.in b/configure.in index 7a2fea2..588450a 100644 --- a/configure.in +++ b/configure.in @@ -24,17 +24,36 @@ AC_CHECK_LIB(resolv, main) dnl Checks for header files. AC_HEADER_STDC AC_HEADER_SYS_WAIT -AC_CHECK_HEADERS(fcntl.h unistd.h getopt.h netinet/tcp.h netinet/in.h sys/param.h sys/types.h sys/time.h sys/pstat.h) +AC_CHECK_HEADERS(fcntl.h unistd.h getopt.h netinet/tcp.h netinet/in.h netdb.h sys/param.h sys/types.h sys/socket.h sys/un.h sys/time.h sys/pstat.h) dnl Checks for typedefs, structures, and compiler characteristics. AC_C_CONST AC_TYPE_PID_T AC_HEADER_TIME +dnl Checks for sockadr_storage structure, members and necessary types +AC_CHECK_TYPES([struct sockaddr_storage], [], [], +[#include +#ifdef HAVE_SYS_SOCKET_H +#include +#endif +]) +AC_CHECK_MEMBERS([struct sockaddr_storage.ss_family, + struct sockaddr_storage.__ss_family, + struct sockaddr_storage.ss_len, + struct sockaddr_storage.__ss_len, + struct sockaddr.sa_len], [], [], +[#include +#ifdef HAVE_SYS_SOCKET_H +#include +#endif +]) + dnl Checks for library functions. AC_TYPE_SIGNAL AC_FUNC_VPRINTF AC_FUNC_WAIT3 +AC_FUNC_ACCEPT_ARGTYPES AC_CHECK_FUNCS(setsid select socket sigprocmask strdup strerror strftime strtok asprintf setproctitle) PGSQL_INCLUDE_DIR=/usr/local/pgsql/include @@ -51,6 +70,16 @@ AC_ARG_WITH(pgsql, AC_SUBST(PGSQL_INCLUDE_DIR) +AC_ARG_WITH(pam, + [ --with-pam build with PAM support], + [AC_DEFINE([USE_PAM], 1, [Define to 1 to build with PAM support. (--with-pam)])]) +if test "$with_pam" = yes ; then + AC_CHECK_LIB(pam, pam_start, [], [AC_MSG_ERROR([library 'pam' is required for PAM])]) + AC_CHECK_HEADERS(security/pam_appl.h, [], + [AC_CHECK_HEADERS(pam/pam_appl.h, [], + [AC_MSG_ERROR([header file or is required for PAM.])])]) +fi + AM_CONFIG_HEADER(config.h) AC_OUTPUT(Makefile) diff --git a/main.c b/main.c index b926bf2..81992b4 100644 --- a/main.c +++ b/main.c @@ -97,6 +97,7 @@ int main(int argc, char **argv) { int opt; char conf_file[POOLMAXPATHLEN+1]; + char hba_file[POOLMAXPATHLEN+1]; int i; int pid; @@ -104,11 +105,21 @@ int main(int argc, char **argv) myargv = argv; snprintf(conf_file, sizeof(conf_file), "%s/%s", DEFAULT_CONFIGDIR, POOL_CONF_FILE_NAME); + snprintf(hba_file, sizeof(hba_file), "%s/%s", DEFAULT_CONFIGDIR, HBA_CONF_FILE_NAME); - while ((opt = getopt(argc, argv, "df:hm:ns:")) != -1) + while ((opt = getopt(argc, argv, "a:df:hm:ns:")) != -1) { switch (opt) { + case 'a': /* specify hba configuration file */ + if (!optarg) + { + usage(); + exit(1); + } + strncpy(hba_file, optarg, sizeof(hba_file)); + break; + case 'd': /* debug option */ debug = 1; break; @@ -192,6 +203,10 @@ int main(int argc, char **argv) pool_debug("weight: %ld", weight_master); + /* read pool_hba.conf */ + if (pool_config.enable_pool_hba) + load_hba(hba_file); + /* * if a non-switch argument remains, then it should be either "stop" or "switch" */ @@ -358,11 +373,12 @@ static void usage(void) { fprintf(stderr, "pgpool version %s(%s),\n", VERSION, PGPOOLVERSION); fprintf(stderr, " a generic connection pool/replication/load balance server for PostgreSQL\n\n"); - fprintf(stderr, "usage: pgpool [-f config_file][-n][-d]\n"); - fprintf(stderr, "usage: pgpool [-f config_file] [-m {s[mart]|f[ast]|i[mmediate]}] stop\n"); - fprintf(stderr, "usage: pgpool [-f config_file] [-s {m[aster]|s[econdary]] switch\n"); + fprintf(stderr, "usage: pgpool [-f config_file][-a hba_file][-n][-d]\n"); + fprintf(stderr, "usage: pgpool [-f config_file][-a hba_file] [-m {s[mart]|f[ast]|i[mmediate]}] stop\n"); + fprintf(stderr, "usage: pgpool [-f config_file][-a hba_file] [-s {m[aster]|s[econdary]] switch\n"); fprintf(stderr, "usage: pgpool -h\n"); fprintf(stderr, " config_file default path: %s/%s\n",DEFAULT_CONFIGDIR, POOL_CONF_FILE_NAME); + fprintf(stderr, " hba_file default path: %s/%s\n",DEFAULT_CONFIGDIR, HBA_CONF_FILE_NAME); fprintf(stderr, " -n: don't run in daemon mode. does not detatch control tty\n"); fprintf(stderr, " -d: debug mode. lots of debug information will be printed\n"); fprintf(stderr, " stop: stop pgpool\n"); diff --git a/pgpool.conf.sample b/pgpool.conf.sample index 18c39ba..5fe90af 100644 --- a/pgpool.conf.sample +++ b/pgpool.conf.sample @@ -118,7 +118,19 @@ insert_lock = false # extra leading white space. ignore_leading_white_space = false +# - What to Log - + # If true, print all statements to the log. Like the log_statement option # to PostgreSQL, this allows for observing queries without engaging in full # debugging. log_statement = false + +# If true, incoming connections will be printed to the log. +log_connections = false + +# - HBA - + +# If true, use pool_hba.conf for client authentication. In pgpool 3.2, +# the default value is false. This parameter is planned to be deleted +# in pgpool 3.3, and pool_hba.conf will always be used. +enable_pool_hba = false diff --git a/pool.h b/pool.h index 5d23eab..b931e26 100644 --- a/pool.h +++ b/pool.h @@ -28,24 +28,11 @@ #include "config.h" #include "pool_signal.h" +#include "pool_type.h" +#include "pool_list.h" #include #include - -/* typdefs */ -#ifndef __cplusplus -#ifndef bool -typedef char bool; -#endif - -#ifndef true -#define true ((bool) 1) -#endif - -#ifndef false -#define false ((bool) 0) -#endif - -#endif +#include /* undef this if you have problems with non blocking accept() */ #define NONE_BLOCK @@ -54,6 +41,7 @@ typedef char bool; /* configuration file name */ #define POOL_CONF_FILE_NAME "pgpool.conf" +#define HBA_CONF_FILE_NAME "pool_hba.conf" /* pid file directory */ #define DEFAULT_LOGDIR "/tmp" @@ -175,6 +163,8 @@ typedef struct { int num_servers; /* number of PostgreSQL servers */ int server_status[MAX_CONNECTION_SLOTS]; /* server status 0:unused, 1:up, 2:down */ int log_statement; /* 0:false, 1: true - logs all SQL statements */ + int log_connections; /* 0:false, 1:true - logs incoming connections */ + int enable_pool_hba; /* 0:false, 1:true - enables pool_hba.conf file authentication */ } POOL_CONFIG; #define MAX_PASSWORD_SIZE 1024 @@ -227,6 +217,19 @@ typedef struct { int no_forward; /* if non 0, do not write to frontend */ + /* + * frontend info needed for hba + */ + int protoVersion; + SockAddr raddr; + UserAuth auth_method; + char *auth_arg; + char *database; + char *username; +#ifdef USE_SSL + bool ssl; +#endif + } POOL_CONNECTION; /* @@ -362,10 +365,14 @@ extern bool update_process_title; extern char **save_ps_display_args(int argc, char **argv); extern void init_ps_display(const char *username, const char *dbname, - const char *host_info, const char *initial_str); + const char *host_info, const char *initial_str); extern void set_ps_display(const char *activity, bool force); extern const char *get_ps_display(int *displen); +/* pool_hba.c */ +extern void load_hba(char *hbapath); +extern void ClientAuthentication(POOL_CONNECTION *frontend); + #endif /* POOL_H */ diff --git a/pool_config.c b/pool_config.c index 2fbe38b..2200391 100644 --- a/pool_config.c +++ b/pool_config.c @@ -1,32 +1,93 @@ -/* A lexical scanner generated by flex */ -/* Scanner skeleton version: - * $Header$ - */ +#line 3 "pool_config.c" + +#define YY_INT_ALIGNED short int + +/* A lexical scanner generated by flex */ #define FLEX_SCANNER #define YY_FLEX_MAJOR_VERSION 2 #define YY_FLEX_MINOR_VERSION 5 +#define YY_FLEX_SUBMINOR_VERSION 33 +#if YY_FLEX_SUBMINOR_VERSION > 0 +#define FLEX_BETA +#endif +/* First, we deal with platform-specific or compiler-specific issues. */ + +/* begin standard C headers. */ #include -#include +#include +#include +#include + +/* end standard C headers. */ + +/* flex integer type definitions */ +#ifndef FLEXINT_H +#define FLEXINT_H -/* cfront 1.2 defines "c_plusplus" instead of "__cplusplus" */ -#ifdef c_plusplus -#ifndef __cplusplus -#define __cplusplus +/* C99 systems have . Non-C99 systems may or may not. */ + +#if __STDC_VERSION__ >= 199901L + +/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h, + * if you want the limit (max/min) macros for int types. + */ +#ifndef __STDC_LIMIT_MACROS +#define __STDC_LIMIT_MACROS 1 +#endif + +#include +typedef int8_t flex_int8_t; +typedef uint8_t flex_uint8_t; +typedef int16_t flex_int16_t; +typedef uint16_t flex_uint16_t; +typedef int32_t flex_int32_t; +typedef uint32_t flex_uint32_t; +#else +typedef signed char flex_int8_t; +typedef short int flex_int16_t; +typedef int flex_int32_t; +typedef unsigned char flex_uint8_t; +typedef unsigned short int flex_uint16_t; +typedef unsigned int flex_uint32_t; +#endif /* ! C99 */ + +/* Limits of integral types. */ +#ifndef INT8_MIN +#define INT8_MIN (-128) +#endif +#ifndef INT16_MIN +#define INT16_MIN (-32767-1) +#endif +#ifndef INT32_MIN +#define INT32_MIN (-2147483647-1) +#endif +#ifndef INT8_MAX +#define INT8_MAX (127) +#endif +#ifndef INT16_MAX +#define INT16_MAX (32767) +#endif +#ifndef INT32_MAX +#define INT32_MAX (2147483647) +#endif +#ifndef UINT8_MAX +#define UINT8_MAX (255U) +#endif +#ifndef UINT16_MAX +#define UINT16_MAX (65535U) #endif +#ifndef UINT32_MAX +#define UINT32_MAX (4294967295U) #endif +#endif /* ! FLEXINT_H */ #ifdef __cplusplus -#include - -/* Use prototypes in function declarations. */ -#define YY_USE_PROTOS - /* The "const" storage-class-modifier is valid. */ #define YY_USE_CONST @@ -34,34 +95,17 @@ #if __STDC__ -#define YY_USE_PROTOS #define YY_USE_CONST #endif /* __STDC__ */ #endif /* ! __cplusplus */ -#ifdef __TURBOC__ - #pragma warn -rch - #pragma warn -use -#include -#include -#define YY_USE_CONST -#define YY_USE_PROTOS -#endif - #ifdef YY_USE_CONST #define yyconst const #else #define yyconst #endif - -#ifdef YY_USE_PROTOS -#define YY_PROTO(proto) proto -#else -#define YY_PROTO(proto) () -#endif - /* Returned upon end-of-file. */ #define YY_NULL 0 @@ -76,71 +120,75 @@ * but we do it the disgusting crufty way forced on us by the ()-less * definition of BEGIN. */ -#define BEGIN yy_start = 1 + 2 * +#define BEGIN (yy_start) = 1 + 2 * /* Translate the current start state into a value that can be later handed * to BEGIN to return to the state. The YYSTATE alias is for lex * compatibility. */ -#define YY_START ((yy_start - 1) / 2) +#define YY_START (((yy_start) - 1) / 2) #define YYSTATE YY_START /* Action number for EOF rule of a given start state. */ #define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1) /* Special action meaning "start processing a new file". */ -#define YY_NEW_FILE yyrestart( yyin ) +#define YY_NEW_FILE yyrestart(yyin ) #define YY_END_OF_BUFFER_CHAR 0 /* Size of default input buffer. */ +#ifndef YY_BUF_SIZE #define YY_BUF_SIZE 16384 +#endif +/* The state buf must be large enough to hold one state per character in the main buffer. + */ +#define YY_STATE_BUF_SIZE ((YY_BUF_SIZE + 2) * sizeof(yy_state_type)) + +#ifndef YY_TYPEDEF_YY_BUFFER_STATE +#define YY_TYPEDEF_YY_BUFFER_STATE typedef struct yy_buffer_state *YY_BUFFER_STATE; +#endif extern int yyleng; + extern FILE *yyin, *yyout; #define EOB_ACT_CONTINUE_SCAN 0 #define EOB_ACT_END_OF_FILE 1 #define EOB_ACT_LAST_MATCH 2 -/* The funky do-while in the following #define is used to turn the definition - * int a single C statement (which needs a semi-colon terminator). This - * avoids problems with code like: - * - * if ( condition_holds ) - * yyless( 5 ); - * else - * do_something_else(); - * - * Prior to using the do-while the compiler would get upset at the - * "else" because it interpreted the "if" statement as being all - * done when it reached the ';' after the yyless() call. - */ - -/* Return all but the first 'n' matched characters back to the input stream. */ - + #define YY_LESS_LINENO(n) + +/* Return all but the first "n" matched characters back to the input stream. */ #define yyless(n) \ do \ { \ /* Undo effects of setting up yytext. */ \ - *yy_cp = yy_hold_char; \ + int yyless_macro_arg = (n); \ + YY_LESS_LINENO(yyless_macro_arg);\ + *yy_cp = (yy_hold_char); \ YY_RESTORE_YY_MORE_OFFSET \ - yy_c_buf_p = yy_cp = yy_bp + n - YY_MORE_ADJ; \ + (yy_c_buf_p) = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \ YY_DO_BEFORE_ACTION; /* set up yytext again */ \ } \ while ( 0 ) -#define unput(c) yyunput( c, yytext_ptr ) +#define unput(c) yyunput( c, (yytext_ptr) ) /* The following is because we cannot portably get our hands on size_t * (without autoconf's help, which isn't available because we want * flex-generated scanners to compile on their own). */ -typedef unsigned int yy_size_t; +#ifndef YY_TYPEDEF_YY_SIZE_T +#define YY_TYPEDEF_YY_SIZE_T +typedef unsigned int yy_size_t; +#endif +#ifndef YY_STRUCT_YY_BUFFER_STATE +#define YY_STRUCT_YY_BUFFER_STATE struct yy_buffer_state { FILE *yy_input_file; @@ -177,12 +225,16 @@ struct yy_buffer_state */ int yy_at_bol; + int yy_bs_lineno; /**< The line count. */ + int yy_bs_column; /**< The column count. */ + /* Whether to try to fill the input buffer when we reach the * end of it. */ int yy_fill_buffer; int yy_buffer_status; + #define YY_BUFFER_NEW 0 #define YY_BUFFER_NORMAL 1 /* When an EOF's been seen but there's still some text to process @@ -196,28 +248,38 @@ struct yy_buffer_state * just pointing yyin at a new input file. */ #define YY_BUFFER_EOF_PENDING 2 + }; +#endif /* !YY_STRUCT_YY_BUFFER_STATE */ -static YY_BUFFER_STATE yy_current_buffer = 0; +/* Stack of input buffers. */ +static size_t yy_buffer_stack_top = 0; /**< index of top of stack. */ +static size_t yy_buffer_stack_max = 0; /**< capacity of stack. */ +static YY_BUFFER_STATE * yy_buffer_stack = 0; /**< Stack as an array. */ /* We provide macros for accessing buffer states in case in the * future we want to put the buffer states in a more general * "scanner state". + * + * Returns the top of the stack, or NULL. */ -#define YY_CURRENT_BUFFER yy_current_buffer +#define YY_CURRENT_BUFFER ( (yy_buffer_stack) \ + ? (yy_buffer_stack)[(yy_buffer_stack_top)] \ + : NULL) +/* Same as previous macro, but useful when we know that the buffer stack is not + * NULL or when we need an lvalue. For internal use only. + */ +#define YY_CURRENT_BUFFER_LVALUE (yy_buffer_stack)[(yy_buffer_stack_top)] /* yy_hold_char holds the character lost when yytext is formed. */ static char yy_hold_char; - static int yy_n_chars; /* number of characters read into yy_ch_buf */ - - int yyleng; /* Points to current character in buffer. */ static char *yy_c_buf_p = (char *) 0; -static int yy_init = 1; /* whether we need to initialize */ +static int yy_init = 0; /* whether we need to initialize */ static int yy_start = 0; /* start state number */ /* Flag which is used to allow yywrap()'s to do buffer switches @@ -225,69 +287,95 @@ static int yy_start = 0; /* start state number */ */ static int yy_did_buffer_switch_on_eof; -void yyrestart YY_PROTO(( FILE *input_file )); +void yyrestart (FILE *input_file ); +void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer ); +YY_BUFFER_STATE yy_create_buffer (FILE *file,int size ); +void yy_delete_buffer (YY_BUFFER_STATE b ); +void yy_flush_buffer (YY_BUFFER_STATE b ); +void yypush_buffer_state (YY_BUFFER_STATE new_buffer ); +void yypop_buffer_state (void ); + +static void yyensure_buffer_stack (void ); +static void yy_load_buffer_state (void ); +static void yy_init_buffer (YY_BUFFER_STATE b,FILE *file ); -void yy_switch_to_buffer YY_PROTO(( YY_BUFFER_STATE new_buffer )); -void yy_load_buffer_state YY_PROTO(( void )); -YY_BUFFER_STATE yy_create_buffer YY_PROTO(( FILE *file, int size )); -void yy_delete_buffer YY_PROTO(( YY_BUFFER_STATE b )); -void yy_init_buffer YY_PROTO(( YY_BUFFER_STATE b, FILE *file )); -void yy_flush_buffer YY_PROTO(( YY_BUFFER_STATE b )); -#define YY_FLUSH_BUFFER yy_flush_buffer( yy_current_buffer ) +#define YY_FLUSH_BUFFER yy_flush_buffer(YY_CURRENT_BUFFER ) -YY_BUFFER_STATE yy_scan_buffer YY_PROTO(( char *base, yy_size_t size )); -YY_BUFFER_STATE yy_scan_string YY_PROTO(( yyconst char *yy_str )); -YY_BUFFER_STATE yy_scan_bytes YY_PROTO(( yyconst char *bytes, int len )); +YY_BUFFER_STATE yy_scan_buffer (char *base,yy_size_t size ); +YY_BUFFER_STATE yy_scan_string (yyconst char *yy_str ); +YY_BUFFER_STATE yy_scan_bytes (yyconst char *bytes,int len ); -static void *yy_flex_alloc YY_PROTO(( yy_size_t )); -static void *yy_flex_realloc YY_PROTO(( void *, yy_size_t )); -static void yy_flex_free YY_PROTO(( void * )); +void *yyalloc (yy_size_t ); +void *yyrealloc (void *,yy_size_t ); +void yyfree (void * ); #define yy_new_buffer yy_create_buffer #define yy_set_interactive(is_interactive) \ { \ - if ( ! yy_current_buffer ) \ - yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \ - yy_current_buffer->yy_is_interactive = is_interactive; \ + if ( ! YY_CURRENT_BUFFER ){ \ + yyensure_buffer_stack (); \ + YY_CURRENT_BUFFER_LVALUE = \ + yy_create_buffer(yyin,YY_BUF_SIZE ); \ + } \ + YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \ } #define yy_set_bol(at_bol) \ { \ - if ( ! yy_current_buffer ) \ - yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \ - yy_current_buffer->yy_at_bol = at_bol; \ + if ( ! YY_CURRENT_BUFFER ){\ + yyensure_buffer_stack (); \ + YY_CURRENT_BUFFER_LVALUE = \ + yy_create_buffer(yyin,YY_BUF_SIZE ); \ + } \ + YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \ } -#define YY_AT_BOL() (yy_current_buffer->yy_at_bol) +#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol) +/* Begin user sect3 */ -#define yywrap() 1 +#define yywrap(n) 1 #define YY_SKIP_YYWRAP + typedef unsigned char YY_CHAR; + FILE *yyin = (FILE *) 0, *yyout = (FILE *) 0; + typedef int yy_state_type; + +extern int yylineno; + +int yylineno = 1; + extern char *yytext; #define yytext_ptr yytext -static yy_state_type yy_get_previous_state YY_PROTO(( void )); -static yy_state_type yy_try_NUL_trans YY_PROTO(( yy_state_type current_state )); -static int yy_get_next_buffer YY_PROTO(( void )); -static void yy_fatal_error YY_PROTO(( yyconst char msg[] )); +static yy_state_type yy_get_previous_state (void ); +static yy_state_type yy_try_NUL_trans (yy_state_type current_state ); +static int yy_get_next_buffer (void ); +static void yy_fatal_error (yyconst char msg[] ); /* Done after the current pattern has been matched and before the * corresponding action - sets up yytext. */ #define YY_DO_BEFORE_ACTION \ - yytext_ptr = yy_bp; \ - yyleng = (int) (yy_cp - yy_bp); \ - yy_hold_char = *yy_cp; \ + (yytext_ptr) = yy_bp; \ + yyleng = (size_t) (yy_cp - yy_bp); \ + (yy_hold_char) = *yy_cp; \ *yy_cp = '\0'; \ - yy_c_buf_p = yy_cp; + (yy_c_buf_p) = yy_cp; #define YY_NUM_RULES 11 #define YY_END_OF_BUFFER 12 -static yyconst short int yy_accept[38] = +/* This struct is not used in this scanner, + but its presence is necessary. */ +struct yy_trans_info + { + flex_int32_t yy_verify; + flex_int32_t yy_nxt; + }; +static yyconst flex_int16_t yy_accept[38] = { 0, 0, 0, 12, 10, 2, 1, 10, 10, 10, 8, 7, 7, 9, 4, 2, 0, 3, 0, 5, 0, @@ -295,7 +383,7 @@ static yyconst short int yy_accept[38] = 5, 0, 0, 8, 7, 6, 0 } ; -static yyconst int yy_ec[256] = +static yyconst flex_int32_t yy_ec[256] = { 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, @@ -327,13 +415,13 @@ static yyconst int yy_ec[256] = 15, 15, 15, 15, 15 } ; -static yyconst int yy_meta[19] = +static yyconst flex_int32_t yy_meta[19] = { 0, 1, 1, 2, 1, 1, 1, 3, 3, 3, 4, 4, 1, 5, 4, 3, 1, 3, 3 } ; -static yyconst short int yy_base[45] = +static yyconst flex_int16_t yy_base[45] = { 0, 0, 0, 61, 86, 58, 86, 55, 14, 23, 43, 10, 46, 86, 28, 47, 40, 86, 16, 86, 22, @@ -342,7 +430,7 @@ static yyconst short int yy_base[45] = 70, 75, 77, 80 } ; -static yyconst short int yy_def[45] = +static yyconst flex_int16_t yy_def[45] = { 0, 37, 1, 37, 37, 37, 37, 38, 39, 37, 40, 9, 9, 37, 41, 37, 38, 37, 39, 37, 42, @@ -351,7 +439,7 @@ static yyconst short int yy_def[45] = 37, 37, 37, 37 } ; -static yyconst short int yy_nxt[105] = +static yyconst flex_int16_t yy_nxt[105] = { 0, 4, 5, 6, 7, 8, 9, 9, 10, 4, 11, 12, 13, 14, 14, 14, 4, 14, 14, 19, 23, @@ -367,7 +455,7 @@ static yyconst short int yy_nxt[105] = 37, 37, 37, 37 } ; -static yyconst short int yy_chk[105] = +static yyconst flex_int16_t yy_chk[105] = { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 8, 11, @@ -386,6 +474,9 @@ static yyconst short int yy_chk[105] = static yy_state_type yy_last_accepting_state; static char *yy_last_accepting_cpos; +extern int yy_flex_debug; +int yy_flex_debug = 0; + /* The intent behind this definition is that it'll catch * any uses of REJECT which flex missed. */ @@ -395,7 +486,6 @@ static char *yy_last_accepting_cpos; #define YY_RESTORE_YY_MORE_OFFSET char *yytext; #line 1 "pool_config.l" -#define INITIAL 0 /* -*-pgsql-c-*- */ /* * @@ -447,9 +537,23 @@ typedef enum { static char *extract_string(char *value, POOL_TOKEN token); static char **extract_string_tokens(char *str, char *delim, int *n); -#define YY_NEVER_INTERACTIVE 1 -#define YY_NO_UNPUT 1 -#line 453 "pool_config.c" +#line 541 "pool_config.c" + +#define INITIAL 0 + +#ifndef YY_NO_UNISTD_H +/* Special case for "unistd.h", since it is non-ANSI. We include it way + * down here because we want the user's section 1 to have been scanned first. + * The user has a chance to override it with an option. + */ +#include +#endif + +#ifndef YY_EXTRA_TYPE +#define YY_EXTRA_TYPE void * +#endif + +static int yy_init_globals (void ); /* Macros after this point can all be overridden by user definitions in * section 1. @@ -457,65 +561,28 @@ static char **extract_string_tokens(char *str, char *delim, int *n); #ifndef YY_SKIP_YYWRAP #ifdef __cplusplus -extern "C" int yywrap YY_PROTO(( void )); +extern "C" int yywrap (void ); #else -extern int yywrap YY_PROTO(( void )); -#endif +extern int yywrap (void ); #endif - -#ifndef YY_NO_UNPUT -static void yyunput YY_PROTO(( int c, char *buf_ptr )); #endif #ifndef yytext_ptr -static void yy_flex_strncpy YY_PROTO(( char *, yyconst char *, int )); +static void yy_flex_strncpy (char *,yyconst char *,int ); #endif #ifdef YY_NEED_STRLEN -static int yy_flex_strlen YY_PROTO(( yyconst char * )); +static int yy_flex_strlen (yyconst char * ); #endif #ifndef YY_NO_INPUT + #ifdef __cplusplus -static int yyinput YY_PROTO(( void )); +static int yyinput (void ); #else -static int input YY_PROTO(( void )); -#endif +static int input (void ); #endif -#if YY_STACK_USED -static int yy_start_stack_ptr = 0; -static int yy_start_stack_depth = 0; -static int *yy_start_stack = 0; -#ifndef YY_NO_PUSH_STATE -static void yy_push_state YY_PROTO(( int new_state )); -#endif -#ifndef YY_NO_POP_STATE -static void yy_pop_state YY_PROTO(( void )); -#endif -#ifndef YY_NO_TOP_STATE -static int yy_top_state YY_PROTO(( void )); -#endif - -#else -#define YY_NO_PUSH_STATE 1 -#define YY_NO_POP_STATE 1 -#define YY_NO_TOP_STATE 1 -#endif - -#ifdef YY_MALLOC_DECL -YY_MALLOC_DECL -#else -#if __STDC__ -#ifndef __cplusplus -#include -#endif -#else -/* Just try to get by without declaring the routines. This will fail - * miserably on non-ANSI systems for which sizeof(size_t) != sizeof(int) - * or sizeof(void*) != sizeof(int). - */ -#endif #endif /* Amount of stuff to slurp up with each read. */ @@ -524,7 +591,6 @@ YY_MALLOC_DECL #endif /* Copy whatever the last rule matched to the standard output. */ - #ifndef ECHO /* This used to be an fputs(), but since the string might contain NUL's, * we now use fwrite(). @@ -537,9 +603,10 @@ YY_MALLOC_DECL */ #ifndef YY_INPUT #define YY_INPUT(buf,result,max_size) \ - if ( yy_current_buffer->yy_is_interactive ) \ + if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \ { \ - int c = '*', n; \ + int c = '*'; \ + size_t n; \ for ( n = 0; n < max_size && \ (c = getc( yyin )) != EOF && c != '\n'; ++n ) \ buf[n] = (char) c; \ @@ -549,9 +616,22 @@ YY_MALLOC_DECL YY_FATAL_ERROR( "input in flex scanner failed" ); \ result = n; \ } \ - else if ( ((result = fread( buf, 1, max_size, yyin )) == 0) \ - && ferror( yyin ) ) \ - YY_FATAL_ERROR( "input in flex scanner failed" ); + else \ + { \ + errno=0; \ + while ( (result = fread(buf, 1, max_size, yyin))==0 && ferror(yyin)) \ + { \ + if( errno != EINTR) \ + { \ + YY_FATAL_ERROR( "input in flex scanner failed" ); \ + break; \ + } \ + errno=0; \ + clearerr(yyin); \ + } \ + }\ +\ + #endif /* No semi-colon after return; correct usage is to write "yyterminate();" - @@ -572,12 +652,18 @@ YY_MALLOC_DECL #define YY_FATAL_ERROR(msg) yy_fatal_error( msg ) #endif +/* end tables serialization structures and prototypes */ + /* Default declaration of generated scanner - a define so the user can * easily add parameters. */ #ifndef YY_DECL -#define YY_DECL int yylex YY_PROTO(( void )) -#endif +#define YY_DECL_IS_OURS 1 + +extern int yylex (void); + +#define YY_DECL int yylex (void) +#endif /* !YY_DECL */ /* Code executed at the beginning of each rule, after yytext and yyleng * have been set up. @@ -594,27 +680,29 @@ YY_MALLOC_DECL #define YY_RULE_SETUP \ YY_USER_ACTION +/** The main scanner function which does all the work. + */ YY_DECL - { +{ register yy_state_type yy_current_state; - register char *yy_cp = NULL, *yy_bp = NULL; + register char *yy_cp, *yy_bp; register int yy_act; - + #line 77 "pool_config.l" -#line 607 "pool_config.c" +#line 695 "pool_config.c" - if ( yy_init ) + if ( !(yy_init) ) { - yy_init = 0; + (yy_init) = 1; #ifdef YY_USER_INIT YY_USER_INIT; #endif - if ( ! yy_start ) - yy_start = 1; /* first start state */ + if ( ! (yy_start) ) + (yy_start) = 1; /* first start state */ if ( ! yyin ) yyin = stdin; @@ -622,34 +710,36 @@ YY_DECL if ( ! yyout ) yyout = stdout; - if ( ! yy_current_buffer ) - yy_current_buffer = - yy_create_buffer( yyin, YY_BUF_SIZE ); + if ( ! YY_CURRENT_BUFFER ) { + yyensure_buffer_stack (); + YY_CURRENT_BUFFER_LVALUE = + yy_create_buffer(yyin,YY_BUF_SIZE ); + } - yy_load_buffer_state(); + yy_load_buffer_state( ); } while ( 1 ) /* loops until end-of-file is reached */ { - yy_cp = yy_c_buf_p; + yy_cp = (yy_c_buf_p); /* Support of yytext. */ - *yy_cp = yy_hold_char; + *yy_cp = (yy_hold_char); /* yy_bp points to the position in yy_ch_buf of the start of * the current run. */ yy_bp = yy_cp; - yy_current_state = yy_start; + yy_current_state = (yy_start); yy_match: do { register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)]; if ( yy_accept[yy_current_state] ) { - yy_last_accepting_state = yy_current_state; - yy_last_accepting_cpos = yy_cp; + (yy_last_accepting_state) = yy_current_state; + (yy_last_accepting_cpos) = yy_cp; } while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { @@ -660,33 +750,28 @@ yy_match: yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; ++yy_cp; } - while ( yy_base[yy_current_state] != 86 ); + while ( yy_current_state != 37 ); + yy_cp = (yy_last_accepting_cpos); + yy_current_state = (yy_last_accepting_state); yy_find_action: yy_act = yy_accept[yy_current_state]; - if ( yy_act == 0 ) - { /* have to back up */ - yy_cp = yy_last_accepting_cpos; - yy_current_state = yy_last_accepting_state; - yy_act = yy_accept[yy_current_state]; - } YY_DO_BEFORE_ACTION; - do_action: /* This label is used only to access EOF actions. */ - switch ( yy_act ) { /* beginning of action switch */ case 0: /* must back up */ /* undo the effects of YY_DO_BEFORE_ACTION */ - *yy_cp = yy_hold_char; - yy_cp = yy_last_accepting_cpos; - yy_current_state = yy_last_accepting_state; + *yy_cp = (yy_hold_char); + yy_cp = (yy_last_accepting_cpos); + yy_current_state = (yy_last_accepting_state); goto yy_find_action; case 1: +/* rule 1 can match eol */ YY_RULE_SETUP #line 79 "pool_config.l" Lineno++; return POOL_EOL; @@ -697,8 +782,8 @@ YY_RULE_SETUP /* eat whitespace */ YY_BREAK case 3: -*yy_cp = yy_hold_char; /* undo effects of setting up yytext */ -yy_c_buf_p = yy_cp -= 1; +*yy_cp = (yy_hold_char); /* undo effects of setting up yytext */ +(yy_c_buf_p) = yy_cp -= 1; YY_DO_BEFORE_ACTION; /* set up yytext again */ YY_RULE_SETUP #line 81 "pool_config.l" @@ -744,33 +829,33 @@ YY_RULE_SETUP #line 92 "pool_config.l" ECHO; YY_BREAK -#line 748 "pool_config.c" +#line 833 "pool_config.c" case YY_STATE_EOF(INITIAL): yyterminate(); case YY_END_OF_BUFFER: { /* Amount of text matched not including the EOB char. */ - int yy_amount_of_matched_text = (int) (yy_cp - yytext_ptr) - 1; + int yy_amount_of_matched_text = (int) (yy_cp - (yytext_ptr)) - 1; /* Undo the effects of YY_DO_BEFORE_ACTION. */ - *yy_cp = yy_hold_char; + *yy_cp = (yy_hold_char); YY_RESTORE_YY_MORE_OFFSET - if ( yy_current_buffer->yy_buffer_status == YY_BUFFER_NEW ) + if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW ) { /* We're scanning a new file or input source. It's * possible that this happened because the user * just pointed yyin at a new source and called * yylex(). If so, then we have to assure - * consistency between yy_current_buffer and our + * consistency between YY_CURRENT_BUFFER and our * globals. Here is the right place to do so, because * this is the first action (other than possibly a * back-up) that will match for the new input source. */ - yy_n_chars = yy_current_buffer->yy_n_chars; - yy_current_buffer->yy_input_file = yyin; - yy_current_buffer->yy_buffer_status = YY_BUFFER_NORMAL; + (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; + YY_CURRENT_BUFFER_LVALUE->yy_input_file = yyin; + YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL; } /* Note that here we test for yy_c_buf_p "<=" to the position @@ -780,13 +865,13 @@ case YY_STATE_EOF(INITIAL): * end-of-buffer state). Contrast this with the test * in input(). */ - if ( yy_c_buf_p <= &yy_current_buffer->yy_ch_buf[yy_n_chars] ) + if ( (yy_c_buf_p) <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] ) { /* This was really a NUL. */ yy_state_type yy_next_state; - yy_c_buf_p = yytext_ptr + yy_amount_of_matched_text; + (yy_c_buf_p) = (yytext_ptr) + yy_amount_of_matched_text; - yy_current_state = yy_get_previous_state(); + yy_current_state = yy_get_previous_state( ); /* Okay, we're now positioned to make the NUL * transition. We couldn't have @@ -799,30 +884,31 @@ case YY_STATE_EOF(INITIAL): yy_next_state = yy_try_NUL_trans( yy_current_state ); - yy_bp = yytext_ptr + YY_MORE_ADJ; + yy_bp = (yytext_ptr) + YY_MORE_ADJ; if ( yy_next_state ) { /* Consume the NUL. */ - yy_cp = ++yy_c_buf_p; + yy_cp = ++(yy_c_buf_p); yy_current_state = yy_next_state; goto yy_match; } else { - yy_cp = yy_c_buf_p; + yy_cp = (yy_last_accepting_cpos); + yy_current_state = (yy_last_accepting_state); goto yy_find_action; } } - else switch ( yy_get_next_buffer() ) + else switch ( yy_get_next_buffer( ) ) { case EOB_ACT_END_OF_FILE: { - yy_did_buffer_switch_on_eof = 0; + (yy_did_buffer_switch_on_eof) = 0; - if ( yywrap() ) + if ( yywrap( ) ) { /* Note: because we've taken care in * yy_get_next_buffer() to have set up @@ -833,7 +919,7 @@ case YY_STATE_EOF(INITIAL): * YY_NULL, it'll still work - another * YY_NULL will get returned. */ - yy_c_buf_p = yytext_ptr + YY_MORE_ADJ; + (yy_c_buf_p) = (yytext_ptr) + YY_MORE_ADJ; yy_act = YY_STATE_EOF(YY_START); goto do_action; @@ -841,30 +927,30 @@ case YY_STATE_EOF(INITIAL): else { - if ( ! yy_did_buffer_switch_on_eof ) + if ( ! (yy_did_buffer_switch_on_eof) ) YY_NEW_FILE; } break; } case EOB_ACT_CONTINUE_SCAN: - yy_c_buf_p = - yytext_ptr + yy_amount_of_matched_text; + (yy_c_buf_p) = + (yytext_ptr) + yy_amount_of_matched_text; - yy_current_state = yy_get_previous_state(); + yy_current_state = yy_get_previous_state( ); - yy_cp = yy_c_buf_p; - yy_bp = yytext_ptr + YY_MORE_ADJ; + yy_cp = (yy_c_buf_p); + yy_bp = (yytext_ptr) + YY_MORE_ADJ; goto yy_match; case EOB_ACT_LAST_MATCH: - yy_c_buf_p = - &yy_current_buffer->yy_ch_buf[yy_n_chars]; + (yy_c_buf_p) = + &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)]; - yy_current_state = yy_get_previous_state(); + yy_current_state = yy_get_previous_state( ); - yy_cp = yy_c_buf_p; - yy_bp = yytext_ptr + YY_MORE_ADJ; + yy_cp = (yy_c_buf_p); + yy_bp = (yytext_ptr) + YY_MORE_ADJ; goto yy_find_action; } break; @@ -875,8 +961,7 @@ case YY_STATE_EOF(INITIAL): "fatal flex scanner internal error--no action found" ); } /* end of action switch */ } /* end of scanning one token */ - } /* end of yylex */ - +} /* end of yylex */ /* yy_get_next_buffer - try to read in a new buffer * @@ -885,21 +970,20 @@ case YY_STATE_EOF(INITIAL): * EOB_ACT_CONTINUE_SCAN - continue scanning from current position * EOB_ACT_END_OF_FILE - end of file */ - -static int yy_get_next_buffer() - { - register char *dest = yy_current_buffer->yy_ch_buf; - register char *source = yytext_ptr; +static int yy_get_next_buffer (void) +{ + register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf; + register char *source = (yytext_ptr); register int number_to_move, i; int ret_val; - if ( yy_c_buf_p > &yy_current_buffer->yy_ch_buf[yy_n_chars + 1] ) + if ( (yy_c_buf_p) > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] ) YY_FATAL_ERROR( "fatal flex scanner internal error--end of buffer missed" ); - if ( yy_current_buffer->yy_fill_buffer == 0 ) + if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 ) { /* Don't try to fill the buffer, so this is an EOF. */ - if ( yy_c_buf_p - yytext_ptr - YY_MORE_ADJ == 1 ) + if ( (yy_c_buf_p) - (yytext_ptr) - YY_MORE_ADJ == 1 ) { /* We matched a single character, the EOB, so * treat this as a final EOF. @@ -919,34 +1003,30 @@ static int yy_get_next_buffer() /* Try to read more data. */ /* First move last chars to start of buffer. */ - number_to_move = (int) (yy_c_buf_p - yytext_ptr) - 1; + number_to_move = (int) ((yy_c_buf_p) - (yytext_ptr)) - 1; for ( i = 0; i < number_to_move; ++i ) *(dest++) = *(source++); - if ( yy_current_buffer->yy_buffer_status == YY_BUFFER_EOF_PENDING ) + if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING ) /* don't do the read, it's not guaranteed to return an EOF, * just force an EOF */ - yy_current_buffer->yy_n_chars = yy_n_chars = 0; + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars) = 0; else { - int num_to_read = - yy_current_buffer->yy_buf_size - number_to_move - 1; + int num_to_read = + YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1; while ( num_to_read <= 0 ) { /* Not enough room in the buffer - grow it. */ -#ifdef YY_USES_REJECT - YY_FATAL_ERROR( -"input buffer overflow, can't enlarge buffer because scanner uses REJECT" ); -#else /* just a shorter name for the current buffer */ - YY_BUFFER_STATE b = yy_current_buffer; + YY_BUFFER_STATE b = YY_CURRENT_BUFFER; int yy_c_buf_p_offset = - (int) (yy_c_buf_p - b->yy_ch_buf); + (int) ((yy_c_buf_p) - b->yy_ch_buf); if ( b->yy_is_our_buffer ) { @@ -959,8 +1039,7 @@ static int yy_get_next_buffer() b->yy_ch_buf = (char *) /* Include room in for 2 EOB chars. */ - yy_flex_realloc( (void *) b->yy_ch_buf, - b->yy_buf_size + 2 ); + yyrealloc((void *) b->yy_ch_buf,b->yy_buf_size + 2 ); } else /* Can't grow it, we don't own it. */ @@ -970,35 +1049,35 @@ static int yy_get_next_buffer() YY_FATAL_ERROR( "fatal error - scanner input buffer overflow" ); - yy_c_buf_p = &b->yy_ch_buf[yy_c_buf_p_offset]; + (yy_c_buf_p) = &b->yy_ch_buf[yy_c_buf_p_offset]; - num_to_read = yy_current_buffer->yy_buf_size - + num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1; -#endif + } if ( num_to_read > YY_READ_BUF_SIZE ) num_to_read = YY_READ_BUF_SIZE; /* Read in more data. */ - YY_INPUT( (&yy_current_buffer->yy_ch_buf[number_to_move]), - yy_n_chars, num_to_read ); + YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]), + (yy_n_chars), num_to_read ); - yy_current_buffer->yy_n_chars = yy_n_chars; + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); } - if ( yy_n_chars == 0 ) + if ( (yy_n_chars) == 0 ) { if ( number_to_move == YY_MORE_ADJ ) { ret_val = EOB_ACT_END_OF_FILE; - yyrestart( yyin ); + yyrestart(yyin ); } else { ret_val = EOB_ACT_LAST_MATCH; - yy_current_buffer->yy_buffer_status = + YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_EOF_PENDING; } } @@ -1006,32 +1085,31 @@ static int yy_get_next_buffer() else ret_val = EOB_ACT_CONTINUE_SCAN; - yy_n_chars += number_to_move; - yy_current_buffer->yy_ch_buf[yy_n_chars] = YY_END_OF_BUFFER_CHAR; - yy_current_buffer->yy_ch_buf[yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR; + (yy_n_chars) += number_to_move; + YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] = YY_END_OF_BUFFER_CHAR; + YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] = YY_END_OF_BUFFER_CHAR; - yytext_ptr = &yy_current_buffer->yy_ch_buf[0]; + (yytext_ptr) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0]; return ret_val; - } - +} /* yy_get_previous_state - get the state just before the EOB char was reached */ -static yy_state_type yy_get_previous_state() - { + static yy_state_type yy_get_previous_state (void) +{ register yy_state_type yy_current_state; register char *yy_cp; + + yy_current_state = (yy_start); - yy_current_state = yy_start; - - for ( yy_cp = yytext_ptr + YY_MORE_ADJ; yy_cp < yy_c_buf_p; ++yy_cp ) + for ( yy_cp = (yytext_ptr) + YY_MORE_ADJ; yy_cp < (yy_c_buf_p); ++yy_cp ) { register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1); if ( yy_accept[yy_current_state] ) { - yy_last_accepting_state = yy_current_state; - yy_last_accepting_cpos = yy_cp; + (yy_last_accepting_state) = yy_current_state; + (yy_last_accepting_cpos) = yy_cp; } while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { @@ -1043,30 +1121,23 @@ static yy_state_type yy_get_previous_state() } return yy_current_state; - } - +} /* yy_try_NUL_trans - try to make a transition on the NUL character * * synopsis * next_state = yy_try_NUL_trans( current_state ); */ - -#ifdef YY_USE_PROTOS -static yy_state_type yy_try_NUL_trans( yy_state_type yy_current_state ) -#else -static yy_state_type yy_try_NUL_trans( yy_current_state ) -yy_state_type yy_current_state; -#endif - { + static yy_state_type yy_try_NUL_trans (yy_state_type yy_current_state ) +{ register int yy_is_jam; - register char *yy_cp = yy_c_buf_p; + register char *yy_cp = (yy_c_buf_p); register YY_CHAR yy_c = 1; if ( yy_accept[yy_current_state] ) { - yy_last_accepting_state = yy_current_state; - yy_last_accepting_cpos = yy_cp; + (yy_last_accepting_state) = yy_current_state; + (yy_last_accepting_cpos) = yy_cp; } while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { @@ -1078,81 +1149,36 @@ yy_state_type yy_current_state; yy_is_jam = (yy_current_state == 37); return yy_is_jam ? 0 : yy_current_state; - } - - -#ifndef YY_NO_UNPUT -#ifdef YY_USE_PROTOS -static void yyunput( int c, register char *yy_bp ) -#else -static void yyunput( c, yy_bp ) -int c; -register char *yy_bp; -#endif - { - register char *yy_cp = yy_c_buf_p; - - /* undo effects of setting up yytext */ - *yy_cp = yy_hold_char; - - if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 ) - { /* need to shift things up to make room */ - /* +2 for EOB chars. */ - register int number_to_move = yy_n_chars + 2; - register char *dest = &yy_current_buffer->yy_ch_buf[ - yy_current_buffer->yy_buf_size + 2]; - register char *source = - &yy_current_buffer->yy_ch_buf[number_to_move]; - - while ( source > yy_current_buffer->yy_ch_buf ) - *--dest = *--source; - - yy_cp += (int) (dest - source); - yy_bp += (int) (dest - source); - yy_current_buffer->yy_n_chars = - yy_n_chars = yy_current_buffer->yy_buf_size; - - if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 ) - YY_FATAL_ERROR( "flex scanner push-back overflow" ); - } - - *--yy_cp = (char) c; - - - yytext_ptr = yy_bp; - yy_hold_char = *yy_cp; - yy_c_buf_p = yy_cp; - } -#endif /* ifndef YY_NO_UNPUT */ - +} #ifndef YY_NO_INPUT #ifdef __cplusplus -static int yyinput() + static int yyinput (void) #else -static int input() + static int input (void) #endif - { - int c; - *yy_c_buf_p = yy_hold_char; +{ + int c; + + *(yy_c_buf_p) = (yy_hold_char); - if ( *yy_c_buf_p == YY_END_OF_BUFFER_CHAR ) + if ( *(yy_c_buf_p) == YY_END_OF_BUFFER_CHAR ) { /* yy_c_buf_p now points to the character we want to return. * If this occurs *before* the EOB characters, then it's a * valid NUL; if not, then we've hit the end of the buffer. */ - if ( yy_c_buf_p < &yy_current_buffer->yy_ch_buf[yy_n_chars] ) + if ( (yy_c_buf_p) < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] ) /* This was really a NUL. */ - *yy_c_buf_p = '\0'; + *(yy_c_buf_p) = '\0'; else { /* need more input */ - int offset = yy_c_buf_p - yytext_ptr; - ++yy_c_buf_p; + int offset = (yy_c_buf_p) - (yytext_ptr); + ++(yy_c_buf_p); - switch ( yy_get_next_buffer() ) + switch ( yy_get_next_buffer( ) ) { case EOB_ACT_LAST_MATCH: /* This happens because yy_g_n_b() @@ -1166,16 +1192,16 @@ static int input() */ /* Reset buffer status. */ - yyrestart( yyin ); + yyrestart(yyin ); - /* fall through */ + /*FALLTHROUGH*/ case EOB_ACT_END_OF_FILE: { - if ( yywrap() ) + if ( yywrap( ) ) return EOF; - if ( ! yy_did_buffer_switch_on_eof ) + if ( ! (yy_did_buffer_switch_on_eof) ) YY_NEW_FILE; #ifdef __cplusplus return yyinput(); @@ -1185,90 +1211,92 @@ static int input() } case EOB_ACT_CONTINUE_SCAN: - yy_c_buf_p = yytext_ptr + offset; + (yy_c_buf_p) = (yytext_ptr) + offset; break; } } } - c = *(unsigned char *) yy_c_buf_p; /* cast for 8-bit char's */ - *yy_c_buf_p = '\0'; /* preserve yytext */ - yy_hold_char = *++yy_c_buf_p; - + c = *(unsigned char *) (yy_c_buf_p); /* cast for 8-bit char's */ + *(yy_c_buf_p) = '\0'; /* preserve yytext */ + (yy_hold_char) = *++(yy_c_buf_p); return c; - } -#endif /* YY_NO_INPUT */ - -#ifdef YY_USE_PROTOS -void yyrestart( FILE *input_file ) -#else -void yyrestart( input_file ) -FILE *input_file; -#endif - { - if ( ! yy_current_buffer ) - yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); +} +#endif /* ifndef YY_NO_INPUT */ - yy_init_buffer( yy_current_buffer, input_file ); - yy_load_buffer_state(); +/** Immediately switch to a different input stream. + * @param input_file A readable stream. + * + * @note This function does not reset the start condition to @c INITIAL . + */ + void yyrestart (FILE * input_file ) +{ + + if ( ! YY_CURRENT_BUFFER ){ + yyensure_buffer_stack (); + YY_CURRENT_BUFFER_LVALUE = + yy_create_buffer(yyin,YY_BUF_SIZE ); } + yy_init_buffer(YY_CURRENT_BUFFER,input_file ); + yy_load_buffer_state( ); +} -#ifdef YY_USE_PROTOS -void yy_switch_to_buffer( YY_BUFFER_STATE new_buffer ) -#else -void yy_switch_to_buffer( new_buffer ) -YY_BUFFER_STATE new_buffer; -#endif - { - if ( yy_current_buffer == new_buffer ) +/** Switch to a different input buffer. + * @param new_buffer The new input buffer. + * + */ + void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer ) +{ + + /* TODO. We should be able to replace this entire function body + * with + * yypop_buffer_state(); + * yypush_buffer_state(new_buffer); + */ + yyensure_buffer_stack (); + if ( YY_CURRENT_BUFFER == new_buffer ) return; - if ( yy_current_buffer ) + if ( YY_CURRENT_BUFFER ) { /* Flush out information for old buffer. */ - *yy_c_buf_p = yy_hold_char; - yy_current_buffer->yy_buf_pos = yy_c_buf_p; - yy_current_buffer->yy_n_chars = yy_n_chars; + *(yy_c_buf_p) = (yy_hold_char); + YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p); + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); } - yy_current_buffer = new_buffer; - yy_load_buffer_state(); + YY_CURRENT_BUFFER_LVALUE = new_buffer; + yy_load_buffer_state( ); /* We don't actually know whether we did this switch during * EOF (yywrap()) processing, but the only time this flag * is looked at is after yywrap() is called, so it's safe * to go ahead and always set it. */ - yy_did_buffer_switch_on_eof = 1; - } - - -#ifdef YY_USE_PROTOS -void yy_load_buffer_state( void ) -#else -void yy_load_buffer_state() -#endif - { - yy_n_chars = yy_current_buffer->yy_n_chars; - yytext_ptr = yy_c_buf_p = yy_current_buffer->yy_buf_pos; - yyin = yy_current_buffer->yy_input_file; - yy_hold_char = *yy_c_buf_p; - } + (yy_did_buffer_switch_on_eof) = 1; +} +static void yy_load_buffer_state (void) +{ + (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; + (yytext_ptr) = (yy_c_buf_p) = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos; + yyin = YY_CURRENT_BUFFER_LVALUE->yy_input_file; + (yy_hold_char) = *(yy_c_buf_p); +} -#ifdef YY_USE_PROTOS -YY_BUFFER_STATE yy_create_buffer( FILE *file, int size ) -#else -YY_BUFFER_STATE yy_create_buffer( file, size ) -FILE *file; -int size; -#endif - { +/** Allocate and initialize an input buffer state. + * @param file A readable stream. + * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE. + * + * @return the allocated buffer state. + */ + YY_BUFFER_STATE yy_create_buffer (FILE * file, int size ) +{ YY_BUFFER_STATE b; - - b = (YY_BUFFER_STATE) yy_flex_alloc( sizeof( struct yy_buffer_state ) ); + + b = (YY_BUFFER_STATE) yyalloc(sizeof( struct yy_buffer_state ) ); if ( ! b ) YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); @@ -1277,75 +1305,71 @@ int size; /* yy_ch_buf has to be 2 characters longer than the size given because * we need to put in 2 end-of-buffer characters. */ - b->yy_ch_buf = (char *) yy_flex_alloc( b->yy_buf_size + 2 ); + b->yy_ch_buf = (char *) yyalloc(b->yy_buf_size + 2 ); if ( ! b->yy_ch_buf ) YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); b->yy_is_our_buffer = 1; - yy_init_buffer( b, file ); + yy_init_buffer(b,file ); return b; - } - +} -#ifdef YY_USE_PROTOS -void yy_delete_buffer( YY_BUFFER_STATE b ) -#else -void yy_delete_buffer( b ) -YY_BUFFER_STATE b; -#endif - { +/** Destroy the buffer. + * @param b a buffer created with yy_create_buffer() + * + */ + void yy_delete_buffer (YY_BUFFER_STATE b ) +{ + if ( ! b ) return; - if ( b == yy_current_buffer ) - yy_current_buffer = (YY_BUFFER_STATE) 0; + if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */ + YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0; if ( b->yy_is_our_buffer ) - yy_flex_free( (void *) b->yy_ch_buf ); - - yy_flex_free( (void *) b ); - } - + yyfree((void *) b->yy_ch_buf ); + yyfree((void *) b ); +} -#ifdef YY_USE_PROTOS -void yy_init_buffer( YY_BUFFER_STATE b, FILE *file ) -#else -void yy_init_buffer( b, file ) -YY_BUFFER_STATE b; -FILE *file; -#endif - +/* Initializes or reinitializes a buffer. + * This function is sometimes called more than once on the same buffer, + * such as during a yyrestart() or at EOF. + */ + static void yy_init_buffer (YY_BUFFER_STATE b, FILE * file ) - { - yy_flush_buffer( b ); +{ + int oerrno = errno; + + yy_flush_buffer(b ); b->yy_input_file = file; b->yy_fill_buffer = 1; -#if YY_ALWAYS_INTERACTIVE - b->yy_is_interactive = 1; -#else -#if YY_NEVER_INTERACTIVE - b->yy_is_interactive = 0; -#else - b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0; -#endif -#endif - } - - -#ifdef YY_USE_PROTOS -void yy_flush_buffer( YY_BUFFER_STATE b ) -#else -void yy_flush_buffer( b ) -YY_BUFFER_STATE b; -#endif + /* If b is the current buffer, then yy_init_buffer was _probably_ + * called from yyrestart() or through yy_get_next_buffer. + * In that case, we don't want to reset the lineno or column. + */ + if (b != YY_CURRENT_BUFFER){ + b->yy_bs_lineno = 1; + b->yy_bs_column = 0; + } + + b->yy_is_interactive = 0; + + errno = oerrno; +} - { - if ( ! b ) +/** Discard all buffered characters. On the next scan, YY_INPUT will be called. + * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER. + * + */ + void yy_flush_buffer (YY_BUFFER_STATE b ) +{ + if ( ! b ) return; b->yy_n_chars = 0; @@ -1362,29 +1386,121 @@ YY_BUFFER_STATE b; b->yy_at_bol = 1; b->yy_buffer_status = YY_BUFFER_NEW; - if ( b == yy_current_buffer ) - yy_load_buffer_state(); + if ( b == YY_CURRENT_BUFFER ) + yy_load_buffer_state( ); +} + +/** Pushes the new state onto the stack. The new state becomes + * the current state. This function will allocate the stack + * if necessary. + * @param new_buffer The new state. + * + */ +void yypush_buffer_state (YY_BUFFER_STATE new_buffer ) +{ + if (new_buffer == NULL) + return; + + yyensure_buffer_stack(); + + /* This block is copied from yy_switch_to_buffer. */ + if ( YY_CURRENT_BUFFER ) + { + /* Flush out information for old buffer. */ + *(yy_c_buf_p) = (yy_hold_char); + YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p); + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); + } + + /* Only push if top exists. Otherwise, replace top. */ + if (YY_CURRENT_BUFFER) + (yy_buffer_stack_top)++; + YY_CURRENT_BUFFER_LVALUE = new_buffer; + + /* copied from yy_switch_to_buffer. */ + yy_load_buffer_state( ); + (yy_did_buffer_switch_on_eof) = 1; +} + +/** Removes and deletes the top of the stack, if present. + * The next element becomes the new top. + * + */ +void yypop_buffer_state (void) +{ + if (!YY_CURRENT_BUFFER) + return; + + yy_delete_buffer(YY_CURRENT_BUFFER ); + YY_CURRENT_BUFFER_LVALUE = NULL; + if ((yy_buffer_stack_top) > 0) + --(yy_buffer_stack_top); + + if (YY_CURRENT_BUFFER) { + yy_load_buffer_state( ); + (yy_did_buffer_switch_on_eof) = 1; } +} +/* Allocates the stack if it does not exist. + * Guarantees space for at least one push. + */ +static void yyensure_buffer_stack (void) +{ + int num_to_alloc; + + if (!(yy_buffer_stack)) { + + /* First allocation is just for 2 elements, since we don't know if this + * scanner will even need a stack. We use 2 instead of 1 to avoid an + * immediate realloc on the next call. + */ + num_to_alloc = 1; + (yy_buffer_stack) = (struct yy_buffer_state**)yyalloc + (num_to_alloc * sizeof(struct yy_buffer_state*) + ); + + memset((yy_buffer_stack), 0, num_to_alloc * sizeof(struct yy_buffer_state*)); + + (yy_buffer_stack_max) = num_to_alloc; + (yy_buffer_stack_top) = 0; + return; + } -#ifndef YY_NO_SCAN_BUFFER -#ifdef YY_USE_PROTOS -YY_BUFFER_STATE yy_scan_buffer( char *base, yy_size_t size ) -#else -YY_BUFFER_STATE yy_scan_buffer( base, size ) -char *base; -yy_size_t size; -#endif - { - YY_BUFFER_STATE b; + if ((yy_buffer_stack_top) >= ((yy_buffer_stack_max)) - 1){ + + /* Increase the buffer to prepare for a possible push. */ + int grow_size = 8 /* arbitrary grow size */; + num_to_alloc = (yy_buffer_stack_max) + grow_size; + (yy_buffer_stack) = (struct yy_buffer_state**)yyrealloc + ((yy_buffer_stack), + num_to_alloc * sizeof(struct yy_buffer_state*) + ); + + /* zero only the new slots.*/ + memset((yy_buffer_stack) + (yy_buffer_stack_max), 0, grow_size * sizeof(struct yy_buffer_state*)); + (yy_buffer_stack_max) = num_to_alloc; + } +} + +/** Setup the input buffer state to scan directly from a user-specified character buffer. + * @param base the character buffer + * @param size the size in bytes of the character buffer + * + * @return the newly allocated buffer state object. + */ +YY_BUFFER_STATE yy_scan_buffer (char * base, yy_size_t size ) +{ + YY_BUFFER_STATE b; + if ( size < 2 || base[size-2] != YY_END_OF_BUFFER_CHAR || base[size-1] != YY_END_OF_BUFFER_CHAR ) /* They forgot to leave room for the EOB's. */ return 0; - b = (YY_BUFFER_STATE) yy_flex_alloc( sizeof( struct yy_buffer_state ) ); + b = (YY_BUFFER_STATE) yyalloc(sizeof( struct yy_buffer_state ) ); if ( ! b ) YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" ); @@ -1398,56 +1514,51 @@ yy_size_t size; b->yy_fill_buffer = 0; b->yy_buffer_status = YY_BUFFER_NEW; - yy_switch_to_buffer( b ); + yy_switch_to_buffer(b ); return b; - } -#endif - - -#ifndef YY_NO_SCAN_STRING -#ifdef YY_USE_PROTOS -YY_BUFFER_STATE yy_scan_string( yyconst char *yy_str ) -#else -YY_BUFFER_STATE yy_scan_string( yy_str ) -yyconst char *yy_str; -#endif - { - int len; - for ( len = 0; yy_str[len]; ++len ) - ; - - return yy_scan_bytes( yy_str, len ); - } -#endif +} +/** Setup the input buffer state to scan a string. The next call to yylex() will + * scan from a @e copy of @a str. + * @param str a NUL-terminated string to scan + * + * @return the newly allocated buffer state object. + * @note If you want to scan bytes that may contain NUL values, then use + * yy_scan_bytes() instead. + */ +YY_BUFFER_STATE yy_scan_string (yyconst char * yystr ) +{ + + return yy_scan_bytes(yystr,strlen(yystr) ); +} -#ifndef YY_NO_SCAN_BYTES -#ifdef YY_USE_PROTOS -YY_BUFFER_STATE yy_scan_bytes( yyconst char *bytes, int len ) -#else -YY_BUFFER_STATE yy_scan_bytes( bytes, len ) -yyconst char *bytes; -int len; -#endif - { +/** Setup the input buffer state to scan the given bytes. The next call to yylex() will + * scan from a @e copy of @a bytes. + * @param bytes the byte buffer to scan + * @param len the number of bytes in the buffer pointed to by @a bytes. + * + * @return the newly allocated buffer state object. + */ +YY_BUFFER_STATE yy_scan_bytes (yyconst char * yybytes, int _yybytes_len ) +{ YY_BUFFER_STATE b; char *buf; yy_size_t n; int i; - + /* Get memory for full buffer, including space for trailing EOB's. */ - n = len + 2; - buf = (char *) yy_flex_alloc( n ); + n = _yybytes_len + 2; + buf = (char *) yyalloc(n ); if ( ! buf ) YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" ); - for ( i = 0; i < len; ++i ) - buf[i] = bytes[i]; + for ( i = 0; i < _yybytes_len; ++i ) + buf[i] = yybytes[i]; - buf[len] = buf[len+1] = YY_END_OF_BUFFER_CHAR; + buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR; - b = yy_scan_buffer( buf, n ); + b = yy_scan_buffer(buf,n ); if ( ! b ) YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" ); @@ -1457,148 +1568,196 @@ int len; b->yy_is_our_buffer = 1; return b; - } +} + +#ifndef YY_EXIT_FAILURE +#define YY_EXIT_FAILURE 2 #endif +static void yy_fatal_error (yyconst char* msg ) +{ + (void) fprintf( stderr, "%s\n", msg ); + exit( YY_EXIT_FAILURE ); +} -#ifndef YY_NO_PUSH_STATE -#ifdef YY_USE_PROTOS -static void yy_push_state( int new_state ) -#else -static void yy_push_state( new_state ) -int new_state; -#endif - { - if ( yy_start_stack_ptr >= yy_start_stack_depth ) - { - yy_size_t new_size; +/* Redefine yyless() so it works in section 3 code. */ - yy_start_stack_depth += YY_START_STACK_INCR; - new_size = yy_start_stack_depth * sizeof( int ); +#undef yyless +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up yytext. */ \ + int yyless_macro_arg = (n); \ + YY_LESS_LINENO(yyless_macro_arg);\ + yytext[yyleng] = (yy_hold_char); \ + (yy_c_buf_p) = yytext + yyless_macro_arg; \ + (yy_hold_char) = *(yy_c_buf_p); \ + *(yy_c_buf_p) = '\0'; \ + yyleng = yyless_macro_arg; \ + } \ + while ( 0 ) - if ( ! yy_start_stack ) - yy_start_stack = (int *) yy_flex_alloc( new_size ); +/* Accessor methods (get/set functions) to struct members. */ - else - yy_start_stack = (int *) yy_flex_realloc( - (void *) yy_start_stack, new_size ); +/** Get the current line number. + * + */ +int yyget_lineno (void) +{ + + return yylineno; +} - if ( ! yy_start_stack ) - YY_FATAL_ERROR( - "out of memory expanding start-condition stack" ); - } +/** Get the input stream. + * + */ +FILE *yyget_in (void) +{ + return yyin; +} - yy_start_stack[yy_start_stack_ptr++] = YY_START; +/** Get the output stream. + * + */ +FILE *yyget_out (void) +{ + return yyout; +} - BEGIN(new_state); - } -#endif +/** Get the length of the current token. + * + */ +int yyget_leng (void) +{ + return yyleng; +} +/** Get the current token. + * + */ -#ifndef YY_NO_POP_STATE -static void yy_pop_state() - { - if ( --yy_start_stack_ptr < 0 ) - YY_FATAL_ERROR( "start-condition stack underflow" ); +char *yyget_text (void) +{ + return yytext; +} - BEGIN(yy_start_stack[yy_start_stack_ptr]); - } -#endif +/** Set the current line number. + * @param line_number + * + */ +void yyset_lineno (int line_number ) +{ + + yylineno = line_number; +} +/** Set the input stream. This does not discard the current + * input buffer. + * @param in_str A readable stream. + * + * @see yy_switch_to_buffer + */ +void yyset_in (FILE * in_str ) +{ + yyin = in_str ; +} -#ifndef YY_NO_TOP_STATE -static int yy_top_state() - { - return yy_start_stack[yy_start_stack_ptr - 1]; - } -#endif +void yyset_out (FILE * out_str ) +{ + yyout = out_str ; +} -#ifndef YY_EXIT_FAILURE -#define YY_EXIT_FAILURE 2 -#endif +int yyget_debug (void) +{ + return yy_flex_debug; +} -#ifdef YY_USE_PROTOS -static void yy_fatal_error( yyconst char msg[] ) +void yyset_debug (int bdebug ) +{ + yy_flex_debug = bdebug ; +} + +static int yy_init_globals (void) +{ + /* Initialization is the same as for the non-reentrant scanner. + * This function is called from yylex_destroy(), so don't allocate here. + */ + + (yy_buffer_stack) = 0; + (yy_buffer_stack_top) = 0; + (yy_buffer_stack_max) = 0; + (yy_c_buf_p) = (char *) 0; + (yy_init) = 0; + (yy_start) = 0; + +/* Defined in main.c */ +#ifdef YY_STDINIT + yyin = stdin; + yyout = stdout; #else -static void yy_fatal_error( msg ) -char msg[]; + yyin = (FILE *) 0; + yyout = (FILE *) 0; #endif - { - (void) fprintf( stderr, "%s\n", msg ); - exit( YY_EXIT_FAILURE ); - } + /* For future reference: Set errno on error, since we are called by + * yylex_init() + */ + return 0; +} +/* yylex_destroy is for both reentrant and non-reentrant scanners. */ +int yylex_destroy (void) +{ + + /* Pop the buffer stack, destroying each element. */ + while(YY_CURRENT_BUFFER){ + yy_delete_buffer(YY_CURRENT_BUFFER ); + YY_CURRENT_BUFFER_LVALUE = NULL; + yypop_buffer_state(); + } -/* Redefine yyless() so it works in section 3 code. */ + /* Destroy the stack itself. */ + yyfree((yy_buffer_stack) ); + (yy_buffer_stack) = NULL; -#undef yyless -#define yyless(n) \ - do \ - { \ - /* Undo effects of setting up yytext. */ \ - yytext[yyleng] = yy_hold_char; \ - yy_c_buf_p = yytext + n; \ - yy_hold_char = *yy_c_buf_p; \ - *yy_c_buf_p = '\0'; \ - yyleng = n; \ - } \ - while ( 0 ) + /* Reset the globals. This is important in a non-reentrant scanner so the next time + * yylex() is called, initialization will occur. */ + yy_init_globals( ); + return 0; +} -/* Internal utility routines. */ +/* + * Internal utility routines. + */ #ifndef yytext_ptr -#ifdef YY_USE_PROTOS -static void yy_flex_strncpy( char *s1, yyconst char *s2, int n ) -#else -static void yy_flex_strncpy( s1, s2, n ) -char *s1; -yyconst char *s2; -int n; -#endif - { +static void yy_flex_strncpy (char* s1, yyconst char * s2, int n ) +{ register int i; for ( i = 0; i < n; ++i ) s1[i] = s2[i]; - } +} #endif #ifdef YY_NEED_STRLEN -#ifdef YY_USE_PROTOS -static int yy_flex_strlen( yyconst char *s ) -#else -static int yy_flex_strlen( s ) -yyconst char *s; -#endif - { +static int yy_flex_strlen (yyconst char * s ) +{ register int n; for ( n = 0; s[n]; ++n ) ; return n; - } +} #endif - -#ifdef YY_USE_PROTOS -static void *yy_flex_alloc( yy_size_t size ) -#else -static void *yy_flex_alloc( size ) -yy_size_t size; -#endif - { +void *yyalloc (yy_size_t size ) +{ return (void *) malloc( size ); - } +} -#ifdef YY_USE_PROTOS -static void *yy_flex_realloc( void *ptr, yy_size_t size ) -#else -static void *yy_flex_realloc( ptr, size ) -void *ptr; -yy_size_t size; -#endif - { +void *yyrealloc (void * ptr, yy_size_t size ) +{ /* The cast to (char *) in the following accommodates both * implementations that use char* generic pointers, and those * that use void* generic pointers. It works with the latter @@ -1607,28 +1766,19 @@ yy_size_t size; * as though doing an assignment. */ return (void *) realloc( (char *) ptr, size ); - } +} -#ifdef YY_USE_PROTOS -static void yy_flex_free( void *ptr ) -#else -static void yy_flex_free( ptr ) -void *ptr; -#endif - { - free( ptr ); - } +void yyfree (void * ptr ) +{ + free( (char *) ptr ); /* see yyrealloc() for (char *) cast */ +} + +#define YYTABLES_NAME "yytables" -#if YY_MAIN -int main() - { - yylex(); - return 0; - } -#endif #line 92 "pool_config.l" + static int eval_logical(char *str); int pool_get_config(char *confpath) @@ -1676,6 +1826,8 @@ int pool_get_config(char *confpath) pool_config.insert_lock = 0; pool_config.num_servers = 0; pool_config.log_statement = 0; + pool_config.log_connections = 0; + pool_config.enable_pool_hba = 0; #define PARSE_ERROR() pool_error("pool_config: parse error at line %d '%s'", Lineno, yytext) /* open config file */ @@ -2154,6 +2306,28 @@ int pool_get_config(char *confpath) } pool_config.log_statement = v; } + else if (!strcmp(key, "log_connections")) + { + int v = eval_logical(yytext); + + if (v < 0) + { + pool_error("pool_config: invalid value %s for %s", yytext, key); + return(-1); + } + pool_config.log_connections = v; + } + else if (!strcmp(key, "enable_pool_hba")) + { + int v = eval_logical(yytext); + + if (v < 0) + { + pool_error("pool_config: invalid value %s for %s", yytext, key); + return(-1); + } + pool_config.enable_pool_hba = v; + } } if (pool_config.backend_port) @@ -2230,3 +2404,4 @@ static char **extract_string_tokens(char *str, char *delimi, int *n) } return tokens; } + diff --git a/pool_config.l b/pool_config.l index 0c8ea53..f40062d 100644 --- a/pool_config.l +++ b/pool_config.l @@ -138,6 +138,8 @@ int pool_get_config(char *confpath) pool_config.insert_lock = 0; pool_config.num_servers = 0; pool_config.log_statement = 0; + pool_config.log_connections = 0; + pool_config.enable_pool_hba = 0; #define PARSE_ERROR() pool_error("pool_config: parse error at line %d '%s'", Lineno, yytext) /* open config file */ @@ -616,6 +618,28 @@ int pool_get_config(char *confpath) } pool_config.log_statement = v; } + else if (!strcmp(key, "log_connections")) + { + int v = eval_logical(yytext); + + if (v < 0) + { + pool_error("pool_config: invalid value %s for %s", yytext, key); + return(-1); + } + pool_config.log_connections = v; + } + else if (!strcmp(key, "enable_pool_hba")) + { + int v = eval_logical(yytext); + + if (v < 0) + { + pool_error("pool_config: invalid value %s for %s", yytext, key); + return(-1); + } + pool_config.enable_pool_hba = v; + } } if (pool_config.backend_port) diff --git a/pool_hba.c b/pool_hba.c new file mode 100644 index 0000000..976b78f --- /dev/null +++ b/pool_hba.c @@ -0,0 +1,1420 @@ +/* -*-pgsql-c-*- */ +/* + * + * $Header$ + * + * pgpool: a language independent connection pool server for PostgreSQL + * written by Tatsuo Ishii + * + * Portions Copyright (c) 2003-2007 PgPool Global Development Group + * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California * + * Permission to use, copy, modify, and distribute this software and + * its documentation for any purpose 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 + * author not be used in advertising or publicity pertaining to + * distribution of the software without specific, written prior + * permission. The author makes no representations about the + * suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * pool_hba.c.: Routines to handle host based authentication. + * + */ + +#include +#include +#include +#include +#include + +#include "pool.h" +#include "pool_path.h" +#include "pool_ip.h" + +#define MULTI_VALUE_SEP "\001" /* delimiter for multi-valued column strings */ +#define MAX_TOKEN 256 + +static List *hba_lines = NIL; +static List *hba_line_nums = NIL; +static char *hbaFileName; + +static void sendAuthRequest(POOL_CONNECTION *frontend, AuthRequest areq); +static void auth_failed(POOL_CONNECTION *frontend); +static void close_all_backend_connections(void); +static bool hba_getauthmethod(POOL_CONNECTION *frontend); +static bool check_hba(POOL_CONNECTION *frontend); +static void parse_hba(List *line, int line_num, POOL_CONNECTION *frontend, bool *found_p, bool *error_p); +static void parse_hba_auth(ListCell **line_item, UserAuth *userauth_p, char **auth_arg_p, bool *error_p); +static bool check_user(char *user, char *param_str); +static bool check_db(char *dbname, char *user, char *param_str); +static void free_lines(List **lines, List **line_nums); +static void tokenize_file(const char *filename, FILE *file, List **lines, List **line_nums); +static char *tokenize_inc_file(const char *outer_filename, const char *inc_filename); +static bool pg_isblank(const char c); +static void next_token(FILE *fp, char *buf, int bufsz); +static char * next_token_expand(const char *filename, FILE *file); + +#ifdef USE_PAM +#ifdef HAVE_PAM_PAM_APPL_H +#include +#endif +#ifdef HAVE_SECURITY_PAM_APPL_H +#include +#endif + +#define PGPOOL_PAM_SERVICE "pgpool" /* Service name passed to PAM */ + +static POOL_STATUS CheckPAMAuth(POOL_CONNECTION *frontend, char *user, char *password); +static int pam_passwd_conv_proc(int num_msg, const struct pam_message ** msg, struct pam_response ** resp, void *appdata_ptr); +/* + * recv_password_packet is usually used with authentications that require a client + * password. However, pgpool's hba function only uses it for PAM authentication, + * so declare a prototype here in "#ifdef USE_PAM" to avoid compilation warning. + */ +static char *recv_password_packet(POOL_CONNECTION *frontend); + +static struct pam_conv pam_passw_conv = { + &pam_passwd_conv_proc, + NULL +}; + +static char *pam_passwd = NULL; /* Workaround for Solaris 2.6 brokenness */ +static POOL_CONNECTION *pam_frontend_kludge; /* Workaround for passing + * POOL_CONNECTION *frontend + * into pam_passwd_conv_proc */ +#endif /* USE_PAM */ + + +/* + * read in hba config file + */ +void load_hba(char *hbapath) +{ + FILE *file; + + if (hba_lines || hba_line_nums) + free_lines(&hba_lines, &hba_line_nums); + + file = fopen(hbapath, "r"); + if (!file) + { + pool_error("could not open \"%s\". reason: %s", + hbapath, strerror(errno)); + exit(1); + } + + pool_debug("loading \"%s\" for client authentication configuration file", + hbapath); + + tokenize_file(hbapath, file, &hba_lines, &hba_line_nums); + fclose(file); + + hbaFileName = strdup(hbapath); + if (hbaFileName == NULL) + { + pool_error("load_hba: strdup failed: %s", strerror(errno)); + exit(1); + } +} + + +/* + * do frontend <-> pgpool authentication based on pool_hba.conf + */ +void ClientAuthentication(POOL_CONNECTION *frontend) +{ + POOL_STATUS status = POOL_ERROR; + + if (! hba_getauthmethod(frontend)) + { + pool_error("missing or erroneous pool_hba.conf file"); + pool_send_error_message(frontend, frontend->protoVersion, "XX000", + "missing or erroneous pool_hba.conf file", "", + "See pgpool log for details.", __FILE__, __LINE__); + close_all_backend_connections(); + /* + * use exit(2) since this is not so fatal. other entries in + * pool_hba.conf may be valid, so treat it as reject. + */ + exit(2); + } + + switch (frontend->auth_method) + { + case uaReject: + { + /* + * This could have come from an explicit "reject" entry in + * pool_hba.conf, but more likely it means there was no matching + * entry. Take pity on the poor user and issue a helpful + * error message. NOTE: this is not a security breach, + * because all the info reported here is known at the frontend + * and must be assumed known to bad guys. We're merely helping + * out the less clueful good guys. + */ + char hostinfo[NI_MAXHOST]; + char *errmessage; + int messagelen; + + getnameinfo_all(&frontend->raddr.addr, frontend->raddr.salen, + hostinfo, sizeof(hostinfo), + NULL, 0, + NI_NUMERICHOST); + + messagelen = sizeof(hostinfo) + + strlen(frontend->username) + strlen(frontend->database) + 80; + if ((errmessage = (char *)malloc(messagelen+1)) == NULL) + { + pool_error("ClientAuthentication: malloc failed: %s", strerror(errno)); + exit(1); + } + +#ifdef USE_SSL + snprintf(errmessage, messagelen+7, /* +7 is for "SSL off" */ + "no pool_hba.conf entry for host \"%s\", user \"%s\", database \"%s\", %s", + hostinfo, frontend->username, frontend->database, + frontend->ssl ? "SSL on" : "SSL off"); +#else + snprintf(errmessage, messagelen, + "no pool_hba.conf entry for host \"%s\", user \"%s\", database \"%s\"", + hostinfo, frontend->username, frontend->database); +#endif + pool_error(errmessage); + pool_send_error_message(frontend, frontend->protoVersion, "XX000", errmessage, + "", "", __FILE__, __LINE__); + + free(errmessage); + break; + } + +/* case uaKrb4: */ +/* break; */ + +/* case uaKrb5: */ +/* break; */ + +/* case uaIdent: */ +/* break; */ + +/* case uaMD5: */ +/* break; */ + +/* case uaCrypt: */ +/* break; */ + +/* case uaPassword: */ +/* break; */ + +#ifdef USE_PAM + case uaPAM: + pam_frontend_kludge = frontend; + status = CheckPAMAuth(frontend, frontend->username, ""); + break; +#endif /* USE_PAM */ + + case uaTrust: + status = POOL_CONTINUE; + break; + } + + if (status == POOL_CONTINUE) + sendAuthRequest(frontend, AUTH_REQ_OK); + else if (status != POOL_CONTINUE) + auth_failed(frontend); +} + + +static void sendAuthRequest(POOL_CONNECTION *frontend, AuthRequest areq) +{ + int wsize; /* number of bytes to write */ + int areq_nbo; /* areq in network byte order */ + + /* + * If AUTH_REQ_OK, then frontend is OK to connect __with_pgpool__. + * Do not send 'R' to the frontend, he still needs to authenticate + * himself with the backend. + */ + if (areq == AUTH_REQ_OK) + return; + + /* request a password */ + pool_write(frontend, "R", 1); + + if (frontend->protoVersion == PROTO_MAJOR_V3) + { +/* if (areq == AUTH_REQ_MD5) */ +/* wsize = htonl(sizeof(int)*2+4); */ +/* else if (areq == AUTH_REQ_CRYPT) */ +/* wsize = htonl(sizeof(int)*2+2); */ +/* else */ + wsize = htonl(sizeof(int)*2); + pool_write(frontend, &wsize, sizeof(int)); + } + + areq_nbo = htonl(areq); + pool_write(frontend, &areq_nbo, sizeof(int)); + + /* Add the salt for encrypted passwords. */ +/* if (areq == AUTH_REQ_MD5) */ +/* pq_sendbytes(&buf, port->md5Salt, 4); */ +/* else if (areq == AUTH_REQ_CRYPT) */ +/* pq_sendbytes(&buf, port->cryptSalt, 2); */ + + pool_flush(frontend); +} + + +#ifdef USE_PAM /* see the prototype comment */ + +/* + * Collect password response packet from frontend. + * + * Returns NULL if couldn't get password, else malloc'd string. + */ +static char *recv_password_packet(POOL_CONNECTION *frontend) +{ + int rsize; + char *passwd; + char *returnVal; + + if (frontend->protoVersion == PROTO_MAJOR_V3) + { + /* Expect 'p' message type */ + char kind; + + if (pool_read(frontend, &kind, 1) < 0) + return NULL; + + if (kind != 'p') + { + pool_error("expected password response, got message type %c", + kind); + return NULL; /* bad message type */ + } + } + /* pre-3.0 protocol does not send a message type */ + + if (pool_read(frontend, &rsize, sizeof(int)) < 0) + return NULL; + + rsize = ntohl(rsize) - 4; + passwd = pool_read2(frontend, rsize); /* retrieve password */ + if (passwd == NULL) + return NULL; + + /* Do not echo password to logs, for security. */ + pool_debug("received password packet from frontend for pgpool's HBA"); + + /* + * Return the received string. Note we do not attempt to do any + * character-set conversion on it; since we don't yet know the + * client's encoding, there wouldn't be much point. + */ + returnVal = strdup(passwd); + if (returnVal == NULL) + { + pool_error("recv_password_packet: strdup failed: %s", strerror(errno)); + exit(1); + } + return returnVal; +} + +#endif /* USE_PAM */ + +/* + * Tell the user the authentication failed. + */ +static void auth_failed(POOL_CONNECTION *frontend) +{ + bool send_error_to_frontend = true; + int messagelen; + char *errmessage; + + messagelen = strlen(frontend->username) + 100; + if ((errmessage = (char *)malloc(messagelen+1)) == NULL) + { + pool_error("auth_failed: malloc failed: %s", strerror(errno)); + exit(1); + } + + switch (frontend->auth_method) + { + case uaReject: + snprintf(errmessage, messagelen, + "authentication with pgpool failed for user \"%s\": host rejected", + frontend->username); + /* + * if uaReject, frontend should have received 'E' and disconnected already. + */ + send_error_to_frontend = false; + break; +/* case uaKrb4: */ +/* snprintf(errmessage, messagelen, */ +/* "Kerberos 4 authentication with pgpool failed for user \"%s\"", */ +/* frontend->username); */ +/* break; */ +/* case uaKrb5: */ +/* snprintf(errmessage, messagelen, */ +/* "Kerberos 5 authentication with pgpool failed for user \"%s\"", */ +/* frontend->username); */ +/* break; */ + case uaTrust: + snprintf(errmessage, messagelen, + "\"trust\" authentication with pgpool failed for user \"%s\"", + frontend->username); + break; +/* case uaIdent: */ +/* snprintf(errmessage, messagelen, */ +/* "Ident authentication with pgpool failed for user \"%s\"", */ +/* frontend->username); */ +/* break; */ +/* case uaMD5: */ +/* case uaCrypt: */ +/* case uaPassword: */ +/* snprintf(errmessage, messagelen, */ +/* "password authentication with pgpool failed for user \"%s\"", */ +/* frontend->username); */ +/* break; */ +#ifdef USE_PAM + case uaPAM: + snprintf(errmessage, messagelen, + "PAM authentication with pgpool failed for user \"%s\"", + frontend->username); + break; +#endif /* USE_PAM */ + default: + snprintf(errmessage, messagelen, + "authentication with pgpool failed for user \"%s\": invalid authentication method", + frontend->username); + break; + } + + pool_error(errmessage); + if (send_error_to_frontend) + pool_send_error_message(frontend, frontend->protoVersion, "XX000", errmessage, + "", "", __FILE__, __LINE__); + + /* + * don't need to free(errmessage). I will just kill myself. + */ + close_all_backend_connections(); + exit(2); +} + + +/* + * Close all of the cached backend connections. + * + * This is exactly the same as send_frontend_exits() in child.c. + */ +static void close_all_backend_connections(void) +{ + int i; + POOL_CONNECTION_POOL *p = pool_connection_pool; + +#ifdef HAVE_SIGPROCMASK + sigset_t oldmask; +#else + int oldmask; +#endif + + POOL_SETMASK2(&BlockSig, &oldmask); + + for (i=0;isp->user == NULL) + continue; + pool_send_frontend_exits(p); + } + + POOL_SETMASK(&oldmask); +} + + +/* + * Determine what authentication method should be used when accessing database + * "database" from frontend "raddr", user "user". Return the method and + * an optional argument (stored in fields of *frontend), and true for success. + * + * Note that false indicates a problem with the hba config file. + * If the file is OK but does not contain any entry matching the request, + * we return true and method = uaReject. + */ +static bool hba_getauthmethod(POOL_CONNECTION *frontend) +{ + if (check_hba(frontend)) + return true; + else + return false; +} + + +/* + * Scan the (pre-parsed) hba file line by line, looking for a match + * to the port's connection request. + */ +static bool check_hba(POOL_CONNECTION *frontend) +{ + bool found_entry = false; + bool error = false; + ListCell *line; + ListCell *line_num; + + forboth(line, hba_lines, line_num, hba_line_nums) + { + parse_hba(lfirst(line), lfirst_int(line_num), + frontend, &found_entry, &error); + if (found_entry || error) + break; + } + + if (!error) + { + /* If no matching entry was found, synthesize 'reject' entry. */ + if (!found_entry) + frontend->auth_method = uaReject; + return true; + } + else + return false; +} + + +/* + * Process one line from the hba config file. + * + * See if it applies to a connection from a frontend with IP address + * frontend->raddr to a database named frontend->database. If so, return + * *found_p true and fill in the auth arguments into the appropriate + * frontend fields. If not, leave *found_p as it was. If the record has + * a syntax error, return *error_p true, after issuing a message to the + * log. If no error, leave *error_p as it was. + */ +static void parse_hba(List *line, int line_num, POOL_CONNECTION *frontend, + bool *found_p, bool *error_p) +{ + char *token; + char *db, *db_tmp; + char *user, *user_tmp; + struct addrinfo *gai_result; + struct addrinfo hints; + int ret; + struct sockaddr_storage addr; + struct sockaddr_storage mask; + char *cidr_slash; + ListCell *line_item; + + line_item = list_head(line); + /* Check the record type. */ + token = lfirst(line_item); + if (strcmp(token, "local") == 0) + { + /* Get the database. */ + line_item = lnext(line_item); + if (!line_item) + goto hba_syntax; + db = lfirst(line_item); + + /* Get the user. */ + line_item = lnext(line_item); + if (!line_item) + goto hba_syntax; + user = lfirst(line_item); + + line_item = lnext(line_item); + if (!line_item) + goto hba_syntax; + + /* Read the rest of the line. */ + parse_hba_auth(&line_item, &frontend->auth_method, + &frontend->auth_arg, error_p); + if (*error_p) + goto hba_syntax; + + /* Disallow auth methods that always need TCP/IP sockets to work */ + /* + if (frontend->auth_method == uaKrb4 || + frontend->auth_method == uaKrb5) + goto hba_syntax; + */ + + /* Does not match if connection isn't AF_UNIX */ + if (!IS_AF_UNIX(frontend->raddr.addr.ss_family)) + return; + } + else if (strcmp(token, "host") == 0 + || strcmp(token, "hostssl") == 0 + || strcmp(token, "hostnossl") == 0) + { + if (token[4] == 's') /* "hostssl" */ + { +#ifdef USE_SSL + /* Record does not match if we are not on an SSL connection */ + if (!frontend->ssl) + return; + + /* Placeholder to require specific SSL level, perhaps? */ + /* Or a client certificate */ + + /* Since we were on SSL, proceed as with normal 'host' mode */ +#else + /* We don't accept this keyword at all if no SSL support */ + goto hba_syntax; +#endif + } +#ifdef USE_SSL + else if (token[4] == 'n') /* "hostnossl" */ + { + /* Record does not match if we are on an SSL connection */ + if (frontend->ssl) + return; + } +#endif + + /* Get the database. */ + line_item = lnext(line_item); + if (!line_item) + goto hba_syntax; + db = lfirst(line_item); + + /* Get the user. */ + line_item = lnext(line_item); + if (!line_item) + goto hba_syntax; + user = lfirst(line_item); + + /* Read the IP address field. (with or without CIDR netmask) */ + line_item = lnext(line_item); + if (!line_item) + goto hba_syntax; + token = lfirst(line_item); + + /* Check if it has a CIDR suffix and if so isolate it */ + cidr_slash = strchr(token, '/'); + if (cidr_slash) + *cidr_slash = '\0'; + + /* Get the IP address either way */ + hints.ai_flags = AI_NUMERICHOST; + hints.ai_family = PF_UNSPEC; + hints.ai_socktype = 0; + hints.ai_protocol = 0; + hints.ai_addrlen = 0; + hints.ai_canonname = NULL; + hints.ai_addr = NULL; + hints.ai_next = NULL; + + ret = getaddrinfo_all(token, NULL, &hints, &gai_result); + if (ret || !gai_result) + { + pool_log("invalid IP address \"%s\" in file \"%s\" line %d: %s", + token, hbaFileName, line_num, gai_strerror(ret)); + if (cidr_slash) + *cidr_slash = '/'; + if (gai_result) + freeaddrinfo_all(hints.ai_family, gai_result); + goto hba_other_error; + } + + if (cidr_slash) + *cidr_slash = '/'; + + memcpy(&addr, gai_result->ai_addr, gai_result->ai_addrlen); + freeaddrinfo_all(hints.ai_family, gai_result); + + /* Get the netmask */ + if (cidr_slash) + { + if (SockAddr_cidr_mask(&mask, cidr_slash + 1, addr.ss_family) < 0) + goto hba_syntax; + } + else + { + /* Read the mask field. */ + line_item = lnext(line_item); + if (!line_item) + goto hba_syntax; + token = lfirst(line_item); + + ret = getaddrinfo_all(token, NULL, &hints, &gai_result); + if (ret || !gai_result) + { + pool_log("invalid IP mask \"%s\" in file \"%s\" line %d: %s", + token, hbaFileName, line_num, gai_strerror(ret)); + if (gai_result) + freeaddrinfo_all(hints.ai_family, gai_result); + goto hba_other_error; + } + + memcpy(&mask, gai_result->ai_addr, gai_result->ai_addrlen); + freeaddrinfo_all(hints.ai_family, gai_result); + + if (addr.ss_family != mask.ss_family) + { + pool_log("IP address and mask do not match in file \"%s\" line %d", + hbaFileName, line_num); + goto hba_other_error; + } + } + + if (addr.ss_family != frontend->raddr.addr.ss_family) + { + /* + * Wrong address family. We allow only one case: if the file + * has IPv4 and the port is IPv6, promote the file address to + * IPv6 and try to match that way. + */ +#ifdef HAVE_IPV6 + if (addr.ss_family == AF_INET && frontend->raddr.addr.ss_family == AF_INET6) + { + promote_v4_to_v6_addr(&addr); + promote_v4_to_v6_mask(&mask); + } + else +#endif /* HAVE_IPV6 */ + { + /* Line doesn't match client port, so ignore it. */ + return; + } + } + + /* Ignore line if client port is not in the matching addr range. */ + if (!rangeSockAddr(&frontend->raddr.addr, &addr, &mask)) + return; + + /* Read the rest of the line. */ + line_item = lnext(line_item); + if (!line_item) + goto hba_syntax; + parse_hba_auth(&line_item, &frontend->auth_method, + &frontend->auth_arg, error_p); + if (*error_p) + goto hba_syntax; + } + else + goto hba_syntax; + + /* Does the entry match database and user? */ + /* + * duplicate db and username since strtok() in check_db() and check_user() + * will override '\001' with '\0'. + */ + db_tmp = strdup(db); + if (db_tmp == NULL) + { + pool_error("parse_hba: strdup failed: %s", strerror(errno)); + exit(1); + } + user_tmp = strdup(user); + if (user_tmp == NULL) + { + pool_error("parse_hba: strdup failed: %s", strerror(errno)); + exit(1); + } + if (!check_db(frontend->database, frontend->username, db_tmp)) + return; + if (!check_user(frontend->username, user_tmp)) + return; + free(db_tmp); + free(user_tmp); + + /* Success */ + *found_p = true; + return; + + hba_syntax: + if (line_item) + pool_log("invalid entry in file \"%s\" at line %d, token \"%s\"", + hbaFileName, line_num, (char *) lfirst(line_item)); + else + pool_log("missing field in file \"%s\" at end of line %d", + hbaFileName, line_num); + + /* Come here if suitable message already logged */ + hba_other_error: + *error_p = true; +} + + +/* + * Scan the rest of a host record (after the mask field) + * and return the interpretation of it as *userauth_p, *auth_arg_p, and + * *error_p. *line_item points to the next token of the line, and is + * advanced over successfully-read tokens. + */ +static void parse_hba_auth(ListCell **line_item, UserAuth *userauth_p, + char **auth_arg_p, bool *error_p) +{ + char *token; + + *auth_arg_p = NULL; + + if (!*line_item) + { + *error_p = true; + return; + } + + token = lfirst(*line_item); + if (strcmp(token, "trust") == 0) + *userauth_p = uaTrust; + /* + else if (strcmp(token, "ident") == 0) + *userauth_p = uaIdent; + else if (strcmp(token, "password") == 0) + *userauth_p = uaPassword; + else if (strcmp(token, "krb4") == 0) + *userauth_p = uaKrb4; + else if (strcmp(token, "krb5") == 0) + *userauth_p = uaKrb5; + */ + else if (strcmp(token, "reject") == 0) + *userauth_p = uaReject; + /* + else if (strcmp(token, "md5") == 0) + *userauth_p = uaMD5; + else if (strcmp(token, "crypt") == 0) + *userauth_p = uaCrypt; + */ +#ifdef USE_PAM + else if (strcmp(token, "pam") == 0) + *userauth_p = uaPAM; +#endif /* USE_PAM */ + else + { + *error_p = true; + return; + } + *line_item = lnext(*line_item); + + /* Get the authentication argument token, if any */ + if (*line_item) + { + token = lfirst(*line_item); + *auth_arg_p = strdup(token); + if (*auth_arg_p == NULL) + { + pool_error("parse_hba_auth: strdup failed: %s", strerror(errno)); + exit(1); + } + *line_item = lnext(*line_item); + /* If there is more on the line, it is an error */ + if (*line_item) + *error_p = true; + } +} + + +/* + * Check comma user list for a specific user, handle group names. + */ +static bool check_user(char *user, char *param_str) +{ + char *tok; + + for (tok = strtok(param_str, MULTI_VALUE_SEP); + tok != NULL; tok = strtok(NULL, MULTI_VALUE_SEP)) + { + if (tok[0] == '+') + { + /* + * pgpool cannot accept groups. commented lines below are the + * original code. + */ + pool_error("group token \"+\" is not supported in pgpool"); + return false; +/* if (check_group(tok + 1, user)) */ +/* return true; */ + } + else if (strcmp(tok, user) == 0 || strcmp(tok, "all\n") == 0) + return true; + } + + return false; +} + + +/* + * Check to see if db/user combination matches param string. + */ +static bool check_db(char *dbname, char *user, char *param_str) +{ + char *tok; + + for (tok = strtok(param_str, MULTI_VALUE_SEP); + tok != NULL; tok = strtok(NULL, MULTI_VALUE_SEP)) + { + if (strcmp(tok, "all\n") == 0) + return true; + else if (strcmp(tok, "sameuser\n") == 0) + { + if (strcmp(dbname, user) == 0) + return true; + } + else if (strcmp(tok, "samegroup\n") == 0) + { + /* + * pgpool cannot accept groups. commented lines below are the + * original code. + */ + pool_error("group token \"samegroup\" is not supported in pgpool"); + return false; +/* if (check_group(dbname, user)) */ +/* return true; */ + } + else if (strcmp(tok, dbname) == 0) + return true; + } + + return false; +} + + +/* + * tokenize the given file, storing the resulting data into two lists: + * a list of sublists, each sublist containing the tokens in a line of + * the file, and a list of line numbers. + * + * filename must be the absolute path to the target file. + */ +static void tokenize_file(const char *filename, FILE *file, + List **lines, List **line_nums) +{ + List *current_line = NIL; + int line_number = 1; + char *buf; + + *lines = *line_nums = NIL; + + while (!feof(file)) + { + buf = next_token_expand(filename, file); + + /* add token to list, unless we are at EOL or comment start */ + if (buf[0]) + { + if (current_line == NIL) + { + /* make a new line List, record its line number */ + current_line = lappend(current_line, buf); + *lines = lappend(*lines, current_line); + *line_nums = lappend_int(*line_nums, line_number); + } + else + { + /* append token to current line's list */ + current_line = lappend(current_line, buf); + } + } + else + { + /* we are at real or logical EOL, so force a new line List */ + current_line = NIL; + /* Advance line number whenever we reach EOL */ + line_number++; + /* Don't forget to free the next_token_expand result */ + free(buf); + } + } +} + + +static char * tokenize_inc_file(const char *outer_filename, + const char *inc_filename) +{ + char *inc_fullname; + FILE *inc_file; + List *inc_lines; + List *inc_line_nums; + ListCell *line; + char *comma_str; + + if (is_absolute_path(inc_filename)) + { + /* absolute path is taken as-is */ + inc_fullname = strdup(inc_filename); + if (inc_fullname == NULL) + { + pool_error("tokenize_inc_file: strdup failed: %s", strerror(errno)); + exit(1); + } + } + else + { + /* relative path is relative to dir of calling file */ + inc_fullname = (char *)malloc(strlen(outer_filename) + 1 + + strlen(inc_filename) + 1); + if (inc_fullname == NULL) + { + pool_error("tokenize_inc_file: malloc failed: %s", strerror(errno)); + exit(1); + } + strcpy(inc_fullname, outer_filename); + get_parent_directory(inc_fullname); + join_path_components(inc_fullname, inc_fullname, inc_filename); + canonicalize_path(inc_fullname); + } + + inc_file = fopen(inc_fullname, "r"); + if (inc_file == NULL) + { + char *returnVal; + + pool_error("could not open secondary authentication file \"@%s\" as \"%s\": reason: %s", + inc_filename, inc_fullname, strerror(errno)); + free(inc_fullname); + + /* return single space, it matches nothing */ + returnVal = strdup(" "); + if (returnVal == NULL) + { + pool_error("tokenize_inc_file: malloc failed: %s", strerror(errno)); + exit(1); + } + return returnVal; + } + + /* There is possible recursion here if the file contains @ */ + tokenize_file(inc_fullname, inc_file, &inc_lines, &inc_line_nums); + + /*FreeFile(inc_file);*/ + fclose(inc_file); + free(inc_fullname); + + /* Create comma-separated string from List */ + comma_str = strdup(""); + if (comma_str == NULL) + { + pool_error("tokenize_inc_file: strdup failed: %s", strerror(errno)); + exit(1); + } + foreach(line, inc_lines) + { + List *token_list = (List *) lfirst(line); + ListCell *token; + + foreach(token, token_list) + { + int oldlen = strlen(comma_str); + int needed; + + needed = oldlen + strlen(lfirst(token)) + 1; + if (oldlen > 0) + needed++; + comma_str = realloc(comma_str, needed); + if (comma_str == NULL) + { + pool_error("tokenize_inc_file: realloc failed: %s", strerror(errno)); + exit(1); + } + if (oldlen > 0) + strcat(comma_str, MULTI_VALUE_SEP); + strcat(comma_str, lfirst(token)); + } + } + + free_lines(&inc_lines, &inc_line_nums); + + /* if file is empty, return single space rather than empty string */ + if (strlen(comma_str) == 0) + { + char *returnVal; + + free(comma_str); + returnVal = strdup(" "); + if (returnVal == NULL) + { + pool_error("tokenize_inc_file: strdup failed: %s", strerror(errno)); + exit(1); + } + return returnVal; + } + + return comma_str; +} + + +/* + * isblank() exists in the ISO C99 spec, but it's not very portable yet, + * so provide our own version. + */ +static bool pg_isblank(const char c) +{ + return c == ' ' || c == '\t' || c == '\r'; +} + + +/* + * Tokenize file and handle file inclusion and comma lists. We have + * to break apart the commas to expand any file names then + * reconstruct with commas. + * + * The result is always a malloc'd string. If it's zero-length then + * we have reached EOL. + */ +static char * next_token_expand(const char *filename, FILE *file) +{ + char buf[MAX_TOKEN]; + char *comma_str; + bool trailing_comma; + char *incbuf; + int needed; + + comma_str = strdup(""); + if (comma_str == NULL) + { + pool_error("next_token_expand: strdup failed: %s", strerror(errno)); + exit(1); + } + + do + { + next_token(file, buf, sizeof(buf)); + if (!buf[0]) + break; + + if (buf[strlen(buf) - 1] == ',') + { + trailing_comma = true; + buf[strlen(buf) - 1] = '\0'; + } + else + trailing_comma = false; + + /* Is this referencing a file? */ + if (buf[0] == '@') + incbuf = tokenize_inc_file(filename, buf + 1); + else + { + incbuf = strdup(buf); + if (incbuf == NULL) + { + pool_error("next_token_expand: strdup failed: %s", strerror(errno)); + exit(1); + } + } + + needed = strlen(comma_str) + strlen(incbuf) + 1; + if (trailing_comma) + needed++; + comma_str = realloc(comma_str, needed); + if (comma_str == NULL) + { + pool_error("next_token_expand: realloc failed: %s", strerror(errno)); + exit(1); + } + strcat(comma_str, incbuf); + if (trailing_comma) + strcat(comma_str, MULTI_VALUE_SEP); + free(incbuf); + } while (trailing_comma); + + return comma_str; +} + + +/* + * Grab one token out of fp. Tokens are strings of non-blank + * characters bounded by blank characters, beginning of line, and + * end of line. Blank means space or tab. Return the token as + * *buf. Leave file positioned at the character immediately after the + * token or EOF, whichever comes first. If no more tokens on line, + * return empty string as *buf and position the file to the beginning + * of the next line or EOF, whichever comes first. Allow spaces in + * quoted strings. Terminate on unquoted commas. Handle + * comments. Treat unquoted keywords that might be user names or + * database names specially, by appending a newline to them. + */ +static void next_token(FILE *fp, char *buf, int bufsz) +{ + int c; + char *start_buf = buf; + char *end_buf = buf + (bufsz - 2); + bool in_quote = false; + bool was_quote = false; + bool saw_quote = false; + + /*Assert(end_buf > start_buf);*/ + + /* Move over initial whitespace and commas */ + while ((c = getc(fp)) != EOF && (pg_isblank(c) || c == ',')) + ; + + if (c == EOF || c == '\n') + { + *buf = '\0'; + return; + } + + /* + * Build a token in buf of next characters up to EOF, EOL, unquoted + * comma, or unquoted whitespace. + */ + while (c != EOF && c != '\n' && + (!pg_isblank(c) || in_quote == true)) + { + /* skip comments to EOL */ + if (c == '#' && !in_quote) + { + while ((c = getc(fp)) != EOF && c != '\n') + ; + /* If only comment, consume EOL too; return EOL */ + if (c != EOF && buf == start_buf) + c = getc(fp); + break; + } + + if (buf >= end_buf) + { + *buf = '\0'; + pool_log("authentication file token too long, skipping: \"%s\"", start_buf); + /* Discard remainder of line */ + while ((c = getc(fp)) != EOF && c != '\n') + ; + break; + } + + if (c != '"' || (c == '"' && was_quote)) + *buf++ = c; + + /* We pass back the comma so the caller knows there is more */ + if ((pg_isblank(c) || c == ',') && !in_quote) + break; + + /* Literal double-quote is two double-quotes */ + if (in_quote && c == '"') + was_quote = !was_quote; + else + was_quote = false; + + if (c == '"') + { + in_quote = !in_quote; + saw_quote = true; + } + + c = getc(fp); + } + + /* + * Put back the char right after the token (critical in case it is + * EOL, since we need to detect end-of-line at next call). + */ + if (c != EOF) + ungetc(c, fp); + + *buf = '\0'; + + if (!saw_quote && + (strcmp(start_buf, "all") == 0 || + strcmp(start_buf, "sameuser") == 0 || + strcmp(start_buf, "samegroup") == 0)) + { + /* append newline to a magical keyword */ + *buf++ = '\n'; + *buf = '\0'; + } +} + + +/* + * free memory used by lines and tokens built by tokenize_file() + */ +static void free_lines(List **lines, List **line_nums) +{ + if (*lines) + { + ListCell *line; + + foreach(line, *lines) + { + List *ln = lfirst(line); + ListCell *token; + + foreach(token, ln) + free(lfirst(token)); + + list_free(ln); + } + + list_free(*lines); + *lines = NIL; + } + + if (*line_nums) + { + list_free(*line_nums); + *line_nums = NIL; + } +} + + +#ifdef USE_PAM + +/* + * PAM conversation function + */ +static int pam_passwd_conv_proc(int num_msg, const struct pam_message ** msg, + struct pam_response ** resp, void *appdata_ptr) +{ + if (num_msg != 1 || msg[0]->msg_style != PAM_PROMPT_ECHO_OFF) + { + switch (msg[0]->msg_style) + { + case PAM_ERROR_MSG: + pool_log("error from underlying PAM layer: %s", + msg[0]->msg); + return PAM_CONV_ERR; + default: + pool_log("unsupported PAM conversation %d/%s", + msg[0]->msg_style, msg[0]->msg); + return PAM_CONV_ERR; + } + } + + if (!appdata_ptr) + { + /* + * Workaround for Solaris 2.6 where the PAM library is broken and + * does not pass appdata_ptr to the conversation routine + */ + appdata_ptr = pam_passwd; + } + + /* + * Password wasn't passed to PAM the first time around - let's go ask + * the client to send a password, which we then stuff into PAM. + */ + if (strlen(appdata_ptr) == 0) + { + char *passwd; + + sendAuthRequest(pam_frontend_kludge, AUTH_REQ_PASSWORD); + passwd = recv_password_packet(pam_frontend_kludge); + + if (passwd == NULL) + return PAM_CONV_ERR; /* client didn't want to send password */ + + if (strlen(passwd) == 0) + { + pool_log("empty password returned by client"); + return PAM_CONV_ERR; + } + appdata_ptr = passwd; + } + + /* + * PAM will free this memory in * pam_end() + */ + *resp = calloc(num_msg, sizeof(struct pam_response)); + if (!*resp) + { + /* originally, it was logged as LOG */ + pool_error("pam_passwd_conv_proc: calloc failed: %s", strerror(errno)); + return PAM_CONV_ERR; + } + + (*resp)[0].resp = strdup((char *) appdata_ptr); + if ((*resp)[0].resp == NULL) + { + pool_error("pam_passwd_conv_proc: strdup failed: %s", strerror(errno)); + exit(1); + } + (*resp)[0].resp_retcode = 0; + + return ((*resp)[0].resp ? PAM_SUCCESS : PAM_CONV_ERR); +} + + +/* + * Check authentication against PAM. + */ +static POOL_STATUS CheckPAMAuth(POOL_CONNECTION *frontend, char *user, char *password) +{ + int retval; + pam_handle_t *pamh = NULL; + + /* + * Apparently, Solaris 2.6 is broken, and needs ugly static variable + * workaround + */ + pam_passwd = password; + + /* + * Set the application data portion of the conversation struct This is + * later used inside the PAM conversation to pass the password to the + * authentication module. + */ + pam_passw_conv.appdata_ptr = (char *) password; /* from password above, + * not allocated */ + + /* Optionally, one can set the service name in pool_hba.conf */ + if (frontend->auth_arg && frontend->auth_arg[0] != '\0') + retval = pam_start(frontend->auth_arg, "pgpool@", + &pam_passw_conv, &pamh); + else + retval = pam_start(PGPOOL_PAM_SERVICE, "pgpool@", + &pam_passw_conv, &pamh); + + if (retval != PAM_SUCCESS) + { + pool_log("could not create PAM authenticator: %s", + pam_strerror(pamh, retval)); + pam_passwd = NULL; /* Unset pam_passwd */ + return POOL_ERROR; + } + + retval = pam_set_item(pamh, PAM_USER, user); + if (retval != PAM_SUCCESS) + { + pool_log("pam_set_item(PAM_USER) failed: %s", + pam_strerror(pamh, retval)); + pam_passwd = NULL; /* Unset pam_passwd */ + return POOL_ERROR; + } + + retval = pam_set_item(pamh, PAM_CONV, &pam_passw_conv); + if (retval != PAM_SUCCESS) + { + pool_log("pam_set_item(PAM_CONV) failed: %s", + pam_strerror(pamh, retval)); + pam_passwd = NULL; /* Unset pam_passwd */ + return POOL_ERROR; + } + + retval = pam_authenticate(pamh, 0); + if (retval != PAM_SUCCESS) /* service name does not exist */ + { + pool_log("pam_authenticate failed: %s", + pam_strerror(pamh, retval)); + pam_passwd = NULL; /* Unset pam_passwd */ + return POOL_ERROR; + } + + retval = pam_acct_mgmt(pamh, 0); + if (retval != PAM_SUCCESS) + { + pool_log("pam_acct_mgmt failed: %s", + pam_strerror(pamh, retval)); + pam_passwd = NULL; /* Unset pam_passwd */ + return POOL_ERROR; + } + + retval = pam_end(pamh, retval); + if (retval != PAM_SUCCESS) + { + pool_log("could not release PAM authenticator: %s", + pam_strerror(pamh, retval)); + } + + pam_passwd = NULL; /* Unset pam_passwd */ + + return (retval == PAM_SUCCESS ? POOL_CONTINUE : POOL_ERROR); +} + +#endif /* USE_PAM */ diff --git a/pool_hba.conf.sample b/pool_hba.conf.sample new file mode 100644 index 0000000..b2fe374 --- /dev/null +++ b/pool_hba.conf.sample @@ -0,0 +1,69 @@ +# pgpool Client Authentication Configuration File +# =============================================== +# +# The format rule in this file follows the rules in the PostgreSQL +# Administrator's Guide. Refer to chapter "Client Authentication" for a +# complete description. A short synopsis follows. +# +# This file controls: which hosts are allowed to connect, how clients +# are authenticated, which user names they can use, which databases they +# can access. Records take one of these forms: +# +# local DATABASE USER METHOD [OPTION] +# host DATABASE USER CIDR-ADDRESS METHOD [OPTION] +# hostnossl DATABASE USER CIDR-ADDRESS METHOD [OPTION] +# +# (The uppercase items must be replaced by actual values.) +# +# The first field is the connection type: "local" is a Unix-domain socket, +# "host" is a plain TCP/IP socket since pgpool currently doest not support +# SSL connection. "hostnossl" is also a plain TCP/IP socket. +# +# DATABASE can be "all", "sameuser", a database name, or a comma-separated +# list thereof. Note that "samegroup" like in PostgreSQL's pg_hba.conf +# file is not supported, since pgpool does not know which group a user +# belongs to. Also note that the database specified here may not exist in +# the backend PostgreSQL. pgpool will authenticate based on the database's +# name, not based on whether it exists or not. +# +# USER can be "all", a user name, or a comma-separated list thereof. In +# both the DATABASE and USER fields you can also write a file name prefixed +# with "@" to include names from a separate file. Note that a group name +# prefixed with "+" like in PostgreSQL's pg_hba.conf file is not supported +# because of the same reason as "samegroup" token. Also note that a user +# name specified here may not exist in the backend PostgreSQL. pgpool will +# authenticate based on the user's name, not based on whether he/she exists. +# +# CIDR-ADDRESS specifies the set of hosts the record matches. +# It is made up of an IP address and a CIDR mask that is an integer +# (between 0 and 32 (IPv4) that specifies the number of significant bits in +# the mask. Alternatively, you can write an IP address and netmask in +# separate columns to specify the set of hosts. +# +# METHOD can be "trust", "reject", or "pam". Note that "pam" sends passwords +# in clear text. +# +# OPTION is the name of the PAM service. Default service name is "pgpool" +# +# Database and user names containing spaces, commas, quotes and other special +# characters must be quoted. Quoting one of the keywords "all" or "sameuser" +# makes the name lose its special character, and just match a database or +# username with that name. +# +# This file is read on pgpool startup. If you edit the file on a running +# system, you have to restart the pgpool for the changes to take effect. + +# Put your actual configuration here +# ---------------------------------- +# +# If you want to allow non-local connections, you need to add more +# "host" records. In that case you will also need to make pgpool listen +# on a non-local interface via the listen_addresses configuration parameter. +# + +# TYPE DATABASE USER CIDR-ADDRESS METHOD + +# "local" is for Unix domain socket connections only +local all all trust +# IPv4 local connections: +host all all 127.0.0.1/32 trust diff --git a/pool_ip.c b/pool_ip.c new file mode 100644 index 0000000..41571ab --- /dev/null +++ b/pool_ip.c @@ -0,0 +1,498 @@ +/* -*-pgsql-c-*- */ +/* + * + * $Header$ + * + * This file was imported from PostgreSQL 8.0.8 source code. + * See below for the copyright and description. + * + * pgpool: a language independent connection pool server for PostgreSQL + * written by Tatsuo Ishii + * + * Portions Copyright (c) 2003-2007 PgPool Global Development Group + * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * Permission to use, copy, modify, and distribute this software and + * its documentation for any purpose 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 + * author not be used in advertising or publicity pertaining to + * distribution of the software without specific, written prior + * permission. The author makes no representations about the + * suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * ------------------------------ + * + * + * This file and the IPV6 implementation were initially provided by + * Nigel Kukard , Linux Based Systems Design + * http://www.lbsd.net. + * + * pool_ip.c.: IPv6-aware network access. + * + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include "pool_ip.h" + + +static int rangeSockAddrAF_INET(const struct sockaddr_in * addr, + const struct sockaddr_in * netaddr, + const struct sockaddr_in * netmask); + +#ifdef HAVE_IPV6 +static int rangeSockAddrAF_INET6(const struct sockaddr_in6 * addr, + const struct sockaddr_in6 * netaddr, + const struct sockaddr_in6 * netmask); +#endif + +static int getaddrinfo_unix(const char *path, + const struct addrinfo * hintsp, + struct addrinfo ** result); + +static int getnameinfo_unix(const struct sockaddr_un * sa, int salen, + char *node, int nodelen, + char *service, int servicelen, + int flags); + + +/* + * getaddrinfo_all - get address info for Unix, IPv4 and IPv6 sockets + */ +int +getaddrinfo_all(const char *hostname, const char *servname, + const struct addrinfo * hintp, struct addrinfo ** result) +{ + /* not all versions of getaddrinfo() zero *result on failure */ + *result = NULL; + + if (hintp->ai_family == AF_UNIX) + return getaddrinfo_unix(servname, hintp, result); + + /* NULL has special meaning to getaddrinfo(). */ + return getaddrinfo((!hostname || hostname[0] == '\0') ? NULL : hostname, + servname, hintp, result); +} + + +/* + * freeaddrinfo_all - free addrinfo structures for IPv4, IPv6, or Unix + * + * Note: the ai_family field of the original hint structure must be passed + * so that we can tell whether the addrinfo struct was built by the system's + * getaddrinfo() routine or our own getaddrinfo_unix() routine. Some versions + * of getaddrinfo() might be willing to return AF_UNIX addresses, so it's + * not safe to look at ai_family in the addrinfo itself. + */ +void +freeaddrinfo_all(int hint_ai_family, struct addrinfo * ai) +{ + if (hint_ai_family == AF_UNIX) + { + /* struct was built by getaddrinfo_unix (see getaddrinfo_all) */ + while (ai != NULL) + { + struct addrinfo *p = ai; + + ai = ai->ai_next; + free(p->ai_addr); + free(p); + } + } + else + { + /* struct was built by getaddrinfo() */ + if (ai != NULL) + freeaddrinfo(ai); + } +} + + +/* + * getnameinfo_all - get name info for Unix, IPv4 and IPv6 sockets + * + * The API of this routine differs from the standard getnameinfo() definition + * in two ways: first, the addr parameter is declared as sockaddr_storage + * rather than struct sockaddr, and second, the node and service fields are + * guaranteed to be filled with something even on failure return. + */ +int +getnameinfo_all(const struct sockaddr_storage * addr, int salen, + char *node, int nodelen, + char *service, int servicelen, + int flags) +{ + int rc; + + if (addr && addr->ss_family == AF_UNIX) + rc = getnameinfo_unix((const struct sockaddr_un *) addr, salen, + node, nodelen, + service, servicelen, + flags); + else + rc = getnameinfo((const struct sockaddr *) addr, salen, + node, nodelen, + service, servicelen, + flags); + + if (rc != 0) + { + if (node) + strncpy(node, "???", nodelen); + if (service) + strncpy(service, "???", servicelen); + } + + return rc; +} + + +const char * +gai_strerror(int errcode) +{ + int hcode; + + switch (errcode) + { + case EAI_NONAME: + hcode = HOST_NOT_FOUND; + break; + case EAI_AGAIN: + hcode = TRY_AGAIN; + break; + case EAI_FAIL: + default: + hcode = NO_RECOVERY; + break; + } + + return hstrerror(hcode); +} + + +/* + * getaddrinfo_unix - get unix socket info using IPv6-compatible API + * + * Bugs: only one addrinfo is set even though hintsp is NULL or + * ai_socktype is 0 + * AI_CANONNAME is not supported. + * + */ +static int +getaddrinfo_unix(const char *path, const struct addrinfo * hintsp, + struct addrinfo ** result) +{ + struct addrinfo hints; + struct addrinfo *aip; + struct sockaddr_un *unp; + + *result = NULL; + + memset(&hints, 0, sizeof(hints)); + + if (strlen(path) >= sizeof(unp->sun_path)) + return EAI_FAIL; + + if (hintsp == NULL) + { + hints.ai_family = AF_UNIX; + hints.ai_socktype = SOCK_STREAM; + } + else + memcpy(&hints, hintsp, sizeof(hints)); + + if (hints.ai_socktype == 0) + hints.ai_socktype = SOCK_STREAM; + + if (hints.ai_family != AF_UNIX) + { + /* shouldn't have been called */ + return EAI_FAIL; + } + + aip = calloc(1, sizeof(struct addrinfo)); + if (aip == NULL) + return EAI_MEMORY; + + unp = calloc(1, sizeof(struct sockaddr_un)); + if (unp == NULL) + { + free(aip); + return EAI_MEMORY; + } + + aip->ai_family = AF_UNIX; + aip->ai_socktype = hints.ai_socktype; + aip->ai_protocol = hints.ai_protocol; + aip->ai_next = NULL; + aip->ai_canonname = NULL; + *result = aip; + + unp->sun_family = AF_UNIX; + aip->ai_addr = (struct sockaddr *) unp; + aip->ai_addrlen = sizeof(struct sockaddr_un); + + strcpy(unp->sun_path, path); + +#ifdef HAVE_STRUCT_SOCKADDR_STORAGE_SS_LEN + unp->sun_len = sizeof(struct sockaddr_un); +#endif + + return 0; +} + +/* + * Convert an address to a hostname. + */ +static int +getnameinfo_unix(const struct sockaddr_un * sa, int salen, + char *node, int nodelen, + char *service, int servicelen, + int flags) +{ + int ret = -1; + + /* Invalid arguments. */ + if (sa == NULL || sa->sun_family != AF_UNIX || + (node == NULL && service == NULL)) + return EAI_FAIL; + + /* We don't support those. */ + if ((node && !(flags & NI_NUMERICHOST)) + || (service && !(flags & NI_NUMERICSERV))) + return EAI_FAIL; + + if (node) + { + ret = snprintf(node, nodelen, "%s", "[local]"); + if (ret == -1 || ret > nodelen) + return EAI_MEMORY; + } + + if (service) + { + ret = snprintf(service, servicelen, "%s", sa->sun_path); + if (ret == -1 || ret > servicelen) + return EAI_MEMORY; + } + + return 0; +} + + +/* + * rangeSockAddr - is addr within the subnet specified by netaddr/netmask ? + * + * Note: caller must already have verified that all three addresses are + * in the same address family; and AF_UNIX addresses are not supported. + */ +int +rangeSockAddr(const struct sockaddr_storage * addr, + const struct sockaddr_storage * netaddr, + const struct sockaddr_storage * netmask) +{ + if (addr->ss_family == AF_INET) + return rangeSockAddrAF_INET((struct sockaddr_in *) addr, + (struct sockaddr_in *) netaddr, + (struct sockaddr_in *) netmask); +#ifdef HAVE_IPV6 + else if (addr->ss_family == AF_INET6) + return rangeSockAddrAF_INET6((struct sockaddr_in6 *) addr, + (struct sockaddr_in6 *) netaddr, + (struct sockaddr_in6 *) netmask); +#endif + else + return 0; +} + +static int +rangeSockAddrAF_INET(const struct sockaddr_in * addr, + const struct sockaddr_in * netaddr, + const struct sockaddr_in * netmask) +{ + if (((addr->sin_addr.s_addr ^ netaddr->sin_addr.s_addr) & + netmask->sin_addr.s_addr) == 0) + return 1; + else + return 0; +} + + +#ifdef HAVE_IPV6 +static int +rangeSockAddrAF_INET6(const struct sockaddr_in6 * addr, + const struct sockaddr_in6 * netaddr, + const struct sockaddr_in6 * netmask) +{ + int i; + + for (i = 0; i < 16; i++) + { + if (((addr->sin6_addr.s6_addr[i] ^ netaddr->sin6_addr.s6_addr[i]) & + netmask->sin6_addr.s6_addr[i]) != 0) + return 0; + } + + return 1; +} +#endif + +/* + * SockAddr_cidr_mask - make a network mask of the appropriate family + * and required number of significant bits + * + * The resulting mask is placed in *mask, which had better be big enough. + * + * Return value is 0 if okay, -1 if not. + */ +int +SockAddr_cidr_mask(struct sockaddr_storage * mask, char *numbits, int family) +{ + long bits; + char *endptr; + + bits = strtol(numbits, &endptr, 10); + + if (*numbits == '\0' || *endptr != '\0') + return -1; + + switch (family) + { + case AF_INET: + { + struct sockaddr_in mask4; + long maskl; + + if (bits < 0 || bits > 32) + return -1; + /* avoid "x << 32", which is not portable */ + if (bits > 0) + maskl = (0xffffffffUL << (32 - (int) bits)) + & 0xffffffffUL; + else + maskl = 0; + mask4.sin_addr.s_addr = htonl(maskl); + memcpy(mask, &mask4, sizeof(mask4)); + break; + } + +#ifdef HAVE_IPV6 + case AF_INET6: + { + struct sockaddr_in6 mask6; + int i; + + if (bits < 0 || bits > 128) + return -1; + for (i = 0; i < 16; i++) + { + if (bits <= 0) + mask6.sin6_addr.s6_addr[i] = 0; + else if (bits >= 8) + mask6.sin6_addr.s6_addr[i] = 0xff; + else + { + mask6.sin6_addr.s6_addr[i] = + (0xff << (8 - (int) bits)) & 0xff; + } + bits -= 8; + } + memcpy(mask, &mask6, sizeof(mask6)); + break; + } +#endif + default: + return -1; + } + + mask->ss_family = family; + return 0; +} + + +#ifdef HAVE_IPV6 + +/* + * promote_v4_to_v6_addr --- convert an AF_INET addr to AF_INET6, using + * the standard convention for IPv4 addresses mapped into IPv6 world + * + * The passed addr is modified in place; be sure it is large enough to + * hold the result! Note that we only worry about setting the fields + * that rangeSockAddr will look at. + */ +void +promote_v4_to_v6_addr(struct sockaddr_storage * addr) +{ + struct sockaddr_in addr4; + struct sockaddr_in6 addr6; + uint32 ip4addr; + + memcpy(&addr4, addr, sizeof(addr4)); + ip4addr = ntohl(addr4.sin_addr.s_addr); + + memset(&addr6, 0, sizeof(addr6)); + + addr6.sin6_family = AF_INET6; + + addr6.sin6_addr.s6_addr[10] = 0xff; + addr6.sin6_addr.s6_addr[11] = 0xff; + addr6.sin6_addr.s6_addr[12] = (ip4addr >> 24) & 0xFF; + addr6.sin6_addr.s6_addr[13] = (ip4addr >> 16) & 0xFF; + addr6.sin6_addr.s6_addr[14] = (ip4addr >> 8) & 0xFF; + addr6.sin6_addr.s6_addr[15] = (ip4addr) & 0xFF; + + memcpy(addr, &addr6, sizeof(addr6)); +} + +/* + * promote_v4_to_v6_mask --- convert an AF_INET netmask to AF_INET6, using + * the standard convention for IPv4 addresses mapped into IPv6 world + * + * This must be different from promote_v4_to_v6_addr because we want to + * set the high-order bits to 1's not 0's. + * + * The passed addr is modified in place; be sure it is large enough to + * hold the result! Note that we only worry about setting the fields + * that rangeSockAddr will look at. + */ +void +promote_v4_to_v6_mask(struct sockaddr_storage * addr) +{ + struct sockaddr_in addr4; + struct sockaddr_in6 addr6; + uint32 ip4addr; + int i; + + memcpy(&addr4, addr, sizeof(addr4)); + ip4addr = ntohl(addr4.sin_addr.s_addr); + + memset(&addr6, 0, sizeof(addr6)); + + addr6.sin6_family = AF_INET6; + + for (i = 0; i < 12; i++) + addr6.sin6_addr.s6_addr[i] = 0xff; + + addr6.sin6_addr.s6_addr[12] = (ip4addr >> 24) & 0xFF; + addr6.sin6_addr.s6_addr[13] = (ip4addr >> 16) & 0xFF; + addr6.sin6_addr.s6_addr[14] = (ip4addr >> 8) & 0xFF; + addr6.sin6_addr.s6_addr[15] = (ip4addr) & 0xFF; + + memcpy(addr, &addr6, sizeof(addr6)); +} + +#endif /* HAVE_IPV6 */ diff --git a/pool_ip.h b/pool_ip.h new file mode 100644 index 0000000..12a8cb6 --- /dev/null +++ b/pool_ip.h @@ -0,0 +1,63 @@ +/* -*-pgsql-c-*- */ +/* + * + * $Header$ + * + * This file was imported from PostgreSQL 8.0.8 source code. + * See below for the copyright and description. + * + * pgpool: a language independent connection pool server for PostgreSQL + * written by Tatsuo Ishii + * + * Portions Copyright (c) 2003-2007 PgPool Global Development Group + * Portions Copyright (c) 2003-2005, PostgreSQL Global Development Group + * + * Permission to use, copy, modify, and distribute this software and + * its documentation for any purpose 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 + * author not be used in advertising or publicity pertaining to + * distribution of the software without specific, written prior + * permission. The author makes no representations about the + * suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * pool_ip.h.: Definitions for IPv6-aware network access. + * + */ + +#ifndef POOL_IP_H +#define POOL_IP_H + +#include "pool_type.h" + +extern int getaddrinfo_all(const char *hostname, const char *servname, + const struct addrinfo * hintp, + struct addrinfo ** result); +extern void freeaddrinfo_all(int hint_ai_family, struct addrinfo * ai); + +extern int getnameinfo_all(const struct sockaddr_storage * addr, int salen, + char *node, int nodelen, + char *service, int servicelen, + int flags); + +extern int rangeSockAddr(const struct sockaddr_storage * addr, + const struct sockaddr_storage * netaddr, + const struct sockaddr_storage * netmask); + +extern int SockAddr_cidr_mask(struct sockaddr_storage * mask, + char *numbits, int family); + +/* imported from PostgreSQL getaddrinfo.c */ +extern const char * gai_strerror(int errcode); + +#ifdef HAVE_IPV6 +extern void promote_v4_to_v6_addr(struct sockaddr_storage * addr); +extern void promote_v4_to_v6_mask(struct sockaddr_storage * addr); +#endif + +#define IS_AF_INET(fam) ((fam) == AF_INET) +#define IS_AF_UNIX(fam) ((fam) == AF_UNIX) + +#endif /* IP_H */ diff --git a/pool_list.c b/pool_list.c new file mode 100644 index 0000000..6e31be6 --- /dev/null +++ b/pool_list.c @@ -0,0 +1,171 @@ +/* -*-pgsql-c-*- */ +/* + * + * $Header$ + * + * pgpool: a language independent connection pool server for PostgreSQL + * written by Tatsuo Ishii + * + * Portions Copyright (c) 2003-2007, PgPool Global Development Group + * Portions Copyright (c) 2004, PostgreSQL Global Development Group + * + * Permission to use, copy, modify, and distribute this software and + * its documentation for any purpose 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 + * author not be used in advertising or publicity pertaining to + * distribution of the software without specific, written prior + * permission. The author makes no representations about the + * suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * pool_list.c.: Implementation of singly-linked homogeneous lists + * + */ + +#include +#include + +#include "pool.h" +#include "pool_type.h" +#include "pool_list.h" + +static List * new_list(void); +/* static void new_head_cell(List *list); */ +static void new_tail_cell(List *list); +static void list_free_private(List *list, bool deep); + +#ifndef __GNUC__ + +ListCell * list_head(List *l) +{ + return l ? l->head : NULL; +} + +ListCell * list_tail(List *l) +{ + return l ? l->tail : NULL; +} + +int list_length(List *l) +{ + return l ? l->length : 0; +} + +#endif /* __GNUC__ */ + +List * lappend(List *list, void *datum) +{ + if (list == NIL) + list = new_list(); + else + new_tail_cell(list); + + lfirst(list->tail) = datum; + + return list; +} + +List * lappend_int(List *list, int datum) +{ + if (list == NIL) + list = new_list(); + else + new_tail_cell(list); + + lfirst_int(list->tail) = datum; + + return list; +} + +static List * new_list(void) +{ + List *new_list; + ListCell *new_head; + + new_head = (ListCell *)malloc(sizeof(*new_head)); + if (new_head == NULL) + { + pool_error("new_list: malloc failed: %s", strerror(errno)); + exit(1); + } + new_head->next = NULL; + + new_list = (List *)malloc(sizeof(*new_list)); + if (new_list == NULL) + { + pool_error("new_list: malloc failed: %s", strerror(errno)); + exit(1); + } + new_list->length = 1; + new_list->head = new_head; + new_list->tail = new_head; + + return new_list; +} + +#ifdef NOT_USED +static void new_head_cell(List *list) +{ + ListCell *new_head; + + new_head = (ListCell *)malloc(sizeof(*new_head)); + if (new_head == NULL) + { + pool_error("new_head_cell: malloc failed: %s", strerror(errno)); + exit(1); + } + new_head->next = list->head; + + list->head = new_head; + list->length++; +} +#endif + +static void new_tail_cell(List *list) +{ + ListCell *new_tail; + + new_tail = (ListCell *)malloc(sizeof(*new_tail)); + if (new_tail == NULL) + { + pool_error("new_tail_cell: malloc failed: %s", strerror(errno)); + exit(1); + } + new_tail->next = NULL; + + list->tail->next = new_tail; + list->tail = new_tail; + list->length++; +} + +/* + * free all storage in a list, but not the pointed-to elements + */ +void list_free(List *list) +{ + list_free_private(list, false); +} + +/* + * free all storage in a list, and the pointed-to elements iff deep is true + */ +static void list_free_private(List *list, bool deep) +{ + ListCell *cell; + + cell = list_head(list); + while (cell != NULL) + { + ListCell *tmp = cell; + + cell = lnext(cell); + if (deep) + free(lfirst(tmp)); + free(tmp); + } + + if (list) + free(list); +} diff --git a/pool_list.h b/pool_list.h new file mode 100644 index 0000000..e13e07c --- /dev/null +++ b/pool_list.h @@ -0,0 +1,95 @@ +/* -*-pgsql-c-*- */ +/* + * + * $Header$ + * + * pgpool: a language independent connection pool server for PostgreSQL + * written by Tatsuo Ishii + * + * Portions Copyright (c) 2003-2007, PgPool Global Development Group + * Portions Copyright (c) 2004, PostgreSQL Global Development Group + * + * Permission to use, copy, modify, and distribute this software and + * its documentation for any purpose 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 + * author not be used in advertising or publicity pertaining to + * distribution of the software without specific, written prior + * permission. The author makes no representations about the + * suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * pool_list.h.: interface to pool_list.c + * + */ + +#ifndef POOL_LIST_H +#define POOL_LIST_H + +#include + +#define NIL ((List *) NULL) + +#define lnext(lc) ((lc)->next) +#define lfirst(lc) ((lc)->data.ptr_value) +#define lfirst_int(lc) ((lc)->data.int_value) +#define foreach(cell, l) \ + for ((cell) = list_head(l); (cell) != NULL; (cell) = lnext(cell)) +#define forboth(cell1, list1, cell2, list2) \ + for ((cell1) = list_head(list1), (cell2) = list_head(list2); \ + (cell1) != NULL && (cell2) != NULL; \ + (cell1) = lnext(cell1), (cell2) = lnext(cell2)) + +typedef struct ListCell ListCell; + +typedef struct List +{ + int length; + ListCell *head; + ListCell *tail; +} List; + +struct ListCell +{ + union + { + void *ptr_value; + int int_value; + } data; + ListCell *next; +}; + +#ifdef __GNUC__ + +static __inline__ ListCell * +list_head(List *l) +{ + return l ? l->head : NULL; +} + +static __inline__ ListCell * +list_tail(List *l) +{ + return l ? l->tail : NULL; +} + +static __inline__ int +list_length(List *l) +{ + return l ? l->length : 0; +} + +#else + +extern ListCell * list_head(List *l); +extern ListCell * list_tail(List *l); +extern int list_length(List *l); + +#endif /* __GNUC__ */ + +extern List * lappend(List *list, void *datum); +extern List * lappend_int(List *list, int datum); +extern void list_free(List *list); + +#endif /* POOL_LIST_H */ diff --git a/pool_path.c b/pool_path.c new file mode 100644 index 0000000..7129f17 --- /dev/null +++ b/pool_path.c @@ -0,0 +1,193 @@ +/* -*-pgsql-c-*- */ +/* + * + * $Header$ + * + * pgpool: a language independent connection pool server for PostgreSQL + * written by Tatsuo Ishii + * + * Portions Copyright (c) 2003-2007, PgPool Global Development Group + * Portions Copyright (c) 2004, PostgreSQL Global Development Group + * + * Permission to use, copy, modify, and distribute this software and + * its documentation for any purpose 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 + * author not be used in advertising or publicity pertaining to + * distribution of the software without specific, written prior + * permission. The author makes no representations about the + * suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * pool_path.c.: small functions to manipulate paths + * + */ + +#include "pool_type.h" +#include "pool_path.h" +#include +#include + +static void trim_directory(char *path); +static void trim_trailing_separator(char *path); + +/* + * get_parent_directory + * + * Modify the given string in-place to name the parent directory of the + * named file. + */ +void get_parent_directory(char *path) +{ + trim_directory(path); +} + + +/* + * trim_directory + * + * Trim trailing directory from path, that is, remove any trailing slashes, + * the last pathname component, and the slash just ahead of it --- but never + * remove a leading slash. + */ +static void trim_directory(char *path) +{ + char *p; + + if (path[0] == '\0') + return; + + /* back up over trailing slash(es) */ + for (p = path + strlen(path) - 1; IS_DIR_SEP(*p) && p > path; p--); + + /* back up over directory name */ + for (; !IS_DIR_SEP(*p) && p > path; p--); + + /* if multiple slashes before directory name, remove 'em all */ + for (; p > path && IS_DIR_SEP(*(p - 1)); p--); + + /* don't erase a leading slash */ + if (p == path && IS_DIR_SEP(*p)) + p++; + + *p = '\0'; +} + + +/* + * join_path_components - join two path components, inserting a slash + * + * ret_path is the output area (must be of size MAXPGPATH) + * + * ret_path can be the same as head, but not the same as tail. + */ +void join_path_components(char *ret_path, const char *head, const char *tail) +{ + if (ret_path != head) + StrNCpy(ret_path, head, MAXPGPATH); + + /* + * Remove any leading "." and ".." in the tail component, + * adjusting head as needed. + */ + for (;;) + { + if (tail[0] == '.' && IS_DIR_SEP(tail[1])) + { + tail += 2; + } + else if (tail[0] == '.' && tail[1] == '\0') + { + tail += 1; + break; + } + else if (tail[0] == '.' && tail[1] == '.' && IS_DIR_SEP(tail[2])) + { + trim_directory(ret_path); + tail += 3; + } + else if (tail[0] == '.' && tail[1] == '.' && tail[2] == '\0') + { + trim_directory(ret_path); + tail += 2; + break; + } + else + break; + } + + if (*tail) + snprintf(ret_path + strlen(ret_path), MAXPGPATH - strlen(ret_path), "/%s", tail); +} + + +/* + * Clean up path by: + * o remove trailing slash + * o remove duplicate adjacent separators + * o remove trailing '.' + * o process trailing '..' ourselves + */ +void canonicalize_path(char *path) +{ + char *p, *to_p; + bool was_sep = false; + + /* + * Removing the trailing slash on a path means we never get ugly + * double trailing slashes. + */ + trim_trailing_separator(path); + + /* + * Remove duplicate adjacent separators + */ + p = path; + to_p = p; + for (; *p; p++, to_p++) + { + /* Handle many adjacent slashes, like "/a///b" */ + while (*p == '/' && was_sep) + p++; + if (to_p != p) + *to_p = *p; + was_sep = (*p == '/'); + } + *to_p = '\0'; + + /* + * Remove any trailing uses of "." and process ".." ourselves + */ + for (;;) + { + int len = strlen(path); + + if (len > 2 && strcmp(path + len - 2, "/.") == 0) + trim_directory(path); + else if (len > 3 && strcmp(path + len - 3, "/..") == 0) + { + trim_directory(path); + trim_directory(path); + /* remove directory above */ + } + else + break; + } +} + + +/* + * trim_trailing_separator + * + * trim off trailing slashes, but not a leading slash + */ +static void trim_trailing_separator(char *path) +{ + char *p; + + p = path + strlen(path); + if (p > path) + for (p--; p > path && IS_DIR_SEP(*p); p--) + *p = '\0'; +} diff --git a/pool_path.h b/pool_path.h new file mode 100644 index 0000000..a1cc9a4 --- /dev/null +++ b/pool_path.h @@ -0,0 +1,81 @@ +/* -*-pgsql-c-*- */ +/* + * + * $Header$ + * + * pgpool: a language independent connection pool server for PostgreSQL + * written by Tatsuo Ishii + * + * Portions Copyright (c) 2003-2007, PgPool Global Development Group + * Portions Copyright (c) 2004, PostgreSQL Global Development Group + * + * Permission to use, copy, modify, and distribute this software and + * its documentation for any purpose 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 + * author not be used in advertising or publicity pertaining to + * distribution of the software without specific, written prior + * permission. The author makes no representations about the + * suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * pool_path.h.: interface to pool_path.c + * + */ + +#ifndef POOL_PATH_H +#define POOL_PATH_H + +/* + * MAXPGPATH: standard size of a pathname buffer in PostgreSQL (hence, + * maximum usable pathname length is one less). + * + * We'd use a standard system header symbol for this, if there weren't + * so many to choose from: MAXPATHLEN, MAX_PATH, PATH_MAX are all + * defined by different "standards", and often have different values + * on the same platform! So we just punt and use a reasonably + * generous setting here. + */ +#define MAXPGPATH 1024 + +#define IS_DIR_SEP(ch) ((ch) == '/') +#define is_absolute_path(filename) \ +( \ + ((filename)[0] == '/') \ +) + +/* + * StrNCpy + * Like standard library function strncpy(), except that result string + * is guaranteed to be null-terminated --- that is, at most N-1 bytes + * of the source string will be kept. + * Also, the macro returns no result (too hard to do that without + * evaluating the arguments multiple times, which seems worse). + * + * BTW: when you need to copy a non-null-terminated string (like a text + * datum) and add a null, do not do it with StrNCpy(..., len+1). That + * might seem to work, but it fetches one byte more than there is in the + * text object. One fine day you'll have a SIGSEGV because there isn't + * another byte before the end of memory. Don't laugh, we've had real + * live bug reports from real live users over exactly this mistake. + * Do it honestly with "memcpy(dst,src,len); dst[len] = '\0';", instead. + */ +#define StrNCpy(dst,src,len) \ + do \ + { \ + char * _dst = (dst); \ + size_t _len = (len); \ +\ + if (_len > 0) \ + { \ + strncpy(_dst, (src), _len); \ + _dst[_len-1] = '\0'; \ + } \ + } while (0) + +extern void get_parent_directory(char *path); +extern void join_path_components(char *ret_path, const char *head, const char *tail); +extern void canonicalize_path(char *path); + +#endif /* POOL_PATH_H */ diff --git a/pool_process_query.c b/pool_process_query.c index c24ce3c..a51d034 100644 --- a/pool_process_query.c +++ b/pool_process_query.c @@ -2243,6 +2243,21 @@ static void process_reporting(POOL_CONNECTION *frontend, POOL_CONNECTION_POOL *b status[i].desc = "number of queries in reset_query_list"; i++; + status[i].name = "log_statement"; + snprintf(status[i].value, MAXVALLEN, "%d", pool_config.log_statement); + status[i].desc = "if true, print all statements to the log"; + i++; + + status[i].name = "log_connections"; + snprintf(status[i].value, MAXVALLEN, "%d", pool_config.log_connections); + status[i].desc = "if true, print incoming connections to the log"; + i++; + + status[i].name = "enable_pool_hba"; + snprintf(status[i].value, MAXVALLEN, "%d", pool_config.enable_pool_hba); + status[i].desc = "if true, use pool_hba.conf for client authentication"; + i++; + status[i].name = "server_status"; if (pool_config.server_status[0] == 0) diff --git a/pool_type.h b/pool_type.h new file mode 100644 index 0000000..2edf9b2 --- /dev/null +++ b/pool_type.h @@ -0,0 +1,139 @@ +/* -*-pgsql-c-*- */ +/* + * + * $Header$ + * + * pgpool: a language independent connection pool server for PostgreSQL + * written by Tatsuo Ishii + * + * Portions Copyright (c) 2003-2007, PgPool Global Development Group + * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * Permission to use, copy, modify, and distribute this software and + * its documentation for any purpose 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 + * author not be used in advertising or publicity pertaining to + * distribution of the software without specific, written prior + * permission. The author makes no representations about the + * suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * pool_type.h.: definition of new types + * + */ + +#ifndef POOL_TYPE_H +#define POOL_TYPE_H + + +#include "config.h" +#include + + +/* Define common boolean type. C++ and BEOS already has it so exclude them. */ +#ifdef c_plusplus +#ifndef __cplusplus +#define __cplusplus +#endif /* __cplusplus */ +#endif /* c_plusplus */ + +#ifndef __BEOS__ +#ifndef __cplusplus +#ifndef bool +typedef char bool; +#endif +#ifndef true +#define true ((bool) 1) +#endif +#ifndef false +#define false ((bool) 0) +#endif +#endif /* not C++ */ +#endif /* __BEOS__ */ + + +/* + * It seems that sockaddr_storage is now commonly used in place of sockaddr. + * So, define it if it is not define yet, and create new SockAddr structure + * that uses sockaddr_storage. + */ +#ifdef HAVE_STRUCT_SOCKADDR_STORAGE + +#ifndef HAVE_STRUCT_SOCKADDR_STORAGE_SS_FAMILY +#ifdef HAVE_STRUCT_SOCKADDR_STORAGE___SS_FAMILY +#define ss_family __ss_family +#else +#error struct sockaddr_storage does not provide an ss_family member +#endif /* HAVE_STRUCT_SOCKADDR_STORAGE___SS_FAMILY */ +#endif /* HAVE_STRUCT_SOCKADDR_STORAGE_SS_FAMILY */ + +#ifdef HAVE_STRUCT_SOCKADDR_STORAGE___SS_LEN +#define ss_len __ss_len +#define HAVE_STRUCT_SOCKADDR_STORAGE_SS_LEN 1 +#endif /* HAVE_STRUCT_SOCKADDR_STORAGE___SS_LEN */ + +#else /* !HAVE_STRUCT_SOCKADDR_STORAGE */ + +/* Define a struct sockaddr_storage if we don't have one. */ +struct sockaddr_storage +{ + union + { + struct sockaddr sa; /* get the system-dependent fields */ + long int ss_align; /* ensures struct is properly aligned. original uses int64 */ + char ss_pad[128]; /* ensures struct has desired size */ + } + ss_stuff; +}; + +#define ss_family ss_stuff.sa.sa_family +/* It should have an ss_len field if sockaddr has sa_len. */ +#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN +#define ss_len ss_stuff.sa.sa_len +#define HAVE_STRUCT_SOCKADDR_STORAGE_SS_LEN 1 +#endif +#endif /* HAVE_STRUCT_SOCKADDR_STORAGE */ + +typedef struct +{ + struct sockaddr_storage addr; + /* ACCEPT_TYPE_ARG3 - Third argument type of accept(). + * It is defined in ac_func_accept_argtypes.m4 + * If a need to run aclocal arises, be sure to use "-I ./" option. + */ + ACCEPT_TYPE_ARG3 salen; +} +SockAddr; + + +/* UserAuth type used for HBA which indicates the authentication method */ +typedef enum UserAuth +{ + uaReject, +/* uaKrb4, */ +/* uaKrb5, */ + uaTrust +/* uaIdent, */ +/* uaPassword, */ +/* uaCrypt, */ +/* uaMD5, */ +#ifdef USE_PAM + ,uaPAM +#endif /* USE_PAM */ +} +UserAuth; + +#define AUTH_REQ_OK 0 /* User is authenticated */ +#define AUTH_REQ_KRB4 1 /* Kerberos V4 */ +#define AUTH_REQ_KRB5 2 /* Kerberos V5 */ +#define AUTH_REQ_PASSWORD 3 /* Password */ +#define AUTH_REQ_CRYPT 4 /* crypt password */ +#define AUTH_REQ_MD5 5 /* md5 password */ +#define AUTH_REQ_SCM_CREDS 6 /* transfer SCM credentials */ + +typedef unsigned int AuthRequest; + +#endif /* POOL_TYPE_H */ -- 2.39.5