Pound-2.8/0000775000175000017500000000000013275266545011511 5ustar rosegrosegPound-2.8/Makefile.in0000644000175000017500000000461513275266545013562 0ustar rosegroseg# Pound - the reverse-proxy load-balancer # Copyright (C) 2002-2010 Apsis GmbH # # This file is part of Pound. # # Pound is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 3 of the License, or # (at your option) any later version. # # Pound is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # # Contact information: # Apsis GmbH # P.O.Box # 8707 Uetikon am See # Switzerland # EMail: roseg@apsis.ch CC=@PTHREAD_CC@ CFLAGS=-DF_CONF=\"@sysconfdir@/pound.cfg\" -DVERSION=\"@PACKAGE_VERSION@\" -DC_SSL=\"@C_SSL@\" -DC_T_RSA=\"@C_T_RSA@\" \ -DC_DH_LEN=\"@C_DH_LEN@\" -DC_MAXBUF=\"@C_MAXBUF@\" -DC_OWNER=\"@C_OWNER@\" -DC_GROUP=\"@C_GROUP@\" \ -DC_SUPER=\"@C_SUPER@\" @CFLAGS@ @PTHREAD_CFLAGS@ @CPPFLAGS@ LIBS=@LIBS@ @PTHREAD_LIBS@ prefix=@prefix@ exec_prefix=@exec_prefix@ # Configuration file default; if none, look at config.c for default! OBJS=pound.o http.o config.o svc.o all: pound poundctl pound.8 pound: $(OBJS) ${CC} @LDFLAGS@ -o pound $(OBJS) $(LIBS) poundctl: poundctl.o ${CC} @LDFLAGS@ -o poundctl poundctl.o $(LIBS) dh512.h: openssl dhparam -5 -C -noout 512 > dh512.h dh@C_DH_LEN@.h: openssl dhparam -5 -C -noout @C_DH_LEN@ > dh@C_DH_LEN@.h svc.o: svc.c dh512.h dh@C_DH_LEN@.h ${CC} ${CFLAGS} -c -o svc.o svc.c $(OBJS) poundctl.o: pound.h config.h install: all @INSTALL@ -d ${DESTDIR}@sbindir@ @INSTALL@ -o @I_OWNER@ -g @I_GRP@ -m 555 pound ${DESTDIR}@sbindir@/pound @INSTALL@ -o @I_OWNER@ -g @I_GRP@ -m 555 poundctl ${DESTDIR}@sbindir@/poundctl @INSTALL@ -d ${DESTDIR}@mandir@/man8 @INSTALL@ -o @I_OWNER@ -g @I_GRP@ -m 644 pound.8 ${DESTDIR}@mandir@/man8/pound.8 @INSTALL@ -o @I_OWNER@ -g @I_GRP@ -m 644 poundctl.8 ${DESTDIR}@mandir@/man8/poundctl.8 clean: rm -f pound $(OBJS) poundctl poundctl.o rm -f dh512.h dh@C_DH_LEN@.h distclean: clean -rm -f config.h config.log config.status Makefile uninstall: -rm -f @sbindir@/pound @sbindir@/poundctl @mandir@/man8/pound.8 @mandir@/cat8/pound.8 @mandir@/man8/poundctl.8 @mandir@/cat8/poundctl.8 Pound-2.8/z2_2_5_1.py0000755000175000017500000006010113275266545013302 0ustar rosegroseg############################################################################## # # Copyright (c) 2001 Zope Corporation and Contributors. All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE # ############################################################################## """Zope 2 ZServer start-up file Usage: %(program)s [options] [environment settings] Options: -h Output this text. -z path The location of the Zope installation. The default is the location of this script, %(here)s. -Z path Unix only! This option is ignored on windows. If this option is specified, a separate managemnt process will be created that restarts Zope after a shutdown (or crash). The path must point to a pid file that the process will record its process id in. The path may be relative, in which case it will be relative to the Zope location. To prevent use of a separate management process, provide an empty string: -Z '' -t n The number of threads to use, if ZODB3 is used. The default is %(NUMBER_OF_THREADS)s. -i n Set the interpreter check interval. This integer value determines how often the interpreter checks for periodic things such as thread switches and signal handlers. The Zope default is 120, but you may want to experiment with other values that may increase performance in your particular environment. -D Run in Zope debug mode. This causes the Zope process not to detach from the controlling terminal, and is equivalent to supplying the environment variable setting Z_DEBUG_MODE=1 -a ipaddress The IP address to listen on. If this is an empty string (e.g. -a ''), then all addresses on the machine are used. The default is %(IP_ADDRESS)s. -d ipaddress IP address of your DNS server. If this is an empty string (e.g. -d ''), then IP addresses will not be logged. If you have DNS service on your local machine then you can set this to 127.0.0.1. The default is: %(DNS_IP)s. -u username or uid number The username to run ZServer as. You may want to run ZServer as 'nobody' or some other user with limited resouces. The only works under Unix, and if ZServer is started by root. The default is: %(UID)s -P [ipaddress:]number Set the web, ftp and monitor port numbers simultaneously as offsets from the number. The web port number will be number+80. The FTP port number will be number+21. The monitor port number will be number+99. The number can be preeceeded by an ip address follwed by a colon to specify an address to listen on. This allows different servers to listen on different addresses. Multiple -P options can be provided to run multiple sets of servers. -w port The Web server (HTTP) port. This defaults to %(HTTP_PORT)s. The standard port for HTTP services is 80. If this is a dash (e.g. -w -), then HTTP is disabled. The number can be preeceeded by an ip address follwed by a colon to specify an address to listen on. This allows different servers to listen on different addresses. Multiple -w options can be provided to run multiple servers. -y port The encrypted Web server (HTTPS) port. This defaults to %(HTTPS_PORT)s. The standard port for HTTP services is 443. If this is a dash (e.g. -y -), then HTTPS is disabled. The number can be preeceeded by an ip address follwed by a colon to specify an address to listen on. This allows different servers to listen on different addresses. Multiple -y options can be provided to run multiple servers. -W port The "WebDAV source" port. If this is a dash (e.g. -W -), then "WebDAV source" is disabled. The default is disabled. Note that this feature is a workaround for the lack of "source-link" support in standard WebDAV clients. The port can be preeceeded by an ip address follwed by a colon to specify an address to listen on. This allows different servers to listen on different addresses. Multiple -W options can be provided to run multiple servers. -f port The FTP port. If this is a dash (e.g. -f -), then FTP is disabled. The standard port for FTP services is 21. The default is %(FTP_PORT)s. The port can be preeceeded by an ip address follwed by a colon to specify an address to listen on. This allows different servers to listen on different addresses. Multiple -f options can be provided to run multiple servers. -p path Path to the PCGI resource file. The default value is %(PCGI_FILE)s, relative to the Zope location. If this is a dash (-p -) or the file does not exist, then PCGI is disabled. -F path_or_port Either a port number (for inet sockets) or a path name (for unix domain sockets) for the FastCGI Server. If the flag and value are not specified then the FastCGI Server is disabled. -m port The secure monitor server port. If this is a dash (-m -), then the monitor server is disabled. The monitor server allows interactive Python style access to a running ZServer. To access the server see medusa/monitor_client.py or medusa/monitor_client_win32.py. The monitor server password is the same as the Zope emergency user password set in the 'access' file. The default is to not start up a monitor server. The port can be preeceeded by an ip address follwed by a colon to specify an address to listen on. This allows different servers to listen on different addresses. Multiple -m options can be provided to run multiple servers. -l path Path to the ZServer log file. If this is a relative path then the log file will be written to the 'var' directory. The default is %(LOG_FILE)s. -r Run ZServer is read-only mode. ZServer won't write anything to disk. No log files, no pid files, nothing. This means that you can't do a lot of stuff like use PCGI, and zdaemon. ZServer will log hits to STDOUT and zLOG will log to STDERR. -L Enable locale (internationalization) support. The value passed for this option should be the name of the locale to be used (see your operating system documentation for locale information specific to your system). If an empty string is passed for this option (-L ''), Zope will set the locale to the user's default setting (typically specified in the $LANG environment variable). If your Python installation does not support the locale module, the requested locale is not supported by your system or an empty string was passed but no default locale can be found, an error will be raised and Zope will not start. -X Disable servers. This might be used to effectively disable all default server settings or previous server settings in the option list before providing new settings. For example to provide just a web server: %(program)s -X -w80 -M file Save detailed logging information to the given file. This log includes separate entries for: - The start of a request, - The start of processing the request in an application thread, - The start of response output, and - The end of the request. Environment settings are of the form: NAME=VALUE. Note: you *must* use Python 2.1 or later! """ # This is required path hackery for the win32 binary distribution # that ensures that the bundled python libraries are used. In a # win32 binary distribution, the installer will have replaced the # marker string with the actual software home. If that has not # happened, then the path munging code is skipped. swhome=r'INSERT_SOFTWARE_HOME' if swhome != 'INSERT_SOFTWARE_HOME': import sys sys.path.insert(0, '%s/lib/python' % swhome) sys.path.insert(1, '%s/bin/lib' % swhome) sys.path.insert(2, '%s/bin/lib/plat-win' % swhome) sys.path.insert(3, '%s/bin/lib/win32' % swhome) sys.path.insert(4, '%s/bin/lib/win32/lib' % swhome) sys.path.insert(5, '%s' % swhome) import os, sys, getopt, string, codecs # workaround to allow unicode encoding conversions in DTML dummy = codecs.lookup('iso-8859-1') sys.setcheckinterval(120) program=sys.argv[0] here=os.path.join(os.getcwd(), os.path.split(program)[0]) Zpid='' ######################################################################## # Configuration section ## General configuration options ## # If you want run as a daemon, then uncomment the line below: if sys.platform=='win32': Zpid='' else: Zpid='zProcessManager.pid' # This is the IP address of the network interface you want your servers to # be visible from. This can be changed to '' to listen on all interfaces. IP_ADDRESS='' # IP address of your DNS server. Set to '' if you do not want to resolve # IP addresses. If you have DNS service on your local machine then you can # set this to '127.0.0.1' DNS_IP='' # User id to run ZServer as. Note that this only works under Unix, and if # ZServer is started by root. UID='nobody' # Log file location. If this is a relative path, then it is joined the # the 'var' directory. LOG_FILE='Z2.log' ## HTTP configuration ## # Port for HTTP Server. The standard port for HTTP services is 80. HTTP_PORT=8080 # HTTP enivornment settings. HTTP_ENV={} # Port for HTTPS Server. The standard port for HTTPS services is 443. HTTPS_PORT=8443 # HTTPS enivornment settings. HTTPS_ENV={} # Port for the special "WebDAV source view" HTTP handler. There is no # standard port for this handler, which is disabled by default. WEBDAV_SOURCE_PORT=[] ## FTP configuration # Port for the FTP Server. The standard port for FTP services is 21. FTP_PORT=8021 ## PCGI configuration # You can configure the PCGI server manually, or have it read its # configuration information from a PCGI info file. PCGI_FILE='Zope.cgi' ## Monitor configuration MONITOR_PORT=0 # Module to be published, which must be Main or Zope MODULE='Zope' # The size of the thread pool, if ZODB3 is used. NUMBER_OF_THREADS=4 # Localization support LOCALE_ID=None # Socket path or port for the FastCGI Server FCGI_PORT=None # Detailed log file DETAILED_LOG_FILE='' # ######################################################################## ######################################################################## # Handle command-line arguments: def server_info(old, v, offset=0): # interpret v as a port or address/port and get new value if v == '-': v='' l=string.find(v, ':') if l >= 0: a=v[:l] v=v[l+1:] else: a=IP_ADDRESS if not v: return v try: v=string.atoi(v) if v < 0: raise 'Invalid port', v v=v+offset except: raise 'Invalid port', v if type(old) is type(0): old=[(a,v)] else: old.append((a,v)) return old try: if string.split(sys.version)[0] < '2.1': raise 'Invalid python version', string.split(sys.version)[0] opts, args = getopt.getopt(sys.argv[1:], 'hz:Z:t:i:a:d:u:w:y:W:f:p:m:Sl:2DP:rF:L:XM:') DEBUG=0 READ_ONLY=0 # Get environment variables for a in args: if string.find(a,'='): a=string.split(a,'=') o=a[0] v=string.join(a[1:],'=') if o: os.environ[o]=v HTTP_ENV[o]=v HTTPS_ENV[o]=v else: raise 'Invalid argument', a for o, v in opts: if o=='-z': here=v elif o=='-Z': if v=='-': v='' Zpid=v elif o=='-r': READ_ONLY=1 elif o=='-t': try: v=string.atoi(v) except: raise 'Invalid number of threads', v NUMBER_OF_THREADS=v elif o=='-i': try: v=string.atoi(v) except: raise 'Invalid value for -i option', v sys.setcheckinterval(v) elif o=='-a': IP_ADDRESS=v elif o=='-d': if v=='-': v='' DNS_IP=v elif o=='-u': UID=v elif o=='-D': os.environ['Z_DEBUG_MODE']='1' DEBUG=1 elif o=='-S': sys.ZMANAGED=1 elif o=='-X': MONITOR_PORT=HTTP_PORT=HTTPS_PORT=FTP_PORT=FCGI_PORT=0 PCGI_FILE='' elif o=='-m': MONITOR_PORT=server_info(MONITOR_PORT, v) elif o=='-w': HTTP_PORT=server_info(HTTP_PORT, v) elif o=='-y': HTTPS_PORT=server_info(HTTPS_PORT, v) elif o=='-W': WEBDAV_SOURCE_PORT=server_info(WEBDAV_SOURCE_PORT, v) elif o=='-f': FTP_PORT=server_info(FTP_PORT, v) elif o=='-P': HTTP_PORT=server_info(HTTP_PORT, v, 80) HTTPS_PORT=server_info(HTTPS_PORT, v, 443) FTP_PORT=server_info(FTP_PORT, v, 21) elif o=='-p': if v=='-': v='' PCGI_FILE=v elif o=='-h': print __doc__ % vars() sys.exit(0) elif o=='-2': MODULE='Main' elif o=='-l': LOG_FILE=v elif o=='-L': if v: LOCALE_ID=v else: LOCALE_ID='' elif o=='-F': if v=='-': v='' FCGI_PORT=v elif o=='-M': DETAILED_LOG_FILE=v except SystemExit: sys.exit(0) except: print __doc__ % vars() print print 'Error:' print "%s: %s" % (sys.exc_type, sys.exc_value) sys.exit(1) if sys.platform=='win32': Zpid='' # ######################################################################## ######################################################################## # OK, let's get going! # Jigger path: sys.path=[os.path.join(here,'lib','python'),here ]+filter(None, sys.path) # Try to set the locale if specified on the command # line. If the locale module is not available or the # requested locale is not supported by the local # machine, raise an error so that the user is made # aware of the problem. def set_locale(val): try: import locale except: raise SystemExit, ( 'The locale module could not be imported.\n' 'To use localization options, you must ensure\n' 'that the locale module is compiled into your\n' 'Python installation.' ) try: locale.setlocale(locale.LC_ALL, val) except: raise SystemExit, ( 'The specified locale is not supported by your system.\n' 'See your operating system documentation for more\n' 'information on locale support.' ) if LOCALE_ID is not None: set_locale(LOCALE_ID) # from this point forward we can use the zope logger # Import ZServer before we open the database or get at interesting # application code so that ZServer's asyncore gets to be the # official one. Also gets SOFTWARE_HOME, INSTANCE_HOME, and CLIENT_HOME import ZServer if Zpid and not READ_ONLY: import zdaemon, App.FindHomes, posix sys.ZMANAGED=1 zdaemon.run(sys.argv, os.path.join(CLIENT_HOME, Zpid)) try: # Import logging support import zLOG import ZLogger if READ_ONLY: if hasattr(zLOG, '_set_stupid_dest'): zLOG._set_stupid_dest(sys.stderr) else: zLOG._stupid_dest = sys.stderr else: zLOG.log_write = ZLogger.ZLogger.log_write if DETAILED_LOG_FILE: from ZServer import DebugLogger logfile=os.path.join(CLIENT_HOME, DETAILED_LOG_FILE) DebugLogger.log=DebugLogger.DebugLogger(logfile).log # Import Zope (or Main) exec "import "+MODULE in {} # Location of the ZServer log file. This file logs all ZServer activity. # You may wish to create different logs for different servers. See # medusa/logger.py for more information. if not os.path.isabs(LOG_FILE): LOG_PATH=os.path.join(CLIENT_HOME, LOG_FILE) else: LOG_PATH=LOG_FILE # Location of the ZServer pid file. When ZServer starts up it will write # its PID to this file. PID_FILE=os.path.join(CLIENT_HOME, 'Z2.pid') # import ZServer stuff # First, we need to increase the number of threads if MODULE=='Zope': from ZServer import setNumberOfThreads setNumberOfThreads(NUMBER_OF_THREADS) from ZServer import resolver, logger, asyncore from ZServer import zhttp_server, zhttp_handler from ZServer.WebDAVSrcHandler import WebDAVSrcHandler from ZServer import PCGIServer,FTPServer,FCGIServer from ZServer import secure_monitor_server ## ZServer startup ## # Resolver and Logger, used by other servers if DNS_IP: rs = resolver.caching_resolver(DNS_IP) else: rs=None if READ_ONLY: lg = logger.file_logger('-') # log to stdout elif os.environ.has_key('ZSYSLOG'): lg = logger.syslog_logger(os.environ['ZSYSLOG']) if os.environ.has_key("ZSYSLOG_FACILITY"): lg = logger.syslog_logger(os.environ['ZSYSLOG'],facility=os.environ['ZSYSLOG_FACILITY']) else: lg = logger.syslog_logger(os.environ['ZSYSLOG']) elif os.environ.has_key('ZSYSLOG_SERVER'): (addr, port) = string.split(os.environ['ZSYSLOG_SERVER'], ':') lg = logger.syslog_logger((addr, int(port))) else: lg = logger.file_logger(LOG_PATH) # HTTP Server if HTTP_PORT: if type(HTTP_PORT) is type(0): HTTP_PORT=((IP_ADDRESS, HTTP_PORT),) for address, port in HTTP_PORT: hs = zhttp_server( ip=address, port=port, resolver=rs, logger_object=lg) # Handler for a published module. zhttp_handler takes 3 arguments: # The name of the module to publish, and optionally the URI base # which is basically the SCRIPT_NAME, and optionally a dictionary # with CGI environment variables which override default # settings. The URI base setting is useful when you want to # publish more than one module with the same HTTP server. The CGI # environment setting is useful when you want to proxy requests # from another web server to ZServer, and would like the CGI # environment to reflect the CGI environment of the other web # server. zh = zhttp_handler(MODULE, '', HTTP_ENV) hs.install_handler(zh) # HTTPS Server if HTTPS_PORT: if type(HTTPS_PORT) is type(0): HTTPS_PORT=((IP_ADDRESS, HTTPS_PORT),) for address, port in HTTPS_PORT: hs = zhttp_server( ip=address, port=port, resolver=rs, logger_object=lg) # Handler for a published module. zhttp_handler takes 3 arguments: # The name of the module to publish, and optionally the URI base # which is basically the SCRIPT_NAME, and optionally a dictionary # with CGI environment variables which override default # settings. The URI base setting is useful when you want to # publish more than one module with the same HTTP server. The CGI # environment setting is useful when you want to proxy requests # from another web server to ZServer, and would like the CGI # environment to reflect the CGI environment of the other web # server. try: del HTTPS_ENV['HTTP'] except KeyError: pass HTTPS_ENV['HTTPS']='ON' zh = zhttp_handler(MODULE, '', HTTPS_ENV) hs.install_handler(zh) # WebDAV source Server (runs HTTP, but munges request to return # 'manage_FTPget'). if WEBDAV_SOURCE_PORT: if type(WEBDAV_SOURCE_PORT) is type(0): WEBDAV_SOURCE_PORT=((IP_ADDRESS, WEBDAV_SOURCE_PORT),) for address, port in WEBDAV_SOURCE_PORT: hs = zhttp_server( ip=address, port=port, resolver=rs, logger_object=lg) # Handler for a published module. zhttp_handler takes 3 arguments: # The name of the module to publish, and optionally the URI base # which is basically the SCRIPT_NAME, and optionally a dictionary # with CGI environment variables which override default # settings. The URI base setting is useful when you want to # publish more than one module with the same HTTP server. The CGI # environment setting is useful when you want to proxy requests # from another web server to ZServer, and would like the CGI # environment to reflect the CGI environment of the other web # server. zh = WebDAVSrcHandler(MODULE, '', HTTP_ENV) hs.install_handler(zh) # FTP Server if FTP_PORT: if type(FTP_PORT) is type(0): FTP_PORT=((IP_ADDRESS, FTP_PORT),) for address, port in FTP_PORT: FTPServer( module=MODULE, ip=address, port=port, resolver=rs, logger_object=lg) # PCGI Server if PCGI_FILE and not READ_ONLY: PCGI_FILE=os.path.join(here, PCGI_FILE) if os.path.exists(PCGI_FILE): zpcgi = PCGIServer( module=MODULE, ip=IP_ADDRESS, pcgi_file=PCGI_FILE, resolver=rs, logger_object=lg) # FastCGI Server if FCGI_PORT and not READ_ONLY: fcgiPort = None fcgiPath = None try: fcgiPort = string.atoi(FCGI_PORT) except ValueError: fcgiPath = FCGI_PORT zfcgi = FCGIServer(module=MODULE, ip=IP_ADDRESS, port=fcgiPort, socket_file=fcgiPath, resolver=rs, logger_object=lg) # Monitor Server if MONITOR_PORT: from AccessControl.User import emergency_user if not hasattr(emergency_user, '__null_user__'): pw = emergency_user._getPassword() else: pw = None zLOG.LOG("z2", zLOG.WARNING, 'Monitor server not started' ' because no emergency user exists.') if pw: if type(MONITOR_PORT) is type(0): MONITOR_PORT=((IP_ADDRESS, MONITOR_PORT),) for address, port in MONITOR_PORT: monitor=secure_monitor_server( password=pw, hostname=address, port=port) # Try to set uid to "-u" -provided uid. # Try to set gid to "-u" user's primary group. # This will only work if this script is run by root. try: import pwd try: try: UID = string.atoi(UID) except: pass gid = None if type(UID) == type(""): uid = pwd.getpwnam(UID)[2] gid = pwd.getpwnam(UID)[3] elif type(UID) == type(1): uid = pwd.getpwuid(UID)[2] gid = pwd.getpwuid(UID)[3] else: raise KeyError try: if gid is not None: try: os.setgid(gid) except OSError: pass os.setuid(uid) except OSError: pass except KeyError: zLOG.LOG("z2", zLOG.ERROR, ("can't find UID %s" % UID)) except: pass # if it hasn't failed at this point, create a .pid file. if not READ_ONLY: pf = open(PID_FILE, 'w') pid=str(os.getpid()) try: pid=str(os.getppid())+' '+pid except: pass pf.write(pid) pf.close() except: # Log startup exception and tell zdaemon not to restart us. try: zLOG.LOG("z2", zLOG.PANIC, "Startup exception", error=sys.exc_info()) except: pass sys.exit(0) # Start Medusa, Ye Hass! sys.ZServerExitCode=0 asyncore.loop() sys.exit(sys.ZServerExitCode) Pound-2.8/poundctl.80000755000175000017500000000371713275266545013443 0ustar rosegroseg.TH POUNDCTL "8" "Jan 2010" "poundctl" "System Manager's Manual" .SH NAME poundctl \- control the pound(8) daemon .SH SYNOPSIS .TP .B poundctl \fI-c /path/to/socket\fR [\fI-L/-l\fR] [\fI-S/-s\fR] [\fI-B/-b\fR] [\fI-N/-n\fR] [\fI-H\fR] [\fI-X\fR] .SH DESCRIPTION .PP .B Poundctl controls various aspects of the operation of the .I pound(8) program. .SH OPTIONS Options available: .TP \fB\-c /path/to/socket\fR The path to the (Unix-domain) socket .B Pound was configured to listen on for control. Your .B Pound configuration file must contain the directive .I Control "/path/to/socket" for .B poundctl to work. .TP \fB\-L/-l n\fR Enable/disable a listener. A disabled listener will stop accepting connection requests. .TP \fB\-S/-s n m\fR Enable/disable a service. A disabled service will not be used by .B Pound to answer requests. .TP \fB\-B/-b n m r\fR Enable/disable a back-end. A disabled back-end will not be passed requests to answer. Note however that existing sessions may still cause requests to be sent their way. .TP \fB\-N n m k r\fR Add a session to service m in listener n. The session key is k and it points to back-end r. .TP \fB\-n n m k\fR Remove a session from service m in listener n. The session key is k. .PP The parameters n, m and r refer to the number assigned to a particular listener, service and back-end in the listings. A listener number of -1 refers by convention to the global context. .TP \fB\-H\fR Try to resolve the addresses to symbolic names. Depending on your configuration, this may require an active DNS. .TP \fB\-X\fR Show the results in XML format. .PP When called without flags .B poundctl will print out a listing of the .B Pound internal state. .SH AUTHOR Written by Robert Segall, Apsis GmbH. .SH "REPORTING BUGS" Report bugs to . .SH COPYRIGHT Copyright \(co 2002-2010 Apsis GmbH. .br This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. Pound-2.8/config.guess0000755000175000017500000012066513275266545014041 0ustar rosegroseg#! /bin/sh # Attempt to guess a canonical system name. # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, # 2000, 2001, 2002, 2003 Free Software Foundation, Inc. timestamp='2003-05-09' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # Originally written by Per Bothner . # Please send patches to . Submit a context # diff and a properly formatted ChangeLog entry. # # This script attempts to guess a canonical system name similar to # config.sub. If it succeeds, it prints the system name on stdout, and # exits with 0. Otherwise, it exits with 1. # # The plan is that this can be called by configure scripts if you # don't specify an explicit build system type. me=`echo "$0" | sed -e 's,.*/,,'` usage="\ Usage: $0 [OPTION] Output the configuration name of the system \`$me' is run on. Operation modes: -h, --help print this help, then exit -t, --time-stamp print date of last modification, then exit -v, --version print version number, then exit Report bugs and patches to ." version="\ GNU config.guess ($timestamp) Originally written by Per Bothner. Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." help=" Try \`$me --help' for more information." # Parse command line while test $# -gt 0 ; do case $1 in --time-stamp | --time* | -t ) echo "$timestamp" ; exit 0 ;; --version | -v ) echo "$version" ; exit 0 ;; --help | --h* | -h ) echo "$usage"; exit 0 ;; -- ) # Stop option processing shift; break ;; - ) # Use stdin as input. break ;; -* ) echo "$me: invalid option $1$help" >&2 exit 1 ;; * ) break ;; esac done if test $# != 0; then echo "$me: too many arguments$help" >&2 exit 1 fi trap 'exit 1' 1 2 15 # CC_FOR_BUILD -- compiler used by this script. Note that the use of a # compiler to aid in system detection is discouraged as it requires # temporary files to be created and, as you can see below, it is a # headache to deal with in a portable fashion. # Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still # use `HOST_CC' if defined, but it is deprecated. # Portable tmp directory creation inspired by the Autoconf team. set_cc_for_build=' trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; : ${TMPDIR=/tmp} ; { tmp=`(umask 077 && mktemp -d -q "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } || { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; dummy=$tmp/dummy ; tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; case $CC_FOR_BUILD,$HOST_CC,$CC in ,,) echo "int x;" > $dummy.c ; for c in cc gcc c89 c99 ; do if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then CC_FOR_BUILD="$c"; break ; fi ; done ; if test x"$CC_FOR_BUILD" = x ; then CC_FOR_BUILD=no_compiler_found ; fi ;; ,,*) CC_FOR_BUILD=$CC ;; ,*,*) CC_FOR_BUILD=$HOST_CC ;; esac ;' # This is needed to find uname on a Pyramid OSx when run in the BSD universe. # (ghazi@noc.rutgers.edu 1994-08-24) if (test -f /.attbin/uname) >/dev/null 2>&1 ; then PATH=$PATH:/.attbin ; export PATH fi UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown # Note: order is significant - the case branches are not exclusive. case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in *:NetBSD:*:*) # NetBSD (nbsd) targets should (where applicable) match one or # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*, # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently # switched to ELF, *-*-netbsd* would select the old # object file format. This provides both forward # compatibility and a consistent mechanism for selecting the # object file format. # # Note: NetBSD doesn't particularly care about the vendor # portion of the name. We always set it to "unknown". sysctl="sysctl -n hw.machine_arch" UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \ /usr/sbin/$sysctl 2>/dev/null || echo unknown)` case "${UNAME_MACHINE_ARCH}" in armeb) machine=armeb-unknown ;; arm*) machine=arm-unknown ;; sh3el) machine=shl-unknown ;; sh3eb) machine=sh-unknown ;; *) machine=${UNAME_MACHINE_ARCH}-unknown ;; esac # The Operating System including object format, if it has switched # to ELF recently, or will in the future. case "${UNAME_MACHINE_ARCH}" in arm*|i386|m68k|ns32k|sh3*|sparc|vax) eval $set_cc_for_build if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ | grep __ELF__ >/dev/null then # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). # Return netbsd for either. FIX? os=netbsd else os=netbsdelf fi ;; *) os=netbsd ;; esac # The OS release # Debian GNU/NetBSD machines have a different userland, and # thus, need a distinct triplet. However, they do not need # kernel version information, so it can be replaced with a # suitable tag, in the style of linux-gnu. case "${UNAME_VERSION}" in Debian*) release='-gnu' ;; *) release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` ;; esac # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: # contains redundant information, the shorter form: # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. echo "${machine}-${os}${release}" exit 0 ;; amiga:OpenBSD:*:*) echo m68k-unknown-openbsd${UNAME_RELEASE} exit 0 ;; arc:OpenBSD:*:*) echo mipsel-unknown-openbsd${UNAME_RELEASE} exit 0 ;; hp300:OpenBSD:*:*) echo m68k-unknown-openbsd${UNAME_RELEASE} exit 0 ;; mac68k:OpenBSD:*:*) echo m68k-unknown-openbsd${UNAME_RELEASE} exit 0 ;; macppc:OpenBSD:*:*) echo powerpc-unknown-openbsd${UNAME_RELEASE} exit 0 ;; mvme68k:OpenBSD:*:*) echo m68k-unknown-openbsd${UNAME_RELEASE} exit 0 ;; mvme88k:OpenBSD:*:*) echo m88k-unknown-openbsd${UNAME_RELEASE} exit 0 ;; mvmeppc:OpenBSD:*:*) echo powerpc-unknown-openbsd${UNAME_RELEASE} exit 0 ;; pmax:OpenBSD:*:*) echo mipsel-unknown-openbsd${UNAME_RELEASE} exit 0 ;; sgi:OpenBSD:*:*) echo mipseb-unknown-openbsd${UNAME_RELEASE} exit 0 ;; sun3:OpenBSD:*:*) echo m68k-unknown-openbsd${UNAME_RELEASE} exit 0 ;; wgrisc:OpenBSD:*:*) echo mipsel-unknown-openbsd${UNAME_RELEASE} exit 0 ;; *:OpenBSD:*:*) echo ${UNAME_MACHINE}-unknown-openbsd${UNAME_RELEASE} exit 0 ;; alpha:OSF1:*:*) if test $UNAME_RELEASE = "V4.0"; then UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` fi # According to Compaq, /usr/sbin/psrinfo has been available on # OSF/1 and Tru64 systems produced since 1995. I hope that # covers most systems running today. This code pipes the CPU # types through head -n 1, so we only detect the type of CPU 0. ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` case "$ALPHA_CPU_TYPE" in "EV4 (21064)") UNAME_MACHINE="alpha" ;; "EV4.5 (21064)") UNAME_MACHINE="alpha" ;; "LCA4 (21066/21068)") UNAME_MACHINE="alpha" ;; "EV5 (21164)") UNAME_MACHINE="alphaev5" ;; "EV5.6 (21164A)") UNAME_MACHINE="alphaev56" ;; "EV5.6 (21164PC)") UNAME_MACHINE="alphapca56" ;; "EV5.7 (21164PC)") UNAME_MACHINE="alphapca57" ;; "EV6 (21264)") UNAME_MACHINE="alphaev6" ;; "EV6.7 (21264A)") UNAME_MACHINE="alphaev67" ;; "EV6.8CB (21264C)") UNAME_MACHINE="alphaev68" ;; "EV6.8AL (21264B)") UNAME_MACHINE="alphaev68" ;; "EV6.8CX (21264D)") UNAME_MACHINE="alphaev68" ;; "EV6.9A (21264/EV69A)") UNAME_MACHINE="alphaev69" ;; "EV7 (21364)") UNAME_MACHINE="alphaev7" ;; "EV7.9 (21364A)") UNAME_MACHINE="alphaev79" ;; esac # A Vn.n version is a released version. # A Tn.n version is a released field test version. # A Xn.n version is an unreleased experimental baselevel. # 1.2 uses "1.2" for uname -r. echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[VTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` exit 0 ;; Alpha\ *:Windows_NT*:*) # How do we know it's Interix rather than the generic POSIX subsystem? # Should we change UNAME_MACHINE based on the output of uname instead # of the specific Alpha model? echo alpha-pc-interix exit 0 ;; 21064:Windows_NT:50:3) echo alpha-dec-winnt3.5 exit 0 ;; Amiga*:UNIX_System_V:4.0:*) echo m68k-unknown-sysv4 exit 0;; *:[Aa]miga[Oo][Ss]:*:*) echo ${UNAME_MACHINE}-unknown-amigaos exit 0 ;; *:[Mm]orph[Oo][Ss]:*:*) echo ${UNAME_MACHINE}-unknown-morphos exit 0 ;; *:OS/390:*:*) echo i370-ibm-openedition exit 0 ;; arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) echo arm-acorn-riscix${UNAME_RELEASE} exit 0;; SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) echo hppa1.1-hitachi-hiuxmpp exit 0;; Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. if test "`(/bin/universe) 2>/dev/null`" = att ; then echo pyramid-pyramid-sysv3 else echo pyramid-pyramid-bsd fi exit 0 ;; NILE*:*:*:dcosx) echo pyramid-pyramid-svr4 exit 0 ;; DRS?6000:UNIX_SV:4.2*:7*) case `/usr/bin/uname -p` in sparc) echo sparc-icl-nx7 && exit 0 ;; esac ;; sun4H:SunOS:5.*:*) echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit 0 ;; sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit 0 ;; i86pc:SunOS:5.*:*) echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit 0 ;; sun4*:SunOS:6*:*) # According to config.sub, this is the proper way to canonicalize # SunOS6. Hard to guess exactly what SunOS6 will be like, but # it's likely to be more like Solaris than SunOS4. echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit 0 ;; sun4*:SunOS:*:*) case "`/usr/bin/arch -k`" in Series*|S4*) UNAME_RELEASE=`uname -v` ;; esac # Japanese Language versions have a version number like `4.1.3-JL'. echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` exit 0 ;; sun3*:SunOS:*:*) echo m68k-sun-sunos${UNAME_RELEASE} exit 0 ;; sun*:*:4.2BSD:*) UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 case "`/bin/arch`" in sun3) echo m68k-sun-sunos${UNAME_RELEASE} ;; sun4) echo sparc-sun-sunos${UNAME_RELEASE} ;; esac exit 0 ;; aushp:SunOS:*:*) echo sparc-auspex-sunos${UNAME_RELEASE} exit 0 ;; # The situation for MiNT is a little confusing. The machine name # can be virtually everything (everything which is not # "atarist" or "atariste" at least should have a processor # > m68000). The system name ranges from "MiNT" over "FreeMiNT" # to the lowercase version "mint" (or "freemint"). Finally # the system name "TOS" denotes a system which is actually not # MiNT. But MiNT is downward compatible to TOS, so this should # be no problem. atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) echo m68k-atari-mint${UNAME_RELEASE} exit 0 ;; atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) echo m68k-atari-mint${UNAME_RELEASE} exit 0 ;; *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) echo m68k-atari-mint${UNAME_RELEASE} exit 0 ;; milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) echo m68k-milan-mint${UNAME_RELEASE} exit 0 ;; hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) echo m68k-hades-mint${UNAME_RELEASE} exit 0 ;; *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) echo m68k-unknown-mint${UNAME_RELEASE} exit 0 ;; powerpc:machten:*:*) echo powerpc-apple-machten${UNAME_RELEASE} exit 0 ;; RISC*:Mach:*:*) echo mips-dec-mach_bsd4.3 exit 0 ;; RISC*:ULTRIX:*:*) echo mips-dec-ultrix${UNAME_RELEASE} exit 0 ;; VAX*:ULTRIX*:*:*) echo vax-dec-ultrix${UNAME_RELEASE} exit 0 ;; 2020:CLIX:*:* | 2430:CLIX:*:*) echo clipper-intergraph-clix${UNAME_RELEASE} exit 0 ;; mips:*:*:UMIPS | mips:*:*:RISCos) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #ifdef __cplusplus #include /* for printf() prototype */ int main (int argc, char *argv[]) { #else int main (argc, argv) int argc; char *argv[]; { #endif #if defined (host_mips) && defined (MIPSEB) #if defined (SYSTYPE_SYSV) printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); #endif #if defined (SYSTYPE_SVR4) printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); #endif #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); #endif #endif exit (-1); } EOF $CC_FOR_BUILD -o $dummy $dummy.c \ && $dummy `echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` \ && exit 0 echo mips-mips-riscos${UNAME_RELEASE} exit 0 ;; Motorola:PowerMAX_OS:*:*) echo powerpc-motorola-powermax exit 0 ;; Motorola:*:4.3:PL8-*) echo powerpc-harris-powermax exit 0 ;; Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) echo powerpc-harris-powermax exit 0 ;; Night_Hawk:Power_UNIX:*:*) echo powerpc-harris-powerunix exit 0 ;; m88k:CX/UX:7*:*) echo m88k-harris-cxux7 exit 0 ;; m88k:*:4*:R4*) echo m88k-motorola-sysv4 exit 0 ;; m88k:*:3*:R3*) echo m88k-motorola-sysv3 exit 0 ;; AViiON:dgux:*:*) # DG/UX returns AViiON for all architectures UNAME_PROCESSOR=`/usr/bin/uname -p` if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] then if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ [ ${TARGET_BINARY_INTERFACE}x = x ] then echo m88k-dg-dgux${UNAME_RELEASE} else echo m88k-dg-dguxbcs${UNAME_RELEASE} fi else echo i586-dg-dgux${UNAME_RELEASE} fi exit 0 ;; M88*:DolphinOS:*:*) # DolphinOS (SVR3) echo m88k-dolphin-sysv3 exit 0 ;; M88*:*:R3*:*) # Delta 88k system running SVR3 echo m88k-motorola-sysv3 exit 0 ;; XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) echo m88k-tektronix-sysv3 exit 0 ;; Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) echo m68k-tektronix-bsd exit 0 ;; *:IRIX*:*:*) echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` exit 0 ;; ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id exit 0 ;; # Note that: echo "'`uname -s`'" gives 'AIX ' i*86:AIX:*:*) echo i386-ibm-aix exit 0 ;; ia64:AIX:*:*) if [ -x /usr/bin/oslevel ] ; then IBM_REV=`/usr/bin/oslevel` else IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} fi echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} exit 0 ;; *:AIX:2:3) if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #include main() { if (!__power_pc()) exit(1); puts("powerpc-ibm-aix3.2.5"); exit(0); } EOF $CC_FOR_BUILD -o $dummy $dummy.c && $dummy && exit 0 echo rs6000-ibm-aix3.2.5 elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then echo rs6000-ibm-aix3.2.4 else echo rs6000-ibm-aix3.2 fi exit 0 ;; *:AIX:*:[45]) IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then IBM_ARCH=rs6000 else IBM_ARCH=powerpc fi if [ -x /usr/bin/oslevel ] ; then IBM_REV=`/usr/bin/oslevel` else IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} fi echo ${IBM_ARCH}-ibm-aix${IBM_REV} exit 0 ;; *:AIX:*:*) echo rs6000-ibm-aix exit 0 ;; ibmrt:4.4BSD:*|romp-ibm:BSD:*) echo romp-ibm-bsd4.4 exit 0 ;; ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to exit 0 ;; # report: romp-ibm BSD 4.3 *:BOSX:*:*) echo rs6000-bull-bosx exit 0 ;; DPX/2?00:B.O.S.:*:*) echo m68k-bull-sysv3 exit 0 ;; 9000/[34]??:4.3bsd:1.*:*) echo m68k-hp-bsd exit 0 ;; hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) echo m68k-hp-bsd4.4 exit 0 ;; 9000/[34678]??:HP-UX:*:*) HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` case "${UNAME_MACHINE}" in 9000/31? ) HP_ARCH=m68000 ;; 9000/[34]?? ) HP_ARCH=m68k ;; 9000/[678][0-9][0-9]) if [ -x /usr/bin/getconf ]; then sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` case "${sc_cpu_version}" in 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 532) # CPU_PA_RISC2_0 case "${sc_kernel_bits}" in 32) HP_ARCH="hppa2.0n" ;; 64) HP_ARCH="hppa2.0w" ;; '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20 esac ;; esac fi if [ "${HP_ARCH}" = "" ]; then eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #define _HPUX_SOURCE #include #include int main () { #if defined(_SC_KERNEL_BITS) long bits = sysconf(_SC_KERNEL_BITS); #endif long cpu = sysconf (_SC_CPU_VERSION); switch (cpu) { case CPU_PA_RISC1_0: puts ("hppa1.0"); break; case CPU_PA_RISC1_1: puts ("hppa1.1"); break; case CPU_PA_RISC2_0: #if defined(_SC_KERNEL_BITS) switch (bits) { case 64: puts ("hppa2.0w"); break; case 32: puts ("hppa2.0n"); break; default: puts ("hppa2.0"); break; } break; #else /* !defined(_SC_KERNEL_BITS) */ puts ("hppa2.0"); break; #endif default: puts ("hppa1.0"); break; } exit (0); } EOF (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` test -z "$HP_ARCH" && HP_ARCH=hppa fi ;; esac if [ ${HP_ARCH} = "hppa2.0w" ] then # avoid double evaluation of $set_cc_for_build test -n "$CC_FOR_BUILD" || eval $set_cc_for_build if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E -) | grep __LP64__ >/dev/null then HP_ARCH="hppa2.0w" else HP_ARCH="hppa64" fi fi echo ${HP_ARCH}-hp-hpux${HPUX_REV} exit 0 ;; ia64:HP-UX:*:*) HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` echo ia64-hp-hpux${HPUX_REV} exit 0 ;; 3050*:HI-UX:*:*) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #include int main () { long cpu = sysconf (_SC_CPU_VERSION); /* The order matters, because CPU_IS_HP_MC68K erroneously returns true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct results, however. */ if (CPU_IS_PA_RISC (cpu)) { switch (cpu) { case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; default: puts ("hppa-hitachi-hiuxwe2"); break; } } else if (CPU_IS_HP_MC68K (cpu)) puts ("m68k-hitachi-hiuxwe2"); else puts ("unknown-hitachi-hiuxwe2"); exit (0); } EOF $CC_FOR_BUILD -o $dummy $dummy.c && $dummy && exit 0 echo unknown-hitachi-hiuxwe2 exit 0 ;; 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) echo hppa1.1-hp-bsd exit 0 ;; 9000/8??:4.3bsd:*:*) echo hppa1.0-hp-bsd exit 0 ;; *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) echo hppa1.0-hp-mpeix exit 0 ;; hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) echo hppa1.1-hp-osf exit 0 ;; hp8??:OSF1:*:*) echo hppa1.0-hp-osf exit 0 ;; i*86:OSF1:*:*) if [ -x /usr/sbin/sysversion ] ; then echo ${UNAME_MACHINE}-unknown-osf1mk else echo ${UNAME_MACHINE}-unknown-osf1 fi exit 0 ;; parisc*:Lites*:*:*) echo hppa1.1-hp-lites exit 0 ;; C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) echo c1-convex-bsd exit 0 ;; C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) if getsysinfo -f scalar_acc then echo c32-convex-bsd else echo c2-convex-bsd fi exit 0 ;; C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) echo c34-convex-bsd exit 0 ;; C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) echo c38-convex-bsd exit 0 ;; C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) echo c4-convex-bsd exit 0 ;; CRAY*Y-MP:*:*:*) echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit 0 ;; CRAY*[A-Z]90:*:*:*) echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ -e 's/\.[^.]*$/.X/' exit 0 ;; CRAY*TS:*:*:*) echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit 0 ;; CRAY*T3E:*:*:*) echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit 0 ;; CRAY*SV1:*:*:*) echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit 0 ;; *:UNICOS/mp:*:*) echo nv1-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit 0 ;; F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" exit 0 ;; i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} exit 0 ;; sparc*:BSD/OS:*:*) echo sparc-unknown-bsdi${UNAME_RELEASE} exit 0 ;; *:BSD/OS:*:*) echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} exit 0 ;; *:FreeBSD:*:*|*:GNU/FreeBSD:*:*) # Determine whether the default compiler uses glibc. eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #include #if __GLIBC__ >= 2 LIBC=gnu #else LIBC= #endif EOF eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^LIBC=` echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`${LIBC:+-$LIBC} exit 0 ;; i*:CYGWIN*:*) echo ${UNAME_MACHINE}-pc-cygwin exit 0 ;; i*:MINGW*:*) echo ${UNAME_MACHINE}-pc-mingw32 exit 0 ;; i*:PW*:*) echo ${UNAME_MACHINE}-pc-pw32 exit 0 ;; x86:Interix*:3*) echo i586-pc-interix3 exit 0 ;; [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) echo i${UNAME_MACHINE}-pc-mks exit 0 ;; i*:Windows_NT*:* | Pentium*:Windows_NT*:*) # How do we know it's Interix rather than the generic POSIX subsystem? # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we # UNAME_MACHINE based on the output of uname instead of i386? echo i586-pc-interix exit 0 ;; i*:UWIN*:*) echo ${UNAME_MACHINE}-pc-uwin exit 0 ;; p*:CYGWIN*:*) echo powerpcle-unknown-cygwin exit 0 ;; prep*:SunOS:5.*:*) echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit 0 ;; *:GNU:*:*) echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` exit 0 ;; i*86:Minix:*:*) echo ${UNAME_MACHINE}-pc-minix exit 0 ;; arm*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit 0 ;; ia64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit 0 ;; m68*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit 0 ;; mips:Linux:*:*) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #undef CPU #undef mips #undef mipsel #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) CPU=mipsel #else #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) CPU=mips #else CPU= #endif #endif EOF eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^CPU=` test x"${CPU}" != x && echo "${CPU}-unknown-linux-gnu" && exit 0 ;; mips64:Linux:*:*) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #undef CPU #undef mips64 #undef mips64el #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) CPU=mips64el #else #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) CPU=mips64 #else CPU= #endif #endif EOF eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^CPU=` test x"${CPU}" != x && echo "${CPU}-unknown-linux-gnu" && exit 0 ;; ppc:Linux:*:*) echo powerpc-unknown-linux-gnu exit 0 ;; ppc64:Linux:*:*) echo powerpc64-unknown-linux-gnu exit 0 ;; alpha:Linux:*:*) case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in EV5) UNAME_MACHINE=alphaev5 ;; EV56) UNAME_MACHINE=alphaev56 ;; PCA56) UNAME_MACHINE=alphapca56 ;; PCA57) UNAME_MACHINE=alphapca56 ;; EV6) UNAME_MACHINE=alphaev6 ;; EV67) UNAME_MACHINE=alphaev67 ;; EV68*) UNAME_MACHINE=alphaev68 ;; esac objdump --private-headers /bin/sh | grep ld.so.1 >/dev/null if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} exit 0 ;; parisc:Linux:*:* | hppa:Linux:*:*) # Look for CPU level case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in PA7*) echo hppa1.1-unknown-linux-gnu ;; PA8*) echo hppa2.0-unknown-linux-gnu ;; *) echo hppa-unknown-linux-gnu ;; esac exit 0 ;; parisc64:Linux:*:* | hppa64:Linux:*:*) echo hppa64-unknown-linux-gnu exit 0 ;; s390:Linux:*:* | s390x:Linux:*:*) echo ${UNAME_MACHINE}-ibm-linux exit 0 ;; sh*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit 0 ;; sparc:Linux:*:* | sparc64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit 0 ;; x86_64:Linux:*:*) echo x86_64-unknown-linux-gnu exit 0 ;; i*86:Linux:*:*) # The BFD linker knows what the default object file format is, so # first see if it will tell us. cd to the root directory to prevent # problems with other programs or directories called `ld' in the path. # Set LC_ALL=C to ensure ld outputs messages in English. ld_supported_targets=`cd /; LC_ALL=C ld --help 2>&1 \ | sed -ne '/supported targets:/!d s/[ ][ ]*/ /g s/.*supported targets: *// s/ .*// p'` case "$ld_supported_targets" in elf32-i386) TENTATIVE="${UNAME_MACHINE}-pc-linux-gnu" ;; a.out-i386-linux) echo "${UNAME_MACHINE}-pc-linux-gnuaout" exit 0 ;; coff-i386) echo "${UNAME_MACHINE}-pc-linux-gnucoff" exit 0 ;; "") # Either a pre-BFD a.out linker (linux-gnuoldld) or # one that does not give us useful --help. echo "${UNAME_MACHINE}-pc-linux-gnuoldld" exit 0 ;; esac # Determine whether the default compiler is a.out or elf eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #include #ifdef __ELF__ # ifdef __GLIBC__ # if __GLIBC__ >= 2 LIBC=gnu # else LIBC=gnulibc1 # endif # else LIBC=gnulibc1 # endif #else #ifdef __INTEL_COMPILER LIBC=gnu #else LIBC=gnuaout #endif #endif EOF eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^LIBC=` test x"${LIBC}" != x && echo "${UNAME_MACHINE}-pc-linux-${LIBC}" && exit 0 test x"${TENTATIVE}" != x && echo "${TENTATIVE}" && exit 0 ;; i*86:DYNIX/ptx:4*:*) # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. # earlier versions are messed up and put the nodename in both # sysname and nodename. echo i386-sequent-sysv4 exit 0 ;; i*86:UNIX_SV:4.2MP:2.*) # Unixware is an offshoot of SVR4, but it has its own version # number series starting with 2... # I am not positive that other SVR4 systems won't match this, # I just have to hope. -- rms. # Use sysv4.2uw... so that sysv4* matches it. echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} exit 0 ;; i*86:OS/2:*:*) # If we were able to find `uname', then EMX Unix compatibility # is probably installed. echo ${UNAME_MACHINE}-pc-os2-emx exit 0 ;; i*86:XTS-300:*:STOP) echo ${UNAME_MACHINE}-unknown-stop exit 0 ;; i*86:atheos:*:*) echo ${UNAME_MACHINE}-unknown-atheos exit 0 ;; i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*) echo i386-unknown-lynxos${UNAME_RELEASE} exit 0 ;; i*86:*DOS:*:*) echo ${UNAME_MACHINE}-pc-msdosdjgpp exit 0 ;; i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} else echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} fi exit 0 ;; i*86:*:5:[78]*) case `/bin/uname -X | grep "^Machine"` in *486*) UNAME_MACHINE=i486 ;; *Pentium) UNAME_MACHINE=i586 ;; *Pent*|*Celeron) UNAME_MACHINE=i686 ;; esac echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} exit 0 ;; i*86:*:3.2:*) if test -f /usr/options/cb.name; then UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ && UNAME_MACHINE=i586 (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ && UNAME_MACHINE=i686 (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ && UNAME_MACHINE=i686 echo ${UNAME_MACHINE}-pc-sco$UNAME_REL else echo ${UNAME_MACHINE}-pc-sysv32 fi exit 0 ;; pc:*:*:*) # Left here for compatibility: # uname -m prints for DJGPP always 'pc', but it prints nothing about # the processor, so we play safe by assuming i386. echo i386-pc-msdosdjgpp exit 0 ;; Intel:Mach:3*:*) echo i386-pc-mach3 exit 0 ;; paragon:*:*:*) echo i860-intel-osf1 exit 0 ;; i860:*:4.*:*) # i860-SVR4 if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 else # Add other i860-SVR4 vendors below as they are discovered. echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 fi exit 0 ;; mini*:CTIX:SYS*5:*) # "miniframe" echo m68010-convergent-sysv exit 0 ;; mc68k:UNIX:SYSTEM5:3.51m) echo m68k-convergent-sysv exit 0 ;; M680?0:D-NIX:5.3:*) echo m68k-diab-dnix exit 0 ;; M68*:*:R3V[567]*:*) test -r /sysV68 && echo 'm68k-motorola-sysv' && exit 0 ;; 3[34]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0) OS_REL='' test -r /etc/.relid \ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && echo i486-ncr-sysv4.3${OS_REL} && exit 0 /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ && echo i586-ncr-sysv4.3${OS_REL} && exit 0 ;; 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && echo i486-ncr-sysv4 && exit 0 ;; m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) echo m68k-unknown-lynxos${UNAME_RELEASE} exit 0 ;; mc68030:UNIX_System_V:4.*:*) echo m68k-atari-sysv4 exit 0 ;; TSUNAMI:LynxOS:2.*:*) echo sparc-unknown-lynxos${UNAME_RELEASE} exit 0 ;; rs6000:LynxOS:2.*:*) echo rs6000-unknown-lynxos${UNAME_RELEASE} exit 0 ;; PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*) echo powerpc-unknown-lynxos${UNAME_RELEASE} exit 0 ;; SM[BE]S:UNIX_SV:*:*) echo mips-dde-sysv${UNAME_RELEASE} exit 0 ;; RM*:ReliantUNIX-*:*:*) echo mips-sni-sysv4 exit 0 ;; RM*:SINIX-*:*:*) echo mips-sni-sysv4 exit 0 ;; *:SINIX-*:*:*) if uname -p 2>/dev/null >/dev/null ; then UNAME_MACHINE=`(uname -p) 2>/dev/null` echo ${UNAME_MACHINE}-sni-sysv4 else echo ns32k-sni-sysv fi exit 0 ;; PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort # says echo i586-unisys-sysv4 exit 0 ;; *:UNIX_System_V:4*:FTX*) # From Gerald Hewes . # How about differentiating between stratus architectures? -djm echo hppa1.1-stratus-sysv4 exit 0 ;; *:*:*:FTX*) # From seanf@swdc.stratus.com. echo i860-stratus-sysv4 exit 0 ;; *:VOS:*:*) # From Paul.Green@stratus.com. echo hppa1.1-stratus-vos exit 0 ;; mc68*:A/UX:*:*) echo m68k-apple-aux${UNAME_RELEASE} exit 0 ;; news*:NEWS-OS:6*:*) echo mips-sony-newsos6 exit 0 ;; R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) if [ -d /usr/nec ]; then echo mips-nec-sysv${UNAME_RELEASE} else echo mips-unknown-sysv${UNAME_RELEASE} fi exit 0 ;; BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. echo powerpc-be-beos exit 0 ;; BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. echo powerpc-apple-beos exit 0 ;; BePC:BeOS:*:*) # BeOS running on Intel PC compatible. echo i586-pc-beos exit 0 ;; SX-4:SUPER-UX:*:*) echo sx4-nec-superux${UNAME_RELEASE} exit 0 ;; SX-5:SUPER-UX:*:*) echo sx5-nec-superux${UNAME_RELEASE} exit 0 ;; SX-6:SUPER-UX:*:*) echo sx6-nec-superux${UNAME_RELEASE} exit 0 ;; Power*:Rhapsody:*:*) echo powerpc-apple-rhapsody${UNAME_RELEASE} exit 0 ;; *:Rhapsody:*:*) echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} exit 0 ;; *:Darwin:*:*) case `uname -p` in *86) UNAME_PROCESSOR=i686 ;; powerpc) UNAME_PROCESSOR=powerpc ;; esac echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} exit 0 ;; *:procnto*:*:* | *:QNX:[0123456789]*:*) UNAME_PROCESSOR=`uname -p` if test "$UNAME_PROCESSOR" = "x86"; then UNAME_PROCESSOR=i386 UNAME_MACHINE=pc fi echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} exit 0 ;; *:QNX:*:4*) echo i386-pc-qnx exit 0 ;; NSR-[DGKLNPTVW]:NONSTOP_KERNEL:*:*) echo nsr-tandem-nsk${UNAME_RELEASE} exit 0 ;; *:NonStop-UX:*:*) echo mips-compaq-nonstopux exit 0 ;; BS2000:POSIX*:*:*) echo bs2000-siemens-sysv exit 0 ;; DS/*:UNIX_System_V:*:*) echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} exit 0 ;; *:Plan9:*:*) # "uname -m" is not consistent, so use $cputype instead. 386 # is converted to i386 for consistency with other x86 # operating systems. if test "$cputype" = "386"; then UNAME_MACHINE=i386 else UNAME_MACHINE="$cputype" fi echo ${UNAME_MACHINE}-unknown-plan9 exit 0 ;; *:TOPS-10:*:*) echo pdp10-unknown-tops10 exit 0 ;; *:TENEX:*:*) echo pdp10-unknown-tenex exit 0 ;; KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) echo pdp10-dec-tops20 exit 0 ;; XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) echo pdp10-xkl-tops20 exit 0 ;; *:TOPS-20:*:*) echo pdp10-unknown-tops20 exit 0 ;; *:ITS:*:*) echo pdp10-unknown-its exit 0 ;; esac #echo '(No uname command or uname output not recognized.)' 1>&2 #echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2 eval $set_cc_for_build cat >$dummy.c < # include #endif main () { #if defined (sony) #if defined (MIPSEB) /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, I don't know.... */ printf ("mips-sony-bsd\n"); exit (0); #else #include printf ("m68k-sony-newsos%s\n", #ifdef NEWSOS4 "4" #else "" #endif ); exit (0); #endif #endif #if defined (__arm) && defined (__acorn) && defined (__unix) printf ("arm-acorn-riscix"); exit (0); #endif #if defined (hp300) && !defined (hpux) printf ("m68k-hp-bsd\n"); exit (0); #endif #if defined (NeXT) #if !defined (__ARCHITECTURE__) #define __ARCHITECTURE__ "m68k" #endif int version; version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; if (version < 4) printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); else printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); exit (0); #endif #if defined (MULTIMAX) || defined (n16) #if defined (UMAXV) printf ("ns32k-encore-sysv\n"); exit (0); #else #if defined (CMU) printf ("ns32k-encore-mach\n"); exit (0); #else printf ("ns32k-encore-bsd\n"); exit (0); #endif #endif #endif #if defined (__386BSD__) printf ("i386-pc-bsd\n"); exit (0); #endif #if defined (sequent) #if defined (i386) printf ("i386-sequent-dynix\n"); exit (0); #endif #if defined (ns32000) printf ("ns32k-sequent-dynix\n"); exit (0); #endif #endif #if defined (_SEQUENT_) struct utsname un; uname(&un); if (strncmp(un.version, "V2", 2) == 0) { printf ("i386-sequent-ptx2\n"); exit (0); } if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ printf ("i386-sequent-ptx1\n"); exit (0); } printf ("i386-sequent-ptx\n"); exit (0); #endif #if defined (vax) # if !defined (ultrix) # include # if defined (BSD) # if BSD == 43 printf ("vax-dec-bsd4.3\n"); exit (0); # else # if BSD == 199006 printf ("vax-dec-bsd4.3reno\n"); exit (0); # else printf ("vax-dec-bsd\n"); exit (0); # endif # endif # else printf ("vax-dec-bsd\n"); exit (0); # endif # else printf ("vax-dec-ultrix\n"); exit (0); # endif #endif #if defined (alliant) && defined (i860) printf ("i860-alliant-bsd\n"); exit (0); #endif exit (1); } EOF $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && $dummy && exit 0 # Apollos put the system type in the environment. test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit 0; } # Convex versions that predate uname can use getsysinfo(1) if [ -x /usr/convex/getsysinfo ] then case `getsysinfo -f cpu_type` in c1*) echo c1-convex-bsd exit 0 ;; c2*) if getsysinfo -f scalar_acc then echo c32-convex-bsd else echo c2-convex-bsd fi exit 0 ;; c34*) echo c34-convex-bsd exit 0 ;; c38*) echo c38-convex-bsd exit 0 ;; c4*) echo c4-convex-bsd exit 0 ;; esac fi cat >&2 < in order to provide the needed information to handle your system. config.guess timestamp = $timestamp uname -m = `(uname -m) 2>/dev/null || echo unknown` uname -r = `(uname -r) 2>/dev/null || echo unknown` uname -s = `(uname -s) 2>/dev/null || echo unknown` uname -v = `(uname -v) 2>/dev/null || echo unknown` /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` /bin/uname -X = `(/bin/uname -X) 2>/dev/null` hostinfo = `(hostinfo) 2>/dev/null` /bin/universe = `(/bin/universe) 2>/dev/null` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` /bin/arch = `(/bin/arch) 2>/dev/null` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` UNAME_MACHINE = ${UNAME_MACHINE} UNAME_RELEASE = ${UNAME_RELEASE} UNAME_SYSTEM = ${UNAME_SYSTEM} UNAME_VERSION = ${UNAME_VERSION} EOF exit 1 # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" # End: Pound-2.8/pound.80000664000175000017500000010410313275266545012726 0ustar rosegroseg.TH POUND "8" "Jan 2010" "pound" "System Manager's Manual" .SH NAME pound \- HTTP/HTTPS reverse-proxy and load-balancer .SH SYNOPSIS .TP .B pound [\fI-v\fR] [\fI-c\fR] [\fI-V\fR] [\fI-f config_file\fR] [\fI-p pid_file\fR] .SH DESCRIPTION .PP .B Pound is a reverse-proxy load balancing server. It accepts requests from HTTP/HTTPS clients and distributes them to one or more Web servers. The HTTPS requests are decrypted and passed to the back-ends as plain HTTP. .PP If more than one back-end server is defined, .B Pound chooses one of them randomly, based on defined priorities. By default, .B Pound keeps track of associations between clients and back-end servers (sessions). .SH GENERAL PRINCIPLES .P In general .B Pound needs three types of objects defined in order to function: .IR listeners , .I services and .IR back-ends . .TP \fBListeners\fR A .I listener is a definition of how .B Pound receives requests from the clients (browsers). Two types of .I listeners may be defined: regular HTTP .I listeners and HTTPS (HTTP over SSL/TLS) .IR listeners . At the very least a .I listener must define the address and port to listen on, with additional requirements for HTTPS .IR listeners . .TP \fBServices\fR A .I service is the definition of how the requests are answered. The .I services may be defined within a .I listener or at the top level (global). When a request is received .B Pound attempts to match them to each .I service in turn, starting with the .I services defined in the .I listener itself and, if needed, continuing with the .I services defined at the global level. The .I services may define their own conditions as to which requests they can answer: typically this involves certain URLs (images only, or a certain path) or specific headers (such as the Host header). A .I service may also define a .I session mechanism: if defined future requests from a given client will always be answered by the same .IR back-end . .TP \fBBack-ends\fR The .I back-ends are the actual servers for the content requested. By itself, .B Pound supplies no responses - all contents must be received from a "real" web server. The .I back-end defines how the server should be contacted. .IP Three types of .I back-ends may be defined: a "regular" .I back-end which receives requests and returns responses, a "redirect" .I back-end in which case .B Pound will respond with a redirect response, without accessing any .I back-end at all, or an "emergency" .I back-end which will be used only if all other backends are "dead". .IP Multiple .I back-ends may be defined within a .IR service , in which case .B Pound will load-balance between the available .IR back-ends . .IP If a .I back-end fails to respond it will be considered "dead", in which case .B Pound will stop sending requests to it. Dead .I back-ends are periodically checked for availability, and once they respond again they are "resurected" and requests are sent again their way. If no .I back-ends are available (none were defined, or all are "dead") then .B Pound will reply with "503 Service Unavailable", without checking additional .IR services . .IP The connection between .B Pound and the .I back-ends is always via HTTP, regardless of the actual protocol used between .B Pound and the client. .SH OPTIONS Options available (see also below for configuration file options): .TP \fB\-v\fR Verbose mode: error messages will be sent to stdout even if .B Pound was configured to log to syslog. This applies only to startup messages, before .B Pound puts itself in the background. Normal operational messages will still go to syslog. .TP \fB\-V\fR Print version: .B Pound will exit immediately after printing the current version and configuration flags. .TP \fB\-c\fR Check only: .B Pound will exit immediately after parsing the configuration file. This may be used for running a quick syntax check before actually activating a server. .TP \fB\-f\fR config_file Location of the configuration file (see below for a full description of the format). Default: .I /usr/local/etc/pound.cfg .TP \fB\-p\fR pid_file Location of the pid file. .B Pound will write its own pid into this file. Normally this is used for shell scripts that control starting and stopping of the daemon. Default: .I /var/run/pound.pid .PP In general, any number of back-end servers may be specified. Use the priority to affect the load distribution among unequal-performance servers. .PP One (or more) copies of .B Pound should be started at boot time. Use "big iron" if you expect heavy loads: while .B Pound is as light-weight as I know how to make it, with a lot of simultaneous requests it will use quite a bit of CPU and memory. Multiple CPUs are your friend. .SH "CONFIGURATION FILE" Each line in the file is considered a complete configuration directive. The directives are case-insensitive. Empty lines or lines starting in '#' are ignored. There are three types of directives: .B global directives (they affect the settings for the entire program instance), .B listener directives (they define which requests .B Pound will listen for), and .B service directives (they affect only a specific group of requests). .SH "GLOBAL DIRECTIVES" Global directives may appear anywhere within the configuration file, though it is customary for them to be at the start. They may appear in any order. .TP \fBUser\fR "user_name" Specify the user .B Pound will run as (must be defined in \fI/etc/passwd\fR). .TP \fBGroup\fR "group_name" Specify the group .B Pound will run as (must be defined in \fI/etc/group\fR). .TP \fBRootJail\fR "directory_path_and_name" Specify the directory that .B Pound will chroot to at runtime. Please note that OpenSSL requires access to /dev/urandom, so make sure you create a device by that name, accessible from the root jail directory. .B Pound may also require access to .I /dev/syslog or similar. .TP \fBDaemon\fR 0|1 Have .B Pound run in the foreground (if 0) or as a daemon (if 1). By default .B Pound runs as a daemon (detaches itself from the controlling terminal and puts itself in the background). By specifying this option you can force .B Pound to work like a regular process. Useful for debugging or if you want to use something like \fIdaemontools\fR. .TP \fBThreads\fR nnn How many worker threads .B Pound should use. Default: 128. Tune this parameter to improve performance. If you set it too high, .B Pound will use a lot memory, and some CPU will be wasted on context switches. If you set it too low requests may be served with some delay. Experiment to find the optimal value for your installation. .TP \fBLogFacility\fR value Specify the log facility to use. .I value (default: daemon) must be one of the symbolic facility names defined in \fIsyslog.h\fR. This facility shall be used for logging. Using a - for the facility name causes .B Pound to log to stdout/stderr. .TP \fBLogLevel\fR value Specify the logging level: 0 for no logging, 1 (default) for regular logging, 2 for extended logging (show chosen backend server as well), 3 for Apache-like format (Combined Log Format with Virtual Host), 4 (same as 3 but without the virtual host information) and 5 (same as 4 but with information about the .I Service and .I BackEnd used). This value can be overridden for specific listeners. .TP \fBIgnoreCase\fR 0|1 Ignore case when matching URLs (default: 0). This value can be overridden for specific services. .TP \fBAlive\fR value Specify how often .B Pound will check for resurected back-end hosts (default: 30 seconds). In general, it is a good idea to set this as low as possible - it will find resurected hosts faster. However, if you set it too low it will consume resources - so beware. .TP \fBClient\fR value Specify for how long .B Pound will wait for a client request (default: 10 seconds). After this long has passed without the client sending any data .B Pound will close the connection. Set it higher if your clients time-out on a slow network or over-loaded server, lower if you start getting DOS attacks or run into problems with IE clients. This value can be overridden for specific listeners. .TP \fBTimeOut\fR value How long should .B Pound wait for a response from the back-end (in seconds). Default: 15 seconds. This value can be overridden for specific back-ends. .TP \fBConnTO\fR value How long should .B Pound wait for a connection to the back-end (in seconds). Default: the .B TimeOut value. This value can be overridden for specific back-ends. .TP \fBGrace\fR value How long should .B Pound continue to answer existing connections after a receiving and INT or HUP signal (default: 30 seconds). The configured listeners are closed immediately. You can bypass this behaviour by stopping .B Pound with a TERM or QUIT signal, in which case the program exits without any delay. .TP \fBSSLEngine\fR "name" Use an OpenSSL hardware acceleration card called \fIname\fR. Available only if OpenSSL-engine is installed on your system. .TP \fBECDHcurve\fR "name" Use the named curve for elliptical curve encryption (default: prime256v1). .TP \fBControl\fR "/path/to/socket" Set the control socket path. If not defined .B Pound does not listen for any commands. The commands may be issued by using the .I poundctl(8) program. .TP \fBInclude\fR "/path/to/file" Include the file as though it were part of the configuration file. .TP \fBAnonymise\fR Replace the last byte of the client address with 0 for logging purposes. Default: log the client address in full. .SH "HTTP Listener" An HTTP listener defines an address and port that .B Pound will listen on for HTTP requests. All configuration directives enclosed between .I ListenHTTP and .I End are specific to a single HTTP listener. At the very least you must specify and address and a port for each listener. The following directives are available: .TP \fBAddress\fR address The address that .B Pound will listen on. This can be a numeric IP address, or a symbolic host name that must be resolvable at run-time. This is a .B mandatory parameter. The address 0.0.0.0 may be used as an alias for 'all available addresses on this machine', but this practice is strongly discouraged, as it will interfere with the rewriting mechanisms (see below). .TP \fBPort\fR port The port number that .B Pound will listen on. This is a .B mandatory parameter. .TP \fBxHTTP\fR value Defines which HTTP verbs are accepted. The possible values are: .IP .I 0 (default) accept only standard HTTP requests (GET, POST, HEAD). .IP .I 1 additionally allow extended HTTP requests (PUT, PATCH, DELETE). .IP .I 2 additionally allow standard WebDAV verbs (LOCK, UNLOCK, PROPFIND, PROPPATCH, SEARCH, MKCOL, MOVE, COPY, OPTIONS, TRACE, MKACTIVITY, CHECKOUT, MERGE, REPORT). .IP .I 3 additionally allow MS extensions WebDAV verbs (SUBSCRIBE, UNSUBSCRIBE, NOTIFY, BPROPFIND, BPROPPATCH, POLL, BMOVE, BCOPY, BDELETE, CONNECT). .IP .I 4 additionally allow MS RPC extensions verbs (RPC_IN_DATA, RPC_OUT_DATA). .TP \fBClient\fR value Override the global .I Client time-out value. .TP \fBCheckURL\fR "pattern to match" Define a pattern that must be matched by each request sent to this listener. A request that does not match is considered to be illegal. By default .B Pound accepts all requests (i.e. the pattern is ".*"), but you are free to limit it to something more reasonable. Please note that this applies only to the request path - .B Pound will still check that the request is syntactically correct. .TP \fBErr414\fR "filename" A file with the text to be displayed if an Error 414 occurs. Default: "Request URI is too long.". .TP \fBErr500\fR "filename" A file with the text to be displayed if an Error 500 occurs. Default: "An internal server error occurred. Please try again later.". .TP \fBErr501\fR "filename" A file with the text to be displayed if an Error 501 occurs. Default: "This method may not be used.". .TP \fBErr503\fR "filename" A file with the text to be displayed if an Error 503 occurs. Default: "The service is not available. Please try again later.". .TP \fBMaxRequest\fR nnn Request maximal size. All requests will be limited to these many bytes. If a request contains more data than allowed an error 414 is returned. Default: unlimited. .TP \fBHeadRemove\fR "header pattern" Remove certain headers from the incoming requests. All occurences of the matching specified header will be removed. Please note that this filtering is done prior to other checks (such as \fIHeadRequire\fR or \fIHeadDeny\fR), so you should not try to check for these headers in later matches. Multiple directives may be specified in order to remove more than one header, and the header itself may be a regular pattern (though this should be used with caution). .TP \fBAddHeader\fR "header: to add" Add the defined header to the request passed to the back-end server. The header is added verbatim. Use multiple \fIAddHeader\fR directives if you need to add more than one header. .TP \fBRewriteLocation\fR 0|1|2 If 1 force .B Pound to change the Location: and Content-location: headers in responses. If they point to the back-end itself or to the listener (but with the wrong protocol) the response will be changed to show the virtual host in the request. Default: 1 (active). If the value is set to 2 only the back-end address is compared; this is useful for redirecting a request to an HTTPS listener on the same server as the HTTP listener. .TP \fBRewriteDestination\fR 0|1 If 1 force .B Pound to change the Destination: header in requests. The header is changed to point to the back-end itself with the correct protocol. Default: 0. .TP \fBLogLevel\fR value Override the global .I LogLevel value. .TP \fBService\fR [ "name" ] This defines a private service (see below for service definition syntax). This service will be used only by this listener. The service may be optionally named, with the name showing in the .I poundctl listings. .SH "HTTPS Listener" An HTTPS listener defines an address and port that .B Pound will listen on for HTTPS requests. All configuration directives enclosed between .I ListenHTTPS and .I End are specific to a single HTTPS listener. At the very least you must specify and address, a port and a server certificate for each listener. All directives defined for HTTP listeners are applicable to HTTPS listeners as well. The following additional directives are also available: .TP \fBCert\fR "certificate file" Specify the server certificate. The .I certificate file is the file containing the certificate, possibly a certificate chain and the signature for this server. This directive is .B mandatory for HTTPS listeners. .IP Please note that multiple .I Cert directives are allowed if your OpenSSL version supports SNI. In such cases, the first directive is the default certificate, with additional certificates used if the client requests them. .IP The ordering of the directives is important: the first certificate where the CN matches the client request will be used, so put your directives in the most-specific-to-least specific order (i.e. wildcard certificates .B after host-specific certificates). .IP .I Cert directives .B must precede all other SSL-specific directives. .TP \fBClientCert\fR 0|1|2|3 depth Ask for the client's HTTPS certificate: 0 - don't ask (default), 1 - ask, 2 - ask and fail if no certificate was presented, 3 - ask but do not verify. .I Depth is the depth of verification for a client certificate (up to 9). The default depth limit is 9, allowing for the peer certificate and additional 9 CA certificates that must be verified. .TP \fBDisable\fR SSLv2|SSLv3|TLSv1|TLSv1_1|TLSv1_2 Disable the protocol \fBand all lower protocols as well\fR. This is due to a limitation in OpenSSL, which does not support disabling a single protocol. For example, .I Disable TLSv1 would disable SSLv2, SSLv3 and TLSv1, thus allowing only TLSv1_1 and TLSv1_2. .TP \fBCiphers\fR "acceptable:cipher:list" This is the list of ciphers that will be accepted by the SSL connection; it is a string in the same format as in OpenSSL .I ciphers(1) and .I SSL_CTX_set_cipher_list(3). .TP \fBSSLHonorCipherOrder\fR 0|1 If this value is 1, the server will broadcast a preference to use \fBCiphers\fR in the order supplied in the \fBCiphers\fR directive. If the value is 0, the server will treat the Ciphers list as the list of Ciphers it will accept, but no preference will be indicated. Default value is 0. .TP \fBSSLAllowClientRenegotiation\fR 0|1|2 If this value is 0, client initiated renegotiation will be disabled. This will mitigate DoS exploits based on client renegotiation, regardless of the patch status of clients and servers related to "Secure renegotiation". If the value is 1, secure renegotiation is supported. If the value is 2, insecure renegotiation is supported, with unpatched clients. \fBThis can lead to a DoS and a Man in the Middle attack!\fR The default value is 0. .TP \fBCAlist\fR "CAcert_file" Set the list of "trusted" CA's for this server. The CAcert_file is a file containing a sequence of CA certificates (PEM format). The names of the defined CA certificates will be sent to the client on connection. .TP \fBVerifyList\fR "Verify_file" Set the CA (Certificate Authority). The Verify_file is a file that contains the CA root certificates (in PEM format). .IP .IR "Please note": there is an important difference between the CAlist and the VerifyList. The CAlist tells the client (browser) which client certificates it should send. The VerifyList defines which CAs are actually used for the verification of the returned certificate. .TP \fBCRLlist\fR "CRL_file" Set the CRL (Certificate Revocation List) file. The CRL_file is a file that contains the CRLs (in PEM format). .TP \fBNoHTTPS11\fR 0|1|2 Behave like an HTTP/1.0 server for HTTPS clients. If this value is 0 disable the check. If the value is 1 do not allow multiple requests on SSL connections. If the value is 2 (default) disable multiple requests on SSL connections only for MSIE clients. Required work-around for a bug in certain versions of IE. .SH "Service" A service is a definition of which back-end servers .B Pound will use to reply to incoming requests. A service may be defined as part of a listener (in which case it will be used only by that listener), or globally (which makes it available to all listeners). .B Pound will always try the private services in the order defined, followed by the global ones. .P All configuration directives enclosed between .I Service and .I End are specific to a single service. The following directives are available: .TP \fBURL\fR "pattern" Match the incoming request. If a request fails to match than this service will be skipped and next one tried. If all services fail to match .B Pound returns an error. You may define multiple .I URL conditions per service, in which case .B all patterns must match. If no .I URL was defined then all requests match. The matching is by default case-sensitive, but this can be overridden by specifying .B IgnoreCase 1 .TP \fBIgnoreCase\fR 0|1 Override the global .B IgnoreCase setting. .TP \fBHeadRequire\fR "pattern" The request must contain at least on header matching the given pattern. Multiple .I HeadRequire directives may be defined per service, in which case all of them must be satisfied. .TP \fBHeadDeny\fR "pattern" The request may .B not contain any header matching the given pattern. Multiple .I HeadDeny directives may be defined per service, in which case all of them must be satisfied. .IP .IR "Please note": if the listener defined a .I HeadRemove directive, the matching headers are removed .B before the service matching is attempted. .TP \fBDisabled\fR 0|1 Start .B Pound with this service disabled (1) or enabled (0). If started as disabled, the service can be later enabled with .I poundctl (8). .TP \fBBackEnd\fR Directives enclosed between a .I BackEnd and the following .I End directives define a single back-end server (see below for details). You may define multiple back-ends per service, in which case .B Pound will attempt to load-balance between them. .TP \fBRedirect\fR [code] "url" This is a special type of back-end. Instead of sending the request to a back-end .B Pound replies immediately with a redirection to the given URL. You may define multiple redirectors in a service, as well as mixing them with regular back-ends. .IP The address the client is redirected to is determined by the actual .I url you specify: if it is a "pure" host (i.e. with no path) then the client will be redirected to the host you specified, with the original request path appended. If your .I url does contain a path then the request path is ignored. .IP Examples: if you specified .br .br Redirect "http://abc.example" .br .br and the client requested .I http://xyz/a/b/c then it will be redirected to .IR "http://abc.example/a/b/c", but if you specified .br .br Redirect "http://abc.example/index.html" .br .br it will be sent to .IR "http://abc.example/index.html". .IP .IR "Technical note": in an ideal world .B Pound should reply with a "307 Temporary Redirect" status. Unfortunately, that is not yet supported by all clients (in particular HTTP 1.0 ones), so .B Pound currently replies by default with a "302 Found" instead. You may override this behaviour by specifying the code to be used (301, 302 or 307). .TP \fBEmergency\fR Directives enclosed between an .I Emergency and the following .I End directives define an emergency back-end server (see below for details). You may define only one emergency server per service, which .B Pound will attempt to use if all backends are down. .TP \fBSession\fR Directives enclosed between a .I Session and the following .I End directives define a session-tracking mechanism for the current service. See below for details. .SH "BackEnd" A back-end is a definition of a single back-end server .B Pound will use to reply to incoming requests. All configuration directives enclosed between .I BackEnd and .I End are specific to a single service. The following directives are available: .TP \fBAddress\fR address The address that .B Pound will connect to. This can be a numeric IP address, or a symbolic host name that must be resolvable at run-time. If the name cannot be resolved to a valid address, .B Pound will assume that it represents the path for a Unix-domain socket. This is a .B mandatory parameter. .TP \fBPort\fR port The port number that .B Pound will connect to. This is a .B mandatory parameter for non Unix-domain back-ends. .TP \fBHTTPS\fR The back-end is using HTTPS. .TP \fBCert\fR "certificate file" Specify the certificate that .B Pound will use as a client. The .I certificate file is the file containing the certificate, possibly a certificate chain and the signature. This directive may appear only after the .I HTTPS directive. .TP \fBDisable\fR SSLv2|SSLv3|TLSv1|TLSv1_1|TLSv1_2 Disable the protocol \fBand all lower protocols as well\fR. This is due to a limitation in OpenSSL, which does not support disabling a single protocol. For example, .I Disable TLSv1 would disable SSLv2, SSLv3 and TLSv1, thus allowing only TLSv1_1 and TLSv1_2. This directive may appear only after the .I HTTPS directive. .TP \fBCiphers\fR "acceptable:cipher:list" This is the list of ciphers that will be accepted by the SSL connection; it is a string in the same format as in OpenSSL .I ciphers(1) and .I SSL_CTX_set_cipher_list(3). This directive may appear only after the .I HTTPS directive. .TP \fBPriority\fR val The priority of this back-end (between 1 and 9, 5 is default). Higher priority back-ends will be used more often than lower priority ones, so you should define higher priorities for more capable servers. .TP \fBTimeOut\fR val Override the global .I TimeOut value. .TP \fBConnTO\fR val Override the global .I ConnTO value. .TP \fBHAport\fR [ address ] port A port (and optional address) to be used for server function checks. See below the "High Availability" section for a more detailed discussion. By default .B Pound uses the same address as the back-end server, but you may use a separate address if you wish. This directive applies only to non Unix-domain servers. .TP \fBDisabled\fR 0|1 Start .B Pound with this back-end disabled (1) or enabled (0). If started as disabled, the back-end can be later enabled with .I poundctl (8). .SH "Emergency" The emergency server will be used once all existing back-ends are "dead". All configuration directives enclosed between .I Emergency and .I End are specific to a single service. The following directives are available: .TP \fBAddress\fR address The address that .B Pound will connect to. This can be a numeric IP address, or a symbolic host name that must be resolvable at run-time. If the name cannot be resolved to a valid address, .B Pound will assume that it represents the path for a Unix-domain socket. This is a .B mandatory parameter. .TP \fBPort\fR port The port number that .B Pound will connect to. This is a .B mandatory parameter for non Unix-domain back-ends. .SH "Session" Defines how a service deals with possible HTTP sessions. All configuration directives enclosed between .I Session and .I End are specific to a single service. Once a sessions is identified, .B Pound will attempt to send all requests within that session to the same back-end server. .PP The following directives are available: .TP \fBType\fR IP|BASIC|URL|PARM|COOKIE|HEADER What kind of sessions are we looking for: IP (the client address), BASIC (basic authentication), URL (a request parameter), PARM (a URI parameter), COOKIE (a certain cookie), or HEADER (a certain request header). This is a .B mandatory parameter. .TP \fBTTL\fR seconds How long can a session be idle (in seconds). A session that has been idle for longer than the specified number of seconds will be discarded. This is a .B mandatory parameter. .TP \fBID\fR "name" The session identifier. This directive is permitted only for sessions of type URL (the name of the request parameter we need to track), COOKIE (the name of the cookie) and HEADER (the header name). .PP See below for some examples. .SH HIGH-AVAILABILITY .B Pound attempts to keep track of active back-end servers, and will temporarily disable servers that do not respond (though not necessarily dead: an overloaded server that .B Pound cannot establish a connection to will be considered dead). However, every .I Alive seconds, an attempt is made to connect to the dead servers in case they have become active again. If this attempt succeeds, connections will be initiated to them again. .PP In general it is a good idea to set this time interval as low as is consistent with your resources in order to benefit from resurected servers at the earliest possible time. The default value of 30 seconds is probably a good choice. .PP The clients that happen upon a dead backend server will just receive a .I "503 Service Unavailable" message. .PP The .I HAport parameter specifies an additional port (and optionally an address) that is used only for viability checks: if this port is specified in a .I BackEnd directive, .B Pound will attempt periodically (every .I Alive seconds) to connect to this port. If the port does not respond the server is considered dead. .B "It never makes sense to have the" .I HAport .B "identical to the main back-end port:" this would only generate extra, unncecessary activity (CPU, network traffic) for no good reason whatsoever. The .I HAport is meant for applications that offer an additional health monitoring port or for installations that wish to take servers off-line in a controlled manner. .PP By default the address of the .I HAport health monitor is the same as that of the back-end server. You may specify a different address though, for example if you have a monitoring program running on another host. .SH HTTPS HEADERS If a client browser connects to .B Pound via HTTPS and if it presents a client certificate .B Pound adds the following headers to the request it issues to the server: .TP \fBX-SSL-Subject\fR Details about the certificate owner. .TP \fBX-SSL-Issuer\fR Details about the certificate issuer (Certificate Authority). .TP \fBX-SSL-notBefore\fR Starting date of certificate validity. .TP \fBX-SSL-notAfter\fR Ending date of certificate validity. .TP \fBX-SSL-serial\fR Certificate serial number (decimal). .TP \fBX-SSL-cipher\fR The cipher currently in use. .TP \fBX-SSL-certificate\fR The full client certificate (PEM-format multi-line) .PP It is the application's responsibility to actually use these headers - Pound just passes this information without checking it in any way (except for signature and encryption correctness). .SH SECURITY .PP In general, .B Pound does not read or write to the hard-disk. The exceptions are reading the configuration file and (possibly) the server certificate file(s) and error message(s), which are opened read-only on startup, read, and closed, and the pid file which is opened on start-up, written to and immediately closed. Following this there is no disk access whatsoever, so using a RootJail directive is only for extra security bonus points. .PP .B Pound tries to sanitise all HTTP/HTTPS requests: the request itself, the headers and the contents are checked for conformance to the RFC's and only valid requests are passed to the back-end servers. This is not absolutely fool-proof - as the recent Apache problem with chunked transfers demonstrated. However, given the current standards, this is the best that can be done - HTTP is an inherently weak protocol. .SH ADDITIONAL NOTES .B Pound uses the system log for messages (default facility LOG_DAEMON). The format is very similar to other web servers, so that if you want to use a log tool: .TP fgrep pound /var/log/messages | your_log_tool .PP Translating HTTPS to HTTP is an iffy proposition: no client information is passed to the server itself (certificates, etc) and the backend server may be misled if it uses absolute URLs. A patch for \fIZope\fR is included in the distribution to address this issue - for other Web servers you are on your own. May the source be with you. .PP .B Pound deals with (and sanitizes) HTTP/1.1 requests. Thus even if you have an HTTP/1.0 server, a single connection to an HTTP/1.1 client is kept, while the connection to the back-end server is re-opened as necessary. .PP .B Pound attempts to resolve the names of the hosts that appear in various requests and/or responses. That means it need a functioning resolver of some kind (be it /etc/hosts, DNS or something else). .SH EXAMPLES To translate HTTPS requests to a local HTTP server (assuming your network address is 123.123.123.123): .IP ListenHTTPS .br Address 1.2.3.4 .br Port 443 .br Cert "/etc/pound/server.pem" .br .br Service .br BackEnd .br Address 127.0.0.1 .br Port 80 .br End .br End .br End .PP To distribute the HTTP/HTTPS requests to three Web servers, where the third one is a newer and faster machine: .IP ListenHTTP .br Address 123.123.123.123 .br Port 80 .br End .br ListenHTTPS .br Address 1.2.3.4 .br Port 443 .br Cert "/etc/pound/server.pem" .br End .br .br Service .br BackEnd .br Address 192.168.0.10 .br Port 80 .br End .br BackEnd .br Address 192.168.0.11 .br Port 80 .br End .br BackEnd .br Address 192.168.0.12 .br Port 80 .br Priority 3 .br End .br End .PP To separate between image requests and other Web content and send all requests for a specific URL to a secure server: .IP ListenHTTP .br Address 123.123.123.123 .br Port 80 .br End .br .br # Images server(s) .br Service .br URL ".*.(jpg|gif)" .br BackEnd .br Address 192.168.0.12 .br Port 80 .br End .br End .br .br # redirect all requests for /forbidden .br Service .br Url "/forbidden.*" .br Redirect "https://xyzzy.com" .br End .br .br # Catch-all server(s) .br Service .br BackEnd .br Address 192.168.0.10 .br Port 80 .br End .br BackEnd .br Address 192.168.0.11 .br Port 80 .br End .br Session .br Type BASIC .br TTL 300 .br End .br End .PP Here is a more complex example: assume your static images (GIF/JPEG) are to be served from a single back-end 192.168.0.10. In addition, 192.168.0.11 is to do the hosting for www.myserver.com with URL-based sessions, and 192.168.0.20 (a 1GHz PIII) and 192.168.0.21 (800Mhz Duron) are for all other requests (cookie-based sessions). The logging will be done by the back-end servers. The configuration file may look like this: .IP User "nobody" .br Group "nogroup" .br RootJail "/var/pound/jail" .br Alive 60 .br LogLevel 0 .br .br # Main listening ports .br ListenHTTP .br Address 1.2.3.4 .br Port 80 .br Client 10 .br End .br ListenHTTPS .br Address 1.2.3.4 .br Port 443 .br Cert "/etc/pound/pound.pem" .br Client 20 .br End .br .br # Image server .br Service .br URL ".*.(jpg|gif)" .br BackEnd .br Address 192.168.0.10 .br Port 80 .br End .br End .br .br # Virtual host www.myserver.com .br Service .br URL ".*sessid=.*" .br HeadRequire "Host:.*www.myserver.com.*" .br BackEnd .br Address 192.168.0.11 .br Port 80 .br End .br Session .br Type URL .br ID "sessid" .br TTL 120 .br End .br End .br .br # Everybody else .br Service .br BackEnd .br Address 192.168.0.20 .br Port 80 .br Priority 5 .br End .br BackEnd .br Address 192.168.0.21 .br Port 80 .br Priority 4 .br End .br Session .br Type COOKIE .br ID "userid" .br TTL 180 .br End .br End .br .SH FILES .TP \fI/var/run/pound.nnn\fR this is where .B Pound will attempt to record its process id. .TP \fI/usr/local/etc/pound.cfg\fR the default configuration file (the location may be changed when compiling - see the F_CONF flag in the Makefile). .TP \fI/usr/local/etc/pound/cert.pem\fR the certificate file(s) for HTTPS. The location must be defined in the configuration file - this is only a suggestion. The file must contain a PEM-encoded certificate, optionally a certificate chain from a known Certificate Authority to your server certificate and a PEM-encoded private key (not password protected). See .I OpenSSL(1) for details. This file should be well protected, lest someone gets your server private key. .SH AUTHOR Written by Robert Segall, Apsis GmbH. .SH "REPORTING BUGS" Report bugs to . .SH COPYRIGHT Copyright \(co 2002-2010 Apsis GmbH. .br This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. Pound-2.8/http.c0000664000175000017500000017436413275266545012653 0ustar rosegroseg/* * Pound - the reverse-proxy load-balancer * Copyright (C) 2002-2010 Apsis GmbH * * This file is part of Pound. * * Pound is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * Pound is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * Contact information: * Apsis GmbH * P.O.Box * 8707 Uetikon am See * Switzerland * EMail: roseg@apsis.ch */ #include "pound.h" /* HTTP error replies */ static char *h500 = "500 Internal Server Error", *h501 = "501 Not Implemented", *h503 = "503 Service Unavailable", *h414 = "414 Request URI too long", *h400 = "Bad Request"; static char *err_response = "HTTP/1.0 %s\r\nContent-Type: text/html\r\nContent-Length: %d\r\nExpires: now\r\nPragma: no-cache\r\nCache-control: no-cache,no-store\r\n\r\n%s"; /* * Reply with an error */ static void err_reply(BIO *const c, const char *head, const char *txt) { BIO_printf(c, err_response, head, strlen(txt), txt); BIO_flush(c); return; } /* * Reply with a redirect */ static void redirect_reply(BIO *const c, const char *url, const int code) { char rep[MAXBUF], cont[MAXBUF], safe_url[MAXBUF], *code_msg; int i, j; switch(code) { case 301: code_msg = "Moved Permanently"; break; case 307: code_msg = "Temporary Redirect"; break; default: code_msg = "Found"; break; } /* * Make sure to return a safe version of the URL (otherwise CSRF becomes a possibility) */ memset(safe_url, 0, MAXBUF); for(i = j = 0; i < MAXBUF && j < MAXBUF && url[i]; i++) if(isalnum(url[i]) || url[i] == '_' || url[i] == '.' || url[i] == ':' || url[i] == '/' || url[i] == '?' || url[i] == '&' || url[i] == ';' || url[i] == '-' || url[i] == '=') safe_url[j++] = url[i]; else { sprintf(safe_url + j, "%%%02x", url[i]); j += 3; } snprintf(cont, sizeof(cont), "Redirect

Redirect

You should go to %s

", safe_url, safe_url); snprintf(rep, sizeof(rep), "HTTP/1.0 %d %s\r\nLocation: %s\r\nContent-Type: text/html\r\nContent-Length: %d\r\n\r\n", code, code_msg, safe_url, (int)strlen(cont)); BIO_write(c, rep, strlen(rep)); BIO_write(c, cont, strlen(cont)); BIO_flush(c); return; } /* * Read and write some binary data */ static int copy_bin(BIO *const cl, BIO *const be, LONG cont, LONG *res_bytes, const int no_write) { char buf[MAXBUF]; int res; while(cont > L0) { if((res = BIO_read(cl, buf, cont > MAXBUF? MAXBUF: cont)) < 0) return -1; else if(res == 0) return -2; if(!no_write) if(BIO_write(be, buf, res) != res) return -3; cont -= res; if(res_bytes) *res_bytes += res; } if(!no_write) if(BIO_flush(be) != 1) return -4; return 0; } /* * Get a "line" from a BIO, strip the trailing newline, skip the input stream if buffer too small * The result buffer is NULL terminated * Return 0 on success */ static int get_line(BIO *const in, char *const buf, const int bufsize) { char tmp; int i, n_read, seen_cr; memset(buf, 0, bufsize); for(i = 0, seen_cr = 0; i < bufsize - 1; i++) switch(BIO_read(in, &tmp, 1)) { case -2: /* BIO_gets not implemented */ return -1; case 0: case -1: return 1; default: if(seen_cr) if(tmp != '\n') { /* we have CR not followed by NL */ do { if(BIO_read(in, &tmp, 1) < 0) return 1; } while(tmp != '\n'); return 1; } else { buf[i - 1] = '\0'; return 0; } if(!iscntrl(tmp) || tmp == '\t') { buf[i] = tmp; continue; } if(tmp == '\r') { seen_cr = 1; continue; } if(tmp == '\n') { /* line ends in NL only (no CR) */ buf[i] = 0; return 0; } /* all other control characters cause an error */ do { if(BIO_read(in, &tmp, 1) < 0) return 1; } while(tmp != '\n'); return 1; } /* line too long */ do { if(BIO_read(in, &tmp, 1) < 0) return 1; } while(tmp != '\n'); return 1; } /* * Strip trailing CRLF */ static int strip_eol(char *lin) { while(*lin) if(*lin == '\n' || (*lin == '\r' && *(lin + 1) == '\n')) { *lin = '\0'; return 1; } else lin++; return 0; } /* * Copy chunked */ static int copy_chunks(BIO *const cl, BIO *const be, LONG *res_bytes, const int no_write, const LONG max_size) { char buf[MAXBUF]; LONG cont, tot_size; regmatch_t matches[2]; int res; for(tot_size = 0L;;) { if((res = get_line(cl, buf, MAXBUF)) < 0) { logmsg(LOG_NOTICE, "(%lx) chunked read error: %s", pthread_self(), strerror(errno)); return -1; } else if(res > 0) /* EOF */ return 0; if(!regexec(&CHUNK_HEAD, buf, 2, matches, 0)) cont = STRTOL(buf, NULL, 16); else { /* not chunk header */ logmsg(LOG_NOTICE, "(%lx) bad chunk header <%s>: %s", pthread_self(), buf, strerror(errno)); return -2; } if(!no_write) if(BIO_printf(be, "%s\r\n", buf) <= 0) { logmsg(LOG_NOTICE, "(%lx) error write chunked: %s", pthread_self(), strerror(errno)); return -3; } tot_size += cont; if(max_size > L0 && tot_size > max_size) { logmsg(LOG_WARNING, "(%lx) chunk content too large", pthread_self); return -4; } if(cont > L0) { if(copy_bin(cl, be, cont, res_bytes, no_write)) { if(errno) logmsg(LOG_NOTICE, "(%lx) error copy chunk cont: %s", pthread_self(), strerror(errno)); return -4; } } else break; /* final CRLF */ if((res = get_line(cl, buf, MAXBUF)) < 0) { logmsg(LOG_NOTICE, "(%lx) error after chunk: %s", pthread_self(), strerror(errno)); return -5; } else if(res > 0) { logmsg(LOG_NOTICE, "(%lx) unexpected EOF after chunk", pthread_self()); return -5; } if(buf[0]) logmsg(LOG_NOTICE, "(%lx) unexpected after chunk \"%s\"", pthread_self(), buf); if(!no_write) if(BIO_printf(be, "%s\r\n", buf) <= 0) { logmsg(LOG_NOTICE, "(%lx) error after chunk write: %s", pthread_self(), strerror(errno)); return -6; } } /* possibly trailing headers */ for(;;) { if((res = get_line(cl, buf, MAXBUF)) < 0) { logmsg(LOG_NOTICE, "(%lx) error post-chunk: %s", pthread_self(), strerror(errno)); return -7; } else if(res > 0) break; if(!no_write) if(BIO_printf(be, "%s\r\n", buf) <= 0) { logmsg(LOG_NOTICE, "(%lx) error post-chunk write: %s", pthread_self(), strerror(errno)); return -8; } if(!buf[0]) break; } if(!no_write) if(BIO_flush(be) != 1) { logmsg(LOG_NOTICE, "(%lx) copy_chunks flush error: %s", pthread_self(), strerror(errno)); return -4; } return 0; } static int err_to = -1; typedef struct { int timeout; RENEG_STATE *reneg_state; } BIO_ARG; /* * Time-out for client read/gets * the SSL manual says not to do it, but it works well enough anyway... */ static long bio_callback(BIO *const bio, const int cmd, const char *argp, int argi, long argl, long ret) { BIO_ARG *bio_arg; struct pollfd p; int to, p_res, p_err; if(cmd != BIO_CB_READ && cmd != BIO_CB_WRITE) return ret; /* a time-out already occured */ if((bio_arg = (BIO_ARG*)BIO_get_callback_arg(bio))==NULL) return ret; if((to = bio_arg->timeout * 1000) < 0) { errno = ETIMEDOUT; return -1; } /* Renegotiations */ /* logmsg(LOG_NOTICE, "RENEG STATE %d", bio_arg->reneg_state==NULL?-1:*bio_arg->reneg_state); */ if (bio_arg->reneg_state != NULL && *bio_arg->reneg_state == RENEG_ABORT) { logmsg(LOG_NOTICE, "REJECTING renegotiated session"); errno = ECONNABORTED; return -1; } if (to == 0) return ret; for(;;) { memset(&p, 0, sizeof(p)); BIO_get_fd(bio, &p.fd); p.events = (cmd == BIO_CB_READ)? (POLLIN | POLLPRI): POLLOUT; p_res = poll(&p, 1, to); p_err = errno; switch(p_res) { case 1: if(cmd == BIO_CB_READ) { if((p.revents & POLLIN) || (p.revents & POLLPRI)) /* there is readable data */ return ret; else { #ifdef EBUG logmsg(LOG_WARNING, "(%lx) CALLBACK read 0x%04x poll: %s", pthread_self(), p.revents, strerror(p_err)); #endif errno = EIO; } } else { if(p.revents & POLLOUT) /* data can be written */ return ret; else { #ifdef EBUG logmsg(LOG_WARNING, "(%lx) CALLBACK write 0x%04x poll: %s", pthread_self(), p.revents, strerror(p_err)); #endif errno = ECONNRESET; } } return -1; case 0: /* timeout - mark the BIO as unusable for the future */ bio_arg->timeout = err_to; #ifdef EBUG logmsg(LOG_WARNING, "(%lx) CALLBACK timeout poll after %d secs: %s", pthread_self(), to / 1000, strerror(p_err)); #endif errno = ETIMEDOUT; return 0; default: /* error */ if(p_err != EINTR) { #ifdef EBUG logmsg(LOG_WARNING, "(%lx) CALLBACK bad %d poll: %s", pthread_self(), p_res, strerror(p_err)); #endif return -2; #ifdef EBUG } else logmsg(LOG_WARNING, "(%lx) CALLBACK interrupted %d poll: %s", pthread_self(), p_res, strerror(p_err)); #else } #endif } } } /* * Check if the file underlying a BIO is readable */ static int is_readable(BIO *const bio, const int to_wait) { struct pollfd p; if(BIO_pending(bio) > 0) return 1; memset(&p, 0, sizeof(p)); BIO_get_fd(bio, &p.fd); p.events = POLLIN | POLLPRI; return (poll(&p, 1, to_wait * 1000) > 0); } static void free_headers(char **headers) { int i; for(i = 0; i < MAXHEADERS; i++) if(headers[i]) free(headers[i]); free(headers); return; } static char ** get_headers(BIO *const in, BIO *const cl, const LISTENER *lstn) { char **headers, buf[MAXBUF]; int res, n, has_eol; /* HTTP/1.1 allows leading CRLF */ memset(buf, 0, MAXBUF); while((res = get_line(in, buf, MAXBUF)) == 0) if(buf[0]) break; if(res < 0) { /* this is expected to occur only on client reads */ /* logmsg(LOG_NOTICE, "headers: bad starting read"); */ return NULL; } if((headers = (char **)calloc(MAXHEADERS, sizeof(char *))) == NULL) { logmsg(LOG_WARNING, "(%lx) e500 headers: out of memory", pthread_self()); err_reply(cl, h500, lstn->err500); return NULL; } if((headers[0] = (char *)malloc(MAXBUF)) == NULL) { free_headers(headers); logmsg(LOG_WARNING, "(%lx) e500 header: out of memory", pthread_self()); err_reply(cl, h500, lstn->err500); return NULL; } memset(headers[0], 0, MAXBUF); strncpy(headers[0], buf, MAXBUF - 1); for(n = 1; n < MAXHEADERS; n++) { if(get_line(in, buf, MAXBUF)) { free_headers(headers); /* this is not necessarily an error, EOF/timeout are possible logmsg(LOG_WARNING, "(%lx) e500 can't read header", pthread_self()); err_reply(cl, h500, lstn->err500); */ return NULL; } if(!buf[0]) return headers; if((headers[n] = (char *)malloc(MAXBUF)) == NULL) { free_headers(headers); logmsg(LOG_WARNING, "(%lx) e500 header: out of memory", pthread_self()); err_reply(cl, h500, lstn->err500); return NULL; } memset(headers[n], 0, MAXBUF); strncpy(headers[n], buf, MAXBUF - 1); } free_headers(headers); logmsg(LOG_NOTICE, "(%lx) e500 too many headers", pthread_self()); err_reply(cl, h500, lstn->err500); return NULL; } #define LOG_TIME_SIZE 32 /* * Apache log-file-style time format */ static void log_time(char *res) { time_t now; struct tm *t_now, t_res; now = time(NULL); #ifdef HAVE_LOCALTIME_R t_now = localtime_r(&now, &t_res); #else t_now = localtime(&now); #endif strftime(res, LOG_TIME_SIZE - 1, "%d/%b/%Y:%H:%M:%S %z", t_now); return; } static double cur_time(void) { #ifdef HAVE_GETTIMEOFDAY struct timeval tv; struct timezone tz; int sv_errno; sv_errno = errno; gettimeofday(&tv, &tz); errno = sv_errno; return tv.tv_sec * 1000000.0 + tv.tv_usec; #else return time(NULL) * 1000000.0; #endif } #define LOG_BYTES_SIZE 32 /* * Apache log-file-style number format */ static void log_bytes(char *res, const LONG cnt) { if(cnt > L0) #ifdef HAVE_LONG_LONG_INT snprintf(res, LOG_BYTES_SIZE - 1, "%lld", cnt); #else snprintf(res, LOG_BYTES_SIZE - 1, "%ld", cnt); #endif else strcpy(res, "-"); return; } /* Cleanup code. This should really be in the pthread_cleanup_push, except for bugs in some implementations */ #define clean_all() { \ if(ssl != NULL) { BIO_ssl_shutdown(cl); } \ if(be != NULL) { BIO_flush(be); BIO_reset(be); BIO_free_all(be); be = NULL; } \ if(cl != NULL) { BIO_flush(cl); BIO_reset(cl); BIO_free_all(cl); cl = NULL; } \ if(x509 != NULL) { X509_free(x509); x509 = NULL; } \ if(ssl != NULL) { ERR_clear_error(); ERR_remove_state(0); } \ } /* * handle an HTTP request */ void do_http(thr_arg *arg) { int cl_11, be_11, res, chunked, n, sock, no_cont, skip, conn_closed, force_10, sock_proto, is_rpc; LISTENER *lstn; SERVICE *svc; BACKEND *backend, *cur_backend, *old_backend; struct addrinfo from_host, z_addr; struct sockaddr_storage from_host_addr; BIO *cl, *be, *bb, *b64; X509 *x509; char request[MAXBUF], response[MAXBUF], buf[MAXBUF], url[MAXBUF], loc_path[MAXBUF], **headers, headers_ok[MAXHEADERS], v_host[MAXBUF], referer[MAXBUF], u_agent[MAXBUF], u_name[MAXBUF], caddr[MAXBUF], req_time[LOG_TIME_SIZE], s_res_bytes[LOG_BYTES_SIZE], *mh; SSL *ssl, *be_ssl; LONG cont, res_bytes; regmatch_t matches[4]; struct linger l; double start_req, end_req; RENEG_STATE reneg_state; BIO_ARG ba1, ba2; reneg_state = RENEG_INIT; ba1.reneg_state = &reneg_state; ba2.reneg_state = &reneg_state; ba1.timeout = 0; ba2.timeout = 0; from_host = ((thr_arg *)arg)->from_host; memcpy(&from_host_addr, from_host.ai_addr, from_host.ai_addrlen); from_host.ai_addr = (struct sockaddr *)&from_host_addr; lstn = ((thr_arg *)arg)->lstn; sock = ((thr_arg *)arg)->sock; free(((thr_arg *)arg)->from_host.ai_addr); free(arg); if(lstn->allow_client_reneg) reneg_state = RENEG_ALLOW; n = 1; setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, (void *)&n, sizeof(n)); l.l_onoff = 1; l.l_linger = 10; setsockopt(sock, SOL_SOCKET, SO_LINGER, (void *)&l, sizeof(l)); #ifdef TCP_LINGER2 n = 5; setsockopt(sock, SOL_TCP, TCP_LINGER2, (void *)&n, sizeof(n)); #endif n = 1; setsockopt(sock, SOL_TCP, TCP_NODELAY, (void *)&n, sizeof(n)); cl = NULL; be = NULL; ssl = NULL; x509 = NULL; if((cl = BIO_new_socket(sock, 1)) == NULL) { logmsg(LOG_WARNING, "(%lx) BIO_new_socket failed", pthread_self()); shutdown(sock, 2); close(sock); return; } ba1.timeout = lstn->to; BIO_set_callback_arg(cl, (char *)&ba1); BIO_set_callback(cl, bio_callback); if(lstn->ctx != NULL) { if((ssl = SSL_new(lstn->ctx->ctx)) == NULL) { logmsg(LOG_WARNING, "(%lx) SSL_new: failed", pthread_self()); BIO_reset(cl); BIO_free_all(cl); return; } SSL_set_app_data(ssl, &reneg_state); SSL_set_bio(ssl, cl, cl); if((bb = BIO_new(BIO_f_ssl())) == NULL) { logmsg(LOG_WARNING, "(%lx) BIO_new(Bio_f_ssl()) failed", pthread_self()); BIO_reset(cl); BIO_free_all(cl); return; } BIO_set_ssl(bb, ssl, BIO_CLOSE); BIO_set_ssl_mode(bb, 0); cl = bb; if(BIO_do_handshake(cl) <= 0) { /* no need to log every client without a certificate... addr2str(caddr, MAXBUF - 1, &from_host, 1); logmsg(LOG_NOTICE, "BIO_do_handshake with %s failed: %s", caddr, ERR_error_string(ERR_get_error(), NULL)); x509 = NULL; */ BIO_reset(cl); BIO_free_all(cl); return; } else { if((x509 = SSL_get_peer_certificate(ssl)) != NULL && lstn->clnt_check < 3 && SSL_get_verify_result(ssl) != X509_V_OK) { addr2str(caddr, MAXBUF - 1, &from_host, 1); logmsg(LOG_NOTICE, "Bad certificate from %s", caddr); X509_free(x509); BIO_reset(cl); BIO_free_all(cl); return; } } } else { x509 = NULL; } cur_backend = NULL; if((bb = BIO_new(BIO_f_buffer())) == NULL) { logmsg(LOG_WARNING, "(%lx) BIO_new(buffer) failed", pthread_self()); if(x509 != NULL) X509_free(x509); BIO_reset(cl); BIO_free_all(cl); return; } BIO_set_close(cl, BIO_CLOSE); BIO_set_buffer_size(cl, MAXBUF); cl = BIO_push(bb, cl); for(cl_11 = be_11 = 0;;) { res_bytes = L0; is_rpc = -1; v_host[0] = referer[0] = u_agent[0] = u_name[0] = '\0'; conn_closed = 0; for(n = 0; n < MAXHEADERS; n++) headers_ok[n] = 1; if((headers = get_headers(cl, cl, lstn)) == NULL) { if(!cl_11) { if(errno) { addr2str(caddr, MAXBUF - 1, &from_host, 1); logmsg(LOG_NOTICE, "(%lx) error read from %s: %s", pthread_self(), caddr, strerror(errno)); /* err_reply(cl, h500, lstn->err500); */ } } clean_all(); return; } memset(req_time, 0, LOG_TIME_SIZE); start_req = cur_time(); log_time(req_time); /* check for correct request */ strncpy(request, headers[0], MAXBUF); if(!regexec(&lstn->verb, request, 3, matches, 0)) { no_cont = !strncasecmp(request + matches[1].rm_so, "HEAD", matches[1].rm_eo - matches[1].rm_so); if(!strncasecmp(request + matches[1].rm_so, "RPC_IN_DATA", matches[1].rm_eo - matches[1].rm_so)) is_rpc = 1; else if(!strncasecmp(request + matches[1].rm_so, "RPC_OUT_DATA", matches[1].rm_eo - matches[1].rm_so)) is_rpc = 0; } else { addr2str(caddr, MAXBUF - 1, &from_host, 1); logmsg(LOG_WARNING, "(%lx) e501 bad request \"%s\" from %s", pthread_self(), request, caddr); err_reply(cl, h501, lstn->err501); free_headers(headers); clean_all(); return; } cl_11 = (request[strlen(request) - 1] == '1'); n = cpURL(url, request + matches[2].rm_so, matches[2].rm_eo - matches[2].rm_so); if(n != strlen(url)) { /* the URL probably contained a %00 aka NULL - which we don't allow */ addr2str(caddr, MAXBUF - 1, &from_host, 1); logmsg(LOG_NOTICE, "(%lx) e501 URL \"%s\" (contains NULL) from %s", pthread_self(), url, caddr); err_reply(cl, h501, lstn->err501); free_headers(headers); clean_all(); return; } if(lstn->has_pat && regexec(&lstn->url_pat, url, 0, NULL, 0)) { addr2str(caddr, MAXBUF - 1, &from_host, 1); logmsg(LOG_NOTICE, "(%lx) e501 bad URL \"%s\" from %s", pthread_self(), url, caddr); err_reply(cl, h501, lstn->err501); free_headers(headers); clean_all(); return; } /* check other headers */ for(chunked = 0, cont = L_1, n = 1; n < MAXHEADERS && headers[n]; n++) { /* no overflow - see check_header for details */ switch(check_header(headers[n], buf)) { case HEADER_HOST: strcpy(v_host, buf); break; case HEADER_REFERER: strcpy(referer, buf); break; case HEADER_USER_AGENT: strcpy(u_agent, buf); break; case HEADER_CONNECTION: if(!strcasecmp("close", buf)) conn_closed = 1; break; case HEADER_TRANSFER_ENCODING: if(!strcasecmp("chunked", buf)) chunked = 1; else { addr2str(caddr, MAXBUF - 1, &from_host, 1); logmsg(LOG_NOTICE, "(%lx) e400 multiple Transfer-encoding \"%s\" from %s", pthread_self(), url, caddr); err_reply(cl, h400, "Bad request: multiple Transfer-encoding values"); free_headers(headers); clean_all(); return; } break; case HEADER_CONTENT_LENGTH: if(cont != L_1 || strchr(buf, ',')) { addr2str(caddr, MAXBUF - 1, &from_host, 1); logmsg(LOG_NOTICE, "(%lx) e400 multiple Content-length \"%s\" from %s", pthread_self(), url, caddr); err_reply(cl, h400, "Bad request: multiple Content-length values"); free_headers(headers); clean_all(); return; } for(mh = buf; *mh; mh++) if(!isdigit(*mh)) { addr2str(caddr, MAXBUF - 1, &from_host, 1); logmsg(LOG_NOTICE, "(%lx) e400 Content-length bad value \"%s\" from %s", pthread_self(), url, caddr); err_reply(cl, h400, "Bad request: Content-length bad value"); free_headers(headers); clean_all(); return; } if((cont = ATOL(buf)) < 0L) headers_ok[n] = 0; if(is_rpc == 1 && (cont < 0x20000L || cont > 0x80000000L)) is_rpc = -1; break; case HEADER_EXPECT: /* * we do NOT support the "Expect: 100-continue" headers * support may involve severe performance penalties (non-responding back-end, etc) * as a stop-gap measure we just skip these headers */ if(!strcasecmp("100-continue", buf)) headers_ok[n] = 0; break; case HEADER_ILLEGAL: if(lstn->log_level > 0) { addr2str(caddr, MAXBUF - 1, &from_host, 1); logmsg(LOG_NOTICE, "(%lx) bad header from %s (%s)", pthread_self(), caddr, headers[n]); } headers_ok[n] = 0; break; } if(headers_ok[n] && lstn->head_off) { /* maybe header to be removed */ MATCHER *m; for(m = lstn->head_off; m; m = m->next) if(!(headers_ok[n] = regexec(&m->pat, headers[n], 0, NULL, 0))) break; } /* get User name */ if(!regexec(&AUTHORIZATION, headers[n], 2, matches, 0)) { int inlen; if((bb = BIO_new(BIO_s_mem())) == NULL) { logmsg(LOG_WARNING, "(%lx) Can't alloc BIO_s_mem", pthread_self()); continue; } if((b64 = BIO_new(BIO_f_base64())) == NULL) { logmsg(LOG_WARNING, "(%lx) Can't alloc BIO_f_base64", pthread_self()); BIO_free(bb); continue; } b64 = BIO_push(b64, bb); BIO_write(bb, headers[n] + matches[1].rm_so, matches[1].rm_eo - matches[1].rm_so); BIO_write(bb, "\n", 1); if((inlen = BIO_read(b64, buf, MAXBUF - 1)) <= 0) { logmsg(LOG_WARNING, "(%lx) Can't read BIO_f_base64", pthread_self()); BIO_free_all(b64); continue; } BIO_free_all(b64); if((mh = strchr(buf, ':')) == NULL) { logmsg(LOG_WARNING, "(%lx) Unknown authentication", pthread_self()); continue; } *mh = '\0'; strcpy(u_name, buf); } } /* check for possible request smuggling attempt */ if(chunked != 0 && cont != L_1) { addr2str(caddr, MAXBUF - 1, &from_host, 1); logmsg(LOG_NOTICE, "(%lx) e501 Transfer-encoding and Content-length \"%s\" from %s", pthread_self(), url, caddr); err_reply(cl, h400, "Bad request: Transfer-encoding and Content-length headers present"); free_headers(headers); clean_all(); return; } /* possibly limited request size */ if(lstn->max_req > L0 && cont > L0 && cont > lstn->max_req && is_rpc != 1) { addr2str(caddr, MAXBUF - 1, &from_host, 1); logmsg(LOG_NOTICE, "(%lx) e501 request too large (%ld) from %s", pthread_self(), cont, caddr); err_reply(cl, h501, lstn->err501); free_headers(headers); clean_all(); return; } if(be != NULL) { if(is_readable(be, 0)) { /* The only way it's readable is if it's at EOF, so close it! */ BIO_reset(be); BIO_free_all(be); be = NULL; } } /* check that the requested URL still fits the old back-end (if any) */ if((svc = get_service(lstn, url, &headers[1])) == NULL) { addr2str(caddr, MAXBUF - 1, &from_host, 1); logmsg(LOG_NOTICE, "(%lx) e503 no service \"%s\" from %s %s", pthread_self(), request, caddr, v_host[0]? v_host: "-"); err_reply(cl, h503, lstn->err503); free_headers(headers); clean_all(); return; } if((backend = get_backend(svc, &from_host, url, &headers[1])) == NULL) { addr2str(caddr, MAXBUF - 1, &from_host, 1); logmsg(LOG_NOTICE, "(%lx) e503 no back-end \"%s\" from %s %s", pthread_self(), request, caddr, v_host[0]? v_host: "-"); err_reply(cl, h503, lstn->err503); free_headers(headers); clean_all(); return; } if(be != NULL && backend != cur_backend) { BIO_reset(be); BIO_free_all(be); be = NULL; } while(be == NULL && backend->be_type == 0) { switch(backend->addr.ai_family) { case AF_INET: sock_proto = PF_INET; break; case AF_INET6: sock_proto = PF_INET6; break; case AF_UNIX: sock_proto = PF_UNIX; break; default: logmsg(LOG_WARNING, "(%lx) e503 backend: unknown family %d", pthread_self(), backend->addr.ai_family); err_reply(cl, h503, lstn->err503); free_headers(headers); clean_all(); return; } if((sock = socket(sock_proto, SOCK_STREAM, 0)) < 0) { str_be(buf, MAXBUF - 1, backend); logmsg(LOG_WARNING, "(%lx) e503 backend %s socket create: %s", pthread_self(), buf, strerror(errno)); err_reply(cl, h503, lstn->err503); free_headers(headers); clean_all(); return; } if(connect_nb(sock, &backend->addr, backend->conn_to) < 0) { str_be(buf, MAXBUF - 1, backend); logmsg(LOG_WARNING, "(%lx) backend %s connect: %s", pthread_self(), buf, strerror(errno)); shutdown(sock, 2); close(sock); /* * kill the back-end only if no HAport is defined for it * otherwise allow the HAport mechanism to do its job */ memset(&z_addr, 0, sizeof(z_addr)); if(memcmp(&(backend->ha_addr), &(z_addr), sizeof(z_addr)) == 0) kill_be(svc, backend, BE_KILL); /* * ...but make sure we don't get into a loop with the same back-end */ old_backend = backend; if((backend = get_backend(svc, &from_host, url, &headers[1])) == NULL || backend == old_backend) { addr2str(caddr, MAXBUF - 1, &from_host, 1); logmsg(LOG_NOTICE, "(%lx) e503 no back-end \"%s\" from %s", pthread_self(), request, caddr); err_reply(cl, h503, lstn->err503); free_headers(headers); clean_all(); return; } continue; } if(sock_proto == PF_INET || sock_proto == PF_INET6) { n = 1; setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, (void *)&n, sizeof(n)); l.l_onoff = 1; l.l_linger = 10; setsockopt(sock, SOL_SOCKET, SO_LINGER, (void *)&l, sizeof(l)); #ifdef TCP_LINGER2 n = 5; setsockopt(sock, SOL_TCP, TCP_LINGER2, (void *)&n, sizeof(n)); #endif n = 1; setsockopt(sock, SOL_TCP, TCP_NODELAY, (void *)&n, sizeof(n)); } if((be = BIO_new_socket(sock, 1)) == NULL) { logmsg(LOG_WARNING, "(%lx) e503 BIO_new_socket server failed", pthread_self()); shutdown(sock, 2); close(sock); err_reply(cl, h503, lstn->err503); free_headers(headers); clean_all(); return; } BIO_set_close(be, BIO_CLOSE); if(backend->to > 0) { ba2.timeout = backend->to; BIO_set_callback_arg(be, (char *)&ba2); BIO_set_callback(be, bio_callback); } if(backend->ctx != NULL) { if((be_ssl = SSL_new(backend->ctx)) == NULL) { logmsg(LOG_WARNING, "(%lx) be SSL_new: failed", pthread_self()); err_reply(cl, h503, lstn->err503); free_headers(headers); clean_all(); return; } SSL_set_bio(be_ssl, be, be); if((bb = BIO_new(BIO_f_ssl())) == NULL) { logmsg(LOG_WARNING, "(%lx) BIO_new(Bio_f_ssl()) failed", pthread_self()); err_reply(cl, h503, lstn->err503); free_headers(headers); clean_all(); return; } BIO_set_ssl(bb, be_ssl, BIO_CLOSE); BIO_set_ssl_mode(bb, 1); be = bb; if(BIO_do_handshake(be) <= 0) { str_be(buf, MAXBUF - 1, backend); logmsg(LOG_NOTICE, "BIO_do_handshake with %s failed: %s", buf, ERR_error_string(ERR_get_error(), NULL)); err_reply(cl, h503, lstn->err503); free_headers(headers); clean_all(); return; } } if((bb = BIO_new(BIO_f_buffer())) == NULL) { logmsg(LOG_WARNING, "(%lx) e503 BIO_new(buffer) server failed", pthread_self()); err_reply(cl, h503, lstn->err503); free_headers(headers); clean_all(); return; } BIO_set_buffer_size(bb, MAXBUF); BIO_set_close(bb, BIO_CLOSE); be = BIO_push(bb, be); } cur_backend = backend; /* if we have anything but a BACK_END we close the channel */ if(be != NULL && cur_backend->be_type) { BIO_reset(be); BIO_free_all(be); be = NULL; } /* send the request */ if(cur_backend->be_type == 0) { for(n = 0; n < MAXHEADERS && headers[n]; n++) { if(!headers_ok[n]) continue; /* this is the earliest we can check for Destination - we had no back-end before */ if(lstn->rewr_dest && check_header(headers[n], buf) == HEADER_DESTINATION) { if(regexec(&LOCATION, buf, 4, matches, 0)) { logmsg(LOG_NOTICE, "(%lx) Can't parse Destination %s", pthread_self(), buf); break; } str_be(caddr, MAXBUF - 1, cur_backend); strcpy(loc_path, buf + matches[3].rm_so); snprintf(buf, MAXBUF, "Destination: http://%s%s", caddr, loc_path); free(headers[n]); if((headers[n] = strdup(buf)) == NULL) { logmsg(LOG_WARNING, "(%lx) rewrite Destination - out of memory: %s", pthread_self(), strerror(errno)); free_headers(headers); clean_all(); return; } } if(BIO_printf(be, "%s\r\n", headers[n]) <= 0) { str_be(buf, MAXBUF - 1, cur_backend); end_req = cur_time(); logmsg(LOG_WARNING, "(%lx) e500 error write to %s/%s: %s (%.3f sec)", pthread_self(), buf, request, strerror(errno), (end_req - start_req) / 1000000.0); err_reply(cl, h500, lstn->err500); free_headers(headers); clean_all(); return; } } /* add header if required */ if(lstn->add_head != NULL) if(BIO_printf(be, "%s\r\n", lstn->add_head) <= 0) { str_be(buf, MAXBUF - 1, cur_backend); end_req = cur_time(); logmsg(LOG_WARNING, "(%lx) e500 error write AddHeader to %s: %s (%.3f sec)", pthread_self(), buf, strerror(errno), (end_req - start_req) / 1000000.0); err_reply(cl, h500, lstn->err500); free_headers(headers); clean_all(); return; } } free_headers(headers); /* if SSL put additional headers for client certificate */ if(cur_backend->be_type == 0 && ssl != NULL) { const SSL_CIPHER *cipher; if((cipher = SSL_get_current_cipher(ssl)) != NULL) { SSL_CIPHER_description(cipher, buf, MAXBUF - 1); strip_eol(buf); if(BIO_printf(be, "X-SSL-cipher: %s/%s\r\n", SSL_get_version(ssl), buf) <= 0) { str_be(buf, MAXBUF - 1, cur_backend); end_req = cur_time(); logmsg(LOG_WARNING, "(%lx) e500 error write X-SSL-cipher to %s: %s (%.3f sec)", pthread_self(), buf, strerror(errno), (end_req - start_req) / 1000000.0); err_reply(cl, h500, lstn->err500); clean_all(); return; } } if(lstn->clnt_check > 0 && x509 != NULL && (bb = BIO_new(BIO_s_mem())) != NULL) { X509_NAME_print_ex(bb, X509_get_subject_name(x509), 8, XN_FLAG_ONELINE & ~ASN1_STRFLGS_ESC_MSB); get_line(bb, buf, MAXBUF); if(BIO_printf(be, "X-SSL-Subject: %s\r\n", buf) <= 0) { str_be(buf, MAXBUF - 1, cur_backend); end_req = cur_time(); logmsg(LOG_WARNING, "(%lx) e500 error write X-SSL-Subject to %s: %s (%.3f sec)", pthread_self(), buf, strerror(errno), (end_req - start_req) / 1000000.0); err_reply(cl, h500, lstn->err500); BIO_free_all(bb); clean_all(); return; } X509_NAME_print_ex(bb, X509_get_issuer_name(x509), 8, XN_FLAG_ONELINE & ~ASN1_STRFLGS_ESC_MSB); get_line(bb, buf, MAXBUF); if(BIO_printf(be, "X-SSL-Issuer: %s\r\n", buf) <= 0) { str_be(buf, MAXBUF - 1, cur_backend); end_req = cur_time(); logmsg(LOG_WARNING, "(%lx) e500 error write X-SSL-Issuer to %s: %s (%.3f sec)", pthread_self(), buf, strerror(errno), (end_req - start_req) / 1000000.0); err_reply(cl, h500, lstn->err500); BIO_free_all(bb); clean_all(); return; } ASN1_TIME_print(bb, X509_get_notBefore(x509)); get_line(bb, buf, MAXBUF); if(BIO_printf(be, "X-SSL-notBefore: %s\r\n", buf) <= 0) { str_be(buf, MAXBUF - 1, cur_backend); end_req = cur_time(); logmsg(LOG_WARNING, "(%lx) e500 error write X-SSL-notBefore to %s: %s (%.3f sec)", pthread_self(), buf, strerror(errno), (end_req - start_req) / 1000000.0); err_reply(cl, h500, lstn->err500); BIO_free_all(bb); clean_all(); return; } ASN1_TIME_print(bb, X509_get_notAfter(x509)); get_line(bb, buf, MAXBUF); if(BIO_printf(be, "X-SSL-notAfter: %s\r\n", buf) <= 0) { str_be(buf, MAXBUF - 1, cur_backend); end_req = cur_time(); logmsg(LOG_WARNING, "(%lx) e500 error write X-SSL-notAfter to %s: %s (%.3f sec)", pthread_self(), buf, strerror(errno), (end_req - start_req) / 1000000.0); err_reply(cl, h500, lstn->err500); BIO_free_all(bb); clean_all(); return; } if(BIO_printf(be, "X-SSL-serial: %ld\r\n", ASN1_INTEGER_get(X509_get_serialNumber(x509))) <= 0) { str_be(buf, MAXBUF - 1, cur_backend); end_req = cur_time(); logmsg(LOG_WARNING, "(%lx) e500 error write X-SSL-serial to %s: %s (%.3f sec)", pthread_self(), buf, strerror(errno), (end_req - start_req) / 1000000.0); err_reply(cl, h500, lstn->err500); BIO_free_all(bb); clean_all(); return; } PEM_write_bio_X509(bb, x509); get_line(bb, buf, MAXBUF); if(BIO_printf(be, "X-SSL-certificate: %s", buf) <= 0) { str_be(buf, MAXBUF - 1, cur_backend); end_req = cur_time(); logmsg(LOG_WARNING, "(%lx) e500 error write X-SSL-certificate to %s: %s (%.3f sec)", pthread_self(), buf, strerror(errno), (end_req - start_req) / 1000000.0); err_reply(cl, h500, lstn->err500); BIO_free_all(bb); clean_all(); return; } while(get_line(bb, buf, MAXBUF) == 0) { if(BIO_printf(be, "%s", buf) <= 0) { str_be(buf, MAXBUF - 1, cur_backend); end_req = cur_time(); logmsg(LOG_WARNING, "(%lx) e500 error write X-SSL-certificate to %s: %s (%.3f sec)", pthread_self(), buf, strerror(errno), (end_req - start_req) / 1000000.0); err_reply(cl, h500, lstn->err500); BIO_free_all(bb); clean_all(); return; } } if(BIO_printf(be, "\r\n") <= 0) { str_be(buf, MAXBUF - 1, cur_backend); end_req = cur_time(); logmsg(LOG_WARNING, "(%lx) e500 error write X-SSL-certificate to %s: %s (%.3f sec)", pthread_self(), buf, strerror(errno), (end_req - start_req) / 1000000.0); err_reply(cl, h500, lstn->err500); BIO_free_all(bb); clean_all(); return; } BIO_free_all(bb); } } /* put additional client IP header */ if(cur_backend->be_type == 0) { addr2str(caddr, MAXBUF - 1, &from_host, 1); BIO_printf(be, "X-Forwarded-For: %s\r\n", caddr); /* final CRLF */ BIO_puts(be, "\r\n"); } if(cl_11 && chunked) { /* had Transfer-encoding: chunked so read/write all the chunks (HTTP/1.1 only) */ if(copy_chunks(cl, be, NULL, cur_backend->be_type, lstn->max_req)) { str_be(buf, MAXBUF - 1, cur_backend); end_req = cur_time(); addr2str(caddr, MAXBUF - 1, &from_host, 1); logmsg(LOG_NOTICE, "(%lx) e500 for %s copy_chunks to %s/%s (%.3f sec)", pthread_self(), caddr, buf, request, (end_req - start_req) / 1000000.0); err_reply(cl, h500, lstn->err500); clean_all(); return; } } else if(cont > L0 && is_rpc != 1) { /* had Content-length, so do raw reads/writes for the length */ if(copy_bin(cl, be, cont, NULL, cur_backend->be_type)) { str_be(buf, MAXBUF - 1, cur_backend); end_req = cur_time(); addr2str(caddr, MAXBUF - 1, &from_host, 1); logmsg(LOG_NOTICE, "(%lx) e500 for %s error copy client cont to %s/%s: %s (%.3f sec)", pthread_self(), caddr, buf, request, strerror(errno), (end_req - start_req) / 1000000.0); err_reply(cl, h500, lstn->err500); clean_all(); return; } } else if(cont > 0L && is_readable(cl, lstn->to)) { char one; BIO *cl_unbuf; /* * special mode for RPC_IN_DATA - content until EOF * force HTTP/1.0 - client closes connection when done. */ cl_11 = be_11 = 0; /* * first read whatever is already in the input buffer */ while(BIO_pending(cl)) { if(BIO_read(cl, &one, 1) != 1) { logmsg(LOG_NOTICE, "(%lx) error read request pending: %s", pthread_self(), strerror(errno)); clean_all(); pthread_exit(NULL); } if (++res_bytes > cont) { logmsg(LOG_NOTICE, "(%lx) error read request pending: max. RPC length exceeded", pthread_self()); clean_all(); pthread_exit(NULL); } if(BIO_write(be, &one, 1) != 1) { if(errno) logmsg(LOG_NOTICE, "(%lx) error write request pending: %s", pthread_self(), strerror(errno)); clean_all(); pthread_exit(NULL); } } BIO_flush(be); /* * find the socket BIO in the chain */ if ((cl_unbuf = BIO_find_type(cl, lstn->ctx? BIO_TYPE_SSL : BIO_TYPE_SOCKET)) == NULL) { logmsg(LOG_WARNING, "(%lx) error get unbuffered: %s", pthread_self(), strerror(errno)); clean_all(); pthread_exit(NULL); } /* * copy till EOF */ while((res = BIO_read(cl_unbuf, buf, MAXBUF)) > 0) { if((res_bytes += res) > cont) { logmsg(LOG_NOTICE, "(%lx) error copy request body: max. RPC length exceeded", pthread_self()); clean_all(); pthread_exit(NULL); } if(BIO_write(be, buf, res) != res) { if(errno) logmsg(LOG_NOTICE, "(%lx) error copy request body: %s", pthread_self(), strerror(errno)); clean_all(); pthread_exit(NULL); } else { BIO_flush(be); } } } /* flush to the back-end */ if(cur_backend->be_type == 0 && BIO_flush(be) != 1) { str_be(buf, MAXBUF - 1, cur_backend); end_req = cur_time(); addr2str(caddr, MAXBUF - 1, &from_host, 1); logmsg(LOG_NOTICE, "(%lx) e500 for %s error flush to %s/%s: %s (%.3f sec)", pthread_self(), caddr, buf, request, strerror(errno), (end_req - start_req) / 1000000.0); err_reply(cl, h500, lstn->err500); clean_all(); return; } /* * check on no_https_11: * - if 0 ignore * - if 1 and SSL force HTTP/1.0 * - if 2 and SSL and MSIE force HTTP/1.0 */ switch(lstn->noHTTPS11) { case 1: force_10 = (ssl != NULL); break; case 2: force_10 = (ssl != NULL && strstr(u_agent, "MSIE") != NULL); break; default: force_10 = 0; break; } /* if we have a redirector */ if(cur_backend->be_type) { memset(buf, 0, sizeof(buf)); if(!cur_backend->redir_req) snprintf(buf, sizeof(buf) - 1, "%s%s", cur_backend->url, url); else strncpy(buf, cur_backend->url, sizeof(buf) - 1); redirect_reply(cl, buf, cur_backend->be_type); addr2str(caddr, MAXBUF - 1, &from_host, 1); switch(lstn->log_level) { case 0: break; case 1: case 2: logmsg(LOG_INFO, "%s %s - REDIRECT %s", caddr, request, buf); break; case 3: if(v_host[0]) logmsg(LOG_INFO, "%s %s - %s [%s] \"%s\" %d 0 \"%s\" \"%s\"", v_host, caddr, u_name[0]? u_name: "-", req_time, request, cur_backend->be_type, referer, u_agent); else logmsg(LOG_INFO, "%s - %s [%s] \"%s\" %d 0 \"%s\" \"%s\"", caddr, u_name[0]? u_name: "-", req_time, request, cur_backend->be_type, referer, u_agent); break; case 4: case 5: logmsg(LOG_INFO, "%s - %s [%s] \"%s\" %d 0 \"%s\" \"%s\"", caddr, u_name[0]? u_name: "-", req_time, request, cur_backend->be_type, referer, u_agent); break; } if(!cl_11 || conn_closed || force_10) break; continue; } else if(is_rpc == 1) { /* log RPC_IN_DATA */ end_req = cur_time(); memset(s_res_bytes, 0, LOG_BYTES_SIZE); /* actual request length */ log_bytes(s_res_bytes, res_bytes); addr2str(caddr, MAXBUF - 1, &from_host, 1); str_be(buf, MAXBUF - 1, cur_backend); switch(lstn->log_level) { case 0: break; case 1: logmsg(LOG_INFO, "%s %s - -", caddr, request); break; case 2: if(v_host[0]) logmsg(LOG_INFO, "%s %s - - (%s/%s -> %s) %.3f sec", caddr, request, v_host, svc->name[0]? svc->name: "-", buf, (end_req - start_req) / 1000000.0); else logmsg(LOG_INFO, "%s %s - - (%s -> %s) %.3f sec", caddr, request, svc->name[0]? svc->name: "-", buf, (end_req - start_req) / 1000000.0); break; case 3: logmsg(LOG_INFO, "%s %s - %s [%s] \"%s\" 000 %s \"%s\" \"%s\"", v_host[0]? v_host: "-", caddr, u_name[0]? u_name: "-", req_time, request, s_res_bytes, referer, u_agent); break; case 4: logmsg(LOG_INFO, "%s - %s [%s] \"%s\" 000 %s \"%s\" \"%s\"", caddr, u_name[0]? u_name: "-", req_time, request, s_res_bytes, referer, u_agent); break; case 5: logmsg(LOG_INFO, "%s %s - %s [%s] \"%s\" 000 %s \"%s\" \"%s\" (%s -> %s) %.3f sec", v_host[0]? v_host: "-", caddr, u_name[0]? u_name: "-", req_time, request, s_res_bytes, referer, u_agent, svc->name[0]? svc->name: "-", buf, (end_req - start_req) / 1000000.0); break; } /* no response expected - bail out */ break; } /* get the response */ for(skip = 1; skip;) { if((headers = get_headers(be, cl, lstn)) == NULL) { str_be(buf, MAXBUF - 1, cur_backend); end_req = cur_time(); addr2str(caddr, MAXBUF - 1, &from_host, 1); logmsg(LOG_NOTICE, "(%lx) e500 for %s response error read from %s/%s: %s (%.3f secs)", pthread_self(), caddr, buf, request, strerror(errno), (end_req - start_req) / 1000000.0); err_reply(cl, h500, lstn->err500); clean_all(); return; } strncpy(response, headers[0], MAXBUF); be_11 = (response[7] == '1'); /* responses with code 100 are never passed back to the client */ skip = !regexec(&RESP_SKIP, response, 0, NULL, 0); /* some response codes (1xx, 204, 304) have no content */ if(!no_cont && !regexec(&RESP_IGN, response, 0, NULL, 0)) no_cont = 1; for(chunked = 0, cont = -1L, n = 1; n < MAXHEADERS && headers[n]; n++) { switch(check_header(headers[n], buf)) { case HEADER_CONNECTION: if(!strcasecmp("close", buf)) conn_closed = 1; break; case HEADER_TRANSFER_ENCODING: if(!strcasecmp("chunked", buf)) { chunked = 1; no_cont = 0; } break; case HEADER_CONTENT_LENGTH: cont = ATOL(buf); /* treat RPC_OUT_DATA like reply without content-length */ if(is_rpc == 0) { if(cont >= 0x20000L && cont <= 0x80000000L) cont = -1L; else is_rpc = -1; } break; case HEADER_LOCATION: if(v_host[0] && need_rewrite(lstn->rewr_loc, buf, loc_path, v_host, lstn, cur_backend)) { snprintf(buf, MAXBUF, "Location: %s://%s/%s", (ssl == NULL? "http": "https"), v_host, loc_path); free(headers[n]); if((headers[n] = strdup(buf)) == NULL) { logmsg(LOG_WARNING, "(%lx) rewrite Location - out of memory: %s", pthread_self(), strerror(errno)); free_headers(headers); clean_all(); return; } } break; case HEADER_CONTLOCATION: if(v_host[0] && need_rewrite(lstn->rewr_loc, buf, loc_path, v_host, lstn, cur_backend)) { snprintf(buf, MAXBUF, "Content-location: %s://%s/%s", (ssl == NULL? "http": "https"), v_host, loc_path); free(headers[n]); if((headers[n] = strdup(buf)) == NULL) { logmsg(LOG_WARNING, "(%lx) rewrite Content-location - out of memory: %s", pthread_self(), strerror(errno)); free_headers(headers); clean_all(); return; } } break; } } /* possibly record session information (only for cookies/header) */ upd_session(svc, &headers[1], cur_backend); /* send the response */ if(!skip) for(n = 0; n < MAXHEADERS && headers[n]; n++) { if(BIO_printf(cl, "%s\r\n", headers[n]) <= 0) { if(errno) { addr2str(caddr, MAXBUF - 1, &from_host, 1); logmsg(LOG_NOTICE, "(%lx) error write to %s: %s", pthread_self(), caddr, strerror(errno)); } free_headers(headers); clean_all(); return; } } free_headers(headers); /* final CRLF */ if(!skip) BIO_puts(cl, "\r\n"); if(BIO_flush(cl) != 1) { if(errno) { addr2str(caddr, MAXBUF - 1, &from_host, 1); logmsg(LOG_NOTICE, "(%lx) error flush headers to %s: %s", pthread_self(), caddr, strerror(errno)); } clean_all(); return; } if(!no_cont) { /* ignore this if request was HEAD or similar */ if(be_11 && chunked) { /* had Transfer-encoding: chunked so read/write all the chunks (HTTP/1.1 only) */ if(copy_chunks(be, cl, &res_bytes, skip, L0)) { /* copy_chunks() has its own error messages */ clean_all(); return; } } else if(cont >= L0) { /* may have had Content-length, so do raw reads/writes for the length */ if(copy_bin(be, cl, cont, &res_bytes, skip)) { if(errno) logmsg(LOG_NOTICE, "(%lx) error copy server cont: %s", pthread_self(), strerror(errno)); clean_all(); return; } } else if(!skip) { if(is_readable(be, cur_backend->to)) { char one; BIO *be_unbuf; /* * old-style response - content until EOF * also implies the client may not use HTTP/1.1 */ cl_11 = be_11 = 0; /* * first read whatever is already in the input buffer */ while(BIO_pending(be)) { if(BIO_read(be, &one, 1) != 1) { logmsg(LOG_NOTICE, "(%lx) error read response pending: %s", pthread_self(), strerror(errno)); clean_all(); return; } if(BIO_write(cl, &one, 1) != 1) { if(errno) logmsg(LOG_NOTICE, "(%lx) error write response pending: %s", pthread_self(), strerror(errno)); clean_all(); return; } res_bytes++; } BIO_flush(cl); /* * find the socket BIO in the chain */ if((be_unbuf = BIO_find_type(be, cur_backend->ctx? BIO_TYPE_SSL : BIO_TYPE_SOCKET)) == NULL) { logmsg(LOG_WARNING, "(%lx) error get unbuffered: %s", pthread_self(), strerror(errno)); clean_all(); return; } /* * copy till EOF */ while((res = BIO_read(be_unbuf, buf, MAXBUF)) > 0) { if(BIO_write(cl, buf, res) != res) { if(errno) logmsg(LOG_NOTICE, "(%lx) error copy response body: %s", pthread_self(), strerror(errno)); clean_all(); return; } else { res_bytes += res; BIO_flush(cl); } } } } if(BIO_flush(cl) != 1) { /* client closes RPC_OUT_DATA connection - no error */ if(is_rpc == 0 && res_bytes > 0L) break; if(errno) { addr2str(caddr, MAXBUF - 1, &from_host, 1); logmsg(LOG_NOTICE, "(%lx) error final flush to %s: %s", pthread_self(), caddr, strerror(errno)); } clean_all(); return; } } } end_req = cur_time(); /* log what happened */ memset(s_res_bytes, 0, LOG_BYTES_SIZE); log_bytes(s_res_bytes, res_bytes); addr2str(caddr, MAXBUF - 1, &from_host, 1); if(anonymise) { char *last; if((last = strrchr(caddr, '.')) != NULL || (last = strrchr(caddr, ':')) != NULL) strcpy(++last, "0"); } str_be(buf, MAXBUF - 1, cur_backend); switch(lstn->log_level) { case 0: break; case 1: logmsg(LOG_INFO, "%s %s - %s", caddr, request, response); break; case 2: if(v_host[0]) logmsg(LOG_INFO, "%s %s - %s (%s/%s -> %s) %.3f sec", caddr, request, response, v_host, svc->name[0]? svc->name: "-", buf, (end_req - start_req) / 1000000.0); else logmsg(LOG_INFO, "%s %s - %s (%s -> %s) %.3f sec", caddr, request, response, svc->name[0]? svc->name: "-", buf, (end_req - start_req) / 1000000.0); break; case 3: logmsg(LOG_INFO, "%s %s - %s [%s] \"%s\" %c%c%c %s \"%s\" \"%s\"", v_host[0]? v_host: "-", caddr, u_name[0]? u_name: "-", req_time, request, response[9], response[10], response[11], s_res_bytes, referer, u_agent); break; case 4: logmsg(LOG_INFO, "%s - %s [%s] \"%s\" %c%c%c %s \"%s\" \"%s\"", caddr, u_name[0]? u_name: "-", req_time, request, response[9], response[10], response[11], s_res_bytes, referer, u_agent); break; case 5: logmsg(LOG_INFO, "%s %s - %s [%s] \"%s\" %c%c%c %s \"%s\" \"%s\" (%s -> %s) %.3f sec", v_host[0]? v_host: "-", caddr, u_name[0]? u_name: "-", req_time, request, response[9], response[10], response[11], s_res_bytes, referer, u_agent, svc->name[0]? svc->name: "-", buf, (end_req - start_req) / 1000000.0); break; } if(!be_11) { BIO_reset(be); BIO_free_all(be); be = NULL; } /* * Stop processing if: * - client is not HTTP/1.1 * or * - we had a "Connection: closed" header * or * - this is an SSL connection and we had a NoHTTPS11 directive */ if(!cl_11 || conn_closed || force_10) break; } /* * This may help with some versions of IE with a broken channel shutdown */ if(ssl != NULL) SSL_set_shutdown(ssl, SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN); clean_all(); return; } void * thr_http(void *dummy) { thr_arg *arg; for(;;) { while((arg = get_thr_arg()) == NULL) logmsg(LOG_NOTICE, "NULL get_thr_arg"); do_http(arg); } } Pound-2.8/z2_2_6_1.py0000755000175000017500000010233713275266545013313 0ustar rosegroseg############################################################################## # # Copyright (c) 2001 Zope Corporation and Contributors. All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE # ############################################################################## """Zope 2 ZServer start-up file Usage: %(program)s [options] [environment settings] Options: -h Output this text. -z path The location of the Zope installation. The default is the location of this script, %(here)s. -Z 0 or 1 UNIX only! This option is ignored on Windows. This option controls whether a management process will be created that restarts Zope after a shutdown or crash. If the argument to -Z is non-null (e.g. "-Z1" or "-Zyes"), a management process will be used. If the argument to -Z is "-", or "0", (e.g. "-Z-" or "-Z0"), a management process will not be used. On UNIX, the default behavior is to create a separate management process (e.g. -Z1) if the -Z option is not specified. (Note: the -Z option in Zopes before Zope 2.6 used to be used to specify a pidfile name for the management process. This pidfile no longer exists). -t n The number of threads to use, if ZODB3 is used. The default is %(NUMBER_OF_THREADS)s. -i n Set the interpreter check interval. This integer value determines how often the interpreter checks for periodic things such as thread switches and signal handlers. The Zope default is 500, but you may want to experiment with other values that may increase performance in your particular environment. -D Run in Zope debug mode. This causes the Zope process not to detach from the controlling terminal, and is equivalent to supplying the environment variable setting Z_DEBUG_MODE=1 -a ipaddress The IP address to listen on. If this is an empty string (e.g. -a ''), then all addresses on the machine are used. The default is %(IP_ADDRESS)s. -d ipaddress IP address of your DNS server. If this is an empty string (e.g. -d ''), then IP addresses will not be logged. If you have DNS service on your local machine then you can set this to 127.0.0.1. The default is: %(DNS_IP)s. -u username or uid number The username to run ZServer as. You may want to run ZServer as a dedicated user. This only works under Unix, and if ZServer is started as root, and is required in that case. -P [ipaddress:]number Set the web, ftp and monitor port numbers simultaneously as offsets from the number. The web port number will be number+80. The FTP port number will be number+21. The monitor port number will be number+99. The number can be preeceeded by an ip address follwed by a colon to specify an address to listen on. This allows different servers to listen on different addresses. Multiple -P options can be provided to run multiple sets of servers. -w port The Web server (HTTP) port. This defaults to %(HTTP_PORT)s. The standard port for HTTP services is 80. If this is a dash (e.g. -w -), then HTTP is disabled. The number can be preeceeded by an ip address follwed by a colon to specify an address to listen on. This allows different servers to listen on different addresses. Multiple -w options can be provided to run multiple servers. -y port The Web secure server (HTTPS) port. This defaults to %(HTTPS_PORT)s. The standard port for HTTPS services is 443. If this is a dash (e.g. -y -), then HTTPS is disabled. The number can be preeceeded by an ip address follwed by a colon to specify an address to listen on. This allows different servers to listen on different addresses. Multiple -w options can be provided to run multiple servers. -W port The "WebDAV source" port. If this is a dash (e.g. -w -), then "WebDAV source" is disabled. The default is disabled. Note that this feature is a workaround for the lack of "source-link" support in standard WebDAV clients. The port can be preeceeded by an ip address follwed by a colon to specify an address to listen on. This allows different servers to listen on different addresses. Multiple -W options can be provided to run multiple servers. -C --force-http-connection-close If present, this option causes Zope to close all HTTP connections, regardless of the 'Connection:' header (or lack of one) sent by the client. -f port The FTP port. If this is a dash (e.g. -f -), then FTP is disabled. The standard port for FTP services is 21. The default is %(FTP_PORT)s. The port can be preeceeded by an ip address follwed by a colon to specify an address to listen on. This allows different servers to listen on different addresses. Multiple -f options can be provided to run multiple servers. -p path Path to the PCGI resource file. The default value is %(PCGI_FILE)s, relative to the Zope location. If this is a dash (-p -) or the file does not exist, then PCGI is disabled. -F path_or_port Either a port number (for inet sockets) or a path name (for unix domain sockets) for the FastCGI Server. If the flag and value are not specified then the FastCGI Server is disabled. -m port The secure monitor server port. If this is a dash (-m -), then the monitor server is disabled. The monitor server allows interactive Python style access to a running ZServer. To access the server see medusa/monitor_client.py or medusa/monitor_client_win32.py. The monitor server password is the same as the Zope emergency user password set in the 'access' file. The default is to not start up a monitor server. The port can be preeceeded by an ip address follwed by a colon to specify an address to listen on. This allows different servers to listen on different addresses. Multiple -m options can be provided to run multiple servers. --icp port The ICP port. ICP can be used to distribute load between back-end zope servers, if you are using an ICP-aware front-end proxy such as Squid. The port can be preeceeded by an ip address follwed by a colon to specify an address to listen on. This allows different servers to listen on different addresses. Multiple --icp options can be provided to run multiple servers. -l path Path to the ZServer log file. If this is a relative path then the log file will be written to the 'var' directory. The default is %(LOG_FILE)s. -r Run ZServer is read-only mode. ZServer won't write anything to disk. No log files, no pid files, nothing. This means that you can't do a lot of stuff like use PCGI, and zdaemon. ZServer will log hits to STDOUT and zLOG will log to STDERR. -L Enable locale (internationalization) support. The value passed for this option should be the name of the locale to be used (see your operating system documentation for locale information specific to your system). If an empty string is passed for this option (-L ''), Zope will set the locale to the user's default setting (typically specified in the $LANG environment variable). If your Python installation does not support the locale module, the requested locale is not supported by your system or an empty string was passed but no default locale can be found, an error will be raised and Zope will not start. -X Disable servers. This might be used to effectively disable all default server settings or previous server settings in the option list before providing new settings. For example to provide just a web server: %(program)s -X -w80 -M file Save detailed logging information to the given file. This log includes separate entries for: - The start of a request, - The start of processing the request in an application thread, - The start of response output, and - The end of the request. Environment settings are of the form: NAME=VALUE. Note: you *must* use Python 2.1 or later! """ # This is required path hackery for the win32 binary distribution # that ensures that the bundled python libraries are used. In a # win32 binary distribution, the installer will have replaced the # marker string with the actual software home. If that has not # happened, then the path munging code is skipped. swhome=r'INSERT_SOFTWARE_HOME' if swhome != 'INSERT_SOFTWARE_HOME': import sys sys.path.insert(0, '%s/lib/python' % swhome) sys.path.insert(1, '%s/bin/lib' % swhome) sys.path.insert(2, '%s/bin/lib/plat-win' % swhome) sys.path.insert(3, '%s/bin/lib/win32' % swhome) sys.path.insert(4, '%s/bin/lib/win32/lib' % swhome) sys.path.insert(5, '%s' % swhome) import os, sys, getopt, codecs, string import socket from types import StringType, IntType # workaround to allow unicode encoding conversions in DTML dummy = codecs.lookup('iso-8859-1') sys.setcheckinterval(500) program=sys.argv[0] here=os.path.join(os.getcwd(), os.path.split(program)[0]) ######################################################################## # Configuration section ## General configuration options ## # This is the IP address of the network interface you want your servers to # be visible from. This can be changed to '' to listen on all interfaces. IP_ADDRESS='' # IP address of your DNS server. Set to '' if you do not want to resolve # IP addresses. If you have DNS service on your local machine then you can # set this to '127.0.0.1' DNS_IP='' # User id to run ZServer as. Note that this only works under Unix, and if # ZServer is started by root. This no longer defaults to 'nobody' since # that can lead to a Zope file compromise. UID=None # Log file location. If this is a relative path, then it is joined the # the 'var' directory. LOG_FILE='Z2.log' ## HTTP configuration ## # HTTP enivornment settings. HTTP_ENV={} # Port for HTTP Server. The standard port for HTTP services is 80. HTTP_PORT=8080 ## HTTPS configuration ## # HTTPS enivornment settings. HTTPS_ENV={} # Port for HTTP Server. The standard port for HTTP services is 80. HTTPS_PORT=8443 # Should we close all HTTP connections, ignoring the (usually absent) # 'Connection:' header? FORCE_HTTP_CONNECTION_CLOSE=0 # Port for the special "WebDAV source view" HTTP handler. There is no # standard port for this handler, which is disabled by default. WEBDAV_SOURCE_PORT=[] ## FTP configuration # Port for the FTP Server. The standard port for FTP services is 21. FTP_PORT=8021 ## PCGI configuration # You can configure the PCGI server manually, or have it read its # configuration information from a PCGI info file. PCGI_FILE='Zope.cgi' ## Monitor configuration MONITOR_PORT=0 ## ICP configuration ICP_PORT=0 # Module to be published, which must be Main or Zope MODULE='Zope' # The size of the thread pool, if ZODB3 is used. NUMBER_OF_THREADS=4 # Localization support LOCALE_ID=None # Socket path or port for the FastCGI Server FCGI_PORT=None # Detailed log file DETAILED_LOG_FILE='' # Use a daemon process USE_DAEMON = 1 # ######################################################################## ######################################################################## # Handle command-line arguments: def server_info(old, v, offset=0): # interpret v as a port or address/port and get new value if v == '-': v='' l=v.find(':') if l >= 0: a=v[:l] v=v[l+1:] else: a=IP_ADDRESS if not v: return v try: v=int(v) if v < 0: raise 'Invalid port', v v=v+offset except: raise 'Invalid port', v if isinstance(old, IntType): old=[(a,v)] else: old.append((a,v)) return old try: python_version = sys.version.split()[0] if python_version < '2.1': raise 'Invalid python version', python_version if python_version[:3] == '2.1': if python_version[4:5] < '3': import warnings err = ('You are running Python version %s. This Python version ' 'has known bugs that may cause Zope to run improperly. ' 'Consider upgrading to a Python in the 2.1 series ' 'with at least version number 2.1.3. (Note that Zope does ' 'not yet run under any Python 2.2 version).' % python_version) warnings.warn(err) if python_version[:3] == '2.2': import warnings err = ('You are running Python version %s. This Python version ' 'has not yet been tested with Zope and you may experience ' 'operational problems as a result. Consider using ' 'Python 2.1.3 instead.' % python_version) warnings.warn(err) opts, args = getopt.getopt(sys.argv[1:], 'hz:Z:t:i:a:d:u:w:y:W:f:p:m:Sl:2DP:rF:L:XM:C', ['icp=', 'force-http-connection-close' ]) DEBUG=0 READ_ONLY=0 if sys.platform == 'win32': USE_DAEMON = 0 # Get environment variables for a in args: if a.find('='): a=a.split('=') o=a[0] v='='.join(a[1:]) if o: os.environ[o]=v HTTP_ENV[o]=v HTTPS_ENV[o]=v else: raise 'Invalid argument', a for o, v in opts: if o=='-z': here=v elif o=='-Z': if v in ('-', '0', ''): USE_DAEMON=0 elif sys.platform != 'win32': USE_DAEMON = 1 elif o=='-r': READ_ONLY=1 elif o=='-t': try: v=int(v) except: raise 'Invalid number of threads', v NUMBER_OF_THREADS=v elif o=='-i': try: v=int(v) except: raise 'Invalid value for -i option', v sys.setcheckinterval(v) elif o=='-a': IP_ADDRESS=v elif o=='-d': if v=='-': v='' DNS_IP=v elif o=='-u': UID=v elif o=='-D': os.environ['Z_DEBUG_MODE']='1' DEBUG=1 elif o=='-S': sys.ZMANAGED=1 elif o=='-X': MONITOR_PORT=HTTP_PORT=HTTPS_PORT=FTP_PORT=FCGI_PORT=ICP_PORT=0 WEBDAV_SOURCE_PORT=0 PCGI_FILE='' elif o=='-m': MONITOR_PORT=server_info(MONITOR_PORT, v) elif o=='-w': HTTP_PORT=server_info(HTTP_PORT, v) elif o=='-y': HTTPS_PORT=server_info(HTTPS_PORT, v) elif o=='-C' or o=='--force-http-connection-close': FORCE_HTTP_CONNECTION_CLOSE=1 elif o=='-W': WEBDAV_SOURCE_PORT=server_info(WEBDAV_SOURCE_PORT, v) elif o=='-f': FTP_PORT=server_info(FTP_PORT, v) elif o=='-P': HTTP_PORT=server_info(HTTP_PORT, v, 80) HTTPS_PORT=server_info(HTTPS_PORT, v, 443) FTP_PORT=server_info(FTP_PORT, v, 21) elif o=='--icp': ICP_PORT=server_info(ICP_PORT, v) elif o=='-p': if v=='-': v='' PCGI_FILE=v elif o=='-h': print __doc__ % vars() sys.exit(0) elif o=='-2': MODULE='Main' elif o=='-l': LOG_FILE=v elif o=='-L': if v: LOCALE_ID=v else: LOCALE_ID='' elif o=='-F': if v=='-': v='' FCGI_PORT=v elif o=='-M': DETAILED_LOG_FILE=v except SystemExit: sys.exit(0) except: print __doc__ % vars() print print 'Error:' print "%s: %s" % (sys.exc_type, sys.exc_value) sys.exit(1) # ######################################################################## ######################################################################## # OK, let's get going! # Jigger path: sys.path=[os.path.join(here,'lib','python'),here ]+filter(None, sys.path) # Try to set the locale if specified on the command # line. If the locale module is not available or the # requested locale is not supported by the local # machine, raise an error so that the user is made # aware of the problem. def set_locale(val): try: import locale except: raise SystemExit, ( 'The locale module could not be imported.\n' 'To use localization options, you must ensure\n' 'that the locale module is compiled into your\n' 'Python installation.' ) try: locale.setlocale(locale.LC_ALL, val) except: raise SystemExit, ( 'The specified locale is not supported by your system.\n' 'See your operating system documentation for more\n' 'information on locale support.' ) if LOCALE_ID is not None: set_locale(LOCALE_ID) import zdaemon # from this point forward we can use the zope logger # importing ZDaemon before importing ZServer causes ZServer logging # not to work. # Import ZServer before we open the database or get at interesting # application code so that ZServer's asyncore gets to be the # official one. Also gets SOFTWARE_HOME, INSTANCE_HOME, and CLIENT_HOME import ZServer # install signal handlers if on posix if os.name == 'posix': from Signals import Signals Signals.registerZopeSignals() # Location of the ZServer pid file. When Zope starts up it will write # its PID to this file. If Zope is run under zdaemon control, zdaemon # will write to this pidfile instead of Zope. PID_FILE=os.path.join(CLIENT_HOME, 'Z2.pid') if USE_DAEMON and not READ_ONLY: import App.FindHomes sys.ZMANAGED=1 # zdaemon.run creates a process which "manages" the actual Zope # process (restarts it if it dies). The management process passes along # signals that it receives to its child. zdaemon.run(sys.argv, os.path.join(CLIENT_HOME, PID_FILE)) os.chdir(CLIENT_HOME) def _warn_nobody(): zLOG.LOG("z2", zLOG.INFO, ("Running Zope as 'nobody' can compromise " "your Zope files; consider using a " "dedicated user account for Zope") ) try: # Import logging support import zLOG import ZLogger if READ_ONLY: if hasattr(zLOG, '_set_stupid_dest'): zLOG._set_stupid_dest(sys.stderr) else: zLOG._stupid_dest = sys.stderr else: zLOG.log_write = ZLogger.ZLogger.log_write if DETAILED_LOG_FILE: from ZServer import DebugLogger logfile=os.path.join(CLIENT_HOME, DETAILED_LOG_FILE) zLOG.LOG('z2', zLOG.BLATHER, 'Using detailed request log file %s' % logfile) DL=DebugLogger.DebugLogger(logfile) DebugLogger.log=DL.log DebugLogger.reopen=DL.reopen sys.__detailedlog=DL # Import Zope (or Main) if MODULE == 'Zope': import Zope Zope.startup() else: exec "import "+MODULE in {} # Location of the ZServer log file. This file logs all ZServer activity. # You may wish to create different logs for different servers. See # medusa/logger.py for more information. if not os.path.isabs(LOG_FILE): LOG_PATH=os.path.join(CLIENT_HOME, LOG_FILE) else: LOG_PATH=LOG_FILE # import ZServer stuff # First, we need to increase the number of threads if MODULE=='Zope': from ZServer import setNumberOfThreads setNumberOfThreads(NUMBER_OF_THREADS) from ZServer import resolver, logger, asyncore from ZServer import zhttp_server, zhttp_handler from ZServer.WebDAVSrcHandler import WebDAVSrcHandler from ZServer import PCGIServer,FTPServer,FCGIServer from ZServer import secure_monitor_server ## ZServer startup ## # Resolver and Logger, used by other servers if DNS_IP: rs = resolver.caching_resolver(DNS_IP) else: rs=None if READ_ONLY: lg = logger.file_logger('-') # log to stdout zLOG.LOG('z2', zLOG.BLATHER, 'Logging access log to stdout') elif os.environ.has_key('ZSYSLOG_ACCESS'): if os.environ.has_key("ZSYSLOG_ACCESS_FACILITY"): lg = logger.syslog_logger( os.environ['ZSYSLOG_ACCESS'], facility=os.environ['ZSYSLOG_ACCESS_FACILITY']) else: lg = logger.syslog_logger(os.environ['ZSYSLOG_ACCESS']) zLOG.LOG('z2', zLOG.BLATHER, 'Using local syslog access log') elif os.environ.has_key('ZSYSLOG_ACCESS_SERVER'): (addr, port) = os.environ['ZSYSLOG_ACCESS_SERVER'].split( ':') lg = logger.syslog_logger((addr, int(port))) zLOG.LOG('z2', zLOG.BLATHER, 'Using remote syslog access log') else: lg = logger.file_logger(LOG_PATH) zLOG.LOG('z2', zLOG.BLATHER, 'Using access log file %s' % LOG_PATH) sys.__lg = lg port_err=('\n\nZope wants to use %(socktype)s port %(port)s for its ' '%(protocol)s service, but it is already in use by another ' 'application on this machine. Either shut the application down ' 'which is using this port, or start Zope with a different ' '%(protocol)s port via the "%(switch)s" command-line switch.\n') # HTTP Server if HTTP_PORT: if isinstance(HTTP_PORT, IntType): HTTP_PORT=((IP_ADDRESS, HTTP_PORT),) for address, port in HTTP_PORT: try: hs = zhttp_server( ip=address, port=port, resolver=rs, logger_object=lg) except socket.error, why: if why[0] == 98: # address in use raise port_err % {'port':port, 'socktype':'TCP', 'protocol':'HTTP', 'switch':'-w'} raise # Handler for a published module. zhttp_handler takes 3 arguments: # The name of the module to publish, and optionally the URI base # which is basically the SCRIPT_NAME, and optionally a dictionary # with CGI environment variables which override default # settings. The URI base setting is useful when you want to # publish more than one module with the same HTTP server. The CGI # environment setting is useful when you want to proxy requests # from another web server to ZServer, and would like the CGI # environment to reflect the CGI environment of the other web # server. zh = zhttp_handler(MODULE, '', HTTP_ENV) if FORCE_HTTP_CONNECTION_CLOSE: zh._force_connection_close = 1 hs.install_handler(zh) # HTTPS Server if HTTPS_PORT: if isinstance(HTTPS_PORT, IntType): HTTPS_PORT=((IP_ADDRESS, HTTPS_PORT),) for address, port in HTTPS_PORT: try: hs = zhttp_server( ip=address, port=port, resolver=rs, logger_object=lg) except socket.error, why: if why[0] == 98: # address in use raise port_err % {'port':port, 'socktype':'TCP', 'protocol':'HTTPS', 'switch':'-y'} raise # Handler for a published module. zhttp_handler takes 3 arguments: # The name of the module to publish, and optionally the URI base # which is basically the SCRIPT_NAME, and optionally a dictionary # with CGI environment variables which override default # settings. The URI base setting is useful when you want to # publish more than one module with the same HTTP server. The CGI # environment setting is useful when you want to proxy requests # from another web server to ZServer, and would like the CGI # environment to reflect the CGI environment of the other web # server. try: del HTTPS_ENV['HTTP'] except KeyError: pass HTTPS_ENV['HTTPS']='ON' zh = zhttp_handler(MODULE, '', HTTPS_ENV) if FORCE_HTTP_CONNECTION_CLOSE: zh._force_connection_close = 1 hs.install_handler(zh) # WebDAV source Server (runs HTTP, but munges request to return # 'manage_FTPget'). if WEBDAV_SOURCE_PORT: if isinstance(WEBDAV_SOURCE_PORT, IntType): WEBDAV_SOURCE_PORT=((IP_ADDRESS, WEBDAV_SOURCE_PORT),) for address, port in WEBDAV_SOURCE_PORT: try: hs = zhttp_server( ip=address, port=port, resolver=rs, logger_object=lg) except socket.error, why: if why[0] == 98: # address in use raise port_err % {'port':port, 'socktype':'TCP', 'protocol':'WebDAV source', 'switch':'-W'} raise # Handler for a published module. zhttp_handler takes 3 arguments: # The name of the module to publish, and optionally the URI base # which is basically the SCRIPT_NAME, and optionally a dictionary # with CGI environment variables which override default # settings. The URI base setting is useful when you want to # publish more than one module with the same HTTP server. The CGI # environment setting is useful when you want to proxy requests # from another web server to ZServer, and would like the CGI # environment to reflect the CGI environment of the other web # server. zh = WebDAVSrcHandler(MODULE, '', HTTP_ENV) hs.install_handler(zh) # enable document retrieval of the document source on the # standard HTTP port clients = os.environ.get('WEBDAV_SOURCE_PORT_CLIENTS') if clients: import re sys.WEBDAV_SOURCE_PORT_CLIENTS = re.compile(clients).search else: sys.WEBDAV_SOURCE_PORT_CLIENTS = None # FTP Server if FTP_PORT: if isinstance(FTP_PORT, IntType): FTP_PORT=((IP_ADDRESS, FTP_PORT),) for address, port in FTP_PORT: try: FTPServer( module=MODULE, ip=address, port=port, resolver=rs, logger_object=lg) except socket.error, why: if why[0] == 98: # address in use raise port_err % {'port':port, 'socktype':'TCP', 'protocol':'FTP', 'switch':'-f'} raise # PCGI Server if PCGI_FILE and not READ_ONLY: PCGI_FILE=os.path.join(here, PCGI_FILE) if os.path.exists(PCGI_FILE): zpcgi = PCGIServer( module=MODULE, ip=IP_ADDRESS, pcgi_file=PCGI_FILE, resolver=rs, logger_object=lg) # FastCGI Server if FCGI_PORT and not READ_ONLY: fcgiPort = None fcgiPath = None try: fcgiPort = int(FCGI_PORT) except ValueError: fcgiPath = FCGI_PORT try: zfcgi = FCGIServer(module=MODULE, ip=IP_ADDRESS, port=fcgiPort, socket_file=fcgiPath, resolver=rs, logger_object=lg) except socket.error, why: if why[0] == 98: # address in use raise port_err % {'port':fcgiPort, 'socktype':'TCP', 'protocol':'FastCGI', 'switch':'-F'} raise # Monitor Server if MONITOR_PORT: from AccessControl.User import emergency_user if not hasattr(emergency_user, '__null_user__'): pw = emergency_user._getPassword() else: pw = None zLOG.LOG("z2", zLOG.WARNING, 'Monitor server not started' ' because no emergency user exists.') if pw: if isinstance(MONITOR_PORT, IntType): MONITOR_PORT=((IP_ADDRESS, MONITOR_PORT),) for address, port in MONITOR_PORT: try: monitor=secure_monitor_server( password=pw, hostname=address, port=port) except socket.error, why: if why[0] == 98: # address in use raise port_err % {'port':port, 'socktype':'TCP', 'protocol':'monitor server', 'switch':'-m'} raise if ICP_PORT: if isinstance(ICP_PORT, IntType): ICP_PORT=((IP_ADDRESS, ICP_PORT),) from ZServer.ICPServer import ICPServer for address, port in ICP_PORT: try: ICPServer(address,port) except socket.error, why: if why[0] == 98: # address in use raise port_err % {'port':port, 'socktype':'UDP', 'protocol':'ICP', 'switch':'--icp'} raise if not USE_DAEMON and not READ_ONLY: if os.path.exists(PID_FILE): os.unlink(PID_FILE) pf = open(PID_FILE, 'w') pid='%s\n' % os.getpid() pf.write(pid) pf.close() # Warn if we were started as nobody. try: import pwd if os.getuid(): if pwd.getpwuid(os.getuid())[0] == 'nobody': _warn_nobody() except: pass # Drop root privileges if we have them, and do some sanity checking # to make sure we're not starting with an obviously insecure setup. try: if os.getuid() == 0: try: import initgroups except: raise SystemExit, 'initgroups is required to safely setuid' if UID == None: raise SystemExit, ('A user was not specified to setuid ' 'to; fix this to start as root (see ' 'doc/SETUID.txt)') import stat client_home_stat = os.stat(CLIENT_HOME) client_home_faults = [] if not (client_home_stat[stat.ST_MODE]&01000): client_home_faults.append('does not have the sticky bit set') if client_home_stat[stat.ST_UID] != 0: client_home_faults.append('is not owned by root') if client_home_faults: client_home_faults.append('fix this to start as root (see ' 'doc/SETUID.txt)') err = '%s %s' % (CLIENT_HOME, ', '.join(client_home_faults)) raise SystemExit, err try: try: UID = string.atoi(UID) except: pass gid = None if isinstance(UID, StringType): uid = pwd.getpwnam(UID)[2] gid = pwd.getpwnam(UID)[3] elif isinstance(UID, IntType): uid = pwd.getpwuid(UID)[2] gid = pwd.getpwuid(UID)[3] UID = pwd.getpwuid(UID)[0] else: raise KeyError if UID == 'nobody': _warn_nobody() try: initgroups.initgroups(UID, gid) if gid is not None: try: os.setgid(gid) except OSError: pass os.setuid(uid) except OSError: pass except KeyError: zLOG.LOG("z2", zLOG.ERROR, ("Can't find UID %s" % UID)) except AttributeError: pass except: raise # Check umask sanity if we're on posix. if os.name == 'posix' and not os.environ.get('Z_DEBUG_MODE'): # umask is silly, blame POSIX. We have to set it to get its value. current_umask = os.umask(0) os.umask(current_umask) if current_umask != 077: current_umask = '%03o' % current_umask zLOG.LOG("z2", zLOG.INFO, ( 'Your umask of %s may be too permissive; for the security of ' 'your Zope data, it is recommended you use 077' % current_umask )) except: # Log startup exception and tell zdaemon not to restart us. try: zLOG.LOG("z2", zLOG.PANIC, "Startup exception", error=sys.exc_info()) except: pass sys.exit(0) # Start Medusa, Ye Hass! sys.ZServerExitCode=0 asyncore.loop() sys.exit(sys.ZServerExitCode) Pound-2.8/config.sub0000755000175000017500000007247413275266545013510 0ustar rosegroseg#! /bin/sh # Configuration validation subroutine script. # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, # 2000, 2001, 2002, 2003 Free Software Foundation, Inc. timestamp='2003-05-09' # This file is (in principle) common to ALL GNU software. # The presence of a machine in this file suggests that SOME GNU software # can handle that machine. It does not imply ALL GNU software can. # # This file is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, # Boston, MA 02111-1307, USA. # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # Please send patches to . Submit a context # diff and a properly formatted ChangeLog entry. # # Configuration subroutine to validate and canonicalize a configuration type. # Supply the specified configuration type as an argument. # If it is invalid, we print an error message on stderr and exit with code 1. # Otherwise, we print the canonical config type on stdout and succeed. # This file is supposed to be the same for all GNU packages # and recognize all the CPU types, system types and aliases # that are meaningful with *any* GNU software. # Each package is responsible for reporting which valid configurations # it does not support. The user should be able to distinguish # a failure to support a valid configuration from a meaningless # configuration. # The goal of this file is to map all the various variations of a given # machine specification into a single specification in the form: # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM # or in some cases, the newer four-part form: # CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM # It is wrong to echo any other type of specification. me=`echo "$0" | sed -e 's,.*/,,'` usage="\ Usage: $0 [OPTION] CPU-MFR-OPSYS $0 [OPTION] ALIAS Canonicalize a configuration name. Operation modes: -h, --help print this help, then exit -t, --time-stamp print date of last modification, then exit -v, --version print version number, then exit Report bugs and patches to ." version="\ GNU config.sub ($timestamp) Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." help=" Try \`$me --help' for more information." # Parse command line while test $# -gt 0 ; do case $1 in --time-stamp | --time* | -t ) echo "$timestamp" ; exit 0 ;; --version | -v ) echo "$version" ; exit 0 ;; --help | --h* | -h ) echo "$usage"; exit 0 ;; -- ) # Stop option processing shift; break ;; - ) # Use stdin as input. break ;; -* ) echo "$me: invalid option $1$help" exit 1 ;; *local*) # First pass through any local machine types. echo $1 exit 0;; * ) break ;; esac done case $# in 0) echo "$me: missing argument$help" >&2 exit 1;; 1) ;; *) echo "$me: too many arguments$help" >&2 exit 1;; esac # Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). # Here we must recognize all the valid KERNEL-OS combinations. maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` case $maybe_os in nto-qnx* | linux-gnu* | freebsd*-gnu* | netbsd*-gnu* | storm-chaos* | os2-emx* | rtmk-nova*) os=-$maybe_os basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` ;; *) basic_machine=`echo $1 | sed 's/-[^-]*$//'` if [ $basic_machine != $1 ] then os=`echo $1 | sed 's/.*-/-/'` else os=; fi ;; esac ### Let's recognize common machines as not being operating systems so ### that things like config.sub decstation-3100 work. We also ### recognize some manufacturers as not being operating systems, so we ### can provide default operating systems below. case $os in -sun*os*) # Prevent following clause from handling this invalid input. ;; -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ -apple | -axis) os= basic_machine=$1 ;; -sim | -cisco | -oki | -wec | -winbond) os= basic_machine=$1 ;; -scout) ;; -wrs) os=-vxworks basic_machine=$1 ;; -chorusos*) os=-chorusos basic_machine=$1 ;; -chorusrdb) os=-chorusrdb basic_machine=$1 ;; -hiux*) os=-hiuxwe2 ;; -sco5) os=-sco3.2v5 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco4) os=-sco3.2v4 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco3.2.[4-9]*) os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco3.2v[4-9]*) # Don't forget version if it is 3.2v4 or newer. basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco*) os=-sco3.2v2 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -udk*) basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -isc) os=-isc2.2 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -clix*) basic_machine=clipper-intergraph ;; -isc*) basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -lynx*) os=-lynxos ;; -ptx*) basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` ;; -windowsnt*) os=`echo $os | sed -e 's/windowsnt/winnt/'` ;; -psos*) os=-psos ;; -mint | -mint[0-9]*) basic_machine=m68k-atari os=-mint ;; esac # Decode aliases for certain CPU-COMPANY combinations. case $basic_machine in # Recognize the basic CPU types without company name. # Some are omitted here because they have special meanings below. 1750a | 580 \ | a29k \ | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr \ | clipper \ | d10v | d30v | dlx | dsp16xx \ | fr30 | frv \ | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ | i370 | i860 | i960 | ia64 \ | ip2k \ | m32r | m68000 | m68k | m88k | mcore \ | mips | mipsbe | mipseb | mipsel | mipsle \ | mips16 \ | mips64 | mips64el \ | mips64vr | mips64vrel \ | mips64orion | mips64orionel \ | mips64vr4100 | mips64vr4100el \ | mips64vr4300 | mips64vr4300el \ | mips64vr5000 | mips64vr5000el \ | mipsisa32 | mipsisa32el \ | mipsisa32r2 | mipsisa32r2el \ | mipsisa64 | mipsisa64el \ | mipsisa64sb1 | mipsisa64sb1el \ | mipsisa64sr71k | mipsisa64sr71kel \ | mipstx39 | mipstx39el \ | mn10200 | mn10300 \ | msp430 \ | ns16k | ns32k \ | openrisc | or32 \ | pdp10 | pdp11 | pj | pjl \ | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \ | pyramid \ | sh | sh[1234] | sh[23]e | sh[34]eb | shbe | shle | sh[1234]le | sh3ele \ | sh64 | sh64le \ | sparc | sparc64 | sparc86x | sparclet | sparclite | sparcv9 | sparcv9b \ | strongarm \ | tahoe | thumb | tic80 | tron \ | v850 | v850e \ | we32k \ | x86 | xscale | xstormy16 | xtensa \ | z8k) basic_machine=$basic_machine-unknown ;; m6811 | m68hc11 | m6812 | m68hc12) # Motorola 68HC11/12. basic_machine=$basic_machine-unknown os=-none ;; m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) ;; # We use `pc' rather than `unknown' # because (1) that's what they normally are, and # (2) the word "unknown" tends to confuse beginning users. i*86 | x86_64) basic_machine=$basic_machine-pc ;; # Object if more than one company name word. *-*-*) echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 exit 1 ;; # Recognize the basic CPU types with company name. 580-* \ | a29k-* \ | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \ | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ | avr-* \ | bs2000-* \ | c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \ | clipper-* | cydra-* \ | d10v-* | d30v-* | dlx-* \ | elxsi-* \ | f30[01]-* | f700-* | fr30-* | frv-* | fx80-* \ | h8300-* | h8500-* \ | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ | i*86-* | i860-* | i960-* | ia64-* \ | ip2k-* \ | m32r-* \ | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ | m88110-* | m88k-* | mcore-* \ | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ | mips16-* \ | mips64-* | mips64el-* \ | mips64vr-* | mips64vrel-* \ | mips64orion-* | mips64orionel-* \ | mips64vr4100-* | mips64vr4100el-* \ | mips64vr4300-* | mips64vr4300el-* \ | mips64vr5000-* | mips64vr5000el-* \ | mipsisa32-* | mipsisa32el-* \ | mipsisa32r2-* | mipsisa32r2el-* \ | mipsisa64-* | mipsisa64el-* \ | mipsisa64sb1-* | mipsisa64sb1el-* \ | mipsisa64sr71k-* | mipsisa64sr71kel-* \ | mipstx39-* | mipstx39el-* \ | msp430-* \ | none-* | np1-* | nv1-* | ns16k-* | ns32k-* \ | orion-* \ | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \ | pyramid-* \ | romp-* | rs6000-* \ | sh-* | sh[1234]-* | sh[23]e-* | sh[34]eb-* | shbe-* \ | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ | sparc-* | sparc64-* | sparc86x-* | sparclet-* | sparclite-* \ | sparcv9-* | sparcv9b-* | strongarm-* | sv1-* | sx?-* \ | tahoe-* | thumb-* \ | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ | tron-* \ | v850-* | v850e-* | vax-* \ | we32k-* \ | x86-* | x86_64-* | xps100-* | xscale-* | xstormy16-* \ | xtensa-* \ | ymp-* \ | z8k-*) ;; # Recognize the various machine names and aliases which stand # for a CPU type and a company and sometimes even an OS. 386bsd) basic_machine=i386-unknown os=-bsd ;; 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) basic_machine=m68000-att ;; 3b*) basic_machine=we32k-att ;; a29khif) basic_machine=a29k-amd os=-udi ;; adobe68k) basic_machine=m68010-adobe os=-scout ;; alliant | fx80) basic_machine=fx80-alliant ;; altos | altos3068) basic_machine=m68k-altos ;; am29k) basic_machine=a29k-none os=-bsd ;; amd64) basic_machine=x86_64-pc ;; amdahl) basic_machine=580-amdahl os=-sysv ;; amiga | amiga-*) basic_machine=m68k-unknown ;; amigaos | amigados) basic_machine=m68k-unknown os=-amigaos ;; amigaunix | amix) basic_machine=m68k-unknown os=-sysv4 ;; apollo68) basic_machine=m68k-apollo os=-sysv ;; apollo68bsd) basic_machine=m68k-apollo os=-bsd ;; aux) basic_machine=m68k-apple os=-aux ;; balance) basic_machine=ns32k-sequent os=-dynix ;; c90) basic_machine=c90-cray os=-unicos ;; convex-c1) basic_machine=c1-convex os=-bsd ;; convex-c2) basic_machine=c2-convex os=-bsd ;; convex-c32) basic_machine=c32-convex os=-bsd ;; convex-c34) basic_machine=c34-convex os=-bsd ;; convex-c38) basic_machine=c38-convex os=-bsd ;; cray | j90) basic_machine=j90-cray os=-unicos ;; crds | unos) basic_machine=m68k-crds ;; cris | cris-* | etrax*) basic_machine=cris-axis ;; da30 | da30-*) basic_machine=m68k-da30 ;; decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) basic_machine=mips-dec ;; decsystem10* | dec10*) basic_machine=pdp10-dec os=-tops10 ;; decsystem20* | dec20*) basic_machine=pdp10-dec os=-tops20 ;; delta | 3300 | motorola-3300 | motorola-delta \ | 3300-motorola | delta-motorola) basic_machine=m68k-motorola ;; delta88) basic_machine=m88k-motorola os=-sysv3 ;; dpx20 | dpx20-*) basic_machine=rs6000-bull os=-bosx ;; dpx2* | dpx2*-bull) basic_machine=m68k-bull os=-sysv3 ;; ebmon29k) basic_machine=a29k-amd os=-ebmon ;; elxsi) basic_machine=elxsi-elxsi os=-bsd ;; encore | umax | mmax) basic_machine=ns32k-encore ;; es1800 | OSE68k | ose68k | ose | OSE) basic_machine=m68k-ericsson os=-ose ;; fx2800) basic_machine=i860-alliant ;; genix) basic_machine=ns32k-ns ;; gmicro) basic_machine=tron-gmicro os=-sysv ;; go32) basic_machine=i386-pc os=-go32 ;; h3050r* | hiux*) basic_machine=hppa1.1-hitachi os=-hiuxwe2 ;; h8300hms) basic_machine=h8300-hitachi os=-hms ;; h8300xray) basic_machine=h8300-hitachi os=-xray ;; h8500hms) basic_machine=h8500-hitachi os=-hms ;; harris) basic_machine=m88k-harris os=-sysv3 ;; hp300-*) basic_machine=m68k-hp ;; hp300bsd) basic_machine=m68k-hp os=-bsd ;; hp300hpux) basic_machine=m68k-hp os=-hpux ;; hp3k9[0-9][0-9] | hp9[0-9][0-9]) basic_machine=hppa1.0-hp ;; hp9k2[0-9][0-9] | hp9k31[0-9]) basic_machine=m68000-hp ;; hp9k3[2-9][0-9]) basic_machine=m68k-hp ;; hp9k6[0-9][0-9] | hp6[0-9][0-9]) basic_machine=hppa1.0-hp ;; hp9k7[0-79][0-9] | hp7[0-79][0-9]) basic_machine=hppa1.1-hp ;; hp9k78[0-9] | hp78[0-9]) # FIXME: really hppa2.0-hp basic_machine=hppa1.1-hp ;; hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) # FIXME: really hppa2.0-hp basic_machine=hppa1.1-hp ;; hp9k8[0-9][13679] | hp8[0-9][13679]) basic_machine=hppa1.1-hp ;; hp9k8[0-9][0-9] | hp8[0-9][0-9]) basic_machine=hppa1.0-hp ;; hppa-next) os=-nextstep3 ;; hppaosf) basic_machine=hppa1.1-hp os=-osf ;; hppro) basic_machine=hppa1.1-hp os=-proelf ;; i370-ibm* | ibm*) basic_machine=i370-ibm ;; # I'm not sure what "Sysv32" means. Should this be sysv3.2? i*86v32) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv32 ;; i*86v4*) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv4 ;; i*86v) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv ;; i*86sol2) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-solaris2 ;; i386mach) basic_machine=i386-mach os=-mach ;; i386-vsta | vsta) basic_machine=i386-unknown os=-vsta ;; iris | iris4d) basic_machine=mips-sgi case $os in -irix*) ;; *) os=-irix4 ;; esac ;; isi68 | isi) basic_machine=m68k-isi os=-sysv ;; m88k-omron*) basic_machine=m88k-omron ;; magnum | m3230) basic_machine=mips-mips os=-sysv ;; merlin) basic_machine=ns32k-utek os=-sysv ;; mingw32) basic_machine=i386-pc os=-mingw32 ;; miniframe) basic_machine=m68000-convergent ;; *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) basic_machine=m68k-atari os=-mint ;; mips3*-*) basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` ;; mips3*) basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown ;; mmix*) basic_machine=mmix-knuth os=-mmixware ;; monitor) basic_machine=m68k-rom68k os=-coff ;; morphos) basic_machine=powerpc-unknown os=-morphos ;; msdos) basic_machine=i386-pc os=-msdos ;; mvs) basic_machine=i370-ibm os=-mvs ;; ncr3000) basic_machine=i486-ncr os=-sysv4 ;; netbsd386) basic_machine=i386-unknown os=-netbsd ;; netwinder) basic_machine=armv4l-rebel os=-linux ;; news | news700 | news800 | news900) basic_machine=m68k-sony os=-newsos ;; news1000) basic_machine=m68030-sony os=-newsos ;; news-3600 | risc-news) basic_machine=mips-sony os=-newsos ;; necv70) basic_machine=v70-nec os=-sysv ;; next | m*-next ) basic_machine=m68k-next case $os in -nextstep* ) ;; -ns2*) os=-nextstep2 ;; *) os=-nextstep3 ;; esac ;; nh3000) basic_machine=m68k-harris os=-cxux ;; nh[45]000) basic_machine=m88k-harris os=-cxux ;; nindy960) basic_machine=i960-intel os=-nindy ;; mon960) basic_machine=i960-intel os=-mon960 ;; nonstopux) basic_machine=mips-compaq os=-nonstopux ;; np1) basic_machine=np1-gould ;; nv1) basic_machine=nv1-cray os=-unicosmp ;; nsr-tandem) basic_machine=nsr-tandem ;; op50n-* | op60c-*) basic_machine=hppa1.1-oki os=-proelf ;; or32 | or32-*) basic_machine=or32-unknown os=-coff ;; OSE68000 | ose68000) basic_machine=m68000-ericsson os=-ose ;; os68k) basic_machine=m68k-none os=-os68k ;; pa-hitachi) basic_machine=hppa1.1-hitachi os=-hiuxwe2 ;; paragon) basic_machine=i860-intel os=-osf ;; pbd) basic_machine=sparc-tti ;; pbb) basic_machine=m68k-tti ;; pc532 | pc532-*) basic_machine=ns32k-pc532 ;; pentium | p5 | k5 | k6 | nexgen | viac3) basic_machine=i586-pc ;; pentiumpro | p6 | 6x86 | athlon | athlon_*) basic_machine=i686-pc ;; pentiumii | pentium2) basic_machine=i686-pc ;; pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentiumpro-* | p6-* | 6x86-* | athlon-*) basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentiumii-* | pentium2-*) basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pn) basic_machine=pn-gould ;; power) basic_machine=power-ibm ;; ppc) basic_machine=powerpc-unknown ;; ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppcle | powerpclittle | ppc-le | powerpc-little) basic_machine=powerpcle-unknown ;; ppcle-* | powerpclittle-*) basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppc64) basic_machine=powerpc64-unknown ;; ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppc64le | powerpc64little | ppc64-le | powerpc64-little) basic_machine=powerpc64le-unknown ;; ppc64le-* | powerpc64little-*) basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ps2) basic_machine=i386-ibm ;; pw32) basic_machine=i586-unknown os=-pw32 ;; rom68k) basic_machine=m68k-rom68k os=-coff ;; rm[46]00) basic_machine=mips-siemens ;; rtpc | rtpc-*) basic_machine=romp-ibm ;; s390 | s390-*) basic_machine=s390-ibm ;; s390x | s390x-*) basic_machine=s390x-ibm ;; sa29200) basic_machine=a29k-amd os=-udi ;; sb1) basic_machine=mipsisa64sb1-unknown ;; sb1el) basic_machine=mipsisa64sb1el-unknown ;; sequent) basic_machine=i386-sequent ;; sh) basic_machine=sh-hitachi os=-hms ;; sparclite-wrs | simso-wrs) basic_machine=sparclite-wrs os=-vxworks ;; sps7) basic_machine=m68k-bull os=-sysv2 ;; spur) basic_machine=spur-unknown ;; st2000) basic_machine=m68k-tandem ;; stratus) basic_machine=i860-stratus os=-sysv4 ;; sun2) basic_machine=m68000-sun ;; sun2os3) basic_machine=m68000-sun os=-sunos3 ;; sun2os4) basic_machine=m68000-sun os=-sunos4 ;; sun3os3) basic_machine=m68k-sun os=-sunos3 ;; sun3os4) basic_machine=m68k-sun os=-sunos4 ;; sun4os3) basic_machine=sparc-sun os=-sunos3 ;; sun4os4) basic_machine=sparc-sun os=-sunos4 ;; sun4sol2) basic_machine=sparc-sun os=-solaris2 ;; sun3 | sun3-*) basic_machine=m68k-sun ;; sun4) basic_machine=sparc-sun ;; sun386 | sun386i | roadrunner) basic_machine=i386-sun ;; sv1) basic_machine=sv1-cray os=-unicos ;; symmetry) basic_machine=i386-sequent os=-dynix ;; t3e) basic_machine=alphaev5-cray os=-unicos ;; t90) basic_machine=t90-cray os=-unicos ;; tic4x | c4x*) basic_machine=tic4x-unknown os=-coff ;; tic54x | c54x*) basic_machine=tic54x-unknown os=-coff ;; tic55x | c55x*) basic_machine=tic55x-unknown os=-coff ;; tic6x | c6x*) basic_machine=tic6x-unknown os=-coff ;; tx39) basic_machine=mipstx39-unknown ;; tx39el) basic_machine=mipstx39el-unknown ;; toad1) basic_machine=pdp10-xkl os=-tops20 ;; tower | tower-32) basic_machine=m68k-ncr ;; udi29k) basic_machine=a29k-amd os=-udi ;; ultra3) basic_machine=a29k-nyu os=-sym1 ;; v810 | necv810) basic_machine=v810-nec os=-none ;; vaxv) basic_machine=vax-dec os=-sysv ;; vms) basic_machine=vax-dec os=-vms ;; vpp*|vx|vx-*) basic_machine=f301-fujitsu ;; vxworks960) basic_machine=i960-wrs os=-vxworks ;; vxworks68) basic_machine=m68k-wrs os=-vxworks ;; vxworks29k) basic_machine=a29k-wrs os=-vxworks ;; w65*) basic_machine=w65-wdc os=-none ;; w89k-*) basic_machine=hppa1.1-winbond os=-proelf ;; xps | xps100) basic_machine=xps100-honeywell ;; ymp) basic_machine=ymp-cray os=-unicos ;; z8k-*-coff) basic_machine=z8k-unknown os=-sim ;; none) basic_machine=none-none os=-none ;; # Here we handle the default manufacturer of certain CPU types. It is in # some cases the only manufacturer, in others, it is the most popular. w89k) basic_machine=hppa1.1-winbond ;; op50n) basic_machine=hppa1.1-oki ;; op60c) basic_machine=hppa1.1-oki ;; romp) basic_machine=romp-ibm ;; rs6000) basic_machine=rs6000-ibm ;; vax) basic_machine=vax-dec ;; pdp10) # there are many clones, so DEC is not a safe bet basic_machine=pdp10-unknown ;; pdp11) basic_machine=pdp11-dec ;; we32k) basic_machine=we32k-att ;; sh3 | sh4 | sh[34]eb | sh[1234]le | sh[23]ele) basic_machine=sh-unknown ;; sh64) basic_machine=sh64-unknown ;; sparc | sparcv9 | sparcv9b) basic_machine=sparc-sun ;; cydra) basic_machine=cydra-cydrome ;; orion) basic_machine=orion-highlevel ;; orion105) basic_machine=clipper-highlevel ;; mac | mpw | mac-mpw) basic_machine=m68k-apple ;; pmac | pmac-mpw) basic_machine=powerpc-apple ;; *-unknown) # Make sure to match an already-canonicalized machine name. ;; *) echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 exit 1 ;; esac # Here we canonicalize certain aliases for manufacturers. case $basic_machine in *-digital*) basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` ;; *-commodore*) basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` ;; *) ;; esac # Decode manufacturer-specific aliases for certain operating systems. if [ x"$os" != x"" ] then case $os in # First match some system type aliases # that might get confused with valid system types. # -solaris* is a basic system type, with this one exception. -solaris1 | -solaris1.*) os=`echo $os | sed -e 's|solaris1|sunos4|'` ;; -solaris) os=-solaris2 ;; -svr4*) os=-sysv4 ;; -unixware*) os=-sysv4.2uw ;; -gnu/linux*) os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` ;; # First accept the basic system types. # The portable systems comes first. # Each alternative MUST END IN A *, to match a version number. # -sysv* is not here because it comes later, after sysvr4. -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\ | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \ | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ | -aos* \ | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ | -hiux* | -386bsd* | -netbsd* | -openbsd* | -freebsd* | -riscix* \ | -lynxos* | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ | -chorusos* | -chorusrdb* \ | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ | -mingw32* | -linux-gnu* | -uxpv* | -beos* | -mpeix* | -udk* \ | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ | -powermax* | -dnix*) # Remember, each alternative MUST END IN *, to match a version number. ;; -qnx*) case $basic_machine in x86-* | i*86-*) ;; *) os=-nto$os ;; esac ;; -nto-qnx*) ;; -nto*) os=`echo $os | sed -e 's|nto|nto-qnx|'` ;; -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ | -windows* | -osx | -abug | -netware* | -os9* | -beos* \ | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) ;; -mac*) os=`echo $os | sed -e 's|mac|macos|'` ;; -linux*) os=`echo $os | sed -e 's|linux|linux-gnu|'` ;; -sunos5*) os=`echo $os | sed -e 's|sunos5|solaris2|'` ;; -sunos6*) os=`echo $os | sed -e 's|sunos6|solaris3|'` ;; -opened*) os=-openedition ;; -wince*) os=-wince ;; -osfrose*) os=-osfrose ;; -osf*) os=-osf ;; -utek*) os=-bsd ;; -dynix*) os=-bsd ;; -acis*) os=-aos ;; -atheos*) os=-atheos ;; -386bsd) os=-bsd ;; -ctix* | -uts*) os=-sysv ;; -nova*) os=-rtmk-nova ;; -ns2 ) os=-nextstep2 ;; -nsk*) os=-nsk ;; # Preserve the version number of sinix5. -sinix5.*) os=`echo $os | sed -e 's|sinix|sysv|'` ;; -sinix*) os=-sysv4 ;; -triton*) os=-sysv3 ;; -oss*) os=-sysv3 ;; -svr4) os=-sysv4 ;; -svr3) os=-sysv3 ;; -sysvr4) os=-sysv4 ;; # This must come after -sysvr4. -sysv*) ;; -ose*) os=-ose ;; -es1800*) os=-ose ;; -xenix) os=-xenix ;; -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) os=-mint ;; -aros*) os=-aros ;; -kaos*) os=-kaos ;; -none) ;; *) # Get rid of the `-' at the beginning of $os. os=`echo $os | sed 's/[^-]*-//'` echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 exit 1 ;; esac else # Here we handle the default operating systems that come with various machines. # The value should be what the vendor currently ships out the door with their # machine or put another way, the most popular os provided with the machine. # Note that if you're going to try to match "-MANUFACTURER" here (say, # "-sun"), then you have to tell the case statement up towards the top # that MANUFACTURER isn't an operating system. Otherwise, code above # will signal an error saying that MANUFACTURER isn't an operating # system, and we'll never get to this point. case $basic_machine in *-acorn) os=-riscix1.2 ;; arm*-rebel) os=-linux ;; arm*-semi) os=-aout ;; # This must come before the *-dec entry. pdp10-*) os=-tops20 ;; pdp11-*) os=-none ;; *-dec | vax-*) os=-ultrix4.2 ;; m68*-apollo) os=-domain ;; i386-sun) os=-sunos4.0.2 ;; m68000-sun) os=-sunos3 # This also exists in the configure program, but was not the # default. # os=-sunos4 ;; m68*-cisco) os=-aout ;; mips*-cisco) os=-elf ;; mips*-*) os=-elf ;; or32-*) os=-coff ;; *-tti) # must be before sparc entry or we get the wrong os. os=-sysv3 ;; sparc-* | *-sun) os=-sunos4.1.1 ;; *-be) os=-beos ;; *-ibm) os=-aix ;; *-wec) os=-proelf ;; *-winbond) os=-proelf ;; *-oki) os=-proelf ;; *-hp) os=-hpux ;; *-hitachi) os=-hiux ;; i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) os=-sysv ;; *-cbm) os=-amigaos ;; *-dg) os=-dgux ;; *-dolphin) os=-sysv3 ;; m68k-ccur) os=-rtu ;; m88k-omron*) os=-luna ;; *-next ) os=-nextstep ;; *-sequent) os=-ptx ;; *-crds) os=-unos ;; *-ns) os=-genix ;; i370-*) os=-mvs ;; *-next) os=-nextstep3 ;; *-gould) os=-sysv ;; *-highlevel) os=-bsd ;; *-encore) os=-bsd ;; *-sgi) os=-irix ;; *-siemens) os=-sysv4 ;; *-masscomp) os=-rtu ;; f30[01]-fujitsu | f700-fujitsu) os=-uxpv ;; *-rom68k) os=-coff ;; *-*bug) os=-coff ;; *-apple) os=-macos ;; *-atari*) os=-mint ;; *) os=-none ;; esac fi # Here we handle the case where we know the os, and the CPU type, but not the # manufacturer. We pick the logical manufacturer. vendor=unknown case $basic_machine in *-unknown) case $os in -riscix*) vendor=acorn ;; -sunos*) vendor=sun ;; -aix*) vendor=ibm ;; -beos*) vendor=be ;; -hpux*) vendor=hp ;; -mpeix*) vendor=hp ;; -hiux*) vendor=hitachi ;; -unos*) vendor=crds ;; -dgux*) vendor=dg ;; -luna*) vendor=omron ;; -genix*) vendor=ns ;; -mvs* | -opened*) vendor=ibm ;; -ptx*) vendor=sequent ;; -vxsim* | -vxworks* | -windiss*) vendor=wrs ;; -aux*) vendor=apple ;; -hms*) vendor=hitachi ;; -mpw* | -macos*) vendor=apple ;; -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) vendor=atari ;; -vos*) vendor=stratus ;; esac basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` ;; esac echo $basic_machine$os exit 0 # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" # End: Pound-2.8/CHANGELOG0000664000175000017500000007736113275266545012741 0ustar rosegroseg------------------------------------------------------------------------ r83 | roseg | 2018-05-11 12:16:05 +0200 (Fri, 11 May 2018) | 9 lines Release 2.8 Enhancements: - removed DynScale flag and support - removed support for multi-line headers (both input and output) Bug fixes: - fixed potential request smuggling via fudged headers ------------------------------------------------------------------------ r82 | roseg | 2016-10-23 16:59:47 +0200 (Sun, 23 Oct 2016) | 8 lines Release 2.8a Enhancements: - removed DynScale flag and support Bug fixes: - fixed potential request smuggling via fudged headers ------------------------------------------------------------------------ r81 | roseg | 2015-01-26 17:47:53 +0100 (Mon, 26 Jan 2015) | 30 lines Release 2.7 Enhancements: - added support for larger DH keys + compile-time parameter for DH bits (workaround for OpenSSL limitation) - added support for elliptical curve encryption - added protocol version in X-SSL-cipher (Tom Fitzhenry) - added "Disable PROTO" directives (fix for Poodle vulnerability) - added Cert, Disable and Cipher directives for HTTPS back-ends. The directive HTTPS "cert" no longer supported. - added filtering of "Expect: 100-continue" headers - Add support for PATCH HTTP method - Anonymise configuration option - show last client address byte as 0 (based on an idea by Christian Doering) - SSLAllowClientRenegotiation (based on a patch from Joe Gooch) - SSLHonorCipherOrder (based on a patch from Joe Gooch) - Certificate alternate names support (based on a patch from Jonas Pasche) - poundctl shows the length of the request queue (based on a request from Leo) Bug fixes: - fixed lh_retrieve warning - fixed potential memory leak on client certificates - fixed alt names problem (Joe Gooch) - removed debugging messages - fixed address comparison for RewriteLocation (IPv4/IPv6 problem - Christopher Bartz) - re-patched the redirect patch (Frank Schmierler) - fixed RPC handling (Frank Schmierler) - sanitize URLs for redirection (prevent CSRF) - SSL disable empty fragments + SSL disable compression (CRIME attack prevention) - fixed bug in configuration of DISABLED directive - changed the log level from WARNING to NOTICE if the thread arg is NULL - fixed testing of gcc options ------------------------------------------------------------------------ r80 | roseg | 2014-12-29 11:47:54 +0100 (Mon, 29 Dec 2014) | 10 lines Release 2.7f Enhancements: - compile-time parameter for DH bits (workaround for OpenSSL limitation) Bug fixes: - allow '-' and '=' again in URLs (redirect) - fixed lh_retrieve warning - fixed "Disable" regex typo ------------------------------------------------------------------------ r79 | roseg | 2014-12-08 14:39:00 +0100 (Mon, 08 Dec 2014) | 12 lines Release 2.7e Enhancements: - added support for elliptical curve encryption - added support for larger DH keys - added protocol version in X-SSL-cipher (Tom Fitzhenry) Bug fixes: - fixed potential memory leak on client certificates - fixed alt names problem (Joe Gooch) - removed debugging messages ------------------------------------------------------------------------ r78 | roseg | 2014-10-18 12:36:28 +0200 (Sat, 18 Oct 2014) | 10 lines Release 2.7d Enhancements: - added "Disable PROTO" directives (fix for Poodle vulnerability) - added Cert, Disable and Cipher directives for HTTPS back-ends. The directive HTTPS "cert" no longer supported. Bug fixes: - fixed address comparison for RewriteLocation (IPv4/IPv6 problem - Christopher Bartz) ------------------------------------------------------------------------ r77 | roseg | 2014-04-21 13:16:07 +0200 (Mon, 21 Apr 2014) | 9 lines Release 2.7c Enhancements: - added filtering of "Expect: 100-continue" headers Bug fixes: - re-patched the redirect patch (Frank Schmierler) - fixed RPC handling (Frank Schmierler) ------------------------------------------------------------------------ r76 | roseg | 2013-09-26 14:33:21 +0200 (Thu, 26 Sep 2013) | 12 lines Release 2.7b Enhancements: - Add support for PATCH HTTP method Bug fixes: - sanitize URLs for redirection (prevent CSRF) - SSL disable empty fragments - SSL disable compression (CRIME attack prevention) - fixed bug in configuration of DISABLED directive - changed the log level from WARNING to NOTICE if the thread arg is NULL ------------------------------------------------------------------------ r75 | roseg | 2012-04-09 15:37:26 +0200 (Mon, 09 Apr 2012) | 12 lines Release 2.7a Enhancements: - Anonymise configuration option - show last client address byte as 0 (based on an idea by Christian Doering) - SSLAllowClientRenegotiation (based on a patch from Joe Gooch) - SSLHonorCipherOrder (based on a patch from Joe Gooch) - Certificate alternate names support (based on a patch from Jonas Pasche) - poundctl shows the length of the request queue (based on a request from Leo) Bug fixes: - fixed testing of gcc options ------------------------------------------------------------------------ r74 | roseg | 2011-12-28 14:57:45 +0100 (Wed, 28 Dec 2011) | 10 lines Release 2.6 Enhancements: - allow multiple AddHeader directives Bug fixes: - fixed memory leak in config/AddHeader - removed call to AC_FUNC_MALLOC for AIX compatability - workaround for AIX getaddrinfo() bug ------------------------------------------------------------------------ r73 | roseg | 2011-06-24 17:59:41 +0200 (Fri, 24 Jun 2011) | 7 lines Release 2.6f Enhancements: Bug fixes: - fixed memory leak in DH (patch by Edvin Torok via Patrizio Tassone) ------------------------------------------------------------------------ r72 | roseg | 2011-04-25 11:10:45 +0200 (Mon, 25 Apr 2011) | 8 lines Release 2.6e Enhancements: Bug fixes: - fixed problem in SNI certificate storage - changed long to long long for support of requests larger than 2GB ------------------------------------------------------------------------ r71 | roseg | 2011-04-11 15:59:05 +0200 (Mon, 11 Apr 2011) | 9 lines Release 2.6d Enhancements: - added parsing for certificate CN Bug fixes: - fixed problem in task enqueing - fixed small problem in Makefile ------------------------------------------------------------------------ r70 | roseg | 2010-12-27 17:54:18 +0100 (Mon, 27 Dec 2010) | 14 lines Release 2.6c Enhancements: - added support for OpenSSL 1.0 - added some more detailed error logging Bug fixes: - fix for RewriteLocation - fix for HTTPS back-ends - fix for RPC support - fix for possible request smuggling by using multiple headers Many thanks to Frank Schmirler and Ruben Kerkhof for the contributed patches ------------------------------------------------------------------------ r69 | roseg | 2010-09-25 16:49:49 +0200 (Sat, 25 Sep 2010) | 7 lines Release 2.6b Enhancements: - pre-defined number of threads for better performance on small hardware Bug fixes: ------------------------------------------------------------------------ r68 | roseg | 2010-06-23 19:18:39 +0200 (Wed, 23 Jun 2010) | 15 lines Release 2.6a Stable release 2.5.1 Enhancements: - support for SNI via multiple Cert directives (thanks to Joe Gooch) - translate hexadecimal characters in URL for pattern matching - added support for a "Disabled" directive in the configuration Bug fixes: - keep sessions for disabled back-ends, continue using them until the time-out - fixed memory leak in session removal - user IgnoreCase for CheckURL too - fixed some issues with OpenSolaris build (thanks to Spradling Cloyce) ------------------------------------------------------------------------ r67 | roseg | 2010-02-02 12:49:00 +0100 (Tue, 02 Feb 2010) | 9 lines Release 2.5 Enhancements: Bug fixes: - fixed XML format to avoid problems with brain-dead parsers - fixed Redirect to accept "/" as a path, so that "Redirect http://x/" is considered an absolute path, but "Redirect http://x" is not ------------------------------------------------------------------------ r66 | roseg | 2010-01-04 17:20:55 +0100 (Mon, 04 Jan 2010) | 7 lines Release 2.5e Enhancements: - added support for symbolic host names in poundctl Bug fixes: ------------------------------------------------------------------------ r65 | roseg | 2009-12-07 17:01:21 +0100 (Mon, 07 Dec 2009) | 9 lines Release 2.5d Enhancements: - added support for --disable-pcreposix, --disable--tcmalloc, --disable-hoard in configuration script Bug fixes: - fixed problem with long input lines in http.c - if libpcreposix is present, then pcreposix.h must also be present ------------------------------------------------------------------------ r64 | roseg | 2009-09-21 13:16:57 +0200 (Mon, 21 Sep 2009) | 8 lines Release 2.5c Enhancements: - added support for HTTPS backends Bug fixes: - fixed problem with sub-patterns in session parameters ------------------------------------------------------------------------ r63 | roseg | 2009-08-19 17:44:07 +0200 (Wed, 19 Aug 2009) | 10 lines Release 2.5b Enhancements: - support for ConnTO directive - support for IgnoreCase directive Bug fixes: - fixed problem in conf_fgets (\n confuses the regexp) - changed RSA ephemeral keys regeneration default time (every 30 minutes) ------------------------------------------------------------------------ r62 | roseg | 2009-08-06 17:23:30 +0200 (Thu, 06 Aug 2009) | 9 lines Release 2.5a Enhancements: - support for include directive Bug fixes: - fixed generation of ephemeral RSA keys (avoid premature locking) - added pre-generated DH parameters ------------------------------------------------------------------------ r61 | roseg | 2009-06-29 17:53:55 +0200 (Mon, 29 Jun 2009) | 13 lines Release 2.4.5 Stable release 2.4.5 Enhancements: - log back-end killed/disabled/enabled (thanks to Joe Gooch and Jon Garvin) - kill a BE on connection failure only if it has no HAport defined (thanks to Albert); the request may still fail! Bug fixes: - fixed parantheses problems in need_rewrite (thanks to SBR) - added call to free_headers in http.c (thanks to SBR) - fixed maximal path length in UNIX domain sockets (thanks to Ricardo Gameiro) ------------------------------------------------------------------------ r60 | roseg | 2009-01-14 17:39:52 +0100 (Wed, 14 Jan 2009) | 18 lines Release 2.4.4 Stable release 2.4.4 Enhancements: - added support for UNSUBSCRIBE and NOTIFY in xHTTP 3 and 4 - added support for BPROPFIND in xHTTP 4 - on SSL connections always pass the cipher used to the back-end (thanks to Magnus Sandin) Bug fixes: - save and restore errno value in cur_time() (thanks to Albert) - fixed problem in timer thread (thanks to Albert) - added shutdown for failed socket connection (thanks to Albert) - fixed problem with CC containing spaces in Makefile.in (thanks to Elan Ruusamäe) - increased MAXBUF to default 4096 - increased T_RSA default to 30 minutes - fixed a problem with Unix sockets back-ends (thanks to Ricardo Gameiro) ------------------------------------------------------------------------ r59 | roseg | 2008-05-31 12:25:41 +0200 (Sat, 31 May 2008) | 11 lines Release 2.4.3 Stable release 2.4.3 Enhancements: Bug fixes: - fixed problem in session access time updating (thanks to Piotr Jakubowski) - fixed problem in session removal (thanks to Doriam Mori) - fixed problem in Redirect logging (thanks to Albert) ------------------------------------------------------------------------ r58 | roseg | 2008-04-24 16:31:28 +0200 (Thu, 24 Apr 2008) | 13 lines Release 2.4.2 Stable release 2.4.2 Enhancements: Bug fixes: - fixed problem with session TTL -1 (thanks to Scott Royston for pointing it out) - fixed problem with back-end killing on failed connect - fixed a small problem in the poundctl XML output (thanks to johnlr for the fix) - added hints in call to getaddrinfo() (for Solaris 10 support) - fixed redirection problem (missing slash in Location/Content-location) ------------------------------------------------------------------------ r57 | roseg | 2008-04-05 11:45:41 +0200 (Sat, 05 Apr 2008) | 12 lines Release 2.4.1 Stable release 2.4.1 Enhancements: - added cache control for errors (thanks to Pavel Merdin for the suggestion) Bug fixes: - fixed problem with double slash in header rewriting (thanks to Cédric P.) - remove sched_policy to avoid problems on systems with poor support for it - fixed memory corruption problem with HAport ------------------------------------------------------------------------ r56 | roseg | 2008-02-11 12:53:51 +0100 (Mon, 11 Feb 2008) | 4 lines Release 2.4 Stable release 2.4 ------------------------------------------------------------------------ r55 | roseg | 2007-12-27 12:54:32 +0100 (Thu, 27 Dec 2007) | 7 lines Release 2.4f Enhancements: Bug fixes: - fixed back-end enable/disable (priority computing) ------------------------------------------------------------------------ r54 | roseg | 2007-11-29 18:16:36 +0100 (Thu, 29 Nov 2007) | 12 lines Enhancements: - added PARM session type. Old PARM is now URL - allow AddHeader for HTTP listeners as well - allow -1 for session (all types) TTL. Will hash the key to a fixed value - Redirect takes an optional code parameter (301, 302/default or 307) - new config param to allow printing the SSL certificate in a single line - new config param to control the maximal size of the input line - added better error messages for SSL loading problems Bug fixes: - if the same cookie is defined more than once use LAST definition ------------------------------------------------------------------------ r53 | roseg | 2007-08-15 18:26:58 +0200 (Wed, 15 Aug 2007) | 10 lines Release 2.4d Enhancements: - moved to GPLv3 - now using lh_hash for the session tables Bug fixes: - allow case-sensitive matching for URLs - fixed memory leak in DNS searches ------------------------------------------------------------------------ r52 | roseg | 2007-07-04 15:29:27 +0200 (Wed, 04 Jul 2007) | 10 lines Release 2.4c Enhancements: - added XML output for poundctl - added more detailed error messages Bug fixes: - fixed problems with extra-long lines - fixed problems with chunked encoding ------------------------------------------------------------------------ r51 | roseg | 2007-05-18 10:35:02 +0200 (Fri, 18 May 2007) | 11 lines Release 2.4b Enhancements: - cleaned resurrection code - added RR threads scheduling Bug fixes: - fixed problem long lines (thanks to Rune Saetre) - fixed pcreposix autoconf for systems that also require pcre - fixed problem with IP session handling ------------------------------------------------------------------------ r49 | roseg | 2007-04-30 15:01:17 +0200 (Mon, 30 Apr 2007) | 11 lines Release 2.4a Enhancements: - added display of configuration switches - added grace period for shutdown (based on an idea from Rune Saetre) - added support for IPv6 (but host caching was removed) Bug fixes: - fixed test for owner/group (BSD portability) - fixed problem with premature opening of control socket ------------------------------------------------------------------------ r46 | roseg | 2007-04-11 15:00:11 +0200 (Wed, 11 Apr 2007) | 8 lines Release 2.3 Enhancements: - added display of configuration switches - added grace period for shutdown (based on an idea from Rune Saetre) Bug fixes: ------------------------------------------------------------------------ r45 | roseg | 2007-04-04 18:15:53 +0200 (Wed, 04 Apr 2007) | 8 lines Release 2.2.8 Enhancements: - more tweaking of the dynamic rescaling code - more information in poundctl printout Bug fixes: ------------------------------------------------------------------------ r44 | roseg | 2007-03-12 18:12:14 +0100 (Mon, 12 Mar 2007) | 8 lines Release 2.2.7 Enhancements: - dynamic scaling is now a configuration directive (DynScale) - added vhost to LogLevel 5 Bug fixes: ------------------------------------------------------------------------ r43 | roseg | 2007-03-02 10:30:01 +0100 (Fri, 02 Mar 2007) | 11 lines Release 2.2.6 Enhancements: - added transaction time to LogLevel 5 - added priority display for poundctl Bug fixes: - fixed problem when adding session via poundctl - fixed problem in session dump to poundctl - fixed problem in kill_be call to t_clean ------------------------------------------------------------------------ r42 | roseg | 2007-02-19 18:19:22 +0100 (Mon, 19 Feb 2007) | 7 lines Release 2.2.5 Enhancements: Bug fixes: - fixed problem with sessions (BACKEND copying) ------------------------------------------------------------------------ r41 | roseg | 2007-02-10 15:26:42 +0100 (Sat, 10 Feb 2007) | 14 lines Release 2.2.4 Enhancements: - modular tree library - consolidated all timed functions into a single thread - added gethostbyname cache - added LogLevel 5 - same as 4 but with service name and back-end information (thanks to Joe Gooch for the suggestion) - added session creation and removal to poundctl Bug fixes: - added LOG_NDELAY to openlog() - accept and immediately close connections to disabled listeners (thanks to Joe Gooch for the suggestion) - fixed problem with -1 values in poundctl ------------------------------------------------------------------------ r40 | roseg | 2007-01-19 21:29:07 +0100 (Fri, 19 Jan 2007) | 5 lines Release 2.2.3 Bug fixes: - fixed problems in bad 2.2 release ------------------------------------------------------------------------ r39 | roseg | 2007-01-15 18:17:48 +0100 (Mon, 15 Jan 2007) | 13 lines Release 2.2.2 Enhancements: - changes in the dynamic rescaling - doubled the session key size (for those people with insanely long cookies) - added LogFacility - for logging to stdout/stderr - added optional Service names Bug fixes: - fixed bug in multiple HeadRemove matching - fixed problem with extra large session keys - fixed problem for OpenBSD accept (blocks all threads) ------------------------------------------------------------------------ r38 | roseg | 2007-01-03 18:25:30 +0100 (Wed, 03 Jan 2007) | 13 lines Release 2.2.1 Enhancements: - allow specific Listeners to override the gloabl LogLevel value - allow a default Client value to be defined at the global level - allow a default TimeOut value to be defined at the global level - added compile-time flags for file owner and group Bug fixes: - fixed some problems in the installation procedure - fixed problem in SSL session string - added protocol check in need_rewrite ------------------------------------------------------------------------ r37 | roseg | 2006-12-16 10:18:38 +0100 (Sat, 16 Dec 2006) | 45 lines Release 2.2 Enhancements: - added the host to LogLevel 2 (if available) - added support for tcmalloc (from the Google perftools package) Bug fixes: - fixed problem with the initialisation of host_mut ***************************** Cumulative changes since 2.1: ***************************** Enhancements: - added dynamic rescaling of back-end priorities, compile-time flag to enable/disable it - added support for emergency back-ends - the program poundctl(8) is now available, added the Control configuration directive - SESS_IP now behaves like other session types (no longer sticky) - added RewriteLocation 2: rewrite location if it points to same address, but ignore port - Redirect uses the original request path - added RewriteDestination configuration flag to enable rewriting the Destination header - removed msdav compile-time configuration flag and MSDAV configuration flag, extended xHTTP to allow for WebDAV, MS-DAV and MS-RPC - added CRLlist directive, split CRL from CA - Error replies are sent as pure HTML - split error messages into: - LOG_ERR: errors (mostly fatal) - LOG_WARNING: errors (non-fatal) - LOG_NOTICE: problems - LOG_INFO: extra information - time to serve the requests is logged in LogLevel 2 - added the (virtual) host to LogLevel 2 (if available) - added line numbers to config error messages - added TCP_NODELAY for faster response times - added support for tcmalloc (from the Google perftools package) Bug fixes: - fixed problem in str_be (evident mostly in LogLevel 2) - added 'const' wherever necessary - check for errors in mutex handling - fixed the verb pattern in HTTPS listeners - content is now ignored only on HEAD requests - fixed problems with autoconf on some systems - fixed problem with the initialisation of host_mut ------------------------------------------------------------------------ r36 | roseg | 2006-12-09 09:39:23 +0100 (Sat, 09 Dec 2006) | 6 lines Release 2.1.8 Bug fixes: - fixed another small problem with autoconf on some systems - added support for systems that don't define SOL_TCP ------------------------------------------------------------------------ r35 | roseg | 2006-12-06 18:32:16 +0100 (Wed, 06 Dec 2006) | 10 lines Release 2.1.7 Enhancements: - added TCP_NODELAY for faster response times - added compile-time flag to enable/disable dynamic priorities rescaling Bug fixes: - fixed problems with autoconf on some systems - fixed error in control function (be instead of svc) ------------------------------------------------------------------------ r34 | roseg | 2006-11-04 11:28:53 +0100 (Sat, 04 Nov 2006) | 9 lines Release 2.1.6 Enhancements: - Redirect uses the original request path Bug fixes: - improved dynamic priorities calculation - fixed problem with Emergency back-ends ------------------------------------------------------------------------ r33 | roseg | 2006-10-23 09:24:28 +0200 (Mon, 23 Oct 2006) | 12 lines Release 2.1.5 Enhancements: - added line numbers to config error messages - added dynamic rescaling of back-end priorities - added support for emergency back-ends - the program poundctl(8) is now available - added the Control configuration directive Bug fixes: - improved owner/group detection for install ------------------------------------------------------------------------ r32 | roseg | 2006-10-14 16:39:29 +0200 (Sat, 14 Oct 2006) | 6 lines Release 2.1.4 Bug fixes: - content is now ignored only on HEAD requests - added CRLlist directive, split CRL from CA ------------------------------------------------------------------------ r31 | roseg | 2006-09-21 18:41:15 +0200 (Thu, 21 Sep 2006) | 6 lines Release 2.1.3 Bug fixes: - fixed the verb pattern in HTTPS listeners - removed the spurious printf in cur_time ------------------------------------------------------------------------ r30 | roseg | 2006-09-18 18:12:16 +0200 (Mon, 18 Sep 2006) | 18 lines Release 2.1.2 Enhancements: - Error replies are sent as pure HTML - split error messages into: - LOG_ERR: errors (mostly fatal) - LOG_WARNING: errors (non-fatal) - LOG_NOTICE: problems - LOG_INFO: extra information - removed msdav compile-time configuration flag - removed MSDAV configuration flag - extended xHTTP to allow for WebDAV, MS-DAV and MS-RPC - added RewriteDestination configuration flag to enable rewriting the Destination header - time to serve the requests is logged in LogLevel 2 Bug fixes: - fixed (again) the RewriteRedirect 2 mode ------------------------------------------------------------------------ r29 | roseg | 2006-09-11 18:35:22 +0200 (Mon, 11 Sep 2006) | 11 lines Release 2.1.1 Enhancements: - SESS_IP now behaves like other session types (no longer sticky) - added RewriteLocation 2: rewrite location if it points to same address, but ignore port Bug fixes: - fixed problem in str_be (evident mostly in LogLevel 2) - added 'const' wherever necessary - check for errors in mutex handling ------------------------------------------------------------------------ r27 | roseg | 2006-08-05 11:35:52 +0200 (Sat, 05 Aug 2006) | 24 lines Release 2.1 Enhancements: - support for pcre library (if available) for much better performance - support for hoard library (if available) for much better performance - rewrite Location and Content-location headers for all responses - improved detection of when is a rewrite necessary - renamed Change30x to RewriteLocation. Default: on Bug fixes: - fixed small problem in the upd_session() code - declared init_RSAgen() as void everywhere - moved to SESS_xxx tokens to avoid Solaris name conflict - added #ifdef's for LOG_FTP and LOG_AUTHPRIV - fixed problem in URL checking - fixed problem in session tracking-code and session updating - fixed LogLevel 3 to show that the v_host is unknown - fixed headers checking in match_service - fixed problem in ClientCert directive handling - fixed potential memory leak in AUTH decoding - allow OPTIONS WebDAV request to have content - replaced inet_ntoa with inet_ntop where available - removed all static buffers ------------------------------------------------------------------------ r25 | roseg | 2006-02-01 10:00:42 +0100 (Wed, 01 Feb 2006) | 14 lines Release 2.0 Enhancements: - new configuration file syntax, offering significant improvements. - the ability to define listener-specific back-ends. In most cases this should eliminate the need for multiple Pound instances. - a new type of back-end: the redirector allows you to respond with a redirect without involving any back-end server. - most "secondary" properties (such as error messages, client time-out, etc.) are now private to listeners. - HAport has an optional address, different from the main back-end - added a -V flag for version - session keeping on a specific Header ------------------------------------------------------------------------ r21 | roseg | 2006-02-01 14:27:19 +0100 (Wed, 01 Feb 2006) | 15 lines Release 1.10 Enhancements: added NoDaemon configuration directive (replaces compile-time switch) added LogFacility configuration directive (replaces compile-time switch) added user name logging Bug fixes: fixed problem with the poll() code fixed problem with empty list in gethostbyname() added call to setsid() if daemon conflicting headers are removed (Content-length - Transfer-encoding) Last release in the 1.x series. ------------------------------------------------------------------------ r19 | roseg | 2005-06-01 15:27:19 +0200 (Wed, 01 Jun 2005) | 18 lines Release 1.9 Enhancements: - Added the VerifyList configuration flag (CA root certs + CRL) - CRL checking code - RewriteRedirect 2 - ignores port value for host matching - Added -c flag (check-only mode) - Added -v flag (verbose mode) - Added -p flag for pid file name Bug fixes: - fixed a potential buffer overflow problem (in checking the Host header) - added call to SSL_library_init - added a check for MSIE before forcing SSL shutdown - X-SSL-Cipher header is added only if HTTPSHeaders is non-zero - added code for shorter linger on badly closed connections (IE work-around) - fixed the locking for session checking (mutex_lock/unlock) ------------------------------------------------------------------------ r17 | roseg | 2004-11-04 14:27:19 +0100 (Thu, 04 Nov 2004) | 23 lines Release 1.8 Changes: - added support for non-blocking connect(2) - added support for 414 - Request URI too long - added RedirectRewrite directive - to prevent redirect changes - added support for NoHTTPS11 value 2 (for MSIE clients only) - added support for HTTPSHeaders 3 (no verify) Problems fixed: - fixed bug if multiple listening ports/addresses - fixed memory leak in SSL - flush stdout (if used) after each log message - assumes only 304, 305 and 306 codes to have no content - fixed problem with delays in 302 without content - fixed problem with time-outs in HTTPS Enhancements: - improved threads detection code in autoconf - added supervisor process disable configuration flag - tweak for the Location rewriting code (only look at current GROUP) - improved print-out for client certificate information ------------------------------------------------------------------------ r15 | roseg | 2004-03-24 14:27:19 +0100 (Wed, 24 Mar 2004) | 12 lines Release 1.7 Fixed bug in X-SSL-CIPHER description Changed README to stx format for consistency Addedd X-SSL-certificate with full client certificate Improved the response times on HTTP/0.9 (content without Content-length) Improved response granularity on above - using unbuffered BIO now Fixed problem with IE/SSL (SSL_set_shutdown) Avoid error messages on premature EOF from client Fixed HeadRemove code so all headers are checked without exception Improved autoconf detection ------------------------------------------------------------------------ r13 | roseg | 2003-11-30 14:27:19 +0100 (Sun, 30 Nov 2003) | 15 lines Release 1.6 Callback for RSA ephemeral keys: - generated in a separate thread - used if required (IE 5.0?) New X-SSL-cipher header encryption level/method Added CheckURL parameter in config file - perform syntax check only if value 1 (default 0) Allow for empty query/param strings in URL syntax Additional SSL engine loading code Added parameter for CA certificates - CA list is sent to client Verify client certificates up to given depth Fixed vulnerability in syslog handling ------------------------------------------------------------------------ r11 | roseg | 2003-10-14 15:27:19 +0200 (Tue, 14 Oct 2003) | 19 lines Release 1.5 Session by Basic Authentication: Session BASIC parameter added Syntax checking of request. User-defined request character set(s): Parameters CSsegment, CSparameter, CSqid, CSqval Request size limit: Parameter MaxRequest Single log function rather than #ifdefs. Added LogLevel 4 (same as 3 but without the virtual host info). Added HeadRemove directive (allows to delete a header from requests). Location rewriting on redirect: if the request contains a Header directive and the response is codes 301, 302, 303, 307 and the Location in the response is to a known host then the Location header in the response will be rewritten to point to the Pound protocol/port itself ------------------------------------------------------------------------ r9 | roseg | 2003-04-24 15:27:19 +0200 (Thu, 24 Apr 2003) | 12 lines Release 1.4 Added 'Server' configuration directive Fixed problem with HTTPSHeaders 0 "..." - the desired header is written even if HTTPSHeaders is 0 Added the ability of loading a certificate chain. Added compatability with OpenSSL 0.9.7 Added user-definable error pages. Added compile-time flags to run in foreground and to log to stderr. Opens separate pid files per-process. Improved autoconf. Some SSL speed optimisations. ------------------------------------------------------------------------ r7 | roseg | 2003-02-19 14:27:19 +0100 (Wed, 19 Feb 2003) | 10 lines Release 1.3 Added support for OpenSSL Engine (crypto hardware) Added support for Subversion WebDAV Added support for mandatory client certificates Added X-SSL-serial header for SSL connections Fixed problem with BIO_pending in is_readable Fixed problem with multi-threading in OpenSSL Improved autoconf ------------------------------------------------------------------------ r5 | roseg | 2003-01-20 14:27:19 +0100 (Mon, 20 Jan 2003) | 5 lines Release 1.2 Better handling of "100 Continue" responses Fixed problem with allowed character set for requests ------------------------------------------------------------------------ r3 | roseg | 2003-01-09 14:27:19 +0100 (Thu, 09 Jan 2003) | 9 lines Better auto-conf detection LogLevel 3 for Apache-like log (Combined Log Format) Don't ask client for certificate if no SSL headers required Added handling for 'Connection: closed' header Added monitor process to restart worker process if crashed Added possibility to listen on all interfaces Fixed HeadDeny code Fixed problem with threads on *BSD ------------------------------------------------------------------------ r1 | roseg | 2002-10-31 14:27:19 +0100 (Thu, 31 Oct 2002) | 1 line Initial import ------------------------------------------------------------------------ Pound-2.8/poundctl.c0000755000175000017500000002747113275266545013521 0ustar rosegroseg/* * Pound - the reverse-proxy load-balancer * Copyright (C) 2002-2010 Apsis GmbH * * This file is part of Pound. * * Pound is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * Pound is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * Contact information: * Apsis GmbH * P.O.Box * 8707 Uetikon am See * Switzerland * EMail: roseg@apsis.ch */ #define NO_EXTERNALS 1 #include "pound.h" static int xml_out = 0; static int host_names = 0; static void usage(const char *arg0) { fprintf(stderr, "Usage: %s -c /control/socket [ -X ] cmd\n", arg0); fprintf(stderr, "\twhere cmd is one of:\n"); fprintf(stderr, "\t-L n - enable listener n\n"); fprintf(stderr, "\t-l n - disable listener n\n"); fprintf(stderr, "\t-S n m - enable service m in service n (use -1 for global services)\n"); fprintf(stderr, "\t-s n m - disable service m in service n (use -1 for global services)\n"); fprintf(stderr, "\t-B n m r - enable back-end r in service m in listener n\n"); fprintf(stderr, "\t-b n m r - disable back-end r in service m in listener n\n"); fprintf(stderr, "\t-N n m k r - add a session with key k and back-end r in service m in listener n\n"); fprintf(stderr, "\t-n n m k - remove a session with key k r in service m in listener n\n"); fprintf(stderr, "\n"); fprintf(stderr, "\tentering the command without arguments lists the current configuration.\n"); fprintf(stderr, "\tthe -X flag results in XML output.\n"); fprintf(stderr, "\tthe -H flag shows symbolic host names instead of addresses.\n"); exit(1); } /* * Translate inet/inet6 address/port into a string */ static char * prt_addr(const struct addrinfo *addr) { static char res[UNIX_PATH_MAX]; char buf[UNIX_PATH_MAX]; int port; void *src; memset(buf, 0, UNIX_PATH_MAX); #ifdef HAVE_INET_NTOP switch(addr->ai_family) { case AF_INET: src = (void *)&((struct sockaddr_in *)addr->ai_addr)->sin_addr.s_addr; port = ntohs(((struct sockaddr_in *)addr->ai_addr)->sin_port); if(host_names && !getnameinfo(addr->ai_addr, addr->ai_addrlen, buf, UNIX_PATH_MAX - 1, NULL, 0, 0)) break; if(inet_ntop(AF_INET, src, buf, UNIX_PATH_MAX - 1) == NULL) strncpy(buf, "(UNKNOWN)", UNIX_PATH_MAX - 1); break; case AF_INET6: src = (void *)&((struct sockaddr_in6 *)addr->ai_addr)->sin6_addr.s6_addr; port = ntohs(((struct sockaddr_in6 *)addr->ai_addr)->sin6_port); if(host_names && !getnameinfo(addr->ai_addr, addr->ai_addrlen, buf, UNIX_PATH_MAX - 1, NULL, 0, 0)) break; if(inet_ntop(AF_INET6, src, buf, UNIX_PATH_MAX - 1) == NULL) strncpy(buf, "(UNKNOWN)", UNIX_PATH_MAX - 1); break; case AF_UNIX: strncpy(buf, (char *)addr->ai_addr, UNIX_PATH_MAX - 1); port = 0; break; default: strncpy(buf, "(UNKNOWN)", UNIX_PATH_MAX - 1); port = 0; break; } snprintf(res, UNIX_PATH_MAX - 1, "%s:%d", buf, port); #else #error "Pound needs inet_ntop()" #endif return res; } static void be_prt(const int sock) { BACKEND be; struct sockaddr_storage a, h; int n_be; n_be = 0; while(read(sock, (void *)&be, sizeof(BACKEND)) == sizeof(BACKEND)) { if(be.disabled < 0) break; read(sock, &a, be.addr.ai_addrlen); be.addr.ai_addr = (struct sockaddr *)&a; if(be.ha_addr.ai_addrlen > 0) { read(sock, &h, be.ha_addr.ai_addrlen); be.ha_addr.ai_addr = (struct sockaddr *)&h; } if(xml_out) printf("\n", n_be++, prt_addr(&be.addr), be.t_average / 1000000, be.priority, be.alive? "yes": "DEAD", be.disabled? "DISABLED": "active"); else printf(" %3d. Backend %s %s (%d %.3f sec) %s\n", n_be++, prt_addr(&be.addr), be.disabled? "DISABLED": "active", be.priority, be.t_average / 1000000, be.alive? "alive": "DEAD"); } return; } static void sess_prt(const int sock) { TABNODE sess; int n_be, n_sess, cont_len; char buf[KEY_SIZE + 1], escaped[KEY_SIZE * 2 + 1]; n_sess = 0; while(read(sock, (void *)&sess, sizeof(TABNODE)) == sizeof(TABNODE)) { if(sess.content == NULL) break; read(sock, &n_be, sizeof(n_be)); read(sock, &cont_len, sizeof(cont_len)); memset(buf, 0, KEY_SIZE + 1); /* cont_len is at most KEY_SIZE */ read(sock, buf, cont_len); if(xml_out) { int i, j; char escaped[KEY_SIZE * 2 + 1]; for(i = j = 0; buf[i]; i++) if(buf[i] == '"') { escaped[j++] = '\\'; escaped[j++] = '"'; } else escaped[j++] = buf[i]; escaped[j] = '\0'; printf("\n", n_sess++, escaped, n_be); } else printf(" %3d. Session %s -> %d\n", n_sess++, buf, n_be); } return; } static void svc_prt(const int sock) { SERVICE svc; int n_svc; n_svc = 0; while(read(sock, (void *)&svc, sizeof(SERVICE)) == sizeof(SERVICE)) { if(svc.disabled < 0) break; if(xml_out) { if(svc.name[0]) printf("\n", n_svc++, svc.name, svc.disabled? "DISABLED": "active"); else printf("\n", n_svc++, svc.disabled? " DISABLED": ""); } else { if(svc.name[0]) printf(" %3d. Service \"%s\" %s (%d)\n", n_svc++, svc.name, svc.disabled? "DISABLED": "active", svc.tot_pri); else printf(" %3d. Service %s (%d)\n", n_svc++, svc.disabled? "DISABLED": "active", svc.tot_pri); } be_prt(sock); sess_prt(sock); if(xml_out) printf("\n"); } return; } static int get_sock(const char *sock_name) { struct sockaddr_un ctrl; int res; memset(&ctrl, 0, sizeof(ctrl)); ctrl.sun_family = AF_UNIX; strncpy(ctrl.sun_path, sock_name, sizeof(ctrl.sun_path) - 1); if((res = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) { perror("socket create"); exit(1); } if(connect(res, (struct sockaddr *)&ctrl, (socklen_t)sizeof(ctrl)) < 0) { perror("connect"); exit(1); } return res; } int main(const int argc, char **argv) { CTRL_CMD cmd; int sock, n_lstn, n_svc, n_be, n_sess, i; char *arg0, *sock_name, buf[KEY_SIZE + 1]; int c_opt, en_lst, de_lst, en_svc, de_svc, en_be, de_be, a_sess, d_sess, is_set; LISTENER lstn; SERVICE svc; BACKEND be; TABNODE sess; struct sockaddr_storage a; arg0 = *argv; sock_name = NULL; en_lst = de_lst = en_svc = de_svc = en_be = de_be = is_set = a_sess = d_sess = 0; memset(&cmd, 0, sizeof(cmd)); opterr = 0; i = 0; while(!i && (c_opt = getopt(argc, argv, "c:LlSsBbNnXH")) > 0) switch(c_opt) { case 'c': sock_name = optarg; break; case 'X': xml_out = 1; break; case 'L': if(is_set) usage(arg0); en_lst = is_set = 1; break; case 'l': if(is_set) usage(arg0); de_lst = is_set = 1; break; case 'S': if(is_set) usage(arg0); en_svc = is_set = 1; break; case 's': if(is_set) usage(arg0); de_svc = is_set = 1; break; case 'B': if(is_set) usage(arg0); en_be = is_set = 1; break; case 'b': if(is_set) usage(arg0); de_be = is_set = 1; break; case 'N': if(is_set) usage(arg0); a_sess = is_set = 1; break; case 'n': if(is_set) usage(arg0); d_sess = is_set = 1; break; case 'H': host_names = 1; break; default: if(optopt == '1') { optind--; i = 1; } else { fprintf(stderr, "bad flag -%c", optopt); usage(arg0); } break; } if(sock_name == NULL) usage(arg0); if(en_lst || de_lst) { if(optind != (argc - 1)) usage(arg0); cmd.cmd = (en_lst? CTRL_EN_LSTN: CTRL_DE_LSTN); cmd.listener = atoi(argv[optind++]); } if(en_svc || de_svc) { if(optind != (argc - 2)) usage(arg0); cmd.cmd = (en_svc? CTRL_EN_SVC: CTRL_DE_SVC); cmd.listener = atoi(argv[optind++]); cmd.service = atoi(argv[optind++]); } if(en_be || de_be) { if(optind != (argc - 3)) usage(arg0); cmd.cmd = (en_be? CTRL_EN_BE: CTRL_DE_BE); cmd.listener = atoi(argv[optind++]); cmd.service = atoi(argv[optind++]); cmd.backend = atoi(argv[optind++]); } if(a_sess) { if(optind != (argc - 4)) usage(arg0); cmd.cmd = CTRL_ADD_SESS; cmd.listener = atoi(argv[optind++]); cmd.service = atoi(argv[optind++]); memset(cmd.key, 0, KEY_SIZE + 1); strncpy(cmd.key, argv[optind++], KEY_SIZE); cmd.backend = atoi(argv[optind++]); } if(d_sess) { if(optind != (argc - 3)) usage(arg0); cmd.cmd = CTRL_DEL_SESS; cmd.listener = atoi(argv[optind++]); cmd.service = atoi(argv[optind++]); strncpy(cmd.key, argv[optind++], KEY_SIZE); } if(!is_set) { if(optind != argc) usage(arg0); cmd.cmd = CTRL_LST; } sock = get_sock(sock_name); write(sock, &cmd, sizeof(cmd)); if (!is_set) { int n; n_lstn = 0; if(xml_out) printf("\n"); if(read(sock, &n, sizeof(n)) == sizeof(n)) if(xml_out) printf("\n", n); else printf("Requests in queue: %d\n", n); while(read(sock, (void *)&lstn, sizeof(LISTENER)) == sizeof(LISTENER)) { if(lstn.disabled < 0) break; read(sock, &a, lstn.addr.ai_addrlen); lstn.addr.ai_addr = (struct sockaddr *)&a; if(xml_out) printf("\n", n_lstn++, lstn.ctx? "HTTPS": "http", prt_addr(&lstn.addr), lstn.disabled? "DISABLED": "active"); else printf("%3d. %s Listener %s %s\n", n_lstn++, lstn.ctx? "HTTPS" : "http", prt_addr(&lstn.addr), lstn.disabled? "*D": "a"); svc_prt(sock); if(xml_out) printf("\n"); } if(!xml_out) printf(" -1. Global services\n"); svc_prt(sock); if(xml_out) printf("\n"); } return 0; } Pound-2.8/pound.h0000644000175000017500000003764413275266545013023 0ustar rosegroseg/* * Pound - the reverse-proxy load-balancer * Copyright (C) 2002-2010 Apsis GmbH * * This file is part of Pound. * * Pound is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * Pound is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * Contact information: * Apsis GmbH * P.O.Box * 8707 Uetikon am See * Switzerland * EMail: roseg@apsis.ch */ #include "config.h" #include #include #if HAVE_STDLIB_H #include #else #error "Pound needs stdlib.h" #endif #if HAVE_UNISTD_H #include #else #error "Pound needs unistd.h" #endif #if HAVE_GETOPT_H #include #endif #if HAVE_PTHREAD_H #include #else #error "Pound needs pthread.h" #endif #if HAVE_STRING_H #include #else #error "Pound needs string.h" #endif #if TIME_WITH_SYS_TIME #if HAVE_SYS_TIME_H #include #else #error "Pound needs sys/time.h" #endif #if HAVE_TIME_H #include #else #error "Pound needs time.h" #endif #else /* may not mix sys/time.h and time.h */ #if HAVE_SYS_TIME_H #include #elif HAVE_TIME_H #include #else #error "Pound needs time.h" #endif #endif /* mix */ #if HAVE_SYS_TYPES_H #include #else #error "Pound needs sys/types.h" #endif #if HAVE_SYS_SOCKET_H #include #else #error "Pound needs sys/socket.h" #endif #if HAVE_SYS_UN_H #include #else #error "Pound needs sys/un.h" #endif #ifndef UNIX_PATH_MAX /* on Linux this is defined in linux/un.h rather than sys/un.h - go figure */ #define UNIX_PATH_MAX 108 #endif #if HAVE_NETINET_IN_H #include #else #error "Pound needs netinet/in.h" #endif #if HAVE_NETINET_TCP_H #include #else #error "Pound needs netinet/tcp.h" #endif #if HAVE_ARPA_INET_H #include #else #error "Pound needs arpa/inet.h" #endif #if HAVE_NETDB_H #include #else #error "Pound needs netdb.h" #endif #if HAVE_SYS_POLL_H #include #else #error "Pound needs sys/poll.h" #endif #if HAVE_OPENSSL_SSL_H #define OPENSSL_THREAD_DEFINES #include #include #include #if OPENSSL_VERSION_NUMBER >= 0x00907000L #ifndef OPENSSL_THREADS #error "Pound requires OpenSSL with thread support" #endif #else #ifndef THREADS #error "Pound requires OpenSSL with thread support" #endif #endif #else #error "Pound needs openssl/ssl.h" #endif #if HAVE_OPENSSL_ENGINE_H #include #endif #if HAVE_PWD_H #include #else #error "Pound needs pwd.h" #endif #if HAVE_GRP_H #include #else #error "Pound needs grp.h" #endif #if HAVE_SYSLOG_H #include #endif #if HAVE_SYS_SYSLOG_H #include #endif #if HAVE_SIGNAL_H #include #else #error "Pound needs signal.h" #endif #if HAVE_LIBPCREPOSIX #if HAVE_PCREPOSIX_H #include #elif HAVE_PCRE_PCREPOSIX_H #include #else #error "You have libpcreposix, but the header files are missing. Use --disable-pcreposix" #endif #elif HAVE_REGEX_H #include #else #error "Pound needs regex.h" #endif #if HAVE_CTYPE_H #include #else #error "Pound needs ctype.h" #endif #if HAVE_ERRNO_H #include #else #error "Pound needs errno.h" #endif #if HAVE_WAIT_H #include #elif HAVE_SYS_WAIT_H #include #else #error "Pound needs sys/wait.h" #endif #if HAVE_SYS_STAT_H #include #else #error "Pound needs sys/stat.h" #endif #if HAVE_FCNTL_H #include #else #error "Pound needs fcntl.h" #endif #if HAVE_STDARG_H #include #else #include #endif #if HAVE_FNMATCH_H #include #else #error "Pound needs fnmatch.h" #endif #ifndef __STDC__ #define const #endif #ifdef HAVE_LONG_LONG_INT #define LONG long long #define L0 0LL #define L_1 -1LL #define STRTOL strtoll #define ATOL atoll #else #define LONG long #define L0 0L #define L_1 -1L #define STRTOL strtol #define ATOL atol #endif #ifndef NO_EXTERNALS /* * Global variables needed by everybody */ extern char *user, /* user to run as */ *group, /* group to run as */ *root_jail, /* directory to chroot to */ *pid_name, /* file to record pid in */ *ctrl_name; /* control socket name */ extern int numthreads, /* number of worker threads */ anonymise, /* anonymise client address */ alive_to, /* check interval for resurrection */ daemonize, /* run as daemon */ log_facility, /* log facility to use */ print_log, /* print log messages to stdout/stderr */ grace, /* grace period before shutdown */ control_sock; /* control socket */ extern regex_t HEADER, /* Allowed header */ CHUNK_HEAD, /* chunk header line */ RESP_SKIP, /* responses for which we skip response */ RESP_IGN, /* responses for which we ignore content */ LOCATION, /* the host we are redirected to */ AUTHORIZATION; /* the Authorisation header */ #ifndef SOL_TCP /* for systems without the definition */ extern int SOL_TCP; #endif #endif /* NO_EXTERNALS */ #ifndef MAXBUF #define MAXBUF 4096 #endif #define MAXHEADERS 128 #ifndef F_CONF #define F_CONF "/usr/local/etc/pound.cfg" #endif #ifndef F_PID #define F_PID "/var/run/pound.pid" #endif /* matcher chain */ typedef struct _matcher { regex_t pat; /* pattern to match the request/header against */ struct _matcher *next; } MATCHER; /* back-end types */ typedef enum { SESS_NONE, SESS_IP, SESS_COOKIE, SESS_URL, SESS_PARM, SESS_HEADER, SESS_BASIC } SESS_TYPE; /* back-end definition */ typedef struct _backend { int be_type; /* 0 if real back-end, otherwise code (301, 302/default, 307) */ struct addrinfo addr; /* IPv4/6 address */ int priority; /* priority */ int to; /* read/write time-out */ int conn_to; /* connection time-out */ struct addrinfo ha_addr; /* HA address/port */ char *url; /* for redirectors */ int redir_req; /* the redirect should include the request path */ SSL_CTX *ctx; /* CTX for SSL connections */ pthread_mutex_t mut; /* mutex for this back-end */ int n_requests; /* number of requests seen */ double t_requests; /* time to answer these requests */ double t_average; /* average time to answer requests */ int alive; /* false if the back-end is dead */ int resurrect; /* this back-end is to be resurrected */ int disabled; /* true if the back-end is disabled */ struct _backend *next; } BACKEND; typedef struct _tn { char *key; void *content; time_t last_acc; } TABNODE; #define n_children(N) ((N)? (N)->children: 0) /* maximal session key size */ #define KEY_SIZE 127 #if OPENSSL_VERSION_NUMBER >= 0x10000000L DECLARE_LHASH_OF(TABNODE); #endif /* service definition */ typedef struct _service { char name[KEY_SIZE + 1]; /* symbolic name */ MATCHER *url, /* request matcher */ *req_head, /* required headers */ *deny_head; /* forbidden headers */ BACKEND *backends; BACKEND *emergency; int abs_pri; /* abs total priority for all back-ends */ int tot_pri; /* total priority for current back-ends */ pthread_mutex_t mut; /* mutex for this service */ SESS_TYPE sess_type; int sess_ttl; /* session time-to-live */ regex_t sess_start; /* pattern to identify the session data */ regex_t sess_pat; /* pattern to match the session data */ #if OPENSSL_VERSION_NUMBER >= 0x10000000L LHASH_OF(TABNODE) *sessions; /* currently active sessions */ #else LHASH *sessions; /* currently active sessions */ #endif int disabled; /* true if the service is disabled */ struct _service *next; } SERVICE; #ifndef NO_EXTERNALS extern SERVICE *services; /* global services (if any) */ #endif /* NO_EXTERNALS */ typedef struct _pound_ctx { SSL_CTX *ctx; char *server_name; unsigned char **subjectAltNames; unsigned int subjectAltNameCount; struct _pound_ctx *next; } POUND_CTX; /* Listener definition */ typedef struct _listener { struct addrinfo addr; /* IPv4/6 address */ int sock; /* listening socket */ POUND_CTX *ctx; /* CTX for SSL connections */ int clnt_check; /* client verification mode */ int noHTTPS11; /* HTTP 1.1 mode for SSL */ char *add_head; /* extra SSL header */ regex_t verb; /* pattern to match the request verb against */ int to; /* client time-out */ int has_pat; /* was a URL pattern defined? */ regex_t url_pat; /* pattern to match the request URL against */ char *err414, /* error messages */ *err500, *err501, *err503; LONG max_req; /* max. request size */ MATCHER *head_off; /* headers to remove */ int rewr_loc; /* rewrite location response */ int rewr_dest; /* rewrite destination header */ int disabled; /* true if the listener is disabled */ int log_level; /* log level for this listener */ int allow_client_reneg; /* Allow Client SSL Renegotiation */ int disable_ssl_v2; /* Disable SSL version 2 */ SERVICE *services; struct _listener *next; } LISTENER; #ifndef NO_EXTERNALS extern LISTENER *listeners; /* all available listeners */ #endif /* NO_EXTERNALS */ typedef struct _thr_arg { int sock; LISTENER *lstn; struct addrinfo from_host; struct _thr_arg *next; } thr_arg; /* argument to processing threads: socket, origin */ /* Track SSL handshare/renegotiation so we can reject client-renegotiations. */ typedef enum { RENEG_INIT=0, RENEG_REJECT, RENEG_ALLOW, RENEG_ABORT } RENEG_STATE; /* Header types */ #define HEADER_ILLEGAL -1 #define HEADER_OTHER 0 #define HEADER_TRANSFER_ENCODING 1 #define HEADER_CONTENT_LENGTH 2 #define HEADER_CONNECTION 3 #define HEADER_LOCATION 4 #define HEADER_CONTLOCATION 5 #define HEADER_HOST 6 #define HEADER_REFERER 7 #define HEADER_USER_AGENT 8 #define HEADER_URI 9 #define HEADER_DESTINATION 10 #define HEADER_EXPECT 11 /* control request stuff */ typedef enum { CTRL_LST, CTRL_EN_LSTN, CTRL_DE_LSTN, CTRL_EN_SVC, CTRL_DE_SVC, CTRL_EN_BE, CTRL_DE_BE, CTRL_ADD_SESS, CTRL_DEL_SESS } CTRL_CODE; typedef struct { CTRL_CODE cmd; int listener; int service; int backend; char key[KEY_SIZE + 1]; } CTRL_CMD; #ifdef NEED_INADDRT /* for oldish Unices - normally this is in /usr/include/netinet/in.h */ typedef u_int32_t in_addr_t; #endif #ifdef NEED_INPORTT /* for oldish Unices - normally this is in /usr/include/netinet/in.h */ typedef u_int16_t in_port_t; #endif #ifdef NEED_TIMET /* for oldish Unices - normally this is in /usr/include/time.h */ typedef u_int32_t time_t; #endif /* * add a request to the queue */ extern int put_thr_arg(thr_arg *); /* * get a request from the queue */ extern thr_arg *get_thr_arg(void); /* * get the current queue length */ extern int get_thr_qlen(void); /* * handle an HTTP request */ extern void *thr_http(void *); /* * Log an error to the syslog or to stderr */ extern void logmsg(const int, const char *, ...); /* * Parse a URL, possibly decoding hexadecimal-encoded characters */ extern int cpURL(char *, char *, int); /* * Translate inet/inet6 address into a string */ extern void addr2str(char *, const int, const struct addrinfo *, const int); /* * Return a string representation for a back-end address */ #define str_be(BUF, LEN, BE) addr2str((BUF), (LEN), &(BE)->addr, 0) /* * Find the right service for a request */ extern SERVICE *get_service(const LISTENER *, const char *, char **const); /* * Find the right back-end for a request */ extern BACKEND *get_backend(SERVICE *const, const struct addrinfo *, const char *, char **const); /* * Search for a host name, return the addrinfo for it */ extern int get_host(char *const, struct addrinfo *, int); /* * Find if a redirect needs rewriting * In general we have two possibilities that require it: * (1) if the redirect was done to the correct location with the wrong protocol * (2) if the redirect was done to the back-end rather than the listener */ extern int need_rewrite(const int, char *const, char *const, const char *, const LISTENER *, const BACKEND *); /* * (for cookies only) possibly create session based on response headers */ extern void upd_session(SERVICE *const, char **const, BACKEND *const); /* * Parse a header */ extern int check_header(const char *, char *); #define BE_DISABLE -1 #define BE_KILL 1 #define BE_ENABLE 0 /* * mark a backend host as dead; * do nothing if no resurection code is active */ extern void kill_be(SERVICE *const, const BACKEND *, const int); /* * Update the number of requests and time to answer for a given back-end */ extern void upd_be(SERVICE *const svc, BACKEND *const be, const double); /* * Non-blocking version of connect(2). Does the same as connect(2) but * ensures it will time-out after a much shorter time period CONN_TO. */ extern int connect_nb(const int, const struct addrinfo *, const int); /* * Parse arguments/config file */ extern void config_parse(const int, char **const); /* * RSA ephemeral keys: how many and how often */ #define N_RSA_KEYS 11 #ifndef T_RSA_KEYS #define T_RSA_KEYS 7200 #endif /* * return a pre-generated RSA key */ extern RSA *RSA_tmp_callback(SSL *, int, int); /* * return a pre-generated RSA key */ extern DH *DH_tmp_callback(SSL *, int, int); /* * Renegotiation callback */ extern void SSLINFO_callback(const SSL *s, int where, int rc); /* * expiration stuff */ #ifndef EXPIRE_TO #define EXPIRE_TO 60 #endif #ifndef HOST_TO #define HOST_TO 300 #endif /* * initialise the timer functions: * - host_mut * - RSA_mut and keys */ extern void init_timer(void); /* * run timed functions: * - RSAgen every T_RSA_KEYS seconds * - resurrect every alive_to seconds * - expire every EXPIRE_TO seconds */ extern void *thr_timer(void *); /* * The controlling thread * listens to client requests and calls the appropriate functions */ extern void *thr_control(void *); Pound-2.8/config.h.in0000755000175000017500000001525113275266545013541 0ustar rosegroseg/* config.h.in. Generated from configure.in by autoheader. */ /* Define to 1 if you have the header file. */ #undef HAVE_ARPA_INET_H /* Define to 1 if you have the header file. */ #undef HAVE_CTYPE_H /* Define to 1 if you have the header file. */ #undef HAVE_ERRNO_H /* Define to 1 if you have the header file. */ #undef HAVE_FCNTL_H /* Define to 1 if you have the `long long' type. */ #undef HAVE_LONG_LONG_INT /* Define to 1 if you have the `fork' function. */ #undef HAVE_FORK /* Define to 1 if you have the `getaddrinfo' function. */ #undef HAVE_GETADDRINFO /* Define to 1 if you have the header file. */ #undef HAVE_GETOPT_H /* Define to 1 if you have the `gettimeofday' function. */ #undef HAVE_GETTIMEOFDAY /* Define to 1 if you have the header file. */ #undef HAVE_GRP_H /* Define to 1 if you have the `inet_ntop' function. */ #undef HAVE_INET_NTOP /* Define to 1 if you have the header file. */ #undef HAVE_INTTYPES_H /* Define to 1 if you have the `dl' library (-ldl). */ #undef HAVE_LIBDL /* Define if libpcreposix is available */ #undef HAVE_LIBPCREPOSIX /* Define to 1 if you have the `localtime_r' function. */ #undef HAVE_LOCALTIME_R /* Define to 1 if you have the header file. */ #undef HAVE_MEMORY_H /* Define to 1 if you have the `memset' function. */ #undef HAVE_MEMSET /* 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_OPENSSL_ENGINE_H /* Define to 1 if you have the header file. */ #undef HAVE_OPENSSL_SSL_H /* Define to 1 if you have the header file. */ #undef HAVE_PCREPOSIX_H /* Define to 1 if you have the header file. */ #undef HAVE_PCRE_PCREPOSIX_H /* Define to 1 if you have the `poll' function. */ #undef HAVE_POLL /* Define if you have POSIX threads libraries and header files. */ #undef HAVE_PTHREAD /* Define to 1 if you have the header file. */ #undef HAVE_PTHREAD_H /* Define to 1 if you have the header file. */ #undef HAVE_PWD_H /* Define to 1 if you have the `regcomp' function. */ #undef HAVE_REGCOMP /* Define to 1 if you have the header file. */ #undef HAVE_REGEX_H /* Define to 1 if you have the `setsid' function. */ #undef HAVE_SETSID /* Define to 1 if you have the header file. */ #undef HAVE_SIGNAL_H /* Define to 1 if you have the `socket' function. */ #undef HAVE_SOCKET /* Define to 1 if `stat' has the bug that it succeeds when given the zero-length file name argument. */ #undef HAVE_STAT_EMPTY_STRING_BUG /* Define to 1 if you have the header file. */ #undef HAVE_STDARG_H /* Define to 1 if you have the header file. */ #undef HAVE_STDINT_H /* Define to 1 if you have the header file. */ #undef HAVE_STDLIB_H /* Define to 1 if you have the `strcasecmp' function. */ #undef HAVE_STRCASECMP /* Define to 1 if you have the `strchr' function. */ #undef HAVE_STRCHR /* Define to 1 if you have the `strdup' function. */ #undef HAVE_STRDUP /* Define to 1 if you have the `strerror' function. */ #undef HAVE_STRERROR /* Define to 1 if you have the `strftime' function. */ #undef HAVE_STRFTIME /* Define to 1 if you have the header file. */ #undef HAVE_STRINGS_H /* Define to 1 if you have the header file. */ #undef HAVE_STRING_H /* Define to 1 if you have the `strncasecmp' function. */ #undef HAVE_STRNCASECMP /* Define to 1 if you have the `strspn' function. */ #undef HAVE_STRSPN /* Define to 1 if you have the `strtol' function. */ #undef HAVE_STRTOL /* Define to 1 if you have the header file. */ #undef HAVE_SYS_POLL_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_SELECT_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 /* Define to 1 if you have the header file. */ #undef HAVE_SYS_TIME_H /* 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 the header file. */ #undef HAVE_SYS_WAIT_H /* Define to 1 if you have the header file. */ #undef HAVE_TIME_H /* Define to 1 if you have the header file. */ #undef HAVE_UNISTD_H /* Define to 1 if you have the `vfork' function. */ #undef HAVE_VFORK /* Define to 1 if you have the header file. */ #undef HAVE_VFORK_H /* Define to 1 if you have the header file. */ #undef HAVE_WAIT_H /* Define to 1 if `fork' works. */ #undef HAVE_WORKING_FORK /* Define to 1 if `vfork' works. */ #undef HAVE_WORKING_VFORK /* Define to 1 if you have the `X509_STORE_set_flags' function. */ #undef HAVE_X509_STORE_SET_FLAGS /* Define to 1 if `lstat' dereferences a symlink specified with a trailing slash. */ #undef LSTAT_FOLLOWS_SLASHED_SYMLINK /* Define to the address where bug reports for this package should be sent. */ #undef PACKAGE_BUGREPORT /* Define to the full name of this package. */ #undef PACKAGE_NAME /* Define to the full name and version of this package. */ #undef PACKAGE_STRING /* Define to the one symbol short name of this package. */ #undef PACKAGE_TARNAME /* Define to the version of this package. */ #undef PACKAGE_VERSION /* Define to the necessary symbol if this constant uses a non-standard name on your system. */ #undef PTHREAD_CREATE_JOINABLE /* Define as the return type of signal handlers (`int' or `void'). */ #undef RETSIGTYPE /* Define to the type of arg 1 for `select'. */ #undef SELECT_TYPE_ARG1 /* Define to the type of args 2, 3 and 4 for `select'. */ #undef SELECT_TYPE_ARG234 /* Define to the type of arg 5 for `select'. */ #undef SELECT_TYPE_ARG5 /* Define to 1 if you have the ANSI C header files. */ #undef STDC_HEADERS /* Define to 1 if you can safely include both and . */ #undef TIME_WITH_SYS_TIME /* Define to 1 if you have the header file. */ #undef HAVE_FNMATCH_H /* Define to empty if `const' does not conform to ANSI C. */ #undef const /* Define to `int' if doesn't define. */ #undef gid_t /* Define to rpl_malloc if the replacement function should be used. */ #undef malloc /* Define to `int' if does not define. */ #undef pid_t /* Define to `int' if doesn't define. */ #undef uid_t /* Define as `fork' if `vfork' does not work. */ #undef vfork Pound-2.8/FAQ0000755000175000017500000003501113275266545012044 0ustar rosegrosegFREQUENTLY ASKED QUESTIONS 1. General ========== 1.1 Will Pound run my Web application? No. Pound is a proxy, not a Web server - it does not deliver content by itself. It is just the middle-man between a client and a server. 1.2 Will Pound make my server go faster? No. Pound is just a proxy - no caching of any kind takes place. Pound IS able to distribute requests between several back-end servers, thus allowing for faster overall response times, but it won't speed-up a single Web sever. 1.3 Will Pound make my server more secure? Probably yes. Pound has its own checks on the validity of HTTP requests and often catches malicious requests that are used to attack Web servers. 1.4 Can I use Pound to change/rewrite/redirect requests? No. Pound tries to be as transparent as possible - ideally a client should not be aware that there is anything between itself and the actual Web server. A limited form of redirect is available - see the man page. 1.5 Can I use Pound to deny certain requests? Yes. Pound has a rather good mechanism for classifying requests and it can deny/reject certain requests based on URL and/or header content. 2. Configuration, Compilation and Installation ============================================== 2.1 I try to compile and it fails on "needs OpenSSL with thread support" Pound is a multi-threaded program and it needs an OpenSSL library compiled with thread support (optional in the OpenSSL configuration and absent in some default installations, such as *BSD). If your default library does not support threads you must install a thread-enabled version. 2.2 Pound compiles correctly but crashes on *BSD On some of the newer versions of *BSD (FreeBSD 5.x, OpenBSD 3.x) the Pound autoconf may not correctly recognize the threading library. Add manually to the generated Makefile the option -DNEED_STACK in the CFLAGS. 2.3 I want to run Pound with daemon-tools but it goes to background You need to configure Pound for non-daemon operations: add "Daemon 0" to the config file. 2.4 Pound runs OK but some normal requests are rejected with "bad URL" Pound checks the requested URLs quite thoroughly and rejects malformed or illegal URLs - or at least illegal according to the RFCs. See the man page for details. 2.5 Pound runs OK but I get a "pthread_create" error message You may be hitting the system limit on the number of processes. On systems that implement threads as processes (as Linux does) you should make sure that the Pound process has permission to start a sufficient number of processes. In some rare cases you may be running into the system limit on the number of threads. Check your system details for the value of PTHREAD_THREADS_MAX. If needed you must recompile the threads library with a higher value. 2.6 What resources does Pound need/use? That depends very much on your system. On some systems, such as Linux and System V (AIX, HP-UX, etc), threads are implemented as processes, which means you must allow enough processes to run. On other systems, such as *BSD, where threads are implemented in user space (in-process), you should make sure that Pound can use sufficient memory for all the threads and that the process is allowed to use enough file descriptors (2 per active connection). Finally, on systems that implement threads natively, such as Solaris, you need to make sure that enough threads and open file descriptors are allowed. 2.7 Is NPTL supported? Theoretically Pound will work with any POSIX-compliant threads package. In practice some of the newer NPTL implementations still have some bugs. At least on Linux running Pound with LD_ASSUME_KERNEL=2.4.19 may be helpful. 3. Virtual Hosts ================ 3.1 How do I redirect specific virtual hosts to specific back-ends? Make the virtual host mandatory in the UrlGroup. For example, to have all requests to www.a.com go to 192.168.0.10 and all requests for www.b.com go to 192.168.0.20, define Service HeadRequire "Host:.*www.a.com.*" BackEnd Address 192.168.0.10 Port 80 End End Service HeadRequire "Host:.*www.b.com.*" BackEnd Address 192.168.0.20 Port 80 End End in your config file. 3.2 How do I redirect requests to specific back-ends based on the client address? You can do it easier via the packet filter you use. If you insist on having Pound do it use a combination of port redirection and separate instances of Pound for each port. For example, assume you want intranet clients (on 192.168.100.0/24) to use the server at 192.168.1.10 and external clients go to 192.168.1.20. Do the following: - redirect requests from 192.168.100.0/24 to port 8080 pf: rdr on rl0 from 192.168.100.0/24 to 192.168.100.1 port 80 \ -> localhost port 8080 netfilter: iptables -t nat -A PREROUTING -p tcp \ -s 192.168.100.0/24 --dport 80 -i eth0 -j DNAT \ --to localhost:8080 - redirect requests from anywhere else to port 8081 pf: rdr on rl0 from any to 192.168.100.1 port 80 \ -> localhost port 8081 netfilter: iptables -t nat -A PREROUTING -p tcp \ --dport 80 -i eth0 -j DNAT --to localhost:8081 - have a Pound listener on port 8080 and sending the requests to 192.168.1.10 - have a Pound listener on port 8081 and sending the requests to 192.168.1.20 3.3 What happens when my server replies with a redirect? Depending on configuration, Pound can watch for redirect replies from back-ends and change them to the correct address. In order for this to happen the following conditions must be met: - Pound has "Check30x 1" - the back-end replies with a redirect. The address of that URL resolves to the same address as the one Pound is listening on or the address of the back-end itself. This feature is commonly used when Pound serves as a HTTPS wrapper, as the backend redirect to "Location: http://x.y.com" is rewritten as "Location: https://x.y.com". 4. HTTPS ======== 4.1 Can I have Pound force HTTPS connections to certain URLs/back-ends? Yes - define a Service with a Redirect back-end. 4.2 How can I do virtual hosting with HTTPS? The simple answer is that neither you, nor anybody else can, due to a limitation of the HTTPS protocol. In its simplest form an HTTPS (SSL) connection goes through the following stages: - negotiation: the client contacts the server, receives a certificate from it, and negotiates the protocol details (cipher parameters, etc). - authentication: the client checks that the certificate received matches the server it wanted and validates that the certificate is correct as attested by some certificate authority. - request/response: normal HTTP, encrypted in transit. As you can see the certificate is sent before any request was received. Unfortunately, the first request specifies the virtual host that the client would like to talk to - and it may not match the server name in the certificate. 4.3 Pound does not start with message "can't read private key" The file you specify in the ListenHTTPS directive must contain both the server certificate and the private key to it in PEM format. See the man page for SSL_CTX_use_PrivateKey_file(3) for details. 4.4 How can a back-end know that the connection is via HTTPS? Pound can add a header for incoming requests indicating that they were received via HTTPS. See the details on AddHeader in the man page. 4.5 HTTPS connections fail when Pound runs chrooted The OpenSSL library requires access to /dev/urandom for its random seed. The normal device is not accessible in a jail root. You should add a link to the device to make it accessible. On Linux this would be: mknod /var/pound/dev/urandom c 1 9 assuming that /var/pound is the root jail. 4.6 How can I force a back-end to generate the correct URL with HTTPS There is no simple answer to this question - each server and application have their own way of doing things. If your server does not use absolute paths then all is well - things will run out of the box. However if some frames, images, links or a base tag are generated with an absolute path you must find a way to force the generation with https://. 4.7 How can I find out about the client certificate in my application? For requests via HTTPS connections Pound can add the details of the client certificate as headers to each and every request it passes to the back-end. See the details on HTTPSHeaders in the man page. 4.8 Can Pound use my crypto accelerator hardware? Pound supports the OpenSSL engine architecture. If your crypto card is supported by OpenSSL then it is supported by Pound. See the SSLEngine directive in the man page. 4.9 Can Pound use HTTPS back-end servers? Yes, but that is not always a very good idea. Such a setup would essentially make Pound into a "man-in-the-middle" program. Even worse, the certificates on the back-end would become meaningless - they are seen only by Pound. 5. Session tracking =================== 5.1 Can I have session tracking based on URL and/or Cookie? Pound can track sessions based on client IP address, a cookie, an URL parameter or BasicAuthentication. These options are mutually exclusive - only one of them can be used per UrlGroup. 5.2 When does a session expire? A session is kept for the specified number of seconds. If during this time no new request was received the session is discarded. 5.3 Does Pound create/track its own sessions? No. Pound does not add anything to the requests or the responses - it uses the tokens generated by the back-end servers exclusively. 6. Logging ========== 6.1 Can I use Webalizer on Pound log files? Yes. If you use LogLevel 3 or 4 Pound uses one of the standard log formats that are recognized by applications such as Webalizer. You will have to remove the time-stamp generated by the syslog - see cut(1) for details. 6.2 How do I log the original client address in the back-end log? Pound adds the X-Forwarded-for header with the original client address to every request. Use it for your logs on the back-end servers. 6.3 How can I separate the Pound log from other syslog messages? If you use the syslog facility you can configure it to send the pound messages to a separate file. You may want to separate by severity as well - normal log messages use LOG_INFO, everything else is not request information. See syslogd(8) for details on how to configure it. 6.4 How can I separate error messages from normal log messages? If you use syslog: normal requests are logged at LOG_INFO, everything else is higher. If you run without syslog: normal request logging to stdout, everything else to stderr. 6.5 Why does Pound not log anything when chrooted? On some systems you need access to /dev/log in order to use the syslog(8) facility. Create/link the device as needed in the root jail you use. 6.6 Why can't Pound log directly to a file? This is a security requirement. As things stand, Pound does not write at all to the disk. The existing tools - such as syslog - allow all the flexibility one could wish for. If you absolutely must you can try the patches from Shinji Tanaka (see http://www.hatena-inc.co.jp/~stanaka/pound/ for details). 7. WebDAV ========= 7.1 I compiled Pound with DAV support but it still rejects the requests You also need to define "WebDAV 1" in your config file, and (depending on your server or application) "xHTTP 1" as well. 7.3 Can I use Pound as a front-end for Subversion? Yes. You may have some problems with using it via HTTPS, but HTTP should work. 8. Zope ======= 8.1 What configurations is Pound most helpful for? If you have several servers running on top of a ZEO server, Pound will allow you to load-balance between them (BTW, this was the original motivation for developing Pound). Pound also makes for a very good, light-weight front-end for a single Zope - exposing the Zope Web-server directly on the big, bad Internet is not a very good idea. 8.2 Can I have virtual hosts in Zope without Apache? Yes. Despite persistent rumors, the Virtual Host Monster works perfectly well on its own (dark incantations at midnight under the shade of the cross-shaped oak branch are NOT required). All you need to do is to add a VHM in the Zope root, click on the Mappings tab and add whatever hosts you need. 8.3 Can I have HTTPS for Zope? Yes. Pound will happily pass SSL requests to Zope. You have three possible methods to force Zope to generate responses with the https:// prefix: - if all you need is a specific area to be accessible only through HTTPS you can add a SiteRoot with the correct name. - alternately the Pound distribution includes patches for z2.py that include a new -y flag for a "https://" port. - finally, for version 2.7 or later you can set it in zope.conf. 8.4 Can I force HTTPS for certain areas in Zope? Yes. Add a check for the SSL-specific headers in the dtml_header or whatever equivalent you use. See the details on HTTPSHeaders in the man page. 9. Miscellaneous/MS =================== 9.1 IE fails to connect to Pound via HTTPS Define the ciphers to be "ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP:+eNULL" in the config file. We have had reports of IE problems with other ciphers. 9.2 IE has big delays in getting replies from Pound Try a shorter Client timeout. IE uses exactly 4 sockets, and as long as they stay open it won't do anything else. A short Client value will force the socket(s) to be closed earlier, thus avoiding annoying waits. 9.3 I try to run MS OWA and Pound rejects the requests Make sure you configured Pound with --enable-msdav. Make sure you included "WebDAV 1" in the config file. Pray that MS would adhere to some known standard. Repeat as necessary. 9.4 How can I force OWA to accept HTTPS requests? Make sure to define AddHeader "Front-End-Https: on" in the config file. This will force OWA to generate the responses with the correct protocol. Pound-2.8/configure0000775000175000017500000061336013275266545013431 0ustar rosegroseg#! /bin/sh # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.69 for pound 2.8. # # Report bugs to . # # # Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. # # # This configure script is free software; the Free Software Foundation # gives unlimited permission to copy, distribute and modify it. ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi as_nl=' ' export as_nl # Printing a long string crashes Solaris 7 /usr/bin/printf. as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo # Prefer a ksh shell builtin over an external printf program on Solaris, # but without wasting forks for bash or zsh. if test -z "$BASH_VERSION$ZSH_VERSION" \ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='print -r --' as_echo_n='print -rn --' elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='printf %s\n' as_echo_n='printf %s' else if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' as_echo_n='/usr/ucb/echo -n' else as_echo_body='eval expr "X$1" : "X\\(.*\\)"' as_echo_n_body='eval arg=$1; case $arg in #( *"$as_nl"*) expr "X$arg" : "X\\(.*\\)$as_nl"; arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; esac; expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" ' export as_echo_n_body as_echo_n='sh -c $as_echo_n_body as_echo' fi export as_echo_body as_echo='sh -c $as_echo_body as_echo' fi # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. as_myself= case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # Unset variables that we do not need and which cause bugs (e.g. in # pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" # suppresses any "Segmentation fault" message there. '((' could # trigger a bug in pdksh 5.2.14. for as_var in BASH_ENV ENV MAIL MAILPATH do eval test x\${$as_var+set} = xset \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # CDPATH. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH # Use a proper internal environment variable to ensure we don't fall # into an infinite loop, continuously re-executing ourselves. if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then _as_can_reexec=no; export _as_can_reexec; # We cannot yet assume a decent shell, so we have to provide a # neutralization value for shells without unset; and this also # works around shells that cannot unset nonexistent variables. # Preserve -v and -x to the replacement shell. BASH_ENV=/dev/null ENV=/dev/null (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV case $- in # (((( *v*x* | *x*v* ) as_opts=-vx ;; *v* ) as_opts=-v ;; *x* ) as_opts=-x ;; * ) as_opts= ;; esac exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} # Admittedly, this is quite paranoid, since all the known shells bail # out after a failed `exec'. $as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 as_fn_exit 255 fi # We don't want this to propagate to other subprocesses. { _as_can_reexec=; unset _as_can_reexec;} if test "x$CONFIG_SHELL" = x; then as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which # is contrary to our usage. Disable this feature. alias -g '\${1+\"\$@\"}'='\"\$@\"' setopt NO_GLOB_SUBST else case \`(set -o) 2>/dev/null\` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi " as_required="as_fn_return () { (exit \$1); } as_fn_success () { as_fn_return 0; } as_fn_failure () { as_fn_return 1; } as_fn_ret_success () { return 0; } as_fn_ret_failure () { return 1; } exitcode=0 as_fn_success || { exitcode=1; echo as_fn_success failed.; } as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then : else exitcode=1; echo positional parameters were not saved. fi test x\$exitcode = x0 || exit 1 test -x / || exit 1" as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1 test \$(( 1 + 1 )) = 2 || exit 1" if (eval "$as_required") 2>/dev/null; then : as_have_required=yes else as_have_required=no fi if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then : else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR as_found=false for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. as_found=: case $as_dir in #( /*) for as_base in sh bash ksh sh5; do # Try only shells that exist, to save several forks. as_shell=$as_dir/$as_base if { test -f "$as_shell" || test -f "$as_shell.exe"; } && { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then : CONFIG_SHELL=$as_shell as_have_required=yes if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then : break 2 fi fi done;; esac as_found=false done $as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } && { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then : CONFIG_SHELL=$SHELL as_have_required=yes fi; } IFS=$as_save_IFS if test "x$CONFIG_SHELL" != x; then : export CONFIG_SHELL # We cannot yet assume a decent shell, so we have to provide a # neutralization value for shells without unset; and this also # works around shells that cannot unset nonexistent variables. # Preserve -v and -x to the replacement shell. BASH_ENV=/dev/null ENV=/dev/null (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV case $- in # (((( *v*x* | *x*v* ) as_opts=-vx ;; *v* ) as_opts=-v ;; *x* ) as_opts=-x ;; * ) as_opts= ;; esac exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} # Admittedly, this is quite paranoid, since all the known shells bail # out after a failed `exec'. $as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 exit 255 fi if test x$as_have_required = xno; then : $as_echo "$0: This script requires a shell more modern than all" $as_echo "$0: the shells that I found on your system." if test x${ZSH_VERSION+set} = xset ; then $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should" $as_echo "$0: be upgraded to zsh 4.3.4 or later." else $as_echo "$0: Please tell bug-autoconf@gnu.org and roseg@apsis.ch $0: about your system, including any error possibly output $0: before this message. Then install a modern shell, or $0: manually run the script under such a shell if you do $0: have one." fi exit 1 fi fi fi SHELL=${CONFIG_SHELL-/bin/sh} export SHELL # Unset more variables known to interfere with behavior of common tools. CLICOLOR_FORCE= GREP_OPTIONS= unset CLICOLOR_FORCE GREP_OPTIONS ## --------------------- ## ## M4sh Shell Functions. ## ## --------------------- ## # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" } # as_fn_mkdir_p # as_fn_executable_p FILE # ----------------------- # Test if FILE is an executable regular file. as_fn_executable_p () { test -f "$1" && test -x "$1" } # as_fn_executable_p # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : eval 'as_fn_append () { eval $1+=\$2 }' else as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : eval 'as_fn_arith () { as_val=$(( $* )) }' else as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith # as_fn_error STATUS ERROR [LINENO LOG_FD] # ---------------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with STATUS, using 1 if that was 0. as_fn_error () { as_status=$1; test $as_status -eq 0 && as_status=1 if test "$4"; then as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi $as_echo "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || $as_echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits as_lineno_1=$LINENO as_lineno_1a=$LINENO as_lineno_2=$LINENO as_lineno_2a=$LINENO eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-) sed -n ' p /[$]LINENO/= ' <$as_myself | sed ' s/[$]LINENO.*/&-/ t lineno b :lineno N :loop s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ t loop s/-\n.*// ' >$as_me.lineno && chmod +x "$as_me.lineno" || { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } # If we had to re-execute with $CONFIG_SHELL, we're ensured to have # already done that, so ensure we don't try to do so again and fall # in an infinite loop. This has already happened in practice. _as_can_reexec=no; export _as_can_reexec # Don't try to exec as it changes $[0], causing all sort of problems # (the dirname of $[0] is not the place where we might find the # original and so on. Autoconf is especially sensitive to this). . "./$as_me.lineno" # Exit status is that of the last command. exit } ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -pR'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -pR' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -pR' fi else as_ln_s='cp -pR' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi as_test_x='test -x' as_executable_p=as_fn_executable_p # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" test -n "$DJDIR" || exec 7<&0 &1 # Name of the host. # hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status, # so uname gets run too. ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` # # Initializations. # ac_default_prefix=/usr/local ac_clean_files= ac_config_libobj_dir=. LIBOBJS= cross_compiling=no subdirs= MFLAGS= MAKEFLAGS= # Identity of this package. PACKAGE_NAME='pound' PACKAGE_TARNAME='pound' PACKAGE_VERSION='2.8' PACKAGE_STRING='pound 2.8' PACKAGE_BUGREPORT='roseg@apsis.ch' PACKAGE_URL='' ac_unique_file="pound.c" ac_c_werror_flag= # Factoring default headers for most tests. ac_includes_default="\ #include #ifdef HAVE_SYS_TYPES_H # include #endif #ifdef HAVE_SYS_STAT_H # include #endif #ifdef STDC_HEADERS # include # include #else # ifdef HAVE_STDLIB_H # include # endif #endif #ifdef HAVE_STRING_H # if !defined STDC_HEADERS && defined HAVE_MEMORY_H # include # endif # include #endif #ifdef HAVE_STRINGS_H # include #endif #ifdef HAVE_INTTYPES_H # include #endif #ifdef HAVE_STDINT_H # include #endif #ifdef HAVE_UNISTD_H # include #endif" ac_subst_vars='LTLIBOBJS I_GRP I_OWNER LIBOBJS EGREP GREP CPP C_SUPER C_GROUP C_OWNER C_MAXBUF C_DH_LEN C_T_RSA C_SSL PTHREAD_CFLAGS PTHREAD_LIBS PTHREAD_CC acx_pthread_config target_os target_vendor target_cpu target host_os host_vendor host_cpu host build_os build_vendor build_cpu build INSTALL_DATA INSTALL_SCRIPT INSTALL_PROGRAM OBJEXT EXEEXT ac_ct_CC CPPFLAGS LDFLAGS CFLAGS CC target_alias host_alias build_alias LIBS ECHO_T ECHO_N ECHO_C DEFS mandir localedir libdir psdir pdfdir dvidir htmldir infodir docdir oldincludedir includedir runstatedir localstatedir sharedstatedir sysconfdir datadir datarootdir libexecdir sbindir bindir program_transform_name prefix exec_prefix PACKAGE_URL PACKAGE_BUGREPORT PACKAGE_STRING PACKAGE_VERSION PACKAGE_TARNAME PACKAGE_NAME PATH_SEPARATOR SHELL' ac_subst_files='' ac_user_opts=' enable_option_checking with_ssl with_t_rsa with_dh with_maxbuf with_owner with_group enable_super enable_pcreposix enable_tcmalloc enable_hoard ' ac_precious_vars='build_alias host_alias target_alias CC CFLAGS LDFLAGS LIBS CPPFLAGS CPP' # Initialize some variables set by options. ac_init_help= ac_init_version=false ac_unrecognized_opts= ac_unrecognized_sep= # The variables have the same names as the options, with # dashes changed to underlines. cache_file=/dev/null exec_prefix=NONE no_create= no_recursion= prefix=NONE program_prefix=NONE program_suffix=NONE program_transform_name=s,x,x, silent= site= srcdir= verbose= x_includes=NONE x_libraries=NONE # Installation directory options. # These are left unexpanded so users can "make install exec_prefix=/foo" # and all the variables that are supposed to be based on exec_prefix # by default will actually change. # Use braces instead of parens because sh, perl, etc. also accept them. # (The list follows the same order as the GNU Coding Standards.) bindir='${exec_prefix}/bin' sbindir='${exec_prefix}/sbin' libexecdir='${exec_prefix}/libexec' datarootdir='${prefix}/share' datadir='${datarootdir}' sysconfdir='${prefix}/etc' sharedstatedir='${prefix}/com' localstatedir='${prefix}/var' runstatedir='${localstatedir}/run' includedir='${prefix}/include' oldincludedir='/usr/include' docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' infodir='${datarootdir}/info' htmldir='${docdir}' dvidir='${docdir}' pdfdir='${docdir}' psdir='${docdir}' libdir='${exec_prefix}/lib' localedir='${datarootdir}/locale' mandir='${datarootdir}/man' ac_prev= ac_dashdash= for ac_option do # If the previous option needs an argument, assign it. if test -n "$ac_prev"; then eval $ac_prev=\$ac_option ac_prev= continue fi case $ac_option in *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; *=) ac_optarg= ;; *) ac_optarg=yes ;; esac # Accept the important Cygnus configure options, so we can diagnose typos. case $ac_dashdash$ac_option in --) ac_dashdash=yes ;; -bindir | --bindir | --bindi | --bind | --bin | --bi) ac_prev=bindir ;; -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) bindir=$ac_optarg ;; -build | --build | --buil | --bui | --bu) ac_prev=build_alias ;; -build=* | --build=* | --buil=* | --bui=* | --bu=*) build_alias=$ac_optarg ;; -cache-file | --cache-file | --cache-fil | --cache-fi \ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) ac_prev=cache_file ;; -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) cache_file=$ac_optarg ;; --config-cache | -C) cache_file=config.cache ;; -datadir | --datadir | --datadi | --datad) ac_prev=datadir ;; -datadir=* | --datadir=* | --datadi=* | --datad=*) datadir=$ac_optarg ;; -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ | --dataroo | --dataro | --datar) ac_prev=datarootdir ;; -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) datarootdir=$ac_optarg ;; -disable-* | --disable-*) ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid feature name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=no ;; -docdir | --docdir | --docdi | --doc | --do) ac_prev=docdir ;; -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) docdir=$ac_optarg ;; -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) ac_prev=dvidir ;; -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) dvidir=$ac_optarg ;; -enable-* | --enable-*) ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid feature name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=\$ac_optarg ;; -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ | --exec | --exe | --ex) ac_prev=exec_prefix ;; -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ | --exec=* | --exe=* | --ex=*) exec_prefix=$ac_optarg ;; -gas | --gas | --ga | --g) # Obsolete; use --with-gas. with_gas=yes ;; -help | --help | --hel | --he | -h) ac_init_help=long ;; -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) ac_init_help=recursive ;; -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) ac_init_help=short ;; -host | --host | --hos | --ho) ac_prev=host_alias ;; -host=* | --host=* | --hos=* | --ho=*) host_alias=$ac_optarg ;; -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) ac_prev=htmldir ;; -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ | --ht=*) htmldir=$ac_optarg ;; -includedir | --includedir | --includedi | --included | --include \ | --includ | --inclu | --incl | --inc) ac_prev=includedir ;; -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ | --includ=* | --inclu=* | --incl=* | --inc=*) includedir=$ac_optarg ;; -infodir | --infodir | --infodi | --infod | --info | --inf) ac_prev=infodir ;; -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) infodir=$ac_optarg ;; -libdir | --libdir | --libdi | --libd) ac_prev=libdir ;; -libdir=* | --libdir=* | --libdi=* | --libd=*) libdir=$ac_optarg ;; -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ | --libexe | --libex | --libe) ac_prev=libexecdir ;; -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ | --libexe=* | --libex=* | --libe=*) libexecdir=$ac_optarg ;; -localedir | --localedir | --localedi | --localed | --locale) ac_prev=localedir ;; -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) localedir=$ac_optarg ;; -localstatedir | --localstatedir | --localstatedi | --localstated \ | --localstate | --localstat | --localsta | --localst | --locals) ac_prev=localstatedir ;; -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) localstatedir=$ac_optarg ;; -mandir | --mandir | --mandi | --mand | --man | --ma | --m) ac_prev=mandir ;; -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) mandir=$ac_optarg ;; -nfp | --nfp | --nf) # Obsolete; use --without-fp. with_fp=no ;; -no-create | --no-create | --no-creat | --no-crea | --no-cre \ | --no-cr | --no-c | -n) no_create=yes ;; -no-recursion | --no-recursion | --no-recursio | --no-recursi \ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) no_recursion=yes ;; -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ | --oldin | --oldi | --old | --ol | --o) ac_prev=oldincludedir ;; -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) oldincludedir=$ac_optarg ;; -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) ac_prev=prefix ;; -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) prefix=$ac_optarg ;; -program-prefix | --program-prefix | --program-prefi | --program-pref \ | --program-pre | --program-pr | --program-p) ac_prev=program_prefix ;; -program-prefix=* | --program-prefix=* | --program-prefi=* \ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) program_prefix=$ac_optarg ;; -program-suffix | --program-suffix | --program-suffi | --program-suff \ | --program-suf | --program-su | --program-s) ac_prev=program_suffix ;; -program-suffix=* | --program-suffix=* | --program-suffi=* \ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) program_suffix=$ac_optarg ;; -program-transform-name | --program-transform-name \ | --program-transform-nam | --program-transform-na \ | --program-transform-n | --program-transform- \ | --program-transform | --program-transfor \ | --program-transfo | --program-transf \ | --program-trans | --program-tran \ | --progr-tra | --program-tr | --program-t) ac_prev=program_transform_name ;; -program-transform-name=* | --program-transform-name=* \ | --program-transform-nam=* | --program-transform-na=* \ | --program-transform-n=* | --program-transform-=* \ | --program-transform=* | --program-transfor=* \ | --program-transfo=* | --program-transf=* \ | --program-trans=* | --program-tran=* \ | --progr-tra=* | --program-tr=* | --program-t=*) program_transform_name=$ac_optarg ;; -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) ac_prev=pdfdir ;; -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) pdfdir=$ac_optarg ;; -psdir | --psdir | --psdi | --psd | --ps) ac_prev=psdir ;; -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) psdir=$ac_optarg ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) silent=yes ;; -runstatedir | --runstatedir | --runstatedi | --runstated \ | --runstate | --runstat | --runsta | --runst | --runs \ | --run | --ru | --r) ac_prev=runstatedir ;; -runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \ | --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \ | --run=* | --ru=* | --r=*) runstatedir=$ac_optarg ;; -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) ac_prev=sbindir ;; -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ | --sbi=* | --sb=*) sbindir=$ac_optarg ;; -sharedstatedir | --sharedstatedir | --sharedstatedi \ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ | --sharedst | --shareds | --shared | --share | --shar \ | --sha | --sh) ac_prev=sharedstatedir ;; -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ | --sha=* | --sh=*) sharedstatedir=$ac_optarg ;; -site | --site | --sit) ac_prev=site ;; -site=* | --site=* | --sit=*) site=$ac_optarg ;; -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) ac_prev=srcdir ;; -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) srcdir=$ac_optarg ;; -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ | --syscon | --sysco | --sysc | --sys | --sy) ac_prev=sysconfdir ;; -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) sysconfdir=$ac_optarg ;; -target | --target | --targe | --targ | --tar | --ta | --t) ac_prev=target_alias ;; -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) target_alias=$ac_optarg ;; -v | -verbose | --verbose | --verbos | --verbo | --verb) verbose=yes ;; -version | --version | --versio | --versi | --vers | -V) ac_init_version=: ;; -with-* | --with-*) ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid package name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=\$ac_optarg ;; -without-* | --without-*) ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid package name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=no ;; --x) # Obsolete; use --with-x. with_x=yes ;; -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ | --x-incl | --x-inc | --x-in | --x-i) ac_prev=x_includes ;; -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) x_includes=$ac_optarg ;; -x-libraries | --x-libraries | --x-librarie | --x-librari \ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) ac_prev=x_libraries ;; -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) x_libraries=$ac_optarg ;; -*) as_fn_error $? "unrecognized option: \`$ac_option' Try \`$0 --help' for more information" ;; *=*) ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` # Reject names that are not valid shell variable names. case $ac_envvar in #( '' | [0-9]* | *[!_$as_cr_alnum]* ) as_fn_error $? "invalid variable name: \`$ac_envvar'" ;; esac eval $ac_envvar=\$ac_optarg export $ac_envvar ;; *) # FIXME: should be removed in autoconf 3.0. $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2 expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2 : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}" ;; esac done if test -n "$ac_prev"; then ac_option=--`echo $ac_prev | sed 's/_/-/g'` as_fn_error $? "missing argument to $ac_option" fi if test -n "$ac_unrecognized_opts"; then case $enable_option_checking in no) ;; fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;; *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; esac fi # Check all directory arguments for consistency. for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ datadir sysconfdir sharedstatedir localstatedir includedir \ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ libdir localedir mandir runstatedir do eval ac_val=\$$ac_var # Remove trailing slashes. case $ac_val in */ ) ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` eval $ac_var=\$ac_val;; esac # Be sure to have absolute directory names. case $ac_val in [\\/$]* | ?:[\\/]* ) continue;; NONE | '' ) case $ac_var in *prefix ) continue;; esac;; esac as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val" done # There might be people who depend on the old broken behavior: `$host' # used to hold the argument of --host etc. # FIXME: To remove some day. build=$build_alias host=$host_alias target=$target_alias # FIXME: To remove some day. if test "x$host_alias" != x; then if test "x$build_alias" = x; then cross_compiling=maybe elif test "x$build_alias" != "x$host_alias"; then cross_compiling=yes fi fi ac_tool_prefix= test -n "$host_alias" && ac_tool_prefix=$host_alias- test "$silent" = yes && exec 6>/dev/null ac_pwd=`pwd` && test -n "$ac_pwd" && ac_ls_di=`ls -di .` && ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || as_fn_error $? "working directory cannot be determined" test "X$ac_ls_di" = "X$ac_pwd_ls_di" || as_fn_error $? "pwd does not report name of working directory" # Find the source files, if location was not specified. if test -z "$srcdir"; then ac_srcdir_defaulted=yes # Try the directory containing this script, then the parent directory. ac_confdir=`$as_dirname -- "$as_myself" || $as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_myself" : 'X\(//\)[^/]' \| \ X"$as_myself" : 'X\(//\)$' \| \ X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_myself" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` srcdir=$ac_confdir if test ! -r "$srcdir/$ac_unique_file"; then srcdir=.. fi else ac_srcdir_defaulted=no fi if test ! -r "$srcdir/$ac_unique_file"; then test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir" fi ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" ac_abs_confdir=`( cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg" pwd)` # When building in place, set srcdir=. if test "$ac_abs_confdir" = "$ac_pwd"; then srcdir=. fi # Remove unnecessary trailing slashes from srcdir. # Double slashes in file names in object file debugging info # mess up M-x gdb in Emacs. case $srcdir in */) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; esac for ac_var in $ac_precious_vars; do eval ac_env_${ac_var}_set=\${${ac_var}+set} eval ac_env_${ac_var}_value=\$${ac_var} eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} eval ac_cv_env_${ac_var}_value=\$${ac_var} done # # Report the --help message. # if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF \`configure' configures pound 2.8 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... To assign environment variables (e.g., CC, CFLAGS...), specify them as VAR=VALUE. See below for descriptions of some of the useful variables. Defaults for the options are specified in brackets. Configuration: -h, --help display this help and exit --help=short display options specific to this package --help=recursive display the short help of all the included packages -V, --version display version information and exit -q, --quiet, --silent do not print \`checking ...' messages --cache-file=FILE cache test results in FILE [disabled] -C, --config-cache alias for \`--cache-file=config.cache' -n, --no-create do not create output files --srcdir=DIR find the sources in DIR [configure dir or \`..'] Installation directories: --prefix=PREFIX install architecture-independent files in PREFIX [$ac_default_prefix] --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX [PREFIX] By default, \`make install' will install all the files in \`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify an installation prefix other than \`$ac_default_prefix' using \`--prefix', for instance \`--prefix=\$HOME'. For better control, use the options below. Fine tuning of the installation directories: --bindir=DIR user executables [EPREFIX/bin] --sbindir=DIR system admin executables [EPREFIX/sbin] --libexecdir=DIR program executables [EPREFIX/libexec] --sysconfdir=DIR read-only single-machine data [PREFIX/etc] --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] --localstatedir=DIR modifiable single-machine data [PREFIX/var] --runstatedir=DIR modifiable per-process data [LOCALSTATEDIR/run] --libdir=DIR object code libraries [EPREFIX/lib] --includedir=DIR C header files [PREFIX/include] --oldincludedir=DIR C header files for non-gcc [/usr/include] --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] --datadir=DIR read-only architecture-independent data [DATAROOTDIR] --infodir=DIR info documentation [DATAROOTDIR/info] --localedir=DIR locale-dependent data [DATAROOTDIR/locale] --mandir=DIR man documentation [DATAROOTDIR/man] --docdir=DIR documentation root [DATAROOTDIR/doc/pound] --htmldir=DIR html documentation [DOCDIR] --dvidir=DIR dvi documentation [DOCDIR] --pdfdir=DIR pdf documentation [DOCDIR] --psdir=DIR ps documentation [DOCDIR] _ACEOF cat <<\_ACEOF System types: --build=BUILD configure for building on BUILD [guessed] --host=HOST cross-compile to build programs to run on HOST [BUILD] --target=TARGET configure for building compilers for TARGET [HOST] _ACEOF fi if test -n "$ac_init_help"; then case $ac_init_help in short | recursive ) echo "Configuration of pound 2.8:";; esac cat <<\_ACEOF Optional Features: --disable-option-checking ignore unrecognized --enable/--with options --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) --enable-FEATURE[=ARG] include FEATURE [ARG=yes] --enable-super enable or disable running with supervisor process (default: enabled) --enable-pcreposix enable or disable using the pcreposix library (default: enabled if available) --enable-tcmalloc enable or disable using the tcmalloc library (default: enabled if available) --enable-hoard enable or disable using the hoard library (default: enabled if available and tcmalloc NOT available) Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) --with-ssl=directory location of OpenSSL package --with-t_rsa=nnn Time-out for RSA ephemeral keys generation --with-dh=nnn DH key length parameter (default: 2048, can set to 1024 --with-maxbuf=nnn Value of the MAXBUF parameter (default: 4096) --with-owner=name The account that will own the files installed by Pound --with-group=name The group that will own the files installed by Pound Some influential environment variables: CC C compiler command CFLAGS C compiler flags LDFLAGS linker flags, e.g. -L if you have libraries in a nonstandard directory LIBS libraries to pass to the linker, e.g. -l CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I if you have headers in a nonstandard directory CPP C preprocessor Use these variables to override the choices made by `configure' or to help it to find libraries and programs with nonstandard names/locations. Report bugs to . _ACEOF ac_status=$? fi if test "$ac_init_help" = "recursive"; then # If there are subdirs, report their specific --help. for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue test -d "$ac_dir" || { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || continue ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix cd "$ac_dir" || { ac_status=$?; continue; } # Check for guested configure. if test -f "$ac_srcdir/configure.gnu"; then echo && $SHELL "$ac_srcdir/configure.gnu" --help=recursive elif test -f "$ac_srcdir/configure"; then echo && $SHELL "$ac_srcdir/configure" --help=recursive else $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 fi || ac_status=$? cd "$ac_pwd" || { ac_status=$?; break; } done fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF pound configure 2.8 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. This configure script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. _ACEOF exit fi ## ------------------------ ## ## Autoconf initialization. ## ## ------------------------ ## # ac_fn_c_try_compile LINENO # -------------------------- # Try to compile conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_compile # ac_fn_c_try_link LINENO # ----------------------- # Try to link conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_link () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext conftest$ac_exeext if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || test -x conftest$ac_exeext }; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would # interfere with the next link command; also delete a directory that is # left behind by Apple's compiler. We do this before executing the actions. rm -rf conftest.dSYM conftest_ipa8_conftest.oo eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_link # ac_fn_c_try_cpp LINENO # ---------------------- # Try to preprocess conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_cpp () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if { { ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } > conftest.i && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_cpp # ac_fn_c_try_run LINENO # ---------------------- # Try to link conftest.$ac_ext, and return whether this succeeded. Assumes # that executables *can* be run. ac_fn_c_try_run () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { ac_try='./conftest$ac_exeext' { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; }; then : ac_retval=0 else $as_echo "$as_me: program exited with status $ac_status" >&5 $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=$ac_status fi rm -rf conftest.dSYM conftest_ipa8_conftest.oo eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_run # ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES # ------------------------------------------------------- # Tests whether HEADER exists, giving a warning if it cannot be compiled using # the include files in INCLUDES and setting the cache variable VAR # accordingly. ac_fn_c_check_header_mongrel () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if eval \${$3+:} false; then : { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } else # Is the header compilable? { $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5 $as_echo_n "checking $2 usability... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 #include <$2> _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_header_compiler=yes else ac_header_compiler=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5 $as_echo "$ac_header_compiler" >&6; } # Is the header present? { $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5 $as_echo_n "checking $2 presence... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include <$2> _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : ac_header_preproc=yes else ac_header_preproc=no fi rm -f conftest.err conftest.i conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5 $as_echo "$ac_header_preproc" >&6; } # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #(( yes:no: ) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5 $as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 $as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} ;; no:yes:* ) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5 $as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5 $as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5 $as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5 $as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 $as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} ( $as_echo "## ----------------------------- ## ## Report this to roseg@apsis.ch ## ## ----------------------------- ##" ) | sed "s/^/$as_me: WARNING: /" >&2 ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else eval "$3=\$ac_header_compiler" fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_header_mongrel # ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES # ------------------------------------------------------- # Tests whether HEADER exists and can be compiled using the include files in # INCLUDES, setting the cache variable VAR accordingly. ac_fn_c_check_header_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 #include <$2> _ACEOF if ac_fn_c_try_compile "$LINENO"; then : eval "$3=yes" else eval "$3=no" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_header_compile # ac_fn_c_check_type LINENO TYPE VAR INCLUDES # ------------------------------------------- # Tests whether TYPE exists after having included INCLUDES, setting cache # variable VAR accordingly. ac_fn_c_check_type () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else eval "$3=no" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main () { if (sizeof ($2)) return 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main () { if (sizeof (($2))) return 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : else eval "$3=yes" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_type # ac_fn_c_check_func LINENO FUNC VAR # ---------------------------------- # Tests whether FUNC exists, setting the cache variable VAR accordingly ac_fn_c_check_func () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Define $2 to an innocuous variant, in case declares $2. For example, HP-UX 11i declares gettimeofday. */ #define $2 innocuous_$2 /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $2 (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef $2 /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char $2 (); /* 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_$2 || defined __stub___$2 choke me #endif int main () { return $2 (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : eval "$3=yes" else eval "$3=no" fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_func cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. It was created by pound $as_me 2.8, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ _ACEOF exec 5>>config.log { cat <<_ASUNAME ## --------- ## ## Platform. ## ## --------- ## hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` uname -m = `(uname -m) 2>/dev/null || echo unknown` uname -r = `(uname -r) 2>/dev/null || echo unknown` uname -s = `(uname -s) 2>/dev/null || echo unknown` uname -v = `(uname -v) 2>/dev/null || echo unknown` /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` /bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` /bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` /usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` /bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` /bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` _ASUNAME as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. $as_echo "PATH: $as_dir" done IFS=$as_save_IFS } >&5 cat >&5 <<_ACEOF ## ----------- ## ## Core tests. ## ## ----------- ## _ACEOF # Keep a trace of the command line. # Strip out --no-create and --no-recursion so they do not pile up. # Strip out --silent because we don't want to record it for future runs. # Also quote any args containing shell meta-characters. # Make two passes to allow for proper duplicate-argument suppression. ac_configure_args= ac_configure_args0= ac_configure_args1= ac_must_keep_next=false for ac_pass in 1 2 do for ac_arg do case $ac_arg in -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) continue ;; *\'*) ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; esac case $ac_pass in 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; 2) as_fn_append ac_configure_args1 " '$ac_arg'" if test $ac_must_keep_next = true; then ac_must_keep_next=false # Got value, back to normal. else case $ac_arg in *=* | --config-cache | -C | -disable-* | --disable-* \ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ | -with-* | --with-* | -without-* | --without-* | --x) case "$ac_configure_args0 " in "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; esac ;; -* ) ac_must_keep_next=true ;; esac fi as_fn_append ac_configure_args " '$ac_arg'" ;; esac done done { ac_configure_args0=; unset ac_configure_args0;} { ac_configure_args1=; unset ac_configure_args1;} # When interrupted or exit'd, cleanup temporary files, and complete # config.log. We remove comments because anyway the quotes in there # would cause problems or look ugly. # WARNING: Use '\'' to represent an apostrophe within the trap. # WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. trap 'exit_status=$? # Save into config.log some information that might help in debugging. { echo $as_echo "## ---------------- ## ## Cache variables. ## ## ---------------- ##" echo # The following way of writing the cache mishandles newlines in values, ( for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( *${as_nl}ac_space=\ *) sed -n \ "s/'\''/'\''\\\\'\'''\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" ;; #( *) sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) echo $as_echo "## ----------------- ## ## Output variables. ## ## ----------------- ##" echo for ac_var in $ac_subst_vars do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac $as_echo "$ac_var='\''$ac_val'\''" done | sort echo if test -n "$ac_subst_files"; then $as_echo "## ------------------- ## ## File substitutions. ## ## ------------------- ##" echo for ac_var in $ac_subst_files do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac $as_echo "$ac_var='\''$ac_val'\''" done | sort echo fi if test -s confdefs.h; then $as_echo "## ----------- ## ## confdefs.h. ## ## ----------- ##" echo cat confdefs.h echo fi test "$ac_signal" != 0 && $as_echo "$as_me: caught signal $ac_signal" $as_echo "$as_me: exit $exit_status" } >&5 rm -f core *.core core.conftest.* && rm -f -r conftest* confdefs* conf$$* $ac_clean_files && exit $exit_status ' 0 for ac_signal in 1 2 13 15; do trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal done ac_signal=0 # confdefs.h avoids OS command line length limits that DEFS can exceed. rm -f -r conftest* confdefs.h $as_echo "/* confdefs.h */" > confdefs.h # Predefined preprocessor variables. cat >>confdefs.h <<_ACEOF #define PACKAGE_NAME "$PACKAGE_NAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_TARNAME "$PACKAGE_TARNAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_VERSION "$PACKAGE_VERSION" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_STRING "$PACKAGE_STRING" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_URL "$PACKAGE_URL" _ACEOF # Let the site file select an alternate cache file if it wants to. # Prefer an explicitly selected file to automatically selected ones. ac_site_file1=NONE ac_site_file2=NONE if test -n "$CONFIG_SITE"; then # We do not want a PATH search for config.site. case $CONFIG_SITE in #(( -*) ac_site_file1=./$CONFIG_SITE;; */*) ac_site_file1=$CONFIG_SITE;; *) ac_site_file1=./$CONFIG_SITE;; esac elif test "x$prefix" != xNONE; then ac_site_file1=$prefix/share/config.site ac_site_file2=$prefix/etc/config.site else ac_site_file1=$ac_default_prefix/share/config.site ac_site_file2=$ac_default_prefix/etc/config.site fi for ac_site_file in "$ac_site_file1" "$ac_site_file2" do test "x$ac_site_file" = xNONE && continue if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 $as_echo "$as_me: loading site script $ac_site_file" >&6;} sed 's/^/| /' "$ac_site_file" >&5 . "$ac_site_file" \ || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "failed to load site script $ac_site_file See \`config.log' for more details" "$LINENO" 5; } fi done if test -r "$cache_file"; then # Some versions of bash will fail to source /dev/null (special files # actually), so we avoid doing that. DJGPP emulates it as a regular file. if test /dev/null != "$cache_file" && test -f "$cache_file"; then { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 $as_echo "$as_me: loading cache $cache_file" >&6;} case $cache_file in [\\/]* | ?:[\\/]* ) . "$cache_file";; *) . "./$cache_file";; esac fi else { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 $as_echo "$as_me: creating cache $cache_file" >&6;} >$cache_file fi # Check that the precious variables saved in the cache have kept the same # value. ac_cache_corrupted=false for ac_var in $ac_precious_vars; do eval ac_old_set=\$ac_cv_env_${ac_var}_set eval ac_new_set=\$ac_env_${ac_var}_set eval ac_old_val=\$ac_cv_env_${ac_var}_value eval ac_new_val=\$ac_env_${ac_var}_value case $ac_old_set,$ac_new_set in set,) { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 $as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} ac_cache_corrupted=: ;; ,set) { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 $as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} ac_cache_corrupted=: ;; ,);; *) if test "x$ac_old_val" != "x$ac_new_val"; then # differences in whitespace do not lead to failure. ac_old_val_w=`echo x $ac_old_val` ac_new_val_w=`echo x $ac_new_val` if test "$ac_old_val_w" != "$ac_new_val_w"; then { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 $as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} ac_cache_corrupted=: else { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 $as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} eval $ac_var=\$ac_old_val fi { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 $as_echo "$as_me: former value: \`$ac_old_val'" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 $as_echo "$as_me: current value: \`$ac_new_val'" >&2;} fi;; esac # Pass precious variables to config.status. if test "$ac_new_set" = set; then case $ac_new_val in *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; *) ac_arg=$ac_var=$ac_new_val ;; esac case " $ac_configure_args " in *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. *) as_fn_append ac_configure_args " '$ac_arg'" ;; esac fi done if $ac_cache_corrupted; then { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 $as_echo "$as_me: error: changes in the environment can compromise the build" >&2;} as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 fi ## -------------------- ## ## Main body of script. ## ## -------------------- ## ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu ac_config_headers="$ac_config_headers config.h" # Checks for programs. ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. set dummy ${ac_tool_prefix}gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_CC"; then ac_ct_CC=$CC # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi else CC="$ac_cv_prog_CC" fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. set dummy ${ac_tool_prefix}cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi fi if test -z "$CC"; then # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else ac_prog_rejected=no as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then ac_prog_rejected=yes continue fi ac_cv_prog_CC="cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS if test $ac_prog_rejected = yes; then # We found a bogon in the path, so make sure we never use it. set dummy $ac_cv_prog_CC shift if test $# != 0; then # We chose a different compiler from the bogus one. # However, it has the same basename, so the bogon will be chosen # first if we set CC to just the basename; use the full file name. shift ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" fi fi fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then for ac_prog in cl.exe do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$CC" && break done fi if test -z "$CC"; then ac_ct_CC=$CC for ac_prog in cl.exe do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_CC" && break done if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi fi fi test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "no acceptable C compiler found in \$PATH See \`config.log' for more details" "$LINENO" 5; } # Provide some information about the compiler. $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 set X $ac_compile ac_compiler=$2 for ac_option in --version -v -V -qversion; do { { ac_try="$ac_compiler $ac_option >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compiler $ac_option >&5") 2>conftest.err ac_status=$? if test -s conftest.err; then sed '10a\ ... rest of stderr output deleted ... 10q' conftest.err >conftest.er1 cat conftest.er1 >&5 fi rm -f conftest.er1 conftest.err $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } done cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out" # Try to create an executable without -o first, disregard a.out. # It will help us diagnose broken compilers, and finding out an intuition # of exeext. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5 $as_echo_n "checking whether the C compiler works... " >&6; } ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` # The possible output files: ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*" ac_rmfiles= for ac_file in $ac_files do case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; * ) ac_rmfiles="$ac_rmfiles $ac_file";; esac done rm -f $ac_rmfiles if { { ac_try="$ac_link_default" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link_default") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. # So ignore a value of `no', otherwise this would lead to `EXEEXT = no' # in a Makefile. We should not override ac_cv_exeext if it was cached, # so that the user can short-circuit this test for compilers unknown to # Autoconf. for ac_file in $ac_files '' do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; [ab].out ) # We found the default executable, but exeext='' is most # certainly right. break;; *.* ) if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; then :; else ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` fi # We set ac_cv_exeext here because the later test for it is not # safe: cross compilers may not add the suffix if given an `-o' # argument, so we may need to know it at that point already. # Even if this section looks crufty: it has the advantage of # actually working. break;; * ) break;; esac done test "$ac_cv_exeext" = no && ac_cv_exeext= else ac_file='' fi if test -z "$ac_file"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error 77 "C compiler cannot create executables See \`config.log' for more details" "$LINENO" 5; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5 $as_echo_n "checking for C compiler default output file name... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5 $as_echo "$ac_file" >&6; } ac_exeext=$ac_cv_exeext rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out ac_clean_files=$ac_clean_files_save { $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5 $as_echo_n "checking for suffix of executables... " >&6; } if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : # If both `conftest.exe' and `conftest' are `present' (well, observable) # catch `conftest.exe'. For instance with Cygwin, `ls conftest' will # work properly (i.e., refer to `conftest.exe'), while it won't with # `rm'. for ac_file in conftest.exe conftest conftest.*; do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` break;; * ) break;; esac done else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot compute suffix of executables: cannot compile and link See \`config.log' for more details" "$LINENO" 5; } fi rm -f conftest conftest$ac_cv_exeext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 $as_echo "$ac_cv_exeext" >&6; } rm -f conftest.$ac_ext EXEEXT=$ac_cv_exeext ac_exeext=$EXEEXT cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { FILE *f = fopen ("conftest.out", "w"); return ferror (f) || fclose (f) != 0; ; return 0; } _ACEOF ac_clean_files="$ac_clean_files conftest.out" # Check that the compiler produces executables we can run. If not, either # the compiler is broken, or we cross compile. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5 $as_echo_n "checking whether we are cross compiling... " >&6; } if test "$cross_compiling" != yes; then { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } if { ac_try='./conftest$ac_cv_exeext' { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; }; then cross_compiling=no else if test "$cross_compiling" = maybe; then cross_compiling=yes else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot run C compiled programs. If you meant to cross compile, use \`--host'. See \`config.log' for more details" "$LINENO" 5; } fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5 $as_echo "$cross_compiling" >&6; } rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out ac_clean_files=$ac_clean_files_save { $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 $as_echo_n "checking for suffix of object files... " >&6; } if ${ac_cv_objext+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.o conftest.obj if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : for ac_file in conftest.o conftest.obj conftest.*; do test -f "$ac_file" || continue; case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;; *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` break;; esac done else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot compute suffix of object files: cannot compile See \`config.log' for more details" "$LINENO" 5; } fi rm -f conftest.$ac_cv_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5 $as_echo "$ac_cv_objext" >&6; } OBJEXT=$ac_cv_objext ac_objext=$OBJEXT { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 $as_echo_n "checking whether we are using the GNU C compiler... " >&6; } if ${ac_cv_c_compiler_gnu+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_compiler_gnu=yes else ac_compiler_gnu=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_c_compiler_gnu=$ac_compiler_gnu fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 $as_echo "$ac_cv_c_compiler_gnu" >&6; } if test $ac_compiler_gnu = yes; then GCC=yes else GCC= fi ac_test_CFLAGS=${CFLAGS+set} ac_save_CFLAGS=$CFLAGS { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 $as_echo_n "checking whether $CC accepts -g... " >&6; } if ${ac_cv_prog_cc_g+:} false; then : $as_echo_n "(cached) " >&6 else ac_save_c_werror_flag=$ac_c_werror_flag ac_c_werror_flag=yes ac_cv_prog_cc_g=no CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes else CFLAGS="" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : else ac_c_werror_flag=$ac_save_c_werror_flag CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_c_werror_flag=$ac_save_c_werror_flag fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 $as_echo "$ac_cv_prog_cc_g" >&6; } if test "$ac_test_CFLAGS" = set; then CFLAGS=$ac_save_CFLAGS elif test $ac_cv_prog_cc_g = yes; then if test "$GCC" = yes; then CFLAGS="-g -O2" else CFLAGS="-g" fi else if test "$GCC" = yes; then CFLAGS="-O2" else CFLAGS= fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 $as_echo_n "checking for $CC option to accept ISO C89... " >&6; } if ${ac_cv_prog_cc_c89+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_prog_cc_c89=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include struct stat; /* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ struct buf { int x; }; FILE * (*rcsopen) (struct buf *, struct stat *, int); static char *e (p, i) char **p; int i; { return p[i]; } static char *f (char * (*g) (char **, int), char **p, ...) { char *s; va_list v; va_start (v,p); s = g (p, va_arg (v,int)); va_end (v); return s; } /* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has function prototypes and stuff, but not '\xHH' hex character constants. These don't provoke an error unfortunately, instead are silently treated as 'x'. The following induces an error, until -std is added to get proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an array size at least. It's necessary to write '\x00'==0 to get something that's true only with -std. */ int osf4_cc_array ['\x00' == 0 ? 1 : -1]; /* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters inside strings and character constants. */ #define FOO(x) 'x' int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; int test (int i, double x); struct s1 {int (*f) (int a);}; struct s2 {int (*f) (double a);}; int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); int argc; char **argv; int main () { return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; ; return 0; } _ACEOF for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" do CC="$ac_save_CC $ac_arg" if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_c89=$ac_arg fi rm -f core conftest.err conftest.$ac_objext test "x$ac_cv_prog_cc_c89" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC fi # AC_CACHE_VAL case "x$ac_cv_prog_cc_c89" in x) { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 $as_echo "none needed" >&6; } ;; xno) { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 $as_echo "unsupported" >&6; } ;; *) CC="$CC $ac_cv_prog_cc_c89" { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 $as_echo "$ac_cv_prog_cc_c89" >&6; } ;; esac if test "x$ac_cv_prog_cc_c89" != xno; then : fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu # expand $ac_aux_dir to an absolute path am_aux_dir=`cd $ac_aux_dir && pwd` ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC understands -c and -o together" >&5 $as_echo_n "checking whether $CC understands -c and -o together... " >&6; } if ${am_cv_prog_cc_c_o+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF # Make sure it works both with $CC and with simple cc. # Following AC_PROG_CC_C_O, we do the test twice because some # compilers refuse to overwrite an existing .o file with -o, # though they will create one. am_cv_prog_cc_c_o=yes for am_i in 1 2; do if { echo "$as_me:$LINENO: $CC -c conftest.$ac_ext -o conftest2.$ac_objext" >&5 ($CC -c conftest.$ac_ext -o conftest2.$ac_objext) >&5 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } \ && test -f conftest2.$ac_objext; then : OK else am_cv_prog_cc_c_o=no break fi done rm -f core conftest* unset am_i fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_prog_cc_c_o" >&5 $as_echo "$am_cv_prog_cc_c_o" >&6; } if test "$am_cv_prog_cc_c_o" != yes; then # Losing compiler, so override with the script. # FIXME: It is wrong to rewrite CC. # But if we don't then we get into trouble of one sort or another. # A longer-term fix would be to have automake use am__CC in this case, # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)" CC="$am_aux_dir/compile $CC" fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu ac_aux_dir= for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do if test -f "$ac_dir/install-sh"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/install-sh -c" break elif test -f "$ac_dir/install.sh"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/install.sh -c" break elif test -f "$ac_dir/shtool"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/shtool install -c" break fi done if test -z "$ac_aux_dir"; then as_fn_error $? "cannot find install-sh, install.sh, or shtool in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" "$LINENO" 5 fi # These three variables are undocumented and unsupported, # and are intended to be withdrawn in a future Autoconf release. # They can cause serious problems if a builder's source tree is in a directory # whose full name contains unusual characters. ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var. ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var. ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. # Find a good install program. We prefer a C program (faster), # so one script is as good as another. But avoid the broken or # incompatible versions: # SysV /etc/install, /usr/sbin/install # SunOS /usr/etc/install # IRIX /sbin/install # AIX /bin/install # AmigaOS /C/install, which installs bootblocks on floppy discs # AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag # AFS /usr/afsws/bin/install, which mishandles nonexistent args # SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" # OS/2's system install, which has a completely different semantic # ./install, which can be erroneously created by make from ./install.sh. # Reject install programs that cannot install multiple files. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5 $as_echo_n "checking for a BSD-compatible install... " >&6; } if test -z "$INSTALL"; then if ${ac_cv_path_install+:} false; then : $as_echo_n "(cached) " >&6 else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. # Account for people who put trailing slashes in PATH elements. case $as_dir/ in #(( ./ | .// | /[cC]/* | \ /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ ?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \ /usr/ucb/* ) ;; *) # OSF1 and SCO ODT 3.0 have their own names for install. # Don't use installbsd from OSF since it installs stuff as root # by default. for ac_prog in ginstall scoinst install; do for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then if test $ac_prog = install && grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then # AIX install. It has an incompatible calling convention. : elif test $ac_prog = install && grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then # program-specific install script used by HP pwplus--don't use. : else rm -rf conftest.one conftest.two conftest.dir echo one > conftest.one echo two > conftest.two mkdir conftest.dir if "$as_dir/$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir" && test -s conftest.one && test -s conftest.two && test -s conftest.dir/conftest.one && test -s conftest.dir/conftest.two then ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" break 3 fi fi fi done done ;; esac done IFS=$as_save_IFS rm -rf conftest.one conftest.two conftest.dir fi if test "${ac_cv_path_install+set}" = set; then INSTALL=$ac_cv_path_install else # As a last resort, use the slow shell script. Don't cache a # value for INSTALL within a source directory, because that will # break other packages using the cache if that directory is # removed, or if the value is a relative name. INSTALL=$ac_install_sh fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5 $as_echo "$INSTALL" >&6; } # Use test -z because SunOS4 sh mishandles braces in ${var-val}. # It thinks the first close brace ends the variable substitution. test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}' test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' # Make sure we can run config.sub. $SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 || as_fn_error $? "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5 { $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5 $as_echo_n "checking build system type... " >&6; } if ${ac_cv_build+:} false; then : $as_echo_n "(cached) " >&6 else ac_build_alias=$build_alias test "x$ac_build_alias" = x && ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"` test "x$ac_build_alias" = x && as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5 ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` || as_fn_error $? "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5 fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5 $as_echo "$ac_cv_build" >&6; } case $ac_cv_build in *-*-*) ;; *) as_fn_error $? "invalid value of canonical build" "$LINENO" 5;; esac build=$ac_cv_build ac_save_IFS=$IFS; IFS='-' set x $ac_cv_build shift build_cpu=$1 build_vendor=$2 shift; shift # Remember, the first character of IFS is used to create $*, # except with old shells: build_os=$* IFS=$ac_save_IFS case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking host system type" >&5 $as_echo_n "checking host system type... " >&6; } if ${ac_cv_host+:} false; then : $as_echo_n "(cached) " >&6 else if test "x$host_alias" = x; then ac_cv_host=$ac_cv_build else ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` || as_fn_error $? "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5 fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5 $as_echo "$ac_cv_host" >&6; } case $ac_cv_host in *-*-*) ;; *) as_fn_error $? "invalid value of canonical host" "$LINENO" 5;; esac host=$ac_cv_host ac_save_IFS=$IFS; IFS='-' set x $ac_cv_host shift host_cpu=$1 host_vendor=$2 shift; shift # Remember, the first character of IFS is used to create $*, # except with old shells: host_os=$* IFS=$ac_save_IFS case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking target system type" >&5 $as_echo_n "checking target system type... " >&6; } if ${ac_cv_target+:} false; then : $as_echo_n "(cached) " >&6 else if test "x$target_alias" = x; then ac_cv_target=$ac_cv_host else ac_cv_target=`$SHELL "$ac_aux_dir/config.sub" $target_alias` || as_fn_error $? "$SHELL $ac_aux_dir/config.sub $target_alias failed" "$LINENO" 5 fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_target" >&5 $as_echo "$ac_cv_target" >&6; } case $ac_cv_target in *-*-*) ;; *) as_fn_error $? "invalid value of canonical target" "$LINENO" 5;; esac target=$ac_cv_target ac_save_IFS=$IFS; IFS='-' set x $ac_cv_target shift target_cpu=$1 target_vendor=$2 shift; shift # Remember, the first character of IFS is used to create $*, # except with old shells: target_os=$* IFS=$ac_save_IFS case $target_os in *\ *) target_os=`echo "$target_os" | sed 's/ /-/g'`;; esac # The aliases save the names the user supplied, while $host etc. # will get canonicalized. test -n "$target_alias" && test "$program_prefix$program_suffix$program_transform_name" = \ NONENONEs,x,x, && program_prefix=${target_alias}- # Pound - the reverse-proxy load-balancer # Copyright (C) 2002-2007 Apsis GmbH # # This file is part of Pound. # # Pound is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 3 of the License, or # (at your option) any later version. # # Pound is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # # Contact information: # Apsis GmbH # P.O.Box # 8707 Uetikon am See # Switzerland # Tel: +41-44-920 4904 # EMail: roseg@apsis.ch CPPFLAGS="${CPPFLAGS} -D_REENTRANT -D_THREAD_SAFE" # if the compiler is gcc, test which flags are supported if test "${CC}" = "gcc" then ac_c_werror_flag=yes { $as_echo "$as_me:${as_lineno-$LINENO}: checking gcc arguments" >&5 $as_echo_n "checking gcc arguments... " >&6; } save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS -Wstrict-prototypes" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int x; _ACEOF if ac_fn_c_try_compile "$LINENO"; then : else CFLAGS="$save_CFLAGS" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS -Wno-unused-result" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int x; _ACEOF if ac_fn_c_try_compile "$LINENO"; then : else CFLAGS="$save_CFLAGS" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS -pipe" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int x; _ACEOF if ac_fn_c_try_compile "$LINENO"; then : else CFLAGS="$save_CFLAGS" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CFLAGS" >&5 $as_echo "$CFLAGS" >&6; } ac_c_werror_flag="" fi { $as_echo "$as_me:${as_lineno-$LINENO}: *** Checking for threads library and/or flags ***" >&5 $as_echo "$as_me: *** Checking for threads library and/or flags ***" >&6;} ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu acx_pthread_ok=no # We used to check for pthread.h first, but this fails if pthread.h # requires special compiler flags (e.g. on True64 or Sequent). # It gets checked for in the link test anyway. # First of all, check if the user has set any of the PTHREAD_LIBS, # etcetera environment variables, and if threads linking works using # them: if test x"$PTHREAD_LIBS$PTHREAD_CFLAGS" != x; then save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $PTHREAD_CFLAGS" save_LIBS="$LIBS" LIBS="$PTHREAD_LIBS $LIBS" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_join in LIBS=$PTHREAD_LIBS with CFLAGS=$PTHREAD_CFLAGS" >&5 $as_echo_n "checking for pthread_join in LIBS=$PTHREAD_LIBS with CFLAGS=$PTHREAD_CFLAGS... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char pthread_join (); int main () { return pthread_join (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : acx_pthread_ok=yes fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $acx_pthread_ok" >&5 $as_echo "$acx_pthread_ok" >&6; } if test x"$acx_pthread_ok" = xno; then PTHREAD_LIBS="" PTHREAD_CFLAGS="" fi LIBS="$save_LIBS" CFLAGS="$save_CFLAGS" fi # We must check for the threads library under a number of different # names; the ordering is very important because some systems # (e.g. DEC) have both -lpthread and -lpthreads, where one of the # libraries is broken (non-POSIX). # Create a list of thread flags to try. Items starting with a "-" are # C compiler flags, and other items are library names, except for "none" # which indicates that we try without any flags at all, and "pthread-config" # which is a program returning the flags for the Pth emulation library. acx_pthread_flags="pthreads none -Kthread -kthread lthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config" # The ordering *is* (sometimes) important. Some notes on the # individual items follow: # pthreads: AIX (must check this before -lpthread) # none: in case threads are in libc; should be tried before -Kthread and # other compiler flags to prevent continual compiler warnings # -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h) # -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able) # lthread: LinuxThreads port on FreeBSD (also preferred to -pthread) # -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads) # -pthreads: Solaris/gcc # -mthreads: Mingw32/gcc, Lynx/gcc # -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it # doesn't hurt to check since this sometimes defines pthreads too; # also defines -D_REENTRANT) # pthread: Linux, etcetera # --thread-safe: KAI C++ # pthread-config: use pthread-config program (for GNU Pth library) case "${host_cpu}-${host_os}" in *solaris*) # On Solaris (at least, for some versions), libc contains stubbed # (non-functional) versions of the pthreads routines, so link-based # tests will erroneously succeed. (We need to link with -pthread or # -lpthread.) (The stubs are missing pthread_cleanup_push, or rather # a function called by this macro, so we could check for that, but # who knows whether they'll stub that too in a future libc.) So, # we'll just look for -pthreads and -lpthread first: acx_pthread_flags="-pthread -pthreads pthread -mt $acx_pthread_flags" ;; esac if test x"$acx_pthread_ok" = xno; then for flag in $acx_pthread_flags; do case $flag in none) { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether pthreads work without any flags" >&5 $as_echo_n "checking whether pthreads work without any flags... " >&6; } ;; -*) { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether pthreads work with $flag" >&5 $as_echo_n "checking whether pthreads work with $flag... " >&6; } PTHREAD_CFLAGS="$flag" ;; pthread-config) # Extract the first word of "pthread-config", so it can be a program name with args. set dummy pthread-config; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_acx_pthread_config+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$acx_pthread_config"; then ac_cv_prog_acx_pthread_config="$acx_pthread_config" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_acx_pthread_config="yes" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS test -z "$ac_cv_prog_acx_pthread_config" && ac_cv_prog_acx_pthread_config="no" fi fi acx_pthread_config=$ac_cv_prog_acx_pthread_config if test -n "$acx_pthread_config"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $acx_pthread_config" >&5 $as_echo "$acx_pthread_config" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test x"$acx_pthread_config" = xno; then continue; fi PTHREAD_CFLAGS="`pthread-config --cflags`" PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`" ;; *) { $as_echo "$as_me:${as_lineno-$LINENO}: checking for the pthreads library -l$flag" >&5 $as_echo_n "checking for the pthreads library -l$flag... " >&6; } PTHREAD_LIBS="-l$flag" ;; esac save_LIBS="$LIBS" save_CFLAGS="$CFLAGS" LIBS="$PTHREAD_LIBS $LIBS" CFLAGS="$CFLAGS $PTHREAD_CFLAGS" # Check for various functions. We must include pthread.h, # since some functions may be macros. (On the Sequent, we # need a special flag -Kthread to make this header compile.) # We check for pthread_join because it is in -lpthread on IRIX # while pthread_create is in libc. We check for pthread_attr_init # due to DEC craziness with -lpthreads. We check for # pthread_cleanup_push because it is one of the few pthread # functions on Solaris that doesn't have a non-functional libc stub. # We try pthread_create on general principles. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { pthread_t th; pthread_join(th, 0); pthread_attr_init(0); pthread_cleanup_push(0, 0); pthread_create(0,0,0,0); pthread_cleanup_pop(0); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : acx_pthread_ok=yes fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS="$save_LIBS" CFLAGS="$save_CFLAGS" { $as_echo "$as_me:${as_lineno-$LINENO}: result: $acx_pthread_ok" >&5 $as_echo "$acx_pthread_ok" >&6; } if test "x$acx_pthread_ok" = xyes; then break; fi PTHREAD_LIBS="" PTHREAD_CFLAGS="" done fi # Various other checks: if test "x$acx_pthread_ok" = xyes; then save_LIBS="$LIBS" LIBS="$PTHREAD_LIBS $LIBS" save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $PTHREAD_CFLAGS" # Detect AIX lossage: threads are created detached by default # and the JOINABLE attribute has a nonstandard name (UNDETACHED). { $as_echo "$as_me:${as_lineno-$LINENO}: checking for joinable pthread attribute" >&5 $as_echo_n "checking for joinable pthread attribute... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { int attr=PTHREAD_CREATE_JOINABLE; ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ok=PTHREAD_CREATE_JOINABLE else ok=unknown fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext if test x"$ok" = xunknown; then cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { int attr=PTHREAD_CREATE_UNDETACHED; ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ok=PTHREAD_CREATE_UNDETACHED else ok=unknown fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi if test x"$ok" != xPTHREAD_CREATE_JOINABLE; then $as_echo "#define PTHREAD_CREATE_JOINABLE \$ok" >>confdefs.h fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${ok}" >&5 $as_echo "${ok}" >&6; } if test x"$ok" = xunknown; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: we do not know how to create joinable pthreads" >&5 $as_echo "$as_me: WARNING: we do not know how to create joinable pthreads" >&2;} fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking if more special flags are required for pthreads" >&5 $as_echo_n "checking if more special flags are required for pthreads... " >&6; } flag=no case "${host_cpu}-${host_os}" in *-aix* | *-freebsd*) flag="-D_THREAD_SAFE";; *solaris* | *-osf* | *-hpux*) flag="-D_REENTRANT";; esac { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${flag}" >&5 $as_echo "${flag}" >&6; } if test "x$flag" != xno; then PTHREAD_CFLAGS="$flag $PTHREAD_CFLAGS" fi LIBS="$save_LIBS" CFLAGS="$save_CFLAGS" # More AIX lossage: must compile with cc_r # Extract the first word of "cc_r", so it can be a program name with args. set dummy cc_r; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_PTHREAD_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$PTHREAD_CC"; then ac_cv_prog_PTHREAD_CC="$PTHREAD_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_PTHREAD_CC="cc_r" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS test -z "$ac_cv_prog_PTHREAD_CC" && ac_cv_prog_PTHREAD_CC="${CC}" fi fi PTHREAD_CC=$ac_cv_prog_PTHREAD_CC if test -n "$PTHREAD_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PTHREAD_CC" >&5 $as_echo "$PTHREAD_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi else PTHREAD_CC="$CC" fi # Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND: if test x"$acx_pthread_ok" = xyes; then LIBS="$PTHREAD_LIBS $LIBS"; CFLAGS="$CFLAGS $PTHREAD_CFLAGS"; CC="$PTHREAD_CC"; LDFLAGS="${LDFLAGS} ${PTHREAD_CFLAGS}" : else acx_pthread_ok=no fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { $as_echo "$as_me:${as_lineno-$LINENO}: *** Parsing options ***" >&5 $as_echo "$as_me: *** Parsing options ***" >&6;} # Check whether --with-ssl was given. if test "${with_ssl+set}" = set; then : withval=$with_ssl; CPPFLAGS="-I${with_ssl}/include ${CPPFLAGS}"; LDFLAGS="-L${with_ssl}/lib ${LDFLAGS}"; C_SSL="${with_ssl}" else C_SSL="" fi # Check whether --with-t_rsa was given. if test "${with_t_rsa+set}" = set; then : withval=$with_t_rsa; CPPFLAGS="-DT_RSA_KEYS=${with_t_rsa} ${CPPFLAGS}"; C_T_RSA="${with_t_rsa}" else C_T_RSA="0" fi # Check whether --with-dh was given. if test "${with_dh+set}" = set; then : withval=$with_dh; CPPFLAGS="-DDH_LEN=${with_dh} ${CPPFLAGS}"; C_DH_LEN="${with_dh}" else CPPFLAGS="-DDH_LEN=2048 ${CPPFLAGS}"; C_DH_LEN="2048" fi # Check whether --with-maxbuf was given. if test "${with_maxbuf+set}" = set; then : withval=$with_maxbuf; CPPFLAGS="-DMAXBUF=${with_maxbuf} ${CPPFLAGS}"; C_MAXBUF="${with_maxbuf}" else C_MAXBUF="0" fi I_OWNER="" # Check whether --with-owner was given. if test "${with_owner+set}" = set; then : withval=$with_owner; I_OWNER="${with_owner}"; C_OWNER="${with_owner}" else C_OWNER="" fi I_GRP="" # Check whether --with-group was given. if test "${with_group+set}" = set; then : withval=$with_group; I_GRP="${with_group}"; C_GROUP="${with_group}" else C_GROUP="" fi # Check whether --enable-super was given. if test "${enable_super+set}" = set; then : enableval=$enable_super; test ${enableval} = "yes" && CFLAGS="${CFLAGS} -DUPER"; C_SUPER="1" else CFLAGS="${CFLAGS} -DUPER"; C_SUPER="0" fi # Check whether --enable-pcreposix was given. if test "${enable_pcreposix+set}" = set; then : enableval=$enable_pcreposix; C_PCREPOSIX=${enableval} else C_PCREPOSIX=yes fi # Check whether --enable-tcmalloc was given. if test "${enable_tcmalloc+set}" = set; then : enableval=$enable_tcmalloc; C_TCMALLOC=${enableval} else C_TCMALLOC=yes fi # Check whether --enable-hoard was given. if test "${enable_hoard+set}" = set; then : enableval=$enable_hoard; C_HOARD=${enableval} else C_HOARD=yes fi { $as_echo "$as_me:${as_lineno-$LINENO}: *** Checking for libraries ***" >&5 $as_echo "$as_me: *** Checking for libraries ***" >&6;} LIBS="${LIBS} -lm" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 $as_echo_n "checking for dlopen in -ldl... " >&6; } if ${ac_cv_lib_dl_dlopen+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldl $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dlopen (); int main () { return dlopen (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_dl_dlopen=yes else ac_cv_lib_dl_dlopen=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 $as_echo "$ac_cv_lib_dl_dlopen" >&6; } if test "x$ac_cv_lib_dl_dlopen" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBDL 1 _ACEOF LIBS="-ldl $LIBS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for socket in -lsocket" >&5 $as_echo_n "checking for socket in -lsocket... " >&6; } if ${ac_cv_lib_socket_socket+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lsocket $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char socket (); int main () { return socket (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_socket_socket=yes else ac_cv_lib_socket_socket=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_socket_socket" >&5 $as_echo "$ac_cv_lib_socket_socket" >&6; } if test "x$ac_cv_lib_socket_socket" = xyes; then : LIBS="-lsocket -lnsl ${LIBS}" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for hstrerror in -lresolv" >&5 $as_echo_n "checking for hstrerror in -lresolv... " >&6; } if ${ac_cv_lib_resolv_hstrerror+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lresolv $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char hstrerror (); int main () { return hstrerror (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_resolv_hstrerror=yes else ac_cv_lib_resolv_hstrerror=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_resolv_hstrerror" >&5 $as_echo "$ac_cv_lib_resolv_hstrerror" >&6; } if test "x$ac_cv_lib_resolv_hstrerror" = xyes; then : LIBS="-lresolv ${LIBS}" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for BIO_new in -lcrypto" >&5 $as_echo_n "checking for BIO_new in -lcrypto... " >&6; } if ${ac_cv_lib_crypto_BIO_new+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lcrypto $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char BIO_new (); int main () { return BIO_new (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_crypto_BIO_new=yes else ac_cv_lib_crypto_BIO_new=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_crypto_BIO_new" >&5 $as_echo "$ac_cv_lib_crypto_BIO_new" >&6; } if test "x$ac_cv_lib_crypto_BIO_new" = xyes; then : LIBS="-lcrypto ${LIBS}" else echo 'Missing OpenSSL (-lcrypto) - aborted'; exit 1 fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for SSL_CTX_new in -lssl" >&5 $as_echo_n "checking for SSL_CTX_new in -lssl... " >&6; } if ${ac_cv_lib_ssl_SSL_CTX_new+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lssl $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char SSL_CTX_new (); int main () { return SSL_CTX_new (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_ssl_SSL_CTX_new=yes else ac_cv_lib_ssl_SSL_CTX_new=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ssl_SSL_CTX_new" >&5 $as_echo "$ac_cv_lib_ssl_SSL_CTX_new" >&6; } if test "x$ac_cv_lib_ssl_SSL_CTX_new" = xyes; then : LIBS="-lssl ${LIBS}" else echo 'Missing OpenSSL (-lssl) - aborted'; exit 1 fi if test x"$C_PCREPOSIX" = xyes; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for regcomp in -lpcreposix" >&5 $as_echo_n "checking for regcomp in -lpcreposix... " >&6; } if ${ac_cv_lib_pcreposix_regcomp+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lpcreposix $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char regcomp (); int main () { return regcomp (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_pcreposix_regcomp=yes else ac_cv_lib_pcreposix_regcomp=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pcreposix_regcomp" >&5 $as_echo "$ac_cv_lib_pcreposix_regcomp" >&6; } if test "x$ac_cv_lib_pcreposix_regcomp" = xyes; then : LIBS="-lpcreposix ${LIBS}"; $as_echo "#define HAVE_LIBPCREPOSIX 1" >>confdefs.h else save_LIBS="$LIBS" LIBS="-lpcre $LIBS" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for regexec in -lpcreposix" >&5 $as_echo_n "checking for regexec in -lpcreposix... " >&6; } if ${ac_cv_lib_pcreposix_regexec+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lpcreposix $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char regexec (); int main () { return regexec (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_pcreposix_regexec=yes else ac_cv_lib_pcreposix_regexec=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pcreposix_regexec" >&5 $as_echo "$ac_cv_lib_pcreposix_regexec" >&6; } if test "x$ac_cv_lib_pcreposix_regexec" = xyes; then : LIBS="-lpcreposix -lpcre $save_LIBS"; $as_echo "#define HAVE_LIBPCREPOSIX 1" >>confdefs.h else LIBS="$save_LIBS" fi fi fi if test x"$C_TCMALLOC" = xyes; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for malloc in -ltcmalloc" >&5 $as_echo_n "checking for malloc in -ltcmalloc... " >&6; } if ${ac_cv_lib_tcmalloc_malloc+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ltcmalloc $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char malloc (); int main () { return malloc (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_tcmalloc_malloc=yes else ac_cv_lib_tcmalloc_malloc=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_tcmalloc_malloc" >&5 $as_echo "$ac_cv_lib_tcmalloc_malloc" >&6; } if test "x$ac_cv_lib_tcmalloc_malloc" = xyes; then : LIBS="${LIBS} -ltcmalloc" fi else if test x"$C_HOARD" = xyes; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for malloc in -lhoard" >&5 $as_echo_n "checking for malloc in -lhoard... " >&6; } if ${ac_cv_lib_hoard_malloc+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lhoard $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char malloc (); int main () { return malloc (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_hoard_malloc=yes else ac_cv_lib_hoard_malloc=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_hoard_malloc" >&5 $as_echo "$ac_cv_lib_hoard_malloc" >&6; } if test "x$ac_cv_lib_hoard_malloc" = xyes; then : LIBS="${LIBS} -lhoard" fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_attr_setstacksize in LIBS=$LIBS with CFLAGS=$CFLAGS" >&5 $as_echo_n "checking for pthread_attr_setstacksize in LIBS=$LIBS with CFLAGS=$CFLAGS... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char pthread_attr_setstacksize (); int main () { return pthread_attr_setstacksize (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : CFLAGS="${CFLAGS} -DNEED_STACK" fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: result: OK" >&5 $as_echo "OK" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: *** Checking for header files ***" >&5 $as_echo "$as_me: *** Checking for header files ***" >&6;} ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5 $as_echo_n "checking how to run the C preprocessor... " >&6; } # On Suns, sometimes $CPP names a directory. if test -n "$CPP" && test -d "$CPP"; then CPP= fi if test -z "$CPP"; then if ${ac_cv_prog_CPP+:} false; then : $as_echo_n "(cached) " >&6 else # Double quotes because CPP needs to be expanded for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" do ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : else # Broken: fails on valid input. continue fi rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : # Broken: success on invalid input. continue else # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.i conftest.err conftest.$ac_ext if $ac_preproc_ok; then : break fi done ac_cv_prog_CPP=$CPP fi CPP=$ac_cv_prog_CPP else ac_cv_prog_CPP=$CPP fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5 $as_echo "$CPP" >&6; } ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : else # Broken: fails on valid input. continue fi rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : # Broken: success on invalid input. continue else # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.i conftest.err conftest.$ac_ext if $ac_preproc_ok; then : else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "C preprocessor \"$CPP\" fails sanity check See \`config.log' for more details" "$LINENO" 5; } fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5 $as_echo_n "checking for grep that handles long lines and -e... " >&6; } if ${ac_cv_path_GREP+:} false; then : $as_echo_n "(cached) " >&6 else if test -z "$GREP"; then ac_path_GREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in grep ggrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_GREP" || continue # Check for GNU ac_path_GREP and select it if it is found. # Check for GNU $ac_path_GREP case `"$ac_path_GREP" --version 2>&1` in *GNU*) ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo 'GREP' >> "conftest.nl" "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_GREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_GREP_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_GREP"; then as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_GREP=$GREP fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5 $as_echo "$ac_cv_path_GREP" >&6; } GREP="$ac_cv_path_GREP" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5 $as_echo_n "checking for egrep... " >&6; } if ${ac_cv_path_EGREP+:} false; then : $as_echo_n "(cached) " >&6 else if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 then ac_cv_path_EGREP="$GREP -E" else if test -z "$EGREP"; then ac_path_EGREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in egrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_EGREP" || continue # Check for GNU ac_path_EGREP and select it if it is found. # Check for GNU $ac_path_EGREP case `"$ac_path_EGREP" --version 2>&1` in *GNU*) ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo 'EGREP' >> "conftest.nl" "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_EGREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_EGREP_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_EGREP"; then as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_EGREP=$EGREP fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5 $as_echo "$ac_cv_path_EGREP" >&6; } EGREP="$ac_cv_path_EGREP" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 $as_echo_n "checking for ANSI C header files... " >&6; } if ${ac_cv_header_stdc+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_header_stdc=yes else ac_cv_header_stdc=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext if test $ac_cv_header_stdc = yes; then # SunOS 4.x string.h does not declare mem*, contrary to ANSI. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "memchr" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "free" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. if test "$cross_compiling" = yes; then : : else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #if ((' ' & 0x0FF) == 0x020) # define ISLOWER(c) ('a' <= (c) && (c) <= 'z') # define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) #else # define ISLOWER(c) \ (('a' <= (c) && (c) <= 'i') \ || ('j' <= (c) && (c) <= 'r') \ || ('s' <= (c) && (c) <= 'z')) # define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) #endif #define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) int main () { int i; for (i = 0; i < 256; i++) if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) return 2; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : else ac_cv_header_stdc=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 $as_echo "$ac_cv_header_stdc" >&6; } if test $ac_cv_header_stdc = yes; then $as_echo "#define STDC_HEADERS 1" >>confdefs.h fi # On IRIX 5.3, sys/types and inttypes.h are conflicting. for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ inttypes.h stdint.h unistd.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default " if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done for ac_header in arpa/inet.h errno.h netdb.h netinet/in.h netinet/tcp.h stdlib.h string.h sys/socket.h sys/un.h sys/time.h unistd.h getopt.h pthread.h sys/types.h sys/poll.h openssl/ssl.h openssl/engine.h time.h pwd.h grp.h signal.h regex.h ctype.h wait.h sys/wait.h sys/stat.h fcntl.h stdarg.h pcreposix.h pcre/pcreposix.h fnmatch.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done { $as_echo "$as_me:${as_lineno-$LINENO}: *** Checking for additonal information ***" >&5 $as_echo "$as_me: *** Checking for additonal information ***" >&6;} save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS -DSYSLOG_NAMES=1" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for facilitynames presence" >&5 $as_echo_n "checking for facilitynames presence... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include int main () { void *attr=(void *)facilitynames; ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ok=yes else ok=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext if test x"$ok" = xyes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } CFLAGS="$save_CFLAGS -DHAVE_SYSLOG_H=1" else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include int main () { void *attr=(void *)facilitynames; ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ok=yes else ok=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext if test x"$ok" = xyes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } CFLAGS="$save_CFLAGS -DHAVE_SYS_SYSLOG_H=1" else { $as_echo "$as_me:${as_lineno-$LINENO}: result: missing" >&5 $as_echo "missing" >&6; } CFLAGS="$save_CFLAGS -DHAVE_SYSLOG_H=1 -DMISS_FACILITYNAMES" fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking return type of signal handlers" >&5 $as_echo_n "checking return type of signal handlers... " >&6; } if ${ac_cv_type_signal+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include int main () { return *(signal (0, 0)) (0) == 1; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_type_signal=int else ac_cv_type_signal=void fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_type_signal" >&5 $as_echo "$ac_cv_type_signal" >&6; } cat >>confdefs.h <<_ACEOF #define RETSIGTYPE $ac_cv_type_signal _ACEOF { $as_echo "$as_me:${as_lineno-$LINENO}: checking for an ANSI C-conforming const" >&5 $as_echo_n "checking for an ANSI C-conforming const... " >&6; } if ${ac_cv_c_const+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { #ifndef __cplusplus /* Ultrix mips cc rejects this sort of thing. */ typedef int charset[2]; const charset cs = { 0, 0 }; /* SunOS 4.1.1 cc rejects this. */ char const *const *pcpcc; char **ppc; /* NEC SVR4.0.2 mips cc rejects this. */ struct point {int x, y;}; static struct point const zero = {0,0}; /* AIX XL C 1.02.0.0 rejects this. It does not let you subtract one const X* pointer from another in an arm of an if-expression whose if-part is not a constant expression */ const char *g = "string"; pcpcc = &g + (g ? g-g : 0); /* HPUX 7.0 cc rejects these. */ ++pcpcc; ppc = (char**) pcpcc; pcpcc = (char const *const *) ppc; { /* SCO 3.2v4 cc rejects this sort of thing. */ char tx; char *t = &tx; char const *s = 0 ? (char *) 0 : (char const *) 0; *t++ = 0; if (s) return 0; } { /* Someone thinks the Sun supposedly-ANSI compiler will reject this. */ int x[] = {25, 17}; const int *foo = &x[0]; ++foo; } { /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */ typedef const int *iptr; iptr p = 0; ++p; } { /* AIX XL C 1.02.0.0 rejects this sort of thing, saying "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */ struct s { int j; const int *ap[3]; } bx; struct s *b = &bx; b->j = 5; } { /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */ const int foo = 10; if (!foo) return 0; } return !cs[0] && !zero.x; #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_c_const=yes else ac_cv_c_const=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_const" >&5 $as_echo "$ac_cv_c_const" >&6; } if test $ac_cv_c_const = no; then $as_echo "#define const /**/" >>confdefs.h fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for uid_t in sys/types.h" >&5 $as_echo_n "checking for uid_t in sys/types.h... " >&6; } if ${ac_cv_type_uid_t+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "uid_t" >/dev/null 2>&1; then : ac_cv_type_uid_t=yes else ac_cv_type_uid_t=no fi rm -f conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_type_uid_t" >&5 $as_echo "$ac_cv_type_uid_t" >&6; } if test $ac_cv_type_uid_t = no; then $as_echo "#define uid_t int" >>confdefs.h $as_echo "#define gid_t int" >>confdefs.h fi ac_fn_c_check_type "$LINENO" "pid_t" "ac_cv_type_pid_t" "$ac_includes_default" if test "x$ac_cv_type_pid_t" = xyes; then : else cat >>confdefs.h <<_ACEOF #define pid_t int _ACEOF fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether time.h and sys/time.h may both be included" >&5 $as_echo_n "checking whether time.h and sys/time.h may both be included... " >&6; } if ${ac_cv_header_time+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include int main () { if ((struct tm *) 0) return 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_header_time=yes else ac_cv_header_time=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_time" >&5 $as_echo "$ac_cv_header_time" >&6; } if test $ac_cv_header_time = yes; then $as_echo "#define TIME_WITH_SYS_TIME 1" >>confdefs.h fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for unsigned long long int" >&5 $as_echo_n "checking for unsigned long long int... " >&6; } if ${ac_cv_type_unsigned_long_long_int+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_type_unsigned_long_long_int=yes if test "x${ac_cv_prog_cc_c99-no}" = xno; then cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* For now, do not test the preprocessor; as of 2007 there are too many implementations with broken preprocessors. Perhaps this can be revisited in 2012. In the meantime, code should not expect #if to work with literals wider than 32 bits. */ /* Test literals. */ long long int ll = 9223372036854775807ll; long long int nll = -9223372036854775807LL; unsigned long long int ull = 18446744073709551615ULL; /* Test constant expressions. */ typedef int a[((-9223372036854775807LL < 0 && 0 < 9223372036854775807ll) ? 1 : -1)]; typedef int b[(18446744073709551615ULL <= (unsigned long long int) -1 ? 1 : -1)]; int i = 63; int main () { /* Test availability of runtime routines for shift and division. */ long long int llmax = 9223372036854775807ll; unsigned long long int ullmax = 18446744073709551615ull; return ((ll << 63) | (ll >> 63) | (ll < i) | (ll > i) | (llmax / ll) | (llmax % ll) | (ull << 63) | (ull >> 63) | (ull << i) | (ull >> i) | (ullmax / ull) | (ullmax % ull)); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : else ac_cv_type_unsigned_long_long_int=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_type_unsigned_long_long_int" >&5 $as_echo "$ac_cv_type_unsigned_long_long_int" >&6; } if test $ac_cv_type_unsigned_long_long_int = yes; then $as_echo "#define HAVE_UNSIGNED_LONG_LONG_INT 1" >>confdefs.h fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for long long int" >&5 $as_echo_n "checking for long long int... " >&6; } if ${ac_cv_type_long_long_int+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_type_long_long_int=yes if test "x${ac_cv_prog_cc_c99-no}" = xno; then ac_cv_type_long_long_int=$ac_cv_type_unsigned_long_long_int if test $ac_cv_type_long_long_int = yes; then if test "$cross_compiling" = yes; then : : else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #ifndef LLONG_MAX # define HALF \ (1LL << (sizeof (long long int) * CHAR_BIT - 2)) # define LLONG_MAX (HALF - 1 + HALF) #endif int main () { long long int n = 1; int i; for (i = 0; ; i++) { long long int m = n << i; if (m >> i != n) return 1; if (LLONG_MAX / 2 < m) break; } return 0; ; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : else ac_cv_type_long_long_int=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_type_long_long_int" >&5 $as_echo "$ac_cv_type_long_long_int" >&6; } if test $ac_cv_type_long_long_int = yes; then $as_echo "#define HAVE_LONG_LONG_INT 1" >>confdefs.h fi ac_fn_c_check_type "$LINENO" "in_addr_t" "ac_cv_type_in_addr_t" "#include #include " if test "x$ac_cv_type_in_addr_t" = xyes; then : else CFLAGS="${CFLAGS} -DNEED_INADDRT" fi ac_fn_c_check_type "$LINENO" "in_port_t" "ac_cv_type_in_port_t" "#include #include " if test "x$ac_cv_type_in_port_t" = xyes; then : else CFLAGS="${CFLAGS} -DNEED_INPORTT" fi ac_fn_c_check_type "$LINENO" "time_t" "ac_cv_type_time_t" "#include " if test "x$ac_cv_type_time_t" = xyes; then : else CFLAGS="${CFLAGS} -DNEED_TIMET" fi for ac_header in vfork.h do : ac_fn_c_check_header_mongrel "$LINENO" "vfork.h" "ac_cv_header_vfork_h" "$ac_includes_default" if test "x$ac_cv_header_vfork_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_VFORK_H 1 _ACEOF fi done for ac_func in fork vfork do : as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" if eval test \"x\$"$as_ac_var"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF fi done if test "x$ac_cv_func_fork" = xyes; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for working fork" >&5 $as_echo_n "checking for working fork... " >&6; } if ${ac_cv_func_fork_works+:} false; then : $as_echo_n "(cached) " >&6 else if test "$cross_compiling" = yes; then : ac_cv_func_fork_works=cross else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_includes_default int main () { /* By Ruediger Kuhlmann. */ return fork () < 0; ; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : ac_cv_func_fork_works=yes else ac_cv_func_fork_works=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_fork_works" >&5 $as_echo "$ac_cv_func_fork_works" >&6; } else ac_cv_func_fork_works=$ac_cv_func_fork fi if test "x$ac_cv_func_fork_works" = xcross; then case $host in *-*-amigaos* | *-*-msdosdjgpp*) # Override, as these systems have only a dummy fork() stub ac_cv_func_fork_works=no ;; *) ac_cv_func_fork_works=yes ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: result $ac_cv_func_fork_works guessed because of cross compilation" >&5 $as_echo "$as_me: WARNING: result $ac_cv_func_fork_works guessed because of cross compilation" >&2;} fi ac_cv_func_vfork_works=$ac_cv_func_vfork if test "x$ac_cv_func_vfork" = xyes; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for working vfork" >&5 $as_echo_n "checking for working vfork... " >&6; } if ${ac_cv_func_vfork_works+:} false; then : $as_echo_n "(cached) " >&6 else if test "$cross_compiling" = yes; then : ac_cv_func_vfork_works=cross else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Thanks to Paul Eggert for this test. */ $ac_includes_default #include #ifdef HAVE_VFORK_H # include #endif /* On some sparc systems, changes by the child to local and incoming argument registers are propagated back to the parent. The compiler is told about this with #include , but some compilers (e.g. gcc -O) don't grok . Test for this by using a static variable whose address is put into a register that is clobbered by the vfork. */ static void #ifdef __cplusplus sparc_address_test (int arg) # else sparc_address_test (arg) int arg; #endif { static pid_t child; if (!child) { child = vfork (); if (child < 0) { perror ("vfork"); _exit(2); } if (!child) { arg = getpid(); write(-1, "", 0); _exit (arg); } } } int main () { pid_t parent = getpid (); pid_t child; sparc_address_test (0); child = vfork (); if (child == 0) { /* Here is another test for sparc vfork register problems. This test uses lots of local variables, at least as many local variables as main has allocated so far including compiler temporaries. 4 locals are enough for gcc 1.40.3 on a Solaris 4.1.3 sparc, but we use 8 to be safe. A buggy compiler should reuse the register of parent for one of the local variables, since it will think that parent can't possibly be used any more in this routine. Assigning to the local variable will thus munge parent in the parent process. */ pid_t p = getpid(), p1 = getpid(), p2 = getpid(), p3 = getpid(), p4 = getpid(), p5 = getpid(), p6 = getpid(), p7 = getpid(); /* Convince the compiler that p..p7 are live; otherwise, it might use the same hardware register for all 8 local variables. */ if (p != p1 || p != p2 || p != p3 || p != p4 || p != p5 || p != p6 || p != p7) _exit(1); /* On some systems (e.g. IRIX 3.3), vfork doesn't separate parent from child file descriptors. If the child closes a descriptor before it execs or exits, this munges the parent's descriptor as well. Test for this by closing stdout in the child. */ _exit(close(fileno(stdout)) != 0); } else { int status; struct stat st; while (wait(&status) != child) ; return ( /* Was there some problem with vforking? */ child < 0 /* Did the child fail? (This shouldn't happen.) */ || status /* Did the vfork/compiler bug occur? */ || parent != getpid() /* Did the file descriptor bug occur? */ || fstat(fileno(stdout), &st) != 0 ); } } _ACEOF if ac_fn_c_try_run "$LINENO"; then : ac_cv_func_vfork_works=yes else ac_cv_func_vfork_works=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_vfork_works" >&5 $as_echo "$ac_cv_func_vfork_works" >&6; } fi; if test "x$ac_cv_func_fork_works" = xcross; then ac_cv_func_vfork_works=$ac_cv_func_vfork { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: result $ac_cv_func_vfork_works guessed because of cross compilation" >&5 $as_echo "$as_me: WARNING: result $ac_cv_func_vfork_works guessed because of cross compilation" >&2;} fi if test "x$ac_cv_func_vfork_works" = xyes; then $as_echo "#define HAVE_WORKING_VFORK 1" >>confdefs.h else $as_echo "#define vfork fork" >>confdefs.h fi if test "x$ac_cv_func_fork_works" = xyes; then $as_echo "#define HAVE_WORKING_FORK 1" >>confdefs.h fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for working memcmp" >&5 $as_echo_n "checking for working memcmp... " >&6; } if ${ac_cv_func_memcmp_working+:} false; then : $as_echo_n "(cached) " >&6 else if test "$cross_compiling" = yes; then : ac_cv_func_memcmp_working=no else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_includes_default int main () { /* Some versions of memcmp are not 8-bit clean. */ char c0 = '\100', c1 = '\200', c2 = '\201'; if (memcmp(&c0, &c2, 1) >= 0 || memcmp(&c1, &c2, 1) >= 0) return 1; /* The Next x86 OpenStep bug shows up only when comparing 16 bytes or more and with at least one buffer not starting on a 4-byte boundary. William Lewis provided this test program. */ { char foo[21]; char bar[21]; int i; for (i = 0; i < 4; i++) { char *a = foo + i; char *b = bar + i; strcpy (a, "--------01111111"); strcpy (b, "--------10000000"); if (memcmp (a, b, 16) >= 0) return 1; } return 0; } ; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : ac_cv_func_memcmp_working=yes else ac_cv_func_memcmp_working=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_memcmp_working" >&5 $as_echo "$ac_cv_func_memcmp_working" >&6; } test $ac_cv_func_memcmp_working = no && case " $LIBOBJS " in *" memcmp.$ac_objext "* ) ;; *) LIBOBJS="$LIBOBJS memcmp.$ac_objext" ;; esac for ac_header in sys/select.h sys/socket.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done { $as_echo "$as_me:${as_lineno-$LINENO}: checking types of arguments for select" >&5 $as_echo_n "checking types of arguments for select... " >&6; } if ${ac_cv_func_select_args+:} false; then : $as_echo_n "(cached) " >&6 else for ac_arg234 in 'fd_set *' 'int *' 'void *'; do for ac_arg1 in 'int' 'size_t' 'unsigned long int' 'unsigned int'; do for ac_arg5 in 'struct timeval *' 'const struct timeval *'; do cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_includes_default #ifdef HAVE_SYS_SELECT_H # include #endif #ifdef HAVE_SYS_SOCKET_H # include #endif int main () { extern int select ($ac_arg1, $ac_arg234, $ac_arg234, $ac_arg234, $ac_arg5); ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_func_select_args="$ac_arg1,$ac_arg234,$ac_arg5"; break 3 fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext done done done # Provide a safe default value. : "${ac_cv_func_select_args=int,int *,struct timeval *}" fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_select_args" >&5 $as_echo "$ac_cv_func_select_args" >&6; } ac_save_IFS=$IFS; IFS=',' set dummy `echo "$ac_cv_func_select_args" | sed 's/\*/\*/g'` IFS=$ac_save_IFS shift cat >>confdefs.h <<_ACEOF #define SELECT_TYPE_ARG1 $1 _ACEOF cat >>confdefs.h <<_ACEOF #define SELECT_TYPE_ARG234 ($2) _ACEOF cat >>confdefs.h <<_ACEOF #define SELECT_TYPE_ARG5 ($3) _ACEOF rm -f conftest* { $as_echo "$as_me:${as_lineno-$LINENO}: checking return type of signal handlers" >&5 $as_echo_n "checking return type of signal handlers... " >&6; } if ${ac_cv_type_signal+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include int main () { return *(signal (0, 0)) (0) == 1; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_type_signal=int else ac_cv_type_signal=void fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_type_signal" >&5 $as_echo "$ac_cv_type_signal" >&6; } cat >>confdefs.h <<_ACEOF #define RETSIGTYPE $ac_cv_type_signal _ACEOF { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether lstat correctly handles trailing slash" >&5 $as_echo_n "checking whether lstat correctly handles trailing slash... " >&6; } if ${ac_cv_func_lstat_dereferences_slashed_symlink+:} false; then : $as_echo_n "(cached) " >&6 else rm -f conftest.sym conftest.file echo >conftest.file if test "$as_ln_s" = "ln -s" && ln -s conftest.file conftest.sym; then if test "$cross_compiling" = yes; then : ac_cv_func_lstat_dereferences_slashed_symlink=no else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_includes_default int main () { struct stat sbuf; /* Linux will dereference the symlink and fail, as required by POSIX. That is better in the sense that it means we will not have to compile and use the lstat wrapper. */ return lstat ("conftest.sym/", &sbuf) == 0; ; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : ac_cv_func_lstat_dereferences_slashed_symlink=yes else ac_cv_func_lstat_dereferences_slashed_symlink=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi else # If the `ln -s' command failed, then we probably don't even # have an lstat function. ac_cv_func_lstat_dereferences_slashed_symlink=no fi rm -f conftest.sym conftest.file fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_lstat_dereferences_slashed_symlink" >&5 $as_echo "$ac_cv_func_lstat_dereferences_slashed_symlink" >&6; } test $ac_cv_func_lstat_dereferences_slashed_symlink = yes && cat >>confdefs.h <<_ACEOF #define LSTAT_FOLLOWS_SLASHED_SYMLINK 1 _ACEOF if test "x$ac_cv_func_lstat_dereferences_slashed_symlink" = xno; then case " $LIBOBJS " in *" lstat.$ac_objext "* ) ;; *) LIBOBJS="$LIBOBJS lstat.$ac_objext" ;; esac fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether stat accepts an empty string" >&5 $as_echo_n "checking whether stat accepts an empty string... " >&6; } if ${ac_cv_func_stat_empty_string_bug+:} false; then : $as_echo_n "(cached) " >&6 else if test "$cross_compiling" = yes; then : ac_cv_func_stat_empty_string_bug=yes else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_includes_default int main () { struct stat sbuf; return stat ("", &sbuf) == 0; ; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : ac_cv_func_stat_empty_string_bug=no else ac_cv_func_stat_empty_string_bug=yes fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_stat_empty_string_bug" >&5 $as_echo "$ac_cv_func_stat_empty_string_bug" >&6; } if test $ac_cv_func_stat_empty_string_bug = yes; then case " $LIBOBJS " in *" stat.$ac_objext "* ) ;; *) LIBOBJS="$LIBOBJS stat.$ac_objext" ;; esac cat >>confdefs.h <<_ACEOF #define HAVE_STAT_EMPTY_STRING_BUG 1 _ACEOF fi for ac_func in strftime do : ac_fn_c_check_func "$LINENO" "strftime" "ac_cv_func_strftime" if test "x$ac_cv_func_strftime" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_STRFTIME 1 _ACEOF else # strftime is in -lintl on SCO UNIX. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for strftime in -lintl" >&5 $as_echo_n "checking for strftime in -lintl... " >&6; } if ${ac_cv_lib_intl_strftime+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lintl $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char strftime (); int main () { return strftime (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_intl_strftime=yes else ac_cv_lib_intl_strftime=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_intl_strftime" >&5 $as_echo "$ac_cv_lib_intl_strftime" >&6; } if test "x$ac_cv_lib_intl_strftime" = xyes; then : $as_echo "#define HAVE_STRFTIME 1" >>confdefs.h LIBS="-lintl $LIBS" fi fi done for ac_func in getaddrinfo inet_ntop memset regcomp poll socket strcasecmp strchr strdup strerror strncasecmp strspn strtol setsid X509_STORE_set_flags localtime_r gettimeofday do : as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" if eval test \"x\$"$as_ac_var"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF fi done if test -z "${I_OWNER}" then egrep -s '^root' /etc/passwd > /dev/null && I_OWNER=root egrep -s '^sys' /etc/passwd > /dev/null && I_OWNER=sys egrep -s '^bin' /etc/passwd > /dev/null && I_OWNER=bin egrep -s '^daemon' /etc/passwd > /dev/null && I_OWNER=daemon egrep -s '^www' /etc/passwd > /dev/null && I_OWNER=www egrep -s '^proxy' /etc/passwd > /dev/null && I_OWNER=proxy fi if test -z "${I_GRP}" then egrep -s '^root' /etc/group > /dev/null && I_GRP=root egrep -s '^sys' /etc/group > /dev/null && I_GRP=sys egrep -s '^bin' /etc/group > /dev/null && I_GRP=bin egrep -s '^daemon' /etc/group > /dev/null && I_GRP=daemon egrep -s '^www' /etc/group > /dev/null && I_GRP=www egrep -s '^proxy' /etc/group > /dev/null && I_GRP=proxy fi ac_config_files="$ac_config_files Makefile" cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure # scripts and configure runs, see configure's option --config-cache. # It is not useful on other systems. If it contains results you don't # want to keep, you may remove or edit it. # # config.status only pays attention to the cache file if you give it # the --recheck option to rerun configure. # # `ac_cv_env_foo' variables (set or unset) will be overridden when # loading this file, other *unset* `ac_cv_foo' will be assigned the # following values. _ACEOF # The following way of writing the cache mishandles newlines in values, # but we know of no workaround that is simple, portable, and efficient. # So, we kill variables containing newlines. # Ultrix sh set writes to stderr and can't be redirected directly, # and sets the high bit in the cache file unless we assign to the vars. ( for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space=' '; set) 2>&1` in #( *${as_nl}ac_space=\ *) # `set' does not quote correctly, so add quotes: double-quote # substitution turns \\\\ into \\, and sed turns \\ into \. sed -n \ "s/'/'\\\\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" ;; #( *) # `set' quotes correctly as required by POSIX, so do not add quotes. sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) | sed ' /^ac_cv_env_/b end t clear :clear s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ t end s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ :end' >>confcache if diff "$cache_file" confcache >/dev/null 2>&1; then :; else if test -w "$cache_file"; then if test "x$cache_file" != "x/dev/null"; then { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 $as_echo "$as_me: updating cache $cache_file" >&6;} if test ! -f "$cache_file" || test -h "$cache_file"; then cat confcache >"$cache_file" else case $cache_file in #( */* | ?:*) mv -f confcache "$cache_file"$$ && mv -f "$cache_file"$$ "$cache_file" ;; #( *) mv -f confcache "$cache_file" ;; esac fi fi else { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 $as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} fi fi rm -f confcache test "x$prefix" = xNONE && prefix=$ac_default_prefix # Let make expand exec_prefix. test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' DEFS=-DHAVE_CONFIG_H ac_libobjs= ac_ltlibobjs= U= for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue # 1. Remove the extension, and $U if already installed. ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' ac_i=`$as_echo "$ac_i" | sed "$ac_script"` # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR # will be set to the directory where LIBOBJS objects are built. as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' done LIBOBJS=$ac_libobjs LTLIBOBJS=$ac_ltlibobjs : "${CONFIG_STATUS=./config.status}" ac_write_fail=0 ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files $CONFIG_STATUS" { $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 $as_echo "$as_me: creating $CONFIG_STATUS" >&6;} as_write_fail=0 cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 #! $SHELL # Generated by $as_me. # Run this file to recreate the current configuration. # Compiler output produced by configure, useful for debugging # configure, is in config.log if it exists. debug=false ac_cs_recheck=false ac_cs_silent=false SHELL=\${CONFIG_SHELL-$SHELL} export SHELL _ASEOF cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi as_nl=' ' export as_nl # Printing a long string crashes Solaris 7 /usr/bin/printf. as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo # Prefer a ksh shell builtin over an external printf program on Solaris, # but without wasting forks for bash or zsh. if test -z "$BASH_VERSION$ZSH_VERSION" \ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='print -r --' as_echo_n='print -rn --' elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='printf %s\n' as_echo_n='printf %s' else if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' as_echo_n='/usr/ucb/echo -n' else as_echo_body='eval expr "X$1" : "X\\(.*\\)"' as_echo_n_body='eval arg=$1; case $arg in #( *"$as_nl"*) expr "X$arg" : "X\\(.*\\)$as_nl"; arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; esac; expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" ' export as_echo_n_body as_echo_n='sh -c $as_echo_n_body as_echo' fi export as_echo_body as_echo='sh -c $as_echo_body as_echo' fi # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. as_myself= case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # Unset variables that we do not need and which cause bugs (e.g. in # pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" # suppresses any "Segmentation fault" message there. '((' could # trigger a bug in pdksh 5.2.14. for as_var in BASH_ENV ENV MAIL MAILPATH do eval test x\${$as_var+set} = xset \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # CDPATH. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH # as_fn_error STATUS ERROR [LINENO LOG_FD] # ---------------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with STATUS, using 1 if that was 0. as_fn_error () { as_status=$1; test $as_status -eq 0 && as_status=1 if test "$4"; then as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi $as_echo "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : eval 'as_fn_append () { eval $1+=\$2 }' else as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : eval 'as_fn_arith () { as_val=$(( $* )) }' else as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || $as_echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -pR'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -pR' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -pR' fi else as_ln_s='cp -pR' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" } # as_fn_mkdir_p if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi # as_fn_executable_p FILE # ----------------------- # Test if FILE is an executable regular file. as_fn_executable_p () { test -f "$1" && test -x "$1" } # as_fn_executable_p as_test_x='test -x' as_executable_p=as_fn_executable_p # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" exec 6>&1 ## ----------------------------------- ## ## Main body of $CONFIG_STATUS script. ## ## ----------------------------------- ## _ASEOF test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Save the log message, to keep $0 and so on meaningful, and to # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" This file was extended by pound $as_me 2.8, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES CONFIG_HEADERS = $CONFIG_HEADERS CONFIG_LINKS = $CONFIG_LINKS CONFIG_COMMANDS = $CONFIG_COMMANDS $ $0 $@ on `(hostname || uname -n) 2>/dev/null | sed 1q` " _ACEOF case $ac_config_files in *" "*) set x $ac_config_files; shift; ac_config_files=$*;; esac case $ac_config_headers in *" "*) set x $ac_config_headers; shift; ac_config_headers=$*;; esac cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 # Files that config.status was made for. config_files="$ac_config_files" config_headers="$ac_config_headers" _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 ac_cs_usage="\ \`$as_me' instantiates files and other configuration actions from templates according to the current configuration. Unless the files and actions are specified as TAGs, all are instantiated by default. Usage: $0 [OPTION]... [TAG]... -h, --help print this help, then exit -V, --version print version number and configuration settings, then exit --config print configuration, then exit -q, --quiet, --silent do not print progress messages -d, --debug don't remove temporary files --recheck update $as_me by reconfiguring in the same conditions --file=FILE[:TEMPLATE] instantiate the configuration file FILE --header=FILE[:TEMPLATE] instantiate the configuration header FILE Configuration files: $config_files Configuration headers: $config_headers Report bugs to ." _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ pound config.status 2.8 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" Copyright (C) 2012 Free Software Foundation, Inc. This config.status script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it." ac_pwd='$ac_pwd' srcdir='$srcdir' INSTALL='$INSTALL' test -n "\$AWK" || AWK=awk _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # The default lists apply if the user does not specify any file. ac_need_defaults=: while test $# != 0 do case $1 in --*=?*) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` ac_shift=: ;; --*=) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg= ac_shift=: ;; *) ac_option=$1 ac_optarg=$2 ac_shift=shift ;; esac case $ac_option in # Handling of the options. -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) ac_cs_recheck=: ;; --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) $as_echo "$ac_cs_version"; exit ;; --config | --confi | --conf | --con | --co | --c ) $as_echo "$ac_cs_config"; exit ;; --debug | --debu | --deb | --de | --d | -d ) debug=: ;; --file | --fil | --fi | --f ) $ac_shift case $ac_optarg in *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; '') as_fn_error $? "missing file argument" ;; esac as_fn_append CONFIG_FILES " '$ac_optarg'" ac_need_defaults=false;; --header | --heade | --head | --hea ) $ac_shift case $ac_optarg in *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; esac as_fn_append CONFIG_HEADERS " '$ac_optarg'" ac_need_defaults=false;; --he | --h) # Conflict between --help and --header as_fn_error $? "ambiguous option: \`$1' Try \`$0 --help' for more information.";; --help | --hel | -h ) $as_echo "$ac_cs_usage"; exit ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil | --si | --s) ac_cs_silent=: ;; # This is an error. -*) as_fn_error $? "unrecognized option: \`$1' Try \`$0 --help' for more information." ;; *) as_fn_append ac_config_targets " $1" ac_need_defaults=false ;; esac shift done ac_configure_extra_args= if $ac_cs_silent; then exec 6>/dev/null ac_configure_extra_args="$ac_configure_extra_args --silent" fi _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 if \$ac_cs_recheck; then set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion shift \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6 CONFIG_SHELL='$SHELL' export CONFIG_SHELL exec "\$@" fi _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 exec 5>>config.log { echo sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX ## Running $as_me. ## _ASBOX $as_echo "$ac_log" } >&5 _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Handling of arguments. for ac_config_target in $ac_config_targets do case $ac_config_target in "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;; "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; esac done # If the user did not use the arguments to specify the items to instantiate, # then the envvar interface is used. Set only those that are not. # We use the long form for the default assignment because of an extremely # bizarre bug on SunOS 4.1.3. if $ac_need_defaults; then test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers fi # Have a temporary directory for convenience. Make it in the build tree # simply because there is no reason against having it here, and in addition, # creating and moving files from /tmp can sometimes cause problems. # Hook for its removal unless debugging. # Note that there is a small window in which the directory will not be cleaned: # after its creation but before its name has been assigned to `$tmp'. $debug || { tmp= ac_tmp= trap 'exit_status=$? : "${ac_tmp:=$tmp}" { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status ' 0 trap 'as_fn_exit 1' 1 2 13 15 } # Create a (secure) tmp directory for tmp files. { tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && test -d "$tmp" } || { tmp=./conf$$-$RANDOM (umask 077 && mkdir "$tmp") } || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 ac_tmp=$tmp # Set up the scripts for CONFIG_FILES section. # No need to generate them if there are no CONFIG_FILES. # This happens for instance with `./config.status config.h'. if test -n "$CONFIG_FILES"; then ac_cr=`echo X | tr X '\015'` # On cygwin, bash can eat \r inside `` if the user requested igncr. # But we know of no other shell where ac_cr would be empty at this # point, so we can use a bashism as a fallback. if test "x$ac_cr" = x; then eval ac_cr=\$\'\\r\' fi ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null` if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then ac_cs_awk_cr='\\r' else ac_cs_awk_cr=$ac_cr fi echo 'BEGIN {' >"$ac_tmp/subs1.awk" && _ACEOF { echo "cat >conf$$subs.awk <<_ACEOF" && echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && echo "_ACEOF" } >conf$$subs.sh || as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'` ac_delim='%!_!# ' for ac_last_try in false false false false false :; do . ./conf$$subs.sh || as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` if test $ac_delim_n = $ac_delim_num; then break elif $ac_last_try; then as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi done rm -f conf$$subs.sh cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK && _ACEOF sed -n ' h s/^/S["/; s/!.*/"]=/ p g s/^[^!]*!// :repl t repl s/'"$ac_delim"'$// t delim :nl h s/\(.\{148\}\)..*/\1/ t more1 s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ p n b repl :more1 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t nl :delim h s/\(.\{148\}\)..*/\1/ t more2 s/["\\]/\\&/g; s/^/"/; s/$/"/ p b :more2 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t delim ' >$CONFIG_STATUS || ac_write_fail=1 rm -f conf$$subs.awk cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 _ACAWK cat >>"\$ac_tmp/subs1.awk" <<_ACAWK && for (key in S) S_is_set[key] = 1 FS = "" } { line = $ 0 nfields = split(line, field, "@") substed = 0 len = length(field[1]) for (i = 2; i < nfields; i++) { key = field[i] keylen = length(key) if (S_is_set[key]) { value = S[key] line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) len += length(value) + length(field[++i]) substed = 1 } else len += 1 + keylen } print line } _ACAWK _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" else cat fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \ || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 _ACEOF # VPATH may cause trouble with some makes, so we remove sole $(srcdir), # ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and # trailing colons and then remove the whole line if VPATH becomes empty # (actually we leave an empty line to preserve line numbers). if test "x$srcdir" = x.; then ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{ h s/// s/^/:/ s/[ ]*$/:/ s/:\$(srcdir):/:/g s/:\${srcdir}:/:/g s/:@srcdir@:/:/g s/^:*// s/:*$// x s/\(=[ ]*\).*/\1/ G s/\n// s/^[^=]*=[ ]*$// }' fi cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 fi # test -n "$CONFIG_FILES" # Set up the scripts for CONFIG_HEADERS section. # No need to generate them if there are no CONFIG_HEADERS. # This happens for instance with `./config.status Makefile'. if test -n "$CONFIG_HEADERS"; then cat >"$ac_tmp/defines.awk" <<\_ACAWK || BEGIN { _ACEOF # Transform confdefs.h into an awk script `defines.awk', embedded as # here-document in config.status, that substitutes the proper values into # config.h.in to produce config.h. # Create a delimiter string that does not exist in confdefs.h, to ease # handling of long lines. ac_delim='%!_!# ' for ac_last_try in false false :; do ac_tt=`sed -n "/$ac_delim/p" confdefs.h` if test -z "$ac_tt"; then break elif $ac_last_try; then as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5 else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi done # For the awk script, D is an array of macro values keyed by name, # likewise P contains macro parameters if any. Preserve backslash # newline sequences. ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]* sed -n ' s/.\{148\}/&'"$ac_delim"'/g t rset :rset s/^[ ]*#[ ]*define[ ][ ]*/ / t def d :def s/\\$// t bsnl s/["\\]/\\&/g s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ D["\1"]=" \3"/p s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2"/p d :bsnl s/["\\]/\\&/g s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ D["\1"]=" \3\\\\\\n"\\/p t cont s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p t cont d :cont n s/.\{148\}/&'"$ac_delim"'/g t clear :clear s/\\$// t bsnlc s/["\\]/\\&/g; s/^/"/; s/$/"/p d :bsnlc s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p b cont ' >$CONFIG_STATUS || ac_write_fail=1 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 for (key in D) D_is_set[key] = 1 FS = "" } /^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ { line = \$ 0 split(line, arg, " ") if (arg[1] == "#") { defundef = arg[2] mac1 = arg[3] } else { defundef = substr(arg[1], 2) mac1 = arg[2] } split(mac1, mac2, "(") #) macro = mac2[1] prefix = substr(line, 1, index(line, defundef) - 1) if (D_is_set[macro]) { # Preserve the white space surrounding the "#". print prefix "define", macro P[macro] D[macro] next } else { # Replace #undef with comments. This is necessary, for example, # in the case of _POSIX_SOURCE, which is predefined and required # on some systems where configure will not decide to define it. if (defundef == "undef") { print "/*", prefix defundef, macro, "*/" next } } } { print } _ACAWK _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 as_fn_error $? "could not setup config headers machinery" "$LINENO" 5 fi # test -n "$CONFIG_HEADERS" eval set X " :F $CONFIG_FILES :H $CONFIG_HEADERS " shift for ac_tag do case $ac_tag in :[FHLC]) ac_mode=$ac_tag; continue;; esac case $ac_mode$ac_tag in :[FHL]*:*);; :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;; :[FH]-) ac_tag=-:-;; :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; esac ac_save_IFS=$IFS IFS=: set x $ac_tag IFS=$ac_save_IFS shift ac_file=$1 shift case $ac_mode in :L) ac_source=$1;; :[FH]) ac_file_inputs= for ac_f do case $ac_f in -) ac_f="$ac_tmp/stdin";; *) # Look for the file first in the build tree, then in the source tree # (if the path is not absolute). The absolute path cannot be DOS-style, # because $ac_f cannot contain `:'. test -f "$ac_f" || case $ac_f in [\\/$]*) false;; *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; esac || as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;; esac case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac as_fn_append ac_file_inputs " '$ac_f'" done # Let's still pretend it is `configure' which instantiates (i.e., don't # use $as_me), people would be surprised to read: # /* config.h. Generated by config.status. */ configure_input='Generated from '` $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' `' by configure.' if test x"$ac_file" != x-; then configure_input="$ac_file. $configure_input" { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 $as_echo "$as_me: creating $ac_file" >&6;} fi # Neutralize special characters interpreted by sed in replacement strings. case $configure_input in #( *\&* | *\|* | *\\* ) ac_sed_conf_input=`$as_echo "$configure_input" | sed 's/[\\\\&|]/\\\\&/g'`;; #( *) ac_sed_conf_input=$configure_input;; esac case $ac_tag in *:-:* | *:-) cat >"$ac_tmp/stdin" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; esac ;; esac ac_dir=`$as_dirname -- "$ac_file" || $as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$ac_file" : 'X\(//\)[^/]' \| \ X"$ac_file" : 'X\(//\)$' \| \ X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$ac_file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` as_dir="$ac_dir"; as_fn_mkdir_p ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix case $ac_mode in :F) # # CONFIG_FILE # case $INSTALL in [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;; esac _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # If the template does not know about datarootdir, expand it. # FIXME: This hack should be removed a few years after 2.60. ac_datarootdir_hack=; ac_datarootdir_seen= ac_sed_dataroot=' /datarootdir/ { p q } /@datadir@/p /@docdir@/p /@infodir@/p /@localedir@/p /@mandir@/p' case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in *datarootdir*) ac_datarootdir_seen=yes;; *@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 $as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_datarootdir_hack=' s&@datadir@&$datadir&g s&@docdir@&$docdir&g s&@infodir@&$infodir&g s&@localedir@&$localedir&g s&@mandir@&$mandir&g s&\\\${datarootdir}&$datarootdir&g' ;; esac _ACEOF # Neutralize VPATH when `$srcdir' = `.'. # Shell code in configure.ac might set extrasub. # FIXME: do we really want to maintain this feature? cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_sed_extra="$ac_vpsub $extrasub _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 :t /@[a-zA-Z_][a-zA-Z_0-9]*@/!b s|@configure_input@|$ac_sed_conf_input|;t t s&@top_builddir@&$ac_top_builddir_sub&;t t s&@top_build_prefix@&$ac_top_build_prefix&;t t s&@srcdir@&$ac_srcdir&;t t s&@abs_srcdir@&$ac_abs_srcdir&;t t s&@top_srcdir@&$ac_top_srcdir&;t t s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t s&@builddir@&$ac_builddir&;t t s&@abs_builddir@&$ac_abs_builddir&;t t s&@abs_top_builddir@&$ac_abs_top_builddir&;t t s&@INSTALL@&$ac_INSTALL&;t t $ac_datarootdir_hack " eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \ >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5 test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } && { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \ "$ac_tmp/out"`; test -z "$ac_out"; } && { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined" >&5 $as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined" >&2;} rm -f "$ac_tmp/stdin" case $ac_file in -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";; *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";; esac \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; :H) # # CONFIG_HEADER # if test x"$ac_file" != x-; then { $as_echo "/* $configure_input */" \ && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" } >"$ac_tmp/config.h" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5 $as_echo "$as_me: $ac_file is unchanged" >&6;} else rm -f "$ac_file" mv "$ac_tmp/config.h" "$ac_file" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 fi else $as_echo "/* $configure_input */" \ && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \ || as_fn_error $? "could not create -" "$LINENO" 5 fi # Compute "$ac_file"'s index in $config_headers. _am_arg="$ac_file" _am_stamp_count=1 for _am_header in $config_headers :; do case $_am_header in $_am_arg | $_am_arg:* ) break ;; * ) _am_stamp_count=`expr $_am_stamp_count + 1` ;; esac done echo "timestamp for $_am_arg" >`$as_dirname -- "$_am_arg" || $as_expr X"$_am_arg" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$_am_arg" : 'X\(//\)[^/]' \| \ X"$_am_arg" : 'X\(//\)$' \| \ X"$_am_arg" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$_am_arg" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'`/stamp-h$_am_stamp_count ;; esac done # for ac_tag as_fn_exit 0 _ACEOF ac_clean_files=$ac_clean_files_save test $ac_write_fail = 0 || as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5 # configure is writing to config.log, and then calls config.status. # config.status does its own redirection, appending to config.log. # Unfortunately, on DOS this fails, as config.log is still kept open # by configure, so config.status won't be able to write to it; its # output is simply discarded. So we exec the FD to /dev/null, # effectively closing config.log, so it can be properly (re)opened and # appended to by config.status. When coming back to configure, we # need to make the FD available again. if test "$no_create" != yes; then ac_cs_success=: ac_config_status_args= test "$silent" = yes && ac_config_status_args="$ac_config_status_args --quiet" exec 5>/dev/null $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false exec 5>>config.log # Use ||, not &&, to avoid exiting from the if with $? = 1, which # would make configure fail if this is the last instruction. $ac_cs_success || as_fn_exit 1 fi if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} fi Pound-2.8/config.c0000664000175000017500000021604013275266545013125 0ustar rosegroseg/* * Pound - the reverse-proxy load-balancer * Copyright (C) 2002-2010 Apsis GmbH * * This file is part of Pound. * * Pound is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * Pound is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * Contact information: * Apsis GmbH * P.O.Box * 8707 Uetikon am See * Switzerland * EMail: roseg@apsis.ch */ #ifndef MISS_FACILITYNAMES #define SYSLOG_NAMES 1 #endif #include "pound.h" #include #ifdef MISS_FACILITYNAMES /* This is lifted verbatim from the Linux sys/syslog.h */ typedef struct _code { char *c_name; int c_val; } CODE; static CODE facilitynames[] = { { "auth", LOG_AUTH }, #ifdef LOG_AUTHPRIV { "authpriv", LOG_AUTHPRIV }, #endif { "cron", LOG_CRON }, { "daemon", LOG_DAEMON }, #ifdef LOG_FTP { "ftp", LOG_FTP }, #endif { "kern", LOG_KERN }, { "lpr", LOG_LPR }, { "mail", LOG_MAIL }, { "mark", 0 }, /* never used! */ { "news", LOG_NEWS }, { "security", LOG_AUTH }, /* DEPRECATED */ { "syslog", LOG_SYSLOG }, { "user", LOG_USER }, { "uucp", LOG_UUCP }, { "local0", LOG_LOCAL0 }, { "local1", LOG_LOCAL1 }, { "local2", LOG_LOCAL2 }, { "local3", LOG_LOCAL3 }, { "local4", LOG_LOCAL4 }, { "local5", LOG_LOCAL5 }, { "local6", LOG_LOCAL6 }, { "local7", LOG_LOCAL7 }, { NULL, -1 } }; #endif static regex_t Empty, Comment, User, Group, RootJail, Daemon, LogFacility, LogLevel, Alive, SSLEngine, Control; static regex_t ListenHTTP, ListenHTTPS, End, Address, Port, Cert, xHTTP, Client, CheckURL; static regex_t Err414, Err500, Err501, Err503, MaxRequest, HeadRemove, RewriteLocation, RewriteDestination; static regex_t Service, ServiceName, URL, HeadRequire, HeadDeny, BackEnd, Emergency, Priority, HAport, HAportAddr; static regex_t Redirect, RedirectN, TimeOut, Session, Type, TTL, ID; static regex_t ClientCert, AddHeader, DisableProto, SSLAllowClientRenegotiation, SSLHonorCipherOrder, Ciphers; static regex_t CAlist, VerifyList, CRLlist, NoHTTPS11, Grace, Include, ConnTO, IgnoreCase, HTTPS; static regex_t Disabled, Threads, CNName, Anonymise, ECDHCurve; static regmatch_t matches[5]; static char *xhttp[] = { "^(GET|POST|HEAD) ([^ ]+) HTTP/1.[01]$", "^(GET|POST|HEAD|PUT|PATCH|DELETE) ([^ ]+) HTTP/1.[01]$", "^(GET|POST|HEAD|PUT|PATCH|DELETE|LOCK|UNLOCK|PROPFIND|PROPPATCH|SEARCH|MKCOL|MOVE|COPY|OPTIONS|TRACE|MKACTIVITY|CHECKOUT|MERGE|REPORT) ([^ ]+) HTTP/1.[01]$", "^(GET|POST|HEAD|PUT|PATCH|DELETE|LOCK|UNLOCK|PROPFIND|PROPPATCH|SEARCH|MKCOL|MOVE|COPY|OPTIONS|TRACE|MKACTIVITY|CHECKOUT|MERGE|REPORT|SUBSCRIBE|UNSUBSCRIBE|BPROPPATCH|POLL|BMOVE|BCOPY|BDELETE|BPROPFIND|NOTIFY|CONNECT) ([^ ]+) HTTP/1.[01]$", "^(GET|POST|HEAD|PUT|PATCH|DELETE|LOCK|UNLOCK|PROPFIND|PROPPATCH|SEARCH|MKCOL|MOVE|COPY|OPTIONS|TRACE|MKACTIVITY|CHECKOUT|MERGE|REPORT|SUBSCRIBE|UNSUBSCRIBE|BPROPPATCH|POLL|BMOVE|BCOPY|BDELETE|BPROPFIND|NOTIFY|CONNECT|RPC_IN_DATA|RPC_OUT_DATA) ([^ ]+) HTTP/1.[01]$", }; static int log_level = 1; static int def_facility = LOG_DAEMON; static int clnt_to = 10; static int be_to = 15; static int be_connto = 15; static int ignore_case = 0; #if OPENSSL_VERSION_NUMBER >= 0x0090800fL #ifndef OPENSSL_NO_ECDH static int EC_nid = NID_X9_62_prime256v1; #endif #endif #define MAX_FIN 8 static FILE *f_in[MAX_FIN]; static char *f_name[MAX_FIN]; static int n_lin[MAX_FIN]; static int cur_fin; static int conf_init(const char *name) { if((f_name[0] = strdup(name)) == NULL) { logmsg(LOG_ERR, "open %s: out of memory", name); exit(1); } if((f_in[0] = fopen(name, "rt")) == NULL) { logmsg(LOG_ERR, "can't open open %s", name); exit(1); } n_lin[0] = 0; cur_fin = 0; return 0; } void conf_err(const char *msg) { logmsg(LOG_ERR, "%s line %d: %s", f_name[cur_fin], n_lin[cur_fin], msg); exit(1); } static char * conf_fgets(char *buf, const int max) { int i; for(;;) { if(fgets(buf, max, f_in[cur_fin]) == NULL) { fclose(f_in[cur_fin]); free(f_name[cur_fin]); if(cur_fin > 0) { cur_fin--; continue; } else return NULL; } n_lin[cur_fin]++; for(i = 0; i < max; i++) if(buf[i] == '\n' || buf[i] == '\r') { buf[i] = '\0'; break; } if(!regexec(&Empty, buf, 4, matches, 0) || !regexec(&Comment, buf, 4, matches, 0)) /* comment or empty line */ continue; if(!regexec(&Include, buf, 4, matches, 0)) { buf[matches[1].rm_eo] = '\0'; if(cur_fin == (MAX_FIN - 1)) conf_err("Include nesting too deep"); cur_fin++; if((f_name[cur_fin] = strdup(&buf[matches[1].rm_so])) == NULL) conf_err("Include out of memory"); if((f_in[cur_fin] = fopen(&buf[matches[1].rm_so], "rt")) == NULL) conf_err("can't open included file"); n_lin[cur_fin] = 0; continue; } return buf; } } unsigned char ** get_subjectaltnames(X509 *x509, unsigned int *count) { unsigned int local_count; unsigned char **result; STACK_OF(GENERAL_NAME) *san_stack = (STACK_OF(GENERAL_NAME)*)X509_get_ext_d2i(x509, NID_subject_alt_name, NULL, NULL); unsigned char *temp[sk_GENERAL_NAME_num(san_stack)]; GENERAL_NAME *name; int i; local_count = 0; result = NULL; name = NULL; *count = 0; if(san_stack == NULL) return NULL; while(sk_GENERAL_NAME_num(san_stack) > 0) { name = sk_GENERAL_NAME_pop(san_stack); switch(name->type) { case GEN_DNS: temp[local_count] = strndup(ASN1_STRING_data(name->d.dNSName), ASN1_STRING_length(name->d.dNSName) + 1); if(temp[local_count] == NULL) conf_err("out of memory"); local_count++; break; default: logmsg(LOG_INFO, "unsupported subjectAltName type encountered: %i", name->type); } GENERAL_NAME_free(name); } result = (unsigned char**)malloc(sizeof(unsigned char*)*local_count); if(result == NULL) conf_err("out of memory"); for(i = 0;i < local_count; i++) { result[i] = strndup(temp[i], strlen(temp[i])+1); if(result[i] == NULL) conf_err("out of memory"); free(temp[i]); } *count = local_count; sk_GENERAL_NAME_pop_free(san_stack, GENERAL_NAME_free); return result; } /* * parse a back-end */ static BACKEND * parse_be(const int is_emergency) { char lin[MAXBUF]; BACKEND *res; int has_addr, has_port; struct hostent *host; struct sockaddr_in in; struct sockaddr_in6 in6; if((res = (BACKEND *)malloc(sizeof(BACKEND))) == NULL) conf_err("BackEnd config: out of memory - aborted"); memset(res, 0, sizeof(BACKEND)); res->be_type = 0; res->addr.ai_socktype = SOCK_STREAM; res->to = is_emergency? 120: be_to; res->conn_to = is_emergency? 120: be_connto; res->alive = 1; memset(&res->addr, 0, sizeof(res->addr)); res->priority = 5; memset(&res->ha_addr, 0, sizeof(res->ha_addr)); res->url = NULL; res->next = NULL; has_addr = has_port = 0; pthread_mutex_init(&res->mut, NULL); while(conf_fgets(lin, MAXBUF)) { if(strlen(lin) > 0 && lin[strlen(lin) - 1] == '\n') lin[strlen(lin) - 1] = '\0'; if(!regexec(&Address, lin, 4, matches, 0)) { lin[matches[1].rm_eo] = '\0'; if(get_host(lin + matches[1].rm_so, &res->addr, PF_UNSPEC)) { /* if we can't resolve it assume this is a UNIX domain socket */ res->addr.ai_socktype = SOCK_STREAM; res->addr.ai_family = AF_UNIX; res->addr.ai_protocol = 0; if((res->addr.ai_addr = (struct sockaddr *)malloc(sizeof(struct sockaddr_un))) == NULL) conf_err("out of memory"); if((strlen(lin + matches[1].rm_so) + 1) > UNIX_PATH_MAX) conf_err("UNIX path name too long"); res->addr.ai_addrlen = strlen(lin + matches[1].rm_so) + 1; res->addr.ai_addr->sa_family = AF_UNIX; strcpy(res->addr.ai_addr->sa_data, lin + matches[1].rm_so); res->addr.ai_addrlen = sizeof( struct sockaddr_un ); } has_addr = 1; } else if(!regexec(&Port, lin, 4, matches, 0)) { switch(res->addr.ai_family) { case AF_INET: memcpy(&in, res->addr.ai_addr, sizeof(in)); in.sin_port = (in_port_t)htons(atoi(lin + matches[1].rm_so)); memcpy(res->addr.ai_addr, &in, sizeof(in)); break; case AF_INET6: memcpy(&in6, res->addr.ai_addr, sizeof(in6)); in6.sin6_port = (in_port_t)htons(atoi(lin + matches[1].rm_so)); memcpy(res->addr.ai_addr, &in6, sizeof(in6)); break; default: conf_err("Port is supported only for INET/INET6 back-ends"); } has_port = 1; } else if(!regexec(&Priority, lin, 4, matches, 0)) { if(is_emergency) conf_err("Priority is not supported for Emergency back-ends"); res->priority = atoi(lin + matches[1].rm_so); } else if(!regexec(&TimeOut, lin, 4, matches, 0)) { res->to = atoi(lin + matches[1].rm_so); } else if(!regexec(&ConnTO, lin, 4, matches, 0)) { res->conn_to = atoi(lin + matches[1].rm_so); } else if(!regexec(&HAport, lin, 4, matches, 0)) { if(is_emergency) conf_err("HAport is not supported for Emergency back-ends"); res->ha_addr = res->addr; if((res->ha_addr.ai_addr = (struct sockaddr *)malloc(res->addr.ai_addrlen)) == NULL) conf_err("out of memory"); memcpy(res->ha_addr.ai_addr, res->addr.ai_addr, res->addr.ai_addrlen); switch(res->addr.ai_family) { case AF_INET: memcpy(&in, res->ha_addr.ai_addr, sizeof(in)); in.sin_port = (in_port_t)htons(atoi(lin + matches[1].rm_so)); memcpy(res->ha_addr.ai_addr, &in, sizeof(in)); break; case AF_INET6: memcpy(&in6, res->addr.ai_addr, sizeof(in6)); in6.sin6_port = (in_port_t)htons(atoi(lin + matches[1].rm_so)); memcpy(res->addr.ai_addr, &in6, sizeof(in6)); break; default: conf_err("HAport is supported only for INET/INET6 back-ends"); } } else if(!regexec(&HAportAddr, lin, 4, matches, 0)) { if(is_emergency) conf_err("HAportAddr is not supported for Emergency back-ends"); lin[matches[1].rm_eo] = '\0'; if(get_host(lin + matches[1].rm_so, &res->ha_addr, PF_UNSPEC)) { /* if we can't resolve it assume this is a UNIX domain socket */ res->addr.ai_socktype = SOCK_STREAM; res->ha_addr.ai_family = AF_UNIX; res->ha_addr.ai_protocol = 0; if((res->ha_addr.ai_addr = (struct sockaddr *)strdup(lin + matches[1].rm_so)) == NULL) conf_err("out of memory"); res->addr.ai_addrlen = strlen(lin + matches[1].rm_so) + 1; } else switch(res->ha_addr.ai_family) { case AF_INET: memcpy(&in, res->ha_addr.ai_addr, sizeof(in)); in.sin_port = (in_port_t)htons(atoi(lin + matches[2].rm_so)); memcpy(res->ha_addr.ai_addr, &in, sizeof(in)); break; case AF_INET6: memcpy(&in6, res->ha_addr.ai_addr, sizeof(in6)); in6.sin6_port = (in_port_t)htons(atoi(lin + matches[2].rm_so)); memcpy(res->ha_addr.ai_addr, &in6, sizeof(in6)); break; default: conf_err("Unknown HA address type"); } } else if(!regexec(&HTTPS, lin, 4, matches, 0)) { if((res->ctx = SSL_CTX_new(SSLv23_client_method())) == NULL) conf_err("SSL_CTX_new failed - aborted"); SSL_CTX_set_app_data(res->ctx, res); SSL_CTX_set_verify(res->ctx, SSL_VERIFY_NONE, NULL); SSL_CTX_set_mode(res->ctx, SSL_MODE_AUTO_RETRY); #ifdef SSL_MODE_SEND_FALLBACK_SCSV SSL_CTX_set_mode(res->ctx, SSL_MODE_SEND_FALLBACK_SCSV); #endif SSL_CTX_set_options(res->ctx, SSL_OP_ALL); #ifdef SSL_OP_NO_COMPRESSION SSL_CTX_set_options(res->ctx, SSL_OP_NO_COMPRESSION); #endif SSL_CTX_clear_options(res->ctx, SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION); SSL_CTX_clear_options(res->ctx, SSL_OP_LEGACY_SERVER_CONNECT); sprintf(lin, "%d-Pound-%ld", getpid(), random()); SSL_CTX_set_session_id_context(res->ctx, (unsigned char *)lin, strlen(lin)); SSL_CTX_set_tmp_rsa_callback(res->ctx, RSA_tmp_callback); SSL_CTX_set_tmp_dh_callback(res->ctx, DH_tmp_callback); #if OPENSSL_VERSION_NUMBER >= 0x0090800fL #ifndef OPENSSL_NO_ECDH /* This generates a EC_KEY structure with no key, but a group defined */ EC_KEY *ecdh; if((ecdh = EC_KEY_new_by_curve_name(EC_nid)) == NULL) conf_err("Unable to generate temp ECDH key"); SSL_CTX_set_tmp_ecdh(res->ctx, ecdh); SSL_CTX_set_options(res->ctx, SSL_OP_SINGLE_ECDH_USE); EC_KEY_free(ecdh); #endif #endif } else if(!regexec(&Cert, lin, 4, matches, 0)) { if(res->ctx == NULL) conf_err("BackEnd Cert can only be used after HTTPS - aborted"); lin[matches[1].rm_eo] = '\0'; if(SSL_CTX_use_certificate_chain_file(res->ctx, lin + matches[1].rm_so) != 1) conf_err("SSL_CTX_use_certificate_chain_file failed - aborted"); if(SSL_CTX_use_PrivateKey_file(res->ctx, lin + matches[1].rm_so, SSL_FILETYPE_PEM) != 1) conf_err("SSL_CTX_use_PrivateKey_file failed - aborted"); if(SSL_CTX_check_private_key(res->ctx) != 1) conf_err("SSL_CTX_check_private_key failed - aborted"); } else if(!regexec(&Ciphers, lin, 4, matches, 0)) { if(res->ctx == NULL) conf_err("BackEnd Ciphers can only be used after HTTPS - aborted"); lin[matches[1].rm_eo] = '\0'; SSL_CTX_set_cipher_list(res->ctx, lin + matches[1].rm_so); } else if(!regexec(&DisableProto, lin, 4, matches, 0)) { if(res->ctx == NULL) conf_err("BackEnd Disable can only be used after HTTPS - aborted"); lin[matches[1].rm_eo] = '\0'; if(strcasecmp(lin + matches[1].rm_so, "SSLv2") == 0) SSL_CTX_set_options(res->ctx, SSL_OP_NO_SSLv2); else if(strcasecmp(lin + matches[1].rm_so, "SSLv3") == 0) SSL_CTX_set_options(res->ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3); #ifdef SSL_OP_NO_TLSv1 else if(strcasecmp(lin + matches[1].rm_so, "TLSv1") == 0) SSL_CTX_set_options(res->ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1); #endif #ifdef SSL_OP_NO_TLSv1_1 else if(strcasecmp(lin + matches[1].rm_so, "TLSv1_1") == 0) SSL_CTX_set_options(res->ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1); #endif #ifdef SSL_OP_NO_TLSv1_2 else if(strcasecmp(lin + matches[1].rm_so, "TLSv1_2") == 0) SSL_CTX_set_options(res->ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1 | SSL_OP_NO_TLSv1_2); #endif } else if(!regexec(&Disabled, lin, 4, matches, 0)) { res->disabled = atoi(lin + matches[1].rm_so); } else if(!regexec(&End, lin, 4, matches, 0)) { if(!has_addr) conf_err("BackEnd missing Address - aborted"); if((res->addr.ai_family == AF_INET || res->addr.ai_family == AF_INET6) && !has_port) conf_err("BackEnd missing Port - aborted"); return res; } else { conf_err("unknown directive"); } } conf_err("BackEnd premature EOF"); return NULL; } /* * parse a session */ static void parse_sess(SERVICE *const svc) { char lin[MAXBUF], *cp, *parm; parm = NULL; while(conf_fgets(lin, MAXBUF)) { if(strlen(lin) > 0 && lin[strlen(lin) - 1] == '\n') lin[strlen(lin) - 1] = '\0'; if(!regexec(&Type, lin, 4, matches, 0)) { if(svc->sess_type != SESS_NONE) conf_err("Multiple Session types in one Service - aborted"); lin[matches[1].rm_eo] = '\0'; cp = lin + matches[1].rm_so; if(!strcasecmp(cp, "IP")) svc->sess_type = SESS_IP; else if(!strcasecmp(cp, "COOKIE")) svc->sess_type = SESS_COOKIE; else if(!strcasecmp(cp, "URL")) svc->sess_type = SESS_URL; else if(!strcasecmp(cp, "PARM")) svc->sess_type = SESS_PARM; else if(!strcasecmp(cp, "BASIC")) svc->sess_type = SESS_BASIC; else if(!strcasecmp(cp, "HEADER")) svc->sess_type = SESS_HEADER; else conf_err("Unknown Session type"); } else if(!regexec(&TTL, lin, 4, matches, 0)) { svc->sess_ttl = atoi(lin + matches[1].rm_so); } else if(!regexec(&ID, lin, 4, matches, 0)) { if(svc->sess_type != SESS_COOKIE && svc->sess_type != SESS_URL && svc->sess_type != SESS_HEADER) conf_err("no ID permitted unless COOKIE/URL/HEADER Session - aborted"); lin[matches[1].rm_eo] = '\0'; if((parm = strdup(lin + matches[1].rm_so)) == NULL) conf_err("ID config: out of memory - aborted"); } else if(!regexec(&End, lin, 4, matches, 0)) { if(svc->sess_type == SESS_NONE) conf_err("Session type not defined - aborted"); if(svc->sess_ttl == 0) conf_err("Session TTL not defined - aborted"); if((svc->sess_type == SESS_COOKIE || svc->sess_type == SESS_URL || svc->sess_type == SESS_HEADER) && parm == NULL) conf_err("Session ID not defined - aborted"); if(svc->sess_type == SESS_COOKIE) { snprintf(lin, MAXBUF - 1, "Cookie[^:]*:.*[ \t]%s=", parm); if(regcomp(&svc->sess_start, lin, REG_ICASE | REG_NEWLINE | REG_EXTENDED)) conf_err("COOKIE pattern failed - aborted"); if(regcomp(&svc->sess_pat, "([^;]*)", REG_ICASE | REG_NEWLINE | REG_EXTENDED)) conf_err("COOKIE pattern failed - aborted"); } else if(svc->sess_type == SESS_URL) { snprintf(lin, MAXBUF - 1, "[?&]%s=", parm); if(regcomp(&svc->sess_start, lin, REG_ICASE | REG_NEWLINE | REG_EXTENDED)) conf_err("URL pattern failed - aborted"); if(regcomp(&svc->sess_pat, "([^&;#]*)", REG_ICASE | REG_NEWLINE | REG_EXTENDED)) conf_err("URL pattern failed - aborted"); } else if(svc->sess_type == SESS_PARM) { if(regcomp(&svc->sess_start, ";", REG_ICASE | REG_NEWLINE | REG_EXTENDED)) conf_err("PARM pattern failed - aborted"); if(regcomp(&svc->sess_pat, "([^?]*)", REG_ICASE | REG_NEWLINE | REG_EXTENDED)) conf_err("PARM pattern failed - aborted"); } else if(svc->sess_type == SESS_BASIC) { if(regcomp(&svc->sess_start, "Authorization:[ \t]*Basic[ \t]*", REG_ICASE | REG_NEWLINE | REG_EXTENDED)) conf_err("BASIC pattern failed - aborted"); if(regcomp(&svc->sess_pat, "([^ \t]*)", REG_ICASE | REG_NEWLINE | REG_EXTENDED)) conf_err("BASIC pattern failed - aborted"); } else if(svc->sess_type == SESS_HEADER) { snprintf(lin, MAXBUF - 1, "%s:[ \t]*", parm); if(regcomp(&svc->sess_start, lin, REG_ICASE | REG_NEWLINE | REG_EXTENDED)) conf_err("HEADER pattern failed - aborted"); if(regcomp(&svc->sess_pat, "([^ \t]*)", REG_ICASE | REG_NEWLINE | REG_EXTENDED)) conf_err("HEADER pattern failed - aborted"); } if(parm != NULL) free(parm); return; } else { conf_err("unknown directive"); } } conf_err("Session premature EOF"); return; } /* * basic hashing function, based on fmv */ static unsigned long t_hash(const TABNODE *e) { unsigned long res; char *k; k = e->key; res = 2166136261; while(*k) res = ((res ^ *k++) * 16777619) & 0xFFFFFFFF; return res; } #if OPENSSL_VERSION_NUMBER >= 0x10000000L static IMPLEMENT_LHASH_HASH_FN(t, TABNODE) #else static IMPLEMENT_LHASH_HASH_FN(t_hash, const TABNODE *) #endif static int t_cmp(const TABNODE *d1, const TABNODE *d2) { return strcmp(d1->key, d2->key); } #if OPENSSL_VERSION_NUMBER >= 0x10000000L static IMPLEMENT_LHASH_COMP_FN(t, TABNODE) #else static IMPLEMENT_LHASH_COMP_FN(t_cmp, const TABNODE *) #endif /* * parse a service */ static SERVICE * parse_service(const char *svc_name) { char lin[MAXBUF]; SERVICE *res; BACKEND *be; MATCHER *m; int ign_case; if((res = (SERVICE *)malloc(sizeof(SERVICE))) == NULL) conf_err("Service config: out of memory - aborted"); memset(res, 0, sizeof(SERVICE)); res->sess_type = SESS_NONE; pthread_mutex_init(&res->mut, NULL); if(svc_name) strncpy(res->name, svc_name, KEY_SIZE); #if OPENSSL_VERSION_NUMBER >= 0x10000000L if((res->sessions = LHM_lh_new(TABNODE, t)) == NULL) #else if((res->sessions = lh_new(LHASH_HASH_FN(t_hash), LHASH_COMP_FN(t_cmp))) == NULL) #endif conf_err("lh_new failed - aborted"); ign_case = ignore_case; while(conf_fgets(lin, MAXBUF)) { if(strlen(lin) > 0 && lin[strlen(lin) - 1] == '\n') lin[strlen(lin) - 1] = '\0'; if(!regexec(&URL, lin, 4, matches, 0)) { if(res->url) { for(m = res->url; m->next; m = m->next) ; if((m->next = (MATCHER *)malloc(sizeof(MATCHER))) == NULL) conf_err("URL config: out of memory - aborted"); m = m->next; } else { if((res->url = (MATCHER *)malloc(sizeof(MATCHER))) == NULL) conf_err("URL config: out of memory - aborted"); m = res->url; } memset(m, 0, sizeof(MATCHER)); lin[matches[1].rm_eo] = '\0'; if(regcomp(&m->pat, lin + matches[1].rm_so, REG_NEWLINE | REG_EXTENDED | (ign_case? REG_ICASE: 0))) conf_err("URL bad pattern - aborted"); } else if(!regexec(&HeadRequire, lin, 4, matches, 0)) { if(res->req_head) { for(m = res->req_head; m->next; m = m->next) ; if((m->next = (MATCHER *)malloc(sizeof(MATCHER))) == NULL) conf_err("HeadRequire config: out of memory - aborted"); m = m->next; } else { if((res->req_head = (MATCHER *)malloc(sizeof(MATCHER))) == NULL) conf_err("HeadRequire config: out of memory - aborted"); m = res->req_head; } memset(m, 0, sizeof(MATCHER)); lin[matches[1].rm_eo] = '\0'; if(regcomp(&m->pat, lin + matches[1].rm_so, REG_ICASE | REG_NEWLINE | REG_EXTENDED)) conf_err("HeadRequire bad pattern - aborted"); } else if(!regexec(&HeadDeny, lin, 4, matches, 0)) { if(res->deny_head) { for(m = res->deny_head; m->next; m = m->next) ; if((m->next = (MATCHER *)malloc(sizeof(MATCHER))) == NULL) conf_err("HeadDeny config: out of memory - aborted"); m = m->next; } else { if((res->deny_head = (MATCHER *)malloc(sizeof(MATCHER))) == NULL) conf_err("HeadDeny config: out of memory - aborted"); m = res->deny_head; } memset(m, 0, sizeof(MATCHER)); lin[matches[1].rm_eo] = '\0'; if(regcomp(&m->pat, lin + matches[1].rm_so, REG_ICASE | REG_NEWLINE | REG_EXTENDED)) conf_err("HeadDeny bad pattern - aborted"); } else if(!regexec(&Redirect, lin, 4, matches, 0)) { if(res->backends) { for(be = res->backends; be->next; be = be->next) ; if((be->next = (BACKEND *)malloc(sizeof(BACKEND))) == NULL) conf_err("Redirect config: out of memory - aborted"); be = be->next; } else { if((res->backends = (BACKEND *)malloc(sizeof(BACKEND))) == NULL) conf_err("Redirect config: out of memory - aborted"); be = res->backends; } memset(be, 0, sizeof(BACKEND)); be->be_type = 302; be->priority = 1; be->alive = 1; pthread_mutex_init(& be->mut, NULL); lin[matches[1].rm_eo] = '\0'; if((be->url = strdup(lin + matches[1].rm_so)) == NULL) conf_err("Redirector config: out of memory - aborted"); /* split the URL into its fields */ if(regexec(&LOCATION, be->url, 4, matches, 0)) conf_err("Redirect bad URL - aborted"); if((be->redir_req = matches[3].rm_eo - matches[3].rm_so) == 1) /* the path is a single '/', so remove it */ be->url[matches[3].rm_so] = '\0'; } else if(!regexec(&RedirectN, lin, 4, matches, 0)) { if(res->backends) { for(be = res->backends; be->next; be = be->next) ; if((be->next = (BACKEND *)malloc(sizeof(BACKEND))) == NULL) conf_err("Redirect config: out of memory - aborted"); be = be->next; } else { if((res->backends = (BACKEND *)malloc(sizeof(BACKEND))) == NULL) conf_err("Redirect config: out of memory - aborted"); be = res->backends; } memset(be, 0, sizeof(BACKEND)); be->be_type = atoi(lin + matches[1].rm_so); be->priority = 1; be->alive = 1; pthread_mutex_init(& be->mut, NULL); lin[matches[2].rm_eo] = '\0'; if((be->url = strdup(lin + matches[2].rm_so)) == NULL) conf_err("Redirector config: out of memory - aborted"); /* split the URL into its fields */ if(regexec(&LOCATION, be->url, 4, matches, 0)) conf_err("Redirect bad URL - aborted"); if((be->redir_req = matches[3].rm_eo - matches[3].rm_so) == 1) /* the path is a single '/', so remove it */ be->url[matches[3].rm_so] = '\0'; } else if(!regexec(&BackEnd, lin, 4, matches, 0)) { if(res->backends) { for(be = res->backends; be->next; be = be->next) ; be->next = parse_be(0); } else res->backends = parse_be(0); } else if(!regexec(&Emergency, lin, 4, matches, 0)) { res->emergency = parse_be(1); } else if(!regexec(&Session, lin, 4, matches, 0)) { parse_sess(res); } else if(!regexec(&IgnoreCase, lin, 4, matches, 0)) { ign_case = atoi(lin + matches[1].rm_so); } else if(!regexec(&Disabled, lin, 4, matches, 0)) { res->disabled = atoi(lin + matches[1].rm_so); } else if(!regexec(&End, lin, 4, matches, 0)) { for(be = res->backends; be; be = be->next) { if(!be->disabled) res->tot_pri += be->priority; res->abs_pri += be->priority; } return res; } else { conf_err("unknown directive"); } } conf_err("Service premature EOF"); return NULL; } /* * return the file contents as a string */ static char * file2str(const char *fname) { char *res; struct stat st; int fin; if(stat(fname, &st)) conf_err("can't stat Err file - aborted"); if((fin = open(fname, O_RDONLY)) < 0) conf_err("can't open Err file - aborted"); if((res = malloc(st.st_size + 1)) == NULL) conf_err("can't alloc Err file (out of memory) - aborted"); if(read(fin, res, st.st_size) != st.st_size) conf_err("can't read Err file - aborted"); res[st.st_size] = '\0'; close(fin); return res; } /* * parse an HTTP listener */ static LISTENER * parse_HTTP(void) { char lin[MAXBUF]; LISTENER *res; SERVICE *svc; MATCHER *m; int has_addr, has_port; struct sockaddr_in in; struct sockaddr_in6 in6; if((res = (LISTENER *)malloc(sizeof(LISTENER))) == NULL) conf_err("ListenHTTP config: out of memory - aborted"); memset(res, 0, sizeof(LISTENER)); res->to = clnt_to; res->rewr_loc = 1; res->err414 = "Request URI is too long"; res->err500 = "An internal server error occurred. Please try again later."; res->err501 = "This method may not be used."; res->err503 = "The service is not available. Please try again later."; res->log_level = log_level; if(regcomp(&res->verb, xhttp[0], REG_ICASE | REG_NEWLINE | REG_EXTENDED)) conf_err("xHTTP bad default pattern - aborted"); has_addr = has_port = 0; while(conf_fgets(lin, MAXBUF)) { if(strlen(lin) > 0 && lin[strlen(lin) - 1] == '\n') lin[strlen(lin) - 1] = '\0'; if(!regexec(&Address, lin, 4, matches, 0)) { lin[matches[1].rm_eo] = '\0'; if(get_host(lin + matches[1].rm_so, &res->addr, PF_UNSPEC)) conf_err("Unknown Listener address"); if(res->addr.ai_family != AF_INET && res->addr.ai_family != AF_INET6) conf_err("Unknown Listener address family"); has_addr = 1; } else if(!regexec(&Port, lin, 4, matches, 0)) { switch(res->addr.ai_family) { case AF_INET: memcpy(&in, res->addr.ai_addr, sizeof(in)); in.sin_port = (in_port_t)htons(atoi(lin + matches[1].rm_so)); memcpy(res->addr.ai_addr, &in, sizeof(in)); break; case AF_INET6: memcpy(&in6, res->addr.ai_addr, sizeof(in6)); in6.sin6_port = htons(atoi(lin + matches[1].rm_so)); memcpy(res->addr.ai_addr, &in6, sizeof(in6)); break; default: conf_err("Unknown Listener address family"); } has_port = 1; } else if(!regexec(&xHTTP, lin, 4, matches, 0)) { int n; n = atoi(lin + matches[1].rm_so); regfree(&res->verb); if(regcomp(&res->verb, xhttp[n], REG_ICASE | REG_NEWLINE | REG_EXTENDED)) conf_err("xHTTP bad pattern - aborted"); } else if(!regexec(&Client, lin, 4, matches, 0)) { res->to = atoi(lin + matches[1].rm_so); } else if(!regexec(&CheckURL, lin, 4, matches, 0)) { if(res->has_pat) conf_err("CheckURL multiple pattern - aborted"); lin[matches[1].rm_eo] = '\0'; if(regcomp(&res->url_pat, lin + matches[1].rm_so, REG_NEWLINE | REG_EXTENDED | (ignore_case? REG_ICASE: 0))) conf_err("CheckURL bad pattern - aborted"); res->has_pat = 1; } else if(!regexec(&Err414, lin, 4, matches, 0)) { lin[matches[1].rm_eo] = '\0'; res->err414 = file2str(lin + matches[1].rm_so); } else if(!regexec(&Err500, lin, 4, matches, 0)) { lin[matches[1].rm_eo] = '\0'; res->err500 = file2str(lin + matches[1].rm_so); } else if(!regexec(&Err501, lin, 4, matches, 0)) { lin[matches[1].rm_eo] = '\0'; res->err501 = file2str(lin + matches[1].rm_so); } else if(!regexec(&Err503, lin, 4, matches, 0)) { lin[matches[1].rm_eo] = '\0'; res->err503 = file2str(lin + matches[1].rm_so); } else if(!regexec(&MaxRequest, lin, 4, matches, 0)) { res->max_req = ATOL(lin + matches[1].rm_so); } else if(!regexec(&HeadRemove, lin, 4, matches, 0)) { if(res->head_off) { for(m = res->head_off; m->next; m = m->next) ; if((m->next = (MATCHER *)malloc(sizeof(MATCHER))) == NULL) conf_err("HeadRemove config: out of memory - aborted"); m = m->next; } else { if((res->head_off = (MATCHER *)malloc(sizeof(MATCHER))) == NULL) conf_err("HeadRemove config: out of memory - aborted"); m = res->head_off; } memset(m, 0, sizeof(MATCHER)); lin[matches[1].rm_eo] = '\0'; if(regcomp(&m->pat, lin + matches[1].rm_so, REG_ICASE | REG_NEWLINE | REG_EXTENDED)) conf_err("HeadRemove bad pattern - aborted"); } else if(!regexec(&AddHeader, lin, 4, matches, 0)) { lin[matches[1].rm_eo] = '\0'; if(res->add_head == NULL) { if((res->add_head = strdup(lin + matches[1].rm_so)) == NULL) conf_err("AddHeader config: out of memory - aborted"); } else { if((res->add_head = realloc(res->add_head, strlen(res->add_head) + strlen(lin + matches[1].rm_so) + 3)) == NULL) conf_err("AddHeader config: out of memory - aborted"); strcat(res->add_head, "\r\n"); strcat(res->add_head, lin + matches[1].rm_so); } } else if(!regexec(&RewriteLocation, lin, 4, matches, 0)) { res->rewr_loc = atoi(lin + matches[1].rm_so); } else if(!regexec(&RewriteDestination, lin, 4, matches, 0)) { res->rewr_dest = atoi(lin + matches[1].rm_so); } else if(!regexec(&LogLevel, lin, 4, matches, 0)) { res->log_level = atoi(lin + matches[1].rm_so); } else if(!regexec(&Service, lin, 4, matches, 0)) { if(res->services == NULL) res->services = parse_service(NULL); else { for(svc = res->services; svc->next; svc = svc->next) ; svc->next = parse_service(NULL); } } else if(!regexec(&ServiceName, lin, 4, matches, 0)) { lin[matches[1].rm_eo] = '\0'; if(res->services == NULL) res->services = parse_service(lin + matches[1].rm_so); else { for(svc = res->services; svc->next; svc = svc->next) ; svc->next = parse_service(lin + matches[1].rm_so); } } else if(!regexec(&End, lin, 4, matches, 0)) { if(!has_addr || !has_port) conf_err("ListenHTTP missing Address or Port - aborted"); return res; } else { conf_err("unknown directive - aborted"); } } conf_err("ListenHTTP premature EOF"); return NULL; } /* * Dummy certificate verification - always OK */ static int verify_OK(int pre_ok, X509_STORE_CTX *ctx) { return 1; } #ifdef SSL_CTRL_SET_TLSEXT_SERVERNAME_CB static int SNI_server_name(SSL *ssl, int *dummy, POUND_CTX *ctx) { const char *server_name; POUND_CTX *pc; if((server_name = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name)) == NULL) return SSL_TLSEXT_ERR_NOACK; /* logmsg(LOG_DEBUG, "Received SSL SNI Header for servername %s", servername); */ SSL_set_SSL_CTX(ssl, NULL); for(pc = ctx; pc; pc = pc->next) { if(fnmatch(pc->server_name, server_name, 0) == 0) { /* logmsg(LOG_DEBUG, "Found cert for %s", servername); */ SSL_set_SSL_CTX(ssl, pc->ctx); return SSL_TLSEXT_ERR_OK; } else if(pc->subjectAltNameCount > 0 && pc->subjectAltNames != NULL) { int i; for(i = 0; i < pc->subjectAltNameCount; i++) { if(fnmatch(pc->subjectAltNames[i], server_name, 0) == 0) { SSL_set_SSL_CTX(ssl, pc->ctx); return SSL_TLSEXT_ERR_OK; } } } } /* logmsg(LOG_DEBUG, "No match for %s, default used", server_name); */ SSL_set_SSL_CTX(ssl, ctx->ctx); return SSL_TLSEXT_ERR_OK; } #endif /* * parse an HTTPS listener */ static LISTENER * parse_HTTPS(void) { char lin[MAXBUF]; LISTENER *res; SERVICE *svc; MATCHER *m; int has_addr, has_port, has_other; long ssl_op_enable, ssl_op_disable; struct hostent *host; struct sockaddr_in in; struct sockaddr_in6 in6; POUND_CTX *pc; ssl_op_enable = SSL_OP_ALL; #ifdef SSL_OP_NO_COMPRESSION ssl_op_enable |= SSL_OP_NO_COMPRESSION; #endif ssl_op_disable = SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION | SSL_OP_LEGACY_SERVER_CONNECT | SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS; if((res = (LISTENER *)malloc(sizeof(LISTENER))) == NULL) conf_err("ListenHTTPS config: out of memory - aborted"); memset(res, 0, sizeof(LISTENER)); res->to = clnt_to; res->rewr_loc = 1; res->err414 = "Request URI is too long"; res->err500 = "An internal server error occurred. Please try again later."; res->err501 = "This method may not be used."; res->err503 = "The service is not available. Please try again later."; res->allow_client_reneg = 0; res->log_level = log_level; if(regcomp(&res->verb, xhttp[0], REG_ICASE | REG_NEWLINE | REG_EXTENDED)) conf_err("xHTTP bad default pattern - aborted"); has_addr = has_port = has_other = 0; while(conf_fgets(lin, MAXBUF)) { if(strlen(lin) > 0 && lin[strlen(lin) - 1] == '\n') lin[strlen(lin) - 1] = '\0'; if(!regexec(&Address, lin, 4, matches, 0)) { lin[matches[1].rm_eo] = '\0'; if(get_host(lin + matches[1].rm_so, &res->addr, PF_UNSPEC)) conf_err("Unknown Listener address"); if(res->addr.ai_family != AF_INET && res->addr.ai_family != AF_INET6) conf_err("Unknown Listener address family"); has_addr = 1; } else if(!regexec(&Port, lin, 4, matches, 0)) { if(res->addr.ai_family == AF_INET) { memcpy(&in, res->addr.ai_addr, sizeof(in)); in.sin_port = (in_port_t)htons(atoi(lin + matches[1].rm_so)); memcpy(res->addr.ai_addr, &in, sizeof(in)); } else { memcpy(&in6, res->addr.ai_addr, sizeof(in6)); in6.sin6_port = htons(atoi(lin + matches[1].rm_so)); memcpy(res->addr.ai_addr, &in6, sizeof(in6)); } has_port = 1; } else if(!regexec(&xHTTP, lin, 4, matches, 0)) { int n; n = atoi(lin + matches[1].rm_so); regfree(&res->verb); if(regcomp(&res->verb, xhttp[n], REG_ICASE | REG_NEWLINE | REG_EXTENDED)) conf_err("xHTTP bad pattern - aborted"); } else if(!regexec(&Client, lin, 4, matches, 0)) { res->to = atoi(lin + matches[1].rm_so); } else if(!regexec(&CheckURL, lin, 4, matches, 0)) { if(res->has_pat) conf_err("CheckURL multiple pattern - aborted"); lin[matches[1].rm_eo] = '\0'; if(regcomp(&res->url_pat, lin + matches[1].rm_so, REG_NEWLINE | REG_EXTENDED | (ignore_case? REG_ICASE: 0))) conf_err("CheckURL bad pattern - aborted"); res->has_pat = 1; } else if(!regexec(&Err414, lin, 4, matches, 0)) { lin[matches[1].rm_eo] = '\0'; res->err414 = file2str(lin + matches[1].rm_so); } else if(!regexec(&Err500, lin, 4, matches, 0)) { lin[matches[1].rm_eo] = '\0'; res->err500 = file2str(lin + matches[1].rm_so); } else if(!regexec(&Err501, lin, 4, matches, 0)) { lin[matches[1].rm_eo] = '\0'; res->err501 = file2str(lin + matches[1].rm_so); } else if(!regexec(&Err503, lin, 4, matches, 0)) { lin[matches[1].rm_eo] = '\0'; res->err503 = file2str(lin + matches[1].rm_so); } else if(!regexec(&MaxRequest, lin, 4, matches, 0)) { res->max_req = ATOL(lin + matches[1].rm_so); } else if(!regexec(&HeadRemove, lin, 4, matches, 0)) { if(res->head_off) { for(m = res->head_off; m->next; m = m->next) ; if((m->next = (MATCHER *)malloc(sizeof(MATCHER))) == NULL) conf_err("HeadRemove config: out of memory - aborted"); m = m->next; } else { if((res->head_off = (MATCHER *)malloc(sizeof(MATCHER))) == NULL) conf_err("HeadRemove config: out of memory - aborted"); m = res->head_off; } memset(m, 0, sizeof(MATCHER)); lin[matches[1].rm_eo] = '\0'; if(regcomp(&m->pat, lin + matches[1].rm_so, REG_ICASE | REG_NEWLINE | REG_EXTENDED)) conf_err("HeadRemove bad pattern - aborted"); } else if(!regexec(&RewriteLocation, lin, 4, matches, 0)) { res->rewr_loc = atoi(lin + matches[1].rm_so); } else if(!regexec(&RewriteDestination, lin, 4, matches, 0)) { res->rewr_dest = atoi(lin + matches[1].rm_so); } else if(!regexec(&LogLevel, lin, 4, matches, 0)) { res->log_level = atoi(lin + matches[1].rm_so); } else if(!regexec(&Cert, lin, 4, matches, 0)) { #ifdef SSL_CTRL_SET_TLSEXT_SERVERNAME_CB /* we have support for SNI */ FILE *fcert; char server_name[MAXBUF], *cp; X509 *x509; if(has_other) conf_err("Cert directives MUST precede other SSL-specific directives - aborted"); if(res->ctx) { for(pc = res->ctx; pc->next; pc = pc->next) ; if((pc->next = malloc(sizeof(POUND_CTX))) == NULL) conf_err("ListenHTTPS new POUND_CTX: out of memory - aborted"); pc = pc->next; } else { if((res->ctx = malloc(sizeof(POUND_CTX))) == NULL) conf_err("ListenHTTPS new POUND_CTX: out of memory - aborted"); pc = res->ctx; } if((pc->ctx = SSL_CTX_new(SSLv23_server_method())) == NULL) conf_err("SSL_CTX_new failed - aborted"); pc->server_name = NULL; pc->next = NULL; lin[matches[1].rm_eo] = '\0'; if(SSL_CTX_use_certificate_chain_file(pc->ctx, lin + matches[1].rm_so) != 1) conf_err("SSL_CTX_use_certificate_chain_file failed - aborted"); if(SSL_CTX_use_PrivateKey_file(pc->ctx, lin + matches[1].rm_so, SSL_FILETYPE_PEM) != 1) conf_err("SSL_CTX_use_PrivateKey_file failed - aborted"); if(SSL_CTX_check_private_key(pc->ctx) != 1) conf_err("SSL_CTX_check_private_key failed - aborted"); if((fcert = fopen(lin + matches[1].rm_so, "r")) == NULL) conf_err("ListenHTTPS: could not open certificate file"); if((x509 = PEM_read_X509(fcert, NULL, NULL, NULL)) == NULL) conf_err("ListenHTTPS: could not get certificate subject"); fclose(fcert); memset(server_name, '\0', MAXBUF); X509_NAME_oneline(X509_get_subject_name(x509), server_name, MAXBUF - 1); pc->subjectAltNameCount = 0; pc->subjectAltNames = NULL; pc->subjectAltNames = get_subjectaltnames(x509, &(pc->subjectAltNameCount)); X509_free(x509); if(!regexec(&CNName, server_name, 4, matches, 0)) { server_name[matches[1].rm_eo] = '\0'; if((pc->server_name = strdup(server_name + matches[1].rm_so)) == NULL) conf_err("ListenHTTPS: could not set certificate subject"); } else conf_err("ListenHTTPS: could not get certificate CN"); #else /* no SNI support */ if(has_other) conf_err("Cert directives MUST precede other SSL-specific directives - aborted"); if(res->ctx) conf_err("ListenHTTPS: multiple certificates not supported - aborted"); if((res->ctx = malloc(sizeof(POUND_CTX))) == NULL) conf_err("ListenHTTPS new POUND_CTX: out of memory - aborted"); res->ctx->server_name = NULL; res->ctx->next = NULL; if((res->ctx->ctx = SSL_CTX_new(SSLv23_server_method())) == NULL) conf_err("SSL_CTX_new failed - aborted"); lin[matches[1].rm_eo] = '\0'; if(SSL_CTX_use_certificate_chain_file(res->ctx->ctx, lin + matches[1].rm_so) != 1) conf_err("SSL_CTX_use_certificate_chain_file failed - aborted"); if(SSL_CTX_use_PrivateKey_file(res->ctx->ctx, lin + matches[1].rm_so, SSL_FILETYPE_PEM) != 1) conf_err("SSL_CTX_use_PrivateKey_file failed - aborted"); if(SSL_CTX_check_private_key(res->ctx->ctx) != 1) conf_err("SSL_CTX_check_private_key failed - aborted"); #endif } else if(!regexec(&ClientCert, lin, 4, matches, 0)) { has_other = 1; if(res->ctx == NULL) conf_err("ClientCert may only be used after Cert - aborted"); switch(res->clnt_check = atoi(lin + matches[1].rm_so)) { case 0: /* don't ask */ for(pc = res->ctx; pc; pc = pc->next) SSL_CTX_set_verify(pc->ctx, SSL_VERIFY_NONE, NULL); break; case 1: /* ask but OK if no client certificate */ for(pc = res->ctx; pc; pc = pc->next) { SSL_CTX_set_verify(pc->ctx, SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE, NULL); SSL_CTX_set_verify_depth(pc->ctx, atoi(lin + matches[2].rm_so)); } break; case 2: /* ask and fail if no client certificate */ for(pc = res->ctx; pc; pc = pc->next) { SSL_CTX_set_verify(pc->ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, NULL); SSL_CTX_set_verify_depth(pc->ctx, atoi(lin + matches[2].rm_so)); } break; case 3: /* ask but do not verify client certificate */ for(pc = res->ctx; pc; pc = pc->next) { SSL_CTX_set_verify(pc->ctx, SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE, verify_OK); SSL_CTX_set_verify_depth(pc->ctx, atoi(lin + matches[2].rm_so)); } break; } } else if(!regexec(&AddHeader, lin, 4, matches, 0)) { lin[matches[1].rm_eo] = '\0'; if(res->add_head == NULL) { if((res->add_head = strdup(lin + matches[1].rm_so)) == NULL) conf_err("AddHeader config: out of memory - aborted"); } else { if((res->add_head = realloc(res->add_head, strlen(res->add_head) + strlen(lin + matches[1].rm_so) + 3)) == NULL) conf_err("AddHeader config: out of memory - aborted"); strcat(res->add_head, "\r\n"); strcat(res->add_head, lin + matches[1].rm_so); } } else if(!regexec(&DisableProto, lin, 4, matches, 0)) { lin[matches[1].rm_eo] = '\0'; if(strcasecmp(lin + matches[1].rm_so, "SSLv2") == 0) ssl_op_enable |= SSL_OP_NO_SSLv2; else if(strcasecmp(lin + matches[1].rm_so, "SSLv3") == 0) ssl_op_enable |= SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3; #ifdef SSL_OP_NO_TLSv1 else if(strcasecmp(lin + matches[1].rm_so, "TLSv1") == 0) ssl_op_enable |= SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1; #endif #ifdef SSL_OP_NO_TLSv1_1 else if(strcasecmp(lin + matches[1].rm_so, "TLSv1_1") == 0) ssl_op_enable |= SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1; #endif #ifdef SSL_OP_NO_TLSv1_2 else if(strcasecmp(lin + matches[1].rm_so, "TLSv1_2") == 0) ssl_op_enable |= SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1 | SSL_OP_NO_TLSv1_2; #endif } else if(!regexec(&SSLAllowClientRenegotiation, lin, 4, matches, 0)) { res->allow_client_reneg = atoi(lin + matches[1].rm_so); if (res->allow_client_reneg == 2) { ssl_op_enable |= SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION; ssl_op_disable &= ~SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION; } else { ssl_op_disable |= SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION; ssl_op_enable &= ~SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION; } } else if(!regexec(&SSLHonorCipherOrder, lin, 4, matches, 0)) { if (atoi(lin + matches[1].rm_so)) { ssl_op_enable |= SSL_OP_CIPHER_SERVER_PREFERENCE; ssl_op_disable &= ~SSL_OP_CIPHER_SERVER_PREFERENCE; } else { ssl_op_disable |= SSL_OP_CIPHER_SERVER_PREFERENCE; ssl_op_enable &= ~SSL_OP_CIPHER_SERVER_PREFERENCE; } } else if(!regexec(&Ciphers, lin, 4, matches, 0)) { has_other = 1; if(res->ctx == NULL) conf_err("Ciphers may only be used after Cert - aborted"); lin[matches[1].rm_eo] = '\0'; for(pc = res->ctx; pc; pc = pc->next) SSL_CTX_set_cipher_list(pc->ctx, lin + matches[1].rm_so); } else if(!regexec(&CAlist, lin, 4, matches, 0)) { STACK_OF(X509_NAME) *cert_names; has_other = 1; if(res->ctx == NULL) conf_err("CAList may only be used after Cert - aborted"); lin[matches[1].rm_eo] = '\0'; if((cert_names = SSL_load_client_CA_file(lin + matches[1].rm_so)) == NULL) conf_err("SSL_load_client_CA_file failed - aborted"); for(pc = res->ctx; pc; pc = pc->next) SSL_CTX_set_client_CA_list(pc->ctx, cert_names); } else if(!regexec(&VerifyList, lin, 4, matches, 0)) { has_other = 1; if(res->ctx == NULL) conf_err("VerifyList may only be used after Cert - aborted"); lin[matches[1].rm_eo] = '\0'; for(pc = res->ctx; pc; pc = pc->next) if(SSL_CTX_load_verify_locations(pc->ctx, lin + matches[1].rm_so, NULL) != 1) conf_err("SSL_CTX_load_verify_locations failed - aborted"); } else if(!regexec(&CRLlist, lin, 4, matches, 0)) { #if HAVE_X509_STORE_SET_FLAGS X509_STORE *store; X509_LOOKUP *lookup; has_other = 1; if(res->ctx == NULL) conf_err("CRLlist may only be used after Cert - aborted"); lin[matches[1].rm_eo] = '\0'; for(pc = res->ctx; pc; pc = pc->next) { store = SSL_CTX_get_cert_store(pc->ctx); if((lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file())) == NULL) conf_err("X509_STORE_add_lookup failed - aborted"); if(X509_load_crl_file(lookup, lin + matches[1].rm_so, X509_FILETYPE_PEM) != 1) conf_err("X509_load_crl_file failed - aborted"); X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL); } #else conf_err("your version of OpenSSL does not support CRL checking"); #endif } else if(!regexec(&NoHTTPS11, lin, 4, matches, 0)) { res->noHTTPS11 = atoi(lin + matches[1].rm_so); } else if(!regexec(&Service, lin, 4, matches, 0)) { if(res->services == NULL) res->services = parse_service(NULL); else { for(svc = res->services; svc->next; svc = svc->next) ; svc->next = parse_service(NULL); } } else if(!regexec(&ServiceName, lin, 4, matches, 0)) { lin[matches[1].rm_eo] = '\0'; if(res->services == NULL) res->services = parse_service(lin + matches[1].rm_so); else { for(svc = res->services; svc->next; svc = svc->next) ; svc->next = parse_service(lin + matches[1].rm_so); } } else if(!regexec(&End, lin, 4, matches, 0)) { X509_STORE *store; if(!has_addr || !has_port || res->ctx == NULL) conf_err("ListenHTTPS missing Address, Port or Certificate - aborted"); #ifdef SSL_CTRL_SET_TLSEXT_SERVERNAME_CB if(res->ctx->next) if(!SSL_CTX_set_tlsext_servername_callback(res->ctx->ctx, SNI_server_name) || !SSL_CTX_set_tlsext_servername_arg(res->ctx->ctx, res->ctx)) conf_err("ListenHTTPS: can't set SNI callback"); #endif for(pc = res->ctx; pc; pc = pc->next) { SSL_CTX_set_app_data(pc->ctx, res); SSL_CTX_set_mode(pc->ctx, SSL_MODE_AUTO_RETRY); SSL_CTX_set_options(pc->ctx, ssl_op_enable); SSL_CTX_clear_options(pc->ctx, ssl_op_disable); sprintf(lin, "%d-Pound-%ld", getpid(), random()); SSL_CTX_set_session_id_context(pc->ctx, (unsigned char *)lin, strlen(lin)); SSL_CTX_set_tmp_rsa_callback(pc->ctx, RSA_tmp_callback); SSL_CTX_set_tmp_dh_callback(pc->ctx, DH_tmp_callback); SSL_CTX_set_info_callback(pc->ctx, SSLINFO_callback); #if OPENSSL_VERSION_NUMBER >= 0x0090800fL #ifndef OPENSSL_NO_ECDH /* This generates a EC_KEY structure with no key, but a group defined */ EC_KEY *ecdh; if((ecdh = EC_KEY_new_by_curve_name(EC_nid)) == NULL) conf_err("Unable to generate temp ECDH key"); SSL_CTX_set_tmp_ecdh(pc->ctx, ecdh); SSL_CTX_set_options(pc->ctx, SSL_OP_SINGLE_ECDH_USE); EC_KEY_free(ecdh); #endif #endif } return res; } else { conf_err("unknown directive"); } } conf_err("ListenHTTPS premature EOF"); return NULL; } /* * parse the config file */ static void parse_file(void) { char lin[MAXBUF]; SERVICE *svc; LISTENER *lstn; int i; #if HAVE_OPENSSL_ENGINE_H ENGINE *e; #endif while(conf_fgets(lin, MAXBUF)) { if(strlen(lin) > 0 && lin[strlen(lin) - 1] == '\n') lin[strlen(lin) - 1] = '\0'; if(!regexec(&User, lin, 4, matches, 0)) { lin[matches[1].rm_eo] = '\0'; if((user = strdup(lin + matches[1].rm_so)) == NULL) conf_err("User config: out of memory - aborted"); } else if(!regexec(&Group, lin, 4, matches, 0)) { lin[matches[1].rm_eo] = '\0'; if((group = strdup(lin + matches[1].rm_so)) == NULL) conf_err("Group config: out of memory - aborted"); } else if(!regexec(&RootJail, lin, 4, matches, 0)) { lin[matches[1].rm_eo] = '\0'; if((root_jail = strdup(lin + matches[1].rm_so)) == NULL) conf_err("RootJail config: out of memory - aborted"); } else if(!regexec(&Daemon, lin, 4, matches, 0)) { daemonize = atoi(lin + matches[1].rm_so); } else if(!regexec(&Threads, lin, 4, matches, 0)) { numthreads = atoi(lin + matches[1].rm_so); } else if(!regexec(&LogFacility, lin, 4, matches, 0)) { lin[matches[1].rm_eo] = '\0'; if(lin[matches[1].rm_so] == '-') def_facility = -1; else for(i = 0; facilitynames[i].c_name; i++) if(!strcmp(facilitynames[i].c_name, lin + matches[1].rm_so)) { def_facility = facilitynames[i].c_val; break; } } else if(!regexec(&Grace, lin, 4, matches, 0)) { grace = atoi(lin + matches[1].rm_so); } else if(!regexec(&LogLevel, lin, 4, matches, 0)) { log_level = atoi(lin + matches[1].rm_so); } else if(!regexec(&Client, lin, 4, matches, 0)) { clnt_to = atoi(lin + matches[1].rm_so); } else if(!regexec(&Alive, lin, 4, matches, 0)) { alive_to = atoi(lin + matches[1].rm_so); } else if(!regexec(&TimeOut, lin, 4, matches, 0)) { be_to = atoi(lin + matches[1].rm_so); } else if(!regexec(&ConnTO, lin, 4, matches, 0)) { be_connto = atoi(lin + matches[1].rm_so); } else if(!regexec(&IgnoreCase, lin, 4, matches, 0)) { ignore_case = atoi(lin + matches[1].rm_so); #if OPENSSL_VERSION_NUMBER >= 0x0090800fL #ifndef OPENSSL_NO_ECDH } else if(!regexec(&ECDHCurve, lin, 4, matches, 0)) { lin[matches[1].rm_eo] = '\0'; if((EC_nid = OBJ_sn2nid(lin + matches[1].rm_so)) == 0) conf_err("ECDHCurve config: invalid curve name"); #endif #endif #if HAVE_OPENSSL_ENGINE_H } else if(!regexec(&SSLEngine, lin, 4, matches, 0)) { lin[matches[1].rm_eo] = '\0'; #if OPENSSL_VERSION_NUMBER >= 0x00907000L ENGINE_load_builtin_engines(); #endif if (!(e = ENGINE_by_id(lin + matches[1].rm_so))) conf_err("could not find engine"); if(!ENGINE_init(e)) { ENGINE_free(e); conf_err("could not init engine"); } if(!ENGINE_set_default(e, ENGINE_METHOD_ALL)) { ENGINE_free(e); conf_err("could not set all defaults"); } ENGINE_finish(e); ENGINE_free(e); #endif } else if(!regexec(&Control, lin, 4, matches, 0)) { if(ctrl_name != NULL) conf_err("Control multiply defined - aborted"); lin[matches[1].rm_eo] = '\0'; ctrl_name = strdup(lin + matches[1].rm_so); } else if(!regexec(&ListenHTTP, lin, 4, matches, 0)) { if(listeners == NULL) listeners = parse_HTTP(); else { for(lstn = listeners; lstn->next; lstn = lstn->next) ; lstn->next = parse_HTTP(); } } else if(!regexec(&ListenHTTPS, lin, 4, matches, 0)) { if(listeners == NULL) listeners = parse_HTTPS(); else { for(lstn = listeners; lstn->next; lstn = lstn->next) ; lstn->next = parse_HTTPS(); } } else if(!regexec(&Service, lin, 4, matches, 0)) { if(services == NULL) services = parse_service(NULL); else { for(svc = services; svc->next; svc = svc->next) ; svc->next = parse_service(NULL); } } else if(!regexec(&ServiceName, lin, 4, matches, 0)) { lin[matches[1].rm_eo] = '\0'; if(services == NULL) services = parse_service(lin + matches[1].rm_so); else { for(svc = services; svc->next; svc = svc->next) ; svc->next = parse_service(lin + matches[1].rm_so); } } else if(!regexec(&Anonymise, lin, 4, matches, 0)) { anonymise = 1; } else { conf_err("unknown directive - aborted"); } } return; } /* * prepare to parse the arguments/config file */ void config_parse(const int argc, char **const argv) { char *conf_name; FILE *f_conf; int c_opt, check_only; if(regcomp(&Empty, "^[ \t]*$", REG_ICASE | REG_NEWLINE | REG_EXTENDED) || regcomp(&Comment, "^[ \t]*#.*$", REG_ICASE | REG_NEWLINE | REG_EXTENDED) || regcomp(&User, "^[ \t]*User[ \t]+\"(.+)\"[ \t]*$", REG_ICASE | REG_NEWLINE | REG_EXTENDED) || regcomp(&Group, "^[ \t]*Group[ \t]+\"(.+)\"[ \t]*$", REG_ICASE | REG_NEWLINE | REG_EXTENDED) || regcomp(&RootJail, "^[ \t]*RootJail[ \t]+\"(.+)\"[ \t]*$", REG_ICASE | REG_NEWLINE | REG_EXTENDED) || regcomp(&Daemon, "^[ \t]*Daemon[ \t]+([01])[ \t]*$", REG_ICASE | REG_NEWLINE | REG_EXTENDED) || regcomp(&Threads, "^[ \t]*Threads[ \t]+([1-9][0-9]*)[ \t]*$", REG_ICASE | REG_NEWLINE | REG_EXTENDED) || regcomp(&LogFacility, "^[ \t]*LogFacility[ \t]+([a-z0-9-]+)[ \t]*$", REG_ICASE | REG_NEWLINE | REG_EXTENDED) || regcomp(&LogLevel, "^[ \t]*LogLevel[ \t]+([0-5])[ \t]*$", REG_ICASE | REG_NEWLINE | REG_EXTENDED) || regcomp(&Grace, "^[ \t]*Grace[ \t]+([0-9]+)[ \t]*$", REG_ICASE | REG_NEWLINE | REG_EXTENDED) || regcomp(&Alive, "^[ \t]*Alive[ \t]+([1-9][0-9]*)[ \t]*$", REG_ICASE | REG_NEWLINE | REG_EXTENDED) || regcomp(&SSLEngine, "^[ \t]*SSLEngine[ \t]+\"(.+)\"[ \t]*$", REG_ICASE | REG_NEWLINE | REG_EXTENDED) || regcomp(&Control, "^[ \t]*Control[ \t]+\"(.+)\"[ \t]*$", REG_ICASE | REG_NEWLINE | REG_EXTENDED) || regcomp(&ListenHTTP, "^[ \t]*ListenHTTP[ \t]*$", REG_ICASE | REG_NEWLINE | REG_EXTENDED) || regcomp(&ListenHTTPS, "^[ \t]*ListenHTTPS[ \t]*$", REG_ICASE | REG_NEWLINE | REG_EXTENDED) || regcomp(&End, "^[ \t]*End[ \t]*$", REG_ICASE | REG_NEWLINE | REG_EXTENDED) || regcomp(&Address, "^[ \t]*Address[ \t]+([^ \t]+)[ \t]*$", REG_ICASE | REG_NEWLINE | REG_EXTENDED) || regcomp(&Port, "^[ \t]*Port[ \t]+([1-9][0-9]*)[ \t]*$", REG_ICASE | REG_NEWLINE | REG_EXTENDED) || regcomp(&Cert, "^[ \t]*Cert[ \t]+\"(.+)\"[ \t]*$", REG_ICASE | REG_NEWLINE | REG_EXTENDED) || regcomp(&xHTTP, "^[ \t]*xHTTP[ \t]+([01234])[ \t]*$", REG_ICASE | REG_NEWLINE | REG_EXTENDED) || regcomp(&Client, "^[ \t]*Client[ \t]+([1-9][0-9]*)[ \t]*$", REG_ICASE | REG_NEWLINE | REG_EXTENDED) || regcomp(&CheckURL, "^[ \t]*CheckURL[ \t]+\"(.+)\"[ \t]*$", REG_ICASE | REG_NEWLINE | REG_EXTENDED) || regcomp(&Err414, "^[ \t]*Err414[ \t]+\"(.+)\"[ \t]*$", REG_ICASE | REG_NEWLINE | REG_EXTENDED) || regcomp(&Err500, "^[ \t]*Err500[ \t]+\"(.+)\"[ \t]*$", REG_ICASE | REG_NEWLINE | REG_EXTENDED) || regcomp(&Err501, "^[ \t]*Err501[ \t]+\"(.+)\"[ \t]*$", REG_ICASE | REG_NEWLINE | REG_EXTENDED) || regcomp(&Err503, "^[ \t]*Err503[ \t]+\"(.+)\"[ \t]*$", REG_ICASE | REG_NEWLINE | REG_EXTENDED) || regcomp(&MaxRequest, "^[ \t]*MaxRequest[ \t]+([1-9][0-9]*)[ \t]*$", REG_ICASE | REG_NEWLINE | REG_EXTENDED) || regcomp(&HeadRemove, "^[ \t]*HeadRemove[ \t]+\"(.+)\"[ \t]*$", REG_ICASE | REG_NEWLINE | REG_EXTENDED) || regcomp(&RewriteLocation, "^[ \t]*RewriteLocation[ \t]+([012])[ \t]*$", REG_ICASE | REG_NEWLINE | REG_EXTENDED) || regcomp(&RewriteDestination, "^[ \t]*RewriteDestination[ \t]+([01])[ \t]*$", REG_ICASE | REG_NEWLINE | REG_EXTENDED) || regcomp(&Service, "^[ \t]*Service[ \t]*$", REG_ICASE | REG_NEWLINE | REG_EXTENDED) || regcomp(&ServiceName, "^[ \t]*Service[ \t]+\"(.+)\"[ \t]*$", REG_ICASE | REG_NEWLINE | REG_EXTENDED) || regcomp(&URL, "^[ \t]*URL[ \t]+\"(.+)\"[ \t]*$", REG_ICASE | REG_NEWLINE | REG_EXTENDED) || regcomp(&HeadRequire, "^[ \t]*HeadRequire[ \t]+\"(.+)\"[ \t]*$", REG_ICASE | REG_NEWLINE | REG_EXTENDED) || regcomp(&HeadDeny, "^[ \t]*HeadDeny[ \t]+\"(.+)\"[ \t]*$", REG_ICASE | REG_NEWLINE | REG_EXTENDED) || regcomp(&BackEnd, "^[ \t]*BackEnd[ \t]*$", REG_ICASE | REG_NEWLINE | REG_EXTENDED) || regcomp(&Emergency, "^[ \t]*Emergency[ \t]*$", REG_ICASE | REG_NEWLINE | REG_EXTENDED) || regcomp(&Priority, "^[ \t]*Priority[ \t]+([1-9])[ \t]*$", REG_ICASE | REG_NEWLINE | REG_EXTENDED) || regcomp(&TimeOut, "^[ \t]*TimeOut[ \t]+([1-9][0-9]*)[ \t]*$", REG_ICASE | REG_NEWLINE | REG_EXTENDED) || regcomp(&HAport, "^[ \t]*HAport[ \t]+([1-9][0-9]*)[ \t]*$", REG_ICASE | REG_NEWLINE | REG_EXTENDED) || regcomp(&HAportAddr, "^[ \t]*HAport[ \t]+([^ \t]+)[ \t]+([1-9][0-9]*)[ \t]*$", REG_ICASE | REG_NEWLINE | REG_EXTENDED) || regcomp(&Redirect, "^[ \t]*Redirect[ \t]+\"(.+)\"[ \t]*$", REG_ICASE | REG_NEWLINE | REG_EXTENDED) || regcomp(&RedirectN, "^[ \t]*Redirect[ \t]+(30[127])[ \t]+\"(.+)\"[ \t]*$", REG_ICASE | REG_NEWLINE | REG_EXTENDED) || regcomp(&Session, "^[ \t]*Session[ \t]*$", REG_ICASE | REG_NEWLINE | REG_EXTENDED) || regcomp(&Type, "^[ \t]*Type[ \t]+([^ \t]+)[ \t]*$", REG_ICASE | REG_NEWLINE | REG_EXTENDED) || regcomp(&TTL, "^[ \t]*TTL[ \t]+([1-9-][0-9]*)[ \t]*$", REG_ICASE | REG_NEWLINE | REG_EXTENDED) || regcomp(&ID, "^[ \t]*ID[ \t]+\"(.+)\"[ \t]*$", REG_ICASE | REG_NEWLINE | REG_EXTENDED) || regcomp(&ClientCert, "^[ \t]*ClientCert[ \t]+([0-3])[ \t]+([1-9])[ \t]*$", REG_ICASE | REG_NEWLINE | REG_EXTENDED) || regcomp(&AddHeader, "^[ \t]*AddHeader[ \t]+\"(.+)\"[ \t]*$", REG_ICASE | REG_NEWLINE | REG_EXTENDED) || regcomp(&SSLAllowClientRenegotiation, "^[ \t]*SSLAllowClientRenegotiation[ \t]+([012])[ \t]*$", REG_ICASE | REG_NEWLINE | REG_EXTENDED) || regcomp(&DisableProto, "^[ \t]*Disable[ \t]+(SSLv2|SSLv3|TLSv1|TLSv1_1|TLSv1_2)[ \t]*$", REG_ICASE | REG_NEWLINE | REG_EXTENDED) || regcomp(&SSLHonorCipherOrder, "^[ \t]*SSLHonorCipherOrder[ \t]+([01])[ \t]*$", REG_ICASE | REG_NEWLINE | REG_EXTENDED) || regcomp(&Ciphers, "^[ \t]*Ciphers[ \t]+\"(.+)\"[ \t]*$", REG_ICASE | REG_NEWLINE | REG_EXTENDED) || regcomp(&CAlist, "^[ \t]*CAlist[ \t]+\"(.+)\"[ \t]*$", REG_ICASE | REG_NEWLINE | REG_EXTENDED) || regcomp(&VerifyList, "^[ \t]*VerifyList[ \t]+\"(.+)\"[ \t]*$", REG_ICASE | REG_NEWLINE | REG_EXTENDED) || regcomp(&CRLlist, "^[ \t]*CRLlist[ \t]+\"(.+)\"[ \t]*$", REG_ICASE | REG_NEWLINE | REG_EXTENDED) || regcomp(&NoHTTPS11, "^[ \t]*NoHTTPS11[ \t]+([0-2])[ \t]*$", REG_ICASE | REG_NEWLINE | REG_EXTENDED) || regcomp(&Include, "^[ \t]*Include[ \t]+\"(.+)\"[ \t]*$", REG_ICASE | REG_NEWLINE | REG_EXTENDED) || regcomp(&ConnTO, "^[ \t]*ConnTO[ \t]+([1-9][0-9]*)[ \t]*$", REG_ICASE | REG_NEWLINE | REG_EXTENDED) || regcomp(&IgnoreCase, "^[ \t]*IgnoreCase[ \t]+([01])[ \t]*$", REG_ICASE | REG_NEWLINE | REG_EXTENDED) || regcomp(&HTTPS, "^[ \t]*HTTPS[ \t]*$", REG_ICASE | REG_NEWLINE | REG_EXTENDED) || regcomp(&Disabled, "^[ \t]*Disabled[ \t]+([01])[ \t]*$", REG_ICASE | REG_NEWLINE | REG_EXTENDED) || regcomp(&CNName, ".*[Cc][Nn]=([-*.A-Za-z0-9]+).*$", REG_ICASE | REG_NEWLINE | REG_EXTENDED) || regcomp(&Anonymise, "^[ \t]*Anonymise[ \t]*$", REG_ICASE | REG_NEWLINE | REG_EXTENDED) #if OPENSSL_VERSION_NUMBER >= 0x0090800fL #ifndef OPENSSL_NO_ECDH || regcomp(&ECDHCurve, "^[ \t]*ECDHCurve[ \t]+\"(.+)\"[ \t]*$", REG_ICASE | REG_NEWLINE | REG_EXTENDED) #endif #endif ) { logmsg(LOG_ERR, "bad config Regex - aborted"); exit(1); } opterr = 0; check_only = 0; conf_name = F_CONF; pid_name = F_PID; while((c_opt = getopt(argc, argv, "f:cvVp:")) > 0) switch(c_opt) { case 'f': conf_name = optarg; break; case 'p': pid_name = optarg; break; case 'c': check_only = 1; break; case 'v': print_log = 1; break; case 'V': print_log = 1; logmsg(LOG_DEBUG, "Version %s", VERSION); logmsg(LOG_DEBUG, " Configuration switches:"); #ifdef C_SUPER if(strcmp(C_SUPER, "0")) logmsg(LOG_DEBUG, " --disable-super"); #endif #ifdef C_SSL if(strcmp(C_SSL, "")) logmsg(LOG_DEBUG, " --with-ssl=%s", C_SSL); #endif #ifdef C_T_RSA if(strcmp(C_T_RSA, "0")) logmsg(LOG_DEBUG, " --with-t_rsa=%s", C_T_RSA); #endif #ifdef C_MAXBUF if(strcmp(C_MAXBUF, "0")) logmsg(LOG_DEBUG, " --with-maxbuf=%s", C_MAXBUF); #endif #ifdef C_OWNER if(strcmp(C_OWNER, "")) logmsg(LOG_DEBUG, " --with-owner=%s", C_OWNER); #endif #ifdef C_GROUP if(strcmp(C_GROUP, "")) logmsg(LOG_DEBUG, " --with-group=%s", C_GROUP); #endif #ifdef C_DH_LEN if(strcmp(C_DH_LEN, "0")) logmsg(LOG_DEBUG, " --with-dh=%s", C_DH_LEN); #endif logmsg(LOG_DEBUG, "Exiting..."); exit(0); break; default: logmsg(LOG_ERR, "bad flag -%c", optopt); exit(1); break; } if(optind < argc) { logmsg(LOG_ERR, "unknown extra arguments (%s...)", argv[optind]); exit(1); } conf_init(conf_name); user = NULL; group = NULL; root_jail = NULL; ctrl_name = NULL; numthreads = 128; alive_to = 30; daemonize = 1; grace = 30; services = NULL; listeners = NULL; parse_file(); if(check_only) { logmsg(LOG_INFO, "Config file %s is OK", conf_name); exit(0); } if(listeners == NULL) { logmsg(LOG_ERR, "no listeners defined - aborted"); exit(1); } regfree(&Empty); regfree(&Comment); regfree(&User); regfree(&Group); regfree(&RootJail); regfree(&Daemon); regfree(&Threads); regfree(&LogFacility); regfree(&LogLevel); regfree(&Grace); regfree(&Alive); regfree(&SSLEngine); regfree(&Control); regfree(&ListenHTTP); regfree(&ListenHTTPS); regfree(&End); regfree(&Address); regfree(&Port); regfree(&Cert); regfree(&xHTTP); regfree(&Client); regfree(&CheckURL); regfree(&Err414); regfree(&Err500); regfree(&Err501); regfree(&Err503); regfree(&MaxRequest); regfree(&HeadRemove); regfree(&RewriteLocation); regfree(&RewriteDestination); regfree(&Service); regfree(&ServiceName); regfree(&URL); regfree(&HeadRequire); regfree(&HeadDeny); regfree(&BackEnd); regfree(&Emergency); regfree(&Priority); regfree(&TimeOut); regfree(&HAport); regfree(&HAportAddr); regfree(&Redirect); regfree(&RedirectN); regfree(&Session); regfree(&Type); regfree(&TTL); regfree(&ID); regfree(&ClientCert); regfree(&AddHeader); regfree(&SSLAllowClientRenegotiation); regfree(&DisableProto); regfree(&SSLHonorCipherOrder); regfree(&Ciphers); regfree(&CAlist); regfree(&VerifyList); regfree(&CRLlist); regfree(&NoHTTPS11); regfree(&Include); regfree(&ConnTO); regfree(&IgnoreCase); regfree(&HTTPS); regfree(&Disabled); regfree(&CNName); regfree(&Anonymise); #if OPENSSL_VERSION_NUMBER >= 0x0090800fL #ifndef OPENSSL_NO_ECDH regfree(&ECDHCurve); #endif #endif /* set the facility only here to ensure the syslog gets opened if necessary */ log_facility = def_facility; return; } Pound-2.8/README0000755000175000017500000010541613275266545012401 0ustar rosegrosegPOUND - REVERSE-PROXY AND LOAD-BALANCER The Pound program is a reverse proxy, load balancer and HTTPS front-end for Web server(s). Pound was developed to enable distributing the load among several Web-servers and to allow for a convenient SSL wrapper for those Web servers that do not offer it natively. Pound is distributed under the GPL - no warranty, it's free to use, copy and give away. WHAT POUND IS: 1. a reverse-proxy: it passes requests from client browsers to one or more back-end servers. 2. a load balancer: it will distribute the requests from the client browsers among several back-end servers, while keeping session information. 3. an SSL wrapper: Pound will decrypt HTTPS requests from client browsers and pass them as plain HTTP to the back-end servers. 4. an HTTP/HTTPS sanitizer: Pound will verify requests for correctness and accept only well-formed ones. 5. a fail over-server: should a back-end server fail, Pound will take note of the fact and stop passing requests to it until it recovers. 6. a request redirector: requests may be distributed among servers according to the requested URL. Pound is a very small program, easily audited for security problems. It can run as setuid/setgid and/or in a chroot jail. Pound does not access the hard-disk at all (except for reading certificate file(s) on start, if required) and should thus pose no security threat to any machine. WHAT POUND IS NOT: 1. Pound is not a Web server: by itself, Pound serves no content - it contacts the back-end server(s) for that purpose. 2. Pound is not a Web accelerator: no caching is done - every request is passed "as is" to a back-end server. STATUS As of release 1.0 Pound is declared to be production-quality code. Quite a few people have reported using Pound successfully in production environments. The largest volume reported to date is a site with an average of about 30M requests per day, peaking at over 600 requests/sec. Pound was successfully used in production with a variety of Web servers, including Apache, IIS, Zope, WebLogic, Jakarta/Tomcat, iPlanet, etc. In general Pound passes requests and responses back and forth unchanged, so we have no reason to think that any web server would be incompatible. Client browsers that were tested: - IE 5.0/5.5 (Windows) HTTP/HTTPS - Netscape 4.7 (Windows/Linux) HTTP/HTTPS - Mozilla (Windows/Linux) HTTP/HTTPS - Konqueror (Linux) HTTP/HTTPS - Galleon (Linux) HTTP/HTTPS - Opera (Linux/Windows) HTTP/HTTPS - Lynx (Linux) HTTP Given that Pound is in production and no problems were reported, we have no reason to believe that other browsers would present a problem. A few issues were observed with problematic SSL implementations, most notably with Opera 6, but these should be OK in the present version. INSTALLATION Probably the easiest way to install Pound is to use a pre-compiled package if you can find one. While Apsis offers no such packages, they are available for quite a few systems (Suse, Debian and derivatives such as Ubuntu), as well as some private packages: - RPMs for RedHat are available at http://www.invoca.ch/pub/packages/pound/ - A nice FreeBSD live-CD distribution is available at http://www.targeted.org as http://www.targeted.org/files/fbsd62_pound23.iso.gz, including a Pound binary. Failing that you should install from sources: 1. Pound was tested on Linux, Solaris and OpenBSD, but it should work unchanged on just about any modern Unix-like system. You will require at least OpenSSL and libpthread. The PCRE package is strongly recommended. Warning: as Pound is a multi-threaded program it requires a version of OpenSSL with thread support. This is normally the case on Linux and Solaris (for example) but not on *BSD. If your system has the wrong library please download, compile and install OpenSSL (from http://www.openssl.org). If the PCRE package is available Pound will link against it. This will provide a significant performance boost. 2. Download the current version of Pound-current file and unpack it. The archive is signed. My signature is available at http://www.apsis.ch/pound/roseg.asc. Alternately see below for stable versions. Unpack. Do the usual thing: ./configure 3. The following options are available for the configure script: --with-ssl=ssl_dir -- OpenSSL home directory (default: system defined). --disable-super -- disable supervisor process (default: enabled) --with-t_rsa=nnn -- timeout of the RSA ephemeral keys regeneration (default: 1800 seconds). --with-owner=owner -- name of installed binaries owner (default is system-dependent). --with-group=group -- name of installed binaries group (default is system-dependent). 4. Check that the resulting Makefile is correct and possibly adjust flags as needed on your system. Compile: make 5. If it works, you may want to do some testing before installing. 6. Install the executable somewhere (it's likely that /usr/local/sbin would make a good choice), as well as the manual page (pound.8 -> /usr/local/man/man8). The supplied Makefile will do it for you. 7. Make sure Pound gets started on boot. Read the man page for available options and examples. COPYRIGHT Pound is copyrighted by Apsis GmbH and is distributed under the terms of the GNU Public License with the additional exemption that compiling, linking, and/or using OpenSSL is allowed. Basically, this means that you can use it free of charge, copy it, distribute it (provided the copyright is maintained and the full package is distributed), modify it, or line a bird-cage with it. We would be happy to hear from you if you use it and suggestions and improvements are gladly accepted. CONTACT Robert Segall, roseg@apsis.ch Apsis GmbH, http://www.apsis.ch P O Box CH-8707 Uetikon am See Switzerland +41-44-920 4904 MAILING LIST Pound has its own mailing list now: please send a message with the subject "subscribe" to pound@apsis.ch in order to subscribe. You will receive confirmation and instructions in the reply. All messages are available and indexed (searcheable) in the archive http://www.apsis.ch/pound/pound_list. The mailing list is the primary support forum for Pound - please post there any questions you may have. The developpers' address is given here for information purposes only. ZOPE A special note for Zope users: the original intent on developing Pound was to allow distributing the load among several Zope servers running on top of ZEO. This it does. A special problem arises when you try using Pound as an SSL wrapper: Zope assumes that the requests are made via HTTP and insists on prepending 'http://' to the (correct) address in the replies, including in the tag and the absolute URLs it generates (for images for example). This is clearly an undesirable behavior. For older Zope versions (prior to 2.7): a modified z2.py (as well as a patch) is included in the distribution. The main difference is that this z2.py allows starting an additional HTTP server via the -y flag that sets the environment HTTPS variable - thus correcting the problem. That means that in order to use Pound as an SSL wrapper you need to: - start Zope (modify the 'start' file) as: python -X -w 8080 -y 8443 ... For Zope 2.7 or later the same effect can be achieved via suitable modifications to zope.conf. VIRTUAL HOSTS (IN GENERAL) Some people asked about the possibility of redirecting requests to back-ends as per some virtual hosts definition. While I believe this is not Pound's job, it can be done. As of version 0.10, Pound supports filtering requests based not only on the request URL, but also on the presence or absence of certain headers. Let's assume that you have internal server 192.168.0.10 that is supposed to serve the needs of virtual host www.server0.com and 192.168.0.11 that serves www.server1.com. You want Pound to listen on address 1.2.3.4 and separate the requests to each host. The config file would look something like this: ListenHTTP Address 1.2.3.4 Port 80 Service HeadRequire "Host: .*www.server0.com.*" BackEnd Address 192.168.0.10 Port 80 End End Service HeadRequire "Host: .*www.server1.com.*" BackEnd Address 192.168.0.11 Port 80 End End End (add whatever else is necessary) or, if you want even safer filtering: ListenHTTP Address 1.2.3.4 Port 80 Service HeadRequire "Host: .*www.server0.com.*" HeadDeny "Host: .*www.server1.com.*" BackEnd Address 192.168.0.10 Port 80 End End Service HeadRequire "Host: .*www.server1.com.*" HeadDeny "Host: .*www.server0.com.*" BackEnd Address 192.168.0.11 Port 80 End End End This is NOT recommended (I personally believe that virtual hosts should be implemented in the back-end servers - putting this in a proxy is a major security kludge) but it works. VIRTUAL HOSTS AND HTTPS Quite often we get inquiries about Pound's ability to do virtual hosting with HTTPS. In order to lay this matter to rest, let me say: HTTPS does not allow virtual hosting! This is not a limitation of Pound, but of HTTPS - no Web server or proxy are able to do it due to the nature of the beast. In order to see why this is the case we need to look at the way HTTPS works. Basically there are three stages in any HTTPS connection: 1. Connection negotiation - the client (your browser) and the server (Web server or proxy) negotiate the basic parameters: ciphers to use, session key, etc. 2. Connection authentication: at the very least the server presents the client with a certificate that says "I am server www.encrypted.com - and certificate.authority.org will verify that". The client may also present a certificate of its own at this stage. 3. Request/response cycle: normal HTTP is sent (through the encrypted channel) back and forth. The vital point to notice here is that connection authentication takes place BEFORE any request was issued. On the other hand, the way virtual hosting works is for the client to specify in the request to which server it would like to talk. This is accomplished via a Host header: GET /index.html HTTP/1.1 Host: http://www.virthost.com Combining the two we get to an impasse: on connection setup the server will reply with the certificate for "www.realhost.com", but the request is really for "www.virthost.com" - and most browsers will scream blue murder (as well they should) if the two do not match. There is a new twist on this however: some of the newer browsers will accept so-called "wild-card certificates". This is a specially crafted certificate that is not issued to a host, but rather to a domain. The result is that on setting-up a new SSL connection, the server replies not with "I am www.encrypted.com", but with "I am *.encrypted.com". If the browser is capable of processing this type of certificate then the connection is set up and normal HTTPS (with www.encrypted.com or special.encrypted.com or even some.other.server.encrypted.com or whatever other name matches) proceeds as usual. Pound supports these certificates and you can use virtual hosts in the normal way. Update June 2010: starting with the 2.6 series, Pound has SNI support, if your OpenSSL version supports it. Basically you supply Pound with several certificates, one for each virtual host (wild card certificates - as described above - are allowed). On connecting the client signals to which server it wants to talk, and Pound searches among its certificates which would fit. Not all versions of OpenSSL and not all clients support this mode, but if available it allows for virtual hosts over HTTPS. An additional option is to use a semi-official TLS extension, the so called alternate subject name. If your version of OpenSSL supports it you may specify in one certificate several alternate server names. This requires support for a special TLS feature, and nor all clients accept it. VIRTUAL HOSTS IN ZOPE For reasons I can't quite grasp, it seems that a lot of Zope users are convinced that virtual hosts are only possible through the Apache/VHM combination and that it requires some kind of magic incantation at midnight in order to work (I won't even start on the virgin sacrifices). The simple fact is that VHM and the Apache VirtualHost directives (as well as various tricks through mod_rewrite and mod_proxy) are (almost) mutually exclusive: they perform exactly the same functions and, leaving aside the logging issues, are used independently of each other. Let me repeat that: you may use the VHM without Apache - just click on the VHM mappings tab and add whatever virtual host you wish. From this moment on any request to that host will be mapped back and forth by Zope to the required URL. This works weather you access Zope directly or via any number of proxies on the way, Pound included. To test: add a new host name to your /etc/hosts file, making it an alias for localhost - something like:: 127.0.0.1 localhost www.testhost.mine Add a mapping in VHM from www.testhost.mine to some Zope folder (Examples is already there). Point your browser to http://localhost and you get the normal Zope start page; point it to http://www.testhost.mine and you'll see the Examples starting page. All requests are mapped correctly, and the URLs in the pages (such as base or absoluteURL) are translated correctly in the response. SESSIONS Pound has the ability to keep track of sessions between a client browser and a back-end server. Unfortunately, HTTP is defined as a stateless protocol, which complicates matters: many schemes have been invented to allow keeping track of sessions, none of which works perfectly. Even worse, sessions are critical in order to allow web-based applications to function correctly - it is vital that once a session is established all subsequent requests from the same browser be directed to the same back-end server. Six possible ways of detecting a session have been implemented in Pound (hopefully the most useful ones): by client address, by Basic authentication (user id/password), by URL parameter, by cookie, by HTTP parameter and by header value. - by client address: in this scheme Pound directs all requests from the same client IP address to the same back-end server. Put the lines Session Type IP TTL 300 End in the configuration file to achieve this effect. The value indicates what period of inactivity is allowed before the session is discarded. - by Basic Authentication: in this scheme Pound directs all requests from the same user (as identified in the Basic Authentication header) to the same back-end server. Put the lines Session Type Basic TTL 300 End in configuration file to achieve this effect. The value indicates what period of inactivity is allowed before the session is discarded. WARNING: given the constraints of the HTTP protocol it may very well be that the authenticated request will go to a different back-end server than the one originally requesting it. Make sure all your servers support the same authentication scheme! - by URL parameter: quite often session information is passed through URL parameters (the browser is pointed to something like http://xxx?id=123). Put the lines Session Type URL ID "id" TTL 300 End to support this scheme and the sessions will be tracked based on the value of the "id" parameter. - by cookie value: applications that use this method pass a certain cookie back and forth. Add the lines Session Type Cookie ID "sess" TTL 300 End to your configuration file - the sessions will be tracked by the value of the "sess" cookie. - by HTTP parameter value: applications that use this method pass an HTTP parameter (http://x.y/z;parameter) back and forth. Add the lines Session Type PARM TTL 300 End to your configuration file - the sessions will be tracked by the value of the parameter. - by header value: applications that use this method pass a certain header back and forth. Add the lines Session Type Header ID "X-sess" TTL 300 End to your configuration file - the sessions will be tracked by the value of the "X-sess" header. Please note the following restrictions on session tracking: - session tracking is always associated with a certain Service. Thus each group may have other methods and parameters. - there is no default session: if you have not defined any sessions no session tracking will be done. - only one session definition is allowed per Service. If your application has alternative methods for sessions you will have to define a separate Service for each method. A note on cookie injection: some applications have no session-tracking mechanism at all but would still like to have the client always directed to the same back-end time after time. Some reverse proxies use a mechanism called "cookie injection" in order to achieve this: a cookie is added to the back-end responses and tracked by the reverse proxy. Pound was designed to be as transparent as possible, and this mechanism is not supported. If you really need this sort of persistent mapping use the client address session mechanism (Session Type IP), which achieves the same result without changing the contents in any way. REQUEST LOGGING As a general rule, Pound passes all headers as they arrive from the client browser to the back-end server(s). There are two exceptions to this rule: Pound may add information about the SSL client certificate (as described below), and it will add an X-Forwarded-For header. The general format is: X-Forwarded-for: client-IP-address The back-end server(s) may use this extra information in order to create their log-files with the real client address (otherwise all requests will appear to originate from Pound itself, which is rather useless). In addition, Pound logs requests and replies to the system log. This is controlled by the LogLevel configuration variable (0 - no logging, 1 - normal log, 2 - full log, 3 - Apache combined log format, 4 - Apache combined log format without virtual host). By default the messages go to the LOG_DAEMON facility, but you can change this in the configuration file. If you don't want to, you can just do a: fgrep pound /var/log/messages to get all the messages generated by Pound. HTTPS CERTIFICATES If a client browser connects via HTTPS and if it presents a certificate and if HTTPSHeaders is set, Pound will obtain the certificate data and add the following HTTP headers to the request it makes to the server: - X-SSL-Subject: information about the certificate owner - X-SSL-Issuer: information about the certificate issuer (CA) - X-SSL-notBefore: begin validity date for the certificate - X-SSL-notAfter: end validity date for the certificate - X-SSL-serial: certificate serial number (in decimal) - X-SSL-cipher: the cipher currently in use - X-SSL-certificate: the full client certificate (multi-line) It is the application's responsibility to actually use these headers - Pound just passes this information without checking it in any way (except for signature and encryption correctness). Please note that this mechanism allows forgeries: a client may (maliciously) send these headers to Pound in order to masquerade as an SSL client with a specific certificate. If this is a problem for your application make sure to deny these requests. Add: HeadDeny "X-SSL-Subject:.*" HeadDeny "X-SSL-Issuer:.*" HeadDeny "X-SSL-notBefore:.*" HeadDeny "X-SSL-notAfter:.*" HeadDeny "X-SSL-serial:.*" HeadDeny "X-SSL-cipher:.*" within the Service(s). THREADS AND LIMITS A few people ran into problems when installing Pound because of the various threading models and how they interact with system-imposed limits. Please keep in mind the following requirements: - on most System V derived Unices (of which Linux up to 2.4 is one), a thread is a process. This means that when doing a 'ps' you will see as many processes with the name 'pound' as there are active threads. Each such process uses only two file descriptors, but the system needs to support the required number of processes, both in total and per user (possibly also per process group). In bash, this is 'ulimit -u', in csh this is 'limit maxproc'. - on BSD style systems all threads run in the same process space. Do a ps and you see a single 'pound' process. The process needs two file descriptors per active request (bash: 'ulimit -n', csh 'limit maxfiles'/'limit openfiles'). - on most systems the thread library comes with a built-in limit on the maximal number of concurrent threads allowed - on older systems it usually is 1024, on newer systems quite a bit higher. In very rare cases (very high load and long response times) you may run into this limitation - the symptom is log messages saying "can't create thread". Your only solution is to recompile the system threads library (and possibly the kernel itself) with a higher limit. Please note that your kernel needs to be configured to support the required resources - the above are just the shell commands. SIMILAR SYSTEMS Quite a few people asked "What is wrong with Apache/Squid/ stunnel/your_favorite? Do we really need another proxy system?". The simple answer is that there is nothing wrong - they are all excellent systems that do their jobs very well. The reasoning behind Pound is however slightly different: - In my experience, a load-balancer may easily become a bottle-neck in itself. If you have a heavily loaded site, there are few things more depressing than seeing your "load-balancer" slow down the entire network. This means that the load-balancer should be kept as light-weight as possible. - Security: auditing a large system for security issues is a major undertaking for anybody (ask Bill Gates about it). This implies that in order to avoid introducing new vulnerabilities into a system (after all, your installation is only as secure as its weakest component) the proxy/load-balancer should be kept as small as possible. - Protection: I assume Pound will be the only component exposed to the Internet - your back-end servers will run in a protected network behind it. This means that Pound should filter requests and make sure only valid, correctly formed ones are passed to the back-end servers, thus protecting them from malicious clients. Taking these criteria into consideration, it is easy to see why the other systems mentioned above do not fit: - Apache (with mod_proxy and mod_backhand): great system, but very large. Imposes a significant load on the system, complex set-up procedure (and it is so easy to get it wrong: check how many Apache servers allow proxying from and to external hosts). While Apache has proven remarkably exploit free, I wouldn't wish to go into a security audit for the tens of thousands of lines of code involved, not to mention all the additional modules. - Squid: great caching proxy, but even should load-balancing features become available in the future, do you really need caching on the load-balancer? After all, Pound can easily run on a disk-less system, whereas with Squid you'd better prepare a high throughput RAID. Squid is still perfectly usable as a caching proxy between Pound and the actual Web server, should it lack its own cache (which Zope happily has). - stunnel: probably comes closest to my understanding of software design (does one job only and does it very well). However, it lacks the load balancing and HTTP filtering features that I considered necessary. Using stunnel in front of Pound (for HTTPS) would have made sense, except that integrating HTTPS into Pound proved to be so simple that it was not worth the trouble. - your favourite system: let me know how it looks in light of the above criteria - I am always interested in new ideas. DEDICATED SERVERS Some people asked about the possibility of dedicating specific back-end servers to some clients - in other words, if a request originates from a certain IP address or group of addresses then it should be sent to a specific group of back-end servers. Given the ease with which IP addresses can be forged I am personally doubtful of the utility of such a feature. Even should you think it desirable, it is probably best implemented via the packet filter, rather than a proxy server. Assuming that requests from x.com are to go to s1.local, requests from y.com to s2.local and everything else to s3.local and s4.local, here is how to do it: - make sure your firewall blocks requests to port 8080, 8081 and 8082 - configure Pound as follows: ListenHTTP Address 127.0.0.1 Port 8080 Service BackEnd Address s1.local Port 80 End End End ListenHTTP Address 127.0.0.1 Port 8081 Service BackEnd Address s2.local Port 80 End End End ListenHTTP Address 127.0.0.1 Port 8082 Service BackEnd Address s3.local Port 80 End BackEnd Address s4.local Port 80 End End End - have your packet filter redirect requests to the right local ports based on the origin address. In OpenBSD pf syntax this would be something like: rdr on rl0 from x.com to myhost.com port 80 -> localhost port 8080 rdr on rl0 from y.com to myhost.com port 80 -> localhost port 8081 rdr on rl0 from any to myhost.com port 80 -> localhost port 8082 or in Linux iptables:: iptables -t nat -A PREROUTING -p tcp -s x.com --dport 80 -i eth0 \ -j DNAT --to 127.0.0.1:8080 iptables -t nat -A PREROUTING -p tcp -s y.com --dport 80 -i eth0 \ -j DNAT --to 127.0.0.1:8081 iptables -t nat -A PREROUTING -p tcp --dport 80 -i eth0 -j DNAT \ --to 127.0.0.1:8082 This would give you the desired effect and probably better performance than a purely proxy-based solution (though the performance improvement is debatable, at least on Linux). WebDAV As of version 1.0 Pound supports the full WebDAV command-set. In fact, it has been tested and is known to (almost) work with the Microsoft Outlook Web Gateway, which is quite remarkable given that Microsoft's own proxy does not. Regrettably, Microsoft adherence to standards leaves something to be desired: they decided to add some characters to their URLs - thus breaking a whole set of RFC's. Rather then change Pound to accept these characters (which could create some serious issues with security on other systems) we have made this behaviour dependent on a configuration switch: xHTTP (see the man page for details). If you also use the SSL wrapper feature in front of a Microsoft server you should probably also add 'AddHeader "Front-End-Https: on"'. These changes are also required to access a Subversion server via Pound. OTHER ISSUES The following problems were reported by various people who use pound: - delays in loading pages when the client browser is IE 5.5 (possibly limited to W2K/XP). It seems that IE opens exactly 4 connections (sockets) to the server and keeps them open until some time-out or until the server closes the connection. This works fine, unless you redirect IE to another server - given that all 4 sockets are used IE waits for a while before the redirect is actually performed. Solution: use the directive "Client 1" to ensure that Pound closes sockets very early, thus freeing the necessary resources. Experiment with the time-out - as it may cause problems with slow connections. - Pound fails to start; HTTPS is enabled and the message "can't read private key from file xxx" appears in the log. Solution: make sure that the certificate file includes: - (optional) a chain of certificates from a known certificate authority to your server certificate - the server certificate - the private key; the key may NOT be password-protected The file should be in PEM format. The OpenSSL command to generate a self-signed certificate in the correct format would be something like:: openssl req -x509 -newkey rsa:1024 -keyout test.pem -out test.pem \ -days 365 -nodes Note the '-nodes' flag - it's important! - Pound fails to operate correctly with SSL when RootJail is specified. Solution: OpenSSL requires access to /dev/urandom, so make sure such a device is accessible from the root jail directory. Thus if your root jail is something like /var/pound: mkdir /var/pound/dev mknod /var/pound/dev/urandom c 1 9 or whatever major/minor number are appropriate for your system. - In chroot mode logging may stop functioning. Solution: make sure /dev and the root jail are on the same filesystem and create a hard link in the root jail to /dev/log: mkdir /chroot/jail/dev ln /dev/log /chroot/jail/dev/log Alternately you can have syslog (or syslog-ng) listen on another socket - see the man page for details. - In chroot mode name resolution (and especially redirects) may stop functioning. Solution: make sure your resolver works correctly in the jail. You probably need copies of /etc/resolv.conf and (at least part) of /etc/hosts. Depending on your system additional files may be required check your resolver man page for details. Should name resolution fail the translation of host names to IP addresses would fail, thereby defeating the mechanism Pound uses to identify when should a Redirect be rewritten. - IE 5.x fails to work (correctly or at all) with Pound in HTTPS mode. Solution: define the supported OpenSSL ciphers for IE compatibility (this is really a work-around for a known IE bug): Ciphers "ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP:+eNULL" (Thanks to Andi Roedl for the tip). - Linux-specific: some people use various redundant Pound solutions for Linux which require Pound instances on separate machines to bind to the same address. The default configuration of Linux does not allow a program to bind() to non-local addresses, which may cause a problem. Solution: add echo 1 > /proc/sys/net/ipv4/ip_nonlocal_bind in your start-up script, or just set net.ipv4.ip_nonlocal_bind = 1 in /etc/sysctl.conf (if you have one). (Thanks to RUne Saetre for the suggestion). ACKNOWLEDGMENTS Albert (of Alacra) for investigating and writing the TCP_NODELAY code. Luuk de Boer did some serious testing and debugging of the WebDAV code for Microsoft servers. Alession Cervellin packages and makes available Solaris packages for various Pound versions. David Couture found some nasty, lurking bugs, as well as contributing some serious testing on big hardware. Frank Denis contributed a few excellent code patches and some good ideas. Dmitriy Dvoinikov makes available a live-CD FreeBSD distribution that includes a Pound binary. Abner G. Jacobsen did a lot of testing in a production environment and contributed some very nice ideas. Akira Higuchi found a significant security issue in Pound and contributed the code to fix it. Ken Lalonde contributed very useful remarks and suggestions, as well as correcting a few code errors. Phil Lodwick contributed essential parts of the high-availability code and came up with some good ideas. In addition, did some serious testing under heavy loads. Simon Matter packages and makes available RPMs for various Pound versions. Jan-Piet Mens raised some interesting security points about the HTTPS implementation and brought the original idea for SSL header filtering. Andreas Roedl for testing and some ideas about logging in root jails. Gurkan Sengun tested Pound on Solaris, contributed the Solaris cc flags and makes a Solaris pre-compiled version available on his Web-site (www.linuks.mine.nu) Shinji Tanaka contributed a patch for controlling logging to disk files. This is available at http://www.hatena-inc.co.jp/~stanaka/pound/ Jim Washington contributed the code for WebDAV and tested it. Maxime Yve discovered a nasty bug in the session tracking code and contributed the patch to fix it. All the others who tested Pound and told me about their results. Pound-2.8/install-sh0000755000175000017500000001273613275266545013524 0ustar rosegroseg#!/bin/sh # # install - install a program, script, or datafile # This comes from X11R5 (mit/util/scripts/install.sh). # # Copyright 1991 by the Massachusetts Institute of Technology # # Permission to use, copy, modify, distribute, and sell this software and its # documentation for any purpose is hereby granted without fee, 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 M.I.T. not be used in advertising or # publicity pertaining to distribution of the software without specific, # written prior permission. M.I.T. makes no representations about the # suitability of this software for any purpose. It is provided "as is" # without express or implied warranty. # # Calling this script install-sh is preferred over install.sh, to prevent # `make' implicit rules from creating a file called install from it # when there is no Makefile. # # This script is compatible with the BSD install script, but was written # from scratch. It can only install one file at a time, a restriction # shared with many OS's install programs. # set DOITPROG to echo to test this script # Don't use :- since 4.3BSD and earlier shells don't like it. doit="${DOITPROG-}" # put in absolute paths if you don't have them in your path; or use env. vars. mvprog="${MVPROG-mv}" cpprog="${CPPROG-cp}" chmodprog="${CHMODPROG-chmod}" chownprog="${CHOWNPROG-chown}" chgrpprog="${CHGRPPROG-chgrp}" stripprog="${STRIPPROG-strip}" rmprog="${RMPROG-rm}" mkdirprog="${MKDIRPROG-mkdir}" transformbasename="" transform_arg="" instcmd="$mvprog" chmodcmd="$chmodprog 0755" chowncmd="" chgrpcmd="" stripcmd="" rmcmd="$rmprog -f" mvcmd="$mvprog" src="" dst="" dir_arg="" while [ x"$1" != x ]; do case $1 in -c) instcmd="$cpprog" shift continue;; -d) dir_arg=true shift continue;; -m) chmodcmd="$chmodprog $2" shift shift continue;; -o) chowncmd="$chownprog $2" shift shift continue;; -g) chgrpcmd="$chgrpprog $2" shift shift continue;; -s) stripcmd="$stripprog" shift continue;; -t=*) transformarg=`echo $1 | sed 's/-t=//'` shift continue;; -b=*) transformbasename=`echo $1 | sed 's/-b=//'` shift continue;; *) if [ x"$src" = x ] then src=$1 else # this colon is to work around a 386BSD /bin/sh bug : dst=$1 fi shift continue;; esac done if [ x"$src" = x ] then echo "install: no input file specified" exit 1 else true fi if [ x"$dir_arg" != x ]; then dst=$src src="" if [ -d $dst ]; then instcmd=: chmodcmd="" else instcmd=mkdir fi else # Waiting for this to be detected by the "$instcmd $src $dsttmp" command # might cause directories to be created, which would be especially bad # if $src (and thus $dsttmp) contains '*'. if [ -f $src -o -d $src ] then true else echo "install: $src does not exist" exit 1 fi if [ x"$dst" = x ] then echo "install: no destination specified" exit 1 else true fi # If destination is a directory, append the input filename; if your system # does not like double slashes in filenames, you may need to add some logic if [ -d $dst ] then dst="$dst"/`basename $src` else true fi fi ## this sed command emulates the dirname command dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'` # Make sure that the destination directory exists. # this part is taken from Noah Friedman's mkinstalldirs script # Skip lots of stat calls in the usual case. if [ ! -d "$dstdir" ]; then defaultIFS=' ' IFS="${IFS-${defaultIFS}}" oIFS="${IFS}" # Some sh's can't handle IFS=/ for some reason. IFS='%' set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'` IFS="${oIFS}" pathcomp='' while [ $# -ne 0 ] ; do pathcomp="${pathcomp}${1}" shift if [ ! -d "${pathcomp}" ] ; then $mkdirprog "${pathcomp}" else true fi pathcomp="${pathcomp}/" done fi if [ x"$dir_arg" != x ] then $doit $instcmd $dst && if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi && if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi && if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi && if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi else # If we're going to rename the final executable, determine the name now. if [ x"$transformarg" = x ] then dstfile=`basename $dst` else dstfile=`basename $dst $transformbasename | sed $transformarg`$transformbasename fi # don't allow the sed command to completely eliminate the filename if [ x"$dstfile" = x ] then dstfile=`basename $dst` else true fi # Make a temp file name in the proper directory. dsttmp=$dstdir/#inst.$$# # Move or copy the file name to the temp name $doit $instcmd $src $dsttmp && trap "rm -f ${dsttmp}" 0 && # and set any options; do chmod last to preserve setuid bits # If any of these fail, we abort the whole thing. If we want to # ignore errors from any of these, just make sure not to ignore # errors from the above "$doit $instcmd $src $dsttmp" command. if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi && if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi && if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi && if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi && # Now rename the file to the real destination. $doit $rmcmd -f $dstdir/$dstfile && $doit $mvcmd $dsttmp $dstdir/$dstfile fi && exit 0 Pound-2.8/GPL.txt0000755000175000017500000010451313275266545012701 0ustar rosegroseg GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The GNU General Public License is a free, copyleft license for software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things. To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others. For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it. For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions. Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users. Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free. The precise terms and conditions for copying, distribution and modification follow. TERMS AND CONDITIONS 0. Definitions. "This License" refers to version 3 of the GNU General Public License. "Copyright" also means copyright-like laws that apply to other kinds of works, such as semiconductor masks. "The Program" refers to any copyrightable work licensed under this License. Each licensee is addressed as "you". "Licensees" and "recipients" may be individuals or organizations. To "modify" a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a "modified version" of the earlier work or a work "based on" the earlier work. A "covered work" means either the unmodified Program or a work based on the Program. To "propagate" a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well. To "convey" a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying. An interactive user interface displays "Appropriate Legal Notices" to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion. 1. Source Code. The "source code" for a work means the preferred form of the work for making modifications to it. "Object code" means any non-source form of a work. A "Standard Interface" means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language. The "System Libraries" of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A "Major Component", in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it. The "Corresponding Source" for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work. The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source. The Corresponding Source for a work in source code form is that same work. 2. Basic Permissions. All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law. You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you. Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary. 3. Protecting Users' Legal Rights From Anti-Circumvention Law. No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures. When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures. 4. Conveying Verbatim Copies. You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program. You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee. 5. Conveying Modified Source Versions. You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions: a) The work must carry prominent notices stating that you modified it, and giving a relevant date. b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to "keep intact all notices". c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it. d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so. A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an "aggregate" if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate. 6. Conveying Non-Source Forms. You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways: a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange. b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge. c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b. d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements. e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d. A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work. A "User Product" is either (1) a "consumer product", which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, "normally used" refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product. "Installation Information" for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made. If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM). The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network. Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying. 7. Additional Terms. "Additional permissions" are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions. When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission. Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms: a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or d) Limiting the use for publicity purposes of names of licensors or authors of the material; or e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors. All other non-permissive additional terms are considered "further restrictions" within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying. If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms. Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way. 8. Termination. You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11). However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10. 9. Acceptance Not Required for Having Copies. You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so. 10. Automatic Licensing of Downstream Recipients. Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License. An "entity transaction" is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts. You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it. 11. Patents. A "contributor" is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's "contributor version". A contributor's "essential patent claims" are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, "control" includes the right to grant patent sublicenses in a manner consistent with the requirements of this License. Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version. In the following three paragraphs, a "patent license" is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To "grant" such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party. If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. "Knowingly relying" means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid. If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it. A patent license is "discriminatory" if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007. Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law. 12. No Surrender of Others' Freedom. If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program. 13. Use with the GNU Affero General Public License. Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such. 14. Revised Versions of this License. The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation. If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program. Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version. 15. Disclaimer of Warranty. THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. Limitation of Liability. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 17. Interpretation of Sections 15 and 16. If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . Also add information on how to contact you by electronic and paper mail. If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode: Copyright (C) This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, your program's commands might be different; for a GUI interface, you would use an "about box". You should also get your employer (if you work as a programmer) or school, if any, to sign a "copyright disclaimer" for the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, see . The GNU General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read . Pound-2.8/svc.c0000644000175000017500000014646013275266545012461 0ustar rosegroseg/* * Pound - the reverse-proxy load-balancer * Copyright (C) 2002-2010 Apsis GmbH * * This file is part of Pound. * * Pound is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * Pound is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * Contact information: * Apsis GmbH * P.O.Box * 8707 Uetikon am See * Switzerland * EMail: roseg@apsis.ch */ #include "pound.h" #ifndef LHASH_OF #define LHASH_OF(x) LHASH #define CHECKED_LHASH_OF(type, h) h #endif /* * Add a new key/content pair to a hash table * the table should be already locked */ static void t_add(LHASH_OF(TABNODE) *const tab, const char *key, const void *content, const size_t cont_len) { TABNODE *t, *old; if((t = (TABNODE *)malloc(sizeof(TABNODE))) == NULL) { logmsg(LOG_WARNING, "t_add() content malloc"); return; } if((t->key = strdup(key)) == NULL) { free(t); logmsg(LOG_WARNING, "t_add() strdup"); return; } if((t->content = malloc(cont_len)) == NULL) { free(t->key); free(t); logmsg(LOG_WARNING, "t_add() content malloc"); return; } memcpy(t->content, content, cont_len); t->last_acc = time(NULL); #if OPENSSL_VERSION_NUMBER >= 0x10000000L if((old = LHM_lh_insert(TABNODE, tab, t)) != NULL) { #else if((old = (TABNODE *)lh_insert(tab, t)) != NULL) { #endif free(old->key); free(old->content); free(old); logmsg(LOG_WARNING, "t_add() DUP"); } return; } /* * Find a key * returns the content in the parameter * side-effect: update the time of last access */ static void * t_find(LHASH_OF(TABNODE) *const tab, char *const key) { TABNODE t, *res; t.key = key; #if OPENSSL_VERSION_NUMBER >= 0x10000000L if((res = (TABNODE *)LHM_lh_retrieve(TABNODE, tab, &t)) != NULL) { #else if((res = (TABNODE *)lh_retrieve(tab, &t)) != NULL) { #endif res->last_acc = time(NULL); return res->content; } return NULL; } /* * Delete a key */ static void t_remove(LHASH_OF(TABNODE) *const tab, char *const key) { TABNODE t, *res; t.key = key; #if OPENSSL_VERSION_NUMBER >= 0x10000000L if((res = LHM_lh_delete(TABNODE, tab, &t)) != NULL) { #else if((res = (TABNODE *)lh_delete(tab, &t)) != NULL) { #endif free(res->key); free(res->content); free(res); } return; } typedef struct { LHASH_OF(TABNODE) *tab; time_t lim; void *content; int cont_len; } ALL_ARG; static void t_old_doall_arg(TABNODE *t, ALL_ARG *a) { TABNODE *res; if(t->last_acc < a->lim) #if OPENSSL_VERSION_NUMBER >= 0x10000000L if((res = LHM_lh_delete(TABNODE, a->tab, t)) != NULL) { #else if((res = lh_delete(a->tab, t)) != NULL) { #endif free(res->key); free(res->content); free(res); } return; } #if OPENSSL_VERSION_NUMBER >= 0x10000000L IMPLEMENT_LHASH_DOALL_ARG_FN(t_old, TABNODE, ALL_ARG) #else #define t_old t_old_doall_arg IMPLEMENT_LHASH_DOALL_ARG_FN(t_old, TABNODE *, ALL_ARG *) #endif /* * Expire all old nodes */ static void t_expire(LHASH_OF(TABNODE) *const tab, const time_t lim) { ALL_ARG a; int down_load; a.tab = tab; a.lim = lim; down_load = CHECKED_LHASH_OF(TABNODE, tab)->down_load; CHECKED_LHASH_OF(TABNODE, tab)->down_load = 0; #if OPENSSL_VERSION_NUMBER >= 0x10000000L LHM_lh_doall_arg(TABNODE, tab, LHASH_DOALL_ARG_FN(t_old), ALL_ARG, &a); #else lh_doall_arg(tab, LHASH_DOALL_ARG_FN(t_old), &a); #endif CHECKED_LHASH_OF(TABNODE, tab)->down_load = down_load; return; } static void t_cont_doall_arg(TABNODE *t, ALL_ARG *arg) { TABNODE *res; if(memcmp(t->content, arg->content, arg->cont_len) == 0) #if OPENSSL_VERSION_NUMBER >= 0x10000000L if((res = LHM_lh_delete(TABNODE, arg->tab, t)) != NULL) { #else if((res = lh_delete(arg->tab, t)) != NULL) { #endif free(res->key); free(res->content); free(res); } return; } #if OPENSSL_VERSION_NUMBER >= 0x10000000L IMPLEMENT_LHASH_DOALL_ARG_FN(t_cont, TABNODE, ALL_ARG) #else #define t_cont t_cont_doall_arg IMPLEMENT_LHASH_DOALL_ARG_FN(t_cont, TABNODE *, ALL_ARG *) #endif /* * Remove all nodes with the given content */ static void t_clean(LHASH_OF(TABNODE) *const tab, void *const content, const size_t cont_len) { ALL_ARG a; int down_load; a.tab = tab; a.content = content; a.cont_len = cont_len; down_load = CHECKED_LHASH_OF(TABNODE, tab)->down_load; CHECKED_LHASH_OF(TABNODE, tab)->down_load = 0; #if OPENSSL_VERSION_NUMBER >= 0x10000000L LHM_lh_doall_arg(TABNODE, tab, LHASH_DOALL_ARG_FN(t_cont), ALL_ARG, &a); #else lh_doall_arg(tab, LHASH_DOALL_ARG_FN(t_cont), &a); #endif CHECKED_LHASH_OF(TABNODE, tab)->down_load = down_load; return; } /* * Log an error to the syslog or to stderr */ #ifdef HAVE_STDARG_H void logmsg(const int priority, const char *fmt, ...) { char buf[MAXBUF + 1]; va_list ap; struct tm *t_now, t_res; buf[MAXBUF] = '\0'; va_start(ap, fmt); vsnprintf(buf, MAXBUF, fmt, ap); va_end(ap); if(log_facility == -1) { fprintf((priority == LOG_INFO || priority == LOG_DEBUG)? stdout: stderr, "%s\n", buf); } else { if(print_log) printf("%s\n", buf); else syslog(log_facility | priority, "%s", buf); } return; } #else void logmsg(const int priority, const char *fmt, va_alist) va_dcl { char buf[MAXBUF + 1]; va_list ap; struct tm *t_now, t_res; buf[MAXBUF] = '\0'; va_start(ap); vsnprintf(buf, MAXBUF, fmt, ap); va_end(ap); if(log_facility == -1) { fprintf((priority == LOG_INFO || priority == LOG_DEBUG)? stdout: stderr, "%s\n", buf); } else { if(print_log) printf("%s\n", buf); else syslog(log_facility | priority, "%s", buf); } return; } #endif /* * Translate inet/inet6 address/port into a string */ void addr2str(char *const res, const int res_len, const struct addrinfo *addr, const int no_port) { char buf[MAXBUF]; int port; void *src; memset(res, 0, res_len); #ifdef HAVE_INET_NTOP switch(addr->ai_family) { case AF_INET: src = (void *)&((struct sockaddr_in *)addr->ai_addr)->sin_addr.s_addr; port = ntohs(((struct sockaddr_in *)addr->ai_addr)->sin_port); if(inet_ntop(AF_INET, src, buf, MAXBUF - 1) == NULL) strncpy(buf, "(UNKNOWN)", MAXBUF - 1); break; case AF_INET6: src = (void *)&((struct sockaddr_in6 *)addr->ai_addr)->sin6_addr.s6_addr; port = ntohs(((struct sockaddr_in6 *)addr->ai_addr)->sin6_port); if(inet_ntop(AF_INET6, src, buf, MAXBUF - 1) == NULL) strncpy(buf, "(UNKNOWN)", MAXBUF - 1); break; case AF_UNIX: strncpy(buf, (char *)addr->ai_addr, MAXBUF - 1); port = 0; break; default: strncpy(buf, "(UNKNOWN)", MAXBUF - 1); port = 0; break; } if(no_port) snprintf(res, res_len, "%s", buf); else snprintf(res, res_len, "%s:%d", buf, port); #else #error "Pound needs inet_ntop()" #endif return; } /* * Parse a URL, possibly decoding hexadecimal-encoded characters */ int cpURL(char *res, char *src, int len) { int state; char *kp_res; for(kp_res = res, state = 0; len > 0; len--) switch(state) { case 1: if(*src >= '0' && *src <= '9') { *res = *src++ - '0'; state = 2; } else if(*src >= 'A' && *src <= 'F') { *res = *src++ - 'A' + 10; state = 2; } else if(*src >= 'a' && *src <= 'f') { *res = *src++ - 'a' + 10; state = 2; } else { *res++ = '%'; *res++ = *src++; state = 0; } break; case 2: if(*src >= '0' && *src <= '9') { *res = *res * 16 + *src++ - '0'; res++; state = 0; } else if(*src >= 'A' && *src <= 'F') { *res = *res * 16 + *src++ - 'A' + 10; res++; state = 0; } else if(*src >= 'a' && *src <= 'f') { *res = *res * 16 + *src++ - 'a' + 10; res++; state = 0; } else { *res++ = '%'; *res++ = *(src - 1); *res++ = *src++; state = 0; } break; default: if(*src != '%') *res++ = *src++; else { src++; state = 1; } break; } if(state > 0) *res++ = '%'; if(state > 1) *res++ = *(src - 1); *res = '\0'; return res - kp_res; } /* * Parse a header * return a code and possibly content in the arg */ int check_header(const char *header, char *const content) { regmatch_t matches[4]; static struct { char header[32]; int len; int val; } hd_types[] = { { "Transfer-encoding", 17, HEADER_TRANSFER_ENCODING }, { "Content-length", 14, HEADER_CONTENT_LENGTH }, { "Connection", 10, HEADER_CONNECTION }, { "Location", 8, HEADER_LOCATION }, { "Content-location", 16, HEADER_CONTLOCATION }, { "Host", 4, HEADER_HOST }, { "Referer", 7, HEADER_REFERER }, { "User-agent", 10, HEADER_USER_AGENT }, { "Destination", 11, HEADER_DESTINATION }, { "Expect", 6, HEADER_EXPECT }, { "", 0, HEADER_OTHER }, }; int i; if(!regexec(&HEADER, header, 4, matches, 0)) { for(i = 0; hd_types[i].len > 0; i++) if((matches[1].rm_eo - matches[1].rm_so) == hd_types[i].len && strncasecmp(header + matches[1].rm_so, hd_types[i].header, hd_types[i].len) == 0) { /* we know that the original header was read into a buffer of size MAXBUF, so no overflow */ strncpy(content, header + matches[2].rm_so, matches[2].rm_eo - matches[2].rm_so); content[matches[2].rm_eo - matches[2].rm_so] = '\0'; return hd_types[i].val; } return HEADER_OTHER; } else return HEADER_ILLEGAL; } static int match_service(const SERVICE *svc, const char *request, char **const headers) { MATCHER *m; int i, found; /* check for request */ for(m = svc->url; m; m = m->next) if(regexec(&m->pat, request, 0, NULL, 0)) return 0; /* check for required headers */ for(m = svc->req_head; m; m = m->next) { for(found = i = 0; i < (MAXHEADERS - 1) && !found; i++) if(headers[i] && !regexec(&m->pat, headers[i], 0, NULL, 0)) found = 1; if(!found) return 0; } /* check for forbidden headers */ for(m = svc->deny_head; m; m = m->next) { for(found = i = 0; i < (MAXHEADERS - 1) && !found; i++) if(headers[i] && !regexec(&m->pat, headers[i], 0, NULL, 0)) found = 1; if(found) return 0; } return 1; } /* * Find the right service for a request */ SERVICE * get_service(const LISTENER *lstn, const char *request, char **const headers) { SERVICE *svc; for(svc = lstn->services; svc; svc = svc->next) { if(svc->disabled) continue; if(match_service(svc, request, headers)) return svc; } /* try global services */ for(svc = services; svc; svc = svc->next) { if(svc->disabled) continue; if(match_service(svc, request, headers)) return svc; } /* nothing matched */ return NULL; } /* * extract the session key for a given request */ static int get_REQUEST(char *res, const SERVICE *svc, const char *request) { int n, s; regmatch_t matches[4]; if(regexec(&svc->sess_start, request, 4, matches, 0)) { res[0] = '\0'; return 0; } s = matches[0].rm_eo; if(regexec(&svc->sess_pat, request + s, 4, matches, 0)) { res[0] = '\0'; return 0; } if((n = matches[1].rm_eo - matches[1].rm_so) > KEY_SIZE) n = KEY_SIZE; strncpy(res, request + s + matches[1].rm_so, n); res[n] = '\0'; return 1; } static int get_HEADERS(char *res, const SERVICE *svc, char **const headers) { int i, n, s; regmatch_t matches[4]; /* this will match SESS_COOKIE, SESS_HEADER and SESS_BASIC */ res[0] = '\0'; for(i = 0; i < (MAXHEADERS - 1); i++) { if(headers[i] == NULL) continue; if(regexec(&svc->sess_start, headers[i], 4, matches, 0)) continue; s = matches[0].rm_eo; if(regexec(&svc->sess_pat, headers[i] + s, 4, matches, 0)) continue; if((n = matches[1].rm_eo - matches[1].rm_so) > KEY_SIZE) n = KEY_SIZE; strncpy(res, headers[i] + s + matches[1].rm_so, n); res[n] = '\0'; } return res[0] != '\0'; } /* * Pick a random back-end from a candidate list */ static BACKEND * rand_backend(BACKEND *be, int pri) { while(be) { if(!be->alive || be->disabled) { be = be->next; continue; } if((pri -= be->priority) < 0) break; be = be->next; } return be; } /* * return a back-end based on a fixed hash value * this is used for session_ttl < 0 * * WARNING: the function may return different back-ends * if the target back-end is disabled or not alive */ static BACKEND * hash_backend(BACKEND *be, int abs_pri, char *key) { unsigned long hv; BACKEND *res, *tb; int pri; hv = 2166136261; while(*key) hv = ((hv ^ *key++) * 16777619) & 0xFFFFFFFF; pri = hv % abs_pri; for(tb = be; tb; tb = tb->next) if((pri -= tb->priority) < 0) break; if(!tb) /* should NEVER happen */ return NULL; for(res = tb; !res->alive || res->disabled; ) { res = res->next; if(res == NULL) res = be; if(res == tb) /* NO back-end available */ return NULL; } return res; } /* * Find the right back-end for a request */ BACKEND * get_backend(SERVICE *const svc, const struct addrinfo *from_host, const char *request, char **const headers) { BACKEND *res; char key[KEY_SIZE + 1]; int ret_val, no_be; void *vp; if(ret_val = pthread_mutex_lock(&svc->mut)) logmsg(LOG_WARNING, "get_backend() lock: %s", strerror(ret_val)); no_be = (svc->tot_pri <= 0); switch(svc->sess_type) { case SESS_NONE: /* choose one back-end randomly */ res = no_be? svc->emergency: rand_backend(svc->backends, random() % svc->tot_pri); break; case SESS_IP: addr2str(key, KEY_SIZE, from_host, 1); if(svc->sess_ttl < 0) res = no_be? svc->emergency: hash_backend(svc->backends, svc->abs_pri, key); else if((vp = t_find(svc->sessions, key)) == NULL) { if(no_be) res = svc->emergency; else { /* no session yet - create one */ res = rand_backend(svc->backends, random() % svc->tot_pri); t_add(svc->sessions, key, &res, sizeof(res)); } } else memcpy(&res, vp, sizeof(res)); break; case SESS_URL: case SESS_PARM: if(get_REQUEST(key, svc, request)) { if(svc->sess_ttl < 0) res = no_be? svc->emergency: hash_backend(svc->backends, svc->abs_pri, key); else if((vp = t_find(svc->sessions, key)) == NULL) { if(no_be) res = svc->emergency; else { /* no session yet - create one */ res = rand_backend(svc->backends, random() % svc->tot_pri); t_add(svc->sessions, key, &res, sizeof(res)); } } else memcpy(&res, vp, sizeof(res)); } else { res = no_be? svc->emergency: rand_backend(svc->backends, random() % svc->tot_pri); } break; default: /* this works for SESS_BASIC, SESS_HEADER and SESS_COOKIE */ if(get_HEADERS(key, svc, headers)) { if(svc->sess_ttl < 0) res = no_be? svc->emergency: hash_backend(svc->backends, svc->abs_pri, key); else if((vp = t_find(svc->sessions, key)) == NULL) { if(no_be) res = svc->emergency; else { /* no session yet - create one */ res = rand_backend(svc->backends, random() % svc->tot_pri); t_add(svc->sessions, key, &res, sizeof(res)); } } else memcpy(&res, vp, sizeof(res)); } else { res = no_be? svc->emergency: rand_backend(svc->backends, random() % svc->tot_pri); } break; } if(ret_val = pthread_mutex_unlock(&svc->mut)) logmsg(LOG_WARNING, "get_backend() unlock: %s", strerror(ret_val)); return res; } /* * (for cookies/header only) possibly create session based on response headers */ void upd_session(SERVICE *const svc, char **const headers, BACKEND *const be) { char key[KEY_SIZE + 1]; int ret_val; if(svc->sess_type != SESS_HEADER && svc->sess_type != SESS_COOKIE) return; if(ret_val = pthread_mutex_lock(&svc->mut)) logmsg(LOG_WARNING, "upd_session() lock: %s", strerror(ret_val)); if(get_HEADERS(key, svc, headers)) if(t_find(svc->sessions, key) == NULL) t_add(svc->sessions, key, &be, sizeof(be)); if(ret_val = pthread_mutex_unlock(&svc->mut)) logmsg(LOG_WARNING, "upd_session() unlock: %s", strerror(ret_val)); return; } /* * mark a backend host as dead/disabled; remove its sessions if necessary * disable_only == 1: mark as disabled * disable_only == 0: mark as dead, remove sessions * disable_only == -1: mark as enabled */ void kill_be(SERVICE *const svc, const BACKEND *be, const int disable_mode) { BACKEND *b; int ret_val; char buf[MAXBUF]; if(ret_val = pthread_mutex_lock(&svc->mut)) logmsg(LOG_WARNING, "kill_be() lock: %s", strerror(ret_val)); svc->tot_pri = 0; for(b = svc->backends; b; b = b->next) { if(b == be) switch(disable_mode) { case BE_DISABLE: b->disabled = 1; str_be(buf, MAXBUF - 1, b); logmsg(LOG_NOTICE, "(%lx) BackEnd %s disabled", pthread_self(), buf); break; case BE_KILL: b->alive = 0; str_be(buf, MAXBUF - 1, b); logmsg(LOG_NOTICE, "(%lx) BackEnd %s dead (killed)", pthread_self(), buf); t_clean(svc->sessions, &be, sizeof(be)); break; case BE_ENABLE: str_be(buf, MAXBUF - 1, b); logmsg(LOG_NOTICE, "(%lx) BackEnd %s enabled", pthread_self(), buf); b->disabled = 0; break; default: logmsg(LOG_WARNING, "kill_be(): unknown mode %d", disable_mode); break; } if(b->alive && !b->disabled) svc->tot_pri += b->priority; } if(ret_val = pthread_mutex_unlock(&svc->mut)) logmsg(LOG_WARNING, "kill_be() unlock: %s", strerror(ret_val)); return; } /* * Search for a host name, return the addrinfo for it */ int get_host(char *const name, struct addrinfo *res, int ai_family) { struct addrinfo *chain, *ap; struct addrinfo hints; int ret_val; #ifdef HAVE_INET_NTOP memset (&hints, 0, sizeof(hints)); hints.ai_family = ai_family; hints.ai_socktype = SOCK_STREAM; hints.ai_flags = AI_CANONNAME; if((ret_val = getaddrinfo(name, NULL, &hints, &chain)) == 0) { #ifdef _AIX ap = chain; #else for(ap = chain; ap != NULL; ap = ap->ai_next) if(ap->ai_socktype == SOCK_STREAM) break; #endif if(ap == NULL) { freeaddrinfo(chain); return EAI_NONAME; } *res = *ap; if((res->ai_addr = (struct sockaddr *)malloc(ap->ai_addrlen)) == NULL) { freeaddrinfo(chain); return EAI_MEMORY; } memcpy(res->ai_addr, ap->ai_addr, ap->ai_addrlen); freeaddrinfo(chain); } #else #error "Pound requires getaddrinfo()" #endif return ret_val; } /* * Find if a redirect needs rewriting * In general we have two possibilities that require it: * (1) if the redirect was done to the correct location with the wrong port * (2) if the redirect was done to the back-end rather than the listener */ int need_rewrite(const int rewr_loc, char *const location, char *const path, const char *v_host, const LISTENER *lstn, const BACKEND *be) { struct addrinfo addr; struct sockaddr_in in_addr, be_addr; struct sockaddr_in6 in6_addr, be6_addr; regmatch_t matches[4]; char *proto, *host, *port, *cp, buf[MAXBUF]; /* check if rewriting is required at all */ if(rewr_loc == 0) return 0; /* applies only to INET/INET6 back-ends */ if(be->addr.ai_family != AF_INET && be->addr.ai_family != AF_INET6) return 0; /* split the location into its fields */ if(regexec(&LOCATION, location, 4, matches, 0)) return 0; proto = location + matches[1].rm_so; host = location + matches[2].rm_so; if(location[matches[3].rm_so] == '/') matches[3].rm_so++; /* path is guaranteed to be large enough */ strcpy(path, location + matches[3].rm_so); location[matches[1].rm_eo] = location[matches[2].rm_eo] = '\0'; if((port = strchr(host, ':')) != NULL) *port++ = '\0'; /* * Check if the location has the same address as the listener or the back-end */ memset(&addr, 0, sizeof(addr)); if(get_host(host, &addr, be->addr.ai_family)) return 0; /* * compare the back-end */ if(addr.ai_family != be->addr.ai_family) { free(addr.ai_addr); return 0; } if(addr.ai_family == AF_INET) { memcpy(&in_addr, addr.ai_addr, sizeof(in_addr)); memcpy(&be_addr, be->addr.ai_addr, sizeof(be_addr)); if(port) in_addr.sin_port = (in_port_t)htons(atoi(port)); else if(!strcasecmp(proto, "https")) in_addr.sin_port = (in_port_t)htons(443); else in_addr.sin_port = (in_port_t)htons(80); /* * check if the Location points to the back-end */ if(memcmp(&be_addr.sin_addr.s_addr, &in_addr.sin_addr.s_addr, sizeof(in_addr.sin_addr.s_addr)) == 0 && memcmp(&be_addr.sin_port, &in_addr.sin_port, sizeof(in_addr.sin_port)) == 0) { free(addr.ai_addr); return 1; } } else /* AF_INET6 */ { memcpy(&in6_addr, addr.ai_addr, sizeof(in6_addr)); memcpy(&be6_addr, be->addr.ai_addr, sizeof(be6_addr)); if(port) in6_addr.sin6_port = (in_port_t)htons(atoi(port)); else if(!strcasecmp(proto, "https")) in6_addr.sin6_port = (in_port_t)htons(443); else in6_addr.sin6_port = (in_port_t)htons(80); /* * check if the Location points to the back-end */ if(memcmp(&be6_addr.sin6_addr.s6_addr, &in6_addr.sin6_addr.s6_addr, sizeof(in6_addr.sin6_addr.s6_addr)) == 0 && memcmp(&be6_addr.sin6_port, &in6_addr.sin6_port, sizeof(in6_addr.sin6_port)) == 0) { free(addr.ai_addr); return 1; } } /* * compare the listener */ if(rewr_loc != 1 || addr.ai_family != lstn->addr.ai_family) { free(addr.ai_addr); return 0; } memset(buf, '\0', MAXBUF); strncpy(buf, v_host, MAXBUF - 1); if((cp = strchr(buf, ':')) != NULL) *cp = '\0'; if(addr.ai_family == AF_INET) { memcpy(&be_addr, lstn->addr.ai_addr, sizeof(be_addr)); /* * check if the Location points to the Listener but with the wrong port or protocol */ if((memcmp(&be_addr.sin_addr.s_addr, &in_addr.sin_addr.s_addr, sizeof(in_addr.sin_addr.s_addr)) == 0 || strcasecmp(host, buf) == 0) && (memcmp(&be_addr.sin_port, &in_addr.sin_port, sizeof(in_addr.sin_port)) != 0 || strcasecmp(proto, lstn->ctx? "http": "https"))) { free(addr.ai_addr); return 1; } } else { memcpy(&be6_addr, lstn->addr.ai_addr, sizeof(be6_addr)); /* * check if the Location points to the Listener but with the wrong port or protocol */ if((memcmp(&be6_addr.sin6_addr.s6_addr, &in6_addr.sin6_addr.s6_addr, sizeof(in6_addr.sin6_addr.s6_addr)) == 0 || strcasecmp(host, buf) == 0) && (memcmp(&be6_addr.sin6_port, &in6_addr.sin6_port, sizeof(in6_addr.sin6_port)) != 0 || strcasecmp(proto, lstn->ctx? "http": "https"))) { free(addr.ai_addr); return 1; } } free(addr.ai_addr); return 0; } /* * Non-blocking connect(). Does the same as connect(2) but ensures * it will time-out after a much shorter time period SERVER_TO */ int connect_nb(const int sockfd, const struct addrinfo *serv_addr, const int to) { int flags, res, error; socklen_t len; struct pollfd p; if((flags = fcntl(sockfd, F_GETFL, 0)) < 0) { logmsg(LOG_WARNING, "(%lx) connect_nb: fcntl GETFL failed: %s", pthread_self(), strerror(errno)); return -1; } if(fcntl(sockfd, F_SETFL, flags | O_NONBLOCK) < 0) { logmsg(LOG_WARNING, "(%lx) connect_nb: fcntl SETFL failed: %s", pthread_self(), strerror(errno)); return -1; } error = 0; if((res = connect(sockfd, serv_addr->ai_addr, serv_addr->ai_addrlen)) < 0) if(errno != EINPROGRESS) { logmsg(LOG_WARNING, "(%lx) connect_nb: connect failed: %s", pthread_self(), strerror(errno)); return (-1); } if(res == 0) { /* connect completed immediately (usually localhost) */ if(fcntl(sockfd, F_SETFL, flags) < 0) { logmsg(LOG_WARNING, "(%lx) connect_nb: fcntl reSETFL failed: %s", pthread_self(), strerror(errno)); return -1; } return 0; } memset(&p, 0, sizeof(p)); p.fd = sockfd; p.events = POLLOUT; if((res = poll(&p, 1, to * 1000)) != 1) { if(res == 0) { /* timeout */ logmsg(LOG_WARNING, "(%lx) connect_nb: poll timed out", pthread_self()); errno = ETIMEDOUT; } else logmsg(LOG_WARNING, "(%lx) connect_nb: poll failed: %s", pthread_self(), strerror(errno)); return -1; } /* socket is writeable == operation completed */ len = sizeof(error); if(getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &error, &len) < 0) { logmsg(LOG_WARNING, "(%lx) connect_nb: getsockopt failed: %s", pthread_self(), strerror(errno)); return -1; } /* restore file status flags */ if(fcntl(sockfd, F_SETFL, flags) < 0) { logmsg(LOG_WARNING, "(%lx) connect_nb: fcntl reSETFL failed: %s", pthread_self(), strerror(errno)); return -1; } if(error) { /* getsockopt() shows an error */ errno = error; logmsg(LOG_WARNING, "(%lx) connect_nb: error after getsockopt: %s", pthread_self(), strerror(errno)); return -1; } /* really connected */ return 0; } /* * Check if dead hosts returned to life; * runs every alive seconds */ static void do_resurect(void) { LISTENER *lstn; SERVICE *svc; BACKEND *be; struct addrinfo z_addr, *addr; int sock, modified; char buf[MAXBUF]; int ret_val; /* check hosts still alive - HAport */ memset(&z_addr, 0, sizeof(z_addr)); for(lstn = listeners; lstn; lstn = lstn->next) for(svc = lstn->services; svc; svc = svc->next) for(be = svc->backends; be; be = be->next) { if(be->be_type) continue; if(!be->alive) /* already dead */ continue; if(memcmp(&(be->ha_addr), &z_addr, sizeof(z_addr)) == 0) /* no HA port */ continue; /* try connecting */ switch(be->ha_addr.ai_family) { case AF_INET: if((sock = socket(PF_INET, SOCK_STREAM, 0)) < 0) continue; break; case AF_INET6: if((sock = socket(PF_INET6, SOCK_STREAM, 0)) < 0) continue; break; case AF_UNIX: if((sock = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) continue; break; default: continue; } if(connect_nb(sock, &be->ha_addr, be->conn_to) != 0) { kill_be(svc, be, BE_KILL); str_be(buf, MAXBUF - 1, be); logmsg(LOG_NOTICE, "BackEnd %s is dead (HA)", buf); } shutdown(sock, 2); close(sock); } for(svc = services; svc; svc = svc->next) for(be = svc->backends; be; be = be->next) { if(be->be_type) continue; if(!be->alive) /* already dead */ continue; if(memcmp(&(be->ha_addr), &z_addr, sizeof(z_addr)) == 0) /* no HA port */ continue; /* try connecting */ switch(be->ha_addr.ai_family) { case AF_INET: if((sock = socket(PF_INET, SOCK_STREAM, 0)) < 0) continue; break; case AF_INET6: if((sock = socket(PF_INET6, SOCK_STREAM, 0)) < 0) continue; break; case AF_UNIX: if((sock = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) continue; break; default: continue; } if(connect_nb(sock, &be->ha_addr, be->conn_to) != 0) { kill_be(svc, be, BE_KILL); str_be(buf, MAXBUF - 1, be); logmsg(LOG_NOTICE, "BackEnd %s is dead (HA)", buf); } shutdown(sock, 2); close(sock); } /* check hosts alive again */ for(lstn = listeners; lstn; lstn = lstn->next) for(svc = lstn->services; svc; svc = svc->next) { for(modified = 0, be = svc->backends; be; be = be->next) { be->resurrect = 0; if(be->be_type) continue; if(be->alive) continue; if(memcmp(&(be->ha_addr), &z_addr, sizeof(z_addr)) == 0) { switch(be->addr.ai_family) { case AF_INET: if((sock = socket(PF_INET, SOCK_STREAM, 0)) < 0) continue; break; case AF_INET6: if((sock = socket(PF_INET6, SOCK_STREAM, 0)) < 0) continue; break; case AF_UNIX: if((sock = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) continue; break; default: continue; } addr = &be->addr; } else { switch(be->ha_addr.ai_family) { case AF_INET: if((sock = socket(PF_INET, SOCK_STREAM, 0)) < 0) continue; break; case AF_INET6: if((sock = socket(PF_INET6, SOCK_STREAM, 0)) < 0) continue; break; case AF_UNIX: if((sock = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) continue; break; default: continue; } addr = &be->ha_addr; } if(connect_nb(sock, addr, be->conn_to) == 0) { be->resurrect = 1; modified = 1; } shutdown(sock, 2); close(sock); } if(modified) { if(ret_val = pthread_mutex_lock(&svc->mut)) logmsg(LOG_WARNING, "do_resurect() lock: %s", strerror(ret_val)); svc->tot_pri = 0; for(be = svc->backends; be; be = be->next) { if(be->resurrect) { be->alive = 1; str_be(buf, MAXBUF - 1, be); logmsg(LOG_NOTICE, "BackEnd %s resurrect", buf); } if(be->alive && !be->disabled) svc->tot_pri += be->priority; } if(ret_val = pthread_mutex_unlock(&svc->mut)) logmsg(LOG_WARNING, "do_resurect() unlock: %s", strerror(ret_val)); } } for(svc = services; svc; svc = svc->next) { for(modified = 0, be = svc->backends; be; be = be->next) { be->resurrect = 0; if(be->be_type) continue; if(be->alive) continue; if(memcmp(&(be->ha_addr), &z_addr, sizeof(z_addr)) == 0) { switch(be->addr.ai_family) { case AF_INET: if((sock = socket(PF_INET, SOCK_STREAM, 0)) < 0) continue; break; case AF_INET6: if((sock = socket(PF_INET6, SOCK_STREAM, 0)) < 0) continue; break; case AF_UNIX: if((sock = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) continue; break; default: continue; } addr = &be->addr; } else { switch(be->ha_addr.ai_family) { case AF_INET: if((sock = socket(PF_INET, SOCK_STREAM, 0)) < 0) continue; break; case AF_INET6: if((sock = socket(PF_INET6, SOCK_STREAM, 0)) < 0) continue; break; case AF_UNIX: if((sock = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) continue; break; default: continue; } addr = &be->ha_addr; } if(connect_nb(sock, addr, be->conn_to) == 0) { be->resurrect = 1; modified = 1; } shutdown(sock, 2); close(sock); } if(modified) { if(ret_val = pthread_mutex_lock(&svc->mut)) logmsg(LOG_WARNING, "do_resurect() lock: %s", strerror(ret_val)); svc->tot_pri = 0; for(be = svc->backends; be; be = be->next) { if(be->resurrect) { be->alive = 1; str_be(buf, MAXBUF - 1, be); logmsg(LOG_NOTICE, "BackEnd %s resurrect", buf); } if(be->alive && !be->disabled) svc->tot_pri += be->priority; } if(ret_val = pthread_mutex_unlock(&svc->mut)) logmsg(LOG_WARNING, "do_resurect() unlock: %s", strerror(ret_val)); } } return; } /* * Remove expired sessions * runs every EXPIRE_TO seconds */ static void do_expire(void) { LISTENER *lstn; SERVICE *svc; time_t cur_time; int ret_val; /* remove stale sessions */ cur_time = time(NULL); for(lstn = listeners; lstn; lstn = lstn->next) for(svc = lstn->services; svc; svc = svc->next) if(svc->sess_type != SESS_NONE) { if(ret_val = pthread_mutex_lock(&svc->mut)) { logmsg(LOG_WARNING, "do_expire() lock: %s", strerror(ret_val)); continue; } t_expire(svc->sessions, cur_time - svc->sess_ttl); if(ret_val = pthread_mutex_unlock(&svc->mut)) logmsg(LOG_WARNING, "do_expire() unlock: %s", strerror(ret_val)); } for(svc = services; svc; svc = svc->next) if(svc->sess_type != SESS_NONE) { if(ret_val = pthread_mutex_lock(&svc->mut)) { logmsg(LOG_WARNING, "do_expire() lock: %s", strerror(ret_val)); continue; } t_expire(svc->sessions, cur_time - svc->sess_ttl); if(ret_val = pthread_mutex_unlock(&svc->mut)) logmsg(LOG_WARNING, "do_expire() unlock: %s", strerror(ret_val)); } return; } static pthread_mutex_t RSA_mut; /* mutex for RSA keygen */ static RSA *RSA512_keys[N_RSA_KEYS]; /* ephemeral RSA keys */ static RSA *RSA1024_keys[N_RSA_KEYS]; /* ephemeral RSA keys */ /* * return a pre-generated RSA key */ RSA * RSA_tmp_callback(/* not used */SSL *ssl, /* not used */int is_export, int keylength) { RSA *res; int ret_val; if(ret_val = pthread_mutex_lock(&RSA_mut)) logmsg(LOG_WARNING, "RSA_tmp_callback() lock: %s", strerror(ret_val)); res = (keylength <= 512)? RSA512_keys[rand() % N_RSA_KEYS]: RSA1024_keys[rand() % N_RSA_KEYS]; if(ret_val = pthread_mutex_unlock(&RSA_mut)) logmsg(LOG_WARNING, "RSA_tmp_callback() unlock: %s", strerror(ret_val)); return res; } /* * Periodically regenerate ephemeral RSA keys * runs every T_RSA_KEYS seconds */ static void do_RSAgen(void) { int n, ret_val; RSA *t_RSA512_keys[N_RSA_KEYS]; RSA *t_RSA1024_keys[N_RSA_KEYS]; for(n = 0; n < N_RSA_KEYS; n++) { t_RSA512_keys[n] = RSA_generate_key(512, RSA_F4, NULL, NULL); t_RSA1024_keys[n] = RSA_generate_key(1024, RSA_F4, NULL, NULL); } if(ret_val = pthread_mutex_lock(&RSA_mut)) logmsg(LOG_WARNING, "thr_RSAgen() lock: %s", strerror(ret_val)); for(n = 0; n < N_RSA_KEYS; n++) { RSA_free(RSA512_keys[n]); RSA512_keys[n] = t_RSA512_keys[n]; RSA_free(RSA1024_keys[n]); RSA1024_keys[n] = t_RSA1024_keys[n]; } if(ret_val = pthread_mutex_unlock(&RSA_mut)) logmsg(LOG_WARNING, "thr_RSAgen() unlock: %s", strerror(ret_val)); return; } #include "dh512.h" #if DH_LEN == 1024 #include "dh1024.h" static DH *DH512_params, *DH1024_params; DH * DH_tmp_callback(/* not used */SSL *s, /* not used */int is_export, int keylength) { return keylength == 512? DH512_params: DH1024_params; } #else #include "dh2048.h" static DH *DH512_params, *DH2048_params; DH * DH_tmp_callback(/* not used */SSL *s, /* not used */int is_export, int keylength) { return keylength == 512? DH512_params: DH2048_params; } #endif static time_t last_RSA, last_alive, last_expire; /* * initialise the timer functions: * - RSA_mut and keys */ void init_timer(void) { int n; last_RSA = last_alive = last_expire = time(NULL); /* * Pre-generate ephemeral RSA keys */ for(n = 0; n < N_RSA_KEYS; n++) { if((RSA512_keys[n] = RSA_generate_key(512, RSA_F4, NULL, NULL)) == NULL) { logmsg(LOG_WARNING,"RSA_generate(%d, 512) failed", n); return; } if((RSA1024_keys[n] = RSA_generate_key(1024, RSA_F4, NULL, NULL)) == NULL) { logmsg(LOG_WARNING,"RSA_generate(%d, 1024) failed", n); return; } } /* pthread_mutex_init() always returns 0 */ pthread_mutex_init(&RSA_mut, NULL); DH512_params = get_dh512(); #if DH_LEN == 1024 DH1024_params = get_dh1024(); #else DH2048_params = get_dh2048(); #endif return; } /* * run timed functions: * - RSAgen every T_RSA_KEYS seconds * - resurect every alive_to seconds * - expire every EXPIRE_TO seconds */ void * thr_timer(void *arg) { time_t last_time, cur_time; int n_wait, n_remain; n_wait = EXPIRE_TO; if(n_wait > alive_to) n_wait = alive_to; if(n_wait > T_RSA_KEYS) n_wait = T_RSA_KEYS; for(last_time = time(NULL) - n_wait;;) { cur_time = time(NULL); if((n_remain = n_wait - (cur_time - last_time)) > 0) sleep(n_remain); last_time = time(NULL); if((last_time - last_RSA) >= T_RSA_KEYS) { last_RSA = time(NULL); do_RSAgen(); } if((last_time - last_alive) >= alive_to) { last_alive = time(NULL); do_resurect(); } if((last_time - last_expire) >= EXPIRE_TO) { last_expire = time(NULL); do_expire(); } } } typedef struct { int control_sock; BACKEND *backends; } DUMP_ARG; static void t_dump_doall_arg(TABNODE *t, DUMP_ARG *arg) { BACKEND *be, *bep; int n_be, sz; memcpy(&bep, t->content, sizeof(bep)); for(n_be = 0, be = arg->backends; be; be = be->next, n_be++) if(be == bep) break; if(!be) /* should NEVER happen */ n_be = 0; (void)write(arg->control_sock, t, sizeof(TABNODE)); (void)write(arg->control_sock, &n_be, sizeof(n_be)); sz = strlen(t->key); (void)write(arg->control_sock, &sz, sizeof(sz)); (void)write(arg->control_sock, t->key, sz); return; } #if OPENSSL_VERSION_NUMBER >= 0x10000000L IMPLEMENT_LHASH_DOALL_ARG_FN(t_dump, TABNODE, DUMP_ARG) #else #define t_dump t_dump_doall_arg IMPLEMENT_LHASH_DOALL_ARG_FN(t_dump, TABNODE *, DUMP_ARG *) #endif /* * write sessions to the control socket */ static void dump_sess(const int control_sock, LHASH_OF(TABNODE) *const sess, BACKEND *const backends) { DUMP_ARG a; a.control_sock = control_sock; a.backends = backends; #if OPENSSL_VERSION_NUMBER >= 0x10000000L LHM_lh_doall_arg(TABNODE, sess, LHASH_DOALL_ARG_FN(t_dump), DUMP_ARG, &a); #else lh_doall_arg(sess, LHASH_DOALL_ARG_FN(t_dump), &a); #endif return; } /* * given a command, select a listener */ static LISTENER * sel_lstn(const CTRL_CMD *cmd) { LISTENER *lstn; int i; if(cmd->listener < 0) return NULL; for(i = 0, lstn = listeners; lstn && i < cmd->listener; i++, lstn = lstn->next) ; return lstn; } /* * given a command, select a service */ static SERVICE * sel_svc(const CTRL_CMD *cmd) { SERVICE *svc; LISTENER *lstn; int i; if(cmd->listener < 0) { svc = services; } else { if((lstn = sel_lstn(cmd)) == NULL) return NULL; svc = lstn->services; } for(i = 0; svc && i < cmd->service; i++, svc = svc->next) ; return svc; } /* * given a command, select a back-end */ static BACKEND * sel_be(const CTRL_CMD *cmd) { BACKEND *be; SERVICE *svc; int i; if((svc = sel_svc(cmd)) == NULL) return NULL; for(i = 0, be = svc->backends; be && i < cmd->backend; i++, be = be->next) ; return be; } /* * The controlling thread * listens to client requests and calls the appropriate functions */ void * thr_control(void *arg) { CTRL_CMD cmd; struct sockaddr sa; int ctl, dummy, n, ret_val; LISTENER *lstn, dummy_lstn; SERVICE *svc, dummy_svc; BACKEND *be, dummy_be; TABNODE dummy_sess; struct pollfd polls; /* just to be safe */ if(control_sock < 0) return NULL; memset(&dummy_lstn, 0, sizeof(dummy_lstn)); dummy_lstn.disabled = -1; memset(&dummy_svc, 0, sizeof(dummy_svc)); dummy_svc.disabled = -1; memset(&dummy_be, 0, sizeof(dummy_be)); dummy_be.disabled = -1; memset(&dummy_sess, 0, sizeof(dummy_sess)); dummy_sess.content = NULL; dummy = sizeof(sa); for(;;) { polls.fd = control_sock; polls.events = POLLIN | POLLPRI; polls.revents = 0; if(poll(&polls, 1, -1) < 0) { logmsg(LOG_WARNING, "thr_control() poll: %s", strerror(errno)); continue; } if((ctl = accept(control_sock, &sa, (socklen_t *)&dummy)) < 0) { logmsg(LOG_WARNING, "thr_control() accept: %s", strerror(errno)); continue; } if(read(ctl, &cmd, sizeof(cmd)) != sizeof(cmd)) { logmsg(LOG_WARNING, "thr_control() read: %s", strerror(errno)); continue; } switch(cmd.cmd) { case CTRL_LST: /* logmsg(LOG_INFO, "thr_control() list"); */ n = get_thr_qlen(); (void)write(ctl, (void *)&n, sizeof(n)); for(lstn = listeners; lstn; lstn = lstn->next) { (void)write(ctl, (void *)lstn, sizeof(LISTENER)); (void)write(ctl, lstn->addr.ai_addr, lstn->addr.ai_addrlen); for(svc = lstn->services; svc; svc = svc->next) { (void)write(ctl, (void *)svc, sizeof(SERVICE)); for(be = svc->backends; be; be = be->next) { (void)write(ctl, (void *)be, sizeof(BACKEND)); (void)write(ctl, be->addr.ai_addr, be->addr.ai_addrlen); if(be->ha_addr.ai_addrlen > 0) (void)write(ctl, be->ha_addr.ai_addr, be->ha_addr.ai_addrlen); } (void)write(ctl, (void *)&dummy_be, sizeof(BACKEND)); if(dummy = pthread_mutex_lock(&svc->mut)) logmsg(LOG_WARNING, "thr_control() lock: %s", strerror(dummy)); else { dump_sess(ctl, svc->sessions, svc->backends); if(dummy = pthread_mutex_unlock(&svc->mut)) logmsg(LOG_WARNING, "thr_control() unlock: %s", strerror(dummy)); } (void)write(ctl, (void *)&dummy_sess, sizeof(TABNODE)); } (void)write(ctl, (void *)&dummy_svc, sizeof(SERVICE)); } (void)write(ctl, (void *)&dummy_lstn, sizeof(LISTENER)); for(svc = services; svc; svc = svc->next) { (void)write(ctl, (void *)svc, sizeof(SERVICE)); for(be = svc->backends; be; be = be->next) { (void)write(ctl, (void *)be, sizeof(BACKEND)); (void)write(ctl, be->addr.ai_addr, be->addr.ai_addrlen); if(be->ha_addr.ai_addrlen > 0) (void)write(ctl, be->ha_addr.ai_addr, be->ha_addr.ai_addrlen); } (void)write(ctl, (void *)&dummy_be, sizeof(BACKEND)); if(dummy = pthread_mutex_lock(&svc->mut)) logmsg(LOG_WARNING, "thr_control() lock: %s", strerror(dummy)); else { dump_sess(ctl, svc->sessions, svc->backends); if(dummy = pthread_mutex_unlock(&svc->mut)) logmsg(LOG_WARNING, "thr_control() unlock: %s", strerror(dummy)); } (void)write(ctl, (void *)&dummy_sess, sizeof(TABNODE)); } (void)write(ctl, (void *)&dummy_svc, sizeof(SERVICE)); break; case CTRL_EN_LSTN: if((lstn = sel_lstn(&cmd)) == NULL) logmsg(LOG_INFO, "thr_control() bad listener %d", cmd.listener); else lstn->disabled = 0; break; case CTRL_DE_LSTN: if((lstn = sel_lstn(&cmd)) == NULL) logmsg(LOG_INFO, "thr_control() bad listener %d", cmd.listener); else lstn->disabled = 1; break; case CTRL_EN_SVC: if((svc = sel_svc(&cmd)) == NULL) logmsg(LOG_INFO, "thr_control() bad service %d/%d", cmd.listener, cmd.service); else svc->disabled = 0; break; case CTRL_DE_SVC: if((svc = sel_svc(&cmd)) == NULL) logmsg(LOG_INFO, "thr_control() bad service %d/%d", cmd.listener, cmd.service); else svc->disabled = 1; break; case CTRL_EN_BE: if((svc = sel_svc(&cmd)) == NULL) { logmsg(LOG_INFO, "thr_control() bad service %d/%d", cmd.listener, cmd.service); break; } if((be = sel_be(&cmd)) == NULL) logmsg(LOG_INFO, "thr_control() bad backend %d/%d/%d", cmd.listener, cmd.service, cmd.backend); else kill_be(svc, be, BE_ENABLE); break; case CTRL_DE_BE: if((svc = sel_svc(&cmd)) == NULL) { logmsg(LOG_INFO, "thr_control() bad service %d/%d", cmd.listener, cmd.service); break; } if((be = sel_be(&cmd)) == NULL) logmsg(LOG_INFO, "thr_control() bad backend %d/%d/%d", cmd.listener, cmd.service, cmd.backend); else kill_be(svc, be, BE_DISABLE); break; case CTRL_ADD_SESS: if((svc = sel_svc(&cmd)) == NULL) { logmsg(LOG_INFO, "thr_control() bad service %d/%d", cmd.listener, cmd.service); break; } if((be = sel_be(&cmd)) == NULL) { logmsg(LOG_INFO, "thr_control() bad back-end %d/%d", cmd.listener, cmd.service); break; } if(ret_val = pthread_mutex_lock(&svc->mut)) logmsg(LOG_WARNING, "thr_control() add session lock: %s", strerror(ret_val)); t_add(svc->sessions, cmd.key, &be, sizeof(be)); if(ret_val = pthread_mutex_unlock(&svc->mut)) logmsg(LOG_WARNING, "thoriginalfiler_control() add session unlock: %s", strerror(ret_val)); break; case CTRL_DEL_SESS: if((svc = sel_svc(&cmd)) == NULL) { logmsg(LOG_INFO, "thr_control() bad service %d/%d", cmd.listener, cmd.service); break; } if(ret_val = pthread_mutex_lock(&svc->mut)) logmsg(LOG_WARNING, "thr_control() del session lock: %s", strerror(ret_val)); t_remove(svc->sessions, cmd.key); if(ret_val = pthread_mutex_unlock(&svc->mut)) logmsg(LOG_WARNING, "thr_control() del session unlock: %s", strerror(ret_val)); break; default: logmsg(LOG_WARNING, "thr_control() unknown command"); break; } close(ctl); } } void SSLINFO_callback(const SSL *ssl, int where, int rc) { RENEG_STATE *reneg_state; /* Get our thr_arg where we're tracking this connection info */ if((reneg_state = (RENEG_STATE *)SSL_get_app_data(ssl)) == NULL) return; /* If we're rejecting renegotiations, move to ABORT if Client Hello is being read. */ if((where & SSL_CB_ACCEPT_LOOP) && *reneg_state == RENEG_REJECT) { int state; state = SSL_get_state(ssl); if (state == SSL3_ST_SR_CLNT_HELLO_A || state == SSL23_ST_SR_CLNT_HELLO_A) { *reneg_state = RENEG_ABORT; logmsg(LOG_WARNING,"rejecting client initiated renegotiation"); } } else if(where & SSL_CB_HANDSHAKE_DONE && *reneg_state == RENEG_INIT) { // Reject any followup renegotiations *reneg_state = RENEG_REJECT; } } Pound-2.8/pound.c0000664000175000017500000004254013275266545013007 0ustar rosegroseg/* * Pound - the reverse-proxy load-balancer * Copyright (C) 2002-2010 Apsis GmbH * * This file is part of Pound. * * Pound is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * Pound is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * Contact information: * Apsis GmbH * P.O.Box * 8707 Uetikon am See * Switzerland * EMail: roseg@apsis.ch */ #include "pound.h" /* common variables */ char *user, /* user to run as */ *group, /* group to run as */ *root_jail, /* directory to chroot to */ *pid_name, /* file to record pid in */ *ctrl_name; /* control socket name */ int alive_to, /* check interval for resurrection */ anonymise, /* anonymise client address */ daemonize, /* run as daemon */ log_facility, /* log facility to use */ print_log, /* print log messages to stdout/stderr */ grace, /* grace period before shutdown */ control_sock; /* control socket */ SERVICE *services; /* global services (if any) */ LISTENER *listeners; /* all available listeners */ regex_t HEADER, /* Allowed header */ CHUNK_HEAD, /* chunk header line */ RESP_SKIP, /* responses for which we skip response */ RESP_IGN, /* responses for which we ignore content */ LOCATION, /* the host we are redirected to */ AUTHORIZATION; /* the Authorisation header */ static int shut_down = 0; #ifndef SOL_TCP /* for systems without the definition */ int SOL_TCP; #endif /* worker pid */ static pid_t son = 0; /* * OpenSSL thread support stuff */ static pthread_mutex_t *l_array; static void l_init(void) { int i, n_locks; n_locks = CRYPTO_num_locks(); if((l_array = (pthread_mutex_t *)calloc(n_locks, sizeof(pthread_mutex_t))) == NULL) { logmsg(LOG_ERR, "lock init: out of memory - aborted..."); exit(1); } for(i = 0; i < n_locks; i++) /* pthread_mutex_init() always returns 0 */ pthread_mutex_init(&l_array[i], NULL); return; } static void l_lock(const int mode, const int n, /* unused */ const char *file, /* unused */ int line) { int ret_val; if(mode & CRYPTO_LOCK) { if(ret_val = pthread_mutex_lock(&l_array[n])) logmsg(LOG_ERR, "l_lock lock(): %s", strerror(ret_val)); } else { if(ret_val = pthread_mutex_unlock(&l_array[n])) logmsg(LOG_ERR, "l_lock unlock(): %s", strerror(ret_val)); } return; } static unsigned long l_id(void) { return (unsigned long)pthread_self(); } /* * work queue stuff */ static thr_arg *first = NULL, *last = NULL; static pthread_cond_t arg_cond; static pthread_mutex_t arg_mut; int numthreads; static void init_thr_arg(void) { pthread_cond_init(&arg_cond, NULL); pthread_mutex_init(&arg_mut, NULL); return; } /* * add a request to the queue */ int put_thr_arg(thr_arg *arg) { thr_arg *res; if((res = malloc(sizeof(thr_arg))) == NULL) { logmsg(LOG_WARNING, "thr_arg malloc"); return -1; } memcpy(res, arg, sizeof(thr_arg)); res->next = NULL; (void)pthread_mutex_lock(&arg_mut); if(last == NULL) first = last = res; else { last->next = res; last = last->next; } (void)pthread_mutex_unlock(&arg_mut); pthread_cond_signal(&arg_cond); return 0; } /* * get a request from the queue */ thr_arg * get_thr_arg(void) { thr_arg *res; (void)pthread_mutex_lock(&arg_mut); if(first == NULL) (void)pthread_cond_wait(&arg_cond, &arg_mut); if((res = first) != NULL) if((first = first->next) == NULL) last = NULL; (void)pthread_mutex_unlock(&arg_mut); if(first != NULL) pthread_cond_signal(&arg_cond); return res; } /* * get the current queue length */ int get_thr_qlen(void) { int res; thr_arg *tap; (void)pthread_mutex_lock(&arg_mut); for(res = 0, tap = first; tap != NULL; tap = tap->next, res++) ; (void)pthread_mutex_unlock(&arg_mut); return res; } /* * handle SIGTERM/SIGQUIT - exit */ static RETSIGTYPE h_term(const int sig) { logmsg(LOG_NOTICE, "received signal %d - exiting...", sig); if(son > 0) kill(son, sig); if(ctrl_name != NULL) (void)unlink(ctrl_name); exit(0); } /* * handle SIGHUP/SIGINT - exit after grace period */ static RETSIGTYPE h_shut(const int sig) { int status; LISTENER *lstn; logmsg(LOG_NOTICE, "received signal %d - shutting down...", sig); if(son > 0) { for(lstn = listeners; lstn; lstn = lstn->next) close(lstn->sock); kill(son, sig); (void)wait(&status); if(ctrl_name != NULL) (void)unlink(ctrl_name); exit(0); } else shut_down = 1; } /* * Pound: the reverse-proxy/load-balancer * * Arguments: * -f config_file configuration file - exclusive of other flags */ int main(const int argc, char **argv) { int n_listeners, i, clnt_length, clnt; struct pollfd *polls; LISTENER *lstn; pthread_t thr; pthread_attr_t attr; struct sched_param sp; uid_t user_id; gid_t group_id; FILE *fpid; struct sockaddr_storage clnt_addr; char tmp[MAXBUF]; #ifndef SOL_TCP struct protoent *pe; #endif print_log = 0; (void)umask(077); control_sock = -1; log_facility = -1; logmsg(LOG_NOTICE, "starting..."); signal(SIGHUP, h_shut); signal(SIGINT, h_shut); signal(SIGTERM, h_term); signal(SIGQUIT, h_term); signal(SIGPIPE, SIG_IGN); srandom(getpid()); /* SSL stuff */ SSL_load_error_strings(); SSL_library_init(); OpenSSL_add_all_algorithms(); l_init(); init_thr_arg(); CRYPTO_set_id_callback(l_id); CRYPTO_set_locking_callback(l_lock); init_timer(); /* Disable SSL Compression for OpenSSL pre-1.0. 1.0 is handled with an option in config.c */ #if OPENSSL_VERSION_NUMBER >= 0x00907000L #ifndef SSL_OP_NO_COMPRESSION { int i,n; STACK_OF(SSL_COMP) *ssl_comp_methods; ssl_comp_methods = SSL_COMP_get_compression_methods(); n = sk_SSL_COMP_num(ssl_comp_methods); for(i=n-1; i>=0; i--) { sk_SSL_COMP_delete(ssl_comp_methods, i); } } #endif #endif /* prepare regular expressions */ if(regcomp(&HEADER, "^([a-z0-9!#$%&'*+.^_`|~-]+):[ \t]*(.*)[ \t]*$", REG_ICASE | REG_NEWLINE | REG_EXTENDED) || regcomp(&CHUNK_HEAD, "^([0-9a-f]+).*$", REG_ICASE | REG_NEWLINE | REG_EXTENDED) || regcomp(&RESP_SKIP, "^HTTP/1.1 100.*$", REG_ICASE | REG_NEWLINE | REG_EXTENDED) || regcomp(&RESP_IGN, "^HTTP/1.[01] (10[1-9]|1[1-9][0-9]|204|30[456]).*$", REG_ICASE | REG_NEWLINE | REG_EXTENDED) || regcomp(&LOCATION, "(http|https)://([^/]+)(.*)", REG_ICASE | REG_NEWLINE | REG_EXTENDED) || regcomp(&AUTHORIZATION, "Authorization:[ \t]*Basic[ \t]*\"?([^ \t]*)\"?[ \t]*", REG_ICASE | REG_NEWLINE | REG_EXTENDED) ) { logmsg(LOG_ERR, "bad essential Regex - aborted"); exit(1); } #ifndef SOL_TCP /* for systems without the definition */ if((pe = getprotobyname("tcp")) == NULL) { logmsg(LOG_ERR, "missing TCP protocol"); exit(1); } SOL_TCP = pe->p_proto; #endif /* read config */ config_parse(argc, argv); if(log_facility != -1) openlog("pound", LOG_CONS | LOG_NDELAY, LOG_DAEMON); if(ctrl_name != NULL) { struct sockaddr_un ctrl; memset(&ctrl, 0, sizeof(ctrl)); ctrl.sun_family = AF_UNIX; strncpy(ctrl.sun_path, ctrl_name, sizeof(ctrl.sun_path) - 1); (void)unlink(ctrl.sun_path); if((control_sock = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) { logmsg(LOG_ERR, "Control \"%s\" create: %s", ctrl.sun_path, strerror(errno)); exit(1); } if(bind(control_sock, (struct sockaddr *)&ctrl, (socklen_t)sizeof(ctrl)) < 0) { logmsg(LOG_ERR, "Control \"%s\" bind: %s", ctrl.sun_path, strerror(errno)); exit(1); } listen(control_sock, 512); } /* open listeners */ for(lstn = listeners, n_listeners = 0; lstn; lstn = lstn->next, n_listeners++) { int opt; /* prepare the socket */ if((lstn->sock = socket(lstn->addr.ai_family == AF_INET? PF_INET: PF_INET6, SOCK_STREAM, 0)) < 0) { addr2str(tmp, MAXBUF - 1, &lstn->addr, 0); logmsg(LOG_ERR, "HTTP socket %s create: %s - aborted", tmp, strerror(errno)); exit(1); } opt = 1; setsockopt(lstn->sock, SOL_SOCKET, SO_REUSEADDR, (void *)&opt, sizeof(opt)); if(bind(lstn->sock, lstn->addr.ai_addr, (socklen_t)lstn->addr.ai_addrlen) < 0) { addr2str(tmp, MAXBUF - 1, &lstn->addr, 0); logmsg(LOG_ERR, "HTTP socket bind %s: %s - aborted", tmp, strerror(errno)); exit(1); } listen(lstn->sock, 512); } /* alloc the poll structures */ if((polls = (struct pollfd *)calloc(n_listeners, sizeof(struct pollfd))) == NULL) { logmsg(LOG_ERR, "Out of memory for poll - aborted"); exit(1); } for(lstn = listeners, i = 0; lstn; lstn = lstn->next, i++) polls[i].fd = lstn->sock; /* set uid if necessary */ if(user) { struct passwd *pw; if((pw = getpwnam(user)) == NULL) { logmsg(LOG_ERR, "no such user %s - aborted", user); exit(1); } user_id = pw->pw_uid; } /* set gid if necessary */ if(group) { struct group *gr; if((gr = getgrnam(group)) == NULL) { logmsg(LOG_ERR, "no such group %s - aborted", group); exit(1); } group_id = gr->gr_gid; } /* Turn off verbose messages (if necessary) */ print_log = 0; if(daemonize) { /* daemonize - make ourselves a subprocess. */ switch (fork()) { case 0: if(log_facility != -1) { close(0); close(1); close(2); } break; case -1: logmsg(LOG_ERR, "fork: %s - aborted", strerror(errno)); exit(1); default: exit(0); } #ifdef HAVE_SETSID (void) setsid(); #endif } /* record pid in file */ if((fpid = fopen(pid_name, "wt")) != NULL) { fprintf(fpid, "%d\n", getpid()); fclose(fpid); } else logmsg(LOG_NOTICE, "Create \"%s\": %s", pid_name, strerror(errno)); /* chroot if necessary */ if(root_jail) { if(chroot(root_jail)) { logmsg(LOG_ERR, "chroot: %s - aborted", strerror(errno)); exit(1); } if(chdir("/")) { logmsg(LOG_ERR, "chroot/chdir: %s - aborted", strerror(errno)); exit(1); } } if(group) if(setgid(group_id) || setegid(group_id)) { logmsg(LOG_ERR, "setgid: %s - aborted", strerror(errno)); exit(1); } if(user) if(setuid(user_id) || seteuid(user_id)) { logmsg(LOG_ERR, "setuid: %s - aborted", strerror(errno)); exit(1); } /* split off into monitor and working process if necessary */ for(;;) { #ifdef UPER if((son = fork()) > 0) { int status; (void)wait(&status); if(WIFEXITED(status)) logmsg(LOG_ERR, "MONITOR: worker exited normally %d, restarting...", WEXITSTATUS(status)); else if(WIFSIGNALED(status)) logmsg(LOG_ERR, "MONITOR: worker exited on signal %d, restarting...", WTERMSIG(status)); else logmsg(LOG_ERR, "MONITOR: worker exited (stopped?) %d, restarting...", status); } else if (son == 0) { #endif /* thread stuff */ pthread_attr_init(&attr); pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); #ifdef NEED_STACK /* set new stack size - necessary for OpenBSD/FreeBSD and Linux NPTL */ if(pthread_attr_setstacksize(&attr, 1 << 18)) { logmsg(LOG_ERR, "can't set stack size - aborted"); exit(1); } #endif /* start timer */ if(pthread_create(&thr, &attr, thr_timer, NULL)) { logmsg(LOG_ERR, "create thr_resurect: %s - aborted", strerror(errno)); exit(1); } /* start the controlling thread (if needed) */ if(control_sock >= 0 && pthread_create(&thr, &attr, thr_control, NULL)) { logmsg(LOG_ERR, "create thr_control: %s - aborted", strerror(errno)); exit(1); } /* pause to make sure the service threads were started */ sleep(1); /* create the worker threads */ for(i = 0; i < numthreads; i++) if(pthread_create(&thr, &attr, thr_http, NULL)) { logmsg(LOG_ERR, "create thr_http: %s - aborted", strerror(errno)); exit(1); } /* pause to make sure at least some of the worker threads were started */ sleep(1); /* and start working */ for(;;) { if(shut_down) { logmsg(LOG_NOTICE, "shutting down..."); for(lstn = listeners; lstn; lstn = lstn->next) close(lstn->sock); if(grace > 0) { sleep(grace); logmsg(LOG_NOTICE, "grace period expired - exiting..."); } if(ctrl_name != NULL) (void)unlink(ctrl_name); exit(0); } for(lstn = listeners, i = 0; i < n_listeners; lstn = lstn->next, i++) { polls[i].events = POLLIN | POLLPRI; polls[i].revents = 0; } if(poll(polls, n_listeners, -1) < 0) { logmsg(LOG_WARNING, "poll: %s", strerror(errno)); } else { for(lstn = listeners, i = 0; lstn; lstn = lstn->next, i++) { if(polls[i].revents & (POLLIN | POLLPRI)) { memset(&clnt_addr, 0, sizeof(clnt_addr)); clnt_length = sizeof(clnt_addr); if((clnt = accept(lstn->sock, (struct sockaddr *)&clnt_addr, (socklen_t *)&clnt_length)) < 0) { logmsg(LOG_WARNING, "HTTP accept: %s", strerror(errno)); } else if(((struct sockaddr_in *)&clnt_addr)->sin_family == AF_INET || ((struct sockaddr_in *)&clnt_addr)->sin_family == AF_INET6) { thr_arg arg; if(lstn->disabled) { /* addr2str(tmp, MAXBUF - 1, &clnt_addr, 1); logmsg(LOG_WARNING, "HTTP disabled listener from %s", tmp); */ close(clnt); } arg.sock = clnt; arg.lstn = lstn; if((arg.from_host.ai_addr = (struct sockaddr *)malloc(clnt_length)) == NULL) { logmsg(LOG_WARNING, "HTTP arg address: malloc"); close(clnt); continue; } memcpy(arg.from_host.ai_addr, &clnt_addr, clnt_length); arg.from_host.ai_addrlen = clnt_length; if(((struct sockaddr_in *)&clnt_addr)->sin_family == AF_INET) arg.from_host.ai_family = AF_INET; else arg.from_host.ai_family = AF_INET6; if(put_thr_arg(&arg)) close(clnt); } else { /* may happen on FreeBSD, I am told */ logmsg(LOG_WARNING, "HTTP connection prematurely closed by peer"); close(clnt); } } } } } #ifdef UPER } else { /* failed to spawn son */ logmsg(LOG_ERR, "Can't fork worker (%s) - aborted", strerror(errno)); exit(1); } #endif } }